Skip to content

Commit b8147ea

Browse files
author
Magento CICD
authored
merge magento/2.3-develop into magento-qwerty/MAGETWO-93969
2 parents c649c5a + ddfc271 commit b8147ea

File tree

108 files changed

+2815
-546
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+2815
-546
lines changed

app/code/Magento/Backend/etc/module.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77
-->
88
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
9-
<module name="Magento_Backend" >
9+
<module name="Magento_Backend">
1010
<sequence>
1111
<module name="Magento_Directory"/>
1212
</sequence>

app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ class Bundle extends \Magento\Catalog\Block\Product\View\AbstractView
5656
*/
5757
private $catalogRuleProcessor;
5858

59+
/**
60+
* @var array
61+
*/
62+
private $optionsPosition = [];
63+
5964
/**
6065
* @param \Magento\Catalog\Block\Product\Context $context
6166
* @param \Magento\Framework\Stdlib\ArrayUtils $arrayUtils
@@ -86,6 +91,8 @@ public function __construct(
8691
}
8792

8893
/**
94+
* Return catalog rule processor or creates processor if it does not exist
95+
*
8996
* @deprecated 100.2.0
9097
* @return \Magento\CatalogRule\Model\ResourceModel\Product\CollectionProcessor
9198
*/
@@ -101,6 +108,7 @@ private function getCatalogRuleProcessor()
101108

102109
/**
103110
* Returns the bundle product options
111+
*
104112
* Will return cached options data if the product options are already initialized
105113
* In a case when $stripSelection parameter is true will reload stored bundle selections collection from DB
106114
*
@@ -135,6 +143,8 @@ public function getOptions($stripSelection = false)
135143
}
136144

137145
/**
146+
* Return true if product has options
147+
*
138148
* @return bool
139149
*/
140150
public function hasOptions()
@@ -150,7 +160,6 @@ public function hasOptions()
150160
* Returns JSON encoded config to be used in JS scripts
151161
*
152162
* @return string
153-
*
154163
*/
155164
public function getJsonConfig()
156165
{
@@ -172,6 +181,7 @@ public function getJsonConfig()
172181
}
173182
$optionId = $optionItem->getId();
174183
$options[$optionId] = $this->getOptionItemData($optionItem, $currentProduct, $position);
184+
$this->optionsPosition[$position] = $optionId;
175185

