Completed
Push — master ( cd140c...4928ad )
by Freek
9s
created

HasMediaTrait   B

Complexity

Total Complexity 38

Size/Duplication

Total Lines 372
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 10

Importance

Changes 0
Metric Value
wmc 38
lcom 3
cbo 10
dl 0
loc 372
rs 8.3999
c 0
b 0
f 0

21 Methods

Rating   Name   Duplication   Size   Complexity  
A media() 0 4 1
A addMedia() 0 4 1
A addMediaFromRequest() 0 4 1
A addMediaFromUrl() 0 16 2
A bootHasMediaTrait() 0 10 2
B addMediaFromBase64() 0 29 4
A copyMedia() 0 4 1
A hasMedia() 0 4 2
A getMedia() 0 4 1
A getFirstMedia() 0 6 1
A getFirstMediaUrl() 0 10 2
A getFirstMediaPath() 0 10 2
B updateMedia() 0 30 4
A removeMediaItemsNotPresentInArray() 0 8 1
A clearMediaCollection() 0 16 2
A deleteMedia() 0 14 3
A addMediaConversion() 0 8 1
A deletePreservingMedia() 0 6 1
A shouldDeletePreservingMedia() 0 4 1
A mediaIsPreloaded() 0 4 1
B loadMedia() 0 25 4
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 a remote file to the medialibrary.
73
     *
74
     * @param string $url
75
     *
76
     * @return \Spatie\MediaLibrary\FileAdder\FileAdder
77
     *
78
     * @throws \Spatie\MediaLibrary\Exceptions\FileCannotBeAdded
79
     */
80
    public function addMediaFromUrl(string $url)
81
    {
82
        if (! $stream = @fopen($url, 'r')) {
83
            throw UnreachableUrl::create($url);
84
        }
85
86
        $tmpFile = tempnam(sys_get_temp_dir(), 'media-library');
87
        file_put_contents($tmpFile, $stream);
88
89
        $filename = basename(parse_url($url, PHP_URL_PATH));
90
91
        return app(FileAdderFactory::class)
92
            ->create($this, $tmpFile)
93
            ->usingName(pathinfo($filename, PATHINFO_FILENAME))
94
            ->usingFileName($filename);
95
    }
96
97
    /**
98
     * Add a base64 encoded file to the medialibrary.
99
     *
100
     * @param string $base64data
101
     *
102
     * @throws InvalidBase64Data
103
     * @throws \Spatie\MediaLibrary\Exceptions\FileCannotBeAdded
104
     *
105
     * @return \Spatie\MediaLibrary\FileAdder\FileAdder
106
     */
107
    public function addMediaFromBase64(string $base64data)
108
    {
109
        // strip out data uri scheme information (see RFC 2397)
110
        if (strpos($base64data, ';base64') !== false) {
111
            list(, $base64data) = explode(';', $base64data);
112
            list(, $base64data) = explode(',', $base64data);
113
        }
114
115
        // strict mode filters for non-base64 alphabet characters
116
        if (base64_decode($base64data, true) === false) {
117
            throw InvalidBase64Data::create();
118
        }
119
120
        // decoding and then reeconding should not change the data
121
        if (base64_encode(base64_decode($base64data)) !== $base64data) {
122
            throw InvalidBase64Data::create();
123
        }
124
125
        $binaryData = base64_decode($base64data);
126
127
        // temporarily store the decoded data on the filesystem to be able to pass it to the fileAdder
128
        $tmpFile = tempnam(sys_get_temp_dir(), 'medialibrary');
129
        file_put_contents($tmpFile, $binaryData);
130
131
        $file = app(FileAdderFactory::class)
132
            ->create($this, $tmpFile);
133
134
        return $file;
135
    }
136
137
    /**
138
     * Copy a file to the medialibrary.
139
     *
140
     * @param string|\Symfony\Component\HttpFoundation\File\UploadedFile $file
141
     *
142
     * @return \Spatie\MediaLibrary\FileAdder\FileAdder
143
     */
144
    public function copyMedia($file)
145
    {
146
        return $this->addMedia($file)->preservingOriginal();
147
    }
148
149
    /*
150
     * Determine if there is media in the given collection.
151
     */
152
    public function hasMedia(string $collectionName = 'default'): bool
153
    {
154
        return count($this->getMedia($collectionName)) ? true : false;
155
    }
156
157
    /**
158
     * Get media collection by its collectionName.
159
     *
160
     * @param string $collectionName
161
     * @param array|callable  $filters
162
     *
163
     * @return \Illuminate\Support\Collection
164
     */
165
    public function getMedia(string $collectionName = 'default', $filters = []): Collection
166
    {
167
        return app(MediaRepository::class)->getCollection($this, $collectionName, $filters);
168
    }
169
170
    /**
171
     * Get the first media item of a media collection.
172
     *
173
     * @param string $collectionName
174
     * @param array $filters
175
     *
176
     * @return Media|null
177
     */
178
    public function getFirstMedia(string $collectionName = 'default', array $filters = [])
179
    {
180
        $media = $this->getMedia($collectionName, $filters);
181
182
        return $media->first();
183
    }
184
185
    /*
186
     * Get the url of the image for the given conversionName
187
     * for first media for the given collectionName.
188
     * If no profile is given, return the source's url.
189
     */
190
    public function getFirstMediaUrl(string $collectionName = 'default', string $conversionName = ''): string
191
    {
192
        $media = $this->getFirstMedia($collectionName);
193
194
        if (! $media) {
195
            return '';
196
        }
197
198
        return $media->getUrl($conversionName);
199
    }
