Ignore:
Timestamp:
Nov 12, 2013, 7:33:30 AM (10 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.