Completed
Push — 0.6 ( 3caceb...07d55c )
by Ben
21:59
created

AssetUploader::upload()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 7
c 0
b 0
f 0
nc 4
nop 2
dl 0
loc 15
rs 9.6111
1
<?php
2
3
namespace Thinktomorrow\AssetLibrary\Application;
4
5
use Illuminate\Http\UploadedFile;
6
use Illuminate\Support\Collection;
7
use Illuminate\Support\Str;
8
use Spatie\MediaLibrary\Exceptions\FileCannotBeAdded;
9
use Spatie\MediaLibrary\FileAdder\FileAdder;
10
use Thinktomorrow\AssetLibrary\Asset;
11
use Traversable;
12
13
class AssetUploader
14
{
15
    /**
16
     * Uploads the file/files or asset by creating the
17
     * asset that is needed to upload the files too.
18
     *
19
     * @param Asset|Traversable|array|Collection|UploadedFile $files
20
     * @param string|null $filename
21
     * @return Collection|null|Asset
22
     * @throws FileCannotBeAdded
23
     */
24
    public static function upload($files, ?string $filename = null)
25
    {
26
        if ($files instanceof Asset) {
27
            return $files;
28
        }
29
30
        if (is_array($files) || $files instanceof Traversable) {
31
            return self::uploadMultiple($files);
32
        }
33
34
        if (! ($files instanceof UploadedFile)) {
0 ignored issues
show
introduced by
$files is always a sub-type of Illuminate\Http\UploadedFile.
Loading history...
35
            return;
36
        }
37
38
        return self::uploadToAsset($files, Asset::create(), $filename);
39
    }
40
41
    /**
42
     * Uploads the multiple files or assets by creating the
43
     * asset that is needed to upload the files too.
44
     *
45
     * @param Asset|Traversable|array $files
46
     * @return Collection
47
     */
48
    private static function uploadMultiple($files)
49
    {
50
        $list = collect([]);
51
        collect($files)->each(function ($file) use ($list) {
52
            if ($file instanceof Asset) {
53
                $list->push($file);
54
            } else {
55
                $asset = new Asset();
56
                $asset->save();
57
                $list->push(self::uploadToAsset($file, $asset, null));
58
            }
59
        });
60
61
        return $list;
62
    }
63
64
    /**
65
     * Uploads the file/files or asset by creating the
66
     * asset that is needed to upload the files too.
67
     *
68
     * @param string $file
69
     * @param string|null $filename
70
     * @return Collection|null|Asset
71
     * @throws FileCannotBeAdded
72
     */
73
    public static function uploadFromBase64($file, $filename = null)
74
    {
75
        return self::uploadBase64ToAsset($file, Asset::create(), $filename);
76
    }
77
78
    /**
79
     * Uploads the url by creating the
80
     * asset that is needed to upload the files too.
81
     *
82
     * @param string $url
83
     * @return Asset
84
     * @throws FileCannotBeAdded
85
     */
86
    public static function uploadFromUrl($url)
87
    {
88
        return self::uploadFromUrlToAsset($url, Asset::create());
89
    }
90
91
    /**
92
     * Uploads the given file to this instance of asset
93
     * and sets the dimensions as a custom property.
94
     *
95
     * @param UploadedFile $file
96
     * @param Asset $asset
97
     * @param string|null $filename
98
     * @return null|Asset
99
     * @throws FileCannotBeAdded
100
     */
101
    public static function uploadToAsset($file, $asset, $filename = null): ?Asset
102
    {
103
        $customProps = [];
104
        if (self::isImage($file)) {
105
            $imagesize = getimagesize($file);
106
107
            $customProps['dimensions'] = $imagesize[0].' x '.$imagesize[1];
108
        }
109
110
        $fileAdd = $asset->addMedia($file)
111
                        ->withCustomProperties($customProps);
112
113
        $fileAdd = self::prepareOptions($fileAdd, $filename);
114
115
        $fileAdd->withResponsiveImages()->toMediaCollection();
116
117
        return $asset->load('media');
118
    }
119
120
    /**
121
     * Uploads the given file to this instance of asset
122
     * and sets the dimensions as a custom property.
123
     *
124
     * @param string $file
125
     * @param Asset $asset
126
     * @param string|null $filename
127
     * @return null|Asset
128
     * @throws FileCannotBeAdded
129
     * @internal param $files
130
     */
131
    public static function uploadBase64ToAsset($file, $asset, $filename = null): ?Asset
132
    {
133
        $fileAdd = $asset->addMediaFromBase64($file);
134
135
        if (! $filename) {
136
            $extension = substr($file, 11, strpos($file, ';') - 11);
137
            $filename  = pathinfo($file, PATHINFO_BASENAME).'.'.$extension;
138
        }
139
140
        $fileAdd = self::prepareOptions($fileAdd, $filename);
141
142
        $fileAdd->toMediaCollection();
143
144
        return $asset->load('media');
145
    }
146
147
    /**
148
     * Uploads the given file to this instance of asset
149
     * and sets the dimensions as a custom property.
150
     *
151
     * @param string $url
152
     * @param Asset $asset
153
     * @return Asset
154
     * @throws FileCannotBeAdded
155
     */
156
    public static function uploadFromUrlToAsset($url, $asset): Asset
157
    {
158
        $fileAdd = $asset->addMediaFromUrl($url);
159
160
        $filename = substr($url, strrpos($url, '/') + 1);
161
        $fileAdd->setName($filename);
162
163
        $fileAdd = self::prepareOptions($fileAdd, $filename);
164
165
        $fileAdd->toMediaCollection();
166
167
        return $asset->load('media');
168
    }
169
170
    /**
171
     * @param UploadedFile $file
172
     * @return bool
173
     */
174
    private static function isImage($file): bool
175
    {
176
        return Str::before($file->getMimetype() ?? '', '/') === 'image';
177
    }
178
179
    /**
180
     * Set the possible options on the fileAdder. This includes preserveOriginal
181
     * and filename.
182
     *
183
     * @param FileAdder $fileAdd
184
     * @param string|null $filename
185
     * @return FileAdder
186
     * @throws FileCannotBeAdded
187
     */
188
    private static function prepareOptions($fileAdd, $filename): FileAdder
189
    {
190
        if ($filename) {
191
            $fileAdd->usingName(substr($filename, 0, strpos($filename, '.')));
192
            $fileAdd->usingFileName($filename);
193
        }
194
195
        $fileAdd->preservingOriginal();
196
197
        // Sanitize filename by sluggifying the filename without the extension
198
        $fileAdd->sanitizingFileName(function ($filename) {
199
            $extension = substr($filename, strrpos($filename, '.') + 1);
200
            $filename  = substr($filename, 0, strrpos($filename, '.'));
201
            $filename  = Str::slug($filename).'.'.$extension;
202
203
            return strtolower($filename);
204
        });
205
206
        return $fileAdd;
207
    }
208
}
209