Completed
Push — master ( c2f76d...03586b )
by Freek
11:35
created

FileAdder::processMediaItem()   B

Complexity

Conditions 6
Paths 12

Size

Total Lines 26
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 26
rs 8.439
c 0
b 0
f 0
cc 6
eloc 13
nc 12
nop 3
1
<?php
2
3
namespace Spatie\MediaLibrary\FileAdder;
4
5
use Spatie\MediaLibrary\Exceptions\FileCannotBeAdded\FileUnacceptableForCollection;
6
use Spatie\MediaLibrary\File as PendingFile;
7
use Spatie\MediaLibrary\Models\Media;
8
use Spatie\MediaLibrary\Helpers\File;
9
use Illuminate\Database\Eloquent\Model;
10
use Spatie\MediaLibrary\Filesystem\Filesystem;
11
use Spatie\MediaLibrary\Exceptions\FileCannotBeAdded;
12
use Spatie\MediaLibrary\HasMedia\HasMedia;
13
use Spatie\MediaLibrary\MediaCollection\MediaCollection;
14
use Symfony\Component\HttpFoundation\File\UploadedFile;
15
use Symfony\Component\HttpFoundation\File\File as SymfonyFile;
16
use Spatie\MediaLibrary\Exceptions\FileCannotBeAdded\UnknownType;
17
use Spatie\MediaLibrary\Exceptions\FileCannotBeAdded\FileIsTooBig;
18
use Spatie\MediaLibrary\Exceptions\FileCannotBeAdded\DiskDoesNotExist;
19
use Spatie\MediaLibrary\Exceptions\FileCannotBeAdded\FileDoesNotExist;
20
use Spatie\MediaLibrary\Jobs\GenerateResponsiveImages;
21
use Spatie\MediaLibrary\ImageGenerators\FileTypes\Image as ImageGenerator;
22
23
class FileAdder
24
{
25
    /** @var \Illuminate\Database\Eloquent\Model subject */
26
    protected $subject;
27
28
    /** @var \Spatie\MediaLibrary\Filesystem\Filesystem */
29
    protected $filesystem;
30
31
    /** @var bool */
32
    protected $preserveOriginal = false;
33
34
    /** @var string|\Symfony\Component\HttpFoundation\File\UploadedFile */
35
    protected $file;
36
37
    /** @var array */
38
    protected $properties = [];
39
40
    /** @var array */
41
    protected $customProperties = [];
42
43
    /** @var array */
44
    protected $manipulations = [];
45
46
    /** @var string */
47
    protected $pathToFile;
48
49
    /** @var string */
50
    protected $fileName;
51
52
    /** @var string */
53
    protected $mediaName;
54
55
    /** @var string */
56
    protected $diskName = '';
57
58
    /** @var null|callable */
59
    protected $fileNameSanitizer;
60
61
    /** @var bool */
62
    protected $generateResponsiveImages = false;
63
64
    /**
65
     * @param Filesystem $fileSystem
66
     */
67
    public function __construct(Filesystem $fileSystem)
68
    {
69
        $this->filesystem = $fileSystem;
70
71
        $this->fileNameSanitizer = function ($fileName) {
72
            return $this->defaultSanitizer($fileName);
73
        };
74
    }
75
76
    /**
77
     * @param \Illuminate\Database\Eloquent\Model $subject
78
     *
79
     * @return FileAdder
80
     */
81
    public function setSubject(Model $subject)
82
    {
83
        $this->subject = $subject;
84
85
        return $this;
86
    }
87
88
    /*
89
     * Set the file that needs to be imported.
90
     *
91
     * @param string|\Symfony\Component\HttpFoundation\File\UploadedFile $file
92
     *
93
     * @return $this
94
     */
95
    public function setFile($file): self
96
    {
97
        $this->file = $file;
98
99
        if (is_string($file)) {
100
            $this->pathToFile = $file;
101
            $this->setFileName(pathinfo($file, PATHINFO_BASENAME));
102
            $this->mediaName = pathinfo($file, PATHINFO_FILENAME);
103
104
            return $this;
105
        }
106
107
        if ($file instanceof UploadedFile) {
108
            $this->pathToFile = $file->getPath() . '/' . $file->getFilename();
109
            $this->setFileName($file->getClientOriginalName());
110
            $this->mediaName = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
111
112
            return $this;
113
        }
114
115
        if ($file instanceof SymfonyFile) {
116
            $this->pathToFile = $file->getPath() . '/' . $file->getFilename();
117
            $this->setFileName(pathinfo($file->getFilename(), PATHINFO_BASENAME));
118
            $this->mediaName = pathinfo($file->getFilename(), PATHINFO_FILENAME);
119
120
            return $this;
121
        }
122
123
        throw UnknownType::create();
124
    }
125
126
    public function preservingOriginal(): self
127
    {
128
        $this->preserveOriginal = true;
129
130
        return $this;
131
    }
132
133
    public function usingName(string $name): self
134
    {
135
        return $this->setName($name);
136
    }
137
138
    public function setName(string $name): self
139
    {
140
        $this->mediaName = $name;
141
142
        return $this;
143
    }
144
145
    public function usingFileName(string $fileName): self
146
    {
147
        return $this->setFileName($fileName);
148
    }
149
150
    public function setFileName(string $fileName): self
151
    {
152
        $this->fileName = $fileName;
153
154
        return $this;
155
    }
156
157
    public function withCustomProperties(array $customProperties): self
158
    {
159
        $this->customProperties = $customProperties;
160
161
        return $this;
162
    }
163
164
    public function withManipulations(array $manipulations): self
165
    {
166
        $this->manipulations = $manipulations;
167
168
        return $this;
169
    }
170
171
    public function withProperties(array $properties): self
172
    {
173
        $this->properties = $properties;
174
175
        return $this;
176
    }
177
178
    public function withAttributes(array $properties): self
179
    {
180
        return $this->withProperties($properties);
181
    }
182
183
    public function withResponsiveImages(): self
184
    {
185
        $this->generateResponsiveImages = true;
186
187
        return $this;
188
    }
189
190
    public function addCustomHeaders(array $customRemoteHeaders): self
191
    {
192
        $this->filesystem->addCustomRemoteHeaders($customRemoteHeaders);
193
194
        return $this;
195
    }
196
197
    public function toMediaCollectionOnCloudDisk(string $collectionName = 'default'): Media
198
    {
199
        return $this->toMediaCollection($collectionName, config('filesystems.cloud'));
200
    }
201
202
    public function toMediaCollection(string $collectionName = 'default', string $diskName = ''): Media
203
    {
204
        if (!is_file($this->pathToFile)) {
205
            throw FileDoesNotExist::create($this->pathToFile);
206
        }
207
208
        if (filesize($this->pathToFile) > config('medialibrary.max_file_size')) {
209
            throw FileIsTooBig::create($this->pathToFile);
210
        }
211
212
        $mediaClass = config('medialibrary.media_model');
213
        $media = new $mediaClass();
214
215
        $media->name = $this->mediaName;
216
217
        $this->fileName = ($this->fileNameSanitizer)($this->fileName);
218
219
        $media->file_name = $this->fileName;
220
221
        $media->disk = $this->determineDiskName($diskName, $collectionName);
222
223
        if (is_null(config("filesystems.disks.{$media->disk}"))) {
224
            throw DiskDoesNotExist::create($media->disk);
225
        }
226
227
        $media->collection_name = $collectionName;
228
229
        $media->mime_type = File::getMimetype($this->pathToFile);
230
        $media->size = filesize($this->pathToFile);
231
        $media->custom_properties = $this->customProperties;
232
233
        $media->responsive_images = [];
234
235
        $media->manipulations = $this->manipulations;
236
237
        $media->fill($this->properties);
238
239
        $this->attachMedia($media);
240
241
        return $media;
242
    }
243
244
    protected function determineDiskName(string $diskName, string $collectionName): string
245
    {
246
        if ($diskName !== '') {
247
            return $diskName;
248
        }
249
250
        if ($collection = $this->getMediaCollection($collectionName)) {
251
            $collectionDiskName = $collection->diskName;
252
253
            if ($collectionDiskName !== '') {
254
                return $collectionDiskName;
255
            }
256
        }
257
258
        return config('medialibrary.default_filesystem');
259
    }
260
261
    public function defaultSanitizer(string $fileName): string
262
    {
263
        return str_replace(['#', '/', '\\', ' '], '-', $fileName);
264
    }
265
266
    public function sanitizingFileName(callable $fileNameSanitizer): self
267
    {
268
        $this->fileNameSanitizer = $fileNameSanitizer;
269
270
        return $this;
271
    }
272
273
    protected function attachMedia(Media $media)
274
    {
275
        if (!$this->subject->exists) {
276
            $this->subject->prepareToAttachMedia($media, $this);
277
278
            $class = get_class($this->subject);
279
280
            $class::created(function ($model) {
281
                $model->processUnattachedMedia(function (Media $media, FileAdder $fileAdder) use ($model) {
282
                    $this->processMediaItem($model, $media, $fileAdder);
283
                });
284
            });
285
286
            return;
287
        }
288
289
        $this->processMediaItem($this->subject, $media, $this);
290
    }
291
292
    protected function processMediaItem(HasMedia $model, Media $media, FileAdder $fileAdder)
293
    {
294
        $this->guardAgainstDisallowedFileAdditions($media, $model);
0 ignored issues
show
Unused Code introduced by
The call to FileAdder::guardAgainstDisallowedFileAdditions() has too many arguments starting with $model.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
295
296
        $model->media()->save($media);
297
298
        $this->filesystem->add($fileAdder->pathToFile, $media, $fileAdder->fileName);
299
300
        if (!$fileAdder->preserveOriginal) {
301
            unlink($fileAdder->pathToFile);
302
        }
303
304
        if ($this->generateResponsiveImages && (new ImageGenerator())->canConvert($media)) {
305
            $job = new GenerateResponsiveImages($media);
306
307
            if ($customQueue = config('medialibrary.queue_name')) {
308
                $job->onQueue($customQueue);
309
            }
310
311
            dispatch($job);
312
        }
313
314
        if (optional($this->getMediaCollection($media->collection_name))->singleFile) {
315
            $model->clearMediaCollectionExcept($media->collection_name, $media);
316
        }
317
    }
318
319
    protected function getMediaCollection(string $collectionName): ?MediaCollection
320
    {
321
        $this->subject->registerMediaCollections();
322
323
        return collect($this->subject->mediaCollections)
324
            ->first(function (MediaCollection $collection) use ($collectionName) {
325
                return $collection->name === $collectionName;
326
            });
327
    }
328
329
    protected function guardAgainstDisallowedFileAdditions(Media $media)
330
    {
331
        $file = PendingFile::createFromMedia($media);
332
333
        if (! $collection = $this->getMediaCollection($media->collection_name)) {
334
            return;
335
        }
336
337
        if (! ($collection->acceptsFile)($file, $this->subject)) {
338
            throw FileUnacceptableForCollection::create($file, $collection, $this->subject);
339
        }
340
    }
341
}
342