Changeset 25462


Ignore:
Timestamp:
11/12/13 07:33:30 (6 years ago)
Author:
rvelices
Message:

bug 2963: Ability to create css/js smarty templates with caching
so far can add template=true to combine_css function

File:
1 edited

Legend:

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

    r25231 r25462  
    416416 
    417417      global $conf; 
    418       $css = array(); 
    419       if ($conf['template_combine_files']) 
    420       { 
    421         $combiner = new FileCombiner('css'); 
    422         foreach ($this->css_by_priority as $files) 
    423         { 
    424           foreach ($files as $file_ver) 
    425             $combiner->add( $file_ver[0], $file_ver[1] ); 
    426         } 
    427         if ( $combiner->combine( $out_file, $out_version) ) 
    428           $css[] = array($out_file, $out_version); 
    429       } 
    430       else 
    431       { 
    432         foreach ($this->css_by_priority as $files) 
    433           $css = array_merge($css, $files); 
    434       } 
     418      $combiner = new FileCombiner('css'); 
     419      foreach ($this->css_by_priority as $files) 
     420      { 
     421        foreach ($files as $combi) 
     422            $combiner->add( $combi ); 
     423      } 
     424      $css = $combiner->combine(); 
    435425 
    436426      $content = array(); 
    437       foreach( $css as $file_ver ) 
    438       { 
    439         $href = embellish_url(get_root_url().$file_ver[0]); 
    440         if ($file_ver[1] !== false) 
    441           $href .= '?v' . ($file_ver[1] ? $file_ver[1] : PHPWG_VERSION); 
     427      foreach( $css as $combi ) 
     428      { 
     429        $href = embellish_url(get_root_url().$combi->path); 
     430        if ($combi->version !== false) 
     431          $href .= '?v' . ($combi->version ? $combi->version : PHPWG_VERSION); 
    442432        // trigger the event for eventual use of a cdn 
    443         $href = trigger_event('combined_css', $href, $file_ver[0], $file_ver[1]); 
     433        $href = trigger_event('combined_css', $href, $combi); 
    444434        $content[] = '<link rel="stylesheet" type="text/css" href="'.$href.'">'; 
    445435      } 
     
    519509      } 
    520510      return 'l10n('.$params[0].')'; 
    521        
     511 
    522512    default: 
    523513      if ($conf['compiled_template_cache_language']) 
     
    765755    $order = (int)@$params['order']; 
    766756    $version = isset($params['version']) ? $params['version'] : 0; 
    767     $this->css_by_priority[$order][] = array( $params['path'], $version); 
     757    $css = new Css('', $params['path'], $version, $order); 
     758    $css->is_template = isset($params['template']) && !empty($params['template']); 
     759    $this->css_by_priority[$order][] = $css; 
    768760  } 
    769761 
     
    987979 
    988980 
    989 final class Script 
     981class Combinable 
    990982{ 
    991983  public $id; 
    992   public $load_mode; 
    993   public $precedents = array(); 
    994984  public $path; 
    995985  public $version; 
    996   public $extra = array(); 
    997  
    998   function Script($load_mode, $id, $path, $version, $precedents) 
    999   { 
    1000     $this->id = $id; 
    1001     $this->load_mode = $load_mode; 
     986  public $is_template; 
     987 
     988  function __construct($id, $path, $version) 
     989  { 
    1002990    $this->id = $id; 
    1003991    $this->set_path($path); 
    1004992    $this->version = $version; 
    1005     $this->precedents = $precedents; 
    1006993  } 
    1007994 
     
    10151002  { 
    10161003    return url_is_remote( $this->path ) || strncmp($this->path, '//', 2)==0; 
     1004  } 
     1005} 
     1006 
     1007final class Script extends Combinable 
     1008{ 
     1009  public $load_mode; 
     1010  public $precedents = array(); 
     1011  public $extra = array(); 
     1012 
     1013  function __construct($load_mode, $id, $path, $version, $precedents) 
     1014  { 
     1015    parent::__construct($id, $path, $version); 
     1016    $this->load_mode = $load_mode; 
     1017    $this->precedents = $precedents; 
     1018  } 
     1019} 
     1020 
     1021final class Css extends Combinable 
     1022{ 
     1023  public $order; 
     1024 
     1025  function __construct($id, $path, $version, $order) 
     1026  { 
     1027    parent::__construct($id, $path, $version); 
     1028    $this->order = $order; 
    10171029  } 
    10181030} 
     
    11851197  private static function do_combine($scripts, $load_mode) 
    11861198  { 
    1187     global $conf; 
    1188     if (count($scripts)<2 or !$conf['template_combine_files']) 
    1189       return $scripts; 
    11901199    $combiner = new FileCombiner('js'); 
    1191     $result = array(); 
    11921200    foreach ($scripts as $script) 
    11931201    { 
    1194       if ($script->is_remote()) 
    1195       { 
    1196         if ( $combiner->combine( $out_file, $out_version) ) 
    1197         { 
    1198           $results[] = new Script($load_mode, 'combi', $out_file, $out_version, array() ); 
    1199         } 
    1200         $results[] = $script; 
    1201       } 
    1202       else 
    1203         $combiner->add( $script->path, $script->version ); 
    1204     } 
    1205     if ( $combiner->combine( $out_file, $out_version) ) 
    1206     { 
    1207       $results[] = new Script($load_mode, 'combi', $out_file, $out_version, array() ); 
    1208     } 
    1209     return $results; 
     1202      $combiner->add( $script); 
     1203    } 
     1204    return $combiner->combine(); 
    12101205  } 
    12111206 
     
    13261321{ 
    13271322  private $type; // js or css 
    1328   private $files = array(); 
    1329   private $versions = array(); 
     1323  private $is_css; 
     1324  private $combinables = array(); 
    13301325 
    13311326  function FileCombiner($type) 
    13321327  { 
    13331328    $this->type = $type; 
     1329    $this->is_css = $type=='css'; 
    13341330  } 
    13351331 
     
    13451341  } 
    13461342 
    1347   function add($file, $version) 
    1348   { 
    1349     $this->files[] = $file; 
    1350     $this->versions[] = $version; 
    1351   } 
    1352  
    1353   function clear() 
    1354   { 
    1355     $this->files = array(); 
    1356     $this->versions = array(); 
    1357   } 
    1358  
    1359   function combine(&$out_file, &$out_version) 
    1360   { 
    1361     if (count($this->files) == 0) 
    1362     { 
    1363       return false; 
    1364     } 
    1365     if (count($this->files) == 1) 
    1366     { 
    1367       $out_file = $this->files[0]; 
    1368       $out_version = $this->versions[0]; 
    1369       $this->clear(); 
    1370       return 1; 
    1371     } 
    1372  
    1373     $is_css = $this->type == "css"; 
     1343  function add($combinable) 
     1344  { 
     1345    $this->combinables[] = $combinable; 
     1346  } 
     1347 
     1348  function combine() 
     1349  { 
    13741350    global $conf; 
     1351    $force = false; 
     1352    if (is_admin() && ($this->is_css || !$conf['template_compile_check']) ) 
     1353    { 
     1354      $force = (isset($_SERVER['HTTP_CACHE_CONTROL']) && strpos($_SERVER['HTTP_CACHE_CONTROL'], 'max-age=0') !== false) 
     1355        || (isset($_SERVER['HTTP_PRAGMA']) && strpos($_SERVER['HTTP_PRAGMA'], 'no-cache')); 
     1356    } 
     1357 
     1358    $result = array(); 
     1359    $pending = array(); 
     1360    $key = $this->is_css ? array(get_absolute_root_url(false)): array(); //because for css we modify bg url 
     1361 
     1362    foreach ($this->combinables as $combinable) 
     1363    { 
     1364      if ($conf['template_combine_files'] && !$combinable->is_remote()) 
     1365      { 
     1366        $key[] = $combinable->path; 
     1367        $key[] = $combinable->version; 
     1368        if ($conf['template_compile_check']) 
     1369          $key[] = filemtime( PHPWG_ROOT_PATH . $combinable->path ); 
     1370        $pending[] = $combinable; 
     1371      } 
     1372      else 
     1373      { 
     1374        $this->flush_pending($result, $pending, $key, $force); 
     1375        $pending = array(); 
     1376        $key = $this->is_css ? array(get_absolute_root_url(false)): array(); //because for css we modify bg url 
     1377        $result[] = $combinable; 
     1378      } 
     1379    } 
     1380    $this->flush_pending($result, $pending, $key, $force); 
     1381    return $result; 
     1382  } 
     1383 
     1384  private function flush_pending(&$result, $pending, $key, $force) 
     1385  { 
     1386    if (count($pending)>1) 
     1387    { 
     1388      $key = join('>', $key); 
     1389      $file = PWG_COMBINED_DIR . base_convert(crc32($key),10,36) . '.' . $this->type; 
     1390      if ($force || !file_exists(PHPWG_ROOT_PATH.$file) ) 
     1391      { 
     1392        $output = ''; 
     1393        foreach ($pending as $combinable) 
     1394        { 
     1395          $output .= "/*BEGIN $combinable->path */\n"; 
     1396          $output .= $this->process_combinable($combinable, true, $force); 
     1397          $output .= "\n"; 
     1398        } 
     1399        mkgetdir( dirname(PHPWG_ROOT_PATH.$file) ); 
     1400        file_put_contents( PHPWG_ROOT_PATH.$file, $output ); 
     1401        @chmod(PHPWG_ROOT_PATH.$file, 0644); 
     1402      } 
     1403      $result[] = new Combinable("combi", $file, false); 
     1404    } 
     1405    elseif ( count($pending)==1) 
     1406    { 
     1407      $this->process_combinable($pending[0], false, $force); 
     1408      $result[] = $pending[0]; 
     1409    } 
    13751410    $key = array(); 
    1376     if ($is_css) 
    1377       $key[] = get_absolute_root_url(false);//because we modify bg url 
    1378     for ($i=0; $i<count($this->files); $i++) 
    1379     { 
    1380       $key[] = $this->files[$i]; 
    1381       $key[] = $this->versions[$i]; 
    1382       if ($conf['template_compile_check']) $key[] = filemtime( PHPWG_ROOT_PATH . $this->files[$i] ); 
    1383     } 
    1384     $key = join('>', $key); 
    1385  
    1386     $file = base_convert(crc32($key),10,36); 
    1387     $file = PWG_COMBINED_DIR . $file . '.' . $this->type; 
    1388  
    1389     $exists = file_exists( PHPWG_ROOT_PATH . $file ); 
    1390     if ($exists) 
    1391     { 
    1392       $is_reload = 
    1393         (isset($_SERVER['HTTP_CACHE_CONTROL']) && strpos($_SERVER['HTTP_CACHE_CONTROL'], 'max-age=0') !== false) 
    1394         || (isset($_SERVER['HTTP_PRAGMA']) && strpos($_SERVER['HTTP_PRAGMA'], 'no-cache')); 
    1395       if (is_admin() && $is_reload) 
    1396       {// the user pressed F5 in the browser 
    1397         if ($is_css || $conf['template_compile_check']==false) 
    1398           $exists = false; // we foce regeneration of css because @import sub-files are never checked for modification 
    1399       } 
    1400     } 
    1401  
    1402     if ($exists) 
    1403     { 
    1404       $out_file = $file; 
    1405       $out_version = false; 
    1406       $this->clear(); 
    1407       return 2; 
    1408     } 
    1409  
    1410     $output = ''; 
    1411     foreach ($this->files as $input_file) 
    1412     { 
    1413       $output .= "/*BEGIN $input_file */\n"; 
    1414       if ($is_css) 
    1415         $output .= self::process_css($input_file); 
     1411    $pending = array(); 
     1412  } 
     1413 
     1414  private function process_combinable($combinable, $return_content, $force) 
     1415  { 
     1416    if ($combinable->is_template) 
     1417    { 
     1418      if (!$return_content) 
     1419      { 
     1420        $key = array($combinable->path, $combinable->version); 
     1421        if ($conf['template_compile_check']) 
     1422          $key[] = filemtime( PHPWG_ROOT_PATH . $combinable->path ); 
     1423        $file = PWG_COMBINED_DIR . 't' . base_convert(crc32($key),10,36) . '.' . $this->type; 
     1424        if (!$force && file_exists(PHPWG_ROOT_PATH.$file) ) 
     1425        { 
     1426          $combinable->path = $file; 
     1427          $combinable->version = false; 
     1428          return; 
     1429        } 
     1430      } 
     1431 
     1432      global $template; 
     1433      $handle = $this->type. '.' .$combinable->id; 
     1434      $template->set_filename($handle, realpath(PHPWG_ROOT_PATH.$combinable->path)); 
     1435      trigger_action( 'combinable_preparse', $template, $combinable, $this); //allow themes and plugins to set their own vars to template ... 
     1436      $content = $template->parse($handle, true); 
     1437 
     1438      if ($this->is_css) 
     1439        $content = self::process_css($content, dirname($combinable->path) ); 
    14161440      else 
    1417         $output .= self::process_js($input_file); 
    1418       $output .= "\n"; 
    1419     } 
    1420  
    1421     mkgetdir( dirname(PHPWG_ROOT_PATH.$file) ); 
    1422     file_put_contents( PHPWG_ROOT_PATH.$file,  $output ); 
    1423     @chmod(PHPWG_ROOT_PATH.$file, 0644); 
    1424     $out_file = $file; 
    1425     $out_version = false; 
    1426     $this->clear(); 
    1427     return 2; 
    1428   } 
    1429  
    1430   private static function process_js($file) 
    1431   { 
    1432     $js = file_get_contents(PHPWG_ROOT_PATH . $file); 
     1441        $content = self::process_js($content, $combinable->path ); 
     1442 
     1443      if ($return_content) 
     1444        return $content; 
     1445      file_put_contents( PHPWG_ROOT_PATH.$file, $content ); 
     1446      $combinable->path = $file; 
     1447    } 
     1448    elseif ($return_content) 
     1449    { 
     1450      $content = file_get_contents(PHPWG_ROOT_PATH . $combinable->path); 
     1451      if ($this->is_css) 
     1452        $content = self::process_css($content, dirname($combinable->path) ); 
     1453      else 
     1454        $content = self::process_js($content, $combinable->path ); 
     1455      return $content; 
     1456    } 
     1457  } 
     1458 
     1459  private static function process_js($js, $file) 
     1460  { 
    14331461    if (strpos($file, '.min')===false and strpos($file, '.packed')===false ) 
    14341462    { 
     
    14391467  } 
    14401468 
    1441   private static function process_css($file) 
    1442   { 
    1443     $css = self::process_css_rec($file); 
     1469  private static function process_css($css, $dir) 
     1470  { 
     1471    $css = self::process_css_rec($css, $dir); 
    14441472    if (version_compare(PHP_VERSION, '5.2.4', '>=')) 
    14451473    { 
     
    14511479  } 
    14521480 
    1453   private static function process_css_rec($file) 
     1481  private static function process_css_rec($css, $dir) 
    14541482  { 
    14551483    static $PATTERN = "#url\(\s*['|\"]{0,1}(.*?)['|\"]{0,1}\s*\)#"; 
    1456     $css = file_get_contents(PHPWG_ROOT_PATH . $file); 
     1484 
    14571485    if (preg_match_all($PATTERN, $css, $matches, PREG_SET_ORDER)) 
    14581486    { 
     
    14621490        if ( !url_is_remote($match[1]) && $match[1][0] != '/') 
    14631491        { 
    1464           $relative = dirname($file) . "/$match[1]"; 
     1492          $relative = $dir . "/$match[1]"; 
    14651493          $search[] = $match[0]; 
    14661494          $replace[] = 'url('.embellish_url(get_absolute_root_url(false).$relative).')'; 
     
    14771505      { 
    14781506        $search[] = $match[0]; 
    1479         $replace[] = self::process_css_rec(dirname($file) . "/$match[1]"); 
     1507        $sub_css = file_get_contents(PHPWG_ROOT_PATH . $dir . "/$match[1]"); 
     1508        $replace[] = self::process_css_rec($sub_css, dirname($dir . "/$match[1]") ); 
    14801509      } 
    14811510      $css = str_replace($search, $replace, $css); 
     
    14831512    return $css; 
    14841513  } 
     1514 
    14851515} 
    14861516 
Note: See TracChangeset for help on using the changeset viewer.