class AssetFactory

The asset factory creates asset objects.

@author Kris Wallsmith <kris.wallsmith@gmail.com>

Hierarchy

Expanded class hierarchy of AssetFactory

8 files declare their use of AssetFactory
AssetFactoryTest.php in drupal/core/vendor/kriswallsmith/assetic/tests/Assetic/Test/Factory/AssetFactoryTest.php
AsseticExtension.php in drupal/core/vendor/kriswallsmith/assetic/src/Assetic/Extension/Twig/AsseticExtension.php
AsseticExtensionTest.php in drupal/core/vendor/kriswallsmith/assetic/tests/Assetic/Test/Extension/Twig/AsseticExtensionTest.php
AsseticTokenParser.php in drupal/core/vendor/kriswallsmith/assetic/src/Assetic/Extension/Twig/AsseticTokenParser.php
BasePhpFormulaLoader.php in drupal/core/vendor/kriswallsmith/assetic/src/Assetic/Factory/Loader/BasePhpFormulaLoader.php

... See full list

File

drupal/core/vendor/kriswallsmith/assetic/src/Assetic/Factory/AssetFactory.php, line 30

Namespace

Assetic\Factory
View source
class AssetFactory {
  private $root;
  private $debug;
  private $output;
  private $workers;
  private $am;
  private $fm;

  /**
   * Constructor.
   *
   * @param string  $root   The default root directory
   * @param string  $output The default output string
   * @param Boolean $debug  Filters prefixed with a "?" will be omitted in debug mode
   */
  public function __construct($root, $debug = false) {
    $this->root = rtrim($root, '/');
    $this->debug = $debug;
    $this->output = 'assetic/*';
    $this->workers = array();
  }

  /**
   * Sets debug mode for the current factory.
   *
   * @param Boolean $debug Debug mode
   */
  public function setDebug($debug) {
    $this->debug = $debug;
  }

  /**
   * Checks if the factory is in debug mode.
   *
   * @return Boolean Debug mode
   */
  public function isDebug() {
    return $this->debug;
  }

  /**
   * Sets the default output string.
   *
   * @param string $output The default output string
   */
  public function setDefaultOutput($output) {
    $this->output = $output;
  }

  /**
   * Adds a factory worker.
   *
   * @param WorkerInterface $worker A worker
   */
  public function addWorker(WorkerInterface $worker) {
    $this->workers[] = $worker;
  }

  /**
   * Returns the current asset manager.
   *
   * @return AssetManager|null The asset manager
   */
  public function getAssetManager() {
    return $this->am;
  }

  /**
   * Sets the asset manager to use when creating asset references.
   *
   * @param AssetManager $am The asset manager
   */
  public function setAssetManager(AssetManager $am) {
    $this->am = $am;
  }

  /**
   * Returns the current filter manager.
   *
   * @return FilterManager|null The filter manager
   */
  public function getFilterManager() {
    return $this->fm;
  }

  /**
   * Sets the filter manager to use when adding filters.
   *
   * @param FilterManager $fm The filter manager
   */
  public function setFilterManager(FilterManager $fm) {
    $this->fm = $fm;
  }

