Skip to content

Commit b5cc833

Browse files
ENGCOM-8337: Fix array to string conversion error when saving row system config with defaults #30322
- Merge Pull Request #30322 from naitsirch/magento2:fix-30314 - Merged commits: 1. c0a9c42
2 parents a1e5689 + c0a9c42 commit b5cc833

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

app/code/Magento/Config/Model/Config/Backend/Serialized.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
namespace Magento\Config\Model\Config\Backend;
77

8+
use Magento\Framework\App\Config\ScopeConfigInterface;
89
use Magento\Framework\App\ObjectManager;
910
use Magento\Framework\Serialize\Serializer\Json;
1011

@@ -84,4 +85,26 @@ public function beforeSave()
8485
parent::beforeSave();
8586
return $this;
8687
}
88+
89+
/**
90+
* Get old value from existing config
91+
*
92+
* @return string
93+
*/
94+
public function getOldValue()
95+
{
96+
// If the value is retrieved from defaults defined in config.xml
97+
// it may be returned as an array.
98+
$value = $this->_config->getValue(
99+
$this->getPath(),
100+
$this->getScope() ?: ScopeConfigInterface::SCOPE_TYPE_DEFAULT,
101+
$this->getScopeCode()
102+
);
103+
104+
if (is_array($value)) {
105+
return $this->serializer->serialize($value);
106+
}
107+
108+
return (string)$value;
109+
}
87110
}

app/code/Magento/Config/Test/Unit/Model/Config/Backend/SerializedTest.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
namespace Magento\Config\Test\Unit\Model\Config\Backend;
99

1010
use Magento\Config\Model\Config\Backend\Serialized;
11+
use Magento\Framework\App\Config\ScopeConfigInterface;
1112
use Magento\Framework\Event\ManagerInterface;
1213
use Magento\Framework\Model\Context;
1314
use Magento\Framework\Serialize\Serializer\Json;
@@ -27,11 +28,14 @@ class SerializedTest extends TestCase
2728
/** @var LoggerInterface|MockObject */
2829
private $loggerMock;
2930

31+
private $scopeConfigMock;
32+
3033
protected function setUp(): void
3134
{
3235
$objectManager = new ObjectManager($this);
3336
$this->serializerMock = $this->createMock(Json::class);
3437
$this->loggerMock = $this->getMockForAbstractClass(LoggerInterface::class);
38+
$this->scopeConfigMock = $this->createMock(ScopeConfigInterface::class);
3539
$contextMock = $this->createMock(Context::class);
3640
$eventManagerMock = $this->getMockForAbstractClass(ManagerInterface::class);
3741
$contextMock->method('getEventDispatcher')
@@ -43,6 +47,7 @@ protected function setUp(): void
4347
[
4448
'serializer' => $this->serializerMock,
4549
'context' => $contextMock,
50+
'config' => $this->scopeConfigMock,
4651
]
4752
);
4853
}
@@ -135,4 +140,29 @@ public function beforeSaveDataProvider()
135140
]
136141
];
137142
}
143+
144+
/**
145+
* If a config value is not available in core_confid_data the defaults are
146+
* loaded from the config.xml file. Those defaults may be arrays.
147+
* The Serialized backend model has to override its parent
148+
* getOldValue function, to prevent an array to string conversion error
149+
* and serialize those values.
150+
*/
151+
public function testGetOldValueWithNonScalarDefaultValue(): void
152+
{
153+
$value = [
154+
['foo' => '1', 'bar' => '2'],
155+
];
156+
$serializedValue = \json_encode($value);
157+
158+
$this->scopeConfigMock->method('getValue')->willReturn($value);
159+
$this->serializerMock->method('serialize')->willReturn($serializedValue);
160+
161+
$this->serializedConfig->setData('value', $serializedValue);
162+
163+
$oldValue = $this->serializedConfig->getOldValue();
164+
165+
$this->assertIsString($oldValue, 'Default value from the config is not serialized.');
166+
$this->assertSame($serializedValue, $oldValue);
167+
}
138168
}

0 commit comments

Comments
 (0)