magento / magento2

Prior to making any Submission(s), you must sign an Adobe Contributor License Agreement, available here at: https://opensource.adobe.com/cla.html. All Submissions you make to Adobe Inc. and its affiliates, assigns and subsidiaries (collectively “Adobe”) are subject to the terms of the Adobe Contributor License Agreement.
http://www.magento.com
Open Software License 3.0
11.47k stars 9.28k forks source link

Custom variable added to variable pool cause unhandled exceptions in different admin on pages with WYSIWYG #38468

Open meandor-ua opened 6 months ago

meandor-ua commented 6 months ago

Preconditions and environment

Snippet must be added to di.xml in the global area.

Steps to reproduce

Example 1

  1. Add snippet from the preconditions to di.xml from the global area.
  2. Flush caches. Recompile DI.
  3. Navigate to Admin Panel => Content => Pages
  4. Open any existing CMS page (or press a button to create a new ones)
  5. Unhandled exception is shown

Example 2

  1. Add snippet from the preconditions to di.xml from the global area.
  2. Flush caches. Recompile DI.
  3. Navigate to Admin Panel => Content => Blocks
  4. Open any existing CMS block (or press a button to create a new ones)
  5. Unhandled exception is shown

Example 3

  1. Add snippet from the preconditions to di.xml from the global area.
  2. Flush caches. Recompile DI.
  3. Navigate to Admin Panel => Marketing => Email Templates
  4. Open any existing email template (or press a button to create a new ones)
  5. Unhandled exception is shown

Example 4

  1. Add snippet from the preconditions to di.xml from the global area.
  2. Flush caches. Recompile DI.
  3. Navigate to Admin Panel => Catalog => Products
  4. Open any product (or try to create a new ones), which has an attribute with WYSIWYG editor (like description) added to at least one attribute group of its attribute set
  5. Unhandled exception is shown

Example 5

  1. Add snippet from the preconditions to di.xml from the global area.
  2. Flush caches. Recompile DI.
  3. Verify that category entity has at least one WYSIWYG attribute
  4. Navigate to Admin Panel => Catalog => Categories
  5. Unhandled exception is shown

Example 6 (for Adobe Commerce with Page Builder)

  1. Add snippet from the preconditions to di.xml from the global area.
  2. Flush caches. Recompile DI.
  3. Navigate to Admin Panel => Content => Templates
  4. Unhandled exception is shown

Expected result

General expected result from upgrading Magento 2.4.2 with custom variables to any Magento 2 starting from 2.4.3 and up to 2.4.7-beta2 would be not crashed Admin Panel pages, which have WYSIWYG editor.

Expected results for given examples.

Example 1

CMS page is rendered without exceptions.

Example 2

CMS block is rendered without exceptions.

Example 3

Transactional email template is rendered without exceptions.

Example 4

Product form is rendered without exceptions.

Example 5

Category management page is rendered without exceptions.

Example 6 for Adobe Commerce with Page Builder (PB)

PB templates page is rendered without exceptions.

Actual result

General actual result from upgrading Magento 2.4.2 with custom variables to any Magento 2 starting from 2.4.3 and up to 2.4.7-beta2 are crashed Admin Panel pages, which have WYSIWYG editor.

Actual results for given examples.

Example 1

CMS page is crashed by exception.

Example 2

CMS block is crashed by exception.

Example 3

Transactional email template is crashed by exception.

Example 4

Product form is crashed by exception.

Example 5

Category management page is crashed by exception.

Example 6 for Adobe Commerce with Page Builder (PB)

PB templates page is crashed by exception.

Additional information

It seems starting from Magento 2.4.3 new way of loading config variables has been introduced. In order to improve performance now config is loaded partially, but not fully. Node depends is added with value null to the partially loaded config in \Magento\Config\Model\Config\Structure\Mapper\Dependencies

Screenshot from debugger

As a solution node depends could be filtered from the light version of the config in \Magento\Variable\Model\Config\Structure\Dom

Current version of the code is

    /**
     * @inheritdoc
     */
    protected function _initDom($xml)
    {
        $dom = parent::_initDom($xml);
        foreach (['tab', 'section', 'group', 'field'] as $element) {
            $this->filterElements($dom, $element, $this->getElementFilters($element));
        }
        return $dom;
    }

It could be replaced with the following code in order to prevent issues with WYSIWYG

    /**
     * @inheritdoc
     */
    protected function _initDom($xml)
    {
        $dom = parent::_initDom($xml);
        foreach (['tab', 'section', 'group', 'field', 'depends'] as $element) {
            $this->filterElements($dom, $element, $this->getElementFilters($element));
        }
        return $dom;
    }

