Skip to content

Commit 6a394d1

Browse files
🔃 [EngCom] Public Pull Requests - 2.3-develop
Accepted Public Pull Requests: - #22074: Remove @SuppressWarnings and optimize imports on Category View (by @arnoudhgz) - #22475: Fixed Dependency on Backup Settings Configuration (by @keyuremipro) - #22178: #21737 Duplicating product with translated url keys over multiple sto… (by @yvechirko) - #22324: Adding a validation before adding or executing layout generator class. (by @tiagosampaio) - #21787: Fix for Issue #7227: "x_forwarded_for" value is always empty in Order object (by @cmuench) - #22059: #22047 Feature: Newrelic transaction name based on CLI name (by @lbajsarowicz) Fixed GitHub Issues: - #22474: Incomplete Dependency on Backup Settings Configuration (reported by @keyuremipro) has been fixed in #22475 by @keyuremipro in 2.3-develop branch Related commits: 1. 60e862f - #21737: Duplicating product with translated url keys over multiple storeviews causes non-unique url keys to be generated (reported by @hostep) has been fixed in #22178 by @yvechirko in 2.3-develop branch Related commits: 1. 48b0ab8 2. 30b0f91 3. 4e15099 4. 0c88939 5. a45d519 6. 5c384be 7. 9721c67 - #7227: "x_forwarded_for" value is always empty in Order object. (reported by @ytorbyk) has been fixed in #21787 by @cmuench in 2.3-develop branch Related commits: 1. 6ce9ee7 2. 056b526 3. c4e4cbd - #22047: Magento CRON Job Names are missing in NewRelic: "Transaction Names" (reported by @PiotrSiejczuk) has been fixed in #22059 by @lbajsarowicz in 2.3-develop branch Related commits: 1. a1661a5 2. 07f8a65 3. 638b73a 4. bb861cc 5. 9cd00fa
2 parents befbcab + d93f872 commit 6a394d1

File tree

11 files changed

+401
-107
lines changed

11 files changed

+401
-107
lines changed

app/code/Magento/Backup/etc/adminhtml/system.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,22 @@
2626
<label>Scheduled Backup Type</label>
2727
<depends>
2828
<field id="enabled">1</field>
29+
<field id="functionality_enabled">1</field>
2930
</depends>
3031
<source_model>Magento\Backup\Model\Config\Source\Type</source_model>
3132
</field>
3233
<field id="time" translate="label" type="time" sortOrder="30" showInDefault="1" showInWebsite="0" showInStore="0">
3334
<label>Start Time</label>
3435
<depends>
3536
<field id="enabled">1</field>
37+
<field id="functionality_enabled">1</field>
3638
</depends>
3739
</field>
3840
<field id="frequency" translate="label" type="select" sortOrder="40" showInDefault="1" showInWebsite="0" showInStore="0">
3941
<label>Frequency</label>
4042
<depends>
4143
<field id="enabled">1</field>
44+
<field id="functionality_enabled">1</field>
4245
</depends>
4346
<source_model>Magento\Cron\Model\Config\Source\Frequency</source_model>
4447
<backend_model>Magento\Backup\Model\Config\Backend\Cron</backend_model>
@@ -48,6 +51,7 @@
4851
<comment>Please put your store into maintenance mode during backup.</comment>
4952
<depends>
5053
<field id="enabled">1</field>
54+
<field id="functionality_enabled">1</field>
5155
</depends>
5256
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
5357
</field>

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

Lines changed: 87 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,28 @@
66
*/
77
namespace Magento\Catalog\Controller\Category;
88

9-
use Magento\Framework\App\Action\HttpPostActionInterface;
10-
use Magento\Framework\App\Action\HttpGetActionInterface;
119
use Magento\Catalog\Api\CategoryRepositoryInterface;
10+
use Magento\Catalog\Model\Category;
11+
use Magento\Catalog\Model\Design;
1212
use Magento\Catalog\Model\Layer\Resolver;
1313
use Magento\Catalog\Model\Product\ProductList\ToolbarMemorizer;
14+
use Magento\Catalog\Model\Session;
15+
use Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator;
16+
use Magento\Framework\App\Action\Action;
17+
use Magento\Framework\App\Action\Context;
18+
use Magento\Framework\App\Action\HttpGetActionInterface;
19+
use Magento\Framework\App\Action\HttpPostActionInterface;
20+
use Magento\Framework\App\ActionInterface;
21+
use Magento\Framework\Controller\Result\ForwardFactory;
22+
use Magento\Framework\Controller\ResultInterface;
23+
use Magento\Framework\DataObject;
24+
use Magento\Framework\Exception\LocalizedException;
1425
use Magento\Framework\Exception\NoSuchEntityException;
26+
use Magento\Framework\Registry;
27+
use Magento\Framework\View\Result\Page;
1528
use Magento\Framework\View\Result\PageFactory;
16-
use Magento\Framework\App\Action\Action;
29+
use Magento\Store\Model\StoreManagerInterface;
30+
use Psr\Log\LoggerInterface;
1731

