Skip to content

REST API Product update url_key doesnt re-gerenate url_rewites (INSANE) #30316

Closed
@Seb2nim

Description

@Seb2nim

Summary

Updating product url_key via REST API ; Product Url Rewrites are not re-generated. (yeah, i know, thats crazy)

This occurs on actually "Simple" setup, out of the box : Single-store mode and calls on "all" Rest Endpoint {{magento_url}}/rest/all/V1/products/{{sku}}, elementary school level

I use the term "Url Rewrites" (with a "s") because that involves category-path-product-urls also. But i focus on product "direct" url

Preconditions

  1. Magento CE 2.3.4 - Single store mode
  2. Magento 2.4-develop
  3. Calls made on "all" : PUT {{magento_url}}/rest/all/V1/products/{{sku}}
    ⚠️ Note: 2.4-develop doesn't contain POST call for {{magento_url}}/rest/all/V1/products/{{sku}}
    image
  4. Stores->Configuration->General->Single-Store Mode->Enable Single-Store Mode=Yes

Steps to reproduce

  1. Given a standard product (simple product, dont try to overcomplicate things)
    • Said product has id=10 : entity_id=10
    • Current url_key="my-product-url" (In Admin Product View : Section "Search Engine Optimization")
  2. Check current Url_Rewrites in (Marketing / SEO & Search / Url Rewrites)
    • Search for target_path like catalog/product/view/id/10
    • Current url_rewrite should exist : "my-product-url.html" (i suppose ".html" as most used case prefix)
  3. REST PUT Update on product :
    Sorry, no time to write a one line curl call. If you read this, you're smart enough to use Postman and already have this call ready to go.
    • PUT {{magento_url}}/rest/all/V1/products/{{sku}}
    • Json pload :
{
  "product": {
    "custom_attributes": [
        {
            "attribute_code": "url_key",
            "value": "my-new-url"
        }
    ]
  }
}
  1. Check Url_key has been updated (In Admin Product View : Section "Search Engine Optimization")
    • Url_key is my-new-url (whaou)
  2. Check Url_Rewrites in (Marketing / SEO & Search / Url Rewrites)
    • Search for target_path like catalog/product/view/id/10(or update tab/search, as you want, take your time)
    • URL rewrites not updated

Expected result

  • URL Rewrites should have been updated

Actual result

  • URL Rewrites NOT updated

Additional info

  • There is absolutely NOTHING related to async, indexing, cache... No, thats really crazy : follow....
  • Url rewrites ARE generated on product CREATION, but NOT ON UPDATE
  • Passing websites_id on extension_attributes does not help (wait, it should, but wait...)
  • Calling update on "default" rest endpoint instead of "all" would work BUT : IT IS A REALLY BAD IDEA :
    You will not see "real value" for the store (1) in Admin product view (and NO way to see it in Single store mode)
    There is another BUG that leads to almost ALL attributes to be copied for store 1 scope, not JUST the one you updated and, sorry but that sucks. I will ckeck if issue is already reported and eventually post. But poor chance to get a fix on that.

Debugging

Actually deep debugged code and i think the issue is on Product Model getStoreIds() even if it HARD to admit on such a central class :
Line $websiteIds = array_keys($websiteIds); gets array_keys()... ???
Does not have much sense... : Website_ids being either an array from json OR retreived from DB : NO WAY that array_keys would be some website_ids !

Checked current 2.4 develop, still there : https://github.com/magento/magento2/blob/2.4-develop/app/code/Magento/Catalog/Model/Product.php#L832

Workaround / I would say "Hack"

To congratulate you for your patience reading me, i offer you this hack if you promise to have a good laugh :

The FACT is that the array_keys() "bug" CAN be used as a temporary workaround hack :
You can pass values so that there will be a key for the targeted website id.
If you pass twice (here) the website_id in extension attribute, you'll exploit the bug and pass => Will work.
Hopefully, these arrays are not "cleaned" by any interceptor before being in product data object... Not surprising.

I think you got what you have to do if you want to re-gen website id 4... LOL

{
  "product": {
    "custom_attributes": [
        {
            "attribute_code": "url_key",
            "value": "my-url-key-16"
        }
    ],
    "extension_attributes": {
        "website_ids": [
            1,1
        ]
    }
  }
}

Exract from Magento\Catalog\Model\Product.php

...
public function getStoreIds()
    {
        if (!$this->hasStoreIds()) {
            $storeIds = [];
            if ($websiteIds = $this->getWebsiteIds()) {
                if (!$this->isObjectNew() && $this->_storeManager->isSingleStoreMode()) {
                    $websiteIds = array_keys($websiteIds);
                }
                foreach ($websiteIds as $websiteId) {
                    $websiteStores = $this->_storeManager->getWebsite($websiteId)->getStoreIds();
                    $storeIds[] = $websiteStores;
                }
            }
            if ($storeIds) {
                $storeIds = array_merge(...$storeIds);
            }
            $this->setStoreIds($storeIds);
        }
        return $this->getData('store_ids');
    }
...

Metadata

Metadata

Labels

Issue: ConfirmedGate 3 Passed. Manual verification of the issue completed. Issue is confirmedPriority: P2A defect with this priority could have functionality issues which are not to expectations.Progress: doneReported on 2.3.4Indicates original Magento version for the Issue report.Reproduced on 2.4.xThe issue has been reproduced on latest 2.4-develop branchSeverity: S3Affects non-critical data or functionality and does not force users to employ a workaround.

Type

No type

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions