Skip to content

Commit 4cbe734

Browse files
committed
Merge remote-tracking branch 'origin/MC-23740' into 2.4-develop-pr121
2 parents cd857f9 + 150e428 commit 4cbe734

File tree

25 files changed

+570
-76
lines changed

25 files changed

+570
-76
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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\Backend\Model\Validator\UrlKey;
9+
10+
/**
11+
* Class Composite validates if urlKey doesn't matches frontName or restricted words(endpoint names)
12+
*/
13+
class CompositeUrlKey implements UrlKeyValidatorInterface
14+
{
15+
/**
16+
* @var UrlKeyValidatorInterface[]
17+
*/
18+
private $validators;
19+
20+
/**
21+
* @param array $validators
22+
*/
23+
public function __construct(
24+
array $validators = []
25+
) {
26+
$this->validators = $validators;
27+
}
28+
29+
/**
30+
* @inheritDoc
31+
*/
32+
public function validate(string $urlKey): array
33+
{
34+
$errors = [];
35+
foreach ($this->validators as $validator) {
36+
$errors[] = $validator->validate($urlKey);
37+
}
38+
39+
return array_merge([], ...$errors);
40+
}
41+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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\Backend\Model\Validator\UrlKey;
9+
10+
use Magento\Backend\App\Area\FrontNameResolver;
11+
12+
/**
13+
* Class FrontName validates if urlKey doesn't matches frontName
14+
*/
15+
class FrontName implements UrlKeyValidatorInterface
16+
{
17+
/**
18+
* @var FrontNameResolver
19+
*/
20+
private $frontNameResolver;
21+
22+
/**
23+
* @param FrontNameResolver $frontNameResolver
24+
*/
25+
public function __construct(
26+
FrontNameResolver $frontNameResolver
27+
) {
28+
$this->frontNameResolver = $frontNameResolver;
29+
}
30+
31+
/**
32+
* @inheritDoc
33+
*/
34+
public function validate(string $urlKey): array
35+
{
36+
$errors = [];
37+
$frontName = $this->frontNameResolver->getFrontName();
38+
if ($urlKey == $frontName) {
39+
$errors[] = __(
40+
'URL key "%1" matches a reserved endpoint name (%2). Use another URL key.',
41+
$urlKey,
42+
$frontName
43+
);
44+
}
45+
46+
return $errors;
47+
}
48+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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\Backend\Model\Validator\UrlKey;
9+
10+
use Magento\Framework\Validator\UrlKey;
11+
12+
/**
13+
* Class RestrictedWords validates if urlKey doesn't matches restricted words(endpoint names)
14+
*/
15+
class RestrictedWords implements UrlKeyValidatorInterface
16+
{
17+
/**
18+
* @var UrlKey
19+
*/
20+
private $urlKey;
21+
22+
/**
23+
* @param UrlKey $urlKey
24+
*/
25+
public function __construct(
26+
UrlKey $urlKey
27+
) {
28+
$this->urlKey = $urlKey;
29+
}
30+
31+
/**
32+
* @inheritDoc
33+
*/
34+
public function validate(string $urlKey): array
35+
{
36+
$errors = [];
37+
if (!$this->urlKey->isValid($urlKey)) {
38+
$errors[] = __(
39+
'URL key "%1" matches a reserved endpoint name (%2). Use another URL key.',
40+
$urlKey,
41+
implode(', ', $this->urlKey->getRestrictedValues())
42+
);
43+
}
44+
45+
return $errors;
46+
}
47+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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\Backend\Model\Validator\UrlKey;
9+
10+
/**
11+
* Interface UrlKeyValidatorInterface is responsive for validating urlKeys
12+
*/
13+
interface UrlKeyValidatorInterface
14+
{
15+
/**
16+
* Validates urlKey
17+
*
18+
* @param string $urlKey
19+
* @return array
20+
*/
21+
public function validate(string $urlKey): array;
22+
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,4 +188,12 @@
188188
<argument name="anchorRenderer" xsi:type="object">Magento\Backend\Block\AnchorRenderer</argument>
189189
</arguments>
190190
</type>
191+
<type name="Magento\Backend\Model\Validator\UrlKey\CompositeUrlKey">
192+
<arguments>
193+
<argument name="validators" xsi:type="array">
194+
<item name="frontNameValidator" xsi:type="object">Magento\Backend\Model\Validator\UrlKey\FrontName</item>
195+
<item name="restrictedWordsValidator" xsi:type="object">Magento\Backend\Model\Validator\UrlKey\RestrictedWords</item>
196+
</argument>
197+
</arguments>
198+
</type>
191199
</config>

app/code/Magento/Backend/i18n/en_US.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,3 +466,4 @@ Pagination,Pagination
466466
"Theme Name","Theme Name"
467467
"Use URL parameter to enable template path hints for Storefront","Use URL parameter to enable template path hints for Storefront"
468468
"Add the following parameter to the URL to show template hints ?templatehints=[parameter_value]","Add the following parameter to the URL to show template hints ?templatehints=[parameter_value]"
469+
"URL key "%1" matches a reserved endpoint name (%2). Use another URL key.","URL key "%1" matches a reserved endpoint name (%2). Use another URL key."

app/code/Magento/CatalogUrlRewrite/Observer/CategoryUrlPathAutogeneratorObserver.php

Lines changed: 13 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Magento\Framework\Exception\LocalizedException;
1717
use Magento\Framework\Exception\NoSuchEntityException;
1818
use Magento\Store\Model\Store;
19+
use Magento\Backend\Model\Validator\UrlKey\CompositeUrlKey;
1920

2021
/**
2122
* Class for set or update url path.
@@ -24,24 +25,17 @@ class CategoryUrlPathAutogeneratorObserver implements ObserverInterface
2425
{
2526

2627
/**
27-
* Reserved endpoint names.
28-
*
29-
* @var string[]
30-
*/
31-
private $invalidValues = [];
32-
33-
/**
34-
* @var \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator
28+
* @var CategoryUrlPathGenerator
3529
*/
3630
protected $categoryUrlPathGenerator;
3731

3832
/**
39-
* @var \Magento\CatalogUrlRewrite\Model\Category\ChildrenCategoriesProvider
33+
* @var ChildrenCategoriesProvider
4034
*/
4135
protected $childrenCategoriesProvider;
4236

4337
/**
44-
* @var \Magento\CatalogUrlRewrite\Service\V1\StoreViewService
38+
* @var StoreViewService
4539
*/
4640
protected $storeViewService;
4741

@@ -51,33 +45,29 @@ class CategoryUrlPathAutogeneratorObserver implements ObserverInterface
5145
private $categoryRepository;
5246

5347
/**
54-
* @var \Magento\Backend\App\Area\FrontNameResolver
48+
* @var CompositeUrlKey
5549
*/
56-
private $frontNameResolver;
50+
private $compositeUrlValidator;
5751

5852
/**
5953
* @param CategoryUrlPathGenerator $categoryUrlPathGenerator
6054
* @param ChildrenCategoriesProvider $childrenCategoriesProvider
61-
* @param \Magento\CatalogUrlRewrite\Service\V1\StoreViewService $storeViewService
55+
* @param StoreViewService $storeViewService
6256
* @param CategoryRepositoryInterface $categoryRepository
63-
* @param \Magento\Backend\App\Area\FrontNameResolver $frontNameResolver
64-
* @param string[] $invalidValues
57+
* @param CompositeUrlKey $compositeUrlValidator
6558
*/
6659
public function __construct(
6760
CategoryUrlPathGenerator $categoryUrlPathGenerator,
6861
ChildrenCategoriesProvider $childrenCategoriesProvider,
6962
StoreViewService $storeViewService,
7063
CategoryRepositoryInterface $categoryRepository,
71-
\Magento\Backend\App\Area\FrontNameResolver $frontNameResolver = null,
72-
array $invalidValues = []
64+
CompositeUrlKey $compositeUrlValidator
7365
) {
7466
$this->categoryUrlPathGenerator = $categoryUrlPathGenerator;
7567
$this->childrenCategoriesProvider = $childrenCategoriesProvider;
7668
$this->storeViewService = $storeViewService;
7769
$this->categoryRepository = $categoryRepository;
78-
$this->frontNameResolver = $frontNameResolver ?: \Magento\Framework\App\ObjectManager::getInstance()
79-
->get(\Magento\Backend\App\Area\FrontNameResolver::class);
80-
$this->invalidValues = $invalidValues;
70+
$this->compositeUrlValidator = $compositeUrlValidator;
8171
}
8272

8373
/**
@@ -161,27 +151,12 @@ private function validateUrlKey(Category $category, ?string $urlKey): void
161151
throw new LocalizedException(__('Invalid URL key'));
162152
}
163153

164-
if (in_array($urlKey, $this->getInvalidValues())) {
165-
throw new LocalizedException(
166-
__(
167-
'URL key "%1" matches a reserved endpoint name (%2). Use another URL key.',
168-
$urlKey,
169-
implode(', ', $this->getInvalidValues())
170-
)
171-
);
154+
$errors = $this->compositeUrlValidator->validate($urlKey);
155+
if (!empty($errors)) {
156+
throw new LocalizedException($errors[0]);
172157
}
173158
}
174159

175-
/**
176-
* Get reserved endpoint names.
177-
*
178-
* @return array
179-
*/
180-
private function getInvalidValues()
181-
{
182-
return array_unique(array_merge($this->invalidValues, [$this->frontNameResolver->getFrontName()]));
183-
}
184-
185160
/**
186161
* Update url path for children category.
187162
*

app/code/Magento/CatalogUrlRewrite/Observer/ProductUrlKeyAutogeneratorObserver.php

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,32 +9,49 @@
99
use Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator;
1010
use Magento\Framework\Event\Observer;
1111
use Magento\Framework\Event\ObserverInterface;
12+
use Magento\Framework\Exception\LocalizedException;
13+
use Magento\Backend\Model\Validator\UrlKey\CompositeUrlKey;
1214

1315
class ProductUrlKeyAutogeneratorObserver implements ObserverInterface
1416
{
1517
/**
16-
* @var \Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator
18+
* @var ProductUrlPathGenerator
1719
*/
1820
protected $productUrlPathGenerator;
1921

22+
/**
23+
* @var CompositeUrlKey
24+
*/
25+
private $compositeUrlValidator;
26+
2027
/**
2128
* @param ProductUrlPathGenerator $productUrlPathGenerator
29+
* @param CompositeUrlKey $compositeUrlValidator
2230
*/
23-
public function __construct(ProductUrlPathGenerator $productUrlPathGenerator)
24-
{
31+
public function __construct(
32+
ProductUrlPathGenerator $productUrlPathGenerator,
33+
CompositeUrlKey $compositeUrlValidator
34+
) {
2535
$this->productUrlPathGenerator = $productUrlPathGenerator;
36+
$this->compositeUrlValidator = $compositeUrlValidator;
2637
}
2738

2839
/**
29-
* @param \Magento\Framework\Event\Observer $observer
30-
* @return void
40+
* Validates and sets url key for product
41+
*
42+
* @param Observer $observer
43+
* @throws LocalizedException
3144
*/
32-
public function execute(\Magento\Framework\Event\Observer $observer)
45+
public function execute(Observer $observer)
3346
{
3447
/** @var Product $product */
3548
$product = $observer->getEvent()->getProduct();
3649
$urlKey = $this->productUrlPathGenerator->getUrlKey($product);
3750
if (null !== $urlKey) {
51+
$errors = $this->compositeUrlValidator->validate($urlKey);
52+
if (!empty($errors)) {
53+
throw new LocalizedException($errors[0]);
54+
}
3855
$product->setUrlKey($urlKey);
3956
}
4057
}

app/code/Magento/CatalogUrlRewrite/Test/Mftf/Data/AdminCategoryRestrictedUrlMessageData.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@
1313
<data key="urlSoap">URL key "soap" matches a reserved endpoint name (admin, soap, rest, graphql, standard). Use another URL key.</data>
1414
<data key="urlRest">URL key "rest" matches a reserved endpoint name (admin, soap, rest, graphql, standard). Use another URL key.</data>
1515
<data key="urlGraphql">URL key "graphql" matches a reserved endpoint name (admin, soap, rest, graphql, standard). Use another URL key.</data>
16+
<data key="urlAdminError">URL key "admin" matches a reserved endpoint name (admin). Use another URL key.</data>
1617
</entity>
1718
</entities>

app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/AdminCategoryWithRestrictedUrlKeyNotCreatedTest.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,12 @@
4545
<argument name="categoryName" value="admin"/>
4646
<argument name="categoryUrlKey" value=""/>
4747
</actionGroup>
48-
<see selector="{{AdminMessagesSection.error}}" userInput='{{AdminCategoryRestrictedUrlErrorMessage.urlAdmin}}' stepKey="seeAdminFirstErrorMessage"/>
48+
<see selector="{{AdminMessagesSection.error}}" userInput='{{AdminCategoryRestrictedUrlErrorMessage.urlAdminError}}' stepKey="seeAdminFirstErrorMessage"/>
4949
<actionGroup ref="FillCategoryNameAndUrlKeyAndSaveActionGroup" stepKey="fillAdminSecondCategoryForm">
5050
<argument name="categoryName" value="{{SimpleSubCategory.name}}"/>
5151
<argument name="categoryUrlKey" value="admin"/>
5252
</actionGroup>
53-
<see selector="{{AdminMessagesSection.error}}" userInput='{{AdminCategoryRestrictedUrlErrorMessage.urlAdmin}}' stepKey="seeAdminSecondErrorMessage"/>
53+
<see selector="{{AdminMessagesSection.error}}" userInput='{{AdminCategoryRestrictedUrlErrorMessage.urlAdminError}}' stepKey="seeAdminSecondErrorMessage"/>
5454
<!--Create category with 'admin' name-->
5555
<comment userInput="Create category with 'admin' name" stepKey="commentAdminCategoryCreation"/>
5656
<actionGroup ref="FillCategoryNameAndUrlKeyAndSaveActionGroup" stepKey="fillAdminThirdCategoryForm">

0 commit comments

Comments
 (0)