1832
/**
1933
* View a category on storefront. Needs to be accessible by POST because of the store switching.
@@ -25,41 +39,41 @@ class View extends Action implements HttpGetActionInterface, HttpPostActionInter
2539
/**
2640
* Core registry
2741
*
28-
* @var \Magento\Framework\Registry
42+
* @var Registry
2943
*/
3044
protected $_coreRegistry = null;
3145

3246
/**
3347
* Catalog session
3448
*
35-
* @var \Magento\Catalog\Model\Session
49+
* @var Session
3650
*/
3751
protected $_catalogSession;
3852

3953
/**
4054
* Catalog design
4155
*
42-
* @var \Magento\Catalog\Model\Design
56+
* @var Design
4357
*/
4458
protected $_catalogDesign;
4559

4660
/**
47-
* @var \Magento\Store\Model\StoreManagerInterface
61+
* @var StoreManagerInterface
4862
*/
4963
protected $_storeManager;
5064

5165
/**
52-
* @var \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator
66+
* @var CategoryUrlPathGenerator
5367
*/
5468
protected $categoryUrlPathGenerator;
5569

5670
/**
57-
* @var \Magento\Framework\View\Result\PageFactory
71+
* @var PageFactory
5872
*/
5973
protected $resultPageFactory;
6074

6175
/**
62-
* @var \Magento\Framework\Controller\Result\ForwardFactory
76+
* @var ForwardFactory
6377
*/
6478
protected $resultForwardFactory;
6579

@@ -83,28 +97,28 @@ class View extends Action implements HttpGetActionInterface, HttpPostActionInter
8397
/**
8498
* Constructor
8599
*
86-
* @param \Magento\Framework\App\Action\Context $context
87-
* @param \Magento\Catalog\Model\Design $catalogDesign
88-
* @param \Magento\Catalog\Model\Session $catalogSession
89-
* @param \Magento\Framework\Registry $coreRegistry
90-
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
91-
* @param \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $categoryUrlPathGenerator
92-
* @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
93-
* @param \Magento\Framework\Controller\Result\ForwardFactory $resultForwardFactory
100+
* @param Context $context
101+
* @param Design $catalogDesign
102+
* @param Session $catalogSession
103+
* @param Registry $coreRegistry
104+
* @param StoreManagerInterface $storeManager
105+
* @param CategoryUrlPathGenerator $categoryUrlPathGenerator
106+
* @param PageFactory $resultPageFactory
107+
* @param ForwardFactory $resultForwardFactory
94108
* @param Resolver $layerResolver
95109
* @param CategoryRepositoryInterface $categoryRepository
96110
* @param ToolbarMemorizer|null $toolbarMemorizer
97111
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
98112
*/
99113
public function __construct(
100-
\Magento\Framework\App\Action\Context $context,
101-
\Magento\Catalog\Model\Design $catalogDesign,
102-
\Magento\Catalog\Model\Session $catalogSession,
103-
\Magento\Framework\Registry $coreRegistry,
104-
\Magento\Store\Model\StoreManagerInterface $storeManager,
105-
\Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $categoryUrlPathGenerator,
114+
Context $context,
115+
Design $catalogDesign,
116+
Session $catalogSession,
117+
Registry $coreRegistry,
118+
StoreManagerInterface $storeManager,
119+
CategoryUrlPathGenerator $categoryUrlPathGenerator,
106120
PageFactory $resultPageFactory,
107-
\Magento\Framework\Controller\Result\ForwardFactory $resultForwardFactory,
121+
ForwardFactory $resultForwardFactory,
108122
Resolver $layerResolver,
109123
CategoryRepositoryInterface $categoryRepository,
110124
ToolbarMemorizer $toolbarMemorizer = null
@@ -125,7 +139,7 @@ public function __construct(
125139
/**
126140
* Initialize requested category object
127141
*
128-
* @return \Magento\Catalog\Model\Category|bool
142+
* @return Category|bool
129143
*/
130144
protected function _initCategory()
131145
{
@@ -150,8 +164,8 @@ protected function _initCategory()
150164
'catalog_controller_category_init_after',
151165
['category' => $category, 'controller_action' => $this]
152166
);
153-
} catch (\Magento\Framework\Exception\LocalizedException $e) {
154-
$this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e);
167+
} catch (LocalizedException $e) {
168+
$this->_objectManager->get(LoggerInterface::class)->critical($e);
155169
return false;
156170
}
157171

