Passed
Branch 0.6 (548853)
by Philippe
03:52
created

Asset   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 279
Duplicated Lines 0 %

Test Coverage

Coverage 78.22%

Importance

Changes 0
Metric Value
eloc 86
dl 0
loc 279
ccs 79
cts 101
cp 0.7822
rs 8.96
c 0
b 0
f 0
wmc 43

17 Methods

Rating   Name   Duplication   Size   Complexity  
A getExtensionForFilter() 0 7 2
A getImageUrl() 0 13 4
A getSize() 0 3 2
A attachToModel() 0 13 2
A getFilename() 0 3 1
A hasFile() 0 3 1
A getExtensionType() 0 23 6
A getFileUrl() 0 12 3
A getMimeType() 0 3 2
A isMediaEmpty() 0 3 1
A getDimensions() 0 14 3
A crop() 0 14 2
A getAllAssets() 0 3 1
A registerMediaConversions() 0 16 3
A removeByIds() 0 16 5
A remove() 0 12 4
A setOrder() 0 5 1

How to fix   Complexity   

Complex Class

Complex classes like Asset often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Asset, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Thinktomorrow\AssetLibrary\Models;
4
5
use Thinktomorrow\Locale\Locale;
0 ignored issues
show
Bug introduced by
The type Thinktomorrow\Locale\Locale was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use Illuminate\Support\Collection;
7
use Spatie\MediaLibrary\Models\Media;
8
use Illuminate\Database\Eloquent\Model;
9
use Spatie\MediaLibrary\HasMedia\HasMediaTrait;
10
use Thinktomorrow\AssetLibrary\Interfaces\HasAsset;
11
use Thinktomorrow\AssetLibrary\Exceptions\ConfigException;
12
use Thinktomorrow\AssetLibrary\Exceptions\AssetUploadException;
13
use Thinktomorrow\AssetLibrary\Exceptions\CorruptMediaException;
14
15
class Asset extends Model implements HasAsset
16
{
17
    use HasMediaTrait;
0 ignored issues
show
introduced by
The trait Spatie\MediaLibrary\HasMedia\HasMediaTrait requires some properties which are not provided by Thinktomorrow\AssetLibrary\Models\Asset: $each, $mediaConversionRegistrations, $forceDeleting, $media, $collection_name
Loading history...
18
19
    private $order;
20
21
    /**
22
     * Attaches this asset instance to the given model and
23
     * sets the type and locale to the given values and
24
     * returns the model with the asset relationship.
25
     *
26
     * @param HasAsset $model
27
     * @param string $type
28
     * @param null|string $locale
29
     * @return HasAsset
30
     * @throws AssetUploadException
31
     */
32 42
    public function attachToModel(HasAsset $model, $type = '', $locale = null): HasAsset
33
    {
34 42
        if ($model->assets()->get()->contains($this)) {
0 ignored issues
show
Bug introduced by
The method assets() does not exist on Thinktomorrow\AssetLibrary\Interfaces\HasAsset. Since it exists in all sub-types, consider adding an abstract or default implementation to Thinktomorrow\AssetLibrary\Interfaces\HasAsset. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

34
        if ($model->/** @scrutinizer ignore-call */ assets()->get()->contains($this)) {
Loading history...
35 1
            throw AssetUploadException::create();
36
        }
37
38 42
        $model->assets->where('pivot.type', $type)->where('pivot.locale', $locale);
39
40 42
        $locale = $locale ?? config('app.fallback_locale');
41
42 42
        $model->assets()->attach($this, ['type' => $type, 'locale' => $locale, 'order' => $this->order]);
43
44 42
        return $model->load('assets');
0 ignored issues
show
Bug introduced by
The method load() does not exist on Thinktomorrow\AssetLibrary\Interfaces\HasAsset. Since it exists in all sub-types, consider adding an abstract or default implementation to Thinktomorrow\AssetLibrary\Interfaces\HasAsset. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

44
        return $model->/** @scrutinizer ignore-call */ load('assets');
Loading history...
45
    }
46
47
    /**
48
     * @return bool
49
     */
50 1
    public function hasFile(): bool
51
    {
52 1
        return (bool) $this->getFileUrl();
53
    }
54
55
    /**
56
     * @param string $size
57
     * @return string
58
     */
59 12
    public function getFilename($size = ''): string
60
    {
61 12
        return basename($this->getFileUrl($size));
62
    }
63
64
    /**
65
     * @param string $size
66
     * @return string
67
     */
68 54
    public function getFileUrl($size = ''): string
69
    {
70 54
        $media = $this->getMedia()->first();
71 54
        if ($media == null) {
72 1
            throw CorruptMediaException::corrupt($this->id);
73
        }
74
75 53
        if ($media == null) {
76
            throw CorruptMediaException::corrupt($this->id);
77
        }
78
79 53
        return $media->getUrl($size);
80
    }
81
82
    /**
83
     * Returns the image url or a fallback specific per filetype.
84
     *
85
     * @param string $type
86
     * @return string
87
     */
88 10
    public function getImageUrl($type = ''): string
89
    {
90 10
        if ($this->getMedia()->isEmpty()) {
91 2
            return asset('assets/back/img/other.png');
92
        }
93 9
        $extension = $this->getExtensionType();
94 9
        if ($extension === 'image') {
95 8
            return $this->getFileUrl($type);
96 1
        } elseif ($extension) {
97 1
            return asset('assets/back/img/'.$extension.'.png');
98
        }
99
100 1
        return asset('assets/back/img/other.png');
101
    }
102
103
    /**
104
     * @return bool|string
105
     */
106 5
    public function getExtensionForFilter()
107
    {
108 5
        if ($extension = $this->getExtensionType()) {
109 5
            return $extension;
110
        }
111
112 1
        return '';
113
    }
114
115
    /**
116
     * @return null|string
117
     * @throws CorruptMediaException
118
     */
119 14
    public function getExtensionType(): ?string
120
    {
121 14
        $media = $this->getMedia()->first();
122 14
        if ($media == null) {
123
            throw CorruptMediaException::corrupt($this->id);
124
        }
125
126 14
        $extension = explode('.', $media->file_name);
127 14
        $extension = end($extension);
128
129 14
        if ($extension) {
130 14
            if (in_array(strtolower($extension), ['xls', 'xlsx', 'numbers', 'sheets'])) {
131 1
                return 'xls';
132
            }
133 14
            if (in_array(strtolower($extension), ['png', 'jpg', 'jpeg', 'gif', 'svg', 'webp'])) {
134 13
                return 'image';
135
            }
136 3
            if (strtolower($extension) === 'pdf') {
137 2
                return 'pdf';
138
            }
139
        }
140
141 2
        return null;
142
    }
143
144
    /**
145
     * @return string
146
     */
147 2
    public function getMimeType(): string
148
    {
149 2
        return $this->isMediaEmpty() ? '' : $this->getMedia()[0]->mime_type;
150
    }
151
152
    /**
153
     * @return bool
154
     */
155 5
    public function isMediaEmpty(): bool
156
    {
157 5
        return $this->getMedia()->isEmpty();
158
    }
159
160
    /**
161
     * @return string
162
     */
163 2
    public function getSize(): string
164
    {
165 2
        return $this->isMediaEmpty() ? '' : $this->getMedia()[0]->human_readable_size;
166
    }
167
168
    /**
169
     * @param string|null $size
170
     * @return string
171
     */
172 3
    public function getDimensions($size = null): string
173
    {
174 3
        if ($this->isMediaEmpty()) {
175 1
            return '';
176
        }
177
178
        //TODO Check the other sizes as well
179 2
        if ($size === 'cropped') {
180 1
            $dimensions = explode(',', $this->getMedia()[0]->manipulations['cropped']['manualCrop']);
181
182 1
            return $dimensions[0].' x'.$dimensions[1];
183
        }
184
185 1
        return $this->getMedia()[0]->getCustomProperty('dimensions');
186
    }
187
188
    /**
189
     * Removes one or more assets by their ids.
190
     * @param $imageIds
191
     */
192
    public static function removeByIds($imageIds)
193
    {
194
        if (is_array($imageIds)) {
195
            foreach ($imageIds as $id) {
196
                if (! $id) {
197
                    continue;
198
                }
199
200
                self::remove($id);
201
            }
202
        } else {
203
            if (! $imageIds) {
204
                return;
205
            }
206
207
            self::remove($imageIds);
208
        }
209
    }
210
211
    /**
212
     * Removes one assets by id.
213
     * It also checks if you have the permissions to remove the file.
214
     *
215
     * @param $imageIds
216
     */
217
    public static function remove($id)
218
    {
219
        $asset = self::find($id)->first();
220
        $media = $asset->media;
221
222
        foreach ($media as $file) {
223
            if (! is_file(public_path($file->getUrl())) || ! is_writable(public_path($file->getUrl()))) {
224
                return;
225
            }
226
        }
227
228
        $asset->delete();
229
    }
230
231
    /**
232
     * Returns a collection of all the assets in the library.
233
     * @return \Illuminate\Support\Collection
234
     */
235
    public static function getAllAssets(): Collection
236
    {
237
        return self::all()->sortByDesc('created_at');
238
    }
239
240
    /**
241
     * @param $width
242
     * @param $height
243
     * @param $x
244
     * @param $y
245
     * @return $this
246
     * @throws ConfigException
247
     */
248 2
    public function crop($width, $height, $x, $y)
249
    {
250 2
        if (! config('assetlibrary.allowCropping')) {
251 1
            throw ConfigException::create();
252
        }
253 1
        $this->media[0]->manipulations = [
0 ignored issues
show
Bug introduced by
The property media does not seem to exist on Thinktomorrow\AssetLibrary\Models\Asset. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
254
            'cropped'   => [
255 1
                'manualCrop' => $width.', '.$height.', '.$x.', '.$y,
256
            ],
257
        ];
258
259 1
        $this->media[0]->save();
260
261 1
        return $this;
262
    }
263
264
    /**
265
     * Register the conversions that should be performed.
266
     *
267
     * @param Media|null $media
268
     * @throws \Spatie\Image\Exceptions\InvalidManipulation
269
     */
270 47
    public function registerMediaConversions(Media $media = null)
271
    {
272 47
        $conversions = config('assetlibrary.conversions');
273
274 47
        foreach ($conversions as $key => $value) {
275 47
            $this->addMediaConversion($key)
276 47
                ->width($value['width'])
277 47
                ->height($value['height'])
278 47
                ->keepOriginalImageFormat()
279 47
                ->optimize();
280
        }
281
282 47
        if (config('assetlibrary.allowCropping')) {
283 1
            $this->addMediaConversion('cropped')
284 1
                ->keepOriginalImageFormat()
285 1
                ->optimize();
286
        }
287 47
    }
288
289 15
    public function setOrder($order)
290
    {
291 15
        $this->order = $order;
292
293 15
        return $this;
294
    }
295
}
296