Backtrace in all cases is similar

1 exception(s):
Exception #0 (Magento\Framework\Exception\RuntimeException): Type Error occurred when creating object: Magento\Ui\Component\Form\Element\Wysiwyg, array_key_exists(): Argument #2 ($array) must be of type array, null given

Exception #0 (Magento\Framework\Exception\RuntimeException): Type Error occurred when creating object: Magento\Ui\Component\Form\Element\Wysiwyg, array_key_exists(): Argument #2 ($array) must be of type array, null given
<pre>#1 Magento\Framework\ObjectManager\Factory\Dynamic\Developer->create() called at [vendor/magento/framework/ObjectManager/ObjectManager.php:56]
#2 Magento\Framework\ObjectManager\ObjectManager->create() called at [vendor/magento/framework/View/Element/UiComponentFactory.php:261]
#3 Magento\Framework\View\Element\UiComponentFactory->create() called at [vendor/magento/module-ui/Component/Form/Field.php:85]
#4 Magento\Ui\Component\Form\Field->prepare() called at [vendor/magento/framework/View/Layout/Generator/UiComponent.php:164]
#5 Magento\Framework\View\Layout\Generator\UiComponent->prepareComponent() called at [vendor/magento/framework/View/Layout/Generator/UiComponent.php:161]
#6 Magento\Framework\View\Layout\Generator\UiComponent->prepareComponent() called at [vendor/magento/framework/View/Layout/Generator/UiComponent.php:161]
#7 Magento\Framework\View\Layout\Generator\UiComponent->prepareComponent() called at [vendor/magento/framework/View/Layout/Generator/UiComponent.php:161]
#8 Magento\Framework\View\Layout\Generator\UiComponent->prepareComponent() called at [vendor/magento/framework/View/Layout/Generator/UiComponent.php:142]
#9 Magento\Framework\View\Layout\Generator\UiComponent->generateComponent() called at [vendor/magento/framework/View/Layout/Generator/UiComponent.php:103]
#10 Magento\Framework\View\Layout\Generator\UiComponent->process() called at [vendor/magento/framework/View/Layout/GeneratorPool.php:93]
#11 Magento\Framework\View\Layout\GeneratorPool->process() called at [vendor/magento/framework/View/Layout.php:365]
#12 Magento\Framework\View\Layout->generateElements() called at [generated/code/Magento/Framework/View/Layout/Interceptor.php:155]
#13 Magento\Framework\View\Layout\Interceptor->generateElements() called at [vendor/magento/framework/View/Layout/Builder.php:129]
#14 Magento\Framework\View\Layout\Builder->generateLayoutBlocks() called at [vendor/magento/framework/View/Page/Builder.php:65]
#15 Magento\Framework\View\Page\Builder->generateLayoutBlocks() called at [vendor/magento/framework/View/Layout/Builder.php:65]
#16 Magento\Framework\View\Layout\Builder->build() called at [vendor/magento/framework/View/Layout.php:271]
#17 Magento\Framework\View\Layout->build() called at [vendor/magento/framework/View/Layout.php:896]
#18 Magento\Framework\View\Layout->getBlock() called at [vendor/magento/module-backend/Model/View/Result/Page.php:26]
#19 Magento\Backend\Model\View\Result\Page->setActiveMenu() called at [vendor/magento/module-catalog/Controller/Adminhtml/Product/Edit.php:82]
#20 Magento\Catalog\Controller\Adminhtml\Product\Edit->execute() called at [generated/code/Magento/Catalog/Controller/Adminhtml/Product/Edit/Interceptor.php:171]
#21 Magento\Catalog\Controller\Adminhtml\Product\Edit\Interceptor->execute() called at [vendor/magento/framework/App/Action/Action.php:111]
#22 Magento\Framework\App\Action\Action->dispatch() called at [vendor/magento/module-backend/App/AbstractAction.php:151]
#23 Magento\Backend\App\AbstractAction->dispatch() called at [generated/code/Magento/Catalog/Controller/Adminhtml/Product/Edit/Interceptor.php:231]
#24 Magento\Catalog\Controller\Adminhtml\Product\Edit\Interceptor->Magento\Catalog\Controller\Adminhtml\Product\Edit\{closure}() called at [vendor/magento/module-backend/App/Action/Plugin/Authentication.php:145]
#25 Magento\Backend\App\Action\Plugin\Authentication->aroundDispatch() called at [generated/code/Magento/Catalog/Controller/Adminhtml/Product/Edit/Interceptor.php:232]
#26 Magento\Catalog\Controller\Adminhtml\Product\Edit\Interceptor->dispatch() called at [vendor/magento/framework/App/FrontController.php:245]
#27 Magento\Framework\App\FrontController->getActionResponse() called at [vendor/magento/framework/App/FrontController.php:212]
#28 Magento\Framework\App\FrontController->processRequest() called at [vendor/magento/framework/App/FrontController.php:147]
#29 Magento\Framework\App\FrontController->dispatch() called at [generated/code/Magento/Framework/App/FrontController/Interceptor.php:153]
#30 Magento\Framework\App\FrontController\Interceptor->dispatch() called at [vendor/magento/framework/App/Http.php:116]
#31 Magento\Framework\App\Http->launch() called at [generated/code/Magento/Framework/App/Http/Interceptor.php:57]
#32 Magento\Framework\App\Http\Interceptor->launch() called at [vendor/magento/framework/App/Bootstrap.php:264]
#33 Magento\Framework\App\Bootstrap->run() called at [pub/index.php:30]
</pre>

