3
3
* Copyright © Magento, Inc. All rights reserved.
4
4
* See COPYING.txt for license details.
5
5
*/
6
+
6
7
namespace Magento \Framework \DB \DataConverter ;
7
8
9
+ use Magento \Framework \App \ResourceConnection ;
10
+ use Magento \Framework \DB \Adapter \AdapterInterface ;
8
11
use Magento \Framework \DB \Adapter \Pdo \Mysql ;
12
+ use Magento \Framework \DB \Ddl \Table ;
13
+ use Magento \Framework \DB \FieldDataConversionException ;
9
14
use Magento \Framework \DB \FieldDataConverter ;
10
15
use Magento \Framework \DB \Select ;
11
16
use Magento \Framework \DB \Select \QueryModifierInterface ;
14
19
use Magento \Framework \DB \Query \Generator ;
15
20
use Magento \Framework \DB \Query \BatchIterator ;
16
21
use Magento \Framework \ObjectManagerInterface ;
22
+ use PHPUnit \Framework \MockObject \MockObject ;
23
+ use PHPUnit \Framework \TestCase ;
17
24
18
- class DataConverterTest extends \ PHPUnit \ Framework \ TestCase
25
+ class DataConverterTest extends TestCase
19
26
{
20
27
/**
21
- * @var InQueryModifier|\PHPUnit\Framework\MockObject\ MockObject
28
+ * @var InQueryModifier|MockObject
22
29
*/
23
30
private $ queryModifierMock ;
24
31
@@ -28,22 +35,22 @@ class DataConverterTest extends \PHPUnit\Framework\TestCase
28
35
private $ dataConverter ;
29
36
30
37
/**
31
- * @var BatchIterator|\PHPUnit\Framework\MockObject\ MockObject
38
+ * @var BatchIterator|MockObject
32
39
*/
33
40
private $ iteratorMock ;
34
41
35
42
/**
36
- * @var Generator|\PHPUnit\Framework\MockObject\ MockObject
43
+ * @var Generator|MockObject
37
44
*/
38
45
private $ queryGeneratorMock ;
39
46
40
47
/**
41
- * @var Select|\PHPUnit\Framework\MockObject\ MockObject
48
+ * @var Select|MockObject
42
49
*/
43
50
private $ selectByRangeMock ;
44
51
45
52
/**
46
- * @var Mysql|\PHPUnit\Framework\MockObject\ MockObject
53
+ * @var Mysql|MockObject
47
54
*/
48
55
private $ adapterMock ;
49
56
@@ -114,18 +121,22 @@ function () use (&$iterationComplete) {
114
121
115
122
$ this ->adapterMock = $ this ->getMockBuilder (Mysql::class)
116
123
->disableOriginalConstructor ()
117
- ->setMethods (['fetchPairs ' , 'quoteInto ' , 'update ' ])
124
+ ->setMethods (['fetchPairs ' , 'fetchAll ' , ' quoteInto ' , 'update ' , ' prepareSqlCondition ' ])
118
125
->getMock ();
119
126
120
127
$ this ->adapterMock ->expects ($ this ->any ())
121
128
->method ('quoteInto ' )
122
129
->willReturn ('field=value ' );
123
130
131
+ $ batchIteratorFactory = $ this ->createMock (\Magento \Framework \DB \Query \BatchRangeIteratorFactory::class);
132
+ $ batchIteratorFactory ->method ('create ' )->willReturn ($ this ->iteratorMock );
133
+
124
134
$ this ->fieldDataConverter = $ this ->objectManager ->create (
125
135
FieldDataConverter::class,
126
136
[
127
137
'queryGenerator ' => $ this ->queryGeneratorMock ,
128
- 'dataConverter ' => $ this ->dataConverter
138
+ 'dataConverter ' => $ this ->dataConverter ,
139
+ 'batchIteratorFactory ' => $ batchIteratorFactory ,
129
140
]
130
141
);
131
142
}
@@ -136,7 +147,7 @@ function () use (&$iterationComplete) {
136
147
*/
137
148
public function testDataConvertErrorReporting ()
138
149
{
139
- $ this ->expectException (\ Magento \ Framework \ DB \ FieldDataConversionException::class);
150
+ $ this ->expectException (FieldDataConversionException::class);
140
151
$ this ->expectExceptionMessage ('Error converting field `value` in table `table` where `id`=2 using ' );
141
152
142
153
$ rows = [
@@ -179,4 +190,158 @@ public function testAlreadyConvertedDataSkipped()
179
190
180
191
$ this ->fieldDataConverter ->convert ($ this ->adapterMock , 'table ' , 'id ' , 'value ' , $ this ->queryModifierMock );
181
192
}
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
+ }
182
347
}
0 commit comments