Skip to content

Commit

Permalink
refactored asset factory to use asset locators
Browse files Browse the repository at this point in the history
  • Loading branch information
everzet committed Mar 19, 2012
1 parent e36d240 commit a0e8bcf
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 105 deletions.
105 changes: 21 additions & 84 deletions src/Assetic/Factory/AssetFactory.php
Expand Up @@ -11,13 +11,10 @@

namespace Assetic\Factory;

use Assetic\Locator\AssetLocatorInterface;
use Assetic\Asset\AssetCollection;
use Assetic\Asset\AssetCollectionInterface;
use Assetic\Asset\AssetInterface;
use Assetic\Asset\AssetReference;
use Assetic\Asset\FileAsset;
use Assetic\Asset\GlobAsset;
use Assetic\Asset\HttpAsset;
use Assetic\AssetManager;
use Assetic\Factory\Worker\WorkerInterface;
use Assetic\FilterManager;
Expand All @@ -33,6 +30,7 @@ class AssetFactory
private $debug;
private $output;
private $workers;
private $locators;
private $am;
private $fm;

Expand All @@ -49,6 +47,7 @@ public function __construct($root, $debug = false)
$this->debug = $debug;
$this->output = 'assetic/*';
$this->workers = array();
$this->locators = array();
}

/**
Expand Down Expand Up @@ -91,6 +90,16 @@ public function addWorker(WorkerInterface $worker)
$this->workers[] = $worker;
}

/**
* Adds asset locator.
*
* @param AssetLocatorInterface $locator A locator
*/
public function addLocator(AssetLocatorInterface $locator)
{
$this->locators[] = $locator;
}

/**
* Returns the current asset manager.
*
Expand Down Expand Up @@ -195,7 +204,7 @@ public function createAsset($inputs = array(), $filters = array(), array $option
// nested formula
$asset->add(call_user_func_array(array($this, 'createAsset'), $input));
} else {
$asset->add($this->parseInput($input, $options));
$asset->add($this->locateAsset($input, $options));
$extensions[pathinfo($input, PATHINFO_EXTENSION)] = true;
}
}
Expand Down Expand Up @@ -249,79 +258,29 @@ public function generateAssetName($inputs, $filters, $options = array())
}

/**
* 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.
* Uses registered asset locators to create asset instance from provided input.
*
* @param string $input An input string
* @param array $options An array of options
*
* @return AssetInterface An asset
*/
protected function parseInput($input, array $options = array())
protected function locateAsset($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;
foreach ($this->locators as $locator) {
if ($asset = $locator->locate($input, $options)) {
return $asset;
}
} 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']);
}

throw new \LogicException(sprintf('Can not locate asset "%s".', $input));
}

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) {
Expand Down Expand Up @@ -361,26 +320,4 @@ private function applyWorkers(AssetCollectionInterface $asset)

return $asset instanceof AssetCollectionInterface ? $asset : $this->createAssetCollection(array($asset));
}

static private 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
*/
static private function findRootDir($path, array $roots)
{
foreach ($roots as $root) {
if (0 === strpos($path, $root)) {
return $root;
}
}
}
}
33 changes: 12 additions & 21 deletions tests/Assetic/Test/Factory/AssetFactoryTest.php
Expand Up @@ -27,28 +27,19 @@ protected function setUp()
$this->factory = new AssetFactory(__DIR__);
$this->factory->setAssetManager($this->am);
$this->factory->setFilterManager($this->fm);
}

public function testNoAssetManagerReference()
{
$this->setExpectedException('LogicException', 'There is no asset manager.');

$factory = new AssetFactory('.');
$factory->createAsset(array('@foo'));
}

public function testNoAssetManagerNotReference()
{
$factory = new AssetFactory('.');
$this->assertInstanceOf('Assetic\\Asset\\AssetInterface', $factory->createAsset(array('foo')));
$this->factory->addLocator(new \Assetic\Locator\AssetReferenceLocator($this->am));
$this->factory->addLocator(new \Assetic\Locator\HttpAssetLocator());
$this->factory->addLocator(new \Assetic\Locator\GlobAssetLocator(__DIR__));
$this->factory->addLocator(new \Assetic\Locator\FileAssetLocator(__DIR__));
}

public function testNoFilterManager()
public function testNoAppropriateLocator()
{
$this->setExpectedException('LogicException', 'There is no filter manager.');
$this->setExpectedException('LogicException', 'Can not locate asset "@foo".');

$factory = new AssetFactory('.');
$factory->createAsset(array('foo'), array('foo'));
$factory->createAsset(array('@foo'));
}

public function testCreateAssetReference()
Expand Down Expand Up @@ -143,7 +134,7 @@ public function testIncludingOptionalFilter()
->with('foo')
->will($this->returnValue($this->getMock('Assetic\\Filter\\FilterInterface')));

$this->factory->createAsset(array('foo.css'), array('?foo'));
$this->factory->createAsset(array('../Fixture/root/foo.css'), array('?foo'));
}

public function testWorkers()
Expand All @@ -156,7 +147,7 @@ public function testWorkers()
->with($this->isInstanceOf('Assetic\\Asset\\AssetInterface'));

$this->factory->addWorker($worker);
$this->factory->createAsset(array('foo.js', 'bar.js'));
$this->factory->createAsset(array('../Fixture/root/foo.js', '../Fixture/root/bar.js'));
}

public function testWorkerReturn()
Expand All @@ -170,7 +161,7 @@ public function testWorkerReturn()
->will($this->returnValue($asset));

$this->factory->addWorker($worker);
$coll = $this->factory->createAsset(array('foo.js', 'bar.js'));
$coll = $this->factory->createAsset(array('../Fixture/root/foo.js', '../Fixture/root/bar.js'));

$this->assertEquals(1, count(iterator_to_array($coll)));
}
Expand All @@ -183,10 +174,10 @@ public function testNestedFormula()
->will($this->returnValue($this->getMock('Assetic\\Filter\\FilterInterface')));

$inputs = array(
'css/main.css',
'../Fixture/root/css/main.css',
array(
// nested formula
array('css/more.sass'),
array('../Fixture/root/css/more.sass'),
array('foo'),
),
);
Expand Down

0 comments on commit a0e8bcf

Please sign in to comment.