]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/Template.php
Update locale
[SourceForge/phpwiki.git] / lib / Template.php
1 <?php
2
3 require_once 'lib/ErrorManager.php';
4
5 /** An HTML template.
6  */
7 class Template
8 {
9     /**
10      * name optionally of form "theme/template" to include parent templates in children
11      */
12     function Template ($name, &$request, $args = false) {
13         global $WikiTheme;
14
15         $this->_request =& $request;
16         $this->_basepage = $request->getArg('pagename');
17
18         if (strstr($name, "/")) {
19             $oldname = $WikiTheme->_name;
20             $oldtheme = $WikiTheme->_theme;
21             list($themename, $name) = explode("/", $name);
22             $WikiTheme->_theme = "themes/$themename";
23             $WikiTheme->_name = $name;
24         }
25         $this->_name = $name;
26         $file = $WikiTheme->findTemplate($name);
27         if (!$file) {
28             trigger_error("no template for $name found.", E_USER_WARNING);
29             return;
30         }
31         if (isset($oldname)) {
32             $WikiTheme->_name = $oldname;
33             $WikiTheme->_theme = $oldtheme;
34         }
35         $fp = fopen($file, "rb");
36         if (!$fp) {
37             trigger_error("$file not found", E_USER_WARNING);
38             return;
39         }
40         $request->_TemplatesProcessed[$name] = 1;
41         $this->_tmpl = fread($fp, filesize($file));
42         if ($fp) fclose($fp);
43         //$userid = $request->_user->_userid;
44         if (is_array($args))
45             $this->_locals = $args;
46         elseif ($args)
47             $this->_locals = array('CONTENT' => $args);
48         else
49             $this->_locals = array();
50     }
51
52     function _munge_input($template) {
53
54         // Convert < ?plugin expr ? > to < ?php $this->_printPluginPI("expr"); ? >
55         $orig[] = '/<\?plugin.*?\?>/se';
56         $repl[] = "\$this->_mungePlugin('\\0')";
57
58         // Convert < ?= expr ? > to < ?php $this->_print(expr); ? >
59         $orig[] = '/<\?=(.*?)\?>/s';
60         $repl[] = '<?php $this->_print(\1);?>';
61
62         // Convert < ?php echo expr ? > to < ?php $this->_print(expr); ? >
63         $orig[] = '/<\?php echo (.*?)\?>/s';
64         $repl[] = '<?php $this->_print(\1);?>';
65
66         return preg_replace($orig, $repl, $template);
67     }
68
69     function _mungePlugin($pi) {
70         // HACK ALERT: PHP's preg_replace, with the /e option seems to
71         // escape both single and double quotes with backslashes.
72         // So we need to unescape the double quotes here...
73
74         $pi = preg_replace('/(?!<\\\\)\\\\"/x', '"', $pi);
75         return sprintf('<?php $this->_printPlugin(%s); ?>',
76                        "'" . str_replace("'", "\'", $pi) . "'");
77     }
78
79     function _printPlugin ($pi) {
80     include_once 'lib/WikiPlugin.php';
81     static $loader;
82
83         if (empty($loader))
84             $loader = new WikiPluginLoader;
85
86         $this->_print($loader->expandPI($pi, $this->_request, $this, $this->_basepage));
87     }
88
89     function _print ($val) {
90         if (isa($val, 'Template')) {
91             $this->_expandSubtemplate($val);
92         } else {
93             PrintXML($val);
94         }
95     }
96
97     function _expandSubtemplate (&$template) {
98         // FIXME: big hack!
99         //if (!$template->_request)
100         //    $template->_request = &$this->_request;
101         if (DEBUG) {
102             echo "<!-- Begin $template->_name -->\n";
103         }
104         // Expand sub-template with defaults from this template.
105         $template->printExpansion($this->_vars);
106         if (DEBUG) {
107             echo "<!-- End $template->_name -->\n";
108         }
109     }
110
111     /**
112      * Substitute HTML replacement text for tokens in template.
113      *
114      * Constructs a new WikiTemplate based upon the named template.
115      *
116      * @access public
117      *
118      * @param $token string Name of token to substitute for.
119      *
120      * @param $replacement string Replacement HTML text.
121      */
122     function replace($varname, $value) {
123         $this->_locals[$varname] = $value;
124     }
125
126
127     function printExpansion ($defaults = false) {
128         if (!is_array($defaults)) // HTML object or template object
129             $defaults = array('CONTENT' => $defaults);
130         $this->_vars = array_merge($defaults, $this->_locals);
131         extract($this->_vars);
132
133         global $request;
134         if (!isset($user))
135             $user = $request->getUser();
136         if (!isset($page))
137             $page = $request->getPage();
138     // Speedup. I checked all templates
139         if (!isset($revision))
140         $revision = false;
141
142         global $WikiTheme, $charset;
143         //$this->_dump_template();
144         $SEP = $WikiTheme->getButtonSeparator();
145
146         global $ErrorManager;
147         $ErrorManager->pushErrorHandler(new WikiMethodCb($this, '_errorHandler'));
148
149         eval('?>' . $this->_munge_input($this->_tmpl));
150
151         $ErrorManager->popErrorHandler();
152     }
153
154     // FIXME (1.3.12)
155     // Find a way to do template expansion less memory intensive and faster.
156     // 1.3.4 needed no memory at all for dumphtml, now it needs +15MB.
157     // Smarty? As before?
158     function getExpansion ($defaults = false) {
159         ob_start();
160         $this->printExpansion($defaults);
161         $xml = ob_get_contents();
162         ob_end_clean();     // PHP problem: Doesn't release its memory?
163         return $xml;
164     }
165
166     function printXML () {
167         $this->printExpansion();
168     }
169
170     function asXML () {
171         return $this->getExpansion();
172     }
173
174
175     // Debugging:
176     function _dump_template () {
177         $lines = explode("\n", $this->_munge_input($this->_tmpl));
178         $pre = HTML::pre();
179         $n = 1;
180         foreach ($lines as $line)
181             $pre->pushContent(fmt("%4d  %s\n", $n++, $line));
182         $pre->printXML();
183     }
184
185     function _errorHandler($error) {
186         //if (!preg_match('/: eval\(\)\'d code$/', $error->errfile))
187     //    return false;
188
189         if (preg_match('/: eval\(\)\'d code$/', $error->errfile)) {
190             $error->errfile = "In template '$this->_name'";
191             // Hack alert: Ignore 'undefined variable' messages for variables
192             //  whose names are ALL_CAPS.
193             if (preg_match('/Undefined variable:\s*[_A-Z]+\s*$/', $error->errstr))
194                 return true;
195         }
196         // ignore recursively nested htmldump loop: browse -> body -> htmldump -> browse -> body ...
197         // FIXME for other possible loops also
198         elseif (strstr($error->errfile, "In template 'htmldump'")) {
199             ; //return $error;
200         }
201         elseif (strstr($error->errfile, "In template '")) { // merge
202             $error->errfile = preg_replace("/'(\w+)'\)$/", "'\\1' < '$this->_name')",
203                                            $error->errfile);
204         }
205         else {
206             $error->errfile .= " (In template '$this->_name')";
207         }
208
209         if (!empty($this->_tmpl)) {
210             $lines = explode("\n", $this->_tmpl);
211             if (isset($lines[$error->errline - 1]))
212                 $error->errstr .= ":\n\t" . $lines[$error->errline - 1];
213         }
214     return $error;
215     }
216 };
217
218 /**
219  * Get a templates
220  *
221  * This is a convenience function and is equivalent to:
222  * <pre>
223  *   new Template(...)
224  * </pre>
225  */
226 function Template($name, $args = false) {
227     global $request;
228     return new Template($name, $request, $args);
229 }
230
231 function alreadyTemplateProcessed($name) {
232     global $request;
233     return !empty($request->_TemplatesProcessed[$name]) ? true : false;
234 }
235 /**
236  * Make and expand the top-level template.
237  *
238  *
239  * @param $content mixed html content to put into the page
240  * @param $title string page title
241  * @param $page_revision object A WikiDB_PageRevision object or false
242  * @param $args hash Extract args for top-level template
243  *
244  * @return string HTML expansion of template.
245  */
246 function GeneratePage($content, $title, $page_revision = false, $args = false) {
247     global $request;
248
249     if (!is_array($args))
250         $args = array();
251
252     $args['CONTENT'] = $content;
253     $args['TITLE'] = $title;
254     $args['revision'] = $page_revision;
255
256     if (!isset($args['HEADER']))
257         $args['HEADER'] = $title;
258
259     printXML(new Template('html', $request, $args));
260 }
261
262
263 /**
264  * For dumping pages as html to a file.
265  * Used for action=dumphtml,action=ziphtml,format=pdf,format=xml
266  */
267 function GeneratePageasXML($content, $title, $page_revision = false, $args = false) {
268     global $request;
269
270     if (!is_array($args))
271         $args = array();
272
273     $content->_basepage = $title;
274     $args['CONTENT'] = $content;
275     $args['TITLE'] = SplitPagename($title);
276     $args['revision'] = $page_revision;
277
278     if (!isset($args['HEADER']))
279         $args['HEADER'] = SplitPagename($title);
280
281     global $HIDE_TOOLBARS, $NO_BASEHREF, $WikiTheme;
282     $HIDE_TOOLBARS = true;
283     if (!$WikiTheme->DUMP_MODE)
284     $WikiTheme->DUMP_MODE = 'HTML';
285
286     // FIXME: unfatal errors and login requirements
287     $html = asXML(new Template('htmldump', $request, $args));
288
289     $HIDE_TOOLBARS = false;
290     //$WikiTheme->DUMP_MODE = false;
291     return $html;
292 }
293
294 // Local Variables:
295 // mode: php
296 // tab-width: 8
297 // c-basic-offset: 4
298 // c-hanging-comment-ender-p: nil
299 // indent-tabs-mode: nil
300 // End: