hoge.cssをhoge.css?20100110にするタスク作った

なぜクエリー文字列を付加するのか

せっかくCSSやJSを変更しても、ブラウザのキャッシュが残っていて変更が反映されない場合があります。そんなときによく使われるテクニックが、ファイル名の後ろにクエリー文字として更新時間を追加するというものです。こうすることで、ブラウザのキャッシュからではなく、更新後のファイルを読み込ませることが可能になります。

でも

変更するたびにview.ymlを書き換えるのはめんどくさい。ということでタスク化してみました。

使い方

$ symfony view:modified-time

このタスクを実行することで、タスクが自動的にview.ymlを探し出しCSSとJSファイル名の後ろに更新時間を付加します。あと、オプションとして、更新時間のフォーマットとYAMLファイルの出力形式を変更できます。

コード

<?php
/**
 * Add modified time to CSS and JS files
 *
 * For example
 * -  stylesheets: [common]
 * +  stylesheets: [common.css?20100105]
 */
class viewModifiedtimeTask extends sfBaseTask
{
  protected
    $format = '', // date format
    $ext    = ''; // file extension

  protected function configure()
  {
    $this->addOptions(array(
      new sfCommandOption('application', null, sfCommandOption::PARAMETER_REQUIRED, 'The application name', 'frontend'),
      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
      new sfCommandOption('connection', null, sfCommandOption::PARAMETER_REQUIRED, 'The connection name', 'doctrine'),
      new sfCommandOption('format', null, sfCommandOption::PARAMETER_REQUIRED, 'The date format', 'Ymd'),
      new sfCommandOption('inline', null, sfCommandOption::PARAMETER_REQUIRED, 'The level where you switch to inline YAML', 2)
    ));

    $this->namespace        = 'view';
    $this->name             = 'modified-time';
    $this->briefDescription = 'Add modified time to CSS and JS files';
    $this->detailedDescription = <<<EOF
The [view:update-time|INFO] task does things.
Call it with:

  [php symfony view:modified-time|INFO]
EOF;
  }

  protected function execute($arguments = array(), $options = array())
  {
    $this->format = $options['format'];

    $files = sfFinder::type('file')->name('view.yml')->in('.');
    foreach ($files as $file)
    {
      $configuration = sfYaml::load($file);

      foreach ($configuration as $view_name => $c)
      {
        if (isset($c['stylesheets']))
        {
          $this->ext = 'css';
          $configuration[$view_name]['stylesheets'] = array_map(array($this, 'addModifiedTime'), $c['stylesheets']);
        }

        if (isset($c['javascripts']))
        {
          $this->ext = 'js';
          $configuration[$view_name]['javascripts'] = array_map(array($this, 'addModifiedTime'), $c['javascripts']);
        }
      }

      file_put_contents($file, sfYaml::dump($configuration, $options['inline']));
    }
  }

  protected function addModifiedTime($source)
  {
    if (false !== strpos($source, '*'))
    {
      return $source;
    }

    if (false !== $pos = strpos($source, '?'))
    {
      // remove query string
      $source = substr($source, 0, $pos);
    }

    if (false === strpos(basename($source), '.'))
    {
      // add file extension
      $source .= '.'.$this->ext;
    }

    $path = sprintf('%s/%s/%s', sfConfig::get('sf_web_dir'), $this->ext, preg_replace('/^-/', '', $source));
    $modified_time = date($this->format, filemtime($path));

    return $source.'?'.$modified_time;
  }
}