Changeset 7987


Ignore:
Timestamp:
12/03/10 08:00:49 (9 years ago)
Author:
rvelices
Message:

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
Location:
trunk
Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/template.class.php

    r7975 r7987  
    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  { 
     
    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') ); 
     
    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      { 
     
    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    { 
     
    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 
     
    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 /** 
     
    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')) 
    730       { 
    731         array_push($css, '<link rel="stylesheet" type="text/css" href="{$ROOT_URL}local/css/'.$theme['id'].'-rules.css">'); 
    732       } 
    733     } 
    734     if (file_exists(PHPWG_ROOT_PATH.'local/css/rules.css')) 
    735     { 
    736       array_push($css, '<link rel="stylesheet" type="text/css" href="{$ROOT_URL}local/css/rules.css">'); 
     762      $f = 'local/css/'.$theme['id'].'-rules.css'; 
     763      if (file_exists(PHPWG_ROOT_PATH.$f)) 
     764      { 
     765        array_push($css, "{combine_css path='$f' order=10}"); 
     766      } 
     767    } 
     768    $f = 'local/css/rules.css'; 
     769    if (file_exists(PHPWG_ROOT_PATH.$f)) 
     770    { 
     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 
     
    9801015} 
    9811016 
     1017 
     1018/*Allows merging of javascript and css files into a single one.*/ 
     1019final 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?> 
  • trunk/themes/default/local_head.tpl

    r6577 r7987  
    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} 
  • trunk/themes/default/print.css

    r7869 r7987  
     1@media print { 
    12#menubar, .content .navigationBar, UL.categoryActions, .content .calendarViews, .calendarBar, 
    23#imageToolBar, .navThumb, #addComment { 
     
    1314        margin: 0 !important;  
    1415} 
     16} 
  • trunk/themes/default/template/header.tpl

    r7975 r7987  
    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} 
     42 
    3943 
    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]--> 
    49  
    50 {get_combined_scripts load='header'} 
    5152 
    5253{if not empty($head_elements)} 
  • trunk/themes/default/template/include/datepicker.inc.tpl

    r7975 r7987  
    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} 
Note: See TracChangeset for help on using the changeset viewer.