Skip to content

Commit b3ead94

Browse files
committed
Merge branch '2.2-develop' of https://github.com/magento/magento2ce into MAGETWO-87872
2 parents c5c47d1 + aaf99a9 commit b3ead94

File tree

14 files changed

+544
-307
lines changed

14 files changed

+544
-307
lines changed

app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php

Lines changed: 21 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,18 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
67
namespace Magento\Catalog\Controller\Adminhtml\Product\Initialization;
78

89
use Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory as CustomOptionFactory;
910
use Magento\Catalog\Api\Data\ProductLinkInterfaceFactory as ProductLinkFactory;
11+
use Magento\Catalog\Api\ProductRepositoryInterface;
1012
use Magento\Catalog\Api\ProductRepositoryInterface\Proxy as ProductRepository;
13+
use Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper\AttributeDefaultValueFilter;
1114
use Magento\Catalog\Model\Product;
1215
use Magento\Catalog\Model\Product\Initialization\Helper\ProductLinks;
1316
use Magento\Catalog\Model\Product\Link\Resolver as LinkResolver;
17+
use Magento\Catalog\Model\Product\LinkTypeProvider;
1418
use Magento\Framework\App\ObjectManager;
1519
use Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper\AttributeFilter;
1620

@@ -81,7 +85,7 @@ class Helper
8185
private $dateTimeFilter;
8286

8387
/**
84-
* @var \Magento\Catalog\Model\Product\LinkTypeProvider
88+
* @var LinkTypeProvider
8589
*/
8690
private $linkTypeProvider;
8791

