Skip to content

Commit 9db8ee6

Browse files
author
rvelices
committed
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
1 parent af1cbac commit 9db8ee6

File tree

6 files changed

+194
-37
lines changed

6 files changed

+194
-37
lines changed

include/template.class.php

Lines changed: 173 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,13 @@ class Template {
4343
// used by html_head smarty block to add content before </head>
4444
var $html_head_elements = array();
4545

46+
const COMBINED_SCRIPTS_TAG = '<!-- COMBINED_SCRIPTS -->';
4647
var $scriptLoader;
4748
var $html_footer_raw_script = array();
4849

50+
const COMBINED_CSS_TAG = '<!-- COMBINED_CSS -->';
51+
var $css_by_priority = array();
52+
4953
function Template($root = ".", $theme= "", $path = "template")
5054
{
5155
global $conf, $lang_info;
@@ -88,6 +92,8 @@ function Template($root = ".", $theme= "", $path = "template")
8892
$this->smarty->register_block('html_head', array(&$this, 'block_html_head') );
8993
$this->smarty->register_function('combine_script', array(&$this, 'func_combine_script') );
9094
$this->smarty->register_function('get_combined_scripts', array(&$this, 'func_get_combined_scripts') );
95+
$this->smarty->register_function('combine_css', array(&$this, 'func_combine_css') );
96+
$this->smarty->register_function('get_combined_css', array(&$this, 'func_get_combined_css') );
9197
$this->smarty->register_block('footer_script', array(&$this, 'block_footer_script') );
9298
$this->smarty->register_function('known_script', array(&$this, 'func_known_script') );
9399
$this->smarty->register_prefilter( array('Template', 'prefilter_white_space') );
@@ -385,8 +391,7 @@ function flush()
385391
{
386392
if (!$this->scriptLoader->did_head())
387393
{
388-
$search = "\n</head>";
389-
$pos = strpos( $this->output, $search );
394+
$pos = strpos( $this->output, self::COMBINED_SCRIPTS_TAG );
390395
if ($pos !== false)
391396
{
392397
$scripts = $this->scriptLoader->get_head_scripts();
@@ -399,10 +404,34 @@ function flush()
399404
.'"></script>';
400405
}
401406

402-
$this->output = substr_replace( $this->output, "\n".implode( "\n", $content ), $pos, 0 );
407+
$this->output = substr_replace( $this->output, "\n".implode( "\n", $content ), $pos, strlen(self::COMBINED_SCRIPTS_TAG) );
403408
} //else maybe error or warning ?
404409
}
405410

411+
if(!empty($this->css_by_priority))
412+
{
413+
ksort($this->css_by_priority);
414+
$combiner = new FileCombiner('css');
415+
foreach ($this->css_by_priority as $files)
416+
{
417+
foreach ($files as $file_ver)
418+
{
419+
$combiner->add( $file_ver[0], $file_ver[1] );
420+
}
421+
}
422+
if ( $combiner->combine( $out_file, $out_version) )
423+
{
424+
$href = get_root_url() . $out_file;
425+
if ($out_version !== false)
426+
$href .= '?v' . ($out_version ? $out_version : PHPWG_VERSION);
427+
// trigger the event for eventual use of a cdn
428+
$href = trigger_event('combined_css', $href, $out_file, $out_version);
429+
$this->output = str_replace(self::COMBINED_CSS_TAG,
430+
'<link rel="stylesheet" type="text/css" href="'.$href.'">',
431+
$this->output );
432+
}
433+
}
434+
406435
if ( count($this->html_head_elements) )
407436
{
408437
$search = "\n</head>";
@@ -535,17 +564,7 @@ function func_get_combined_scripts($params, &$smarty)
535564

536565
if ($load==0)
537566
{
538-
if ($this->scriptLoader->did_head())
539-
fatal_error('get_combined_scripts several times header');
540-
541-
$scripts = $this->scriptLoader->get_head_scripts();
542-
foreach ($scripts as $id => $script)
543-
{
544-
$content[]=
545-
'<script type="text/javascript" src="'
546-
. Template::make_script_src($script)
547-
.'"></script>';
548-
}
567+
return self::COMBINED_SCRIPTS_TAG;
549568
}
550569
else
551570
{
@@ -612,6 +631,21 @@ function block_footer_script($params, $content, &$smarty, &$repeat)
612631
$this->html_footer_raw_script[] = $content;
613632
}
614633
}
634+
635+
function func_combine_css($params, &$smarty)
636+
{
637+
!empty($params['path']) || fatal_error('combine_css missing path');
638+
$order = (int)@$params['order'];
639+
$version = isset($params['version']) ? $params['version'] : 0;
640+
$this->css_by_priority[$order][] = array( $params['path'], $version);
641+
//var_export( $this->css_by_priority ); echo "<br>";
642+
}
643+
644+
function func_get_combined_css($params, &$smarty)
645+
{
646+
return self::COMBINED_CSS_TAG;
647+
}
648+
615649

616650
/**
617651
* This function allows to declare a Smarty prefilter from a plugin, thus allowing
@@ -723,22 +757,23 @@ static function prefilter_language($source, &$smarty)
723757
static function prefilter_local_css($source, &$smarty)
724758
{
725759
$css = array();
726-
727760
foreach ($smarty->get_template_vars('themes') as $theme)
728761
{
729-
if (file_exists(PHPWG_ROOT_PATH.'local/css/'.$theme['id'].'-rules.css'))
762+
$f = 'local/css/'.$theme['id'].'-rules.css';
763+
if (file_exists(PHPWG_ROOT_PATH.$f))
730764
{
731-
array_push($css, '<link rel="stylesheet" type="text/css" href="{$ROOT_URL}local/css/'.$theme['id'].'-rules.css">');
765+
array_push($css, "{combine_css path='$f' order=10}");
732766
}
733767
}
734-
if (file_exists(PHPWG_ROOT_PATH.'local/css/rules.css'))
768+
$f = 'local/css/rules.css';
769+
if (file_exists(PHPWG_ROOT_PATH.$f))
735770
{
736-
array_push($css, '<link rel="stylesheet" type="text/css" href="{$ROOT_URL}local/css/rules.css">');
771+
array_push($css, "{combine_css path='$f' order=10}");
737772
}
738773

739774
if (!empty($css))
740775
{
741-
$source = str_replace("\n</head>", "\n".implode( "\n", $css )."\n</head>", $source);
776+
$source = str_replace("\n{get_combined_css}", "\n".implode( "\n", $css )."\n{get_combined_css}", $source);
742777
}
743778

744779
return $source;
@@ -979,4 +1014,122 @@ private static function cmp_by_mode_and_order($s1, $s2)
9791014
}
9801015
}
9811016

1017+
1018+
/*Allows merging of javascript and css files into a single one.*/
1019+
final class FileCombiner
1020+
{
1021+
const OUT_SUB_DIR = 'local/combined/';
1022+
private $type; // js or css
1023+
private $files = array();
1024+
private $versions = array();
1025+
1026+
function FileCombiner($type)
1027+
{
1028+
$this->type = $type;
1029+
}
1030+
1031+
function add($file, $version)
1032+
{
1033+
$this->files[] = $file;
1034+
$this->versions[] = $version;
1035+
}
1036+
1037+
function clear()
1038+
{
1039+
$this->files = array();
1040+
$this->versions = array();
1041+
}
1042+
1043+
function combine(&$out_file, &$out_version)
1044+
{
1045+
//var_export($this);
1046+
if (count($this->files) == 0)
1047+
{
1048+
return false;
1049+
}
1050+
if (count($this->files) == 1)
1051+
{
1052+
$out_file = $this->files[0];
1053+
$out_version = $this->versions[0];
1054+
$this->clear();
1055+
return 1;
1056+
}
1057+
1058+
global $conf;
1059+
$key = array();
1060+
1061+
for ($i=0; $i<count($this->files); $i++)
1062+
{
1063+
$key[] = $this->files[$i];
1064+
$key[] = $this->versions[$i];
1065+
if ($conf['template_compile_check']) $key[] = filemtime( PHPWG_ROOT_PATH . $this->files[$i] );
1066+
}
1067+
$key = join('>', $key);
1068+
1069+
$file = base_convert(crc32($key),10,36);
1070+
$file = self::OUT_SUB_DIR . $file . '.' . $this->type;
1071+
if (file_exists( PHPWG_ROOT_PATH . $file ) )
1072+
{
1073+
$out_file = $file;
1074+
$out_version = false;
1075+
$this->clear();
1076+
return 2;
1077+
}
1078+
1079+
$output = '';
1080+
if ($conf['debug_template'])
1081+
$output .= "/*".join("\n", $this->files)."*/\n";
1082+
foreach ($this->files as $input_file)
1083+
{
1084+
$output .= "/* BEGIN $input_file */\n";
1085+
if ($this->type == "css")
1086+
{
1087+
$output .= $this->process_css($input_file);
1088+
}
1089+
else
1090+
$output .= file_get_contents(PHPWG_ROOT_PATH . $input_file);
1091+
$output .= "\n";
1092+
}
1093+
1094+
file_put_contents( PHPWG_ROOT_PATH . $file, $output );
1095+
$out_file = $file;
1096+
$out_version = false;
1097+
$this->clear();
1098+
return 2;
1099+
}
1100+
1101+
private function process_css($file)
1102+
{
1103+
static $PATTERN = "#url\(\s*['|\"]{0,1}(.*?)['|\"]{0,1}\s*\)#";
1104+
$css = file_get_contents(PHPWG_ROOT_PATH . $file);
1105+
if (preg_match_all($PATTERN, $css, $matches, PREG_SET_ORDER))
1106+
{
1107+
$search = $replace = array();
1108+
foreach ($matches as $match)
1109+
{
1110+
if ( !url_is_remote($match[1]) || $match[1][0] != '/')
1111+
{
1112+
$relative = dirname($file) . "/$match[1]";
1113+
$search[] = $match[0];
1114+
$replace[] = "url('" . get_absolute_root_url(false) . $relative . "')";
1115+
}
1116+
}
1117+
$css = str_replace($search, $replace, $css);
1118+
}
1119+
1120+
$imports = preg_match_all("#@import\s*['|\"]{0,1}(.*?)['|\"]{0,1};#", $css, $matches, PREG_SET_ORDER);
1121+
if ($imports)
1122+
{
1123+
$search = $replace = array();
1124+
foreach ($matches as $match)
1125+
{
1126+
$search[] = $match[0];
1127+
$replace[] = $this->process_css(dirname($file) . "/$match[1]");
1128+
}
1129+
$css = str_replace($search, $replace, $css);
1130+
}
1131+
return $css;
1132+
}
1133+
}
1134+
9821135
?>

local/combined/index.htm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Not allowed!

themes/default/local_head.tpl

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
<!--[if lt IE 7]>
2-
<link rel="stylesheet" type="text/css" href="{$ROOT_URL}themes/default/fix-ie5-ie6.css">
3-
<![endif]-->
4-
<!--[if IE 7]>
5-
<link rel="stylesheet" type="text/css" href="{$ROOT_URL}themes/default/fix-ie7.css">
6-
<![endif]-->
7-
<link rel="stylesheet" type="text/css" media="print" href="{$ROOT_URL}themes/default/print.css">
1+
{if $load_css}
2+
<!--[if lt IE 7]>
3+
<link rel="stylesheet" type="text/css" href="{$ROOT_URL}themes/default/fix-ie5-ie6.css">
4+
<![endif]-->
5+
<!--[if IE 7]>
6+
<link rel="stylesheet" type="text/css" href="{$ROOT_URL}themes/default/fix-ie7.css">
7+
<![endif]-->
8+
{combine_css path="themes/default/print.css" order=-10}
9+
{/if}

themes/default/print.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
@media print {
12
#menubar, .content .navigationBar, UL.categoryActions, .content .calendarViews, .calendarBar,
23
#imageToolBar, .navThumb, #addComment {
34
display: none;
@@ -12,3 +13,4 @@ BODY {
1213
#theCategoryPage .content {
1314
margin: 0 !important;
1415
}
16+
}

themes/default/template/header.tpl

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,25 +30,26 @@
3030
{if isset($last.U_IMG) }<link rel="last" title="{'Last'|@translate}" href="{$last.U_IMG}" >{/if}
3131
{if isset($U_UP) }<link rel="up" title="{'Thumbnails'|@translate}" href="{$U_UP}" >{/if}
3232

33+
34+
{get_combined_css}
35+
3336
{foreach from=$themes item=theme}
3437
{if $theme.load_css}
35-
<link rel="stylesheet" type="text/css" href="{$ROOT_URL}themes/{$theme.id}/theme.css">
38+
{combine_css path="themes/`$theme.id`/theme.css" order=-10}
3639
{/if}
37-
{if !empty($theme.local_head)}{include file=$theme.local_head}{/if}
40+
{if !empty($theme.local_head)}{include file=$theme.local_head load_css=$theme.load_css}{/if}
3841
{/foreach}
3942

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

4246
{if not empty($page_refresh) }<meta http-equiv="refresh" content="{$page_refresh.TIME};url={$page_refresh.U_REFRESH}">{/if}
43-
{*
44-
<script type="text/javascript" src="{$ROOT_URL}themes/default/js/scripts.js"></script>
45-
*}
47+
48+
{get_combined_scripts load='header'}
4649
<!--[if lt IE 7]>
4750
<script type="text/javascript" src="{$ROOT_URL}themes/default/js/pngfix.js"></script>
4851
<![endif]-->
4952

50-
{get_combined_scripts load='header'}
51-
5253
{if not empty($head_elements)}
5354
{foreach from=$head_elements item=elt}{$elt}
5455
{/foreach}

themes/default/template/include/datepicker.inc.tpl

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@
1010
{combine_script id="jquery.ui.datepicker-$lang_info.code" path=$datepicker_language}
1111
{/if}
1212

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

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

0 commit comments

Comments
 (0)