2012-04-10 22:36:20 -05:00
|
|
|
<?php namespace Laravel;
|
2011-07-29 23:17:57 -05:00
|
|
|
|
|
|
|
|
class Asset {
|
|
|
|
|
|
|
|
|
|
/**
|
2011-08-13 22:19:04 -05:00
|
|
|
* All of the instantiated asset containers.
|
|
|
|
|
*
|
2011-07-29 23:17:57 -05:00
|
|
|
* @var array
|
|
|
|
|
*/
|
2012-01-18 10:25:12 -06:00
|
|
|
public static $containers = array();
|
2011-07-29 23:17:57 -05:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get an asset container instance.
|
|
|
|
|
*
|
2011-09-21 22:15:42 -05:00
|
|
|
* <code>
|
|
|
|
|
* // Get the default asset container
|
|
|
|
|
* $container = Asset::container();
|
|
|
|
|
*
|
|
|
|
|
* // Get a named asset container
|
|
|
|
|
* $container = Asset::container('footer');
|
|
|
|
|
* </code>
|
|
|
|
|
*
|
2011-08-09 13:25:52 -05:00
|
|
|
* @param string $container
|
|
|
|
|
* @return Asset_Container
|
2011-07-29 23:17:57 -05:00
|
|
|
*/
|
2011-09-20 23:14:09 -05:00
|
|
|
public static function container($container = 'default')
|
2011-07-29 23:17:57 -05:00
|
|
|
{
|
2011-09-20 23:14:09 -05:00
|
|
|
if ( ! isset(static::$containers[$container]))
|
2011-07-29 23:17:57 -05:00
|
|
|
{
|
2011-09-20 23:14:09 -05:00
|
|
|
static::$containers[$container] = new Asset_Container($container);
|
2011-07-29 23:17:57 -05:00
|
|
|
}
|
|
|
|
|
|
2011-09-20 23:14:09 -05:00
|
|
|
return static::$containers[$container];
|
2011-07-29 23:17:57 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2012-01-16 13:59:24 -06:00
|
|
|
* Magic Method for calling methods on the default container.
|
2011-09-21 22:15:42 -05:00
|
|
|
*
|
|
|
|
|
* <code>
|
|
|
|
|
* // Call the "styles" method on the default container
|
|
|
|
|
* echo Asset::styles();
|
|
|
|
|
*
|
|
|
|
|
* // Call the "add" method on the default container
|
|
|
|
|
* Asset::add('jquery', 'js/jquery.js');
|
|
|
|
|
* </code>
|
2011-07-29 23:17:57 -05:00
|
|
|
*/
|
2011-09-20 23:14:09 -05:00
|
|
|
public static function __callStatic($method, $parameters)
|
2011-07-29 23:17:57 -05:00
|
|
|
{
|
2011-09-20 23:14:09 -05:00
|
|
|
return call_user_func_array(array(static::container(), $method), $parameters);
|
2011-07-29 23:17:57 -05:00
|
|
|
}
|
|
|
|
|
|
2011-07-31 14:28:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Asset_Container {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The asset container name.
|
|
|
|
|
*
|
|
|
|
|
* @var string
|
|
|
|
|
*/
|
|
|
|
|
public $name;
|
|
|
|
|
|
2012-01-16 13:59:24 -06:00
|
|
|
/**
|
|
|
|
|
* The bundle that the assets belong to.
|
|
|
|
|
*
|
|
|
|
|
* @var string
|
|
|
|
|
*/
|
|
|
|
|
public $bundle = DEFAULT_BUNDLE;
|
|
|
|
|
|
2011-07-31 14:28:24 -05:00
|
|
|
/**
|
|
|
|
|
* All of the registered assets.
|
|
|
|
|
*
|
|
|
|
|
* @var array
|
|
|
|
|
*/
|
|
|
|
|
public $assets = array();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Create a new asset container instance.
|
|
|
|
|
*
|
|
|
|
|
* @param string $name
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
2011-09-20 23:14:09 -05:00
|
|
|
public function __construct($name)
|
2011-07-31 14:28:24 -05:00
|
|
|
{
|
|
|
|
|
$this->name = $name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add an asset to the container.
|
|
|
|
|
*
|
2011-08-09 13:25:52 -05:00
|
|
|
* The extension of the asset source will be used to determine the type of
|
2012-01-16 13:59:24 -06:00
|
|
|
* asset being registered (CSS or JavaScript). When using a non-standard
|
|
|
|
|
* extension, the style/script methods may be used to register assets.
|
2011-08-09 13:25:52 -05:00
|
|
|
*
|
2011-09-21 22:15:42 -05:00
|
|
|
* <code>
|
|
|
|
|
* // Add an asset to the container
|
|
|
|
|
* Asset::container()->add('jquery', 'js/jquery.js');
|
|
|
|
|
*
|
|
|
|
|
* // Add an asset that has dependencies on other assets
|
|
|
|
|
* Asset::add('jquery', 'js/jquery.js', 'jquery-ui');
|
|
|
|
|
*
|
|
|
|
|
* // Add an asset that should have attributes applied to its tags
|
|
|
|
|
* Asset::add('jquery', 'js/jquery.js', null, array('defer'));
|
|
|
|
|
* </code>
|
|
|
|
|
*
|
2011-07-31 14:28:24 -05:00
|
|
|
* @param string $name
|
|
|
|
|
* @param string $source
|
|
|
|
|
* @param array $dependencies
|
|
|
|
|
* @param array $attributes
|
2012-09-28 10:10:35 +02:00
|
|
|
* @return Asset_Container
|
2011-07-31 14:28:24 -05:00
|
|
|
*/
|
|
|
|
|
public function add($name, $source, $dependencies = array(), $attributes = array())
|
|
|
|
|
{
|
2011-08-26 21:42:04 -05:00
|
|
|
$type = (pathinfo($source, PATHINFO_EXTENSION) == 'css') ? 'style' : 'script';
|
2011-08-11 21:27:20 -05:00
|
|
|
|
2012-01-16 13:59:24 -06:00
|
|
|
return $this->$type($name, $source, $dependencies, $attributes);
|
2011-07-31 14:28:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2011-09-08 17:49:16 -05:00
|
|
|
* Add a CSS file to the registered assets.
|
2011-07-31 14:28:24 -05:00
|
|
|
*
|
2011-09-08 17:49:16 -05:00
|
|
|
* @param string $name
|
|
|
|
|
* @param string $source
|
|
|
|
|
* @param array $dependencies
|
|
|
|
|
* @param array $attributes
|
|
|
|
|
* @return Asset_Container
|
2011-07-31 14:28:24 -05:00
|
|
|
*/
|
|
|
|
|
public function style($name, $source, $dependencies = array(), $attributes = array())
|
|
|
|
|
{
|
|
|
|
|
if ( ! array_key_exists('media', $attributes))
|
|
|
|
|
{
|
|
|
|
|
$attributes['media'] = 'all';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->register('style', $name, $source, $dependencies, $attributes);
|
2011-09-08 17:49:16 -05:00
|
|
|
|
|
|
|
|
return $this;
|
2011-07-31 14:28:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2011-09-08 17:49:16 -05:00
|
|
|
* Add a JavaScript file to the registered assets.
|
2011-07-31 14:28:24 -05:00
|
|
|
*
|
2011-09-08 17:49:16 -05:00
|
|
|
* @param string $name
|
|
|
|
|
* @param string $source
|
|
|
|
|
* @param array $dependencies
|
|
|
|
|
* @param array $attributes
|
|
|
|
|
* @return Asset_Container
|
2011-07-31 14:28:24 -05:00
|
|
|
*/
|
|
|
|
|
public function script($name, $source, $dependencies = array(), $attributes = array())
|
|
|
|
|
{
|
|
|
|
|
$this->register('script', $name, $source, $dependencies, $attributes);
|
2011-09-08 17:49:16 -05:00
|
|
|
|
|
|
|
|
return $this;
|
2011-07-31 14:28:24 -05:00
|
|
|
}
|
|
|
|
|
|
2012-01-16 13:59:24 -06:00
|
|
|
/**
|
|
|
|
|
* Returns the full-path for an asset.
|
|
|
|
|
*
|
|
|
|
|
* @param string $source
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
|
|
|
|
public function path($source)
|
|
|
|
|
{
|
|
|
|
|
return Bundle::assets($this->bundle).$source;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the bundle that the container's assets belong to.
|
|
|
|
|
*
|
|
|
|
|
* @param string $bundle
|
|
|
|
|
* @return Asset_Container
|
|
|
|
|
*/
|
|
|
|
|
public function bundle($bundle)
|
|
|
|
|
{
|
|
|
|
|
$this->bundle = $bundle;
|
|
|
|
|
return $this;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-31 14:28:24 -05:00
|
|
|
/**
|
2011-08-18 19:56:29 -05:00
|
|
|
* Add an asset to the array of registered assets.
|
|
|
|
|
*
|
2011-07-31 14:28:24 -05:00
|
|
|
* @param string $type
|
|
|
|
|
* @param string $name
|
|
|
|
|
* @param string $source
|
|
|
|
|
* @param array $dependencies
|
|
|
|
|
* @param array $attributes
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
2011-09-06 23:29:19 -05:00
|
|
|
protected function register($type, $name, $source, $dependencies, $attributes)
|
2011-07-31 14:28:24 -05:00
|
|
|
{
|
|
|
|
|
$dependencies = (array) $dependencies;
|
|
|
|
|
|
2011-09-21 22:15:42 -05:00
|
|
|
$attributes = (array) $attributes;
|
|
|
|
|
|
2011-07-31 14:28:24 -05:00
|
|
|
$this->assets[$type][$name] = compact('source', 'dependencies', 'attributes');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2011-08-09 13:25:52 -05:00
|
|
|
* Get the links to all of the registered CSS assets.
|
2011-07-31 14:28:24 -05:00
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
|
|
|
|
public function styles()
|
|
|
|
|
{
|
2011-09-06 23:39:50 -05:00
|
|
|
return $this->group('style');
|
2011-07-31 14:28:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2011-08-09 13:25:52 -05:00
|
|
|
* Get the links to all of the registered JavaScript assets.
|
2011-07-31 14:28:24 -05:00
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
|
|
|
|
public function scripts()
|
|
|
|
|
{
|
2011-09-06 23:39:50 -05:00
|
|
|
return $this->group('script');
|
2011-07-31 14:28:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2011-08-18 19:56:29 -05:00
|
|
|
* Get all of the registered assets for a given type / group.
|
2011-07-31 14:28:24 -05:00
|
|
|
*
|
|
|
|
|
* @param string $group
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
2011-09-06 23:39:50 -05:00
|
|
|
protected function group($group)
|
2011-07-31 14:28:24 -05:00
|
|
|
{
|
|
|
|
|
if ( ! isset($this->assets[$group]) or count($this->assets[$group]) == 0) return '';
|
|
|
|
|
|
|
|
|
|
$assets = '';
|
|
|
|
|
|
|
|
|
|
foreach ($this->arrange($this->assets[$group]) as $name => $data)
|
|
|
|
|
{
|
2011-09-06 23:39:50 -05:00
|
|
|
$assets .= $this->asset($group, $name);
|
2011-07-31 14:28:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $assets;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2011-08-18 19:56:29 -05:00
|
|
|
* Get the HTML link to a registered asset.
|
2011-07-31 14:28:24 -05:00
|
|
|
*
|
|
|
|
|
* @param string $group
|
|
|
|
|
* @param string $name
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
2011-09-06 23:39:50 -05:00
|
|
|
protected function asset($group, $name)
|
2011-07-31 14:28:24 -05:00
|
|
|
{
|
2011-08-08 08:31:57 -05:00
|
|
|
if ( ! isset($this->assets[$group][$name])) return '';
|
2011-07-31 14:28:24 -05:00
|
|
|
|
|
|
|
|
$asset = $this->assets[$group][$name];
|
|
|
|
|
|
2012-01-16 13:59:24 -06:00
|
|
|
// If the bundle source is not a complete URL, we will go ahead and prepend
|
|
|
|
|
// the bundle's asset path to the source provided with the asset. This will
|
|
|
|
|
// ensure that we attach the correct path to the asset.
|
|
|
|
|
if (filter_var($asset['source'], FILTER_VALIDATE_URL) === false)
|
|
|
|
|
{
|
2012-01-18 10:47:48 -06:00
|
|
|
$asset['source'] = $this->path($asset['source']);
|
2012-01-16 13:59:24 -06:00
|
|
|
}
|
|
|
|
|
|
2011-09-20 23:14:09 -05:00
|
|
|
return HTML::$group($asset['source'], $asset['attributes']);
|
2011-07-31 14:28:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sort and retrieve assets based on their dependencies
|
|
|
|
|
*
|
|
|
|
|
* @param array $assets
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
2011-09-06 23:29:19 -05:00
|
|
|
protected function arrange($assets)
|
2011-07-31 14:28:24 -05:00
|
|
|
{
|
|
|
|
|
list($original, $sorted) = array($assets, array());
|
|
|
|
|
|
|
|
|
|
while (count($assets) > 0)
|
|
|
|
|
{
|
|
|
|
|
foreach ($assets as $asset => $value)
|
|
|
|
|
{
|
|
|
|
|
$this->evaluate_asset($asset, $value, $original, $sorted, $assets);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $sorted;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Evaluate an asset and its dependencies.
|
|
|
|
|
*
|
|
|
|
|
* @param string $asset
|
|
|
|
|
* @param string $value
|
|
|
|
|
* @param array $original
|
|
|
|
|
* @param array $sorted
|
|
|
|
|
* @param array $assets
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
2011-09-06 23:29:19 -05:00
|
|
|
protected function evaluate_asset($asset, $value, $original, &$sorted, &$assets)
|
2011-07-31 14:28:24 -05:00
|
|
|
{
|
|
|
|
|
// If the asset has no more dependencies, we can add it to the sorted list
|
|
|
|
|
// and remove it from the array of assets. Otherwise, we will not verify
|
2012-01-16 13:59:24 -06:00
|
|
|
// the asset's dependencies and determine if they've been sorted.
|
2011-07-31 14:28:24 -05:00
|
|
|
if (count($assets[$asset]['dependencies']) == 0)
|
|
|
|
|
{
|
|
|
|
|
$sorted[$asset] = $value;
|
2011-10-22 23:25:07 -05:00
|
|
|
|
2011-07-31 14:28:24 -05:00
|
|
|
unset($assets[$asset]);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
foreach ($assets[$asset]['dependencies'] as $key => $dependency)
|
|
|
|
|
{
|
|
|
|
|
if ( ! $this->dependency_is_valid($asset, $dependency, $original, $assets))
|
|
|
|
|
{
|
|
|
|
|
unset($assets[$asset]['dependencies'][$key]);
|
2011-10-22 23:25:07 -05:00
|
|
|
|
2011-07-31 14:28:24 -05:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If the dependency has not yet been added to the sorted list, we can not
|
|
|
|
|
// remove it from this asset's array of dependencies. We'll try again on
|
|
|
|
|
// the next trip through the loop.
|
|
|
|
|
if ( ! isset($sorted[$dependency])) continue;
|
|
|
|
|
|
|
|
|
|
unset($assets[$asset]['dependencies'][$key]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2011-08-18 19:56:29 -05:00
|
|
|
* Verify that an asset's dependency is valid.
|
|
|
|
|
*
|
|
|
|
|
* A dependency is considered valid if it exists, is not a circular reference, and is
|
2012-01-16 13:59:24 -06:00
|
|
|
* not a reference to the owning asset itself. If the dependency doesn't exist, no
|
|
|
|
|
* error or warning will be given. For the other cases, an exception is thrown.
|
2011-07-31 14:28:24 -05:00
|
|
|
*
|
|
|
|
|
* @param string $asset
|
|
|
|
|
* @param string $dependency
|
|
|
|
|
* @param array $original
|
|
|
|
|
* @param array $assets
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
2011-09-06 23:29:19 -05:00
|
|
|
protected function dependency_is_valid($asset, $dependency, $original, $assets)
|
2011-07-31 14:28:24 -05:00
|
|
|
{
|
2012-01-16 13:59:24 -06:00
|
|
|
if ( ! isset($original[$dependency]))
|
2011-07-31 14:28:24 -05:00
|
|
|
{
|
2012-01-16 13:59:24 -06:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
elseif ($dependency === $asset)
|
|
|
|
|
{
|
|
|
|
|
throw new \Exception("Asset [$asset] is dependent on itself.");
|
2011-07-31 14:28:24 -05:00
|
|
|
}
|
|
|
|
|
elseif (isset($assets[$dependency]) and in_array($asset, $assets[$dependency]['dependencies']))
|
|
|
|
|
{
|
2012-01-16 13:59:24 -06:00
|
|
|
throw new \Exception("Assets [$asset] and [$dependency] have a circular dependency.");
|
2011-07-31 14:28:24 -05:00
|
|
|
}
|
2012-01-16 13:59:24 -06:00
|
|
|
|
|
|
|
|
return true;
|
2011-07-31 14:28:24 -05:00
|
|
|
}
|
|
|
|
|
|
2011-11-15 12:35:04 +00:00
|
|
|
}
|