Skip to content

Commit d85b4fd

Browse files
Merge remote-tracking branch 'origin/MC-35478' into 2.3-develop-pr53
2 parents d68bf21 + 9ee1e6c commit d85b4fd

File tree

2 files changed

+75
-28
lines changed

2 files changed

+75
-28
lines changed

app/code/Magento/Cms/Model/PageRepository.php

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,27 @@
77
namespace Magento\Cms\Model;
88

99
use Magento\Cms\Api\Data;
10+
use Magento\Cms\Api\Data\PageInterface;
11+
use Magento\Cms\Api\Data\PageInterfaceFactory;
12+
use Magento\Cms\Api\Data\PageSearchResultsInterface;
1013
use Magento\Cms\Api\PageRepositoryInterface;
14+
use Magento\Cms\Model\Api\SearchCriteria\PageCollectionProcessor;
1115
use Magento\Cms\Model\Page\IdentityMap;
16+
use Magento\Cms\Model\ResourceModel\Page as ResourcePage;
17+
use Magento\Cms\Model\ResourceModel\Page\CollectionFactory as PageCollectionFactory;
1218
use Magento\Framework\Api\DataObjectHelper;
1319
use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface;
20+
use Magento\Framework\Api\SearchCriteriaInterface;
1421
use Magento\Framework\App\ObjectManager;
22+
use Magento\Framework\App\Route\Config;
1523
use Magento\Framework\Exception\CouldNotDeleteException;
1624
use Magento\Framework\Exception\CouldNotSaveException;
1725
use Magento\Framework\Exception\NoSuchEntityException;
1826
use Magento\Framework\Reflection\DataObjectProcessor;
19-
use Magento\Cms\Model\ResourceModel\Page as ResourcePage;
20-
use Magento\Cms\Model\ResourceModel\Page\CollectionFactory as PageCollectionFactory;
2127
use Magento\Store\Model\StoreManagerInterface;
2228

2329
/**
24-
* Class PageRepository
30+
* Cms page repository
2531
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2632
*/
2733
class PageRepository implements PageRepositoryInterface
@@ -57,12 +63,12 @@ class PageRepository implements PageRepositoryInterface
5763
protected $dataObjectProcessor;
5864

5965
/**
60-
* @var \Magento\Cms\Api\Data\PageInterfaceFactory
66+
* @var PageInterfaceFactory
6167
*/
6268
protected $dataPageFactory;
6369

6470
/**
65-
* @var \Magento\Store\Model\StoreManagerInterface
71+
* @var StoreManagerInterface
6672
*/
6773
private $storeManager;
6874

@@ -76,30 +82,37 @@ class PageRepository implements PageRepositoryInterface
7682
*/
7783
private $identityMap;
7884

