zend-blog-3-backend
257 строк · 6.9 Кб
1<?php
2/**
3* Created by PhpStorm.
4* User: morontt
5* Date: 03.05.18
6* Time: 0:01
7*/
8
9namespace App\Model;10
11use App\Entity\MediaFile;12use App\Entity\Post;13use App\Model\Resizer\AvifResizer;14use App\Model\Resizer\DefaultResizer;15use App\Model\Resizer\JpegResizer;16use App\Model\Resizer\PngResizer;17use App\Model\Resizer\WebpResizer;18use App\Service\ImageManager;19use 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*/
34class Image35{
36/**37* @var array
38*/
39protected $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*/
60protected $media;61
62/**63* @param MediaFile $media
64*/
65public function __construct(MediaFile $media)66{67$this->media = $media;68}69
70public function getSrcSet(): SrcSet71{72$srcSet = new SrcSet();73$srcSet74->setOrigin($this->getSrcSetData())75->setWebp($this->getSrcSetData('webp'))76->setAvif($this->getSrcSetData('avif'))77;78
79return $srcSet;80}81
82/**83* @param string|null $format
84*
85* @return array
86*/
87public function getSrcSetData(string $format = null): array88{89$width = $this->media->getWidth();90$height = $this->media->getHeight();91
92$data = [];93$addOriginal = false;94foreach ($this->sizes as $key => $config) {95if (isset($config['width']) && (strpos($key, 'article_') === 0)) {96if ($config['width'] < $width) {97if ($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
110if ($addOriginal) {111if ($format) {112$ext = pathinfo($this->media->getPath(), PATHINFO_EXTENSION);113$resizer = $this->getResizer($this->media->getPath(), $format);114if ($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
134return $item;135}, $data);136
137usort($data, function ($a, $b) {138if ($a['width'] === $b['width']) {139return 0;140}141
142return ($a['width'] < $b['width']) ? 1 : -1;143});144
145return $data;146}147
148/**149* @param string $size
150* @param string|null $format
151*
152* @return string|null
153*/
154public function getPreview(string $size, string $format = null): ?string155{156$newPath = $this->getPathBySize($this->media->getPath(), $size, $format);157$fsPath = ImageManager::getUploadsDir() . '/' . $this->media->getPath();158$fsNewPath = ImageManager::getUploadsDir() . '/' . $newPath;159
160if (!file_exists($fsNewPath) && file_exists($fsPath) && is_file($fsPath)) {161$resizer = $this->getResizer($fsPath, $format);162try {163$resizer->resize(164$fsPath,165$fsNewPath,166$this->sizes[$size]['width'] ?? 0,167$this->sizes[$size]['height'] ?? 0168);169} catch (\Throwable $e) {170//TODO add error to logger171return null;172}173}174
175return $newPath;176}177
178/**179* @param string $currentPath
180* @param string $size
181* @param string|null $format
182*
183* @return string
184*/
185public function getPathBySize(string $currentPath, string $size, string $format = null): string186{187if (!isset($this->sizes[$size])) {188throw new \RuntimeException('undefined size');189}190
191$pathInfo = pathinfo($currentPath);192if ($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'],203isset($this->sizes[$size]['width']) ? '_' . $this->sizes[$size]['width'] . 'w' : '',204isset($this->sizes[$size]['height']) ? '_' . $this->sizes[$size]['height'] . 'h' : '',205$ext206);207
208return $dirNamePrefix . $res;209}210
211public function getImageGeometry(): ImageGeometry212{213$fsPath = ImageManager::getUploadsDir() . '/' . $this->media->getPath();214$obj = new ImageGeometry();215
216try {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 logger225}226
227return $obj;228}229
230/**231* @param $method
232* @param $arguments
233*
234* @return mixed
235*/
236public function __call($method, $arguments)237{238return call_user_func_array([$this->media, $method], $arguments);239}240
241private function getResizer(string $fsPath, string $format = null): ResizerInterface242{243switch ($format ?? strtolower(pathinfo($fsPath, PATHINFO_EXTENSION))) {244case 'jpeg':245case 'jpg':246return new JpegResizer();247case 'png':248return new PngResizer();249case 'webp':250return new WebpResizer();251case 'avif':252return new AvifResizer();253}254
255return new DefaultResizer();256}257}
258