Passed
Push — dependabot/npm_and_yarn/string... ( b56eb5...bc569b )
by
unknown
45:46 queued 33s
created

UploadMedia   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 140
Duplicated Lines 0 %

Test Coverage

Coverage 90.63%

Importance

Changes 0
Metric Value
wmc 35
eloc 55
dl 0
loc 140
ccs 58
cts 64
cp 0.9063
rs 9.6
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A validateFileUploads() 0 10 6
A sluggifyFilename() 0 7 1
A addFiles() 0 10 6
A addFile() 0 14 3
A fromUploadComponent() 0 22 5
A addAsset() 0 15 3
A replaceFiles() 0 11 6
A removeFiles() 0 5 5
1
<?php
2
3
namespace Thinktomorrow\Chief\Media;
4
5
use Illuminate\Http\UploadedFile;
6
use Spatie\MediaLibrary\HasMedia\HasMedia;
7
use Thinktomorrow\AssetLibrary\Models\Asset;
8
use Thinktomorrow\AssetLibrary\Models\AssetUploader;
9
10
class UploadMedia
11
{
12
    /**
13
     * Upload from base64encoded files, usually
14
     * coming from slim upload component
15
     */
16 50
    public function fromUploadComponent(HasMedia $model, array $files_by_type, array $files_order_by_type)
17
    {
18
        // When no files are uploaded, we still would like to sort our assets duh
19 50
        if (empty($files_by_type)) {
20 41
            foreach ($files_order_by_type as $type => $files_order) {
21 1
                $model->sortFiles($type, explode(',', $files_order));
22
            }
23
24 41
            return;
25
        }
26
27
        // We allow for more memory consumption because the gd decoding can require a lot of memory when parsing large images.
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 126 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
28 9
        ini_set('memory_limit', '256M');
29 9
        foreach ($files_by_type as $type => $files) {
30 9
            $this->validateFileUploads($files);
31
32 9
            $files_order = isset($files_order_by_type[$type]) ? explode(',', $files_order_by_type[$type]) : [];
33 9
            $this->addFiles($model, $type, $files, $files_order);
34 9
            $this->replaceFiles($model, $files);
35 9
            $this->removeFiles($model, $files);
36
37 9
            $model->sortFiles($type, $files_order);
38
        }
39 9
    }
40
41 9
    private function addFiles(HasMedia $model, string $type, array $files, array &$files_order)
42
    {
43 9
        if (isset($files['new']) && is_array($files['new']) && !empty($files['new'])) {
44 7
            foreach ($files['new'] as $file) {
45
                // new but removed files are passed as null, just leave them alone!
46 7
                if (!$file) {
47
                    continue;
48
                }
49
50 7
                $this->addFile($model, $type, $files_order, $file);
51
            }
52
        }
53 9
    }
54
55 7
    private function addFile(HasMedia $model, string $type, array &$files_order, $file)
56
    {
57 7
        if (is_string($file)) {
58 4
            $image_name = json_decode($file)->output->name;
59 4
            $asset      = $this->addAsset(json_decode($file)->output->image, $type, null, $image_name, $model);
60
        } else {
61 4
            $image_name = $file->getClientOriginalName();
62 4
            $asset      = $this->addAsset($file, $type, null, $image_name, $model);
63
        }
64
65
        // New files are passed with their filename (instead of their id)
66
        // For new files we will replace the filename with the id.
67 7
        if (false !== ($key = array_search($image_name, $files_order))) {
68
            $files_order[$key] = $asset->id;
69
        }
70 7
    }
71
72
    /**
73
     * Note: this is a replication of the AssetTrait::addFile() with the exception
74
     * that we want to return the asset in order to retrieve the id. This is
75
     * currently not available via the AssetTrait.
76
     */
77 7
    private function addAsset($file, $type = '', $locale = null, $filename = null, HasMedia $model)
0 ignored issues
show
Coding Style introduced by
Parameters which have default values should be placed at the end.

If you place a parameter with a default value before a parameter with a default value, the default value of the first parameter will never be used as it will always need to be passed anyway:

// $a must always be passed; it's default value is never used.
function someFunction($a = 5, $b) { }
Loading history...
78
    {
79 7
        $filename = $this->sluggifyFilename($filename);
80
81 7
        if (is_string($file)) {
82 4
            $asset = AssetUploader::uploadFromBase64($file, $filename);
83
        } else {
84 4
            $asset = AssetUploader::upload($file, $filename);
85
        }
86
87 7
        if ($asset instanceof Asset) {
88 7
            $asset->attachToModel($model, $type, $locale);
89
        }
90
91 7
        return $asset;
92
    }
93
94
    /**
95
     * @param HasMedia $model
96
     * @param array $files
97
     * @return array
98
     */
99 9
    private function replaceFiles(HasMedia $model, array $files)
100
    {
101 9
        if (isset($files['replace']) && is_array($files['replace']) && !empty($files['replace'])) {
102 1
            foreach ($files['replace'] as $id => $file) {
103
                // Existing files are passed as null, just leave them alone!
104 1
                if (!$file) {
105
                    continue;
106
                }
107
108 1
                $asset = AssetUploader::uploadFromBase64(json_decode($file)->output->image, json_decode($file)->output->name);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 126 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
109 1
                $model->replaceAsset($id, $asset->id);
110
            }
111
        }
112 9
    }
113
114 9
    private function removeFiles(HasMedia $model, array $files)
115
    {
116 9
        if (isset($files['delete']) && is_array($files['delete']) && !empty($files['delete'])) {
117 2
            foreach($model->assets()->whereIn('id', $files['delete'])->get() as $asset){
118 2
                $asset->delete();
119
            }
120
        }
121 9
    }
122
123
    /**
124
     * @param $filename
125
     * @return string
126
     */
127 7
    private function sluggifyFilename($filename): string
128
    {
129 7
        $extension = substr($filename, strrpos($filename, '.') + 1);
130 7
        $filename  = substr($filename, 0, strrpos($filename, '.'));
131 7
        $filename  = str_slug($filename) . '.' . $extension;
0 ignored issues
show
Deprecated Code introduced by
The function str_slug() has been deprecated: Str::slug() should be used directly instead. Will be removed in Laravel 5.9. ( Ignorable by Annotation )

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

131
        $filename  = /** @scrutinizer ignore-deprecated */ str_slug($filename) . '.' . $extension;

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
132
133 7
        return $filename;
134
    }
135
136
    /**
137
     * @param $files
138
     * @throws FileTooBigException
139
     */
140 9
    private function validateFileUploads($files): void
141
    {
142 9
        foreach ($files as $_files) {
143 9
            foreach ($_files as $file) {
144 9
                if ($file instanceof UploadedFile && !$file->isValid()) {
145
                    if ($file->getError() == UPLOAD_ERR_INI_SIZE) {
146
                        throw new FileTooBigException(
0 ignored issues
show
Bug introduced by
The type Thinktomorrow\Chief\Media\FileTooBigException 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...
147
                            'Cannot upload file because it exceeded the allowed upload_max_filesize: upload_max_filesize is smaller than post size. ' .
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 151 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
148
                            'upload_max_filesize: ' . (int)ini_get('upload_max_filesize') . 'MB, ' .
149 9
                            'post_max_size: ' . (int)(ini_get('post_max_size')) . 'MB'
150
                        );
151
                    }
152
                }
153
            }
154
        }
155 9
    }
156
}
157