ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
AssetFactory.php
Go to the documentation of this file.
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
13
25
32{
33 private $root;
34 private $debug;
35 private $output;
36 private $workers;
37 private $am;
38 private $fm;
39
46 public function __construct($root, $debug = false)
47 {
48 $this->root = rtrim($root, '/');
49 $this->debug = $debug;
50 $this->output = 'assetic/*';
51 $this->workers = array();
52 }
53
59 public function setDebug($debug)
60 {
61 $this->debug = $debug;
62 }
63
69 public function isDebug()
70 {
71 return $this->debug;
72 }
73
79 public function setDefaultOutput($output)
80 {
81 $this->output = $output;
82 }
83
89 public function addWorker(WorkerInterface $worker)
90 {
91 $this->workers[] = $worker;
92 }
93
99 public function getAssetManager()
100 {
101 return $this->am;
102 }
103
110 {
111 $this->am = $am;
112 }
113
119 public function getFilterManager()
120 {
121 return $this->fm;
122 }
123
130 {
131 $this->fm = $fm;
132 }
133
153 public function createAsset($inputs = array(), $filters = array(), array $options = array())
154 {
155 if (!is_array($inputs)) {
156 $inputs = array($inputs);
157 }
158
159 if (!is_array($filters)) {
160 $filters = array($filters);
161 }
162
163 if (!isset($options['output'])) {
164 $options['output'] = $this->output;
165 }
166
167 if (!isset($options['vars'])) {
168 $options['vars'] = array();
169 }
170
171 if (!isset($options['debug'])) {
172 $options['debug'] = $this->debug;
173 }
174
175 if (!isset($options['root'])) {
176 $options['root'] = array($this->root);
177 } else {
178 if (!is_array($options['root'])) {
179 $options['root'] = array($options['root']);
180 }
181
182 $options['root'][] = $this->root;
183 }
184
185 if (!isset($options['name'])) {
186 $options['name'] = $this->generateAssetName($inputs, $filters, $options);
187 }
188
189 $asset = $this->createAssetCollection(array(), $options);
190 $extensions = array();
191
192 // inner assets
193 foreach ($inputs as $input) {
194 if (is_array($input)) {
195 // nested formula
196 $asset->add(call_user_func_array(array($this, 'createAsset'), $input));
197 } else {
198 $asset->add($this->parseInput($input, $options));
199 $extensions[pathinfo($input, PATHINFO_EXTENSION)] = true;
200 }
201 }
202
203 // filters
204 foreach ($filters as $filter) {
205 if ('?' != $filter[0]) {
206 $asset->ensureFilter($this->getFilter($filter));
207 } elseif (!$options['debug']) {
208 $asset->ensureFilter($this->getFilter(substr($filter, 1)));
209 }
210 }
211
212 // append variables
213 if (!empty($options['vars'])) {
214 $toAdd = array();
215 foreach ($options['vars'] as $var) {
216 if (false !== strpos($options['output'], '{'.$var.'}')) {
217 continue;
218 }
219
220 $toAdd[] = '{'.$var.'}';
221 }
222
223 if ($toAdd) {
224 $options['output'] = str_replace('*', '*.'.implode('.', $toAdd), $options['output']);
225 }
226 }
227
228 // append consensus extension if missing
229 if (1 == count($extensions) && !pathinfo($options['output'], PATHINFO_EXTENSION) && $extension = key($extensions)) {
230 $options['output'] .= '.'.$extension;
231 }
232
233 // output --> target url
234 $asset->setTargetPath(str_replace('*', $options['name'], $options['output']));
235
236 // apply workers and return
237 return $this->applyWorkers($asset);
238 }
239
240 public function generateAssetName($inputs, $filters, $options = array())
241 {
242 foreach (array_diff(array_keys($options), array('output', 'debug', 'root')) as $key) {
243 unset($options[$key]);
244 }
245
246 ksort($options);
247
248 return substr(sha1(serialize($inputs).serialize($filters).serialize($options)), 0, 7);
249 }
250
251 public function getLastModified(AssetInterface $asset)
252 {
253 $mtime = 0;
254 foreach ($asset instanceof AssetCollectionInterface ? $asset : array($asset) as $leaf) {
255 $mtime = max($mtime, $leaf->getLastModified());
256
257 if (!$filters = $leaf->getFilters()) {
258 continue;
259 }
260
261 $prevFilters = array();
262 foreach ($filters as $filter) {
263 $prevFilters[] = $filter;
264
265 if (!$filter instanceof DependencyExtractorInterface) {
266 continue;
267 }
268
269 // extract children from leaf after running all preceeding filters
270 $clone = clone $leaf;
271 $clone->clearFilters();
272 foreach (array_slice($prevFilters, 0, -1) as $prevFilter) {
273 $clone->ensureFilter($prevFilter);
274 }
275 $clone->load();
276
277 foreach ($filter->getChildren($this, $clone->getContent(), $clone->getSourceDirectory()) as $child) {
278 $mtime = max($mtime, $this->getLastModified($child));
279 }
280 }
281 }
282
283 return $mtime;
284 }
285
303 protected function parseInput($input, array $options = array())
304 {
305 if ('@' == $input[0]) {
306 return $this->createAssetReference(substr($input, 1));
307 }
308
309 if (false !== strpos($input, '://') || 0 === strpos($input, '//')) {
310 return $this->createHttpAsset($input, $options['vars']);
311 }
312
313 if (self::isAbsolutePath($input)) {
314 if ($root = self::findRootDir($input, $options['root'])) {
315 $path = ltrim(substr($input, strlen($root)), '/');
316 } else {
317 $path = null;
318 }
319 } else {
321 $path = $input;
322 $input = $this->root.'/'.$path;
323 }
324
325 if (false !== strpos($input, '*')) {
326 return $this->createGlobAsset($input, $root, $options['vars']);
327 }
328
329 return $this->createFileAsset($input, $root, $path, $options['vars']);
330 }
331
332 protected function createAssetCollection(array $assets = array(), array $options = array())
333 {
334 return new AssetCollection($assets, array(), null, isset($options['vars']) ? $options['vars'] : array());
335 }
336
337 protected function createAssetReference($name)
338 {
339 if (!$this->am) {
340 throw new \LogicException('There is no asset manager.');
341 }
342
343 return new AssetReference($this->am, $name);
344 }
345
346 protected function createHttpAsset($sourceUrl, $vars)
347 {
348 return new HttpAsset($sourceUrl, array(), false, $vars);
349 }
350
351 protected function createGlobAsset($glob, $root = null, $vars)
352 {
353 return new GlobAsset($glob, array(), $root, $vars);
354 }
355
356 protected function createFileAsset($source, $root = null, $path = null, $vars)
357 {
358 return new FileAsset($source, array(), $root, $path, $vars);
359 }
360
361 protected function getFilter($name)
362 {
363 if (!$this->fm) {
364 throw new \LogicException('There is no filter manager.');
365 }
366
367 return $this->fm->get($name);
368 }
369
380 private function applyWorkers(AssetCollectionInterface $asset)
381 {
382 foreach ($asset as $leaf) {
383 foreach ($this->workers as $worker) {
384 $retval = $worker->process($leaf, $this);
385
386 if ($retval instanceof AssetInterface && $leaf !== $retval) {
387 $asset->replaceLeaf($leaf, $retval);
388 }
389 }
390 }
391
392 foreach ($this->workers as $worker) {
393 $retval = $worker->process($asset, $this);
394
395 if ($retval instanceof AssetInterface) {
396 $asset = $retval;
397 }
398 }
399
400 return $asset instanceof AssetCollectionInterface ? $asset : $this->createAssetCollection(array($asset));
401 }
402
403 private static function isAbsolutePath($path)
404 {
405 return '/' == $path[0] || '\\' == $path[0] || (3 < strlen($path) && ctype_alpha($path[0]) && $path[1] == ':' && ('\\' == $path[2] || '/' == $path[2]));
406 }
407
416 private static function findRootDir($path, array $roots)
417 {
418 foreach ($roots as $root) {
419 if (0 === strpos($path, $root)) {
420 return $root;
421 }
422 }
423 }
424}
$path
Definition: aliased.php:25
Manages assets.
A collection of assets.
A reference to an asset in the asset manager.
Represents an asset loaded from a file.
Definition: FileAsset.php:23
A collection of assets loaded by glob.
Definition: GlobAsset.php:23
Represents an asset loaded via an HTTP request.
Definition: HttpAsset.php:23
The asset factory creates asset objects.
addWorker(WorkerInterface $worker)
Adds a factory worker.
__construct($root, $debug=false)
Constructor.
createAssetCollection(array $assets=array(), array $options=array())
setFilterManager(FilterManager $fm)
Sets the filter manager to use when adding filters.
createAsset($inputs=array(), $filters=array(), array $options=array())
Creates a new asset.
createGlobAsset($glob, $root=null, $vars)
applyWorkers(AssetCollectionInterface $asset)
Filters an asset collection through the factory workers.
generateAssetName($inputs, $filters, $options=array())
setDebug($debug)
Sets debug mode for the current factory.
setDefaultOutput($output)
Sets the default output string.
getAssetManager()
Returns the current asset manager.
getFilterManager()
Returns the current filter manager.
getLastModified(AssetInterface $asset)
isDebug()
Checks if the factory is in debug mode.
parseInput($input, array $options=array())
Parses an input string string into an asset.
setAssetManager(AssetManager $am)
Sets the asset manager to use when creating asset references.
static findRootDir($path, array $roots)
Loops through the root directories and returns the first match.
createFileAsset($source, $root=null, $path=null, $vars)
createHttpAsset($sourceUrl, $vars)
Manages the available filters.
An exception for terminatinating execution or to throw for unit testing.
replaceLeaf(AssetInterface $needle, AssetInterface $replacement, $graceful=false)
Replaces an existing leaf with a new one.
An asset has a mutable URL and content and can be loaded and dumped.
Assets are passed through factory workers before leaving the factory.
A filter that knows how to extract dependencies.
if(!is_array($argv)) $options