From cc3f69a2a33cf166c348aa5b742cf9f4c5aa01fc Mon Sep 17 00:00:00 2001 From: uwetews Date: Sun, 1 Nov 2015 02:58:27 +0100 Subject: [PATCH] - update config file processing --- change_log.txt | 3 + lexer/smarty_internal_templateparser.y | 8 +- libs/Smarty.class.php | 2 +- .../smarty_internal_compile_config_load.php | 38 +++-- .../smarty_internal_config_file_compiler.php | 4 +- .../smarty_internal_method_configload.php | 135 ++++++++++++++---- .../smarty_internal_runtime_config.php | 39 ----- .../smarty_internal_runtime_subtemplate.php | 34 +++-- .../smarty_internal_templatecompilerbase.php | 25 +++- .../smarty_internal_templateparser.php | 19 ++- .../smarty_internal_testinstall.php | 1 - 11 files changed, 196 insertions(+), 112 deletions(-) delete mode 100644 libs/sysplugins/smarty_internal_runtime_config.php diff --git a/change_log.txt b/change_log.txt index 1be6ac27..36f1749f 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,7 @@  ===== 3.1.28-dev===== (xx.xx.2015) + 01.11.2015 + - update config file processing + 31.10.2015 - bugfix add missing $trusted_dir property to SmartyBC class (forum topic 25751) diff --git a/lexer/smarty_internal_templateparser.y b/lexer/smarty_internal_templateparser.y index 03fa4967..47d81c01 100644 --- a/lexer/smarty_internal_templateparser.y +++ b/lexer/smarty_internal_templateparser.y @@ -903,19 +903,19 @@ variable(res) ::= object(o). { // config variable variable(res) ::= HATCH ID(i) HATCH. { - res = '$_smarty_tpl->smarty->ext->_config->_getConfigVariable($_smarty_tpl, \''. i .'\')'; + res = $this->compiler->compileConfigVariable("'" . i . "'"); } variable(res) ::= HATCH ID(i) HATCH arrayindex(a). { - res = '(is_array($tmp = $_smarty_tpl->smarty->ext->_config->_getConfigVariable($_smarty_tpl, \''. i .'\')) ? $tmp'.a.' :null)'; + res = '(is_array($tmp = ' . $this->compiler->compileConfigVariable("'" . i . "'") . ') ? $tmp'.a.' :null)'; } variable(res) ::= HATCH variable(v) HATCH. { - res = '$_smarty_tpl->smarty->ext->_config->_getConfigVariable($_smarty_tpl, '. v .')'; + res = $this->compiler->compileConfigVariable(v); } variable(res) ::= HATCH variable(v) HATCH arrayindex(a). { - res = '(is_array($tmp = $_smarty_tpl->smarty->ext->_config->_getConfigVariable($_smarty_tpl, '. v .')) ? $tmp'.a.' : null)'; + res = '(is_array($tmp = ' . $this->compiler->compileConfigVariable(v) . ') ? $tmp'.a.' : null)'; } varindexed(res) ::= DOLLARID(i) arrayindex(a). { diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index 9ceff2f7..6ad1f789 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -118,7 +118,7 @@ class Smarty extends Smarty_Internal_TemplateBase /** * smarty version */ - const SMARTY_VERSION = '3.1.28-dev/75'; + const SMARTY_VERSION = '3.1.28-dev/76'; /** * define variable scopes diff --git a/libs/sysplugins/smarty_internal_compile_config_load.php b/libs/sysplugins/smarty_internal_compile_config_load.php index 69c44882..d2e50a08 100644 --- a/libs/sysplugins/smarty_internal_compile_config_load.php +++ b/libs/sysplugins/smarty_internal_compile_config_load.php @@ -38,7 +38,15 @@ class Smarty_Internal_Compile_Config_Load extends Smarty_Internal_CompileBase * @var array * @see Smarty_Internal_CompileBase */ - public $optional_attributes = array('section', 'scope'); + public $optional_attributes = array('section', 'scope', 'bubble_up'); + + /** + * Valid scope names + * + * @var array + */ + public $valid_scopes = array('local' => true, 'parent' => true, 'root' => true, 'global' => true, + 'smarty' => true, 'tpl_root' => true); /** * Compiles code for the {config_load} tag @@ -51,7 +59,6 @@ class Smarty_Internal_Compile_Config_Load extends Smarty_Internal_CompileBase */ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler) { - static $_is_legal_scope = array('local' => true, 'parent' => true, 'root' => true, 'global' => true); // check and get attributes $_attr = $this->getAttributes($compiler, $args); @@ -66,18 +73,31 @@ class Smarty_Internal_Compile_Config_Load extends Smarty_Internal_CompileBase } else { $section = 'null'; } - $scope = 'local'; - // scope setup + $_scope = Smarty::SCOPE_LOCAL; if (isset($_attr['scope'])) { $_attr['scope'] = trim($_attr['scope'], "'\""); - if (isset($_is_legal_scope[$_attr['scope']])) { - $scope = $_attr['scope']; - } else { - $compiler->trigger_template_error('illegal value for "scope" attribute', null, true); + if (!isset($this->valid_scopes[$_attr['scope']])) { + $compiler->trigger_template_error("illegal value '{$_attr['scope']}' for \"scope\" attribute", null, true); + } + if ($_attr['scope'] != 'local') { + if ($_attr['scope'] == 'parent') { + $_scope = Smarty::SCOPE_PARENT; + } elseif ($_attr['scope'] == 'root') { + $_scope = Smarty::SCOPE_ROOT; + } elseif ($_attr['scope'] == 'global') { + $_scope = Smarty::SCOPE_GLOBAL; + } elseif ($_attr['scope'] == 'smarty') { + $_scope = Smarty::SCOPE_SMARTY; + } elseif ($_attr['scope'] == 'tpl_root') { + $_scope = Smarty::SCOPE_TPL_ROOT; + } + $_scope += (isset($_attr['bubble_up']) && $_attr['bubble_up'] == 'false') ? 0 : Smarty::SCOPE_BUBBLE_UP; } } + // create config object - $_output = "configLoad($conf_file, $section, '$scope');?>"; + $_output = + "smarty->ext->configLoad->_loadConfigFile(\$_smarty_tpl, {$conf_file}, {$section}, {$_scope});\n?>\n"; return $_output; } diff --git a/libs/sysplugins/smarty_internal_config_file_compiler.php b/libs/sysplugins/smarty_internal_config_file_compiler.php index 4cf3a0c3..56d3b066 100644 --- a/libs/sysplugins/smarty_internal_config_file_compiler.php +++ b/libs/sysplugins/smarty_internal_config_file_compiler.php @@ -108,8 +108,10 @@ class Smarty_Internal_Config_File_Compiler $this->smarty->_debug->start_compile($this->template); } // init the lexer/parser to compile the config file + /* @var Smarty_Internal_ConfigFileLexer $lex */ $lex = new $this->lexer_class(str_replace(array("\r\n", "\r"), "\n", $template->source->getContent()) . "\n", $this); + /* @var Smarty_Internal_ConfigFileParser $parser */ $parser = new $this->parser_class($lex, $this); if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) { @@ -143,7 +145,7 @@ class Smarty_Internal_Config_File_Compiler strftime("%Y-%m-%d %H:%M:%S") . "\n"; $template_header .= " compiled from \"" . $this->template->source->filepath . "\" */ ?>\n"; - $code = 'smarty->ext->configLoad->_loadConfigVars($_smarty_tpl, ' . var_export($this->config_data, true) . '); ?>'; return $template_header . $this->template->smarty->ext->_codeFrame->create($this->template, $code); } diff --git a/libs/sysplugins/smarty_internal_method_configload.php b/libs/sysplugins/smarty_internal_method_configload.php index 2832bfe4..ec023ec8 100644 --- a/libs/sysplugins/smarty_internal_method_configload.php +++ b/libs/sysplugins/smarty_internal_method_configload.php @@ -28,18 +28,38 @@ class Smarty_Internal_Method_ConfigLoad * @param string $config_file filename * @param mixed $sections array of section names, single * section or null - * @param string $scope scope into which config variables + * + * @return \Smarty|\Smarty_Internal_Data|\Smarty_Internal_Template + * @throws \SmartyException + */ + public function configLoad(Smarty_Internal_Data $data, $config_file, $sections = null) + { + $this->_loadConfigFile($data, $config_file, $sections, 0); + return $data; + } + + /** + * load a config file, optionally load just selected sections + * + * @api Smarty::configLoad() + * @link http://www.smarty.net/docs/en/api.config.load.tpl + * + * @param \Smarty|\Smarty_Internal_Data|\Smarty_Internal_Template $data + * @param string $config_file filename + * @param mixed $sections array of section names, single + * section or null + * @param int $scope scope into which config variables * shall be loaded * * @return \Smarty|\Smarty_Internal_Data|\Smarty_Internal_Template * @throws \SmartyException */ - public function configLoad(Smarty_Internal_Data $data, $config_file, $sections = null, $scope = 'local') + public function _loadConfigFile(Smarty_Internal_Data $data, $config_file, $sections = null, $scope = 0) { /* @var \Smarty $smarty */ $smarty = isset($data->smarty) ? $data->smarty : $data; /* @var \Smarty_Internal_Template $confObj */ - $confObj = new $smarty->template_class($config_file, $smarty, $data); + $confObj = new Smarty_Internal_Template($config_file, $smarty, $data); $confObj->caching = Smarty::CACHING_OFF; $confObj->source = Smarty_Template_Config::load($confObj); $confObj->source->config_sections = $sections; @@ -47,55 +67,116 @@ class Smarty_Internal_Method_ConfigLoad $confObj->compiled = Smarty_Template_Compiled::load($confObj); $confObj->compiled->render($confObj); if ($data->_objType == 2) { - $data->compiled->file_dependency[$confObj->source->uid] = array($confObj->source->filepath, - $confObj->source->getTimeStamp(), - $confObj->source->type); + $data->compiled->file_dependency[$confObj->source->uid] = + array($confObj->source->filepath, $confObj->source->getTimeStamp(), $confObj->source->type); } - return $data; } /** * load config variables into template object * - * @param \Smarty_Internal_Template $_template + * @param \Smarty_Internal_Template $tpl * @param array $_config_vars + * */ - static function _loadConfigVars(Smarty_Internal_Template $_template, $_config_vars) + public function _loadConfigVars(Smarty_Internal_Template $tpl, $_config_vars) { - $scope = $_template->source->scope; - // pointer to scope (local scope is parent of template object - $scope_ptr = $_template->parent; - if ($scope == 'parent') { - if (isset($_template->parent->parent)) { - $scope_ptr = $_template->parent->parent; - } - } elseif ($scope == 'root' || $scope == 'global') { - while (isset($scope_ptr->parent)) { - $scope_ptr = $scope_ptr->parent; + $this->_assignConfigVars($tpl->parent, $tpl, $_config_vars); + $scope = $tpl->source->scope; + if (!$scope && !$tpl->scope) { + return; + } + foreach (array($scope, $tpl->scope) as $s) { + $s = ($bubble_up = $s >= Smarty::SCOPE_BUBBLE_UP) ? $s - Smarty::SCOPE_BUBBLE_UP : $s; + if ($bubble_up && $s) { + $ptr = $tpl->parent->parent; + if (isset($ptr)) { + $this->_assignConfigVars($ptr, $tpl, $_config_vars); + $ptr = $ptr->parent; + } + if ($s == Smarty::SCOPE_PARENT) { + continue; + } + while (isset($ptr) && $ptr->_objType == 2) { + $this->_assignConfigVars($ptr, $tpl, $_config_vars); + $ptr = $ptr->parent; + } + if ($s == Smarty::SCOPE_TPL_ROOT) { + continue; + } elseif ($s == Smarty::SCOPE_SMARTY) { + $this->_assignConfigVars($tpl->smarty, $tpl, $_config_vars); + } elseif ($s == Smarty::SCOPE_GLOBAL) { + $this->_assignConfigVars($tpl->smarty, $tpl, $_config_vars); + } elseif ($s == Smarty::SCOPE_ROOT) { + while (isset($ptr->parent)) { + $ptr = $ptr->parent; + } + $this->_assignConfigVars($ptr, $tpl, $_config_vars); + } } } + } + + /** + * Assign all config variables in given scope + * + * @param \Smarty_Internal_Data $scope_ptr + * @param \Smarty_Internal_Template $tpl + * @param array $_config_vars + */ + public function _assignConfigVars(Smarty_Internal_Data $scope_ptr, Smarty_Internal_Template $tpl, $_config_vars) + { // copy global config vars foreach ($_config_vars['vars'] as $variable => $value) { - if ($_template->smarty->config_overwrite || !isset($scope_ptr->config_vars[$variable])) { + if ($tpl->smarty->config_overwrite || !isset($scope_ptr->config_vars[$variable])) { $scope_ptr->config_vars[$variable] = $value; } else { - $scope_ptr->config_vars[$variable] = array_merge((array) $scope_ptr->config_vars[$variable], (array) $value); + $scope_ptr->config_vars[$variable] = + array_merge((array) $scope_ptr->config_vars[$variable], (array) $value); } } // scan sections - $sections = $_template->source->config_sections; + $sections = $tpl->source->config_sections; if (!empty($sections)) { - foreach ((array) $sections as $_template_section) { - if (isset($_config_vars['sections'][$_template_section])) { - foreach ($_config_vars['sections'][$_template_section]['vars'] as $variable => $value) { - if ($_template->smarty->config_overwrite || !isset($scope_ptr->config_vars[$variable])) { + foreach ((array) $sections as $tpl_section) { + if (isset($_config_vars['sections'][$tpl_section])) { + foreach ($_config_vars['sections'][$tpl_section]['vars'] as $variable => $value) { + if ($tpl->smarty->config_overwrite || !isset($scope_ptr->config_vars[$variable])) { $scope_ptr->config_vars[$variable] = $value; } else { - $scope_ptr->config_vars[$variable] = array_merge((array) $scope_ptr->config_vars[$variable], (array) $value); + $scope_ptr->config_vars[$variable] = + array_merge((array) $scope_ptr->config_vars[$variable], (array) $value); } } } } } } + + /** + * gets a config variable value + * + * @param \Smarty_Internal_Template $tpl template object + * @param string $varName the name of the config variable + * @param bool $errorEnable + * + * @return mixed the value of the config variable + */ + public function _getConfigVariable(\Smarty_Internal_Template $tpl, $varName, $errorEnable = true) + { + $_ptr = $tpl; + while ($_ptr !== null) { + if (isset($_ptr->config_vars[$varName])) { + // found it, return it + return $_ptr->config_vars[$varName]; + } + // not found, try at parent + $_ptr = $_ptr->parent; + } + if ($tpl->smarty->error_unassigned && $errorEnable) { + // force a notice + $x = $$varName; + } + return null; + } } diff --git a/libs/sysplugins/smarty_internal_runtime_config.php b/libs/sysplugins/smarty_internal_runtime_config.php deleted file mode 100644 index 895dae1a..00000000 --- a/libs/sysplugins/smarty_internal_runtime_config.php +++ /dev/null @@ -1,39 +0,0 @@ -config_vars[$varName])) { - // found it, return it - return $_ptr->config_vars[$varName]; - } - // not found, try at parent - $_ptr = $_ptr->parent; - } - if ($tpl->smarty->error_unassigned && $errorEnable) { - // force a notice - $x = $$varName; - } - return null; - } -} diff --git a/libs/sysplugins/smarty_internal_runtime_subtemplate.php b/libs/sysplugins/smarty_internal_runtime_subtemplate.php index 252c89ab..2c7623f9 100644 --- a/libs/sysplugins/smarty_internal_runtime_subtemplate.php +++ b/libs/sysplugins/smarty_internal_runtime_subtemplate.php @@ -59,8 +59,8 @@ class Smarty_Internal_Runtime_SubTemplate unset($tpl->compiled); } // get variables from calling scope - $tpl->tpl_vars = $parent->tpl_vars; - $tpl->config_vars = $parent->config_vars; + $tpl->tpl_vars = $parent->tpl_vars; + $tpl->config_vars = $parent->config_vars; // get template functions $tpl->tpl_function = $parent->tpl_function; // copy inheritance object? @@ -114,22 +114,25 @@ class Smarty_Internal_Runtime_SubTemplate if ($scope & ~Smarty::SCOPE_BUBBLE_UP) { if ($scope == Smarty::SCOPE_GLOBAL) { $tpl->tpl_vars = Smarty::$global_tpl_vars; + $tpl->config_vars = $tpl->smarty->config_vars; $scopePtr = true; - } elseif ($scope == Smarty::SCOPE_PARENT) { - $scopePtr = $parent; - } elseif ($scope == Smarty::SCOPE_SMARTY) { - $scopePtr = $tpl->smarty; } else { - $scopePtr = $tpl; - while (isset($scopePtr->parent)) { - if ($scopePtr->parent->_objType != 2 && $scope & Smarty::SCOPE_TPL_ROOT) { - break; + if ($scope == Smarty::SCOPE_PARENT) { + $scopePtr = $parent; + } elseif ($scope == Smarty::SCOPE_SMARTY) { + $scopePtr = $tpl->smarty; + } else { + $scopePtr = $tpl; + while (isset($scopePtr->parent)) { + if ($scopePtr->parent->_objType != 2 && $scope & Smarty::SCOPE_TPL_ROOT) { + break; + } + $scopePtr = $scopePtr->parent; } - $scopePtr = $scopePtr->parent; } + $tpl->tpl_vars = $scopePtr->tpl_vars; + $tpl->config_vars = $scopePtr->config_vars; } - $tpl->tpl_vars = $scopePtr->tpl_vars; - $tpl->config_vars = $scopePtr->config_vars; } if (!isset($this->tplObjects[$tpl->_getTemplateId()]) && !$tpl->source->handler->recompiled) { @@ -174,6 +177,7 @@ class Smarty_Internal_Runtime_SubTemplate if ($scopePtr) { if ($scope == Smarty::SCOPE_GLOBAL) { Smarty::$global_tpl_vars = $tpl->tpl_vars; + $tpl->smarty->config_vars = $tpl->config_vars; } else { $scopePtr->tpl_vars = $tpl->tpl_vars; $scopePtr->config_vars = $tpl->config_vars; @@ -186,7 +190,8 @@ class Smarty_Internal_Runtime_SubTemplate * * @param \Smarty_Internal_Template $tpl */ - public function registerSubTemplates(Smarty_Internal_Template $tpl) { + public function registerSubTemplates(Smarty_Internal_Template $tpl) + { foreach ($tpl->compiled->includes as $name => $count) { if (isset($this->subTplInfo[$name])) { $this->subTplInfo[$name] += $count; @@ -194,6 +199,5 @@ class Smarty_Internal_Runtime_SubTemplate $this->subTplInfo[$name] = $count; } } - } } diff --git a/libs/sysplugins/smarty_internal_templatecompilerbase.php b/libs/sysplugins/smarty_internal_templatecompilerbase.php index ed3bb280..59cf2192 100644 --- a/libs/sysplugins/smarty_internal_templatecompilerbase.php +++ b/libs/sysplugins/smarty_internal_templatecompilerbase.php @@ -317,10 +317,11 @@ abstract class Smarty_Internal_TemplateCompilerBase Smarty_Internal_TemplateCompilerBase $parent_compiler = null) { // get code frame of compiled template - $_compiled_code = $template->smarty->ext->_codeFrame->create($template, $this->compileTemplateSource($template, $nocache, - $parent_compiler), - $this->postFilter($this->blockOrFunctionCode) . - join('', $this->mergedSubTemplatesCode)); + $_compiled_code = $template->smarty->ext->_codeFrame->create($template, + $this->compileTemplateSource($template, $nocache, + $parent_compiler), + $this->postFilter($this->blockOrFunctionCode) . + join('', $this->mergedSubTemplatesCode)); return $_compiled_code; } @@ -744,12 +745,26 @@ abstract class Smarty_Internal_TemplateCompilerBase if (strpos($variable, '(') == 0) { // not a variable variable $var = trim($variable, '\''); - $this->tag_nocache = $this->tag_nocache | $this->template->ext->getTemplateVars->_getVariable($this->template, $var, null, true, false)->nocache; + $this->tag_nocache = $this->tag_nocache | + $this->template->ext->getTemplateVars->_getVariable($this->template, $var, null, true, false)->nocache; // todo $this->template->compiled->properties['variables'][$var] = $this->tag_nocache | $this->nocache; } return '$_smarty_tpl->tpl_vars[' . $variable . ']->value'; } + /** + * compile config variable + * + * @param string $variable + * + * @return string + */ + public function compileConfigVariable($variable) + { + // return '$_smarty_tpl->config_vars[' . $variable . ']'; + return '$_smarty_tpl->smarty->ext->configLoad->_getConfigVariable($_smarty_tpl, ' . $variable . ')'; + } + /** * This method is called from parser to process a text content section * - remove text from inheritance child templates as they may generate output diff --git a/libs/sysplugins/smarty_internal_templateparser.php b/libs/sysplugins/smarty_internal_templateparser.php index 98833973..57dbf61a 100644 --- a/libs/sysplugins/smarty_internal_templateparser.php +++ b/libs/sysplugins/smarty_internal_templateparser.php @@ -2197,31 +2197,30 @@ class Smarty_Internal_Templateparser #line 905 "../smarty/lexer/smarty_internal_templateparser.y" function yy_r118() { - $this->_retvalue = '$_smarty_tpl->smarty->ext->_config->_getConfigVariable($_smarty_tpl, \'' . - $this->yystack[$this->yyidx + - 1]->minor . '\')'; + $this->_retvalue = + $this->compiler->compileConfigVariable("'" . $this->yystack[$this->yyidx + - 1]->minor . "'"); } #line 909 "../smarty/lexer/smarty_internal_templateparser.y" function yy_r119() { - $this->_retvalue = '(is_array($tmp = $_smarty_tpl->smarty->ext->_config->_getConfigVariable($_smarty_tpl, \'' . - $this->yystack[$this->yyidx + - 2]->minor . '\')) ? $tmp' . $this->yystack[$this->yyidx + 0]->minor . - ' :null)'; + $this->_retvalue = '(is_array($tmp = ' . + $this->compiler->compileConfigVariable("'" . $this->yystack[$this->yyidx + - 2]->minor . "'") . ') ? $tmp' . + $this->yystack[$this->yyidx + 0]->minor . ' :null)'; } #line 913 "../smarty/lexer/smarty_internal_templateparser.y" function yy_r120() { - $this->_retvalue = '$_smarty_tpl->smarty->ext->_config->_getConfigVariable($_smarty_tpl, ' . - $this->yystack[$this->yyidx + - 1]->minor . ')'; + $this->_retvalue = $this->compiler->compileConfigVariable($this->yystack[$this->yyidx + - 1]->minor); } #line 917 "../smarty/lexer/smarty_internal_templateparser.y" function yy_r121() { - $this->_retvalue = '(is_array($tmp = $_smarty_tpl->smarty->ext->_config->_getConfigVariable($_smarty_tpl, ' . - $this->yystack[$this->yyidx + - 2]->minor . ')) ? $tmp' . $this->yystack[$this->yyidx + 0]->minor . - ' : null)'; + $this->_retvalue = + '(is_array($tmp = ' . $this->compiler->compileConfigVariable($this->yystack[$this->yyidx + - 2]->minor) . + ') ? $tmp' . $this->yystack[$this->yyidx + 0]->minor . ' : null)'; } #line 921 "../smarty/lexer/smarty_internal_templateparser.y" diff --git a/libs/sysplugins/smarty_internal_testinstall.php b/libs/sysplugins/smarty_internal_testinstall.php index b23f5592..5b6475cc 100644 --- a/libs/sysplugins/smarty_internal_testinstall.php +++ b/libs/sysplugins/smarty_internal_testinstall.php @@ -471,7 +471,6 @@ class Smarty_Internal_TestInstall 'smarty_internal_resource_string.php' => true, 'smarty_internal_runtime_cachemodify.php' => true, 'smarty_internal_runtime_codeframe.php' => true, - 'smarty_internal_runtime_config.php' => true, 'smarty_internal_runtime_filterhandler.php' => true, 'smarty_internal_runtime_foreach.php' => true, 'smarty_internal_runtime_getincludepath.php' => true,