]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/Template.php
<link media="print"> is interpreted very strict by Mozilla and it won't display on...
[SourceForge/phpwiki.git] / lib / Template.php
1 <?php rcs_id('$Id: Template.php,v 1.19 2002-01-15 21:41:10 carstenklapp Exp $');
2
3 require_once("lib/ErrorManager.php");
4 require_once("lib/WikiPlugin.php");
5 require_once("lib/Toolbar.php");
6
7 //FIXME: This is a mess and needs to be refactored.
8 //  (In other words: this is all in a state of flux, so don't count on any
9 //   of this being the same tomorrow...)
10
11 class Template
12 {
13     function Template($tmpl) {
14         //$this->_tmpl = $this->_munge_input($tmpl);
15         $this->_tmpl = $tmpl;
16         $this->_vars = array();
17     }
18
19     function _munge_input($template) {
20         // Expand "< ?plugin-* ...? >"
21         preg_match_all('/<\?plugin.*?\?>/s', $template, $m);
22         global $dbi, $request;  // FIXME: no globals?
23         $pluginLoader = new WikiPluginLoader;
24         foreach (array_unique($m[0]) as $plugin_pi) {
25             $orig[] = '/' . preg_quote($plugin_pi, '/') . '/s';
26             // Plugin args like 'description=_("Get backlinks")' get
27             // gettexted.
28             // FIXME: move this to WikiPlugin.php.
29             $translated_pi = preg_replace('/(\s\w+=)_\("((?:[^"\\\\]|\\.)*)"\)/xse',
30                                           '"\1\"" . gettext("\2") . "\""',
31                                           $plugin_pi);
32             $repl[] = $pluginLoader->expandPI($translated_pi, $dbi, $request);
33         }
34
35          // Convert ${VAR} to < ?php echo "$VAR"; ? >
36         //$orig[] = '/\${(\w[\w\d]*)}/';
37         //$repl[] = '<?php echo "$\1"; ? >';
38         $orig[] = '/\${(\w[\w\d]*)}/e';
39         $repl[] = '$this->_getReplacement("\1")';
40
41         // Convert $VAR[ind] to < ?php echo "$VAR[ind]"; ? >
42         $orig[] = '/\$(\w[\w\d]*)\[([\w\d]+)\]/e';
43         $repl[] = '$this->_getReplacement("\1", "\2")';
44
45         // Convert $_("String") to < ?php echo htmlspecialchars(gettext("String")); ? >
46         $orig[] = '/\$_\(("(?:[^"\\\\]|\\.)*")\)/xs';
47         $repl[] = "<?php echo htmlspecialchars(gettext(\\1)); ?>";
48         
49         // Convert tag attributes like foo=_("String") to foo="String" (with gettext mapping).
50         $orig[] = '/( < \w [^>]* \w=)_\("((?:[^"\\\\]|\\.)*)"\)/xse';
51         $repl[] = '"\1\"" . htmlspecialchars(gettext("\2")) . "\""';
52         
53         return preg_replace($orig, $repl, $template);
54
55         $ret = preg_replace($orig, $repl, $template);
56         echo QElement('pre', $ret);
57         return $ret;
58         
59
60     }
61
62     function _getReplacement($varname, $index = false) {
63         // FIXME: report missing vars.
64         $vars = &$this->_vars;
65         if (isset($vars[$varname])) {
66             $value = $vars[$varname];
67             if ($index !== false)
68                 @$value = (string) $value[$index];
69             return str_replace('?', '&#63;', $value);
70         }
71         return false;
72     }
73     
74     /**
75      * Substitute HTML replacement text for tokens in template. 
76      *
77      * Constructs a new WikiTemplate based upon the named template.
78      *
79      * @access public
80      *
81      * @param $token string Name of token to substitute for.
82      *
83      * @param $replacement string Replacement HTML text.
84      */
85     function replace($varname, $value) {
86         $this->_vars[$varname] = $value;
87     }
88
89     /**
90      * Substitute text for tokens in template. 
91      *
92      * @access public
93      *
94      * @param $token string Name of token to substitute for.
95      *
96      * @param $replacement string Replacement text.
97      * The replacement text is run through htmlspecialchars()
98      * to escape any special characters.
99      */
100     function qreplace($varname, $value) {
101         $this->_vars[$varname] = htmlspecialchars($value);
102     }
103     
104
105     /**
106      * Include/remove conditional text in template.
107      *
108      * @access public
109      *
110      * @param $token string Conditional token name.
111      * The text within any matching if blocks (or single line ifs) will
112      * be included in the template expansion, while the text in matching
113      * negated if blocks will be excluded. 
114      */
115     /*
116     function setConditional($token, $value = true) {
117         $this->_iftoken[$token] = $value;
118     }
119     */
120     
121     function getExpansion($varhash = false) {
122         $savevars = $this->_vars;
123         if (is_array($varhash)) {
124             foreach ($varhash as $key => $val)
125                 $this->_vars[$key] = $val;
126         }
127         extract($this->_vars);
128         if (isset($this->_iftoken))
129             $_iftoken = $this->_iftoken;
130         
131         ob_start();
132
133         //$this->_dump_template();
134
135         global $ErrorManager;
136         $ErrorManager->pushErrorHandler(new WikiMethodCb($this, '_errorHandler'));
137         eval('?>' . $this->_munge_input($this->_tmpl));
138         $ErrorManager->popErrorHandler();
139
140         $html = ob_get_contents();
141         ob_end_clean();
142
143         return $html;
144     }
145
146     function printExpansion($args = false) {
147         echo $this->getExpansion($args);
148     }
149
150     // Debugging:
151     function _dump_template () {
152         $lines = explode("\n", $this->_munge_input($this->_tmpl));
153         echo "<pre>\n";
154         $n = 1;
155         foreach ($lines as $line)
156             printf("%4d  %s\n", $n++, htmlspecialchars($line));
157         echo "</pre>\n";
158     }
159
160     function _errorHandler($error) {
161         if (!preg_match('/: eval\(\)\'d code$/', $error->errfile))
162             return false;
163         $error->errfile = "In template";
164         $lines = explode("\n", $this->_tmpl);
165         if (isset($lines[$error->errline - 1]))
166             $error->errstr .= ":\n\t" . $lines[$error->errline - 1];
167         return $error;
168     }
169 };
170
171 class TemplateFile
172 extends Template
173 {
174     function TemplateFile($filename) {
175         $this->_template_file = $filename;
176         $fp = fopen($filename, "rb");
177         $data = fread($fp, filesize($filename));
178         fclose($fp);
179         $this->Template($data);
180     }
181 }
182
183 class WikiTemplate
184 extends TemplateFile
185 {
186     /**
187      * Constructor.
188      *
189      * Constructs a new WikiTemplate based upon the named template.
190      *
191      * @access public
192      *
193      * @param $template string Which template.
194      */
195     function WikiTemplate($template, $page_revision = false) {
196         global $templates;
197
198         $this->TemplateFile(FindFile($templates[$template]));
199
200         $this->_template_name = $template;
201
202         $this->setGlobalTokens();
203         if ($page_revision)
204             $this->setPageRevisionTokens($page_revision);
205     }
206     
207
208     function setPageTokens(&$page) {
209         /*
210         if ($page->get('locked'))
211             $this->setConditional('LOCK');
212         // HACK: note that EDITABLE may also be set in setWikiUserTokens.
213         if (!$page->get('locked'))
214             $this->setConditional('EDITABLE');
215         */
216         
217         $pagename = $page->getName();
218         $this->replace('NAVIGATION', toolbar_action_Navigation($pagename));
219         $this->replace('SEARCH', toolbar_action_SearchActions($pagename,CHARSET));
220
221         $this->replace('page', $page);
222         $this->qreplace('CHARSET', CHARSET);
223         $this->qreplace('PAGE', $pagename);
224         $this->qreplace('PAGEURL', rawurlencode($pagename));
225         $this->qreplace('SPLIT_PAGE', split_pagename($pagename));
226         $this->qreplace('BROWSE_PAGE', WikiURL($pagename));
227
228         $this->replace('EDIT_TIPS', toolbar_Info_EditTips());
229
230         // FIXME: this is a bit of dangerous hackage.
231         $this->qreplace('ACTION', WikiURL($pagename, array('action' => '')));
232
233         // FIXME:?
234         //$this->replace_callback('HITS', array($page, 'getHitCount'));
235         //$this->replace_callback('RELATEDPAGES', array($page, 'getHitCount'));
236         //_dotoken('RELATEDPAGES', LinkRelatedPages($dbi, $name), $page);
237     }
238
239     function setPageRevisionTokens(&$revision) {
240         $page = & $revision->getPage();
241         
242         $current = & $page->getCurrentRevision();
243         $previous = & $page->getRevisionBefore($revision->getVersion());
244
245         $this->replace('VIEW_WARNINGS',
246                        toolbar_Warnings_View($current->getVersion() == $revision->getVersion(),$page->getName()));
247         $this->replace('IS_CURRENT',
248                        $current->getVersion() == $revision->getVersion());
249 //        $this->replace('EDIT_WARNINGS',
250 //                       toolbar_Warnings_Edit(!empty($PREVIEW_CONTENT),
251 //                                             $current->getVersion() == $revision->getVersion()));
252         /*
253         if ($previous && $previous->getVersion() != 0)
254             $this->setConditional('COPY'); // FIXME: should rename HAVE_COPY?
255         */
256         
257         global $datetimeformat;
258         
259         $this->replace('LASTMODIFIED',
260                          toolbar_Info_LastModified(
261                             ($current->getVersion() == $revision->getVersion()),
262                             strftime($datetimeformat, $revision->get('mtime')),
263                             $revision->getVersion() ));
264 //        $this->qreplace('LASTMODIFIED',
265 //                        strftime($datetimeformat, $revision->get('mtime')));
266
267         $this->qreplace('LASTAUTHOR', $revision->get('author'));
268         $this->qreplace('VERSION', $revision->getVersion());
269         $this->qreplace('CURRENT_VERSION', $current->getVersion());
270
271         $this->setPageTokens($page);
272     }
273
274     function setWikiUserTokens(&$user) {
275         /*
276         if ( $user->is_admin() ) {
277             $this->setConditional('ADMIN');
278             $this->setConditional('EDITABLE');
279         }
280         if ( ! $user->is_authenticated() )
281             $this->setConditional('ANONYMOUS');
282         */
283         $this->replace('user', $user);
284         $this->qreplace('USERID', $user->id());
285
286         //WARNING: hackage! $pagename is not available here
287         $pagename="";
288         $this->replace('SIGNIN', toolbar_User_UserSignInOut($user->is_authenticated(), $user->id(), $pagename, $user->is_admin()));
289
290         $prefs = $user->getPreferences();
291         $this->qreplace('EDIT_AREA_WIDTH', $prefs['edit_area.width']);
292         $this->qreplace('EDIT_AREA_HEIGHT', $prefs['edit_area.height']);
293     }
294
295     function setGlobalTokens () {
296         global $user, $logo, $RCS_IDS;
297         
298         // FIXME: This a a bit of dangerous hackage.
299         $this->qreplace('BROWSE', WikiURL(''));
300         $this->replace('CSS', WikiTemplate::__css_links());
301         $this->qreplace('WIKI_NAME', WIKI_NAME);
302
303         if (isset($user))
304             $this->setWikiUserTokens($user);
305         if (isset($logo))
306             $this->replace('LOGO', toolbar_action_Logo(WIKI_NAME, $logo));
307 //            $this->qreplace('LOGO', DataURL($logo));
308         if (isset($RCS_IDS))
309             $this->qreplace('RCS_IDS', $RCS_IDS);
310
311         $this->qreplace('BASE_URL',
312                         // FIXME:
313                         //WikiURL($GLOBALS['pagename'], false, 'absolute_url')
314                         BaseURL()
315                         );
316     }
317
318     
319     function __css_links () {
320         global $CSS_URLS, $CSS_DEFAULT;
321         
322         $html = array();
323         foreach  ($CSS_URLS as $key => $val) {
324             $link = array('rel'     => 'stylesheet',
325                           'title'   => _($key),
326                           'href'    => DataURL($val),
327                           'type'    => 'text/css',
328                           'charset' => CHARSET);
329             // FIXME: why the charset?  Is a style-sheet really ever going to
330             // be other than US-ASCII?
331
332             // The next line is also used by xgettext to localise the word
333             // "Printer" used in the stylesheet's 'title' (see above).
334             if ($key == _("Printer")) {
335                 $link['media'] = 'print, screen';
336             }
337
338             if ($key != $CSS_DEFAULT) {
339                 $link['rel'] = 'alternate stylesheet';
340                 $html[] = Element('link', $link);
341             }
342             else {
343                 // Default CSS should be listed first, otherwise some
344                 // browsers (incl. Galeon) don't seem to treat it as
345                 // default (regardless of whether rel="stylesheet" or
346                 // rel="alternate stylesheet".)
347                 array_unshift($html, Element('link', $link));
348             }
349         }
350         return join("\n", $html);
351     }
352 };
353
354
355 /**
356  * Generate page contents using a template.
357  *
358  * This is a convenience function for backwards compatibility with the old
359  * GeneratePage().
360  *
361  * @param $template string name of the template (see config.php for list of names)
362  *
363  * @param $content string html content to put into the page
364  *
365  * @param $title string page title
366  *
367  * @param $page_revision object Current WikiDB_PageRevision, if available.
368  *
369  * @return string HTML expansion of template.
370  */
371 function GeneratePage($template, $content, $title, $page_revision = false) {
372     // require_once("lib/template.php");
373     $t = new WikiTemplate($template);
374     if ($page_revision)
375         $t->setPageRevisionTokens($page_revision);
376     $t->replace('CONTENT', $content);
377     $t->replace('TITLE', $title);
378     return $t->getExpansion();
379 }
380
381 // Local Variables:
382 // mode: php
383 // tab-width: 8
384 // c-basic-offset: 4
385 // c-hanging-comment-ender-p: nil
386 // indent-tabs-mode: nil
387 // End:   
388 ?>