1: <?php
2: 3: 4: 5: 6: 7: 8: 9:
10:
11: 12: 13: 14: 15: 16:
17: abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
18: {
19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33:
34: public function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null, $display = false, $merge_tpl_vars = true, $no_output_filter = false)
35: {
36: if ($template === null && $this instanceof $this->template_class) {
37: $template = $this;
38: }
39: if ($cache_id !== null && is_object($cache_id)) {
40: $parent = $cache_id;
41: $cache_id = null;
42: }
43: if ($parent === null && ($this instanceof Smarty || is_string($template))) {
44: $parent = $this;
45: }
46:
47: $_template = ($template instanceof $this->template_class)
48: ? $template
49: : $this->smarty->createTemplate($template, $cache_id, $compile_id, $parent, false);
50:
51: if ($this instanceof Smarty) {
52: $_template->caching = $this->caching;
53: }
54:
55: if ($merge_tpl_vars) {
56:
57: $save_tpl_vars = $_template->tpl_vars;
58: $save_config_vars = $_template->config_vars;
59: $ptr_array = array($_template);
60: $ptr = $_template;
61: while (isset($ptr->parent)) {
62: $ptr_array[] = $ptr = $ptr->parent;
63: }
64: $ptr_array = array_reverse($ptr_array);
65: $parent_ptr = reset($ptr_array);
66: $tpl_vars = $parent_ptr->tpl_vars;
67: $config_vars = $parent_ptr->config_vars;
68: while ($parent_ptr = next($ptr_array)) {
69: if (!empty($parent_ptr->tpl_vars)) {
70: $tpl_vars = array_merge($tpl_vars, $parent_ptr->tpl_vars);
71: }
72: if (!empty($parent_ptr->config_vars)) {
73: $config_vars = array_merge($config_vars, $parent_ptr->config_vars);
74: }
75: }
76: if (!empty(Smarty::$global_tpl_vars)) {
77: $tpl_vars = array_merge(Smarty::$global_tpl_vars, $tpl_vars);
78: }
79: $_template->tpl_vars = $tpl_vars;
80: $_template->config_vars = $config_vars;
81: }
82:
83: if (!isset($_template->tpl_vars['smarty'])) {
84: $_template->tpl_vars['smarty'] = new Smarty_Variable;
85: }
86: if (isset($this->smarty->error_reporting)) {
87: $_smarty_old_error_level = error_reporting($this->smarty->error_reporting);
88: }
89:
90: if (!$this->smarty->debugging && $this->smarty->debugging_ctrl == 'URL') {
91: if (isset($_SERVER['QUERY_STRING'])) {
92: $_query_string = $_SERVER['QUERY_STRING'];
93: } else {
94: $_query_string = '';
95: }
96: if (false !== strpos($_query_string, $this->smarty->smarty_debug_id)) {
97: if (false !== strpos($_query_string, $this->smarty->smarty_debug_id . '=on')) {
98:
99: setcookie('SMARTY_DEBUG', true);
100: $this->smarty->debugging = true;
101: } elseif (false !== strpos($_query_string, $this->smarty->smarty_debug_id . '=off')) {
102:
103: setcookie('SMARTY_DEBUG', false);
104: $this->smarty->debugging = false;
105: } else {
106:
107: $this->smarty->debugging = true;
108: }
109: } else {
110: if (isset($_COOKIE['SMARTY_DEBUG'])) {
111: $this->smarty->debugging = true;
112: }
113: }
114: }
115:
116: $_template->smarty->merged_templates_func = array();
117:
118:
119: if ($_template->source->recompiled) {
120: $_template->caching = false;
121: }
122:
123: if (!$_template->source->exists) {
124: if ($_template->parent instanceof Smarty_Internal_Template) {
125: $parent_resource = " in '{$_template->parent->template_resource}'";
126: } else {
127: $parent_resource = '';
128: }
129: throw new SmartyException("Unable to load template {$_template->source->type} '{$_template->source->name}'{$parent_resource}");
130: }
131:
132: if (!($_template->caching == Smarty::CACHING_LIFETIME_CURRENT || $_template->caching == Smarty::CACHING_LIFETIME_SAVED) || !$_template->cached->valid) {
133:
134: if (!$_template->source->uncompiled) {
135: 136: 137:
138: $_smarty_tpl = $_template;
139: if ($_template->source->recompiled) {
140: $code = $_template->compiler->compileTemplate($_template);
141: if ($this->smarty->debugging) {
142: Smarty_Internal_Debug::start_render($_template);
143: }
144: try {
145: ob_start();
146: eval("?>" . $code);
147: unset($code);
148: }
149: catch (Exception $e) {
150: ob_get_clean();
151: throw $e;
152: }
153: } else {
154: if (!$_template->compiled->exists || ($_template->smarty->force_compile && !$_template->compiled->isCompiled)) {
155: $_template->compileTemplateSource();
156: $code = file_get_contents($_template->compiled->filepath);
157: eval("?>" . $code);
158: unset($code);
159: $_template->compiled->loaded = true;
160: $_template->compiled->isCompiled = true;
161: }
162: if ($this->smarty->debugging) {
163: Smarty_Internal_Debug::start_render($_template);
164: }
165: if (!$_template->compiled->loaded) {
166: include($_template->compiled->filepath);
167: if ($_template->mustCompile) {
168:
169: $_template->compileTemplateSource();
170: $code = file_get_contents($_template->compiled->filepath);
171: eval("?>" . $code);
172: unset($code);
173: $_template->compiled->isCompiled = true;
174: }
175: $_template->compiled->loaded = true;
176: } else {
177: $_template->decodeProperties($_template->compiled->_properties, false);
178: }
179: try {
180: ob_start();
181: if (empty($_template->properties['unifunc']) || !is_callable($_template->properties['unifunc'])) {
182: throw new SmartyException("Invalid compiled template for '{$_template->template_resource}'");
183: }
184: array_unshift($_template->_capture_stack, array());
185:
186:
187:
188: $_template->properties['unifunc']($_template);
189:
190: if (isset($_template->_capture_stack[0][0])) {
191: $_template->capture_error();
192: }
193: array_shift($_template->_capture_stack);
194: }
195: catch (Exception $e) {
196: ob_get_clean();
197: throw $e;
198: }
199: }
200: } else {
201: if ($_template->source->uncompiled) {
202: if ($this->smarty->debugging) {
203: Smarty_Internal_Debug::start_render($_template);
204: }
205: try {
206: ob_start();
207: $_template->source->renderUncompiled($_template);
208: }
209: catch (Exception $e) {
210: ob_get_clean();
211: throw $e;
212: }
213: } else {
214: throw new SmartyException("Resource '$_template->source->type' must have 'renderUncompiled' method");
215: }
216: }
217: $_output = ob_get_clean();
218: if (!$_template->source->recompiled && empty($_template->properties['file_dependency'][$_template->source->uid])) {
219: $_template->properties['file_dependency'][$_template->source->uid] = array($_template->source->filepath, $_template->source->timestamp, $_template->source->type);
220: }
221: if ($_template->parent instanceof Smarty_Internal_Template) {
222: $_template->parent->properties['file_dependency'] = array_merge($_template->parent->properties['file_dependency'], $_template->properties['file_dependency']);
223: foreach ($_template->required_plugins as $code => $tmp1) {
224: foreach ($tmp1 as $name => $tmp) {
225: foreach ($tmp as $type => $data) {
226: $_template->parent->required_plugins[$code][$name][$type] = $data;
227: }
228: }
229: }
230: }
231: if ($this->smarty->debugging) {
232: Smarty_Internal_Debug::end_render($_template);
233: }
234:
235: if (!$_template->source->recompiled && ($_template->caching == Smarty::CACHING_LIFETIME_SAVED || $_template->caching == Smarty::CACHING_LIFETIME_CURRENT)) {
236: if ($this->smarty->debugging) {
237: Smarty_Internal_Debug::start_cache($_template);
238: }
239: $_template->properties['has_nocache_code'] = false;
240:
241: $cache_split = preg_split("!/\*%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*\/(.+?)/\*/%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*/!s", $_output);
242:
243: preg_match_all("!/\*%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*\/(.+?)/\*/%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*/!s", $_output, $cache_parts);
244: $output = '';
245:
246: foreach ($cache_split as $curr_idx => $curr_split) {
247:
248: $output .= preg_replace('/(<%|%>|<\?php|<\?|\?>|<script\s+language\s*=\s*[\"\']?\s*php\s*[\"\']?\s*>)/', "<?php echo '\$1'; ?>\n", $curr_split);
249: if (isset($cache_parts[0][$curr_idx])) {
250: $_template->properties['has_nocache_code'] = true;
251:
252: $output .= preg_replace("!/\*/?%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*/!", '', $cache_parts[0][$curr_idx]);
253: }
254: }
255: if (!$no_output_filter && !$_template->has_nocache_code && (isset($this->smarty->autoload_filters['output']) || isset($this->smarty->registered_filters['output']))) {
256: $output = Smarty_Internal_Filter_Handler::runFilter('output', $output, $_template);
257: }
258:
259: 260: 261:
262: $_smarty_tpl = $_template;
263: try {
264: ob_start();
265: eval("?>" . $output);
266: $_output = ob_get_clean();
267: }
268: catch (Exception $e) {
269: ob_get_clean();
270: throw $e;
271: }
272:
273: $_template->writeCachedContent($output);
274: if ($this->smarty->debugging) {
275: Smarty_Internal_Debug::end_cache($_template);
276: }
277: } else {
278:
279: if (!empty($_template->properties['nocache_hash']) && !empty($_template->parent->properties['nocache_hash'])) {
280:
281: $_output = str_replace("{$_template->properties['nocache_hash']}", $_template->parent->properties['nocache_hash'], $_output);
282: $_template->parent->has_nocache_code = $_template->parent->has_nocache_code || $_template->has_nocache_code;
283: }
284: }
285: } else {
286: if ($this->smarty->debugging) {
287: Smarty_Internal_Debug::start_cache($_template);
288: }
289: try {
290: ob_start();
291: array_unshift($_template->_capture_stack, array());
292:
293:
294:
295: $_template->properties['unifunc']($_template);
296:
297: if (isset($_template->_capture_stack[0][0])) {
298: $_template->capture_error();
299: }
300: array_shift($_template->_capture_stack);
301: $_output = ob_get_clean();
302: }
303: catch (Exception $e) {
304: ob_get_clean();
305: throw $e;
306: }
307: if ($this->smarty->debugging) {
308: Smarty_Internal_Debug::end_cache($_template);
309: }
310: }
311: if ((!$this->caching || $_template->has_nocache_code || $_template->source->recompiled) && !$no_output_filter && (isset($this->smarty->autoload_filters['output']) || isset($this->smarty->registered_filters['output']))) {
312: $_output = Smarty_Internal_Filter_Handler::runFilter('output', $_output, $_template);
313: }
314: if (isset($this->error_reporting)) {
315: error_reporting($_smarty_old_error_level);
316: }
317:
318: if ($display) {
319: if ($this->caching && $this->cache_modified_check) {
320: $_isCached = $_template->isCached() && !$_template->has_nocache_code;
321: $_last_modified_date = @substr($_SERVER['HTTP_IF_MODIFIED_SINCE'], 0, strpos($_SERVER['HTTP_IF_MODIFIED_SINCE'], 'GMT') + 3);
322: if ($_isCached && $_template->cached->timestamp <= strtotime($_last_modified_date)) {
323: switch (PHP_SAPI) {
324: case 'cgi':
325: case 'cgi-fcgi':
326: case 'fpm-fcgi':
327: header('Status: 304 Not Modified');
328: break;
329:
330: case 'cli':
331: if (
332: !empty($_SERVER['SMARTY_PHPUNIT_DISABLE_HEADERS'])
333: ) {
334: $_SERVER['SMARTY_PHPUNIT_HEADERS'][] = '304 Not Modified';
335: }
336: break;
337:
338: default:
339: header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified');
340: break;
341: }
342: } else {
343: switch (PHP_SAPI) {
344: case 'cli':
345: if (
346: !empty($_SERVER['SMARTY_PHPUNIT_DISABLE_HEADERS'])
347: ) {
348: $_SERVER['SMARTY_PHPUNIT_HEADERS'][] = 'Last-Modified: ' . gmdate('D, d M Y H:i:s', $_template->cached->timestamp) . ' GMT';
349: }
350: break;
351:
352: default:
353: header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $_template->cached->timestamp) . ' GMT');
354: break;
355: }
356: echo $_output;
357: }
358: } else {
359: echo $_output;
360: }
361:
362: if ($this->smarty->debugging) {
363: Smarty_Internal_Debug::display_debug($_template);
364: }
365: if ($merge_tpl_vars) {
366:
367: $_template->tpl_vars = $save_tpl_vars;
368: $_template->config_vars = $save_config_vars;
369: }
370:
371: return;
372: } else {
373: if ($merge_tpl_vars) {
374:
375: $_template->tpl_vars = $save_tpl_vars;
376: $_template->config_vars = $save_config_vars;
377: }
378:
379: return $_output;
380: }
381: }
382:
383: 384: 385: 386: 387: 388: 389: 390:
391: public function display($template = null, $cache_id = null, $compile_id = null, $parent = null)
392: {
393:
394: $this->fetch($template, $cache_id, $compile_id, $parent, true);
395: }
396:
397: 398: 399: 400: 401: 402: 403: 404: 405: 406:
407: public function isCached($template = null, $cache_id = null, $compile_id = null, $parent = null)
408: {
409: if ($template === null && $this instanceof $this->template_class) {
410: return $this->cached->valid;
411: }
412: if (!($template instanceof $this->template_class)) {
413: if ($parent === null) {
414: $parent = $this;
415: }
416: $template = $this->smarty->createTemplate($template, $cache_id, $compile_id, $parent, false);
417: }
418:
419: return $template->cached->valid;
420: }
421:
422: 423: 424: 425: 426: 427: 428:
429: public function createData($parent = null)
430: {
431: return new Smarty_Data($parent, $this);
432: }
433:
434: 435: 436: 437: 438: 439: 440: 441: 442: 443: 444: 445:
446: public function registerPlugin($type, $tag, $callback, $cacheable = true, $cache_attr = null)
447: {
448: if (isset($this->smarty->registered_plugins[$type][$tag])) {
449: throw new SmartyException("Plugin tag \"{$tag}\" already registered");
450: } elseif (!is_callable($callback)) {
451: throw new SmartyException("Plugin \"{$tag}\" not callable");
452: } else {
453: $this->smarty->registered_plugins[$type][$tag] = array($callback, (bool) $cacheable, (array) $cache_attr);
454: }
455:
456: return $this;
457: }
458:
459: 460: 461: 462: 463: 464: 465: 466:
467: public function unregisterPlugin($type, $tag)
468: {
469: if (isset($this->smarty->registered_plugins[$type][$tag])) {
470: unset($this->smarty->registered_plugins[$type][$tag]);
471: }
472:
473: return $this;
474: }
475:
476: 477: 478: 479: 480: 481: 482: 483:
484: public function registerResource($type, $callback)
485: {
486: $this->smarty->registered_resources[$type] = $callback instanceof Smarty_Resource ? $callback : array($callback, false);
487:
488: return $this;
489: }
490:
491: 492: 493: 494: 495: 496: 497:
498: public function unregisterResource($type)
499: {
500: if (isset($this->smarty->registered_resources[$type])) {
501: unset($this->smarty->registered_resources[$type]);
502: }
503:
504: return $this;
505: }
506:
507: 508: 509: 510: 511: 512: 513: 514:
515: public function registerCacheResource($type, Smarty_CacheResource $callback)
516: {
517: $this->smarty->registered_cache_resources[$type] = $callback;
518:
519: return $this;
520: }
521:
522: 523: 524: 525: 526: 527: 528:
529: public function unregisterCacheResource($type)
530: {
531: if (isset($this->smarty->registered_cache_resources[$type])) {
532: unset($this->smarty->registered_cache_resources[$type]);
533: }
534:
535: return $this;
536: }
537:
538: 539: 540: 541: 542: 543: 544: 545: 546: 547: 548: 549:
550: public function registerObject($object_name, $object_impl, $allowed = array(), $smarty_args = true, $block_methods = array())
551: {
552:
553: if (!empty($allowed)) {
554: foreach ((array) $allowed as $method) {
555: if (!is_callable(array($object_impl, $method)) && !property_exists($object_impl, $method)) {
556: throw new SmartyException("Undefined method or property '$method' in registered object");
557: }
558: }
559: }
560:
561: if (!empty($block_methods)) {
562: foreach ((array) $block_methods as $method) {
563: if (!is_callable(array($object_impl, $method))) {
564: throw new SmartyException("Undefined method '$method' in registered object");
565: }
566: }
567: }
568:
569: $this->smarty->registered_objects[$object_name] =
570: array($object_impl, (array) $allowed, (boolean) $smarty_args, (array) $block_methods);
571:
572: return $this;
573: }
574:
575: 576: 577: 578: 579: 580: 581: 582:
583: public function getRegisteredObject($name)
584: {
585: if (!isset($this->smarty->registered_objects[$name])) {
586: throw new SmartyException("'$name' is not a registered object");
587: }
588: if (!is_object($this->smarty->registered_objects[$name][0])) {
589: throw new SmartyException("registered '$name' is not an object");
590: }
591:
592: return $this->smarty->registered_objects[$name][0];
593: }
594:
595: 596: 597: 598: 599: 600: 601:
602: public function unregisterObject($name)
603: {
604: if (isset($this->smarty->registered_objects[$name])) {
605: unset($this->smarty->registered_objects[$name]);
606: }
607:
608: return $this;
609: }
610:
611: 612: 613: 614: 615: 616: 617: 618: 619:
620: public function registerClass($class_name, $class_impl)
621: {
622:
623: if (!class_exists($class_impl)) {
624: throw new SmartyException("Undefined class '$class_impl' in register template class");
625: }
626:
627: $this->smarty->registered_classes[$class_name] = $class_impl;
628:
629: return $this;
630: }
631:
632: 633: 634: 635: 636: 637: 638: 639:
640: public function registerDefaultPluginHandler($callback)
641: {
642: if (is_callable($callback)) {
643: $this->smarty->default_plugin_handler_func = $callback;
644: } else {
645: throw new SmartyException("Default plugin handler '$callback' not callable");
646: }
647:
648: return $this;
649: }
650:
651: 652: 653: 654: 655: 656: 657: 658:
659: public function registerDefaultTemplateHandler($callback)
660: {
661: if (is_callable($callback)) {
662: $this->smarty->default_template_handler_func = $callback;
663: } else {
664: throw new SmartyException("Default template handler '$callback' not callable");
665: }
666:
667: return $this;
668: }
669:
670: 671: 672: 673: 674: 675: 676: 677:
678: public function registerDefaultConfigHandler($callback)
679: {
680: if (is_callable($callback)) {
681: $this->smarty->default_config_handler_func = $callback;
682: } else {
683: throw new SmartyException("Default config handler '$callback' not callable");
684: }
685:
686: return $this;
687: }
688:
689: 690: 691: 692: 693: 694: 695: 696:
697: public function registerFilter($type, $callback)
698: {
699: $this->smarty->registered_filters[$type][$this->_get_filter_name($callback)] = $callback;
700:
701: return $this;
702: }
703:
704: 705: 706: 707: 708: 709: 710: 711:
712: public function unregisterFilter($type, $callback)
713: {
714: $name = $this->_get_filter_name($callback);
715: if (isset($this->smarty->registered_filters[$type][$name])) {
716: unset($this->smarty->registered_filters[$type][$name]);
717: }
718:
719: return $this;
720: }
721:
722: 723: 724: 725: 726: 727: 728:
729: public function _get_filter_name($function_name)
730: {
731: if (is_array($function_name)) {
732: $_class_name = (is_object($function_name[0]) ?
733: get_class($function_name[0]) : $function_name[0]);
734:
735: return $_class_name . '_' . $function_name[1];
736: } else {
737: return $function_name;
738: }
739: }
740:
741: 742: 743: 744: 745: 746: 747: 748:
749: public function loadFilter($type, $name)
750: {
751: $_plugin = "smarty_{$type}filter_{$name}";
752: $_filter_name = $_plugin;
753: if ($this->smarty->loadPlugin($_plugin)) {
754: if (class_exists($_plugin, false)) {
755: $_plugin = array($_plugin, 'execute');
756: }
757: if (is_callable($_plugin)) {
758: $this->smarty->registered_filters[$type][$_filter_name] = $_plugin;
759:
760: return true;
761: }
762: }
763: throw new SmartyException("{$type}filter \"{$name}\" not callable");
764: }
765:
766: 767: 768: 769: 770: 771: 772: 773:
774: public function unloadFilter($type, $name)
775: {
776: $_filter_name = "smarty_{$type}filter_{$name}";
777: if (isset($this->smarty->registered_filters[$type][$_filter_name])) {
778: unset ($this->smarty->registered_filters[$type][$_filter_name]);
779: }
780:
781: return $this;
782: }
783:
784: 785: 786: 787: 788: 789: 790:
791: private function replaceCamelcase($match)
792: {
793: return "_" . strtolower($match[1]);
794: }
795:
796: 797: 798: 799: 800: 801: 802: 803:
804: public function __call($name, $args)
805: {
806: static $_prefixes = array('set' => true, 'get' => true);
807: static $_resolved_property_name = array();
808: static $_resolved_property_source = array();
809:
810:
811: if (method_exists($this->smarty, $name)) {
812: return call_user_func_array(array($this->smarty, $name), $args);
813: }
814:
815: $first3 = strtolower(substr($name, 0, 3));
816: if (isset($_prefixes[$first3]) && isset($name[3]) && $name[3] !== '_') {
817: if (isset($_resolved_property_name[$name])) {
818: $property_name = $_resolved_property_name[$name];
819: } else {
820:
821:
822: $property_name = strtolower(substr($name, 3, 1)) . substr($name, 4);
823:
824: $property_name = preg_replace_callback('/([A-Z])/', array($this, 'replaceCamelcase'), $property_name);
825: $_resolved_property_name[$name] = $property_name;
826: }
827: if (isset($_resolved_property_source[$property_name])) {
828: $_is_this = $_resolved_property_source[$property_name];
829: } else {
830: $_is_this = null;
831: if (property_exists($this, $property_name)) {
832: $_is_this = true;
833: } elseif (property_exists($this->smarty, $property_name)) {
834: $_is_this = false;
835: }
836: $_resolved_property_source[$property_name] = $_is_this;
837: }
838: if ($_is_this) {
839: if ($first3 == 'get') {
840: return $this->$property_name;
841: } else {
842: return $this->$property_name = $args[0];
843: }
844: } elseif ($_is_this === false) {
845: if ($first3 == 'get') {
846: return $this->smarty->$property_name;
847: } else {
848: return $this->smarty->$property_name = $args[0];
849: }
850: } else {
851: throw new SmartyException("property '$property_name' does not exist.");
852: }
853: }
854: if ($name == 'Smarty') {
855: throw new SmartyException("PHP5 requires you to call __construct() instead of Smarty()");
856: }
857:
858: throw new SmartyException("Call of unknown method '$name'.");
859: }
860: }
861: