Skip to content

Commit 6e9bc45

Browse files
author
Magento CICD
authored
merge magento/2.3-develop into magento-tsg/2.3-develop-pr34
2 parents 43960ce + 602ba15 commit 6e9bc45

File tree

79 files changed

+1971
-418
lines changed

Some content is hidden

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

79 files changed

+1971
-418
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
@@ -54,6 +54,16 @@ class Save extends \Magento\Catalog\Controller\Adminhtml\Product
5454
*/
5555
private $storeManager;
5656

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

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

113128
$originalSku = $product->getSku();
129+
$canSaveCustomOptions = $product->getCanSaveCustomOptions();
114130
$product->save();
115131
$this->handleImageRemoveError($data, $product->getId());
116132
$this->getCategoryLinkManagement()->assignProductToCategories(
@@ -120,20 +136,17 @@ public function execute()
120136
$productId = $product->getEntityId();
121137
$productAttributeSetId = $product->getAttributeSetId();
122138
$productTypeId = $product->getTypeId();
123-
124-
$this->copyToStores($data, $productId);
139+
$extendedData = $data;
140+
$extendedData['can_save_custom_options'] = $canSaveCustomOptions;
141+
$this->copyToStores($extendedData, $productId);
125142
$this->messageManager->addSuccessMessage(__('You saved the product.'));
126143
$this->getDataPersistor()->clear('catalog_product');
127144
if ($product->getSku() != $originalSku) {
128145
$this->messageManager->addNoticeMessage(
129146
__(
130147
'SKU for product %1 has been changed to %2.',
131-
$this->_objectManager->get(
132-
\Magento\Framework\Escaper::class
133-
)->escapeHtml($product->getName()),
134-
$this->_objectManager->get(
135-
\Magento\Framework\Escaper::class
136-
)->escapeHtml($product->getSku())
148+
$this->escaper->escapeHtml($product->getName()),
149+
$this->escaper->escapeHtml($product->getSku())
137150
)
138151
);
139152
}
@@ -143,17 +156,18 @@ public function execute()
143156
);
144157

145158
if ($redirectBack === 'duplicate') {
159+
$product->unsetData('quantity_and_stock_status');
146160
$newProduct = $this->productCopier->copy($product);
147161
$this->messageManager->addSuccessMessage(__('You duplicated the product.'));
148162
}
149163
} catch (\Magento\Framework\Exception\LocalizedException $e) {
150-
$this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e);
164+
$this->logger->critical($e);
151165
$this->messageManager->addExceptionMessage($e);
152166
$data = isset($product) ? $this->persistMediaData($product, $data) : $data;
153167
$this->getDataPersistor()->set('catalog_product', $data);
154168
$redirectBack = $productId ? true : 'new';
155169
} catch (\Exception $e) {
156-
$this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e);
170+
$this->logger->critical($e);
157171
$this->messageManager->addErrorMessage($e->getMessage());
158172
$data = isset($product) ? $this->persistMediaData($product, $data) : $data;
159173
$this->getDataPersistor()->set('catalog_product', $data);
@@ -242,6 +256,7 @@ protected function copyToStores($data, $productId)
242256
->setStoreId($copyFrom)
243257
->load($productId)
244258
->setStoreId($copyTo)
259+
->setCanSaveCustomOptions($data['can_save_custom_options'])
245260
->setCopyFromView(true)
246261
->save();
247262
}

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/Test/Unit/Ui/DataProvider/Product/Form/Modifier/WebsitesTest.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ class WebsitesTest extends AbstractModifierTest
7474
*/
7575
protected $storeViewMock;
7676

77+
/**
78+
* @inheritdoc
79+
*/
7780
protected function setUp()
7881
{
7982
parent::setUp();
@@ -90,14 +93,11 @@ protected function setUp()
9093
->disableOriginalConstructor()
9194
->getMock();
9295
$this->websiteRepositoryMock = $this->getMockBuilder(\Magento\Store\Api\WebsiteRepositoryInterface::class)
93-
->setMethods(['getList', 'getDefault'])
96+
->setMethods(['getList'])
9497
->getMockForAbstractClass();
9598
$this->websiteRepositoryMock->expects($this->any())
9699
->method('getDefault')
97100
->willReturn($this->websiteMock);
98-
$this->websiteRepositoryMock->expects($this->any())
99-
->method('getList')
100-
->willReturn([$this->websiteMock, $this->secondWebsiteMock]);
101101
$this->groupRepositoryMock = $this->getMockBuilder(\Magento\Store\Api\GroupRepositoryInterface::class)
102102
->setMethods(['getList'])
103103
->getMockForAbstractClass();
@@ -111,8 +111,10 @@ protected function setUp()
111111
->method('getWebsiteIds')
112112
->willReturn($this->assignedWebsites);
113113
$this->storeManagerMock = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class)
114-
->setMethods(['isSingleStoreMode'])
114+
->setMethods(['isSingleStoreMode', 'getWesites'])
115115
->getMockForAbstractClass();
116+
$this->storeManagerMock->method('getWebsites')
117+
->willReturn([$this->websiteMock, $this->secondWebsiteMock]);
116118
$this->storeManagerMock->expects($this->any())
117119
->method('isSingleStoreMode')
118120
->willReturn(false);

app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ public function __construct(
290290
}
291291

292292
/**
293-
* {@inheritdoc}
293+
* @inheritdoc
294294
* @since 101.0.0
295295
*/
296296
public function modifyMeta(array $meta)
@@ -401,7 +401,7 @@ public function getContainerChildren(ProductAttributeInterface $attribute, $grou
401401
}
402402

403403
/**
404-
* {@inheritdoc}
404+
* @inheritdoc
405405
* @since 101.0.0
406406
*/
407407
public function modifyData(array $data)
@@ -532,7 +532,7 @@ private function getAttributes()
532532
/**
533533
* Loads attributes for specified groups at once
534534
*
535-
* @param AttributeGroupInterface[] ...$groups
535+
* @param AttributeGroupInterface[] $groups
536536
* @return @return ProductAttributeInterface[]
537537
*/
538538
private function loadAttributesForGroups(array $groups)
@@ -707,7 +707,8 @@ public function setupAttributeMeta(ProductAttributeInterface $attribute, $groupC
707707
}
708708

709709
/**
710-
* Returns attribute default value, based on db setting or setting in the system configuration
710+
* Returns attribute default value, based on db setting or setting in the system configuration.
711+
*
711712
* @param ProductAttributeInterface $attribute
712713
* @return null|string
713714
*/
@@ -742,6 +743,8 @@ private function convertOptionsValueToString(array $options) : array
742743
}
743744

744745
/**
746+
* Adds 'use default value' checkbox.
747+
*
745748
* @param ProductAttributeInterface $attribute
746749
* @param array $meta
747750
* @return array
@@ -944,6 +947,9 @@ private function canDisplayUseDefault(ProductAttributeInterface $attribute)
944947
$attributeCode = $attribute->getAttributeCode();
945948
/** @var Product $product */
946949
$product = $this->locator->getProduct();
950+
if ($product->isLockedAttribute($attributeCode)) {
951+
return false;
952+
}
947953

948954
if (isset($this->canDisplayUseDefault[$attributeCode])) {
949955
return $this->canDisplayUseDefault[$attributeCode];

0 commit comments

Comments
 (0)