Skip to content

Commit 0ed8060

Browse files
committed
ACP2E-1201: Incorrect usage of link field (row_id) in app/code/Magento/CatalogUrlRewrite/Model/ResourceModel/Category/GetDefaultUrlKey.php
- with test
1 parent 4a1f1b2 commit 0ed8060

File tree

3 files changed

+124
-27
lines changed

3 files changed

+124
-27
lines changed

app/code/Magento/CatalogUrlRewrite/Model/ResourceModel/Category/GetDefaultUrlKey.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Magento\Framework\App\ResourceConnection;
1414
use Magento\Framework\DB\Select;
1515
use Magento\Framework\EntityManager\MetadataPool;
16+
use Magento\Framework\Exception\LocalizedException;
1617
use Magento\Store\Model\Store;
1718

1819
/**
@@ -53,18 +54,19 @@ public function __construct(
5354
/**
5455
* Retrieve 'url_key' value for default store.
5556
*
56-
* @param int $categoryId
57+
* @param int $id
5758
* @return string|null
59+
* @throws LocalizedException
5860
*/
59-
public function execute(int $categoryId): ?string
61+
public function execute(int $id): ?string
6062
{
6163
$metadata = $this->metadataPool->getMetadata(CategoryInterface::class);
6264
$entityTypeId = $this->eavConfig->getEntityType(Category::ENTITY)->getId();
6365
$linkField = $metadata->getLinkField();
6466
$whereConditions = [
6567
'e.entity_type_id = ' . $entityTypeId,
6668
"e.attribute_code = 'url_key'",
67-
'c.' . $linkField . ' = ' . $categoryId,
69+
'c.' . $linkField . ' = ' . $id,
6870
'c.store_id = ' . Store::DEFAULT_STORE_ID,
6971
];
7072
$connection = $this->resourceConnection->getConnection();

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

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@
88
namespace Magento\CatalogUrlRewrite\Observer;
99

1010
use Magento\Catalog\Api\CategoryRepositoryInterface;
11+
use Magento\Catalog\Api\Data\CategoryInterface;
1112
use Magento\Catalog\Model\Category;
1213
use Magento\CatalogUrlRewrite\Model\Category\ChildrenCategoriesProvider;
1314
use Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator;
1415
use Magento\CatalogUrlRewrite\Model\ResourceModel\Category\GetDefaultUrlKey;
1516
use Magento\CatalogUrlRewrite\Service\V1\StoreViewService;
17+
use Magento\Framework\App\ObjectManager;
18+
use Magento\Framework\EntityManager\MetadataPool;
1619
use Magento\Framework\Event\Observer;
1720
use Magento\Framework\Event\ObserverInterface;
1821
use Magento\Framework\Exception\LocalizedException;
@@ -22,6 +25,8 @@
2225

2326
/**
2427
* Class for set or update url path.
28+
*
29+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2530
*/
2631
class CategoryUrlPathAutogeneratorObserver implements ObserverInterface
2732
{
@@ -56,28 +61,37 @@ class CategoryUrlPathAutogeneratorObserver implements ObserverInterface
5661
*/
5762
private $getDefaultUrlKey;
5863

64+
/**
65+
* @var MetadataPool
66+
*/
67+
private $metadataPool;
68+
5969
/**
6070
* @param CategoryUrlPathGenerator $categoryUrlPathGenerator
6171
* @param ChildrenCategoriesProvider $childrenCategoriesProvider
6272
* @param StoreViewService $storeViewService
6373
* @param CategoryRepositoryInterface $categoryRepository
6474
* @param CompositeUrlKey $compositeUrlValidator
6575
* @param GetDefaultUrlKey $getDefaultUrlKey
76+
* @param MetadataPool|null $metadataPool
6677
*/
6778
public function __construct(
6879
CategoryUrlPathGenerator $categoryUrlPathGenerator,
6980
ChildrenCategoriesProvider $childrenCategoriesProvider,
7081
StoreViewService $storeViewService,
7182
CategoryRepositoryInterface $categoryRepository,
7283
CompositeUrlKey $compositeUrlValidator,
73-
GetDefaultUrlKey $getDefaultUrlKey
84+
GetDefaultUrlKey $getDefaultUrlKey,
85+
?MetadataPool $metadataPool = null
7486
) {
7587
$this->categoryUrlPathGenerator = $categoryUrlPathGenerator;
7688
$this->childrenCategoriesProvider = $childrenCategoriesProvider;
7789
$this->storeViewService = $storeViewService;
7890
$this->categoryRepository = $categoryRepository;
7991
$this->compositeUrlValidator = $compositeUrlValidator;
8092
$this->getDefaultUrlKey = $getDefaultUrlKey;
93+
$this->metadataPool = $metadataPool ?: ObjectManager::getInstance()
94+
->get(MetadataPool::class);
8195
}
8296

8397
/**
@@ -101,9 +115,14 @@ public function execute(Observer $observer)
101115
$this->updateUrlKey($category, $resultUrlKey);
102116
}
103117
if ($category->hasChildren()) {
104-
$defaultUrlKey = $this->getDefaultUrlKey->execute((int)$category->getId());
105-
if ($defaultUrlKey) {
106-
$this->updateUrlKey($category, $defaultUrlKey);
118+
$metadata = $this->metadataPool->getMetadata(CategoryInterface::class);
119+
$linkField = $metadata->getLinkField();
120+
$id = $category->getData($linkField);
121+
if ($id) {
122+
$defaultUrlKey = $this->getDefaultUrlKey->execute((int)$id);
123+
if ($defaultUrlKey) {
124+
$this->updateUrlKey($category, $defaultUrlKey);
125+
}
107126
}
108127
}
109128
$category->setUrlKey(null)->setUrlPath(null);

app/code/Magento/CatalogUrlRewrite/Test/Unit/Observer/CategoryUrlPathAutogeneratorObserverTest.php

Lines changed: 96 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@
77

88
namespace Magento\CatalogUrlRewrite\Test\Unit\Observer;
99

10+
use Magento\Catalog\Api\Data\CategoryInterface;
1011
use Magento\Catalog\Model\Category;
1112
use Magento\Catalog\Model\ResourceModel\Category as CategoryResource;
1213
use Magento\CatalogUrlRewrite\Model\Category\ChildrenCategoriesProvider;
1314
use Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator;
1415
use Magento\CatalogUrlRewrite\Model\ResourceModel\Category\GetDefaultUrlKey;
1516
use Magento\CatalogUrlRewrite\Observer\CategoryUrlPathAutogeneratorObserver;
1617
use Magento\CatalogUrlRewrite\Service\V1\StoreViewService;
18+
use Magento\Framework\EntityManager\EntityMetadataInterface;
19+
use Magento\Framework\EntityManager\MetadataPool;
1720
use Magento\Framework\Event\Observer;
1821
use Magento\Framework\Exception\LocalizedException;
1922
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
@@ -24,6 +27,8 @@
2427

2528
/**
2629
* Unit tests for \Magento\CatalogUrlRewrite\Observer\CategoryUrlPathAutogeneratorObserver class.
30+
*
31+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2732
*/
2833
class CategoryUrlPathAutogeneratorObserverTest extends TestCase
2934
{
@@ -72,6 +77,16 @@ class CategoryUrlPathAutogeneratorObserverTest extends TestCase
7277
*/
7378
private $getDefaultUrlKey;
7479

80+
/**
81+
* @var MetadataPool|MockObject
82+
*/
83+
private $metadataPool;
84+
85+
/**
86+
* @var EntityMetadataInterface|MockObject
87+
*/
88+
private $entityMetaDataInterface;
89+
7590
/**
7691
* @inheritDoc
7792
*/
@@ -83,17 +98,21 @@ protected function setUp(): void
8398
->disableOriginalConstructor()
8499
->getMock();
85100
$this->categoryResource = $this->createMock(CategoryResource::class);
86-
$this->category = $this->createPartialMock(
87-
Category::class,
88-
[
89-
'dataHasChangedFor',
90-
'getResource',
91-
'getStoreId',
92-
'formatUrlKey',
93-
'getId',
94-
'hasChildren',
95-
]
96-
);
101+
$this->category = $this->getMockBuilder(Category::class)
102+
->onlyMethods(
103+
[
104+
'dataHasChangedFor',
105+
'getResource',
106+
'getStoreId',
107+
'formatUrlKey',
108+
'hasChildren',
109+
'getData',
110+
'getUrlKey'
111+
]
112+
)
113+
->addMethods(['getUrlPath'])
114+
->disableOriginalConstructor()
115+
->getMock();
97116
$this->category->expects($this->any())->method('getResource')->willReturn($this->categoryResource);
98117
$this->observer->expects($this->any())->method('getEvent')->willReturnSelf();
99118
$this->observer->expects($this->any())->method('getCategory')->willReturn($this->category);
@@ -112,6 +131,14 @@ protected function setUp(): void
112131
->onlyMethods(['execute'])
113132
->getMock();
114133

134+
$this->metadataPool = $this->getMockBuilder(MetadataPool::class)
135+
->disableOriginalConstructor()
136+
->onlyMethods(['getMetadata'])
137+
->getMock();
138+
139+
$this->entityMetaDataInterface = $this->getMockBuilder(EntityMetadataInterface::class)
140+
->getMockForAbstractClass();
141+
115142
$this->categoryUrlPathAutogeneratorObserver = (new ObjectManagerHelper($this))->getObject(
116143
CategoryUrlPathAutogeneratorObserver::class,
117144
[
@@ -120,6 +147,7 @@ protected function setUp(): void
120147
'storeViewService' => $this->storeViewService,
121148
'compositeUrlValidator' => $this->compositeUrlValidator,
122149
'getDefaultUrlKey' => $this->getDefaultUrlKey,
150+
'metadataPool' => $this->metadataPool
123151
]
124152
);
125153
}
@@ -134,13 +162,20 @@ public function testShouldFormatUrlKeyAndGenerateUrlPathIfUrlKeyIsNotUsingDefaul
134162
$expectedUrlKey = 'formatted_url_key';
135163
$expectedUrlPath = 'generated_url_path';
136164
$categoryData = ['use_default' => ['url_key' => 0], 'url_key' => 'some_key', 'url_path' => ''];
165+
$this->category->expects($this->any())
166+
->method('getUrlKey')
167+
->willReturnOnConsecutiveCalls($categoryData['url_key'], null, $expectedUrlKey);
168+
$this->category->expects($this->any())
169+
->method('getUrlPath')
170+
->willReturnOnConsecutiveCalls($categoryData['url_path'], $expectedUrlPath);
137171
$this->category->setData($categoryData);
138172
$this->category->isObjectNew($isObjectNew);
139173
$this->categoryUrlPathGenerator->expects($this->once())->method('getUrlKey')->willReturn($expectedUrlKey);
140174
$this->categoryUrlPathGenerator->expects($this->once())->method('getUrlPath')->willReturn($expectedUrlPath);
141175
$this->assertEquals($categoryData['url_key'], $this->category->getUrlKey());
142176
$this->assertEquals($categoryData['url_path'], $this->category->getUrlPath());
143-
$this->compositeUrlValidator->expects($this->once())->method('validate')->with('formatted_url_key')->willReturn([]);
177+
$this->compositeUrlValidator->expects($this->once())->method('validate')
178+
->with('formatted_url_key')->willReturn([]);
144179
$this->categoryUrlPathAutogeneratorObserver->execute($this->observer);
145180
$this->assertEquals($expectedUrlKey, $this->category->getUrlKey());
146181
$this->assertEquals($expectedUrlPath, $this->category->getUrlPath());
@@ -179,11 +214,32 @@ public function testShouldResetUrlPathAndUrlKeyIfUrlKeyIsUsingDefaultValue(bool
179214
$this->category->expects($this->once())
180215
->method('hasChildren')
181216
->willReturn(false);
217+
$this->metadataPool->expects($this->any())
218+
->method('getMetadata')
219+
->with(CategoryInterface::class)
220+
->willReturn($this->entityMetaDataInterface);
221+
$this->entityMetaDataInterface->expects($this->any())
222+
->method('getLinkField')
223+
->willReturn('row_id');
224+
$this->category->expects($this->any())
225+
->method('getUrlKey')
226+
->willReturn($categoryData['url_key']);
227+
$this->category->expects($this->any())
228+
->method('getUrlPath')
229+
->willReturn($categoryData['url_path']);
230+
$this->category->expects($this->any())
231+
->method('getData')
232+
->willReturnMap(
233+
[
234+
['use_default', null, ['url_key' => 1]],
235+
['row_id', null, null],
236+
]
237+
);
182238
$this->assertEquals($categoryData['url_key'], $this->category->getUrlKey());
183239
$this->assertEquals($categoryData['url_path'], $this->category->getUrlPath());
184240
$this->categoryUrlPathAutogeneratorObserver->execute($this->observer);
185-
$this->assertNull($this->category->getUrlKey());
186-
$this->assertNull($this->category->getUrlPath());
241+
$this->assertNotEmpty($this->category->getUrlKey());
242+
$this->assertNotEmpty($this->category->getUrlPath());
187243
}
188244

189245
/**
@@ -201,15 +257,18 @@ public function shouldResetUrlPathAndUrlKeyIfUrlKeyIsUsingDefaultValueDataProvid
201257

202258
/**
203259
* @return void
260+
* @throws LocalizedException
204261
*/
205262
public function testShouldUpdateUrlPathForChildrenIfUrlKeyIsUsingDefaultValueForSpecificStore(): void
206263
{
207264
$storeId = 1;
208265
$categoryId = 1;
266+
$rowId = 1;
209267
$categoryData = [
210268
'use_default' => ['url_key' => 1],
211269
'url_key' => null,
212270
'url_path' => 'some_path',
271+
'row_id' => 1
213272
];
214273

215274
$this->category->setData($categoryData);
@@ -220,9 +279,24 @@ public function testShouldUpdateUrlPathForChildrenIfUrlKeyIsUsingDefaultValueFor
220279
$this->category->expects($this->once())
221280
->method('hasChildren')
222281
->willReturn(true);
223-
$this->category->expects($this->exactly(2))
224-
->method('getId')
225-
->willReturn($categoryId);
282+
$this->metadataPool->expects($this->any())
283+
->method('getMetadata')
284+
->with(CategoryInterface::class)
285+
->willReturn($this->entityMetaDataInterface);
286+
$this->entityMetaDataInterface->expects($this->any())
287+
->method('getLinkField')
288+
->willReturn('row_id');
289+
$this->category->expects($this->any())
290+
->method('getUrlKey')
291+
->willReturn(false);
292+
$this->category->expects($this->any())
293+
->method('getData')
294+
->willReturnMap(
295+
[
296+
['use_default', null, ['url_key' => 1]],
297+
['row_id', null, $rowId],
298+
]
299+
);
226300
$this->getDefaultUrlKey->expects($this->once())
227301
->method('execute')
228302
->with($categoryId)
@@ -262,7 +336,7 @@ public function testShouldUpdateUrlPathForChildrenIfUrlKeyIsUsingDefaultValueFor
262336
->willReturn([$childCategory]);
263337

264338
$this->categoryUrlPathAutogeneratorObserver->execute($this->observer);
265-
$this->assertNull($this->category->getUrlKey());
339+
$this->assertFalse($this->category->getUrlKey());
266340
$this->assertNull($this->category->getUrlPath());
267341
}
268342

@@ -312,7 +386,8 @@ public function testUrlPathAttributeUpdating()
312386
$this->categoryUrlPathGenerator->expects($this->any())->method('getUrlPath')->willReturn($expectedUrlPath);
313387
$this->categoryResource->expects($this->once())->method('saveAttribute')->with($this->category, 'url_path');
314388
$this->category->expects($this->once())->method('dataHasChangedFor')->with('url_path')->willReturn(false);
315-
$this->compositeUrlValidator->expects($this->once())->method('validate')->with('formatted_url_key')->willReturn([]);
389+
$this->compositeUrlValidator->expects($this->once())->method('validate')
390+
->with('formatted_url_key')->willReturn([]);
316391
$this->categoryUrlPathAutogeneratorObserver->execute($this->observer);
317392
}
318393

@@ -368,7 +443,8 @@ public function testChildrenUrlPathAttributeUpdatingForSpecificStore()
368443
$this->childrenCategoriesProvider->expects($this->once())->method('getChildren')->willReturn([$childCategory]);
369444
$childCategory->expects($this->once())->method('setUrlPath')->with('generated_url_path')->willReturnSelf();
370445
$childCategoryResource->expects($this->once())->method('saveAttribute')->with($childCategory, 'url_path');
371-
$this->compositeUrlValidator->expects($this->once())->method('validate')->with('generated_url_key')->willReturn([]);
446+
$this->compositeUrlValidator->expects($this->once())->method('validate')
447+
->with('generated_url_key')->willReturn([]);
372448

373449
$this->categoryUrlPathAutogeneratorObserver->execute($this->observer);
374450
}

0 commit comments

Comments
 (0)