Changeset 7987


Ignore:
Timestamp:
Dec 3, 2010, 8:00:49 AM (13 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.