Completed
Pull Request — master (#14)
by
unknown
15:13 queued 07:44
created

Image::storeFile()   B

Complexity

Conditions 10
Paths 96

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 110

Importance

Changes 0
Metric Value
dl 0
loc 31
ccs 0
cts 26
cp 0
rs 7.6666
c 0
b 0
f 0
cc 10
nc 96
nop 8
crap 110

How to fix   Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace Yaro\Jarboe\Table\Fields;
4
5
use Illuminate\Http\Request;
6
use Illuminate\Http\UploadedFile;
7
use Illuminate\Support\Arr;
8
use Illuminate\Support\Str;
9
use Yaro\Jarboe\Table\Fields\Traits\Filename;
10
use Yaro\Jarboe\Table\Fields\Traits\Nullable;
11
use Yaro\Jarboe\Table\Fields\Traits\Placeholder;
12
use Yaro\Jarboe\Table\Fields\Traits\Storage;
13
use Illuminate\Support\Facades\Storage as IlluminateStorage;
14
use Intervention\Image\ImageManagerStatic as InterventionImage;
15
16
class Image extends AbstractField
17
{
18
    use Storage;
19
    use Placeholder;
20
    use Nullable;
21
    use Filename;
22
23
    protected $encode = false;
24
    protected $crop = false;
25
    protected $ratio = [
26
        'width'  => false,
27
        'height' => false,
28
    ];
29
    private $originalImageData;
30
    private $defaultImageDataStructure =  [
31
        'storage' => [
32
            'disk' => null,
33
            'is_encoded' => false,
34
        ],
35
        'crop' => [
36
            'width' => null,
37
            'height' => null,
38
            'x' => null,
39
            'y' => null,
40
            'rotate' => null,
41
            'rotate_background' => null,
42
        ],
43
        'sources' => [
44
            'original' => null,
45
            'cropped' => null,
46
        ],
47
    ];
48
49
    public function __construct()
50
    {
51
        $this->disk = config('filesystems.default');
52
    }
53
54
    public function isEncode()
55
    {
56
        return $this->encode;
57
    }
58
59
    /**
60
     * Encode image as data-url.
61
     *
62
     * @param bool $encode
63
     * @return $this
64
     */
65
    public function encode(bool $encode = true)
66
    {
67
        $this->encode = $encode;
68
69
        return $this;
70
    }
71
72
    protected function storeFile($filepath, $filename, $width = null, $height = null, $x = null, $y = null, $rotate = null, $rotateBackgroundColor = null)
73
    {
74
        $image = InterventionImage::make($filepath);
75
        $rotateBackgroundColor = $rotateBackgroundColor ?: 'rgba(255, 255, 255, 0)';
76
77
        if ($rotate) {
78
            // because js plugin and php library rotating in different directions.
79
            $angle = $rotate * -1;
80
            $image->rotate($angle, $rotateBackgroundColor);
81
        }
82
        $hasCropProperties = !is_null($width) && !is_null($height) && !is_null($x) && !is_null($y);
83
        if ($this->isCrop() && $hasCropProperties) {
84
            $image->crop(round($width), round($height), round($x), round($y));
85
        }
86
87
        if ($this->isEncode()) {
88
            return (string) $image->encode('data-url');
89
        }
90
91
        $format = '';
92
        if ($this->isTransparentColor($rotateBackgroundColor)) {
93
            $format = 'png';
94
        }
95
        $path = trim($this->getPath() .'/'. $filename, '/');
96
        IlluminateStorage::disk($this->getDisk())->put(
97
            $path,
98
            (string) $image->encode($format)
99
        );
100
101
        return $path;
102
    }
103
104
    public function value(Request $request)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
105
    {
106
        $images = $request->all($this->name());
107
        $images = $images[$this->name()];
108
109
        $data = [];
110
        foreach ($images as $image) {
111
            $imageData = $this->defaultImageDataStructure;
112
            $imageData['storage'] = [
113
                'disk' => $this->getDisk(),
114
                'is_encoded' => $this->isEncode(),
115
            ];
116
117
            $imageData['crop'] = $image['crop'];
118
            $imageData['sources'] = $image['sources'];
119
            /** @var UploadedFile|null $file */
120
            $file = $image['file'] ?? null;
121
            if ($file) {
122
                $imageData['sources']['original'] = $this->storeFile(
123
                    $file->getRealPath(),
124
                    $this->generateFilename(
125
                        $request,
126
                        $file,
127
                        $image,
128
                        $this->isTransparentColor((string) $image['crop']['rotate_background']),
129
                        true
130
                    )
131
                );
132
                $imageData['sources']['cropped'] = $this->storeFile(
133
                    $file->getRealPath(),
134
                    $this->generateFilename(
135
                        $request,
136
                        $file,
137
                        $image,
138
                        $this->isTransparentColor((string) $image['crop']['rotate_background']),
139
                        false
140
                    ),
141
                    $image['crop']['width'],
142
                    $image['crop']['height'],
143
                    $image['crop']['x'],
144
                    $image['crop']['y'],
145
                    $image['crop']['rotate'],
146
                    $image['crop']['rotate_background']
147
                );
148
            } elseif (!$image['sources']['original']) {
149
                continue;
150
            } elseif ($this->isCrop() && !$image['sources']['cropped']) {
151
                $imageData['sources']['cropped'] = $this->storeFile(
152
                    IlluminateStorage::disk($this->getDisk())->path($imageData['sources']['original']),
153
                    $this->generateFilename(
154
                        $request,
155
                        null,
156
                        $image,
157
                        $this->isTransparentColor((string) $image['crop']['rotate_background']),
158
                        false
159
                    ),
160
                    $image['crop']['width'],
161
                    $image['crop']['height'],
162
                    $image['crop']['x'],
163
                    $image['crop']['y'],
164
                    $image['crop']['rotate'],
165
                    $image['crop']['rotate_background']
166
                );
167
            }
168
169
            $data[] = $imageData;
170
        }
171
172
        if (!$this->isMultiple()) {
173
            $data = array_pop($data);
174
        }
175
176
        $data = $data ?: [];
177
        if ($this->isNullable() ) {
178
            $data = $data ?: null;
179
        }
180
181
        return $data;
182
    }
183
184
    public function crop(bool $enabled = true)
185
    {
186
        $this->crop = $enabled;
187
188
        return $this;
189
    }
190
191
    public function ratio(int $width, int $height)
192
    {
193
        $this->ratio['width'] = $width;
194
        $this->ratio['height'] = $height;
195
196
        return $this;
197
    }
198
199
    public function isCrop()
200
    {
201
        return $this->crop;
202
    }
203
204 View Code Duplication
    public function getRatio(string $type)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
205
    {
206
        $type = strtolower($type);
207
208
        switch ($type) {
209
            case 'width':
210
            case 'height':
211
                return $this->ratio[$type];
212
            default:
213
                return false;
214
        }
215
    }
216
217
    public function getListView($model)
218
    {
219
        return view('jarboe::crud.fields.image.list', [
220
            'model' => $model,
221
            'field' => $this,
222
        ]);
223
    }
224
225
    public function getEditFormView($model)
226
    {
227
        $template = $this->isReadonly() ? 'readonly' : 'edit';
228
229
        return view('jarboe::crud.fields.image.'. $template, [
230
            'model' => $model,
231
            'field' => $this,
232
        ]);
233
    }
234
235
    public function getCreateFormView()
236
    {
237
        return view('jarboe::crud.fields.image.create', [
238
            'model' => null,
239
            'field' => $this,
240
        ]);
241
    }
242
243
    public function getImage($data = []): \Yaro\Jarboe\Pack\Image
244
    {
245
        return new \Yaro\Jarboe\Pack\Image($data);
246
    }
247
248
    private function isTransparentColor(string $rgbaColor)
249
    {
250
        $segmentsString = preg_replace('~rgba\(|\)~', '', $rgbaColor);
251
        $segments = explode(',', $segmentsString);
252
253
        $opacity = $segments[3] ?? 0;
254
255
        return $opacity < 1;
256
    }
257
258
    /**
259
     * @param Request $request
260
     * @param UploadedFile|null $file
261
     * @param array $imageData
262
     * @param bool $hasTransparentColor
263
     * @param bool $isOriginalImage
264
     * @return string
265
     */
266
    private function generateFilename(Request $request, UploadedFile $file = null, array $imageData, bool $hasTransparentColor, bool $isOriginalImage): string
267
    {
268
        $isRecropFromOriginal = !$file && !$isOriginalImage;
269
        $extension = $isRecropFromOriginal ? pathinfo($imageData['sources']['original'], PATHINFO_EXTENSION) : $file->extension();
0 ignored issues
show
Bug introduced by
It seems like $file is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
270
        $filename = Str::random(40) .'.'. $extension;
271
272
        $closure = $this->filenameClosure;
273
        if (is_callable($closure)) {
274
            $filename = $closure($file, $request, $imageData, $isOriginalImage);
275
        }
276
277
        if ($hasTransparentColor) {
278
            $regexp = '~'. preg_quote(pathinfo($filename, PATHINFO_EXTENSION)) .'$~';
279
            $filename = preg_replace($regexp, 'png', $filename);
280
        }
281
282
        return (string) $filename;
283
    }
284
285
    public function getImagesPack($model): array
286
    {
287
        $defaultImage = $this->getImage();
288
        if (!$model) {
289
            return [$defaultImage];
290
        }
291
292
        $imagesData = $this->getAttribute($model);
293
        if (!is_array($imagesData)) {
294
            $imagesData = [];
295
        }
296
297
        if (!$this->isMultiple()) {
298
            $imagesData = [$imagesData];
299
        }
300
301
302
        $pack = [];
303
        foreach ($imagesData as $imageData) {
304
            $pack[] = $this->getImage($imageData);
305
        }
306
307
        return $pack ?: [$defaultImage];
308
    }
309
}
310