Skip to content

Missing return value in Magento\CmsUrlRewrite\Plugin\Cms\Model\Store\View::afterSave can cause saving a storeview to crash #29034

Closed
@hostep

Description

@hostep

Preconditions (*)

  1. Tested on a vanilla Magento 2.3.5 and 2.4-develop (commit 735579d) instance

Steps to reproduce (*)

  1. Setup a vanilla Magento installation
  2. In the backend, go to Stores > All Stores
  3. Open the 'Default Store View'
  4. Save the storeview, no need to change anything, notice that this works fine
  5. Now simulate we installed a bunch of custom modules which changes the sort order of certain Magento modules in the app/etc/config.php file, so manually change that file so Magento_CatalogUrlRewrite comes later then Magento_CmsUrlRewrite:
--- app/etc/config.php	2020-07-08 11:42:38.000000000 +0200
+++ app/etc/config2.php	2020-07-08 11:42:35.000000000 +0200
@@ -30,7 +30,6 @@
         'Magento_Payment' => 1,
         'Magento_CatalogRuleGraphQl' => 1,
         'Magento_CatalogRule' => 1,
-        'Magento_CatalogUrlRewrite' => 1,
         'Magento_StoreGraphQl' => 1,
         'Magento_Widget' => 1,
         'Magento_Quote' => 1,
@@ -39,6 +38,7 @@
         'Magento_CmsGraphQl' => 1,
         'Magento_EavGraphQl' => 1,
         'Magento_CmsUrlRewrite' => 1,
+        'Magento_CatalogUrlRewrite' => 1,
         'Magento_CmsUrlRewriteGraphQl' => 1,
         'Magento_User' => 1,
         'Magento_Msrp' => 1,
  1. Flush the caches: bin/magento cache:flush (do not run bin/magento setup:upgrade because it will revert the changes you just did)
  2. In the backend, go to Stores > All Stores and open the 'Default Store View' again
  3. Save the storeview again and notice it throws the following error:
TypeError: Argument 2 passed to Magento\CatalogUrlRewrite\Model\Category\Plugin\Store\View::afterSave() must be an instance of Magento\Store\Model\ResourceModel\Store, null given, called in lib/internal/Magento/Framework/Interception/Interceptor.php on line 146 and defined in app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/View.php:103 Stack trace:
#0 lib/internal/Magento/Framework/Interception/Interceptor.php(146): Magento\CatalogUrlRewrite\Model\Category\Plugin\Store\View->afterSave(Object(Magento\Store\Model\ResourceModel\Store\Interceptor), NULL, Object(Magento\Store\Model\Store\Interceptor))
#1 lib/internal/Magento/Framework/Interception/Interceptor.php(153): Magento\Store\Model\ResourceModel\Store\Interceptor->Magento\Framework\Interception\{closure}(Object(Magento\Store\Model\Store\Interceptor))
#2 generated/code/Magento/Store/Model/ResourceModel/Store/Interceptor.php(86): Magento\Store\Model\ResourceModel\Store\Interceptor->___callPlugins('save', Array, Array)
#3 lib/internal/Magento/Framework/Model/AbstractModel.php(654): Magento\Store\Model\ResourceModel\Store\Interceptor->save(Object(Magento\Store\Model\Store\Interceptor))
#4 lib/internal/Magento/Framework/Interception/Interceptor.php(58): Magento\Framework\Model\AbstractModel->save()
#5 lib/internal/Magento/Framework/Interception/Interceptor.php(138): Magento\Store\Model\Store\Interceptor->___callParent('save', Array)
...

Expected result (*)

  1. Storeview gets saved without errors
  2. All after plugins should return a value, in this case Magento\CmsUrlRewrite\Plugin\Cms\Model\Store\View::aftersSave is missing one

Actual result (*)

  1. Saving a storeview results in an error
  2. The after plugin is missing a return value

Discussion

Error was introduced in Magento 2.3.4 by MC-18561

Following patch seems to resolve the issue:

--- vendor/magento/module-cms-url-rewrite/Plugin/Cms/Model/Store/View.php   2020-01-10 06:20:40.000000000 +0100
+++ /vendor/magento/module-cms-url-rewrite/Plugin/Cms/Model/Store/View.php   2020-07-08 11:25:17.000000000 +0200
@@ -67,16 +67,18 @@
      * @param ResourceStore $object
      * @param ResourceStore $result
      * @param ResourceStore $store
-     * @return void
+     * @return ResourceStore
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function afterSave(ResourceStore $object, ResourceStore $result, AbstractModel $store): void
+    public function afterSave(ResourceStore $object, ResourceStore $result, AbstractModel $store): ResourceStore
     {
         if ($store->isObjectNew() || $store->dataHasChangedFor('group_id')) {
             $this->urlPersist->replace(
                 $this->generateCmsPagesUrls((int)$store->getId())
             );
         }
+
+        return $result;
     }

     /**

Please provide Severity assessment for the Issue as Reporter. This information will help during Confirmation and Issue triage processes.

  • Severity: S0 - Affects critical data or functionality and leaves users without workaround.
  • Severity: S1 - Affects critical data or functionality and forces users to employ a workaround.
  • Severity: S2 - Affects non-critical data or functionality and forces users to employ a workaround.
  • Severity: S3 - Affects non-critical data or functionality and does not force users to employ a workaround.
  • Severity: S4 - Affects aesthetics, professional look and feel, “quality” or “usability”.

(Not sure if S0 is correct here, creating a storeview feels like critical functionality, but I'm fine with S2 as well ...)

Metadata

Metadata

Assignees

Labels

Component: CmsUrlRewriteComponent: StoreFixed in 2.4.xThe issue has been fixed in 2.4-develop branchIssue: ConfirmedGate 3 Passed. Manual verification of the issue completed. Issue is confirmedIssue: Format is validGate 1 Passed. Automatic verification of issue format passedIssue: Ready for WorkGate 4. Acknowledged. Issue is added to backlog and ready for developmentPriority: 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: S1Affects critical data or functionality and forces users to employ a workaround.Triage: Dev.ExperienceIssue related to Developer Experience and needs help with Triage to Confirm or Reject it

Type

No type

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions