Skip to content

Commit 0ab05a0

Browse files
committed
MC-42265: Dynamic block language overwritten for all store views after upgrading 2.4.1 -> 2.4.2
- Add support for composite identifier in DB data converter
1 parent 8599e3c commit 0ab05a0

File tree

2 files changed

+287
-10
lines changed

2 files changed

+287
-10
lines changed

dev/tests/integration/testsuite/Magento/Framework/DB/DataConverter/DataConverterTest.php

Lines changed: 174 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,14 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
67
namespace Magento\Framework\DB\DataConverter;
78

9+
use Magento\Framework\App\ResourceConnection;
10+
use Magento\Framework\DB\Adapter\AdapterInterface;
811
use Magento\Framework\DB\Adapter\Pdo\Mysql;
12+
use Magento\Framework\DB\Ddl\Table;
13+
use Magento\Framework\DB\FieldDataConversionException;
914
use Magento\Framework\DB\FieldDataConverter;
1015
use Magento\Framework\DB\Select;
1116
use Magento\Framework\DB\Select\QueryModifierInterface;
@@ -14,11 +19,13 @@
1419
use Magento\Framework\DB\Query\Generator;
1520
use Magento\Framework\DB\Query\BatchIterator;
1621
use Magento\Framework\ObjectManagerInterface;
22+
use PHPUnit\Framework\MockObject\MockObject;
23+
use PHPUnit\Framework\TestCase;
1724

