Passed
Push — master ( 6410ef...806142 )
by Robbie
48:34 queued 35:53
created

ArrayListTest::testZeroLimit()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 0
dl 0
loc 8
rs 10
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 SilverStripe\ORM\SS_List;
11
use stdClass;
12
13
class ArrayListTest extends SapphireTest
14
{
15
16
    public function testPushOperator()
17
    {
18
        $list = new ArrayList(
19
            array(
20
            array('Num' => 1)
21
            )
22
        );
23
24
        $list[] = array('Num' => 2);
25
        $this->assertEquals(2, count($list));
26
        $this->assertEquals(array('Num' => 2), $list->last());
27
28
        $list[] = array('Num' => 3);
29
        $this->assertEquals(3, count($list));
30
        $this->assertEquals(array('Num' => 3), $list->last());
31
    }
32
33
    public function testArrayAccessExists()
34
    {
35
        $list = new ArrayList(
36
            array(
37
            $one = new DataObject(array('Title' => 'one')),
38
            $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...
39
            $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...
40
            )
41
        );
42
        $this->assertEquals(count($list), 3);
43
        $this->assertTrue(isset($list[0]), 'First item in the set is set');
44
        $this->assertEquals($one, $list[0], 'First item in the set is accessible by array notation');
45
    }
46
47
    public function testArrayAccessUnset()
48
    {
49
        $list = new ArrayList(
50
            array(
51
            $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...
52
            $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...
53
            $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...
54
            )
55
        );
56
        unset($list[0]);
57
        $this->assertEquals(count($list), 2);
58
    }
59
60
    public function testArrayAccessSet()
61
    {
62
        $list = new ArrayList();
63
        $this->assertEquals(0, count($list));
64
        $list['testing!'] = $test = new DataObject(array('Title' => 'I\'m testing!'));
65
        $this->assertEquals($test, $list['testing!'], 'Set item is accessible by the key we set it as');
66
    }
67
68
    public function testCount()
69
    {
70
        $list = new ArrayList();
71
        $this->assertEquals(0, $list->count());
72
        $list = new ArrayList(array(1, 2, 3));
73
        $this->assertEquals(3, $list->count());
74
    }
75
76
    public function testExists()
77
    {
78
        $list = new ArrayList();
79
        $this->assertFalse($list->exists());
80
        $list = new ArrayList(array(1, 2, 3));
81
        $this->assertTrue($list->exists());
82
    }
83
84
    public function testToNestedArray()
85
    {
86
        $list = new ArrayList(
87
            array(
88
            array('First' => 'FirstFirst', 'Second' => 'FirstSecond'),
89
            (object) array('First' => 'SecondFirst', 'Second' => 'SecondSecond'),
90
            new ArrayListTest\TestObject('ThirdFirst', 'ThirdSecond')
91
            )
92
        );
93
94
        $this->assertEquals(
95
            $list->toNestedArray(),
96
            array(
97
            array('First' => 'FirstFirst', 'Second' => 'FirstSecond'),
98
            array('First' => 'SecondFirst', 'Second' => 'SecondSecond'),
99
            array('First' => 'ThirdFirst', 'Second' => 'ThirdSecond')
100
            )
101
        );
102
    }
103
104
    public function testEach()
105
    {
106
        $list = new ArrayList(array(1, 2, 3));
107
108
        $count = 0;
109
        $test = $this;
110
111
        $list->each(
112
            function ($item) use (&$count, $test) {
113
                $count++;
114
115
                $test->assertTrue(is_int($item));
116
            }
117
        );
118
119
        $this->assertEquals($list->Count(), $count);
120
    }
121
122
    public function testLimit()
123
    {
124
        $list = new ArrayList(
125
            array(
126
            array('Key' => 1), array('Key' => 2), array('Key' => 3)
127
            )
128
        );
129
        $this->assertEquals(
130
            $list->limit(2, 1)->toArray(),
131
            array(
132
            array('Key' => 2), array('Key' => 3)
133
            )
134
        );
135
    }
136
137
    /**
138
     * @expectedException PHPUnit_Framework_Error
139
     */
140
    public function testZeroLimit()
141
    {
142
        Deprecation::notification_version('4.3.0');
143
        $list = new ArrayList([
144
            ['Key' => 1],
145
            ['Key' => 2],
146
        ]);
147
        $list->limit(0);
148
    }
149
150
    public function testAddRemove()
151
    {
152
        $list = new ArrayList(
153
            array(
154
            array('Key' => 1), array('Key' => 2)
155
            )
156
        );
157
158
        $list->add(array('Key' => 3));
159
        $this->assertEquals(
160
            $list->toArray(),
161
            array(
162
            array('Key' => 1), array('Key' => 2), array('Key' => 3)
163
            )
164
        );
165
166
        $list->remove(array('Key' => 2));
167
        $this->assertEquals(
168
            array_values($list->toArray()),
169
            array(
170
            array('Key' => 1), array('Key' => 3)
171
            )
172
        );
173
    }
174
175
    public function testReplace()
176
    {
177
        $list = new ArrayList(
178
            array(
179
            array('Key' => 1),
180
            $two = (object) array('Key' => 2),
181
            (object) array('Key' => 3)
182
            )
183
        );
184
185
        $this->assertEquals(array('Key' => 1), $list[0]);
186
        $list->replace(array('Key' => 1), array('Replaced' => 1));
187
        $this->assertEquals(3, count($list));
188
        $this->assertEquals(array('Replaced' => 1), $list[0]);
189
190
        $this->assertEquals($two, $list[1]);
191
        $list->replace($two, array('Replaced' => 2));
192
        $this->assertEquals(3, count($list));
193
        $this->assertEquals(array('Replaced' => 2), $list[1]);
194
    }
195
196
    public function testMerge()
197
    {
198
        $list = new ArrayList(
199
            array(
200
            array('Num' => 1), array('Num' => 2)
201
            )
202
        );
203
        $list->merge(
204
            array(
205
            array('Num' => 3), array('Num' => 4)
206
            )
207
        );
208
209
        $this->assertEquals(4, count($list));
210
        $this->assertEquals(
211
            $list->toArray(),
212
            array(
213
            array('Num' => 1), array('Num' => 2), array('Num' => 3), array('Num' => 4)
214
            )
215
        );
216
    }
217
218
    public function testRemoveDuplicates()
219
    {
220
        $list = new ArrayList(
221
            array(
222
            array('ID' => 1, 'Field' => 1),
223
            array('ID' => 2, 'Field' => 2),
224
            array('ID' => 3, 'Field' => 3),
225
            array('ID' => 4, 'Field' => 1),
226
            (object) array('ID' => 5, 'Field' => 2)
227
            )
228
        );
229
230
        $this->assertEquals(5, count($list));
231
        $list->removeDuplicates();
232
        $this->assertEquals(5, count($list));
233
234
        $list->removeDuplicates('Field');
235
        $this->assertEquals(3, count($list));
236
        $this->assertEquals(array(1, 2, 3), $list->column('Field'));
237
        $this->assertEquals(array(1, 2, 3), $list->column('ID'));
238
    }
239
240
    public function testPushPop()
241
    {
242
        $list = new ArrayList(array('Num' => 1));
243
        $this->assertEquals(1, count($list));
244
245
        $list->push(array('Num' => 2));
246
        $this->assertEquals(2, count($list));
247
        $this->assertEquals(array('Num' => 2), $list->last());
248
249
        $list->push(array('Num' => 3));
250
        $this->assertEquals(3, count($list));
251
        $this->assertEquals(array('Num' => 3), $list->last());
252
253
        $this->assertEquals(array('Num' => 3), $list->pop());
254
        $this->assertEquals(2, count($list));
255
        $this->assertEquals(array('Num' => 2), $list->last());
256
    }
257
258
    public function testShiftUnshift()
259
    {
260
        $list = new ArrayList(array('Num' => 1));
261
        $this->assertEquals(1, count($list));
262
263
        $list->unshift(array('Num' => 2));
264
        $this->assertEquals(2, count($list));
265
        $this->assertEquals(array('Num' => 2), $list->first());
266
267
        $list->unshift(array('Num' => 3));
268
        $this->assertEquals(3, count($list));
269
        $this->assertEquals(array('Num' => 3), $list->first());
270
271
        $this->assertEquals(array('Num' => 3), $list->shift());
272
        $this->assertEquals(2, count($list));
273
        $this->assertEquals(array('Num' => 2), $list->first());
274
    }
275
276
    public function testFirstLast()
277
    {
278
        $list = new ArrayList(
279
            array(
280
            array('Key' => 1), array('Key' => 2), array('Key' => 3)
281
            )
282
        );
283
        $this->assertEquals($list->first(), array('Key' => 1));
284
        $this->assertEquals($list->last(), array('Key' => 3));
285
    }
286
287
    public function testMap()
288
    {
289
        $list = new ArrayList(
290
            array(
291
            array('ID' => 1, 'Name' => 'Steve',),
292
            (object) array('ID' => 3, 'Name' => 'Bob'),
293
            array('ID' => 5, 'Name' => 'John')
294
            )
295
        );
296
        $map = $list->map('ID', 'Name');
297
        // Items added after calling map should not be included retroactively
298
        $list->add(array('ID' => 7, 'Name' => 'Andrew'));
299
        $this->assertInstanceOf('SilverStripe\\ORM\\Map', $map);
300
        $this->assertEquals(
301
            array(
302
            1 => 'Steve',
303
            3 => 'Bob',
304
            5 => 'John'
305
            ),
306
            $map->toArray()
307
        );
308
    }
309
310
    public function testFind()
311
    {
312
        $list = new ArrayList(
313
            array(
314
            array('Name' => 'Steve'),
315
            (object) array('Name' => 'Bob'),
316
            array('Name' => 'John')
317
            )
318
        );
319
        $this->assertEquals(
320
            $list->find('Name', 'Bob'),
321
            (object) array(
322
            'Name' => 'Bob'
323
            )
324
        );
325
    }
326
327
    public function testColumn()
328
    {
329
        $list = new ArrayList(
330
            array(
331
            array('Name' => 'Steve'),
332
            (object) array('Name' => 'Bob'),
333
            array('Name' => 'John')
334
            )
335
        );
336
        $this->assertEquals(
337
            $list->column('Name'),
338
            array(
339
            'Steve', 'Bob', 'John'
340
            )
341
        );
342
    }
343
344
    public function testSortSimpleDefaultIsSortedASC()
345
    {
346
        $list = new ArrayList(
347
            array(
348
            array('Name' => 'Steve'),
349
            (object) array('Name' => 'Bob'),
350
            array('Name' => 'John'),
351
            array('Name' => 'bonny'),
352
            )
353
        );
354
355
        // Unquoted name
356
        $list1 = $list->sort('Name');
357
        $this->assertEquals(
358
            array(
359
            (object) array('Name' => 'Bob'),
360
            array('Name' => 'bonny'),
361
            array('Name' => 'John'),
362
            array('Name' => 'Steve'),
363
            ),
364
            $list1->toArray()
365
        );
366
367
        // Quoted name name
368
        $list2 = $list->sort('"Name"');
369
        $this->assertEquals(
370
            array(
371
            (object) array('Name' => 'Bob'),
372
            array('Name' => 'bonny'),
373
            array('Name' => 'John'),
374
            array('Name' => 'Steve'),
375
            ),
376
            $list2->toArray()
377
        );
378
379
        // Array (non-associative)
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
380
        $list3 = $list->sort(array('"Name"'));
381
        $this->assertEquals(
382
            array(
383
            (object) array('Name' => 'Bob'),
384
            array('Name' => 'bonny'),
385
            array('Name' => 'John'),
386
            array('Name' => 'Steve'),
387
            ),
388
            $list3->toArray()
389
        );
390
391
        // Quoted name name with table
392
        $list4 = $list->sort('"Record"."Name"');
393
        $this->assertEquals(
394
            array(
395
            (object) array('Name' => 'Bob'),
396
            array('Name' => 'bonny'),
397
            array('Name' => 'John'),
398
            array('Name' => 'Steve')
399
            ),
400
            $list4->toArray()
401
        );
402
403
        // Quoted name name with table (desc)
404
        $list5 = $list->sort('"Record"."Name" DESC');
405
        $this->assertEquals(
406
            array(
407
            array('Name' => 'Steve'),
408
            array('Name' => 'John'),
409
            array('Name' => 'bonny'),
410
            (object) array('Name' => 'Bob')
411
            ),
412
            $list5->toArray()
413
        );
414
415
        // Table without quotes
416
        $list6 = $list->sort('Record.Name');
417
        $this->assertEquals(
418
            array(
419
            (object) array('Name' => 'Bob'),
420
            array('Name' => 'bonny'),
421
            array('Name' => 'John'),
422
            array('Name' => 'Steve')
423
            ),
424
            $list6->toArray()
425
        );
426
427
        // Check original list isn't altered
428
        $this->assertEquals(
429
            array(
430
            array('Name' => 'Steve'),
431
            (object) array('Name' => 'Bob'),
432
            array('Name' => 'John'),
433
            array('Name' => 'bonny'),
434
            ),
435
            $list->toArray()
436
        );
437
    }
438
439
    public function testMixedCaseSort()
440
    {
441
        // Note: Natural sorting is not expected, so if 'bonny10' were included
442
        // below we would expect it to appear between bonny1 and bonny2. That's
443
        // undesirable though so we're not enforcing it in tests.
444
        $original = array(
445
            array('Name' => 'Steve'),
446
            (object) array('Name' => 'Bob'),
447
            array('Name' => 'John'),
448
            array('Name' => 'bonny'),
449
            array('Name' => 'bonny1'),
450
            //array('Name' => 'bonny10'),
0 ignored issues
show
Unused Code Comprehensibility introduced by
78% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
451
            array('Name' => 'bonny2'),
452
        );
453
454
        $list = new ArrayList($original);
455
456
        $expected = array(
457
            (object) array('Name' => 'Bob'),
458
            array('Name' => 'bonny'),
459
            array('Name' => 'bonny1'),
460
            //array('Name' => 'bonny10'),
0 ignored issues
show
Unused Code Comprehensibility introduced by
78% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
461
            array('Name' => 'bonny2'),
462
            array('Name' => 'John'),
463
            array('Name' => 'Steve'),
464
        );
465
466
        // Unquoted name
467
        $list1 = $list->sort('Name');
468
        $this->assertEquals($expected, $list1->toArray());
469
470
        // Quoted name name
471
        $list2 = $list->sort('"Name"');
472
        $this->assertEquals($expected, $list2->toArray());
473
474
        // Array (non-associative)
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
475
        $list3 = $list->sort(array('"Name"'));
476
        $this->assertEquals($expected, $list3->toArray());
477
478
        // Check original list isn't altered
479
        $this->assertEquals($original, $list->toArray());
480
    }
481
482
    public function testSortSimpleASCOrder()
483
    {
484
        $list = new ArrayList(
485
            array(
486
            array('Name' => 'Steve'),
487
            (object) array('Name' => 'Bob'),
488
            array('Name' => 'John')
489
            )
490
        );
491
492
        // Sort two arguments
493
        $list1 = $list->sort('Name', 'ASC');
494
        $this->assertEquals(
495
            $list1->toArray(),
496
            array(
497
            (object) array('Name' => 'Bob'),
498
            array('Name' => 'John'),
499
            array('Name' => 'Steve')
500
            )
501
        );
502
503
        // Sort single string
504
        $list2 = $list->sort('Name asc');
505
        $this->assertEquals(
506
            $list2->toArray(),
507
            array(
508
            (object) array('Name' => 'Bob'),
509
            array('Name' => 'John'),
510
            array('Name' => 'Steve')
511
            )
512
        );
513
514
        // Sort quoted string
515
        $list3 = $list->sort('"Name" ASCENDING');
516
        $this->assertEquals(
517
            $list3->toArray(),
518
            array(
519
            (object) array('Name' => 'Bob'),
520
            array('Name' => 'John'),
521
            array('Name' => 'Steve')
522
            )
523
        );
524
525
        // Sort array specifier
526
        $list4 = $list->sort(array('Name' => 'ascending'));
527
        $this->assertEquals(
528
            $list4->toArray(),
529
            array(
530
            (object) array('Name' => 'Bob'),
531
            array('Name' => 'John'),
532
            array('Name' => 'Steve')
533
            )
534
        );
535
536
        // Check original list isn't altered
537
        $this->assertEquals(
538
            $list->toArray(),
539
            array(
540
            array('Name' => 'Steve'),
541
            (object) array('Name' => 'Bob'),
542
            array('Name' => 'John')
543
            )
544
        );
545
    }
546
547
    public function testSortSimpleDESCOrder()
548
    {
549
        $list = new ArrayList(
550
            array(
551
            array('Name' => 'Steve'),
552
            (object) array('Name' => 'Bob'),
553
            array('Name' => 'John')
554
            )
555
        );
556
557
        // Sort two arguments
558
        $list1 = $list->sort('Name', 'DESC');
559
        $this->assertEquals(
560
            $list1->toArray(),
561
            array(
562
            array('Name' => 'Steve'),
563
            array('Name' => 'John'),
564
            (object) array('Name' => 'Bob')
565
            )
566
        );
567
568
        // Sort single string
569
        $list2 = $list->sort('Name desc');
570
        $this->assertEquals(
571
            $list2->toArray(),
572
            array(
573
            array('Name' => 'Steve'),
574
            array('Name' => 'John'),
575
            (object) array('Name' => 'Bob')
576
            )
577
        );
578
579
        // Sort quoted string
580
        $list3 = $list->sort('"Name" DESCENDING');
581
        $this->assertEquals(
582
            $list3->toArray(),
583
            array(
584
            array('Name' => 'Steve'),
585
            array('Name' => 'John'),
586
            (object) array('Name' => 'Bob')
587
            )
588
        );
589
590
        // Sort array specifier
591
        $list4 = $list->sort(array('Name' => 'descending'));
592
        $this->assertEquals(
593
            $list4->toArray(),
594
            array(
595
            array('Name' => 'Steve'),
596
            array('Name' => 'John'),
597
            (object) array('Name' => 'Bob')
598
            )
599
        );
600
601
        // Check original list isn't altered
602
        $this->assertEquals(
603
            $list->toArray(),
604
            array(
605
            array('Name' => 'Steve'),
606
            (object) array('Name' => 'Bob'),
607
            array('Name' => 'John')
608
            )
609
        );
610
    }
611
612
    public function testSortNumeric()
613
    {
614
        $list = new ArrayList(
615
            array(
616
            array('Sort' => 0),
617
            array('Sort' => -1),
618
            array('Sort' => 1),
619
            array('Sort' => -2),
620
            array('Sort' => 2),
621
            array('Sort' => -10),
622
            array('Sort' => 10)
623
            )
624
        );
625
626
        // Sort descending
627
        $list1 = $list->sort('Sort', 'DESC');
628
        $this->assertEquals(
629
            array(
630
            array('Sort' => 10),
631
            array('Sort' => 2),
632
            array('Sort' => 1),
633
            array('Sort' => 0),
634
            array('Sort' => -1),
635
            array('Sort' => -2),
636
            array('Sort' => -10)
637
            ),
638
            $list1->toArray()
639
        );
640
641
        // Sort ascending
642
        $list1 = $list->sort('Sort', 'ASC');
643
        $this->assertEquals(
644
            array(
645
            array('Sort' => -10),
646
            array('Sort' => -2),
647
            array('Sort' => -1),
648
            array('Sort' => 0),
649
            array('Sort' => 1),
650
            array('Sort' => 2),
651
            array('Sort' => 10)
652
            ),
653
            $list1->toArray()
654
        );
655
    }
656
657
    public function testReverse()
658
    {
659
        $list = new ArrayList(
660
            array(
661
            array('Name' => 'John'),
662
            array('Name' => 'Bob'),
663
            array('Name' => 'Steve')
664
            )
665
        );
666
667
        $list = $list->sort('Name', 'ASC');
668
        $list = $list->reverse();
669
670
        $this->assertEquals(
671
            $list->toArray(),
672
            array(
673
            array('Name' => 'Steve'),
674
            array('Name' => 'John'),
675
            array('Name' => 'Bob')
676
            )
677
        );
678
    }
679
680
    public function testSimpleMultiSort()
681
    {
682
        $list = new ArrayList(
683
            array(
684
            (object) array('Name'=>'Object1', 'F1'=>1, 'F2'=>2, 'F3'=>3),
685
            (object) array('Name'=>'Object2', 'F1'=>2, 'F2'=>1, 'F3'=>4),
686
            (object) array('Name'=>'Object3', 'F1'=>5, 'F2'=>2, 'F3'=>2),
687
            )
688
        );
689
690
        $list = $list->sort('F3', 'ASC');
691
        $this->assertEquals($list->first()->Name, 'Object3', 'Object3 should be first in the list');
692
        $this->assertEquals($list->last()->Name, 'Object2', 'Object2 should be last in the list');
693
694
        $list = $list->sort('F3', 'DESC');
695
        $this->assertEquals($list->first()->Name, 'Object2', 'Object2 should be first in the list');
696
        $this->assertEquals($list->last()->Name, 'Object3', 'Object3 should be last in the list');
697
    }
698
699
    public function testMultiSort()
700
    {
701
        $list = new ArrayList(
702
            array(
703
            (object) array('ID'=>3, 'Name'=>'Bert', 'Importance'=>1),
704
            (object) array('ID'=>1, 'Name'=>'Aron', 'Importance'=>2),
705
            (object) array('ID'=>2, 'Name'=>'Aron', 'Importance'=>1),
706
            )
707
        );
708
709
        $list = $list->sort(array('Name'=>'ASC', 'Importance'=>'ASC'));
710
        $this->assertEquals($list->first()->ID, 2, 'Aron.2 should be first in the list');
711
        $this->assertEquals($list->last()->ID, 3, 'Bert.3 should be last in the list');
712
713
        $list = $list->sort(array('Name'=>'ASC', 'Importance'=>'DESC'));
714
        $this->assertEquals($list->first()->ID, 1, 'Aron.2 should be first in the list');
715
        $this->assertEquals($list->last()->ID, 3, 'Bert.3 should be last in the list');
716
    }
717
718
    /**
719
     * Check that we don't cause recursion errors with array_multisort() and circular dependencies
720
     */
721
    public function testSortWithCircularDependencies()
722
    {
723
        $itemA = new stdClass;
724
        $childA = new stdClass;
725
        $itemA->child = $childA;
726
        $childA->parent = $itemA;
727
        $itemA->Sort = 1;
728
729
        $itemB = new stdClass;
730
        $childB = new stdClass;
731
        $itemB->child = $childB;
732
        $childB->parent = $itemB;
733
        $itemB->Sort = 1;
734
735
        $items = new ArrayList;
736
        $items->add($itemA);
737
        $items->add($itemB);
738
739
        // This call will trigger a fatal error if there are issues with circular dependencies
740
        $this->assertInstanceOf(SS_List::class, $items->sort('Sort'));
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');
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
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');
0 ignored issues
show
Unused Code Comprehensibility introduced by
69% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
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)));
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
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);
0 ignored issues
show
Bug Best Practice introduced by
The property ID does not exist on SilverStripe\View\ArrayData. Since you implemented __get, consider adding a @property annotation.
Loading history...
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