@@ -161,13 +175,12 @@ protected function _initCategory()
161175
/**
162176
* Category view action
163177
*
164-
* @return \Magento\Framework\Controller\ResultInterface
165-
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
166-
* @SuppressWarnings(PHPMD.NPathComplexity)
178+
* @return ResultInterface
179+
* @throws NoSuchEntityException
167180
*/
168181
public function execute()
169182
{
170-
if ($this->_request->getParam(\Magento\Framework\App\ActionInterface::PARAM_NAME_URL_ENCODED)) {
183+
if ($this->_request->getParam(ActionInterface::PARAM_NAME_URL_ENCODED)) {
171184
return $this->resultRedirectFactory->create()->setUrl($this->_redirect->getRedirectUrl());
172185
}
173186
$category = $this->_initCategory();
@@ -188,29 +201,18 @@ public function execute()
188201
$page->getConfig()->setPageLayout($settings->getPageLayout());
189202
}
190203

191-
$hasChildren = $category->hasChildren();
192-
if ($category->getIsAnchor()) {
193-
$type = $hasChildren ? 'layered' : 'layered_without_children';
194-
} else {
195-
$type = $hasChildren ? 'default' : 'default_without_children';
196-
}
204+
$pageType = $this->getPageType($category);
197205

198-
if (!$hasChildren) {
206+
if (!$category->hasChildren()) {
199207
// Two levels removed from parent. Need to add default page type.
200-
$parentType = strtok($type, '_');
201-
$page->addPageLayoutHandles(['type' => $parentType], null, false);
208+
$parentPageType = strtok($pageType, '_');
209+
$page->addPageLayoutHandles(['type' => $parentPageType], null, false);
202210
}
203-
$page->addPageLayoutHandles(['type' => $type], null, false);
211+
$page->addPageLayoutHandles(['type' => $pageType], null, false);
204212
$page->addPageLayoutHandles(['id' => $category->getId()]);
205213

206214
// apply custom layout update once layout is loaded
207-
$layoutUpdates = $settings->getLayoutUpdates();
208-
if ($layoutUpdates && is_array($layoutUpdates)) {
209-
foreach ($layoutUpdates as $layoutUpdate) {
210-
$page->addUpdate($layoutUpdate);
211-
$page->addPageLayoutHandles(['layout_update' => sha1($layoutUpdate)], null, false);
212-
}
213-
}
215+
$this->applyLayoutUpdates($page, $settings);
214216

215217
$page->getConfig()->addBodyClass('page-products')
216218
->addBodyClass('categorypath-' . $this->categoryUrlPathGenerator->getUrlPath($category))
@@ -221,4 +223,40 @@ public function execute()
221223
return $this->resultForwardFactory->create()->forward('noroute');
222224
}
223225
}
226+
227+
/**
228+
* Get page type based on category
229+
*
230+
* @param Category $category
231+
* @return string
232+
*/
233+
private function getPageType(Category $category) : string
234+
{
235+
$hasChildren = $category->hasChildren();
236+
if ($category->getIsAnchor()) {
237+
return $hasChildren ? 'layered' : 'layered_without_children';
238+
}
239+
240+
return $hasChildren ? 'default' : 'default_without_children';
241+
}
242+
243+
/**
244+
* Apply custom layout updates
245+
*
246+
* @param Page $page
247+
* @param DataObject $settings
248+
* @return void
249+
*/
250+
private function applyLayoutUpdates(
251+
Page $page,
252+
DataObject $settings
253+
) {
254+
$layoutUpdates = $settings->getLayoutUpdates();
255+
if ($layoutUpdates && is_array($layoutUpdates)) {
256+
foreach ($layoutUpdates as $layoutUpdate) {
257+
$page->addUpdate($layoutUpdate);
258+
$page->addPageLayoutHandles(['layout_update' => sha1($layoutUpdate)], null, false);
259+
}
260+
}
261+
}
224262
}

app/code/Magento/Catalog/Model/Product/Copier.php

Lines changed: 82 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
<?php
22
/**
3-
* Catalog product copier. Creates product duplicate
4-
*
53
* Copyright © Magento, Inc. All rights reserved.
64
* See COPYING.txt for license details.
75
*/
@@ -11,7 +9,11 @@
119
use Magento\Catalog\Model\Product;
1210

