Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
 
3
/**
4
 * Capsule is a simple "template" engine that essentially provides an isolated context
5
 * for PHP scripts.
6
 *
7
 * There is no special templating language, and therefore no limitations to what
8
 * can be accomplished within templates. The main purpose of Capsule is to separate
9
 * the business logic from display / output logic.
10
 *
11
 * @author Hans Lellelid <hans@xmpl.org>
12
 * @version $Revision: 1.9 $ $Date: 2006-09-14 22:19:08 +0200 (Thu, 14 Sep 2006) $
13
 */
14
class Capsule {
15
 
16
    /**
17
     * Look for templates here (if relative path provided).
18
     * @var string
19
     */
20
    protected $templatePath;
21
 
22
    /**
23
     * Where should output files be written?
24
     * (This is named inconsistently to be compatible w/ Texen.)
25
     * @var string
26
     */
27
    protected $outputDirectory;
28
 
29
    /**
30
     * The variables that can be used by the templates.
31
     * @var array Hash of variables.
32
     */
33
    public $vars = array();
34
 
35
    /**
36
     * Has template been initialized.
37
     */
38
    protected $initialized = false;
39
 
40
    /**
41
     * Stores the pre-parse() include_path.
42
     * @var string
43
     */
44
    private $old_include_path;
45
 
46
    function __construct() {
47
    }
48
 
49
    /**
50
     * Clears one or several or all variables.
51
     * @param mixed $which String name of var, or array of names.
52
     * @return void
53
     */
54
    function clear($which = null) {
55
        if ($which === null) {
56
            $this->vars = array();
57
        } elseif (is_array($which)) {
58
            foreach($which as $var) {
59
                unset($this->vars[$var]);
60
            }
61
        } else {
62
            unset($this->vars[$which]);
63
        }
64
    }
65
 
66
    /**
67
     * Set the basepath to use for template lookups.
68
     * @param string $v
69
     */
70
    function setTemplatePath($v) {
71
        $this->templatePath = rtrim($v, DIRECTORY_SEPARATOR.'/');
72
    }
73
 
74
    /**
75
     * Get the basepath to use for template lookups.
76
     * @return string
77
     */
78
    function getTemplatePath() {
79
        return $this->templatePath;
80
    }
81
 
82
    /**
83
     * Set a basepath to use for output file creation.
84
     * @param string $v
85
     */
86
    function setOutputDirectory($v) {
87
        $this->outputDirectory = rtrim($v, DIRECTORY_SEPARATOR.'/');
88
    }
89
 
90
    /**
91
     * Get basepath to use for output file creation.
92
     * @return string
93
     */
94
    function getOutputDirectory() {
95
        return $this->outputDirectory;
96
    }
97
 
98
    /**
99
     * Low overhead (no output buffering) method to simply dump template
100
     * to buffer.
101
     *
102
     * @param string $__template
103
     * @return void
104
     * @throws Exception - if template cannot be found
105
     */
106
    function display($__template) {
107
 
108
        // Prepend "private" variable names with $__ in this function
109
        // to keep namespace conflict potential to a minimum.
110
 
111
        // Alias this class to $generator.
112
        $generator = $this;
113
 
114
        if (isset($this->vars['this'])) {
115
            throw new Exception("Assigning a variable named \$this to a context conflicts with class namespace.");
116
        }
117
 
118
        // extract variables into local namespace
119
        extract($this->vars);
120
 
121
        // prepend template path to include path,
122
        // so that include "path/relative/to/templates"; can be used within templates
123
        $__old_inc_path = ini_get('include_path');
124
        ini_set('include_path', $this->templatePath . PATH_SEPARATOR . $__old_inc_path);
125
 
126
        @ini_set('track_errors', true);
127
        include $__template;
128
        @ini_restore('track_errors');
129
 
130
        // restore the include path
131
        ini_set('include_path', $__old_inc_path);
132
 
133
        if (!empty($php_errormsg)) {
134
            throw new Exception("Unable to parse template " . $__template . ": " . $php_errormsg);
135
        }
136
    }
137
 
138
    /**
139
     * Fetches the results of a tempalte parse and either returns
140
     * the string or writes results to a specified output file.
141
     *
142
     * @param string $template The template filename (relative to templatePath or absolute).
143
     * @param string $outputFile If specified, contents of template will also be written to this file.
144
     * @param boolean $append Should output be appended to source file?
145
     * @return string The "parsed" template output.
146
     * @throws Exception - if template not found.
147
     */
148
    function parse($template, $outputFile = null, $append = false) {
149
 
150
        // main work done right here:
151
        // hopefully this works recursively ... fingers crossed.
152
        ob_start();
153
 
154
        try {
155
            $this->display($template);
156
        } catch (Exception $e) {
157
            ob_end_flush(); // flush the output on error (so we can see up to what point it parsed everything)
158
            throw $e;
159
        }
160
 
161
        $output = ob_get_contents();
162
        ob_end_clean();
163
 
164
        if ($outputFile !== null) {
165
            $outputFile = $this->resolvePath($outputFile, $this->outputDirectory);
166
 
167
            $flags = null;
168
            if ($append) $flags = FILE_APPEND;
169
 
170
            if (!file_put_contents($outputFile, $output, $flags) && $output != "") {
171
                throw new Exception("Unable to write output to " . $outputFile);
172
            }
173
        }
174
 
175
        return $output;
176
    }
177
 
178
    /**
179
     * This returns a "best guess" path for the given file.
180
     *
181
     * @param string $file File name or possibly absolute path.
182
     * @param string $basepath The basepath that should be prepended if $file is not absolute.
183
     * @return string "Best guess" path for this file.
184
     */
185
    protected function resolvePath($file, $basepath) {
186
        if ( !($file{0} == DIRECTORY_SEPARATOR || $file{0} == '/')
187
            // also account for C:\ style path
188
                && !($file{1} == ':' && ($file{2} ==  DIRECTORY_SEPARATOR || $file{2} == '/'))) {
189
            if ($basepath != null) {
190
                $file = $basepath . DIRECTORY_SEPARATOR . $file;
191
            }
192
        }
193
        return $file;
194
    }
195
 
196
    /**
197
     * Gets value of specified var or NULL if var has not been put().
198
     * @param string $name Variable name to retrieve.
199
     * @return mixed
200
     */
201
    function get($name) {
202
        if (!isset($this->vars[$name])) return null;
203
        return $this->vars[$name];
204
    }
205
 
206
    /**
207
     * Merges in passed hash to vars array.
208
     *
209
     * Given an array like:
210
     *
211
     *            array(     'myvar' => 'Hello',
212
     *                    'myvar2' => 'Hello')
213
     *
214
     * Resulting template will have access to $myvar and $myvar2.
215
     *
216
     * @param array $vars
217
     * @param boolean $recursiveMerge Should matching keys be recursively merged?
218
     * @return void
219
     */
220
    function putAll($vars, $recursiveMerge = false) {
221
        if ($recursiveMerge) {
222
            $this->vars = array_merge_recursive($this->vars, $vars);
223
        } else {
224
            $this->vars = array_merge($this->vars, $vars);
225
        }
226
    }
227
 
228
    /**
229
     * Adds a variable to the context.
230
     *
231
     * Resulting template will have access to ${$name$} variable.
232
     *
233
     * @param string $name
234
     * @param mixed $value
235
     */
236
    function put($name, $value) {
237
        $this->vars[$name] = $value;
238
    }
239
 
240
    /**
241
     * Put a variable into the context, assigning it by reference.
242
     * This means that if the template modifies the variable, then it
243
     * will also be modified in the context.
244
     *
245
     * @param $name
246
     * @param &$value
247
     */
248
    function putRef($name, &$value) {
249
        $this->vars[$name] = &$value;
250
    }
251
 
252
    /**
253
     * Makes a copy of the value and puts it into the context.
254
     * This is primarily to force copying (cloning) of objects, rather
255
     * than the default behavior which is to assign them by reference.
256
     * @param string $name
257
     * @param mixed $value
258
     */
259
    function putCopy($name, $value) {
260
        if (is_object($value)) {
261
            $value = clone $value;
262
        }
263
        $this->vars[$name] = $value;
264
    }
265
 
266
}