200
201
    /*
202
     * Get the url of the image for the given conversionName
203
     * for first media for the given collectionName.
204
     * If no profile is given, return the source's url.
205
     */
206
    public function getFirstMediaPath(string $collectionName = 'default', string $conversionName = ''): string
207
    {
208
        $media = $this->getFirstMedia($collectionName);
209
210
        if (! $media) {
211
            return '';
212
        }
213
214
        return $media->getPath($conversionName);
215
    }
216
217
    /**
218
     * Update a media collection by deleting and inserting again with new values.
219
     *
220
     * @param array $newMediaArray
221
     * @param string $collectionName
222
     *
223
     * @return \Illuminate\Support\Collection
224
     *
225
     * @throws \Spatie\MediaLibrary\Exceptions\MediaCannotBeUpdated
226
     */
227
    public function updateMedia(array $newMediaArray, string $collectionName = 'default'): Collection
228
    {
229
        $this->removeMediaItemsNotPresentInArray($newMediaArray, $collectionName);
230
231
        return collect($newMediaArray)
232
            ->map(function (array $newMediaItem) use ($collectionName) {
233
                static $orderColumn = 1;
234
235
                $mediaClass = config('medialibrary.media_model');
236
                $currentMedia = $mediaClass::findOrFail($newMediaItem['id']);
237
238
                if ($currentMedia->collection_name != $collectionName) {
239
                    throw MediaCannotBeUpdated::doesNotBelongToCollection($collectionName, $currentMedia);
240
                }
241
242
                if (array_key_exists('name', $newMediaItem)) {
243
                    $currentMedia->name = $newMediaItem['name'];
244
                }
245
246
                if (array_key_exists('custom_properties', $newMediaItem)) {
247
                    $currentMedia->custom_properties = $newMediaItem['custom_properties'];
248
                }
249
250
                $currentMedia->order_column = $orderColumn++;
251
252
                $currentMedia->save();
253
254
                return $currentMedia;
255
            });
256
    }
257
258
    /**
259
     * @param array $newMediaArray
260
     * @param string $collectionName
261
     */
262
    protected function removeMediaItemsNotPresentInArray(array $newMediaArray, string $collectionName = 'default')
263
    {
264
        $this->getMedia($collectionName)
265
            ->reject(function (Media $currentMediaItem) use ($newMediaArray) {
266
                return in_array($currentMediaItem->id, array_column($newMediaArray, 'id'));
267
            })
268
            ->each->delete();
269
    }
270
271
    /**
272
     * Remove all media in the given collection.
273
     *
274
     * @param string $collectionName
275
     *
276
     * @return $this
277
     */
278
    public function clearMediaCollection(string $collectionName = 'default')
279
    {
280
        $this->getMedia($collectionName)
281
            ->each(function (Media $media) {
282
                app(Filesystem::class)->removeFiles($media);
283
                $media->delete();
284
            });
285
286
        event(new CollectionHasBeenCleared($this, $collectionName));
287
288
        if ($this->mediaIsPreloaded()) {
289
            unset($this->media);
290
        }
291
292
        return $this;
293
    }
294
295
    /**
296
     * Delete the associated media with the given id.
297
     * You may also pass a media object.
298
     *
299
     * @param int|\Spatie\MediaLibrary\Media $mediaId
300
     *
301
     * @throws \Spatie\MediaLibrary\Exceptions\MediaCannotBeDeleted
302
     */
303
    public function deleteMedia($mediaId)
304
    {
305
        if ($mediaId instanceof Media) {
306
            $mediaId = $mediaId->id;
307
        }
308
309
        $media = $this->media->find($mediaId);
310
311
        if (! $media) {
312
            throw MediaCannotBeDeleted::doesNotBelongToModel($media, $this);
313
        }
314
315
        $media->delete();
316
    }
317
318
    /*
319
     * Add a conversion.
320
     */
321
    public function addMediaConversion(string $name): Conversion
322
    {
323
        $conversion = Conversion::create($name);
324
325
        $this->mediaConversions[] = $conversion;
326
327
        return $conversion;
328
    }
329
330
    /**
331
     * Delete the model, but preserve all the associated media.
332
     *
333
     * @return bool
334
     */
335
    public function deletePreservingMedia(): bool
336
    {
337
        $this->deletePreservingMedia = true;
338
339
        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...
340
    }
341
342
    /**
343
     * Determines if the media files should be preserved when the media object gets deleted.
344
     *
345
     * @return \Spatie\MediaLibrary\Media
346
     */
347
    public function shouldDeletePreservingMedia()
348
    {
349
        return $this->deletePreservingMedia ?? false;
350
    }
351
352
    protected function mediaIsPreloaded(): bool
353
    {
354
        return isset($this->media);
355
    }
356
357
    /**
358
     * Cache the media on the object.
359
     *
360
     * @param string $collectionName
361
     *
362
     * @return mixed
363
     */
364
    public function loadMedia(string $collectionName)
365
    {
366
        if ($this->mediaIsPreloaded()) {
367
            return $this->media
368
                ->filter(function (Media $mediaItem) use ($collectionName) {
369
                    if ($collectionName == '') {
370
                        return true;
371
                    }
372
373
                    return $mediaItem->collection_name === $collectionName;
374
                })
375
                ->sortBy('order_column')
376
                ->values();
377
        }
378
379
        $query = $this->media();
380
381
        if ($collectionName !== '') {
382
            $query = $query->where('collection_name', $collectionName);
383
        }
384
385
        return $query
386
            ->orderBy('order_column')
387
            ->get();
388
    }
389
}
390