Skip to content

Commit cf316b4

Browse files
committed
MAGETWO-95176: Detaching category from product causes massive product url regeneration
1 parent 401203a commit cf316b4

File tree

2 files changed

+77
-12
lines changed

2 files changed

+77
-12
lines changed

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

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,16 +100,19 @@ public function execute(\Magento\Framework\Event\Observer $observer)
100100
}
101101

102102
$mapsGenerated = false;
103-
if ($category->dataHasChangedFor('url_key')
104-
|| $category->dataHasChangedFor('is_anchor')
105-
|| $category->getChangedProductIds()
106-
) {
103+
if ($this->isCategoryHasChanged($category)) {
107104
if ($category->dataHasChangedFor('url_key')) {
108105
$categoryUrlRewriteResult = $this->categoryUrlRewriteGenerator->generate($category);
109106
$this->urlRewriteBunchReplacer->doBunchReplace($categoryUrlRewriteResult);
110107
}
111-
$productUrlRewriteResult = $this->urlRewriteHandler->generateProductUrlRewrites($category);
112-
$this->urlRewriteBunchReplacer->doBunchReplace($productUrlRewriteResult);
108+
if ($this->isChangedOnlyProduct($category)) {
109+
$productUrlRewriteResult =
110+
$this->urlRewriteHandler->updateProductUrlRewritesForChangedProduct($category);
111+
$this->urlRewriteBunchReplacer->doBunchReplace($productUrlRewriteResult);
112+
} else {
113+
$productUrlRewriteResult = $this->urlRewriteHandler->generateProductUrlRewrites($category);
114+
$this->urlRewriteBunchReplacer->doBunchReplace($productUrlRewriteResult);
115+
}
113116
$mapsGenerated = true;
114117
}
115118

@@ -120,8 +123,42 @@ public function execute(\Magento\Framework\Event\Observer $observer)
120123
}
121124

122125
/**
123-
* in case store_id is not set for category then we can assume that it was passed through product import.
124-
* store group must have only one root category, so receiving category's path and checking if one of it parts
126+
* Check is category changed changed.
127+
*
128+
* @param Category $category
129+
* @return bool
130+
*/
131+
private function isCategoryHasChanged(Category $category): bool
132+
{
133+
if ($category->dataHasChangedFor('url_key')
134+
|| $category->dataHasChangedFor('is_anchor')
135+
|| !empty($category->getChangedProductIds())) {
136+
return true;
137+
}
138+
139+
return false;
140+
}
141+
142+
/**
143+
* Check is only product changed.
144+
*
145+
* @param Category $category
146+
* @return bool
147+
*/
148+
private function isChangedOnlyProduct(Category $category): bool
149+
{
150+
if (!empty($category->getChangedProductIds())
151+
&& !$category->dataHasChangedFor('is_anchor')
152+
&& !$category->dataHasChangedFor('url_key')) {
153+
return true;
154+
}
155+
156+
return false;
157+
}
158+
159+
/**
160+
* In case store_id is not set for category then we can assume that it was passed through product import.
161+
* Store group must have only one root category, so receiving category's path and checking if one of it parts
125162
* is the root category for store group, we can set default_store_id value from it to category.
126163
* it prevents urls duplication for different stores
127164
* ("Default Category/category/sub" and "Default Category2/category/sub")

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

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;
2525

2626
/**
27+
* Class for management url rewrites.
28+
*
2729
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2830
*/
2931
class UrlRewriteHandler
@@ -125,7 +127,7 @@ public function generateProductUrlRewrites(Category $category): array
125127
{
126128
$mergeDataProvider = clone $this->mergeDataProviderPrototype;
127129
$this->isSkippedProduct[$category->getEntityId()] = [];
128-
$saveRewriteHistory = $category->getData('save_rewrites_history');
130+
$saveRewriteHistory = (bool)$category->getData('save_rewrites_history');
129131
$storeId = (int)$category->getStoreId();
130132

131133
if ($category->getChangedProductIds()) {
@@ -156,6 +158,30 @@ public function generateProductUrlRewrites(Category $category): array
156158
}
157159

158160
/**
161+
* Update product url rewrites for changed product.
162+
*
163+
* @param Category $category
164+
* @return array
165+
*/
166+
public function updateProductUrlRewritesForChangedProduct(Category $category): array
167+
{
168+
$mergeDataProvider = clone $this->mergeDataProviderPrototype;
169+
$this->isSkippedProduct[$category->getEntityId()] = [];
170+
$saveRewriteHistory = (bool)$category->getData('save_rewrites_history');
171+
$storeIds = $this->getCategoryStoreIds($category);
172+
173+
if ($category->getChangedProductIds()) {
174+
foreach ($storeIds as $storeId) {
175+
$this->generateChangedProductUrls($mergeDataProvider, $category, (int)$storeId, $saveRewriteHistory);
176+
}
177+
}
178+
179+
return $mergeDataProvider->getData();
180+
}
181+
182+
/**
183+
* Delete category rewrites for children.
184+
*
159185
* @param Category $category
160186
* @return void
161187
*/
@@ -184,6 +210,8 @@ public function deleteCategoryRewritesForChildren(Category $category)
184210
}
185211

186212
/**
213+
* Get category products url rewrites.
214+
*
187215
* @param Category $category
188216
* @param int $storeId
189217
* @param bool $saveRewriteHistory
@@ -230,15 +258,15 @@ private function getCategoryProductsUrlRewrites(
230258
*
231259
* @param MergeDataProvider $mergeDataProvider
232260
* @param Category $category
233-
* @param Product $product
234261
* @param int $storeId
235-
* @param $saveRewriteHistory
262+
* @param bool $saveRewriteHistory
263+
* @return void
236264
*/
237265
private function generateChangedProductUrls(
238266
MergeDataProvider $mergeDataProvider,
239267
Category $category,
240268
int $storeId,
241-
$saveRewriteHistory
269+
bool $saveRewriteHistory
242270
) {
243271
$this->isSkippedProduct[$category->getEntityId()] = $category->getAffectedProductIds();
244272

0 commit comments

Comments
 (0)