Completed
Push — master ( c17796...052b15 )
by Damian
01:29
created

DataListTest::getExtraDataObjects()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\ORM\Tests;
4
5
use InvalidArgumentException;
6
use SilverStripe\Core\Convert;
7
use SilverStripe\Core\Injector\InjectorNotFoundException;
8
use SilverStripe\ORM\DataList;
9
use SilverStripe\ORM\DataQuery;
10
use SilverStripe\ORM\DB;
11
use SilverStripe\ORM\Filterable;
12
use SilverStripe\ORM\Filters\ExactMatchFilter;
13
use SilverStripe\Dev\SapphireTest;
14
use SilverStripe\ORM\Tests\DataObjectTest\Bracket;
15
use SilverStripe\ORM\Tests\DataObjectTest\EquipmentCompany;
16
use SilverStripe\ORM\Tests\DataObjectTest\Fan;
17
use SilverStripe\ORM\Tests\DataObjectTest\Player;
18
use SilverStripe\ORM\Tests\DataObjectTest\Sortable;
19
use SilverStripe\ORM\Tests\DataObjectTest\SubTeam;
20
use SilverStripe\ORM\Tests\DataObjectTest\Team;
21
use SilverStripe\ORM\Tests\DataObjectTest\TeamComment;
22
use SilverStripe\ORM\Tests\DataObjectTest\ValidatedObject;
23
use SilverStripe\ORM\Tests\DataObjectTest\Staff;
24
25
/**
26
 * @skipUpgrade
27
 */
