-
Notifications
You must be signed in to change notification settings - Fork 9.4k
MC-38931: Product URL Rewrites are not removed when product removed from website #31106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MC-38931: Product URL Rewrites are not removed when product removed from website #31106
Conversation
Hi @engcom-Golf. Thank you for your contribution
❗ Automated tests can be triggered manually with an appropriate comment:
You can find more information about the builds here ℹ️ Please run only needed test builds instead of all when developing. Please run all test builds before sending your PR for review. For more details, please, review the Magento Contributor Guide documentation. 🕙 You can find the schedule on the Magento Community Calendar page. 📞 The triage of Pull Requests happens in the queue order. If you want to speed up the delivery of your contribution, please join the Community Contributions Triage session to discuss the appropriate ticket. 🎥 You can find the recording of the previous Community Contributions Triage on the Magento Youtube Channel ✏️ Feel free to post questions/proposals/feedback related to the Community Contributions Triage process to the corresponding Slack Channel |
@magento run all tests |
array_diff($product->getWebsiteIds(), $oldWebsiteIds) | ||
); | ||
} | ||
$this->appendRewrites->execute([$product], $storesToAdd); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$this->appendRewrites->execute() may throw UrlAlreadyExistsException. Please make sure it will be processed or process it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't need to handle this exception. This is expected behavior in case when admin tries to save a product with url-key that already assigned to another item either product or category. See \Magento\CatalogUrlRewrite\Model\ProductUrlRewriteTest::testUrlRewriteOnProductSaveWithExistingUrlKey
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case please add exception to annotaions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added
} | ||
} | ||
if (!empty($urls)) { | ||
$this->urlPersist->replace(array_merge(...$urls)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$this->urlPersist->replace() may throw UrlAlreadyExistsException. Please add it to annotations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case, if an exception is thrown in a sub-routine, then @throws must not be used in the parent method.
https://devdocs.magento.com/guides/v2.4/coding-standards/docblock-standard-general.html
private $dataLocator; | ||
|
||
/** | ||
* AppendUrlRewritesToProducts constructor. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed
use Magento\UrlRewrite\Model\UrlPersistInterface; | ||
|
||
/** | ||
* Update url rewrites to products class |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bit confusing description and class name. Could you please add more clear description and/or class name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated
} | ||
} | ||
|
||
return array_merge([], ...$storeIdsArray); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add result to local cache. This method already used twice during observer execution.
Also it would be better to use $product instead on $websiteIds as parameter to avoid code duplication.
Lines
$oldWebsiteIds = $product->getOrigData('website_ids') ?? []
$websiteIds = array_diff($oldWebsiteIds, $product->getWebsiteIds())
could be moved in this method. Rename method to more appropriate one after this changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is no code duplication, as we use the different order of sub-arrays to compare and getting result of website ids. A cache can be added but in the current implementation, it won't give any result of performance improvement. Don't see a possibility to add and delete the same website at the same time.
/** | ||
* Update URL rewrites after website change | ||
*/ | ||
class ProductToWebsiteChange |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Plugin name is confusing. Please change it to url rewrite related.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
renamed
* @magentoDataFixture Magento/Catalog/_files/category_product.php | ||
* @magentoDataFixture Magento/UrlRewrite/_files/url_rewrite.php |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this file could be reverted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case, changing the order of fixture loading have sense, as product save generates rewrites for all assigned websites. Then can not be checked logic of redirect from unexisting rewrite to home page.
*/ | ||
protected function setUp(): void | ||
{ | ||
parent::setUp(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to call parent construct
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed
private function loadWebsiteByCode($websiteCode) | ||
{ | ||
$websiteRepository = Bootstrap::getObjectManager()->get(WebsiteRepository::class); | ||
try { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to wrap it in try-catch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed
*/ | ||
private function getProductModel(string $sku, int $storeId = null): ProductInterface | ||
{ | ||
try { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to wrap it in try-catch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed
@magento run all tests |
* @param $websiteCode | ||
* @return Website | ||
*/ | ||
private function loadWebsiteByCode($websiteCode) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to extract couple code lines into separate method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
* @param int|null $storeId | ||
* @return ProductInterface | ||
*/ | ||
private function getProductModel(string $sku, int $storeId = null): ProductInterface |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to extract couple code lines into separate method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
array_diff($product->getWebsiteIds(), $oldWebsiteIds) | ||
); | ||
} | ||
$this->appendRewrites->execute([$product], $storesToAdd); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case please add exception to annotaions.
@magento run all tests |
@magento import code to https://github.com/magento-tsg/magento2ce |
@magento run all tests |
@zakdma the branch with code successfully imported into |
@magento run all tests |
@magento import code to https://github.com/magento-tsg/magento2ce |
@zakdma, an error occurred during the Pull Request import. |
@magento import code to https://github.com/magento-tsg/magento2ce |
@zakdma the branch with code successfully imported into |
@magento run all tests |
@magento run all tests |
* @return void | ||
* @throws \Magento\UrlRewrite\Model\Exception\UrlAlreadyExistsException | ||
* @throws UrlAlreadyExistsException |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should not add Exception to annotation if your method does not throw exception directly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@engcom-Golf please refer to docblock magento standards
https://devdocs.magento.com/guides/v2.3/coding-standards/docblock-standard-general.html#functions-methods
A declaration of possible exceptions using the @throws tag, if the actual body of function triggers an exception.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@engcom-Golf please refer to docblock magento standards
https://devdocs.magento.com/guides/v2.3/coding-standards/docblock-standard-general.html#functions-methods
A declaration of possible exceptions using the @throws tag, IF THE ACTUAL BODY OF FUNCTION TRIGGERS AN EXCEPTION.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some kind of collision, but I'd like to not hide the possible exception throwing. This was required by @engcom-Kilo review as well.
#31106 (comment)
{ | ||
$oldWebsiteIds = $product->getOrigData('website_ids'); | ||
|
||
return array_values($oldWebsiteIds) != array_values($product->getWebsiteIds()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This array comparison is unreliable. Better use array_diff instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
array_diff returns empty result in case if new websites added
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and what about this case
http://sandbox.onlinephpfunctions.com/code/c2007754d416a55aea54a6630a990b984cb08c6d
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added check both variants with array diff
* @param array $websiteIds | ||
* @return array | ||
*/ | ||
private function getStoresListByWebsiteIds(array $websiteIds): array |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you move this code in separate class since you use it also in UpdateProductWebsiteUrlRewrites
Store module should be right place for it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
*/ | ||
private function isRewriteUseCategoryPath(): bool | ||
{ | ||
return $this->scopeConfig->isSetFlag('catalog/seo/product_use_categories'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like you check flag for default scope but not for particular scope
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wrong configuration was taken, changed to Generate "category/product" URL Rewrites global config instead
{ | ||
$productId = $product->getId(); | ||
if (isset($this->urlRewriteData[$productId][$storeId])) { | ||
return $this->urlRewriteData[$productId][$storeId]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its a little bit dangerous to have cache here. You should at least have method to reset cache and do it after rewrites changed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added clearing of local cache by product after generation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please name it clearProductUrlRewriteDataCache to clarify that we clear exactly cache, not url rewrite data itself
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
'is_auto_generated' => 1, | ||
'redirect_type' => 0, | ||
'store_id' => $testStore4->getId(), | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add comma
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added
'is_auto_generated' => 1, | ||
'redirect_type' => 0, | ||
'store_id' => $testStore4->getId(), | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add comma
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added
'is_auto_generated' => 1, | ||
'redirect_type' => 0, | ||
'store_id' => $testStore1->getId(), | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add comma
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added
'is_auto_generated' => 1, | ||
'redirect_type' => 0, | ||
'store_id' => $testStore3->getId(), | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add comma
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added
'redirect_type' => 0, | ||
'store_id' => $testStore4->getId(), | ||
] | ||
]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add comma
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added
@magento run all tests |
* | ||
* @param ProductInterface $product | ||
*/ | ||
public function clearProductRewriteData(ProductInterface $product) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please name it clearProductUrlRewriteDataCache to clarify that we clear exactly cache, not url rewrite data itself
{ | ||
$productId = $product->getId(); | ||
if (isset($this->urlRewriteData[$productId][$storeId])) { | ||
return $this->urlRewriteData[$productId][$storeId]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please name it clearProductUrlRewriteDataCache to clarify that we clear exactly cache, not url rewrite data itself
@magento run all tests |
@magento import code to https://github.com/magento-tsg/magento2ce |
@zakdma the branch with code successfully imported into |
2195e72
to
a08e303
Compare
e31e93e
to
d30fd1f
Compare
@magento import code to https://github.com/magento-tsg/magento2ce |
@zakdma the branch with code successfully imported into |
Hi @engcom-Golf, thank you for your contribution! |
Description (*)
Fixes URL rewrite delete/generation on website remove/assign
Related Pull Requests
Fixed Issues (if relevant)
Manual testing scenarios (*)
Questions or comments
Contribution checklist (*)