libs/sysplugins/smarty_internal_template.php Quellcode

smarty_internal_template.php
gehe zur Dokumentation dieser Datei
1 <?php
22 {
28  public $smarty = null;
29 
35  public $template_resource = null;
41  public $templateId = null;
47  public $mustCompile = null;
53  public $has_nocache_code = false;
59  public $properties = array('file_dependency' => array(),
60  'nocache_hash' => '',
61  'tpl_function' => array(),
62  );
68  public $required_plugins = array('compiled' => array(), 'nocache' => array());
74  public $block_data = array();
80  public $variable_filters = array();
86  public $used_tags = array();
92  public $allow_relative_path = false;
98  public $_capture_stack = array(0 => array());
99 
113  public function __construct($template_resource, $smarty, $_parent = null, $_cache_id = null, $_compile_id = null, $_caching = null, $_cache_lifetime = null)
114  {
115  $this->smarty = &$smarty;
116  // Smarty parameter
117  $this->cache_id = $_cache_id === null ? $this->smarty->cache_id : $_cache_id;
118  $this->compile_id = $_compile_id === null ? $this->smarty->compile_id : $_compile_id;
119  $this->caching = $_caching === null ? $this->smarty->caching : $_caching;
120  if ($this->caching === true) {
121  $this->caching = Smarty::CACHING_LIFETIME_CURRENT;
122  }
123  $this->cache_lifetime = $_cache_lifetime === null ? $this->smarty->cache_lifetime : $_cache_lifetime;
124  $this->parent = $_parent;
125  // Template resource
126  $this->template_resource = $template_resource;
127  // copy block data of template inheritance
128  if ($this->parent instanceof Smarty_Internal_Template) {
129  $this->block_data = $this->parent->block_data;
130  }
131  }
132 
140  public function fetch()
141  {
142  return $this->render(true, false, false);
143  }
144 
148  public function display()
149  {
150  $this->render(true, false, true);
151  }
152 
164  public function render($merge_tpl_vars = false, $no_output_filter = true, $display = null)
165  {
166  $parentIsTpl = $this->parent instanceof Smarty_Internal_Template;
167  if ($this->smarty->debugging) {
168  Smarty_Internal_Debug::start_template($this, $display);
169  }
170  $save_tpl_vars = null;
171  $save_config_vars = null;
172  // merge all variable scopes into template
173  if ($merge_tpl_vars) {
174  // save local variables
175  $save_tpl_vars = $this->tpl_vars;
176  $save_config_vars = $this->config_vars;
177  $ptr_array = array($this);
178  $ptr = $this;
179  while (isset($ptr->parent)) {
180  $ptr_array[] = $ptr = $ptr->parent;
181  }
182  $ptr_array = array_reverse($ptr_array);
183  $parent_ptr = reset($ptr_array);
184  $tpl_vars = $parent_ptr->tpl_vars;
185  $config_vars = $parent_ptr->config_vars;
186  while ($parent_ptr = next($ptr_array)) {
187  if (!empty($parent_ptr->tpl_vars)) {
188  $tpl_vars = array_merge($tpl_vars, $parent_ptr->tpl_vars);
189  }
190  if (!empty($parent_ptr->config_vars)) {
191  $config_vars = array_merge($config_vars, $parent_ptr->config_vars);
192  }
193  }
194  if (!empty(Smarty::$global_tpl_vars)) {
196  }
197  $this->tpl_vars = $tpl_vars;
198  $this->config_vars = $config_vars;
199  }
200  // dummy local smarty variable
201  if (!isset($this->tpl_vars['smarty'])) {
202  $this->tpl_vars['smarty'] = new Smarty_Variable;
203  }
204  $_smarty_old_error_level = isset($this->smarty->error_reporting) ? error_reporting($this->smarty->error_reporting) : null;
205  // check URL debugging control
206  if (!$this->smarty->debugging && $this->smarty->debugging_ctrl == 'URL') {
208  }
209  if (!isset($this->source)) {
210  $this->loadSource();
211  }
212  // checks if template exists
213  if (!$this->source->exists) {
214  if ($parentIsTpl) {
215  $parent_resource = " in '{$this->parent->template_resource}'";
216  } else {
217  $parent_resource = '';
218  }
219  throw new SmartyException("Unable to load template {$this->source->type} '{$this->source->name}'{$parent_resource}");
220  }
221  // disable caching for evaluated code
222  if ($this->source->recompiled) {
223  $this->caching = false;
224  }
225  // read from cache or render
226  $isCacheTpl = $this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED;
227  if ($isCacheTpl) {
228  if (!isset($this->cached)) {
229  $this->loadCached();
230  }
231  $this->cached->isCached($this);
232  }
233  if (!($isCacheTpl) || !$this->cached->valid) {
234  if ($isCacheTpl) {
235  $this->properties['tpl_function'] = array();
236  }
237  // render template (not loaded and not in cache)
238  if ($this->smarty->debugging) {
240  }
241  if (!$this->source->uncompiled) {
242  // render compiled code
243  if (!isset($this->compiled)) {
244  $this->loadCompiled();
245  }
246  $content = $this->compiled->render($this);
247  } else {
248  $content = $this->source->renderUncompiled($this);
249  }
250  if (!$this->source->recompiled && empty($this->properties['file_dependency'][$this->source->uid])) {
251  $this->properties['file_dependency'][$this->source->uid] = array($this->source->filepath, $this->source->timestamp, $this->source->type);
252  }
253  if ($parentIsTpl) {
254  $this->parent->properties['file_dependency'] = array_merge($this->parent->properties['file_dependency'], $this->properties['file_dependency']);
255  //$this->parent->properties['tpl_function'] = array_merge($this->parent->properties['tpl_function'], $this->properties['tpl_function']);
256  }
257  if ($this->smarty->debugging) {
259  }
260  // write to cache when necessary
261  if (!$this->source->recompiled && $isCacheTpl) {
262  if ($this->smarty->debugging) {
264  }
265  $this->cached->updateCache($this, $content, $no_output_filter);
266  $compile_check = $this->smarty->compile_check;
267  $this->smarty->compile_check = false;
268  if ($parentIsTpl) {
269  $this->properties['tpl_function'] = $this->parent->properties['tpl_function'];
270  }
271  if (!$this->cached->processed) {
272  $this->cached->process($this);
273  }
274  $this->smarty->compile_check = $compile_check;
275  $content = $this->getRenderedTemplateCode();
276  if ($this->smarty->debugging) {
278  }
279  } else {
280  if (!empty($this->properties['nocache_hash']) && !empty($this->parent->properties['nocache_hash'])) {
281  // replace nocache_hash
282  $content = str_replace("{$this->properties['nocache_hash']}", $this->parent->properties['nocache_hash'], $content);
283  $this->parent->has_nocache_code = $this->parent->has_nocache_code || $this->has_nocache_code;
284  }
285  }
286  } else {
287  if ($this->smarty->debugging) {
289  }
290  $content = $this->cached->render($this);
291  if ($this->smarty->debugging) {
293  }
294  }
295  if ((!$this->caching || $this->has_nocache_code || $this->source->recompiled) && !$no_output_filter && (isset($this->smarty->autoload_filters['output']) || isset($this->smarty->registered_filters['output']))) {
296  $content = Smarty_Internal_Filter_Handler::runFilter('output', $content, $this);
297  }
298  if (isset($_smarty_old_error_level)) {
299  error_reporting($_smarty_old_error_level);
300  }
301  // display or fetch
302  if ($display) {
303  if ($this->caching && $this->smarty->cache_modified_check) {
304  $this->cached->cacheModifiedCheck($this, $content);
305  } else {
306  echo $content;
307  }
308  if ($this->smarty->debugging) {
310  }
311  // debug output
312  if ($this->smarty->debugging) {
314  }
315  if ($merge_tpl_vars) {
316  // restore local variables
317  $this->tpl_vars = $save_tpl_vars;
318  $this->config_vars = $save_config_vars;
319  }
320  return '';
321  } else {
322  if ($merge_tpl_vars) {
323  // restore local variables
324  $this->tpl_vars = $save_tpl_vars;
325  $this->config_vars = $save_config_vars;
326  }
327  if ($this->smarty->debugging) {
329  }
330  if ($this->smarty->debugging == 2 and $display === false) {
331  if ($this->smarty->debugging) {
333  }
334  }
335  if ($parentIsTpl) {
336  $this->parent->properties['tpl_function'] = array_merge($this->parent->properties['tpl_function'], $this->properties['tpl_function']);
337  foreach ($this->required_plugins as $code => $tmp1) {
338  foreach ($tmp1 as $name => $tmp) {
339  foreach ($tmp as $type => $data) {
340  $this->parent->required_plugins[$code][$name][$type] = $data;
341  }
342  }
343  }
344  }
345  // return cache content
346  return $content;
347  }
348  }
349 
356  public function getRenderedTemplateCode()
357  {
358  $level = ob_get_level();
359  try {
360  ob_start();
361  if (empty($this->properties['unifunc']) || !is_callable($this->properties['unifunc'])) {
362  throw new SmartyException("Invalid compiled template for '{$this->template_resource}'");
363  }
364  if (isset($this->smarty->security_policy)) {
365  $this->smarty->security_policy->startTemplate($this);
366  }
367  array_unshift($this->_capture_stack, array());
368  //
369  // render compiled or saved template code
370  //
371  $this->properties['unifunc']($this);
372  // any unclosed {capture} tags ?
373  if (isset($this->_capture_stack[0][0])) {
374  $this->capture_error();
375  }
376  array_shift($this->_capture_stack);
377  if (isset($this->smarty->security_policy)) {
378  $this->smarty->security_policy->exitTemplate($this);
379  }
380  return ob_get_clean();
381  }
382  catch (Exception $e) {
383  while (ob_get_level() > $level) {
384  ob_end_clean();
385  }
386  throw $e;
387  }
388  }
389 
398  public function mustCompile()
399  {
400  if (!$this->source->exists) {
401  if ($this->parent instanceof Smarty_Internal_Template) {
402  $parent_resource = " in '$this->parent->template_resource}'";
403  } else {
404  $parent_resource = '';
405  }
406  throw new SmartyException("Unable to load template {$this->source->type} '{$this->source->name}'{$parent_resource}");
407  }
408  if ($this->mustCompile === null) {
409  $this->mustCompile = (!$this->source->uncompiled && ($this->smarty->force_compile || $this->source->recompiled || $this->compiled->timestamp === false ||
410  ($this->smarty->compile_check && $this->compiled->timestamp < $this->source->timestamp)));
411  }
412 
413  return $this->mustCompile;
414  }
415 
420  public function compileTemplateSource()
421  {
422  return $this->compiled->compileTemplateSource($this);
423  }
424 
432  public function writeCachedContent($content)
433  {
434  return $this->cached->writeCachedContent($this, $content);
435  }
436 
450  public function getSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope)
451  {
452  $tpl = $this->setupSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope);
453  return $tpl->render();
454  }
455 
469  public function setupSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope)
470  {
471  $_templateId = $this->getTemplateId($template, $cache_id, $compile_id);
472  // already in template cache?
473  if (isset($this->smarty->template_objects[$_templateId])) {
474  // clone cached template object because of possible recursive call
475  $tpl = clone $this->smarty->template_objects[$_templateId];
476  $tpl->parent = $this;
477  if ((bool) $tpl->caching !== (bool) $caching) {
478  unset($tpl->compiled);
479  }
480  $tpl->caching = $caching;
481  $tpl->cache_lifetime = $cache_lifetime;
482  } else {
483  $tpl = new $this->smarty->template_class($template, $this->smarty, $this, $cache_id, $compile_id, $caching, $cache_lifetime);
484  $tpl->templateId = $_templateId;
485  }
486  // get variables from calling scope
487  if ($parent_scope == Smarty::SCOPE_LOCAL) {
488  $tpl->tpl_vars = $this->tpl_vars;
489  $tpl->tpl_vars['smarty'] = clone $this->tpl_vars['smarty'];
490  } elseif ($parent_scope == Smarty::SCOPE_PARENT) {
491  $tpl->tpl_vars = &$this->tpl_vars;
492  } elseif ($parent_scope == Smarty::SCOPE_GLOBAL) {
493  $tpl->tpl_vars = &Smarty::$global_tpl_vars;
494  } elseif (($scope_ptr = $this->getScopePointer($parent_scope)) == null) {
495  $tpl->tpl_vars = &$this->tpl_vars;
496  } else {
497  $tpl->tpl_vars = &$scope_ptr->tpl_vars;
498  }
499  $tpl->config_vars = $this->config_vars;
500  if (!empty($data)) {
501  // set up variable values
502  foreach ($data as $_key => $_val) {
503  $tpl->tpl_vars[$_key] = new Smarty_Variable($_val);
504  }
505  }
506  $tpl->properties['tpl_function'] = $this->properties['tpl_function'];
507  return $tpl;
508  }
509 
525  public function getInlineSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope, $hash, $content_func)
526  {
527  $tpl = $this->setupSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope);
528  $tpl->properties['nocache_hash'] = $hash;
529  if (!isset($this->smarty->template_objects[$tpl->templateId])) {
530  $this->smarty->template_objects[$tpl->templateId] = $tpl;
531  }
532  if ($this->smarty->debugging) {
535  }
536  $tpl->properties['unifunc'] = $content_func;
537  $output = $tpl->getRenderedTemplateCode();
538  if ($this->smarty->debugging) {
541  }
542  if (!empty($tpl->properties['file_dependency'])) {
543  $this->properties['file_dependency'] = array_merge($this->properties['file_dependency'], $tpl->properties['file_dependency']);
544  }
545  $this->properties['tpl_function'] = $tpl->properties['tpl_function'];
546  return str_replace($tpl->properties['nocache_hash'], $this->properties['nocache_hash'], $output);
547  }
548 
559  public function callTemplateFunction($name, Smarty_Internal_Template $_smarty_tpl, $params, $nocache)
560  {
561  if (isset($_smarty_tpl->properties['tpl_function'][$name])) {
562  if (!$_smarty_tpl->caching || ($_smarty_tpl->caching && $nocache)) {
563  $function = $_smarty_tpl->properties['tpl_function'][$name]['call_name'];
564  } else {
565  if (isset($_smarty_tpl->properties['tpl_function'][$name]['call_name_caching'])) {
566  $function = $_smarty_tpl->properties['tpl_function'][$name]['call_name_caching'];
567  } else {
568  $function = $_smarty_tpl->properties['tpl_function'][$name]['call_name'];
569  }
570  }
571  if (function_exists($function)) {
572  $function ($_smarty_tpl, $params);
573  return;
574  }
575  // try to load template function dynamically
576  if (Smarty_Internal_Function_Call_Handler::call($name, $_smarty_tpl, $function, $params, $nocache)) {
577  $function ($_smarty_tpl, $params);
578  return;
579  }
580  }
581  throw new SmartyException("Unable to find template function '{$name}'");
582  }
583 
594  public function decodeProperties($properties, $cache = false)
595  {
596  $properties['version'] = (isset($properties['version'])) ? $properties['version'] : '';
597  $is_valid = true;
598  if (Smarty::SMARTY_VERSION != $properties['version']) {
599  // new version must rebuild
600  $is_valid = false;
601  } elseif ((!$cache && $this->smarty->compile_check || $cache && ($this->smarty->compile_check === true || $this->smarty->compile_check === Smarty::COMPILECHECK_ON)) && !empty($properties['file_dependency'])) {
602  // check file dependencies at compiled code
603  foreach ($properties['file_dependency'] as $_file_to_check) {
604  if ($_file_to_check[2] == 'file' || $_file_to_check[2] == 'php') {
605  if ($this->source->filepath == $_file_to_check[0] && isset($this->source->timestamp)) {
606  // do not recheck current template
607  $mtime = $this->source->timestamp;
608  } else {
609  // file and php types can be checked without loading the respective resource handlers
610  $mtime = is_file($_file_to_check[0]) ? @filemtime($_file_to_check[0]) : false;
611  }
612  } elseif ($_file_to_check[2] == 'string') {
613  continue;
614  } else {
615  $source = Smarty_Resource::source(null, $this->smarty, $_file_to_check[0]);
616  $mtime = $source->timestamp;
617  }
618  if (!$mtime || $mtime > $_file_to_check[1]) {
619  $is_valid = false;
620  break;
621  }
622  }
623  }
624  if ($cache) {
625  // CACHING_LIFETIME_SAVED cache expiry has to be validated here since otherwise we'd define the unifunc
626  if ($this->caching === Smarty::CACHING_LIFETIME_SAVED &&
627  $properties['cache_lifetime'] >= 0 &&
628  (time() > ($this->cached->timestamp + $properties['cache_lifetime']))
629  ) {
630  $is_valid = false;
631  }
632  $this->cached->valid = $is_valid;
633  } else {
634  $this->mustCompile = !$is_valid;
635  }
636  if ($is_valid) {
637  $this->has_nocache_code = $properties['has_nocache_code'];
638  // $this->properties['nocache_hash'] = $properties['nocache_hash'];
639  if (isset($properties['cache_lifetime'])) {
640  $this->properties['cache_lifetime'] = $properties['cache_lifetime'];
641  }
642  if (isset($properties['file_dependency'])) {
643  $this->properties['file_dependency'] = array_merge($this->properties['file_dependency'], $properties['file_dependency']);
644  }
645  if (isset($properties['tpl_function'])) {
646  $this->properties['tpl_function'] = array_merge($this->properties['tpl_function'], $properties['tpl_function']);
647  }
648  $this->properties['version'] = $properties['version'];
649  $this->properties['unifunc'] = $properties['unifunc'];
650  }
651  return $is_valid;
652  }
653 
661  public function createLocalArrayVariable($tpl_var, $nocache = false, $scope = Smarty::SCOPE_LOCAL)
662  {
663  if (!isset($this->tpl_vars[$tpl_var])) {
664  $this->tpl_vars[$tpl_var] = new Smarty_Variable(array(), $nocache, $scope);
665  } else {
666  $this->tpl_vars[$tpl_var] = clone $this->tpl_vars[$tpl_var];
667  if ($scope != Smarty::SCOPE_LOCAL) {
668  $this->tpl_vars[$tpl_var]->scope = $scope;
669  }
670  if (!(is_array($this->tpl_vars[$tpl_var]->value) || $this->tpl_vars[$tpl_var]->value instanceof ArrayAccess)) {
671  settype($this->tpl_vars[$tpl_var]->value, 'array');
672  }
673  }
674  }
675 
683  public function &getScope($scope)
684  {
685  if ($scope == Smarty::SCOPE_PARENT && !empty($this->parent)) {
686  return $this->parent->tpl_vars;
687  } elseif ($scope == Smarty::SCOPE_ROOT && !empty($this->parent)) {
688  $ptr = $this->parent;
689  while (!empty($ptr->parent)) {
690  $ptr = $ptr->parent;
691  }
692 
693  return $ptr->tpl_vars;
694  } elseif ($scope == Smarty::SCOPE_GLOBAL) {
696  }
697  $null = null;
698 
699  return $null;
700  }
701 
709  public function getScopePointer($scope)
710  {
711  if ($scope == Smarty::SCOPE_PARENT && !empty($this->parent)) {
712  return $this->parent;
713  } elseif ($scope == Smarty::SCOPE_ROOT && !empty($this->parent)) {
714  $ptr = $this->parent;
715  while (!empty($ptr->parent)) {
716  $ptr = $ptr->parent;
717  }
718 
719  return $ptr;
720  }
721 
722  return null;
723  }
724 
733  public function _count($value)
734  {
735  if (is_array($value) === true || $value instanceof Countable) {
736  return count($value);
737  } elseif ($value instanceof IteratorAggregate) {
738  // Note: getIterator() returns a Traversable, not an Iterator
739  // thus rewind() and valid() methods may not be present
740  return iterator_count($value->getIterator());
741  } elseif ($value instanceof Iterator) {
742  return iterator_count($value);
743  } elseif ($value instanceof PDOStatement) {
744  return $value->rowCount();
745  } elseif ($value instanceof Traversable) {
746  return iterator_count($value);
747  } elseif ($value instanceof ArrayAccess) {
748  if ($value->offsetExists(0)) {
749  return 1;
750  }
751  } elseif (is_object($value)) {
752  return count($value);
753  }
754 
755  return 0;
756  }
757 
761  public function capture_error()
762  {
763  throw new SmartyException("Not matching {capture} open/close in \"{$this->template_resource}\"");
764  }
765 
773  public function clearCache($exp_time = null)
774  {
776 
777  return $this->cached->handler->clear($this->smarty, $this->template_resource, $this->cache_id, $this->compile_id, $exp_time);
778  }
779 
785  public function loadSource()
786  {
787  $this->source = Smarty_Template_Source::load($this);
788  if ($this->smarty->template_resource_caching && !$this->source->recompiled && isset($this->templateId)) {
789  $this->smarty->template_objects[$this->templateId] = $this;
790  }
791  }
792 
797  public function loadCompiled()
798  {
799  if (!isset($this->compiled)) {
800  if (!class_exists('Smarty_Template_Compiled', false)) {
801  require SMARTY_SYSPLUGINS_DIR . 'smarty_template_compiled.php';
802  }
803  $this->compiled = Smarty_Template_Compiled::load($this);
804  }
805  }
806 
811  public function loadCached()
812  {
813  if (!isset($this->cached)) {
814  if (!class_exists('Smarty_Template_Cached', false)) {
815  require SMARTY_SYSPLUGINS_DIR . 'smarty_template_cached.php';
816  }
817  $this->cached = Smarty_Template_Cached::load($this);
818  }
819  }
820 
826  public function loadCompiler()
827  {
828  $this->smarty->loadPlugin($this->source->compiler_class);
829  $this->compiler = new $this->source->compiler_class($this->source->template_lexer_class, $this->source->template_parser_class, $this->smarty);
830  }
831 
841  public function __call($name, $args)
842  {
843  // method of Smarty object?
844  if (method_exists($this->smarty, $name)) {
845  return call_user_func_array(array($this->smarty, $name), $args);
846  }
847  // parent
848  return parent::__call($name, $args);
849  }
850 
859  public function __set($property_name, $value)
860  {
861  switch ($property_name) {
862  case 'source':
863  case 'compiled':
864  case 'cached':
865  case 'compiler':
866  $this->$property_name = $value;
867  return;
868  default:
869  // Smarty property ?
870  if (property_exists($this->smarty, $property_name)) {
871  $this->smarty->$property_name = $value;
872  return;
873  }
874  }
875  throw new SmartyException("invalid template property '$property_name'.");
876  }
877 
886  public function __get($property_name)
887  {
888  switch ($property_name) {
889  case 'source':
890  $this->loadSource();
891  return $this->source;
892 
893  case 'compiled':
894  $this->loadCompiled();
895  return $this->compiled;
896 
897  case 'cached':
898  $this->loadCached();
899  return $this->cached;
900 
901  case 'compiler':
902  $this->loadCompiler();
903  return $this->compiler;
904  default:
905  // Smarty property ?
906  if (property_exists($this->smarty, $property_name)) {
907  return $this->smarty->$property_name;
908  }
909  }
910  throw new SmartyException("template property '$property_name' does not exist.");
911  }
912 
916  public function __destruct()
917  {
918  if ($this->smarty->cache_locking && isset($this->cached) && $this->cached->is_locked) {
919  $this->cached->handler->releaseLock($this->smarty, $this->cached);
920  }
921  }
922 }




Korrekturen, Hinweise und Ergänzungen

Bitte scheuen Sie sich nicht und melden Sie, was auf dieser Seite sachlich falsch oder irreführend ist, was ergänzt werden sollte, was fehlt usw. Dazu bitte oben aus dem Menü Seite den Eintrag Support Forum wählen. Es ist eine kostenlose Anmeldung erforderlich, um Anmerkungen zu posten. Unpassende Postings, Spam usw. werden kommentarlos entfernt.