Skip to content

Commit 6e20e2e

Browse files
committed
MAGETWO-95539: [2.3] Moving Category generate duplicate url_rewrite when 4th level category exist and is translated
- Fixed url rewrites regeneration after category moving
1 parent 8460e4e commit 6e20e2e

File tree

3 files changed

+86
-12
lines changed

3 files changed

+86
-12
lines changed

app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Category/Move.php

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,14 @@
66
namespace Magento\CatalogUrlRewrite\Model\Category\Plugin\Category;
77

88
use Magento\Catalog\Model\Category;
9+
use Magento\Catalog\Model\CategoryFactory;
910
use Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator;
1011
use Magento\CatalogUrlRewrite\Model\Category\ChildrenCategoriesProvider;
12+
use Magento\Store\Model\Store;
1113

14+
/**
15+
* Perform url updating for children categories.
16+
*/
1217
class Move
1318
{
1419
/**
@@ -21,16 +26,24 @@ class Move
2126
*/
2227
private $childrenCategoriesProvider;
2328

29+
/**
30+
* @var CategoryFactory
31+
*/
32+
private $categoryFactory;
33+
2434
/**
2535
* @param CategoryUrlPathGenerator $categoryUrlPathGenerator
2636
* @param ChildrenCategoriesProvider $childrenCategoriesProvider
37+
* @param CategoryFactory $categoryFactory
2738
*/
2839
public function __construct(
2940
CategoryUrlPathGenerator $categoryUrlPathGenerator,
30-
ChildrenCategoriesProvider $childrenCategoriesProvider
41+
ChildrenCategoriesProvider $childrenCategoriesProvider,
42+
CategoryFactory $categoryFactory
3143
) {
3244
$this->categoryUrlPathGenerator = $categoryUrlPathGenerator;
3345
$this->childrenCategoriesProvider = $childrenCategoriesProvider;
46+
$this->categoryFactory = $categoryFactory;
3447
}
3548

3649
/**
@@ -51,20 +64,54 @@ public function afterChangeParent(
5164
Category $newParent,
5265
$afterCategoryId
5366
) {
54-
$category->setUrlPath($this->categoryUrlPathGenerator->getUrlPath($category));
55-
$category->getResource()->saveAttribute($category, 'url_path');
56-
$this->updateUrlPathForChildren($category);
67+
foreach ($category->getStoreIds() as $storeId) {
68+
$category->setStoreId($storeId);
69+
if (!$this->isGlobalScope($storeId)) {
70+
$this->updateCategoryUrlKeyForStore($category);
71+
$category->setUrlPath($this->categoryUrlPathGenerator->getUrlPath($category));
72+
$category->getResource()->saveAttribute($category, 'url_path');
73+
$this->updateUrlPathForChildren($category);
74+
}
75+
}
5776

5877
return $result;
5978
}
6079

6180
/**
81+
* Set category url_key according to current category store id.
82+
*
83+
* @param Category $category
84+
* @return void
85+
*/
86+
private function updateCategoryUrlKeyForStore(Category $category)
87+
{
88+
$item = $this->categoryFactory->create();
89+
$item->setStoreId($category->getStoreId());
90+
$item->load($category->getId());
91+
$category->setUrlKey($item->getUrlKey());
92+
}
93+
94+
/**
95+
* Check is global scope.
96+
*
97+
* @param int|null $storeId
98+
* @return bool
99+
*/
100+
private function isGlobalScope($storeId)
101+
{
102+
return null === $storeId || $storeId == Store::DEFAULT_STORE_ID;
103+
}
104+
105+
/**
106+
* Updates url_path for child categories.
107+
*
62108
* @param Category $category
63109
* @return void
64110
*/
65-
protected function updateUrlPathForChildren($category)
111+
private function updateUrlPathForChildren($category)
66112
{
67113
foreach ($this->childrenCategoriesProvider->getChildren($category, true) as $childCategory) {
114+
$childCategory->setStoreId($category->getStoreId());
68115
$childCategory->unsUrlPath();
69116
$childCategory->setUrlPath($this->categoryUrlPathGenerator->getUrlPath($childCategory));
70117
$childCategory->getResource()->saveAttribute($childCategory, 'url_path');

app/code/Magento/CatalogUrlRewrite/Model/CategoryUrlRewriteGenerator.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
use Magento\Framework\App\ObjectManager;
1616
use Magento\UrlRewrite\Model\MergeDataProviderFactory;
1717

18+
/**
19+
* Generate list of urls.
20+
*/
1821
class CategoryUrlRewriteGenerator
1922
{
2023
/** Entity type code */
@@ -84,6 +87,8 @@ public function __construct(
8487
}
8588

8689
/**
90+
* Generate list of urls.
91+
*
8792
* @param \Magento\Catalog\Model\Category $category
8893
* @param bool $overrideStoreUrls
8994
* @param int|null $rootCategoryId
@@ -119,6 +124,7 @@ protected function generateForGlobalScope(
119124
$mergeDataProvider = clone $this->mergeDataProviderPrototype;
120125
$categoryId = $category->getId();
121126
foreach ($category->getStoreIds() as $storeId) {
127+
$category->setStoreId($storeId);
122128
if (!$this->isGlobalScope($storeId)
123129
&& $this->isOverrideUrlsForStore($storeId, $categoryId, $overrideStoreUrls)
124130
) {
@@ -131,6 +137,8 @@ protected function generateForGlobalScope(
131137
}
132138

133139
/**
140+
* Checks if urls should be overridden for store.
141+
*
134142
* @param int $storeId
135143
* @param int $categoryId
136144
* @param bool $overrideStoreUrls

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

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
namespace Magento\CatalogUrlRewrite\Test\Unit\Model\Category\Plugin\Category;
77

8+
use Magento\Catalog\Model\CategoryFactory;
89
use Magento\CatalogUrlRewrite\Model\Category\Plugin\Category\Move as CategoryMovePlugin;
910
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
1011
use Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator;
@@ -39,6 +40,11 @@ class MoveTest extends \PHPUnit\Framework\TestCase
3940
*/
4041
private $categoryMock;
4142

43+
/**
44+
* @var CategoryFactory|\PHPUnit_Framework_MockObject_MockObject
45+
*/
46+
private $categoryFactory;
47+
4248
/**
4349
* @var CategoryMovePlugin
4450
*/
@@ -55,28 +61,44 @@ protected function setUp()
5561
->disableOriginalConstructor()
5662
->setMethods(['getChildren'])
5763
->getMock();
64+
$this->categoryFactory = $this->getMockBuilder(CategoryFactory::class)
65+
->disableOriginalConstructor()
66+
->getMock();
5867
$this->subjectMock = $this->getMockBuilder(CategoryResourceModel::class)
5968
->disableOriginalConstructor()
6069
->getMock();
6170
$this->categoryMock = $this->getMockBuilder(Category::class)
6271
->disableOriginalConstructor()
63-
->setMethods(['getResource', 'setUrlPath'])
72+
->setMethods(['getResource', 'setUrlPath', 'getStoreIds'])
6473
->getMock();
6574
$this->plugin = $this->objectManager->getObject(
6675
CategoryMovePlugin::class,
6776
[
6877
'categoryUrlPathGenerator' => $this->categoryUrlPathGeneratorMock,
69-
'childrenCategoriesProvider' => $this->childrenCategoriesProviderMock
78+
'childrenCategoriesProvider' => $this->childrenCategoriesProviderMock,
79+
'categoryFactory' => $this->categoryFactory
7080
]
7181
);
7282
}
7383

84+
/**
85+
* Tests url updating for children categories.
86+
*/
7487
public function testAfterChangeParent()
7588
{
7689
$urlPath = 'test/path';
77-
$this->categoryMock->expects($this->once())
78-
->method('getResource')
90+
$storeIds = [1];
91+
$originalCategory = $this->getMockBuilder(Category::class)
92+
->disableOriginalConstructor()
93+
->getMock();
94+
$this->categoryFactory->method('create')
95+
->willReturn($originalCategory);
96+
97+
$this->categoryMock->method('getResource')
7998
->willReturn($this->subjectMock);
99+
$this->categoryMock->expects($this->once())
100+
->method('getStoreIds')
101+
->willReturn($storeIds);
80102
$this->childrenCategoriesProviderMock->expects($this->once())
81103
->method('getChildren')
82104
->with($this->categoryMock, true)
@@ -85,9 +107,6 @@ public function testAfterChangeParent()
85107
->method('getUrlPath')
86108
->with($this->categoryMock)
87109
->willReturn($urlPath);
88-
$this->categoryMock->expects($this->once())
89-
->method('getResource')
90-
->willReturn($this->subjectMock);
91110
$this->categoryMock->expects($this->once())
92111
->method('setUrlPath')
93112
->with($urlPath);

0 commit comments

Comments
 (0)