123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 |
- <?php namespace Laravel;
- class Asset {
- /**
- * All of the instantiated asset containers.
- *
- * @var array
- */
- public static $containers = array();
- /**
- * Get an asset container instance.
- *
- * <code>
- * // Get the default asset container
- * $container = Asset::container();
- *
- * // Get a named asset container
- * $container = Asset::container('footer');
- * </code>
- *
- * @param string $container
- * @return Asset_Container
- */
- public static function container($container = 'default')
- {
- if ( ! isset(static::$containers[$container]))
- {
- static::$containers[$container] = new Asset_Container($container);
- }
- return static::$containers[$container];
- }
- /**
- * Magic Method for calling methods on the default container.
- *
- * <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>
- */
- public static function __callStatic($method, $parameters)
- {
- return call_user_func_array(array(static::container(), $method), $parameters);
- }
- }
- class Asset_Container {
- /**
- * The asset container name.
- *
- * @var string
- */
- public $name;
- /**
- * The bundle that the assets belong to.
- *
- * @var string
- */
- public $bundle = DEFAULT_BUNDLE;
- /**
- * All of the registered assets.
- *
- * @var array
- */
- public $assets = array();
- /**
- * Create a new asset container instance.
- *
- * @param string $name
- * @return void
- */
- public function __construct($name)
- {
- $this->name = $name;
- }
- /**
- * Add an asset to the container.
- *
- * The extension of the asset source will be used to determine the type of
- * asset being registered (CSS or JavaScript). When using a non-standard
- * extension, the style/script methods may be used to register assets.
- *
- * <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>
- *
- * @param string $name
- * @param string $source
- * @param array $dependencies
- * @param array $attributes
- * @return void
- */
- public function add($name, $source, $dependencies = array(), $attributes = array())
- {
- $type = (pathinfo($source, PATHINFO_EXTENSION) == 'css') ? 'style' : 'script';
- return $this->$type($name, $source, $dependencies, $attributes);
- }
- /**
- * Add a CSS file to the registered assets.
- *
- * @param string $name
- * @param string $source
- * @param array $dependencies
- * @param array $attributes
- * @return Asset_Container
- */
- 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);
- return $this;
- }
- /**
- * Add a JavaScript file to the registered assets.
- *
- * @param string $name
- * @param string $source
- * @param array $dependencies
- * @param array $attributes
- * @return Asset_Container
- */
- public function script($name, $source, $dependencies = array(), $attributes = array())
- {
- $this->register('script', $name, $source, $dependencies, $attributes);
- return $this;
- }
- /**
- * 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;
- }
- /**
- * Add an asset to the array of registered assets.
- *
- * @param string $type
- * @param string $name
- * @param string $source
- * @param array $dependencies
- * @param array $attributes
- * @return void
- */
- protected function register($type, $name, $source, $dependencies, $attributes)
- {
- $dependencies = (array) $dependencies;
- $attributes = (array) $attributes;
- $this->assets[$type][$name] = compact('source', 'dependencies', 'attributes');
- }
- /**
- * Get the links to all of the registered CSS assets.
- *
- * @return string
- */
- public function styles()
- {
- return $this->group('style');
- }
- /**
- * Get the links to all of the registered JavaScript assets.
- *
- * @return string
- */
- public function scripts()
- {
- return $this->group('script');
- }
- /**
- * Get all of the registered assets for a given type / group.
- *
- * @param string $group
- * @return string
- */
- protected function group($group)
- {
- if ( ! isset($this->assets[$group]) or count($this->assets[$group]) == 0) return '';
- $assets = '';
- foreach ($this->arrange($this->assets[$group]) as $name => $data)
- {
- $assets .= $this->asset($group, $name);
- }
-
- return $assets;
- }
- /**
- * Get the HTML link to a registered asset.
- *
- * @param string $group
- * @param string $name
- * @return string
- */
- protected function asset($group, $name)
- {
- if ( ! isset($this->assets[$group][$name])) return '';
- $asset = $this->assets[$group][$name];
- // 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)
- {
- $asset['source'] = $this->path($asset['source']);
- }
- return HTML::$group($asset['source'], $asset['attributes']);
- }
- /**
- * Sort and retrieve assets based on their dependencies
- *
- * @param array $assets
- * @return array
- */
- protected function arrange($assets)
- {
- 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
- */
- protected function evaluate_asset($asset, $value, $original, &$sorted, &$assets)
- {
- // 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
- // the asset's dependencies and determine if they've been sorted.
- if (count($assets[$asset]['dependencies']) == 0)
- {
- $sorted[$asset] = $value;
- 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]);
- 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]);
- }
- }
- }
- /**
- * Verify that an asset's dependency is valid.
- *
- * A dependency is considered valid if it exists, is not a circular reference, and is
- * 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.
- *
- * @param string $asset
- * @param string $dependency
- * @param array $original
- * @param array $assets
- * @return bool
- */
- protected function dependency_is_valid($asset, $dependency, $original, $assets)
- {
- if ( ! isset($original[$dependency]))
- {
- return false;
- }
- elseif ($dependency === $asset)
- {
- throw new \Exception("Asset [$asset] is dependent on itself.");
- }
- elseif (isset($assets[$dependency]) and in_array($asset, $assets[$dependency]['dependencies']))
- {
- throw new \Exception("Assets [$asset] and [$dependency] have a circular dependency.");
- }
- return true;
- }
- }
|