Completed
Push — master ( 0406ad...05b406 )
by Freek
29:56 queued 16:17
created

HasMediaTrait::addMultipleMediaFromRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace Spatie\MediaLibrary\HasMedia;
4
5
use Spatie\MediaLibrary\Media;
6
use Illuminate\Support\Collection;
7
use Spatie\MediaLibrary\MediaRepository;
8
use Spatie\MediaLibrary\Conversion\Conversion;
9
use Spatie\MediaLibrary\Filesystem\Filesystem;
10
use Spatie\MediaLibrary\FileAdder\FileAdderFactory;
11
use Spatie\MediaLibrary\HasMedia\Interfaces\HasMedia;
12
use Spatie\MediaLibrary\Events\CollectionHasBeenCleared;
13
use Spatie\MediaLibrary\Exceptions\MediaCannotBeDeleted;
14
use Spatie\MediaLibrary\Exceptions\MediaCannotBeUpdated;
15
use Spatie\MediaLibrary\Exceptions\FileCannotBeAdded\UnreachableUrl;
16
use Spatie\MediaLibrary\Exceptions\FileCannotBeAdded\InvalidBase64Data;
17
18
trait HasMediaTrait
19
{
20
    /** @var array */
21
    public $mediaConversions = [];
22
23
    /** @var bool */
24
    protected $deletePreservingMedia = false;
25
26
    public static function bootHasMediaTrait()
27
    {
28
        static::deleted(function (HasMedia $entity) {
29
            if ($entity->shouldDeletePreservingMedia()) {
30
                return;
31
            }
32
33
            $entity->media()->get()->each->delete();
34
        });
35
    }
36
37
    /**
38
     * Set the polymorphic relation.
39
     *
40
     * @return mixed
41
     */
42
    public function media()
43
    {
44
        return $this->morphMany(config('medialibrary.media_model'), 'model');
45
    }
46
47
    /**
48
     * Add a file to the medialibrary.
49
     *
50
     * @param string|\Symfony\Component\HttpFoundation\File\UploadedFile $file
51
     *
52
     * @return \Spatie\MediaLibrary\FileAdder\FileAdder
53
     */
54
    public function addMedia($file)
55
    {
56
        return app(FileAdderFactory::class)->create($this, $file);
57
    }
58
59
    /**
60
     * Add a file from a request.
61
     *
62
     * @param string $key
63
     *
64
     * @return \Spatie\MediaLibrary\FileAdder\FileAdder
65
     */
66
    public function addMediaFromRequest(string $key)
67
    {
68
        return app(FileAdderFactory::class)->createFromRequest($this, $key);
69
    }
70
71
    /**
72
     * Add multiple files from a request by keys.
73
     *
74
     * @param string[] $keys
75
     *
76
     * @return \Spatie\MediaLibrary\FileAdder\FileAdder[]
77
     */
78
    public function addMultipleMediaFromRequest(array $keys)
79
    {
80
        return app(FileAdderFactory::class)->createMultipleFromRequest($this, $keys);
81
    }
82
83
    /**
84
     * Add all files from a request.
85
     *
86
     * @return \Spatie\MediaLibrary\FileAdder\FileAdder[]
87
     */
88
    public function addAllMediaFromRequest()
89
    {
90
        return app(FileAdderFactory::class)->createAllFromRequest($this);
91
    }
92
93
    /**
94
     * Add a remote file to the medialibrary.
95
     *
96
     * @param string $url
97
     *
98
     * @return \Spatie\MediaLibrary\FileAdder\FileAdder
99
     *
100
     * @throws \Spatie\MediaLibrary\Exceptions\FileCannotBeAdded
101
     */
102
    public function addMediaFromUrl(string $url)
103
    {
104
        if (! $stream = @fopen($url, 'r')) {
105
            throw UnreachableUrl::create($url);
106
        }
107
108
        $tmpFile = tempnam(sys_get_temp_dir(), 'media-library');
109
        file_put_contents($tmpFile, $stream);
110
111
        $filename = basename(parse_url($url, PHP_URL_PATH));
112
113
        return app(FileAdderFactory::class)
114
            ->create($this, $tmpFile)
115
            ->usingName(pathinfo($filename, PATHINFO_FILENAME))
116
            ->usingFileName($filename);
117
    }
118
119
    /**
120
     * Add a base64 encoded file to the medialibrary.
121
     *
122
     * @param string $base64data
123
     *
124
     * @throws InvalidBase64Data
125
     * @throws \Spatie\MediaLibrary\Exceptions\FileCannotBeAdded
126
     *
127
     * @return \Spatie\MediaLibrary\FileAdder\FileAdder
128
     */
129
    public function addMediaFromBase64(string $base64data)
130
    {
131
        // strip out data uri scheme information (see RFC 2397)
132
        if (strpos($base64data, ';base64') !== false) {
133
            list(, $base64data) = explode(';', $base64data);
134
            list(, $base64data) = explode(',', $base64data);
135
        }
136
137
        // strict mode filters for non-base64 alphabet characters
138
        if (base64_decode($base64data, true) === false) {
139
            throw InvalidBase64Data::create();
140
        }
141
142
        // decoding and then reeconding should not change the data
143
        if (base64_encode(base64_decode($base64data)) !== $base64data) {
144
            throw InvalidBase64Data::create();
145
        }
146
147
        $binaryData = base64_decode($base64data);
148
149
        // temporarily store the decoded data on the filesystem to be able to pass it to the fileAdder
150
        $tmpFile = tempnam(sys_get_temp_dir(), 'medialibrary');
151
        file_put_contents($tmpFile, $binaryData);
152
153
        $file = app(FileAdderFactory::class)
154
            ->create($this, $tmpFile);
155
156
        return $file;
157
    }
158
159
    /**
160
     * Copy a file to the medialibrary.
161
     *
162
     * @param string|\Symfony\Component\HttpFoundation\File\UploadedFile $file
163
     *
164
     * @return \Spatie\MediaLibrary\FileAdder\FileAdder
165
     */
166
    public function copyMedia($file)
167
    {
168
        return $this->addMedia($file)->preservingOriginal();
169
    }
170
171
    /*
172
     * Determine if there is media in the given collection.
173
     */
174
    public function hasMedia(string $collectionName = 'default'): bool
175
    {
176
        return count($this->getMedia($collectionName)) ? true : false;
177
    }
178
179
    /**
180
     * Get media collection by its collectionName.
181
     *
182
     * @param string $collectionName
183
     * @param array|callable  $filters
184
     *
185
     * @return \Illuminate\Support\Collection
186
     */
187
    public function getMedia(string $collectionName = 'default', $filters = []): Collection
188
    {
189
        return app(MediaRepository::class)->getCollection($this, $collectionName, $filters);
190
    }
191
192
    /**
193
     * Get the first media item of a media collection.
194
     *
195
     * @param string $collectionName
196
     * @param array $filters
197
     *
198
     * @return Media|null
199
     */
200
    public function getFirstMedia(string $collectionName = 'default', array $filters = [])
201
    {
202
        $media = $this->getMedia($collectionName, $filters);
203
204
        return $media->first();
205
    }
206
207
    /*
208
     * Get the url of the image for the given conversionName
209
     * for first media for the given collectionName.
210
     * If no profile is given, return the source's url.
211
     */
212
    public function getFirstMediaUrl(string $collectionName = 'default', string $conversionName = ''): string
213
    {
214
        $media = $this->getFirstMedia($collectionName);
215
216
        if (! $media) {
217
            return '';
218
        }
219
220
        return $media->getUrl($conversionName);
221
    }
222
223
    /*
224
     * Get the url of the image for the given conversionName
225
     * for first media for the given collectionName.
226
     * If no profile is given, return the source's url.
227
     */
228
    public function getFirstMediaPath(string $collectionName = 'default', string $conversionName = ''): string
229
    {
230
        $media = $this->getFirstMedia($collectionName);
231
232
        if (! $media) {
233
            return '';
234
        }
235
236
        return $media->getPath($conversionName);
237
    }
238
239
    /**
240
     * Update a media collection by deleting and inserting again with new values.
241
     *
242
     * @param array $newMediaArray
243
     * @param string $collectionName
244
     *
245
     * @return \Illuminate\Support\Collection
246
     *
247
     * @throws \Spatie\MediaLibrary\Exceptions\MediaCannotBeUpdated
248
     */
249
    public function updateMedia(array $newMediaArray, string $collectionName = 'default'): Collection
250
    {
251
        $this->removeMediaItemsNotPresentInArray($newMediaArray, $collectionName);
252
253
        return collect($newMediaArray)
254
            ->map(function (array $newMediaItem) use ($collectionName) {
255
                static $orderColumn = 1;
256
257
                $mediaClass = config('medialibrary.media_model');
258
                $currentMedia = $mediaClass::findOrFail($newMediaItem['id']);
259
260
                if ($currentMedia->collection_name != $collectionName) {
261
                    throw MediaCannotBeUpdated::doesNotBelongToCollection($collectionName, $currentMedia);
262
                }
263
264
                if (array_key_exists('name', $newMediaItem)) {
265
                    $currentMedia->name = $newMediaItem['name'];
266
                }
267
268
                if (array_key_exists('custom_properties', $newMediaItem)) {
269
                    $currentMedia->custom_properties = $newMediaItem['custom_properties'];
270
                }
271
272
                $currentMedia->order_column = $orderColumn++;
273
274
                $currentMedia->save();
275
276
                return $currentMedia;
277
            });
278
    }
279
280
    /**
281
     * @param array $newMediaArray
282
     * @param string $collectionName
283
     */
284
    protected function removeMediaItemsNotPresentInArray(array $newMediaArray, string $collectionName = 'default')
285
    {
286
        $this->getMedia($collectionName)
287
            ->reject(function (Media $currentMediaItem) use ($newMediaArray) {
288
                return in_array($currentMediaItem->id, array_column($newMediaArray, 'id'));
289
            })
290
            ->each->delete();
291
    }
292
293
    /**
294
     * Remove all media in the given collection.
295
     *
296
     * @param string $collectionName
297
     *
298
     * @return $this
299
     */
300
    public function clearMediaCollection(string $collectionName = 'default')
301
    {
302
        $this->getMedia($collectionName)
303
            ->each(function (Media $media) {
304
                app(Filesystem::class)->removeFiles($media);
305
                $media->delete();
306
            });
307
308
        event(new CollectionHasBeenCleared($this, $collectionName));
309
310
        if ($this->mediaIsPreloaded()) {
311
            unset($this->media);
312
        }
313
314
        return $this;
315
    }
316
317
    /**
318
     * Delete the associated media with the given id.
319
     * You may also pass a media object.
320
     *
321
     * @param int|\Spatie\MediaLibrary\Media $mediaId
322
     *
323
     * @throws \Spatie\MediaLibrary\Exceptions\MediaCannotBeDeleted
324
     */
325
    public function deleteMedia($mediaId)
326
    {
327
        if ($mediaId instanceof Media) {
328
            $mediaId = $mediaId->id;
329
        }
330
331
        $media = $this->media->find($mediaId);
332
333
        if (! $media) {
334
            throw MediaCannotBeDeleted::doesNotBelongToModel($media, $this);
335
        }
336
337
        $media->delete();
338
    }
339
340
    /*
341
     * Add a conversion.
342
     */
343
    public function addMediaConversion(string $name): Conversion
344
    {
345
        $conversion = Conversion::create($name);
346
347
        $this->mediaConversions[] = $conversion;
348
349
        return $conversion;
350
    }
351
352
    /**
353
     * Delete the model, but preserve all the associated media.
354
     *
355
     * @return bool
356
     */
357
    public function deletePreservingMedia(): bool
358
    {
359
        $this->deletePreservingMedia = true;
360
361
        return $this->delete();
0 ignored issues
show
Bug introduced by
The method delete() does not exist on Spatie\MediaLibrary\HasMedia\HasMediaTrait. Did you maybe mean deleteMedia()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
362
    }
363
364
    /**
365
     * Determines if the media files should be preserved when the media object gets deleted.
366
     *
367
     * @return \Spatie\MediaLibrary\Media
368
     */
369
    public function shouldDeletePreservingMedia()
370
    {
371
        return $this->deletePreservingMedia ?? false;
372
    }
373
374
    protected function mediaIsPreloaded(): bool
375
    {
376
        return isset($this->media);
377
    }
378
379
    /**
380
     * Cache the media on the object.
381
     *
382
     * @param string $collectionName
383
     *
384
     * @return mixed
385
     */
386
    public function loadMedia(string $collectionName)
387
    {
388
        if ($this->mediaIsPreloaded()) {
389
            return $this->media
390
                ->filter(function (Media $mediaItem) use ($collectionName) {
391
                    if ($collectionName == '') {
392
                        return true;
393
                    }
394
395
                    return $mediaItem->collection_name === $collectionName;
396
                })
397
                ->sortBy('order_column')
398
                ->values();
399
        }
400
401
        $query = $this->media();
402
403
        if ($collectionName !== '') {
404
            $query = $query->where('collection_name', $collectionName);
405
        }
406
407
        return $query
408
            ->orderBy('order_column')
409
            ->get();
410
    }
411
}
412