18-
class DataConverterTest extends \PHPUnit\Framework\TestCase
25+
class DataConverterTest extends TestCase
1926
{
2027
/**
21-
* @var InQueryModifier|\PHPUnit\Framework\MockObject\MockObject
28+
* @var InQueryModifier|MockObject
2229
*/
2330
private $queryModifierMock;
2431

@@ -28,22 +35,22 @@ class DataConverterTest extends \PHPUnit\Framework\TestCase
2835
private $dataConverter;
2936

3037
/**
31-
* @var BatchIterator|\PHPUnit\Framework\MockObject\MockObject
38+
* @var BatchIterator|MockObject
3239
*/
3340
private $iteratorMock;
3441

3542
/**
36-
* @var Generator|\PHPUnit\Framework\MockObject\MockObject
43+
* @var Generator|MockObject
3744
*/
3845
private $queryGeneratorMock;
3946

4047
/**
41-
* @var Select|\PHPUnit\Framework\MockObject\MockObject
48+
* @var Select|MockObject
4249
*/
4350
private $selectByRangeMock;
4451

4552
/**
46-
* @var Mysql|\PHPUnit\Framework\MockObject\MockObject
53+
* @var Mysql|MockObject
4754
*/
4855
private $adapterMock;
4956

@@ -114,18 +121,22 @@ function () use (&$iterationComplete) {
114121

115122
$this->adapterMock = $this->getMockBuilder(Mysql::class)
116123
->disableOriginalConstructor()
117-
->setMethods(['fetchPairs', 'quoteInto', 'update'])
124+
->setMethods(['fetchPairs', 'fetchAll', 'quoteInto', 'update', 'prepareSqlCondition'])
118125
->getMock();
119126

120127
$this->adapterMock->expects($this->any())
121128
->method('quoteInto')
122129
->willReturn('field=value');
123130

131+
$batchIteratorFactory = $this->createMock(\Magento\Framework\DB\Query\BatchRangeIteratorFactory::class);
132+
$batchIteratorFactory->method('create')->willReturn($this->iteratorMock);
133+
124134
$this->fieldDataConverter = $this->objectManager->create(
125135
FieldDataConverter::class,
126136
[
127137
'queryGenerator' => $this->queryGeneratorMock,
128-
'dataConverter' => $this->dataConverter
138+
'dataConverter' => $this->dataConverter,
139+
'batchIteratorFactory' => $batchIteratorFactory,
129140
]
130141
);
131142
}
@@ -136,7 +147,7 @@ function () use (&$iterationComplete) {
136147
*/
137148
public function testDataConvertErrorReporting()
138149
{
139-
$this->expectException(\Magento\Framework\DB\FieldDataConversionException::class);
150+
$this->expectException(FieldDataConversionException::class);
140151
$this->expectExceptionMessage('Error converting field `value` in table `table` where `id`=2 using');
141152

142153
$rows = [
@@ -179,4 +190,158 @@ public function testAlreadyConvertedDataSkipped()
179190

180191
$this->fieldDataConverter->convert($this->adapterMock, 'table', 'id', 'value', $this->queryModifierMock);
181192
}
193+
194+
public function testAlreadyConvertedDataSkippedWithCompositeIdentifier(): void
195+
{
196+
$rows = [
197+
[
198+
'key_one' => 1,
199+
'key_two' => 1,
200+
'value' => '[]',
201+
],
202+
[
203+
'key_one' => 1,
204+
'key_two' => 2,
205+
'value' => '{}',
206+
],
207+
[
208+
'key_one' => 3,
209+
'key_two' => 3,
210+
'value' => 'N;',
211+
],
212+
[
213+
'key_one' => 4,
214+
'key_two' => 1,
215+
'value' => '{"valid": "json value"}',
216+
]
217+
];
218+
219+
$this->adapterMock->expects($this->any())
220+
->method('prepareSqlCondition')
221+
->willReturnCallback(
222+
function ($column, $value) {
223+
return "$column = $value";
224+
}
225+
);
226+
227+
$this->adapterMock->expects($this->any())
228+
->method('fetchAll')
229+
->with($this->selectByRangeMock)
230+
->willReturn($rows);
231+
232+
$this->adapterMock->expects($this->once())
233+
->method('update')
234+
->with('table', ['value' => 'null'], 'key_one = 3 AND key_two = 3');
235+
236+
$this->fieldDataConverter->convert($this->adapterMock, 'table', 'id1,id2', 'value', $this->queryModifierMock);
237+
}
238+
239+
/**
240+
* @magentoDbIsolation disabled
241+
* @magentoDataFixture createFixtureTable
242+
*/
243+
public function testTableWithCompositeIdentifier(): void
244+
{
245+
$resource = Bootstrap::getObjectManager()->get(ResourceConnection::class);
246+
$tableName = 'test_fixture_table';
247+
$keyOneValues = range(1, 9);
248+
$keyTwoValues = [3, 6, 9];
249+
$records = [];
250+
foreach ($keyOneValues as $keyOneValue) {
251+
foreach (array_slice($keyTwoValues, 0, rand(1, 3)) as $keyTwoValue) {
252+
$records[] = [
253+
'key_one' => $keyOneValue,
254+
'key_two' => $keyTwoValue,
255+
// phpcs:ignore
256+
'value' => serialize(['key_one' => $keyOneValue, 'key_two' => $keyTwoValue]),
257+
];
258+
}
259+
}
260+
// phpcs:ignore
261+
$repeatedVal = serialize([]);
262+
$records[] = [
263+
'key_one' => 10,
264+
'key_two' => 3,
265+
'value' => $repeatedVal,
266+
];
267+
$records[] = [
268+
'key_one' => 10,
269+
'key_two' => 6,
270+
'value' => $repeatedVal,
271+
];
272+
$records[] = [
273+
'key_one' => 11,
274+
'key_two' => 6,
275+
'value' => $repeatedVal,
276+
];
277+
278+
$resource->getConnection()->insertMultiple($tableName, $records);
279+
280+
$expected = [];
281+
282+
foreach ($records as $record) {
283+
$record['value'] = $this->dataConverter->convert($record['value']);
284+
$expected[] = $record;
285+
}
286+
287+
$batchSize = 5;
288+
$fieldDataConverter = $this->objectManager->create(
289+
FieldDataConverter::class,
290+
[
291+
'dataConverter' => $this->dataConverter,
292+
'envBatchSize' => $batchSize
293+
]
294+
);
295+
$fieldDataConverter->convert($resource->getConnection(), $tableName, 'key_one,key_two', 'value');
296+
$actual = $resource->getConnection()->fetchAll(
297+
$resource->getConnection()->select()->from($tableName)
298+
);
299+
$this->assertEquals($expected, $actual, json_encode($records));
300+
}
301+
302+
public static function createFixtureTable(): void
303+
{
304+
$resource = Bootstrap::getObjectManager()->get(ResourceConnection::class);
305+
$tableName = 'test_fixture_table';
306+
$table = $resource->getConnection()
307+
->newTable(
308+
$tableName
309+
)
310+
->addColumn(
311+
'key_one',
312+
Table::TYPE_INTEGER,
313+
null,
314+
['unsigned' => true, 'nullable' => false]
315+
)
316+
->addColumn(
317+
'key_two',
318+
Table::TYPE_INTEGER,
319+
null,
320+
['unsigned' => true, 'nullable' => false]
321+
)
322+
->addColumn(
323+
'value',
324+
Table::TYPE_TEXT,
325+
null,
326+
['nullable' => true]
327+
)
328+
->addIndex(
329+
$tableName . '_index_key_one_key_two',
330+
[
331+
'key_one',
332+
'key_two',
333+
],
334+
[
335+
'type' => AdapterInterface::INDEX_TYPE_PRIMARY
336+
]
337+
);
338+
$resource->getConnection()->createTable($table);
339+
}
340+
341+
public static function createFixtureTableRollback(): void
342+
{
343+
$resource = Bootstrap::getObjectManager()->get(ResourceConnection::class);
344+
$tableName = 'test_fixture_table';
345+
$resource->getConnection()->dropTable($tableName);
346+
}
182347
}

0 commit comments

Comments
 (0)