GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

UploadImageBehavior::getThumbFileName()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
3
namespace h0rseduck\file;
4
5
use Imagine\Image\Box;
6
use Imagine\Image\ImageInterface;
7
use Imagine\Image\ManipulatorInterface;
8
use Yii;
9
use yii\base\InvalidArgumentException;
10
use yii\base\InvalidConfigException;
11
use yii\base\NotSupportedException;
12
use yii\db\BaseActiveRecord;
13
use yii\helpers\ArrayHelper;
14
use yii\helpers\FileHelper;
15
use yii\imagine\Image;
16
17
/**
18
 * UploadImageBehavior automatically uploads image, creates thumbnails and fills
19
 * the specified attribute with a value of the name of the uploaded image.
20
 *
21
 * To use UploadImageBehavior, insert the following code to your ActiveRecord class:
22
 *
23
 * ```php
24
 * use h0rseduck\file\UploadImageBehavior;
25
 *
26
 * function behaviors()
27
 * {
28
 *     return [
29
 *         [
30
 *             'class' => UploadImageBehavior::class,
31
 *             'attribute' => 'file',
32
 *             'scenarios' => ['insert', 'update'],
33
 *             'placeholder' => '@app/modules/user/assets/images/userpic.jpg',
34
 *             'path' => '@webroot/upload/{id}/images',
35
 *             'url' => '@web/upload/{id}/images',
36
 *             'thumbPath' => '@webroot/upload/{id}/images/thumb',
37
 *             'thumbUrl' => '@web/upload/{id}/images/thumb',
38
 *             'autorotate' => true,
39
 *             'thumbs' => [
40
 *                   'thumb' => ['width' => 400, 'quality' => 90],
41
 *                   'preview' => ['width' => 200, 'height' => 200],
42
 *              ],
43
 *         ],
44
 *     ];
45
 * }
46
 * ```
47
 *
48
 * @author Alexander Mohorev <[email protected]>
49
 * @author Alexey Samoylov <[email protected]>
50
 * @author H0rse Duck <[email protected]>
51
 */
