Passed
Push — master ( 3f7190...385f04 )
by Adrien
13:37
created

Image::readFileInfo()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 48
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 31
c 1
b 0
f 0
dl 0
loc 48
ccs 23
cts 23
cp 1
rs 8.8017
cc 6
nc 10
nop 0
crap 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Ecodev\Felix\Model\Traits;
6
7
use Doctrine\ORM\Mapping as ORM;
8
use GraphQL\Doctrine\Attribute as API;
9
use Imagine\Filter\Basic\Autorotate;
10
use Imagine\Image\Box;
11
use Imagine\Image\ImagineInterface;
12
use Psr\Http\Message\UploadedFileInterface;
13
14
/**
15
 * An image and some information about it.
16
 */
17
trait Image
18
{
19
    use AbstractFile {
20
        setFile as abstractFileSetFile;
21
    }
22
23 1
    protected function getBasePath(): string
24
    {
25 1
        return 'data/images/';
26
    }
27
28 6
    protected function getAcceptedMimeTypes(): array
29
    {
30
        return [
31 6
            'image/bmp',
32
            'image/x-ms-bmp',
33
            'image/gif',
34
            'image/jpeg',
35
            'image/pjpeg',
36
            'image/png',
37
            'image/svg+xml',
38
            'image/webp',
39
        ];
40
    }
41
42
    #[ORM\Column(type: 'integer')]
43
    private int $width = 0;
44
45
    #[ORM\Column(type: 'integer')]
46
    private int $height = 0;
47
48
    /**
49
     * Get image width.
50
     */
51 7
    public function getWidth(): int
52
    {
53 7
        return $this->width;
54
    }
55
56
    /**
57
     * Set image width.
58
     */
59 7
    #[API\Exclude]
60
    public function setWidth(int $width): void
61
    {
62 7
        $this->width = $width;
63
    }
64
65
    /**
66
     * Get image height.
67
     */
68 7
    public function getHeight(): int
69
    {
70 7
        return $this->height;
71
    }
72
73
    /**
74
     * Set image height.
75
     */
76 7
    #[API\Exclude]
77
    public function setHeight(int $height): void
78
    {
79 7
        $this->height = $height;
80
    }
81
82
    /**
83
     * Set the file.
84
     */
85 6
    public function setFile(UploadedFileInterface $file): void
86
    {
87 6
        $this->abstractFileSetFile($file);
88 6
        $this->readFileInfo();
89
    }
90
91
    /**
92
     * Read dimension and size from file on disk.
93
     */
94 6
    private function readFileInfo(): void
95
    {
96
        global $container;
97 6
        $path = $this->getPath();
98
99
        /** @var ImagineInterface $imagine */
100 6
        $imagine = $container->get(ImagineInterface::class);
101 6
        $image = $imagine->open($path);
102
103 6
        $size = $image->getSize();
104 6
        $maxSize = 3500; // Maximum size ever of an image is a bit less than 4K
105 6
        $tooBig = $size->getWidth() > $maxSize || $size->getHeight() > $maxSize;
106
107
        // Pretty much only SVG is better than WebP
108 6
        $worseThanWebp = in_array($this->getMime(), [
109
            'image/bmp',
110
            'image/x-ms-bmp',
111
            'image/gif',
112
            'image/jpeg',
113
            'image/pjpeg',
114
            'image/png', // We lose animation, even though WebP supports it, but we assume we never use animated PNG anyway
115
        ], true);
116
117 6
        if ($tooBig || $worseThanWebp) {
118
            // Auto-rotate image if EXIF says it's rotated, but only JPG, otherwise it might deteriorate other format (SVG)
119 4
            if ($this->getMime() === 'image/jpeg') {
120 2
                $autorotate = new Autorotate();
121 2
                $autorotate->apply($image);
122
            }
123
124 4
            $image = $image->thumbnail(new Box($maxSize, $maxSize));
125 4
            $size = $image->getSize();
126
127
            // Replace extension
128 4
            if ($worseThanWebp) {
129 3
                $this->setFilename(preg_replace('~((\\.[^.]+)?$)~', '', $this->getFilename()) . '.webp');
130 3
                $newPath = $this->getPath();
131 3
                $image->save($newPath);
132 3
                unlink($path);
133
            } else {
134 1
                $image->save($path);
135
            }
136
137 4
            $this->validateMimeType();
138
        }
139
140 6
        $this->setWidth($size->getWidth());
141 6
        $this->setHeight($size->getHeight());
142
    }
143
}
144