85+
/**
86+
* @var Config
87+
*/
88+
private $routeConfig;
89+
7990
/**
8091
* @param ResourcePage $resource
8192
* @param PageFactory $pageFactory
82-
* @param Data\PageInterfaceFactory $dataPageFactory
93+
* @param PageInterfaceFactory $dataPageFactory
8394
* @param PageCollectionFactory $pageCollectionFactory
8495
* @param Data\PageSearchResultsInterfaceFactory $searchResultsFactory
8596
* @param DataObjectHelper $dataObjectHelper
8697
* @param DataObjectProcessor $dataObjectProcessor
8798
* @param StoreManagerInterface $storeManager
8899
* @param CollectionProcessorInterface $collectionProcessor
89100
* @param IdentityMap|null $identityMap
101+
* @param Config|null $routeConfig
90102
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
91103
*/
92104
public function __construct(
93105
ResourcePage $resource,
94106
PageFactory $pageFactory,
95-
Data\PageInterfaceFactory $dataPageFactory,
107+
PageInterfaceFactory $dataPageFactory,
96108
PageCollectionFactory $pageCollectionFactory,
97109
Data\PageSearchResultsInterfaceFactory $searchResultsFactory,
98110
DataObjectHelper $dataObjectHelper,
99111
DataObjectProcessor $dataObjectProcessor,
100112
StoreManagerInterface $storeManager,
101113
CollectionProcessorInterface $collectionProcessor = null,
102-
?IdentityMap $identityMap = null
114+
?IdentityMap $identityMap = null,
115+
?Config $routeConfig = null
103116
) {
104117
$this->resource = $resource;
105118
$this->pageFactory = $pageFactory;
@@ -110,17 +123,20 @@ public function __construct(
110123
$this->dataObjectProcessor = $dataObjectProcessor;
111124
$this->storeManager = $storeManager;
112125
$this->collectionProcessor = $collectionProcessor ?: $this->getCollectionProcessor();
113-
$this->identityMap = $identityMap ?? ObjectManager::getInstance()->get(IdentityMap::class);
126+
$this->identityMap = $identityMap ?? ObjectManager::getInstance()
127+
->get(IdentityMap::class);
128+
$this->routeConfig = $routeConfig ?? ObjectManager::getInstance()
129+
->get(Config::class);
114130
}
115131

116132
/**
117133
* Validate new layout update values.
118134
*
119-
* @param Data\PageInterface $page
135+
* @param PageInterface $page
120136
* @return void
121137
* @throws \InvalidArgumentException
122138
*/
123-
private function validateLayoutUpdate(Data\PageInterface $page): void
139+
private function validateLayoutUpdate(PageInterface $page): void
124140
{
125141
//Persisted data
126142
$savedPage = $page->getId() ? $this->getById($page->getId()) : null;
@@ -140,18 +156,19 @@ private function validateLayoutUpdate(Data\PageInterface $page): void
140156
/**
141157
* Save Page data
142158
*
143-
* @param \Magento\Cms\Api\Data\PageInterface|Page $page
159+
* @param PageInterface|Page $page
144160
* @return Page
145161
* @throws CouldNotSaveException
146162
*/
147-
public function save(\Magento\Cms\Api\Data\PageInterface $page)
163+
public function save(PageInterface $page)
148164
{
149165
if ($page->getStoreId() === null) {
150166
$storeId = $this->storeManager->getStore()->getId();
151167
$page->setStoreId($storeId);
152168
}
153169
try {
154170
$this->validateLayoutUpdate($page);
171+
$this->validateRoutesDuplication($page);
155172
$this->resource->save($page);
156173
$this->identityMap->add($page);
157174
} catch (\Exception $exception) {
@@ -168,7 +185,7 @@ public function save(\Magento\Cms\Api\Data\PageInterface $page)
168185
*
169186
* @param string $pageId
170187
* @return Page
171-
* @throws \Magento\Framework\Exception\NoSuchEntityException
188+
* @throws NoSuchEntityException
172189
*/
173190
public function getById($pageId)
174191
{
@@ -187,17 +204,15 @@ public function getById($pageId)
187204
*
188205
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
189206
* @SuppressWarnings(PHPMD.NPathComplexity)
190-
* @param \Magento\Framework\Api\SearchCriteriaInterface $criteria
191-
* @return \Magento\Cms\Api\Data\PageSearchResultsInterface
207+
* @param SearchCriteriaInterface $criteria
208+
* @return PageSearchResultsInterface
192209
*/
193-
public function getList(\Magento\Framework\Api\SearchCriteriaInterface $criteria)
210+
public function getList(SearchCriteriaInterface $criteria)
194211
{
195-
/** @var \Magento\Cms\Model\ResourceModel\Page\Collection $collection */
196212
$collection = $this->pageCollectionFactory->create();
197213

198214
$this->collectionProcessor->process($criteria, $collection);
199215

200-
/** @var Data\PageSearchResultsInterface $searchResults */
201216
$searchResults = $this->searchResultsFactory->create();
202217
$searchResults->setSearchCriteria($criteria);
203218
$searchResults->setItems($collection->getItems());
@@ -208,11 +223,11 @@ public function getList(\Magento\Framework\Api\SearchCriteriaInterface $criteria
208223
/**
209224
* Delete Page
210225
*
211-
* @param \Magento\Cms\Api\Data\PageInterface $page
226+
* @param PageInterface $page
212227
* @return bool
213228
* @throws CouldNotDeleteException
214229
*/
215-
public function delete(\Magento\Cms\Api\Data\PageInterface $page)
230+
public function delete(PageInterface $page)
216231
{
217232
try {
218233
$this->resource->delete($page);
@@ -247,10 +262,26 @@ public function deleteById($pageId)
247262
private function getCollectionProcessor()
248263
{
249264
if (!$this->collectionProcessor) {
250-
$this->collectionProcessor = \Magento\Framework\App\ObjectManager::getInstance()->get(
251-
\Magento\Cms\Model\Api\SearchCriteria\PageCollectionProcessor::class
252-
);
265+
// phpstan:ignore "Class Magento\Cms\Model\Api\SearchCriteria\PageCollectionProcessor not found."
266+
$this->collectionProcessor = ObjectManager::getInstance()
267+
->get(PageCollectionProcessor::class);
253268
}
254269
return $this->collectionProcessor;
255270
}
271+
272+
/**
273+
* Checks that page identifier doesn't duplicate existed routes
274+
*
275+
* @param PageInterface $page
276+
* @return void
277+
* @throws CouldNotSaveException
278+
*/
279+
private function validateRoutesDuplication($page): void
280+
{
281+
if ($this->routeConfig->getRouteByFrontName($page->getIdentifier(), 'frontend')) {
282+
throw new CouldNotSaveException(
283+
__('The value specified in the URL Key field would generate a URL that already exists.')
284+
);
285+
}
286+
}
256287
}

dev/tests/integration/testsuite/Magento/Cms/Model/PageRepositoryTest.php

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,11 @@ class PageRepositoryTest extends TestCase
3232
/**
3333
* @inheritDoc
3434
*/
35-
protected function setUp()
35+
protected function setUp(): void
3636
{
37-
$this->repo = Bootstrap::getObjectManager()->get(PageRepositoryInterface::class);
38-
$this->retriever = Bootstrap::getObjectManager()->get(GetPageByIdentifierInterface::class);
37+
$objectManager = Bootstrap::getObjectManager();
38+
$this->repo = $objectManager->get(PageRepositoryInterface::class);
39+
$this->retriever = $objectManager->get(GetPageByIdentifierInterface::class);
3940
}
4041

4142
/**
@@ -48,7 +49,7 @@ protected function setUp()
4849
public function testSaveUpdateXml(): void
4950
{
5051
$page = $this->retriever->execute('test_custom_layout_page_1', 0);
51-
$page->setTitle($page->getTitle() .'TEST');
52+
$page->setTitle($page->getTitle() . 'TEST');
5253

5354
//Is successfully saved without changes to the custom layout xml.
5455
$page = $this->repo->save($page);
@@ -80,4 +81,19 @@ public function testSaveUpdateXml(): void
8081
$this->assertEmpty($page->getCustomLayoutUpdateXml());
8182
$this->assertEmpty($page->getLayoutUpdateXml());
8283
}
84+
85+
/**
86+
* Verifies that cms page with identifier which duplicates existed route shouldn't be saved
87+
*
88+
* @return void
89+
* @throws \Throwable
90+
* @magentoDataFixture Magento/Cms/_files/pages.php
91+
*/
92+
public function testSaveWithRouteDuplicate(): void
93+
{
94+
$page = $this->retriever->execute('page100', 0);
95+
$page->setIdentifier('customer');
96+
$this->expectException(CouldNotSaveException::class);
97+
$this->repo->save($page);
98+
}
8399
}

0 commit comments

Comments
 (0)