1<?php 2 3/* 4 * This file is part of the Assetic package, an OpenSky project. 5 * 6 * (c) 2010-2014 OpenSky Project Inc 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12namespace Assetic\Factory; 13 14use Assetic\Asset\AssetInterface; 15use Assetic\AssetManager; 16use Assetic\Factory\Loader\FormulaLoaderInterface; 17use Assetic\Factory\Resource\ResourceInterface; 18 19/** 20 * A lazy asset manager is a composition of a factory and many formula loaders. 21 * 22 * @author Kris Wallsmith <kris.wallsmith@gmail.com> 23 */ 24class LazyAssetManager extends AssetManager 25{ 26 private $factory; 27 private $loaders; 28 private $resources; 29 private $formulae; 30 private $loaded; 31 private $loading; 32 33 /** 34 * Constructor. 35 * 36 * @param AssetFactory $factory The asset factory 37 * @param array $loaders An array of loaders indexed by alias 38 */ 39 public function __construct(AssetFactory $factory, $loaders = array()) 40 { 41 $this->factory = $factory; 42 $this->loaders = array(); 43 $this->resources = array(); 44 $this->formulae = array(); 45 $this->loaded = false; 46 $this->loading = false; 47 48 foreach ($loaders as $alias => $loader) { 49 $this->setLoader($alias, $loader); 50 } 51 } 52 53 /** 54 * Adds a loader to the asset manager. 55 * 56 * @param string $alias An alias for the loader 57 * @param FormulaLoaderInterface $loader A loader 58 */ 59 public function setLoader($alias, FormulaLoaderInterface $loader) 60 { 61 $this->loaders[$alias] = $loader; 62 $this->loaded = false; 63 } 64 65 /** 66 * Adds a resource to the asset manager. 67 * 68 * @param ResourceInterface $resource A resource 69 * @param string $loader The loader alias for this resource 70 */ 71 public function addResource(ResourceInterface $resource, $loader) 72 { 73 $this->resources[$loader][] = $resource; 74 $this->loaded = false; 75 } 76 77 /** 78 * Returns an array of resources. 79 * 80 * @return array An array of resources 81 */ 82 public function getResources() 83 { 84 $resources = array(); 85 foreach ($this->resources as $r) { 86 $resources = array_merge($resources, $r); 87 } 88 89 return $resources; 90 } 91 92 /** 93 * Checks for an asset formula. 94 * 95 * @param string $name An asset name 96 * 97 * @return Boolean If there is a formula 98 */ 99 public function hasFormula($name) 100 { 101 if (!$this->loaded) { 102 $this->load(); 103 } 104 105 return isset($this->formulae[$name]); 106 } 107 108 /** 109 * Returns an asset's formula. 110 * 111 * @param string $name An asset name 112 * 113 * @return array The formula 114 * 115 * @throws \InvalidArgumentException If there is no formula by that name 116 */ 117 public function getFormula($name) 118 { 119 if (!$this->loaded) { 120 $this->load(); 121 } 122 123 if (!isset($this->formulae[$name])) { 124 throw new \InvalidArgumentException(sprintf('There is no "%s" formula.', $name)); 125 } 126 127 return $this->formulae[$name]; 128 } 129 130 /** 131 * Sets a formula on the asset manager. 132 * 133 * @param string $name An asset name 134 * @param array $formula A formula 135 */ 136 public function setFormula($name, array $formula) 137 { 138 $this->formulae[$name] = $formula; 139 } 140 141 /** 142 * Loads formulae from resources. 143 * 144 * @throws \LogicException If a resource has been added to an invalid loader 145 */ 146 public function load() 147 { 148 if ($this->loading) { 149 return; 150 } 151 152 if ($diff = array_diff(array_keys($this->resources), array_keys($this->loaders))) { 153 throw new \LogicException('The following loader(s) are not registered: '.implode(', ', $diff)); 154 } 155 156 $this->loading = true; 157 158 foreach ($this->resources as $loader => $resources) { 159 foreach ($resources as $resource) { 160 $this->formulae = array_replace($this->formulae, $this->loaders[$loader]->load($resource)); 161 } 162 } 163 164 $this->loaded = true; 165 $this->loading = false; 166 } 167 168 public function get($name) 169 { 170 if (!$this->loaded) { 171 $this->load(); 172 } 173 174 if (!parent::has($name) && isset($this->formulae[$name])) { 175 list($inputs, $filters, $options) = $this->formulae[$name]; 176 $options['name'] = $name; 177 parent::set($name, $this->factory->createAsset($inputs, $filters, $options)); 178 } 179 180 return parent::get($name); 181 } 182 183 public function has($name) 184 { 185 if (!$this->loaded) { 186 $this->load(); 187 } 188 189 return isset($this->formulae[$name]) || parent::has($name); 190 } 191 192 public function getNames() 193 { 194 if (!$this->loaded) { 195 $this->load(); 196 } 197 198 return array_unique(array_merge(parent::getNames(), array_keys($this->formulae))); 199 } 200 201 public function isDebug() 202 { 203 return $this->factory->isDebug(); 204 } 205 206 public function getLastModified(AssetInterface $asset) 207 { 208 return $this->factory->getLastModified($asset); 209 } 210} 211