308 abstract protected function doCompile($_content);
315 $this->nocache_hash = str_replace(array(
'.',
','),
'_', uniqid(rand(),
true));
331 if (isset($this->template->smarty->security_policy)) {
332 $this->php_handling = $this->
template->smarty->security_policy->php_handling;
334 $this->php_handling = $this->
template->smarty->php_handling;
338 if (empty($template->properties[
'nocache_hash'])) {
341 $this->nocache_hash = $template->properties[
'nocache_hash'];
343 $save_source = $this->
template->source;
345 $template_header =
'';
346 if (!$this->suppressHeader) {
347 $template_header .=
"<?php /* Smarty version " .
Smarty::SMARTY_VERSION .
", created on " . strftime(
"%Y-%m-%d %H:%M:%S") .
"\n";
348 $template_header .=
" compiled from \"" . $this->
template->source->filepath .
"\" */ ?>\n";
351 if (empty($this->template->source->components)) {
352 $this->sources = array($template->source);
355 $this->sources = array_reverse($template->source->components);
359 while ($this->template->source = array_shift($this->sources)) {
360 $this->smarty->_current_file = $this->
template->source->filepath;
361 if ($this->smarty->debugging) {
364 $no_sources = count($this->sources);
365 $this->parent_compiler->template->properties[
'file_dependency'][$this->
template->source->uid] = array($this->template->source->filepath, $this->template->source->timestamp, $this->template->source->type);
368 $this->inheritance_child =
true;
370 $this->inheritance_child =
false;
375 $this->tag_nocache =
false;
377 $this->
template->has_nocache_code =
false;
378 $this->has_variable_string =
false;
379 $this->prefix_code = array();
380 $_compiled_code =
'';
382 $this->abort_and_recompile =
false;
384 $_content = $this->
template->source->content;
385 if ($_content !=
'') {
387 if ((isset($this->smarty->autoload_filters[
'pre']) || isset($this->smarty->registered_filters[
'pre'])) && !$this->suppressFilter) {
391 $_compiled_code = $this->
doCompile($_content,
true);
393 }
while ($this->abort_and_recompile);
394 if ($this->smarty->debugging) {
399 $this->
template->source = $save_source;
401 $this->smarty->_current_file = $this->
template->source->filepath;
403 unset($this->parser->root_buffer, $this->parser->current_buffer, $this->parser, $this->lex);
404 self::$_tag_objects = array();
407 if (!empty($this->mergedSubTemplatesCode)) {
408 foreach ($this->mergedSubTemplatesCode as $code) {
409 $merged_code .= $code;
413 if ((isset($this->smarty->autoload_filters[
'post']) || isset($this->smarty->registered_filters[
'post'])) && !$this->suppressFilter && $_compiled_code !=
'') {
416 if ($this->suppressTemplatePropertyHeader) {
417 $_compiled_code .= $merged_code;
421 if (!empty($this->templateFunctionCode)) {
423 if ((isset($this->smarty->autoload_filters[
'post']) || isset($this->smarty->registered_filters[
'post'])) && !$this->suppressFilter) {
430 unset ($template->source->content);
431 $this->parent_compiler = null;
432 $this->
template = null;
433 return $_compiled_code;
453 public function compileTag($tag, $args, $parameter = array())
456 $this->prefix_code = array();
457 $result = $this->
compileTag2($tag, $args, $parameter);
458 $this->prefix_code = array_merge($this->prefix_code, array_pop($this->prefixCodeStack));
478 $this->has_code =
true;
479 $this->has_output =
false;
481 if (isset($this->smarty->get_used_tags) && $this->smarty->get_used_tags) {
482 $this->
template->used_tags[] = array($tag, $args);
485 if (in_array(
"'nocache'", $args) || in_array(array(
'nocache' =>
'true'), $args) || in_array(array(
'nocache' =>
'"true"'), $args) || in_array(array(
'nocache' =>
"'true'"), $args)
487 $this->tag_nocache =
true;
490 if (($_output = $this->
callTagCompiler($tag, $args, $parameter)) ===
false) {
491 if (isset($this->parent_compiler->templateProperties[
'tpl_function'][$tag])) {
493 $args[
'_attr'][
'name'] =
"'" . $tag .
"'";
497 if ($_output !==
false) {
498 if ($_output !==
true) {
500 if ($this->has_code) {
502 if ($this->has_output) {
513 if (isset($args[
'_attr'])) {
514 foreach ($args[
'_attr'] as $key => $attribute) {
515 if (is_array($attribute)) {
516 $args = array_merge($args, $attribute);
521 if (strlen($tag) < 6 || substr($tag, - 5) !=
'close') {
523 if (isset($this->smarty->registered_objects[$tag]) && isset($parameter[
'object_method'])) {
524 $method = $parameter[
'object_method'];
525 if (!in_array($method, $this->smarty->registered_objects[$tag][3]) && (empty($this->smarty->registered_objects[$tag][1]) || in_array($method, $this->smarty->registered_objects[$tag][1]))
527 return $this->
callTagCompiler(
'private_object_function', $args, $parameter, $tag, $method);
528 } elseif (in_array($method, $this->smarty->registered_objects[$tag][3])) {
529 return $this->
callTagCompiler(
'private_object_block_function', $args, $parameter, $tag, $method);
532 $this->
trigger_template_error(
'not allowed method "' . $method .
'" in registered object "' . $tag .
'"', $this->lex->taglineno);
537 if (isset($this->smarty->registered_plugins[$plugin_type][$tag])) {
541 foreach ($args as $key => $mixed) {
542 if (is_array($mixed)) {
543 $new_args = array_merge($new_args, $mixed);
545 $new_args[$key] = $mixed;
548 if (!$this->smarty->registered_plugins[$plugin_type][$tag][1]) {
549 $this->tag_nocache =
true;
551 $function = $this->smarty->registered_plugins[$plugin_type][$tag][0];
552 if (!is_array($function)) {
553 return $function($new_args, $this);
554 } elseif (is_object($function[0])) {
555 return $this->smarty->registered_plugins[$plugin_type][$tag][0][0]->$function[1]($new_args, $this);
557 return call_user_func_array($function, array($new_args, $this));
562 return $this->
callTagCompiler(
'private_registered_' . $plugin_type, $args, $parameter, $tag);
567 foreach ($this->smarty->plugin_search_order as $plugin_type) {
568 if ($plugin_type ==
Smarty::PLUGIN_COMPILER && $this->smarty->loadPlugin(
'smarty_compiler_' . $tag) && (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($tag, $this))) {
569 $plugin =
'smarty_compiler_' . $tag;
570 if (is_callable($plugin)) {
573 foreach ($args as $key => $mixed) {
574 if (is_array($mixed)) {
575 $new_args = array_merge($new_args, $mixed);
577 $new_args[$key] = $mixed;
581 return $plugin($new_args, $this->smarty);
583 if (class_exists($plugin,
false)) {
584 $plugin_object =
new $plugin;
585 if (method_exists($plugin_object,
'compile')) {
586 return $plugin_object->compile($args, $this);
591 if ($function = $this->
getPlugin($tag, $plugin_type)) {
592 if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($tag, $this)) {
593 return $this->
callTagCompiler(
'private_' . $plugin_type .
'_plugin', $args, $parameter, $tag, $function);
598 if (is_callable($this->smarty->default_plugin_handler_func)) {
601 foreach ($this->smarty->plugin_search_order as $plugin_type) {
602 if (isset($this->default_handler_plugins[$plugin_type][$tag])) {
609 foreach ($this->smarty->plugin_search_order as $plugin_type) {
620 foreach ($args as $mixed) {
621 $new_args = array_merge($new_args, $mixed);
623 $function = $this->default_handler_plugins[$plugin_type][$tag][0];
624 if (!is_array($function)) {
625 return $function($new_args, $this);
626 } elseif (is_object($function[0])) {
627 return $this->default_handler_plugins[$plugin_type][$tag][0][0]->$function[1]($new_args, $this);
629 return call_user_func_array($function, array($new_args, $this));
632 return $this->
callTagCompiler(
'private_registered_' . $plugin_type, $args, $parameter, $tag);
638 $base_tag = substr($tag, 0, - 5);
640 if (isset($this->smarty->registered_objects[$base_tag]) && isset($parameter[
'object_method'])) {
641 $method = $parameter[
'object_method'];
642 if (in_array($method, $this->smarty->registered_objects[$base_tag][3])) {
643 return $this->
callTagCompiler(
'private_object_block_function', $args, $parameter, $tag, $method);
646 $this->
trigger_template_error(
'not allowed closing tag method "' . $method .
'" in registered object "' . $base_tag .
'"', $this->lex->taglineno);
651 return $this->
callTagCompiler(
'private_registered_block', $args, $parameter, $tag);
655 return $this->
callTagCompiler(
'private_block_plugin', $args, $parameter, $tag, $function);
662 $this->tag_nocache =
true;
665 if (!is_array($function)) {
666 return $function($args, $this);
667 } elseif (is_object($function[0])) {
670 return call_user_func_array($function, array($args, $this));
673 if ($this->smarty->loadPlugin(
'smarty_compiler_' . $tag)) {
674 $plugin =
'smarty_compiler_' . $tag;
675 if (is_callable($plugin)) {
676 return $plugin($args, $this->smarty);
678 if (class_exists($plugin,
false)) {
679 $plugin_object =
new $plugin;
680 if (method_exists($plugin_object,
'compile')) {
681 return $plugin_object->compile($args, $this);
700 if (strpos($variable,
'(') == 0) {
702 $var = trim($variable,
'\'');
703 $this->tag_nocache = $this->tag_nocache | $this->
template->getVariable($var, null,
true,
false)->nocache;
704 $this->
template->properties[
'variables'][$var] = $this->tag_nocache |
$this->nocache;
706 return '$_smarty_tpl->tpl_vars[' . $variable .
']->value';
720 if ($this->parser->strip) {
741 public function callTagCompiler($tag, $args, $param1 = null, $param2 = null, $param3 = null)
744 if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($tag, $this)) {
746 if (!isset(self::$_tag_objects[$tag])) {
748 $class_name =
'Smarty_Internal_Compile_' . $tag;
749 if ($this->smarty->loadPlugin($class_name)) {
750 self::$_tag_objects[$tag] =
new $class_name;
756 return self::$_tag_objects[$tag]->compile($args, $this, $param1, $param2, $param3);
773 if ($this->template->caching && ($this->nocache || $this->tag_nocache)) {
774 if (isset($this->template->required_plugins[
'nocache'][$plugin_name][$plugin_type])) {
775 $function = $this->
template->required_plugins[
'nocache'][$plugin_name][$plugin_type][
'function'];
776 } elseif (isset($this->template->required_plugins[
'compiled'][$plugin_name][$plugin_type])) {
777 $this->
template->required_plugins[
'nocache'][$plugin_name][$plugin_type] = $this->
template->required_plugins[
'compiled'][$plugin_name][$plugin_type];
778 $function = $this->
template->required_plugins[
'nocache'][$plugin_name][$plugin_type][
'function'];
781 if (isset($this->template->required_plugins[
'compiled'][$plugin_name][$plugin_type])) {
782 $function = $this->
template->required_plugins[
'compiled'][$plugin_name][$plugin_type][
'function'];
783 } elseif (isset($this->template->required_plugins[
'nocache'][$plugin_name][$plugin_type])) {
784 $this->
template->required_plugins[
'compiled'][$plugin_name][$plugin_type] = $this->
template->required_plugins[
'nocache'][$plugin_name][$plugin_type];
785 $function = $this->
template->required_plugins[
'compiled'][$plugin_name][$plugin_type][
'function'];
788 if (isset($function)) {
789 if ($plugin_type ==
'modifier') {
790 $this->modifier_plugins[$plugin_name] =
true;
796 $function =
'smarty_' . $plugin_type .
'_' . $plugin_name;
797 $file = $this->smarty->loadPlugin($function,
false);
799 if (is_string($file)) {
800 if ($this->template->caching && ($this->nocache || $this->tag_nocache)) {
801 $this->
template->required_plugins[
'nocache'][$plugin_name][$plugin_type][
'file'] = $file;
802 $this->
template->required_plugins[
'nocache'][$plugin_name][$plugin_type][
'function'] = $function;
804 $this->
template->required_plugins[
'compiled'][$plugin_name][$plugin_type][
'file'] = $file;
805 $this->
template->required_plugins[
'compiled'][$plugin_name][$plugin_type][
'function'] = $function;
807 if ($plugin_type ==
'modifier') {
808 $this->modifier_plugins[$plugin_name] =
true;
813 if (is_callable($function)) {
834 $result = call_user_func_array($this->smarty->default_plugin_handler_func, array($tag, $plugin_type, $this->
template, &$callback, &$script, &$cacheable));
836 $this->tag_nocache = $this->tag_nocache || !$cacheable;
837 if ($script !== null) {
838 if (is_file($script)) {
839 if ($this->template->caching && ($this->nocache || $this->tag_nocache)) {
840 $this->
template->required_plugins[
'nocache'][$tag][$plugin_type][
'file'] = $script;
841 $this->
template->required_plugins[
'nocache'][$tag][$plugin_type][
'function'] = $callback;
843 $this->
template->required_plugins[
'compiled'][$tag][$plugin_type][
'file'] = $script;
844 $this->
template->required_plugins[
'compiled'][$tag][$plugin_type][
'function'] = $callback;
846 require_once $script;
848 $this->
trigger_template_error(
"Default plugin handler: Returned script file \"{$script}\" for \"{$tag}\" not found");
851 if (!is_string($callback) && !(is_array($callback) && is_string($callback[0]) && is_string($callback[1]))) {
852 $this->
trigger_template_error(
"Default plugin handler: Returned callback for \"{$tag}\" must be a static function name or array of class and function name");
854 if (is_callable($callback)) {
855 $this->default_handler_plugins[$plugin_type][$tag] = array($callback,
true, array());
876 if (preg_match(
'/\s*\?>\s*$/', $left) && preg_match(
'/^\s*<\?php\s+/', $right)) {
877 $left = preg_replace(
'/\s*\?>\s*$/',
"\n", $left);
878 $left .= preg_replace(
'/^\s*<\?php\s+/',
'', $right);
899 if ($is_code && !empty($content)) {
901 if ((!($this->template->source->recompiled) || $this->forceNocache) && $this->template->caching && !$this->suppressNocacheProcessing && ($this->nocache || $this->tag_nocache)
903 $this->
template->has_nocache_code =
true;
904 $_output = addcslashes($content,
'\'\\
');
905 $_output = str_replace("^#^", "'", $_output);
906 $_output = "<?php echo
'/*%%SmartyNocache:{$this->nocache_hash}%%*/" . $_output . "/*/%%SmartyNocache:{$this->nocache_hash}%%*/';?>\n
";
907 // make sure we include modifier plugins for nocache code
908 foreach ($this->modifier_plugins as $plugin_name => $dummy) {
909 if (isset($this->template->required_plugins['compiled'][$plugin_name]['modifier'])) {
910 $this->template->required_plugins['nocache'][$plugin_name]['modifier'] = $this->template->required_plugins['compiled'][$plugin_name]['modifier'];
919 $this->modifier_plugins = array();
920 $this->suppressNocacheProcessing = false;
921 $this->tag_nocache = false;
933 public function makeNocacheCode($code)
935 return "echo
'/*%%SmartyNocache:{$this->nocache_hash}%%*/<?php " . str_replace("^#^", "'", addcslashes($code, '\'\\')) . "?>
';\n";
946 public function pushTrace($file, $uid, $line, $debug = true)
948 if ($this->smarty->debugging && $debug) {
949 Smarty_Internal_Debug::end_compile($this->template);
951 array_push($this->trace_stack, array($this->smarty->_current_file, $this->trace_filepath, $this->trace_uid, $this->trace_line_offset));
952 $this->trace_filepath = $this->smarty->_current_file = $file;
953 $this->trace_uid = $uid;
954 $this->trace_line_offset = $line;
955 if ($this->smarty->debugging) {
956 Smarty_Internal_Debug::start_compile($this->template);
963 public function popTrace()
965 if ($this->smarty->debugging) {
966 Smarty_Internal_Debug::end_compile($this->template);
968 $r = array_pop($this->trace_stack);
969 $this->smarty->_current_file = $r[0];
970 $this->trace_filepath = $r[1];
971 $this->trace_uid = $r[2];
972 $this->trace_line_offset = $r[3];
973 if ($this->smarty->debugging) {
974 Smarty_Internal_Debug::start_compile($this->template);
989 public function trigger_template_error($args = null, $line = null)
991 // get template source line which has error
993 $line = $this->lex->line;
995 // $line += $this->trace_line_offset;
996 $match = preg_split("/\n/", $this->lex->data);
997 $error_text = 'Syntax error in
template "' . (empty($this->trace_filepath) ? $this->template->source->filepath : $this->trace_filepath) . '" on line
' . ($line + $this->trace_line_offset) . ' "' . trim(preg_replace('![\t\r\n]+!', ' ', $match[$line - 1])) . '" ';
999 // individual error message
1000 $error_text .= $args;
1003 // expected token from parser
1004 $error_text .= ' - Unexpected
"' . $this->lex->value . '"';
1005 if (count($this->parser->yy_get_expected_tokens($this->parser->yymajor)) <= 4) {
1006 foreach ($this->parser->yy_get_expected_tokens($this->parser->yymajor) as $token) {
1007 $exp_token = $this->parser->yyTokenName[$token];
1008 if (isset($this->lex->smarty_token_names[$exp_token])) {
1009 // token type from lexer
1010 $expect[] = '"' . $this->lex->smarty_token_names[$exp_token] . '"';
1012 // otherwise internal token name
1013 $expect[] = $this->parser->yyTokenName[$token];
1016 $error_text .= ', expected one of:
' . implode(' ,
', $expect);
1019 $e = new SmartyCompilerException($error_text);
1021 $e->source = trim(preg_replace('![\t\r\n]+!
', ' ', $match[$line - 1]));
1023 $e->template = $this->template->source->filepath;