Completed
Push — master ( 61abbf...bcc21c )
by Daniel
09:54
created

testMultipleExcludeWithMultipleThatCheersEitherTeam()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 9
nc 1
nop 0
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
use SilverStripe\ORM\DataList;
4
use SilverStripe\ORM\DB;
5
use SilverStripe\ORM\Filterable;
6
use SilverStripe\Dev\SapphireTest;
7
8
9
/**
10
 * @package framework
11
 * @subpackage tests
12
 */
13
class DataListTest extends SapphireTest {
14
15
	// Borrow the model from DataObjectTest
16
	protected static $fixture_file = 'DataObjectTest.yml';
17
18
	public function setUpOnce() {
19
		$this->extraDataObjects = DataObjectTest::$extra_data_objects;
20
		parent::setUpOnce();
21
	}
22
23
	public function testFilterDataObjectByCreatedDate() {
24
		// create an object to test with
25
		$obj1 = new DataObjectTest_ValidatedObject();
26
		$obj1->Name = 'test obj 1';
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<DataObjectTest_ValidatedObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
27
		$obj1->write();
28
		$this->assertTrue($obj1->isInDB());
29
30
		// reload the object from the database and reset its Created timestamp to a known value
31
		$obj1 = DataObjectTest_ValidatedObject::get()->filter(array('Name' => 'test obj 1'))->first();
32
		$this->assertTrue(is_object($obj1));
33
		$this->assertEquals('test obj 1', $obj1->Name);
34
		$obj1->Created = '2013-01-01 00:00:00';
35
		$obj1->write();
36
37
		// reload the object again and make sure that our Created date was properly persisted
38
		$obj1 = DataObjectTest_ValidatedObject::get()->filter(array('Name' => 'test obj 1'))->first();
39
		$this->assertTrue(is_object($obj1));
40
		$this->assertEquals('test obj 1', $obj1->Name);
41
		$this->assertEquals('2013-01-01 00:00:00', $obj1->Created);
42
43
		// now save a second object to the DB with an automatically-set Created value
44
		$obj2 = new DataObjectTest_ValidatedObject();
45
		$obj2->Name = 'test obj 2';
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<DataObjectTest_ValidatedObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
46
		$obj2->write();
47
		$this->assertTrue($obj2->isInDB());
48
49
		// and a third object
50
		$obj3 = new DataObjectTest_ValidatedObject();
51
		$obj3->Name = 'test obj 3';
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<DataObjectTest_ValidatedObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
52
		$obj3->write();
53
		$this->assertTrue($obj3->isInDB());
54
55
		// now test the filtering based on Created timestamp
56
		$list = DataObjectTest_ValidatedObject::get()
57
			->filter(array('Created:GreaterThan' => '2013-02-01 00:00:00'))
58
			->toArray();
59
		$this->assertEquals(2, count($list));
60
61
	}
62
63
	public function testSubtract(){
64
		$comment1 = $this->objFromFixture('DataObjectTest_TeamComment', 'comment1');
65
		$subtractList = DataObjectTest_TeamComment::get()->filter('ID', $comment1->ID);
66
		$fullList = DataObjectTest_TeamComment::get();
67
		$newList = $fullList->subtract($subtractList);
68
		$this->assertEquals(2, $newList->Count(), 'List should only contain two objects after subtraction');
69
	}
70
71
	public function testSubtractBadDataclassThrowsException(){
72
		$this->setExpectedException('InvalidArgumentException');
73
		$teamsComments = DataObjectTest_TeamComment::get();
74
		$teams = DataObjectTest_Team::get();
75
		$teamsComments->subtract($teams);
76
	}
77
78
	public function testListCreationSortAndLimit() {
79
		// By default, a DataList will contain all items of that class
80
		$list = DataObjectTest_TeamComment::get()->sort('ID');
81
82
		// We can iterate on the DataList
83
		$names = array();
84
		foreach($list as $item) {
85
			$names[] = $item->Name;
86
		}
87
		$this->assertEquals(array('Joe', 'Bob', 'Phil'), $names);
88
89
		// If we don't want to iterate, we can extract a single column from the list with column()
90
		$this->assertEquals(array('Joe', 'Bob', 'Phil'), $list->column('Name'));
91
92
		// We can sort a list
93
		$list = $list->sort('Name');
94
		$this->assertEquals(array('Bob', 'Joe', 'Phil'), $list->column('Name'));
95
96
		// We can also restrict the output to a range
97
		$this->assertEquals(array('Joe', 'Phil'), $list->limit(2, 1)->column('Name'));
98
	}
99
100
	public function testLimitAndOffset() {
101
		$list = DataObjectTest_TeamComment::get();
102
		$check = $list->limit(3);
103
104
		$this->assertEquals(3, $check->count());
105
106
		$check = $list->limit(1);
107
		$this->assertEquals(1, $check->count());
108
109
		$check = $list->limit(1, 1);
110
		$this->assertEquals(1, $check->count());
111
112
		$check = $list->limit(false);
113
		$this->assertEquals(3, $check->count());
114
115
		$check = $list->limit(null);
116
		$this->assertEquals(3, $check->count());
117
118
		$check = $list->limit(null, 2);
119
		$this->assertEquals(1, $check->count());
120
121
		// count()/first()/last() methods may alter limit/offset, so run the query and manually check the count
122
		$check = $list->limit(null, 1)->toArray();
123
		$this->assertEquals(2, count($check));
124
	}
125
126
	public function testDistinct() {
127
		$list = DataObjectTest_TeamComment::get();
128
		$this->assertContains('SELECT DISTINCT', $list->dataQuery()->sql($params), 'Query is set as distinct by default');
129
130
		$list = $list->distinct(false);
131
		$this->assertNotContains('SELECT DISTINCT', $list->dataQuery()->sql($params), 'Query does not contain distinct');
132
133
		$list = $list->distinct(true);
134
		$this->assertContains('SELECT DISTINCT', $list->dataQuery()->sql($params), 'Query contains distinct');
135
	}
136
137
	public function testDataClass() {
138
		$list = DataObjectTest_TeamComment::get();
139
		$this->assertEquals('DataObjectTest_TeamComment',$list->dataClass());
140
	}
141
142
	public function testDataClassCaseInsensitive() {
143
		$list = DataList::create('dataobjecttest_teamcomment');
144
		$this->assertTrue($list->exists());
145
	}
146
147
	public function testClone() {
148
		$list = DataObjectTest_TeamComment::get();
149
		$this->assertEquals($list, clone($list));
150
	}
151
152
	public function testSql() {
153
		$db = DB::get_conn();
154
		$list = DataObjectTest_TeamComment::get();
155
		$expected = 'SELECT DISTINCT "DataObjectTest_TeamComment"."ClassName", '
156
			. '"DataObjectTest_TeamComment"."LastEdited", "DataObjectTest_TeamComment"."Created", '
157
			. '"DataObjectTest_TeamComment"."Name", "DataObjectTest_TeamComment"."Comment", '
158
			. '"DataObjectTest_TeamComment"."TeamID", "DataObjectTest_TeamComment"."ID", '
159
			. 'CASE WHEN "DataObjectTest_TeamComment"."ClassName" IS NOT NULL '
160
			. 'THEN "DataObjectTest_TeamComment"."ClassName" ELSE '
161
			. $db->quoteString('DataObjectTest_TeamComment')
162
			. ' END AS "RecordClassName" FROM "DataObjectTest_TeamComment"'
163
			. ' ORDER BY "DataObjectTest_TeamComment"."Name" ASC';
164
		$this->assertSQLEquals($expected, $list->sql($parameters));
165
	}
166
167
	public function testInnerJoin() {
168
		$db = DB::get_conn();
169
170
		$list = DataObjectTest_TeamComment::get();
171
		$list = $list->innerJoin(
172
			'DataObjectTest_Team',
173
			'"DataObjectTest_Team"."ID" = "DataObjectTest_TeamComment"."TeamID"',
174
			'Team'
175
		);
176
177
		$expected = 'SELECT DISTINCT "DataObjectTest_TeamComment"."ClassName", '
178
			. '"DataObjectTest_TeamComment"."LastEdited", "DataObjectTest_TeamComment"."Created", '
179
			. '"DataObjectTest_TeamComment"."Name", "DataObjectTest_TeamComment"."Comment", '
180
			. '"DataObjectTest_TeamComment"."TeamID", "DataObjectTest_TeamComment"."ID", '
181
			. 'CASE WHEN "DataObjectTest_TeamComment"."ClassName" IS NOT NULL'
182
			. ' THEN "DataObjectTest_TeamComment"."ClassName" ELSE '
183
			. $db->quoteString('DataObjectTest_TeamComment')
184
			. ' END AS "RecordClassName" FROM "DataObjectTest_TeamComment" INNER JOIN '
185
			. '"DataObjectTest_Team" AS "Team" ON "DataObjectTest_Team"."ID" = '
186
			. '"DataObjectTest_TeamComment"."TeamID"'
187
			. ' ORDER BY "DataObjectTest_TeamComment"."Name" ASC';
188
189
190
		$this->assertSQLEquals($expected, $list->sql($parameters));
191
		$this->assertEmpty($parameters);
192
	}
193
194
	public function testInnerJoinParameterised() {
195
		$db = DB::get_conn();
196
197
		$list = DataObjectTest_TeamComment::get();
198
		$list = $list->innerJoin(
199
			'DataObjectTest_Team',
200
			'"DataObjectTest_Team"."ID" = "DataObjectTest_TeamComment"."TeamID" '
201
			. 'AND "DataObjectTest_Team"."Title" LIKE ?',
202
			'Team',
203
			20,
204
			array('Team%')
205
		);
206
207
		$expected = 'SELECT DISTINCT "DataObjectTest_TeamComment"."ClassName", '
208
			. '"DataObjectTest_TeamComment"."LastEdited", "DataObjectTest_TeamComment"."Created", '
209
			. '"DataObjectTest_TeamComment"."Name", "DataObjectTest_TeamComment"."Comment", '
210
			. '"DataObjectTest_TeamComment"."TeamID", "DataObjectTest_TeamComment"."ID", '
211
			. 'CASE WHEN "DataObjectTest_TeamComment"."ClassName" IS NOT NULL'
212
			. ' THEN "DataObjectTest_TeamComment"."ClassName" ELSE '
213
			. $db->quoteString('DataObjectTest_TeamComment')
214
			. ' END AS "RecordClassName" FROM "DataObjectTest_TeamComment" INNER JOIN '
215
			. '"DataObjectTest_Team" AS "Team" ON "DataObjectTest_Team"."ID" = '
216
			. '"DataObjectTest_TeamComment"."TeamID" '
217
			. 'AND "DataObjectTest_Team"."Title" LIKE ?'
218
			. ' ORDER BY "DataObjectTest_TeamComment"."Name" ASC';
219
220
		$this->assertSQLEquals($expected, $list->sql($parameters));
221
		$this->assertEquals(array('Team%'), $parameters);
222
	}
223
224
	public function testLeftJoin() {
225
		$db = DB::get_conn();
226
227
		$list = DataObjectTest_TeamComment::get();
228
		$list = $list->leftJoin(
229
			'DataObjectTest_Team',
230
			'"DataObjectTest_Team"."ID" = "DataObjectTest_TeamComment"."TeamID"',
231
			'Team'
232
		);
233
234
		$expected = 'SELECT DISTINCT "DataObjectTest_TeamComment"."ClassName", '
235
			. '"DataObjectTest_TeamComment"."LastEdited", "DataObjectTest_TeamComment"."Created", '
236
			. '"DataObjectTest_TeamComment"."Name", "DataObjectTest_TeamComment"."Comment", '
237
			. '"DataObjectTest_TeamComment"."TeamID", "DataObjectTest_TeamComment"."ID", '
238
			. 'CASE WHEN "DataObjectTest_TeamComment"."ClassName" IS NOT NULL '
239
			. 'THEN "DataObjectTest_TeamComment"."ClassName" ELSE '
240
			. $db->quoteString('DataObjectTest_TeamComment')
241
			. ' END AS "RecordClassName" FROM "DataObjectTest_TeamComment" LEFT JOIN "DataObjectTest_Team" '
242
			. 'AS "Team" ON "DataObjectTest_Team"."ID" = "DataObjectTest_TeamComment"."TeamID"'
243
			. ' ORDER BY "DataObjectTest_TeamComment"."Name" ASC';
244
245
246
		$this->assertSQLEquals($expected, $list->sql($parameters));
247
		$this->assertEmpty($parameters);
248
249
		// Test with namespaces (with non-sensical join, but good enough for testing)
250
		$list = DataObjectTest_TeamComment::get();
251
		$list = $list->leftJoin(
252
			'DataObjectTest\NamespacedClass',
253
			'"DataObjectTest\NamespacedClass"."ID" = "DataObjectTest_TeamComment"."ID"'
254
		);
255
256
		$expected = 'SELECT DISTINCT "DataObjectTest_TeamComment"."ClassName", '
257
			. '"DataObjectTest_TeamComment"."LastEdited", '
258
			. '"DataObjectTest_TeamComment"."Created", '
259
			. '"DataObjectTest_TeamComment"."Name", '
260
			. '"DataObjectTest_TeamComment"."Comment", '
261
			. '"DataObjectTest_TeamComment"."TeamID", '
262
			. '"DataObjectTest_TeamComment"."ID", '
263
			. 'CASE WHEN "DataObjectTest_TeamComment"."ClassName" IS NOT NULL '
264
			. 'THEN "DataObjectTest_TeamComment"."ClassName" '
265
			. 'ELSE ' . $db->quoteString('DataObjectTest_TeamComment') . ' END AS "RecordClassName" '
266
			. 'FROM "DataObjectTest_TeamComment" '
267
			. 'LEFT JOIN "DataObjectTest\NamespacedClass" ON '
268
			. '"DataObjectTest\NamespacedClass"."ID" = "DataObjectTest_TeamComment"."ID"'
269
			. ' ORDER BY "DataObjectTest_TeamComment"."Name" ASC';
270
		$this->assertSQLEquals($expected, $list->sql($parameters), 'Retains backslashes in namespaced classes');
271
		$this->assertEmpty($parameters);
272
273
	}
274
275
	public function testLeftJoinParameterised() {
276
		$db = DB::get_conn();
277
278
		$list = DataObjectTest_TeamComment::get();
279
		$list = $list->leftJoin(
280
			'DataObjectTest_Team',
281
			'"DataObjectTest_Team"."ID" = "DataObjectTest_TeamComment"."TeamID" '
282
			. 'AND "DataObjectTest_Team"."Title" LIKE ?',
283
			'Team',
284
			20,
285
			array('Team%')
286
		);
287
288
		$expected = 'SELECT DISTINCT "DataObjectTest_TeamComment"."ClassName", '
289
			. '"DataObjectTest_TeamComment"."LastEdited", "DataObjectTest_TeamComment"."Created", '
290
			. '"DataObjectTest_TeamComment"."Name", "DataObjectTest_TeamComment"."Comment", '
291
			. '"DataObjectTest_TeamComment"."TeamID", "DataObjectTest_TeamComment"."ID", '
292
			. 'CASE WHEN "DataObjectTest_TeamComment"."ClassName" IS NOT NULL'
293
			. ' THEN "DataObjectTest_TeamComment"."ClassName" ELSE '
294
			. $db->quoteString('DataObjectTest_TeamComment')
295
			. ' END AS "RecordClassName" FROM "DataObjectTest_TeamComment" LEFT JOIN '
296
			. '"DataObjectTest_Team" AS "Team" ON "DataObjectTest_Team"."ID" = '
297
			. '"DataObjectTest_TeamComment"."TeamID" '
298
			. 'AND "DataObjectTest_Team"."Title" LIKE ?'
299
			. ' ORDER BY "DataObjectTest_TeamComment"."Name" ASC';
300
301
		$this->assertSQLEquals($expected, $list->sql($parameters));
302
		$this->assertEquals(array('Team%'), $parameters);
303
	}
304
305
	public function testToNestedArray() {
306
		$list = DataObjectTest_TeamComment::get()->sort('ID');
307
		$nestedArray = $list->toNestedArray();
308
		$expected = array(
309
			0=>
310
			array(
311
				'ClassName'=>'DataObjectTest_TeamComment',
312
				'Name'=>'Joe',
313
				'Comment'=>'This is a team comment by Joe',
314
				'TeamID'=> $this->objFromFixture('DataObjectTest_TeamComment', 'comment1')->TeamID,
315
			),
316
			1=>
317
			array(
318
				'ClassName'=>'DataObjectTest_TeamComment',
319
				'Name'=>'Bob',
320
				'Comment'=>'This is a team comment by Bob',
321
				'TeamID'=> $this->objFromFixture('DataObjectTest_TeamComment', 'comment2')->TeamID,
322
			),
323
			2=>
324
			array(
325
				'ClassName'=>'DataObjectTest_TeamComment',
326
				'Name'=>'Phil',
327
				'Comment'=>'Phil is a unique guy, and comments on team2',
328
				'TeamID'=> $this->objFromFixture('DataObjectTest_TeamComment', 'comment3')->TeamID,
329
			),
330
		);
331
		$this->assertEquals(3, count($nestedArray));
332
		$this->assertEquals($expected[0]['Name'], $nestedArray[0]['Name']);
333
		$this->assertEquals($expected[1]['Comment'], $nestedArray[1]['Comment']);
334
		$this->assertEquals($expected[2]['TeamID'], $nestedArray[2]['TeamID']);
335
	}
336
337
	public function testMap() {
338
		$map = DataObjectTest_TeamComment::get()->map()->toArray();
339
		$expected = array(
340
			$this->idFromFixture('DataObjectTest_TeamComment', 'comment1') => 'Joe',
341
			$this->idFromFixture('DataObjectTest_TeamComment', 'comment2') => 'Bob',
342
			$this->idFromFixture('DataObjectTest_TeamComment', 'comment3') => 'Phil'
343
		);
344
345
		$this->assertEquals($expected, $map);
346
		$otherMap = DataObjectTest_TeamComment::get()->map('Name', 'TeamID')->toArray();
347
		$otherExpected = array(
348
			'Joe' => $this->objFromFixture('DataObjectTest_TeamComment', 'comment1')->TeamID,
349
			'Bob' => $this->objFromFixture('DataObjectTest_TeamComment', 'comment2')->TeamID,
350
			'Phil' => $this->objFromFixture('DataObjectTest_TeamComment', 'comment3')->TeamID
351
		);
352
353
		$this->assertEquals($otherExpected, $otherMap);
354
	}
355
356
	public function testAmbiguousAggregate() {
357
		// Test that we avoid ambiguity error when a field exists on two joined tables
358
		// Fetch the sponsors in a round-about way to simulate this
359
		$teamID = $this->idFromFixture('DataObjectTest_Team','team2');
360
		$sponsors = DataObjectTest_EquipmentCompany::get()->filter('SponsoredTeams.ID', $teamID);
361
		$this->assertNotNull($sponsors->Max('ID'));
362
		$this->assertNotNull($sponsors->Min('ID'));
363
		$this->assertNotNull($sponsors->Avg('ID'));
364
		$this->assertNotNull($sponsors->Sum('ID'));
365
	}
366
367
	public function testEach() {
368
		$list = DataObjectTest_TeamComment::get();
369
370
		$count = 0;
371
		$test = $this;
372
373
		$list->each(function($item) use (&$count, $test) {
374
			$count++;
375
376
			$test->assertTrue(is_a($item, "DataObjectTest_TeamComment"));
377
		});
378
379
		$this->assertEquals($list->Count(), $count);
380
	}
381
382
	public function testWhere() {
383
		// We can use raw SQL queries with where.  This is only recommended for advanced uses;
384
		// if you can, you should use filter().
385
		$list = DataObjectTest_TeamComment::get();
386
387
		// where() returns a new DataList, like all the other modifiers, so it can be chained.
388
		$list2 = $list->where('"Name" = \'Joe\'');
389
		$this->assertEquals(array('This is a team comment by Joe'), $list2->column('Comment'));
390
391
		// The where() clauses are chained together with AND
392
		$list3 = $list2->where('"Name" = \'Bob\'');
393
		$this->assertEquals(array(), $list3->column('Comment'));
394
	}
395
396
	/**
397
	 * Test DataList->byID()
398
	 */
399
	public function testByID() {
400
		// We can get a single item by ID.
401
		$id = $this->idFromFixture('DataObjectTest_Team','team2');
402
		$team = DataObjectTest_Team::get()->byID($id);
403
404
		// byID() returns a DataObject, rather than a DataList
405
		$this->assertInstanceOf('DataObjectTest_Team', $team);
406
		$this->assertEquals('Team 2', $team->Title);
407
408
		// Assert that filtering on ID searches by the base table, not the child table field
409
		$query = DataObjectTest_SubTeam::get()->filter('ID', 4)->sql($parameters);
410
		$this->assertContains('WHERE ("DataObjectTest_Team"."ID" = ?)', $query);
411
		$this->assertNotContains('WHERE ("DataObjectTest_SubTeam"."ID" = ?)', $query);
412
	}
413
414
	public function testByIDs() {
415
		$knownIDs = $this->allFixtureIDs('DataObjectTest_Player');
416
		$removedID = array_pop($knownIDs);
417
		$filteredPlayers = DataObjectTest_Player::get()->byIDs($knownIDs);
418
		foreach ($filteredPlayers as $player) {
419
			$this->assertContains($player->ID, $knownIDs);
420
			$this->assertNotEquals($removedID, $player->ID);
421
		}
422
	}
423
424
	/**
425
	 * Test DataList->removeByID()
426
	 */
427
	public function testRemoveByID() {
428
		$list = DataObjectTest_Team::get();
429
		$id = $this->idFromFixture('DataObjectTest_Team','team2');
430
431
		$this->assertNotNull($list->byID($id));
432
		$list->removeByID($id);
433
		$this->assertNull($list->byID($id));
434
	}
435
436
	/**
437
	 * Test DataList->canSortBy()
438
	 */
439
	public function testCanSortBy() {
440
		// Basic check
441
		$team = DataObjectTest_Team::get();
442
		$this->assertTrue($team->canSortBy("Title"));
443
		$this->assertFalse($team->canSortBy("SomethingElse"));
444
445
		// Subclasses
446
		$subteam = DataObjectTest_SubTeam::get();
447
		$this->assertTrue($subteam->canSortBy("Title"));
448
		$this->assertTrue($subteam->canSortBy("SubclassDatabaseField"));
449
	}
450
451
	public function testDataListArrayAccess() {
452
		$list = DataObjectTest_Team::get()->sort('Title');
453
454
		// We can use array access to refer to single items in the DataList, as if it were an array
455
		$this->assertEquals("Subteam 1", $list[0]->Title);
456
		$this->assertEquals("Subteam 3", $list[2]->Title);
457
		$this->assertEquals("Team 2", $list[4]->Title);
458
	}
459
460
	public function testFind() {
461
		$list = DataObjectTest_Team::get();
462
		$record = $list->find('Title', 'Team 1');
463
		$this->assertEquals($this->idFromFixture('DataObjectTest_Team', 'team1'), $record->ID);
464
	}
465
466
	public function testFindById() {
467
		$list = DataObjectTest_Team::get();
468
		$record = $list->find('ID', $this->idFromFixture('DataObjectTest_Team', 'team1'));
469
		$this->assertEquals('Team 1', $record->Title);
470
		// Test that you can call it twice on the same list
471
		$record = $list->find('ID', $this->idFromFixture('DataObjectTest_Team', 'team2'));
472
		$this->assertEquals('Team 2', $record->Title);
473
	}
474
475
	public function testSimpleSort() {
476
		$list = DataObjectTest_TeamComment::get();
477
		$list = $list->sort('Name');
478
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
479
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
480
	}
481
482
	public function testSimpleSortOneArgumentASC() {
483
		$list = DataObjectTest_TeamComment::get();
484
		$list = $list->sort('Name ASC');
485
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
486
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
487
	}
488
489
	public function testSimpleSortOneArgumentDESC() {
490
		$list = DataObjectTest_TeamComment::get();
491
		$list = $list->sort('Name DESC');
492
		$this->assertEquals('Phil', $list->first()->Name, 'Last comment should be from Phil');
493
		$this->assertEquals('Bob', $list->last()->Name, 'First comment should be from Bob');
494
	}
495
496
	public function testSortOneArgumentMultipleColumns() {
497
		$list = DataObjectTest_TeamComment::get();
498
		$list = $list->sort('TeamID ASC, Name DESC');
499
		$this->assertEquals('Joe', $list->first()->Name, 'First comment should be from Bob');
500
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
501
	}
502
503
	public function testSimpleSortASC() {
504
		$list = DataObjectTest_TeamComment::get();
505
		$list = $list->sort('Name', 'asc');
506
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
507
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
508
	}
509
510
	public function testSimpleSortDESC() {
511
		$list = DataObjectTest_TeamComment::get();
512
		$list = $list->sort('Name', 'desc');
513
		$this->assertEquals('Phil', $list->first()->Name, 'Last comment should be from Phil');
514
		$this->assertEquals('Bob', $list->last()->Name, 'First comment should be from Bob');
515
	}
516
517
	public function testSortWithArraySyntaxSortASC() {
518
		$list = DataObjectTest_TeamComment::get();
519
		$list = $list->sort(array('Name'=>'asc'));
520
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
521
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
522
	}
523
524
	public function testSortWithArraySyntaxSortDESC() {
525
		$list = DataObjectTest_TeamComment::get();
526
		$list = $list->sort(array('Name'=>'desc'));
527
		$this->assertEquals('Phil', $list->first()->Name, 'Last comment should be from Phil');
528
		$this->assertEquals('Bob', $list->last()->Name, 'First comment should be from Bob');
529
	}
530
531
	public function testSortWithMultipleArraySyntaxSort() {
532
		$list = DataObjectTest_TeamComment::get();
533
		$list = $list->sort(array('TeamID'=>'asc','Name'=>'desc'));
534
		$this->assertEquals('Joe', $list->first()->Name, 'First comment should be from Bob');
535
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
536
	}
537
538
	public function testSortWithCompositeSyntax() {
539
		// Phil commented on team with founder surname "Aaron"
540
		$list = DataObjectTest_TeamComment::get();
541
		$list = $list->sort('Team.Founder.Surname', 'asc');
542
		$this->assertEquals('Phil', $list->first()->Name);
543
		$list = $list->sort('Team.Founder.Surname', 'desc');
544
		$this->assertEquals('Phil', $list->last()->Name);
545
	}
546
547
	public function testSortInvalidParameters() {
548
		$this->setExpectedException(
549
			'InvalidArgumentException',
550
			'Fans is not a linear relation on model DataObjectTest_Player'
551
		);
552
		$list = DataObjectTest_Team::get();
553
		$list = $list->sort('Founder.Fans.Surname'); // Can't sort on has_many
554
	}
555
556
557
558
	public function testSortNumeric() {
559
		$list = DataObjectTest_Sortable::get();
560
		$list1 = $list->sort('Sort', 'ASC');
561
		$this->assertEquals(array(
562
			-10,
563
			-2,
564
			-1,
565
			0,
566
			1,
567
			2,
568
			10
569
		), $list1->column('Sort'));
570
	}
571
572
	public function testSortMixedCase() {
573
		$list = DataObjectTest_Sortable::get();
574
		$list1 = $list->sort('Name', 'ASC');
575
		$this->assertEquals(array(
576
            'Bob',
577
            'bonny',
578
            'jane',
579
            'John',
580
            'sam',
581
            'Steve',
582
            'steven'
583
		), $list1->column('Name'));
584
	}
585
586
	/**
587
	 * Test DataList->canFilterBy()
588
	 */
589
	public function testCanFilterBy() {
590
		// Basic check
591
		$team = DataObjectTest_Team::get();
592
		$this->assertTrue($team->canFilterBy("Title"));
593
		$this->assertFalse($team->canFilterBy("SomethingElse"));
594
595
		// Has one
596
		$this->assertTrue($team->canFilterBy("CaptainID"));
597
		$this->assertTrue($team->canFilterBy("Captain.ShirtNumber"));
598
		$this->assertFalse($team->canFilterBy("SomethingElse.ShirtNumber"));
599
		$this->assertFalse($team->canFilterBy("Captain.SomethingElse"));
600
		$this->assertTrue($team->canFilterBy("Captain.FavouriteTeam.Captain.ShirtNumber"));
601
602
		// Has many
603
		$this->assertTrue($team->canFilterBy("Fans.Name"));
604
		$this->assertFalse($team->canFilterBy("SomethingElse.Name"));
605
		$this->assertFalse($team->canFilterBy("Fans.SomethingElse"));
606
607
		// Many many
608
		$this->assertTrue($team->canFilterBy("Players.FirstName"));
609
		$this->assertFalse($team->canFilterBy("SomethingElse.FirstName"));
610
		$this->assertFalse($team->canFilterBy("Players.SomethingElse"));
611
612
		// Subclasses
613
		$subteam = DataObjectTest_SubTeam::get();
614
		$this->assertTrue($subteam->canFilterBy("Title"));
615
		$this->assertTrue($subteam->canFilterBy("SubclassDatabaseField"));
616
	}
617
618
	/**
619
	 * $list->filter('Name', 'bob'); // only bob in the list
620
	 */
621
	public function testSimpleFilter() {
622
		$list = DataObjectTest_Team::get();
623
		$list = $list->filter('Title','Team 2');
624
		$this->assertEquals(1, $list->count());
625
		$this->assertEquals('Team 2', $list->first()->Title, 'List should only contain Team 2');
626
		$this->assertEquals('Team 2', $list->last()->Title, 'Last should only contain Team 2');
627
	}
628
629
	public function testSimpleFilterEndsWith() {
630
		$list = DataObjectTest_TeamComment::get();
631
		$list = $list->filter('Name:EndsWith', 'b');
632
		$this->assertEquals(1, $list->count());
633
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
634
	}
635
636
	public function testSimpleFilterExactMatchFilter() {
637
		$list = DataObjectTest_TeamComment::get();
638
		$list = $list->filter('Name:ExactMatch', 'Bob');
639
		$this->assertEquals(1, $list->count());
640
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
641
	}
642
643
	public function testSimpleFilterGreaterThanFilter() {
644
		$list = DataObjectTest_TeamComment::get();
645
		$list = $list->filter('TeamID:GreaterThan', $this->idFromFixture('DataObjectTest_Team', 'team1'));
646
		$this->assertEquals(1, $list->count());
647
		$this->assertEquals('Phil', $list->first()->Name, 'First comment should be from Phil');
648
	}
649
650
	public function testSimpleFilterGreaterThanOrEqualFilter() {
651
		$list = DataObjectTest_TeamComment::get();
652
		$list = $list->filter('TeamID:GreaterThanOrEqual',
653
			$this->idFromFixture('DataObjectTest_Team', 'team1'))->sort("ID");
654
		$this->assertEquals(3, $list->count());
655
		$this->assertEquals('Joe', $list->first()->Name, 'First comment should be from Joe');
656
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
657
	}
658
659
	public function testSimpleFilterLessThanFilter() {
660
		$list = DataObjectTest_TeamComment::get();
661
		$list = $list->filter('TeamID:LessThan',
662
			$this->idFromFixture('DataObjectTest_Team', 'team2'))->sort('Name');
663
		$this->assertEquals(2, $list->count());
664
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
665
		$this->assertEquals('Joe', $list->Last()->Name, 'Last comment should be from Joe');
666
	}
667
668
	public function testSimpleFilterLessThanOrEqualFilter() {
669
		$list = DataObjectTest_TeamComment::get();
670
		$list = $list->filter('TeamID:LessThanOrEqual',
671
			$this->idFromFixture('DataObjectTest_Team', 'team1'))->sort('ID');
672
		$this->assertEquals(2, $list->count());
673
		$this->assertEquals('Joe', $list->first()->Name, 'First comment should be from Joe');
674
		$this->assertEquals('Bob', $list->Last()->Name, 'Last comment should be from Bob');
675
	}
676
677
	public function testSimplePartialMatchFilter() {
678
		$list = DataObjectTest_TeamComment::get();
679
		$list = $list->filter('Name:PartialMatch', 'o')->sort('Name');
680
		$this->assertEquals(2, $list->count());
681
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
682
		$this->assertEquals('Joe', $list->last()->Name, 'First comment should be from Joe');
683
	}
684
685
	public function testSimpleFilterStartsWith() {
686
		$list = DataObjectTest_TeamComment::get();
687
		$list = $list->filter('Name:StartsWith', 'B');
688
		$this->assertEquals(1, $list->count());
689
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
690
	}
691
692
	public function testSimpleFilterWithNonExistingComparisator() {
693
		$this->setExpectedException(
694
			'ReflectionException',
695
			'Class DataListFilter.Bogus does not exist'
696
		);
697
		$list = DataObjectTest_TeamComment::get();
698
		$list->filter('Comment:Bogus', 'team comment');
699
	}
700
701
	public function testInvalidModifier() {
702
		// Invalid modifiers are treated as failed filter construction
703
		$this->setExpectedException(
704
			'ReflectionException',
705
			'Class DataListFilter.invalidmodifier does not exist'
706
		);
707
		$list = DataObjectTest_TeamComment::get();
708
		$list->filter('Comment:invalidmodifier', 'team comment');
709
	}
710
711
	/**
712
	 * $list->filter('Name', array('aziz', 'bob'); // aziz and bob in list
713
	 */
714
	public function testSimpleFilterWithMultiple() {
715
		$list = DataObjectTest_TeamComment::get();
716
		$list = $list->filter('Name', array('Bob','Phil'));
717
		$list = $list->sort('Name', 'ASC');
718
		$this->assertEquals(2, $list->count());
719
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
720
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
721
	}
722
723
	public function testMultipleFilterWithNoMatch() {
724
		$list = DataObjectTest_TeamComment::get();
725
		$list = $list->filter(array('Name'=>'Bob', 'Comment'=>'Phil is a unique guy, and comments on team2'));
726
		$this->assertEquals(0, $list->count());
727
	}
728
729
	/**
730
	 *  $list->filter(array('Name'=>'bob, 'Age'=>21)); // bob with the age 21
731
	 */
732
	public function testFilterMultipleArray() {
733
		$list = DataObjectTest_TeamComment::get();
734
		$list = $list->filter(array('Name'=>'Bob', 'Comment'=>'This is a team comment by Bob'));
735
		$list = $list->sort('Name', 'ASC');
736
		$this->assertEquals(1, $list->count());
737
		$this->assertEquals('Bob', $list->first()->Name, 'Only comment should be from Bob');
738
	}
739
740
	public function testFilterMultipleWithTwoMatches() {
741
		$list = DataObjectTest_TeamComment::get();
742
		$list = $list->filter(array('TeamID'=>$this->idFromFixture('DataObjectTest_Team', 'team1')));
743
		$this->assertEquals(2, $list->count());
744
	}
745
746
	public function testFilterMultipleWithArrayFilter() {
747
		$list = DataObjectTest_TeamComment::get();
748
		$list = $list->filter(array('Name'=>array('Bob','Phil')));
749
		$list = $list->sort('Name', 'ASC');
750
		$this->assertEquals(2, $list->count(), 'There should be two comments');
751
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
752
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
753
	}
754
755
	public function testFilterMultipleWithArrayFilterAndModifiers() {
756
		$list = DataObjectTest_TeamComment::get();
757
		$list = $list->filter(array('Name:StartsWith'=>array('Bo', 'Jo')));
758
		$list = $list->sort('Name', 'ASC');
759
		$this->assertEquals(2, $list->count());
760
		$this->assertEquals('Bob', $list->first()->Name);
761
		$this->assertEquals('Joe', $list->last()->Name);
762
	}
763
764
	/**
765
	 * $list->filter(array('Name'=>array('aziz','bob'), 'Age'=>array(21, 43)));
766
	 */
767
	public function testFilterArrayInArray() {
768
		$list = DataObjectTest_TeamComment::get();
769
		$list = $list->filter(array(
770
			'Name'=>array('Bob','Phil'),
771
			'TeamID'=>array($this->idFromFixture('DataObjectTest_Team', 'team1'))));
772
		$this->assertEquals(1, $list->count(), 'There should be one comment');
773
		$this->assertEquals('Bob', $list->first()->Name, 'Only comment should be from Bob');
774
	}
775
776
	public function testFilterWithModifiers() {
777
		$list = DataObjectTest_TeamComment::get();
778
		$nocaseList = $list->filter('Name:nocase', 'bob');
779
		$this->assertEquals(1, $nocaseList->count(), 'There should be one comment');
780
		$caseList = $list->filter('Name:case', 'bob');
781
		$this->assertEquals(0, $caseList->count(), 'There should be no comments');
782
		$gtList = $list->filter('TeamID:GreaterThan:not',
783
			$this->idFromFixture('DataObjectTest_Team', 'team1'));
784
		$this->assertEquals(2, $gtList->count());
785
	}
786
787
	public function testFilterAny() {
788
		$list = DataObjectTest_TeamComment::get();
789
		$list = $list->filterAny('Name', 'Bob');
790
		$this->assertEquals(1, $list->count());
791
	}
792
793
	public function testFilterAnyMultipleArray() {
794
		$list = DataObjectTest_TeamComment::get();
795
		$list = $list->filterAny(array('Name'=>'Bob', 'Comment'=>'This is a team comment by Bob'));
796
		$this->assertEquals(1, $list->count());
797
		$this->assertEquals('Bob', $list->first()->Name, 'Only comment should be from Bob');
798
	}
799
800
	public function testFilterAnyOnFilter() {
801
		$list = DataObjectTest_TeamComment::get();
802
		$list = $list->filter(array(
803
			'TeamID'=>$this->idFromFixture('DataObjectTest_Team', 'team1')
804
		));
805
		$list = $list->filterAny(array(
806
			'Name'=>array('Phil', 'Joe'),
807
			'Comment'=>'This is a team comment by Bob'
808
		));
809
		$list = $list->sort('Name');
810
		$this->assertEquals(2, $list->count());
811
		$this->assertEquals(
812
			'Bob',
813
			$list->offsetGet(0)->Name,
814
			'Results should include comments from Bob, matched by comment and team'
815
		);
816
		$this->assertEquals(
817
			'Joe',
818
			$list->offsetGet(1)->Name,
819
			'Results should include comments by Joe, matched by name and team (not by comment)'
820
		);
821
822
		$list = DataObjectTest_TeamComment::get();
823
		$list = $list->filter(array(
824
			'TeamID'=>$this->idFromFixture('DataObjectTest_Team', 'team1')
825
		));
826
		$list = $list->filterAny(array(
827
			'Name'=>array('Phil', 'Joe'),
828
			'Comment'=>'This is a team comment by Bob'
829
		));
830
		$list = $list->sort('Name');
831
		$list = $list->filter(array('Name' => 'Bob'));
832
		$this->assertEquals(1, $list->count());
833
		$this->assertEquals(
834
			'Bob',
835
			$list->offsetGet(0)->Name,
836
			'Results should include comments from Bob, matched by name and team'
837
		);
838
	}
839
840
	public function testFilterAnyMultipleWithArrayFilter() {
841
		$list = DataObjectTest_TeamComment::get();
842
		$list = $list->filterAny(array('Name'=>array('Bob','Phil')));
843
		$this->assertEquals(2, $list->count(), 'There should be two comments');
844
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
845
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
846
	}
847
848
	public function testFilterAnyArrayInArray() {
849
		$list = DataObjectTest_TeamComment::get();
850
		$list = $list->filterAny(array(
851
			'Name'=>array('Bob','Phil'),
852
			'TeamID'=>array($this->idFromFixture('DataObjectTest_Team', 'team1'))))
853
			->sort('Name');
854
		$this->assertEquals(3, $list->count());
855
		$this->assertEquals(
856
			'Bob',
857
			$list->offsetGet(0)->Name,
858
			'Results should include comments from Bob, matched by name and team'
859
		);
860
		$this->assertEquals(
861
			'Joe',
862
			$list->offsetGet(1)->Name,
863
			'Results should include comments by Joe, matched by team (not by name)'
864
		);
865
		$this->assertEquals(
866
			'Phil',
867
			$list->offsetGet(2)->Name,
868
			'Results should include comments from Phil, matched by name (even if he\'s not in Team1)'
869
		);
870
	}
871
872
	public function testFilterOnJoin() {
873
		$list = DataObjectTest_TeamComment::get()
874
			->leftJoin('DataObjectTest_Team',
875
				'"DataObjectTest_Team"."ID" = "DataObjectTest_TeamComment"."TeamID"'
876
			)->filter(array(
877
				'Title' => 'Team 1'
878
			));
879
880
		$this->assertEquals(2, $list->count());
881
		$values = $list->column('Name');
882
		$this->assertEquals(array_intersect($values, array('Joe', 'Bob')), $values);
883
	}
884
885
	public function testFilterOnImplicitJoin() {
886
		// Many to many
887
		$list = DataObjectTest_Team::get()
888
			->filter('Players.FirstName', array('Captain', 'Captain 2'));
889
890
		$this->assertEquals(2, $list->count());
891
892
		// Has many
893
		$list = DataObjectTest_Team::get()
894
			->filter('Comments.Name', array('Joe', 'Phil'));
895
896
		$this->assertEquals(2, $list->count());
897
898
		// Has one
899
		$list = DataObjectTest_Player::get()
900
			->filter('FavouriteTeam.Title', 'Team 1');
901
902
		$this->assertEquals(1, $list->count());
903
		$this->assertEquals('007', $list->first()->ShirtNumber);
904
	}
905
906
	public function testFilterOnInvalidRelation() {
907
		$this->setExpectedException(
908
			'InvalidArgumentException',
909
			"MascotAnimal is not a relation on model DataObjectTest_Team"
910
		);
911
		// Filter on missing relation 'MascotAnimal'
912
		DataObjectTest_Team::get()
913
			->filter('MascotAnimal.Name', 'Richard')
914
			->toArray();
915
	}
916
917
	public function testFilterAndExcludeById() {
918
		$id = $this->idFromFixture('DataObjectTest_SubTeam', 'subteam1');
919
		$list = DataObjectTest_SubTeam::get()->filter('ID', $id);
920
		$this->assertEquals($id, $list->first()->ID);
921
922
		$list = DataObjectTest_SubTeam::get();
923
		$this->assertEquals(3, count($list));
924
		$this->assertEquals(2, count($list->exclude('ID', $id)));
925
926
		// Check that classes with namespaces work.
927
		$obj = new DataObjectTest\NamespacedClass();
928
		$obj->Name = "Test";
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<DataObjectTest\NamespacedClass>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
929
		$obj->write();
930
931
		$list = DataObjectTest\NamespacedClass::get()->filter('ID', $obj->ID);
932
		$this->assertEquals('Test', $list->First()->Name);
933
		$this->assertEquals(0, $list->exclude('ID', $obj->ID)->count());
934
	}
935
936
	/**
937
	 * @skipUpgrade
938
	 */
939
	public function testFilterByNull() {
940
		$list = DataObjectTest_Fan::get();
941
		// Force DataObjectTest_Fan/fan5::Email to empty string
942
		$fan5id = $this->idFromFixture('DataObjectTest_Fan', 'fan5');
943
		DB::prepared_query("UPDATE \"DataObjectTest_Fan\" SET \"Email\" = '' WHERE \"ID\" = ?", array($fan5id));
944
945
		// Filter by null email
946
		$nullEmails = $list->filter('Email', null);
947
		$this->assertDOSEquals(array(
948
			array(
949
				'Name' => 'Stephen',
950
			),
951
			array(
952
				'Name' => 'Mitch',
953
			)
954
		), $nullEmails);
955
956
		// Filter by non-null
957
		$nonNullEmails = $list->filter('Email:not', null);
958
		$this->assertDOSEquals(array(
959
			array(
960
				'Name' => 'Damian',
961
				'Email' => '[email protected]',
962
			),
963
			array(
964
				'Name' => 'Richard',
965
				'Email' => '[email protected]',
966
			),
967
			array(
968
				'Name' => 'Hamish',
969
			)
970
		), $nonNullEmails);
971
972
		// Filter by empty only
973
		$emptyOnly = $list->filter('Email', '');
974
		$this->assertDOSEquals(array(
975
			array(
976
				'Name' => 'Hamish',
977
			)
978
		), $emptyOnly);
979
980
		// Non-empty only. This should include null values, since ExactMatchFilter works around
981
		// the caveat that != '' also excludes null values in ANSI SQL-92 behaviour.
982
		$nonEmptyOnly = $list->filter('Email:not', '');
983
		$this->assertDOSEquals(array(
984
			array(
985
				'Name' => 'Damian',
986
				'Email' => '[email protected]',
987
			),
988
			array(
989
				'Name' => 'Richard',
990
				'Email' => '[email protected]',
991
			),
992
			array(
993
				'Name' => 'Stephen',
994
			),
995
			array(
996
				'Name' => 'Mitch',
997
			)
998
		), $nonEmptyOnly);
999
1000
		// Filter by many including null, empty string, and non-empty
1001
		$items1 = $list->filter('Email', array(null, '', '[email protected]'));
1002
		$this->assertDOSEquals(array(
1003
			array(
1004
				'Name' => 'Damian',
1005
				'Email' => '[email protected]',
1006
			),
1007
			array(
1008
				'Name' => 'Stephen',
1009
			),
1010
			array(
1011
				'Name' => 'Mitch',
1012
			),
1013
			array(
1014
				'Name' => 'Hamish',
1015
			)
1016
		), $items1);
1017
1018
		// Filter exclusion of above list
1019
		$items2 = $list->filter('Email:not', array(null, '', '[email protected]'));
1020
		$this->assertDOSEquals(array(
1021
			array(
1022
				'Name' => 'Richard',
1023
				'Email' => '[email protected]',
1024
			),
1025
		), $items2);
1026
1027
		// Filter by many including empty string and non-empty
1028
		$items3 = $list->filter('Email', array('', '[email protected]'));
1029
		$this->assertDOSEquals(array(
1030
			array(
1031
				'Name' => 'Damian',
1032
				'Email' => '[email protected]',
1033
			),
1034
			array(
1035
				'Name' => 'Hamish',
1036
			)
1037
		), $items3);
1038
1039
		// Filter by many including empty string and non-empty
1040
		// This also relies no the workaround for null comparison as in the $nonEmptyOnly test
1041
		$items4 = $list->filter('Email:not', array('', '[email protected]'));
1042
		$this->assertDOSEquals(array(
1043
			array(
1044
				'Name' => 'Richard',
1045
				'Email' => '[email protected]',
1046
			),
1047
			array(
1048
				'Name' => 'Stephen',
1049
			),
1050
			array(
1051
				'Name' => 'Mitch',
1052
			)
1053
		), $items4);
1054
1055
		// Filter by many including empty string and non-empty
1056
		// The extra null check isn't necessary, but check that this doesn't fail
1057
		$items5 = $list->filterAny(array(
1058
			'Email:not' => array('', '[email protected]'),
1059
			'Email' => null
1060
		));
1061
		$this->assertDOSEquals(array(
1062
			array(
1063
				'Name' => 'Richard',
1064
				'Email' => '[email protected]',
1065
			),
1066
			array(
1067
				'Name' => 'Stephen',
1068
			),
1069
			array(
1070
				'Name' => 'Mitch',
1071
			)
1072
		), $items5);
1073
1074
		// Filter by null or empty values
1075
		$items6 = $list->filter('Email', array(null, ''));
1076
		$this->assertDOSEquals(array(
1077
			array(
1078
				'Name' => 'Stephen',
1079
			),
1080
			array(
1081
				'Name' => 'Mitch',
1082
			),
1083
			array(
1084
				'Name' => 'Hamish',
1085
			)
1086
		), $items6);
1087
	}
1088
1089
	/**
1090
	 * Test null checks with case modifiers
1091
	 */
1092
	public function testFilterByNullCase() {
1093
		// Test with case (case/nocase both use same code path)
1094
		// Test with and without null, and with inclusion/exclusion permutations
1095
		$list = DataObjectTest_Fan::get();
1096
1097
		// Only an explicit NOT NULL should include null values
1098
		$items6 = $list->filter('Email:not:case', array(null, '', '[email protected]'));
1099
		$this->assertSQLContains(' AND "DataObjectTest_Fan"."Email" IS NOT NULL', $items6->sql());
1100
1101
		// These should all include values where Email IS NULL
1102
		$items7 = $list->filter('Email:nocase', array(null, '', '[email protected]'));
1103
		$this->assertSQLContains(' OR "DataObjectTest_Fan"."Email" IS NULL', $items7->sql());
1104
		$items8 = $list->filter('Email:not:case', array('', '[email protected]'));
1105
		$this->assertSQLContains(' OR "DataObjectTest_Fan"."Email" IS NULL', $items8->sql());
1106
1107
		// These should not contain any null checks at all
1108
		$items9 = $list->filter('Email:nocase', array('', '[email protected]'));
1109
		$this->assertSQLNotContains('"DataObjectTest_Fan"."Email" IS NULL', $items9->sql());
1110
		$this->assertSQLNotContains('"DataObjectTest_Fan"."Email" IS NOT NULL', $items9->sql());
1111
	}
1112
1113
	/**
1114
	 * $list = $list->filterByCallback(function($item, $list) { return $item->Age == 21; })
1115
	 */
1116
	public function testFilterByCallback() {
1117
		$team1ID = $this->idFromFixture('DataObjectTest_Team', 'team1');
1118
		$list = DataObjectTest_TeamComment::get();
1119
		$list = $list->filterByCallback(function ($item, $list) use ($team1ID) {
0 ignored issues
show
Unused Code introduced by
The parameter $list is not used and could be removed.

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

Loading history...
1120
			return $item->TeamID == $team1ID;
1121
		});
1122
1123
		$result = $list->column('Name');
1124
		$expected = array_intersect($result, array('Joe', 'Bob'));
1125
1126
		$this->assertEquals(2, $list->count());
1127
		$this->assertEquals($expected, $result, 'List should only contain comments from Team 1 (Joe and Bob)');
1128
		$this->assertTrue($list instanceof Filterable, 'The List should be of type SS_Filterable');
1129
	}
1130
1131
	/**
1132
	 * $list->exclude('Name', 'bob'); // exclude bob from list
1133
	 */
1134
	public function testSimpleExclude() {
1135
		$list = DataObjectTest_TeamComment::get();
1136
		$list = $list->exclude('Name', 'Bob');
1137
		$list = $list->sort('Name');
1138
		$this->assertEquals(2, $list->count());
1139
		$this->assertEquals('Joe', $list->first()->Name, 'First comment should be from Joe');
1140
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
1141
	}
1142
//
1143
	/**
1144
	 * $list->exclude('Name', array('aziz', 'bob'); // exclude aziz and bob from list
1145
	 */
1146
	public function testSimpleExcludeWithMultiple() {
1147
		$list = DataObjectTest_TeamComment::get();
1148
		$list = $list->exclude('Name', array('Joe','Phil'));
1149
		$this->assertEquals(1, $list->count());
1150
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
1151
	}
1152
1153
	/**
1154
	 * $list->exclude(array('Name'=>'bob, 'Age'=>21)); // negative version
1155
	 */
1156
	public function testMultipleExcludeWithMiss() {
1157
		$list = DataObjectTest_TeamComment::get();
1158
		$list = $list->exclude(array('Name'=>'Bob', 'Comment'=>'Does not match any comments'));
1159
		$this->assertEquals(3, $list->count());
1160
	}
1161
1162
	/**
1163
	 * $list->exclude(array('Name'=>'bob, 'Age'=>21)); // exclude bob that has Age 21
1164
	 */
1165
	public function testMultipleExclude() {
1166
		$list = DataObjectTest_TeamComment::get();
1167
		$list = $list->exclude(array('Name'=>'Bob', 'Comment'=>'This is a team comment by Bob'));
1168
		$this->assertEquals(2, $list->count());
1169
	}
1170
1171
	/**
1172
	 * Test that if an exclude() is applied to a filter(), the filter() is still preserved.
1173
	 */
1174
	public function testExcludeOnFilter() {
1175
		$list = DataObjectTest_TeamComment::get();
1176
		$list = $list->filter('Comment', 'Phil is a unique guy, and comments on team2');
1177
		$list = $list->exclude('Name', 'Bob');
1178
1179
		$sql = $list->sql($parameters);
1180
		$this->assertSQLContains(
1181
			'WHERE ("DataObjectTest_TeamComment"."Comment" = ?) AND (("DataObjectTest_TeamComment"."Name" != ? '
1182
			. 'OR "DataObjectTest_TeamComment"."Name" IS NULL))',
1183
			$sql);
1184
		$this->assertEquals(array('Phil is a unique guy, and comments on team2', 'Bob'), $parameters);
1185
	}
1186
1187
	public function testExcludeWithSearchFilter() {
1188
		$list = DataObjectTest_TeamComment::get();
1189
		$list = $list->exclude('Name:LessThan', 'Bob');
1190
1191
		$sql = $list->sql($parameters);
1192
		$this->assertSQLContains('WHERE (("DataObjectTest_TeamComment"."Name" >= ?))', $sql);
1193
		$this->assertEquals(array('Bob'), $parameters);
1194
	}
1195
1196
	/**
1197
	 * Test exact match filter with empty array items
1198
	 */
1199
	public function testEmptyFilter() {
1200
		$this->setExpectedException("InvalidArgumentException", 'Cannot filter "DataObjectTest_TeamComment"."Name" against an empty set');
1201
		$list = DataObjectTest_TeamComment::get();
1202
		$list->exclude('Name', array());
1203
	}
1204
1205
	/**
1206
	 * $list->exclude(array('Name'=>'bob, 'Age'=>array(21, 43))); // exclude bob with Age 21 or 43
1207
	 */
1208
	public function testMultipleExcludeWithMultipleThatCheersEitherTeam() {
1209
		$list = DataObjectTest_TeamComment::get();
1210
		$list = $list->exclude(array('Name'=>'Bob', 'TeamID'=>array(
1211
			$this->idFromFixture('DataObjectTest_Team', 'team1'),
1212
			$this->idFromFixture('DataObjectTest_Team', 'team2')
1213
		)));
1214
		$list = $list->sort('Name');
1215
		$this->assertEquals(2, $list->count());
1216
		$this->assertEquals('Joe', $list->first()->Name, 'First comment should be from Phil');
1217
		$this->assertEquals('Phil', $list->last()->Name, 'First comment should be from Phil');
1218
	}
1219
1220
	/**
1221
	 * $list->exclude(array('Name'=>'bob, 'Age'=>array(21, 43))); // negative version
1222
	 */
1223
	public function testMultipleExcludeWithMultipleThatCheersOnNonExistingTeam() {
1224
		$list = DataObjectTest_TeamComment::get();
1225
		$list = $list->exclude(array('Name'=>'Bob', 'TeamID'=>array(3)));
1226
		$this->assertEquals(3, $list->count());
1227
	}
1228
1229
	/**
1230
	 * $list->exclude(array('Name'=>array('bob','phil'), 'Age'=>array(21, 43))); //negative version
1231
	 */
1232
	public function testMultipleExcludeWithNoExclusion() {
1233
		$list = DataObjectTest_TeamComment::get();
1234
		$list = $list->exclude(array(
1235
			'Name'=>array('Bob','Joe'),
1236
			'Comment' => 'Phil is a unique guy, and comments on team2'));
1237
		$this->assertEquals(3, $list->count());
1238
	}
1239
1240
	/**
1241
	 *  $list->exclude(array('Name'=>array('bob','phil'), 'Age'=>array(21, 43)));
1242
	 */
1243
	public function testMultipleExcludeWithTwoArray() {
1244
		$list = DataObjectTest_TeamComment::get();
1245
		$list = $list->exclude(array('Name' => array('Bob','Joe'), 'TeamID' => array(
1246
			$this->idFromFixture('DataObjectTest_Team', 'team1'),
1247
			$this->idFromFixture('DataObjectTest_Team', 'team2')
1248
		)));
1249
		$this->assertEquals(1, $list->count());
1250
		$this->assertEquals('Phil', $list->last()->Name, 'Only comment should be from Phil');
1251
	}
1252
1253
	/**
1254
	 *  $list->exclude(array('Name'=>array('bob','phil'), 'Age'=>array(21, 43)));
1255
	 */
1256
	public function testMultipleExcludeWithTwoArrayOneTeam() {
1257
		$list = DataObjectTest_TeamComment::get();
1258
		$list = $list->exclude(array(
1259
			'Name' => array('Bob', 'Phil'),
1260
			'TeamID' => array($this->idFromFixture('DataObjectTest_Team', 'team1'))));
1261
		$list = $list->sort('Name');
1262
		$this->assertEquals(2, $list->count());
1263
		$this->assertEquals('Joe', $list->first()->Name, 'First comment should be from Joe');
1264
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
1265
	}
1266
1267
	/**
1268
	 *
1269
	 */
1270
	public function testSortByRelation() {
1271
		$list = DataObjectTest_TeamComment::get();
1272
		$list = $list->sort(array('Team.Title' => 'DESC'));
1273
		$this->assertEquals(3, $list->count());
1274
		$this->assertEquals($this->idFromFixture('DataObjectTest_Team', 'team2'), $list->first()->TeamID,
1275
			'First comment should be for Team 2');
1276
		$this->assertEquals($this->idFromFixture('DataObjectTest_Team', 'team1'), $list->last()->TeamID,
1277
			'Last comment should be for Team 1');
1278
	}
1279
1280
	public function testReverse() {
1281
		$list = DataObjectTest_TeamComment::get();
1282
		$list = $list->sort('Name');
1283
		$list = $list->reverse();
1284
1285
		$this->assertEquals('Bob', $list->last()->Name, 'Last comment should be from Bob');
1286
		$this->assertEquals('Phil', $list->first()->Name, 'First comment should be from Phil');
1287
	}
1288
1289
	public function testSortByComplexExpression() {
1290
		// Test an expression with both spaces and commas. This test also tests that column() can be called
1291
		// with a complex sort expression, so keep using column() below
1292
		$list = DataObjectTest_Team::get()->sort(
1293
			'CASE WHEN "DataObjectTest_Team"."ClassName" = \'DataObjectTest_SubTeam\' THEN 0 ELSE 1 END, "Title" DESC'
1294
		);
1295
		$this->assertEquals(array(
1296
			'Subteam 3',
1297
			'Subteam 2',
1298
			'Subteam 1',
1299
			'Team 3',
1300
			'Team 2',
1301
			'Team 1',
1302
		), $list->column("Title"));
1303
	}
1304
}
1305