1: <?php
2: 3: 4: 5: 6: 7: 8: 9:
10:
11: 12: 13: 14: 15: 16: 17: 18: 19:
20: class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
21: {
22: 23: 24: 25: 26:
27: public $cache_id = null;
28: 29: 30: 31:
32: public $compile_id = null;
33: 34: 35: 36: 37:
38: public $caching = null;
39: 40: 41: 42: 43:
44: public $cache_lifetime = null;
45: 46: 47: 48: 49:
50: public $template_resource = null;
51: 52: 53: 54: 55:
56: public $mustCompile = null;
57: 58: 59: 60: 61:
62: public $has_nocache_code = false;
63: 64: 65: 66: 67:
68: public $properties = array('file_dependency' => array(),
69: 'nocache_hash' => '',
70: 'function' => array());
71: 72: 73: 74: 75:
76: public $required_plugins = array('compiled' => array(), 'nocache' => array());
77: 78: 79: 80: 81:
82: public $smarty = null;
83: 84: 85: 86: 87:
88: public $block_data = array();
89: 90: 91: 92: 93:
94: public $variable_filters = array();
95: 96: 97: 98: 99:
100: public $used_tags = array();
101: 102: 103: 104: 105:
106: public $allow_relative_path = false;
107: 108: 109: 110: 111:
112: public $_capture_stack = array(0 => array());
113:
114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126:
127: public function __construct($template_resource, $smarty, $_parent = null, $_cache_id = null, $_compile_id = null, $_caching = null, $_cache_lifetime = null)
128: {
129: $this->smarty = & $smarty;
130:
131: $this->cache_id = $_cache_id === null ? $this->smarty->cache_id : $_cache_id;
132: $this->compile_id = $_compile_id === null ? $this->smarty->compile_id : $_compile_id;
133: $this->caching = $_caching === null ? $this->smarty->caching : $_caching;
134: if ($this->caching === true) {
135: $this->caching = Smarty::CACHING_LIFETIME_CURRENT;
136: }
137: $this->cache_lifetime = $_cache_lifetime === null ? $this->smarty->cache_lifetime : $_cache_lifetime;
138: $this->parent = $_parent;
139:
140: $this->template_resource = $template_resource;
141:
142: if ($this->parent instanceof Smarty_Internal_Template) {
143: $this->block_data = $this->parent->block_data;
144: }
145: }
146:
147: 148: 149: 150: 151: 152: 153:
154: public function mustCompile()
155: {
156: if (!$this->source->exists) {
157: if ($this->parent instanceof Smarty_Internal_Template) {
158: $parent_resource = " in '$this->parent->template_resource}'";
159: } else {
160: $parent_resource = '';
161: }
162: throw new SmartyException("Unable to load template {$this->source->type} '{$this->source->name}'{$parent_resource}");
163: }
164: if ($this->mustCompile === null) {
165: $this->mustCompile = (!$this->source->uncompiled && ($this->smarty->force_compile || $this->source->recompiled || $this->compiled->timestamp === false ||
166: ($this->smarty->compile_check && $this->compiled->timestamp < $this->source->timestamp)));
167: }
168:
169: return $this->mustCompile;
170: }
171:
172: 173: 174: 175:
176: public function compileTemplateSource()
177: {
178: if (!$this->source->recompiled) {
179: $this->properties['file_dependency'] = array();
180: if ($this->source->components) {
181:
182:
183:
184:
185: } else {
186: $this->properties['file_dependency'][$this->source->uid] = array($this->source->filepath, $this->source->timestamp, $this->source->type);
187: }
188: }
189:
190: if ($this->smarty->compile_locking && !$this->source->recompiled) {
191: if ($saved_timestamp = $this->compiled->timestamp) {
192: touch($this->compiled->filepath);
193: }
194: }
195:
196: try {
197: $code = $this->compiler->compileTemplate($this);
198: }
199: catch (Exception $e) {
200:
201: if ($this->smarty->compile_locking && !$this->source->recompiled && $saved_timestamp) {
202: touch($this->compiled->filepath, $saved_timestamp);
203: }
204: throw $e;
205: }
206:
207: if (!$this->source->recompiled && $this->compiler->write_compiled_code) {
208:
209: $_filepath = $this->compiled->filepath;
210: if ($_filepath === false) {
211: throw new SmartyException('getCompiledFilepath() did not return a destination to save the compiled template to');
212: }
213: Smarty_Internal_Write_File::writeFile($_filepath, $code, $this->smarty);
214: $this->compiled->exists = true;
215: $this->compiled->isCompiled = true;
216: }
217:
218: unset($this->compiler);
219: }
220:
221: 222: 223: 224: 225: 226: 227:
228: public function writeCachedContent($content)
229: {
230: if ($this->source->recompiled || !($this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED)) {
231:
232: return false;
233: }
234: $this->cached->timestamp = time();
235: $this->properties['cache_lifetime'] = $this->cache_lifetime;
236: $this->properties['unifunc'] = 'content_' . str_replace(array('.', ','), '_', uniqid('', true));
237: $content = $this->createTemplateCodeFrame($content, true);
238: 239: 240:
241: $_smarty_tpl = $this;
242: eval("?>" . $content);
243: $this->cached->valid = true;
244: $this->cached->processed = true;
245:
246: return $this->cached->write($this, $content);
247: }
248:
249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261:
262: public function getSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope)
263: {
264:
265: if ($this->smarty->allow_ambiguous_resources) {
266: $_templateId = Smarty_Resource::getUniqueTemplateName($this, $template) . $cache_id . $compile_id;
267: } else {
268: $_templateId = $this->smarty->joined_template_dir . '#' . $template . $cache_id . $compile_id;
269: }
270:
271: if (isset($_templateId[150])) {
272: $_templateId = sha1($_templateId);
273: }
274: if (isset($this->smarty->template_objects[$_templateId])) {
275:
276: $tpl = clone $this->smarty->template_objects[$_templateId];
277: $tpl->parent = $this;
278: $tpl->caching = $caching;
279: $tpl->cache_lifetime = $cache_lifetime;
280: } else {
281: $tpl = new $this->smarty->template_class($template, $this->smarty, $this, $cache_id, $compile_id, $caching, $cache_lifetime);
282: }
283:
284: if ($parent_scope == Smarty::SCOPE_LOCAL) {
285: $tpl->tpl_vars = $this->tpl_vars;
286: $tpl->tpl_vars['smarty'] = clone $this->tpl_vars['smarty'];
287: } elseif ($parent_scope == Smarty::SCOPE_PARENT) {
288: $tpl->tpl_vars = & $this->tpl_vars;
289: } elseif ($parent_scope == Smarty::SCOPE_GLOBAL) {
290: $tpl->tpl_vars = & Smarty::$global_tpl_vars;
291: } elseif (($scope_ptr = $this->getScopePointer($parent_scope)) == null) {
292: $tpl->tpl_vars = & $this->tpl_vars;
293: } else {
294: $tpl->tpl_vars = & $scope_ptr->tpl_vars;
295: }
296: $tpl->config_vars = $this->config_vars;
297: if (!empty($data)) {
298:
299: foreach ($data as $_key => $_val) {
300: $tpl->tpl_vars[$_key] = new Smarty_variable($_val);
301: }
302: }
303:
304: return $tpl->fetch(null, null, null, null, false, false, true);
305: }
306:
307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320:
321: public function setupInlineSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope, $hash)
322: {
323: $tpl = new $this->smarty->template_class($template, $this->smarty, $this, $cache_id, $compile_id, $caching, $cache_lifetime);
324: $tpl->properties['nocache_hash'] = $hash;
325:
326: if ($parent_scope == Smarty::SCOPE_LOCAL) {
327: $tpl->tpl_vars = $this->tpl_vars;
328: $tpl->tpl_vars['smarty'] = clone $this->tpl_vars['smarty'];
329: } elseif ($parent_scope == Smarty::SCOPE_PARENT) {
330: $tpl->tpl_vars = & $this->tpl_vars;
331: } elseif ($parent_scope == Smarty::SCOPE_GLOBAL) {
332: $tpl->tpl_vars = & Smarty::$global_tpl_vars;
333: } elseif (($scope_ptr = $this->getScopePointer($parent_scope)) == null) {
334: $tpl->tpl_vars = & $this->tpl_vars;
335: } else {
336: $tpl->tpl_vars = & $scope_ptr->tpl_vars;
337: }
338: $tpl->config_vars = $this->config_vars;
339: if (!empty($data)) {
340:
341: foreach ($data as $_key => $_val) {
342: $tpl->tpl_vars[$_key] = new Smarty_variable($_val);
343: }
344: }
345:
346: return $tpl;
347: }
348:
349: 350: 351: 352: 353: 354: 355: 356:
357: public function createTemplateCodeFrame($content = '', $cache = false)
358: {
359: $plugins_string = '';
360:
361: if (!$cache) {
362: if (!empty($this->required_plugins['compiled'])) {
363: $plugins_string = '<?php ';
364: foreach ($this->required_plugins['compiled'] as $tmp) {
365: foreach ($tmp as $data) {
366: $file = addslashes($data['file']);
367: if (is_Array($data['function'])) {
368: $plugins_string .= "if (!is_callable(array('{$data['function'][0]}','{$data['function'][1]}'))) include '{$file}';\n";
369: } else {
370: $plugins_string .= "if (!is_callable('{$data['function']}')) include '{$file}';\n";
371: }
372: }
373: }
374: $plugins_string .= '?>';
375: }
376: if (!empty($this->required_plugins['nocache'])) {
377: $this->has_nocache_code = true;
378: $plugins_string .= "<?php echo '/*%%SmartyNocache:{$this->properties['nocache_hash']}%%*/<?php \$_smarty = \$_smarty_tpl->smarty; ";
379: foreach ($this->required_plugins['nocache'] as $tmp) {
380: foreach ($tmp as $data) {
381: $file = addslashes($data['file']);
382: if (is_Array($data['function'])) {
383: $plugins_string .= addslashes("if (!is_callable(array('{$data['function'][0]}','{$data['function'][1]}'))) include '{$file}';\n");
384: } else {
385: $plugins_string .= addslashes("if (!is_callable('{$data['function']}')) include '{$file}';\n");
386: }
387: }
388: }
389: $plugins_string .= "?>/*/%%SmartyNocache:{$this->properties['nocache_hash']}%%*/';?>\n";
390: }
391: }
392:
393: $this->properties['has_nocache_code'] = $this->has_nocache_code;
394: $output = '';
395: if (!$this->source->recompiled) {
396: $output = "<?php /*%%SmartyHeaderCode:{$this->properties['nocache_hash']}%%*/";
397: if ($this->smarty->direct_access_security) {
398: $output .= "if(!defined('SMARTY_DIR')) exit('no direct access allowed');\n";
399: }
400: }
401: if ($cache) {
402:
403: unset($this->properties['function']);
404: if (!empty($this->smarty->template_functions)) {
405:
406: foreach ($this->smarty->template_functions as $name => $function_data) {
407: if (isset($function_data['called_nocache'])) {
408: foreach ($function_data['called_functions'] as $func_name) {
409: $this->smarty->template_functions[$func_name]['called_nocache'] = true;
410: }
411: }
412: }
413: foreach ($this->smarty->template_functions as $name => $function_data) {
414: if (isset($function_data['called_nocache'])) {
415: unset($function_data['called_nocache'], $function_data['called_functions'], $this->smarty->template_functions[$name]['called_nocache']);
416: $this->properties['function'][$name] = $function_data;
417: }
418: }
419: }
420: }
421: $this->properties['version'] = Smarty::SMARTY_VERSION;
422: if (!isset($this->properties['unifunc'])) {
423: $this->properties['unifunc'] = 'content_' . str_replace(array('.', ','), '_', uniqid('', true));
424: }
425: if (!$this->source->recompiled) {
426: $output .= "\$_valid = \$_smarty_tpl->decodeProperties(" . var_export($this->properties, true) . ',' . ($cache ? 'true' : 'false') . "); /*/%%SmartyHeaderCode%%*/?>\n";
427: $output .= '<?php if ($_valid && !is_callable(\'' . $this->properties['unifunc'] . '\')) {function ' . $this->properties['unifunc'] . '($_smarty_tpl) {?>';
428: }
429: $output .= $plugins_string;
430: $output .= $content;
431: if (!$this->source->recompiled) {
432: $output .= "<?php }} ?>\n";
433: }
434:
435: return $output;
436: }
437:
438: 439: 440: 441: 442: 443: 444: 445: 446: 447:
448: public function decodeProperties($properties, $cache = false)
449: {
450: $this->has_nocache_code = $properties['has_nocache_code'];
451: $this->properties['nocache_hash'] = $properties['nocache_hash'];
452: if (isset($properties['cache_lifetime'])) {
453: $this->properties['cache_lifetime'] = $properties['cache_lifetime'];
454: }
455: if (isset($properties['file_dependency'])) {
456: $this->properties['file_dependency'] = array_merge($this->properties['file_dependency'], $properties['file_dependency']);
457: }
458: if (!empty($properties['function'])) {
459: $this->properties['function'] = array_merge($this->properties['function'], $properties['function']);
460: $this->smarty->template_functions = array_merge($this->smarty->template_functions, $properties['function']);
461: }
462: $this->properties['version'] = (isset($properties['version'])) ? $properties['version'] : '';
463: $this->properties['unifunc'] = $properties['unifunc'];
464:
465: $is_valid = true;
466: if ($this->properties['version'] != Smarty::SMARTY_VERSION) {
467: $is_valid = false;
468: } elseif (((!$cache && $this->smarty->compile_check && empty($this->compiled->_properties) && !$this->compiled->isCompiled) || $cache && ($this->smarty->compile_check === true || $this->smarty->compile_check === Smarty::COMPILECHECK_ON)) && !empty($this->properties['file_dependency'])) {
469: foreach ($this->properties['file_dependency'] as $_file_to_check) {
470: if ($_file_to_check[2] == 'file' || $_file_to_check[2] == 'php') {
471: if ($this->source->filepath == $_file_to_check[0] && isset($this->source->timestamp)) {
472:
473: $mtime = $this->source->timestamp;
474: } else {
475:
476: $mtime = @filemtime($_file_to_check[0]);
477: }
478: } elseif ($_file_to_check[2] == 'string') {
479: continue;
480: } else {
481: $source = Smarty_Resource::source(null, $this->smarty, $_file_to_check[0]);
482: $mtime = $source->timestamp;
483: }
484: if (!$mtime || $mtime > $_file_to_check[1]) {
485: $is_valid = false;
486: break;
487: }
488: }
489: }
490: if ($cache) {
491:
492: if ($this->caching === Smarty::CACHING_LIFETIME_SAVED &&
493: $this->properties['cache_lifetime'] >= 0 &&
494: (time() > ($this->cached->timestamp + $this->properties['cache_lifetime']))
495: ) {
496: $is_valid = false;
497: }
498: $this->cached->valid = $is_valid;
499: } else {
500: $this->mustCompile = !$is_valid;
501: }
502:
503: if (!$cache) {
504: $this->compiled->_properties = $properties;
505: }
506:
507: return $is_valid;
508: }
509:
510: 511: 512: 513: 514: 515: 516:
517: public function createLocalArrayVariable($tpl_var, $nocache = false, $scope = Smarty::SCOPE_LOCAL)
518: {
519: if (!isset($this->tpl_vars[$tpl_var])) {
520: $this->tpl_vars[$tpl_var] = new Smarty_variable(array(), $nocache, $scope);
521: } else {
522: $this->tpl_vars[$tpl_var] = clone $this->tpl_vars[$tpl_var];
523: if ($scope != Smarty::SCOPE_LOCAL) {
524: $this->tpl_vars[$tpl_var]->scope = $scope;
525: }
526: if (!(is_array($this->tpl_vars[$tpl_var]->value) || $this->tpl_vars[$tpl_var]->value instanceof ArrayAccess)) {
527: settype($this->tpl_vars[$tpl_var]->value, 'array');
528: }
529: }
530: }
531:
532: 533: 534: 535: 536: 537: 538:
539: public function &getScope($scope)
540: {
541: if ($scope == Smarty::SCOPE_PARENT && !empty($this->parent)) {
542: return $this->parent->tpl_vars;
543: } elseif ($scope == Smarty::SCOPE_ROOT && !empty($this->parent)) {
544: $ptr = $this->parent;
545: while (!empty($ptr->parent)) {
546: $ptr = $ptr->parent;
547: }
548:
549: return $ptr->tpl_vars;
550: } elseif ($scope == Smarty::SCOPE_GLOBAL) {
551: return Smarty::$global_tpl_vars;
552: }
553: $null = null;
554:
555: return $null;
556: }
557:
558: 559: 560: 561: 562: 563: 564:
565: public function getScopePointer($scope)
566: {
567: if ($scope == Smarty::SCOPE_PARENT && !empty($this->parent)) {
568: return $this->parent;
569: } elseif ($scope == Smarty::SCOPE_ROOT && !empty($this->parent)) {
570: $ptr = $this->parent;
571: while (!empty($ptr->parent)) {
572: $ptr = $ptr->parent;
573: }
574:
575: return $ptr;
576: }
577:
578: return null;
579: }
580:
581: 582: 583: 584: 585: 586: 587:
588: public function _count($value)
589: {
590: if (is_array($value) === true || $value instanceof Countable) {
591: return count($value);
592: } elseif ($value instanceof IteratorAggregate) {
593:
594:
595: return iterator_count($value->getIterator());
596: } elseif ($value instanceof Iterator) {
597: return iterator_count($value);
598: } elseif ($value instanceof PDOStatement) {
599: return $value->rowCount();
600: } elseif ($value instanceof Traversable) {
601: return iterator_count($value);
602: } elseif ($value instanceof ArrayAccess) {
603: if ($value->offsetExists(0)) {
604: return 1;
605: }
606: } elseif (is_object($value)) {
607: return count($value);
608: }
609:
610: return 0;
611: }
612:
613: 614: 615: 616:
617: public function capture_error()
618: {
619: throw new SmartyException("Not matching {capture} open/close in \"{$this->template_resource}\"");
620: }
621:
622: 623: 624: 625: 626: 627: 628:
629: public function clearCache($exp_time = null)
630: {
631: Smarty_CacheResource::invalidLoadedCache($this->smarty);
632:
633: return $this->cached->handler->clear($this->smarty, $this->template_name, $this->cache_id, $this->compile_id, $exp_time);
634: }
635:
636: 637: 638: 639: 640: 641: 642: 643:
644: public function __set($property_name, $value)
645: {
646: switch ($property_name) {
647: case 'source':
648: case 'compiled':
649: case 'cached':
650: case 'compiler':
651: $this->$property_name = $value;
652:
653: return;
654:
655:
656: default:
657: if (property_exists($this->smarty, $property_name)) {
658: $this->smarty->$property_name = $value;
659:
660: return;
661: }
662: }
663:
664: throw new SmartyException("invalid template property '$property_name'.");
665: }
666:
667: 668: 669: 670: 671: 672: 673:
674: public function __get($property_name)
675: {
676: switch ($property_name) {
677: case 'source':
678: if (strlen($this->template_resource) == 0) {
679: throw new SmartyException('Missing template name');
680: }
681: $this->source = Smarty_Resource::source($this);
682:
683:
684: if ($this->source->type != 'eval') {
685: if ($this->smarty->allow_ambiguous_resources) {
686: $_templateId = $this->source->unique_resource . $this->cache_id . $this->compile_id;
687: } else {
688: $_templateId = $this->smarty->joined_template_dir . '#' . $this->template_resource . $this->cache_id . $this->compile_id;
689: }
690:
691: if (isset($_templateId[150])) {
692: $_templateId = sha1($_templateId);
693: }
694: $this->smarty->template_objects[$_templateId] = $this;
695: }
696:
697: return $this->source;
698:
699: case 'compiled':
700: $this->compiled = $this->source->getCompiled($this);
701:
702: return $this->compiled;
703:
704: case 'cached':
705: if (!class_exists('Smarty_Template_Cached')) {
706: include SMARTY_SYSPLUGINS_DIR . 'smarty_cacheresource.php';
707: }
708: $this->cached = new Smarty_Template_Cached($this);
709:
710: return $this->cached;
711:
712: case 'compiler':
713: $this->smarty->loadPlugin($this->source->compiler_class);
714: $this->compiler = new $this->source->compiler_class($this->source->template_lexer_class, $this->source->template_parser_class, $this->smarty);
715:
716: return $this->compiler;
717:
718:
719: default:
720: if (property_exists($this->smarty, $property_name)) {
721: return $this->smarty->$property_name;
722: }
723: }
724:
725: throw new SmartyException("template property '$property_name' does not exist.");
726: }
727:
728: 729: 730: 731:
732: public function __destruct()
733: {
734: if ($this->smarty->cache_locking && isset($this->cached) && $this->cached->is_locked) {
735: $this->cached->handler->releaseLock($this->smarty, $this->cached);
736: }
737: }
738: }
739: