Skip to content

Commit 48b0ab8

Browse files
committed
#21737 Duplicating product with translated url keys over multiple storeviews causes non-unique url keys to be generated
1 parent 62ae101 commit 48b0ab8

File tree

1 file changed

+68
-15
lines changed

1 file changed

+68
-15
lines changed

app/code/Magento/Catalog/Model/Product/Copier.php

Lines changed: 68 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -74,22 +74,9 @@ public function copy(Product $product)
7474
$duplicate->setUpdatedAt(null);
7575
$duplicate->setId(null);
7676
$duplicate->setStoreId(\Magento\Store\Model\Store::DEFAULT_STORE_ID);
77-
7877
$this->copyConstructor->build($product, $duplicate);
79-
$isDuplicateSaved = false;
80-
do {
81-
$urlKey = $duplicate->getUrlKey();
82-
$urlKey = preg_match('/(.*)-(\d+)$/', $urlKey, $matches)
83-
? $matches[1] . '-' . ($matches[2] + 1)
84-
: $urlKey . '-1';
85-
$duplicate->setUrlKey($urlKey);
86-
$duplicate->setData('url_path', null);
87-
try {
88-
$duplicate->save();
89-
$isDuplicateSaved = true;
90-
} catch (\Magento\Framework\Exception\AlreadyExistsException $e) {
91-
}
92-
} while (!$isDuplicateSaved);
78+
$this->setDefaultUrl($product, $duplicate);
79+
$this->setStoresUrl($product, $duplicate);
9380
$this->getOptionRepository()->duplicate($product, $duplicate);
9481
$product->getResource()->duplicate(
9582
$product->getData($metadata->getLinkField()),
@@ -98,6 +85,72 @@ public function copy(Product $product)
9885
return $duplicate;
9986
}
10087

88+
/**
89+
* Set default URL.
90+
*
91+
* @param Product $product
92+
* @param Product $duplicate
93+
* @return void
94+
*/
95+
private function setDefaultUrl(Product $product, Product $duplicate) : void
96+
{
97+
$duplicate->setStoreId(\Magento\Store\Model\Store::DEFAULT_STORE_ID);
98+
$resource = $product->getResource();
99+
$attribute = $resource->getAttribute('url_key');
100+
$productId = $product->getId();
101+
$urlKey = $resource->getAttributeRawValue($productId, 'url_key', \Magento\Store\Model\Store::DEFAULT_STORE_ID);
102+
do {
103+
$urlKey = $this->modifyUrl($urlKey);
104+
$duplicate->setUrlKey($urlKey);
105+
} while (!$attribute->getEntity()->checkAttributeUniqueValue($attribute, $duplicate));
106+
$duplicate->setData('url_path', null);
107+
$duplicate->save();
108+
}
109+
110+
/**
111+
* Set URL for each store.
112+
*
113+
* @param Product $product
114+
* @param Product $duplicate
115+
* @return void
116+
*/
117+
private function setStoresUrl(Product $product, Product $duplicate) : void
118+
{
119+
$storeIds = $duplicate->getStoreIds();
120+
$resource = $product->getResource();
121+
$productId = $product->getId();
122+
$duplicate->setData('save_rewrites_history', false);
123+
foreach ($storeIds as $storeId) {
124+
$isDuplicateSaved = false;
125+
$duplicate->setStoreId($storeId);
126+
$urlKey = $resource->getAttributeRawValue($productId, 'url_key', $storeId);
127+
do {
128+
$urlKey = $this->modifyUrl($urlKey);
129+
$duplicate->setUrlKey($urlKey);
130+
$duplicate->setData('url_path', null);
131+
try {
132+
$duplicate->save();
133+
$isDuplicateSaved = true;
134+
} catch (\Magento\Framework\Exception\AlreadyExistsException $e) {
135+
}
136+
} while (!$isDuplicateSaved);
137+
}
138+
$duplicate->setStoreId(\Magento\Store\Model\Store::DEFAULT_STORE_ID);
139+
}
140+
141+
/**
142+
* Modify URL key.
143+
*
144+
* @param string $urlKey
145+
* @return string
146+
*/
147+
private function modifyUrl(string $urlKey) : string
148+
{
149+
return preg_match('/(.*)-(\d+)$/', $urlKey, $matches)
150+
? $matches[1] . '-' . ($matches[2] + 1)
151+
: $urlKey . '-1';
152+
}
153+
101154
/**
102155
* Returns product option repository.
103156
*

0 commit comments

Comments
 (0)