AssembleInputTest::testProcessException1()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
c 0
b 0
f 0
rs 9.552
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Maketok\DataMigration\Action\Type;
4
5
use Maketok\DataMigration\ArrayMap;
6
use Maketok\DataMigration\Expression\LanguageAdapter;
7
use Maketok\DataMigration\Input\InputResourceInterface;
8
use Maketok\DataMigration\MapInterface;
9
use Maketok\DataMigration\Storage\Filesystem\ResourceInterface;
10
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
11
12
class AssembleInputTest extends \PHPUnit_Framework_TestCase
0 ignored issues
show
Complexity introduced by
This class has 1268 lines of code which exceeds the configured maximum of 1000.

Really long classes often contain too much logic and violate the single responsibility principle.

We suggest to take a look at the “Code” section for options on how to refactor this code.

Loading history...
13
{
14
    use ServiceGetterTrait;
15
16
    /**
17
     * @var AssembleInput
18
     */
19
    private $action;
20
21
    public function setUp()
22
    {
23
        $this->action = $this->getAction();
24
    }
25
26
    /**
27
     * @param array $units
28
     * @param array $inputExpectations
29
     * @return AssembleInput
30
     */
31
    public function getAction($units = [], $inputExpectations = [])
32
    {
33
        return new AssembleInput(
34
            $this->getUnitBag($units),
35
            $this->getConfig(),
36
            new LanguageAdapter(new ExpressionLanguage()),
37
            $this->getInputResource($inputExpectations),
38
            new ArrayMap()
39
        );
40
    }
41
42
    public function testGetCode()
43
    {
44
        $this->assertEquals('assemble_input', $this->action->getCode());
45
    }
46
47
    /**
48
     * @param array $data
49
     * @return InputResourceInterface
50
     */
51
    protected function getInputResource(array $data = [])
52
    {
53
        $input = $this->getMockBuilder('\Maketok\DataMigration\Input\InputResourceInterface')
54
            ->getMock();
55
        $count = count($data);
56
        $method = $input->expects($this->exactly($count))->method('add');
57
        call_user_func_array([$method, 'withConsecutive'], $data);
58
        return $input;
59
    }
60
61
    /**
62
     * @param array $returns
63
     * @return ResourceInterface
64
     */
65
    protected function getFS($returns = [])
66
    {
67
        $filesystem = $this->getMockBuilder('\Maketok\DataMigration\Storage\Filesystem\ResourceInterface')
68
            ->getMock();
69
        $cntReturns = count($returns);
70
        $method = $filesystem->expects($this->exactly($cntReturns))
71
            ->method('readRow');
72
        call_user_func_array([$method, 'willReturnOnConsecutiveCalls'], $returns);
73
        return $filesystem;
74
    }
75
76
    /**
77
     * standard process
78
     * 2 branches 1 leaf
79
     */
80
    public function testProcess()
81
    {
82
        $unit1 = $this->getUnit('customer');
83
        $unit1->setReversedMapping([
84
            'email' => 'map.email',
85
            'age' => 'map.age',
86
        ]);
87
        $unit1->setReversedConnection([
88
            'customer_id' => 'id',
89
        ]);
90
        $unit1->setMapping([
91
            'id' => 'map.id',
92
            'email' => 'map.email',
93
            'age' => 'map.age',
94
        ]);
95
        $unit1->setFilesystem($this->getFS(
96
            [
97
                [1, '[email protected]', 30],
98
                [2, '[email protected]', 33],
99
                [3, '[email protected]', 55],
100
                [4, '[email protected]', 11],
101
                false,
102
            ]
103
        ));
104
        $unit1->setIsEntityCondition(function (
105
            MapInterface $map,
106
            MapInterface $oldmap
107
        ) {
108
            return $oldmap->offsetGet('email') != $map->offsetGet('email');
109
        });
110
        $unit1->setTmpFileName('customer_tmp.csv');
111
112
        $unit2 = $this->getUnit('customer_data');
113
        $unit2->setReversedMapping([
114
            'name' => function ($map) {
115
                return $map['fname'] . ' ' . $map['lname'];
116
            },
117
        ]);
118
        $unit2->setReversedConnection([
119
            'customer_id' => 'parent_id',
120
        ]);
121
        $unit2->setMapping([
122
            'id' => 'map.data_id',
123
            'parent_id' => 'map.id',
124
            'fname' => function ($map) {
125
                list($fname) = explode(" ", $map['name']);
126
                return $fname;
127
            },
128
            'lname' => function ($map) {
129
                list(, $lname) = explode(" ", $map['name']);
130
                return $lname;
131
            },
132
        ]);
133
        $unit2->setTmpFileName('customer_data_tmp.csv');
134
        $unit2->setFilesystem($this->getFS(
135
            [
136
                [1, 1, 'Olaf', 'Stone'],
137
                [2, 2,  'Peter', 'Ostridge'],
138
                [3, 3, 'Bill', 'Murray'],
139
                [4, 4, 'Peter', 'Pan'],
140
                false,
141
            ]
142
        ));
143
        $unit2->addSibling($unit1);
144
145
        $unit3 = $this->getUnit('address');
146
        $unit3->setReversedMapping([
147
            'addr_city' => 'map.city',
148
            'addr_street' => 'map.street',
149
        ]);
150
        $unit3->setReversedConnection([
151
            'customer_id' => 'parent_id',
152
        ]);
153
        $unit3->setMapping([
154
            'id' => 'map.addr_id',
155
            'street' => 'map.addr_street',
156
            'city' => 'map.addr_city',
157
            'parent_id' => 'map.id',
158
        ]);
159
        $unit3->addContribution(function (MapInterface $map) {
160
            $map->incr('addr_id', 1);
161
        });
162
        $unit3->setFilesystem($this->getFS(
163
            [
164
                [1, '4100 Marine dr. App. 54', 'Chicago', 1],
165
                [2, '3300 St. George, Suite 300', 'New York', 1],
166
                [3, '111 W Jackson', 'Chicago', 2],
167
                [4, '111 W Jackson-2', 'Chicago', 3],
168
                [5, '111 W Jackson-3', 'Chicago', 3],
169
                [6, 'Hollywood', 'LA', 3],
170
                [7, 'fake', 'LA', 3],
171
                [8, 'Fairy Tale', 'NY', 4],
172
                false,
173
            ]
174
        ));
175
        $unit3->setTmpFileName('address_tmp.csv');
176
        $unit3->setParent($unit1);
177
178
        $expected = [
179
            [[
180
                'email' => '[email protected]',
181
                'name' => 'Olaf Stone',
182
                'age' => 30,
183
                'address' => [
184
                    [
185
                        'addr_city' => 'Chicago',
186
                        'addr_street' => '4100 Marine dr. App. 54',
187
                    ],
188
                    [
189
                        'addr_city' => 'New York',
190
                        'addr_street' => '3300 St. George, Suite 300',
191
                    ],
192
                ]
193
            ]],
194
            [[
195
                'email' => '[email protected]',
196
                'name' => 'Peter Ostridge',
197
                'age' => 33,
198
                'address' => [
199
                    [
200
                        'addr_city' => 'Chicago',
201
                        'addr_street' => '111 W Jackson',
202
                    ]
203
                ]
204
            ]],
205
            [[
206
                'email' => '[email protected]',
207
                'name' => 'Bill Murray',
208
                'age' => 55,
209
                'address' => [
210
                    [
211
                        'addr_city' => 'Chicago',
212
                        'addr_street' => '111 W Jackson-2',
213
                    ],
214
                    [
215
                        'addr_city' => 'Chicago',
216
                        'addr_street' => '111 W Jackson-3',
217
                    ],
218
                    [
219
                        'addr_city' => 'LA',
220
                        'addr_street' => 'Hollywood',
221
                    ],
222
                    [
223
                        'addr_city' => 'LA',
224
                        'addr_street' => 'fake',
225
                    ]
226
                ]
227
            ]],
228
            [[
229
                'email' => '[email protected]',
230
                'name' => 'Peter Pan',
231
                'age' => 11,
232
                'address' => [
233
                    [
234
                        'addr_city' => 'NY',
235
                        'addr_street' => 'Fairy Tale',
236
                    ]
237
                ]
238
            ]],
239
        ];
240
241
        $action = $this->getAction([$unit1, $unit2, $unit3], $expected);
242
        $action->process($this->getResultMock());
243
    }
244
245
    /**
246
     * standard process
247
     * 1 branch 2 leaf
248
     */
249
    public function testProcess1b2l()
250
    {
251
        $unit1 = $this->getUnit('customer');
252
        $unit1->setReversedMapping([
253
            'email' => 'map.email',
254
            'name' => function ($map) {
255
                return $map['fname'] . ' ' . $map['lname'];
256
            },
257
            'age' => 'map.age',
258
        ]);
259
        $unit1->setReversedConnection([
260
            'customer_id' => 'id',
261
        ]);
262
        $unit1->setMapping([
263
            'id' => 'map.id',
264
            'email' => 'map.email',
265
            'age' => 'map.age',
266
            'fname' => function ($map) {
267
                list($fname) = explode(" ", $map['name']);
268
                return $fname;
269
            },
270
            'lname' => function ($map) {
271
                list(, $lname) = explode(" ", $map['name']);
272
                return $lname;
273
            },
274
        ]);
275
        $unit1->setFilesystem($this->getFS(
276
            [
277
                [1, '[email protected]', 30, 'Olaf', 'Stone'],
278
                [2, '[email protected]', 33, 'Peter', 'Ostridge'],
279
                [3, '[email protected]', 55, 'Bill', 'Murray'],
280
                [4, '[email protected]', 11, 'Peter', 'Pan'],
281
                false,
282
            ]
283
        ));
284
        $unit1->setIsEntityCondition(function (
285
            MapInterface $map,
286
            MapInterface $oldmap
287
        ) {
288
            return $oldmap->offsetGet('email') != $map->offsetGet('email');
289
        });
290
        $unit1->setTmpFileName('customer_tmp.csv');
291
292
        $unit3 = $this->getUnit('address');
293
        $unit3->setReversedMapping([
294
            'addr_city' => 'map.city',
295
        ]);
296
        $unit3->setReversedConnection([
297
            'customer_id' => 'parent_id',
298
            'address_id' => 'id',
299
        ]);
300
        $unit3->setMapping([
301
            'id' => 'map.addr_id',
302
            'city' => 'map.addr_city',
303
            'parent_id' => 'map.id',
304
        ]);
305
        $unit3->addContribution(function (MapInterface $map) {
306
            $map->incr('addr_id', 1);
307
        });
308
        $unit3->setFilesystem($this->getFS(
309
            [
310
                [1, 'Chicago', 1],
311
                [2, 'New York', 1],
312
                [3, 'Chicago', 2],
313
                [4, 'Chicago', 3],
314
                [5, 'Chicago', 3],
315
                [6, 'LA', 3],
316
                [7, 'LA', 3],
317
                [8, 'NY', 4],
318
                false,
319
            ]
320
        ));
321
        $unit3->setTmpFileName('address_tmp.csv');
322
        $unit3->setParent($unit1);
323
324
        $unit2 = $this->getUnit('address_data');
325
        $unit2->setReversedMapping([
326
            'addr_street' => 'map.street',
327
        ]);
328
        $unit2->setReversedConnection([
329
            'address_id' => 'parent_id',
330
        ]);
331
        $unit2->setMapping([
332
            'id' => 'map.addr_data_id',
333
            'street' => 'map.addr_street',
334
            'parent_id' => 'map.address_id',
335
        ]);
336
        $unit2->setTmpFileName('customer_data_tmp.csv');
337
        $unit2->setFilesystem($this->getFS(
338
            [
339
                [1, '4100 Marine dr. App. 54', 1],
340
                [2, '3300 St. George, Suite 300', 2],
341
                [3, '111 W Jackson', 3],
342
                [4, '111 W Jackson-2', 4],
343
                [5, '111 W Jackson-3', 5],
344
                [6, 'Hollywood', 6],
345
                [7, 'fake', 7],
346
                [8, 'Fairy Tale', 8],
347
                false,
348
            ]
349
        ));
350
        $unit2->addSibling($unit3);
351
352
        $expected = [
353
            [[
354
                'email' => '[email protected]',
355
                'name' => 'Olaf Stone',
356
                'age' => 30,
357
                'address' => [
358
                    [
359
                        'addr_city' => 'Chicago',
360
                        'addr_street' => '4100 Marine dr. App. 54',
361
                    ],
362
                    [
363
                        'addr_city' => 'New York',
364
                        'addr_street' => '3300 St. George, Suite 300',
365
                    ],
366
                ]
367
            ]],
368
            [[
369
                'email' => '[email protected]',
370
                'name' => 'Peter Ostridge',
371
                'age' => 33,
372
                'address' => [
373
                    [
374
                        'addr_city' => 'Chicago',
375
                        'addr_street' => '111 W Jackson',
376
                    ]
377
                ]
378
            ]],
379
            [[
380
                'email' => '[email protected]',
381
                'name' => 'Bill Murray',
382
                'age' => 55,
383
                'address' => [
384
                    [
385
                        'addr_city' => 'Chicago',
386
                        'addr_street' => '111 W Jackson-2',
387
                    ],
388
                    [
389
                        'addr_city' => 'Chicago',
390
                        'addr_street' => '111 W Jackson-3',
391
                    ],
392
                    [
393
                        'addr_city' => 'LA',
394
                        'addr_street' => 'Hollywood',
395
                    ],
396
                    [
397
                        'addr_city' => 'LA',
398
                        'addr_street' => 'fake',
399
                    ]
400
                ]
401
            ]],
402
            [[
403
                'email' => '[email protected]',
404
                'name' => 'Peter Pan',
405
                'age' => 11,
406
                'address' => [
407
                    [
408
                        'addr_city' => 'NY',
409
                        'addr_street' => 'Fairy Tale',
410
                    ]
411
                ]
412
            ]],
413
        ];
414
415
        $action = $this->getAction([$unit1, $unit2, $unit3], $expected);
416
        $action->process($this->getResultMock());
417
    }
418
419
    /**
420
     * test process with incorrect connection (addresses do not match customers)
421
     * @expectedException \LogicException
422
     * @expectedExceptionMessage Orphaned rows in some of the units
423
     */
424
    public function testProcess2()
425
    {
426
        $unit1 = $this->getUnit('customer');
427
        $unit1->setReversedMapping([
428
            'email' => 'map.email',
429
            'name' => function ($map) {
430
                return $map['fname'] . ' ' . $map['lname'];
431
            },
432
            'age' => 'map.age',
433
        ]);
434
        $unit1->setReversedConnection([
435
            'customer_id' => 'id',
436
        ]);
437
        $unit1->setMapping([
438
            'id' => 'map.id',
439
            'fname' => function ($map) {
440
                list($fname) = explode(" ", $map['name']);
441
                return $fname;
442
            },
443
            'lname' => function ($map) {
444
                list(, $lname) = explode(" ", $map['name']);
445
                return $lname;
446
            },
447
            'email' => 'map.email',
448
            'age' => 'map.age',
449
        ]);
450
        $unit1->setFilesystem($this->getFS(
451
            [
452
                [1, 'Olaf', 'Stone', '[email protected]', 30],
453
                [2, 'Peter', 'Ostridge', '[email protected]', 33],
454
                false,
455
            ]
456
        ));
457
        $unit1->setTmpFileName('customer_tmp.csv');
458
459
        $unit2 = $this->getUnit('address');
460
        $unit2->setReversedMapping([
461
            'addr_city' => 'map.city',
462
            'addr_street' => 'map.street',
463
        ]);
464
        $unit2->setReversedConnection([
465
            'customer_id' => 'parent_id',
466
        ]);
467
        $unit2->setMapping([
468
            'id' => 'map.addr_id',
469
            'street' => 'map.addr_street',
470
            'city' => 'map.addr_city',
471
            'parent_id' => 'map.id',
472
        ]);
473
        $unit2->addContribution(function (MapInterface $map) {
474
            $map->incr('addr_id', 1);
475
        });
476
        $unit2->setFilesystem($this->getFS(
477
            [
478
                [1, '4100 Marine dr. App. 54', 'Chicago', 1],
479
                [2, '3300 St. George, Suite 300', 'New York', 1],
480
                [3, '111 W Jackson', 'Chicago', 4],
481
                [4, '111 W Jackson-2', 'Chicago', 4],
482
                // next rows will not be read due to LogicException
483
                // [5, 'Hollywood', 'LA', 4],
484
                // false,
485
            ]
486
        ));
487
        $unit2->setTmpFileName('address_tmp.csv');
488
        $unit2->setParent($unit1);
489
490
        $expected = [
491
            [[
492
                'email' => '[email protected]',
493
                'name' => 'Olaf Stone',
494
                'age' => 30,
495
                'address' => [
496
                    [
497
                        'addr_city' => 'Chicago',
498
                        'addr_street' => '4100 Marine dr. App. 54',
499
                    ],
500
                    [
501
                        'addr_city' => 'New York',
502
                        'addr_street' => '3300 St. George, Suite 300',
503
                    ]
504
                ]
505
            ]],
506
        ];
507
508
        $action = $this->getAction([$unit1, $unit2], $expected);
509
        $action->process($this->getResultMock());
510
    }
511
512
    /**
513
     * process unit with incorrect map
514
     * @expectedException \LogicException
515
     * @expectedExceptionMessage Wrong reversed connection key given.
516
     */
517
    public function testProcessException1()
518
    {
519
        $unit1 = $this->getUnit('test');
520
        $unit1->setReversedMapping([
521
            'name' => 'field3',
522
        ]);
523
        $unit1->setReversedConnection([
524
            'id' => 'field4',
525
        ]);
526
        $unit1->setMapping([
527
            'field1' => 'name',
528
            'field2' => 'code',
529
        ]);
530
        $unit1->setFilesystem($this->getFS(
531
            [
532
                ['Pete', 'tst1']
533
            ]
534
        ));
535
        $unit1->setTmpFileName('customer_tmp.csv');
536
537
        $action = $this->getAction([$unit1]);
538
        $action->process($this->getResultMock());
539
    }
540
541
    /**
542
     * try to process units that do not match
543
     * no additions should be done
544
     */
545
    public function testProcessWeirdCase1()
546
    {
547
        $unit1 = $this->getUnit('test');
548
        $unit1->setReversedMapping([
549
            'name' => 'map.field1',
550
        ]);
551
        $unit1->setReversedConnection([
552
            'tid' => 'id',
553
        ]);
554
        $unit1->setMapping([
555
            'field1' => 'name',
556
            'field2' => 'code',
557
            'id' => 'id',
558
        ]);
559
        $unit1->setFilesystem($this->getFS(
560
            [
561
                ['Pete', 'tst1', '1'],
562
                false,
563
            ]
564
        ));
565
        $unit1->setTmpFileName('customer_tmp.csv');
566
567
        $unit2 = $this->getUnit('test2');
568
        $unit2->setReversedMapping([
569
            'name' => 'map.field1',
570
        ]);
571
        $unit2->setReversedConnection([
572
            'tid' => 'parent_id',
573
        ]);
574
        $unit2->setMapping([
575
            'field1' => 'name',
576
            'field2' => 'code',
577
            'parent_id' => 'id',
578
        ]);
579
        $unit2->setFilesystem($this->getFS(
580
            [
581
                ['Pete', 'tst1', '2'],
582
                false,
583
            ]
584
        ));
585
        $unit2->setTmpFileName('customer_tmp.csv');
586
        $unit2->setParent($unit1);
587
588
        $action = $this->getAction([$unit1, $unit2]);
589
        $action->process($this->getResultMock());
590
    }
591
592
    /**
593
     * try to process 2 units one of which is empty
594
     * nothing should happen here (not single addition nor exceptions)
595
     */
596
    public function testProcessWeirdCase2()
597
    {
598
        $unit1 = $this->getUnit('test');
599
        $unit1->setReversedMapping([
600
            'name' => 'map.field1',
601
        ]);
602
        $unit1->setReversedConnection([
603
            'tid' => 'id',
604
        ]);
605
        $unit1->setMapping([
606
            'field1' => 'name',
607
            'field2' => 'code',
608
            'id' => 'id',
609
        ]);
610
        $unit1->setFilesystem($this->getFS(
611
            [
612
                ['Pete', 'tst1', '1'],
613
                 false,
614
            ]
615
        ));
616
        $unit1->setTmpFileName('customer_tmp.csv');
617
618
        $unit2 = $this->getUnit('test2');
619
        $unit2->setReversedMapping([
620
            'name' => 'map.field1',
621
        ]);
622
        $unit2->setReversedConnection([
623
            'tid' => 'parent_id',
624
        ]);
625
        $unit2->setMapping([
626
            'field1' => 'name',
627
            'field2' => 'code',
628
            'parent_id' => 'id',
629
        ]);
630
        $unit2->setFilesystem($this->getFS(
631
            [
632
                false
633
            ]
634
        ));
635
        $unit2->setTmpFileName('customer_tmp.csv');
636
        $unit2->setParent($unit1);
637
638
        $action = $this->getAction([$unit1, $unit2]);
639
        $action->process($this->getResultMock());
640
    }
641
642
    /**
643
     * @expectedException \Maketok\DataMigration\Action\Exception\WrongContextException
644
     * @expectedExceptionMessage Action can not be used for current unit test121312
645
     */
646
    public function testWrongProcess()
647
    {
648
        $action = $this->getAction([$this->getUnit('test121312')]);
649
        $action->process($this->getResultMock());
650
    }
651
652
    /**
653
     * Test that units which have same keys for data (field1)
654
     * append unit code as prefix for it
655
     * @throws \Exception
656
     * @test
657
     */
658
    public function testSameCodes()
659
    {
660
        $unit1 = $this->getUnit('test');
661
        $unit1->setReversedMapping([
662
            'name' => 'map.test_field1',
663
        ]);
664
        $unit1->setReversedConnection([
665
            'tid' => 'id',
666
        ]);
667
        $unit1->setMapping([
668
            'field1' => 'name',
669
            'field2' => 'code',
670
            'id' => 'id',
671
        ]);
672
        $unit1->setFilesystem($this->getFS(
673
            [
674
                ['Pete', 'tst1', '1'],
675
                false,
676
            ]
677
        ));
678
        $unit1->setTmpFileName('test_tmp.csv');
679
680
        $unit2 = $this->getUnit('test2');
681
        $unit2->setReversedMapping([
682
            'secondName' => 'map.test2_field1',
683
        ]);
684
        $unit2->setReversedConnection([
685
            'tid' => 'parent_id',
686
        ]);
687
        $unit2->setMapping([
688
            'field1' => 'name',
689
            'field2' => 'code',
690
            'parent_id' => 'id',
691
        ]);
692
        $unit2->setFilesystem($this->getFS(
693
            [
694
                ['George', 'tst2', '1'],
695
                false,
696
            ]
697
        ));
698
        $unit2->setTmpFileName('test2_tmp.csv');
699
        $unit2->addSibling($unit1);
700
701
        $expected = [
702
            [[
703
                'name' => 'Pete',
704
                'secondName' => 'George',
705
            ]],
706
        ];
707
708
        $action = $this->getAction([$unit1, $unit2], $expected);
709
        $action->process($this->getResultMock());
710
    }
711
712
    /**
713
     * test inconsistent siblings process
714
     * when some of the sibling can be absent for current row
715
     */
716
    public function testInconsistentSiblings()
717
    {
718
        $unit1 = $this->getUnit('shipment');
719
        $unit1->setReversedMapping([
720
            'total' => 'map.total'
721
        ]);
722
        $unit1->setReversedConnection([
723
            'shipment_id' => 'shipment_id',
724
        ]);
725
        $unit1->setMapping([
726
            'shipment_id' => 'map.shipment_id',
727
            'total' => 'map.total',
728
        ]);
729
        $unit1->setFilesystem($this->getFS(
730
            [
731
                [1, 30],
732
                [2, 33],
733
                [3, 55],
734
                [4, 11],
735
                false,
736
            ]
737
        ));
738
        $unit1->setIsEntityCondition(function (MapInterface $map) {
739
            return !empty($map['shipment_id']);
740
        });
741
        $unit1->setTmpFileName('shipment_tmp.csv');
742
743
        $unit3 = $this->getUnit('tracking');
744
        $unit3->setReversedMapping([
745
            'tracking_number' => 'map.tracking_number',
746
        ]);
747
        $unit3->setReversedConnection([
748
            'shipment_id' => 'shipment_id',
749
        ]);
750
        $unit3->setMapping([
751
            'id' => 'map.incr("track_id", 1)',
752
            'tracking_number' => 'map.tracking_number',
753
            'shipment_id' => 'map.shipment_id',
754
        ]);
755
        $unit3->setFilesystem($this->getFS(
756
            [
757
                [1, '56465454', 1],
758
                [2, '13122333', 3],
759
                [3, '13343443', 4],
760
                false,
761
            ]
762
        ));
763
        $unit3->setTmpFileName('tracking_tmp.csv');
764
        $unit3->addSibling($unit1);
765
        $unit3->setOptional(true);
766
767
        $expected = [
768
            [[
769
                'total' => 30,
770
                'tracking_number' => '56465454',
771
            ]],
772
            [[
773
                'total' => 33,
774
                'tracking_number' => null,
775
            ]],
776
            [[
777
                'total' => 55,
778
                'tracking_number' => '13122333',
779
            ]],
780
            [[
781
                'total' => 11,
782
                'tracking_number' => '13343443',
783
            ]],
784
        ];
785
786
        $action = $this->getAction([$unit1, $unit3], $expected);
787
        $action->process($this->getResultMock());
788
    }
789
790
    /**
791
     * test inconsistent siblings process
792
     * when some of the sibling can be absent for current row
793
     */
794
    public function testInconsistentSiblings2Levels()
795
    {
796
        $unit1 = $this->getUnit('shipment');
797
        $unit1->setReversedMapping([
798
            'total' => 'map.total'
799
        ]);
800
        $unit1->setReversedConnection([
801
            'shipment_id' => 'shipment_id',
802
        ]);
803
        $unit1->setMapping([
804
            'shipment_id' => 'map.shipment_id',
805
            'total' => 'map.total',
806
        ]);
807
        $unit1->setFilesystem($this->getFS(
808
            [
809
                [1, 30],
810
                [2, 33],
811
                [3, 55],
812
                [4, 11],
813
                false,
814
            ]
815
        ));
816
        $unit1->setIsEntityCondition(function (MapInterface $map) {
817
            return !empty($map['shipment_id']);
818
        });
819
        $unit1->setTmpFileName('shipment_tmp.csv');
820
821
        $unit2 = $this->getUnit('item');
822
        $unit2->setReversedMapping([
823
            'item_name' => 'map.name',
824
        ]);
825
        $unit2->setReversedConnection([
826
            'shipment_id' => 'shipment_id',
827
        ]);
828
        $unit2->setMapping([
829
            'id' => 'map.incr("item_id", 1)',
830
            'name' => 'map.item_name',
831
            'shipment_id' => 'map.shipment_id',
832
        ]);
833
        $unit2->setFilesystem($this->getFS(
834
            [
835
                [1, 'cool item', 1],
836
                [2, 'another super item', 1],
837
                [3, 'Coca Cola', 2],
838
                [4, 'Pepsi', 3],
839
                [5, 'pants', 4],
840
                false,
841
            ]
842
        ));
843
        $unit2->setTmpFileName('item_tmp.csv');
844
        $unit2->setParent($unit1);
845
846
        $unit3 = $this->getUnit('tracking');
847
        $unit3->setReversedMapping([
848
            'tracking_number' => 'map.tracking_number',
849
        ]);
850
        $unit3->setReversedConnection([
851
            'shipment_id' => 'shipment_id',
852
        ]);
853
        $unit3->setMapping([
854
            'id' => 'map.incr("track_id", 1)',
855
            'tracking_number' => 'map.tracking_number',
856
            'shipment_id' => 'map.shipment_id',
857
        ]);
858
        $unit3->setFilesystem($this->getFS(
859
            [
860
                [1, '56465454', 1],
861
                [2, '13122333', 3],
862
                [3, '13343443', 4],
863
                false,
864
            ]
865
        ));
866
        $unit3->setTmpFileName('tracking_tmp.csv');
867
        $unit3->addSibling($unit1);
868
        $unit3->setOptional(true);
869
870
        $expected = [
871
            [[
872
                'total' => 30,
873
                'tracking_number' => '56465454',
874
                'item' => [
875
                    [
876
                        'item_name' => 'cool item'
877
                    ],
878
                    [
879
                        'item_name' => 'another super item'
880
                    ],
881
                ],
882
            ]],
883
            [[
884
                'total' => 33,
885
                'tracking_number' => null,
886
                'item' => [
887
                    [
888
                        'item_name' => 'Coca Cola'
889
                    ],
890
                ],
891
            ]],
892
            [[
893
                'total' => 55,
894
                'tracking_number' => '13122333',
895
                'item' => [
896
                    [
897
                        'item_name' => 'Pepsi'
898
                    ],
899
                ],
900
            ]],
901
            [[
902
                'total' => 11,
903
                'tracking_number' => '13343443',
904
                'item' => [
905
                    [
906
                        'item_name' => 'pants'
907
                    ],
908
                ],
909
            ]],
910
        ];
911
912
        $action = $this->getAction([$unit1, $unit2, $unit3], $expected);
913
        $action->process($this->getResultMock());
914
    }
915
916
    /**
917
     * test inconsistent siblings process
918
     * when some of the sibling can be absent for current row
919
     */
920
    public function testUnexistingChildren()
921
    {
922
        $unit1 = $this->getUnit('customer');
923
        $unit1->setReversedMapping([
924
            'email' => 'map.email'
925
        ]);
926
        $unit1->setReversedConnection([
927
            'customer_id' => 'id',
928
        ]);
929
        $unit1->setMapping([
930
            'id' => 'map.customer_id',
931
            'email' => 'map.email',
932
        ]);
933
        $unit1->setFilesystem($this->getFS(
934
            [
935
                [1, '[email protected]'],
936
                [2, '[email protected]'],
937
                [3, '[email protected]'],
938
                [4, '[email protected]'],
939
                false,
940
            ]
941
        ));
942
        $unit1->setIsEntityCondition(function (MapInterface $map) {
943
            return !empty($map['email']);
944
        });
945
        $unit1->setTmpFileName('customer_tmp.csv');
946
947
        $unit2 = $this->getUnit('address');
948
        $unit2->setReversedMapping([
949
            'city' => 'map.city',
950
        ]);
951
        $unit2->setReversedConnection([
952
            'customer_id' => 'customer_id',
953
        ]);
954
        $unit2->setMapping([
955
            'id' => 'map.incr("address_id", 1)',
956
            'city' => 'map.city',
957
            'customer_id' => 'map.customer_id',
958
        ]);
959
        $unit2->setFilesystem($this->getFS(
960
            [
961
                [1, 'Kiev', 1],
962
                [2, 'Chicago', 1],
963
                [3, 'Wroclaw', 2],
964
                [4, 'Warsaw', 4],
965
                [5, 'Donetsk', 4],
966
                false,
967
            ]
968
        ));
969
        $unit2->setTmpFileName('address_tmp.csv');
970
        $unit2->setParent($unit1);
971
        $unit2->setOptional(true);
972
973
        $expected = [
974
            [[
975
                'email' => '[email protected]',
976
                'address' => [
977
                    [
978
                        'city' => 'Kiev'
979
                    ],
980
                    [
981
                        'city' => 'Chicago'
982
                    ],
983
                ],
984
            ]],
985
            [[
986
                'email' => '[email protected]',
987
                'address' => [
988
                    [
989
                        'city' => 'Wroclaw'
990
                    ],
991
                ],
992
            ]],
993
            [[
994
                'email' => '[email protected]',
995
                'address' => [
996
                    [
997
                        'city' => null,
998
                    ],
999
                ],
1000
            ]],
1001
            [[
1002
                'email' => '[email protected]',
1003
                'address' => [
1004
                    [
1005
                        'city' => 'Warsaw'
1006
                    ],
1007
                    [
1008
                        'city' => 'Donetsk'
1009
                    ],
1010
                ],
1011
            ]],
1012
        ];
1013
1014
        $action = $this->getAction([$unit1, $unit2], $expected);
1015
        $action->process($this->getResultMock());
1016
    }
1017
1018
1019
    /**
1020
     * test process with both optional siblings and children
1021
     */
1022
    public function testDoubleOptionalProcess()
1023
    {
1024
        $unit1 = $this->getUnit('shipment');
1025
        $unit1->setReversedMapping([
1026
            'total' => 'map.total'
1027
        ]);
1028
        $unit1->setReversedConnection([
1029
            'shipment_id' => 'shipment_id',
1030
        ]);
1031
        $unit1->setMapping([
1032
            'shipment_id' => 'map.shipment_id',
1033
            'total' => 'map.total',
1034
        ]);
1035
        $unit1->setFilesystem($this->getFS(
1036
            [
1037
                [1, 30],
1038
                [2, 33],
1039
                [3, 55],
1040
                [4, 11],
1041
                false,
1042
            ]
1043
        ));
1044
        $unit1->setIsEntityCondition(function (MapInterface $map) {
1045
            return !empty($map['shipment_id']);
1046
        });
1047
        $unit1->setTmpFileName('shipment_tmp.csv');
1048
1049
        $unit2 = $this->getUnit('item');
1050
        $unit2->setReversedMapping([
1051
            'item_name' => 'map.name',
1052
        ]);
1053
        $unit2->setReversedConnection([
1054
            'shipment_id' => 'shipment_id',
1055
        ]);
1056
        $unit2->setMapping([
1057
            'id' => 'map.incr("item_id", 1)',
1058
            'name' => 'map.item_name',
1059
            'shipment_id' => 'map.shipment_id',
1060
        ]);
1061
        $unit2->setFilesystem($this->getFS(
1062
            [
1063
                [1, 'cool item', 1],
1064
                [2, 'another super item', 1],
1065
                [3, 'Coca Cola', 2],
1066
                [4, 'Pepsi', 3],
1067
                false,
1068
                false,
1069
            ]
1070
        ));
1071
        $unit2->setTmpFileName('item_tmp.csv');
1072
        $unit2->setParent($unit1);
1073
        $unit2->setOptional(true);
1074
1075
        $unit3 = $this->getUnit('tracking');
1076
        $unit3->setReversedMapping([
1077
            'tracking_number' => 'map.tracking_number',
1078
        ]);
1079
        $unit3->setReversedConnection([
1080
            'shipment_id' => 'shipment_id',
1081
        ]);
1082
        $unit3->setMapping([
1083
            'id' => 'map.incr("track_id", 1)',
1084
            'tracking_number' => 'map.tracking_number',
1085
            'shipment_id' => 'map.shipment_id',
1086
        ]);
1087
        $unit3->setFilesystem($this->getFS(
1088
            [
1089
                [1, '13122333', 3],
1090
                [2, '13343443', 4],
1091
                false,
1092
            ]
1093
        ));
1094
        $unit3->setTmpFileName('tracking_tmp.csv');
1095
        $unit3->addSibling($unit1);
1096
        $unit3->setOptional(true);
1097
1098
        $expected = [
1099
            [[
1100
                'total' => 30,
1101
                'tracking_number' => null,
1102
                'item' => [
1103
                    [
1104
                        'item_name' => 'cool item'
1105
                    ],
1106
                    [
1107
                        'item_name' => 'another super item'
1108
                    ],
1109
                ],
1110
            ]],
1111
            [[
1112
                'total' => 33,
1113
                'tracking_number' => null,
1114
                'item' => [
1115
                    [
1116
                        'item_name' => 'Coca Cola'
1117
                    ],
1118
                ],
1119
            ]],
1120
            [[
1121
                'total' => 55,
1122
                'tracking_number' => '13122333',
1123
                'item' => [
1124
                    [
1125
                        'item_name' => 'Pepsi'
1126
                    ],
1127
                ],
1128
            ]],
1129
            [[
1130
                'total' => 11,
1131
                'tracking_number' => '13343443',
1132
                'item' => [
1133
                    [
1134
                        'item_name' => null
1135
                    ],
1136
                ],
1137
            ]],
1138
        ];
1139
1140
        $action = $this->getAction([$unit1, $unit2, $unit3], $expected);
1141
        $action->process($this->getResultMock());
1142
    }
1143
1144
    /**
1145
     * test process with a lot of missing trackings
1146
     */
1147
    public function testOptionalTracking2()
1148
    {
1149
        $unit1 = $this->getUnit('shipment');
1150
        $unit1->setReversedMapping([
1151
            'total' => 'map.total'
1152
        ]);
1153
        $unit1->setReversedConnection([
1154
            'shipment_id' => 'shipment_id',
1155
        ]);
1156
        $unit1->setMapping([
1157
            'shipment_id' => 'map.shipment_id',
1158
            'total' => 'map.total',
1159
        ]);
1160
        $unit1->setFilesystem($this->getFS(
1161
            [
1162
                [1, 30],
1163
                [2, 33],
1164
                [3, 55],
1165
                [4, 11],
1166
                [5, 22],
1167
                false,
1168
            ]
1169
        ));
1170
        $unit1->setIsEntityCondition(function (MapInterface $map) {
1171
            return !empty($map['shipment_id']);
1172
        });
1173
        $unit1->setTmpFileName('shipment_tmp.csv');
1174
1175
        $unit2 = $this->getUnit('item');
1176
        $unit2->setReversedMapping([
1177
            'item_name' => 'map.name',
1178
        ]);
1179
        $unit2->setReversedConnection([
1180
            'shipment_id' => 'shipment_id',
1181
        ]);
1182
        $unit2->setMapping([
1183
            'id' => 'map.incr("item_id", 1)',
1184
            'name' => 'map.item_name',
1185
            'shipment_id' => 'map.shipment_id',
1186
        ]);
1187
        $unit2->setFilesystem($this->getFS(
1188
            [
1189
                [1, 'cool item', 1],
1190
                [2, 'another super item', 1],
1191
                [3, 'Coca Cola', 2],
1192
                [4, 'Pepsi', 3],
1193
                [5, 'Zope', 4],
1194
                [6, 'Bingo', 5],
1195
                false,
1196
            ]
1197
        ));
1198
        $unit2->setTmpFileName('item_tmp.csv');
1199
        $unit2->setParent($unit1);
1200
1201
        $unit3 = $this->getUnit('tracking');
1202
        $unit3->setReversedMapping([
1203
            'tracking_number' => 'map.tracking_number',
1204
        ]);
1205
        $unit3->setReversedConnection([
1206
            'shipment_id' => 'shipment_id',
1207
        ]);
1208
        $unit3->setMapping([
1209
            'id' => 'map.incr("track_id", 1)',
1210
            'tracking_number' => 'map.tracking_number',
1211
            'shipment_id' => 'map.shipment_id',
1212
        ]);
1213
        $unit3->setFilesystem($this->getFS(
1214
            [
1215
                [1, '13122333', 3],
1216
                false,
1217
                false,
1218
                false,
1219
            ]
1220
        ));
1221
        $unit3->setTmpFileName('tracking_tmp.csv');
1222
        $unit3->addSibling($unit1);
1223
        $unit3->setOptional(true);
1224
1225
        $expected = [
1226
            [[
1227
                'total' => 30,
1228
                'tracking_number' => null,
1229
                'item' => [
1230
                    [
1231
                        'item_name' => 'cool item'
1232
                    ],
1233
                    [
1234
                        'item_name' => 'another super item'
1235
                    ],
1236
                ],
1237
            ]],
1238
            [[
1239
                'total' => 33,
1240
                'tracking_number' => null,
1241
                'item' => [
1242
                    [
1243
                        'item_name' => 'Coca Cola'
1244
                    ],
1245
                ],
1246
            ]],
1247
            [[
1248
                'total' => 55,
1249
                'tracking_number' => '13122333',
1250
                'item' => [
1251
                    [
1252
                        'item_name' => 'Pepsi'
1253
                    ],
1254
                ],
1255
            ]],
1256
            [[
1257
                'total' => 11,
1258
                'tracking_number' => null,
1259
                'item' => [
1260
                    [
1261
                        'item_name' => 'Zope',
1262
                    ],
1263
                ],
1264
            ]],
1265
            [[
1266
                'total' => 22,
1267
                'tracking_number' => null,
1268
                'item' => [
1269
                    [
1270
                        'item_name' => 'Bingo',
1271
                    ],
1272
                ],
1273
            ]],
1274
        ];
1275
1276
        $action = $this->getAction([$unit1, $unit2, $unit3], $expected);
1277
        $action->process($this->getResultMock());
1278
    }
1279
}
1280