28
class DataListTest extends SapphireTest
29
{
30
31
    // Borrow the model from DataObjectTest
32
    protected static $fixture_file = 'DataObjectTest.yml';
33
34
    public static function getExtraDataObjects()
35
    {
36
        return array_merge(
37
            DataObjectTest::$extra_data_objects,
38
            ManyManyListTest::$extra_data_objects
39
        );
40
    }
41
42
43
    public function testFilterDataObjectByCreatedDate()
44
    {
45
        // create an object to test with
46
        $obj1 = new ValidatedObject();
47
        $obj1->Name = 'test obj 1';
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\Tests\D...ectTest\ValidatedObject. Since you implemented __set, consider adding a @property annotation.
Loading history...
48
        $obj1->write();
49
        $this->assertTrue($obj1->isInDB());
50
51
        // reload the object from the database and reset its Created timestamp to a known value
52
        $obj1 = ValidatedObject::get()->filter(array('Name' => 'test obj 1'))->first();
53
        $this->assertTrue(is_object($obj1));
54
        $this->assertEquals('test obj 1', $obj1->Name);
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
55
        $obj1->Created = '2013-01-01 00:00:00';
56
        $obj1->write();
57
58
        // reload the object again and make sure that our Created date was properly persisted
59
        $obj1 = ValidatedObject::get()->filter(array('Name' => 'test obj 1'))->first();
60
        $this->assertTrue(is_object($obj1));
61
        $this->assertEquals('test obj 1', $obj1->Name);
62
        $this->assertEquals('2013-01-01 00:00:00', $obj1->Created);
63
64
        // now save a second object to the DB with an automatically-set Created value
65
        $obj2 = new ValidatedObject();
66
        $obj2->Name = 'test obj 2';
67
        $obj2->write();
68
        $this->assertTrue($obj2->isInDB());
69
70
        // and a third object
71
        $obj3 = new ValidatedObject();
72
        $obj3->Name = 'test obj 3';
73
        $obj3->write();
74
        $this->assertTrue($obj3->isInDB());
75
76
        // now test the filtering based on Created timestamp
77
        $list = ValidatedObject::get()
78
            ->filter(array('Created:GreaterThan' => '2013-02-01 00:00:00'))
79
            ->toArray();
80
        $this->assertEquals(2, count($list));
81
    }
82
83
    public function testSubtract()
84
    {
85
        $comment1 = $this->objFromFixture(DataObjectTest\TeamComment::class, 'comment1');
86
        $subtractList = TeamComment::get()->filter('ID', $comment1->ID);
87
        $fullList = TeamComment::get();
88
        $newList = $fullList->subtract($subtractList);
89
        $this->assertEquals(2, $newList->Count(), 'List should only contain two objects after subtraction');
90
    }
91
92
    /**
93
     * @expectedException \InvalidArgumentException
94
     */
95
    public function testSubtractBadDataclassThrowsException()
96
    {
97
        $teamsComments = TeamComment::get();
98
        $teams = Team::get();
99
        $teamsComments->subtract($teams);
100
    }
101
102
    public function testListCreationSortAndLimit()
103
    {
104
        // By default, a DataList will contain all items of that class
105
        $list = TeamComment::get()->sort('ID');
106
107
        // We can iterate on the DataList
108
        $names = array();
109
        foreach ($list as $item) {
110
            $names[] = $item->Name;
111
        }
112
        $this->assertEquals(array('Joe', 'Bob', 'Phil'), $names);
113
114
        // If we don't want to iterate, we can extract a single column from the list with column()
115
        $this->assertEquals(array('Joe', 'Bob', 'Phil'), $list->column('Name'));
116
117
        // We can sort a list
118
        $list = $list->sort('Name');
119
        $this->assertEquals(array('Bob', 'Joe', 'Phil'), $list->column('Name'));
120
121
        // We can also restrict the output to a range
122
        $this->assertEquals(array('Joe', 'Phil'), $list->limit(2, 1)->column('Name'));
123
    }
124
125
    public function testLimitAndOffset()
126
    {
127
        $list = TeamComment::get();
128
        $check = $list->limit(3);
129
130
        $this->assertEquals(3, $check->count());
131
132
        $check = $list->limit(1);
133
        $this->assertEquals(1, $check->count());
134
135
        $check = $list->limit(1, 1);
136
        $this->assertEquals(1, $check->count());
137
138
        $check = $list->limit(false);
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type integer expected by parameter $limit of SilverStripe\ORM\DataList::limit(). ( Ignorable by Annotation )

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

138
        $check = $list->limit(/** @scrutinizer ignore-type */ false);
Loading history...
139
        $this->assertEquals(3, $check->count());
140
141
        $check = $list->limit(null);
142
        $this->assertEquals(3, $check->count());
143
144
        $check = $list->limit(null, 2);
145
        $this->assertEquals(1, $check->count());
146
147
        // count()/first()/last() methods may alter limit/offset, so run the query and manually check the count
148
        $check = $list->limit(null, 1)->toArray();
149
        $this->assertEquals(2, count($check));
150
    }
151
152
    public function testDistinct()
153
    {
154
        $list = TeamComment::get();
155
        $this->assertContains('SELECT DISTINCT', $list->dataQuery()->sql($params), 'Query is set as distinct by default');
156
157
        $list = $list->distinct(false);
158
        $this->assertNotContains('SELECT DISTINCT', $list->dataQuery()->sql($params), 'Query does not contain distinct');
159
160
        $list = $list->distinct(true);
161
        $this->assertContains('SELECT DISTINCT', $list->dataQuery()->sql($params), 'Query contains distinct');
162
    }
163
164
    public function testDataClass()
165
    {
166
        $list = TeamComment::get();
167
        $this->assertEquals(DataObjectTest\TeamComment::class, $list->dataClass());
168
    }
169
170
    public function testDataClassCaseInsensitive()
171
    {
172
        $list = DataList::create(strtolower(DataObjectTest\TeamComment::class));
0 ignored issues
show
Bug introduced by
strtolower(SilverStripe\...est\TeamComment::class) of type string is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

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

172
        $list = DataList::create(/** @scrutinizer ignore-type */ strtolower(DataObjectTest\TeamComment::class));
Loading history...
173
        $this->assertTrue($list->exists());
174
    }
175
176
    public function testClone()
177
    {
178
        $list = TeamComment::get();
179
        $this->assertEquals($list, clone($list));
180
    }
181
182
    public function testSql()
183
    {
184
        $db = DB::get_conn();
185
        $list = TeamComment::get();
186
        $expected = 'SELECT DISTINCT "DataObjectTest_TeamComment"."ClassName", '
187
            . '"DataObjectTest_TeamComment"."LastEdited", "DataObjectTest_TeamComment"."Created", '
188
            . '"DataObjectTest_TeamComment"."Name", "DataObjectTest_TeamComment"."Comment", '
189
            . '"DataObjectTest_TeamComment"."TeamID", "DataObjectTest_TeamComment"."ID", '
190
            . 'CASE WHEN "DataObjectTest_TeamComment"."ClassName" IS NOT NULL '
191
            . 'THEN "DataObjectTest_TeamComment"."ClassName" ELSE '
192
            . $db->quoteString(DataObjectTest\TeamComment::class)
193
            . ' END AS "RecordClassName" FROM "DataObjectTest_TeamComment"'
194
            . ' ORDER BY "DataObjectTest_TeamComment"."Name" ASC';
195
        $this->assertSQLEquals($expected, $list->sql($parameters));
196
    }
197
198
    public function testInnerJoin()
199
    {
200
        $db = DB::get_conn();
201
202
        $list = TeamComment::get();
203
        $list = $list->innerJoin(
204
            'DataObjectTest_Team',
205
            '"DataObjectTest_Team"."ID" = "DataObjectTest_TeamComment"."TeamID"',
206
            'Team'
207
        );
208
209
        $expected = 'SELECT DISTINCT "DataObjectTest_TeamComment"."ClassName", '
210
            . '"DataObjectTest_TeamComment"."LastEdited", "DataObjectTest_TeamComment"."Created", '
211
            . '"DataObjectTest_TeamComment"."Name", "DataObjectTest_TeamComment"."Comment", '
212
            . '"DataObjectTest_TeamComment"."TeamID", "DataObjectTest_TeamComment"."ID", '
213
            . 'CASE WHEN "DataObjectTest_TeamComment"."ClassName" IS NOT NULL'
214
            . ' THEN "DataObjectTest_TeamComment"."ClassName" ELSE '
215
            . $db->quoteString(DataObjectTest\TeamComment::class)
216
            . ' END AS "RecordClassName" FROM "DataObjectTest_TeamComment" INNER JOIN '
217
            . '"DataObjectTest_Team" AS "Team" ON "DataObjectTest_Team"."ID" = '
218
            . '"DataObjectTest_TeamComment"."TeamID"'
219
            . ' ORDER BY "DataObjectTest_TeamComment"."Name" ASC';
220
221
222
        $this->assertSQLEquals($expected, $list->sql($parameters));
223
        $this->assertEmpty($parameters);
224
    }
225
226
    public function testInnerJoinParameterised()
227
    {
228
        $db = DB::get_conn();
229
230
        $list = TeamComment::get();
231
        $list = $list->innerJoin(
232
            'DataObjectTest_Team',
233
            '"DataObjectTest_Team"."ID" = "DataObjectTest_TeamComment"."TeamID" '
234
            . 'AND "DataObjectTest_Team"."Title" LIKE ?',
235
            'Team',
236
            20,
237
            array('Team%')
238
        );
239
240
        $expected = 'SELECT DISTINCT "DataObjectTest_TeamComment"."ClassName", '
241
            . '"DataObjectTest_TeamComment"."LastEdited", "DataObjectTest_TeamComment"."Created", '
242
            . '"DataObjectTest_TeamComment"."Name", "DataObjectTest_TeamComment"."Comment", '
243
            . '"DataObjectTest_TeamComment"."TeamID", "DataObjectTest_TeamComment"."ID", '
244
            . 'CASE WHEN "DataObjectTest_TeamComment"."ClassName" IS NOT NULL'
245
            . ' THEN "DataObjectTest_TeamComment"."ClassName" ELSE '
246
            . $db->quoteString(DataObjectTest\TeamComment::class)
247
            . ' END AS "RecordClassName" FROM "DataObjectTest_TeamComment" INNER JOIN '
248
            . '"DataObjectTest_Team" AS "Team" ON "DataObjectTest_Team"."ID" = '
249
            . '"DataObjectTest_TeamComment"."TeamID" '
250
            . 'AND "DataObjectTest_Team"."Title" LIKE ?'
251
            . ' ORDER BY "DataObjectTest_TeamComment"."Name" ASC';
252
253
        $this->assertSQLEquals($expected, $list->sql($parameters));
254
        $this->assertEquals(array('Team%'), $parameters);
255
    }
256
257
    public function testLeftJoin()
258
    {
259
        $db = DB::get_conn();
260
261
        $list = TeamComment::get();
262
        $list = $list->leftJoin(
263
            'DataObjectTest_Team',
264
            '"DataObjectTest_Team"."ID" = "DataObjectTest_TeamComment"."TeamID"',
265
            'Team'
266
        );
267
268
        $expected = 'SELECT DISTINCT "DataObjectTest_TeamComment"."ClassName", '
269
            . '"DataObjectTest_TeamComment"."LastEdited", "DataObjectTest_TeamComment"."Created", '
270
            . '"DataObjectTest_TeamComment"."Name", "DataObjectTest_TeamComment"."Comment", '
271
            . '"DataObjectTest_TeamComment"."TeamID", "DataObjectTest_TeamComment"."ID", '
272
            . 'CASE WHEN "DataObjectTest_TeamComment"."ClassName" IS NOT NULL '
273
            . 'THEN "DataObjectTest_TeamComment"."ClassName" ELSE '
274
            . $db->quoteString(DataObjectTest\TeamComment::class)
275
            . ' END AS "RecordClassName" FROM "DataObjectTest_TeamComment" LEFT JOIN "DataObjectTest_Team" '
276
            . 'AS "Team" ON "DataObjectTest_Team"."ID" = "DataObjectTest_TeamComment"."TeamID"'
277
            . ' ORDER BY "DataObjectTest_TeamComment"."Name" ASC';
278
279
280
        $this->assertSQLEquals($expected, $list->sql($parameters));
281
        $this->assertEmpty($parameters);
282
    }
283
284
    public function testLeftJoinParameterised()
285
    {
286
        $db = DB::get_conn();
287
288
        $list = TeamComment::get();
289
        $list = $list->leftJoin(
290
            'DataObjectTest_Team',
291
            '"DataObjectTest_Team"."ID" = "DataObjectTest_TeamComment"."TeamID" '
292
            . 'AND "DataObjectTest_Team"."Title" LIKE ?',
293
            'Team',
294
            20,
295
            array('Team%')
296
        );
297
298
        $expected = 'SELECT DISTINCT "DataObjectTest_TeamComment"."ClassName", '
299
            . '"DataObjectTest_TeamComment"."LastEdited", "DataObjectTest_TeamComment"."Created", '
300
            . '"DataObjectTest_TeamComment"."Name", "DataObjectTest_TeamComment"."Comment", '
301
            . '"DataObjectTest_TeamComment"."TeamID", "DataObjectTest_TeamComment"."ID", '
302
            . 'CASE WHEN "DataObjectTest_TeamComment"."ClassName" IS NOT NULL'
303
            . ' THEN "DataObjectTest_TeamComment"."ClassName" ELSE '
304
            . $db->quoteString(DataObjectTest\TeamComment::class)
305
            . ' END AS "RecordClassName" FROM "DataObjectTest_TeamComment" LEFT JOIN '
306
            . '"DataObjectTest_Team" AS "Team" ON "DataObjectTest_Team"."ID" = '
307
            . '"DataObjectTest_TeamComment"."TeamID" '
308
            . 'AND "DataObjectTest_Team"."Title" LIKE ?'
309
            . ' ORDER BY "DataObjectTest_TeamComment"."Name" ASC';
310
311
        $this->assertSQLEquals($expected, $list->sql($parameters));
312
        $this->assertEquals(array('Team%'), $parameters);
313
    }
314
315
    public function testToNestedArray()
316
    {
317
        $list = TeamComment::get()->sort('ID');
318
        $nestedArray = $list->toNestedArray();
319
        $expected = array(
320
            0=>
321
            array(
322
                'ClassName'=>DataObjectTest\TeamComment::class,
323
                'Name'=>'Joe',
324
                'Comment'=>'This is a team comment by Joe',
325
                'TeamID'=> $this->objFromFixture(DataObjectTest\TeamComment::class, 'comment1')->TeamID,
0 ignored issues
show
Bug Best Practice introduced by
The property TeamID does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
326
            ),
327
            1=>
328
            array(
329
                'ClassName'=>DataObjectTest\TeamComment::class,
330
                'Name'=>'Bob',
331
                'Comment'=>'This is a team comment by Bob',
332
                'TeamID'=> $this->objFromFixture(DataObjectTest\TeamComment::class, 'comment2')->TeamID,
333
            ),
334
            2=>
335
            array(
336
                'ClassName'=>DataObjectTest\TeamComment::class,
337
                'Name'=>'Phil',
338
                'Comment'=>'Phil is a unique guy, and comments on team2',
339
                'TeamID'=> $this->objFromFixture(DataObjectTest\TeamComment::class, 'comment3')->TeamID,
340
            ),
341
        );
342
        $this->assertEquals(3, count($nestedArray));
343
        $this->assertEquals($expected[0]['Name'], $nestedArray[0]['Name']);
344
        $this->assertEquals($expected[1]['Comment'], $nestedArray[1]['Comment']);
345
        $this->assertEquals($expected[2]['TeamID'], $nestedArray[2]['TeamID']);
346
    }
347
348
    public function testMap()
349
    {
350
        $map = TeamComment::get()->map()->toArray();
351
        $expected = array(
352
            $this->idFromFixture(DataObjectTest\TeamComment::class, 'comment1') => 'Joe',
353
            $this->idFromFixture(DataObjectTest\TeamComment::class, 'comment2') => 'Bob',
354
            $this->idFromFixture(DataObjectTest\TeamComment::class, 'comment3') => 'Phil'
355
        );
356
357
        $this->assertEquals($expected, $map);
358
        $otherMap = TeamComment::get()->map('Name', 'TeamID')->toArray();
359
        $otherExpected = array(
360
            'Joe' => $this->objFromFixture(DataObjectTest\TeamComment::class, 'comment1')->TeamID,
0 ignored issues
show
Bug Best Practice introduced by
The property TeamID does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
361
            'Bob' => $this->objFromFixture(DataObjectTest\TeamComment::class, 'comment2')->TeamID,
362
            'Phil' => $this->objFromFixture(DataObjectTest\TeamComment::class, 'comment3')->TeamID
363
        );
364
365
        $this->assertEquals($otherExpected, $otherMap);
366
    }
367
368
    public function testAmbiguousAggregate()
369
    {
370
        // Test that we avoid ambiguity error when a field exists on two joined tables
371
        // Fetch the sponsors in a round-about way to simulate this
372
        $teamID = $this->idFromFixture(DataObjectTest\Team::class, 'team2');
373
        $sponsors = EquipmentCompany::get()->filter('SponsoredTeams.ID', $teamID);
374
        $this->assertNotNull($sponsors->Max('ID'));
375
        $this->assertNotNull($sponsors->Min('ID'));
376
        $this->assertNotNull($sponsors->Avg('ID'));
377
        $this->assertNotNull($sponsors->Sum('ID'));
378
379
        // Test non-orm many_many_extraFields
380
        $company = $this->objFromFixture(EquipmentCompany::class, 'equipmentcompany1');
381
        $this->assertNotNull($company->SponsoredTeams()->Max('SponsorFee'));
0 ignored issues
show
Bug introduced by
The method SponsoredTeams() does not exist on SilverStripe\ORM\DataObject. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

381
        $this->assertNotNull($company->/** @scrutinizer ignore-call */ SponsoredTeams()->Max('SponsorFee'));
Loading history...
382
        $this->assertNotNull($company->SponsoredTeams()->Min('SponsorFee'));
383
        $this->assertNotNull($company->SponsoredTeams()->Avg('SponsorFee'));
384
        $this->assertNotNull($company->SponsoredTeams()->Sum('SponsorFee'));
385
    }
386
387
    public function testEach()
388
    {
389
        $list = TeamComment::get();
390
391
        $count = 0;
392
        $list->each(
393
            function ($item) use (&$count) {
394
                $count++;
395
                $this->assertInstanceOf(TeamComment::class, $item);
396
            }
397
        );
398
399
        $this->assertEquals($count, $list->count());
400
    }
401
402
    public function testWhere()
403
    {
404
        // We can use raw SQL queries with where.  This is only recommended for advanced uses;
405
        // if you can, you should use filter().
406
        $list = TeamComment::get();
407
408
        // where() returns a new DataList, like all the other modifiers, so it can be chained.
409
        $list2 = $list->where('"Name" = \'Joe\'');
410
        $this->assertEquals(array('This is a team comment by Joe'), $list2->column('Comment'));
411
412
        // The where() clauses are chained together with AND
413
        $list3 = $list2->where('"Name" = \'Bob\'');
414
        $this->assertEquals(array(), $list3->column('Comment'));
415
    }
416
417
    /**
418
     * Test DataList->byID()
419
     */
420
    public function testByID()
421
    {
422
        // We can get a single item by ID.
423
        $id = $this->idFromFixture(DataObjectTest\Team::class, 'team2');
424
        $team = Team::get()->byID($id);
425
426
        // byID() returns a DataObject, rather than a DataList
427
        $this->assertInstanceOf(DataObjectTest\Team::class, $team);
428
        $this->assertEquals('Team 2', $team->Title);
429
430
        // Assert that filtering on ID searches by the base table, not the child table field
431
        $query = SubTeam::get()->filter('ID', 4)->sql($parameters);
432
        $this->assertContains('WHERE ("DataObjectTest_Team"."ID" = ?)', $query);
433
        $this->assertNotContains('WHERE ("DataObjectTest_SubTeam"."ID" = ?)', $query);
434
    }
435
436
    public function testByIDs()
437
    {
438
        $knownIDs = $this->allFixtureIDs(DataObjectTest\Player::class);
439
        $removedID = array_pop($knownIDs);
440
        $filteredPlayers = Player::get()->byIDs($knownIDs);
441
        foreach ($filteredPlayers as $player) {
442
            $this->assertContains($player->ID, $knownIDs);
443
            $this->assertNotEquals($removedID, $player->ID);
444
        }
445
    }
446
447
    /**
448
     * Test DataList->removeByID()
449
     */
450
    public function testRemoveByID()
451
    {
452
        $list = Team::get();
453
        $id = $this->idFromFixture(DataObjectTest\Team::class, 'team2');
454
455
        $this->assertNotNull($list->byID($id));
456
        $list->removeByID($id);
457
        $this->assertNull($list->byID($id));
458
    }
459
460
    /**
461
     * Test DataList->canSortBy()
462
     */
463
    public function testCanSortBy()
464
    {
465
        // Basic check
466
        $team = Team::get();
467
        $this->assertTrue($team->canSortBy("Title"));
468
        $this->assertFalse($team->canSortBy("SomethingElse"));
469
470
        // Subclasses
471
        $subteam = SubTeam::get();
472
        $this->assertTrue($subteam->canSortBy("Title"));
473
        $this->assertTrue($subteam->canSortBy("SubclassDatabaseField"));
474
    }
475
476
    public function testDataListArrayAccess()
477
    {
478
        $list = Team::get()->sort('Title');
479
480
        // We can use array access to refer to single items in the DataList, as if it were an array
481
        $this->assertEquals("Subteam 1", $list[0]->Title);
482
        $this->assertEquals("Subteam 3", $list[2]->Title);
483
        $this->assertEquals("Team 2", $list[4]->Title);
484
    }
485
486
    public function testFind()
487
    {
488
        $list = Team::get();
489
        $record = $list->find('Title', 'Team 1');
490
        $this->assertEquals($this->idFromFixture(DataObjectTest\Team::class, 'team1'), $record->ID);
491
    }
492
493
    public function testFindById()
494
    {
495
        $list = Team::get();
496
        $record = $list->find('ID', $this->idFromFixture(DataObjectTest\Team::class, 'team1'));
497
        $this->assertEquals('Team 1', $record->Title);
498
        // Test that you can call it twice on the same list
499
        $record = $list->find('ID', $this->idFromFixture(DataObjectTest\Team::class, 'team2'));
500
        $this->assertEquals('Team 2', $record->Title);
501
    }
502
503
    public function testSimpleSort()
504
    {
505
        $list = TeamComment::get();
506
        $list = $list->sort('Name');
507
        $this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
508
        $this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
509
    }
510
511
    public function testSimpleSortOneArgumentASC()
512
    {
513
        $list = TeamComment::get();
514
        $list = $list->sort('Name ASC');
515
        $this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
516
        $this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
517
    }
518
519
    public function testSimpleSortOneArgumentDESC()
520
    {
521
        $list = TeamComment::get();
522
        $list = $list->sort('Name DESC');
523
        $this->assertEquals('Phil', $list->first()->Name, 'Last comment should be from Phil');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
524
        $this->assertEquals('Bob', $list->last()->Name, 'First comment should be from Bob');
525
    }
526
527
    public function testSortOneArgumentMultipleColumns()
528
    {
529
        $list = TeamComment::get();
530
        $list = $list->sort('TeamID ASC, Name DESC');
531
        $this->assertEquals('Joe', $list->first()->Name, 'First comment should be from Bob');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
532
        $this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
533
    }
534
535
    public function testSimpleSortASC()
536
    {
537
        $list = TeamComment::get();
538
        $list = $list->sort('Name', 'asc');
539
        $this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
540
        $this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
541
    }
542
543
    public function testSimpleSortDESC()
544
    {
545
        $list = TeamComment::get();
546
        $list = $list->sort('Name', 'desc');
547
        $this->assertEquals('Phil', $list->first()->Name, 'Last comment should be from Phil');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
548
        $this->assertEquals('Bob', $list->last()->Name, 'First comment should be from Bob');
549
    }
550
551
    public function testSortWithArraySyntaxSortASC()
552
    {
553
        $list = TeamComment::get();
554
        $list = $list->sort(array('Name'=>'asc'));
555
        $this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
556
        $this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
557
    }
558
559
    public function testSortWithArraySyntaxSortDESC()
560
    {
561
        $list = TeamComment::get();
562
        $list = $list->sort(array('Name'=>'desc'));
563
        $this->assertEquals('Phil', $list->first()->Name, 'Last comment should be from Phil');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
564
        $this->assertEquals('Bob', $list->last()->Name, 'First comment should be from Bob');
565
    }
566
567
    public function testSortWithMultipleArraySyntaxSort()
568
    {
569
        $list = TeamComment::get();
570
        $list = $list->sort(array('TeamID'=>'asc','Name'=>'desc'));
571
        $this->assertEquals('Joe', $list->first()->Name, 'First comment should be from Bob');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
572
        $this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
573
    }
574
575
    public function testSortWithCompositeSyntax()
576
    {
577
        // Phil commented on team with founder surname "Aaron"
578
        $list = TeamComment::get();
579
        $list = $list->sort('Team.Founder.Surname', 'asc');
580
        $this->assertEquals('Phil', $list->first()->Name);
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
581
        $list = $list->sort('Team.Founder.Surname', 'desc');
582
        $this->assertEquals('Phil', $list->last()->Name);
583
    }
584
585
    /**
586
     * @expectedException \InvalidArgumentException
587
     * @expectedExceptionMessage Fans is not a linear relation on model SilverStripe\ORM\Tests\DataObjectTest\Player
588
     */
589
    public function testSortInvalidParameters()
590
    {
591
        $list = Team::get();
592
        $list->sort('Founder.Fans.Surname'); // Can't sort on has_many
593
    }
594
595
    public function testSortNumeric()
596
    {
597
        $list = Sortable::get();
598
        $list1 = $list->sort('Sort', 'ASC');
599
        $this->assertEquals(
600
            array(
601
            -10,
602
            -2,
603
            -1,
604
            0,
605
            1,
606
            2,
607
            10
608
            ),
609
            $list1->column('Sort')
610
        );
611
    }
612
613
    public function testSortMixedCase()
614
    {
615
        $list = Sortable::get();
616
        $list1 = $list->sort('Name', 'ASC');
617
        $this->assertEquals(
618
            array(
619
            'Bob',
620
            'bonny',
621
            'jane',
622
            'John',
623
            'sam',
624
            'Steve',
625
            'steven'
626
            ),
627
            $list1->column('Name')
628
        );
629
    }
630
631
    /**
632
     * Test DataList->canFilterBy()
633
     */
634
    public function testCanFilterBy()
635
    {
636
        // Basic check
637
        $team = Team::get();
638
        $this->assertTrue($team->canFilterBy("Title"));
639
        $this->assertFalse($team->canFilterBy("SomethingElse"));
640
641
        // Has one
642
        $this->assertTrue($team->canFilterBy("CaptainID"));
643
        $this->assertTrue($team->canFilterBy("Captain.ShirtNumber"));
644
        $this->assertFalse($team->canFilterBy("SomethingElse.ShirtNumber"));
645
        $this->assertFalse($team->canFilterBy("Captain.SomethingElse"));
646
        $this->assertTrue($team->canFilterBy("Captain.FavouriteTeam.Captain.ShirtNumber"));
647
648
        // Has many
649
        $this->assertTrue($team->canFilterBy("Fans.Name"));
650
        $this->assertFalse($team->canFilterBy("SomethingElse.Name"));
651
        $this->assertFalse($team->canFilterBy("Fans.SomethingElse"));
652
653
        // Many many
654
        $this->assertTrue($team->canFilterBy("Players.FirstName"));
655
        $this->assertFalse($team->canFilterBy("SomethingElse.FirstName"));
656
        $this->assertFalse($team->canFilterBy("Players.SomethingElse"));
657
658
        // Subclasses
659
        $subteam = SubTeam::get();
660
        $this->assertTrue($subteam->canFilterBy("Title"));
661
        $this->assertTrue($subteam->canFilterBy("SubclassDatabaseField"));
662
    }
663
664
    /**
665
     * $list->filter('Name', 'bob'); // only bob in the list
666
     */
667
    public function testSimpleFilter()
668
    {
669
        $list = Team::get();
670
        $list = $list->filter('Title', 'Team 2');
671
        $this->assertEquals(1, $list->count());
672
        $this->assertEquals('Team 2', $list->first()->Title, 'List should only contain Team 2');
673
        $this->assertEquals('Team 2', $list->last()->Title, 'Last should only contain Team 2');
674
    }
675
676
    public function testSimpleFilterEndsWith()
677
    {
678
        $list = TeamComment::get();
679
        $list = $list->filter('Name:EndsWith', 'b');
680
        $this->assertEquals(1, $list->count());
681
        $this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
682
    }
683
684
    public function testSimpleFilterExactMatchFilter()
685
    {
686
        $list = TeamComment::get();
687
        $list = $list->filter('Name:ExactMatch', 'Bob');
688
        $this->assertEquals(1, $list->count());
689
        $this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
690
    }
691
692
    public function testSimpleFilterGreaterThanFilter()
693
    {
694
        $list = TeamComment::get();
695
        $list = $list->filter('TeamID:GreaterThan', $this->idFromFixture(DataObjectTest\Team::class, 'team1'));
696
        $this->assertEquals(1, $list->count());
697
        $this->assertEquals('Phil', $list->first()->Name, 'First comment should be from Phil');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
698
    }
699
700
    public function testSimpleFilterGreaterThanOrEqualFilter()
701
    {
702
        $list = TeamComment::get();
703
        $list = $list->filter(
704
            'TeamID:GreaterThanOrEqual',
705
            $this->idFromFixture(DataObjectTest\Team::class, 'team1')
706
        )->sort("ID");
707
        $this->assertEquals(3, $list->count());
708
        $this->assertEquals('Joe', $list->first()->Name, 'First comment should be from Joe');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
709
        $this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
710
    }
711
712
    public function testSimpleFilterLessThanFilter()
713
    {
714
        $list = TeamComment::get();
715
        $list = $list->filter(
716
            'TeamID:LessThan',
717
            $this->idFromFixture(DataObjectTest\Team::class, 'team2')
718
        )->sort('Name');
719
        $this->assertEquals(2, $list->count());
720
        $this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
721
        $this->assertEquals('Joe', $list->Last()->Name, 'Last comment should be from Joe');
722
    }
723
724
    public function testSimpleFilterLessThanOrEqualFilter()
725
    {
726
        $list = TeamComment::get();
727
        $list = $list->filter(
728
            'TeamID:LessThanOrEqual',
729
            $this->idFromFixture(DataObjectTest\Team::class, 'team1')
730
        )->sort('ID');
731
        $this->assertEquals(2, $list->count());
732
        $this->assertEquals('Joe', $list->first()->Name, 'First comment should be from Joe');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
733
        $this->assertEquals('Bob', $list->Last()->Name, 'Last comment should be from Bob');
734
    }
735
736
    public function testSimplePartialMatchFilter()
737
    {
738
        $list = TeamComment::get();
739
        $list = $list->filter('Name:PartialMatch', 'o')->sort('Name');
740
        $this->assertEquals(2, $list->count());
741
        $this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
742
        $this->assertEquals('Joe', $list->last()->Name, 'First comment should be from Joe');
743
    }
744
745
    public function testSimpleFilterStartsWith()
746
    {
747
        $list = TeamComment::get();
748
        $list = $list->filter('Name:StartsWith', 'B');
749
        $this->assertEquals(1, $list->count());
750
        $this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
751
    }
752
753
    /**
754
     * @expectedException \SilverStripe\Core\Injector\InjectorNotFoundException
755
     * @expectedExceptionMessage Class DataListFilter.Bogus does not exist
756
     */
757
    public function testSimpleFilterWithNonExistingComparisator()
758
    {
759
        $list = TeamComment::get();
760
        $list->filter('Comment:Bogus', 'team comment');
761
    }
762
763
    /**
764
     * Invalid modifiers are treated as failed filter construction
765
     *
766
     * @expectedException \SilverStripe\Core\Injector\InjectorNotFoundException
767
     * @expectedExceptionMessage Class DataListFilter.invalidmodifier does not exist
768
     */
769
    public function testInvalidModifier()
770
    {
771
        $list = TeamComment::get();
772
        $list->filter('Comment:invalidmodifier', 'team comment');
773
    }
774
775
    /**
776
     * $list->filter('Name', array('aziz', 'bob'); // aziz and bob in list
777
     */
778
    public function testSimpleFilterWithMultiple()
779
    {
780
        $list = TeamComment::get();
781
        $list = $list->filter('Name', array('Bob','Phil'));
782
        $list = $list->sort('Name', 'ASC');
783
        $this->assertEquals(2, $list->count());
784
        $this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
785
        $this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
786
    }
787
788
    public function testMultipleFilterWithNoMatch()
789
    {
790
        $list = TeamComment::get();
791
        $list = $list->filter(array('Name'=>'Bob', 'Comment'=>'Phil is a unique guy, and comments on team2'));
792
        $this->assertEquals(0, $list->count());
793
    }
794
795
    /**
796
     *  $list->filter(array('Name'=>'bob, 'Age'=>21)); // bob with the age 21
797
     */
798
    public function testFilterMultipleArray()
799
    {
800
        $list = TeamComment::get();
801
        $list = $list->filter(array('Name'=>'Bob', 'Comment'=>'This is a team comment by Bob'));
802
        $list = $list->sort('Name', 'ASC');
803
        $this->assertEquals(1, $list->count());
804
        $this->assertEquals('Bob', $list->first()->Name, 'Only comment should be from Bob');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
805
    }
806
807
    public function testFilterMultipleWithTwoMatches()
808
    {
809
        $list = TeamComment::get();
810
        $list = $list->filter(array('TeamID'=>$this->idFromFixture(DataObjectTest\Team::class, 'team1')));
811
        $this->assertEquals(2, $list->count());
812
    }
813
814
    public function testFilterMultipleWithArrayFilter()
815
    {
816
        $list = TeamComment::get();
817
        $list = $list->filter(array('Name'=>array('Bob','Phil')));
818
        $list = $list->sort('Name', 'ASC');
819
        $this->assertEquals(2, $list->count(), 'There should be two comments');
820
        $this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
821
        $this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
822
    }
823
824
    public function testFilterMultipleWithArrayFilterAndModifiers()
825
    {
826
        $list = TeamComment::get();
827
        $list = $list->filter(array('Name:StartsWith'=>array('Bo', 'Jo')));
828
        $list = $list->sort('Name', 'ASC');
829
        $this->assertEquals(2, $list->count());
830
        $this->assertEquals('Bob', $list->first()->Name);
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
831
        $this->assertEquals('Joe', $list->last()->Name);
832
    }
833
834
    /**
835
     * $list->filter(array('Name'=>array('aziz','bob'), 'Age'=>array(21, 43)));
836
     */
837
    public function testFilterArrayInArray()
838
    {
839
        $list = TeamComment::get();
840
        $list = $list->filter(
841
            array(
842
            'Name'=>array('Bob','Phil'),
843
            'TeamID'=>array($this->idFromFixture(DataObjectTest\Team::class, 'team1')))
844
        );
845
        $this->assertEquals(1, $list->count(), 'There should be one comment');
846
        $this->assertEquals('Bob', $list->first()->Name, 'Only comment should be from Bob');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
847
    }
848
849
    public function testFilterWithModifiers()
850
    {
851
        $list = TeamComment::get();
852
        $nocaseList = $list->filter('Name:nocase', 'bob');
853
        $this->assertEquals(1, $nocaseList->count(), 'There should be one comment');
854
        $caseList = $list->filter('Name:case', 'bob');
855
        $this->assertEquals(0, $caseList->count(), 'There should be no comments');
856
        $gtList = $list->filter(
857
            'TeamID:GreaterThan:not',
858
            $this->idFromFixture(DataObjectTest\Team::class, 'team1')
859
        );
860
        $this->assertEquals(2, $gtList->count());
861
    }
862
863
    /**
864
     * Test that a filter correctly aliases relationships that share common classes
865
     */
866
    public function testFilterSharedRelationalClasses()
867
    {
868
        /** @var Bracket $final1 */
869
        $final1 = $this->objFromFixture(Bracket::class, 'final');
870
        $prefinal1 = $this->objFromFixture(Bracket::class, 'prefinal1');
871
        $prefinal2 = $this->objFromFixture(Bracket::class, 'prefinal2');
872
        $semifinal1 = $this->objFromFixture(Bracket::class, 'semifinal1');
873
        $team2 = $this->objFromFixture(Team::class, 'team2');
874
875
        // grand child can be found from parent
876
        $found = Bracket::get()->filter('Next.Next.Title', $final1->Title);
877
        $this->assertListEquals(
878
            [['Title' => $semifinal1->Title]],
879
            $found
880
        );
881
882
        // grand child can be found from child
883
        $found = Bracket::get()->filter('Next.Title', $prefinal1->Title);
884
        $this->assertListEquals(
885
            [['Title' => $semifinal1->Title]],
886
            $found
887
        );
888
889
        // child can be found from parent
890
        $found = Bracket::get()->filter('Next.Title', $final1->Title);
891
        $this->assertListEquals(
892
            [
893
                ['Title' => $prefinal1->Title],
894
                ['Title' => $prefinal2->Title]
895
            ],
896
            $found
897
        );
898
899
        // Complex filter, get brackets where the following bracket was won by team 1
900
        // Note: Includes results from multiple levels
901
        $found = Bracket::get()->filter('Next.Winner.Title', $team2->Title);
902
        $this->assertListEquals(
903
            [
904
                ['Title' => $prefinal1->Title],
905
                ['Title' => $prefinal2->Title],
906
                ['Title' => $semifinal1->Title]
907
            ],
908
            $found
909
        );
910
    }
911
912
    public function testFilterOnImplicitJoinWithSharedInheritance()
913
    {
914
        $list = DataObjectTest\RelationChildFirst::get()->filter(array(
915
            'ManyNext.ID' => array(
916
                $this->idFromFixture(DataObjectTest\RelationChildSecond::class, 'test1'),
917
                $this->idFromFixture(DataObjectTest\RelationChildSecond::class, 'test2'),
918
            ),
919
        ));
920
        $this->assertEquals(2, $list->count());
921
        $ids = $list->column('ID');
922
        $this->assertContains($this->idFromFixture(DataObjectTest\RelationChildFirst::class, 'test1'), $ids);
923
        $this->assertContains($this->idFromFixture(DataObjectTest\RelationChildFirst::class, 'test2'), $ids);
924
    }
925
926
    public function testFilterAny()
927
    {
928
        $list = TeamComment::get();
929
        $list = $list->filterAny('Name', 'Bob');
930
        $this->assertEquals(1, $list->count());
931
    }
932
933
    public function testFilterAnyWithRelation()
934
    {
935
        $list = Player::get();
936
        $list = $list->filterAny(array(
937
            'Teams.Title:StartsWith' => 'Team',
938
            'ID:GreaterThan' => 0,
939
        ));
940
        $this->assertCount(4, $list);
941
    }
942
943
    public function testFilterAnyMultipleArray()
944
    {
945
        $list = TeamComment::get();
946
        $list = $list->filterAny(array('Name'=>'Bob', 'Comment'=>'This is a team comment by Bob'));
947
        $this->assertEquals(1, $list->count());
948
        $this->assertEquals('Bob', $list->first()->Name, 'Only comment should be from Bob');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
949
    }
950
951
    public function testFilterAnyOnFilter()
952
    {
953
        $list = TeamComment::get();
954
        $list = $list->filter(
955
            array(
956
            'TeamID'=>$this->idFromFixture(DataObjectTest\Team::class, 'team1')
957
            )
958
        );
959
        $list = $list->filterAny(
960
            array(
961
            'Name'=>array('Phil', 'Joe'),
962
            'Comment'=>'This is a team comment by Bob'
963
            )
964
        );
965
        $list = $list->sort('Name');
966
        $this->assertEquals(2, $list->count());
967
        $this->assertEquals(
968
            'Bob',
969
            $list->offsetGet(0)->Name,
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
970
            'Results should include comments from Bob, matched by comment and team'
971
        );
972
        $this->assertEquals(
973
            'Joe',
974
            $list->offsetGet(1)->Name,
975
            'Results should include comments by Joe, matched by name and team (not by comment)'
976
        );
977
978
        $list = TeamComment::get();
979
        $list = $list->filter(
980
            array(
981
            'TeamID'=>$this->idFromFixture(DataObjectTest\Team::class, 'team1')
982
            )
983
        );
984
        $list = $list->filterAny(
985
            array(
986
            'Name'=>array('Phil', 'Joe'),
987
            'Comment'=>'This is a team comment by Bob'
988
            )
989
        );
990
        $list = $list->sort('Name');
991
        $list = $list->filter(array('Name' => 'Bob'));
992
        $this->assertEquals(1, $list->count());
993
        $this->assertEquals(
994
            'Bob',
995
            $list->offsetGet(0)->Name,
996
            'Results should include comments from Bob, matched by name and team'
997
        );
998
    }
999
1000
    public function testFilterAnyMultipleWithArrayFilter()
1001
    {
1002
        $list = TeamComment::get();
1003
        $list = $list->filterAny(array('Name'=>array('Bob','Phil')));
1004
        $this->assertEquals(2, $list->count(), 'There should be two comments');
1005
        $this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
1006
        $this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
1007
    }
1008
1009
    public function testFilterAnyArrayInArray()
1010
    {
1011
        $list = TeamComment::get();
1012
        $list = $list->filterAny(
1013
            array(
1014
            'Name'=>array('Bob','Phil'),
1015
            'TeamID'=>array($this->idFromFixture(DataObjectTest\Team::class, 'team1')))
1016
        )
1017
            ->sort('Name');
1018
        $this->assertEquals(3, $list->count());
1019
        $this->assertEquals(
1020
            'Bob',
1021
            $list->offsetGet(0)->Name,
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
1022
            'Results should include comments from Bob, matched by name and team'
1023
        );
1024
        $this->assertEquals(
1025
            'Joe',
1026
            $list->offsetGet(1)->Name,
1027
            'Results should include comments by Joe, matched by team (not by name)'
1028
        );
1029
        $this->assertEquals(
1030
            'Phil',
1031
            $list->offsetGet(2)->Name,
1032
            'Results should include comments from Phil, matched by name (even if he\'s not in Team1)'
1033
        );
1034
    }
1035
1036
    public function testFilterOnJoin()
1037
    {
1038
        $list = TeamComment::get()
1039
            ->leftJoin(
1040
                'DataObjectTest_Team',
1041
                '"DataObjectTest_Team"."ID" = "DataObjectTest_TeamComment"."TeamID"'
1042
            )->filter(
1043
                array(
1044
                'Title' => 'Team 1'
1045
                )
1046
            );
1047
1048
        $this->assertEquals(2, $list->count());
1049
        $values = $list->column('Name');
1050
        $this->assertEquals(array_intersect($values, array('Joe', 'Bob')), $values);
1051
    }
1052
1053
    public function testFilterOnImplicitJoin()
1054
    {
1055
        // Many to many
1056
        $list = Team::get()
1057
            ->filter('Players.FirstName', array('Captain', 'Captain 2'));
1058
1059
        $this->assertEquals(2, $list->count());
1060
1061
        // Has many
1062
        $list = Team::get()
1063
            ->filter('Comments.Name', array('Joe', 'Phil'));
1064
1065
        $this->assertEquals(2, $list->count());
1066
1067
        // Has one
1068
        $list = Player::get()
1069
            ->filter('FavouriteTeam.Title', 'Team 1');
1070
1071
        $this->assertEquals(1, $list->count());
1072
        $this->assertEquals('007', $list->first()->ShirtNumber);
0 ignored issues
show
Bug Best Practice introduced by
The property ShirtNumber does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
1073
    }
1074
1075
    /**
1076
     * @expectedException \InvalidArgumentException
1077
     * @expectedExceptionMessage MascotAnimal is not a relation on model SilverStripe\ORM\Tests\DataObjectTest\Team
1078
     */
1079
    public function testFilterOnInvalidRelation()
1080
    {
1081
        // Filter on missing relation 'MascotAnimal'
1082
        Team::get()
1083
            ->filter('MascotAnimal.Name', 'Richard')
1084
            ->toArray();
1085
    }
1086
1087
    public function testFilterAndExcludeById()
1088
    {
1089
        $id = $this->idFromFixture(SubTeam::class, 'subteam1');
1090
        $list = SubTeam::get()->filter('ID', $id);
1091
        $this->assertEquals($id, $list->first()->ID);
1092
1093
        $list = SubTeam::get();
1094
        $this->assertEquals(3, count($list));
1095
        $this->assertEquals(2, count($list->exclude('ID', $id)));
1096
    }
1097
1098
    /**
1099
     * @skipUpgrade
1100
     */
1101
    public function testFilterByNull()
1102
    {
1103
        $list = Fan::get();
1104
        // Force DataObjectTest_Fan/fan5::Email to empty string
1105
        $fan5id = $this->idFromFixture(Fan::class, 'fan5');
1106
        DB::prepared_query("UPDATE \"DataObjectTest_Fan\" SET \"Email\" = '' WHERE \"ID\" = ?", array($fan5id));
1107
1108
        // Filter by null email
1109
        $nullEmails = $list->filter('Email', null);
1110
        $this->assertListEquals(
1111
            array(
1112
            array(
1113
                'Name' => 'Stephen',
1114
            ),
1115
            array(
1116
                'Name' => 'Mitch',
1117
            )
1118
            ),
1119
            $nullEmails
1120
        );
1121
1122
        // Filter by non-null
1123
        $nonNullEmails = $list->filter('Email:not', null);
1124
        $this->assertListEquals(
1125
            array(
1126
            array(
1127
                'Name' => 'Damian',
1128
                'Email' => '[email protected]',
1129
            ),
1130
            array(
1131
                'Name' => 'Richard',
1132
                'Email' => '[email protected]',
1133
            ),
1134
            array(
1135
                'Name' => 'Hamish',
1136
            )
1137
            ),
1138
            $nonNullEmails
1139
        );
1140
1141
        // Filter by empty only
1142
        $emptyOnly = $list->filter('Email', '');
1143
        $this->assertListEquals(
1144
            array(
1145
            array(
1146
                'Name' => 'Hamish',
1147
            )
1148
            ),
1149
            $emptyOnly
1150
        );
1151
1152
        // Non-empty only. This should include null values, since ExactMatchFilter works around
1153
        // the caveat that != '' also excludes null values in ANSI SQL-92 behaviour.
1154
        $nonEmptyOnly = $list->filter('Email:not', '');
1155
        $this->assertListEquals(
1156
            array(
1157
            array(
1158
                'Name' => 'Damian',
1159
                'Email' => '[email protected]',
1160
            ),
1161
            array(
1162
                'Name' => 'Richard',
1163
                'Email' => '[email protected]',
1164
            ),
1165
            array(
1166
                'Name' => 'Stephen',
1167
            ),
1168
            array(
1169
                'Name' => 'Mitch',
1170
            )
1171
            ),
1172
            $nonEmptyOnly
1173
        );
1174
1175
        // Filter by many including null, empty string, and non-empty
1176
        $items1 = $list->filter('Email', array(null, '', '[email protected]'));
1177
        $this->assertListEquals(
1178
            array(
1179
            array(
1180
                'Name' => 'Damian',
1181
                'Email' => '[email protected]',
1182
            ),
1183
            array(
1184
                'Name' => 'Stephen',
1185
            ),
1186
            array(
1187
                'Name' => 'Mitch',
1188
            ),
1189
            array(
1190
                'Name' => 'Hamish',
1191
            )
1192
            ),
1193
            $items1
1194
        );
1195
1196
        // Filter exclusion of above list
1197
        $items2 = $list->filter('Email:not', array(null, '', '[email protected]'));
1198
        $this->assertListEquals(
1199
            array(
1200
            array(
1201
                'Name' => 'Richard',
1202
                'Email' => '[email protected]',
1203
            ),
1204
            ),
1205
            $items2
1206
        );
1207
1208
        // Filter by many including empty string and non-empty
1209
        $items3 = $list->filter('Email', array('', '[email protected]'));
1210
        $this->assertListEquals(
1211
            array(
1212
            array(
1213
                'Name' => 'Damian',
1214
                'Email' => '[email protected]',
1215
            ),
1216
            array(
1217
                'Name' => 'Hamish',
1218
            )
1219
            ),
1220
            $items3
1221
        );
1222
1223
        // Filter by many including empty string and non-empty
1224
        // This also relies no the workaround for null comparison as in the $nonEmptyOnly test
1225
        $items4 = $list->filter('Email:not', array('', '[email protected]'));
1226
        $this->assertListEquals(
1227
            array(
1228
            array(
1229
                'Name' => 'Richard',
1230
                'Email' => '[email protected]',
1231
            ),
1232
            array(
1233
                'Name' => 'Stephen',
1234
            ),
1235
            array(
1236
                'Name' => 'Mitch',
1237
            )
1238
            ),
1239
            $items4
1240
        );
1241
1242
        // Filter by many including empty string and non-empty
1243
        // The extra null check isn't necessary, but check that this doesn't fail
1244
        $items5 = $list->filterAny(
1245
            array(
1246
            'Email:not' => array('', '[email protected]'),
1247
            'Email' => null
1248
            )
1249
        );
1250
        $this->assertListEquals(
1251
            array(
1252
            array(
1253
                'Name' => 'Richard',
1254
                'Email' => '[email protected]',
1255
            ),
1256
            array(
1257
                'Name' => 'Stephen',
1258
            ),
1259
            array(
1260
                'Name' => 'Mitch',
1261
            )
1262
            ),
1263
            $items5
1264
        );
1265
1266
        // Filter by null or empty values
1267
        $items6 = $list->filter('Email', array(null, ''));
1268
        $this->assertListEquals(
1269
            array(
1270
            array(
1271
                'Name' => 'Stephen',
1272
            ),
1273
            array(
1274
                'Name' => 'Mitch',
1275
            ),
1276
            array(
1277
                'Name' => 'Hamish',
1278
            )
1279
            ),
1280
            $items6
1281
        );
1282
    }
1283
1284
    /**
1285
     * Test null checks with case modifiers
1286
     */
1287
    public function testFilterByNullCase()
1288
    {
1289
        // Test with case (case/nocase both use same code path)
1290
        // Test with and without null, and with inclusion/exclusion permutations
1291
        $list = Fan::get();
1292
1293
        // Only an explicit NOT NULL should include null values
1294
        $items6 = $list->filter('Email:not:case', array(null, '', '[email protected]'));
1295
        $this->assertSQLContains(' AND "DataObjectTest_Fan"."Email" IS NOT NULL', $items6->sql());
1296
1297
        // These should all include values where Email IS NULL
1298
        $items7 = $list->filter('Email:nocase', array(null, '', '[email protected]'));
1299
        $this->assertSQLContains(' OR "DataObjectTest_Fan"."Email" IS NULL', $items7->sql());
1300
        $items8 = $list->filter('Email:not:case', array('', '[email protected]'));
1301
        $this->assertSQLContains(' OR "DataObjectTest_Fan"."Email" IS NULL', $items8->sql());
1302
1303
        // These should not contain any null checks at all
1304
        $items9 = $list->filter('Email:nocase', array('', '[email protected]'));
1305
        $this->assertSQLNotContains('"DataObjectTest_Fan"."Email" IS NULL', $items9->sql());
1306
        $this->assertSQLNotContains('"DataObjectTest_Fan"."Email" IS NOT NULL', $items9->sql());
1307
    }
1308
1309
    public function testAggregateDBName()
1310
    {
1311
        $filter = new ExactMatchFilter(
1312
            'Comments.Count()'
1313
        );
1314
        $filter->apply(new DataQuery(DataObjectTest\Team::class));
1315
        $this->assertEquals('COUNT("comments_DataObjectTest_TeamComment"."ID")', $filter->getDBName());
1316
1317
        foreach (['Comments.Max(ID)', 'Comments.Max( ID )', 'Comments.Max(  ID)'] as $name) {
1318
            $filter = new ExactMatchFilter($name);
1319
            $filter->apply(new DataQuery(DataObjectTest\Team::class));
1320
            $this->assertEquals('MAX("comments_DataObjectTest_TeamComment"."ID")', $filter->getDBName());
1321
        }
1322
    }
1323
1324
    public function testAggregateFilterExceptions()
1325
    {
1326
        $ex = null;
1327
        try {
1328
            $filter = new ExactMatchFilter('Comments.Max( This will not parse! )');
0 ignored issues
show
Unused Code introduced by
The assignment to $filter is dead and can be removed.
Loading history...
1329
        } catch (\Exception $e) {
1330
            $ex = $e;
1331
        }
1332
        $this->assertInstanceOf(\InvalidArgumentException::class, $ex);
1333
        $this->assertRegExp('/Malformed/', $ex->getMessage());
0 ignored issues
show
Bug introduced by
The method getMessage() does not exist on null. ( Ignorable by Annotation )

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

1333
        $this->assertRegExp('/Malformed/', $ex->/** @scrutinizer ignore-call */ getMessage());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1334
1335
1336
        $filter = new ExactMatchFilter('Comments.Max(NonExistentColumn)');
1337
        $filter->setModel(new DataObjectTest\Team());
1338
        $ex = null;
1339
        try {
1340
            $name = $filter->getDBName();
0 ignored issues
show
Unused Code introduced by
The assignment to $name is dead and can be removed.
Loading history...
1341
        } catch (\Exception $e) {
1342
            $ex = $e;
1343
        }
1344
        $this->assertInstanceOf(\InvalidArgumentException::class, $ex);
1345
        $this->assertRegExp('/Invalid column/', $ex->getMessage());
1346
    }
1347
1348
    public function testAggregateFilters()
1349
    {
1350
        $teams = Team::get()->filter('Comments.Count()', 2);
1351
1352
        $team1 = $this->objFromFixture(Team::class, 'team1');
1353
        $team2 = $this->objFromFixture(Team::class, 'team2');
1354
        $team3 = $this->objFromFixture(Team::class, 'team3');
1355
        $team4 = $this->objFromFixture(SubTeam::class, 'subteam1');
1356
        $team5 = $this->objFromFixture(SubTeam::class, 'subteam2_with_player_relation');
1357
        $team6 = $this->objFromFixture(SubTeam::class, 'subteam3_with_empty_fields');
1358
1359
        $company1 = $this->objFromFixture(EquipmentCompany::class, 'equipmentcompany1');
1360
        $company2 = $this->objFromFixture(EquipmentCompany::class, 'equipmentcompany2');
1361
1362
        $company1->CurrentStaff()->add(Staff::create(['Salary' => 3])->write());
0 ignored issues
show
Bug introduced by
The method CurrentStaff() does not exist on SilverStripe\ORM\DataObject. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

1362
        $company1->/** @scrutinizer ignore-call */ 
1363
                   CurrentStaff()->add(Staff::create(['Salary' => 3])->write());
Loading history...
1363
        $company1->CurrentStaff()->add(Staff::create(['Salary' => 5])->write());
1364
        $company2->CurrentStaff()->add(Staff::create(['Salary' => 4])->write());
1365
1366
        $this->assertCount(1, $teams);
1367
        $this->assertEquals($team1->ID, $teams->first()->ID);
1368
1369
        $teams = Team::get()->filter('Comments.Count()', [1,2]);
1370
1371
        $this->assertCount(2, $teams);
1372
        foreach ([$team1, $team2] as $expectedTeam) {
1373
            $this->assertContains($expectedTeam->ID, $teams->column('ID'));
1374
        }
1375
1376
        $teams = Team::get()->filter('Comments.Count():GreaterThan', 1);
1377
1378
        $this->assertCount(1, $teams);
1379
        $this->assertContains(
1380
            $this->objFromFixture(Team::class, 'team1')->ID,
1381
            $teams->column('ID')
1382
        );
1383
1384
        $teams = Team::get()->filter('Comments.Count():LessThan', 2);
1385
1386
        $this->assertCount(5, $teams);
1387
        foreach ([$team2, $team3, $team4, $team5, $team6] as $expectedTeam) {
1388
            $this->assertContains($expectedTeam->ID, $teams->column('ID'));
1389
        }
1390
1391
        $teams = Team::get()->filter('Comments.Count():GreaterThanOrEqual', 1);
1392
1393
        $this->assertCount(2, $teams);
1394
        foreach ([$team1, $team2] as $expectedTeam) {
1395
            $this->assertContains($expectedTeam->ID, $teams->column('ID'));
1396
        }
1397
1398
        $teams = Team::get()->filter('Comments.Count():LessThanOrEqual', 1);
1399
1400
        $this->assertCount(5, $teams);
1401
        foreach ([$team2, $team3, $team4, $team5, $team6] as $expectedTeam) {
1402
            $this->assertContains($expectedTeam->ID, $teams->column('ID'));
1403
        }
1404
1405
        $companies = EquipmentCompany::get()->filter('CurrentStaff.Max(Salary)', 5);
1406
        $this->assertCount(1, $companies);
1407
        $this->assertEquals($company1->ID, $companies->first()->ID);
1408
1409
        $companies = EquipmentCompany::get()->filter('CurrentStaff.Min(Salary)', 3);
1410
        $this->assertCount(1, $companies);
1411
        $this->assertEquals($company1->ID, $companies->first()->ID);
1412
1413
        $companies = EquipmentCompany::get()->filter('CurrentStaff.Max(Salary):GreaterThan', 3);
1414
        $this->assertCount(2, $companies);
1415
        foreach ([$company1, $company2] as $expectedTeam) {
1416
            $this->assertContains($expectedTeam->ID, $companies->column('ID'));
1417
        }
1418
1419
        $companies = EquipmentCompany::get()->filter('CurrentStaff.Sum(Salary)', 8);
1420
        $this->assertCount(1, $companies);
1421
        $this->assertEquals($company1->ID, $companies->first()->ID);
1422
1423
        $companies = EquipmentCompany::get()->filter('CurrentStaff.Sum(Salary):LessThan', 7);
1424
        $this->assertCount(1, $companies);
1425
        $this->assertEquals($company2->ID, $companies->first()->ID);
1426
1427
        $companies = EquipmentCompany::get()->filter('CurrentStaff.Sum(Salary):GreaterThan', 100);
1428
        $this->assertCount(0, $companies);
1429
1430
        $companies = EquipmentCompany::get()->filter('CurrentStaff.Sum(Salary):GreaterThan', 7);
1431
        $this->assertCount(1, $companies);
1432
        $this->assertEquals($company1->ID, $companies->first()->ID);
1433
1434
        $companies = EquipmentCompany::get()->filter('CurrentStaff.Avg(Salary)', 4);
1435
        $this->assertCount(2, $companies);
1436
        foreach ([$company1, $company2] as $expectedTeam) {
1437
            $this->assertContains($expectedTeam->ID, $companies->column('ID'));
1438
        }
1439
1440
        $companies = EquipmentCompany::get()->filter('CurrentStaff.Avg(Salary):LessThan', 10);
1441
        $this->assertCount(2, $companies);
1442
        foreach ([$company1, $company2] as $expectedTeam) {
1443
            $this->assertContains($expectedTeam->ID, $companies->column('ID'));
1444
        }
1445
    }
1446
1447
    /**
1448
     * $list = $list->filterByCallback(function($item, $list) { return $item->Age == 21; })
1449
     */
1450
    public function testFilterByCallback()
1451
    {
1452
        $team1ID = $this->idFromFixture(DataObjectTest\Team::class, 'team1');
1453
        $list = TeamComment::get();
1454
        $list = $list->filterByCallback(
1455
            function ($item, $list) use ($team1ID) {
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

1455
            function ($item, /** @scrutinizer ignore-unused */ $list) use ($team1ID) {

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...
1456
                return $item->TeamID == $team1ID;
1457
            }
1458
        );
1459
1460
        $result = $list->column('Name');
1461
        $expected = array_intersect($result, array('Joe', 'Bob'));
1462
1463
        $this->assertEquals(2, $list->count());
1464
        $this->assertEquals($expected, $result, 'List should only contain comments from Team 1 (Joe and Bob)');
1465
        $this->assertTrue($list instanceof Filterable, 'The List should be of type SS_Filterable');
1466
    }
1467
1468
    /**
1469
     * $list->exclude('Name', 'bob'); // exclude bob from list
1470
     */
1471
    public function testSimpleExclude()
1472
    {
1473
        $list = TeamComment::get();
1474
        $list = $list->exclude('Name', 'Bob');
1475
        $list = $list->sort('Name');
1476
        $this->assertEquals(2, $list->count());
1477
        $this->assertEquals('Joe', $list->first()->Name, 'First comment should be from Joe');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
1478
        $this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
1479
    }
1480
    //
1481
    /**
1482
     * $list->exclude('Name', array('aziz', 'bob'); // exclude aziz and bob from list
1483
     */
1484
    public function testSimpleExcludeWithMultiple()
1485
    {
1486
        $list = TeamComment::get();
1487
        $list = $list->exclude('Name', array('Joe','Phil'));
1488
        $this->assertEquals(1, $list->count());
1489
        $this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
1490
    }
1491
1492
    /**
1493
     * $list->exclude(array('Name'=>'bob, 'Age'=>21)); // negative version
1494
     */
1495
    public function testMultipleExcludeWithMiss()
1496
    {
1497
        $list = TeamComment::get();
1498
        $list = $list->exclude(array('Name'=>'Bob', 'Comment'=>'Does not match any comments'));
1499
        $this->assertEquals(3, $list->count());
1500
    }
1501
1502
    /**
1503
     * $list->exclude(array('Name'=>'bob, 'Age'=>21)); // exclude bob that has Age 21
1504
     */
1505
    public function testMultipleExclude()
1506
    {
1507
        $list = TeamComment::get();
1508
        $list = $list->exclude(array('Name'=>'Bob', 'Comment'=>'This is a team comment by Bob'));
1509
        $this->assertEquals(2, $list->count());
1510
    }
1511
1512
    /**
1513
     * Test that if an exclude() is applied to a filter(), the filter() is still preserved.
1514
     */
1515
    public function testExcludeOnFilter()
1516
    {
1517
        /**
1518
 * @var DataList $list
1519
*/
1520
        $list = TeamComment::get();
1521
        $list = $list->filter('Comment', 'Phil is a unique guy, and comments on team2');
1522
        $list = $list->exclude('Name', 'Bob');
1523
1524
        $sql = $list->sql($parameters);
1525
        $this->assertSQLContains(
1526
            'WHERE ("DataObjectTest_TeamComment"."Comment" = ?) AND (("DataObjectTest_TeamComment"."Name" != ? '
1527
            . 'OR "DataObjectTest_TeamComment"."Name" IS NULL))',
1528
            $sql
1529
        );
1530
        $this->assertEquals(array('Phil is a unique guy, and comments on team2', 'Bob'), $parameters);
1531
    }
1532
1533
    public function testExcludeWithSearchFilter()
1534
    {
1535
        $list = TeamComment::get();
1536
        $list = $list->exclude('Name:LessThan', 'Bob');
1537
1538
        $sql = $list->sql($parameters);
1539
        $this->assertSQLContains('WHERE (("DataObjectTest_TeamComment"."Name" >= ?))', $sql);
1540
        $this->assertEquals(array('Bob'), $parameters);
1541
    }
1542
1543
    /**
1544
     * Test exact match filter with empty array items
1545
     *
1546
     * @expectedException \InvalidArgumentException
1547
     * @expectedExceptionMessage Cannot filter "DataObjectTest_TeamComment"."Name" against an empty set
1548
     */
1549
    public function testEmptyFilter()
1550
    {
1551
        $list = TeamComment::get();
1552
        $list->exclude('Name', array());
1553
    }
1554
1555
    /**
1556
     * $list->exclude(array('Name'=>'bob, 'Age'=>array(21, 43))); // exclude bob with Age 21 or 43
1557
     */
1558
    public function testMultipleExcludeWithMultipleThatCheersEitherTeam()
1559
    {
1560
        $list = TeamComment::get();
1561
        $list = $list->exclude(
1562
            array('Name'=>'Bob', 'TeamID'=>array(
1563
            $this->idFromFixture(DataObjectTest\Team::class, 'team1'),
1564
            $this->idFromFixture(DataObjectTest\Team::class, 'team2')
1565
            ))
1566
        );
1567
        $list = $list->sort('Name');
1568
        $this->assertEquals(2, $list->count());
1569
        $this->assertEquals('Joe', $list->first()->Name, 'First comment should be from Phil');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
1570
        $this->assertEquals('Phil', $list->last()->Name, 'First comment should be from Phil');
1571
    }
1572
1573
    /**
1574
     * $list->exclude(array('Name'=>'bob, 'Age'=>array(21, 43))); // negative version
1575
     */
1576
    public function testMultipleExcludeWithMultipleThatCheersOnNonExistingTeam()
1577
    {
1578
        $list = TeamComment::get();
1579
        $list = $list->exclude(array('Name'=>'Bob', 'TeamID'=>array(3)));
1580
        $this->assertEquals(3, $list->count());
1581
    }
1582
1583
    /**
1584
     * $list->exclude(array('Name'=>array('bob','phil'), 'Age'=>array(21, 43))); //negative version
1585
     */
1586
    public function testMultipleExcludeWithNoExclusion()
1587
    {
1588
        $list = TeamComment::get();
1589
        $list = $list->exclude(
1590
            array(
1591
            'Name'=>array('Bob','Joe'),
1592
            'Comment' => 'Phil is a unique guy, and comments on team2')
1593
        );
1594
        $this->assertEquals(3, $list->count());
1595
    }
1596
1597
    /**
1598
     *  $list->exclude(array('Name'=>array('bob','phil'), 'Age'=>array(21, 43)));
1599
     */
1600
    public function testMultipleExcludeWithTwoArray()
1601
    {
1602
        $list = TeamComment::get();
1603
        $list = $list->exclude(
1604
            array('Name' => array('Bob','Joe'), 'TeamID' => array(
1605
            $this->idFromFixture(DataObjectTest\Team::class, 'team1'),
1606
            $this->idFromFixture(DataObjectTest\Team::class, 'team2')
1607
            ))
1608
        );
1609
        $this->assertEquals(1, $list->count());
1610
        $this->assertEquals('Phil', $list->last()->Name, 'Only comment should be from Phil');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
1611
    }
1612
1613
    /**
1614
     *  $list->exclude(array('Name'=>array('bob','phil'), 'Age'=>array(21, 43)));
1615
     */
1616
    public function testMultipleExcludeWithTwoArrayOneTeam()
1617
    {
1618
        $list = TeamComment::get();
1619
        $list = $list->exclude(
1620
            array(
1621
            'Name' => array('Bob', 'Phil'),
1622
            'TeamID' => array($this->idFromFixture(DataObjectTest\Team::class, 'team1')))
1623
        );
1624
        $list = $list->sort('Name');
1625
        $this->assertEquals(2, $list->count());
1626
        $this->assertEquals('Joe', $list->first()->Name, 'First comment should be from Joe');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
1627
        $this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
1628
    }
1629
1630
    /**
1631
     *
1632
     */
1633
    public function testSortByRelation()
1634
    {
1635
        $list = TeamComment::get();
1636
        $list = $list->sort(array('Team.Title' => 'DESC'));
1637
        $this->assertEquals(3, $list->count());
1638
        $this->assertEquals(
1639
            $this->idFromFixture(DataObjectTest\Team::class, 'team2'),
1640
            $list->first()->TeamID,
0 ignored issues
show
Bug Best Practice introduced by
The property TeamID does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
1641
            'First comment should be for Team 2'
1642
        );
1643
        $this->assertEquals(
1644
            $this->idFromFixture(DataObjectTest\Team::class, 'team1'),
1645
            $list->last()->TeamID,
1646
            'Last comment should be for Team 1'
1647
        );
1648
    }
1649
1650
    public function testReverse()
1651
    {
1652
        $list = TeamComment::get();
1653
        $list = $list->sort('Name');
1654
        $list = $list->reverse();
1655
1656
        $this->assertEquals('Bob', $list->last()->Name, 'Last comment should be from Bob');
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
1657
        $this->assertEquals('Phil', $list->first()->Name, 'First comment should be from Phil');
1658
    }
1659
1660
    public function testSortByComplexExpression()
1661
    {
1662
        // Test an expression with both spaces and commas. This test also tests that column() can be called
1663
        // with a complex sort expression, so keep using column() below
1664
        $teamClass = Convert::raw2sql(SubTeam::class);
1665
        $list = Team::get()->sort(
1666
            'CASE WHEN "DataObjectTest_Team"."ClassName" = \''.$teamClass.'\' THEN 0 ELSE 1 END, "Title" DESC'
1667
        );
1668
        $this->assertEquals(
1669
            array(
1670
            'Subteam 3',
1671
            'Subteam 2',
1672
            'Subteam 1',
1673
            'Team 3',
1674
            'Team 2',
1675
            'Team 1',
1676
            ),
1677
            $list->column("Title")
1678
        );
1679
    }
1680
}
1681