1
|
|
|
<?php namespace Anomaly\Streams\Platform\Asset; |
2
|
|
|
|
3
|
|
|
use Anomaly\Streams\Platform\Addon\Theme\ThemeCollection; |
4
|
|
|
use Anomaly\Streams\Platform\Application\Application; |
5
|
|
|
use Anomaly\Streams\Platform\Asset\Filter\CoffeeFilter; |
6
|
|
|
use Anomaly\Streams\Platform\Asset\Filter\CssMinFilter; |
7
|
|
|
use Anomaly\Streams\Platform\Asset\Filter\JsMinFilter; |
8
|
|
|
use Anomaly\Streams\Platform\Asset\Filter\LessFilter; |
9
|
|
|
use Anomaly\Streams\Platform\Asset\Filter\NodeLessFilter; |
10
|
|
|
use Anomaly\Streams\Platform\Asset\Filter\ParseFilter; |
11
|
|
|
use Anomaly\Streams\Platform\Asset\Filter\RubySassFilter; |
12
|
|
|
use Anomaly\Streams\Platform\Asset\Filter\RubyScssFilter; |
13
|
|
|
use Anomaly\Streams\Platform\Asset\Filter\SassFilter; |
14
|
|
|
use Anomaly\Streams\Platform\Asset\Filter\ScssFilter; |
15
|
|
|
use Anomaly\Streams\Platform\Asset\Filter\SeparatorFilter; |
16
|
|
|
use Anomaly\Streams\Platform\Asset\Filter\StylusFilter; |
17
|
|
|
use Anomaly\Streams\Platform\Routing\UrlGenerator; |
18
|
|
|
use Assetic\Asset\AssetCollection; |
19
|
|
|
use Assetic\Asset\FileAsset; |
20
|
|
|
use Assetic\Asset\GlobAsset; |
21
|
|
|
use Assetic\Filter\PhpCssEmbedFilter; |
22
|
|
|
use Collective\Html\HtmlBuilder; |
23
|
|
|
use Illuminate\Config\Repository; |
24
|
|
|
use Illuminate\Filesystem\Filesystem; |
25
|
|
|
use Illuminate\Http\Request; |
26
|
|
|
use League\Flysystem\MountManager; |
27
|
|
|
|
28
|
|
|
class Asset |
29
|
|
|
{ |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* The public base directory. |
33
|
|
|
* |
34
|
|
|
* @var null |
35
|
|
|
*/ |
36
|
|
|
protected $directory = null; |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* Groups of assets. Groups can |
40
|
|
|
* be single files as well. |
41
|
|
|
* |
42
|
|
|
* @var array |
43
|
|
|
*/ |
44
|
|
|
protected $collections = []; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* The URL generator. |
48
|
|
|
* |
49
|
|
|
* @var UrlGenerator |
50
|
|
|
*/ |
51
|
|
|
protected $url; |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* The HTML utility. |
55
|
|
|
* |
56
|
|
|
* @var HtmlBuilder |
57
|
|
|
*/ |
58
|
|
|
protected $html; |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* The files system. |
62
|
|
|
* |
63
|
|
|
* @var Filesystem |
64
|
|
|
*/ |
65
|
|
|
protected $files; |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* Asset path hints by namespace. |
69
|
|
|
* |
70
|
|
|
* 'module.users' => 'the/resources/path' |
71
|
|
|
* |
72
|
|
|
* @var AssetPaths |
73
|
|
|
*/ |
74
|
|
|
protected $paths; |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* The asset parser utility. |
78
|
|
|
* |
79
|
|
|
* @var AssetParser |
80
|
|
|
*/ |
81
|
|
|
protected $parser; |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* The theme collection. |
85
|
|
|
* |
86
|
|
|
* @var ThemeCollection |
87
|
|
|
*/ |
88
|
|
|
protected $themes; |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* The mount manager. |
92
|
|
|
* |
93
|
|
|
* @var MountManager |
94
|
|
|
*/ |
95
|
|
|
protected $manager; |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* The HTTP request. |
99
|
|
|
* |
100
|
|
|
* @var Request |
101
|
|
|
*/ |
102
|
|
|
protected $request; |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* The stream application. |
106
|
|
|
* |
107
|
|
|
* @var Application |
108
|
|
|
*/ |
109
|
|
|
protected $application; |
110
|
|
|
|
111
|
|
|
/** |
112
|
|
|
* The config repository. |
113
|
|
|
* |
114
|
|
|
* @var array |
115
|
|
|
*/ |
116
|
|
|
protected $config; |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* Create a new Application instance. |
120
|
|
|
* |
121
|
|
|
* @param Application $application |
122
|
|
|
* @param ThemeCollection $themes |
123
|
|
|
* @param MountManager $manager |
124
|
|
|
* @param AssetParser $parser |
125
|
|
|
* @param Repository $config |
126
|
|
|
* @param Filesystem $files |
127
|
|
|
* @param AssetPaths $paths |
128
|
|
|
* @param Request $request |
129
|
|
|
* @param HtmlBuilder $html |
130
|
|
|
* @param UrlGenerator $url |
131
|
|
|
*/ |
132
|
|
View Code Duplication |
public function __construct( |
|
|
|
|
133
|
|
|
Application $application, |
134
|
|
|
ThemeCollection $themes, |
135
|
|
|
MountManager $manager, |
136
|
|
|
AssetParser $parser, |
137
|
|
|
Repository $config, |
138
|
|
|
Filesystem $files, |
139
|
|
|
AssetPaths $paths, |
140
|
|
|
Request $request, |
|
|
|
|
141
|
|
|
HtmlBuilder $html, |
142
|
|
|
UrlGenerator $url |
143
|
|
|
) { |
144
|
|
|
$this->url = $url; |
145
|
|
|
$this->html = $html; |
146
|
|
|
$this->files = $files; |
147
|
|
|
$this->paths = $paths; |
148
|
|
|
$this->config = $config; |
|
|
|
|
149
|
|
|
$this->themes = $themes; |
150
|
|
|
$this->parser = $parser; |
151
|
|
|
$this->manager = $manager; |
152
|
|
|
$this->request = $request; |
153
|
|
|
$this->application = $application; |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* Add an asset or glob pattern to an asset collection. |
158
|
|
|
* |
159
|
|
|
* This should support the asset being the collection |
160
|
|
|
* and the asset (for single files) internally |
161
|
|
|
* so asset.links / asset.scripts will work. |
162
|
|
|
* |
163
|
|
|
* @param $collection |
164
|
|
|
* @param $file |
165
|
|
|
* @param array $filters |
166
|
|
|
* @return $this |
167
|
|
|
* @throws \Exception |
168
|
|
|
*/ |
169
|
|
|
public function add($collection, $file, array $filters = []) |
170
|
|
|
{ |
171
|
|
|
if (!isset($this->collections[$collection])) { |
172
|
|
|
$this->collections[$collection] = []; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
$filters = $this->addConvenientFilters($file, $filters); |
176
|
|
|
|
177
|
|
|
$file = $this->paths->realPath($file); |
178
|
|
|
|
179
|
|
|
/* |
180
|
|
|
* If this is a remote or single existing |
181
|
|
|
* file then add it normally. |
182
|
|
|
*/ |
183
|
|
|
if (starts_with($file, ['http', '//']) || file_exists($file)) { |
184
|
|
|
$this->collections[$collection][$file] = $filters; |
185
|
|
|
|
186
|
|
|
return $this; |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
/* |
190
|
|
|
* If this is a valid glob pattern then add |
191
|
|
|
* it to the collection and add the glob filter. |
192
|
|
|
*/ |
193
|
|
|
if (count(glob($file)) > 0) { |
194
|
|
|
$this->collections[$collection][$file] = array_merge($filters, ['glob']); |
195
|
|
|
|
196
|
|
|
return $this; |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
if ($this->config->get('app.debug')) { |
|
|
|
|
200
|
|
|
throw new \Exception("Asset [{$file}] does not exist!"); |
201
|
|
|
} |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
/** |
205
|
|
|
* Download a file and return it's path. |
206
|
|
|
* |
207
|
|
|
* @param $url |
208
|
|
|
* @param int $ttl |
209
|
|
|
* @param null $path |
210
|
|
|
* @return null|string |
211
|
|
|
*/ |
212
|
|
|
public function download($url, $ttl = 3600, $path = null) |
213
|
|
|
{ |
214
|
|
|
$path = $this->paths->downloadPath($url, $path); |
215
|
|
|
|
216
|
|
|
if (!$this->files->isDirectory($directory = dirname($path = public_path(ltrim($path, '/\\'))))) { |
217
|
|
|
$this->files->makeDirectory($directory, 0777, true); |
218
|
|
|
} |
219
|
|
|
|
220
|
|
|
if (!$this->files->exists($path) || filemtime($path) < (time() - $ttl)) { |
221
|
|
|
$this->files->put($path, file_get_contents($url)); |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
return $path; |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
/** |
228
|
|
|
* Return the contents of a collection. |
229
|
|
|
* |
230
|
|
|
* @param $collection |
231
|
|
|
* @param array $filters |
232
|
|
|
* @return string |
233
|
|
|
*/ |
234
|
|
|
public function inline($collection, array $filters = []) |
235
|
|
|
{ |
236
|
|
|
return file_get_contents( |
237
|
|
|
$this->paths->realPath('public::' . ltrim($this->path($collection, $filters), '/\\')) |
238
|
|
|
); |
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
/** |
242
|
|
|
* Return the URL to a compiled asset collection. |
243
|
|
|
* |
244
|
|
|
* @param $collection |
245
|
|
|
* @param array $filters |
246
|
|
|
* @return string |
247
|
|
|
*/ |
248
|
|
|
public function url($collection, array $filters = [], array $parameters = [], $secure = null) |
249
|
|
|
{ |
250
|
|
|
if (!isset($this->collections[$collection])) { |
251
|
|
|
$this->add($collection, $collection, $filters); |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
if (!$path = $this->getPath($collection, $filters)) { |
255
|
|
|
return null; |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
return $this->url->asset($this->getPath($collection, $filters), $parameters, $secure); |
259
|
|
|
} |
260
|
|
|
|
261
|
|
|
/** |
262
|
|
|
* Return the path to a compiled asset collection. |
263
|
|
|
* |
264
|
|
|
* @param $collection |
265
|
|
|
* @param array $filters |
266
|
|
|
* @return string |
267
|
|
|
*/ |
268
|
|
|
public function path($collection, array $filters = []) |
269
|
|
|
{ |
270
|
|
|
if (!isset($this->collections[$collection])) { |
271
|
|
|
$this->add($collection, $collection, $filters); |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
return $this->getPath($collection, $filters); |
275
|
|
|
} |
276
|
|
|
|
277
|
|
|
/** |
278
|
|
|
* Return the asset path to a compiled asset collection. |
279
|
|
|
* |
280
|
|
|
* @param $collection |
281
|
|
|
* @param array $filters |
282
|
|
|
* @return string |
283
|
|
|
*/ |
284
|
|
|
public function asset($collection, array $filters = []) |
285
|
|
|
{ |
286
|
|
|
if (!isset($this->collections[$collection])) { |
287
|
|
|
$this->add($collection, $collection, $filters); |
288
|
|
|
} |
289
|
|
|
|
290
|
|
|
return $this->url->asset($this->getPath($collection, $filters)); |
291
|
|
|
} |
292
|
|
|
|
293
|
|
|
/** |
294
|
|
|
* Return the script tag for a collection. |
295
|
|
|
* |
296
|
|
|
* @param $collection |
297
|
|
|
* @param array $filters |
298
|
|
|
* @param array $attributes |
299
|
|
|
* @return string |
300
|
|
|
*/ |
301
|
|
|
public function script($collection, array $filters = [], array $attributes = []) |
302
|
|
|
{ |
303
|
|
|
$attributes['src'] = $this->asset($collection, $filters); |
304
|
|
|
|
305
|
|
|
return '<script' . $this->html->attributes($attributes) . '></script>'; |
306
|
|
|
} |
307
|
|
|
|
308
|
|
|
/** |
309
|
|
|
* Return the style tag for a collection. |
310
|
|
|
* |
311
|
|
|
* @param $collection |
312
|
|
|
* @param array $filters |
313
|
|
|
* @param array $attributes |
314
|
|
|
* @return string |
315
|
|
|
*/ |
316
|
|
View Code Duplication |
public function style($collection, array $filters = [], array $attributes = []) |
|
|
|
|
317
|
|
|
{ |
318
|
|
|
$defaults = ['media' => 'all', 'type' => 'text/css', 'rel' => 'stylesheet']; |
319
|
|
|
|
320
|
|
|
$attributes = $attributes + $defaults; |
321
|
|
|
|
322
|
|
|
$attributes['href'] = $this->asset($collection, $filters); |
323
|
|
|
|
324
|
|
|
return '<link' . $this->html->attributes($attributes) . '>'; |
325
|
|
|
} |
326
|
|
|
|
327
|
|
|
/** |
328
|
|
|
* Return an array of script tags. |
329
|
|
|
* |
330
|
|
|
* @param $collection |
331
|
|
|
* @param array $filters |
332
|
|
|
* @param array $attributes |
333
|
|
|
* @return array |
334
|
|
|
*/ |
335
|
|
|
public function scripts($collection, array $filters = [], array $attributes = []) |
336
|
|
|
{ |
337
|
|
|
return array_map( |
338
|
|
|
function ($path) use ($attributes) { |
339
|
|
|
$attributes['src'] = $path; |
340
|
|
|
|
341
|
|
|
return '<script' . $this->html->attributes($attributes) . '></script>'; |
342
|
|
|
}, |
343
|
|
|
$this->paths($collection, $filters) |
344
|
|
|
); |
345
|
|
|
} |
346
|
|
|
|
347
|
|
|
/** |
348
|
|
|
* Return an array of style tags. |
349
|
|
|
* |
350
|
|
|
* @param $collection |
351
|
|
|
* @param array $filters |
352
|
|
|
* @param array $attributes |
353
|
|
|
* @return array |
354
|
|
|
*/ |
355
|
|
View Code Duplication |
public function styles($collection, array $filters = [], array $attributes = []) |
|
|
|
|
356
|
|
|
{ |
357
|
|
|
return array_map( |
358
|
|
|
function ($path) use ($attributes) { |
359
|
|
|
$defaults = ['media' => 'all', 'type' => 'text/css', 'rel' => 'stylesheet']; |
360
|
|
|
|
361
|
|
|
$attributes = $attributes + $defaults; |
|
|
|
|
362
|
|
|
|
363
|
|
|
$attributes['href'] = $path; |
364
|
|
|
|
365
|
|
|
return '<link' . $this->html->attributes($attributes) . '>'; |
366
|
|
|
}, |
367
|
|
|
$this->paths($collection, $filters) |
368
|
|
|
); |
369
|
|
|
} |
370
|
|
|
|
371
|
|
|
/** |
372
|
|
|
* Return an array of paths to an asset collection. |
373
|
|
|
* |
374
|
|
|
* This instead of combining the collection contents |
375
|
|
|
* just returns an array of individual processed |
376
|
|
|
* paths instead. |
377
|
|
|
* |
378
|
|
|
* @param $collection |
379
|
|
|
* @param array $additionalFilters |
380
|
|
|
* @return array |
381
|
|
|
*/ |
382
|
|
|
public function paths($collection, array $additionalFilters = []) |
383
|
|
|
{ |
384
|
|
|
if (!isset($this->collections[$collection])) { |
385
|
|
|
return []; |
386
|
|
|
} |
387
|
|
|
|
388
|
|
|
return array_filter( |
389
|
|
|
array_map( |
390
|
|
|
function ($file, $filters) use ($additionalFilters) { |
391
|
|
|
$filters = array_filter(array_unique(array_merge($filters, $additionalFilters))); |
392
|
|
|
|
393
|
|
|
return $this->asset($file, $filters); |
394
|
|
|
}, |
395
|
|
|
array_keys($this->collections[$collection]), |
396
|
|
|
array_values($this->collections[$collection]) |
397
|
|
|
) |
398
|
|
|
); |
399
|
|
|
} |
400
|
|
|
|
401
|
|
|
/** |
402
|
|
|
* Return an array of style URLs. |
403
|
|
|
* |
404
|
|
|
* @param $collection |
405
|
|
|
* @param array $filters |
406
|
|
|
* @param array $attributes |
407
|
|
|
* @param null $secure |
408
|
|
|
* @return array |
409
|
|
|
*/ |
410
|
|
|
public function urls($collection, array $filters = [], array $attributes = [], $secure = null) |
411
|
|
|
{ |
412
|
|
|
return array_map( |
413
|
|
|
function ($path) use ($attributes, $secure) { |
414
|
|
|
return $this->url($path, [], $attributes, $secure); |
415
|
|
|
}, |
416
|
|
|
$this->paths($collection, $filters) |
417
|
|
|
); |
418
|
|
|
} |
419
|
|
|
|
420
|
|
|
/** |
421
|
|
|
* @param $collection |
422
|
|
|
* @param $filters |
423
|
|
|
* @return string |
424
|
|
|
*/ |
425
|
|
|
protected function getPath($collection, $filters) |
426
|
|
|
{ |
427
|
|
|
/* |
428
|
|
|
* If the asset is remote just return it. |
429
|
|
|
*/ |
430
|
|
|
if (starts_with($collection, ['http', '//'])) { |
431
|
|
|
return $collection; |
432
|
|
|
} |
433
|
|
|
|
434
|
|
|
$path = $this->paths->outputPath($collection); |
435
|
|
|
|
436
|
|
|
if ($this->shouldPublish($path, $collection, $filters)) { |
437
|
|
|
$this->publish($path, $collection, $filters); |
438
|
|
|
} |
439
|
|
|
|
440
|
|
|
if ( |
441
|
|
|
!in_array('noversion', $filters) && |
442
|
|
|
($this->config->get('streams::assets.version') || in_array('version', $filters)) |
|
|
|
|
443
|
|
|
) { |
444
|
|
|
$path .= '?v=' . filemtime(public_path(trim($path, '/\\'))); |
445
|
|
|
} |
446
|
|
|
|
447
|
|
|
return $path; |
448
|
|
|
} |
449
|
|
|
|
450
|
|
|
/** |
451
|
|
|
* Return the collection path. This |
452
|
|
|
* is primarily used to determine paths |
453
|
|
|
* to single assets. |
454
|
|
|
* |
455
|
|
|
* @param $collection |
456
|
|
|
* @return string |
457
|
|
|
*/ |
458
|
|
|
public function getCollectionPath($collection) |
459
|
|
|
{ |
460
|
|
|
return ($this->request->segment(1) == 'admin' ? 'admin' : 'public') . '/' . ltrim( |
461
|
|
|
str_replace(base_path(), '', $this->paths->realPath($collection)), |
462
|
|
|
'/\\' |
463
|
|
|
); |
464
|
|
|
} |
465
|
|
|
|
466
|
|
|
/** |
467
|
|
|
* Publish the collection of assets to the path. |
468
|
|
|
* |
469
|
|
|
* @param $path |
470
|
|
|
* @param $collection |
471
|
|
|
* @param $additionalFilters |
472
|
|
|
*/ |
473
|
|
|
protected function publish($path, $collection, $additionalFilters) |
474
|
|
|
{ |
475
|
|
|
$path = ltrim($path, '/\\'); |
476
|
|
|
|
477
|
|
|
if (str_contains($collection, public_path())) { |
478
|
|
|
return; |
479
|
|
|
} |
480
|
|
|
|
481
|
|
|
$assets = $this->getAssetCollection($collection, $additionalFilters); |
482
|
|
|
|
483
|
|
|
$path = $this->directory . $path; |
484
|
|
|
|
485
|
|
|
$this->files->makeDirectory((new \SplFileInfo($path))->getPath(), 0777, true, true); |
486
|
|
|
|
487
|
|
|
$this->files->put($path, $assets->dump()); |
488
|
|
|
|
489
|
|
|
if ($this->paths->extension($path) == 'css') { |
490
|
|
|
try { |
491
|
|
|
$this->files->put($path, app('twig')->render(str_replace($this->directory, 'assets::', $path))); |
492
|
|
|
} catch (\Exception $e) { |
493
|
|
|
// Don't even.. |
494
|
|
|
} |
495
|
|
|
} |
496
|
|
|
} |
497
|
|
|
|
498
|
|
|
/** |
499
|
|
|
* Transform an array of filters to |
500
|
|
|
* an array of Assetic filters. |
501
|
|
|
* |
502
|
|
|
* @param $filters |
503
|
|
|
* @param $hint |
504
|
|
|
* @return mixed |
505
|
|
|
*/ |
506
|
|
|
protected function transformFilters($filters, $hint) |
507
|
|
|
{ |
508
|
|
|
foreach ($filters as $k => &$filter) { |
509
|
|
|
|
510
|
|
|
/* |
511
|
|
|
* Parse Twg tags in the asset content. |
512
|
|
|
*/ |
513
|
|
|
if ($filter == 'parse') { |
514
|
|
|
$filter = new ParseFilter($this->parser); |
515
|
|
|
|
516
|
|
|
continue; |
517
|
|
|
} |
518
|
|
|
|
519
|
|
|
/* |
520
|
|
|
* Compile LESS to CSS with PHP. |
521
|
|
|
*/ |
522
|
|
View Code Duplication |
if ($filter == 'less' && $this->config->get('streams::assets.filters.less', 'php') == 'php') { |
|
|
|
|
523
|
|
|
$filter = new LessFilter($this->parser); |
524
|
|
|
|
525
|
|
|
continue; |
526
|
|
|
} |
527
|
|
|
|
528
|
|
|
/* |
529
|
|
|
* Compile LESS to CSS with Node. |
530
|
|
|
*/ |
531
|
|
View Code Duplication |
if ($filter == 'less' && $this->config->get('streams::assets.filters.less', 'php') == 'node') { |
|
|
|
|
532
|
|
|
$filter = new NodeLessFilter($this->parser); |
533
|
|
|
|
534
|
|
|
continue; |
535
|
|
|
} |
536
|
|
|
|
537
|
|
|
/* |
538
|
|
|
* Compile Stylus to CSS. |
539
|
|
|
*/ |
540
|
|
|
if ($filter == 'styl') { |
541
|
|
|
$filter = new StylusFilter($this->parser); |
542
|
|
|
|
543
|
|
|
continue; |
544
|
|
|
} |
545
|
|
|
|
546
|
|
|
/* |
547
|
|
|
* Compile SCSS to CSS with PHP. |
548
|
|
|
*/ |
549
|
|
View Code Duplication |
if ($filter == 'scss' && $this->config->get('streams::assets.filters.sass', 'php') == 'php') { |
|
|
|
|
550
|
|
|
$filter = new ScssFilter($this->parser); |
551
|
|
|
|
552
|
|
|
continue; |
553
|
|
|
} |
554
|
|
|
|
555
|
|
|
/* |
556
|
|
|
* Compile SCSS to CSS with Ruby. |
557
|
|
|
*/ |
558
|
|
View Code Duplication |
if ($filter == 'scss' && $this->config->get('streams::assets.filters.sass', 'php') == 'ruby') { |
|
|
|
|
559
|
|
|
$filter = new RubyScssFilter($this->parser); |
560
|
|
|
|
561
|
|
|
continue; |
562
|
|
|
} |
563
|
|
|
|
564
|
|
|
/* |
565
|
|
|
* Compile SASS to CSS with PHP. |
566
|
|
|
*/ |
567
|
|
View Code Duplication |
if ($filter == 'sass' && $this->config->get('streams::assets.filters.sass', 'php') == 'php') { |
|
|
|
|
568
|
|
|
$filter = new SassFilter($this->parser); |
569
|
|
|
|
570
|
|
|
continue; |
571
|
|
|
} |
572
|
|
|
|
573
|
|
|
/* |
574
|
|
|
* Compile SASS to CSS with Ruby. |
575
|
|
|
*/ |
576
|
|
View Code Duplication |
if ($filter == 'sass' && $this->config->get('streams::assets.filters.sass', 'php') == 'ruby') { |
|
|
|
|
577
|
|
|
$filter = new RubySassFilter($this->parser); |
578
|
|
|
|
579
|
|
|
continue; |
580
|
|
|
} |
581
|
|
|
|
582
|
|
|
/* |
583
|
|
|
* Compile CoffeeScript to JS |
584
|
|
|
*/ |
585
|
|
|
if ($filter == 'coffee') { |
586
|
|
|
$filter = new CoffeeFilter($this->parser); |
587
|
|
|
|
588
|
|
|
continue; |
589
|
|
|
} |
590
|
|
|
|
591
|
|
|
/* |
592
|
|
|
* Look for and embed CSS images. |
593
|
|
|
*/ |
594
|
|
|
if ($filter == 'embed') { |
595
|
|
|
$filter = new PhpCssEmbedFilter(); |
596
|
|
|
|
597
|
|
|
continue; |
598
|
|
|
} |
599
|
|
|
|
600
|
|
|
/* |
601
|
|
|
* Minify JS |
602
|
|
|
*/ |
603
|
|
|
if ($filter == 'min' && $hint == 'js') { |
604
|
|
|
$filter = new JsMinFilter(); |
605
|
|
|
|
606
|
|
|
continue; |
607
|
|
|
} |
608
|
|
|
|
609
|
|
|
/* |
610
|
|
|
* Minify CSS |
611
|
|
|
*/ |
612
|
|
|
if ($filter == 'min' && $hint == 'css') { |
613
|
|
|
$filter = new CssMinFilter(); |
614
|
|
|
|
615
|
|
|
continue; |
616
|
|
|
} |
617
|
|
|
|
618
|
|
|
/* |
619
|
|
|
* Glob is a flag that's used later. |
620
|
|
|
*/ |
621
|
|
|
if ($filter == 'glob') { |
622
|
|
|
continue; |
623
|
|
|
} |
624
|
|
|
|
625
|
|
|
/* |
626
|
|
|
* No filter class could be determined! |
627
|
|
|
*/ |
628
|
|
|
$filter = null; |
629
|
|
|
} |
630
|
|
|
|
631
|
|
|
/* |
632
|
|
|
* Be sure to separate JS concatenations. |
633
|
|
|
*/ |
634
|
|
|
if ($hint == 'js') { |
635
|
|
|
$filters[] = new SeparatorFilter(); |
636
|
|
|
} |
637
|
|
|
|
638
|
|
|
return array_filter($filters); |
639
|
|
|
} |
640
|
|
|
|
641
|
|
|
/** |
642
|
|
|
* Add filters that we can assume based |
643
|
|
|
* on the asset's file name. |
644
|
|
|
* |
645
|
|
|
* @param $file |
646
|
|
|
* @param $filters |
647
|
|
|
* @return array |
648
|
|
|
*/ |
649
|
|
|
protected function addConvenientFilters($file, $filters) |
650
|
|
|
{ |
651
|
|
|
if (ends_with($file, '.less')) { |
652
|
|
|
$filters[] = 'less'; |
653
|
|
|
} |
654
|
|
|
|
655
|
|
|
if (ends_with($file, '.styl')) { |
656
|
|
|
$filters[] = 'styl'; |
657
|
|
|
} |
658
|
|
|
|
659
|
|
|
if (ends_with($file, '.scss')) { |
660
|
|
|
$filters[] = 'scss'; |
661
|
|
|
} |
662
|
|
|
|
663
|
|
|
if (ends_with($file, '.coffee')) { |
664
|
|
|
$filters[] = 'coffee'; |
665
|
|
|
} |
666
|
|
|
|
667
|
|
|
return array_unique($filters); |
668
|
|
|
} |
669
|
|
|
|
670
|
|
|
/** |
671
|
|
|
* Decide whether we need to publish the file |
672
|
|
|
* to the path or not. |
673
|
|
|
* |
674
|
|
|
* @param $path |
675
|
|
|
* @param $collection |
676
|
|
|
* @param array $filters |
677
|
|
|
* @return bool |
678
|
|
|
*/ |
679
|
|
|
protected function shouldPublish($path, $collection, array $filters = []) |
680
|
|
|
{ |
681
|
|
|
$path = ltrim($path, '/\\'); |
682
|
|
|
|
683
|
|
|
if (starts_with($path, 'http')) { |
684
|
|
|
return false; |
685
|
|
|
} |
686
|
|
|
|
687
|
|
|
if (!$this->files->exists($path)) { |
688
|
|
|
return true; |
689
|
|
|
} |
690
|
|
|
|
691
|
|
|
if (in_array('force', $this->collectionFilters($collection, $filters))) { |
692
|
|
|
return true; |
693
|
|
|
} |
694
|
|
|
|
695
|
|
|
$debug = $this->config->get('streams::assets.live', false); |
|
|
|
|
696
|
|
|
|
697
|
|
|
$live = in_array('live', $this->collectionFilters($collection, $filters)); |
698
|
|
|
|
699
|
|
|
if ($debug === true && $live) { |
700
|
|
|
return true; |
701
|
|
|
} |
702
|
|
|
|
703
|
|
View Code Duplication |
if ($debug == 'public' && $live && $this->request->segment(1) !== 'admin') { |
|
|
|
|
704
|
|
|
return true; |
705
|
|
|
} |
706
|
|
|
|
707
|
|
View Code Duplication |
if ($debug == 'admin' && $live && $this->request->segment(1) === 'admin') { |
|
|
|
|
708
|
|
|
return true; |
709
|
|
|
} |
710
|
|
|
|
711
|
|
|
// Merge filters from collection files. |
712
|
|
|
foreach ($this->collections[$collection] as $fileFilters) { |
713
|
|
|
$filters = array_filter(array_unique(array_merge($filters, $fileFilters))); |
714
|
|
|
} |
715
|
|
|
|
716
|
|
|
$assets = $this->getAssetCollection($collection); |
717
|
|
|
|
718
|
|
|
// If any of the files are more recent than the cache file, publish, otherwise skip |
719
|
|
|
if ($assets->getLastModified() < filemtime($path)) { |
720
|
|
|
return false; |
721
|
|
|
} |
722
|
|
|
|
723
|
|
|
return true; |
724
|
|
|
} |
725
|
|
|
|
726
|
|
|
/** |
727
|
|
|
* Add a namespace path hint. |
728
|
|
|
* |
729
|
|
|
* @param $namespace |
730
|
|
|
* @param $path |
731
|
|
|
* @return $this |
732
|
|
|
*/ |
733
|
|
|
public function addPath($namespace, $path) |
734
|
|
|
{ |
735
|
|
|
$this->paths->addPath($namespace, $path); |
736
|
|
|
|
737
|
|
|
return $this; |
738
|
|
|
} |
739
|
|
|
|
740
|
|
|
/** |
741
|
|
|
* Set the public base directory. |
742
|
|
|
* |
743
|
|
|
* @param $directory |
744
|
|
|
* @return $this |
745
|
|
|
*/ |
746
|
|
|
public function setDirectory($directory) |
747
|
|
|
{ |
748
|
|
|
$this->directory = $directory; |
749
|
|
|
|
750
|
|
|
return $this; |
751
|
|
|
} |
752
|
|
|
|
753
|
|
|
/** |
754
|
|
|
* Create asset collection from collection array |
755
|
|
|
* |
756
|
|
|
* @param $collection |
757
|
|
|
* @param array $additionalFilters |
758
|
|
|
* @return AssetCollection |
759
|
|
|
*/ |
760
|
|
|
private function getAssetCollection($collection, $additionalFilters = []) |
761
|
|
|
{ |
762
|
|
|
$assets = new AssetCollection(); |
763
|
|
|
|
764
|
|
|
$hint = $this->paths->hint($collection); |
765
|
|
|
|
766
|
|
|
foreach ($this->collections[$collection] as $file => $filters) { |
767
|
|
|
$filters = array_filter(array_unique(array_merge($filters, $additionalFilters))); |
768
|
|
|
|
769
|
|
|
$filters = $this->transformFilters($filters, $hint); |
770
|
|
|
|
771
|
|
|
if (in_array('glob', $filters)) { |
772
|
|
|
unset($filters[array_search('glob', $filters)]); |
773
|
|
|
|
774
|
|
|
$file = new GlobAsset($file, $filters); |
775
|
|
|
} else { |
776
|
|
|
$file = new FileAsset($file, $filters); |
777
|
|
|
} |
778
|
|
|
|
779
|
|
|
$assets->add($file); |
780
|
|
|
} |
781
|
|
|
|
782
|
|
|
return $assets; |
783
|
|
|
} |
784
|
|
|
|
785
|
|
|
/** |
786
|
|
|
* Return the filters used in a collection. |
787
|
|
|
* |
788
|
|
|
* @param $collection |
789
|
|
|
* @param array $filters |
790
|
|
|
* @return array |
791
|
|
|
*/ |
792
|
|
|
protected function collectionFilters($collection, array $filters = []) |
793
|
|
|
{ |
794
|
|
|
return array_unique( |
795
|
|
|
array_merge($filters, call_user_func_array('array_merge', array_get($this->collections, $collection, []))) |
796
|
|
|
); |
797
|
|
|
} |
798
|
|
|
|
799
|
|
|
/** |
800
|
|
|
* Return nothing. |
801
|
|
|
* |
802
|
|
|
* @return string |
803
|
|
|
*/ |
804
|
|
|
public function __toString() |
805
|
|
|
{ |
806
|
|
|
return ''; |
807
|
|
|
} |
808
|
|
|
} |
809
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.