52
class UploadImageBehavior extends UploadBehavior
53
{
54
    /**
55
     * @var string
56
     */
57
    public $placeholder;
58
59
    /**
60
     * @var boolean
61
     */
62
    public $createThumbsOnSave = true;
63
64
    /**
65
     * @var boolean
66
     */
67
    public $createThumbsOnRequest = false;
68
69
    /**
70
     * Rotates an image automatically based on EXIF information.
71
     * @var boolean
72
     */
73
    public $autorotate = false;
74
75
    /**
76
     * Whether delete original uploaded image after thumbs generating.
77
     * Defaults to FALSE
78
     * @var boolean
79
     */
80
    public $deleteOriginalFile = false;
81
82
    /**
83
     * @var array the thumbnail profiles
84
     * - `width`
85
     * - `height`
86
     * - `quality`
87
     */
88
    public $thumbs = [
89
        'thumb' => ['width' => 200, 'height' => 200, 'quality' => 90],
90
    ];
91
92
    /**
93
     * @var string|null
94
     */
95
    public $thumbPath;
96
97
    /**
98
     * @var string|null
99
     */
100
    public $thumbUrl;
101
102
    /**
103
     * @var ImageInterface
104
     */
105
    private $originalImage;
106
107
    /**
108
     * @inheritdoc
109
     * @throws NotSupportedException
110
     * @throws InvalidConfigException
111
     */
112
    public function init()
113
    {
114
        if (!class_exists(Image::class)) {
115
            throw new NotSupportedException("Yii2-imagine extension is required to use the UploadImageBehavior");
116
        }
117
118
        parent::init();
119
120
        if ($this->createThumbsOnSave || $this->createThumbsOnRequest) {
121
            if ($this->thumbPath === null) {
122
                $this->thumbPath = $this->path;
123
            }
124
            if ($this->thumbUrl === null) {
125
                $this->thumbUrl = $this->url;
126
            }
127
        }
128
    }
129
130
    /**
131
     * @inheritdoc
132
     * @throws InvalidConfigException
133
     * @throws \yii\base\Exception
134
     */
135
    protected function afterUpload()
136
    {
137
        parent::afterUpload();
138
        $path = $this->getPathOriginalImage();
139
        if ($path) {
140
            $this->originalImage = Image::getImagine()->open($path);
141
            if ($this->autorotate) {
142
                Image::autorotate($this->originalImage)->save($path);
0 ignored issues
show
Bug introduced by
It seems like $path defined by $this->getPathOriginalImage() on line 138 can also be of type boolean; however, Imagine\Image\ManipulatorInterface::save() does only seem to accept string|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
143
            }
144
            if ($this->createThumbsOnSave) {
145
                $this->createThumbs($path);
146
            }
147
        }
148
    }
149
150
    /**
151
     * @param $path
152
     * @throws InvalidConfigException
153
     * @throws \yii\base\Exception
154
     */
155
    protected function createThumbs($path)
156
    {
157
        foreach ($this->thumbs as $profile => $config) {
158
            $thumbPath = $this->getThumbUploadPath($this->attribute, $profile);
159
            if ($thumbPath !== null) {
160
                if (!FileHelper::createDirectory(dirname($thumbPath))) {
161
                    throw new InvalidArgumentException(
162
                        "Directory specified in 'thumbPath' attribute doesn't exist or cannot be created."
163
                    );
164
                }
165
                if (!is_file($thumbPath)) {
166
                    $this->generateImageThumb($config, $path, $thumbPath);
0 ignored issues
show
Bug introduced by
It seems like $thumbPath defined by $this->getThumbUploadPat...s->attribute, $profile) on line 158 can also be of type boolean; however, h0rseduck\file\UploadIma...r::generateImageThumb() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
167
                }
168
            }
169
        }
170
171
        if ($this->deleteOriginalFile) {
172
            parent::delete($this->attribute);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (delete() instead of createThumbs()). Are you sure this is correct? If so, you might want to change this to $this->delete().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
173
        }
174
    }
175
176
    /**
177
     * @param string $attribute
178
     * @param string $profile
179
     * @param boolean $old
180
     * @return string
181
     */
182
    public function getThumbUploadPath($attribute, $profile = 'thumb', $old = false)
183
    {
184
        /** @var BaseActiveRecord $model */
185
        $model = $this->owner;
186
        $path = $this->resolvePath($this->thumbPath);
187
        $attribute = ($old === true) ? $model->getOldAttribute($attribute) : $model->$attribute;
188
        $filename = $this->getThumbFileName($attribute, $profile);
189
190
        return $filename ? Yii::getAlias($path . '/' . $filename) : null;
191
    }
192
193
    /**
194
     * @param string $attribute
195
     * @param string $profile
196
     * @return string|null
197
     * @throws InvalidConfigException
198
     * @throws \yii\base\Exception
199
     */
200
    public function getThumbUploadUrl($attribute, $profile = 'thumb')
201
    {
202
        /** @var BaseActiveRecord $model */
203
        $model = $this->owner;
204
        $path = $this->getPathOriginalImage();
205
        if ($path && $this->createThumbsOnRequest) {
206
            $this->createThumbs($path);
207
        }
208
209
        if (is_file($this->getThumbUploadPath($attribute, $profile))) {
210
            $url = $this->resolvePath($this->thumbUrl);
211
            $fileName = $model->getOldAttribute($attribute);
212
            $thumbName = $this->getThumbFileName($fileName, $profile);
213
214
            return Yii::getAlias($url . '/' . $thumbName);
215
        } elseif ($this->placeholder) {
216
            return $this->getPlaceholderUrl($profile);
217
        } else {
218
            return null;
219
        }
220
    }
221
222
    /**
223
     * @param $profile
224
     * @return string
225
     * @throws InvalidConfigException
226
     */
227
    protected function getPlaceholderUrl($profile)
