Skip to content

Commit 7f3d8d4

Browse files
committed
AC-12336: WYSIWYG is empty in dynamic rows
Created plugin for Magento\Config\Model\Config\Backend\Serialized\ArraySerialized to convert string keys to numeric keys. Only applies in adminhtml area and on design config edit page
1 parent 4f82be7 commit 7f3d8d4

File tree

3 files changed

+257
-2
lines changed

3 files changed

+257
-2
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
/**
3+
* Copyright 2025 Adobe
4+
* All rights reserved.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Ui\Plugin\Config\Backend;
9+
10+
use Magento\Config\Model\Config\Backend\Serialized\ArraySerialized;
11+
use Magento\Framework\App\Area;
12+
use Magento\Framework\App\RequestInterface;
13+
use Magento\Framework\App\State;
14+
15+
/**
16+
* Plugin for ArraySerialized backend model
17+
* Automatically converts row1/row2/row3 format to numerically indexed arrays
18+
* Only works in adminhtml area and on design config edit page
19+
*/
20+
class ArraySerializedPlugin
21+
{
22+
private const DESIGN_CONFIG_EDIT_PAGE = ['theme_design_config_edit', '_design_config_edit'];
23+
24+
/**
25+
* @param State $appState
26+
* @param RequestInterface $request
27+
*/
28+
public function __construct(
29+
private readonly State $appState,
30+
private readonly RequestInterface $request
31+
) {
32+
}
33+
34+
/**
35+
* Check if we're on the design config edit page.
36+
*
37+
* @return bool
38+
*/
39+
private function isDesignConfigEditPage(): bool
40+
{
41+
return in_array($this->request->getFullActionName(), self::DESIGN_CONFIG_EDIT_PAGE);
42+
}
43+
44+
/**
45+
* Convert string keys to numeric keys. Only applies in adminhtml area and on design config edit page
46+
*
47+
* @param ArraySerialized $subject
48+
* @param ArraySerialized $result
49+
* @return ArraySerialized
50+
*/
51+
public function afterAfterLoad(ArraySerialized $subject, ArraySerialized $result)
52+
{
53+
// Only apply the conversion in adminhtml area and on design config edit page
54+
if ($this->appState->getAreaCode() !== Area::AREA_ADMINHTML || !$this->isDesignConfigEditPage()) {
55+
return $result;
56+
}
57+
58+
$value = $subject->getValue();
59+
60+
// If the value is an array but has string keys (row1, row2, row3)
61+
if (is_array($value) && !empty($value)) {
62+
$keys = array_keys($value);
63+
64+
// Check if keys are string-based (row1, row2, row3) instead of numeric
65+
if (!empty($keys) && !is_numeric($keys[0])) {
66+
// Convert to numerically indexed array
67+
$convertedValue = array_values($value);
68+
$subject->setValue($convertedValue);
69+
}
70+
}
71+
72+
return $result;
73+
}
74+
}

