diff --git a/change_log.txt b/change_log.txt index 39c841ef..d4eeb703 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,3 +1,6 @@ +31/03/2010 +- compile locking by touching old compiled files to avoid concurrent compilations + 29/03/2010 - bugfix allow array definitions as modifier parameter - bugfix observe compile_check property when loading config files diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index 96ba6fb3..427a9888 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -129,6 +129,8 @@ class Smarty extends Smarty_Internal_Data { public $force_compile = false; // check template for modifications? public $compile_check = true; + // locking concurrent compiles + public $compile_locking = true; // use sub dirs for compiled/cached files? public $use_sub_dirs = false; // compile_error? diff --git a/libs/sysplugins/smarty_internal_config.php b/libs/sysplugins/smarty_internal_config.php index abbfcb93..6d485200 100644 --- a/libs/sysplugins/smarty_internal_config.php +++ b/libs/sysplugins/smarty_internal_config.php @@ -173,88 +173,96 @@ class Smarty_Internal_Config { { return $this->mustCompile === null ? $this->mustCompile = ($this->smarty->force_compile || $this->smarty->compile_check && $this->getCompiledTimestamp () !== $this->getTimestamp ()): - $this->mustCompile; - } - /** - * Returns the compiled config file - * - * It checks if the config file must be compiled or just read the compiled version - * - * @return string the compiled config file - */ - public function getCompiledConfig () - { - if ($this->compiled_config === null) { - // see if template needs compiling. - if ($this->mustCompile()) { - $this->compileConfigSource(); - } else { - $this->compiled_config = file_get_contents($this->getCompiledFilepath()); - } - } - return $this->compiled_config; - } - - /** - * Compiles the config files - */ - public function compileConfigSource () - { - // compile template - if (!is_object($this->compiler_object)) { - // load compiler - $this->compiler_object = new Smarty_Internal_Config_File_Compiler($this->smarty); - } - // call compiler - if ($this->compiler_object->compileSource($this)) { - // compiling succeded - // write compiled template - Smarty_Internal_Write_File::writeFile($this->getCompiledFilepath(), $this->getCompiledConfig(), $this->smarty); - // make template and compiled file timestamp match - touch($this->getCompiledFilepath(), $this->getTimestamp()); + $this->mustCompile; + } + /** + * Returns the compiled config file + * + * It checks if the config file must be compiled or just read the compiled version + * + * @return string the compiled config file + */ + public function getCompiledConfig () + { + if ($this->compiled_config === null) { + // see if template needs compiling. + if ($this->mustCompile()) { + $this->compileConfigSource(); } else { - // error compiling template - throw new Exception("Error compiling template {$this->getConfigFilepath ()}"); - return false; + $this->compiled_config = file_get_contents($this->getCompiledFilepath()); } } + return $this->compiled_config; + } - /* + /** + * Compiles the config files + */ + public function compileConfigSource () + { + // compile template + if (!is_object($this->compiler_object)) { + // load compiler + $this->compiler_object = new Smarty_Internal_Config_File_Compiler($this->smarty); + } + // compile locking + if ($this->smarty->compile_locking) { + if ($saved_timestamp = $this->getCompiledTimestamp()) { + touch($this->getCompiledFilepath()); + } + } + // call compiler + try { + $this->compiler_object->compileSource($this); + } + catch (Exception $e) { + // restore old timestamp in case of error + if ($this->smarty->compile_locking && $saved_timestamp) { + touch($this->getCompiledFilepath(), $saved_timestamp); + } + throw $e; + } + // compiling succeded + // write compiled template + Smarty_Internal_Write_File::writeFile($this->getCompiledFilepath(), $this->getCompiledConfig(), $this->smarty); + } + + /* * load config variables * * @param mixed $sections array of section names, single section or null * @param object $scope global,parent or local */ - public function loadConfigVars ($sections = null, $scope) - { - if (isset($this->template)) { - $this->template->properties['file_dependency'][sha1($this->getConfigFilepath())] = array($this->getConfigFilepath(), $this->getTimestamp()); + public function loadConfigVars ($sections = null, $scope) + { + if (isset($this->template)) { + $this->template->properties['file_dependency'][sha1($this->getConfigFilepath())] = array($this->getConfigFilepath(), $this->getTimestamp()); + } else { + $this->smarty->properties['file_dependency'][sha1($this->getConfigFilepath())] = array($this->getConfigFilepath(), $this->getTimestamp()); + } + $config_data = unserialize($this->getCompiledConfig()); + // var_dump($config_data); + // copy global config vars + foreach ($config_data['vars'] as $variable => $value) { + if ($this->smarty->config_overwrite || !isset($scope->config_vars[$variable])) { + $scope->config_vars[$variable] = $value; } else { - $this->smarty->properties['file_dependency'][sha1($this->getConfigFilepath())] = array($this->getConfigFilepath(), $this->getTimestamp()); + $scope->config_vars[$variable] = array_merge((array)$scope->config_vars[$variable], (array)$value); } - $config_data = unserialize($this->getCompiledConfig()); - // var_dump($config_data); - // copy global config vars - foreach ($config_data['vars'] as $variable => $value) { - if ($this->smarty->config_overwrite || !isset($scope->config_vars[$variable])) { - $scope->config_vars[$variable] = $value; - } else { - $scope->config_vars[$variable] = array_merge((array)$scope->config_vars[$variable], (array)$value); - } - } - // scan sections - foreach ($config_data['sections'] as $this_section => $dummy) { - if ($sections == null || in_array($this_section, (array)$sections)) { - foreach ($config_data['sections'][$this_section]['vars'] as $variable => $value) { - if ($this->smarty->config_overwrite || !isset($scope->config_vars[$variable])) { - $scope->config_vars[$variable] = $value; - } else { - $scope->config_vars[$variable] = array_merge((array)$scope->config_vars[$variable], (array)$value); - } + } + // scan sections + foreach ($config_data['sections'] as $this_section => $dummy) { + if ($sections == null || in_array($this_section, (array)$sections)) { + foreach ($config_data['sections'][$this_section]['vars'] as $variable => $value) { + if ($this->smarty->config_overwrite || !isset($scope->config_vars[$variable])) { + $scope->config_vars[$variable] = $value; + } else { + $scope->config_vars[$variable] = array_merge((array)$scope->config_vars[$variable], (array)$value); } } } } } +} - ?> \ No newline at end of file +?> \ No newline at end of file diff --git a/libs/sysplugins/smarty_internal_config_file_compiler.php b/libs/sysplugins/smarty_internal_config_file_compiler.php index f120b56d..5662a21b 100644 --- a/libs/sysplugins/smarty_internal_config_file_compiler.php +++ b/libs/sysplugins/smarty_internal_config_file_compiler.php @@ -14,7 +14,6 @@ * Main config file compiler class */ class Smarty_Internal_Config_File_Compiler { - public $compile_error = false; /** * Initialize compiler */ @@ -59,12 +58,6 @@ class Smarty_Internal_Config_File_Compiler { $parser->doParse(0, 0); $config->compiled_config = serialize($this->config_data); - if (!$this->compile_error) { - return true; - } else { - // compilation error - return false; - } } /** * display compiler error messages without dying @@ -107,8 +100,6 @@ class Smarty_Internal_Config_File_Compiler { $error_text .= ' - Unexpected "' . $this->lex->value . '", expected one of: ' . implode(' , ', $expect); } throw new Exception($error_text); - // set error flag - $this->compile_error = true; } } diff --git a/libs/sysplugins/smarty_internal_smartytemplatecompiler.php b/libs/sysplugins/smarty_internal_smartytemplatecompiler.php index a6b7e7c3..58f0c8ad 100644 --- a/libs/sysplugins/smarty_internal_smartytemplatecompiler.php +++ b/libs/sysplugins/smarty_internal_smartytemplatecompiler.php @@ -1,22 +1,22 @@ smarty = $smarty; @@ -27,11 +27,11 @@ class Smarty_Internal_SmartyTemplateCompiler extends Smarty_Internal_TemplateCom } /** - * Methode to compile a Smarty template - * - * @param $_content template source - * @return bool true if compiling succeeded, false if it failed - */ + * Methode to compile a Smarty template + * + * @param $_content template source + * @return bool true if compiling succeeded, false if it failed + */ protected function doCompile($_content) { /* here is where the compiling takes place. Smarty @@ -39,11 +39,11 @@ class Smarty_Internal_SmartyTemplateCompiler extends Smarty_Internal_TemplateCom then written to compiled files. */ // init the lexer/parser to compile the template $this->lex = new $this->lexer_class($_content, $this); - $this->parser = new $this->parser_class($this->lex, $this); - if (isset($this->smarty->_parserdebug)) $this->parser->PrintTrace(); + $this->parser = new $this->parser_class($this->lex, $this); + if (isset($this->smarty->_parserdebug)) $this->parser->PrintTrace(); // get tokens from lexer and parse them while ($this->lex->yylex() && !$this->abort_and_recompile) { - if (isset($this->smarty->_parserdebug)) echo "
Line {$this->lex->line} Parsing  {$this->parser->yyTokenName[$this->lex->token]} Token ".htmlentities($this->lex->value)."
"; + if (isset($this->smarty->_parserdebug)) echo "
Line {$this->lex->line} Parsing  {$this->parser->yyTokenName[$this->lex->token]} Token " . htmlentities($this->lex->value) . "
"; $this->parser->doParse($this->lex->token, $this->lex->value); } @@ -59,15 +59,9 @@ class Smarty_Internal_SmartyTemplateCompiler extends Smarty_Internal_TemplateCom list($_open_tag, $_data) = array_pop($this->_tag_stack); $this->trigger_template_error("unclosed {" . $_open_tag . "} tag"); } - - if (!$this->compile_error) { - // return compiled code - // return str_replace(array("? >\nparser->retvalue); - return $this->parser->retvalue; - } else { - // compilation error - return false; - } + // return compiled code + // return str_replace(array("? >\nparser->retvalue); + return $this->parser->retvalue; } } diff --git a/libs/sysplugins/smarty_internal_template.php b/libs/sysplugins/smarty_internal_template.php index f48bf450..d107730b 100644 --- a/libs/sysplugins/smarty_internal_template.php +++ b/libs/sysplugins/smarty_internal_template.php @@ -1,18 +1,18 @@ smarty = &$smarty; @@ -109,12 +109,12 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * Returns the template filepath - * - * The template filepath is determined by the actual resource handler - * - * @return string the template filepath - */ + * Returns the template filepath + * + * The template filepath is determined by the actual resource handler + * + * @return string the template filepath + */ public function getTemplateFilepath () { return $this->template_filepath === null ? @@ -123,12 +123,12 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * Returns the timpestamp of the template source - * - * The template timestamp is determined by the actual resource handler - * - * @return integer the template timestamp - */ + * Returns the timpestamp of the template source + * + * The template timestamp is determined by the actual resource handler + * + * @return integer the template timestamp + */ public function getTemplateTimestamp () { return $this->template_timestamp === null ? @@ -137,12 +137,12 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * Returns the template source code - * - * The template source is being read by the actual resource handler - * - * @return string the template source - */ + * Returns the template source code + * + * The template source is being read by the actual resource handler + * + * @return string the template source + */ public function getTemplateSource () { if ($this->template_source === null) { @@ -154,12 +154,12 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * Returns if the template is existing - * - * The status is determined by the actual resource handler - * - * @return boolean true if the template exists - */ + * Returns if the template is existing + * + * The status is determined by the actual resource handler + * + * @return boolean true if the template exists + */ public function isExisting ($error = false) { if ($this->isExisting === null) { @@ -172,12 +172,12 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * Returns if the current template must be compiled by the Smarty compiler - * - * It does compare the timestamps of template source and the compiled templates and checks the force compile configuration - * - * @return boolean true if the template must be compiled - */ + * Returns if the current template must be compiled by the Smarty compiler + * + * It does compare the timestamps of template source and the compiled templates and checks the force compile configuration + * + * @return boolean true if the template must be compiled + */ public function mustCompile () { $this->isExisting(true); @@ -190,10 +190,10 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * Returns the compiled template filepath - * - * @return string the template filepath - */ + * Returns the compiled template filepath + * + * @return string the template filepath + */ public function getCompiledFilepath () { return $this->compiled_filepath === null ? @@ -202,10 +202,10 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * Returns the timpestamp of the compiled template - * - * @return integer the template timestamp - */ + * Returns the timpestamp of the compiled template + * + * @return integer the template timestamp + */ public function getCompiledTimestamp () { return $this->compiled_timestamp === null ? @@ -214,12 +214,12 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * Returns the compiled template - * - * It checks if the template must be compiled or just read from the template resource - * - * @return string the compiled template - */ + * Returns the compiled template + * + * It checks if the template must be compiled or just read from the template resource + * + * @return string the compiled template + */ public function getCompiledTemplate () { if ($this->compiled_template === null) { @@ -236,10 +236,10 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * Compiles the template - * - * If the template is not evaluated the compiled template is saved on disk - */ + * Compiles the template + * + * If the template is not evaluated the compiled template is saved on disk + */ public function compileTemplateSource () { if (!$this->resource_object->isEvaluated) { @@ -255,17 +255,27 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { $this->smarty->loadPlugin($this->resource_object->compiler_class); $this->compiler_object = new $this->resource_object->compiler_class($this->resource_object->template_lexer_class, $this->resource_object->template_parser_class, $this->smarty); } - // call compiler - if ($this->compiler_object->compileTemplate($this)) { - // compiling succeded - if (!$this->resource_object->isEvaluated) { - // write compiled template - Smarty_Internal_Write_File::writeFile($this->getCompiledFilepath(), $this->compiled_template, $this->smarty); + // compile locking + if ($this->smarty->compile_locking && !$this->resource_object->isEvaluated) { + if ($saved_timestamp = $this->getCompiledTimestamp()) { + touch($this->getCompiledFilepath()); } - } else { - // error compiling template - throw new Exception("Error compiling template {$this->getTemplateFilepath ()}"); - return false; + } + // call compiler + try { + $this->compiler_object->compileTemplate($this); + } + catch (Exception $e) { + // restore old timestamp in case of error + if ($this->smarty->compile_locking && !$this->resource_object->isEvaluated && $saved_timestamp) { + touch($this->getCompiledFilepath(), $saved_timestamp); + } + throw $e; + } + // compiling succeded + if (!$this->resource_object->isEvaluated) { + // write compiled template + Smarty_Internal_Write_File::writeFile($this->getCompiledFilepath(), $this->compiled_template, $this->smarty); } if ($this->smarty->debugging) { Smarty_Internal_Debug::end_compile($this); @@ -273,12 +283,12 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * Returns the filepath of the cached template output - * - * The filepath is determined by the actual cache resource - * - * @return string the cache filepath - */ + * Returns the filepath of the cached template output + * + * The filepath is determined by the actual cache resource + * + * @return string the cache filepath + */ public function getCachedFilepath () { return $this->cached_filepath === null ? @@ -287,12 +297,12 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * Returns the timpestamp of the cached template output - * - * The timestamp is determined by the actual cache resource - * - * @return integer the template timestamp - */ + * Returns the timpestamp of the cached template output + * + * The timestamp is determined by the actual cache resource + * + * @return integer the template timestamp + */ public function getCachedTimestamp () { return $this->cached_timestamp === null ? @@ -301,10 +311,10 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * Returns the cached template output - * - * @return string |booelan the template content or false if the file does not exist - */ + * Returns the cached template output + * + * @return string |booelan the template content or false if the file does not exist + */ public function getCachedContent () { return $this->rendered_content === null ? @@ -313,8 +323,8 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * Writes the cached template output - */ + * Writes the cached template output + */ public function writeCachedContent ($content) { if ($this->resource_object->isEvaluated || !($this->caching == SMARTY_CACHING_LIFETIME_CURRENT || $this->caching == SMARTY_CACHING_LIFETIME_SAVED)) { @@ -326,12 +336,12 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * Checks of a valid version redered HTML output is in the cache - * - * If the cache is valid the contents is stored in the template object - * - * @return boolean true if cache is valid - */ + * Checks of a valid version redered HTML output is in the cache + * + * If the cache is valid the contents is stored in the template object + * + * @return boolean true if cache is valid + */ public function isCached () { if ($this->isCached === null) { @@ -385,12 +395,12 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * Render the output using the compiled template or the PHP template source - * - * The rendering process is accomplished by just including the PHP files. - * The only exceptions are evaluated templates (string template). Their code has - * to be evaluated - */ + * Render the output using the compiled template or the PHP template source + * + * The rendering process is accomplished by just including the PHP files. + * The only exceptions are evaluated templates (string template). Their code has + * to be evaluated + */ public function renderTemplate () { if ($this->resource_object->usesCompiler) { @@ -504,13 +514,13 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * Returns the rendered HTML output - * - * If the cache is valid the cached content is used, otherwise - * the output is rendered from the compiled template or PHP template source - * - * @return string rendered HTML output - */ + * Returns the rendered HTML output + * + * If the cache is valid the cached content is used, otherwise + * the output is rendered from the compiled template or PHP template source + * + * @return string rendered HTML output + */ public function getRenderedTemplate () { // disable caching for evaluated code @@ -530,14 +540,14 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * Parse a template resource in its name and type - * Load required resource handler - * - * @param string $template_resource template resource specification - * @param string $resource_type return resource type - * @param string $resource_name return resource name - * @param object $resource_handler return resource handler object - */ + * Parse a template resource in its name and type + * Load required resource handler + * + * @param string $template_resource template resource specification + * @param string $resource_type return resource type + * @param string $resource_name return resource name + * @param object $resource_handler return resource handler object + */ public function parseResourceName($template_resource, &$resource_type, &$resource_name, &$resource_handler) { if (empty($template_resource)) @@ -554,8 +564,8 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * get system filepath to template - */ + * get system filepath to template + */ public function buildTemplateFilepath ($file = null) { if ($file == null) { @@ -590,8 +600,8 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * Update Smarty variables in other scopes - */ + * Update Smarty variables in other scopes + */ public function updateParentVariables ($scope = SMARTY_LOCAL_SCOPE) { $has_root = false; @@ -645,12 +655,12 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * Split a template resource in its name and type - * - * @param string $template_resource template resource specification - * @param string $resource_type return resource type - * @param string $resource_name return resource name - */ + * Split a template resource in its name and type + * + * @param string $template_resource template resource specification + * @param string $resource_type return resource type + * @param string $resource_name return resource name + */ protected function getResourceTypeName ($template_resource, &$resource_type, &$resource_name) { if (strpos($template_resource, ':') === false) { @@ -671,11 +681,11 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * Load template resource handler by type - * - * @param string $resource_type template resource type - * @return object resource handler object - */ + * Load template resource handler by type + * + * @param string $resource_type template resource type + * @return object resource handler object + */ protected function loadTemplateResourceHandler ($resource_type) { // try registered resource @@ -718,8 +728,8 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * Create property header - */ + * Create property header + */ public function createPropertyHeader ($cache = false) { $plugins_string = ''; @@ -769,8 +779,8 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * Decode saved properties from compiled template and cache files - */ + * Decode saved properties from compiled template and cache files + */ public function decodeProperties ($properties) { $this->has_nocache_code = $properties['has_nocache_code']; @@ -788,21 +798,21 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { } /** - * wrapper for display - */ + * wrapper for display + */ public function display () { return $this->smarty->display($this); } /** - * wrapper for fetch - */ + * wrapper for fetch + */ public function fetch () { return $this->smarty->fetch($this); - } - + } + /** * lazy loads (valid) property objects * @@ -818,10 +828,10 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { // Smarty 2 BC $this->_version = self::SMARTY_VERSION; return $this->_version; - } + } return null; - } - + } + /** * Takes unknown class methods and lazy loads sysplugin files for them * class name format: Smarty_Method_MethodName @@ -852,12 +862,12 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { else return $this->$property_name = $args[0]; } - } + } } /** -* wrapper for template class -*/ + * wrapper for template class + */ class Smarty_Template extends Smarty_Internal_Template { } diff --git a/libs/sysplugins/smarty_internal_templatecompilerbase.php b/libs/sysplugins/smarty_internal_templatecompilerbase.php index b036c797..1aa999bc 100644 --- a/libs/sysplugins/smarty_internal_templatecompilerbase.php +++ b/libs/sysplugins/smarty_internal_templatecompilerbase.php @@ -50,8 +50,6 @@ class Smarty_Internal_TemplateCompilerBase { // flag for nochache sections $this->nocache = false; $this->tag_nocache = false; - // assume successfull compiling - $this->compile_error = false; // save template object in compiler class $this->template = $template; $this->smarty->_current_file = $this->template->getTemplateFilepath(); @@ -82,22 +80,16 @@ class Smarty_Internal_TemplateCompilerBase { } // call compiler $_compiled_code = $this->doCompile($_content); - } while ($this->abort_and_recompile); - if (!$this->compile_error) { - // return compiled code to template object - if ($template->suppressFileDependency) { - $template->compiled_template = $_compiled_code; - } else { - $template->compiled_template = $template_header . $template->createPropertyHeader() . $_compiled_code; - } - // run postfilter if required - if (isset($this->smarty->autoload_filters['post']) || isset($this->smarty->registered_filters['post'])) { - $template->compiled_template = Smarty_Internal_Filter_Handler::runFilter('post', $template->compiled_template, $this->smarty, $template); - } - return true; + } while ($this->abort_and_recompile); + // return compiled code to template object + if ($template->suppressFileDependency) { + $template->compiled_template = $_compiled_code; } else { - // compilation error - return false; + $template->compiled_template = $template_header . $template->createPropertyHeader() . $_compiled_code; + } + // run postfilter if required + if (isset($this->smarty->autoload_filters['post']) || isset($this->smarty->registered_filters['post'])) { + $template->compiled_template = Smarty_Internal_Filter_Handler::runFilter('post', $template->compiled_template, $this->smarty, $template); } } @@ -429,9 +421,7 @@ class Smarty_Internal_TemplateCompilerBase { // output parser error message $error_text .= ' - Unexpected "' . $this->lex->value . '", expected one of: ' . implode(' , ', $expect); } - throw new Exception($error_text); - // set error flag - $this->compile_error = true; + throw new Exception($error_text); } }