1
|
|
|
<?php namespace Anomaly\Streams\Platform\Image; |
2
|
|
|
|
3
|
|
|
use Anomaly\FilesModule\File\Contract\FileInterface; |
4
|
|
|
use Anomaly\FilesModule\File\FilePresenter; |
5
|
|
|
use Anomaly\Streams\Platform\Addon\FieldType\FieldType; |
6
|
|
|
use Anomaly\Streams\Platform\Application\Application; |
7
|
|
|
use Anomaly\Streams\Platform\Routing\UrlGenerator; |
8
|
|
|
use Closure; |
9
|
|
|
use Collective\Html\HtmlBuilder; |
10
|
|
|
use Illuminate\Contracts\Config\Repository; |
11
|
|
|
use Illuminate\Filesystem\Filesystem; |
12
|
|
|
use Intervention\Image\Constraint; |
13
|
|
|
use Intervention\Image\ImageManager; |
14
|
|
|
use League\Flysystem\File; |
15
|
|
|
use League\Flysystem\MountManager; |
16
|
|
|
use Mobile_Detect; |
17
|
|
|
use Robbo\Presenter\Presenter; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* Class Image |
21
|
|
|
* |
22
|
|
|
* @link http://pyrocms.com/ |
23
|
|
|
* @author PyroCMS, Inc. <[email protected]> |
24
|
|
|
* @author Ryan Thompson <[email protected]> |
25
|
|
|
*/ |
26
|
|
|
class Image |
27
|
|
|
{ |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* The publish flag. |
31
|
|
|
* |
32
|
|
|
* @var bool |
33
|
|
|
*/ |
34
|
|
|
protected $publish = false; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* The publishable base directory. |
38
|
|
|
* |
39
|
|
|
* @var null |
40
|
|
|
*/ |
41
|
|
|
protected $directory = null; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* The image object. |
45
|
|
|
* |
46
|
|
|
* @var null|string |
47
|
|
|
*/ |
48
|
|
|
protected $image = null; |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* The file extension. |
52
|
|
|
* |
53
|
|
|
* @var null|string |
54
|
|
|
*/ |
55
|
|
|
protected $extension = null; |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* The desired filename. |
59
|
|
|
* |
60
|
|
|
* @var null|string |
61
|
|
|
*/ |
62
|
|
|
protected $filename = null; |
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* The default output method. |
66
|
|
|
* |
67
|
|
|
* @var string |
68
|
|
|
*/ |
69
|
|
|
protected $output = 'url'; |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* The image attributes. |
73
|
|
|
* |
74
|
|
|
* @var array |
75
|
|
|
*/ |
76
|
|
|
protected $attributes = []; |
77
|
|
|
|
78
|
|
|
/** |
79
|
|
|
* Applied alterations. |
80
|
|
|
* |
81
|
|
|
* @var array |
82
|
|
|
*/ |
83
|
|
|
protected $alterations = []; |
84
|
|
|
|
85
|
|
|
/** |
86
|
|
|
* Image srcsets. |
87
|
|
|
* |
88
|
|
|
* @var array |
89
|
|
|
*/ |
90
|
|
|
protected $srcsets = []; |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* Image sources. |
94
|
|
|
* |
95
|
|
|
* @var array |
96
|
|
|
*/ |
97
|
|
|
protected $sources = []; |
98
|
|
|
|
99
|
|
|
/** |
100
|
|
|
* Allowed methods. |
101
|
|
|
* |
102
|
|
|
* @var array |
103
|
|
|
*/ |
104
|
|
|
protected $allowedMethods = [ |
105
|
|
|
'blur', |
106
|
|
|
'brightness', |
107
|
|
|
'colorize', |
108
|
|
|
'contrast', |
109
|
|
|
'crop', |
110
|
|
|
'encode', |
111
|
|
|
'fit', |
112
|
|
|
'flip', |
113
|
|
|
'gamma', |
114
|
|
|
'greyscale', |
115
|
|
|
'heighten', |
116
|
|
|
'insert', |
117
|
|
|
'invert', |
118
|
|
|
'limitColors', |
119
|
|
|
'pixelate', |
120
|
|
|
'opacity', |
121
|
|
|
'resize', |
122
|
|
|
'rotate', |
123
|
|
|
'amount', |
124
|
|
|
'widen', |
125
|
|
|
'orientate', |
126
|
|
|
]; |
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* The quality of the output. |
130
|
|
|
* |
131
|
|
|
* @var null|int |
132
|
|
|
*/ |
133
|
|
|
protected $quality = null; |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* The image width. |
137
|
|
|
* |
138
|
|
|
* @var null|int |
139
|
|
|
*/ |
140
|
|
|
protected $width = null; |
141
|
|
|
|
142
|
|
|
/** |
143
|
|
|
* The image height. |
144
|
|
|
* |
145
|
|
|
* @var null|int |
146
|
|
|
*/ |
147
|
|
|
protected $height = null; |
148
|
|
|
|
149
|
|
|
/** |
150
|
|
|
* The URL generator. |
151
|
|
|
* |
152
|
|
|
* @var UrlGenerator |
153
|
|
|
*/ |
154
|
|
|
protected $url; |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* The HTML builder. |
158
|
|
|
* |
159
|
|
|
* @var HtmlBuilder |
160
|
|
|
*/ |
161
|
|
|
protected $html; |
162
|
|
|
|
163
|
|
|
/** |
164
|
|
|
* Image path hints by namespace. |
165
|
|
|
* |
166
|
|
|
* @var ImagePaths |
167
|
|
|
*/ |
168
|
|
|
protected $paths; |
169
|
|
|
|
170
|
|
|
/** |
171
|
|
|
* The image macros. |
172
|
|
|
* |
173
|
|
|
* @var ImageMacros |
174
|
|
|
*/ |
175
|
|
|
protected $macros; |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* The file system. |
179
|
|
|
* |
180
|
|
|
* @var Filesystem |
181
|
|
|
*/ |
182
|
|
|
protected $files; |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* The user agent utility. |
186
|
|
|
* |
187
|
|
|
* @var Mobile_Detect |
188
|
|
|
*/ |
189
|
|
|
protected $agent; |
190
|
|
|
|
191
|
|
|
/** |
192
|
|
|
* The config repository. |
193
|
|
|
* |
194
|
|
|
* @var Repository |
195
|
|
|
*/ |
196
|
|
|
protected $config; |
197
|
|
|
|
198
|
|
|
/** |
199
|
|
|
* The image manager. |
200
|
|
|
* |
201
|
|
|
* @var ImageManager |
202
|
|
|
*/ |
203
|
|
|
protected $manager; |
204
|
|
|
|
205
|
|
|
/** |
206
|
|
|
* The stream application. |
207
|
|
|
* |
208
|
|
|
* @var Application |
209
|
|
|
*/ |
210
|
|
|
protected $application; |
211
|
|
|
|
212
|
|
|
/** |
213
|
|
|
* Create a new Image instance. |
214
|
|
|
* |
215
|
|
|
* @param UrlGenerator $url |
216
|
|
|
* @param HtmlBuilder $html |
217
|
|
|
* @param Filesystem $files |
218
|
|
|
* @param Mobile_Detect $agent |
219
|
|
|
* @param Repository $config |
220
|
|
|
* @param ImageManager $manager |
221
|
|
|
* @param Application $application |
222
|
|
|
* @param ImagePaths $paths |
223
|
|
|
* @param ImageMacros $macros |
224
|
|
|
*/ |
225
|
|
|
public function __construct( |
226
|
|
|
UrlGenerator $url, |
227
|
|
|
HtmlBuilder $html, |
228
|
|
|
Filesystem $files, |
229
|
|
|
Mobile_Detect $agent, |
230
|
|
|
Repository $config, |
231
|
|
|
ImageManager $manager, |
232
|
|
|
Application $application, |
233
|
|
|
ImagePaths $paths, |
234
|
|
|
ImageMacros $macros |
235
|
|
|
) { |
236
|
|
|
$this->url = $url; |
237
|
|
|
$this->html = $html; |
238
|
|
|
$this->files = $files; |
239
|
|
|
$this->agent = $agent; |
240
|
|
|
$this->paths = $paths; |
241
|
|
|
$this->config = $config; |
242
|
|
|
$this->macros = $macros; |
243
|
|
|
$this->manager = $manager; |
244
|
|
|
$this->application = $application; |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
/** |
248
|
|
|
* Make a new image instance. |
249
|
|
|
* |
250
|
|
|
* @param mixed $image |
251
|
|
|
* @param null $output |
252
|
|
|
* @return $this |
253
|
|
|
*/ |
254
|
|
|
public function make($image, $output = null) |
255
|
|
|
{ |
256
|
|
|
if ($image instanceof Image) { |
257
|
|
|
return $image; |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
if ($output) { |
261
|
|
|
$this->setOutput($output); |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
$clone = clone($this); |
265
|
|
|
|
266
|
|
|
$clone->setAlterations([]); |
267
|
|
|
$clone->setSources([]); |
268
|
|
|
$clone->setSrcsets([]); |
269
|
|
|
$clone->setImage(null); |
270
|
|
|
|
271
|
|
|
try { |
272
|
|
|
return $clone->setImage($image); |
273
|
|
|
} catch (\Exception $e) { |
274
|
|
|
return $this; |
275
|
|
|
} |
276
|
|
|
} |
277
|
|
|
|
278
|
|
|
/** |
279
|
|
|
* Return the path to an image. |
280
|
|
|
* |
281
|
|
|
* @return string |
282
|
|
|
*/ |
283
|
|
|
public function path() |
284
|
|
|
{ |
285
|
|
|
$path = $this->getCachePath(); |
286
|
|
|
|
287
|
|
|
return $path; |
288
|
|
|
} |
289
|
|
|
|
290
|
|
|
/** |
291
|
|
|
* Return the asset path to an image. |
292
|
|
|
* |
293
|
|
|
* @return string |
294
|
|
|
*/ |
295
|
|
|
public function asset() |
296
|
|
|
{ |
297
|
|
|
$path = $this->getCachePath(); |
298
|
|
|
|
299
|
|
|
return $this->url->asset($path); |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
/** |
303
|
|
|
* Run a macro on the image. |
304
|
|
|
* |
305
|
|
|
* @param $macro |
306
|
|
|
* @return Image |
307
|
|
|
* @throws \Exception |
308
|
|
|
*/ |
309
|
|
|
public function macro($macro) |
310
|
|
|
{ |
311
|
|
|
return $this->macros->run($macro, $this); |
312
|
|
|
} |
313
|
|
|
|
314
|
|
|
/** |
315
|
|
|
* Return the URL to an image. |
316
|
|
|
* |
317
|
|
|
* @param array $parameters |
318
|
|
|
* @param null $secure |
319
|
|
|
* @return string |
320
|
|
|
*/ |
321
|
|
|
public function url(array $parameters = [], $secure = null) |
322
|
|
|
{ |
323
|
|
|
return $this->url->asset($this->path(), $parameters, $secure); |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
/** |
327
|
|
|
* Return the image tag to an image. |
328
|
|
|
* |
329
|
|
|
* @param null $alt |
330
|
|
|
* @param array $attributes |
331
|
|
|
* @return string |
332
|
|
|
*/ |
333
|
|
|
public function image($alt = null, array $attributes = []) |
334
|
|
|
{ |
335
|
|
|
if (!$alt) { |
336
|
|
|
$alt = array_get($this->getAttributes(), 'alt'); |
337
|
|
|
} |
338
|
|
|
|
339
|
|
|
$attributes = array_merge($this->getAttributes(), $attributes); |
340
|
|
|
|
341
|
|
|
if ($srcset = $this->srcset()) { |
342
|
|
|
$attributes['srcset'] = $srcset; |
343
|
|
|
} |
344
|
|
|
|
345
|
|
|
$attributes['alt'] = $alt; |
346
|
|
|
|
347
|
|
|
return '<img src="' . $this->asset() . '"' . $this->html->attributes($attributes) . '>'; |
348
|
|
|
} |
349
|
|
|
|
350
|
|
|
/** |
351
|
|
|
* Return the image tag to an image. |
352
|
|
|
* |
353
|
|
|
* @param null $alt |
354
|
|
|
* @param array $attributes |
355
|
|
|
* @return string |
356
|
|
|
*/ |
357
|
|
|
public function img($alt = null, array $attributes = []) |
358
|
|
|
{ |
359
|
|
|
return $this->image($alt, $attributes); |
360
|
|
|
} |
361
|
|
|
|
362
|
|
|
/** |
363
|
|
|
* Return a picture tag. |
364
|
|
|
* |
365
|
|
|
* @return string |
366
|
|
|
*/ |
367
|
|
|
public function picture(array $attributes = []) |
368
|
|
|
{ |
369
|
|
|
$sources = []; |
370
|
|
|
|
371
|
|
|
$attributes = array_merge($this->getAttributes(), $attributes); |
372
|
|
|
|
373
|
|
|
/* @var Image $image */ |
374
|
|
|
foreach ($this->getSources() as $media => $image) { |
375
|
|
|
if ($media != 'fallback') { |
376
|
|
|
$sources[] = $image->source(); |
377
|
|
|
} else { |
378
|
|
|
$sources[] = $image->image(); |
379
|
|
|
} |
380
|
|
|
} |
381
|
|
|
|
382
|
|
|
$sources = implode("\n", $sources); |
383
|
|
|
|
384
|
|
|
$attributes = $this->html->attributes($attributes); |
385
|
|
|
|
386
|
|
|
return "<picture {$attributes}>\n{$sources}\n</picture>"; |
387
|
|
|
} |
388
|
|
|
|
389
|
|
|
/** |
390
|
|
|
* Return a source tag. |
391
|
|
|
* |
392
|
|
|
* @return string |
393
|
|
|
*/ |
394
|
|
|
public function source() |
395
|
|
|
{ |
396
|
|
|
$this->addAttribute('srcset', $this->srcset() ?: $this->asset() . ' 2x, ' . $this->asset() . ' 1x'); |
397
|
|
|
|
398
|
|
|
$attributes = $this->html->attributes($this->getAttributes()); |
399
|
|
|
|
400
|
|
|
if ($srcset = $this->srcset()) { |
401
|
|
|
$attributes['srcset'] = $srcset; |
402
|
|
|
} |
403
|
|
|
|
404
|
|
|
return "<source {$attributes}>"; |
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
/** |
408
|
|
|
* Return the image response. |
409
|
|
|
* |
410
|
|
|
* @param null $format |
411
|
|
|
* @param int $quality |
412
|
|
|
* @return String |
413
|
|
|
*/ |
414
|
|
|
public function encode($format = null, $quality = null) |
415
|
|
|
{ |
416
|
|
|
return $this->manager->make($this->getCachePath())->encode($format, $quality ?: $this->getQuality()); |
417
|
|
|
} |
418
|
|
|
|
419
|
|
|
/** |
420
|
|
|
* Return the image contents. |
421
|
|
|
* |
422
|
|
|
* @return string |
423
|
|
|
*/ |
424
|
|
|
public function data() |
425
|
|
|
{ |
426
|
|
|
return $this->dumpImage(); |
427
|
|
|
} |
428
|
|
|
|
429
|
|
|
/** |
430
|
|
|
* Return the output. |
431
|
|
|
* |
432
|
|
|
* @return string |
433
|
|
|
*/ |
434
|
|
|
public function output() |
435
|
|
|
{ |
436
|
|
|
return $this->{$this->output}(); |
437
|
|
|
} |
438
|
|
|
|
439
|
|
|
/** |
440
|
|
|
* Set the filename. |
441
|
|
|
* |
442
|
|
|
* @param $filename |
443
|
|
|
* @return $this |
444
|
|
|
*/ |
445
|
|
|
public function rename($filename = null) |
446
|
|
|
{ |
447
|
|
|
return $this->setFilename($filename); |
448
|
|
|
} |
449
|
|
|
|
450
|
|
|
/** |
451
|
|
|
* Set the quality. |
452
|
|
|
* |
453
|
|
|
* @param $quality |
454
|
|
|
* @return $this |
455
|
|
|
*/ |
456
|
|
|
public function quality($quality) |
457
|
|
|
{ |
458
|
|
|
return $this->setQuality($quality); |
459
|
|
|
} |
460
|
|
|
|
461
|
|
|
/** |
462
|
|
|
* Set the width attribute. |
463
|
|
|
* |
464
|
|
|
* @param null $width |
465
|
|
|
* @return Image |
466
|
|
|
*/ |
467
|
|
|
public function width($width = null) |
468
|
|
|
{ |
469
|
|
|
return $this->addAttribute('width', $width ?: $this->getWidth()); |
470
|
|
|
} |
471
|
|
|
|
472
|
|
|
/** |
473
|
|
|
* Set the height attribute. |
474
|
|
|
* |
475
|
|
|
* @param null $height |
476
|
|
|
* @return Image |
477
|
|
|
*/ |
478
|
|
|
public function height($height = null) |
479
|
|
|
{ |
480
|
|
|
return $this->addAttribute('height', $height ?: $this->getHeight()); |
481
|
|
|
} |
482
|
|
|
|
483
|
|
|
/** |
484
|
|
|
* Set the quality. |
485
|
|
|
* |
486
|
|
|
* @param $quality |
487
|
|
|
* @return $this |
488
|
|
|
*/ |
489
|
|
|
public function setQuality($quality) |
490
|
|
|
{ |
491
|
|
|
$this->quality = (int)$quality; |
492
|
|
|
|
493
|
|
|
return $this; |
494
|
|
|
} |
495
|
|
|
|
496
|
|
|
/** |
497
|
|
|
* Get the cache path of the image. |
498
|
|
|
* |
499
|
|
|
* @return string |
500
|
|
|
*/ |
501
|
|
|
protected function getCachePath() |
502
|
|
|
{ |
503
|
|
|
if (starts_with($this->getImage(), ['http://', 'https://', '//'])) { |
504
|
|
|
return $this->getImage(); |
505
|
|
|
} |
506
|
|
|
|
507
|
|
|
$path = $this->paths->outputPath($this); |
508
|
|
|
|
509
|
|
|
try { |
510
|
|
|
if ($this->shouldPublish($path)) { |
511
|
|
|
$this->publish($path); |
512
|
|
|
} |
513
|
|
|
} catch (\Exception $e) { |
514
|
|
|
return $this->config->get('app.debug', false) ? $e->getMessage() : null; |
515
|
|
|
} |
516
|
|
|
|
517
|
|
|
return $path; |
518
|
|
|
} |
519
|
|
|
|
520
|
|
|
/** |
521
|
|
|
* Determine if the image needs to be published |
522
|
|
|
* |
523
|
|
|
* @param $path |
524
|
|
|
* @return bool |
525
|
|
|
*/ |
526
|
|
|
private function shouldPublish($path) |
527
|
|
|
{ |
528
|
|
|
$path = ltrim($path, '/'); |
529
|
|
|
|
530
|
|
|
if (!$this->files->exists($path)) { |
531
|
|
|
return true; |
532
|
|
|
} |
533
|
|
|
|
534
|
|
View Code Duplication |
if (is_string($this->image) && !str_is('*://*', $this->image) && filemtime($path) < filemtime($this->image)) { |
|
|
|
|
535
|
|
|
return true; |
536
|
|
|
} |
537
|
|
|
|
538
|
|
View Code Duplication |
if (is_string($this->image) && str_is('*://*', $this->image) && filemtime($path) < app( |
|
|
|
|
539
|
|
|
'League\Flysystem\MountManager' |
540
|
|
|
)->getTimestamp($this->image) |
541
|
|
|
) { |
542
|
|
|
return true; |
543
|
|
|
} |
544
|
|
|
|
545
|
|
|
if ($this->image instanceof File && filemtime($path) < $this->image->getTimestamp()) { |
546
|
|
|
return true; |
547
|
|
|
} |
548
|
|
|
|
549
|
|
|
if ($this->image instanceof FileInterface && filemtime($path) < $this->image->lastModified()->format('U')) { |
|
|
|
|
550
|
|
|
return true; |
551
|
|
|
} |
552
|
|
|
|
553
|
|
|
return false; |
554
|
|
|
} |
555
|
|
|
|
556
|
|
|
/** |
557
|
|
|
* Publish an image to the publish directory. |
558
|
|
|
* |
559
|
|
|
* @param $path |
560
|
|
|
*/ |
561
|
|
|
protected function publish($path) |
562
|
|
|
{ |
563
|
|
|
$path = ltrim($path, '/'); |
564
|
|
|
|
565
|
|
|
$this->files->makeDirectory((new \SplFileInfo($path))->getPath(), 0777, true, true); |
566
|
|
|
|
567
|
|
|
if (!$this->supportsType($this->getExtension())) { |
568
|
|
|
|
569
|
|
|
$this->files->put($path, $this->dumpImage()); |
570
|
|
|
|
571
|
|
|
return; |
572
|
|
|
} |
573
|
|
|
|
574
|
|
|
if (!$image = $this->makeImage()) { |
575
|
|
|
return; |
576
|
|
|
} |
577
|
|
|
|
578
|
|
|
if (function_exists('exif_read_data') && $image->exif('Orientation') && $image->exif('Orientation') > 1) { |
579
|
|
|
$this->addAlteration('orientate'); |
580
|
|
|
} |
581
|
|
|
|
582
|
|
|
if (!$this->getAlterations() && $content = $this->dumpImage()) { |
583
|
|
|
$this->files->put($this->directory . $path, $content); |
584
|
|
|
|
585
|
|
|
return; |
586
|
|
|
} |
587
|
|
|
|
588
|
|
|
if (is_callable('exif_read_data') && in_array('orientate', $this->getAlterations())) { |
589
|
|
|
$this->setAlterations(array_unique(array_merge(['orientate'], $this->getAlterations()))); |
590
|
|
|
} |
591
|
|
|
|
592
|
|
|
foreach ($this->getAlterations() as $method => $arguments) { |
593
|
|
|
if ($method == 'resize') { |
594
|
|
|
$this->guessResizeArguments($arguments); |
595
|
|
|
} |
596
|
|
|
|
597
|
|
|
if (in_array($method, $this->getAllowedMethods())) { |
598
|
|
|
if (is_array($arguments)) { |
599
|
|
|
call_user_func_array([$image, $method], $arguments); |
600
|
|
|
} else { |
601
|
|
|
call_user_func([$image, $method], $arguments); |
602
|
|
|
} |
603
|
|
|
} |
604
|
|
|
} |
605
|
|
|
|
606
|
|
|
$image->save($this->directory . $path, $this->getQuality()); |
607
|
|
|
} |
608
|
|
|
|
609
|
|
|
/** |
610
|
|
|
* Set an attribute value. |
611
|
|
|
* |
612
|
|
|
* @param $attribute |
613
|
|
|
* @param $value |
614
|
|
|
* @return $this |
615
|
|
|
*/ |
616
|
|
|
public function attr($attribute, $value) |
617
|
|
|
{ |
618
|
|
|
array_set($this->attributes, $attribute, $value); |
619
|
|
|
|
620
|
|
|
return $this; |
621
|
|
|
} |
622
|
|
|
|
623
|
|
|
/** |
624
|
|
|
* Return the image srcsets by set. |
625
|
|
|
* |
626
|
|
|
* @return array |
627
|
|
|
*/ |
628
|
|
|
public function srcset() |
629
|
|
|
{ |
630
|
|
|
$sources = []; |
631
|
|
|
|
632
|
|
|
/* @var Image $image */ |
633
|
|
|
foreach ($this->getSrcsets() as $descriptor => $image) { |
634
|
|
|
$sources[] = $image->asset() . ' ' . $descriptor; |
635
|
|
|
} |
636
|
|
|
|
637
|
|
|
return implode(', ', $sources); |
638
|
|
|
} |
639
|
|
|
|
640
|
|
|
/** |
641
|
|
|
* Set the srcsets/alterations. |
642
|
|
|
* |
643
|
|
|
* @param array $srcsets |
644
|
|
|
*/ |
645
|
|
|
public function srcsets(array $srcsets) |
646
|
|
|
{ |
647
|
|
|
foreach ($srcsets as $descriptor => &$alterations) { |
648
|
|
|
$image = $this->make(array_pull($alterations, 'image', $this->getImage()))->setOutput('url'); |
649
|
|
|
|
650
|
|
View Code Duplication |
foreach ($alterations as $method => $arguments) { |
|
|
|
|
651
|
|
|
if (is_array($arguments)) { |
652
|
|
|
call_user_func_array([$image, $method], $arguments); |
653
|
|
|
} else { |
654
|
|
|
call_user_func([$image, $method], $arguments); |
655
|
|
|
} |
656
|
|
|
} |
657
|
|
|
|
658
|
|
|
$alterations = $image; |
659
|
|
|
} |
660
|
|
|
|
661
|
|
|
$this->setSrcsets($srcsets); |
662
|
|
|
|
663
|
|
|
return $this; |
664
|
|
|
} |
665
|
|
|
|
666
|
|
|
/** |
667
|
|
|
* Set the sources/alterations. |
668
|
|
|
* |
669
|
|
|
* @param array $sources |
670
|
|
|
* @param bool $merge |
671
|
|
|
* @return $this |
672
|
|
|
*/ |
673
|
|
|
public function sources(array $sources, $merge = true) |
674
|
|
|
{ |
675
|
|
|
foreach ($sources as $media => &$alterations) { |
676
|
|
|
if ($merge) { |
677
|
|
|
$alterations = array_merge($this->getAlterations(), $alterations); |
678
|
|
|
} |
679
|
|
|
|
680
|
|
|
$image = $this->make(array_pull($alterations, 'image', $this->getImage()))->setOutput('source'); |
681
|
|
|
|
682
|
|
|
if ($media != 'fallback') { |
683
|
|
|
call_user_func([$image, 'media'], $media); |
684
|
|
|
} |
685
|
|
|
|
686
|
|
View Code Duplication |
foreach ($alterations as $method => $arguments) { |
|
|
|
|
687
|
|
|
if (is_array($arguments)) { |
688
|
|
|
call_user_func_array([$image, $method], $arguments); |
689
|
|
|
} else { |
690
|
|
|
call_user_func([$image, $method], $arguments); |
691
|
|
|
} |
692
|
|
|
} |
693
|
|
|
|
694
|
|
|
$alterations = $image; |
695
|
|
|
} |
696
|
|
|
|
697
|
|
|
$this->setSources($sources); |
698
|
|
|
|
699
|
|
|
return $this; |
700
|
|
|
} |
701
|
|
|
|
702
|
|
|
/** |
703
|
|
|
* Alter the image based on the user agents. |
704
|
|
|
* |
705
|
|
|
* @param array $agents |
706
|
|
|
* @param bool $exit |
707
|
|
|
* @return $this |
708
|
|
|
*/ |
709
|
|
|
public function agents(array $agents, $exit = false) |
710
|
|
|
{ |
711
|
|
|
foreach ($agents as $agent => $alterations) { |
712
|
|
|
if ( |
713
|
|
|
$this->agent->is($agent) |
714
|
|
|
|| ($agent == 'phone' && $this->agent->isPhone()) |
715
|
|
|
|| ($agent == 'mobile' && $this->agent->isMobile()) |
716
|
|
|
|| ($agent == 'tablet' && $this->agent->isTablet()) |
717
|
|
|
|| ($agent == 'desktop' && $this->agent->isDesktop()) |
718
|
|
|
) { |
719
|
|
View Code Duplication |
foreach ($alterations as $method => $arguments) { |
|
|
|
|
720
|
|
|
if (is_array($arguments)) { |
721
|
|
|
call_user_func_array([$this, $method], $arguments); |
722
|
|
|
} else { |
723
|
|
|
call_user_func([$this, $method], $arguments); |
724
|
|
|
} |
725
|
|
|
} |
726
|
|
|
|
727
|
|
|
if ($exit) { |
728
|
|
|
return $this; |
729
|
|
|
} |
730
|
|
|
} |
731
|
|
|
} |
732
|
|
|
|
733
|
|
|
return $this; |
734
|
|
|
} |
735
|
|
|
|
736
|
|
|
/** |
737
|
|
|
* Return if an extension is supported. |
738
|
|
|
* |
739
|
|
|
* @param $extension |
740
|
|
|
* @return bool |
741
|
|
|
*/ |
742
|
|
|
protected function supportsType($extension) |
743
|
|
|
{ |
744
|
|
|
return !in_array($extension, ['svg', 'webp']); |
745
|
|
|
} |
746
|
|
|
|
747
|
|
|
/** |
748
|
|
|
* Set the image. |
749
|
|
|
* |
750
|
|
|
* @param $image |
751
|
|
|
* @return $this |
752
|
|
|
*/ |
753
|
|
|
public function setImage($image) |
754
|
|
|
{ |
755
|
|
|
if ($image instanceof Presenter) { |
756
|
|
|
$image = $image->getObject(); |
757
|
|
|
} |
758
|
|
|
|
759
|
|
|
if ($image instanceof FieldType) { |
760
|
|
|
$image = $image->getValue(); |
761
|
|
|
} |
762
|
|
|
|
763
|
|
|
// Replace path prefixes. |
764
|
|
|
if (is_string($image) && str_contains($image, '::')) { |
765
|
|
|
$image = $this->paths->realPath($image); |
766
|
|
|
|
767
|
|
|
$this->setExtension(pathinfo($image, PATHINFO_EXTENSION)); |
768
|
|
|
|
769
|
|
|
$size = getimagesize($image); |
770
|
|
|
|
771
|
|
|
$this->setWidth(array_get($size, 0)); |
772
|
|
|
$this->setHeight(array_get($size, 1)); |
773
|
|
|
} |
774
|
|
|
|
775
|
|
|
if (is_string($image) && str_is('*://*', $image) && !starts_with($image, ['http', 'https'])) { |
776
|
|
|
$this->setExtension(pathinfo($image, PATHINFO_EXTENSION)); |
777
|
|
|
} |
778
|
|
|
|
779
|
|
View Code Duplication |
if ($image instanceof FileInterface) { |
|
|
|
|
780
|
|
|
|
781
|
|
|
/* @var FileInterface $image */ |
782
|
|
|
$this->setExtension($image->getExtension()); |
783
|
|
|
|
784
|
|
|
$this->setWidth($image->getWidth()); |
785
|
|
|
$this->setHeight($image->getHeight()); |
786
|
|
|
} |
787
|
|
|
|
788
|
|
View Code Duplication |
if ($image instanceof FilePresenter) { |
|
|
|
|
789
|
|
|
|
790
|
|
|
/* @var FilePresenter|FileInterface $image */ |
791
|
|
|
$image = $image->getObject(); |
792
|
|
|
|
793
|
|
|
$this->setExtension($image->getExtension()); |
794
|
|
|
|
795
|
|
|
$this->setWidth($image->getWidth()); |
796
|
|
|
$this->setHeight($image->getHeight()); |
797
|
|
|
} |
798
|
|
|
|
799
|
|
|
$this->image = $image; |
800
|
|
|
|
801
|
|
|
return $this; |
802
|
|
|
} |
803
|
|
|
|
804
|
|
|
/** |
805
|
|
|
* Make an image instance. |
806
|
|
|
* |
807
|
|
|
* @return \Intervention\Image\Image |
808
|
|
|
*/ |
809
|
|
|
protected function makeImage() |
810
|
|
|
{ |
811
|
|
|
if ($this->image instanceof FileInterface) { |
|
|
|
|
812
|
|
|
return $this->manager->make(app(MountManager::class)->read($this->image->location())); |
813
|
|
|
} |
814
|
|
|
|
815
|
|
|
if (is_string($this->image) && str_is('*://*', $this->image)) { |
816
|
|
|
return $this->manager->make(app(MountManager::class)->read($this->image)); |
817
|
|
|
} |
818
|
|
|
|
819
|
|
|
if ($this->image instanceof File) { |
820
|
|
|
return $this->manager->make($this->image->read()); |
821
|
|
|
} |
822
|
|
|
|
823
|
|
|
if (is_string($this->image) && file_exists($this->image)) { |
824
|
|
|
return $this->manager->make($this->image); |
825
|
|
|
} |
826
|
|
|
|
827
|
|
|
if ($this->image instanceof Image) { |
828
|
|
|
return $this->image; |
829
|
|
|
} |
830
|
|
|
|
831
|
|
|
return null; |
832
|
|
|
} |
833
|
|
|
|
834
|
|
|
/** |
835
|
|
|
* Dump an image instance's data. |
836
|
|
|
* |
837
|
|
|
* @return string |
838
|
|
|
*/ |
839
|
|
|
protected function dumpImage() |
840
|
|
|
{ |
841
|
|
|
if ($this->image instanceof FileInterface) { |
|
|
|
|
842
|
|
|
return app('League\Flysystem\MountManager')->read($this->image->location()); |
843
|
|
|
} |
844
|
|
|
|
845
|
|
View Code Duplication |
if (is_string($this->image) && str_is('*://*', $this->image) && !starts_with($this->image, ['http', '//'])) { |
|
|
|
|
846
|
|
|
return app('League\Flysystem\MountManager')->read($this->image); |
847
|
|
|
} |
848
|
|
|
|
849
|
|
View Code Duplication |
if (is_string($this->image) && (file_exists($this->image) || starts_with($this->image, ['http', '//']))) { |
|
|
|
|
850
|
|
|
return file_get_contents($this->image); |
851
|
|
|
} |
852
|
|
|
|
853
|
|
|
if (is_string($this->image) && file_exists($this->image)) { |
854
|
|
|
return file_get_contents($this->image); |
855
|
|
|
} |
856
|
|
|
|
857
|
|
|
if ($this->image instanceof File) { |
858
|
|
|
return $this->image->read(); |
859
|
|
|
} |
860
|
|
|
|
861
|
|
|
if ($this->image instanceof Image) { |
862
|
|
|
return $this->image->encode(); |
863
|
|
|
} |
864
|
|
|
|
865
|
|
|
if (is_string($this->image) && file_exists($this->image)) { |
866
|
|
|
return file_get_contents($this->image); |
867
|
|
|
} |
868
|
|
|
|
869
|
|
|
return null; |
870
|
|
|
} |
871
|
|
|
|
872
|
|
|
/** |
873
|
|
|
* Get the image instance. |
874
|
|
|
* |
875
|
|
|
* @return \Intervention\Image\Image |
876
|
|
|
*/ |
877
|
|
|
public function getImage() |
878
|
|
|
{ |
879
|
|
|
return $this->image; |
880
|
|
|
} |
881
|
|
|
|
882
|
|
|
/** |
883
|
|
|
* Get the file name. |
884
|
|
|
* |
885
|
|
|
* @return null|string |
886
|
|
|
*/ |
887
|
|
|
public function getFilename() |
888
|
|
|
{ |
889
|
|
|
return $this->filename; |
890
|
|
|
} |
891
|
|
|
|
892
|
|
|
/** |
893
|
|
|
* Set the file name. |
894
|
|
|
* |
895
|
|
|
* @param $filename |
896
|
|
|
* @return $this |
897
|
|
|
*/ |
898
|
|
|
public function setFilename($filename = null) |
899
|
|
|
{ |
900
|
|
|
if (!$filename) { |
901
|
|
|
$filename = $this->getImageFilename(); |
|
|
|
|
902
|
|
|
} |
903
|
|
|
|
904
|
|
|
$this->filename = $filename; |
905
|
|
|
|
906
|
|
|
return $this; |
907
|
|
|
} |
908
|
|
|
|
909
|
|
|
/** |
910
|
|
|
* Get the alterations. |
911
|
|
|
* |
912
|
|
|
* @return array |
913
|
|
|
*/ |
914
|
|
|
public function getAlterations() |
915
|
|
|
{ |
916
|
|
|
return $this->alterations; |
917
|
|
|
} |
918
|
|
|
|
919
|
|
|
/** |
920
|
|
|
* Set the alterations. |
921
|
|
|
* |
922
|
|
|
* @param array $alterations |
923
|
|
|
* @return $this |
924
|
|
|
*/ |
925
|
|
|
public function setAlterations(array $alterations) |
926
|
|
|
{ |
927
|
|
|
$this->alterations = $alterations; |
928
|
|
|
|
929
|
|
|
return $this; |
930
|
|
|
} |
931
|
|
|
|
932
|
|
|
/** |
933
|
|
|
* Add an alteration. |
934
|
|
|
* |
935
|
|
|
* @param $method |
936
|
|
|
* @param $arguments |
937
|
|
|
* @return $this |
938
|
|
|
*/ |
939
|
|
|
public function addAlteration($method, $arguments = []) |
940
|
|
|
{ |
941
|
|
|
$this->alterations[$method] = $arguments; |
942
|
|
|
|
943
|
|
|
return $this; |
944
|
|
|
} |
945
|
|
|
|
946
|
|
|
/** |
947
|
|
|
* Get the attributes. |
948
|
|
|
* |
949
|
|
|
* @return array |
950
|
|
|
*/ |
951
|
|
|
public function getAttributes() |
952
|
|
|
{ |
953
|
|
|
return $this->attributes; |
954
|
|
|
} |
955
|
|
|
|
956
|
|
|
/** |
957
|
|
|
* Set the attributes. |
958
|
|
|
* |
959
|
|
|
* @param array $attributes |
960
|
|
|
* @return $this |
961
|
|
|
*/ |
962
|
|
|
public function setAttributes(array $attributes) |
963
|
|
|
{ |
964
|
|
|
$this->attributes = $attributes; |
965
|
|
|
|
966
|
|
|
return $this; |
967
|
|
|
} |
968
|
|
|
|
969
|
|
|
/** |
970
|
|
|
* Add an attribute. |
971
|
|
|
* |
972
|
|
|
* @param $attribute |
973
|
|
|
* @param $value |
974
|
|
|
* @return $this |
975
|
|
|
*/ |
976
|
|
|
protected function addAttribute($attribute, $value) |
977
|
|
|
{ |
978
|
|
|
$this->attributes[$attribute] = $value; |
979
|
|
|
|
980
|
|
|
return $this; |
981
|
|
|
} |
982
|
|
|
|
983
|
|
|
/** |
984
|
|
|
* Get the srcsets. |
985
|
|
|
* |
986
|
|
|
* @return array |
987
|
|
|
*/ |
988
|
|
|
public function getSrcsets() |
989
|
|
|
{ |
990
|
|
|
return $this->srcsets; |
991
|
|
|
} |
992
|
|
|
|
993
|
|
|
/** |
994
|
|
|
* Set the srcsets. |
995
|
|
|
* |
996
|
|
|
* @param array $srcsets |
997
|
|
|
* @return $this |
998
|
|
|
*/ |
999
|
|
|
public function setSrcsets(array $srcsets) |
1000
|
|
|
{ |
1001
|
|
|
$this->srcsets = $srcsets; |
1002
|
|
|
|
1003
|
|
|
return $this; |
1004
|
|
|
} |
1005
|
|
|
|
1006
|
|
|
/** |
1007
|
|
|
* Get the sources. |
1008
|
|
|
* |
1009
|
|
|
* @return array |
1010
|
|
|
*/ |
1011
|
|
|
public function getSources() |
1012
|
|
|
{ |
1013
|
|
|
return $this->sources; |
1014
|
|
|
} |
1015
|
|
|
|
1016
|
|
|
/** |
1017
|
|
|
* Set the sources. |
1018
|
|
|
* |
1019
|
|
|
* @param array $sources |
1020
|
|
|
* @return $this |
1021
|
|
|
*/ |
1022
|
|
|
public function setSources(array $sources) |
1023
|
|
|
{ |
1024
|
|
|
$this->sources = $sources; |
1025
|
|
|
|
1026
|
|
|
return $this; |
1027
|
|
|
} |
1028
|
|
|
|
1029
|
|
|
/** |
1030
|
|
|
* Get the quality. |
1031
|
|
|
* |
1032
|
|
|
* @param null $default |
1033
|
|
|
* @return int |
1034
|
|
|
*/ |
1035
|
|
|
public function getQuality($default = null) |
1036
|
|
|
{ |
1037
|
|
|
if (!$default) { |
1038
|
|
|
$this->config->get('streams::images.quality', 80); |
1039
|
|
|
} |
1040
|
|
|
|
1041
|
|
|
return $this->quality ?: $default; |
1042
|
|
|
} |
1043
|
|
|
|
1044
|
|
|
/** |
1045
|
|
|
* Set the output mode. |
1046
|
|
|
* |
1047
|
|
|
* @param $output |
1048
|
|
|
* @return $this |
1049
|
|
|
*/ |
1050
|
|
|
public function setOutput($output) |
1051
|
|
|
{ |
1052
|
|
|
$this->output = $output; |
1053
|
|
|
|
1054
|
|
|
return $this; |
1055
|
|
|
} |
1056
|
|
|
|
1057
|
|
|
/** |
1058
|
|
|
* Get the extension. |
1059
|
|
|
* |
1060
|
|
|
* @return null|string |
1061
|
|
|
*/ |
1062
|
|
|
public function getExtension() |
1063
|
|
|
{ |
1064
|
|
|
return $this->extension; |
1065
|
|
|
} |
1066
|
|
|
|
1067
|
|
|
/** |
1068
|
|
|
* Set the extension. |
1069
|
|
|
* |
1070
|
|
|
* @param $extension |
1071
|
|
|
* @return $this |
1072
|
|
|
*/ |
1073
|
|
|
public function setExtension($extension) |
1074
|
|
|
{ |
1075
|
|
|
$this->extension = $extension; |
1076
|
|
|
|
1077
|
|
|
return $this; |
1078
|
|
|
} |
1079
|
|
|
|
1080
|
|
|
/** |
1081
|
|
|
* Get the allowed methods. |
1082
|
|
|
* |
1083
|
|
|
* @return array |
1084
|
|
|
*/ |
1085
|
|
|
public function getAllowedMethods() |
1086
|
|
|
{ |
1087
|
|
|
return $this->allowedMethods; |
1088
|
|
|
} |
1089
|
|
|
|
1090
|
|
|
/** |
1091
|
|
|
* Add a path by it's namespace hint. |
1092
|
|
|
* |
1093
|
|
|
* @param $namespace |
1094
|
|
|
* @param $path |
1095
|
|
|
* @return $this |
1096
|
|
|
*/ |
1097
|
|
|
public function addPath($namespace, $path) |
1098
|
|
|
{ |
1099
|
|
|
$this->paths->addPath($namespace, $path); |
1100
|
|
|
|
1101
|
|
|
return $this; |
1102
|
|
|
} |
1103
|
|
|
|
1104
|
|
|
|
1105
|
|
|
/** |
1106
|
|
|
* Get the width. |
1107
|
|
|
* |
1108
|
|
|
* @return int|null |
1109
|
|
|
*/ |
1110
|
|
|
public function getWidth() |
1111
|
|
|
{ |
1112
|
|
|
return $this->width; |
1113
|
|
|
} |
1114
|
|
|
|
1115
|
|
|
/** |
1116
|
|
|
* Set the width. |
1117
|
|
|
* |
1118
|
|
|
* @param $width |
1119
|
|
|
* @return $this |
1120
|
|
|
*/ |
1121
|
|
|
public function setWidth($width) |
1122
|
|
|
{ |
1123
|
|
|
$this->width = $width; |
1124
|
|
|
|
1125
|
|
|
return $this; |
1126
|
|
|
} |
1127
|
|
|
|
1128
|
|
|
/** |
1129
|
|
|
* Get the height. |
1130
|
|
|
* |
1131
|
|
|
* @return int|null |
1132
|
|
|
*/ |
1133
|
|
|
public function getHeight() |
1134
|
|
|
{ |
1135
|
|
|
return $this->height; |
1136
|
|
|
} |
1137
|
|
|
|
1138
|
|
|
/** |
1139
|
|
|
* Set the height. |
1140
|
|
|
* |
1141
|
|
|
* @param $height |
1142
|
|
|
* @return $this |
1143
|
|
|
*/ |
1144
|
|
|
public function setHeight($height) |
1145
|
|
|
{ |
1146
|
|
|
$this->height = $height; |
1147
|
|
|
|
1148
|
|
|
return $this; |
1149
|
|
|
} |
1150
|
|
|
|
1151
|
|
|
/** |
1152
|
|
|
* Guess the resize callback value |
1153
|
|
|
* from a boolean. |
1154
|
|
|
* |
1155
|
|
|
* @param array $arguments |
1156
|
|
|
*/ |
1157
|
|
|
protected function guessResizeArguments(array &$arguments) |
1158
|
|
|
{ |
1159
|
|
|
$arguments = array_pad($arguments, 3, null); |
1160
|
|
|
|
1161
|
|
|
if (end($arguments) instanceof \Closure) { |
1162
|
|
|
return; |
1163
|
|
|
} |
1164
|
|
|
|
1165
|
|
|
if (array_pop($arguments) !== false && (is_null($arguments[0]) || is_null($arguments[1]))) { |
1166
|
|
|
$arguments[] = function (Constraint $constraint) { |
1167
|
|
|
$constraint->aspectRatio(); |
1168
|
|
|
}; |
1169
|
|
|
} |
1170
|
|
|
} |
1171
|
|
|
|
1172
|
|
|
/** |
1173
|
|
|
* Return the output. |
1174
|
|
|
* |
1175
|
|
|
* @return string |
1176
|
|
|
*/ |
1177
|
|
|
public function __toString() |
1178
|
|
|
{ |
1179
|
|
|
return (string)$this->output(); |
1180
|
|
|
} |
1181
|
|
|
|
1182
|
|
|
/** |
1183
|
|
|
* If the method does not exist then |
1184
|
|
|
* add an attribute and return. |
1185
|
|
|
* |
1186
|
|
|
* @param $name |
1187
|
|
|
* @param $arguments |
1188
|
|
|
* @return $this|mixed |
1189
|
|
|
*/ |
1190
|
|
|
public function __call($name, $arguments) |
1191
|
|
|
{ |
1192
|
|
|
if (in_array($name, $this->getAllowedMethods())) { |
1193
|
|
|
return $this->addAlteration($name, $arguments); |
1194
|
|
|
} |
1195
|
|
|
|
1196
|
|
|
if ($this->macros->isMacro($macro = snake_case($name))) { |
1197
|
|
|
return $this->macro($macro); |
1198
|
|
|
} |
1199
|
|
|
|
1200
|
|
|
if (!method_exists($this, $name)) { |
1201
|
|
|
array_set($this->attributes, $name, array_shift($arguments)); |
1202
|
|
|
|
1203
|
|
|
return $this; |
1204
|
|
|
} |
1205
|
|
|
|
1206
|
|
|
return call_user_func_array([$this, $name], $arguments); |
1207
|
|
|
} |
1208
|
|
|
} |
1209
|
|
|
|
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.