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.57k stars 9.32k forks source link

[Issue] Fix dynamic rows dnd array serializer in design config #38733

Open m2-assistant[bot] opened 6 months ago

m2-assistant[bot] commented 6 months ago

This issue is automatically created based on existing pull request: magento/magento2#38731: Fix dynamic rows dnd array serializer in design config


Description (*)

When using a dynamic rows component in design config, the save fails because when Magento tries to compare current value with the parent one, an error occurs:

TypeError: Magento\Theme\Model\Design\Config\ValueChecker::isEqualArrays(): Argument #2 ($defaultValue) must be of type array, bool given, called in /var/www/project/magento/vendor/magento/module-theme/Model/Design/Config/ValueChecker.php on line 87 and defined in /var/www/project/magento/vendor/magento/module-theme/Model/Design/Config/ValueChecker.php:100

It's because the argument types are array, but the default value is never caster while it could be null, an empty string or a boolean.

Related Pull Requests

Fixed Issues (if relevant)

  1. Fixes magento/magento2#

Manual testing scenarios (*)

  1. ...
  2. ...

Questions or comments

Contribution checklist (*)

m2-assistant[bot] commented 6 months ago

Hi @engcom-Hotel. 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-Hotel commented 6 months ago

Hello @thomas-kl1,

Thanks for reporting the issue!

We have tried to reproduce the issue in the Magento 2.4-develop instance and it seems the issue is not reproducible for us. We are able to save the dynamic rows and fetch it successfully.

Please refer to the below custom module for reference and let us know if we missed anything: Magz.zip

Thanks

thomas-kl1 commented 6 months ago

Hello @engcom-Bravo

The problem occurs when you add a dynamic rows to the design config view, not the system config. Field must bee added to ui_component design_config_form.xml.

thomas-kl1 commented 6 months ago

E.g:

<?xml version="1.0" encoding="UTF-8"?>
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <fieldset name="other_settings">
        <fieldset name="header">
            <field name="show_top_information" formElement="select">
                <settings>
                    <dataType>text</dataType>
                    <label translate="true">Show Top Information</label>
                    <dataScope>header_translate_title</dataScope>
                </settings>
                <formElements>
                    <select>
                        <settings>
                            <options class="Magento\Config\Model\Config\Source\Yesno"/>
                        </settings>
                    </select>
                </formElements>
            </field>
            <dynamicRows name="top_information">
                <settings>
                    <addButtonLabel translate="true">Add Line</addButtonLabel>
                    <label translate="true">Top Information</label>
                    <componentType>dynamicRows</componentType>
                </settings>
                <container name="record" component="Magento_Ui/js/dynamic-rows/record">
                    <argument name="data" xsi:type="array">
                        <item name="config" xsi:type="array">
                            <item name="isTemplate" xsi:type="boolean">true</item>
                            <item name="is_collection" xsi:type="boolean">true</item>
                            <item name="componentType" xsi:type="string">container</item>
                        </item>
                    </argument>
                    <field name="caption" formElement="input">
                        <argument name="data" xsi:type="array">
                            <item name="config" xsi:type="array">
                                <item name="fit" xsi:type="boolean">false</item>
                            </item>
                        </argument>
                        <settings>
                            <validation>
                                <rule name="required-entry" xsi:type="boolean">true</rule>
                            </validation>
                            <dataType>text</dataType>
                            <label>Caption</label>
                        </settings>
                    </field>
                    <field name="details" formElement="input">
                        <argument name="data" xsi:type="array">
                            <item name="config" xsi:type="array">
                                <item name="fit" xsi:type="boolean">false</item>
                            </item>
                        </argument>
                        <settings>
                            <dataType>text</dataType>
                            <label>Details</label>
                        </settings>
                    </field>
                    <actionDelete template="Magento_Backend/dynamic-rows/cells/action-delete">
                        <argument name="data" xsi:type="array">
                            <item name="config" xsi:type="array">
                                <item name="fit" xsi:type="boolean">false</item>
                            </item>
                        </argument>
                        <settings>
                            <dataType>text</dataType>
                            <label>Actions</label>
                            <componentType>actionDelete</componentType>
                        </settings>
                    </actionDelete>
                </container>
            </dynamicRows>
        </fieldset>
    </fieldset>
