These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Spatie\MediaLibrary\HasMedia; |
||
4 | |||
5 | use DateTimeInterface; |
||
6 | use Illuminate\Http\File; |
||
7 | use Illuminate\Support\Collection; |
||
8 | use Spatie\MediaLibrary\Models\Media; |
||
9 | use Spatie\MediaLibrary\MediaRepository; |
||
10 | use Illuminate\Support\Facades\Validator; |
||
11 | use Spatie\MediaLibrary\FileAdder\FileAdder; |
||
12 | use Illuminate\Database\Eloquent\SoftDeletes; |
||
13 | use Spatie\MediaLibrary\Conversion\Conversion; |
||
14 | use Spatie\MediaLibrary\FileAdder\FileAdderFactory; |
||
15 | use Spatie\MediaLibrary\Events\CollectionHasBeenCleared; |
||
16 | use Spatie\MediaLibrary\Exceptions\MediaCannotBeDeleted; |
||
17 | use Spatie\MediaLibrary\Exceptions\MediaCannotBeUpdated; |
||
18 | use Spatie\MediaLibrary\MediaCollection\MediaCollection; |
||
19 | use Spatie\MediaLibrary\Exceptions\FileCannotBeAdded\UnreachableUrl; |
||
20 | use Spatie\MediaLibrary\Exceptions\FileCannotBeAdded\InvalidBase64Data; |
||
21 | use Spatie\MediaLibrary\Exceptions\FileCannotBeAdded\MimeTypeNotAllowed; |
||
22 | |||
23 | trait HasMediaTrait |
||
24 | { |
||
25 | /** @var array */ |
||
26 | public $mediaConversions = []; |
||
27 | |||
28 | /** @var array */ |
||
29 | public $mediaCollections = []; |
||
30 | |||
31 | /** @var bool */ |
||
32 | protected $deletePreservingMedia = false; |
||
33 | |||
34 | /** @var array */ |
||
35 | protected $unAttachedMediaLibraryItems = []; |
||
36 | |||
37 | public static function bootHasMediaTrait() |
||
38 | { |
||
39 | static::deleting(function (HasMedia $entity) { |
||
40 | if ($entity->shouldDeletePreservingMedia()) { |
||
41 | return; |
||
42 | } |
||
43 | |||
44 | if (in_array(SoftDeletes::class, class_uses_recursive($entity))) { |
||
45 | if (! $entity->forceDeleting) { |
||
46 | return; |
||
47 | } |
||
48 | } |
||
49 | |||
50 | $entity->media()->get()->each->delete(); |
||
51 | }); |
||
52 | } |
||
53 | |||
54 | /** |
||
55 | * Set the polymorphic relation. |
||
56 | * |
||
57 | * @return \Illuminate\Database\Eloquent\Relations\MorphMany |
||
58 | */ |
||
59 | public function media() |
||
60 | { |
||
61 | return $this->morphMany(config('medialibrary.media_model'), 'model'); |
||
62 | } |
||
63 | |||
64 | /** |
||
65 | * Add a file to the medialibrary. |
||
66 | * |
||
67 | * @param string|\Symfony\Component\HttpFoundation\File\UploadedFile $file |
||
68 | * |
||
69 | * @return \Spatie\MediaLibrary\FileAdder\FileAdder |
||
70 | */ |
||
71 | public function addMedia($file) |
||
72 | { |
||
73 | return app(FileAdderFactory::class)->create($this, $file); |
||
74 | } |
||
75 | |||
76 | /** |
||
77 | * Add a file from a request. |
||
78 | * |
||
79 | * @param string $key |
||
80 | * |
||
81 | * @return \Spatie\MediaLibrary\FileAdder\FileAdder |
||
82 | */ |
||
83 | public function addMediaFromRequest(string $key) |
||
84 | { |
||
85 | return app(FileAdderFactory::class)->createFromRequest($this, $key); |
||
86 | } |
||
87 | |||
88 | /** |
||
89 | * Add multiple files from a request by keys. |
||
90 | * |
||
91 | * @param string[] $keys |
||
92 | * |
||
93 | * @return \Spatie\MediaLibrary\FileAdder\FileAdder[] |
||
94 | */ |
||
95 | public function addMultipleMediaFromRequest(array $keys) |
||
96 | { |
||
97 | return app(FileAdderFactory::class)->createMultipleFromRequest($this, $keys); |
||
98 | } |
||
99 | |||
100 | /** |
||
101 | * Add all files from a request. |
||
102 | * |
||
103 | * @return \Spatie\MediaLibrary\FileAdder\FileAdder[] |
||
104 | */ |
||
105 | public function addAllMediaFromRequest() |
||
106 | { |
||
107 | return app(FileAdderFactory::class)->createAllFromRequest($this); |
||
108 | } |
||
109 | |||
110 | /** |
||
111 | * Add a remote file to the medialibrary. |
||
112 | * |
||
113 | * @param string $url |
||
114 | * @param string|array ...$allowedMimeTypes |
||
115 | * |
||
116 | * @return \Spatie\MediaLibrary\FileAdder\FileAdder |
||
117 | * |
||
118 | * @throws \Spatie\MediaLibrary\Exceptions\FileCannotBeAdded |
||
119 | */ |
||
120 | public function addMediaFromUrl(string $url, ...$allowedMimeTypes) |
||
121 | { |
||
122 | if (! $stream = @fopen($url, 'r')) { |
||
123 | throw UnreachableUrl::create($url); |
||
124 | } |
||
125 | |||
126 | $temporaryFile = tempnam(sys_get_temp_dir(), 'media-library'); |
||
127 | file_put_contents($temporaryFile, $stream); |
||
128 | |||
129 | $this->guardAgainstInvalidMimeType($temporaryFile, $allowedMimeTypes); |
||
130 | |||
131 | $filename = basename(parse_url($url, PHP_URL_PATH)); |
||
132 | $filename = str_replace('%20', ' ', $filename); |
||
133 | |||
134 | if ($filename === '') { |
||
135 | $filename = 'file'; |
||
136 | } |
||
137 | |||
138 | $mediaExtension = explode('/', mime_content_type($temporaryFile)); |
||
139 | |||
140 | if (! str_contains($filename, '.')) { |
||
0 ignored issues
–
show
|
|||
141 | $filename = "{$filename}.{$mediaExtension[1]}"; |
||
142 | } |
||
143 | |||
144 | return app(FileAdderFactory::class) |
||
145 | ->create($this, $temporaryFile) |
||
146 | ->usingName(pathinfo($filename, PATHINFO_FILENAME)) |
||
147 | ->usingFileName($filename); |
||
148 | } |
||
149 | |||
150 | /** |
||
151 | * Add a base64 encoded file to the medialibrary. |
||
152 | * |
||
153 | * @param string $base64data |
||
154 | * @param string|array ...$allowedMimeTypes |
||
155 | * |
||
156 | * @throws InvalidBase64Data |
||
157 | * @throws \Spatie\MediaLibrary\Exceptions\FileCannotBeAdded |
||
158 | * |
||
159 | * @return \Spatie\MediaLibrary\FileAdder\FileAdder |
||
160 | */ |
||
161 | public function addMediaFromBase64(string $base64data, ...$allowedMimeTypes): FileAdder |
||
162 | { |
||
163 | // strip out data uri scheme information (see RFC 2397) |
||
164 | if (strpos($base64data, ';base64') !== false) { |
||
165 | [$_, $base64data] = explode(';', $base64data); |
||
166 | [$_, $base64data] = explode(',', $base64data); |
||
167 | } |
||
168 | |||
169 | // strict mode filters for non-base64 alphabet characters |
||
170 | if (base64_decode($base64data, true) === false) { |
||
171 | throw InvalidBase64Data::create(); |
||
172 | } |
||
173 | |||
174 | // decoding and then reencoding should not change the data |
||
175 | if (base64_encode(base64_decode($base64data)) !== $base64data) { |
||
176 | throw InvalidBase64Data::create(); |
||
177 | } |
||
178 | |||
179 | $binaryData = base64_decode($base64data); |
||
180 | |||
181 | // temporarily store the decoded data on the filesystem to be able to pass it to the fileAdder |
||
182 | $tmpFile = tempnam(sys_get_temp_dir(), 'medialibrary'); |
||
183 | file_put_contents($tmpFile, $binaryData); |
||
184 | |||
185 | $this->guardAgainstInvalidMimeType($tmpFile, $allowedMimeTypes); |
||
186 | |||
187 | $file = app(FileAdderFactory::class)->create($this, $tmpFile); |
||
188 | |||
189 | return $file; |
||
190 | } |
||
191 | |||
192 | /** |
||
193 | * Copy a file to the medialibrary. |
||
194 | * |
||
195 | * @param string|\Symfony\Component\HttpFoundation\File\UploadedFile $file |
||
196 | * |
||
197 | * @return \Spatie\MediaLibrary\FileAdder\FileAdder |
||
198 | */ |
||
199 | public function copyMedia($file) |
||
200 | { |
||
201 | return $this->addMedia($file)->preservingOriginal(); |
||
202 | } |
||
203 | |||
204 | /* |
||
205 | * Determine if there is media in the given collection. |
||
206 | */ |
||
207 | public function hasMedia(string $collectionName = 'default'): bool |
||
208 | { |
||
209 | return count($this->getMedia($collectionName)) ? true : false; |
||
210 | } |
||
211 | |||
212 | /** |
||
213 | * Get media collection by its collectionName. |
||
214 | * |
||
215 | * @param string $collectionName |
||
216 | * @param array|callable $filters |
||
217 | * |
||
218 | * @return \Illuminate\Support\Collection |
||
219 | */ |
||
220 | public function getMedia(string $collectionName = 'default', $filters = []): Collection |
||
221 | { |
||
222 | return app(MediaRepository::class)->getCollection($this, $collectionName, $filters); |
||
223 | } |
||
224 | |||
225 | public function getFirstMedia(string $collectionName = 'default', array $filters = []): ?Media |
||
226 | { |
||
227 | $media = $this->getMedia($collectionName, $filters); |
||
228 | |||
229 | return $media->first(); |
||
230 | } |
||
231 | |||
232 | /* |
||
233 | * Get the url of the image for the given conversionName |
||
234 | * for first media for the given collectionName. |
||
235 | * If no profile is given, return the source's url. |
||
236 | */ |
||
237 | public function getFirstMediaUrl(string $collectionName = 'default', string $conversionName = ''): string |
||
238 | { |
||
239 | $media = $this->getFirstMedia($collectionName); |
||
240 | |||
241 | if (! $media) { |
||
242 | return ''; |
||
243 | } |
||
244 | |||
245 | return $media->getUrl($conversionName); |
||
246 | } |
||
247 | |||
248 | /* |
||
249 | * Get the url of the image for the given conversionName |
||
250 | * for first media for the given collectionName. |
||
251 | * If no profile is given, return the source's url. |
||
252 | */ |
||
253 | public function getFirstTemporaryUrl(DateTimeInterface $expiration, string $collectionName = 'default', string $conversionName = ''): string |
||
254 | { |
||
255 | $media = $this->getFirstMedia($collectionName); |
||
256 | |||
257 | if (! $media) { |
||
258 | return ''; |
||
259 | } |
||
260 | |||
261 | return $media->getTemporaryUrl($expiration, $conversionName); |
||
262 | } |
||
263 | |||
264 | /* |
||
265 | * Get the url of the image for the given conversionName |
||
266 | * for first media for the given collectionName. |
||
267 | * If no profile is given, return the source's url. |
||
268 | */ |
||
269 | public function getFirstMediaPath(string $collectionName = 'default', string $conversionName = ''): string |
||
270 | { |
||
271 | $media = $this->getFirstMedia($collectionName); |
||
272 | |||
273 | if (! $media) { |
||
274 | return ''; |
||
275 | } |
||
276 | |||
277 | return $media->getPath($conversionName); |
||
278 | } |
||
279 | |||
280 | /** |
||
281 | * Update a media collection by deleting and inserting again with new values. |
||
282 | * |
||
283 | * @param array $newMediaArray |
||
284 | * @param string $collectionName |
||
285 | * |
||
286 | * @return \Illuminate\Support\Collection |
||
287 | * |
||
288 | * @throws \Spatie\MediaLibrary\Exceptions\MediaCannotBeUpdated |
||
289 | */ |
||
290 | public function updateMedia(array $newMediaArray, string $collectionName = 'default'): Collection |
||
291 | { |
||
292 | $this->removeMediaItemsNotPresentInArray($newMediaArray, $collectionName); |
||
293 | |||
294 | return collect($newMediaArray) |
||
295 | ->map(function (array $newMediaItem) use ($collectionName) { |
||
296 | static $orderColumn = 1; |
||
297 | |||
298 | $mediaClass = config('medialibrary.media_model'); |
||
299 | $currentMedia = $mediaClass::findOrFail($newMediaItem['id']); |
||
300 | |||
301 | if ($currentMedia->collection_name !== $collectionName) { |
||
302 | throw MediaCannotBeUpdated::doesNotBelongToCollection($collectionName, $currentMedia); |
||
303 | } |
||
304 | |||
305 | if (array_key_exists('name', $newMediaItem)) { |
||
306 | $currentMedia->name = $newMediaItem['name']; |
||
307 | } |
||
308 | |||
309 | if (array_key_exists('custom_properties', $newMediaItem)) { |
||
310 | $currentMedia->custom_properties = $newMediaItem['custom_properties']; |
||
311 | } |
||
312 | |||
313 | $currentMedia->order_column = $orderColumn++; |
||
314 | |||
315 | $currentMedia->save(); |
||
316 | |||
317 | return $currentMedia; |
||
318 | }); |
||
319 | } |
||
320 | |||
321 | protected function removeMediaItemsNotPresentInArray(array $newMediaArray, string $collectionName = 'default') |
||
322 | { |
||
323 | $this->getMedia($collectionName) |
||
324 | ->reject(function (Media $currentMediaItem) use ($newMediaArray) { |
||
325 | return in_array($currentMediaItem->id, array_column($newMediaArray, 'id')); |
||
326 | }) |
||
327 | ->each->delete(); |
||
328 | } |
||
329 | |||
330 | /** |
||
331 | * Remove all media in the given collection. |
||
332 | * |
||
333 | * @param string $collectionName |
||
334 | * |
||
335 | * @return $this |
||
336 | */ |
||
337 | public function clearMediaCollection(string $collectionName = 'default'): self |
||
338 | { |
||
339 | $this->getMedia($collectionName) |
||
340 | ->each->delete(); |
||
341 | |||
342 | event(new CollectionHasBeenCleared($this, $collectionName)); |
||
343 | |||
344 | if ($this->mediaIsPreloaded()) { |
||
345 | unset($this->media); |
||
346 | } |
||
347 | |||
348 | return $this; |
||
349 | } |
||
350 | |||
351 | /** |
||
352 | * Remove all media in the given collection except some. |
||
353 | * |
||
354 | * @param string $collectionName |
||
355 | * @param \Spatie\MediaLibrary\Models\Media[]|\Illuminate\Support\Collection $excludedMedia |
||
356 | * |
||
357 | * @return $this |
||
358 | */ |
||
359 | public function clearMediaCollectionExcept(string $collectionName = 'default', $excludedMedia = []) |
||
360 | { |
||
361 | if ($excludedMedia instanceof Media) { |
||
362 | $excludedMedia = collect()->push($excludedMedia); |
||
363 | } |
||
364 | |||
365 | $excludedMedia = collect($excludedMedia); |
||
366 | |||
367 | if ($excludedMedia->isEmpty()) { |
||
368 | return $this->clearMediaCollection($collectionName); |
||
369 | } |
||
370 | |||
371 | $this->getMedia($collectionName) |
||
372 | ->reject(function (Media $media) use ($excludedMedia) { |
||
373 | return $excludedMedia->where('id', $media->id)->count(); |
||
374 | }) |
||
375 | ->each->delete(); |
||
376 | |||
377 | if ($this->mediaIsPreloaded()) { |
||
378 | unset($this->media); |
||
379 | } |
||
380 | |||
381 | return $this; |
||
382 | } |
||
383 | |||
384 | /** |
||
385 | * Delete the associated media with the given id. |
||
386 | * You may also pass a media object. |
||
387 | * |
||
388 | * @param int|\Spatie\MediaLibrary\Models\Media $mediaId |
||
389 | * |
||
390 | * @throws \Spatie\MediaLibrary\Exceptions\MediaCannotBeDeleted |
||
391 | */ |
||
392 | public function deleteMedia($mediaId) |
||
393 | { |
||
394 | if ($mediaId instanceof Media) { |
||
395 | $mediaId = $mediaId->id; |
||
396 | } |
||
397 | |||
398 | $media = $this->media->find($mediaId); |
||
399 | |||
400 | if (! $media) { |
||
401 | throw MediaCannotBeDeleted::doesNotBelongToModel($mediaId, $this); |
||
402 | } |
||
403 | |||
404 | $media->delete(); |
||
405 | } |
||
406 | |||
407 | /* |
||
408 | * Add a conversion. |
||
409 | */ |
||
410 | public function addMediaConversion(string $name): Conversion |
||
411 | { |
||
412 | $conversion = Conversion::create($name); |
||
413 | |||
414 | $this->mediaConversions[] = $conversion; |
||
415 | |||
416 | return $conversion; |
||
417 | } |
||
418 | |||
419 | public function addMediaCollection(string $name): MediaCollection |
||
420 | { |
||
421 | $mediaCollection = MediaCollection::create($name); |
||
422 | |||
423 | $this->mediaCollections[] = $mediaCollection; |
||
424 | |||
425 | return $mediaCollection; |
||
426 | } |
||
427 | |||
428 | /** |
||
429 | * Delete the model, but preserve all the associated media. |
||
430 | * |
||
431 | * @return bool |
||
432 | */ |
||
433 | public function deletePreservingMedia(): bool |
||
434 | { |
||
435 | $this->deletePreservingMedia = true; |
||
436 | |||
437 | return $this->delete(); |
||
438 | } |
||
439 | |||
440 | /** |
||
441 | * Determines if the media files should be preserved when the media object gets deleted. |
||
442 | * |
||
443 | * @return bool |
||
444 | */ |
||
445 | public function shouldDeletePreservingMedia() |
||
446 | { |
||
447 | return $this->deletePreservingMedia ?? false; |
||
448 | } |
||
449 | |||
450 | protected function mediaIsPreloaded(): bool |
||
451 | { |
||
452 | return $this->relationLoaded('media'); |
||
453 | } |
||
454 | |||
455 | /** |
||
456 | * Cache the media on the object. |
||
457 | * |
||
458 | * @param string $collectionName |
||
459 | * |
||
460 | * @return mixed |
||
461 | */ |
||
462 | public function loadMedia(string $collectionName) |
||
463 | { |
||
464 | $collection = $this->exists |
||
465 | ? $this->media |
||
466 | : collect($this->unAttachedMediaLibraryItems)->pluck('media'); |
||
467 | |||
468 | return $collection |
||
469 | ->filter(function (Media $mediaItem) use ($collectionName) { |
||
470 | if ($collectionName == '') { |
||
471 | return true; |
||
472 | } |
||
473 | |||
474 | return $mediaItem->collection_name === $collectionName; |
||
475 | }) |
||
476 | ->sortBy('order_column') |
||
477 | ->values(); |
||
478 | } |
||
479 | |||
480 | public function prepareToAttachMedia(Media $media, FileAdder $fileAdder) |
||
481 | { |
||
482 | $this->unAttachedMediaLibraryItems[] = compact('media', 'fileAdder'); |
||
483 | } |
||
484 | |||
485 | public function processUnattachedMedia(callable $callable) |
||
486 | { |
||
487 | foreach ($this->unAttachedMediaLibraryItems as $item) { |
||
488 | $callable($item['media'], $item['fileAdder']); |
||
489 | } |
||
490 | |||
491 | $this->unAttachedMediaLibraryItems = []; |
||
492 | } |
||
493 | |||
494 | protected function guardAgainstInvalidMimeType(string $file, ...$allowedMimeTypes) |
||
495 | { |
||
496 | $allowedMimeTypes = array_flatten($allowedMimeTypes); |
||
0 ignored issues
–
show
The function
array_flatten() has been deprecated with message: Arr::flatten() should be used directly instead. Will be removed in Laravel 5.9.
This function has been deprecated. The supplier of the file has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.
Loading history...
|
|||
497 | |||
498 | if (empty($allowedMimeTypes)) { |
||
499 | return; |
||
500 | } |
||
501 | |||
502 | $validation = Validator::make( |
||
503 | ['file' => new File($file)], |
||
504 | ['file' => 'mimetypes:'.implode(',', $allowedMimeTypes)] |
||
505 | ); |
||
506 | |||
507 | if ($validation->fails()) { |
||
508 | throw MimeTypeNotAllowed::create($file, $allowedMimeTypes); |
||
509 | } |
||
510 | } |
||
511 | |||
512 | public function registerMediaConversions(Media $media = null) |
||
513 | { |
||
514 | } |
||
515 | |||
516 | public function registerMediaCollections() |
||
517 | { |
||
518 | } |
||
519 | |||
520 | public function registerAllMediaConversions(Media $media = null) |
||
521 | { |
||
522 | $this->registerMediaCollections(); |
||
523 | |||
524 | collect($this->mediaCollections)->each(function (MediaCollection $mediaCollection) use ($media) { |
||
525 | $actualMediaConversions = $this->mediaConversions; |
||
526 | |||
527 | $this->mediaConversions = []; |
||
528 | |||
529 | ($mediaCollection->mediaConversionRegistrations)($media); |
||
530 | |||
531 | $preparedMediaConversions = collect($this->mediaConversions) |
||
532 | ->each(function (Conversion $conversion) use ($mediaCollection) { |
||
533 | $conversion->performOnCollections($mediaCollection->name); |
||
534 | }) |
||
535 | ->values() |
||
536 | ->toArray(); |
||
537 | |||
538 | $this->mediaConversions = array_merge($actualMediaConversions, $preparedMediaConversions); |
||
539 | }); |
||
540 | |||
541 | $this->registerMediaConversions($media); |
||
542 | } |
||
543 | } |
||
544 |
This function has been deprecated. The supplier of the file has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.