| Current Path : /home/rtorresani/www/vendor/magento/module-catalog/Model/Product/Gallery/ |
| Current File : //home/rtorresani/www/vendor/magento/module-catalog/Model/Product/Gallery/Processor.php |
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Catalog\Model\Product\Gallery;
use Magento\Framework\Api\Data\ImageContentInterface;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\App\ObjectManager;
/**
* Catalog product Media Gallery attribute processor.
*
* @api
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @since 101.0.0
*/
class Processor
{
/**
* @var \Magento\Catalog\Api\Data\ProductAttributeInterface
* @since 101.0.0
*/
protected $attribute;
/**
* @var \Magento\Catalog\Api\ProductAttributeRepositoryInterface
* @since 101.0.0
*/
protected $attributeRepository;
/**
* @var \Magento\MediaStorage\Helper\File\Storage\Database
* @since 101.0.0
*/
protected $fileStorageDb;
/**
* @var \Magento\Catalog\Model\Product\Media\Config
* @since 101.0.0
*/
protected $mediaConfig;
/**
* @var \Magento\Framework\Filesystem\Directory\WriteInterface
* @since 101.0.0
*/
protected $mediaDirectory;
/**
* @var \Magento\Catalog\Model\ResourceModel\Product\Gallery
* @since 101.0.0
*/
protected $resourceModel;
/**
* @var \Magento\Framework\File\Mime
*/
private $mime;
/**
* @param \Magento\Catalog\Api\ProductAttributeRepositoryInterface $attributeRepository
* @param \Magento\MediaStorage\Helper\File\Storage\Database $fileStorageDb
* @param \Magento\Catalog\Model\Product\Media\Config $mediaConfig
* @param \Magento\Framework\Filesystem $filesystem
* @param \Magento\Catalog\Model\ResourceModel\Product\Gallery $resourceModel
* @param \Magento\Framework\File\Mime|null $mime
* @throws \Magento\Framework\Exception\FileSystemException
*/
public function __construct(
\Magento\Catalog\Api\ProductAttributeRepositoryInterface $attributeRepository,
\Magento\MediaStorage\Helper\File\Storage\Database $fileStorageDb,
\Magento\Catalog\Model\Product\Media\Config $mediaConfig,
\Magento\Framework\Filesystem $filesystem,
\Magento\Catalog\Model\ResourceModel\Product\Gallery $resourceModel,
\Magento\Framework\File\Mime $mime = null
) {
$this->attributeRepository = $attributeRepository;
$this->fileStorageDb = $fileStorageDb;
$this->mediaConfig = $mediaConfig;
$this->mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA);
$this->resourceModel = $resourceModel;
$this->mime = $mime ?: ObjectManager::getInstance()->get(\Magento\Framework\File\Mime::class);
}
/**
* Return media_gallery attribute
*
* @return \Magento\Catalog\Api\Data\ProductAttributeInterface
* @since 101.0.0
*/
public function getAttribute()
{
if (!$this->attribute) {
$this->attribute = $this->attributeRepository->get('media_gallery');
}
return $this->attribute;
}
/**
* Validate media_gallery attribute data
*
* @param \Magento\Catalog\Model\Product $object
* @return bool
* @throws \Magento\Framework\Exception\LocalizedException
* @since 101.0.0
*/
public function validate($object)
{
if ($this->getAttribute()->getIsRequired()) {
$value = $object->getData($this->getAttribute()->getAttributeCode());
if ($this->getAttribute()->isValueEmpty($value)) {
return false;
}
}
if ($this->getAttribute()->getIsUnique()) {
if (!$this->getAttribute()->getEntity()->checkAttributeUniqueValue($this->getAttribute(), $object)) {
$label = $this->getAttribute()->getFrontend()->getLabel();
throw new LocalizedException(
__('The value of the "%1" attribute isn\'t unique. Set a unique value and try again.', $label)
);
}
}
return true;
}
/**
* Add image to media gallery and return new filename
*
* @param \Magento\Catalog\Model\Product $product
* @param string $file file path of image in file system
* @param string|string[] $mediaAttribute code of attribute with type 'media_image',
* leave blank if image should be only in gallery
* @param boolean $move if true, it will move source file
* @param boolean $exclude mark image as disabled in product page view
* @return string
* @throws \Magento\Framework\Exception\LocalizedException
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
* @since 101.0.0
*/
public function addImage(
\Magento\Catalog\Model\Product $product,
$file,
$mediaAttribute = null,
$move = false,
$exclude = true
) {
$file = $this->mediaDirectory->getRelativePath($file);
if (!$this->mediaDirectory->isFile($file)) {
throw new LocalizedException(__("The image doesn't exist."));
}
// phpcs:ignore Magento2.Functions.DiscouragedFunction
$pathinfo = pathinfo($file);
$imgExtensions = ['jpg', 'jpeg', 'gif', 'png'];
if (!isset($pathinfo['extension']) || !in_array(strtolower($pathinfo['extension']), $imgExtensions)) {
throw new LocalizedException(
__('The image type for the file is invalid. Enter the correct image type and try again.')
);
}
$fileName = \Magento\MediaStorage\Model\File\Uploader::getCorrectFileName($pathinfo['basename']);
$dispersionPath = \Magento\MediaStorage\Model\File\Uploader::getDispersionPath($fileName);
$fileName = $dispersionPath . '/' . $fileName;
$fileName = $this->getNotDuplicatedFilename($fileName, $dispersionPath);
$destinationFile = $this->mediaConfig->getTmpMediaPath($fileName);
try {
/** @var $storageHelper \Magento\MediaStorage\Helper\File\Storage\Database */
$storageHelper = $this->fileStorageDb;
if ($move) {
$this->mediaDirectory->renameFile($file, $destinationFile);
//If this is used, filesystem should be configured properly
$storageHelper->saveFile($this->mediaConfig->getTmpMediaShortUrl($fileName));
} else {
$this->mediaDirectory->copyFile($file, $destinationFile);
$storageHelper->saveFile($this->mediaConfig->getTmpMediaShortUrl($fileName));
}
} catch (\Exception $e) {
throw new LocalizedException(__('The "%1" file couldn\'t be moved.', $e->getMessage()));
}
$fileName = str_replace('\\', '/', $fileName);
$attrCode = $this->getAttribute()->getAttributeCode();
$mediaGalleryData = $product->getData($attrCode);
$position = 0;
$absoluteFilePath = $this->mediaDirectory->getAbsolutePath($destinationFile);
$imageMimeType = $this->mime->getMimeType($absoluteFilePath);
$imageContent = $this->mediaDirectory->readFile($absoluteFilePath);
$imageBase64 = base64_encode($imageContent);
$imageName = $pathinfo['filename'];
if (!is_array($mediaGalleryData)) {
$mediaGalleryData = ['images' => []];
}
foreach ($mediaGalleryData['images'] as &$image) {
if (isset($image['position']) && $image['position'] > $position) {
$position = $image['position'];
}
}
$position++;
$mediaGalleryData['images'][] = [
'file' => $fileName,
'position' => $position,
'label' => '',
'disabled' => (int)$exclude,
'media_type' => 'image',
'types' => $mediaAttribute,
'content' => [
'data' => [
ImageContentInterface::NAME => $imageName,
ImageContentInterface::BASE64_ENCODED_DATA => $imageBase64,
ImageContentInterface::TYPE => $imageMimeType,
]
]
];
$product->setData($attrCode, $mediaGalleryData);
if ($mediaAttribute !== null) {
$this->setMediaAttribute($product, $mediaAttribute, $fileName);
}
return $fileName;
}
/**
* Update image in gallery
*
* @param \Magento\Catalog\Model\Product $product
* @param string $file
* @param array $data
* @return $this
* @since 101.0.0
*/
public function updateImage(\Magento\Catalog\Model\Product $product, $file, $data)
{
$fieldsMap = [
'label' => 'label',
'position' => 'position',
'disabled' => 'disabled',
'exclude' => 'disabled',
'media_type' => 'media_type',
];
$attrCode = $this->getAttribute()->getAttributeCode();
$mediaGalleryData = $product->getData($attrCode);
if (!isset($mediaGalleryData['images']) || !is_array($mediaGalleryData['images'])) {
return $this;
}
foreach ($mediaGalleryData['images'] as &$image) {
if ($image['file'] == $file) {
foreach ($fieldsMap as $mappedField => $realField) {
if (isset($data[$mappedField])) {
$image[$realField] = $data[$mappedField];
}
}
}
}
$product->setData($attrCode, $mediaGalleryData);
return $this;
}
/**
* Remove image from gallery
*
* @param \Magento\Catalog\Model\Product $product
* @param string $file
* @return $this
* @since 101.0.0
*/
public function removeImage(\Magento\Catalog\Model\Product $product, $file)
{
$attrCode = $this->getAttribute()->getAttributeCode();
$mediaGalleryData = $product->getData($attrCode);
if (!isset($mediaGalleryData['images']) || !is_array($mediaGalleryData['images'])) {
return $this;
}
foreach ($mediaGalleryData['images'] as &$image) {
if ($image['file'] == $file) {
$image['removed'] = 1;
}
}
$product->setData($attrCode, $mediaGalleryData);
return $this;
}
/**
* Retrieve image from gallery
*
* @param \Magento\Catalog\Model\Product $product
* @param string $file
* @return array|boolean
* @since 101.0.0
*/
public function getImage(\Magento\Catalog\Model\Product $product, $file)
{
$attrCode = $this->getAttribute()->getAttributeCode();
$mediaGalleryData = $product->getData($attrCode);
if (!isset($mediaGalleryData['images']) || !is_array($mediaGalleryData['images'])) {
return false;
}
foreach ($mediaGalleryData['images'] as $image) {
if ($image['file'] == $file) {
return $image;
}
}
return false;
}
/**
* Clear media attribute value
*
* @param \Magento\Catalog\Model\Product $product
* @param string|string[] $mediaAttribute
* @return $this
* @since 101.0.0
*/
public function clearMediaAttribute(\Magento\Catalog\Model\Product $product, $mediaAttribute)
{
$mediaAttributeCodes = $this->mediaConfig->getMediaAttributeCodes();
if (is_array($mediaAttribute)) {
foreach ($mediaAttribute as $attribute) {
if (in_array($attribute, $mediaAttributeCodes)) {
$product->setData($attribute, 'no_selection');
}
}
} elseif (in_array($mediaAttribute, $mediaAttributeCodes)) {
$product->setData($mediaAttribute, 'no_selection');
}
return $this;
}
/**
* Set media attribute value
*
* @param \Magento\Catalog\Model\Product $product
* @param string|string[] $mediaAttribute
* @param string $value
* @return $this
* @since 101.0.0
*/
public function setMediaAttribute(\Magento\Catalog\Model\Product $product, $mediaAttribute, $value)
{
$mediaAttributeCodes = $this->mediaConfig->getMediaAttributeCodes();
if (is_array($mediaAttribute)) {
foreach ($mediaAttribute as $attribute) {
if (in_array($attribute, $mediaAttributeCodes)) {
$product->setData($attribute, $value);
}
}
} elseif (in_array($mediaAttribute, $mediaAttributeCodes)) {
$product->setData($mediaAttribute, $value);
}
return $this;
}
/**
* Get media attribute codes
*
* @return array
* @since 101.0.0
*/
public function getMediaAttributeCodes()
{
return $this->mediaConfig->getMediaAttributeCodes();
}
/**
* Trim .tmp ending from filename
*
* @param string $file
* @return string
* @since 101.0.0
*/
protected function getFilenameFromTmp($file)
{
return strrpos($file, '.tmp') == strlen($file) - 4 ? substr($file, 0, strlen($file) - 4) : $file;
}
/**
* Duplicate temporary images
*
* @param string $file
* @return string
* @since 101.0.0
*/
public function duplicateImageFromTmp($file)
{
$file = $this->getFilenameFromTmp((string)$file);
$destinationFile = $this->getUniqueFileName($file, true);
if ($this->fileStorageDb->checkDbUsage()) {
$this->fileStorageDb->copyFile(
$this->mediaDirectory->getAbsolutePath($this->mediaConfig->getTmpMediaShortUrl($file)),
$this->mediaConfig->getTmpMediaShortUrl($destinationFile)
);
} else {
$this->mediaDirectory->copyFile(
$this->mediaConfig->getTmpMediaPath($file),
$this->mediaConfig->getTmpMediaPath($destinationFile)
);
}
return str_replace('\\', '/', $destinationFile);
}
/**
* Check whether file to move exists. Getting unique name
*
* @param string $file
* @param bool $forTmp
* @return string
* @since 101.0.0
*/
protected function getUniqueFileName($file, $forTmp = false)
{
if ($this->fileStorageDb->checkDbUsage()) {
$destFile = $this->fileStorageDb->getUniqueFilename(
$this->mediaConfig->getBaseMediaUrlAddition(),
$file
);
} else {
$destinationFile = $forTmp
? $this->mediaDirectory->getAbsolutePath($this->mediaConfig->getTmpMediaPath($file))
: $this->mediaDirectory->getAbsolutePath($this->mediaConfig->getMediaPath($file));
// phpcs:ignore Magento2.Functions.DiscouragedFunction
$destFile = dirname($file) . '/'
. \Magento\MediaStorage\Model\File\Uploader::getNewFileName($destinationFile);
}
return $destFile;
}
/**
* Get filename which is not duplicated with other files in media temporary and media directories
*
* @param string $fileName
* @param string $dispersionPath
* @return string
* @since 101.0.0
*/
protected function getNotDuplicatedFilename($fileName, $dispersionPath)
{
$fileMediaName = $dispersionPath . '/'
. \Magento\MediaStorage\Model\File\Uploader::getNewFileName($this->mediaConfig->getMediaPath($fileName));
$fileTmpMediaName = $dispersionPath . '/'
. \Magento\MediaStorage\Model\File\Uploader::getNewFileName($this->mediaConfig->getTmpMediaPath($fileName));
if ($fileMediaName != $fileTmpMediaName) {
if ($fileMediaName != $fileName) {
return $this->getNotDuplicatedFilename(
$fileMediaName,
$dispersionPath
);
} elseif ($fileTmpMediaName != $fileName) {
return $this->getNotDuplicatedFilename(
$fileTmpMediaName,
$dispersionPath
);
}
}
return $fileMediaName;
}
/**
* Retrieve data for update attribute
*
* @param \Magento\Catalog\Model\Product $object
* @return array
* @since 101.0.0
*/
public function getAffectedFields($object)
{
$data = [];
$images = (array)$object->getData($this->getAttribute()->getName());
$tableName = $this->resourceModel->getMainTable();
foreach ($images['images'] as $value) {
if (empty($value['value_id'])) {
continue;
}
$data[$tableName][] = [
'value_id' => $value['value_id'],
'attribute_id' => $this->getAttribute()->getAttributeId(),
'entity_id' => $object->getId(),
];
}
return $data;
}
/**
* Attribute value is not to be saved in a conventional way, separate table is used to store the complex value
*
* @since 101.0.0
*/
public function isScalar()
{
return false;
}
}