Skip to content

Commit 7e7eb07

Browse files
committed
MC-34483: Moving a store view to a different website resets URLs
1 parent 8d90d12 commit 7e7eb07

File tree

4 files changed

+144
-55
lines changed
  • app/code/Magento
    • CatalogUrlRewrite
    • CmsUrlRewrite/Plugin/Cms/Model/Store
  • dev/tests/integration/testsuite/Magento/CmsUrlRewrite/Plugin/Cms/Model/Store

4 files changed

+144
-55
lines changed

app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/View.php

Lines changed: 52 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,18 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
7+
68
namespace Magento\CatalogUrlRewrite\Model\Category\Plugin\Store;
79

810
use Magento\Catalog\Model\Category;
911
use Magento\Catalog\Model\CategoryFactory;
12+
use Magento\Catalog\Model\Product;
1013
use Magento\Catalog\Model\ProductFactory;
1114
use Magento\CatalogUrlRewrite\Model\CategoryUrlRewriteGenerator;
1215
use Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator;
1316
use Magento\Framework\Model\AbstractModel;
17+
use Magento\Store\Model\ResourceModel\Store;
1418
use Magento\UrlRewrite\Model\UrlPersistInterface;
1519
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;
1620

@@ -19,32 +23,31 @@
1923
*
2024
* @see \Magento\Store\Model\ResourceModel\Store
2125
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
22-
* @package Magento\CatalogUrlRewrite\Model\Category\Plugin\Store
2326
*/
2427
class View
2528
{
2629
/**
27-
* @var \Magento\UrlRewrite\Model\UrlPersistInterface
30+
* @var UrlPersistInterface
2831
*/
2932
protected $urlPersist;
3033

3134
/**
32-
* @var \Magento\Catalog\Model\CategoryFactory
35+
* @var CategoryFactory
3336
*/
3437
protected $categoryFactory;
3538

3639
/**
37-
* @var \Magento\Catalog\Model\ProductFactory
40+
* @var ProductFactory
3841
*/
3942
protected $productFactory;
4043

4144
/**
42-
* @var \Magento\CatalogUrlRewrite\Model\CategoryUrlRewriteGenerator
45+
* @var CategoryUrlRewriteGenerator
4346
*/
4447
protected $categoryUrlRewriteGenerator;
4548

4649
/**
47-
* @var \Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator
50+
* @var ProductUrlRewriteGenerator
4851
*/
4952
protected $productUrlRewriteGenerator;
5053

@@ -75,114 +78,116 @@ public function __construct(
7578
}
7679

7780
/**
78-
* @param \Magento\Store\Model\ResourceModel\Store $object
81+
* Set original store before saving
82+
*
83+
* @param Store $object
7984
* @param AbstractModel $store
8085
* @return void
8186
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
8287
*/
8388
public function beforeSave(
84-
\Magento\Store\Model\ResourceModel\Store $object,
89+
Store $object,
8590
AbstractModel $store
86-
) {
91+
): void {
8792
$this->origStore = $store;
8893
}
8994

9095
/**
9196
* Regenerate urls on store after save
9297
*
93-
* @param \Magento\Store\Model\ResourceModel\Store $object
94-
* @param \Magento\Store\Model\ResourceModel\Store $store
95-
* @return \Magento\Store\Model\ResourceModel\Store
98+
* @param Store $object
99+
* @param Store $store
100+
* @return Store
96101
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
97102
*/
98103
public function afterSave(
99-
\Magento\Store\Model\ResourceModel\Store $object,
100-
\Magento\Store\Model\ResourceModel\Store $store
101-
) {
104+
Store $object,
105+
Store $store
106+
): Store {
102107
if ($this->origStore->isObjectNew() || $this->origStore->dataHasChangedFor('group_id')) {
103108
if (!$this->origStore->isObjectNew()) {
104-
$this->urlPersist->deleteByData([UrlRewrite::STORE_ID => $this->origStore->getId()]);
109+
$this->urlPersist->deleteByData([
110+
UrlRewrite::STORE_ID => $this->origStore->getId(),
111+
UrlRewrite::ENTITY_TYPE => [
112+
CategoryUrlRewriteGenerator::ENTITY_TYPE,
113+
ProductUrlRewriteGenerator::ENTITY_TYPE,
114+
],
115+
]);
105116
}
106117

107118
$this->urlPersist->replace(
108-
$this->generateCategoryUrls($this->origStore->getRootCategoryId(), $this->origStore->getId())
119+
$this->generateCategoryUrls((int)$this->origStore->getRootCategoryId(), (int)$this->origStore->getId())
109120
);
110121

111122
$this->urlPersist->replace(
112-
$this->generateProductUrls(
113-
$this->origStore->getWebsiteId(),
114-
$this->origStore->getOrigData('website_id'),
115-
$this->origStore->getId()
116-
)
123+
$this->generateProductUrls((int)$this->origStore->getId())
117124
);
118125
}
126+
119127
return $store;
120128
}
121129

122130
/**
123-
* Generate url rewrites for products assigned to website
131+
* Generate url rewrites for products assigned to store
124132
*
125-
* @param int $websiteId
126-
* @param int $originWebsiteId
127133
* @param int $storeId
128134
* @return array
129135
*/
130-
protected function generateProductUrls($websiteId, $originWebsiteId, $storeId)
136+
protected function generateProductUrls(int $storeId): array
131137
{
132138
$urls = [];
133-
$websiteIds = $websiteId != $originWebsiteId && $originWebsiteId !== null
134-
? [$websiteId, $originWebsiteId]
135-
: [$websiteId];
139+
$rewrites = [];
136140
$collection = $this->productFactory->create()
137141
->getCollection()
138142
->addCategoryIds()
139143
->addAttributeToSelect(['name', 'url_path', 'url_key', 'visibility'])
140-
->addWebsiteFilter($websiteIds);
144+
->addStoreFilter($storeId);
141145
foreach ($collection as $product) {
142146
$product->setStoreId($storeId);
143-
/** @var \Magento\Catalog\Model\Product $product */
144-
$urls = array_merge(
145-
$urls,
146-
$this->productUrlRewriteGenerator->generate($product)
147-
);
147+
/** @var Product $product */
148+
$rewrites[] = $this->productUrlRewriteGenerator->generate($product);
148149
}
150+
$urls = array_merge($urls, ...$rewrites);
151+
149152
return $urls;
150153
}
151154

152155
/**
156+
* Generate url rewrites for categories assigned to store
157+
*
153158
* @param int $rootCategoryId
154159
* @param int $storeId
155160
* @return array
156161
*/
157-
protected function generateCategoryUrls($rootCategoryId, $storeId)
162+
protected function generateCategoryUrls(int $rootCategoryId, int $storeId): array
158163
{
159164
$urls = [];
165+
$rewrites = [];
160166
$categories = $this->categoryFactory->create()->getCategories($rootCategoryId, 1, false, true);
161167
foreach ($categories as $category) {
162-
/** @var \Magento\Catalog\Model\Category $category */
168+
/** @var Category $category */
163169
$category->setStoreId($storeId);
164-
$urls = array_merge(
165-
$urls,
166-
$this->categoryUrlRewriteGenerator->generate($category)
167-
);
170+
$rewrites[] = $this->categoryUrlRewriteGenerator->generate($category);
168171
}
172+
$urls = array_merge($urls, ...$rewrites);
173+
169174
return $urls;
170175
}
171176

172177
/**
173178
* Delete unused url rewrites
174179
*
175-
* @param \Magento\Store\Model\ResourceModel\Store $subject
176-
* @param \Magento\Store\Model\ResourceModel\Store $result
180+
* @param Store $subject
181+
* @param Store $result
177182
* @param AbstractModel $store
178-
* @return \Magento\Store\Model\ResourceModel\Store
183+
* @return Store
179184
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
180185
*/
181186
public function afterDelete(
182-
\Magento\Store\Model\ResourceModel\Store $subject,
183-
\Magento\Store\Model\ResourceModel\Store $result,
187+
Store $subject,
188+
Store $result,
184189
AbstractModel $store
185-
) {
190+
): Store {
186191
$this->urlPersist->deleteByData([UrlRewrite::STORE_ID => $store->getId()]);
187192

188193
return $result;

app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Store/ViewTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ protected function setUp(): void
121121
->getMock();
122122
$this->productCollectionMock = $this->getMockBuilder(ProductCollection::class)
123123
->disableOriginalConstructor()
124-
->setMethods(['addCategoryIds', 'addAttributeToSelect', 'addWebsiteFilter', 'getIterator'])
124+
->setMethods(['addCategoryIds', 'addAttributeToSelect', 'getIterator', 'addStoreFilter'])
125125
->getMock();
126126
$this->productMock = $this->getMockBuilder(Product::class)
127127
->disableOriginalConstructor()
@@ -174,7 +174,7 @@ public function testAfterSave()
174174
->method('addAttributeToSelect')
175175
->willReturn($this->productCollectionMock);
176176
$this->productCollectionMock->expects($this->once())
177-
->method('addWebsiteFilter')
177+
->method('addStoreFilter')
178178
->willReturn($this->productCollectionMock);
179179
$iterator = new \ArrayIterator([$this->productMock]);
180180
$this->productCollectionMock->expects($this->once())

app/code/Magento/CmsUrlRewrite/Plugin/Cms/Model/Store/View.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public function __construct(
7272
*/
7373
public function afterSave(ResourceStore $object, ResourceStore $result, AbstractModel $store): void
7474
{
75-
if ($store->isObjectNew() || $store->dataHasChangedFor('group_id')) {
75+
if ($store->isObjectNew()) {
7676
$this->urlPersist->replace(
7777
$this->generateCmsPagesUrls((int)$store->getId())
7878
);

dev/tests/integration/testsuite/Magento/CmsUrlRewrite/Plugin/Cms/Model/Store/ViewTest.php

Lines changed: 89 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,30 @@
77

88
namespace Magento\CmsUrlRewrite\Plugin\Cms\Model\Store;
99

10+
use Magento\Cms\Api\Data\PageInterface;
11+
use Magento\Cms\Api\PageRepositoryInterface;
12+
use Magento\CmsUrlRewrite\Model\CmsPageUrlPathGenerator;
13+
use Magento\CmsUrlRewrite\Model\CmsPageUrlRewriteGenerator;
14+
use Magento\Framework\Api\Filter;
15+
use Magento\Framework\Api\Search\FilterGroup;
16+
use Magento\Framework\Api\SearchCriteriaInterface;
1017
use Magento\Framework\ObjectManagerInterface;
1118
use Magento\Store\Model\Store;
1219
use Magento\Store\Model\StoreFactory;
1320
use Magento\TestFramework\Helper\Bootstrap;
1421
use Magento\UrlRewrite\Model\UrlFinderInterface;
22+
use Magento\UrlRewrite\Model\UrlPersistInterface;
1523
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;
24+
use Magento\UrlRewrite\Service\V1\Data\UrlRewriteFactory;
25+
use PHPUnit\Framework\TestCase;
1626

1727
/**
1828
* Test for plugin which is listening store resource model and on save replace cms page url rewrites
1929
*
2030
* @magentoAppArea adminhtml
31+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2132
*/
22-
class ViewTest extends \PHPUnit\Framework\TestCase
33+
class ViewTest extends TestCase
2334
{
2435
/**
2536
* @var UrlFinderInterface
@@ -36,6 +47,26 @@ class ViewTest extends \PHPUnit\Framework\TestCase
3647
*/
3748
private $storeFactory;
3849

50+
/**
51+
* @var UrlPersistInterface
52+
*/
53+
private $urlPersist;
54+
55+
/**
56+
* @var UrlRewriteFactory
57+
*/
58+
private $urlRewriteFactory;
59+
60+
/**
61+
* @var PageRepositoryInterface
62+
*/
63+
private $pageRepository;
64+
65+
/**
66+
* @var CmsPageUrlPathGenerator
67+
*/
68+
private $cmsPageUrlPathGenerator;
69+
3970
/**
4071
* @inheritdoc
4172
*/
@@ -44,6 +75,10 @@ protected function setUp(): void
4475
$this->objectManager = Bootstrap::getObjectManager();
4576
$this->urlFinder = $this->objectManager->create(UrlFinderInterface::class);
4677
$this->storeFactory = $this->objectManager->create(StoreFactory::class);
78+
$this->urlPersist = $this->objectManager->create(UrlPersistInterface::class);
79+
$this->urlRewriteFactory = $this->objectManager->create(UrlRewriteFactory::class);
80+
$this->pageRepository = $this->objectManager->create(PageRepositoryInterface::class);
81+
$this->cmsPageUrlPathGenerator = $this->objectManager->create(CmsPageUrlPathGenerator::class);
4782
}
4883

4984
/**
@@ -54,21 +89,25 @@ protected function setUp(): void
5489
public function testUrlRewritesChangesAfterStoreSave()
5590
{
5691
$storeId = $this->createStore();
57-
$this->assertUrlRewritesCount($storeId, 1);
92+
$this->assertUrlRewritesCount($storeId, 'page100', 1);
93+
$this->editUrlRewrite($storeId, 'page100');
94+
$this->saveStore($storeId);
95+
$this->assertUrlRewritesCount($storeId, 'page100-test', 1);
5896
$this->deleteStore($storeId);
59-
$this->assertUrlRewritesCount($storeId, 0);
97+
$this->assertUrlRewritesCount($storeId, 'page100', 0);
6098
}
6199

62100
/**
63101
* Assert url rewrites count by store id
64102
*
65103
* @param int $storeId
104+
* @param string $pageIdentifier
66105
* @param int $expectedCount
67106
*/
68-
private function assertUrlRewritesCount(int $storeId, int $expectedCount): void
107+
private function assertUrlRewritesCount(int $storeId, string $pageIdentifier, int $expectedCount): void
69108
{
70109
$data = [
71-
UrlRewrite::REQUEST_PATH => 'page100',
110+
UrlRewrite::REQUEST_PATH => $pageIdentifier,
72111
UrlRewrite::STORE_ID => $storeId
73112
];
74113
$urlRewrites = $this->urlFinder->findAllByData($data);
@@ -105,4 +144,49 @@ private function deleteStore(int $storeId): void
105144
$store->delete();
106145
}
107146
}
147+
148+
/**
149+
* Edit url rewrite
150+
*
151+
* @param int $storeId
152+
* @param string $pageIdentifier
153+
*/
154+
private function editUrlRewrite(int $storeId, string $pageIdentifier): void
155+
{
156+
$filter = $this->objectManager->create(Filter::class);
157+
$filter->setField('identifier')->setValue($pageIdentifier);
158+
$filterGroup = $this->objectManager->create(FilterGroup::class);
159+
$filterGroup->setFilters([$filter]);
160+
$searchCriteria = $this->objectManager->create(SearchCriteriaInterface::class);
161+
$searchCriteria->setFilterGroups([$filterGroup]);
162+
$pageSearchResults = $this->pageRepository->getList($searchCriteria);
163+
$pages = $pageSearchResults->getItems();
164+
/** @var PageInterface $page */
165+
$cmsPage = array_values($pages)[0];
166+
167+
$urlRewrite = $this->urlRewriteFactory->create()->setStoreId($storeId)
168+
->setEntityType(CmsPageUrlRewriteGenerator::ENTITY_TYPE)
169+
->setEntityId($cmsPage->getId())
170+
->setRequestPath($cmsPage->getIdentifier() . '-test')
171+
->setTargetPath($this->cmsPageUrlPathGenerator->getCanonicalUrlPath($cmsPage))
172+
->setIsAutogenerated(0)
173+
->setRedirectType(0);
174+
175+
$this->urlPersist->replace([$urlRewrite]);
176+
}
177+
178+
/**
179+
* Edit test store
180+
*
181+
* @param int $storeId
182+
* @return void
183+
*/
184+
private function saveStore(int $storeId): void
185+
{
186+
$store = $this->storeFactory->create();
187+
$store->load($storeId);
188+
if ($store !== null) {
189+
$store->save();
190+
}
191+
}
108192
}

0 commit comments

Comments
 (0)