Skip to content

Do not trigger url rewrites re-generation for all store views #32808

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
Oct 28, 2021

Conversation

ihor-sviziev
Copy link
Contributor

@ihor-sviziev ihor-sviziev commented Apr 21, 2021

Description (*)

During creating a new website, Store Group and Store view using php bin/magento setup:upgrade - we noticed that some URL rewrites for categories on different stores were re-generated in DB, that's absolutely not obvious and for sure not expected behavior. Such behavior, especially for us changed URLs for some categories w/o creating any redirect from old -> new URL (for some reason, we had incorrect url_path values in DB, that's another story).
As a result of this issue - some advertised categories started returning 404 pages, and we basically started burning our money.

Root cause analyze

Investigation showed, that app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/Group.php plugin was executed due to 2 step saving of group:

  • at first, we just creating a new group
  • later we're assigning it to a website
    private function createGroups(array $items, array $data)
    {
    foreach ($items as $groupData) {
    $websiteId = $groupData['website_id'];
    unset(
    $groupData['group_id'],
    $groupData['website_id']
    );
    $website = $this->detectWebsiteById(
    $data,
    $websiteId
    );
    $group = $this->groupFactory->create();
    if (!isset($groupData['root_category_id'])) {
    $groupData['root_category_id'] = 0;
    }
    $group->setData($groupData);
    $group->getResource()->save($group);
    $group->getResource()->addCommitCallback(function () use ($data, $group, $website) {
    $store = $this->detectStoreById($data, (int)$group->getDefaultStoreId());
    $group->setDefaultStoreId($store->getStoreId());
    $group->setWebsite($website);
    $group->getResource()->save($group);
    });
    }
    }

As a store group still don't have any store IDs assigned (the store will be created on the next step) - $group->getStoreIds() returns an empty array, we're setting this value to the category and trying to generate URL rewrites

$category->setStoreId(Store::DEFAULT_STORE_ID);
$category->setStoreIds($storeIds);
$urls[] = $this->categoryUrlRewriteGenerator->generate($category);

Then it goes to this method, which tries to fetch a list of store Ids:

/**
* Generate list of urls for global scope
*
* @param \Magento\Catalog\Model\Category|null $category
* @param bool $overrideStoreUrls
* @param int|null $rootCategoryId
* @return \Magento\UrlRewrite\Service\V1\Data\UrlRewrite[]
*/
protected function generateForGlobalScope(
Category $category = null,
$overrideStoreUrls = false,
$rootCategoryId = null
) {
$mergeDataProvider = clone $this->mergeDataProviderPrototype;
$categoryId = $category->getId();
foreach ($category->getStoreIds() as $storeId) {
if (!$this->isGlobalScope($storeId)
&& $this->isOverrideUrlsForStore($storeId, $categoryId, $overrideStoreUrls)
) {
$category = clone $category; // prevent undesired side effects on original object
$category->setStoreId($storeId);
$this->updateCategoryUrlForStore($storeId, $category);
$mergeDataProvider->merge($this->generateForSpecificStoreView($storeId, $category, $rootCategoryId));
}
}
$result = $mergeDataProvider->getData();
return $result;
}

Here we don't have any saved store_ids, so it fetches the list of stores where this category used as a root.

public function getStoreIds()
{
if ($this->getInitialSetupFlag()) {
return [];
}
$storeIds = $this->getData('store_ids');
if ($storeIds) {
return $storeIds;
}
if (!$this->getId()) {
return [];
}
$nodes = [];
foreach ($this->getPathIds() as $id) {
$nodes[] = $id;
}
$storeIds = [];
$storeCollection = $this->_storeCollectionFactory->create()->loadByCategoryIds($nodes);
foreach ($storeCollection as $store) {
$storeIds[$store->getId()] = $store->getId();
}
$entityStoreId = $this->getStoreId();
if (!in_array($entityStoreId, $storeIds)) {
array_unshift($storeIds, $entityStoreId);
}
if (!in_array(0, $storeIds)) {
array_unshift($storeIds, 0);
}
$this->setData('store_ids', $storeIds);
return $storeIds;
}

As a result - we're re-generating category URL rewrites for all store views with the same root category ID.

Related Pull Requests

Fixed Issues (if relevant)

  1. Fixes magento/magento2#<issue_number>

