zend-blog-3-backend

Форк
0
257 строк · 6.9 Кб
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: morontt
5
 * Date: 03.05.18
6
 * Time: 0:01
7
 */
8

9
namespace App\Model;
10

11
use App\Entity\MediaFile;
12
use App\Entity\Post;
13
use App\Model\Resizer\AvifResizer;
14
use App\Model\Resizer\DefaultResizer;
15
use App\Model\Resizer\JpegResizer;
16
use App\Model\Resizer\PngResizer;
17
use App\Model\Resizer\WebpResizer;
18
use App\Service\ImageManager;
19
use Imagick;
20

21
/**
22
 * @method int getId()
23
 * @method Post|null getPost()
24
 * @method string getPath()
25
 * @method string getOriginalFileName()
26
 * @method int getFileSize()
27
 * @method string|null getDescription()
28
 * @method \DateTime getTimeCreated()
29
 * @method \DateTime getLastUpdate()
30
 * @method bool isDefaultImage()
31
 * @method int|null getWidth()
32
 * @method int|null getHeight()
33
 */
34
class Image
35
{
36
    /**
37
     * @var array
38
     */
39
    protected $sizes = [
40
        'admin_list' => [
41
            'height' => 60,
42
        ],
43
        'article_864' => [
44
            'width' => 864,
45
        ],
46
        'article_624' => [
47
            'width' => 624,
48
        ],
49
        'article_444' => [
50
            'width' => 448,
51
        ],
52
        'article_320' => [
53
            'width' => 320,
54
        ],
55
    ];
56

57
    /**
58
     * @var MediaFile
59
     */
60
    protected $media;
61

62
    /**
63
     * @param MediaFile $media
64
     */
65
    public function __construct(MediaFile $media)
66
    {
67
        $this->media = $media;
68
    }
69

70
    public function getSrcSet(): SrcSet
71
    {
72
        $srcSet = new SrcSet();
73
        $srcSet
74
            ->setOrigin($this->getSrcSetData())
75
            ->setWebp($this->getSrcSetData('webp'))
76
            ->setAvif($this->getSrcSetData('avif'))
77
        ;
78

79
        return $srcSet;
80
    }
81

82
    /**
83
     * @param string|null $format
84
     *
85
     * @return array
86
     */
87
    public function getSrcSetData(string $format = null): array
88
    {
89
        $width = $this->media->getWidth();
90
        $height = $this->media->getHeight();
91

92
        $data = [];
93
        $addOriginal = false;
94
        foreach ($this->sizes as $key => $config) {
95
            if (isset($config['width']) && (strpos($key, 'article_') === 0)) {
96
                if ($config['width'] < $width) {
97
                    if ($newPath = $this->getPreview($key, $format)) {
98
                        $data[] = [
99
                            'width' => $config['width'],
100
                            'height' => (int)round(1.0 * $height * $config['width'] / $width),
101
                            'path' => $newPath,
102
                        ];
103
                    }
104
                } else {
105
                    $addOriginal = true;
106
                }
107
            }
108
        }
109

110
        if ($addOriginal) {
111
            if ($format) {
112
                $ext = pathinfo($this->media->getPath(), PATHINFO_EXTENSION);
113
                $resizer = $this->getResizer($this->media->getPath(), $format);
114
                if ($ext !== $format && method_exists($resizer, 'convert')) {
115
                    $newPath = $resizer->convert($this->media->getPath(), ImageManager::getUploadsDir());
116
                    $data[] = [
117
                        'width' => $width,
118
                        'height' => $height,
119
                        'path' => $newPath,
120
                    ];
121
                }
122
            } else {
123
                $data[] = [
124
                    'width' => $width,
125
                    'height' => $height,
126
                    'path' => $this->media->getPath(),
127
                ];
128
            }
129
        }
130

131
        $data = array_map(function (array $item) {
132
            $item['length'] = (int)filesize(ImageManager::getUploadsDir() . '/' . $item['path']);
133

134
            return $item;
135
        }, $data);
136

137
        usort($data, function ($a, $b) {
138
            if ($a['width'] === $b['width']) {
139
                return 0;
140
            }
141

142
            return ($a['width'] < $b['width']) ? 1 : -1;
143
        });
144

145
        return $data;
146
    }
147

148
    /**
149
     * @param string $size
150
     * @param string|null $format
151
     *
152
     * @return string|null
153
     */
154
    public function getPreview(string $size, string $format = null): ?string
155
    {
156
        $newPath = $this->getPathBySize($this->media->getPath(), $size, $format);
157
        $fsPath = ImageManager::getUploadsDir() . '/' . $this->media->getPath();
158
        $fsNewPath = ImageManager::getUploadsDir() . '/' . $newPath;
159

160
        if (!file_exists($fsNewPath) && file_exists($fsPath) && is_file($fsPath)) {
161
            $resizer = $this->getResizer($fsPath, $format);
162
            try {
163
                $resizer->resize(
164
                    $fsPath,
165
                    $fsNewPath,
166
                    $this->sizes[$size]['width'] ?? 0,
167
                    $this->sizes[$size]['height'] ?? 0
168
                );
169
            } catch (\Throwable $e) {
170
                //TODO add error to logger
171
                return null;
172
            }
173
        }
174

175
        return $newPath;
176
    }
177

178
    /**
179
     * @param string $currentPath
180
     * @param string $size
181
     * @param string|null $format
182
     *
183
     * @return string
184
     */
185
    public function getPathBySize(string $currentPath, string $size, string $format = null): string
186
    {
187
        if (!isset($this->sizes[$size])) {
188
            throw new \RuntimeException('undefined size');
189
        }
190

191
        $pathInfo = pathinfo($currentPath);
192
        if ($pathInfo['dirname'] === '.') {
193
            $dirNamePrefix = '';
194
        } else {
195
            $dirNamePrefix = $pathInfo['dirname'] . '/';
196
        }
197

198
        $ext = $format ?? $pathInfo['extension'];
199

200
        $res = sprintf(
201
            '%s%s%s.%s',
202
            $pathInfo['filename'],
203
            isset($this->sizes[$size]['width']) ? '_' . $this->sizes[$size]['width'] . 'w' : '',
204
            isset($this->sizes[$size]['height']) ? '_' . $this->sizes[$size]['height'] . 'h' : '',
205
            $ext
206
        );
207

208
        return $dirNamePrefix . $res;
209
    }
210

211
    public function getImageGeometry(): ImageGeometry
212
    {
213
        $fsPath = ImageManager::getUploadsDir() . '/' . $this->media->getPath();
214
        $obj = new ImageGeometry();
215

216
        try {
217
            $image = new Imagick($fsPath);
218
            $geometry = $image->getImageGeometry();
219
            $image->clear();
220

221
            $obj->width = $geometry['width'];
222
            $obj->height = $geometry['height'];
223
        } catch (\ImagickException $e) {
224
            //TODO add error to logger
225
        }
226

227
        return $obj;
228
    }
229

230
    /**
231
     * @param $method
232
     * @param $arguments
233
     *
234
     * @return mixed
235
     */
236
    public function __call($method, $arguments)
237
    {
238
        return call_user_func_array([$this->media, $method], $arguments);
239
    }
240

241
    private function getResizer(string $fsPath, string $format = null): ResizerInterface
242
    {
243
        switch ($format ?? strtolower(pathinfo($fsPath, PATHINFO_EXTENSION))) {
244
            case 'jpeg':
245
            case 'jpg':
246
                return new JpegResizer();
247
            case 'png':
248
                return new PngResizer();
249
            case 'webp':
250
                return new WebpResizer();
251
            case 'avif':
252
                return new AvifResizer();
253
        }
254

255
        return new DefaultResizer();
256
    }
257
}
258

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.