228
    {
229
        list ($path, $url) = Yii::$app->assetManager->publish($this->placeholder);
230
        $filename = basename($path);
231
        $thumb = $this->getThumbFileName($filename, $profile);
232
        $thumbPath = dirname($path) . DIRECTORY_SEPARATOR . $thumb;
233
        $thumbUrl = dirname($url) . '/' . $thumb;
234
235
        if (!is_file($thumbPath)) {
236
            $this->generateImageThumb($this->thumbs[$profile], $path, $thumbPath);
237
        }
238
239
        return $thumbUrl;
240
    }
241
242
    /**
243
     * @inheritdoc
244
     */
245
    protected function delete($attribute, $old = false)
246
    {
247
        parent::delete($attribute, $old);
248
249
        $profiles = array_keys($this->thumbs);
250
        foreach ($profiles as $profile) {
251
            $path = $this->getThumbUploadPath($attribute, $profile, $old);
252
            if (is_file($path)) {
253
                unlink($path);
254
            }
255
        }
256
    }
257
258
    /**
259
     * @param $filename
260
     * @param string $profile
261
     * @return string
262
     */
263
    protected function getThumbFileName($filename, $profile = 'thumb')
264
    {
265
        return $profile . '-' . $filename;
266
    }
267
268
    /**
269
     * @param array $config
270
     * @param string $path
271
     * @param string $thumbPath
272
     * @throws InvalidConfigException
273
     */
274
    protected function generateImageThumb($config, $path, $thumbPath)
0 ignored issues
show
Unused Code introduced by
The parameter $path is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
275
    {
276
        $width = $this->getConfigValue($config, 'width');
277
        $height = $this->getConfigValue($config, 'height');
278
279
        if ($height < 1 && $width < 1) {
280
            throw new InvalidConfigException(sprintf(
281
                'Length of either side of thumb cannot be 0 or negative, current size ' .
282
                'is %sx%s', $width, $height
283
            ));
284
        }
285
286
        $quality = $this->getConfigValue($config, 'quality', 100);
287
        $mode = $this->getConfigValue($config, 'mode', ManipulatorInterface::THUMBNAIL_INSET);
288
        $bg_color = $this->getConfigValue($config, 'bg_color', 'FFF');
289
290
        if (!$width || !$height) {
291
            $ratio = $this->originalImage->getSize()->getWidth() / $this->originalImage->getSize()->getHeight();
292
            if ($width) {
293
                $height = ceil($width / $ratio);
294
            } else {
295
                $width = ceil($height * $ratio);
296
            }
297
        }
298
299
        $processor = ArrayHelper::getValue($config, 'processor');
300
        if (!$processor || !is_callable($processor)) {
301
            $processor = function (ImageInterface $thumb) use ($width, $height, $mode) {
302
                $thumb->thumbnail(new Box($width, $height), $mode);
303
            };
304
        }
305
306
        // Fix error "PHP GD Allowed memory size exhausted".
307
        ini_set('memory_limit', '512M');
308
        Image::$thumbnailBackgroundColor = $bg_color;
309
310
        $thumb = clone $this->originalImage;
311
        call_user_func($processor, $thumb);
312
        $thumb->save($thumbPath, ['quality' => $quality]);
313
    }
314
315
    /**
316
     * @param array $config
317
     * @param string $attribute
318
     * @param mixed|null $default
319
     * @return mixed
320
     */
321
    private function getConfigValue($config, $attribute, $default = null)
322
    {
323
        $value = ArrayHelper::getValue($config, $attribute, $default);
324
        if ($value instanceof \Closure) {
325
            $value = call_user_func($value, $this->owner);
326
        }
327
        return $value;
328
    }
329
330
    /**
331
     * @return bool|string
332
     */
333
    private function getPathOriginalImage()
334
    {
335
        $path = $this->getUploadPath($this->attribute);
336
        if (!$path || !is_file($path)) {
337
            return false;
338
        }
339
        return $path;
340
    }
341
}
342