_mediaDirectory = $filesystem->getDirectoryRead(DirectoryList::MEDIA); $this->_imageFactory = $imageFactory; $this->_file = $file; $this->_storeManager = $storeManager; $this->_appState = $appState; $this->adapterFactory = $adapterFactory; parent::__construct($context); } /** * @return bool */ public function checkDependencies() { try { $this->adapterFactory->create(); return true; } catch (Exception $e) { $this->_logger->critical($e->getMessage()); return false; } } public function adaptiveResize($size, $fileTemplate = null) { if (!empty($fileTemplate)) { $this->setFileTemplate($fileTemplate); } try { [$width, $height] = $this->prepareSize($size); $this->setWidth($width); $this->setHeight($height); if ($this->_keepAspectRatio && $this->_cropOnly) { $this->crop(); } $this->resize(); } catch (Exception $e) { if (State::MODE_DEVELOPER == $this->_appState->getMode()) { $this->_logger->warning("Olegnax Core. Can\'t resize image, skipping. The file does not exist or not accessible: " . $e, [$this->_baseFile]); } } return $this; } public function setFileTemplate($fileTemplate) { $this->_resizeTemplate = $fileTemplate; return $this; } private function prepareSize($size) { if (is_array($size) && 1 >= count($size)) { $size = array_shift($size); } if (!is_array($size)) { $size = [$size, $size]; } $size = array_map('intval', $size); $size = array_map('abs', $size); return $size; } public function crop() { if ($this->_width == 0 && $this->_height == 0 && !$this->getBaseFile()) { return $this; } if ($this->_fileExists($this->getResizedFile())) { return $this; } $_imageSrcWidth = $this->getImageProcessor()->getOriginalWidth(); $_imageSrcHeight = $this->getImageProcessor()->getOriginalHeight(); $_imageSrcRatio = $_imageSrcWidth / $_imageSrcHeight; $_ratio = $this->_width / $this->_height; if ($_imageSrcRatio != $_ratio) { if (1 > $_imageSrcRatio) { $newHeight = round($_imageSrcWidth / $_ratio); $deltHeight = $_imageSrcHeight - $newHeight; $_deltHeight = floor($deltHeight / 2); $__deltHeight = $deltHeight % 2; $this->getImageProcessor()->crop($_deltHeight + $__deltHeight, 0, 0, $_deltHeight); } elseif (1 < $_imageSrcRatio) { $newWidth = round($_imageSrcHeight * $_ratio); $deltWidth = $_imageSrcWidth - $newWidth; $_deltWidth = floor($deltWidth / 2); $__deltWidth = $deltWidth % 2; $this->getImageProcessor()->crop(0, $_deltWidth + $__deltWidth, $_deltWidth, 0); } } return $this; } /** * @return string */ public function getBaseFile() { return $this->_baseFile; } /** * Set filenames for base file and new file * * @param string $file * * @return Image */ public function setBaseFile($file) { if ($this->_fileExists($file)) { $this->_baseFile = $file; } elseif (State::MODE_DEVELOPER == $this->_appState->getMode()) { $this->_logger->warning(__('Olegnax Core. The file does not exist or not accessible: ') . $file); } return $this; } /** * First check this file on FS * If it doesn't exist - try to download it from DB * * @param string $filename * * @return bool */ protected function _fileExists($filename) { return $this->_file->fileExists($this->_mediaDirectory->getAbsolutePath($filename)); } /** * @return string */ private function getResizedFile() { $path_data = pathinfo($this->getBaseFile()); if (is_array($path_data) && !empty($path_data)) { if (array_key_exists('extension', $path_data)) { $filename = str_replace( [ '{dirname}', '{basename}', '{extension}', '{filename}', '{width}', '{height}', '{originalWidth}', '{originalHeight}', '{destinationSubdir}', '{keepFrame}', '{constrainOnly}', '{keepAspectRatio}', '{crop}', '{keepTransparency}', '{quality}', ], [ $path_data['dirname'], $path_data['basename'], $path_data['extension'], $path_data['filename'], $this->getWidth(), $this->getHeight(), $this->getOriginalWidth(), $this->getOriginalHeight(), $this->getDestinationSubdir(), $this->getQuality(), $this->_keepFrame, $this->_constrainOnly, $this->_keepAspectRatio, $this->_cropOnly, $this->_keepTransparency, ], $this->_resizeTemplate ); return $filename; } } return ''; } /** * @return int */ public function getWidth() { return $this->_width ?: $this->getOriginalWidth(); } /** * @param int $width * * @return Image */ public function setWidth($width) { $this->_width = abs((int)$width); return $this; } /** * @return int|null */ public function getOriginalWidth() { return $this->getImageProcessor()->getOriginalWidth(); } /** * @return \Magento\Framework\Image */ public function getImageProcessor() { if (!$this->_processor) { $filename = $this->getBaseFile() ? $this->_mediaDirectory->getAbsolutePath($this->getBaseFile()) : null; $this->_processor = $this->_imageFactory->create($filename); } $this->_processor->keepAspectRatio($this->_keepAspectRatio); $this->_processor->keepFrame($this->_keepFrame); $this->_processor->keepTransparency($this->_keepTransparency); $this->_processor->constrainOnly($this->_constrainOnly); $this->_processor->backgroundColor($this->_backgroundColor); $this->_processor->quality($this->_quality); return $this->_processor; } /** * @return int */ public function getHeight() { return $this->_height ?: $this->getOriginalHeight(); } /** * @param int $height * * @return $this */ public function setHeight($height) { $this->_height = abs((int)$height); return $this; } /** * @return int|null */ public function getOriginalHeight() { return $this->getImageProcessor()->getOriginalHeight(); } /** * @return string */ public function getDestinationSubdir() { return $this->_destinationSubdir; } /** * @param string $dir * * @return $this */ public function setDestinationSubdir($dir) { $this->_destinationSubdir = $dir; return $this; } /** * Get image quality * * @return int */ public function getQuality() { return $this->_quality; } /** * Set image quality, values in percentage from 0 to 100 * * @param int $quality * * @return $this */ public function setQuality($quality) { $quality = abs((int)$quality); if (0 < $quality) { $this->_quality = $quality; } return $this; } /** * @return $this * @see \Magento\Framework\Image\Adapter\AbstractAdapter */ public function resize() { if ($this->_width == 0 && $this->_height == 0 || !$this->getBaseFile() || !$this->_fileExists($this->getBaseFile()) ) { return $this; } $resizedFile = $this->getResizedFile(); if ($resizedFile && $this->_fileExists($resizedFile)) { return $this; } $new_filename = $this->_mediaDirectory->getAbsolutePath($resizedFile); $this->getImageProcessor()->resize($this->_width, $this->_height); $this->getImageProcessor()->save($new_filename); return $this; } /** * @param \Magento\Framework\Image $processor * * @return $this */ public function setImageProcessor($processor) { $this->_processor = $processor; return $this; } /** * @return string * @throws NoSuchEntityException */ public function getUrl() { $media_url = $this->_storeManager->getStore()->getBaseUrl(UrlInterface::URL_TYPE_MEDIA); if ($this->getBaseFile()) { $resizedFile = $this->getResizedFile(); if ($resizedFile && $this->_fileExists($resizedFile)) { return $media_url . $this->getResizedFile(); } } return $media_url . $this->__file; } /** * @param string $size * * @return $this */ public function setSize($size) { // determine width and height from string $width = $height = 0; if (is_numeric($size)) { $width = $height = $size; } elseif (is_array($size)) { if (1 >= count($size)) { [$width, $height] = $size; } else { $width = $height = array_shift($size); } } elseif (is_string($size)) { [$width, $height] = explode('x', strtolower($size), 2); } foreach (['width', 'height'] as $wh) { ${$wh} = (int)${$wh}; if (empty(${$wh})) { ${$wh} = null; } } // set sizes $this->setWidth($width)->setHeight($height); return $this; } /** * @param $file * * @throws Exception */ public function removeResized($file) { if (!empty($file)) { $this->init($file); } $file = $this->getBaseFile(); if (!empty($file)) { $new_filename = pathinfo($file); $filename = implode( '_', [ $new_filename['filename'], '*', ] ); $new_filename['filename'] = $filename . '.' . $new_filename['extension']; $pattern = implode( '/', [ $this->getDestinationSubdir(), $new_filename['dirname'], $new_filename['filename'], ] ); $pattern = $this->_mediaDirectory->getAbsolutePath($pattern); $files = Glob::glob($pattern); if (!empty($files)) { foreach ($files as $_file) { if ($this->_fileExists($_file)) { $this->_file->rm($_file); } } } } } /** * @param $file * @param array $attributes * * @return $this * @throws Exception */ public function init($file, $attributes = []) { $this->_reset(); $this->__file = $file; $this->setBaseFile($file); $this->attributes = $attributes; $this->setImageProperties(); return $this; } /** * Resset all attributes */ protected function _reset() { $this->_processor = null; $this->_baseFile = null; $this->setQuality(90); $this->setFileTemplate(static::BASE_TEMPLATE_FILE_NAME); $this->setBackgroundColor([255, 255, 255]); $this->setConstrainOnly(true); $this->setDestinationSubdir('resized'); $this->setKeepAspectRatio(true); $this->setKeepFrame(true); $this->setKeepTransparency(true); $this->setWidth(null); $this->setHeight(null); } /** * @param int[] $rgbArray * * @return $this */ public function setBackgroundColor(array $rgbArray) { $this->_backgroundColor = $rgbArray; return $this; } /** * @param bool $flag * * @return $this */ public function setConstrainOnly($flag) { $this->_constrainOnly = $flag && $flag !== 'false'; return $this; } /** * @param bool $keep * * @return $this */ public function setKeepAspectRatio($keep) { $this->_keepAspectRatio = $keep && $keep !== 'false'; return $this; } /** * @param bool $keep * * @return $this */ public function setKeepFrame($keep) { $this->_keepFrame = $keep && $keep !== 'false'; return $this; } /** * @param bool $keep * * @return $this */ public function setKeepTransparency($keep) { $this->_keepTransparency = $keep && $keep !== 'false'; return $this; } /** * Set image properties * * @return $this */ protected function setImageProperties() { // Set 'keep frame' flag $frame = $this->getAttribute('frame'); if (!empty($frame)) { $this->setKeepFrame($frame); } // Set 'quality' $quality = $this->getAttribute('quality'); if (!empty($quality)) { $this->setQuality($quality); } // Set 'constrain only' flag $constrain = $this->getAttribute('constrain'); if (!empty($constrain)) { $this->setConstrainOnly($constrain); } // Set 'keep aspect ratio' flag $aspectRatio = $this->getAttribute('aspect_ratio'); if (!empty($aspectRatio)) { $this->setKeepAspectRatio($aspectRatio); } // Set 'keep $crop' flag $crop = $this->getAttribute('crop'); if (!empty($crop)) { $this->seCropOnly($crop); } // Set 'transparency' flag $transparency = $this->getAttribute('transparency'); if (!empty($transparency)) { $this->setKeepTransparency($transparency); } // Set background color $background = (array)$this->getAttribute('background'); if (!empty($background)) { $this->setBackgroundColor($background); } $fileTemplate = $this->getAttribute('fileTemplate'); $this->setFileTemplate(!empty($fileTemplate) ? $fileTemplate : static::BASE_TEMPLATE_FILE_NAME); return $this; } /** * Retrieve image attribute * * @param string $name * * @return string */ protected function getAttribute($name) { return $this->attributes[$name] ?? null; } /** * @param bool $flag * * @return $this */ public function seCropOnly($flag) { $this->_cropOnly = $flag && $flag !== 'false'; return $this; } }