Skip to content
Permalink
Browse files

new template feature: combine_css

- fully functional with file merging
- takes care of url() in css and recursively merge all @import
- migrated public templates only; need more code doc

git-svn-id: http://piwigo.org/svn/trunk@7987 68402e56-0260-453c-a942-63ccdbb3a9ee
  • Loading branch information...
modus75 committed Dec 3, 2010
1 parent af1cbac commit 9db8ee600860893a18f76ebbe822393426463bcb
@@ -43,9 +43,13 @@ class Template {
// used by html_head smarty block to add content before </head>
var $html_head_elements = array();
const COMBINED_SCRIPTS_TAG = '<!-- COMBINED_SCRIPTS -->';
var $scriptLoader;
var $html_footer_raw_script = array();
const COMBINED_CSS_TAG = '<!-- COMBINED_CSS -->';
var $css_by_priority = array();
function Template($root = ".", $theme= "", $path = "template")
{
global $conf, $lang_info;
@@ -88,6 +92,8 @@ function Template($root = ".", $theme= "", $path = "template")
$this->smarty->register_block('html_head', array(&$this, 'block_html_head') );
$this->smarty->register_function('combine_script', array(&$this, 'func_combine_script') );
$this->smarty->register_function('get_combined_scripts', array(&$this, 'func_get_combined_scripts') );
$this->smarty->register_function('combine_css', array(&$this, 'func_combine_css') );
$this->smarty->register_function('get_combined_css', array(&$this, 'func_get_combined_css') );
$this->smarty->register_block('footer_script', array(&$this, 'block_footer_script') );
$this->smarty->register_function('known_script', array(&$this, 'func_known_script') );
$this->smarty->register_prefilter( array('Template', 'prefilter_white_space') );
@@ -385,8 +391,7 @@ function flush()
{
if (!$this->scriptLoader->did_head())
{
$search = "\n</head>";
$pos = strpos( $this->output, $search );
$pos = strpos( $this->output, self::COMBINED_SCRIPTS_TAG );
if ($pos !== false)
{
$scripts = $this->scriptLoader->get_head_scripts();
@@ -399,10 +404,34 @@ function flush()
.'"></script>';
}
$this->output = substr_replace( $this->output, "\n".implode( "\n", $content ), $pos, 0 );
$this->output = substr_replace( $this->output, "\n".implode( "\n", $content ), $pos, strlen(self::COMBINED_SCRIPTS_TAG) );
} //else maybe error or warning ?
}
if(!empty($this->css_by_priority))
{
ksort($this->css_by_priority);
$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) )
{
$href = get_root_url() . $out_file;
if ($out_version !== false)
$href .= '?v' . ($out_version ? $out_version : PHPWG_VERSION);
// trigger the event for eventual use of a cdn
$href = trigger_event('combined_css', $href, $out_file, $out_version);
$this->output = str_replace(self::COMBINED_CSS_TAG,
'<link rel="stylesheet" type="text/css" href="'.$href.'">',
$this->output );
}
}
if ( count($this->html_head_elements) )
{
$search = "\n</head>";
@@ -535,17 +564,7 @@ function func_get_combined_scripts($params, &$smarty)
if ($load==0)
{
if ($this->scriptLoader->did_head())
fatal_error('get_combined_scripts several times header');
$scripts = $this->scriptLoader->get_head_scripts();
foreach ($scripts as $id => $script)
{
$content[]=
'<script type="text/javascript" src="'
. Template::make_script_src($script)
.'"></script>';
}
return self::COMBINED_SCRIPTS_TAG;
}
else
{
@@ -612,6 +631,21 @@ function block_footer_script($params, $content, &$smarty, &$repeat)
$this->html_footer_raw_script[] = $content;
}
}
function func_combine_css($params, &$smarty)
{
!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);
//var_export( $this->css_by_priority ); echo "<br>";
}
function func_get_combined_css($params, &$smarty)
{
return self::COMBINED_CSS_TAG;
}
/**
* This function allows to declare a Smarty prefilter from a plugin, thus allowing
@@ -723,22 +757,23 @@ static function prefilter_language($source, &$smarty)
static function prefilter_local_css($source, &$smarty)
{
$css = array();
foreach ($smarty->get_template_vars('themes') as $theme)
{
if (file_exists(PHPWG_ROOT_PATH.'local/css/'.$theme['id'].'-rules.css'))
$f = 'local/css/'.$theme['id'].'-rules.css';
if (file_exists(PHPWG_ROOT_PATH.$f))
{
array_push($css, '<link rel="stylesheet" type="text/css" href="{$ROOT_URL}local/css/'.$theme['id'].'-rules.css">');
array_push($css, "{combine_css path='$f' order=10}");
}
}
if (file_exists(PHPWG_ROOT_PATH.'local/css/rules.css'))
$f = 'local/css/rules.css';
if (file_exists(PHPWG_ROOT_PATH.$f))
{
array_push($css, '<link rel="stylesheet" type="text/css" href="{$ROOT_URL}local/css/rules.css">');
array_push($css, "{combine_css path='$f' order=10}");
}
if (!empty($css))
{
$source = str_replace("\n</head>", "\n".implode( "\n", $css )."\n</head>", $source);
$source = str_replace("\n{get_combined_css}", "\n".implode( "\n", $css )."\n{get_combined_css}", $source);
}
return $source;
@@ -979,4 +1014,122 @@ private static function cmp_by_mode_and_order($s1, $s2)
}
}
/*Allows merging of javascript and css files into a single one.*/
final class FileCombiner
{
const OUT_SUB_DIR = 'local/combined/';
private $type; // js or css
private $files = array();
private $versions = array();
function FileCombiner($type)
{
$this->type = $type;
}
function add($file, $version)
{
$this->files[] = $file;
$this->versions[] = $version;
}
function clear()
{
$this->files = array();
$this->versions = array();
}
function combine(&$out_file, &$out_version)
{
//var_export($this);
if (count($this->files) == 0)
{
return false;
}
if (count($this->files) == 1)
{
$out_file = $this->files[0];
$out_version = $this->versions[0];
$this->clear();
return 1;
}
global $conf;
$key = array();
for ($i=0; $i<count($this->files); $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 = self::OUT_SUB_DIR . $file . '.' . $this->type;
if (file_exists( PHPWG_ROOT_PATH . $file ) )
{
$out_file = $file;
$out_version = false;
$this->clear();
return 2;
}
$output = '';
if ($conf['debug_template'])
$output .= "/*".join("\n", $this->files)."*/\n";
foreach ($this->files as $input_file)
{
$output .= "/* BEGIN $input_file */\n";
if ($this->type == "css")
{
$output .= $this->process_css($input_file);
}
else
$output .= file_get_contents(PHPWG_ROOT_PATH . $input_file);
$output .= "\n";
}
file_put_contents( PHPWG_ROOT_PATH . $file, $output );
$out_file = $file;
$out_version = false;
$this->clear();
return 2;
}
private function process_css($file)
{
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();
foreach ($matches as $match)
{
if ( !url_is_remote($match[1]) || $match[1][0] != '/')
{
$relative = dirname($file) . "/$match[1]";
$search[] = $match[0];
$replace[] = "url('" . get_absolute_root_url(false) . $relative . "')";
}
}
$css = str_replace($search, $replace, $css);
}
$imports = preg_match_all("#@import\s*['|\"]{0,1}(.*?)['|\"]{0,1};#", $css, $matches, PREG_SET_ORDER);
if ($imports)
{
$search = $replace = array();
foreach ($matches as $match)
{
$search[] = $match[0];
$replace[] = $this->process_css(dirname($file) . "/$match[1]");
}
$css = str_replace($search, $replace, $css);
}
return $css;
}
}
?>
@@ -0,0 +1 @@
Not allowed!
@@ -1,7 +1,9 @@
<!--[if lt IE 7]>
<link rel="stylesheet" type="text/css" href="{$ROOT_URL}themes/default/fix-ie5-ie6.css">
<![endif]-->
<!--[if IE 7]>
<link rel="stylesheet" type="text/css" href="{$ROOT_URL}themes/default/fix-ie7.css">
<![endif]-->
<link rel="stylesheet" type="text/css" media="print" href="{$ROOT_URL}themes/default/print.css">
{if $load_css}
<!--[if lt IE 7]>
<link rel="stylesheet" type="text/css" href="{$ROOT_URL}themes/default/fix-ie5-ie6.css">
<![endif]-->
<!--[if IE 7]>
<link rel="stylesheet" type="text/css" href="{$ROOT_URL}themes/default/fix-ie7.css">
<![endif]-->
{combine_css path="themes/default/print.css" order=-10}
{/if}
@@ -1,3 +1,4 @@
@media print {
#menubar, .content .navigationBar, UL.categoryActions, .content .calendarViews, .calendarBar,
#imageToolBar, .navThumb, #addComment {
display: none;
@@ -12,3 +13,4 @@ BODY {
#theCategoryPage .content {
margin: 0 !important;
}
}
@@ -30,25 +30,26 @@
{if isset($last.U_IMG) }<link rel="last" title="{'Last'|@translate}" href="{$last.U_IMG}" >{/if}
{if isset($U_UP) }<link rel="up" title="{'Thumbnails'|@translate}" href="{$U_UP}" >{/if}