app/code/Magento/Ui/etc/adminhtml/di.xml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<?xml version="1.0"?>
22
<!--
33
/**
4-
* Copyright © Magento, Inc. All rights reserved.
5-
* See COPYING.txt for license details.
4+
* Copyright 2016 Adobe
5+
* All rights reserved.
66
*/
77
-->
88
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
@@ -61,4 +61,9 @@
6161
</argument>
6262
</arguments>
6363
</type>
64+
65+
<!-- Plugin to automatically convert row1/row2/row3 format to numerically indexed arrays -->
66+
<type name="Magento\Config\Model\Config\Backend\Serialized\ArraySerialized">
67+
<plugin name="ui_array_serialized_plugin" type="Magento\Ui\Plugin\Config\Backend\ArraySerializedPlugin" />
68+
</type>
6469
</config>
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
<?php
2+
/**
3+
* Copyright 2025 Adobe
4+
* All rights reserved.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Ui\Plugin\Config\Backend;
9+
10+
use Magento\Config\Model\Config\Backend\Serialized\ArraySerialized;
11+
use Magento\Framework\ObjectManagerInterface;
12+
use Magento\TestFramework\Fixture\AppArea;
13+
use Magento\TestFramework\Helper\Bootstrap;
14+
use Magento\TestFramework\TestCase\AbstractBackendController;
15+
16+
/**
17+
* Integration test for ArraySerializedPlugin
18+
*/
19+
class ArraySerializedPluginTest extends AbstractBackendController
20+
{
21+
/**
22+
* @var ObjectManagerInterface
23+
*/
24+
private $objectManager;
25+
26+
protected function setUp(): void
27+
{
28+
parent::setUp();
29+
$this->objectManager = Bootstrap::getObjectManager();
30+
}
31+
32+
/**
33+
* Test that plugin converts string keys to numeric keys. Works only on design config edit page
34+
*
35+
* @dataProvider serializeDataProvider
36+
*/
37+
#[
38+
AppArea('adminhtml')
39+
]
40+
public function testPluginConvertsStringKeysOnDesignConfigEditPage($stringKeyedArray, $resultArray)
41+
{
42+
// Set up the request to simulate design config edit page
43+
$this->setPageContext();
44+
45+
// Create ArraySerialized backend model
46+
$backendModel = $this->objectManager->create(ArraySerialized::class);
47+
$backendModel->setValue($stringKeyedArray);
48+
49+
// Trigger the afterAfterLoad method (this is where the plugin should run)
50+
$backendModel->afterLoad();
51+
52+
// Get the processed value
53+
$processedValue = $backendModel->getValue();
54+
55+
// Assert that string keys were converted to numeric keys
56+
$this->assertEquals($resultArray, $processedValue);
57+
}
58+
59+
/**
60+
* Test that plugin doesn't convert data when not on design config edit page
61+
*/
62+
#[
63+
AppArea('adminhtml')
64+
]
65+
public function testPluginDoesNotConvertOnOtherPages()
66+
{
67+
// Create test data with string keys
68+
$stringKeyedArray = [
69+
'row1' => ['field1' => 'value1'],
70+
'row2' => ['field2' => 'value2'],
71+
'row3' => ['field3' => 'value3']
72+
];
73+
74+
// Create ArraySerialized backend model
75+
$backendModel = $this->objectManager->create(ArraySerialized::class);
76+
$backendModel->setValue($stringKeyedArray);
77+
78+
// Trigger the afterAfterLoad method
79+
$backendModel->afterLoad();
80+
81+
// Get the processed value
82+
$processedValue = $backendModel->getValue();
83+
84+
// Assert that string keys are preserved (no conversion should happen)
85+
$this->assertIsArray($processedValue);
86+
$this->assertEquals($stringKeyedArray, $processedValue);
87+
}
88+
89+
/**
90+
* Test that plugin doesn't convert data in frontend area
91+
*/
92+
#[
93+
AppArea('frontend')
94+
]
95+
public function testPluginDoesNotConvertInFrontendArea()
96+
{
97+
// Set up the request to simulate design config edit page
98+
$this->setPageContext();
99+
100+
// Create test data with string keys
101+
$stringKeyedArray = [
102+
'row1' => ['field1' => 'value1'],
103+
'row2' => ['field2' => 'value2'],
104+
'row3' => ['field3' => 'value3']
105+
];
106+
107+
// Create ArraySerialized backend model
108+
$backendModel = $this->objectManager->create(ArraySerialized::class);
109+
$backendModel->setValue($stringKeyedArray);
110+
111+
// Trigger the afterAfterLoad method
112+
$backendModel->afterLoad();
113+
114+
// Get the processed value
115+
$processedValue = $backendModel->getValue();
116+
117+
// Assert that string keys are preserved (no conversion should happen in frontend)
118+
$this->assertIsArray($processedValue);
119+
$this->assertEquals($stringKeyedArray, $processedValue);
120+
}
121+
122+
/**
123+
* Data provider for ArraySerializedPlugin. Input array and resultant array.
124+
*
125+
* @return array
126+
*/
127+
public function serializeDataProvider()
128+
{
129+
return [
130+
[ //Test that plugin converts string keys to numeric keys.
131+
[
132+
'row1' => ['field1' => 'value1'],
133+
'row2' => ['field2' => 'value2'],
134+
'row3' => ['field3' => 'value3']
135+
],
136+
[
137+
['field1' => 'value1'],
138+
['field2' => 'value2'],
139+
['field3' => 'value3']
140+
]
141+
],
142+
[ //Test that plugin doesn't convert already numeric arrays.
143+
[
144+
['field1' => 'value1'],
145+
['field2' => 'value2'],
146+
['field3' => 'value3']
147+
],
148+
[
149+
['field1' => 'value1'],
150+
['field2' => 'value2'],
151+
['field3' => 'value3']
152+
]
153+
],
154+
[ // Test that plugin handles empty arrays correctly
155+
[],
156+
[]
157+
],
158+
[ // Test that plugin handles non-array values correctly
159+
'test_string',
160+
false
161+
]
162+
];
163+
}
164+
165+
/**
166+
* Set up the request to simulate design config edit page
167+
*
168+
* @return void
169+
*/
170+
private function setPageContext()
171+
{
172+
$this->getRequest()->setModuleName('theme');
173+
$this->getRequest()->setControllerName('design_config');
174+
$this->getRequest()->setActionName('edit');
175+
}
176+
}

0 commit comments

Comments
 (0)