</form>
engcom-Hotel commented 5 months ago

Hello @thomas-kl1,

Thanks for the reply!

We have tried to reproduce the issue with the design config view, but it seems the issue is still not reproducible for us. I order to reproduce the issue, we have modified the below file:

https://github.com/magento/magento2/blob/91cb4d46834b88bb8dc9f5b06279a63d9ad0963c/app/code/Magento/Theme/view/adminhtml/ui_component/design_config_form.xml#L47

And add the below XML in the other_settings fieldset:

<field name="show_top_information" formElement="select">
                <settings>
                    <dataType>text</dataType>
                    <label translate="true">Show Top Information</label>
                    <dataScope>header_translate_title</dataScope>
                </settings>
                <formElements>
                    <select>
                        <settings>
                            <options class="Magento\Config\Model\Config\Source\Yesno"/>
                        </settings>
                    </select>
                </formElements>
            </field>
            <dynamicRows name="top_information">
                <settings>
                    <addButtonLabel translate="true">Add Line</addButtonLabel>
                    <label translate="true">Top Information</label>
                    <componentType>dynamicRows</componentType>
                </settings>
                <container name="record" component="Magento_Ui/js/dynamic-rows/record">
                    <argument name="data" xsi:type="array">
                        <item name="config" xsi:type="array">
                            <item name="isTemplate" xsi:type="boolean">true</item>
                            <item name="is_collection" xsi:type="boolean">true</item>
                            <item name="componentType" xsi:type="string">container</item>
                        </item>
                    </argument>
                    <field name="caption" formElement="input">
                        <argument name="data" xsi:type="array">
                            <item name="config" xsi:type="array">
                                <item name="fit" xsi:type="boolean">false</item>
                            </item>
                        </argument>
                        <settings>
                            <validation>
                                <rule name="required-entry" xsi:type="boolean">true</rule>
                            </validation>
                            <dataType>text</dataType>
                            <label>Caption</label>
                        </settings>
                    </field>
                    <field name="details" formElement="input">
                        <argument name="data" xsi:type="array">
                            <item name="config" xsi:type="array">
                                <item name="fit" xsi:type="boolean">false</item>
                            </item>
                        </argument>
                        <settings>
                            <dataType>text</dataType>
                            <label>Details</label>
                        </settings>
                    </field>
                    <actionDelete template="Magento_Backend/dynamic-rows/cells/action-delete">
                        <argument name="data" xsi:type="array">
                            <item name="config" xsi:type="array">
                                <item name="fit" xsi:type="boolean">false</item>
                            </item>
                        </argument>
                        <settings>
                            <dataType>text</dataType>
                            <label>Actions</label>
                            <componentType>actionDelete</componentType>
                        </settings>
                    </actionDelete>
                </container>
            </dynamicRows>

Please refer to the below-screenshot of the dynamic row field: image

Below screenshot shows that we are able to successfully post the page, we are able to get the values: image

Please let us know if we missed anything.

Thanks

thomas-kl1 commented 5 months ago

How did you setup the di.xml part? Mine is:

I do use the Magento\Config\Model\Config\Backend\Serialized\ArraySerialized which is what we need to use for dynamic rows on system.xml

   <type name="Magento\Theme\Model\Design\Config\MetadataProvider">
      <arguments>
          <argument name="metadata" xsi:type="array">
              <item name="top_information" xsi:type="array">
                  <item name="path" xsi:type="string">design/header/top_information</item>
                  <item name="fieldset" xsi:type="string">other_settings/header</item>
                  <item name="backend_model" xsi:type="string">Magento\Config\Model\Config\Backend\Serialized\ArraySerialized</item>
              </item>
          </argument>
      </arguments>
  </type>
