Skip to content

Commit 8b0ce06

Browse files
[Magento Community Engineering] Community Contributions - 2.3-develop
- merged latest code from mainline branch
2 parents d405adb + 7c44546 commit 8b0ce06

File tree

142 files changed

+8117
-1046
lines changed

Some content is hidden

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

142 files changed

+8117
-1046
lines changed

app/code/Magento/Catalog/Controller/Adminhtml/Category.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public function __construct(
8282
}
8383

8484
/**
85-
* Initialize requested category and put it into registry
85+
* Initialize requested category and put it into registry.
8686
*
8787
* Root category can be returned, if inappropriate store/category is specified
8888
*
@@ -111,6 +111,8 @@ protected function _initCategory($getRootInstead = false)
111111
}
112112
}
113113

114+
$this->registry->unregister('category');
115+
$this->registry->unregister('current_category');
114116
$this->registry->register('category', $category);
115117
$this->registry->register('current_category', $category);
116118
$this->wysiwigConfig->setStoreId($storeId);

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

+24-18
Original file line numberDiff line numberDiff line change
@@ -183,29 +183,29 @@ public function execute()
183183
$products = json_decode($categoryPostData['category_products'], true);
184184
$category->setPostedProducts($products);
185185
}
186-
$this->_eventManager->dispatch(
187-
'catalog_category_prepare_save',
188-
['category' => $category, 'request' => $this->getRequest()]
189-
);
190186

191-
/**
192-
* Check "Use Default Value" checkboxes values
193-
*/
194-
if (isset($categoryPostData['use_default']) && !empty($categoryPostData['use_default'])) {
195-
foreach ($categoryPostData['use_default'] as $attributeCode => $attributeValue) {
196-
if ($attributeValue) {
197-
$category->setData($attributeCode, null);
187+
try {
188+
$this->_eventManager->dispatch(
189+
'catalog_category_prepare_save',
190+
['category' => $category, 'request' => $this->getRequest()]
191+
);
192+
/**
193+
* Check "Use Default Value" checkboxes values
194+
*/
195+
if (isset($categoryPostData['use_default']) && !empty($categoryPostData['use_default'])) {
196+
foreach ($categoryPostData['use_default'] as $attributeCode => $attributeValue) {
197+
if ($attributeValue) {
198+
$category->setData($attributeCode, null);
199+
}
198200
}
199201
}
200-
}
201202

202-
/**
203-
* Proceed with $_POST['use_config']
204-
* set into category model for processing through validation
205-
*/
206-
$category->setData('use_post_data_config', $useConfig);
203+
/**
204+
* Proceed with $_POST['use_config']
205+
* set into category model for processing through validation
206+
*/
207+
$category->setData('use_post_data_config', $useConfig);
207208

208-
try {
209209
$categoryResource = $category->getResource();
210210
if ($category->hasCustomDesignTo()) {
211211
$categoryResource->getAttribute('custom_design_from')->setMaxValue($category->getCustomDesignTo());
@@ -231,10 +231,16 @@ public function execute()
231231

232232
$category->save();
233233
$this->messageManager->addSuccessMessage(__('You saved the category.'));
234+
// phpcs:disable Magento2.Exceptions.ThrowCatch
234235
} catch (\Magento\Framework\Exception\LocalizedException $e) {
235236
$this->messageManager->addExceptionMessage($e);
236237
$this->logger->critical($e);
237238
$this->_getSession()->setCategoryData($categoryPostData);
239+
// phpcs:disable Magento2.Exceptions.ThrowCatch
240+
} catch (\Throwable $e) {
241+
$this->messageManager->addErrorMessage(__('Something went wrong while saving the category.'));
242+
$this->logger->critical($e);
243+
$this->_getSession()->setCategoryData($categoryPostData);
238244
}
239245
}
240246

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

+3
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ public function build(RequestInterface $request): ProductInterface
115115
$store = $this->storeFactory->create();
116116
$store->load($storeId);
117117

118+
$this->registry->unregister('product');
119+
$this->registry->unregister('current_product');
120+
$this->registry->unregister('current_store');
118121
$this->registry->register('product', $product);
119122
$this->registry->register('current_product', $product);
120123
$this->registry->register('current_store', $store);

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

+13-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use Magento\Framework\Stdlib\DateTime\Filter\Date;
2525
use Magento\Store\Model\StoreManagerInterface;
2626
use Zend_Filter_Input;
27+
use Magento\Catalog\Model\Product\Authorization as ProductAuthorization;
2728

2829
/**
2930
* Product helper
@@ -103,6 +104,11 @@ class Helper
103104
*/
104105
private $attributeFilter;
105106

107+
/**
108+
* @var ProductAuthorization
109+
*/
110+
private $productAuthorization;
111+
106112
/**
107113
* @var FormatInterface
108114
*/
@@ -123,6 +129,7 @@ class Helper
123129
* @param LinkTypeProvider|null $linkTypeProvider
124130
* @param AttributeFilter|null $attributeFilter
125131
* @param FormatInterface|null $localeFormat
132+
* @param ProductAuthorization|null $productAuthorization
126133
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
127134
*/
128135
public function __construct(
@@ -137,7 +144,8 @@ public function __construct(
137144
ProductRepositoryInterface $productRepository = null,
138145
LinkTypeProvider $linkTypeProvider = null,
139146
AttributeFilter $attributeFilter = null,
140-
FormatInterface $localeFormat = null
147+
FormatInterface $localeFormat = null,
148+
?ProductAuthorization $productAuthorization = null
141149
) {
142150
$this->request = $request;
143151
$this->storeManager = $storeManager;
@@ -153,6 +161,7 @@ public function __construct(
153161
$this->linkTypeProvider = $linkTypeProvider ?: $objectManager->get(LinkTypeProvider::class);
154162
$this->attributeFilter = $attributeFilter ?: $objectManager->get(AttributeFilter::class);
155163
$this->localeFormat = $localeFormat ?: $objectManager->get(FormatInterface::class);
164+
$this->productAuthorization = $productAuthorization ?? $objectManager->get(ProductAuthorization::class);
156165
}
157166

158167
/**
@@ -243,8 +252,10 @@ public function initializeFromData(Product $product, array $productData)
243252
public function initialize(Product $product)
244253
{
245254
$productData = $this->request->getPost('product', []);
255+
$product = $this->initializeFromData($product, $productData);
256+
$this->productAuthorization->authorizeSavingOf($product);
246257

247-
return $this->initializeFromData($product, $productData);
258+
return $product;
248259
}
249260

250261
/**

app/code/Magento/Catalog/Controller/Category/View.php

+17-3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
use Magento\Framework\View\Result\PageFactory;
3131
use Magento\Store\Model\StoreManagerInterface;
3232
use Psr\Log\LoggerInterface;
33+
use Magento\Catalog\Model\Category\Attribute\LayoutUpdateManager;
3334

3435
/**
3536
* View a category on storefront. Needs to be accessible by POST because of the store switching.
@@ -96,6 +97,11 @@ class View extends Action implements HttpGetActionInterface, HttpPostActionInter
9697
*/
9798
private $toolbarMemorizer;
9899

100+
/**
101+
* @var LayoutUpdateManager
102+
*/
103+
private $customLayoutManager;
104+
99105
/**
100106
* @var CategoryHelper
101107
*/
@@ -119,7 +125,8 @@ class View extends Action implements HttpGetActionInterface, HttpPostActionInter
119125
* @param ForwardFactory $resultForwardFactory
120126
* @param Resolver $layerResolver
121127
* @param CategoryRepositoryInterface $categoryRepository
122-
* @param ToolbarMemorizer $toolbarMemorizer
128+
* @param ToolbarMemorizer|null $toolbarMemorizer
129+
* @param LayoutUpdateManager|null $layoutUpdateManager
123130
* @param CategoryHelper $categoryHelper
124131
* @param LoggerInterface $logger
125132
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
@@ -136,6 +143,7 @@ public function __construct(
136143
Resolver $layerResolver,
137144
CategoryRepositoryInterface $categoryRepository,
138145
ToolbarMemorizer $toolbarMemorizer = null,
146+
?LayoutUpdateManager $layoutUpdateManager = null,
139147
CategoryHelper $categoryHelper = null,
140148
LoggerInterface $logger = null
141149
) {
@@ -149,8 +157,9 @@ public function __construct(
149157
$this->resultForwardFactory = $resultForwardFactory;
150158
$this->layerResolver = $layerResolver;
151159
$this->categoryRepository = $categoryRepository;
152-
$this->toolbarMemorizer = $toolbarMemorizer ?: ObjectManager::getInstance()
153-
->get(ToolbarMemorizer::class);
160+
$this->toolbarMemorizer = $toolbarMemorizer ?: ObjectManager::getInstance()->get(ToolbarMemorizer::class);
161+
$this->customLayoutManager = $layoutUpdateManager
162+
?? ObjectManager::getInstance()->get(LayoutUpdateManager::class);
154163
$this->categoryHelper = $categoryHelper ?: ObjectManager::getInstance()
155164
->get(CategoryHelper::class);
156165
$this->logger = $logger ?: ObjectManager::getInstance()
@@ -279,5 +288,10 @@ private function applyLayoutUpdates(
279288
$page->addPageLayoutHandles(['layout_update' => sha1($layoutUpdate)], null, false);
280289
}
281290
}
291+
292+
//Selected files
293+
if ($settings->getPageLayoutHandles()) {
294+
$page->addPageLayoutHandles($settings->getPageLayoutHandles());
295+
}
282296
}
283297
}

app/code/Magento/Catalog/Helper/Product/View.php

+17-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
namespace Magento\Catalog\Helper\Product;
88

9+
use Magento\Catalog\Model\Product\Attribute\LayoutUpdateManager;
10+
use Magento\Framework\App\ObjectManager;
911
use Magento\Framework\View\Result\Page as ResultPage;
1012

1113
/**
@@ -66,6 +68,11 @@ class View extends \Magento\Framework\App\Helper\AbstractHelper
6668
*/
6769
private $string;
6870

71+
/**
72+
* @var LayoutUpdateManager
73+
*/
74+
private $layoutUpdateManager;
75+
6976
/**
7077
* Constructor
7178
*
@@ -78,6 +85,8 @@ class View extends \Magento\Framework\App\Helper\AbstractHelper
7885
* @param \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $categoryUrlPathGenerator
7986
* @param array $messageGroups
8087
* @param \Magento\Framework\Stdlib\StringUtils|null $string
88+
* @param LayoutUpdateManager|null $layoutUpdateManager
89+
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
8190
*/
8291
public function __construct(
8392
\Magento\Framework\App\Helper\Context $context,
@@ -88,7 +97,8 @@ public function __construct(
8897
\Magento\Framework\Message\ManagerInterface $messageManager,
8998
\Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $categoryUrlPathGenerator,
9099
array $messageGroups = [],
91-
\Magento\Framework\Stdlib\StringUtils $string = null
100+
\Magento\Framework\Stdlib\StringUtils $string = null,
101+
?LayoutUpdateManager $layoutUpdateManager = null
92102
) {
93103
$this->_catalogSession = $catalogSession;
94104
$this->_catalogDesign = $catalogDesign;
@@ -97,8 +107,9 @@ public function __construct(
97107
$this->messageGroups = $messageGroups;
98108
$this->messageManager = $messageManager;
99109
$this->categoryUrlPathGenerator = $categoryUrlPathGenerator;
100-
$this->string = $string ?: \Magento\Framework\App\ObjectManager::getInstance()
101-
->get(\Magento\Framework\Stdlib\StringUtils::class);
110+
$this->string = $string ?: ObjectManager::getInstance()->get(\Magento\Framework\Stdlib\StringUtils::class);
111+
$this->layoutUpdateManager = $layoutUpdateManager
112+
?? ObjectManager::getInstance()->get(LayoutUpdateManager::class);
102113
parent::__construct($context);
103114
}
104115

@@ -203,6 +214,9 @@ public function initProductLayout(ResultPage $resultPage, $product, $params = nu
203214
}
204215
}
205216
}
217+
if ($settings->getPageLayoutHandles()) {
218+
$resultPage->addPageLayoutHandles($settings->getPageLayoutHandles());
219+
}
206220

207221
$currentCategory = $this->_coreRegistry->registry('current_category');
208222
$controllerClass = $this->_request->getFullActionName();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Catalog\Model\Attribute\Backend;
10+
11+
use Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend;
12+
use Magento\Framework\Exception\LocalizedException;
13+
use Magento\Catalog\Model\AbstractModel;
14+
15+
/**
16+
* Custom layout file attribute.
17+
*/
18+
abstract class AbstractLayoutUpdate extends AbstractBackend
19+
{
20+
public const VALUE_USE_UPDATE_XML = '__existing__';
21+
22+
public const VALUE_NO_UPDATE = '__no_update__';
23+
24+
/**
25+
* Extract attribute value.
26+
*
27+
* @param AbstractModel $model
28+
* @return mixed
29+
*/
30+
private function extractAttributeValue(AbstractModel $model)
31+
{
32+
$code = $this->getAttribute()->getAttributeCode();
33+
34+
return $model->getData($code);
35+
}
36+
37+
/**
38+
* Compose list of available files (layout handles) for given entity.
39+
*
40+
* @param AbstractModel $forModel
41+
* @return string[]
42+
*/
43+
abstract protected function listAvailableValues(AbstractModel $forModel): array;
44+
45+
/**
46+
* Extracts prepare attribute value to be saved.
47+
*
48+
* @throws LocalizedException
49+
* @param AbstractModel $model
50+
* @return string|null
51+
*/
52+
private function prepareValue(AbstractModel $model): ?string
53+
{
54+
$value = $this->extractAttributeValue($model);
55+
if (!is_string($value)) {
56+
$value = null;
57+
}
58+
if ($value
59+
&& $value !== self::VALUE_USE_UPDATE_XML
60+
&& $value !== self::VALUE_NO_UPDATE
61+
&& !in_array($value, $this->listAvailableValues($model), true)
62+
) {
63+
throw new LocalizedException(__('Selected layout update is not available'));
64+
}
65+
66+
return $value;
67+
}
68+
69+
/**
70+
* Set value for the object.
71+
*
72+
* @param string|null $value
73+
* @param AbstractModel $forObject
74+
* @param string|null $attrCode
75+
* @return void
76+
*/
77+
private function setAttributeValue(?string $value, AbstractModel $forObject, ?string $attrCode = null): void
78+
{
79+
$attrCode = $attrCode ?? $this->getAttribute()->getAttributeCode();
80+
if ($forObject->hasData(AbstractModel::CUSTOM_ATTRIBUTES)) {
81+
$forObject->setCustomAttribute($attrCode, $value);
82+
}
83+
$forObject->setData($attrCode, $value);
84+
}
85+
86+
/**
87+
* @inheritDoc
88+
*
89+
* @param AbstractModel $object
90+
*/
91+
public function validate($object)
92+
{
93+
$valid = parent::validate($object);
94+
if ($valid) {
95+
$this->prepareValue($object);
96+
}
97+
98+
return $valid;
99+
}
100+
101+
/**
102+
* @inheritDoc
103+
* @param AbstractModel $object
104+
* @throws LocalizedException
105+
*/
106+
public function beforeSave($object)
107+
{
108+
$value = $this->prepareValue($object);
109+
if ($value && ($value === self::VALUE_NO_UPDATE || $value !== self::VALUE_USE_UPDATE_XML)) {
110+
$this->setAttributeValue(null, $object, 'custom_layout_update');
111+
}
112+
if (!$value || $value === self::VALUE_USE_UPDATE_XML || $value === self::VALUE_NO_UPDATE) {
113+
$value = null;
114+
}
115+
$this->setAttributeValue($value, $object);
116+
117+
return $this;
118+
}
119+
}

0 commit comments

Comments
 (0)