Skip to content

Commit a87d4ec

Browse files
committed
ACP2E-1783: Unable to create 301/302 redirect for product with a category path when Generate "category/product" URL Rewrites set to Yes
- implemented new solution
1 parent b17fd8a commit a87d4ec

File tree

2 files changed

+75
-42
lines changed

2 files changed

+75
-42
lines changed

app/code/Magento/CatalogUrlRewrite/Model/Products/AppendUrlRewritesToProducts.php

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -79,38 +79,65 @@ public function __construct(
7979
public function execute(array $products, array $storesToAdd): void
8080
{
8181
foreach ($products as $product) {
82-
$forceGenerateDefault = false;
83-
foreach ($storesToAdd as $storeId) {
84-
if ($this->needGenerateUrlForStore($product, (int)$storeId)) {
85-
$urls[] = $this->generateUrls($product, (int)$storeId);
86-
} elseif ((int)$product->getStoreId() !== Store::DEFAULT_STORE_ID) {
87-
$forceGenerateDefault = true;
88-
}
89-
}
90-
if ($product->getStoreId() === Store::DEFAULT_STORE_ID
91-
|| $this->isProductAssignedToStore($product)) {
92-
$product->unsUrlPath();
93-
$product->setUrlPath($this->productUrlPathGenerator->getUrlPath($product));
94-
$urls[] = $this->productUrlRewriteGenerator->generate($product);
95-
}
96-
if ($forceGenerateDefault && $product->getStoreId() !== Store::DEFAULT_STORE_ID) {
97-
$urls[] = $this->generateUrls($product, Store::DEFAULT_STORE_ID);
98-
}
82+
$urls = $this->getProductUrlRewrites($product, $storesToAdd);
9983
$this->getDataByStore->clearProductUrlRewriteDataCache($product);
10084
}
10185
if (!empty($urls)) {
10286
$this->urlPersist->replace(array_merge(...$urls));
10387
}
10488
}
10589

90+
/**
91+
* Generate store product URLs
92+
*
93+
* @param ProductInterface $product
94+
* @param array $stores
95+
* @return array
96+
*/
97+
public function getProductUrlRewrites(ProductInterface $product, array $stores): array
98+
{
99+
$urls = [];
100+
$forceGenerateDefault = false;
101+
foreach ($stores as $storeId) {
102+
if ($this->needGenerateUrlForStore($product, (int)$storeId)) {
103+
$urls[] = $this->generateProductStoreUrls($product, (int)$storeId);
104+
} elseif ((int)$product->getStoreId() !== Store::DEFAULT_STORE_ID) {
105+
$forceGenerateDefault = true;
106+
}
107+
}
108+
if ($product->getStoreId() === Store::DEFAULT_STORE_ID
109+
|| $this->isProductAssignedToStore($product)) {
110+
$product->unsUrlPath();
111+
$product->setUrlPath($this->productUrlPathGenerator->getUrlPath($product));
112+
$urls[] = $this->productUrlRewriteGenerator->generate($product);
113+
}
114+
if ($forceGenerateDefault && $product->getStoreId() !== Store::DEFAULT_STORE_ID) {
115+
$urls[] = $this->generateProductStoreUrls($product, Store::DEFAULT_STORE_ID);
116+
}
117+
118+
return $urls;
119+
}
120+
121+
/**
122+
* Replaces given product URL rewrites
123+
*
124+
* @param array $rewrites
125+
* @return \Magento\UrlRewrite\Service\V1\Data\UrlRewrite[]
126+
* @throws UrlAlreadyExistsException
127+
*/
128+
public function saveProductUrlRewrites(array $rewrites)
129+
{
130+
return $this->urlPersist->replace($rewrites);
131+
}
132+
106133
/**
107134
* Generate urls for specific store
108135
*
109136
* @param ProductInterface $product
110137
* @param int $storeId
111138
* @return array
112139
*/
113-
private function generateUrls(ProductInterface $product, int $storeId): array
140+
private function generateProductStoreUrls(ProductInterface $product, int $storeId): array
114141
{
115142
$storeData = $this->getDataByStore->execute($product, $storeId);
116143
$origStoreId = $product->getStoreId();

app/code/Magento/UrlRewrite/Controller/Adminhtml/Url/Rewrite/Save.php

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ class Save extends \Magento\UrlRewrite\Controller\Adminhtml\Url\Rewrite implemen
4747
*/
4848
protected AppendUrlRewritesToProducts $productAppendRewrites;
4949

50+
/**
51+
* @var array
52+
*/
53+
protected array $missingRewrites = [];
54+
5055
/**
5156
* @param Context $context
5257
* @param ProductUrlPathGenerator $productUrlPathGenerator
@@ -61,7 +66,7 @@ public function __construct(
6166
\Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $categoryUrlPathGenerator,
6267
\Magento\CmsUrlRewrite\Model\CmsPageUrlPathGenerator $cmsPageUrlPathGenerator,
6368
UrlFinderInterface $urlFinder,
64-
AppendUrlRewritesToProducts $productAppendRewrites = null
69+
?AppendUrlRewritesToProducts $productAppendRewrites = null
6570
) {
6671
parent::__construct($context);
6772
$this->productUrlPathGenerator = $productUrlPathGenerator;
@@ -91,58 +96,57 @@ protected function _handleCatalogUrlRewrite($model)
9196
$model->setMetadata(['category_id' => $categoryId]);
9297
}
9398
}
94-
$model->setTargetPath($this->generateTargetPath($model));
99+
$this->generateTargetPath($model);
95100
}
96101
}
97102

98103
/**
99104
* Generate Target Path
100105
*
101106
* @param \Magento\UrlRewrite\Model\UrlRewrite $model
102-
* @return string
103107
* @throws \Magento\Framework\Exception\LocalizedException
104108
*/
105109
protected function generateTargetPath($model)
106110
{
107111
$targetPath = $this->getCanonicalTargetPath();
108112
if ($model->getRedirectType() && !$model->getIsAutogenerated()) {
109-
$data = [
113+
if ($rewrite = $this->urlFinder->findOneByData([
110114
UrlRewrite::ENTITY_ID => $model->getEntityId(),
111115
UrlRewrite::TARGET_PATH => $targetPath,
112116
UrlRewrite::ENTITY_TYPE => $model->getEntityType(),
113-
UrlRewrite::STORE_ID => $model->getStoreId(),
114-
];
115-
$rewrite = $this->urlFinder->findOneByData($data);
116-
if (!$rewrite) {
117+
UrlRewrite::STORE_ID => $model->getStoreId()
118+
])) {
119+
$targetPath = $rewrite->getRequestPath();
120+
} else {
117121
if ($model->getEntityType() === self::ENTITY_TYPE_PRODUCT) {
118-
$this->productAppendRewrites->execute(
119-
[$this->_getProduct()],
122+
$productRewrites = $this->productAppendRewrites->getProductUrlRewrites(
123+
$this->_getProduct(),
120124
[$this->getRequest()->getParam('store_id', 0)]
121125
);
122-
$rewrite = $this->urlFinder->findOneByData($data);
123-
if (!$rewrite) {
126+
$productRewrites = array_merge(...$productRewrites);
127+
/** @var UrlRewrite $rewrite */
128+
foreach ($productRewrites as $rewrite) {
129+
if ($rewrite->getTargetPath() == $model->getTargetPath()) {
130+
$targetPath = $rewrite->getRequestPath();
131+
} else {
132+
$this->missingRewrites[] = $rewrite;
133+
}
134+
}
135+
if (!$targetPath) {
124136
throw new LocalizedException(
125137
__(
126138
"The selected product isn't associated with the selected store or category."
127139
)
128140
);
129141
}
130-
$targetPath = $rewrite->getRequestPath();
131-
if ($rewrite->getRequestPath() == $model->getRequestPath() &&
132-
$rewrite->getStoreId() == $model->getStoreId()) {
133-
$obsoleteRewrite = $this->_objectManager->create(\Magento\UrlRewrite\Model\UrlRewrite::class);
134-
$obsoleteRewrite->load($rewrite->getUrlRewriteId());
135-
$obsoleteRewrite->delete();
136-
}
137142
} else {
138143
throw new
139144
LocalizedException(__("The selected category isn't associated with the selected store."));
140145
}
141-
} else {
142-
$targetPath = $rewrite->getRequestPath();
143146
}
144147
}
145-
return $targetPath;
148+
149+
$model->setTargetPath($targetPath);
146150
}
147151

148152
/**
@@ -207,10 +211,12 @@ public function execute()
207211
->setStoreId($this->getRequest()->getParam('store_id', 0))
208212
->setDescription($this->getRequest()->getParam('description'));
209213

210-
$this->_handleCatalogUrlRewrite($model);
211214
$this->_handleCmsPageUrlRewrite($model);
215+
$this->_handleCatalogUrlRewrite($model);
212216
$model->save();
213-
217+
if (!empty($this->missingRewrites)) {
218+
$this->productAppendRewrites->saveProductUrlRewrites($this->missingRewrites);
219+
}
214220
$this->messageManager->addSuccess(__('The URL Rewrite has been saved.'));
215221
$this->_redirect('adminhtml/*/');
216222
return;

0 commit comments

Comments
 (0)