176186
// Add attribute default value (if set)
177187
if ($preConfiguredFlag) {
@@ -370,6 +380,7 @@ private function getConfigData(Product $product, array $options)
370380
$config = [
371381
'options' => $options,
372382
'selected' => $this->selectedOptions,
383+
'positions' => $this->optionsPosition,
373384
'bundleId' => $product->getId(),
374385
'priceFormat' => $this->localeFormat->getPriceFormat(),
375386
'prices' => [

app/code/Magento/Bundle/Test/Unit/Block/Catalog/Product/View/Type/BundleTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ public function testGetJsonConfigFixedPriceBundle()
280280
$this->assertEquals(110, $jsonConfig['prices']['oldPrice']['amount']);
281281
$this->assertEquals(100, $jsonConfig['prices']['basePrice']['amount']);
282282
$this->assertEquals(100, $jsonConfig['prices']['finalPrice']['amount']);
283+
$this->assertEquals([1], $jsonConfig['positions']);
283284
}
284285

285286
/**

app/code/Magento/Bundle/view/frontend/web/js/product-summary.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,9 @@ define([
5656

5757
// Clear Summary box
5858
this.element.html('');
59-
60-
$.each(this.cache.currentElement.selected, $.proxy(this._renderOption, this));
59+
this.cache.currentElement.positions.forEach(function (optionId) {
60+
this._renderOption(optionId, this.cache.currentElement.selected[optionId]);
61+
}, this);
6162
this.element
6263
.parents(this.options.bundleSummaryContainer)
6364
.toggleClass('empty', !this.cache.currentElementCount); // Zero elements equal '.empty' container

app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,16 @@ class Save extends \Magento\Catalog\Controller\Adminhtml\Product implements Http
5555
*/
5656
private $storeManager;
5757

58+
/**
59+
* @var \Magento\Framework\Escaper|null
60+
*/
61+
private $escaper;
62+
63+
/**
64+
* @var null|\Psr\Log\LoggerInterface
65+
*/
66+
private $logger;
67+
5868
/**
5969
* Save constructor.
6070
*
@@ -64,20 +74,26 @@ class Save extends \Magento\Catalog\Controller\Adminhtml\Product implements Http
6474
* @param \Magento\Catalog\Model\Product\Copier $productCopier
6575
* @param \Magento\Catalog\Model\Product\TypeTransitionManager $productTypeManager
6676
* @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
77+
* @param \Magento\Framework\Escaper|null $escaper
78+
* @param \Psr\Log\LoggerInterface|null $logger
6779
*/
6880
public function __construct(
6981
\Magento\Backend\App\Action\Context $context,
7082
Product\Builder $productBuilder,
7183
Initialization\Helper $initializationHelper,
7284
\Magento\Catalog\Model\Product\Copier $productCopier,
7385
\Magento\Catalog\Model\Product\TypeTransitionManager $productTypeManager,
74-
\Magento\Catalog\Api\ProductRepositoryInterface $productRepository
86+
\Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
87+
\Magento\Framework\Escaper $escaper = null,
88+
\Psr\Log\LoggerInterface $logger = null
7589
) {
7690
$this->initializationHelper = $initializationHelper;
7791
$this->productCopier = $productCopier;
7892
$this->productTypeManager = $productTypeManager;
7993
$this->productRepository = $productRepository;
8094
parent::__construct($context, $productBuilder);
95+
$this->escaper = $escaper ?? $this->_objectManager->get(\Magento\Framework\Escaper::class);
96+
$this->logger = $logger ?? $this->_objectManager->get(\Psr\Log\LoggerInterface::class);
8197
}
8298

8399
/**
@@ -104,14 +120,14 @@ public function execute()
104120
$this->productBuilder->build($this->getRequest())
105121
);
106122
$this->productTypeManager->processProduct($product);
107-
108123
if (isset($data['product'][$product->getIdFieldName()])) {
109124
throw new \Magento\Framework\Exception\LocalizedException(
110125
__('The product was unable to be saved. Please try again.')
111126
);
112127
}
113128

114129
$originalSku = $product->getSku();
130+
$canSaveCustomOptions = $product->getCanSaveCustomOptions();
115131
$product->save();
116132
$this->handleImageRemoveError($data, $product->getId());
117133
$this->getCategoryLinkManagement()->assignProductToCategories(
@@ -121,20 +137,17 @@ public function execute()
121137
$productId = $product->getEntityId();
122138
$productAttributeSetId = $product->getAttributeSetId();
123139
$productTypeId = $product->getTypeId();
124-
125-
$this->copyToStores($data, $productId);
140+
$extendedData = $data;
141+
$extendedData['can_save_custom_options'] = $canSaveCustomOptions;
142+
$this->copyToStores($extendedData, $productId);
126143
$this->messageManager->addSuccessMessage(__('You saved the product.'));
127144
$this->getDataPersistor()->clear('catalog_product');
128145
if ($product->getSku() != $originalSku) {
129146
$this->messageManager->addNoticeMessage(
130147
__(
131148
'SKU for product %1 has been changed to %2.',
132-
$this->_objectManager->get(
133-
\Magento\Framework\Escaper::class
134-
)->escapeHtml($product->getName()),
135-
$this->_objectManager->get(
136-
\Magento\Framework\Escaper::class
137-
)->escapeHtml($product->getSku())
149+
$this->escaper->escapeHtml($product->getName()),
150+
$this->escaper->escapeHtml($product->getSku())
138151
)
139152
);
140153
}
@@ -144,17 +157,18 @@ public function execute()
144157
);
145158

146159
if ($redirectBack === 'duplicate') {
160+
$product->unsetData('quantity_and_stock_status');
147161
$newProduct = $this->productCopier->copy($product);
148162
$this->messageManager->addSuccessMessage(__('You duplicated the product.'));
149163
}
150164
} catch (\Magento\Framework\Exception\LocalizedException $e) {
151-
$this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e);
165+
$this->logger->critical($e);
152166
$this->messageManager->addExceptionMessage($e);
153167
$data = isset($product) ? $this->persistMediaData($product, $data) : $data;
154168
$this->getDataPersistor()->set('catalog_product', $data);
155169
$redirectBack = $productId ? true : 'new';
156170
} catch (\Exception $e) {
157-
$this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e);
171+
$this->logger->critical($e);
158172
$this->messageManager->addErrorMessage($e->getMessage());
159173
$data = isset($product) ? $this->persistMediaData($product, $data) : $data;
160174
$this->getDataPersistor()->set('catalog_product', $data);
@@ -243,6 +257,7 @@ protected function copyToStores($data, $productId)
243257
->setStoreId($copyFrom)
244258
->load($productId)
245259
->setStoreId($copyTo)
260+
->setCanSaveCustomOptions($data['can_save_custom_options'])
246261
->setCopyFromView(true)
247262
->save();
248263
}

app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,7 @@ protected function doAddWebsiteNamesToResult()
831831
foreach ($this as $product) {
832832
if (isset($productWebsites[$product->getId()])) {
833833
$product->setData('websites', $productWebsites[$product->getId()]);
834+
$product->setData('website_ids', $productWebsites[$product->getId()]);
834835
}
835836
}
836837
return $this;
@@ -1126,11 +1127,11 @@ public function getSelectCountSql()
11261127
/**
11271128
* Get SQL for get record count
11281129
*
1129-
* @param \Magento\Framework\DB\Select $select
1130+
* @param Select $select
11301131
* @param bool $resetLeftJoins
1131-
* @return \Magento\Framework\DB\Select
1132+
* @return Select
11321133
*/
1133-
protected function _getSelectCountSql($select = null, $resetLeftJoins = true)
1134+
protected function _getSelectCountSql(?Select $select = null, $resetLeftJoins = true)
11341135
{
11351136
$this->_renderFilters();
11361137
$countSelect = $select === null ? $this->_getClearSelect() : $this->_buildClearSelect($select);
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Catalog\Observer;
9+
10+
use Magento\Catalog\Model\Indexer\Category\Product\Processor;
11+
use Magento\Framework\Event\Observer;
12+
use Magento\Framework\Event\ObserverInterface;
13+
14+
/**
15+
* Checks if a category has changed products and depends on indexer configuration.
16+
*/
17+
class CategoryProductIndexer implements ObserverInterface
18+
{
19+
/**
20+
* @var Processor
21+
*/
22+
private $processor;
23+
24+
/**
25+
* @param Processor $processor
26+
*/
27+
public function __construct(Processor $processor)
28+
{
29+
$this->processor = $processor;
30+
}
31+
32+
/**
33+
* @inheritdoc
34+
*/
35+
public function execute(Observer $observer): void
36+
{
37+
$productIds = $observer->getEvent()->getProductIds();
38+
if (!empty($productIds) && $this->processor->isIndexerScheduled()) {
39+
$this->processor->markIndexerAsInvalid();
40+
}
41+
}
42+
}

app/code/Magento/Catalog/Plugin/Model/Attribute/Backend/AttributeValidation.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,21 @@
77

88
use Magento\Store\Model\Store;
99

10+
/**
11+
* Attribute validation
12+
*/
1013
class AttributeValidation
1114
{
1215
/**
1316
* @var \Magento\Store\Model\StoreManagerInterface
1417
*/
1518
private $storeManager;
1619

20+
/**
21+
* @var array
22+
*/
23+
private $allowedEntityTypes;
24+
1725
/**
1826
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
1927
* @param array $allowedEntityTypes
@@ -27,9 +35,12 @@ public function __construct(
2735
}
2836

2937
/**
38+
* Around validate
39+
*
3040
* @param \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend $subject
3141
* @param \Closure $proceed
3242
* @param \Magento\Framework\DataObject $entity
43+
* @throws \Magento\Framework\Exception\NoSuchEntityException
3344
* @return bool
3445
*/
3546
public function aroundValidate(
@@ -41,7 +52,7 @@ public function aroundValidate(
4152
return $entity instanceof $allowedEntity;
4253
}, $this->allowedEntityTypes)));
4354

44-
if ($isAllowedType && $this->storeManager->getStore()->getId() !== Store::DEFAULT_STORE_ID) {
55+
if ($isAllowedType && (int) $this->storeManager->getStore()->getId() !== Store::DEFAULT_STORE_ID) {
4556
$attrCode = $subject->getAttribute()->getAttributeCode();
4657
// Null is meaning "no value" which should be overridden by value from default scope
4758
if (array_key_exists($attrCode, $entity->getData()) && $entity->getData($attrCode) === null) {

0 commit comments

Comments
 (0)