1311
/**
14-
* The copier creates product duplicates.
12+
* Catalog product copier.
13+
*
14+
* Creates product duplicate.
15+
*
16+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
1517
*/
1618
class Copier
1719
{
@@ -74,22 +76,9 @@ public function copy(Product $product)
7476
$duplicate->setUpdatedAt(null);
7577
$duplicate->setId(null);
7678
$duplicate->setStoreId(\Magento\Store\Model\Store::DEFAULT_STORE_ID);
77-
7879
$this->copyConstructor->build($product, $duplicate);
79-
$isDuplicateSaved = false;
80-
do {
81-
$urlKey = $duplicate->getUrlKey();
82-
$urlKey = preg_match('/(.*)-(\d+)$/', $urlKey, $matches)
83-
? $matches[1] . '-' . ($matches[2] + 1)
84-
: $urlKey . '-1';
85-
$duplicate->setUrlKey($urlKey);
86-
$duplicate->setData('url_path', null);
87-
try {
88-
$duplicate->save();
89-
$isDuplicateSaved = true;
90-
} catch (\Magento\Framework\Exception\AlreadyExistsException $e) {
91-
}
92-
} while (!$isDuplicateSaved);
80+
$this->setDefaultUrl($product, $duplicate);
81+
$this->setStoresUrl($product, $duplicate);
9382
$this->getOptionRepository()->duplicate($product, $duplicate);
9483
$product->getResource()->duplicate(
9584
$product->getData($metadata->getLinkField()),
@@ -98,6 +87,81 @@ public function copy(Product $product)
9887
return $duplicate;
9988
}
10089

90+
/**
91+
* Set default URL.
92+
*
93+
* @param Product $product
94+
* @param Product $duplicate
95+
* @return void
96+
*/
97+
private function setDefaultUrl(Product $product, Product $duplicate) : void
98+
{
99+
$duplicate->setStoreId(\Magento\Store\Model\Store::DEFAULT_STORE_ID);
100+
$resource = $product->getResource();
101+
$attribute = $resource->getAttribute('url_key');
102+
$productId = $product->getId();
103+
$urlKey = $resource->getAttributeRawValue($productId, 'url_key', \Magento\Store\Model\Store::DEFAULT_STORE_ID);
104+
do {
105+
$urlKey = $this->modifyUrl($urlKey);
106+
$duplicate->setUrlKey($urlKey);
107+
} while (!$attribute->getEntity()->checkAttributeUniqueValue($attribute, $duplicate));
108+
$duplicate->setData('url_path', null);
109+
$duplicate->save();
110+
}
111+
112+
/**
113+
* Set URL for each store.
114+
*
115+
* @param Product $product
116+
* @param Product $duplicate
117+
* @return void
118+
*/
119+
private function setStoresUrl(Product $product, Product $duplicate) : void
120+
{
121+
$storeIds = $duplicate->getStoreIds();
122+
$productId = $product->getId();
123+
$productResource = $product->getResource();
124+
$defaultUrlKey = $productResource->getAttributeRawValue(
125+
$productId,
126+
'url_key',
127+
\Magento\Store\Model\Store::DEFAULT_STORE_ID
128+
);
129+
$duplicate->setData('save_rewrites_history', false);
130+
foreach ($storeIds as $storeId) {
131+
$isDuplicateSaved = false;
132+
$duplicate->setStoreId($storeId);
133+
$urlKey = $productResource->getAttributeRawValue($productId, 'url_key', $storeId);
134+
if ($urlKey === $defaultUrlKey) {
135+
continue;
136+
}
137+
do {
138+
$urlKey = $this->modifyUrl($urlKey);
139+
$duplicate->setUrlKey($urlKey);
140+
$duplicate->setData('url_path', null);
141+
try {
142+
$duplicate->save();
143+
$isDuplicateSaved = true;
144+
// phpcs:ignore Magento2.CodeAnalysis.EmptyBlock
145+
} catch (\Magento\Framework\Exception\AlreadyExistsException $e) {
146+
}
147+
} while (!$isDuplicateSaved);
148+
}
149+
$duplicate->setStoreId(\Magento\Store\Model\Store::DEFAULT_STORE_ID);
150+
}
151+
152+
/**
153+
* Modify URL key.
154+
*
155+
* @param string $urlKey
156+
* @return string
157+
*/
158+
private function modifyUrl(string $urlKey) : string
159+
{
160+
return preg_match('/(.*)-(\d+)$/', $urlKey, $matches)
161+
? $matches[1] . '-' . ($matches[2] + 1)
162+
: $urlKey . '-1';
163+
}
164+
101165
/**
102166
* Returns product option repository.
103167
*

0 commit comments

Comments
 (0)