source: branches/2.0/include/template.class.php @ 3191

Last change on this file since 3191 was 3191, checked in by patdenice, 15 years ago

merge part of r3190 from trunk to branch 2.0.
URL parameter for template extensions can be used in slideshow.

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Author Date Id Revision
File size: 14.3 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based picture gallery                                  |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008-2009 Piwigo Team                  http://piwigo.org |
6// | Copyright(C) 2003-2008 PhpWebGallery Team    http://phpwebgallery.net |
7// | Copyright(C) 2002-2003 Pierrick LE GALL   http://le-gall.net/pierrick |
8// +-----------------------------------------------------------------------+
9// | This program is free software; you can redistribute it and/or modify  |
10// | it under the terms of the GNU General Public License as published by  |
11// | the Free Software Foundation                                          |
12// |                                                                       |
13// | This program is distributed in the hope that it will be useful, but   |
14// | WITHOUT ANY WARRANTY; without even the implied warranty of            |
15// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
16// | General Public License for more details.                              |
17// |                                                                       |
18// | You should have received a copy of the GNU General Public License     |
19// | along with this program; if not, write to the Free Software           |
20// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
21// | USA.                                                                  |
22// +-----------------------------------------------------------------------+
23
24
25require_once(PHPWG_ROOT_PATH.'include/smarty/libs/Smarty.class.php');
26
27// migrate lang:XXX
28//    sed "s/{lang:\([^}]\+\)}/{\'\1\'|@translate}/g" my_template.tpl
29// migrate change root level vars {XXX}
30//    sed "s/{pwg_root}/{ROOT_URL}/g" my_template.tpl
31// migrate change root level vars {XXX}
32//    sed "s/{\([a-zA-Z_]\+\)}/{$\1}/g" my_template.tpl
33// migrate all
34//    cat my_template.tpl | sed "s/{lang:\([^}]\+\)}/{\'\1\'|@translate}/g" | sed "s/{pwg_root}/{ROOT_URL}/g" | sed "s/{\([a-zA-Z_]\+\)}/{$\1}/g"
35
36
37class Template {
38
39  var $smarty;
40
41  var $output = '';
42
43  // Hash of filenames for each template handle.
44  var $files = array();
45
46  // Template extents filenames for each template handle.
47  var $extents = array();
48
49  // used by html_head smarty block to add content before </head>
50  var $html_head_elements = array();
51
52  function Template($root = ".", $theme= "")
53  {
54    global $conf, $lang_info;
55
56    $this->smarty = new Smarty;
57    $this->smarty->debugging = $conf['debug_template'];
58    $this->smarty->compile_check=$conf['template_compile_check'];
59
60    $compile_dir = $conf['local_data_dir'].'/templates_c';
61    mkgetdir( $compile_dir );
62
63    $this->smarty->compile_dir = $compile_dir;
64
65    $this->smarty->assign_by_ref( 'pwg', new PwgTemplateAdapter() );
66    $this->smarty->register_modifier( 'translate', array('Template', 'mod_translate') );
67    $this->smarty->register_modifier( 'explode', array('Template', 'mod_explode') );
68    $this->smarty->register_modifier( 'get_extent', array(&$this, 'get_extent') );
69    $this->smarty->register_block('html_head', array(&$this, 'block_html_head') );
70    $this->smarty->register_function('known_script', array(&$this, 'func_known_script') );
71    $this->smarty->register_prefilter( array('Template', 'prefilter_white_space') );
72    if ( $conf['compiled_template_cache_language'] )
73    {
74      $this->smarty->register_prefilter( array('Template', 'prefilter_language') );
75    }
76
77    if ( !empty($theme) )
78    {
79      include($root.'/theme/'.$theme.'/themeconf.inc.php');
80      $this->smarty->assign('themeconf', $themeconf);
81    }
82
83    $this->smarty->assign('lang_info', $lang_info);
84
85    $this->set_template_dir($root);
86
87    if (!defined('IN_ADMIN') and isset($conf['extents_for_templates']))
88    {
89      $tpl_extents = unserialize($conf['extents_for_templates']);
90      $this->set_extents($tpl_extents, './template-extension/', true);
91    }
92  }
93
94  /**
95   * Sets the template root directory for this Template object.
96   */
97  function set_template_dir($dir)
98  {
99    $this->smarty->template_dir = $dir;
100
101    $real_dir = realpath($dir);
102    $compile_id = crc32( $real_dir===false ? $dir : $real_dir);
103    $this->smarty->compile_id = base_convert($compile_id, 10, 36 );
104  }
105
106  /**
107   * Gets the template root directory for this Template object.
108   */
109  function get_template_dir()
110  {
111    return $this->smarty->template_dir;
112  }
113
114  /**
115   * Deletes all compiled templates.
116   */
117  function delete_compiled_templates()
118  {
119      $save_compile_id = $this->smarty->compile_id;
120      $this->smarty->compile_id = null;
121      $this->smarty->clear_compiled_tpl();
122      $this->smarty->compile_id = $save_compile_id;
123      file_put_contents($this->smarty->compile_dir.'/index.htm', 'Not allowed!');
124  }
125
126  function get_themeconf($val)
127  {
128    $tc = $this->smarty->get_template_vars('themeconf');
129    return isset($tc[$val]) ? $tc[$val] : '';
130  }
131
132  /**
133   * Sets the template filename for handle.
134   */
135  function set_filename($handle, $filename)
136  {
137    return $this->set_filenames( array($handle=>$filename) );
138  }
139
140  /**
141   * Sets the template filenames for handles. $filename_array should be a
142   * hash of handle => filename pairs.
143   */
144  function set_filenames($filename_array)
145  {
146    if (!is_array($filename_array))
147    {
148      return false;
149    }
150    reset($filename_array);
151    while(list($handle, $filename) = each($filename_array))
152    {
153      if (is_null($filename))
154      {
155        unset($this->files[$handle]);
156      }
157      else
158      {
159        $this->files[$handle] = $this->get_extent($filename, $handle);
160      }
161    }
162    return true;
163  }
164
165  /**
166   * Sets template extention filename for handles.
167   */
168  function set_extent($filename, $param, $dir='', $overwrite=true)
169  {
170    return $this->set_extents(array($filename => $param), $dir, $overwrite);
171  }
172
173  /**
174   * Sets template extentions filenames for handles.
175   * $filename_array should be an hash of filename => array( handle, param) or filename => handle
176   */
177  function set_extents($filename_array, $dir='', $overwrite=true)
178  {
179    if (!is_array($filename_array))
180    {
181      return false;
182    }
183    foreach ($filename_array as $filename => $value)
184    {
185      if (is_array($value))
186      {
187        $handle = $value[0];
188        $param = $value[1];
189        $tpl = $value[2];
190      }
191      elseif (is_string($value))
192      {
193        $handle = $value;
194        $param = 'N/A';
195        $tpl = 'N/A';
196      }
197      else
198      {
199        return false;
200      }
201
202      if ((stripos(implode('/',array_keys($_GET)), $param) > 0 or $param == 'N/A')
203        and (preg_match('/'.preg_quote($tpl,'/').'$/', $this->get_template_dir()) or $tpl == 'N/A')
204        and (!isset($this->extents[$handle]) or $overwrite)
205        and file_exists($dir . $filename))
206      {
207        $this->extents[$handle] = realpath($dir . $filename);
208      }
209    }
210    return true;
211  }
212
213  /** return template extension if exists  */
214  function get_extent($filename='', $handle='')
215  {
216    if (isset($this->extents[$handle]))
217    {
218      $filename = $this->extents[$handle];
219    }
220    return $filename;
221  }
222
223  /** see smarty assign http://www.smarty.net/manual/en/api.assign.php */
224  function assign($tpl_var, $value = null)
225  {
226    $this->smarty->assign( $tpl_var, $value );
227  }
228
229  /**
230   * Inserts the uncompiled code for $handle as the value of $varname in the
231   * root-level. This can be used to effectively include a template in the
232   * middle of another template.
233   * This is equivalent to assign($varname, $this->parse($handle, true))
234   */
235  function assign_var_from_handle($varname, $handle)
236  {
237    $this->assign($varname, $this->parse($handle, true));
238    return true;
239  }
240
241  /** see smarty append http://www.smarty.net/manual/en/api.append.php */
242  function append($tpl_var, $value=null, $merge=false)
243  {
244    $this->smarty->append( $tpl_var, $value, $merge );
245  }
246
247  /**
248   * Root-level variable concatenation. Appends a  string to an existing
249   * variable assignment with the same name.
250   */
251  function concat($tpl_var, $value)
252  {
253    $old_val = & $this->smarty->get_template_vars($tpl_var);
254    if ( isset($old_val) )
255    {
256      $old_val .= $value;
257    }
258    else
259    {
260      $this->assign($tpl_var, $value);
261    }
262  }
263
264  /** see smarty append http://www.smarty.net/manual/en/api.clear_assign.php */
265  function clear_assign($tpl_var)
266  {
267    $this->smarty->clear_assign( $tpl_var );
268  }
269
270  /** see smarty get_template_vars http://www.smarty.net/manual/en/api.get_template_vars.php */
271  function &get_template_vars($name=null)
272  {
273    return $this->smarty->get_template_vars( $name );
274  }
275
276
277  /**
278   * Load the file for the handle, eventually compile the file and run the compiled
279   * code. This will add the output to the results or return the result if $return
280   * is true.
281   */
282  function parse($handle, $return=false)
283  {
284    if ( !isset($this->files[$handle]) )
285    {
286      fatal_error("Template->parse(): Couldn't load template file for handle $handle");
287    }
288
289    $this->smarty->assign( 'ROOT_URL', get_root_url() );
290    $this->smarty->assign( 'TAG_INPUT_ENABLED',
291      ((is_adviser()) ? 'disabled="disabled" onclick="return false;"' : ''));
292
293    global $conf, $lang_info;
294    if ( $conf['compiled_template_cache_language'] and isset($lang_info['code']) )
295    {
296      $save_compile_id = $this->smarty->compile_id;
297      $this->smarty->compile_id .= '.'.$lang_info['code'];
298    }
299
300    $v = $this->smarty->fetch($this->files[$handle], null, null, false);
301
302    if (isset ($save_compile_id) )
303    {
304      $this->smarty->compile_id = $save_compile_id;
305    }
306
307    if ($return)
308    {
309      return $v;
310    }
311    $this->output .= $v;
312  }
313
314  /**
315   * Load the file for the handle, eventually compile the file and run the compiled
316   * code. This will print out the results of executing the template.
317   */
318  function pparse($handle)
319  {
320    $this->parse($handle, false);
321    $this->flush();
322  }
323
324  function flush()
325  {
326    if ( count($this->html_head_elements) )
327    {
328      $search = "\n</head>";
329      $pos = strpos( $this->output, $search );
330      if ($pos !== false)
331      {
332        $this->output = substr_replace( $this->output, "\n".implode( "\n", $this->html_head_elements ), $pos, 0 );
333      } //else maybe error or warning ?
334      $this->html_head_elements = array();
335    }
336    echo $this->output;
337    $this->output='';
338  }
339
340  /** flushes the output */
341  function p()
342  {
343    $this->flush();
344
345    if ($this->smarty->debugging)
346    {
347      global $t2;
348      $this->smarty->assign(
349        array(
350        'AAAA_DEBUG_TOTAL_TIME__' => get_elapsed_time($t2, get_moment())
351        )
352        );
353      require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php');
354      echo smarty_core_display_debug_console(null, $this->smarty);
355    }
356  }
357
358  /**
359   * translate variable modifier - translates a text to the currently loaded
360   * language
361   */
362  static function mod_translate($text)
363  {
364    return l10n($text);
365  }
366
367  /**
368   * explode variable modifier - similar to php explode
369   * 'Yes;No'|@explode:';' -> array('Yes', 'No')
370   */
371  static function mod_explode($text, $delimiter=',')
372  {
373    return explode($delimiter, $text);
374  }
375
376  /**
377   * This smarty "html_head" block allows to add content just before
378   * </head> element in the output after the head has been parsed. This is
379   * handy in order to respect strict standards when <style> and <link>
380   * html elements must appear in the <head> element
381   */
382  function block_html_head($params, $content, &$smarty, &$repeat)
383  {
384    $content = trim($content);
385    if ( !empty($content) )
386    { // second call
387      $this->html_head_elements[] = $content;
388    }
389  }
390
391 /**
392   * This smarty "known_script" functions allows to insert well known java scripts
393   * such as prototype, jquery, etc... only once. Examples:
394   * {known_script id="jquery" src="{$ROOT_URL}template-common/lib/jquery.packed.js"}
395   */
396  function func_known_script($params, &$smarty )
397  {
398    if (!isset($params['id']))
399    {
400        $smarty->trigger_error("known_script: missing 'id' parameter");
401        return;
402    }
403    $id = $params['id'];
404    if (! isset( $this->known_scripts[$id] ) )
405    {
406      if (!isset($params['src']))
407      {
408          $smarty->trigger_error("known_script: missing 'src' parameter");
409          return;
410      }
411      $this->known_scripts[$id] = $params['src'];
412      $content = '<script type="text/javascript" src="'.$params['src'].'"></script>';
413      if (isset($params['now']) and $params['now'] and empty($this->output) )
414      {
415        return $content;
416      }
417      $repeat = false;
418      $this->block_html_head(null, $content, $smarty, $repeat);
419    }
420  }
421
422  static function prefilter_white_space($source, &$smarty)
423  {
424    $ld = $smarty->left_delimiter;
425    $rd = $smarty->right_delimiter;
426    $ldq = preg_quote($ld, '#');
427    $rdq = preg_quote($rd, '#');
428
429    $regex = array();
430    $tags = array('if', 'foreach', 'section');
431    foreach($tags as $tag)
432    {
433      array_push($regex, "#^[ \t]+($ldq$tag"."[^$ld$rd]*$rdq)\s*$#m");
434      array_push($regex, "#^[ \t]+($ldq/$tag$rdq)\s*$#m");
435    }
436    $tags = array('include', 'else', 'html_head');
437    foreach($tags as $tag)
438    {
439      array_push($regex, "#^[ \t]+($ldq$tag"."[^$ld$rd]*$rdq)\s*$#m");
440    }
441    $source = preg_replace( $regex, "$1", $source);
442    return $source;
443  }
444
445  /**
446   * Smarty prefilter to allow caching (whenever possible) language strings
447   * from templates.
448   */
449  static function prefilter_language($source, &$smarty)
450  {
451    global $lang;
452    $ldq = preg_quote($smarty->left_delimiter, '~');
453    $rdq = preg_quote($smarty->right_delimiter, '~');
454
455    $regex = "~$ldq *\'([^'$]+)\'\|@translate *$rdq~";
456    $source = preg_replace( $regex.'e', 'isset($lang[\'$1\']) ? $lang[\'$1\'] : \'$0\'', $source);
457
458    $regex = "~$ldq *\'([^'$]+)\'\|@translate\|~";
459    $source = preg_replace( $regex.'e', 'isset($lang[\'$1\']) ? \'{\'.var_export($lang[\'$1\'],true).\'|\' : \'$0\'', $source);
460
461    $regex = "~($ldq *assign +var=.+ +value=)\'([^'$]+)\'\|@translate~e";
462    $source = preg_replace( $regex, 'isset($lang[\'$2\']) ? \'$1\'.var_export($lang[\'$2\'],true) : \'$0\'', $source);
463
464    return $source;
465  }
466}
467
468/**
469 * This class contains basic functions that can be called directly from the
470 * templates in the form $pwg->l10n('edit')
471 */
472class PwgTemplateAdapter
473{
474  function l10n($text)
475  {
476    return l10n($text);
477  }
478
479  function l10n_dec($s, $p, $v)
480  {
481    return l10n_dec($s, $p, $v);
482  }
483
484  function sprintf()
485  {
486    $args = func_get_args();
487    return call_user_func_array('sprintf',  $args );
488  }
489}
490
491?>
Note: See TracBrowser for help on using the repository browser.