  /**
   * Creates a new asset.
   *
   * Prefixing a filter name with a question mark will cause it to be
   * omitted when the factory is in debug mode.
   *
   * Available options:
   *
   *  * output: An output string
   *  * name:   An asset name for interpolation in output patterns
   *  * debug:  Forces debug mode on or off for this asset
   *  * root:   An array or string of more root directories
   *
   * @param array|string $inputs  An array of input strings
   * @param array|string $filters An array of filter names
   * @param array        $options An array of options
   *
   * @return AssetCollection An asset collection
   */
  public function createAsset($inputs = array(), $filters = array(), array $options = array()) {
    if (!is_array($inputs)) {
      $inputs = array(
        $inputs,
      );
    }
    if (!is_array($filters)) {
      $filters = array(
        $filters,
      );
    }
    if (!isset($options['output'])) {
      $options['output'] = $this->output;
    }
    if (!isset($options['vars'])) {
      $options['vars'] = array();
    }
    if (!isset($options['debug'])) {
      $options['debug'] = $this->debug;
    }
    if (!isset($options['root'])) {
      $options['root'] = array(
        $this->root,
      );
    }
    else {
      if (!is_array($options['root'])) {
        $options['root'] = array(
          $options['root'],
        );
      }
      $options['root'][] = $this->root;
    }
    if (!isset($options['name'])) {
      $options['name'] = $this
        ->generateAssetName($inputs, $filters, $options);
    }
    $asset = $this
      ->createAssetCollection(array(), $options);
    $extensions = array();

    // inner assets
    foreach ($inputs as $input) {
      if (is_array($input)) {

        // nested formula
        $asset
          ->add(call_user_func_array(array(
          $this,
          'createAsset',
        ), $input));
      }
      else {
        $asset
          ->add($this
          ->parseInput($input, $options));
        $extensions[pathinfo($input, PATHINFO_EXTENSION)] = true;
      }
    }

    // filters
    foreach ($filters as $filter) {
      if ('?' != $filter[0]) {
        $asset
          ->ensureFilter($this
          ->getFilter($filter));
      }
      elseif (!$options['debug']) {
        $asset
          ->ensureFilter($this
          ->getFilter(substr($filter, 1)));
      }
    }

    // append variables
    if (!empty($options['vars'])) {
      $toAdd = array();
      foreach ($options['vars'] as $var) {
        if (false !== strpos($options['output'], '{' . $var . '}')) {
          continue;
        }
        $toAdd[] = '{' . $var . '}';
      }
      if ($toAdd) {
        $options['output'] = str_replace('*', '*.' . implode('.', $toAdd), $options['output']);
      }
    }

    // append consensus extension if missing
    if (1 == count($extensions) && !pathinfo($options['output'], PATHINFO_EXTENSION) && ($extension = key($extensions))) {
      $options['output'] .= '.' . $extension;
    }

    // output --> target url
    $asset
      ->setTargetPath(str_replace('*', $options['name'], $options['output']));

    // apply workers and return
    return $this
      ->applyWorkers($asset);
  }
  public function generateAssetName($inputs, $filters, $options = array()) {
    foreach (array_diff(array_keys($options), array(
      'output',
      'debug',
      'root',
    )) as $key) {
      unset($options[$key]);
    }
    ksort($options);
    return substr(sha1(serialize($inputs) . serialize($filters) . serialize($options)), 0, 7);
  }

  /**
   * Parses an input string string into an asset.
   *
   * The input string can be one of the following:
   *
   *  * A reference:     If the string starts with an "at" sign it will be interpreted as a reference to an asset in the asset manager
   *  * An absolute URL: If the string contains "://" or starts with "//" it will be interpreted as an HTTP asset
   *  * A glob:          If the string contains a "*" it will be interpreted as a glob
   *  * A path:          Otherwise the string is interpreted as a filesystem path
   *
   * Both globs and paths will be absolutized using the current root directory.
   *
   * @param string $input   An input string
   * @param array  $options An array of options
   *
   * @return AssetInterface An asset
   */
  protected function parseInput($input, array $options = array()) {
    if ('@' == $input[0]) {
      return $this
        ->createAssetReference(substr($input, 1));
    }
    if (false !== strpos($input, '://') || 0 === strpos($input, '//')) {
      return $this
        ->createHttpAsset($input, $options['vars']);
    }
    if (self::isAbsolutePath($input)) {
      if ($root = self::findRootDir($input, $options['root'])) {
        $path = ltrim(substr($input, strlen($root)), '/');
      }
      else {
        $path = null;
      }
    }
    else {
      $root = $this->root;
      $path = $input;
      $input = $this->root . '/' . $path;
    }
    if (false !== strpos($input, '*')) {
      return $this
        ->createGlobAsset($input, $root, $options['vars']);
    }
    else {
      return $this
        ->createFileAsset($input, $root, $path, $options['vars']);
    }
  }
  protected function createAssetCollection(array $assets = array(), array $options = array()) {
    return new AssetCollection($assets, array(), null, isset($options['vars']) ? $options['vars'] : array());
  }
  protected function createAssetReference($name) {
    if (!$this->am) {
      throw new \LogicException('There is no asset manager.');
    }
    return new AssetReference($this->am, $name);
  }
  protected function createHttpAsset($sourceUrl, $vars) {
    return new HttpAsset($sourceUrl, array(), false, $vars);
  }
  protected function createGlobAsset($glob, $root = null, $vars) {
    return new GlobAsset($glob, array(), $root, $vars);
  }
  protected function createFileAsset($source, $root = null, $path = null, $vars) {
    return new FileAsset($source, array(), $root, $path, $vars);
  }
  protected function getFilter($name) {
    if (!$this->fm) {
      throw new \LogicException('There is no filter manager.');
    }
    return $this->fm
      ->get($name);
  }

