1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Charcoal\Property; |
4
|
|
|
|
5
|
|
|
use InvalidArgumentException; |
6
|
|
|
use OutOfBoundsException; |
7
|
|
|
|
8
|
|
|
// From 'charcoal-image' |
9
|
|
|
use Charcoal\Image\ImageFactory; |
10
|
|
|
use Charcoal\Image\ImageInterface; |
11
|
|
|
|
12
|
|
|
// From 'charccoal-translator' |
13
|
|
|
use Charcoal\Translator\Translation; |
14
|
|
|
|
15
|
|
|
// From 'charcoal-property' |
16
|
|
|
use Charcoal\Property\FileProperty; |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* Image Property. |
20
|
|
|
* |
21
|
|
|
* The image property is a specialized file property that stores image file. |
22
|
|
|
*/ |
23
|
|
|
class ImageProperty extends FileProperty |
24
|
|
|
{ |
25
|
|
|
const DEFAULT_DRIVER_TYPE = 'imagick'; |
26
|
|
|
|
27
|
|
|
const EFFECTS_EVENT_SAVE = 'save'; |
28
|
|
|
const EFFECTS_EVENT_NEVER = 'never'; |
29
|
|
|
const EFFECTS_EVENT_UPLOAD = 'upload'; |
30
|
|
|
const DEFAULT_APPLY_EFFECTS = self::EFFECTS_EVENT_SAVE; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* One or more effects to apply on the image. |
34
|
|
|
* |
35
|
|
|
* @var array |
36
|
|
|
*/ |
37
|
|
|
private $effects = []; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* Whether to apply any effects on the uploaded image. |
41
|
|
|
* |
42
|
|
|
* @var mixed |
43
|
|
|
*/ |
44
|
|
|
private $applyEffects = self::DEFAULT_APPLY_EFFECTS; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* The type of image processing engine. |
48
|
|
|
* |
49
|
|
|
* @var string |
50
|
|
|
*/ |
51
|
|
|
private $driverType = self::DEFAULT_DRIVER_TYPE; |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* Internal storage of the image factory instance. |
55
|
|
|
* |
56
|
|
|
* @var ImageFactory |
57
|
|
|
*/ |
58
|
|
|
private $imageFactory; |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* @return string |
62
|
|
|
*/ |
63
|
|
|
public function type() |
64
|
|
|
{ |
65
|
|
|
return 'image'; |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* Retrieve the image factory. |
70
|
|
|
* |
71
|
|
|
* @return ImageFactory |
72
|
|
|
*/ |
73
|
|
|
public function imageFactory() |
74
|
|
|
{ |
75
|
|
|
if ($this->imageFactory === null) { |
76
|
|
|
$this->imageFactory = $this->createImageFactory(); |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
return $this->imageFactory; |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* Set the name of the property's image processing driver. |
84
|
|
|
* |
85
|
|
|
* @param string $type The processing engine. |
86
|
|
|
* @throws InvalidArgumentException If the drive type is not a string. |
87
|
|
|
* @return ImageProperty Chainable |
88
|
|
|
*/ |
89
|
|
View Code Duplication |
public function setDriverType($type) |
|
|
|
|
90
|
|
|
{ |
91
|
|
|
if (!is_string($type)) { |
92
|
|
|
throw new InvalidArgumentException(sprintf( |
93
|
|
|
'Image driver type must be a string, received %s', |
94
|
|
|
(is_object($type) ? get_class($type) : gettype($type)) |
95
|
|
|
)); |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
$this->driverType = $type; |
99
|
|
|
|
100
|
|
|
return $this; |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* Retrieve the name of the property's image processing driver. |
105
|
|
|
* |
106
|
|
|
* @return string |
107
|
|
|
*/ |
108
|
|
|
public function getDriverType() |
109
|
|
|
{ |
110
|
|
|
return $this->driverType; |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* Set whether effects should be applied. |
115
|
|
|
* |
116
|
|
|
* @param mixed $event When to apply affects. |
117
|
|
|
* @throws OutOfBoundsException If the effects event does not exist. |
118
|
|
|
* @return ImageProperty Chainable |
119
|
|
|
*/ |
120
|
|
|
public function setApplyEffects($event) |
121
|
|
|
{ |
122
|
|
|
if ($event === false) { |
123
|
|
|
$this->applyEffects = self::EFFECTS_EVENT_NEVER; |
124
|
|
|
return $this; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
if ($event === null || $event === '') { |
128
|
|
|
$this->applyEffects = self::EFFECTS_EVENT_SAVE; |
129
|
|
|
return $this; |
130
|
|
|
} |
131
|
|
|
|
132
|
|
View Code Duplication |
if (!in_array($event, $this->acceptedEffectsEvents())) { |
|
|
|
|
133
|
|
|
if (!is_string($event)) { |
134
|
|
|
$event = (is_object($event) ? get_class($event) : gettype($event)); |
135
|
|
|
} |
136
|
|
|
throw new OutOfBoundsException(sprintf( |
137
|
|
|
'Unsupported image property event "%s" provided', |
138
|
|
|
$event |
139
|
|
|
)); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
$this->applyEffects = $event; |
143
|
|
|
|
144
|
|
|
return $this; |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
/** |
148
|
|
|
* Determine if effects should be applied. |
149
|
|
|
* |
150
|
|
|
* @return string Returns the property's condition on effects. |
151
|
|
|
*/ |
152
|
|
|
public function getApplyEffects() |
153
|
|
|
{ |
154
|
|
|
return $this->applyEffects; |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
/** |
158
|
|
|
* Determine if effects should be applied. |
159
|
|
|
* |
160
|
|
|
* @param string|boolean $event A specific event to check or a global flag to set. |
161
|
|
|
* @throws OutOfBoundsException If the effects event does not exist. |
162
|
|
|
* @return mixed Returns TRUE or FALSE if the property applies effects for the given event. |
163
|
|
|
*/ |
164
|
|
|
public function canApplyEffects($event) |
165
|
|
|
{ |
166
|
|
View Code Duplication |
if (!in_array($event, $this->acceptedEffectsEvents())) { |
|
|
|
|
167
|
|
|
if (!is_string($event)) { |
168
|
|
|
$event = (is_object($event) ? get_class($event) : gettype($event)); |
169
|
|
|
} |
170
|
|
|
throw new OutOfBoundsException(sprintf( |
171
|
|
|
'Unsupported image property event "%s" provided', |
172
|
|
|
$event |
173
|
|
|
)); |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
return $this->applyEffects === $event; |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
/** |
180
|
|
|
* Retrieve the supported events where effects can be applied. |
181
|
|
|
* |
182
|
|
|
* @return array |
183
|
|
|
*/ |
184
|
|
|
public function acceptedEffectsEvents() |
185
|
|
|
{ |
186
|
|
|
return [ |
187
|
|
|
self::EFFECTS_EVENT_UPLOAD, |
188
|
|
|
self::EFFECTS_EVENT_SAVE, |
189
|
|
|
self::EFFECTS_EVENT_NEVER, |
190
|
|
|
]; |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* Set (reset, in fact) the image effects. |
195
|
|
|
* |
196
|
|
|
* @param array $effects The effects to set to the image. |
197
|
|
|
* @return ImageProperty Chainable |
198
|
|
|
*/ |
199
|
|
|
public function setEffects(array $effects) |
200
|
|
|
{ |
201
|
|
|
$this->effects = []; |
202
|
|
|
foreach ($effects as $effect) { |
203
|
|
|
$this->addEffect($effect); |
204
|
|
|
} |
205
|
|
|
return $this; |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
/** |
209
|
|
|
* @param mixed $effect An image effect. |
210
|
|
|
* @return ImageProperty Chainable |
211
|
|
|
*/ |
212
|
|
|
public function addEffect($effect) |
213
|
|
|
{ |
214
|
|
|
$this->effects[] = $effect; |
215
|
|
|
return $this; |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* @return array |
220
|
|
|
*/ |
221
|
|
|
public function getEffects() |
222
|
|
|
{ |
223
|
|
|
return $this->effects; |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
/** |
227
|
|
|
* Process the property's effects on the given image(s). |
228
|
|
|
* |
229
|
|
|
* @param mixed $value The target(s) to apply effects on. |
230
|
|
|
* @param array $effects The effects to apply on the target. |
231
|
|
|
* @param ImageInterface|null $image Optional. The image for processing. |
232
|
|
|
* @return mixed Returns the given images. Depending on the effects applied, |
233
|
|
|
* certain images might be renamed. |
234
|
|
|
*/ |
235
|
|
|
public function processEffects($value, array $effects = null, ImageInterface $image = null) |
236
|
|
|
{ |
237
|
|
|
$value = $this->parseVal($value); |
238
|
|
|
|
239
|
|
|
if ($value instanceof Translation) { |
240
|
|
|
$value = $value->data(); |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
if ($effects === null) { |
244
|
|
|
$effects = $this->batchEffects(); |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
if ($effects) { |
|
|
|
|
248
|
|
|
if ($image === null) { |
249
|
|
|
$image = $this->createImage(); |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
if (is_array($value)) { |
253
|
|
|
foreach ($value as &$val) { |
254
|
|
|
$val = $this->processEffectsOne($val, $effects, $image); |
255
|
|
|
} |
256
|
|
|
} else { |
257
|
|
|
$value = $this->processEffectsOne($value, $effects, $image); |
258
|
|
|
} |
259
|
|
|
} |
260
|
|
|
|
261
|
|
|
return $value; |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
/** |
265
|
|
|
* Retrieves the default list of acceptable MIME types for uploaded files. |
266
|
|
|
* |
267
|
|
|
* This method should be overriden. |
268
|
|
|
* |
269
|
|
|
* @return string[] |
270
|
|
|
*/ |
271
|
|
View Code Duplication |
public function getDefaultAcceptedMimetypes() |
|
|
|
|
272
|
|
|
{ |
273
|
|
|
return [ |
274
|
|
|
'image/gif', |
275
|
|
|
'image/jpg', |
276
|
|
|
'image/jpeg', |
277
|
|
|
'image/pjpeg', |
278
|
|
|
'image/png', |
279
|
|
|
'image/svg+xml', |
280
|
|
|
'image/webp', |
281
|
|
|
]; |
282
|
|
|
} |
283
|
|
|
|
284
|
|
|
/** |
285
|
|
|
* Resolve the file extension from the given MIME type. |
286
|
|
|
* |
287
|
|
|
* @param string $type The MIME type to resolve. |
288
|
|
|
* @return string|null The extension based on the MIME type. |
289
|
|
|
*/ |
290
|
|
View Code Duplication |
protected function resolveExtensionFromMimeType($type) |
|
|
|
|
291
|
|
|
{ |
292
|
|
|
switch ($type) { |
293
|
|
|
case 'image/gif': |
294
|
|
|
return 'gif'; |
295
|
|
|
|
296
|
|
|
case 'image/jpg': |
297
|
|
|
case 'image/jpeg': |
298
|
|
|
case 'image/pjpeg': |
299
|
|
|
return 'jpg'; |
300
|
|
|
|
301
|
|
|
case 'image/png': |
302
|
|
|
return 'png'; |
303
|
|
|
|
304
|
|
|
case 'image/svg+xml': |
305
|
|
|
return 'svg'; |
306
|
|
|
|
307
|
|
|
case 'image/webp': |
308
|
|
|
return 'webp'; |
309
|
|
|
} |
310
|
|
|
|
311
|
|
|
return null; |
312
|
|
|
} |
313
|
|
|
|
314
|
|
|
/** |
315
|
|
|
* @param mixed $val The value, at time of saving. |
316
|
|
|
* @return mixed |
317
|
|
|
*/ |
318
|
|
|
public function save($val) |
319
|
|
|
{ |
320
|
|
|
$val = parent::save($val); |
321
|
|
|
|
322
|
|
|
if ($this->canApplyEffects('save')) { |
323
|
|
|
$val = $this->processEffects($val); |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
return $val; |
327
|
|
|
} |
328
|
|
|
|
329
|
|
|
/** |
330
|
|
|
* Apply effects to the uploaded data URI(s). |
331
|
|
|
* |
332
|
|
|
* @see FileProperty::fileUpload() |
333
|
|
|
* @param string $fileData The file data, raw. |
334
|
|
|
* @return string |
335
|
|
|
*/ |
336
|
|
View Code Duplication |
public function dataUpload($fileData) |
|
|
|
|
337
|
|
|
{ |
338
|
|
|
$target = parent::dataUpload($fileData); |
339
|
|
|
|
340
|
|
|
if ($this->canApplyEffects('upload')) { |
341
|
|
|
$target = $this->processEffects($target); |
342
|
|
|
} |
343
|
|
|
|
344
|
|
|
return $target; |
345
|
|
|
} |
346
|
|
|
|
347
|
|
|
/** |
348
|
|
|
* Apply effects to the uploaded file(s). |
349
|
|
|
* |
350
|
|
|
* @see FileProperty::fileUpload() |
351
|
|
|
* @param array $fileData The file data to upload. |
352
|
|
|
* @return string |
353
|
|
|
*/ |
354
|
|
View Code Duplication |
public function fileUpload(array $fileData) |
|
|
|
|
355
|
|
|
{ |
356
|
|
|
$target = parent::fileUpload($fileData); |
357
|
|
|
|
358
|
|
|
if ($this->canApplyEffects('upload')) { |
359
|
|
|
$target = $this->processEffects($target); |
360
|
|
|
} |
361
|
|
|
|
362
|
|
|
return $target; |
363
|
|
|
} |
364
|
|
|
|
365
|
|
|
/** |
366
|
|
|
* Set an image factory. |
367
|
|
|
* |
368
|
|
|
* @param ImageFactory $factory The image factory, to manipulate images. |
369
|
|
|
* @return self |
370
|
|
|
*/ |
371
|
|
|
protected function setImageFactory(ImageFactory $factory) |
372
|
|
|
{ |
373
|
|
|
$this->imageFactory = $factory; |
374
|
|
|
|
375
|
|
|
return $this; |
376
|
|
|
} |
377
|
|
|
|
378
|
|
|
/** |
379
|
|
|
* Create an image factory. |
380
|
|
|
* |
381
|
|
|
* @return ImageFactory |
382
|
|
|
*/ |
383
|
|
|
protected function createImageFactory() |
384
|
|
|
{ |
385
|
|
|
return new ImageFactory(); |
386
|
|
|
} |
387
|
|
|
|
388
|
|
|
/** |
389
|
|
|
* Create an image. |
390
|
|
|
* |
391
|
|
|
* @return ImageInterface |
392
|
|
|
*/ |
393
|
|
|
protected function createImage() |
394
|
|
|
{ |
395
|
|
|
return $this->imageFactory()->create($this['driverType']); |
396
|
|
|
} |
397
|
|
|
|
398
|
|
|
/** |
399
|
|
|
* @return array |
400
|
|
|
*/ |
401
|
|
|
protected function batchEffects() |
402
|
|
|
{ |
403
|
|
|
$effects = $this['effects']; |
404
|
|
|
$grouped = []; |
405
|
|
|
if ($effects) { |
406
|
|
|
$blueprint = [ |
407
|
|
|
'effects' => [], |
408
|
|
|
'save' => true, |
409
|
|
|
'rename' => null, |
410
|
|
|
'reset' => false, |
411
|
|
|
'copy' => null, |
412
|
|
|
]; |
413
|
|
|
$fxGroup = $blueprint; |
414
|
|
|
foreach ($effects as $effect) { |
415
|
|
|
if (isset($effect['type']) && $effect['type'] === 'condition') { |
416
|
|
|
$grouped[] = array_merge( |
417
|
|
|
[ |
418
|
|
|
'condition' => null, |
419
|
|
|
'ignore' => null, |
420
|
|
|
'extension' => null, |
421
|
|
|
'mimetype' => null, |
422
|
|
|
], |
423
|
|
|
$effect |
424
|
|
|
); |
425
|
|
|
} elseif (isset($effect['type']) && $effect['type'] === 'save') { |
426
|
|
|
if (isset($effect['rename'])) { |
427
|
|
|
$fxGroup['rename'] = $effect['rename']; |
428
|
|
|
} |
429
|
|
|
if (isset($effect['copy'])) { |
430
|
|
|
$fxGroup['copy'] = $effect['copy']; |
431
|
|
|
} |
432
|
|
|
if (isset($effect['reset'])) { |
433
|
|
|
$fxGroup['reset'] = $effect['reset']; |
434
|
|
|
} |
435
|
|
|
|
436
|
|
|
$grouped[] = $fxGroup; |
437
|
|
|
|
438
|
|
|
$fxGroup = $blueprint; |
439
|
|
|
} else { |
440
|
|
|
$fxGroup['effects'][] = $effect; |
441
|
|
|
} |
442
|
|
|
} |
443
|
|
|
|
444
|
|
|
if (empty($grouped)) { |
445
|
|
|
$grouped[] = $fxGroup; |
446
|
|
|
} |
447
|
|
|
} |
448
|
|
|
|
449
|
|
|
return $grouped; |
450
|
|
|
} |
451
|
|
|
|
452
|
|
|
/** |
453
|
|
|
* Process the property's effects on the given image. |
454
|
|
|
* |
455
|
|
|
* @param string $value The target to apply effects on. |
456
|
|
|
* @param array $effects The effects to apply on the target. |
457
|
|
|
* @param ImageInterface|null $image Optional. The image for processing. |
458
|
|
|
* @throws InvalidArgumentException If the $value is not a string. |
459
|
|
|
* @return mixed Returns the processed target or NULL. |
460
|
|
|
*/ |
461
|
|
|
private function processEffectsOne($value, array $effects = null, ImageInterface $image = null) |
462
|
|
|
{ |
463
|
|
|
if ($value === null || $value === '') { |
464
|
|
|
return null; |
465
|
|
|
} |
466
|
|
|
|
467
|
|
|
if (!is_string($value)) { |
468
|
|
|
throw new InvalidArgumentException(sprintf( |
469
|
|
|
'Target image must be a string, received %s', |
470
|
|
|
(is_object($value) ? get_class($value) : gettype($value)) |
471
|
|
|
)); |
472
|
|
|
} |
473
|
|
|
|
474
|
|
|
if (!$this->fileExists($value)) { |
475
|
|
|
return $value; |
476
|
|
|
} |
477
|
|
|
|
478
|
|
|
if ($image === null) { |
479
|
|
|
$image = $this->createImage(); |
480
|
|
|
} |
481
|
|
|
|
482
|
|
|
if ($effects === null) { |
483
|
|
|
$effects = $this->batchEffects(); |
484
|
|
|
} |
485
|
|
|
|
486
|
|
|
if ($effects) { |
|
|
|
|
487
|
|
|
$basePath = $this->basePath(); |
488
|
|
|
|
489
|
|
|
$isAbsolute = false; |
490
|
|
|
if (null !== parse_url($value, PHP_URL_HOST)) { |
491
|
|
|
$isAbsolute = true; |
492
|
|
|
} |
493
|
|
|
|
494
|
|
|
// @todo Save original file here |
495
|
|
|
$valuePath = ($isAbsolute ? '' : $basePath); |
496
|
|
|
$image->open(static::normalizePath($valuePath.$value)); |
497
|
|
|
$target = null; |
498
|
|
|
if ($isAbsolute) { |
499
|
|
|
$target = static::normalizePath($basePath.$this['uploadPath'].pathinfo($value, PATHINFO_BASENAME)); |
500
|
|
|
} |
501
|
|
|
|
502
|
|
|
foreach ($effects as $fxGroup) { |
503
|
|
|
if (isset($fxGroup['type']) && !empty($fxGroup['condition'])) { |
504
|
|
|
if ($fxGroup['condition'] === 'ignore') { |
505
|
|
|
switch ($fxGroup['ignore']) { |
506
|
|
|
case 'extension': |
507
|
|
|
$type = pathinfo($value, PATHINFO_EXTENSION); |
508
|
|
|
if (in_array($type, (array)$fxGroup['extension'])) { |
509
|
|
|
break 2; |
510
|
|
|
} |
511
|
|
|
break; |
512
|
|
|
|
513
|
|
|
case 'mimetype': |
514
|
|
|
$type = $this->getMimetypeFor($value); |
515
|
|
|
if (in_array($type, (array)$fxGroup['mimetype'])) { |
516
|
|
|
break 2; |
517
|
|
|
} |
518
|
|
|
break; |
519
|
|
|
} |
520
|
|
|
} else { |
521
|
|
|
if (is_string($fxGroup['condition'])) { |
522
|
|
|
$this->logger->warning(sprintf( |
523
|
|
|
'[Image Property] Unsupported conditional effect: \'%s\'', |
524
|
|
|
$fxGroup['condition'] |
525
|
|
|
)); |
526
|
|
|
} else { |
527
|
|
|
$this->logger->warning(sprintf( |
528
|
|
|
'[Image Property] Invalid conditional effect: \'%s\'', |
529
|
|
|
gettype($fxGroup['condition']) |
530
|
|
|
)); |
531
|
|
|
} |
532
|
|
|
} |
533
|
|
|
} elseif ($fxGroup['save']) { |
534
|
|
|
$rename = $fxGroup['rename']; |
535
|
|
|
$copy = $fxGroup['copy']; |
536
|
|
|
|
537
|
|
|
$doRename = false; |
538
|
|
|
$doCopy = false; |
539
|
|
|
$doSave = true; |
540
|
|
|
|
541
|
|
|
if ($rename || $copy) { |
542
|
|
View Code Duplication |
if ($copy) { |
|
|
|
|
543
|
|
|
$copy = $this->renderFileRenamePattern(($target ?: $value), $copy); |
544
|
|
|
$exists = $this->fileExists(static::normalizePath($basePath.$copy)); |
545
|
|
|
$doCopy = ($copy && ($this['overwrite'] || !$exists)); |
546
|
|
|
} |
547
|
|
|
|
548
|
|
View Code Duplication |
if ($rename) { |
|
|
|
|
549
|
|
|
$value = $this->renderFileRenamePattern(($target ?: $value), $rename); |
550
|
|
|
$exists = $this->fileExists(static::normalizePath($basePath.$value)); |
551
|
|
|
$doRename = ($value && ($this['overwrite'] || !$exists)); |
552
|
|
|
} |
553
|
|
|
|
554
|
|
|
$doSave = ($doCopy || $doRename); |
555
|
|
|
} |
556
|
|
|
|
557
|
|
|
if ($doSave) { |
558
|
|
|
if ($fxGroup['effects']) { |
559
|
|
|
$image->setEffects($fxGroup['effects']); |
560
|
|
|
$image->process(); |
561
|
|
|
} |
562
|
|
|
|
563
|
|
|
if ($rename || $copy) { |
564
|
|
|
if ($doCopy) { |
565
|
|
|
$image->save(static::normalizePath($valuePath.$copy)); |
566
|
|
|
} |
567
|
|
|
|
568
|
|
|
if ($doRename) { |
569
|
|
|
$image->save(static::normalizePath($valuePath.$value)); |
570
|
|
|
} |
571
|
|
|
} else { |
572
|
|
|
$image->save($target ?: static::normalizePath($valuePath.$value)); |
573
|
|
|
} |
574
|
|
|
} |
575
|
|
|
} |
576
|
|
|
// reset to default image allow starting effects chains from original image. |
577
|
|
|
if ($fxGroup['reset']) { |
578
|
|
|
$image = $image->open(static::normalizePath($valuePath.$value)); |
579
|
|
|
} |
580
|
|
|
} |
581
|
|
|
} |
582
|
|
|
|
583
|
|
|
return $value; |
584
|
|
|
} |
585
|
|
|
} |
586
|
|
|
|
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.