@@ -99,10 +103,10 @@ class Helper
99103
* @param ProductLinks $productLinks
100104
* @param \Magento\Backend\Helper\Js $jsHelper
101105
* @param \Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter
102-
* @param \Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory|null $customOptionFactory
103-
* @param \Magento\Catalog\Api\Data\ProductLinkInterfaceFactory|null $productLinkFactory
104-
* @param \Magento\Catalog\Api\ProductRepositoryInterface|null $productRepository
105-
* @param \Magento\Catalog\Model\Product\LinkTypeProvider|null $linkTypeProvider
106+
* @param CustomOptionFactory|null $customOptionFactory
107+
* @param ProductLinkFactory |null $productLinkFactory
108+
* @param ProductRepositoryInterface|null $productRepository
109+
* @param LinkTypeProvider|null $linkTypeProvider
106110
* @param AttributeFilter|null $attributeFilter
107111
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
108112
*/
@@ -113,10 +117,10 @@ public function __construct(
113117
\Magento\Catalog\Model\Product\Initialization\Helper\ProductLinks $productLinks,
114118
\Magento\Backend\Helper\Js $jsHelper,
115119
\Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter,
116-
\Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory $customOptionFactory = null,
117-
\Magento\Catalog\Api\Data\ProductLinkInterfaceFactory $productLinkFactory = null,
118-
\Magento\Catalog\Api\ProductRepositoryInterface $productRepository = null,
119-
\Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider = null,
120+
CustomOptionFactory $customOptionFactory = null,
121+
ProductLinkFactory $productLinkFactory = null,
122+
ProductRepositoryInterface $productRepository = null,
123+
LinkTypeProvider $linkTypeProvider = null,
120124
AttributeFilter $attributeFilter = null
121125
) {
122126
$this->request = $request;
@@ -125,16 +129,13 @@ public function __construct(
125129
$this->productLinks = $productLinks;
126130
$this->jsHelper = $jsHelper;
127131
$this->dateFilter = $dateFilter;
128-
$this->customOptionFactory = $customOptionFactory ?: \Magento\Framework\App\ObjectManager::getInstance()
129-
->get(\Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory::class);
130-
$this->productLinkFactory = $productLinkFactory ?: \Magento\Framework\App\ObjectManager::getInstance()
131-
->get(\Magento\Catalog\Api\Data\ProductLinkInterfaceFactory::class);
132-
$this->productRepository = $productRepository ?: \Magento\Framework\App\ObjectManager::getInstance()
133-
->get(\Magento\Catalog\Api\ProductRepositoryInterface::class);
134-
$this->linkTypeProvider = $linkTypeProvider ?: \Magento\Framework\App\ObjectManager::getInstance()
135-
->get(\Magento\Catalog\Model\Product\LinkTypeProvider::class);
136-
$this->attributeFilter = $attributeFilter ?: \Magento\Framework\App\ObjectManager::getInstance()
137-
->get(AttributeFilter::class);
132+
133+
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
134+
$this->customOptionFactory = $customOptionFactory ?: $objectManager->get(CustomOptionFactory::class);
135+
$this->productLinkFactory = $productLinkFactory ?: $objectManager->get(ProductLinkFactory::class);
136+
$this->productRepository = $productRepository ?: $objectManager->get(ProductRepositoryInterface::class);
137+
$this->linkTypeProvider = $linkTypeProvider ?: $objectManager->get(LinkTypeProvider::class);
138+
$this->attributeFilter = $attributeFilter ?: $objectManager->get(AttributeFilter::class);
138139
}
139140

140141
/**
@@ -150,8 +151,7 @@ public function __construct(
150151
*/
151152
public function initializeFromData(\Magento\Catalog\Model\Product $product, array $productData)
152153
{
153-
unset($productData['custom_attributes']);
154-
unset($productData['extension_attributes']);
154+
unset($productData['custom_attributes'], $productData['extension_attributes']);
155155

156156
if ($productData) {
157157
$stockData = isset($productData['stock_data']) ? $productData['stock_data'] : [];
@@ -199,28 +199,13 @@ public function initializeFromData(\Magento\Catalog\Model\Product $product, arra
199199
$productData['tier_price'] = isset($productData['tier_price']) ? $productData['tier_price'] : [];
200200

201201
$useDefaults = (array)$this->request->getPost('use_default', []);
202-
203202
$productData = $this->attributeFilter->prepareProductAttributes($product, $productData, $useDefaults);
204-
205203
$product->addData($productData);
206204

207205
if ($wasLockedMedia) {
208206
$product->lockAttribute('media');
209207
}
210208

211-
/**
212-
* Check "Use Default Value" checkboxes values
213-
*/
214-
foreach ($useDefaults as $attributeCode => $useDefaultState) {
215-
if ($useDefaultState) {
216-
$product->setData($attributeCode, null);
217-
// UI component sends value even if field is disabled, so 'Use Config Settings' must be reset to false
218-
if ($product->hasData('use_config_' . $attributeCode)) {
219-
$product->setData('use_config_' . $attributeCode, false);
220-
}
221-
}
222-
}
223-
224209
$product = $this->setProductLinks($product);
225210
$product = $this->fillProductOptions($product, $productOptions);
226211

app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,57 @@ class AttributeFilter
2525
* @param array $useDefaults
2626
* @return array
2727
*/
28-
public function prepareProductAttributes(Product $product, array $productData, array $useDefaults)
28+
public function prepareProductAttributes(Product $product, array $productData, array $useDefaults): array
2929
{
30-
foreach ($productData as $attribute => $value) {
31-
if ($this->isAttributeShouldNotBeUpdated($product, $useDefaults, $attribute, $value)) {
32-
unset($productData[$attribute]);
30+
$attributeList = $product->getAttributes();
31+
foreach ($productData as $attributeCode => $attributeValue) {
32+
if ($this->isAttributeShouldNotBeUpdated($product, $useDefaults, $attributeCode, $attributeValue)) {
33+
unset($productData[$attributeCode]);
34+
}
35+
36+
if (isset($useDefaults[$attributeCode]) && $useDefaults[$attributeCode] === '1') {
37+
$productData = $this->prepareDefaultData($attributeList, $attributeCode, $productData);
38+
$productData = $this->prepareConfigData($product, $attributeCode, $productData);
39+
}
40+
}
41+
42+
return $productData;
43+
}
44+
45+
/**
46+
* @param Product $product
47+
* @param string $attributeCode
48+
* @param array $productData
49+
* @return array
50+
*/
51+
private function prepareConfigData(Product $product, $attributeCode, array $productData): array
52+
{
53+
// UI component sends value even if field is disabled, so 'Use Config Settings' must be reset to false
54+
if ($product->hasData('use_config_' . $attributeCode)) {
55+
$productData['use_config_' . $attributeCode] = false;
56+
}
57+
58+
return $productData;
59+
}
60+
61+
/**
62+
* @param array $attributeList
63+
* @param string $attributeCode
64+
* @param array $productData
65+
* @return array
66+
*/
67+
private function prepareDefaultData(array $attributeList, $attributeCode, array $productData): array
68+
{
69+
if (isset($attributeList[$attributeCode])) {
70+
/** @var \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute */
71+
$attribute = $attributeList[$attributeCode];
72+
$attributeType = $attribute->getBackendType();
73+
// For non-numberic types set the attributeValue to 'false' to trigger their removal from the db
74+
if ($attributeType === 'varchar' || $attributeType === 'text' || $attributeType === 'datetime') {
75+
$attribute->setIsRequired(false);
76+
$productData[$attributeCode] = false;
77+
} else {
78+
$productData[$attributeCode] = null;
3379
}
3480
}
3581

@@ -43,9 +89,9 @@ public function prepareProductAttributes(Product $product, array $productData, a
4389
* @param $value
4490
* @return bool
4591
*/
46-
private function isAttributeShouldNotBeUpdated(Product $product, $useDefaults, $attribute, $value)
92+
private function isAttributeShouldNotBeUpdated(Product $product, $useDefaults, $attribute, $value): bool
4793
{
48-
$considerUseDefaultsAttribute = !isset($useDefaults[$attribute]) || $useDefaults[$attribute] === "1";
94+
$considerUseDefaultsAttribute = !isset($useDefaults[$attribute]) || $useDefaults[$attribute] === '1';
4995

5096
return ($value === '' && $considerUseDefaultsAttribute && !$product->getData($attribute));
5197
}

app/code/Magento/Catalog/Model/ProductRepository.php

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,8 @@ public function __construct(
232232
public function get($sku, $editMode = false, $storeId = null, $forceReload = false)
233233
{
234234
$cacheKey = $this->getCacheKey([$editMode, $storeId]);
235-
if (!isset($this->instances[$sku][$cacheKey]) || $forceReload) {
235+
$cachedProduct = $this->getProductFromLocalCache($sku, $cacheKey);
236+
if ($cachedProduct === null || $forceReload) {
236237
$product = $this->productFactory->create();
237238

238239
$productId = $this->resourceModel->getIdBySku($sku);
@@ -247,11 +248,9 @@ public function get($sku, $editMode = false, $storeId = null, $forceReload = fal
247248
}
248249
$product->load($productId);
249250
$this->cacheProduct($cacheKey, $product);
251+
$cachedProduct = $product;
250252
}
251-
if (!isset($this->instances[$sku])) {
252-
$sku = trim($sku);
253-
}
254-
return $this->instances[$sku][$cacheKey];
253+
return $cachedProduct;
255254
}
256255

257256
/**
@@ -307,7 +306,7 @@ protected function getCacheKey($data)
307306
private function cacheProduct($cacheKey, \Magento\Catalog\Api\Data\ProductInterface $product)
308307
{
309308
$this->instancesById[$product->getId()][$cacheKey] = $product;
310-
$this->instances[$product->getSku()][$cacheKey] = $product;
309+
$this->saveProductInLocalCache($product, $cacheKey);
311310

312311
if ($this->cacheLimit && count($this->instances) > $this->cacheLimit) {
313312
$offset = round($this->cacheLimit / -2);
@@ -340,7 +339,7 @@ protected function initializeProductData(array $productData, $createNew)
340339
unset($this->instancesById[$productData['id']]);
341340
$product = $this->getById($productData['id']);
342341
} else {
343-
unset($this->instances[$productData['sku']]);
342+
$this->removeProductFromLocalCache($productData['sku']);
344343
$product = $this->get($productData['sku']);
345344
}
346345
}
@@ -495,7 +494,7 @@ public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveO
495494
if ($tierPrices !== null) {
496495
$product->setData('tier_price', $tierPrices);
497496
}
498-
unset($this->instances[$product->getSku()]);
497+
$this->removeProductFromLocalCache($product->getSku());
499498
unset($this->instancesById[$product->getId()]);
500499
$this->resourceModel->save($product);
501500
} catch (ConnectionException $exception) {
@@ -529,7 +528,7 @@ public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveO
529528
} catch (\Exception $e) {
530529
throw new \Magento\Framework\Exception\CouldNotSaveException(__('Unable to save product'), $e);
531530
}
532-
unset($this->instances[$product->getSku()]);
531+
$this->removeProductFromLocalCache($product->getSku());
533532
unset($this->instancesById[$product->getId()]);
534533
return $this->get($product->getSku(), false, $product->getStoreId());
535534
}
@@ -542,7 +541,7 @@ public function delete(\Magento\Catalog\Api\Data\ProductInterface $product)
542541
$sku = $product->getSku();
543542
$productId = $product->getId();
544543
try {
545-
unset($this->instances[$product->getSku()]);
544+
$this->removeProductFromLocalCache($product->getSku());
546545
unset($this->instancesById[$product->getId()]);
547546
$this->resourceModel->delete($product);
548547
} catch (ValidatorException $e) {
@@ -552,7 +551,7 @@ public function delete(\Magento\Catalog\Api\Data\ProductInterface $product)
552551
__('Unable to remove product %1', $sku)
553552
);
554553
}
555-
unset($this->instances[$sku]);
554+
$this->removeProductFromLocalCache($sku);
556555
unset($this->instancesById[$productId]);
557556
return true;
558557
}
@@ -675,4 +674,56 @@ private function getCollectionProcessor()
675674
}
676675
return $this->collectionProcessor;
677676
}
677+
678+
/**
679+
* Gets product from the local cache by SKU.
680+
*
681+
* @param string $sku
682+
* @param string $cacheKey
683+
* @return Product|null
684+
*/
685+
private function getProductFromLocalCache(string $sku, string $cacheKey)
686+
{
687+
$preparedSku = $this->prepareSku($sku);
688+
if (!isset($this->instances[$preparedSku])) {
689+
return null;
690+
}
691+
692+
return $this->instances[$preparedSku][$cacheKey] ?? null;
693+
}
694+
695+
/**
696+
* Removes product in the local cache.
697+
*
698+
* @param string $sku
699+
* @return void
700+
*/
701+
private function removeProductFromLocalCache(string $sku)
702+
{
703+
$preparedSku = $this->prepareSku($sku);
704+
unset($this->instances[$preparedSku]);
705+
}
706+
707+
/**
708+
* Saves product in the local cache.
709+
*
710+
* @param Product $product
711+
* @param string $cacheKey
712+
*/
713+
private function saveProductInLocalCache(Product $product, string $cacheKey)
714+
{
715+
$preparedSku = $this->prepareSku($product->getSku());
716+
$this->instances[$preparedSku][$cacheKey] = $product;
717+
}
718+
719+
/**
720+
* Converts SKU to lower case and trims.
721+
*
722+
* @param string $sku
723+
* @return string
724+
*/
725+
private function prepareSku(string $sku): string
726+
{
727+
return mb_strtolower(trim($sku));
728+
}
678729
}

0 commit comments

Comments
 (0)