Image::readFileInfo()   B
last analyzed

Complexity

Conditions 6
Paths 10

Size

Total Lines 45
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 26
CRAP Score 6

Importance

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