Completed
Push — master ( a50e59...22377b )
by Freek
10:42
created

src/Models/Media.php (4 issues)

Upgrade to new PHP Analysis Engine

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\Models;
4
5
use DateTimeInterface;
6
use Illuminate\Support\Collection;
7
use Illuminate\Support\HtmlString;
8
use Spatie\MediaLibrary\Helpers\File;
9
use Illuminate\Database\Eloquent\Model;
10
use Illuminate\Contracts\Support\Htmlable;
11
use Spatie\MediaLibrary\HasMedia\HasMedia;
12
use Illuminate\Contracts\Support\Responsable;
13
use Spatie\MediaLibrary\Conversion\Conversion;
14
use Spatie\MediaLibrary\Filesystem\Filesystem;
15
use Spatie\MediaLibrary\Models\Concerns\IsSorted;
16
use Illuminate\Database\Eloquent\Relations\MorphTo;
17
use Spatie\MediaLibrary\Helpers\TemporaryDirectory;
18
use Spatie\MediaLibrary\Conversion\ConversionCollection;
19
use Spatie\MediaLibrary\ImageGenerators\FileTypes\Image;
20
use Spatie\MediaLibrary\UrlGenerator\UrlGeneratorFactory;
21
use Spatie\MediaLibrary\Models\Traits\CustomMediaProperties;
22
use Spatie\MediaLibrary\ResponsiveImages\RegisteredResponsiveImages;
23
24
class Media extends Model implements Responsable, Htmlable
25
{
26
    use IsSorted,
27
        CustomMediaProperties;
28
29
    const TYPE_OTHER = 'other';
30
31
    protected $guarded = [];
32
33
    protected $casts = [
34
        'manipulations' => 'array',
35
        'custom_properties' => 'array',
36
        'responsive_images' => 'array',
37
    ];
38
39
    public function model(): MorphTo
40
    {
41
        return $this->morphTo();
42
    }
43
44
    /*
45
     * Get the full url to a original media file.
46
    */
47
    public function getFullUrl(string $conversionName = ''): string
48
    {
49
        return url($this->getUrl($conversionName));
50
    }
51
52
    /*
53
     * Get the url to a original media file.
54
     */
55
    public function getUrl(string $conversionName = ''): string
56
    {
57
        $urlGenerator = UrlGeneratorFactory::createForMedia($this, $conversionName);
58
59
        return $urlGenerator->getUrl();
60
    }
61
62
    public function getTemporaryUrl(DateTimeInterface $expiration, string $conversionName = '', array $options = []): string
63
    {
64
        $urlGenerator = UrlGeneratorFactory::createForMedia($this, $conversionName);
65
66
        return $urlGenerator->getTemporaryUrl($expiration, $options);
67
    }
68
69
    /*
70
     * Get the path to the original media file.
71
     */
72
    public function getPath(string $conversionName = ''): string
73
    {
74
        $urlGenerator = UrlGeneratorFactory::createForMedia($this, $conversionName);
75
76
        return $urlGenerator->getPath();
77
    }
78
79
    public function getImageGenerators(): Collection
80
    {
81
        return collect(config('medialibrary.image_generators'));
82
    }
83
84
    public function getTypeAttribute(): string
85
    {
86
        $type = $this->getTypeFromExtension();
87
88
        if ($type !== self::TYPE_OTHER) {
89
            return $type;
90
        }
91
92
        return $this->getTypeFromMime();
93
    }
94
95
    public function getTypeFromExtension(): string
96
    {
97
        $imageGenerator = $this->getImageGenerators()
98
            ->map(function (string $className) {
99
                return app($className);
100
            })
101
            ->first->canHandleExtension(strtolower($this->extension));
102
103
        return $imageGenerator
104
            ? $imageGenerator->getType()
105
            : static::TYPE_OTHER;
106
    }
107
108
    public function getTypeFromMime(): string
109
    {
110
        $imageGenerator = $this->getImageGenerators()
111
            ->map(function (string $className) {
112
                return app($className);
113
            })
114
            ->first->canHandleMime($this->mime_type);
115
116
        return $imageGenerator
117
            ? $imageGenerator->getType()
118
            : static::TYPE_OTHER;
119
    }
120
121
    public function getExtensionAttribute(): string
122
    {
123
        return pathinfo($this->file_name, PATHINFO_EXTENSION);
124
    }
125
126
    public function getHumanReadableSizeAttribute(): string
127
    {
128
        return File::getHumanReadableSize($this->size);
129
    }
130
131
    public function getDiskDriverName(): string
132
    {
133
        return strtolower(config("filesystems.disks.{$this->disk}.driver"));
134
    }
135
136
    /*
137
     * Determine if the media item has a custom property with the given name.
138
     */
139
    public function hasCustomProperty(string $propertyName): bool
140
    {
141
        return array_has($this->custom_properties, $propertyName);
0 ignored issues
show
Deprecated Code introduced by
The function array_has() has been deprecated with message: Arr::has() 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...
142
    }
143
144
    /**
145
     * Get the value of custom property with the given name.
146
     *
147
     * @param string $propertyName
148
     * @param mixed $default
149
     *
150
     * @return mixed
151
     */
152
    public function getCustomProperty(string $propertyName, $default = null)
153
    {
154
        return array_get($this->custom_properties, $propertyName, $default);
0 ignored issues
show
Deprecated Code introduced by
The function array_get() has been deprecated with message: Arr::get() 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...
155
    }
156
157
    /**
158
     * @param string $name
159
     * @param mixed $value
160
     *
161
     * @return $this
162
     */
163
    public function setCustomProperty(string $name, $value): self
164
    {
165
        $customProperties = $this->custom_properties;
166
167
        array_set($customProperties, $name, $value);
0 ignored issues
show
Deprecated Code introduced by
The function array_set() has been deprecated with message: Arr::set() 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...
168
169
        $this->custom_properties = $customProperties;
170
171
        return $this;
172
    }
173
174
    public function forgetCustomProperty(string $name): self
175
    {
176
        $customProperties = $this->custom_properties;
177
178
        array_forget($customProperties, $name);
0 ignored issues
show
Deprecated Code introduced by
The function array_forget() has been deprecated with message: Arr::forget() 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...
179
180
        $this->custom_properties = $customProperties;
181
182
        return $this;
183
    }
184
185
    /*
186
     * Get all the names of the registered media conversions.
187
     */
188
    public function getMediaConversionNames(): array
189
    {
190
        $conversions = ConversionCollection::createForMedia($this);
191
192
        return $conversions->map(function (Conversion $conversion) {
193
            return $conversion->getName();
194
        })->toArray();
195
    }
196
197
    public function hasGeneratedConversion(string $conversionName): bool
198
    {
199
        $generatedConversions = $this->getGeneratedConversions();
200
201
        return $generatedConversions[$conversionName] ?? false;
202
    }
203
204
    public function markAsConversionGenerated(string $conversionName, bool $generated): self
205
    {
206
        $this->setCustomProperty("generated_conversions.{$conversionName}", $generated);
207
208
        $this->save();
209
210
        return $this;
211
    }
212
213
    public function getGeneratedConversions(): Collection
214
    {
215
        return collect($this->getCustomProperty('generated_conversions', []));
216
    }
217
218
    /**
219
     * Create an HTTP response that represents the object.
220
     *
221
     * @param  \Illuminate\Http\Request $request
222
     *
223
     * @return \Illuminate\Http\Response
224
     */
225
    public function toResponse($request)
226
    {
227
        $downloadHeaders = [
228
            'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0',
229
            'Content-Type' => $this->mime_type,
230
            'Content-Length' => $this->size,
231
            'Content-Disposition' => 'attachment; filename="'.$this->file_name.'"',
232
            'Pragma' => 'public',
233
        ];
234
235
        return response()->stream(function () {
236
            $stream = $this->stream();
237
238
            fpassthru($stream);
239
240
            if (is_resource($stream)) {
241
                fclose($stream);
242
            }
243
        }, 200, $downloadHeaders);
244
    }
245
246
    public function getResponsiveImageUrls(string $conversionName = ''): array
247
    {
248
        return $this->responsiveImages($conversionName)->getUrls();
249
    }
250
251
    public function hasResponsiveImages(string $conversionName = ''): bool
252
    {
253
        return count($this->getResponsiveImageUrls($conversionName)) > 0;
254
    }
255
256
    public function getSrcset(string $conversionName = ''): string
257
    {
258
        return $this->responsiveImages($conversionName)->getSrcset();
259
    }
260
261
    public function toHtml()
262
    {
263
        return $this->img();
264
    }
265
266
    /**
267
     * @param string|array $conversion
268
     * @param array $extraAttributes
269
     *
270
     * @return string
271
     */
272
    public function img($conversion = '', array $extraAttributes = []): string
273
    {
274
        if (! (new Image())->canHandleMime($this->mime_type)) {
275
            return '';
276
        }
277
278
        if (is_array($conversion)) {
279
            $attributes = $conversion;
280
281
            $conversion = $attributes['conversion'] ?? '';
282
283
            unset($attributes['conversion']);
284
285
            $extraAttributes = array_merge($attributes, $extraAttributes);
286
        }
287
288
        $attributeString = collect($extraAttributes)
289
            ->map(function ($value, $name) {
290
                return $name.'="'.$value.'"';
291
            })->implode(' ');
292
293
        if (strlen($attributeString)) {
294
            $attributeString = ' '.$attributeString;
295
        }
296
297
        $media = $this;
298
299
        $viewName = 'image';
300
301
        $width = '';
302
303
        if ($this->hasResponsiveImages($conversion)) {
304
            $viewName = config('medialibrary.responsive_images.use_tiny_placeholders')
305
                ? 'responsiveImageWithPlaceholder'
306
                : 'responsiveImage';
307
308
            $width = $this->responsiveImages($conversion)->files->first()->width();
309
        }
310
311
        return view("medialibrary::{$viewName}", compact(
312
            'media',
313
            'conversion',
314
            'attributeString',
315
            'width'
316
        ));
317
    }
318
319
    public function move(HasMedia $model, $collectionName = 'default'): self
320
    {
321
        $newMedia = $this->copy($model, $collectionName);
322
323
        $this->delete();
324
325
        return $newMedia;
326
    }
327
328
    public function copy(HasMedia $model, $collectionName = 'default'): self
329
    {
330
        $temporaryDirectory = TemporaryDirectory::create();
331
332
        $temporaryFile = $temporaryDirectory->path($this->file_name);
333
334
        app(Filesystem::class)->copyFromMediaLibrary($this, $temporaryFile);
335
336
        $newMedia = $model
337
            ->addMedia($temporaryFile)
338
            ->usingName($this->name)
339
            ->withCustomProperties($this->custom_properties)
340
            ->toMediaCollection($collectionName);
341
342
        $temporaryDirectory->delete();
343
344
        return $newMedia;
345
    }
346
347
    public function responsiveImages(string $conversionName = ''): RegisteredResponsiveImages
348
    {
349
        return new RegisteredResponsiveImages($this, $conversionName);
350
    }
351
352
    public function stream()
353
    {
354
        $filesystem = app(Filesystem::class);
355
356
        return $filesystem->getStream($this);
357
    }
358
359
    public function __invoke(...$arguments)
360
    {
361
        return new HtmlString($this->img(...$arguments));
362
    }
363
}
364