  /**
   * Filters an asset collection through the factory workers.
   *
   * Each leaf asset will be processed first, followed by the asset
   * collection itself.
   *
   * @param AssetCollectionInterface $asset An asset collection
   */
  private function applyWorkers(AssetCollectionInterface $asset) {
    foreach ($asset as $leaf) {
      foreach ($this->workers as $worker) {
        $retval = $worker
          ->process($leaf);
        if ($retval instanceof AssetInterface && $leaf !== $retval) {
          $asset
            ->replaceLeaf($leaf, $retval);
        }
      }
    }
    foreach ($this->workers as $worker) {
      $retval = $worker
        ->process($asset);
      if ($retval instanceof AssetInterface) {
        $asset = $retval;
      }
    }
    return $asset instanceof AssetCollectionInterface ? $asset : $this
      ->createAssetCollection(array(
      $asset,
    ));
  }
  private static function isAbsolutePath($path) {
    return '/' == $path[0] || '\\' == $path[0] || 3 < strlen($path) && ctype_alpha($path[0]) && $path[1] == ':' && ('\\' == $path[2] || '/' == $path[2]);
  }

  /**
   * Loops through the root directories and returns the first match.
   *
   * @param string $path  An absolute path
   * @param array  $roots An array of root directories
   *
   * @return string|null The matching root directory, if found
   */
  private static function findRootDir($path, array $roots) {
    foreach ($roots as $root) {
      if (0 === strpos($path, $root)) {
        return $root;
      }
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
AssetFactory::$am private property
AssetFactory::$debug private property
AssetFactory::$fm private property
AssetFactory::$output private property
AssetFactory::$root private property
AssetFactory::$workers private property
AssetFactory::addWorker public function Adds a factory worker.
AssetFactory::applyWorkers private function Filters an asset collection through the factory workers.
AssetFactory::createAsset public function Creates a new asset.
AssetFactory::createAssetCollection protected function
AssetFactory::createAssetReference protected function
AssetFactory::createFileAsset protected function
AssetFactory::createGlobAsset protected function
AssetFactory::createHttpAsset protected function
AssetFactory::findRootDir private static function Loops through the root directories and returns the first match.
AssetFactory::generateAssetName public function
AssetFactory::getAssetManager public function Returns the current asset manager.
AssetFactory::getFilter protected function
AssetFactory::getFilterManager public function Returns the current filter manager.
AssetFactory::isAbsolutePath private static function
AssetFactory::isDebug public function Checks if the factory is in debug mode.
AssetFactory::parseInput protected function Parses an input string string into an asset.
AssetFactory::setAssetManager public function Sets the asset manager to use when creating asset references.
AssetFactory::setDebug public function Sets debug mode for the current factory.
AssetFactory::setDefaultOutput public function Sets the default output string.
AssetFactory::setFilterManager public function Sets the filter manager to use when adding filters.
AssetFactory::__construct public function Constructor.