Release note

Fixed crashing of Admin Panel pages, which contain WYSIWYG editor, when custom variable from the config group with dependencies is added to variable pool.

Triage and priority

m2-assistant[bot] commented 6 months ago

Hi @meandor-ua. Thank you for your report. To speed up processing of this issue, make sure that the issue is reproducible on the vanilla Magento instance following Steps to reproduce. To deploy vanilla Magento instance on our environment, Add a comment to the issue:

m2-assistant[bot] commented 6 months ago

Hi @engcom-November. Thank you for working on this issue. In order to make sure that issue has enough information and ready for development, please read and check the following instruction: :point_down:

engcom-November commented 6 months ago

Hello @meandor-ua,

Thank you for the report and collaboration!

Tried to reproduce this issue in 2.4-develop, But in our case it is not reproducible. Added the given configuration snippet in app/etc/di.xml, but we did not see any exception when using the WYSIWYG editor.

Please let us know if we are missing anything.

Thank you.

meandor-ua commented 6 months ago

@engcom-November for me it either doesn’t work with primary DI area, but I can reproduce it for the common global area. I still can reproduce issue on M2 2.4.7-beta2 when I add that snippet either to custom module or to magento/module-variable. Currently on my local instance I checked out vanilla M2 2.4.7-beta2 Adobe Commerce with sample data. I can reproduce issue if I push code snippet from the ticket description to the end of allowed variables from magento/module-variable. In vendor/magento/module-variable/etc/di.xml

    <type name="Magento\Variable\Model\Config\Structure\AvailableVariables">
        <arguments>
            <argument name="configPaths" xsi:type="array">
                <item name="web" xsi:type="array">
                    <item name="web/unsecure/base_url" xsi:type="string">1</item>
                    <item name="web/secure/base_url" xsi:type="string">1</item>
                </item>
                <item name="trans_email/ident_general" xsi:type="array">
                    <item name="trans_email/ident_general/name" xsi:type="string">1</item>
                    <item name="trans_email/ident_general/email" xsi:type="string">1</item>
                </item>
                <item name="trans_email/ident_sales" xsi:type="array">
                    <item name="trans_email/ident_sales/name" xsi:type="string">1</item>
                    <item name="trans_email/ident_sales/email" xsi:type="string">1</item>
                </item>
                <item name="trans_email/ident_support" xsi:type="array">
                    <item name="trans_email/ident_support/name" xsi:type="string">1</item>
                    <item name="trans_email/ident_support/email" xsi:type="string">1</item>
                </item>
                <item name="trans_email/ident_custom1" xsi:type="array">
                    <item name="trans_email/ident_custom1/name" xsi:type="string">1</item>
                    <item name="trans_email/ident_custom1/email" xsi:type="string">1</item>
                </item>
                <item name="trans_email/ident_custom2" xsi:type="array">
                    <item name="trans_email/ident_custom2/name" xsi:type="string">1</item>
                    <item name="trans_email/ident_custom2/email" xsi:type="string">1</item>
                </item>
                <item name="general/store_information" xsi:type="array">
                    <item name="general/store_information/name" xsi:type="string">1</item>
                    <item name="general/store_information/phone" xsi:type="string">1</item>
                    <item name="general/store_information/hours" xsi:type="string">1</item>
                    <item name="general/store_information/country_id" xsi:type="string">1</item>
                    <item name="general/store_information/region_id" xsi:type="string">1</item>
                    <item name="general/store_information/postcode" xsi:type="string">1</item>
                    <item name="general/store_information/city" xsi:type="string">1</item>
                    <item name="general/store_information/street_line1" xsi:type="string">1</item>
                    <item name="general/store_information/street_line2" xsi:type="string">1</item>
                    <item name="general/store_information/merchant_vat_number" xsi:type="string">1</item>
                </item>
                <item name="wishlist/wishlist_link" xsi:type="array">
                    <item name="wishlist/wishlist_link/use_qty" xsi:type="string">1</item>
                </item>
            </argument>
        </arguments>
    </type>

