From 35337b01aeabfddd8eede74ca1c7e2b48672b595 Mon Sep 17 00:00:00 2001 From: rvelices Date: Tue, 12 Nov 2013 06:33:30 +0000 Subject: bug 2963: Ability to create css/js smarty templates with caching so far can add template=true to combine_css function git-svn-id: http://piwigo.org/svn/trunk@25462 68402e56-0260-453c-a942-63ccdbb3a9ee --- include/template.class.php | 270 +++++++++++++++++++++++++-------------------- 1 file changed, 150 insertions(+), 120 deletions(-) (limited to 'include/template.class.php') diff --git a/include/template.class.php b/include/template.class.php index 6628dbec9..6f37aa897 100644 --- a/include/template.class.php +++ b/include/template.class.php @@ -415,32 +415,22 @@ class Template { ksort($this->css_by_priority); global $conf; - $css = array(); - if ($conf['template_combine_files']) + $combiner = new FileCombiner('css'); + foreach ($this->css_by_priority as $files) { - $combiner = new FileCombiner('css'); - foreach ($this->css_by_priority as $files) - { - foreach ($files as $file_ver) - $combiner->add( $file_ver[0], $file_ver[1] ); - } - if ( $combiner->combine( $out_file, $out_version) ) - $css[] = array($out_file, $out_version); - } - else - { - foreach ($this->css_by_priority as $files) - $css = array_merge($css, $files); + foreach ($files as $combi) + $combiner->add( $combi ); } + $css = $combiner->combine(); $content = array(); - foreach( $css as $file_ver ) + foreach( $css as $combi ) { - $href = embellish_url(get_root_url().$file_ver[0]); - if ($file_ver[1] !== false) - $href .= '?v' . ($file_ver[1] ? $file_ver[1] : PHPWG_VERSION); + $href = embellish_url(get_root_url().$combi->path); + if ($combi->version !== false) + $href .= '?v' . ($combi->version ? $combi->version : PHPWG_VERSION); // trigger the event for eventual use of a cdn - $href = trigger_event('combined_css', $href, $file_ver[0], $file_ver[1]); + $href = trigger_event('combined_css', $href, $combi); $content[] = ''; } $this->output = str_replace(self::COMBINED_CSS_TAG, @@ -518,7 +508,7 @@ class Template { return var_export($lang[$key], true); } return 'l10n('.$params[0].')'; - + default: if ($conf['compiled_template_cache_language']) { @@ -764,7 +754,9 @@ var s,after = document.getElementsByTagName(\'script\')[document.getElementsByTa !empty($params['path']) || fatal_error('combine_css missing path'); $order = (int)@$params['order']; $version = isset($params['version']) ? $params['version'] : 0; - $this->css_by_priority[$order][] = array( $params['path'], $version); + $css = new Css('', $params['path'], $version, $order); + $css->is_template = isset($params['template']) && !empty($params['template']); + $this->css_by_priority[$order][] = $css; } function func_get_combined_css($params) @@ -986,23 +978,18 @@ class PwgTemplateAdapter } -final class Script +class Combinable { public $id; - public $load_mode; - public $precedents = array(); public $path; public $version; - public $extra = array(); + public $is_template; - function Script($load_mode, $id, $path, $version, $precedents) + function __construct($id, $path, $version) { - $this->id = $id; - $this->load_mode = $load_mode; $this->id = $id; $this->set_path($path); $this->version = $version; - $this->precedents = $precedents; } function set_path($path) @@ -1017,6 +1004,31 @@ final class Script } } +final class Script extends Combinable +{ + public $load_mode; + public $precedents = array(); + public $extra = array(); + + function __construct($load_mode, $id, $path, $version, $precedents) + { + parent::__construct($id, $path, $version); + $this->load_mode = $load_mode; + $this->precedents = $precedents; + } +} + +final class Css extends Combinable +{ + public $order; + + function __construct($id, $path, $version, $order) + { + parent::__construct($id, $path, $version); + $this->order = $order; + } +} + /** Manage a list of required scripts for a page, by optimizing their loading location (head, bottom, async) and later on by combining them in a unique file respecting at the same time dependencies.*/ @@ -1184,29 +1196,12 @@ class ScriptLoader private static function do_combine($scripts, $load_mode) { - global $conf; - if (count($scripts)<2 or !$conf['template_combine_files']) - return $scripts; $combiner = new FileCombiner('js'); - $result = array(); foreach ($scripts as $script) { - if ($script->is_remote()) - { - if ( $combiner->combine( $out_file, $out_version) ) - { - $results[] = new Script($load_mode, 'combi', $out_file, $out_version, array() ); - } - $results[] = $script; - } - else - $combiner->add( $script->path, $script->version ); - } - if ( $combiner->combine( $out_file, $out_version) ) - { - $results[] = new Script($load_mode, 'combi', $out_file, $out_version, array() ); + $combiner->add( $script); } - return $results; + return $combiner->combine(); } // checks that if B depends on A, then B->load_mode >= A->load_mode in order to respect execution order @@ -1325,12 +1320,13 @@ class ScriptLoader final class FileCombiner { private $type; // js or css - private $files = array(); - private $versions = array(); + private $is_css; + private $combinables = array(); function FileCombiner($type) { $this->type = $type; + $this->is_css = $type=='css'; } static function clear_combined_files() @@ -1344,92 +1340,124 @@ final class FileCombiner closedir($dir); } - function add($file, $version) + function add($combinable) { - $this->files[] = $file; - $this->versions[] = $version; + $this->combinables[] = $combinable; } - function clear() + function combine() { - $this->files = array(); - $this->versions = array(); + global $conf; + $force = false; + if (is_admin() && ($this->is_css || !$conf['template_compile_check']) ) + { + $force = (isset($_SERVER['HTTP_CACHE_CONTROL']) && strpos($_SERVER['HTTP_CACHE_CONTROL'], 'max-age=0') !== false) + || (isset($_SERVER['HTTP_PRAGMA']) && strpos($_SERVER['HTTP_PRAGMA'], 'no-cache')); + } + + $result = array(); + $pending = array(); + $key = $this->is_css ? array(get_absolute_root_url(false)): array(); //because for css we modify bg url + + foreach ($this->combinables as $combinable) + { + if ($conf['template_combine_files'] && !$combinable->is_remote()) + { + $key[] = $combinable->path; + $key[] = $combinable->version; + if ($conf['template_compile_check']) + $key[] = filemtime( PHPWG_ROOT_PATH . $combinable->path ); + $pending[] = $combinable; + } + else + { + $this->flush_pending($result, $pending, $key, $force); + $pending = array(); + $key = $this->is_css ? array(get_absolute_root_url(false)): array(); //because for css we modify bg url + $result[] = $combinable; + } + } + $this->flush_pending($result, $pending, $key, $force); + return $result; } - function combine(&$out_file, &$out_version) + private function flush_pending(&$result, $pending, $key, $force) { - if (count($this->files) == 0) + if (count($pending)>1) { - return false; + $key = join('>', $key); + $file = PWG_COMBINED_DIR . base_convert(crc32($key),10,36) . '.' . $this->type; + if ($force || !file_exists(PHPWG_ROOT_PATH.$file) ) + { + $output = ''; + foreach ($pending as $combinable) + { + $output .= "/*BEGIN $combinable->path */\n"; + $output .= $this->process_combinable($combinable, true, $force); + $output .= "\n"; + } + mkgetdir( dirname(PHPWG_ROOT_PATH.$file) ); + file_put_contents( PHPWG_ROOT_PATH.$file, $output ); + @chmod(PHPWG_ROOT_PATH.$file, 0644); + } + $result[] = new Combinable("combi", $file, false); } - if (count($this->files) == 1) + elseif ( count($pending)==1) { - $out_file = $this->files[0]; - $out_version = $this->versions[0]; - $this->clear(); - return 1; + $this->process_combinable($pending[0], false, $force); + $result[] = $pending[0]; } - - $is_css = $this->type == "css"; - global $conf; $key = array(); - if ($is_css) - $key[] = get_absolute_root_url(false);//because we modify bg url - for ($i=0; $ifiles); $i++) - { - $key[] = $this->files[$i]; - $key[] = $this->versions[$i]; - if ($conf['template_compile_check']) $key[] = filemtime( PHPWG_ROOT_PATH . $this->files[$i] ); - } - $key = join('>', $key); - - $file = base_convert(crc32($key),10,36); - $file = PWG_COMBINED_DIR . $file . '.' . $this->type; + $pending = array(); + } - $exists = file_exists( PHPWG_ROOT_PATH . $file ); - if ($exists) + private function process_combinable($combinable, $return_content, $force) + { + if ($combinable->is_template) { - $is_reload = - (isset($_SERVER['HTTP_CACHE_CONTROL']) && strpos($_SERVER['HTTP_CACHE_CONTROL'], 'max-age=0') !== false) - || (isset($_SERVER['HTTP_PRAGMA']) && strpos($_SERVER['HTTP_PRAGMA'], 'no-cache')); - if (is_admin() && $is_reload) - {// the user pressed F5 in the browser - if ($is_css || $conf['template_compile_check']==false) - $exists = false; // we foce regeneration of css because @import sub-files are never checked for modification + if (!$return_content) + { + $key = array($combinable->path, $combinable->version); + if ($conf['template_compile_check']) + $key[] = filemtime( PHPWG_ROOT_PATH . $combinable->path ); + $file = PWG_COMBINED_DIR . 't' . base_convert(crc32($key),10,36) . '.' . $this->type; + if (!$force && file_exists(PHPWG_ROOT_PATH.$file) ) + { + $combinable->path = $file; + $combinable->version = false; + return; + } } - } - if ($exists) - { - $out_file = $file; - $out_version = false; - $this->clear(); - return 2; - } + global $template; + $handle = $this->type. '.' .$combinable->id; + $template->set_filename($handle, realpath(PHPWG_ROOT_PATH.$combinable->path)); + trigger_action( 'combinable_preparse', $template, $combinable, $this); //allow themes and plugins to set their own vars to template ... + $content = $template->parse($handle, true); - $output = ''; - foreach ($this->files as $input_file) + if ($this->is_css) + $content = self::process_css($content, dirname($combinable->path) ); + else + $content = self::process_js($content, $combinable->path ); + + if ($return_content) + return $content; + file_put_contents( PHPWG_ROOT_PATH.$file, $content ); + $combinable->path = $file; + } + elseif ($return_content) { - $output .= "/*BEGIN $input_file */\n"; - if ($is_css) - $output .= self::process_css($input_file); + $content = file_get_contents(PHPWG_ROOT_PATH . $combinable->path); + if ($this->is_css) + $content = self::process_css($content, dirname($combinable->path) ); else - $output .= self::process_js($input_file); - $output .= "\n"; + $content = self::process_js($content, $combinable->path ); + return $content; } - - mkgetdir( dirname(PHPWG_ROOT_PATH.$file) ); - file_put_contents( PHPWG_ROOT_PATH.$file, $output ); - @chmod(PHPWG_ROOT_PATH.$file, 0644); - $out_file = $file; - $out_version = false; - $this->clear(); - return 2; } - private static function process_js($file) + private static function process_js($js, $file) { - $js = file_get_contents(PHPWG_ROOT_PATH . $file); if (strpos($file, '.min')===false and strpos($file, '.packed')===false ) { require_once(PHPWG_ROOT_PATH.'include/jshrink.class.php'); @@ -1438,9 +1466,9 @@ final class FileCombiner return trim($js, " \t\r\n;").";\n"; } - private static function process_css($file) + private static function process_css($css, $dir) { - $css = self::process_css_rec($file); + $css = self::process_css_rec($css, $dir); if (version_compare(PHP_VERSION, '5.2.4', '>=')) { require_once(PHPWG_ROOT_PATH.'include/cssmin.class.php'); @@ -1450,10 +1478,10 @@ final class FileCombiner return $css; } - private static function process_css_rec($file) + private static function process_css_rec($css, $dir) { static $PATTERN = "#url\(\s*['|\"]{0,1}(.*?)['|\"]{0,1}\s*\)#"; - $css = file_get_contents(PHPWG_ROOT_PATH . $file); + if (preg_match_all($PATTERN, $css, $matches, PREG_SET_ORDER)) { $search = $replace = array(); @@ -1461,7 +1489,7 @@ final class FileCombiner { if ( !url_is_remote($match[1]) && $match[1][0] != '/') { - $relative = dirname($file) . "/$match[1]"; + $relative = $dir . "/$match[1]"; $search[] = $match[0]; $replace[] = 'url('.embellish_url(get_absolute_root_url(false).$relative).')'; } @@ -1476,12 +1504,14 @@ final class FileCombiner foreach ($matches as $match) { $search[] = $match[0]; - $replace[] = self::process_css_rec(dirname($file) . "/$match[1]"); + $sub_css = file_get_contents(PHPWG_ROOT_PATH . $dir . "/$match[1]"); + $replace[] = self::process_css_rec($sub_css, dirname($dir . "/$match[1]") ); } $css = str_replace($search, $replace, $css); } return $css; } + } ?> \ No newline at end of file -- cgit v1.2.3