1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace League\Glide; |
4
|
|
|
|
5
|
|
|
use InvalidArgumentException; |
6
|
|
|
use League\Flysystem\FileExistsException; |
7
|
|
|
use League\Flysystem\FilesystemInterface; |
8
|
|
|
use League\Flysystem\FilesystemOperator; |
9
|
|
|
use League\Flysystem\UnableToReadFile; |
10
|
|
|
use League\Glide\Api\ApiInterface; |
11
|
|
|
use League\Glide\Filesystem\FileNotFoundException; |
12
|
|
|
use League\Glide\Filesystem\FilesystemException; |
13
|
|
|
use League\Glide\Responses\ResponseFactoryInterface; |
14
|
|
|
|
15
|
|
|
class Server |
16
|
|
|
{ |
17
|
|
|
/** |
18
|
|
|
* Source file system. |
19
|
|
|
* @var FilesystemInterface|FilesystemOperator |
20
|
|
|
*/ |
21
|
|
|
protected $source; |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* Source path prefix. |
25
|
|
|
* @var string |
26
|
|
|
*/ |
27
|
|
|
protected $sourcePathPrefix; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* Cache file system. |
31
|
|
|
* @var FilesystemInterface|FilesystemOperator |
32
|
|
|
*/ |
33
|
|
|
protected $cache; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* Cache path prefix. |
37
|
|
|
* @var string |
38
|
|
|
*/ |
39
|
|
|
protected $cachePathPrefix; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* Whether to group cache in folders. |
43
|
|
|
* @var bool |
44
|
|
|
*/ |
45
|
|
|
protected $groupCacheInFolders = true; |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* Whether to cache with file extensions. |
49
|
|
|
* @var bool |
50
|
|
|
*/ |
51
|
|
|
protected $cacheWithFileExtensions = false; |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* Image manipulation API. |
55
|
|
|
* @var ApiInterface |
56
|
|
|
*/ |
57
|
|
|
protected $api; |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* Response factory. |
61
|
|
|
* @var ResponseFactoryInterface|null |
62
|
|
|
*/ |
63
|
|
|
protected $responseFactory; |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Base URL. |
67
|
|
|
* @var string |
68
|
|
|
*/ |
69
|
|
|
protected $baseUrl; |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* Default image manipulations. |
73
|
|
|
* @var array |
74
|
|
|
*/ |
75
|
|
|
protected $defaults = []; |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* Preset image manipulations. |
79
|
|
|
* @var array |
80
|
|
|
*/ |
81
|
|
|
protected $presets = []; |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* Create Server instance. |
85
|
|
|
* @param FilesystemInterface|FilesystemOperator $source Source file system. |
86
|
|
|
* @param FilesystemInterface|FilesystemOperator $cache Cache file system. |
87
|
|
|
* @param ApiInterface $api Image manipulation API. |
88
|
|
|
*/ |
89
|
|
|
public function __construct($source, $cache, ApiInterface $api) |
90
|
|
|
{ |
91
|
|
|
$this->setSource($source); |
92
|
|
|
$this->setCache($cache); |
93
|
|
|
$this->setApi($api); |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* Set source file system. |
98
|
|
|
* @param FilesystemInterface|FilesystemOperator $source Source file system. |
99
|
|
|
*/ |
100
|
|
|
public function setSource($source) |
101
|
|
|
{ |
102
|
|
|
$this->source = $source; |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
/** |
106
|
|
|
* Get source file system. |
107
|
|
|
* @return FilesystemInterface|FilesystemOperator Source file system. |
108
|
|
|
*/ |
109
|
|
|
public function getSource() |
110
|
|
|
{ |
111
|
|
|
return $this->source; |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* Set source path prefix. |
116
|
|
|
* @param string $sourcePathPrefix Source path prefix. |
117
|
|
|
*/ |
118
|
|
|
public function setSourcePathPrefix($sourcePathPrefix) |
119
|
|
|
{ |
120
|
|
|
$this->sourcePathPrefix = trim($sourcePathPrefix, '/'); |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Get source path prefix. |
125
|
|
|
* @return string Source path prefix. |
126
|
|
|
*/ |
127
|
|
|
public function getSourcePathPrefix() |
128
|
|
|
{ |
129
|
|
|
return $this->sourcePathPrefix; |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* Get source path. |
134
|
|
|
* @param string $path Image path. |
135
|
|
|
* @return string The source path. |
136
|
|
|
* @throws FileNotFoundException |
137
|
|
|
*/ |
138
|
|
|
public function getSourcePath($path) |
139
|
|
|
{ |
140
|
|
|
$path = trim($path, '/'); |
141
|
|
|
|
142
|
|
|
$baseUrl = $this->baseUrl.'/'; |
143
|
|
|
|
144
|
|
|
if (substr($path, 0, strlen($baseUrl)) === $baseUrl) { |
145
|
|
|
$path = trim(substr($path, strlen($baseUrl)), '/'); |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
if ($path === '') { |
149
|
|
|
throw new FileNotFoundException('Image path missing.'); |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
if ($this->sourcePathPrefix) { |
153
|
|
|
$path = $this->sourcePathPrefix.'/'.$path; |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
return rawurldecode($path); |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
/** |
160
|
|
|
* Check if a source file exists. |
161
|
|
|
* @param string $path Image path. |
162
|
|
|
* @return bool Whether the source file exists. |
163
|
|
|
*/ |
164
|
|
|
public function sourceFileExists($path) |
165
|
|
|
{ |
166
|
|
|
if ($this->source instanceof FilesystemInterface) { |
|
|
|
|
167
|
|
|
return $this->source->has($this->getSourcePath($path)); |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
return $this->source->fileExists($this->getSourcePath($path)); |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
/** |
174
|
|
|
* Set base URL. |
175
|
|
|
* @param string $baseUrl Base URL. |
176
|
|
|
*/ |
177
|
|
|
public function setBaseUrl($baseUrl) |
178
|
|
|
{ |
179
|
|
|
$this->baseUrl = trim($baseUrl, '/'); |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
/** |
183
|
|
|
* Get base URL. |
184
|
|
|
* @return string Base URL. |
185
|
|
|
*/ |
186
|
|
|
public function getBaseUrl() |
187
|
|
|
{ |
188
|
|
|
return $this->baseUrl; |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
/** |
192
|
|
|
* Set cache file system. |
193
|
|
|
* @param FilesystemInterface|FilesystemOperator $cache Cache file system. |
194
|
|
|
*/ |
195
|
|
|
public function setCache($cache) |
196
|
|
|
{ |
197
|
|
|
$this->cache = $cache; |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
/** |
201
|
|
|
* Get cache file system. |
202
|
|
|
* @return FilesystemInterface|FilesystemOperator Cache file system. |
203
|
|
|
*/ |
204
|
|
|
public function getCache() |
205
|
|
|
{ |
206
|
|
|
return $this->cache; |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* Set cache path prefix. |
211
|
|
|
* @param string $cachePathPrefix Cache path prefix. |
212
|
|
|
*/ |
213
|
|
|
public function setCachePathPrefix($cachePathPrefix) |
214
|
|
|
{ |
215
|
|
|
$this->cachePathPrefix = trim($cachePathPrefix, '/'); |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* Get cache path prefix. |
220
|
|
|
* @return string Cache path prefix. |
221
|
|
|
*/ |
222
|
|
|
public function getCachePathPrefix() |
223
|
|
|
{ |
224
|
|
|
return $this->cachePathPrefix; |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
/** |
228
|
|
|
* Set the group cache in folders setting. |
229
|
|
|
* @param bool $groupCacheInFolders Whether to group cache in folders. |
230
|
|
|
*/ |
231
|
|
|
public function setGroupCacheInFolders($groupCacheInFolders) |
232
|
|
|
{ |
233
|
|
|
$this->groupCacheInFolders = $groupCacheInFolders; |
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
/** |
237
|
|
|
* Get the group cache in folders setting. |
238
|
|
|
* @return bool Whether to group cache in folders. |
239
|
|
|
*/ |
240
|
|
|
public function getGroupCacheInFolders() |
241
|
|
|
{ |
242
|
|
|
return $this->groupCacheInFolders; |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
/** |
246
|
|
|
* Set the cache with file extensions setting. |
247
|
|
|
* @param bool $cacheWithFileExtensions Whether to cache with file extensions. |
248
|
|
|
*/ |
249
|
|
|
public function setCacheWithFileExtensions($cacheWithFileExtensions) |
250
|
|
|
{ |
251
|
|
|
$this->cacheWithFileExtensions = $cacheWithFileExtensions; |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
/** |
255
|
|
|
* Get the cache with file extensions setting. |
256
|
|
|
* @return bool Whether to cache with file extensions. |
257
|
|
|
*/ |
258
|
|
|
public function getCacheWithFileExtensions() |
259
|
|
|
{ |
260
|
|
|
return $this->cacheWithFileExtensions; |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
/** |
264
|
|
|
* Get cache path. |
265
|
|
|
* @param string $path Image path. |
266
|
|
|
* @param array $params Image manipulation params. |
267
|
|
|
* @return string Cache path. |
268
|
|
|
*/ |
269
|
|
|
public function getCachePath($path, array $params = []) |
270
|
|
|
{ |
271
|
|
|
$sourcePath = $this->getSourcePath($path); |
272
|
|
|
|
273
|
|
|
if ($this->sourcePathPrefix) { |
274
|
|
|
$sourcePath = substr($sourcePath, strlen($this->sourcePathPrefix) + 1); |
275
|
|
|
} |
276
|
|
|
|
277
|
|
|
$params = $this->getAllParams($params); |
278
|
|
|
unset($params['s'], $params['p']); |
279
|
|
|
ksort($params); |
280
|
|
|
|
281
|
|
|
$md5 = md5($sourcePath.'?'.http_build_query($params)); |
282
|
|
|
|
283
|
|
|
$cachedPath = $this->groupCacheInFolders ? $sourcePath.'/'.$md5 : $md5; |
284
|
|
|
|
285
|
|
|
if ($this->cachePathPrefix) { |
286
|
|
|
$cachedPath = $this->cachePathPrefix.'/'.$cachedPath; |
287
|
|
|
} |
288
|
|
|
|
289
|
|
|
if ($this->cacheWithFileExtensions) { |
290
|
|
|
$ext = (isset($params['fm']) ? $params['fm'] : pathinfo($path)['extension']); |
291
|
|
|
$ext = ($ext === 'pjpg') ? 'jpg' : $ext; |
292
|
|
|
$cachedPath .= '.'.$ext; |
293
|
|
|
} |
294
|
|
|
|
295
|
|
|
return $cachedPath; |
296
|
|
|
} |
297
|
|
|
|
298
|
|
|
/** |
299
|
|
|
* Check if a cache file exists. |
300
|
|
|
* @param string $path Image path. |
301
|
|
|
* @param array $params Image manipulation params. |
302
|
|
|
* @return bool Whether the cache file exists. |
303
|
|
|
*/ |
304
|
|
|
public function cacheFileExists($path, array $params) |
305
|
|
|
{ |
306
|
|
|
if ($this->cache instanceof FilesystemInterface) { |
|
|
|
|
307
|
|
|
return $this->cache->has( |
308
|
|
|
$this->getCachePath($path, $params) |
309
|
|
|
); |
310
|
|
|
} |
311
|
|
|
|
312
|
|
|
return $this->cache->fileExists( |
313
|
|
|
$this->getCachePath($path, $params) |
314
|
|
|
); |
315
|
|
|
} |
316
|
|
|
|
317
|
|
|
/** |
318
|
|
|
* Delete cached manipulations for an image. |
319
|
|
|
* @param string $path Image path. |
320
|
|
|
* @return bool Whether the delete succeeded. |
321
|
|
|
*/ |
322
|
|
|
public function deleteCache($path) |
323
|
|
|
{ |
324
|
|
|
if (!$this->groupCacheInFolders) { |
325
|
|
|
throw new InvalidArgumentException( |
326
|
|
|
'Deleting cached image manipulations is not possible when grouping cache into folders is disabled.' |
327
|
|
|
); |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
if ($this->cache instanceof FilesystemInterface) { |
|
|
|
|
331
|
|
|
return $this->cache->deleteDir( |
332
|
|
|
dirname($this->getCachePath($path)) |
333
|
|
|
); |
334
|
|
|
} |
335
|
|
|
|
336
|
|
|
return $this->cache->deleteDirectory( |
337
|
|
|
dirname($this->getCachePath($path)) |
338
|
|
|
); |
339
|
|
|
} |
340
|
|
|
|
341
|
|
|
/** |
342
|
|
|
* Set image manipulation API. |
343
|
|
|
* @param ApiInterface $api Image manipulation API. |
344
|
|
|
*/ |
345
|
|
|
public function setApi(ApiInterface $api) |
346
|
|
|
{ |
347
|
|
|
$this->api = $api; |
348
|
|
|
} |
349
|
|
|
|
350
|
|
|
/** |
351
|
|
|
* Get image manipulation API. |
352
|
|
|
* @return ApiInterface Image manipulation API. |
353
|
|
|
*/ |
354
|
|
|
public function getApi() |
355
|
|
|
{ |
356
|
|
|
return $this->api; |
357
|
|
|
} |
358
|
|
|
|
359
|
|
|
/** |
360
|
|
|
* Set default image manipulations. |
361
|
|
|
* @param array $defaults Default image manipulations. |
362
|
|
|
*/ |
363
|
|
|
public function setDefaults(array $defaults) |
364
|
|
|
{ |
365
|
|
|
$this->defaults = $defaults; |
366
|
|
|
} |
367
|
|
|
|
368
|
|
|
/** |
369
|
|
|
* Get default image manipulations. |
370
|
|
|
* @return array Default image manipulations. |
371
|
|
|
*/ |
372
|
|
|
public function getDefaults() |
373
|
|
|
{ |
374
|
|
|
return $this->defaults; |
375
|
|
|
} |
376
|
|
|
|
377
|
|
|
/** |
378
|
|
|
* Set preset image manipulations. |
379
|
|
|
* @param array $presets Preset image manipulations. |
380
|
|
|
*/ |
381
|
|
|
public function setPresets(array $presets) |
382
|
|
|
{ |
383
|
|
|
$this->presets = $presets; |
384
|
|
|
} |
385
|
|
|
|
386
|
|
|
/** |
387
|
|
|
* Get preset image manipulations. |
388
|
|
|
* @return array Preset image manipulations. |
389
|
|
|
*/ |
390
|
|
|
public function getPresets() |
391
|
|
|
{ |
392
|
|
|
return $this->presets; |
393
|
|
|
} |
394
|
|
|
|
395
|
|
|
/** |
396
|
|
|
* Get all image manipulations params, including defaults and presets. |
397
|
|
|
* @param array $params Image manipulation params. |
398
|
|
|
* @return array All image manipulation params. |
399
|
|
|
*/ |
400
|
|
|
public function getAllParams(array $params) |
401
|
|
|
{ |
402
|
|
|
$all = $this->defaults; |
403
|
|
|
|
404
|
|
|
if (isset($params['p'])) { |
405
|
|
|
foreach (explode(',', $params['p']) as $preset) { |
406
|
|
|
if (isset($this->presets[$preset])) { |
407
|
|
|
$all = array_merge($all, $this->presets[$preset]); |
408
|
|
|
} |
409
|
|
|
} |
410
|
|
|
} |
411
|
|
|
|
412
|
|
|
return array_merge($all, $params); |
413
|
|
|
} |
414
|
|
|
|
415
|
|
|
/** |
416
|
|
|
* Set response factory. |
417
|
|
|
* @param ResponseFactoryInterface|null $responseFactory Response factory. |
418
|
|
|
*/ |
419
|
|
|
public function setResponseFactory(ResponseFactoryInterface $responseFactory = null) |
420
|
|
|
{ |
421
|
|
|
$this->responseFactory = $responseFactory; |
422
|
|
|
} |
423
|
|
|
|
424
|
|
|
/** |
425
|
|
|
* Get response factory. |
426
|
|
|
* @return ResponseFactoryInterface Response factory. |
427
|
|
|
*/ |
428
|
|
|
public function getResponseFactory() |
429
|
|
|
{ |
430
|
|
|
return $this->responseFactory; |
431
|
|
|
} |
432
|
|
|
|
433
|
|
|
/** |
434
|
|
|
* Generate and return image response. |
435
|
|
|
* @param string $path Image path. |
436
|
|
|
* @param array $params Image manipulation params. |
437
|
|
|
* @return mixed Image response. |
438
|
|
|
* @throws InvalidArgumentException |
439
|
|
|
*/ |
440
|
|
|
public function getImageResponse($path, array $params) |
441
|
|
|
{ |
442
|
|
|
if (is_null($this->responseFactory)) { |
443
|
|
|
throw new InvalidArgumentException( |
444
|
|
|
'Unable to get image response, no response factory defined.' |
445
|
|
|
); |
446
|
|
|
} |
447
|
|
|
|
448
|
|
|
$path = $this->makeImage($path, $params); |
449
|
|
|
|
450
|
|
|
return $this->responseFactory->create($this->cache, $path); |
|
|
|
|
451
|
|
|
} |
452
|
|
|
|
453
|
|
|
/** |
454
|
|
|
* Generate and return Base64 encoded image. |
455
|
|
|
* @param string $path Image path. |
456
|
|
|
* @param array $params Image manipulation params. |
457
|
|
|
* @return string Base64 encoded image. |
458
|
|
|
* @throws FilesystemException |
459
|
|
|
*/ |
460
|
|
|
public function getImageAsBase64($path, array $params) |
461
|
|
|
{ |
462
|
|
|
$path = $this->makeImage($path, $params); |
463
|
|
|
|
464
|
|
|
try { |
465
|
|
|
$source = $this->cache->read($path); |
466
|
|
|
} catch (UnableToReadFile $exception) { |
467
|
|
|
$source = false; |
468
|
|
|
} |
469
|
|
|
|
470
|
|
|
if ($source === false) { |
471
|
|
|
throw new FilesystemException( |
472
|
|
|
'Could not read the image `'.$path.'`.' |
473
|
|
|
); |
474
|
|
|
} |
475
|
|
|
|
476
|
|
|
if ($this->cache instanceof FilesystemInterface) { |
|
|
|
|
477
|
|
|
return 'data:'.$this->cache->getMimetype($path).';base64,'.base64_encode($source); |
478
|
|
|
} |
479
|
|
|
|
480
|
|
|
return 'data:'.$this->cache->mimeType($path).';base64,'.base64_encode($source); |
481
|
|
|
} |
482
|
|
|
|
483
|
|
|
/** |
484
|
|
|
* Generate and output image. |
485
|
|
|
* @param string $path Image path. |
486
|
|
|
* @param array $params Image manipulation params. |
487
|
|
|
* @throws InvalidArgumentException |
488
|
|
|
*/ |
489
|
|
|
public function outputImage($path, array $params) |
490
|
|
|
{ |
491
|
|
|
$path = $this->makeImage($path, $params); |
492
|
|
|
|
493
|
|
|
if ($this->cache instanceof FilesystemInterface) { |
|
|
|
|
494
|
|
|
header('Content-Type:'.$this->cache->getMimetype($path)); |
495
|
|
|
header('Content-Length:'.$this->cache->getSize($path)); |
496
|
|
|
} else { |
497
|
|
|
header('Content-Type:'.$this->cache->mimeType($path)); |
498
|
|
|
header('Content-Length:'.$this->cache->fileSize($path)); |
499
|
|
|
} |
500
|
|
|
header('Cache-Control:'.'max-age=31536000, public'); |
501
|
|
|
header('Expires:'.date_create('+1 years')->format('D, d M Y H:i:s').' GMT'); |
502
|
|
|
|
503
|
|
|
$stream = $this->cache->readStream($path); |
504
|
|
|
|
505
|
|
|
if (ftell($stream) !== 0) { |
506
|
|
|
rewind($stream); |
507
|
|
|
} |
508
|
|
|
fpassthru($stream); |
509
|
|
|
fclose($stream); |
510
|
|
|
} |
511
|
|
|
|
512
|
|
|
/** |
513
|
|
|
* Generate manipulated image. |
514
|
|
|
* @param string $path Image path. |
515
|
|
|
* @param array $params Image manipulation params. |
516
|
|
|
* @return string Cache path. |
517
|
|
|
* @throws FileNotFoundException |
518
|
|
|
* @throws FilesystemException |
519
|
|
|
*/ |
520
|
|
|
public function makeImage($path, array $params) |
521
|
|
|
{ |
522
|
|
|
$sourcePath = $this->getSourcePath($path); |
523
|
|
|
$cachedPath = $this->getCachePath($path, $params); |
524
|
|
|
|
525
|
|
|
if ($this->cacheFileExists($path, $params) === true) { |
526
|
|
|
return $cachedPath; |
527
|
|
|
} |
528
|
|
|
|
529
|
|
|
if ($this->sourceFileExists($path) === false) { |
530
|
|
|
throw new FileNotFoundException( |
531
|
|
|
'Could not find the image `'.$sourcePath.'`.' |
532
|
|
|
); |
533
|
|
|
} |
534
|
|
|
|
535
|
|
|
try { |
536
|
|
|
$source = $this->source->read( |
537
|
|
|
$sourcePath |
538
|
|
|
); |
539
|
|
|
} catch (UnableToReadFile $exception) { |
540
|
|
|
$source = false; |
541
|
|
|
} |
542
|
|
|
|
543
|
|
|
if ($source === false) { |
544
|
|
|
throw new FilesystemException( |
545
|
|
|
'Could not read the image `'.$sourcePath.'`.' |
546
|
|
|
); |
547
|
|
|
} |
548
|
|
|
|
549
|
|
|
// We need to write the image to the local disk before |
550
|
|
|
// doing any manipulations. This is because EXIF data |
551
|
|
|
// can only be read from an actual file. |
552
|
|
|
$tmp = tempnam(sys_get_temp_dir(), 'Glide'); |
553
|
|
|
|
554
|
|
|
if (file_put_contents($tmp, $source) === false) { |
555
|
|
|
throw new FilesystemException( |
556
|
|
|
'Unable to write temp file for `'.$sourcePath.'`.' |
557
|
|
|
); |
558
|
|
|
} |
559
|
|
|
|
560
|
|
|
try { |
561
|
|
|
$write = $this->cache->write( |
562
|
|
|
$cachedPath, |
563
|
|
|
$this->api->run($tmp, $this->getAllParams($params)) |
564
|
|
|
); |
565
|
|
|
|
566
|
|
|
if ($write === false) { |
567
|
|
|
throw new FilesystemException( |
568
|
|
|
'Could not write the image `'.$cachedPath.'`.' |
569
|
|
|
); |
570
|
|
|
} |
571
|
|
|
} catch (FileExistsException $exception) { |
|
|
|
|
572
|
|
|
// This edge case occurs when the target already exists |
573
|
|
|
// because it's currently be written to disk in another |
574
|
|
|
// request. It's best to just fail silently. |
575
|
|
|
} finally { |
576
|
|
|
unlink($tmp); |
577
|
|
|
} |
578
|
|
|
|
579
|
|
|
return $cachedPath; |
580
|
|
|
} |
581
|
|
|
} |
582
|
|
|
|
This error could be the result of:
1. Missing dependencies
PHP Analyzer uses your
composer.json
file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects thecomposer.json
to be in the root folder of your repository.Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the
require
orrequire-dev
section?2. Missing use statement
PHP does not complain about undefined classes in
ìnstanceof
checks. For example, the following PHP code will work perfectly fine:If you have not tested against this specific condition, such errors might go unnoticed.