I just added 3 lines

                <item name="wishlist/wishlist_link" xsi:type="array">
                    <item name="wishlist/wishlist_link/use_qty" xsi:type="string">1</item>
                </item>

to the original file.

engcom-November commented 6 months ago

Hello @meandor-ua,

Thank you for the quick response!

Verified this issue on 2.4-develop. When adding a custom variable with dependency to variable pool, an unhandled exception is thrown while opening a cms page with WYSIWYG editor.

Below is the exception being thrown:

Exception

1 exception(s):
Exception #0 (Magento\Framework\Exception\RuntimeException): Type Error occurred when creating object: Magento\Ui\Component\Form\Element\Wysiwyg, array_key_exists(): Argument #2 ($array) must be of type array, null given

Exception #0 (Magento\Framework\Exception\RuntimeException): Type Error occurred when creating object: Magento\Ui\Component\Form\Element\Wysiwyg, array_key_exists(): Argument #2 ($array) must be of type array, null given
#1 Magento\Framework\ObjectManager\Factory\Compiled->create() called at [lib/internal/Magento/Framework/ObjectManager/ObjectManager.php:59]
#2 Magento\Framework\ObjectManager\ObjectManager->create() called at [lib/internal/Magento/Framework/View/Element/UiComponentFactory.php:260]
#3 Magento\Framework\View\Element\UiComponentFactory->create() called at [app/code/Magento/Ui/Component/Form/Field.php:82]
#4 Magento\Ui\Component\Form\Field->prepare() called at [lib/internal/Magento/Framework/View/Layout/Generator/UiComponent.php:164]
#5 Magento\Framework\View\Layout\Generator\UiComponent->prepareComponent() called at [lib/internal/Magento/Framework/View/Layout/Generator/UiComponent.php:161]
#6 Magento\Framework\View\Layout\Generator\UiComponent->prepareComponent() called at [lib/internal/Magento/Framework/View/Layout/Generator/UiComponent.php:161]
#7 Magento\Framework\View\Layout\Generator\UiComponent->prepareComponent() called at [lib/internal/Magento/Framework/View/Layout/Generator/UiComponent.php:142]
#8 Magento\Framework\View\Layout\Generator\UiComponent->generateComponent() called at [lib/internal/Magento/Framework/View/Layout/Generator/UiComponent.php:103]
#9 Magento\Framework\View\Layout\Generator\UiComponent->process() called at [lib/internal/Magento/Framework/View/Layout/GeneratorPool.php:93]
#10 Magento\Framework\View\Layout\GeneratorPool->process() called at [lib/internal/Magento/Framework/View/Layout.php:365]
#11 Magento\Framework\View\Layout->generateElements() called at [generated/code/Magento/Framework/View/Layout/Interceptor.php:32]
#12 Magento\Framework\View\Layout\Interceptor->generateElements() called at [lib/internal/Magento/Framework/View/Layout/Builder.php:129]
#13 Magento\Framework\View\Layout\Builder->generateLayoutBlocks() called at [lib/internal/Magento/Framework/View/Page/Builder.php:65]
#14 Magento\Framework\View\Page\Builder->generateLayoutBlocks() called at [lib/internal/Magento/Framework/View/Layout/Builder.php:65]
#15 Magento\Framework\View\Layout\Builder->build() called at [lib/internal/Magento/Framework/View/Layout.php:271]
#16 Magento\Framework\View\Layout->build() called at [lib/internal/Magento/Framework/View/Layout.php:896]
#17 Magento\Framework\View\Layout->getBlock() called at [app/code/Magento/Backend/Model/View/Result/Page.php:26]
#18 Magento\Backend\Model\View\Result\Page->setActiveMenu() called at [app/code/Magento/Cms/Controller/Adminhtml/Page/Edit.php:60]
#19 Magento\Cms\Controller\Adminhtml\Page\Edit->_initAction() called at [app/code/Magento/Cms/Controller/Adminhtml/Page/Edit.php:93]
#20 Magento\Cms\Controller\Adminhtml\Page\Edit->execute() called at [lib/internal/Magento/Framework/Interception/Interceptor.php:58]
#21 Magento\Cms\Controller\Adminhtml\Page\Edit\Interceptor->___callParent() called at [lib/internal/Magento/Framework/Interception/Interceptor.php:138]
#22 Magento\Cms\Controller\Adminhtml\Page\Edit\Interceptor->Magento\Framework\Interception\{closure}() called at [lib/internal/Magento/Framework/Interception/Interceptor.php:153]
#23 Magento\Cms\Controller\Adminhtml\Page\Edit\Interceptor->___callPlugins() called at [generated/code/Magento/Cms/Controller/Adminhtml/Page/Edit/Interceptor.php:23]
#24 Magento\Cms\Controller\Adminhtml\Page\Edit\Interceptor->execute() called at [lib/internal/Magento/Framework/App/Action/Action.php:111]
#25 Magento\Framework\App\Action\Action->dispatch() called at [app/code/Magento/Backend/App/AbstractAction.php:151]
#26 Magento\Backend\App\AbstractAction->dispatch() called at [lib/internal/Magento/Framework/Interception/Interceptor.php:58]
#27 Magento\Cms\Controller\Adminhtml\Page\Edit\Interceptor->___callParent() called at [lib/internal/Magento/Framework/Interception/Interceptor.php:138]
#28 Magento\Cms\Controller\Adminhtml\Page\Edit\Interceptor->Magento\Framework\Interception\{closure}() called at [app/code/Magento/Backend/App/Action/Plugin/Authentication.php:145]
#29 Magento\Backend\App\Action\Plugin\Authentication->aroundDispatch() called at [lib/internal/Magento/Framework/Interception/Interceptor.php:135]
#30 Magento\Cms\Controller\Adminhtml\Page\Edit\Interceptor->Magento\Framework\Interception\{closure}() called at [lib/internal/Magento/Framework/Interception/Interceptor.php:153]
#31 Magento\Cms\Controller\Adminhtml\Page\Edit\Interceptor->___callPlugins() called at [generated/code/Magento/Cms/Controller/Adminhtml/Page/Edit/Interceptor.php:32]
#32 Magento\Cms\Controller\Adminhtml\Page\Edit\Interceptor->dispatch() called at [lib/internal/Magento/Framework/App/FrontController.php:245]
#33 Magento\Framework\App\FrontController->getActionResponse() called at [lib/internal/Magento/Framework/App/FrontController.php:212]
#34 Magento\Framework\App\FrontController->processRequest() called at [lib/internal/Magento/Framework/App/FrontController.php:146]
#35 Magento\Framework\App\FrontController->dispatch() called at [lib/internal/Magento/Framework/Interception/Interceptor.php:58]
#36 Magento\Framework\App\FrontController\Interceptor->___callParent() called at [lib/internal/Magento/Framework/Interception/Interceptor.php:138]
#37 Magento\Framework\App\FrontController\Interceptor->Magento\Framework\Interception\{closure}() called at [lib/internal/Magento/Framework/Interception/Interceptor.php:153]
#38 Magento\Framework\App\FrontController\Interceptor->___callPlugins() called at [generated/code/Magento/Framework/App/FrontController/Interceptor.php:23]
#39 Magento\Framework\App\FrontController\Interceptor->dispatch() called at [lib/internal/Magento/Framework/App/Http.php:116]
#40 Magento\Framework\App\Http->launch() called at [lib/internal/Magento/Framework/App/Bootstrap.php:264]
#41 Magento\Framework\App\Bootstrap->run() called at [pub/index.php:30]

Hence confirming the issue.

Thank you.

github-jira-sync-bot commented 6 months ago

:white_check_mark: Jira issue https://jira.corp.adobe.com/browse/AC-11428 is successfully created for this GitHub issue.

m2-assistant[bot] commented 6 months ago

:white_check_mark: Confirmed by @engcom-November. Thank you for verifying the issue.
Issue Available: @engcom-November, You will be automatically unassigned. Contributors/Maintainers can claim this issue to continue. To reclaim and continue work, reassign the ticket to yourself.