Passed
Push — partial-fix-4622 ( 983d36 )
by Sam
07:19
created

ArrayListTest::testColumn()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 9
nc 1
nop 0
dl 0
loc 13
rs 9.9666
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\ORM\Tests;
4
5
use SilverStripe\Dev\Deprecation;
6
use SilverStripe\Dev\SapphireTest;
7
use SilverStripe\ORM\ArrayList;
8
use SilverStripe\ORM\DataObject;
9
use SilverStripe\ORM\Filterable;
10
use stdClass;
11
12
class ArrayListTest extends SapphireTest
13
{
14
15
    public function testPushOperator()
16
    {
17
        $list = new ArrayList(
18
            array(
19
            array('Num' => 1)
20
            )
21
        );
22
23
        $list[] = array('Num' => 2);
24
        $this->assertEquals(2, count($list));
25
        $this->assertEquals(array('Num' => 2), $list->last());
26
27
        $list[] = array('Num' => 3);
28
        $this->assertEquals(3, count($list));
29
        $this->assertEquals(array('Num' => 3), $list->last());
30
    }
31
32
    public function testArrayAccessExists()
33
    {
34
        $list = new ArrayList(
35
            array(
36
            $one = new DataObject(array('Title' => 'one')),
37
            $two = new DataObject(array('Title' => 'two')),
0 ignored issues
show
Unused Code introduced by
The assignment to $two is dead and can be removed.
Loading history...
38
            $three = new DataObject(array('Title' => 'three'))
0 ignored issues
show
Unused Code introduced by
The assignment to $three is dead and can be removed.
Loading history...
39
            )
40
        );
41
        $this->assertEquals(count($list), 3);
42
        $this->assertTrue(isset($list[0]), 'First item in the set is set');
43
        $this->assertEquals($one, $list[0], 'First item in the set is accessible by array notation');
44
    }
45
46
    public function testArrayAccessUnset()
47
    {
48
        $list = new ArrayList(
49
            array(
50
            $one = new DataObject(array('Title' => 'one')),
0 ignored issues
show
Unused Code introduced by
The assignment to $one is dead and can be removed.
Loading history...
51
            $two = new DataObject(array('Title' => 'two')),
0 ignored issues
show
Unused Code introduced by
The assignment to $two is dead and can be removed.
Loading history...
52
            $three = new DataObject(array('Title' => 'three'))
0 ignored issues
show
Unused Code introduced by
The assignment to $three is dead and can be removed.
Loading history...
53
            )
54
        );
55
        unset($list[0]);
56
        $this->assertEquals(count($list), 2);
57
    }
58
59
    public function testArrayAccessSet()
60
    {
61
        $list = new ArrayList();
62
        $this->assertEquals(0, count($list));
63
        $list['testing!'] = $test = new DataObject(array('Title' => 'I\'m testing!'));
64
        $this->assertEquals($test, $list['testing!'], 'Set item is accessible by the key we set it as');
65
    }
66
67
    public function testCount()
68
    {
69
        $list = new ArrayList();
70
        $this->assertEquals(0, $list->count());
71
        $list = new ArrayList(array(1, 2, 3));
72
        $this->assertEquals(3, $list->count());
73
    }
74
75
    public function testExists()
76
    {
77
        $list = new ArrayList();
78
        $this->assertFalse($list->exists());
79
        $list = new ArrayList(array(1, 2, 3));
80
        $this->assertTrue($list->exists());
81
    }
82
83
    public function testToNestedArray()
84
    {
85
        $list = new ArrayList(
86
            array(
87
            array('First' => 'FirstFirst', 'Second' => 'FirstSecond'),
88
            (object) array('First' => 'SecondFirst', 'Second' => 'SecondSecond'),
89
            new ArrayListTest\TestObject('ThirdFirst', 'ThirdSecond')
90
            )
91
        );
92
93
        $this->assertEquals(
94
            $list->toNestedArray(),
95
            array(
96
            array('First' => 'FirstFirst', 'Second' => 'FirstSecond'),
97
            array('First' => 'SecondFirst', 'Second' => 'SecondSecond'),
98
            array('First' => 'ThirdFirst', 'Second' => 'ThirdSecond')
99
            )
100
        );
101
    }
102
103
    public function testEach()
104
    {
105
        $list = new ArrayList(array(1, 2, 3));
106
107
        $count = 0;
108
        $test = $this;
109
110
        $list->each(
111
            function ($item) use (&$count, $test) {
112
                $count++;
113
114
                $test->assertTrue(is_int($item));
115
            }
116
        );
117
118
        $this->assertEquals($list->Count(), $count);
119
    }
120
121
    public function testLimit()
122
    {
123
        $list = new ArrayList(
124
            array(
125
            array('Key' => 1), array('Key' => 2), array('Key' => 3)
126
            )
127
        );
128
        $this->assertEquals(
129
            $list->limit(2, 1)->toArray(),
130
            array(
131
            array('Key' => 2), array('Key' => 3)
132
            )
133
        );
134
    }
135
136
    /**
137
     * @expectedException PHPUnit_Framework_Error
138
     */
139
    public function testZeroLimit()
140
    {
141
        Deprecation::notification_version('4.3.0');
142
        $list = new ArrayList([
143
            ['Key' => 1],
144
            ['Key' => 2],
145
        ]);
146
        $list->limit(0);
147
    }
148
149
    public function testAddRemove()
150
    {
151
        $list = new ArrayList(
152
            array(
153
            array('Key' => 1), array('Key' => 2)
154
            )
155
        );
156
157
        $list->add(array('Key' => 3));
158
        $this->assertEquals(
159
            $list->toArray(),
160
            array(
161
            array('Key' => 1), array('Key' => 2), array('Key' => 3)
162
            )
163
        );
164
165
        $list->remove(array('Key' => 2));
166
        $this->assertEquals(
167
            array_values($list->toArray()),
168
            array(
169
            array('Key' => 1), array('Key' => 3)
170
            )
171
        );
172
    }
173
174
    public function testReplace()
175
    {
176
        $list = new ArrayList(
177
            array(
178
            array('Key' => 1),
179
            $two = (object) array('Key' => 2),
180
            (object) array('Key' => 3)
181
            )
182
        );
183
184
        $this->assertEquals(array('Key' => 1), $list[0]);
185
        $list->replace(array('Key' => 1), array('Replaced' => 1));
186
        $this->assertEquals(3, count($list));
187
        $this->assertEquals(array('Replaced' => 1), $list[0]);
188
189
        $this->assertEquals($two, $list[1]);
190
        $list->replace($two, array('Replaced' => 2));
191
        $this->assertEquals(3, count($list));
192
        $this->assertEquals(array('Replaced' => 2), $list[1]);
193
    }
194
195
    public function testMerge()
196
    {
197
        $list = new ArrayList(
198
            array(
199
            array('Num' => 1), array('Num' => 2)
200
            )
201
        );
202
        $list->merge(
203
            array(
204
            array('Num' => 3), array('Num' => 4)
205
            )
206
        );
207
208
        $this->assertEquals(4, count($list));
209
        $this->assertEquals(
210
            $list->toArray(),
211
            array(
212
            array('Num' => 1), array('Num' => 2), array('Num' => 3), array('Num' => 4)
213
            )
214
        );
215
    }
216
217
    public function testRemoveDuplicates()
218
    {
219
        $list = new ArrayList(
220
            array(
221
            array('ID' => 1, 'Field' => 1),
222
            array('ID' => 2, 'Field' => 2),
223
            array('ID' => 3, 'Field' => 3),
224
            array('ID' => 4, 'Field' => 1),
225
            (object) array('ID' => 5, 'Field' => 2)
226
            )
227
        );
228
229
        $this->assertEquals(5, count($list));
230
        $list->removeDuplicates();
231
        $this->assertEquals(5, count($list));
232
233
        $list->removeDuplicates('Field');
234
        $this->assertEquals(3, count($list));
235
        $this->assertEquals(array(1, 2, 3), $list->column('Field'));
236
        $this->assertEquals(array(1, 2, 3), $list->column('ID'));
237
    }
238
239
    public function testPushPop()
240
    {
241
        $list = new ArrayList(array('Num' => 1));
242
        $this->assertEquals(1, count($list));
243
244
        $list->push(array('Num' => 2));
245
        $this->assertEquals(2, count($list));
246
        $this->assertEquals(array('Num' => 2), $list->last());
247
248
        $list->push(array('Num' => 3));
249
        $this->assertEquals(3, count($list));
250
        $this->assertEquals(array('Num' => 3), $list->last());
251
252
        $this->assertEquals(array('Num' => 3), $list->pop());
253
        $this->assertEquals(2, count($list));
254
        $this->assertEquals(array('Num' => 2), $list->last());
255
    }
256
257
    public function testShiftUnshift()
258
    {
259
        $list = new ArrayList(array('Num' => 1));
260
        $this->assertEquals(1, count($list));
261
262
        $list->unshift(array('Num' => 2));
263
        $this->assertEquals(2, count($list));
264
        $this->assertEquals(array('Num' => 2), $list->first());
265
266
        $list->unshift(array('Num' => 3));
267
        $this->assertEquals(3, count($list));
268
        $this->assertEquals(array('Num' => 3), $list->first());
269
270
        $this->assertEquals(array('Num' => 3), $list->shift());
271
        $this->assertEquals(2, count($list));
272
        $this->assertEquals(array('Num' => 2), $list->first());
273
    }
274
275
    public function testFirstLast()
276
    {
277
        $list = new ArrayList(
278
            array(
279
            array('Key' => 1), array('Key' => 2), array('Key' => 3)
280
            )
281
        );
282
        $this->assertEquals($list->first(), array('Key' => 1));
283
        $this->assertEquals($list->last(), array('Key' => 3));
284
    }
285
286
    public function testMap()
287
    {
288
        $list = new ArrayList(
289
            array(
290
            array('ID' => 1, 'Name' => 'Steve',),
291
            (object) array('ID' => 3, 'Name' => 'Bob'),
292
            array('ID' => 5, 'Name' => 'John')
293
            )
294
        );
295
        $map = $list->map('ID', 'Name');
296
        // Items added after calling map should not be included retroactively
297
        $list->add(array('ID' => 7, 'Name' => 'Andrew'));
298
        $this->assertInstanceOf('SilverStripe\\ORM\\Map', $map);
299
        $this->assertEquals(
300
            array(
301
            1 => 'Steve',
302
            3 => 'Bob',
303
            5 => 'John'
304
            ),
305
            $map->toArray()
306
        );
307
    }
308
309
    public function testFind()
310
    {
311
        $list = new ArrayList(
312
            array(
313
            array('Name' => 'Steve'),
314
            (object) array('Name' => 'Bob'),
315
            array('Name' => 'John')
316
            )
317
        );
318
        $this->assertEquals(
319
            $list->find('Name', 'Bob'),
320
            (object) array(
321
            'Name' => 'Bob'
322
            )
323
        );
324
    }
325
326
    public function testColumn()
327
    {
328
        $list = new ArrayList(
329
            array(
330
            array('Name' => 'Steve'),
331
            (object) array('Name' => 'Bob'),
332
            array('Name' => 'John')
333
            )
334
        );
335
        $this->assertEquals(
336
            $list->column('Name'),
337
            array(
338
            'Steve', 'Bob', 'John'
339
            )
340
        );
341
    }
342
343
    public function testSortSimpleDefaultIsSortedASC()
344
    {
345
        $list = new ArrayList(
346
            array(
347
            array('Name' => 'Steve'),
348
            (object) array('Name' => 'Bob'),
349
            array('Name' => 'John'),
350
            array('Name' => 'bonny'),
351
            )
352
        );
353
354
        // Unquoted name
355
        $list1 = $list->sort('Name');
356
        $this->assertEquals(
357
            array(
358
            (object) array('Name' => 'Bob'),
359
            array('Name' => 'bonny'),
360
            array('Name' => 'John'),
361
            array('Name' => 'Steve'),
362
            ),
363
            $list1->toArray()
364
        );
365
366
        // Quoted name name
367
        $list2 = $list->sort('"Name"');
368
        $this->assertEquals(
369
            array(
370
            (object) array('Name' => 'Bob'),
371
            array('Name' => 'bonny'),
372
            array('Name' => 'John'),
373
            array('Name' => 'Steve'),
374
            ),
375
            $list2->toArray()
376
        );
377
378
        // Array (non-associative)
379
        $list3 = $list->sort(array('"Name"'));
380
        $this->assertEquals(
381
            array(
382
            (object) array('Name' => 'Bob'),
383
            array('Name' => 'bonny'),
384
            array('Name' => 'John'),
385
            array('Name' => 'Steve'),
386
            ),
387
            $list3->toArray()
388
        );
389
390
        // Quoted name name with table
391
        $list4 = $list->sort('"Record"."Name"');
392
        $this->assertEquals(
393
            array(
394
            (object) array('Name' => 'Bob'),
395
            array('Name' => 'bonny'),
396
            array('Name' => 'John'),
397
            array('Name' => 'Steve')
398
            ),
399
            $list4->toArray()
400
        );
401
402
        // Quoted name name with table (desc)
403
        $list5 = $list->sort('"Record"."Name" DESC');
404
        $this->assertEquals(
405
            array(
406
            array('Name' => 'Steve'),
407
            array('Name' => 'John'),
408
            array('Name' => 'bonny'),
409
            (object) array('Name' => 'Bob')
410
            ),
411
            $list5->toArray()
412
        );
413
414
        // Table without quotes
415
        $list6 = $list->sort('Record.Name');
416
        $this->assertEquals(
417
            array(
418
            (object) array('Name' => 'Bob'),
419
            array('Name' => 'bonny'),
420
            array('Name' => 'John'),
421
            array('Name' => 'Steve')
422
            ),
423
            $list6->toArray()
424
        );
425
426
        // Check original list isn't altered
427
        $this->assertEquals(
428
            array(
429
            array('Name' => 'Steve'),
430
            (object) array('Name' => 'Bob'),
431
            array('Name' => 'John'),
432
            array('Name' => 'bonny'),
433
            ),
434
            $list->toArray()
435
        );
436
    }
437
438
    public function testMixedCaseSort()
439
    {
440
        // Note: Natural sorting is not expected, so if 'bonny10' were included
441
        // below we would expect it to appear between bonny1 and bonny2. That's
442
        // undesirable though so we're not enforcing it in tests.
443
        $original = array(
444
            array('Name' => 'Steve'),
445
            (object) array('Name' => 'Bob'),
446
            array('Name' => 'John'),
447
            array('Name' => 'bonny'),
448
            array('Name' => 'bonny1'),
449
            //array('Name' => 'bonny10'),
450
            array('Name' => 'bonny2'),
451
        );
452
453
        $list = new ArrayList($original);
454
455
        $expected = array(
456
            (object) array('Name' => 'Bob'),
457
            array('Name' => 'bonny'),
458
            array('Name' => 'bonny1'),
459
            //array('Name' => 'bonny10'),
460
            array('Name' => 'bonny2'),
461
            array('Name' => 'John'),
462
            array('Name' => 'Steve'),
463
        );
464
465
        // Unquoted name
466
        $list1 = $list->sort('Name');
467
        $this->assertEquals($expected, $list1->toArray());
468
469
        // Quoted name name
470
        $list2 = $list->sort('"Name"');
471
        $this->assertEquals($expected, $list2->toArray());
472
473
        // Array (non-associative)
474
        $list3 = $list->sort(array('"Name"'));
475
        $this->assertEquals($expected, $list3->toArray());
476
477
        // Check original list isn't altered
478
        $this->assertEquals($original, $list->toArray());
479
    }
480
481
    public function testSortSimpleASCOrder()
482
    {
483
        $list = new ArrayList(
484
            array(
485
            array('Name' => 'Steve'),
486
            (object) array('Name' => 'Bob'),
487
            array('Name' => 'John')
488
            )
489
        );
490
491
        // Sort two arguments
492
        $list1 = $list->sort('Name', 'ASC');
493
        $this->assertEquals(
494
            $list1->toArray(),
495
            array(
496
            (object) array('Name' => 'Bob'),
497
            array('Name' => 'John'),
498
            array('Name' => 'Steve')
499
            )
500
        );
501
502
        // Sort single string
503
        $list2 = $list->sort('Name asc');
504
        $this->assertEquals(
505
            $list2->toArray(),
506
            array(
507
            (object) array('Name' => 'Bob'),
508
            array('Name' => 'John'),
509
            array('Name' => 'Steve')
510
            )
511
        );
512
513
        // Sort quoted string
514
        $list3 = $list->sort('"Name" ASCENDING');
515
        $this->assertEquals(
516
            $list3->toArray(),
517
            array(
518
            (object) array('Name' => 'Bob'),
519
            array('Name' => 'John'),
520
            array('Name' => 'Steve')
521
            )
522
        );
523
524
        // Sort array specifier
525
        $list4 = $list->sort(array('Name' => 'ascending'));
526
        $this->assertEquals(
527
            $list4->toArray(),
528
            array(
529
            (object) array('Name' => 'Bob'),
530
            array('Name' => 'John'),
531
            array('Name' => 'Steve')
532
            )
533
        );
534
535
        // Check original list isn't altered
536
        $this->assertEquals(
537
            $list->toArray(),
538
            array(
539
            array('Name' => 'Steve'),
540
            (object) array('Name' => 'Bob'),
541
            array('Name' => 'John')
542
            )
543
        );
544
    }
545
546
    public function testSortSimpleDESCOrder()
547
    {
548
        $list = new ArrayList(
549
            array(
550
            array('Name' => 'Steve'),
551
            (object) array('Name' => 'Bob'),
552
            array('Name' => 'John')
553
            )
554
        );
555
556
        // Sort two arguments
557
        $list1 = $list->sort('Name', 'DESC');
558
        $this->assertEquals(
559
            $list1->toArray(),
560
            array(
561
            array('Name' => 'Steve'),
562
            array('Name' => 'John'),
563
            (object) array('Name' => 'Bob')
564
            )
565
        );
566
567
        // Sort single string
568
        $list2 = $list->sort('Name desc');
569
        $this->assertEquals(
570
            $list2->toArray(),
571
            array(
572
            array('Name' => 'Steve'),
573
            array('Name' => 'John'),
574
            (object) array('Name' => 'Bob')
575
            )
576
        );
577
578
        // Sort quoted string
579
        $list3 = $list->sort('"Name" DESCENDING');
580
        $this->assertEquals(
581
            $list3->toArray(),
582
            array(
583
            array('Name' => 'Steve'),
584
            array('Name' => 'John'),
585
            (object) array('Name' => 'Bob')
586
            )
587
        );
588
589
        // Sort array specifier
590
        $list4 = $list->sort(array('Name' => 'descending'));
591
        $this->assertEquals(
592
            $list4->toArray(),
593
            array(
594
            array('Name' => 'Steve'),
595
            array('Name' => 'John'),
596
            (object) array('Name' => 'Bob')
597
            )
598
        );
599
600
        // Check original list isn't altered
601
        $this->assertEquals(
602
            $list->toArray(),
603
            array(
604
            array('Name' => 'Steve'),
605
            (object) array('Name' => 'Bob'),
606
            array('Name' => 'John')
607
            )
608
        );
609
    }
610
611
    public function testSortNumeric()
612
    {
613
        $list = new ArrayList(
614
            array(
615
            array('Sort' => 0),
616
            array('Sort' => -1),
617
            array('Sort' => 1),
618
            array('Sort' => -2),
619
            array('Sort' => 2),
620
            array('Sort' => -10),
621
            array('Sort' => 10)
622
            )
623
        );
624
625
        // Sort descending
626
        $list1 = $list->sort('Sort', 'DESC');
627
        $this->assertEquals(
628
            array(
629
            array('Sort' => 10),
630
            array('Sort' => 2),
631
            array('Sort' => 1),
632
            array('Sort' => 0),
633
            array('Sort' => -1),
634
            array('Sort' => -2),
635
            array('Sort' => -10)
636
            ),
637
            $list1->toArray()
638
        );
639
640
        // Sort ascending
641
        $list1 = $list->sort('Sort', 'ASC');
642
        $this->assertEquals(
643
            array(
644
            array('Sort' => -10),
645
            array('Sort' => -2),
646
            array('Sort' => -1),
647
            array('Sort' => 0),
648
            array('Sort' => 1),
649
            array('Sort' => 2),
650
            array('Sort' => 10)
651
            ),
652
            $list1->toArray()
653
        );
654
    }
655
656
    public function testReverse()
657
    {
658
        $list = new ArrayList(
659
            array(
660
            array('Name' => 'John'),
661
            array('Name' => 'Bob'),
662
            array('Name' => 'Steve')
663
            )
664
        );
665
666
        $list = $list->sort('Name', 'ASC');
667
        $list = $list->reverse();
668
669
        $this->assertEquals(
670
            $list->toArray(),
671
            array(
672
            array('Name' => 'Steve'),
673
            array('Name' => 'John'),
674
            array('Name' => 'Bob')
675
            )
676
        );
677
    }
678
679
    public function testSimpleMultiSort()
680
    {
681
        $list = new ArrayList(
682
            array(
683
            (object) array('Name'=>'Object1', 'F1'=>1, 'F2'=>2, 'F3'=>3),
684
            (object) array('Name'=>'Object2', 'F1'=>2, 'F2'=>1, 'F3'=>4),
685
            (object) array('Name'=>'Object3', 'F1'=>5, 'F2'=>2, 'F3'=>2),
686
            )
687
        );
688
689
        $list = $list->sort('F3', 'ASC');
690
        $this->assertEquals($list->first()->Name, 'Object3', 'Object3 should be first in the list');
691
        $this->assertEquals($list->last()->Name, 'Object2', 'Object2 should be last in the list');
692
693
        $list = $list->sort('F3', 'DESC');
694
        $this->assertEquals($list->first()->Name, 'Object2', 'Object2 should be first in the list');
695
        $this->assertEquals($list->last()->Name, 'Object3', 'Object3 should be last in the list');
696
    }
697
698
    public function testMultiSort()
699
    {
700
        $list = new ArrayList(
701
            array(
702
            (object) array('ID'=>3, 'Name'=>'Bert', 'Importance'=>1),
703
            (object) array('ID'=>1, 'Name'=>'Aron', 'Importance'=>2),
704
            (object) array('ID'=>2, 'Name'=>'Aron', 'Importance'=>1),
705
            )
706
        );
707
708
        $list = $list->sort(array('Name'=>'ASC', 'Importance'=>'ASC'));
709
        $this->assertEquals($list->first()->ID, 2, 'Aron.2 should be first in the list');
710
        $this->assertEquals($list->last()->ID, 3, 'Bert.3 should be last in the list');
711
712
        $list = $list->sort(array('Name'=>'ASC', 'Importance'=>'DESC'));
713
        $this->assertEquals($list->first()->ID, 1, 'Aron.2 should be first in the list');
714
        $this->assertEquals($list->last()->ID, 3, 'Bert.3 should be last in the list');
715
    }
716
717
    /**
718
     * Check that we don't cause recursion errors with array_multisort() and circular dependencies
719
     */
720
    public function testSortWithCircularDependencies()
721
    {
722
        $itemA = new stdClass;
723
        $childA = new stdClass;
724
        $itemA->child = $childA;
725
        $childA->parent = $itemA;
726
        $itemA->Sort = 1;
727
728
        $itemB = new stdClass;
729
        $childB = new stdClass;
730
        $itemB->child = $childB;
731
        $childB->parent = $itemB;
732
        $itemB->Sort = 1;
733
734
        $items = new ArrayList;
735
        $items->add($itemA);
736
        $items->add($itemB);
737
738
        // This call will trigger a fatal error if there are issues with circular dependencies
739
        $items->sort('Sort');
740
    }
741
742
    /**
743
     * $list->filter('Name', 'bob'); // only bob in the list
744
     */
745
    public function testSimpleFilter()
746
    {
747
        $list = new ArrayList(
748
            array(
749
            array('Name' => 'Steve'),
750
            (object) array('Name' => 'Bob'),
751
            array('Name' => 'John')
752
            )
753
        );
754
        $list = $list->filter('Name', 'Bob');
755
        $this->assertEquals(array((object)array('Name'=>'Bob')), $list->toArray(), 'List should only contain Bob');
756
    }
757
758
    /**
759
     * $list->filter('Name', array('Steve', 'John'); // Steve and John in list
760
     */
761
    public function testSimpleFilterWithMultiple()
762
    {
763
        $list = new ArrayList(
764
            array(
765
            array('Name' => 'Steve'),
766
            (object) array('Name' => 'Bob'),
767
            array('Name' => 'John')
768
            )
769
        );
770
771
        $expected = array(
772
            array('Name' => 'Steve'),
773
            array('Name' => 'John')
774
        );
775
        $list = $list->filter('Name', array('Steve','John'));
776
        $this->assertEquals($expected, $list->toArray(), 'List should only contain Steve and John');
777
    }
778
779
    /**
780
     * $list->filter('Name', array('Steve', 'John'); // negative version
781
     */
782
    public function testSimpleFilterWithMultipleNoMatch()
783
    {
784
        $list = new ArrayList(
785
            array(
786
            array('Name' => 'Steve', 'ID' => 1),
787
            (object) array('Name' => 'Steve', 'ID' => 2),
788
            array('Name' => 'John', 'ID' => 2)
789
            )
790
        );
791
        $list = $list->filter(array('Name'=>'Clair'));
792
        $this->assertEquals(array(), $list->toArray(), 'List should be empty');
793
    }
794
795
    /**
796
     * $list->filter(array('Name'=>'bob, 'Age'=>21)); // bob with the Age 21 in list
797
     */
798
    public function testMultipleFilter()
799
    {
800
        $list = new ArrayList(
801
            array(
802
            array('Name' => 'Steve', 'ID' => 1),
803
            (object) array('Name' => 'Steve', 'ID' => 2),
804
            array('Name' => 'John', 'ID' => 2)
805
            )
806
        );
807
        $list = $list->filter(array('Name'=>'Steve', 'ID'=>2));
808
        $this->assertEquals(
809
            array((object)array('Name'=>'Steve', 'ID'=>2)),
810
            $list->toArray(),
811
            'List should only contain object Steve'
812
        );
813
    }
814
815
    /**
816
     * $list->filter(array('Name'=>'bob, 'Age'=>21)); // negative version
817
     */
818
    public function testMultipleFilterNoMatch()
819
    {
820
        $list = new ArrayList(
821
            array(
822
            array('Name' => 'Steve', 'ID' => 1),
823
            (object) array('Name' => 'Steve', 'ID' => 2),
824
            array('Name' => 'John', 'ID' => 2)
825
            )
826
        );
827
        $list = $list->filter(array('Name'=>'Steve', 'ID'=>4));
828
        $this->assertEquals(array(), $list->toArray(), 'List should be empty');
829
    }
830
831
    /**
832
     * $list->filter(array('Name'=>'Steve', 'Age'=>array(21, 43))); // Steve with the Age 21 or 43
833
     */
834
    public function testMultipleWithArrayFilter()
835
    {
836
        $list = new ArrayList(
837
            array(
838
            array('Name' => 'Steve', 'ID' => 1, 'Age'=>21),
839
            array('Name' => 'Steve', 'ID' => 2, 'Age'=>18),
840
            array('Name' => 'Clair', 'ID' => 2, 'Age'=>21),
841
            array('Name' => 'Steve', 'ID' => 3, 'Age'=>43)
842
            )
843
        );
844
845
        $list = $list->filter(array('Name'=>'Steve','Age'=>array(21, 43)));
846
847
        $expected = array(
848
            array('Name' => 'Steve', 'ID' => 1, 'Age'=>21),
849
            array('Name' => 'Steve', 'ID' => 3, 'Age'=>43)
850
        );
851
        $this->assertEquals(2, $list->count());
852
        $this->assertEquals($expected, $list->toArray(), 'List should only contain Steve and Steve');
853
    }
854
855
    /**
856
     * $list->filter(array('Name'=>array('aziz','bob'), 'Age'=>array(21, 43)));
857
     */
858
    public function testMultipleWithArrayFilterAdvanced()
859
    {
860
        $list = new ArrayList(
861
            array(
862
            array('Name' => 'Steve', 'ID' => 1, 'Age'=>21),
863
            array('Name' => 'Steve', 'ID' => 2, 'Age'=>18),
864
            array('Name' => 'Clair', 'ID' => 2, 'Age'=>21),
865
            array('Name' => 'Clair', 'ID' => 2, 'Age'=>52),
866
            array('Name' => 'Steve', 'ID' => 3, 'Age'=>43)
867
            )
868
        );
869
870
        $list = $list->filter(array('Name'=>array('Steve','Clair'),'Age'=>array(21, 43)));
871
872
        $expected = array(
873
            array('Name' => 'Steve', 'ID' => 1, 'Age'=>21),
874
            array('Name' => 'Clair', 'ID' => 2, 'Age'=>21),
875
            array('Name' => 'Steve', 'ID' => 3, 'Age'=>43)
876
        );
877
878
        $this->assertEquals(3, $list->count());
879
        $this->assertEquals($expected, $list->toArray(), 'List should only contain Steve and Steve and Clair');
880
    }
881
882
    public function testFilterAny()
883
    {
884
885
        $list = new ArrayList(
886
            array(
887
            $steve = array('Name' => 'Steve', 'ID' => 1, 'Age' => 21),
888
            $bob = array('Name' => 'Bob', 'ID' => 2, 'Age' => 18),
889
            $clair = array('Name' => 'Clair', 'ID' => 3, 'Age' => 21),
890
            $phil = array('Name' => 'Phil', 'ID' => 4, 'Age' => 21),
891
            $oscar = array('Name' => 'Oscar', 'ID' => 5, 'Age' => 52),
0 ignored issues
show
Unused Code introduced by
The assignment to $oscar is dead and can be removed.
Loading history...
892
            $mike = array('Name' => 'Mike', 'ID' => 6, 'Age' => 43),
893
            )
894
        );
895
896
        // only bob in the list
897
        //$list = $list->filterAny('Name', 'bob');
898
        $filteredList = $list->filterAny('Name', 'Bob')->toArray();
899
        $this->assertCount(1, $filteredList);
900
        $this->assertContains($bob, $filteredList);
901
902
        // azis or bob in the list
903
        //$list = $list->filterAny('Name', array('aziz', 'bob');
904
        $filteredList = $list->filterAny('Name', array('Aziz', 'Bob'))->toArray();
905
        $this->assertCount(1, $filteredList);
906
        $this->assertContains($bob, $filteredList);
907
908
        $filteredList = $list->filterAny('Name', array('Steve', 'Bob'))->toArray();
909
        $this->assertCount(2, $filteredList);
910
        $this->assertContains($steve, $filteredList);
911
        $this->assertContains($bob, $filteredList);
912
913
        // bob or anyone aged 21 in the list
914
        //$list = $list->filterAny(array('Name'=>'bob, 'Age'=>21));
915
        $filteredList = $list->filterAny(array('Name' => 'Bob', 'Age' => 21))->toArray();
916
        $this->assertCount(4, $filteredList);
917
        $this->assertContains($bob, $filteredList);
918
        $this->assertContains($steve, $filteredList);
919
        $this->assertContains($clair, $filteredList);
920
        $this->assertContains($phil, $filteredList);
921
922
        // bob or anyone aged 21 or 43 in the list
923
        // $list = $list->filterAny(array('Name'=>'bob, 'Age'=>array(21, 43)));
924
        $filteredList = $list->filterAny(array('Name' => 'Bob', 'Age' => array(21, 43)))->toArray();
925
        $this->assertCount(5, $filteredList);
926
        $this->assertContains($bob, $filteredList);
927
        $this->assertContains($steve, $filteredList);
928
        $this->assertContains($clair, $filteredList);
929
        $this->assertContains($mike, $filteredList);
930
        $this->assertContains($phil, $filteredList);
931
932
        // all bobs, phils or anyone aged 21 or 43 in the list
933
        //$list = $list->filterAny(array('Name'=>array('bob','phil'), 'Age'=>array(21, 43)));
934
        $filteredList = $list->filterAny(array('Name' => array('Bob', 'Phil'), 'Age' => array(21, 43)))->toArray();
935
        $this->assertCount(5, $filteredList);
936
        $this->assertContains($bob, $filteredList);
937
        $this->assertContains($steve, $filteredList);
938
        $this->assertContains($clair, $filteredList);
939
        $this->assertContains($mike, $filteredList);
940
        $this->assertContains($phil, $filteredList);
941
942
        $filteredList = $list->filterAny(array('Name' => array('Bob', 'Nobody'), 'Age' => array(21, 43)))->toArray();
943
        $this->assertCount(5, $filteredList);
944
        $this->assertContains($bob, $filteredList);
945
        $this->assertContains($steve, $filteredList);
946
        $this->assertContains($clair, $filteredList);
947
        $this->assertContains($mike, $filteredList);
948
        $this->assertContains($phil, $filteredList);
949
    }
950
951
    /**
952
     * $list = $list->filterByCallback(function($item, $list) { return $item->Age == 21; })
953
     */
954
    public function testFilterByCallback()
955
    {
956
        $list = new ArrayList(
957
            array(
958
            $steve = array('Name' => 'Steve', 'ID' => 1, 'Age' => 21),
959
            array('Name' => 'Bob', 'ID' => 2, 'Age' => 18),
960
            $clair = array('Name' => 'Clair', 'ID' => 2, 'Age' => 21),
961
            array('Name' => 'Oscar', 'ID' => 2, 'Age' => 52),
962
            array('Name' => 'Mike', 'ID' => 3, 'Age' => 43)
963
            )
964
        );
965
966
        $list = $list->filterByCallback(
967
            function ($item, $list) {
0 ignored issues
show
Unused Code introduced by
The parameter $list is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

967
            function ($item, /** @scrutinizer ignore-unused */ $list) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
968
                return $item->Age == 21;
969
            }
970
        );
971
972
        $this->assertEquals(2, $list->count());
973
        $this->assertEquals($steve, $list[0]->toMap(), 'List should only contain Steve and Clair');
974
        $this->assertEquals($clair, $list[1]->toMap(), 'List should only contain Steve and Clair');
975
        $this->assertTrue($list instanceof Filterable, 'The List should be of type SS_Filterable');
976
    }
977
978
    /**
979
     * $list->exclude('Name', 'bob'); // exclude bob from list
980
     */
981
    public function testSimpleExclude()
982
    {
983
        $list = new ArrayList(
984
            array(
985
            array('Name' => 'Steve'),
986
            array('Name' => 'Bob'),
987
            array('Name' => 'John')
988
            )
989
        );
990
991
        $list = $list->exclude('Name', 'Bob');
992
        $expected = array(
993
            array('Name' => 'Steve'),
994
            array('Name' => 'John')
995
        );
996
        $this->assertEquals(2, $list->count());
997
        $this->assertEquals($expected, $list->toArray(), 'List should not contain Bob');
998
    }
999
1000
    /**
1001
     * $list->exclude('Name', 'bob'); // No exclusion version
1002
     */
1003
    public function testSimpleExcludeNoMatch()
1004
    {
1005
        $list = new ArrayList(
1006
            array(
1007
            array('Name' => 'Steve'),
1008
            array('Name' => 'Bob'),
1009
            array('Name' => 'John')
1010
            )
1011
        );
1012
1013
        $list = $list->exclude('Name', 'Clair');
1014
        $expected = array(
1015
            array('Name' => 'Steve'),
1016
            array('Name' => 'Bob'),
1017
            array('Name' => 'John')
1018
        );
1019
        $this->assertEquals($expected, $list->toArray(), 'List should be unchanged');
1020
    }
1021
1022
    /**
1023
     * $list->exclude('Name', array('Steve','John'));
1024
     */
1025
    public function testSimpleExcludeWithArray()
1026
    {
1027
        $list = new ArrayList(
1028
            array(
1029
            array('Name' => 'Steve'),
1030
            array('Name' => 'Bob'),
1031
            array('Name' => 'John')
1032
            )
1033
        );
1034
        $list = $list->exclude('Name', array('Steve','John'));
1035
        $expected = array(array('Name' => 'Bob'));
1036
        $this->assertEquals(1, $list->count());
1037
        $this->assertEquals($expected, $list->toArray(), 'List should only contain Bob');
1038
    }
1039
1040
    /**
1041
     * $list->exclude(array('Name'=>'bob, 'Age'=>21)); // exclude all Bob that has Age 21
1042
     */
1043
    public function testExcludeWithTwoArrays()
1044
    {
1045
        $list = new ArrayList(
1046
            array(
1047
            array('Name' => 'Bob' , 'Age' => 21),
1048
            array('Name' => 'Bob' , 'Age' => 32),
1049
            array('Name' => 'John', 'Age' => 21)
1050
            )
1051
        );
1052
1053
        $list = $list->exclude(array('Name' => 'Bob', 'Age' => 21));
1054
1055
        $expected = array(
1056
            array('Name' => 'Bob', 'Age' => 32),
1057
            array('Name' => 'John', 'Age' => 21)
1058
        );
1059
1060
        $this->assertEquals(2, $list->count());
1061
        $this->assertEquals($expected, $list->toArray(), 'List should only contain John and Bob');
1062
    }
1063
1064
    /**
1065
     * $list->exclude(array('Name'=>array('bob','phil'), 'Age'=>array(10, 16)));
1066
     */
1067
    public function testMultipleExclude()
1068
    {
1069
        $list = new ArrayList(
1070
            array(
1071
            array('Name' => 'bob', 'Age' => 10),
1072
            array('Name' => 'phil', 'Age' => 11),
1073
            array('Name' => 'bob', 'Age' => 12),
1074
            array('Name' => 'phil', 'Age' => 12),
1075
            array('Name' => 'bob', 'Age' => 14),
1076
            array('Name' => 'phil', 'Age' => 14),
1077
            array('Name' => 'bob', 'Age' => 16),
1078
            array('Name' => 'phil', 'Age' => 16)
1079
            )
1080
        );
1081
1082
        $list = $list->exclude(array('Name'=>array('bob','phil'),'Age'=>array(10, 16)));
1083
        $expected = array(
1084
            array('Name' => 'phil', 'Age' => 11),
1085
            array('Name' => 'bob', 'Age' => 12),
1086
            array('Name' => 'phil', 'Age' => 12),
1087
            array('Name' => 'bob', 'Age' => 14),
1088
            array('Name' => 'phil', 'Age' => 14),
1089
        );
1090
        $this->assertEquals($expected, $list->toArray());
1091
    }
1092
1093
    /**
1094
     * $list->exclude(array('Name'=>array('bob','phil'), 'Age'=>array(10, 16), 'Bananas'=>true));
1095
     */
1096
    public function testMultipleExcludeNoMatch()
1097
    {
1098
        $list = new ArrayList(
1099
            array(
1100
            array('Name' => 'bob', 'Age' => 10),
1101
            array('Name' => 'phil', 'Age' => 11),
1102
            array('Name' => 'bob', 'Age' => 12),
1103
            array('Name' => 'phil', 'Age' => 12),
1104
            array('Name' => 'bob', 'Age' => 14),
1105
            array('Name' => 'phil', 'Age' => 14),
1106
            array('Name' => 'bob', 'Age' => 16),
1107
            array('Name' => 'phil', 'Age' => 16)
1108
            )
1109
        );
1110
1111
        $list = $list->exclude(array('Name'=>array('bob','phil'),'Age'=>array(10, 16),'Bananas'=>true));
1112
        $expected = array(
1113
            array('Name' => 'bob', 'Age' => 10),
1114
            array('Name' => 'phil', 'Age' => 11),
1115
            array('Name' => 'bob', 'Age' => 12),
1116
            array('Name' => 'phil', 'Age' => 12),
1117
            array('Name' => 'bob', 'Age' => 14),
1118
            array('Name' => 'phil', 'Age' => 14),
1119
            array('Name' => 'bob', 'Age' => 16),
1120
            array('Name' => 'phil', 'Age' => 16)
1121
        );
1122
        $this->assertEquals($expected, $list->toArray());
1123
    }
1124
1125
    /**
1126
     * $list->exclude(array('Name'=>array('bob','phil'), 'Age'=>array(10, 16), 'HasBananas'=>true));
1127
     */
1128
    public function testMultipleExcludeThreeArguments()
1129
    {
1130
        $list = new ArrayList(
1131
            array(
1132
            array('Name' => 'bob', 'Age' => 10, 'HasBananas'=>false),
1133
            array('Name' => 'phil','Age' => 11, 'HasBananas'=>true),
1134
            array('Name' => 'bob', 'Age' => 12, 'HasBananas'=>true),
1135
            array('Name' => 'phil','Age' => 12, 'HasBananas'=>true),
1136
            array('Name' => 'bob', 'Age' => 14, 'HasBananas'=>false),
1137
            array('Name' => 'ann', 'Age' => 14, 'HasBananas'=>true),
1138
            array('Name' => 'phil','Age' => 14, 'HasBananas'=>false),
1139
            array('Name' => 'bob', 'Age' => 16, 'HasBananas'=>false),
1140
            array('Name' => 'phil','Age' => 16, 'HasBananas'=>true),
1141
            array('Name' => 'clair','Age' => 16, 'HasBananas'=>true)
1142
            )
1143
        );
1144
1145
        $list = $list->exclude(array('Name'=>array('bob','phil'),'Age'=>array(10, 16),'HasBananas'=>true));
1146
        $expected = array(
1147
            array('Name' => 'bob', 'Age' => 10, 'HasBananas'=>false),
1148
            array('Name' => 'phil','Age' => 11, 'HasBananas'=>true),
1149
            array('Name' => 'bob', 'Age' => 12, 'HasBananas'=>true),
1150
            array('Name' => 'phil','Age' => 12, 'HasBananas'=>true),
1151
            array('Name' => 'bob', 'Age' => 14, 'HasBananas'=>false),
1152
            array('Name' => 'ann', 'Age' => 14, 'HasBananas'=>true),
1153
            array('Name' => 'phil','Age' => 14, 'HasBananas'=>false),
1154
            array('Name' => 'bob', 'Age' => 16, 'HasBananas'=>false),
1155
            array('Name' => 'clair','Age' => 16, 'HasBananas'=>true)
1156
        );
1157
        $this->assertEquals($expected, $list->toArray());
1158
    }
1159
1160
    public function testCanFilterBy()
1161
    {
1162
        $list = new ArrayList(
1163
            array(
1164
            array('Name' => 'Steve'),
1165
            array('Name' => 'Bob'),
1166
            array('Name' => 'John')
1167
            )
1168
        );
1169
1170
        $this->assertTrue($list->canFilterBy('Name'));
1171
        $this->assertFalse($list->canFilterBy('Age'));
1172
    }
1173
1174
    public function testCanFilterByEmpty()
1175
    {
1176
        $list = new ArrayList();
1177
1178
        $this->assertFalse($list->canFilterBy('Name'));
1179
        $this->assertFalse($list->canFilterBy('Age'));
1180
    }
1181
1182
    public function testByID()
1183
    {
1184
        $list = new ArrayList(
1185
            array(
1186
            array('ID' => 1, 'Name' => 'Steve'),
1187
            array('ID' => 2, 'Name' => 'Bob'),
1188
            array('ID' => 3, 'Name' => 'John')
1189
            )
1190
        );
1191
1192
        $element = $list->byID(1);
1193
        $this->assertEquals($element['Name'], 'Steve');
1194
1195
        $element = $list->byID(2);
1196
        $this->assertEquals($element['Name'], 'Bob');
1197
1198
        $element = $list->byID(4);
1199
        $this->assertNull($element);
1200
    }
1201
1202
    public function testByIDs()
1203
    {
1204
        $list = new ArrayList(
1205
            array(
1206
            array('ID' => 1, 'Name' => 'Steve'),
1207
            array('ID' => 2, 'Name' => 'Bob'),
1208
            array('ID' => 3, 'Name' => 'John')
1209
            )
1210
        );
1211
        $knownIDs = $list->column('ID');
1212
        $removedID = array_pop($knownIDs);
1213
        $filteredItems = $list->byIDs($knownIDs);
1214
        foreach ($filteredItems as $item) {
1215
            $this->assertContains($item->ID, $knownIDs);
1216
            $this->assertNotEquals($removedID, $item->ID);
1217
        }
1218
    }
1219
1220
    public function testByIDEmpty()
1221
    {
1222
        $list = new ArrayList();
1223
1224
        $element = $list->byID(1);
1225
        $this->assertNull($element);
1226
    }
1227
1228
    public function testDataClass()
1229
    {
1230
        $list = new ArrayList([
1231
            new DataObject(['Title' => 'one']),
1232
        ]);
1233
        $this->assertEquals(DataObject::class, $list->dataClass());
1234
        $list->pop();
1235
        $this->assertNull($list->dataClass());
1236
        $list->setDataClass(DataObject::class);
1237
        $this->assertEquals(DataObject::class, $list->dataClass());
1238
    }
1239
1240
    public function testShuffle()
1241
    {
1242
        $upperLimit = 50;
1243
1244
        $list = new ArrayList(range(1, $upperLimit));
1245
1246
        $list->shuffle();
1247
1248
        for ($i = 1; $i <= $upperLimit; $i++) {
1249
            $this->assertContains($i, $list);
1250
        }
1251
1252
        $this->assertNotEquals(range(1, $upperLimit), $list->toArray());
1253
    }
1254
}
1255