Skip to content

Commit

Permalink
Merge pull request #6943 from magento-l3/PR_20210609_1
Browse files Browse the repository at this point in the history
L3 Bugfix delivery. 2.4-develop
  • Loading branch information
dhorytskyi authored Jun 28, 2021
2 parents f45fe09 + 6ae3cc9 commit 21d65a6
Show file tree
Hide file tree
Showing 23 changed files with 846 additions and 31 deletions.
12 changes: 11 additions & 1 deletion app/code/Magento/Backend/Block/Widget/Form.php
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,10 @@ protected function _applyTypeSpecificConfig($inputType, $element, \Magento\Eav\M
case 'date':
$element->setDateFormat($this->_localeDate->getDateFormatWithLongYear());
break;
case 'datetime':
$element->setDateFormat($this->_localeDate->getDateFormatWithLongYear());
$element->setTimeFormat($this->_localeDate->getTimeFormat());
break;
case 'multiline':
$element->setLineCount($attribute->getMultilineCount());
break;
Expand All @@ -246,7 +250,13 @@ protected function _applyTypeSpecificConfig($inputType, $element, \Magento\Eav\M
*/
protected function _addElementTypes(\Magento\Framework\Data\Form\AbstractForm $baseElement)
{
$types = $this->_getAdditionalElementTypes();
$types = array_merge(
[
'datetime' => 'date'
],
$this->_getAdditionalElementTypes()
);

foreach ($types as $code => $className) {
$baseElement->addType($code, $className);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
namespace Magento\Catalog\Controller\Adminhtml\Product\Action\Attribute;

use Magento\AsynchronousOperations\Api\Data\OperationInterface;
use Magento\Catalog\Model\Product\Filter\DateTime as DateTimeFilter;
use Magento\Catalog\Model\ProductFactory;
use Magento\Catalog\Api\Data\ProductAttributeInterface;
use Magento\Eav\Model\Config;
use Magento\Framework\App\Action\HttpPostActionInterface;
use Magento\Backend\App\Action;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Stdlib\DateTime;
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;

/**
Expand Down Expand Up @@ -67,6 +69,11 @@ class Save extends \Magento\Catalog\Controller\Adminhtml\Product\Action\Attribut
*/
private $productFactory;

/**
* @var DateTimeFilter
*/
private $dateTimeFilter;

/**
* @param Action\Context $context
* @param \Magento\Catalog\Helper\Product\Edit\Action\Attribute $attributeHelper
Expand All @@ -76,9 +83,10 @@ class Save extends \Magento\Catalog\Controller\Adminhtml\Product\Action\Attribut
* @param \Magento\Framework\Serialize\SerializerInterface $serializer
* @param \Magento\Authorization\Model\UserContextInterface $userContext
* @param int $bulkSize
* @param TimezoneInterface $timezone
* @param Config $eavConfig
* @param ProductFactory $productFactory
* @param TimezoneInterface|null $timezone
* @param Config|null $eavConfig
* @param ProductFactory|null $productFactory
* @param DateTimeFilter|null $dateTimeFilter
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
Expand All @@ -92,7 +100,8 @@ public function __construct(
int $bulkSize = 100,
TimezoneInterface $timezone = null,
Config $eavConfig = null,
ProductFactory $productFactory = null
ProductFactory $productFactory = null,
?DateTimeFilter $dateTimeFilter = null
) {
parent::__construct($context, $attributeHelper);
$this->bulkManagement = $bulkManagement;
Expand All @@ -106,6 +115,7 @@ public function __construct(
$this->eavConfig = $eavConfig ?: ObjectManager::getInstance()
->get(Config::class);
$this->productFactory = $productFactory ?? ObjectManager::getInstance()->get(ProductFactory::class);
$this->dateTimeFilter = $dateTimeFilter ?? ObjectManager::getInstance()->get(DateTimeFilter::class);
}

/**
Expand Down Expand Up @@ -155,8 +165,6 @@ public function execute()
*/
private function sanitizeProductAttributes($attributesData)
{
$dateFormat = $this->timezone->getDateFormat(\IntlDateFormatter::SHORT);

foreach ($attributesData as $attributeCode => $value) {
if ($attributeCode === ProductAttributeInterface::CODE_HAS_WEIGHT) {
continue;
Expand All @@ -170,16 +178,10 @@ private function sanitizeProductAttributes($attributesData)
}

if ($attribute->getBackendType() === 'datetime') {
if (!empty($value)) {
$filterInput = new \Zend_Filter_LocalizedToNormalized(['date_format' => $dateFormat]);
$filterInternal = new \Zend_Filter_NormalizedToLocalized(
['date_format' => \Magento\Framework\Stdlib\DateTime::DATE_INTERNAL_FORMAT]
);
$value = $filterInternal->filter($filterInput->filter($value));
} else {
$value = null;
}
$attributesData[$attributeCode] = $value;
$attributesData[$attributeCode] = $this->filterDate(
$value,
$attribute->getFrontendInput() === 'datetime'
);
} elseif ($attribute->getFrontendInput() === 'multiselect') {
// Check if 'Change' checkbox has been checked by admin for this attribute
$isChanged = (bool)$this->getRequest()->getPost('toggle_' . $attributeCode);
Expand All @@ -196,6 +198,24 @@ private function sanitizeProductAttributes($attributesData)
return $attributesData;
}

/**
* Get the date and time value in internal format and timezone
*
* @param string $value
* @param bool $isDatetime
* @return string|null
* @throws LocalizedException
*/
private function filterDate(string $value, bool $isDatetime = false): ?string
{
$date = !empty($value) ? $this->dateTimeFilter->filter($value) : null;
if ($date && $isDatetime) {
$date = $this->timezone->convertConfigTimeToUtc($date, DateTime::DATETIME_PHP_FORMAT);
}

return $date;
}

/**
* Validate product attributes data.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

/**
*
* Speical Start Date attribute backend
* Special Start Date attribute backend
*
* @api
*
Expand Down Expand Up @@ -83,7 +83,7 @@ public function validate($object)
$attr = $this->getAttribute();
$maxDate = $attr->getMaxValue();
$startDate = $this->_getValueForSave($object);
if ($startDate === false) {
if ($startDate === false || $startDate === null) {
return true;
}

Expand Down
173 changes: 173 additions & 0 deletions app/code/Magento/Catalog/Model/Product/Gallery/CopyHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\Catalog\Model\Product\Gallery;

use Magento\Catalog\Api\Data\ProductAttributeInterface;
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
use Magento\Catalog\Model\Product;
use Magento\Catalog\Model\ResourceModel\Product\Gallery;
use Magento\Eav\Model\ResourceModel\AttributeValue;
use Magento\Framework\EntityManager\EntityMetadata;
use Magento\Framework\EntityManager\MetadataPool;
use Magento\Framework\EntityManager\Operation\ExtensionInterface;
use Magento\Framework\Serialize\Serializer\Json;

/**
* Copy gallery data from one product to another
*/
class CopyHandler implements ExtensionInterface
{
/**
* @var EntityMetadata
*/
private $metadata;

/**
* @var Gallery
*/
private $galleryResourceModel;

/**
* @var ProductAttributeRepositoryInterface
*/
private $attributeRepository;

/**
* @var AttributeValue
*/
private $attributeValue;

/**
* @var Json
*/
private $json;

/**
* @var ProductAttributeInterface
*/
private $attribute;

/**
* @param MetadataPool $metadataPool
* @param Gallery $galleryResourceModel
* @param ProductAttributeRepositoryInterface $attributeRepository
* @param AttributeValue $attributeValue
* @param Json $json
*/
public function __construct(
MetadataPool $metadataPool,
Gallery $galleryResourceModel,
ProductAttributeRepositoryInterface $attributeRepository,
AttributeValue $attributeValue,
Json $json
) {
$this->metadata = $metadataPool->getMetadata(ProductInterface::class);
$this->galleryResourceModel = $galleryResourceModel;
$this->attributeRepository = $attributeRepository;
$this->attributeValue = $attributeValue;
$this->json = $json;
}

/**
* Copy gallery data from one product to another
*
* @param Product $product
* @param array $arguments
* @return void
*/
public function execute($product, $arguments = []): void
{
$fromId = (int) $arguments['original_link_id'];
$toId = $product->getData($this->metadata->getLinkField());
$attributeId = $this->getAttribute()->getAttributeId();
$valueIdMap = $this->galleryResourceModel->duplicate($attributeId, [], $fromId, $toId);
$gallery = $this->getMediaGalleryCollection($product);

if (!empty($gallery['images'])) {
$images = [];
foreach ($gallery['images'] as $key => $image) {
$valueId = $image['value_id'] ?? null;
$newKey = $key;
if ($valueId !== null) {
$newValueId = $valueId;
if (isset($valueIdMap[$valueId])) {
$newValueId = $valueIdMap[$valueId];
}
if (((int) $valueId) === $key) {
$newKey = $newValueId;
}
$image['value_id'] = $newValueId;
}
$images[$newKey] = $image;
}
$gallery['images'] = $images;
$attrCode = $this->getAttribute()->getAttributeCode();
$product->setData($attrCode, $gallery);
}

//Copy media attribute values from one product to another
if (isset($arguments['media_attribute_codes'])) {
$values = $this->attributeValue->getValues(
ProductInterface::class,
$fromId,
$arguments['media_attribute_codes']
);
if ($values) {
foreach (array_keys($values) as $key) {
$values[$key][$this->metadata->getLinkField()] = $product->getData($this->metadata->getLinkField());
unset($values[$key]['value_id']);
}
$this->attributeValue->insertValues(
ProductInterface::class,
$values
);
}
}
}

/**
* Get product media gallery collection
*
* @param Product $product
* @return array
*/
private function getMediaGalleryCollection(Product $product): array
{
$attrCode = $this->getAttribute()->getAttributeCode();
$value = $product->getData($attrCode);

if (is_array($value) && isset($value['images'])) {
if (!is_array($value['images']) && strlen($value['images']) > 0) {
$value['images'] = $this->json->unserialize($value['images']);
}

if (!is_array($value['images'])) {
$value['images'] = [];
}
}

return $value;
}

/**
* Returns media gallery attribute instance
*
* @return ProductAttributeInterface
*/
private function getAttribute(): ProductAttributeInterface
{
if (!$this->attribute) {
$this->attribute = $this->attributeRepository->get(
ProductInterface::MEDIA_GALLERY
);
}

return $this->attribute;
}
}
Loading

0 comments on commit 21d65a6

Please sign in to comment.