Manual testing scenarios (*)

  1. Install magento, so you'll have 1 website, 1 store group, 1 store view
  2. Create some categories structure
  3. Run php bin/magento app:config:dump scopes to dump all the stores data into the config.php
  4. Create a DB dump
  5. Go to Admin, and create a new website, store group and a store view (re-use the same root category for that)
  6. Run php bin/magento app:config:dump scopes to dump all the stores data into the config.php, save the file
  7. Apply the DB dump from the step 4 in order to emulate the case, when we didn't have 2nd website, store group, etc
  8. Run php bin/magento setup:upgrade or php bin/magento app:config:import to create a new website, store group, store view
  9. Compare data in the url_rewrites table with a backup file for the store 1.

Expected result:
✔ URL rewrites for store 1 shouldn't be touched when we creating a new website / store group / store view

Actual result:
❌ URL rewrites for store 1 are re-generated when we creating a new website / store group / store view

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)
  • README.md files for modified modules are updated and included in the pull request if any README.md predefined sections require an update
  • All automated tests passed successfully (all builds are green)

Resolved issues:

  1. resolves [Issue] Do not trigger url rewrites re-generation for all store views #32954: Do not trigger url rewrites re-generation for all store views

@m2-assistant
Copy link

m2-assistant bot commented Apr 21, 2021

Hi @ihor-sviziev. Thank you for your contribution
Here are 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
  13. Semantic Version Checker

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

@ihor-sviziev
Copy link
Contributor Author

@magento run all tests

@ihor-sviziev ihor-sviziev added the Severity: S1 Affects critical data or functionality and forces users to employ a workaround. label Apr 21, 2021
@ihor-sviziev
Copy link
Contributor Author

@magento run Functional Tests EE, WebAPI Tests

@gabrieldagama
Copy link
Contributor

Hi @ihor-sviziev, thanks for contributing! Can you provide more details on the impact of this fix? Thanks!

@ihor-sviziev
Copy link
Contributor Author

@magento run all tests

@ihor-sviziev
Copy link
Contributor Author

Hi @gabrieldagama,
I updated the PR description

@ihor-sviziev ihor-sviziev marked this pull request as ready for review April 23, 2021 23:27
@ihor-sviziev
Copy link
Contributor Author

@magento run Functional Tests B2B

@magento-automated-testing
Copy link

No builds to run for your request.

@ihor-sviziev
Copy link
Contributor Author

@magento run Functional Tests B2B

@magento-automated-testing
Copy link

No builds to run for your request.

@gabrieldagama
Copy link
Contributor

@magento run Functional Tests B2B

@magento-automated-testing
Copy link

The requested builds are added to the queue. You should be able to see them here within a few minutes. Please re-request them if they don't show in a reasonable amount of time.

@gabrieldagama gabrieldagama added the Priority: P2 A defect with this priority could have functionality issues which are not to expectations. label Apr 29, 2021
@Den4ik
Copy link
Contributor

Den4ik commented May 5, 2021

@magento create issue

@Den4ik
Copy link
Contributor

Den4ik commented May 5, 2021

@ihor-sviziev Thanks for collaboration and detailed description.
Do we really need save group 2 times at https://github.com/magento/magento2/blob/2.4-develop/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php#L187-L193 ?

@ihor-sviziev
Copy link
Contributor Author

@Den4ik, in theory, we might change it, but I don't know why it was done in this way and wonder if it would cause some regression. Also, potentially, there might be similar code in some other piece or custom extension with the same behavior. My current changes fix all cases at once, so should cover all cases

@Den4ik
Copy link
Contributor

Den4ik commented May 6, 2021

@ihor-sviziev May be we could little bit research and if it's possible reduce count of save calls that will have a positive effect on performance?

@ihor-sviziev
Copy link
Contributor Author

@Den4ik, in general, it's a good idea to do such research and get rid of such pieces. But in the case of fixing this issue - that's not relevant - I won't break any functionality.

Copy link
Contributor

@Den4ik Den4ik left a comment

Choose a reason for hiding this comment

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

✔️ Approve. All looks good for me.
As we discussed in Slack research should be done as separate work.

@magento-engcom-team
Copy link
Contributor

Hi @Den4ik, thank you for the review.
ENGCOM-9074 has been created to process this Pull Request
✳️ @Den4ik, could you please add one of the following labels to the Pull Request?

Label Description
Auto-Tests: Covered All changes in Pull Request is covered by auto-tests
Auto-Tests: Not Covered Changes in Pull Request requires coverage by auto-tests
Auto-Tests: Not Required Changes in Pull Request does not require coverage by auto-tests

