Skip to content

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

Merged
merged 2 commits into from
Dec 12, 2020

Conversation

engcom-Golf
Copy link
Contributor

Description (*)

Fixes URL rewrite delete/generation on website remove/assign

Related Pull Requests

Fixed Issues (if relevant)

  1. Fixes Product URL Rewrites are not removed when product removed from website #24184

Manual testing scenarios (*)

  1. test URL rewrite generation/delete from admin
  2. test URL rewrite generation/delete by REST API requests (productRepository POST/PUT/DELETE)
  3. test URL rewrite generation/delete by mass update (corn should be enabled)
  4. test URL rewrite generation/delete through import

Questions or comments

Contribution checklist (*)

  • Pull request has a meaningful description of its purpose
  • All commits are accompanied by meaningful commit messages
  • All new or changed code is covered with unit/integration tests (if applicable)
  • All automated tests passed successfully (all builds are green)

@m2-assistant
Copy link

m2-assistant bot commented Dec 1, 2020

Hi @engcom-Golf. Thank you for your contribution
Here is some useful tips how you can test your changes using Magento test environment.
Add the comment under your pull request to deploy test or vanilla Magento instance:

  • @magento give me test instance - deploy test instance based on PR changes
  • @magento give me 2.4-develop instance - deploy vanilla Magento instance

❗ Automated tests can be triggered manually with an appropriate comment:

  • @magento run all tests - run or re-run all required tests against the PR changes
  • @magento run <test-build(s)> - run or re-run specific test build(s)
    For example: @magento run Unit Tests

<test-build(s)> is a comma-separated list of build names. Allowed build names are:

  1. Database Compare
  2. Functional Tests CE
  3. Functional Tests EE,
  4. Functional Tests B2B
  5. Integration Tests
  6. Magento Health Index
  7. Sample Data Tests CE
  8. Sample Data Tests EE
  9. Sample Data Tests B2B
  10. Static Tests
  11. Unit Tests
  12. WebAPI Tests

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.

⚠️ According to the Magento Contribution requirements, all Pull Requests must go through the Community Contributions Triage process. Community Contributions Triage is a public meeting.

🕙 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

@engcom-Golf
Copy link
Contributor Author

@magento run all tests

array_diff($product->getWebsiteIds(), $oldWebsiteIds)
);
}
$this->appendRewrites->execute([$product], $storesToAdd);
Copy link
Contributor

@engcom-Kilo engcom-Kilo Dec 2, 2020

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.

Copy link
Contributor Author

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

Copy link
Contributor

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.

Copy link
Contributor Author

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));
Copy link
Contributor

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.

Copy link
Contributor Author

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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove.

Copy link
Contributor Author

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
Copy link
Contributor

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?

Copy link
Contributor Author

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);
Copy link
Contributor

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.

Copy link
Contributor Author

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
Copy link
Contributor

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.

Copy link
Contributor Author

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
Copy link
Contributor

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.

Copy link
Contributor Author

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();
Copy link
Contributor

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

Copy link
Contributor Author

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 {
Copy link
Contributor

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.

Copy link
Contributor Author

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 {
Copy link
Contributor

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

@sidolov sidolov added Priority: P2 A defect with this priority could have functionality issues which are not to expectations. Severity: S2 Major restrictions or short-term circumventions are required until a fix is available. labels Dec 2, 2020
@engcom-Golf
Copy link
Contributor Author

@magento run all tests

* @param $websiteCode
* @return Website
*/
private function loadWebsiteByCode($websiteCode)
Copy link
Contributor

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.

Copy link
Contributor Author

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
Copy link
Contributor

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.

Copy link
Contributor Author

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);
Copy link
Contributor

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.

@engcom-Golf
Copy link
Contributor Author

@magento run all tests

@zakdma
Copy link
Contributor

zakdma commented Dec 3, 2020

@engcom-Golf
Copy link
Contributor Author

@magento run all tests

@magento-engcom-team
Copy link
Contributor

@zakdma the branch with code successfully imported intomagento-tsg/magento2ce repository. Branch name: imported-magento-magento2-31106.

@engcom-Golf
Copy link
Contributor Author

@magento run all tests

@zakdma
Copy link
Contributor

zakdma commented Dec 7, 2020

@magento-engcom-team
Copy link
Contributor

@zakdma, an error occurred during the Pull Request import.

@zakdma
Copy link
Contributor

zakdma commented Dec 7, 2020

@magento-engcom-team
Copy link
Contributor

@zakdma the branch with code successfully imported intomagento-tsg/magento2ce repository. Branch name: imported-magento-magento2-31106.

@engcom-Golf
Copy link
Contributor Author

@magento run all tests

@engcom-Golf
Copy link
Contributor Author

@magento run all tests

* @return void
* @throws \Magento\UrlRewrite\Model\Exception\UrlAlreadyExistsException
* @throws UrlAlreadyExistsException
Copy link
Contributor

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

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.

Copy link
Contributor

@zakdma zakdma Dec 8, 2020

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.

Copy link
Contributor Author

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());
Copy link
Contributor

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

Copy link
Contributor Author

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

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

@engcom-Golf engcom-Golf Dec 8, 2020

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
Copy link
Contributor

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

Copy link
Contributor Author

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');
Copy link
Contributor

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

Copy link
Contributor Author

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];
Copy link
Contributor

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

Copy link
Contributor Author

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

Copy link
Contributor

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

Copy link
Contributor Author

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(),
]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add comma

Copy link
Contributor Author

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(),
]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add comma

Copy link
Contributor Author

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(),
]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add comma

Copy link
Contributor Author

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(),
]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add comma

Copy link
Contributor Author

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(),
]
];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add comma

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

@engcom-Golf
Copy link
Contributor Author

@magento run all tests

*
* @param ProductInterface $product
*/
public function clearProductRewriteData(ProductInterface $product)
Copy link
Contributor

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];
Copy link
Contributor

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

@engcom-Golf
Copy link
Contributor Author

@magento run all tests

@zakdma
Copy link
Contributor

zakdma commented Dec 10, 2020

@magento-engcom-team
Copy link
Contributor

@zakdma the branch with code successfully imported intomagento-tsg/magento2ce repository. Branch name: imported-magento-magento2-31106.

@zakdma
Copy link
Contributor

zakdma commented Dec 10, 2020

@magento-engcom-team
Copy link
Contributor

@zakdma the branch with code successfully imported intomagento-tsg/magento2ce repository. Branch name: imported-magento-magento2-31106.

@magento-engcom-team magento-engcom-team merged commit a41bd02 into magento:2.4-develop Dec 12, 2020
@m2-assistant
Copy link

m2-assistant bot commented Dec 12, 2020

Hi @engcom-Golf, thank you for your contribution!
Please, complete Contribution Survey, it will take less than a minute.
Your feedback will help us to improve contribution process.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: Catalog Component: CatalogUrlRewrite Priority: P2 A defect with this priority could have functionality issues which are not to expectations. Progress: review Release Line: 2.4 Severity: S2 Major restrictions or short-term circumventions are required until a fix is available.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Product URL Rewrites are not removed when product removed from website
5 participants