Passed
Push — develop ( 69d9cf...9333dd )
by BENARD
04:14
created

Picture::loadFileFromStream()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 2
c 2
b 0
f 0
dl 0
loc 5
rs 10
cc 1
nc 1
nop 2
1
<?php
2
3
namespace VideoGamesRecords\CoreBundle\File;
4
5
use Exception;
6
use GdImage;
7
8
class Picture
9
{
10
    protected $picture = null;
11
12
    protected array $fonts = [];
13
    protected array $colors = [];
14
15
    protected ?string $activeColor = null;
16
    protected ?string $activeFont = null;
17
18
    protected array $mimeTypes = [
19
        'bmp' => 'image/bmp',
20
        'gif' => 'image/gif',
21
        'jpeg' => 'image/jpeg',
22
        'jpg' => 'image/jpeg',
23
        'png' => 'image/png',
24
        'wbmp' => 'image/vnd.wap.wbmp',
25
        'xbm' => 'image/x-xbitmap',
26
    ];
27
28
    /**
29
     * Picture constructor.
30
     * @param      $width
31
     * @param      $height
32
     * @param bool $trueColor
33
     */
34
    public function __construct($width, $height, bool $trueColor = true)
35
    {
36
        $width = (int) $width;
37
        $height = (int) $height;
38
39
        if ($trueColor) {
40
            $this->picture = imagecreatetruecolor($width, $height);
41
        } else {
42
            $this->picture = imagecreate($width, $height);
43
        }
44
    }
45
46
    /**
47
     * @param bool          $keepTrueColor
48
     * @param GdImage|bool $picture
49
     * @return self
50
     */
51
    public static function extracted(bool $keepTrueColor, GdImage|bool $picture): Picture
52
    {
53
        $oSelf = new self(imagesx($picture), imagesy($picture));
0 ignored issues
show
Bug introduced by
It seems like $picture can also be of type boolean; however, parameter $image of imagesy() does only seem to accept GdImage|resource, maybe add an additional type check? ( Ignorable by Annotation )

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

53
        $oSelf = new self(imagesx($picture), imagesy(/** @scrutinizer ignore-type */ $picture));
Loading history...
Bug introduced by
It seems like $picture can also be of type boolean; however, parameter $image of imagesx() does only seem to accept GdImage|resource, maybe add an additional type check? ( Ignorable by Annotation )

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

53
        $oSelf = new self(imagesx(/** @scrutinizer ignore-type */ $picture), imagesy($picture));
Loading history...
54
        if ($keepTrueColor) {
55
            $oSrc = new self(imagesx($picture), imagesy($picture));
56
            $oSrc->setPicture($picture);
57
            $oSelf->copyResized($oSrc, 0, 0);
58
            unset($oSrc);
59
        } else {
60
            $oSelf->setPicture($picture);
61
        }
62
        return $oSelf;
63
    }
64
65
    /**
66
     *
67
     */
68
    public function __destruct()
69
    {
70
        imagedestroy($this->picture);
71
    }
72
73
    /**
74
     * @param $picture
75
     * @return Picture
76
     */
77
    public function setPicture($picture): Picture
78
    {
79
        $this->picture = $picture;
80
        return $this;
81
    }
82
83
    /**
84
     * @return false|int
85
     */
86
    public function getWidth()
87
    {
88
        return imagesx($this->picture);
89
    }
90
91
    /**
92
     * @return false|int
93
     */
94
    public function getHeight()
95
    {
96
        return imagesy($this->picture);
97
    }
98
99
    /**
100
     * @return false|resource|null
101
     */
102
    public function getPicture()
103
    {
104
        return $this->picture;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->picture also could return the type GdImage which is incompatible with the documented return type false|null|resource.
Loading history...
105
    }
106
107
    /**
108
     * @param $name
109
     * @return mixed
110
     * @throws Exception
111
     */
112
    public function getColor($name)
113
    {
114
        if (!isset($this->colors[$name])) {
115
            throw new Exception('Unknown color ' . $name . '.');
116
        }
117
        $this->activeColor = $this->colors[$name];
118
        return $this->colors[$name];
119
    }
120
121
    /**
122
     * @param $name
123
     * @return mixed
124
     * @throws Exception
125
     */
126
    public function getFont($name)
127
    {
128
        if (!isset($this->fonts[$name])) {
129
            throw new Exception('Unknown font ' . $name . '.');
130
        }
131
        $this->activeFont = $this->fonts[$name];
132
        return $this->fonts[$name];
133
    }
134
135
    /**
136
     * @param $name
137
     * @param $filePath
138
     * @return Picture
139
     * @throws Exception
140
     */
141
    public function addFont($name, $filePath): Picture
142
    {
143
        $fontPath = realpath($filePath);
144
        if ($fontPath === false) {
145
            throw new Exception('Unable to load font file. The file does not exists.');
146
        }
147
        $this->fonts[$name] = $fontPath;
148
        $this->activeFont = $fontPath;
149
        return $this;
150
    }
151
152
    /**
153
     * @param      $name
154
     * @param      $red
155
     * @param      $green
156
     * @param      $blue
157
     * @param      $alpha
158
     * @return Picture
159
     */
160
    public function addColor($name, $red, $green, $blue, $alpha = null): Picture
161
    {
162
        $red %= 256;
163
        $green %= 256;
164
        $blue %= 256;
165
        if ($alpha !== null) {
166
            $alpha %= 128;
167
            $color = imagecolorallocatealpha($this->picture, $red, $green, $blue, $alpha);
168
        } else {
169
            $color = imagecolorallocate($this->picture, $red, $green, $blue);
170
        }
171
        $this->colors[$name] = $color;
172
        $this->activeColor = $color;
173
        return $this;
174
    }
175
176
    /**
177
     * @param Picture $pic
178
     * @param                   $dstX
179
     * @param                   $dstY
180
     * @param int               $srcX
181
     * @param int               $srcY
182
     * @param null              $dstW
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $dstW is correct as it would always require null to be passed?
Loading history...
183
     * @param null              $dstH
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $dstH is correct as it would always require null to be passed?
Loading history...
184
     * @param null              $srcW
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $srcW is correct as it would always require null to be passed?
Loading history...
185
     * @param null              $srcH
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $srcH is correct as it would always require null to be passed?
Loading history...
186
     * @return Picture
187
     */
188
    public function copyResized(
189
        Picture $pic,
190
        $dstX,
191
        $dstY,
192
        $srcX = 0,
193
        $srcY = 0,
194
        $dstW = null,
195
        $dstH = null,
196
        $srcW = null,
197
        $srcH = null
198
    ): Picture {
199
        $dstW = is_null($dstW) ? $pic->getWidth() : $dstW;
0 ignored issues
show
introduced by
The condition is_null($dstW) is always true.
Loading history...
200
        $dstH = is_null($dstH) ? $pic->getHeight() : $dstH;
0 ignored issues
show
introduced by
The condition is_null($dstH) is always true.
Loading history...
201
        $srcW = is_null($srcW) ? $pic->getWidth() : $srcW;
0 ignored issues
show
introduced by
The condition is_null($srcW) is always true.
Loading history...
202
        $srcH = is_null($srcH) ? $pic->getHeight() : $srcH;
0 ignored issues
show
introduced by
The condition is_null($srcH) is always true.
Loading history...
203
204
        imagecopyresized($this->picture, $pic->getPicture(), $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH);
205
        return $this;
206
    }
207
208
    /**
209
     * @param      $xA
210
     * @param      $yA
211
     * @param      $xB
212
     * @param      $yB
213
     * @param null $color
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $color is correct as it would always require null to be passed?
Loading history...
214
     * @return Picture
215
     * @throws Exception
216
     */
217
    public function addRectangle($xA, $yA, $xB, $yB, $color = null): Picture
218
    {
219
        if ($color === null) {
0 ignored issues
show
introduced by
The condition $color === null is always true.
Loading history...
220
            $color = $this->activeColor;
221
            if ($color === null) {
222
                throw new Exception('No active color defined.');
223
            }
224
        }
225
        imagefilledrectangle($this->picture, $xA, $yA, $xB, $yB, $color);
0 ignored issues
show
Bug introduced by
$color of type string is incompatible with the type integer expected by parameter $color of imagefilledrectangle(). ( Ignorable by Annotation )

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

225
        imagefilledrectangle($this->picture, $xA, $yA, $xB, $yB, /** @scrutinizer ignore-type */ $color);
Loading history...
226
        return $this;
227
    }
228
229
    /**
230
     * @param      $message
231
     * @param      $size
232
     * @param      $x
233
     * @param      $y
234
     * @param int  $angle
235
     * @param null $color
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $color is correct as it would always require null to be passed?
Loading history...
236
     * @param null $font
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $font is correct as it would always require null to be passed?
Loading history...
237
     * @return Picture
238
     * @throws Exception
239
     */
240
    public function write($message, $size, $x, $y, $angle = 0, $color = null, $font = null): Picture
241
    {
242
        if ($color === null) {
0 ignored issues
show
introduced by
The condition $color === null is always true.
Loading history...
243
            $color = $this->activeColor;
244
            if ($color === null) {
245
                throw new Exception('No active color defined.');
246
            }
247
        }
248
        if ($font === null) {
0 ignored issues
show
introduced by
The condition $font === null is always true.
Loading history...
249
            $font = $this->activeFont;
250
            if ($font === null) {
251
                throw new Exception('No active font defined.');
252
            }
253
        }
254
        imagettftext($this->picture, $size, $angle, $x, $y, $color, $font, $message);
0 ignored issues
show
Bug introduced by
$color of type string is incompatible with the type integer expected by parameter $color of imagettftext(). ( Ignorable by Annotation )

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

254
        imagettftext($this->picture, $size, $angle, $x, $y, /** @scrutinizer ignore-type */ $color, $font, $message);
Loading history...
255
        return $this;
256
    }
257
258
    /**
259
     * @param      $file
260
     * @param bool $keepTrueColor
261
     * @return Picture
262
     * @throws Exception
263
     */
264
    public static function loadFile($file, bool $keepTrueColor = false): Picture
265
    {
266
        $file = realpath($file);
267
        if ($file === false) {
268
            throw new Exception('Unable to load picture file. The file does not exists.');
269
        }
270
271
        $sExtension = mb_strtolower(pathinfo($file, PATHINFO_EXTENSION));
0 ignored issues
show
Bug introduced by
It seems like pathinfo($file, VideoGam...ile\PATHINFO_EXTENSION) can also be of type array; however, parameter $string of mb_strtolower() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

271
        $sExtension = mb_strtolower(/** @scrutinizer ignore-type */ pathinfo($file, PATHINFO_EXTENSION));
Loading history...
272
273
        switch ($sExtension) {
274
            case 'gd':
275
                $picture = imagecreatefromgd($file);
276
                break;
277
            case 'gd2':
278
                $picture = imagecreatefromgd2($file);
279
                break;
280
            case 'gif':
281
                $picture = imagecreatefromgif($file);
282
                break;
283
            case 'jpeg':
284
            case 'jpg':
285
                $picture = imagecreatefromjpeg($file);
286
                break;
287
            case 'png':
288
                $picture = imagecreatefrompng($file);
289
                break;
290
            case 'wbmp':
291
            case 'bmp':
292
                $picture = imagecreatefromwbmp($file);
293
                break;
294
            case 'xbm':
295
                $picture = imagecreatefromxbm($file);
296
                break;
297
            default:
298
                throw new Exception('Unknown extension of file when converting to PHP resource.');
299
        }
300
301
        return self::extracted($keepTrueColor, $picture);
0 ignored issues
show
Bug introduced by
It seems like $picture can also be of type resource; however, parameter $picture of VideoGamesRecords\CoreBu...le\Picture::extracted() does only seem to accept GdImage|boolean, maybe add an additional type check? ( Ignorable by Annotation )

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

301
        return self::extracted($keepTrueColor, /** @scrutinizer ignore-type */ $picture);
Loading history...
302
    }
303
304
    /**
305
     * @param string $data
306
     * @param bool $keepTrueColor
307
     * @return Picture
308
     * @throws Exception
309
     */
310
    public static function loadFileFromStream(string $data, bool $keepTrueColor = false): Picture
311
    {
312
        $picture = imagecreatefromstring($data);
313
314
        return self::extracted($keepTrueColor, $picture);
0 ignored issues
show
Bug introduced by
It seems like $picture can also be of type resource; however, parameter $picture of VideoGamesRecords\CoreBu...le\Picture::extracted() does only seem to accept GdImage|boolean, maybe add an additional type check? ( Ignorable by Annotation )

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

314
        return self::extracted($keepTrueColor, /** @scrutinizer ignore-type */ $picture);
Loading history...
315
    }
316
317
    /**
318
     * @param        $type
319
     * @param string $filename
320
     * @throws Exception
321
     */
322
    public function downloadPicture($type, string $filename): void
323
    {
324
        header('Content-Disposition: "attachement"; filename="' . $filename . '"');
325
        $this->showPicture($type);
326
    }
327
328
    /**
329
     * @param $type
330
     * @throws Exception
331
     */
332
    public function showPicture($type)
333
    {
334
        $method = $this->getMethod($type);
335
        $contentType = $this->getMimeType($type);
336
337
        header('Content-Type: ' . $contentType);
338
        $method($this->picture);
339
        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
340
    }
341
342
    /**
343
     * @param $filename
344
     * @return $this
345
     * @throws Exception
346
     */
347
    public function savePicture($filename): static
348
    {
349
        $sExtension = pathinfo($filename, PATHINFO_EXTENSION);
350
        $method = $this->getMethod($sExtension);
351
352
        $method($this->picture, $filename);
353
        return $this;
354
    }
355
356
    /**
357
     * @param $type
358
     * @return string
359
     * @throws Exception
360
     */
361
    protected function getMethod($type): string
362
    {
363
        switch ($type) {
364
            case 'gd':
365
                $method = 'imagegd';
366
                break;
367
            case 'gd2':
368
                $method = 'imagegd2';
369
                break;
370
            case 'gif':
371
                $method = 'imagegif';
372
                break;
373
            case 'jpeg':
374
            case 'jpg':
375
                $method = 'imagejpeg';
376
                break;
377
            case 'png':
378
                $method = 'imagepng';
379
                break;
380
            case 'wbmp':
381
            case 'bmp':
382
                $method = 'imagewbmp';
383
                break;
384
            case 'xbm':
385
                $method = 'imagexbm';
386
                break;
387
            default:
388
                throw new Exception('Unknown picture type.');
389
        }
390
        return $method;
391
    }
392
393
    /**
394
     * @param $extension
395
     * @return mixed|string
396
     */
397
    public function getMimeType($extension): mixed
398
    {
399
        if (!isset($this->mimeTypes[$extension])) {
400
            return 'application/octet-stream';
401
        }
402
        return $this->mimeTypes[$extension];
403
    }
404
}
405