@Den4ik Den4ik added the Auto-Tests: Covered All changes in Pull Request is covered by auto-tests label May 6, 2021
@engcom-Alfa engcom-Alfa self-assigned this Sep 16, 2021
@engcom-Alfa
Copy link
Contributor

Hi @ihor-sviziev , @Den4ik
Thanks for the collaboration & contribution!

❌ QA not Passed

URL Re-Write regenerates for all the store views

Execution steps followed as below

  1. Installed a Magento freshly having PR changes, so by default l have 1 website, 1 store group, 1 store view.
  2. Created a 3 categories inside default category and one product for better analysis. Noted the below URL Re Writes table and the data of the table is below:
<style> </style>
ID Store View Request Path Target Path Redirect Type
1 Main Website  Main Website Store  Default Store View no-route cms/page/view/page_id/1 No
2 Main Website  Main Website Store  Default Store View home cms/page/view/page_id/2 No
3 Main Website  Main Website Store  Default Store View enable-cookies cms/page/view/page_id/3 No
4 Main Website  Main Website Store  Default Store View privacy-policy-cookie-restriction-mode cms/page/view/page_id/4 No
5 Main Website  Main Website Store  Default Store View mks1.html catalog/category/view/id/3 No
6 Main Website  Main Website Store  Default Store View mks1/mks2.html catalog/category/view/id/4 No
7 Main Website  Main Website Store  Default Store View mks1/mks3.html catalog/category/view/id/5 No
8 Main Website  Main Website Store  Default Store View mksprod1.html catalog/product/view/id/1 No
9 Main Website  Main Website Store  Default Store View mks1/mks3/mksprod1.html catalog/product/view/id/1/category/5 No
10 Main Website  Main Website Store  Default Store View mks1/mksprod1.html catalog/product/view/id/1/category/3 No
  1. Ran the command php bin/magento app:config:dump scopes

  2. Created a DB dump

  3. Created a new store with new website and store view, setting the same default category. Checked the new store domain is able to open in the front end as shown in the below screenshot.
    image
    Where the default main store had the domain with the url local.prurlrewriteafter.com, and now the additional store is with local.prurlrewriteafter.fr. Both stores front end are working fine.

  4. Noted the updated URL Re Write table again and the relevant table data is below

<style> </style>
ID Store View Request Path Target Path Redirect Type
1 Main Website  Main Website Store  Default Store View no-route cms/page/view/page_id/1 No
2 Main Website  Main Website Store  Default Store View home cms/page/view/page_id/2 No
3 Main Website  Main Website Store  Default Store View enable-cookies cms/page/view/page_id/3 No
4 Main Website  Main Website Store  Default Store View privacy-policy-cookie-restriction-mode cms/page/view/page_id/4 No
5 Main Website  Main Website Store  Default Store View mks1.html catalog/category/view/id/3 No
6 Main Website  Main Website Store  Default Store View mks1/mks2.html catalog/category/view/id/4 No
7 Main Website  Main Website Store  Default Store View mks1/mks3.html catalog/category/view/id/5 No
8 Main Website  Main Website Store  Default Store View mksprod1.html catalog/product/view/id/1 No
9 Main Website  Main Website Store  Default Store View mks1/mks3/mksprod1.html catalog/product/view/id/1/category/5 No
10 Main Website  Main Website Store  Default Store View mks1/mksprod1.html catalog/product/view/id/1/category/3 No
11 FrenchWebsite  FrenchStore  FrenchStoreView mks1.html catalog/category/view/id/3 No
12 FrenchWebsite  FrenchStore  FrenchStoreView mks1/mks2.html catalog/category/view/id/4 No
13 FrenchWebsite  FrenchStore  FrenchStoreView mks1/mks3.html catalog/category/view/id/5 No
14 FrenchWebsite  FrenchStore  FrenchStoreView no-route cms/page/view/page_id/1 No
15 FrenchWebsite  FrenchStore  FrenchStoreView home cms/page/view/page_id/2 No
16 FrenchWebsite  FrenchStore  FrenchStoreView enable-cookies cms/page/view/page_id/3 No
17 FrenchWebsite  FrenchStore  FrenchStoreView privacy-policy-cookie-restriction-mode cms/page/view/page_id/4 No
  1. Ran php bin/magento app:config:dump scopes
  2. Applied the DB dump back to Magento instance from the step 4.
  3. Ran php bin/magento setup:upgrade and followed by static deploy and re indexed as well.
  4. Noted the updated URL Re Write table again and the relevant table data is below