{get_combined_css}

{foreach from=$themes item=theme}
{if $theme.load_css}
<link rel="stylesheet" type="text/css" href="{$ROOT_URL}themes/{$theme.id}/theme.css">
{combine_css path="themes/`$theme.id`/theme.css" order=-10}
{/if}
{if !empty($theme.local_head)}{include file=$theme.local_head}{/if}
{if !empty($theme.local_head)}{include file=$theme.local_head load_css=$theme.load_css}{/if}
{/foreach}


{if isset($U_PREFETCH) }<link rel="prefetch" href="{$U_PREFETCH}">{/if}

{if not empty($page_refresh) }<meta http-equiv="refresh" content="{$page_refresh.TIME};url={$page_refresh.U_REFRESH}">{/if}
{*
<script type="text/javascript" src="{$ROOT_URL}themes/default/js/scripts.js"></script>
*}

{get_combined_scripts load='header'}
<!--[if lt IE 7]>
<script type="text/javascript" src="{$ROOT_URL}themes/default/js/pngfix.js"></script>
<![endif]-->

{get_combined_scripts load='header'}

{if not empty($head_elements)}
{foreach from=$head_elements item=elt}{$elt}
{/foreach}
@@ -10,9 +10,7 @@
{combine_script id="jquery.ui.datepicker-$lang_info.code" path=$datepicker_language}
{/if}

{html_head}
<link rel="stylesheet" type="text/css" href="{$ROOT_URL}themes/default/js/ui/theme/ui.datepicker.css">
{/html_head}
{combine_css path="themes/default/js/ui/theme/ui.datepicker.css"}

{footer_script}
function pwg_initialization_datepicker(day, month, year, linked_date, checked_on_change, min_linked_date, max_linked_date)

0 comments on commit 9db8ee6

Please sign in to comment.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.