pulsarvp/vps-tools

View on GitHub
src/components/ImageManager.php

Summary

Maintainability
A
1 hr
Test Coverage
<?php

    namespace vps\tools\components;

    use Imagine\Gd\Imagine;
    use Imagine\Image\Box;
    use Imagine\Image\BoxInterface;
    use Imagine\Image\ImageInterface;
    use vps\tools\config\ImageSizeConfig;
    use vps\tools\config\ImageSizeFit;
    use vps\tools\helpers\FileHelper;
    use vps\tools\helpers\UuidHelper;
    use Yii;
    use yii\base\Component;
    use yii\web\UploadedFile;

    class ImageManager extends Component
    {
        const F_ORIGINAL = 'original';
        const F_SD       = 'sd';
        const F_HD       = 'hd';
        public $config = null;

        public function init ($config = null)
        {
            parent::init();
            if ($config == null)
                $this->config = new ImageSizeConfig();
            else
                $this->config = $config;
        }

        /**
         * Save all formats image.
         *
         * @param string       $path The path to the file.
         * @param UploadedFile $file The path to the source file.
         *
         * ```php
         * return Yii::$app->image->saveImage('var/www/site/data/img/author', $image);
         * ```
         * @return bool|string
         */
        public function saveImage ($path, $file, $resize = false)
        {
            $filename = UuidHelper::generate() . '.' . $file->extension;
            $name = $filename[ 0 ] . DIRECTORY_SEPARATOR . $filename[ 1 ] . DIRECTORY_SEPARATOR . $filename;
            $filepath = $path . DIRECTORY_SEPARATOR . $name;
            if ($resize)
            {
                $paths = [
                    self::F_ORIGINAL => $path . DIRECTORY_SEPARATOR . $name,
                    self::F_SD => $path . DIRECTORY_SEPARATOR . self::F_SD . DIRECTORY_SEPARATOR . $name,
                    self::F_HD => $path . DIRECTORY_SEPARATOR . self::F_HD . DIRECTORY_SEPARATOR . $name,
                ];

                $this->_saveOriginal($path, $name, $file->tempName);
                $this->_save($paths[self::F_SD], $file->tempName, self::F_SD);
                $this->_save($paths[self::F_HD], $file->tempName, self::F_HD);

                if (file_exists($filepath))
                    return $paths;
                else
                    return false;
            }
            else
            {
                $this->_saveOriginal($path, $name, $file->tempName);

                if (file_exists($filepath))
                    return [ self::F_ORIGINAL => $path . DIRECTORY_SEPARATOR . $name ];
                else
                    return false;
            }
        }

        /**
         * Resize the image proportionally with max sizes constraints
         *
         * @param ImageInterface $image
         * @param BoxInterface   $newSize
         */
        private function _resize (ImageInterface $image, BoxInterface $newSize)
        {
            $size = $image->getSize();
            $ratio = min($newSize->getHeight() / $size->getHeight(), $newSize->getWidth() / $size->getWidth());
            if ($ratio < 1)
                $image->resize($size->scale($ratio));
        }

        /**
         * Saves image to the format using sizes from settings.
         *
         * @param string $path
         * @param string $dest
         * @param string $type
         * @param string $format
         */
        private function _save ($path, $file, $format)
        {
            $image = ( new Imagine() )->open($file);
            $class = $this->config;
            $params = $class::get($format);
            $newSize = $this->_size($format);
            if ($class::$fit == ImageSizeFit::WIDTH)
                $this->resizeToWidth($image, $newSize->getWidth());
            elseif ($class::$fit == ImageSizeFit::HEIGHT)
                $this->resizeToHeight($image, $newSize->getHeight());
            else
                $this->_resize($image, $newSize);
            FileHelper::createDirectory(dirname($path));
            $image->save($path, [ 'jpeg_quality' => $params[ 'quality' ] ]);
        }

        /**
         * Resizes image according to the given height (width proportional)
         *
         * @param integer $height
         * @param boolean $allow_enlarge
         * @return static
         */
        public function resizeToHeight ($image, $height)
        {
            $ratio = $height / $image->getSize()->getHeight();
            $width = $image->getSize()->getWidth() * $ratio;
            $this->_resize($image, new Box($width, $height));

            return $this;
        }

        /**
         * Resizes image according to the given width (height proportional)
         *
         * @param integer $width
         * @param boolean $allow_enlarge
         * @return static
         */
        public function resizeToWidth ($image, $width)
        {
            $ratio = $width / $image->getSize()->getWidth();
            $height = $image->getSize()->getHeight() * $ratio;
            $this->_resize($image, new Box($width, $height));

            return $this;
        }

        /**
         * Saves a image to the original format.
         *
         * @param string $path
         * @param string $dest
         * @param string $type
         */
        private function _saveOriginal ($path, $name, $file)
        {
            $filepath = $path . DIRECTORY_SEPARATOR . $name;
            if (Yii::$app->settings->get('image_original_save', true))
            {
                FileHelper::createDirectory(dirname($filepath));
                copy($file, $filepath);
            }
        }

        /**
         * @param string $type
         * @param string $format
         * @return BoxInterface Size of a image for the type and the format.
         */
        private function _size ($format)
        {
            $class = $this->config;
            $params = $class::get(strtoupper($format));

            return new Box(
                Yii::$app->settings->get('image_' . $format . '_width', $params[ 'width' ]),
                Yii::$app->settings->get('image_' . $format . '_height', $params[ 'height' ]));
        }
    }