<style> </style>
ID Store View Request Path Target Path Redirect Type
1 Main Website  Main Website Store  Default Store View no-route cms/page/view/page_id/1 No
2 Main Website  Main Website Store  Default Store View home cms/page/view/page_id/2 No
3 Main Website  Main Website Store  Default Store View enable-cookies cms/page/view/page_id/3 No
4 Main Website  Main Website Store  Default Store View privacy-policy-cookie-restriction-mode cms/page/view/page_id/4 No
8 Main Website  Main Website Store  Default Store View mksprod1.html catalog/product/view/id/1 No
9 Main Website  Main Website Store  Default Store View mks1/mks3/mksprod1.html catalog/product/view/id/1/category/5 No
10 Main Website  Main Website Store  Default Store View mks1/mksprod1.html catalog/product/view/id/1/category/3 No
15 Main Website  Main Website Store  Default Store View mks1.html catalog/category/view/id/3 No
16 Main Website  Main Website Store  Default Store View mks1/mks2.html catalog/category/view/id/4 No
17 Main Website  Main Website Store  Default Store View mks1/mks3.html catalog/category/view/id/5 No
21 FrenchWebsite  FrenchStore  FrenchStoreView mks1.html catalog/category/view/id/3 No
22 FrenchWebsite  FrenchStore  FrenchStoreView mks1/mks2.html catalog/category/view/id/4 No
23 FrenchWebsite  FrenchStore  FrenchStoreView mks1/mks3.html catalog/category/view/id/5 No
24 FrenchWebsite  FrenchStore  FrenchStoreView no-route cms/page/view/page_id/1 No
25 FrenchWebsite  FrenchStore  FrenchStoreView home cms/page/view/page_id/2 No
26 FrenchWebsite  FrenchStore  FrenchStoreView enable-cookies cms/page/view/page_id/3 No
27 FrenchWebsite  FrenchStore  FrenchStoreView privacy-policy-cookie-restriction-mode cms/page/view/page_id/4 No

✔️ Expected result After Fix

  • Along with the default store's front end, the newly created front end should also work fine!
  • The URL Rewrite data should not be re generated

❌ Actual result After Fix

  • If we hit the store's front end domain, redirecting to main default store domain.
  • URL Rewrite data updated with newly generated record IDs.

Copy link
Contributor

@engcom-Alfa engcom-Alfa left a comment

Choose a reason for hiding this comment

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

Based on the above comment, moving it back to to Request Changes

@engcom-Charlie
Copy link
Contributor

Hi @ihor-sviziev,

Thank you for your contribution!

I am trying to understand and reproduce this issue on my local. Followed below steps but I am getting the same results on 2.4 develop and PR branch.

  1. Setup fresh magento instance
  2. Added 2 new sub categories under Default Category. Created 2 products under one sub category and 1 in other. Eg.(Electronics and Cloths are sub categories and lamp, geyser are products under Electronics and t-shirt product is under cloths)
  3. Checked url_rewrite table: total 12 records were present.
  4. Execute php bin/magento app:config:dump scopes command
  5. Took Db dump at this stage
  6. Added one website, store and view against default category
  7. Checked the url_rewrite table again. Now total 18 records were present
  8. Executed php bin/magento app:config:dump scopes again
  9. Applied the DB dump back to Magento instance from the step 5.
  10. Executed php bin/magento setup:upgrade, At this, it asked about “do you want to continue with creating the website” of step 7 , I have opted for Yes option
  11. Tried to browse the site again, its accessible and checked url_rewrite table again. Its having 18 records
  12. Executed php bin/magento app:config:import cmd : Got nothing to import message here

On both the branches ie. on 2.4 develop and on this PR branch, url_rewrite_ids of few records are getting changed after step 9 on, so can you please confirm once and give us some more information on this.

Thank you in advance!

@ihor-sviziev
Copy link
Contributor Author

ihor-sviziev commented Oct 11, 2021 via email

@engcom-Charlie
Copy link
Contributor

Hi @ihor-sviziev, Thanks for the information over slack.

@engcom-Alfa, I have tried to reproduce the issue on 2.4 develop with below steps. Some URL rewrites for categories on  stores were re-generated in DB and hence issue is reproducible.

1.	Setup fresh magento instance
2.	Added 2 new sub categories under Default Category. Created 2 products under one sub category and 1 in other. Eg.(Electronics and Cloths are sub categories and lamp, geyser are products under Electronics and t-shirt product is under cloths)
3.	Added 2 websites, 2 stores and 2 store views.
4.	Checked url_rewrite table: total 24 records were present.