engcom-Hotel commented 5 months ago

Yes @thomas-kl1,

We are using the below setup in the di.xml:

<type name="Magento\Theme\Model\Design\Config\MetadataProvider">
        <arguments>
            <argument name="data" xsi:type="array">
                <item name="top_information" xsi:type="array">
                    <item name="path" xsi:type="string">design/header/top_information</item>
                    <item name="fieldset" xsi:type="string">other_settings/header</item>
                    <item name="backend_model" xsi:type="string">Magento\Config\Model\Config\Backend\Serialized\ArraySerialized</item>
                </item>
            </argument>
        </arguments>
    </type>

But still, the issue is not reproducible for us.

Thanks

thomas-kl1 commented 4 months ago

I'm still facing the issue on the latest Magento version, could you send me the updated version of your module?

thomas-kl1 commented 4 months ago

Ok @engcom-Hotel in order to reproduce the issue you need to be on a website or store scope level.

That is because of \Magento\Theme\Model\Design\Config\ValueChecker::isDifferentFromDefault we got into the isEqual method when we are in a specific scope, then we face the error because it tries to compare the default value from the default scope with the current one. The error occurs becaus there's no specified default value in config.xml or set before

thomas-kl1 commented 4 months ago

I've also noticed an other error when we use a wysiwyg (with the following options:

<item name="pagebuilder_button" xsi:type="boolean">false</item>
<item name="is_pagebuilder_enabled" xsi:type="boolean">false</item>
<item name="toggle_button" xsi:type="boolean">true</item>
<item name="dynamic_id" xsi:type="boolean">true</item>

If I add a new row and delete the added row, the content of second row is now visible..

engcom-Hotel commented 4 months ago

Hello @thomas-kl1,

I'm still facing the issue on the latest Magento version, could you send me the updated version of your module?

Please find attached the module: Magentoissues.zip

in order to reproduce the issue you need to be on a website or store scope level.

We have tried it with the website scope as well, but still unable to reproduce the issue. If possible please provide us with your module in which you can reproduce the issue.

Thanks

thomas-kl1 commented 4 months ago

@engcom-Hotel How were you able to test it? I see the di.xml is missing, so you shouldn't be able to save the value

thomas-kl1 commented 4 months ago

Ok I do reproduce the issue with your code and the following di:

    <type name="Magento\Theme\Model\Design\Config\MetadataProvider">
        <arguments>
            <argument name="metadata" xsi:type="array">
                <item name="show_top_information" xsi:type="array">
                    <item name="path" xsi:type="string">design/header/show_top_information</item>
                    <item name="fieldset" xsi:type="string">other_settings/header</item>
                </item>
                <item name="top_information" xsi:type="array">
                    <item name="path" xsi:type="string">design/header/top_information</item>
                    <item name="fieldset" xsi:type="string">other_settings/header</item>
                    <item name="backend_model" xsi:type="string">Magento\Config\Model\Config\Backend\Serialized\ArraySerialized</item>
                </item>
            </argument>
        </arguments>
    </type>

In order to reproduce:

You will face the error. It's because for the scoped values, Magento always tries to compare to the default scope value, which actually doesn't exists so the type check fails. Change from https://github.com/magento/magento2/pull/38731/files fix it.

thomas-kl1 commented 4 months ago

The workaround is to setup a default value in config.xml, as explained before (but not ideal).

engcom-Hotel commented 4 months ago

Thanks @thomas-kl1 for the inputs, we can reproduce the issue now.

@engcom-Hotel How were you able to test it? I see the di.xml is missing, so you shouldn't be able to save the value

I think by mistakenly provided you with the older version of the module.

We are confirming the issue for further processing.

Thanks

github-jira-sync-bot commented 4 months ago

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

m2-assistant[bot] commented 4 months ago

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