image

5.	Execute php bin/magento app:config:dump scopes command
6.	Took Db dump at this stage
7.	Added one website(Spanish), store and view against default category
8.	Checked the url_rewrite table again. Now total 30 records were present

image

9.	Executed php bin/magento app:config:dump scopes again
10.	Applied the DB dump back to Magento instance from the step 6. 
11.	Executed php bin/magento setup:upgrade, At this, it asked about “do you want to continue with creating the website Spanish” of step 7 , I have opted for Yes option

image

12.	Checked url_rewrite table again. Its having 30 records. Here, check that the url_rewrite_ids of url rewrites were changed. You can see new ids for old records. This is the issue. 

image

After doing php bin/magento setup:upgrade, the URL rewrites for categories should not be re-generated in this scenario. As the issue exists on mainline so moving this PR further.

Thank you!

@engcom-Alfa
Copy link
Contributor

engcom-Alfa commented Oct 18, 2021

Hi @ihor-sviziev, Thanks for the information over slack.

@engcom-Alfa, I have tried to reproduce the issue on 2.4 develop with below steps. Some URL rewrites for categories on  stores were re-generated in DB and hence issue is reproducible.

1.	Setup fresh magento instance
2.	Added 2 new sub categories under Default Category. Created 2 products under one sub category and 1 in other. Eg.(Electronics and Cloths are sub categories and lamp, geyser are products under Electronics and t-shirt product is under cloths)
3.	Added 2 websites, 2 stores and 2 store views.
4.	Checked url_rewrite table: total 24 records were present.

image

5.	Execute php bin/magento app:config:dump scopes command
6.	Took Db dump at this stage
7.	Added one website(Spanish), store and view against default category
8.	Checked the url_rewrite table again. Now total 30 records were present

image

9.	Executed php bin/magento app:config:dump scopes again
10.	Applied the DB dump back to Magento instance from the step 6. 
11.	Executed php bin/magento setup:upgrade, At this, it asked about “do you want to continue with creating the website Spanish” of step 7 , I have opted for Yes option

image

12.	Checked url_rewrite table again. Its having 30 records. Here, check that the url_rewrite_ids of url rewrites were changed. You can see new ids for old records. This is the issue. 

image

After doing php bin/magento setup:upgrade, the URL rewrites for categories should not be re-generated in this scenario. As the issue exists on mainline so moving this PR further.

Thank you!

Hi @ihor-sviziev and @engcom-Charlie , Thanks for collaboration and coming back with proper steps to reproduce it! I am able to work on it now!

@engcom-Alfa
Copy link
Contributor

✔️ QA Passed

Manual testing scenario:

  1. Setup fresh Magento instance

  2. Add 2 new sub categories under Default Category. Create 2 products under one created sub category and 1 product in other.

  3. Added 2 websites, 2 stores and 2 store views. Make sure newly created both stores are working fine with their frontend website links.

  4. Check url_rewrite table in the database.

  5. Execute php bin/magento app:config:dump scopes command

  6. Take a DB dump at this stage

  7. Add one more new store website(Spanish), store and store view using default category, make sure it is also working

  8. Check the url_rewrite table in the DB again. Now total records count will be more (comparing step 4)! Make note of all records.

  9. Execute php bin/magento app:config:dump scopes again

  10. Apply the DB dump back to Magento instance from the step 6.

  11. Execute the php bin/magento setup:upgrade command, At this, it asks about “do you want to continue with creating the website Spanish” of step 7; opt for Yes.

  12. Check url_rewrite table again. Make note of all records.

  13. Compare url_rewrite_ids of url rewrite noted table records from step 8 and step12. (Using diff checker tools would give more clarity)

Before: ✖️ New url_rewrite_ids were getting generated to old records

image

After: ✔️ New url_rewrite_ids are not getting generated to old records, they are retained as it is!

image

It is a specific case were the DB dump is involved when we are having multi store views, and has no impact on other features, and hence no additional regression is required on this.

@m2-assistant
Copy link

m2-assistant bot commented Oct 28, 2021

Hi @ihor-sviziev, 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
Auto-Tests: Covered All changes in Pull Request is covered by auto-tests Award: bug fix Award: category of expertise Component: CatalogUrlRewrite Priority: P2 A defect with this priority could have functionality issues which are not to expectations. Progress: accept Release Line: 2.4 Severity: S1 Affects critical data or functionality and forces users to employ a workaround.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Issue] Do not trigger url rewrites re-generation for all store views
6 participants