Completed
Pull Request — 3.4 (#6199)
by Jono
10:26
created

DataListTest::testAmbiguousAggregate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 7
nc 1
nop 0
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @package framework
5
 * @subpackage tests
6
 */
7
class DataListTest extends SapphireTest {
8
9
	// Borrow the model from DataObjectTest
10
	protected static $fixture_file = 'DataObjectTest.yml';
11
12
	protected $extraDataObjects = array(
13
		'DataObjectTest_Team',
14
		'DataObjectTest_Fixture',
15
		'DataObjectTest_SubTeam',
16
		'OtherSubclassWithSameField',
17
		'DataObjectTest_FieldlessTable',
18
		'DataObjectTest_FieldlessSubTable',
19
		'DataObjectTest_ValidatedObject',
20
		'DataObjectTest_Player',
21
		'DataObjectTest_TeamComment',
22
		'DataObjectTest_ExtendedTeamComment',
23
		'DataObjectTest_EquipmentCompany',
24
		'DataObjectTest_SubEquipmentCompany',
25
		'DataObjectTest\NamespacedClass',
26
		'DataObjectTest_Sortable',
27
		'DataObjectTest_Company',
28
		'DataObjectTest_Fan',
29
		'ManyManyListTest_Product',
30
		'ManyManyListTest_Category',
31
	);
32
33
	public function testFilterDataObjectByCreatedDate() {
34
		// create an object to test with
35
		$obj1 = new DataObjectTest_ValidatedObject();
36
		$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...
37
		$obj1->write();
38
		$this->assertTrue($obj1->isInDB());
39
40
		// reload the object from the database and reset its Created timestamp to a known value
41
		$obj1 = DataObjectTest_ValidatedObject::get()->filter(array('Name' => 'test obj 1'))->first();
42
		$this->assertTrue(is_object($obj1));
43
		$this->assertEquals('test obj 1', $obj1->Name);
44
		$obj1->Created = '2013-01-01 00:00:00';
45
		$obj1->write();
46
47
		// reload the object again and make sure that our Created date was properly persisted
48
		$obj1 = DataObjectTest_ValidatedObject::get()->filter(array('Name' => 'test obj 1'))->first();
49
		$this->assertTrue(is_object($obj1));
50
		$this->assertEquals('test obj 1', $obj1->Name);
51
		$this->assertEquals('2013-01-01 00:00:00', $obj1->Created);
52
53
		// now save a second object to the DB with an automatically-set Created value
54
		$obj2 = new DataObjectTest_ValidatedObject();
55
		$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...
56
		$obj2->write();
57
		$this->assertTrue($obj2->isInDB());
58
59
		// and a third object
60
		$obj3 = new DataObjectTest_ValidatedObject();
61
		$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...
62
		$obj3->write();
63
		$this->assertTrue($obj3->isInDB());
64
65
		// now test the filtering based on Created timestamp
66
		$list = DataObjectTest_ValidatedObject::get()
67
			->filter(array('Created:GreaterThan' => '2013-02-01 00:00:00'))
68
			->toArray();
69
		$this->assertEquals(2, count($list));
70
71
	}
72
73
	public function testSubtract(){
74
		$comment1 = $this->objFromFixture('DataObjectTest_TeamComment', 'comment1');
75
		$subtractList = DataObjectTest_TeamComment::get()->filter('ID', $comment1->ID);
76
		$fullList = DataObjectTest_TeamComment::get();
77
		$newList = $fullList->subtract($subtractList);
78
		$this->assertEquals(2, $newList->Count(), 'List should only contain two objects after subtraction');
79
	}
80
81
	public function testSubtractBadDataclassThrowsException(){
82
		$this->setExpectedException('InvalidArgumentException');
83
		$teamsComments = DataObjectTest_TeamComment::get();
84
		$teams = DataObjectTest_Team::get();
85
		$teamsComments->subtract($teams);
86
	}
87
88
	public function testListCreationSortAndLimit() {
89
		// By default, a DataList will contain all items of that class
90
		$list = DataObjectTest_TeamComment::get()->sort('ID');
91
92
		// We can iterate on the DataList
93
		$names = array();
94
		foreach($list as $item) {
95
			$names[] = $item->Name;
96
		}
97
		$this->assertEquals(array('Joe', 'Bob', 'Phil'), $names);
98
99
		// If we don't want to iterate, we can extract a single column from the list with column()
100
		$this->assertEquals(array('Joe', 'Bob', 'Phil'), $list->column('Name'));
101
102
		// We can sort a list
103
		$list = $list->sort('Name');
104
		$this->assertEquals(array('Bob', 'Joe', 'Phil'), $list->column('Name'));
105
106
		// We can also restrict the output to a range
107
		$this->assertEquals(array('Joe', 'Phil'), $list->limit(2, 1)->column('Name'));
108
	}
109
110
	public function testLimitAndOffset() {
111
		$list = DataObjectTest_TeamComment::get();
112
		$check = $list->limit(3);
113
114
		$this->assertEquals(3, $check->count());
115
116
		$check = $list->limit(1);
117
		$this->assertEquals(1, $check->count());
118
119
		$check = $list->limit(1, 1);
120
		$this->assertEquals(1, $check->count());
121
122
		$check = $list->limit(false);
123
		$this->assertEquals(3, $check->count());
124
125
		$check = $list->limit(null);
126
		$this->assertEquals(3, $check->count());
127
128
		$check = $list->limit(null, 2);
129
		$this->assertEquals(1, $check->count());
130
131
		// count()/first()/last() methods may alter limit/offset, so run the query and manually check the count
132
		$check = $list->limit(null, 1)->toArray();
133
		$this->assertEquals(2, count($check));
134
	}
135
136
	public function testDistinct() {
137
		$list = DataObjectTest_TeamComment::get();
138
		$this->assertContains('SELECT DISTINCT', $list->dataQuery()->sql($params), 'Query is set as distinct by default');
139
140
		$list = $list->distinct(false);
141
		$this->assertNotContains('SELECT DISTINCT', $list->dataQuery()->sql($params), 'Query does not contain distinct');
142
143
		$list = $list->distinct(true);
144
		$this->assertContains('SELECT DISTINCT', $list->dataQuery()->sql($params), 'Query contains distinct');
145
	}
146
147
	public function testDataClass() {
148
		$list = DataObjectTest_TeamComment::get();
149
		$this->assertEquals('DataObjectTest_TeamComment',$list->dataClass());
150
	}
151
152
	public function testDataClassCaseInsensitive() {
153
		$list = DataList::create('dataobjecttest_teamcomment');
154
		$this->assertTrue($list->exists());
155
	}
156
157
	public function testClone() {
158
		$list = DataObjectTest_TeamComment::get();
159
		$this->assertEquals($list, clone($list));
160
	}
161
162
	public function testSql() {
163
		$db = DB::get_conn();
164
		$list = DataObjectTest_TeamComment::get();
165
		$expected = 'SELECT DISTINCT "DataObjectTest_TeamComment"."ClassName", '
166
			. '"DataObjectTest_TeamComment"."LastEdited", "DataObjectTest_TeamComment"."Created", '
167
			. '"DataObjectTest_TeamComment"."Name", "DataObjectTest_TeamComment"."Comment", '
168
			. '"DataObjectTest_TeamComment"."TeamID", "DataObjectTest_TeamComment"."ID", '
169
			. 'CASE WHEN "DataObjectTest_TeamComment"."ClassName" IS NOT NULL '
170
			. 'THEN "DataObjectTest_TeamComment"."ClassName" ELSE '
171
			. $db->quoteString('DataObjectTest_TeamComment')
172
			. ' END AS "RecordClassName" FROM "DataObjectTest_TeamComment"'
173
			. ' ORDER BY "DataObjectTest_TeamComment"."Name" ASC';
174
		$this->assertSQLEquals($expected, $list->sql($parameters));
175
	}
176
177
	public function testInnerJoin() {
178
		$db = DB::get_conn();
179
180
		$list = DataObjectTest_TeamComment::get();
181
		$list = $list->innerJoin(
182
			'DataObjectTest_Team',
183
			'"DataObjectTest_Team"."ID" = "DataObjectTest_TeamComment"."TeamID"',
184
			'Team'
185
		);
186
187
		$expected = 'SELECT DISTINCT "DataObjectTest_TeamComment"."ClassName", '
188
			. '"DataObjectTest_TeamComment"."LastEdited", "DataObjectTest_TeamComment"."Created", '
189
			. '"DataObjectTest_TeamComment"."Name", "DataObjectTest_TeamComment"."Comment", '
190
			. '"DataObjectTest_TeamComment"."TeamID", "DataObjectTest_TeamComment"."ID", '
191
			. 'CASE WHEN "DataObjectTest_TeamComment"."ClassName" IS NOT NULL'
192
			. ' THEN "DataObjectTest_TeamComment"."ClassName" ELSE '
193
			. $db->quoteString('DataObjectTest_TeamComment')
194
			. ' END AS "RecordClassName" FROM "DataObjectTest_TeamComment" INNER JOIN '
195
			. '"DataObjectTest_Team" AS "Team" ON "DataObjectTest_Team"."ID" = '
196
			. '"DataObjectTest_TeamComment"."TeamID"'
197
			. ' ORDER BY "DataObjectTest_TeamComment"."Name" ASC';
198
199
200
		$this->assertSQLEquals($expected, $list->sql($parameters));
201
		$this->assertEmpty($parameters);
202
	}
203
204
	public function testInnerJoinParameterised() {
205
		$db = DB::get_conn();
206
207
		$list = DataObjectTest_TeamComment::get();
208
		$list = $list->innerJoin(
209
			'DataObjectTest_Team',
210
			'"DataObjectTest_Team"."ID" = "DataObjectTest_TeamComment"."TeamID" '
211
			. 'AND "DataObjectTest_Team"."Title" LIKE ?',
212
			'Team',
213
			20,
214
			array('Team%')
215
		);
216
217
		$expected = 'SELECT DISTINCT "DataObjectTest_TeamComment"."ClassName", '
218
			. '"DataObjectTest_TeamComment"."LastEdited", "DataObjectTest_TeamComment"."Created", '
219
			. '"DataObjectTest_TeamComment"."Name", "DataObjectTest_TeamComment"."Comment", '
220
			. '"DataObjectTest_TeamComment"."TeamID", "DataObjectTest_TeamComment"."ID", '
221
			. 'CASE WHEN "DataObjectTest_TeamComment"."ClassName" IS NOT NULL'
222
			. ' THEN "DataObjectTest_TeamComment"."ClassName" ELSE '
223
			. $db->quoteString('DataObjectTest_TeamComment')
224
			. ' END AS "RecordClassName" FROM "DataObjectTest_TeamComment" INNER JOIN '
225
			. '"DataObjectTest_Team" AS "Team" ON "DataObjectTest_Team"."ID" = '
226
			. '"DataObjectTest_TeamComment"."TeamID" '
227
			. 'AND "DataObjectTest_Team"."Title" LIKE ?'
228
			. ' ORDER BY "DataObjectTest_TeamComment"."Name" ASC';
229
230
		$this->assertSQLEquals($expected, $list->sql($parameters));
231
		$this->assertEquals(array('Team%'), $parameters);
232
	}
233
234
	public function testLeftJoin() {
235
		$db = DB::get_conn();
236
237
		$list = DataObjectTest_TeamComment::get();
238
		$list = $list->leftJoin(
239
			'DataObjectTest_Team',
240
			'"DataObjectTest_Team"."ID" = "DataObjectTest_TeamComment"."TeamID"',
241
			'Team'
242
		);
243
244
		$expected = 'SELECT DISTINCT "DataObjectTest_TeamComment"."ClassName", '
245
			. '"DataObjectTest_TeamComment"."LastEdited", "DataObjectTest_TeamComment"."Created", '
246
			. '"DataObjectTest_TeamComment"."Name", "DataObjectTest_TeamComment"."Comment", '
247
			. '"DataObjectTest_TeamComment"."TeamID", "DataObjectTest_TeamComment"."ID", '
248
			. 'CASE WHEN "DataObjectTest_TeamComment"."ClassName" IS NOT NULL '
249
			. 'THEN "DataObjectTest_TeamComment"."ClassName" ELSE '
250
			. $db->quoteString('DataObjectTest_TeamComment')
251
			. ' END AS "RecordClassName" FROM "DataObjectTest_TeamComment" LEFT JOIN "DataObjectTest_Team" '
252
			. 'AS "Team" ON "DataObjectTest_Team"."ID" = "DataObjectTest_TeamComment"."TeamID"'
253
			. ' ORDER BY "DataObjectTest_TeamComment"."Name" ASC';
254
255
256
		$this->assertSQLEquals($expected, $list->sql($parameters));
257
		$this->assertEmpty($parameters);
258
259
		// Test with namespaces (with non-sensical join, but good enough for testing)
260
		$list = DataObjectTest_TeamComment::get();
261
		$list = $list->leftJoin(
262
			'DataObjectTest\NamespacedClass',
263
			'"DataObjectTest\NamespacedClass"."ID" = "DataObjectTest_TeamComment"."ID"'
264
		);
265
266
		$expected = 'SELECT DISTINCT "DataObjectTest_TeamComment"."ClassName", '
267
			. '"DataObjectTest_TeamComment"."LastEdited", '
268
			. '"DataObjectTest_TeamComment"."Created", '
269
			. '"DataObjectTest_TeamComment"."Name", '
270
			. '"DataObjectTest_TeamComment"."Comment", '
271
			. '"DataObjectTest_TeamComment"."TeamID", '
272
			. '"DataObjectTest_TeamComment"."ID", '
273
			. 'CASE WHEN "DataObjectTest_TeamComment"."ClassName" IS NOT NULL '
274
			. 'THEN "DataObjectTest_TeamComment"."ClassName" '
275
			. 'ELSE ' . $db->quoteString('DataObjectTest_TeamComment') . ' END AS "RecordClassName" '
276
			. 'FROM "DataObjectTest_TeamComment" '
277
			. 'LEFT JOIN "DataObjectTest\NamespacedClass" ON '
278
			. '"DataObjectTest\NamespacedClass"."ID" = "DataObjectTest_TeamComment"."ID"'
279
			. ' ORDER BY "DataObjectTest_TeamComment"."Name" ASC';
280
		$this->assertSQLEquals($expected, $list->sql($parameters), 'Retains backslashes in namespaced classes');
281
		$this->assertEmpty($parameters);
282
283
	}
284
285
	public function testLeftJoinParameterised() {
286
		$db = DB::get_conn();
287
288
		$list = DataObjectTest_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')
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
		$list = DataObjectTest_TeamComment::get()->sort('ID');
317
		$nestedArray = $list->toNestedArray();
318
		$expected = array(
319
			0=>
320
			array(
321
				'ClassName'=>'DataObjectTest_TeamComment',
322
				'Name'=>'Joe',
323
				'Comment'=>'This is a team comment by Joe',
324
				'TeamID'=> $this->objFromFixture('DataObjectTest_TeamComment', 'comment1')->TeamID,
325
			),
326
			1=>
327
			array(
328
				'ClassName'=>'DataObjectTest_TeamComment',
329
				'Name'=>'Bob',
330
				'Comment'=>'This is a team comment by Bob',
331
				'TeamID'=> $this->objFromFixture('DataObjectTest_TeamComment', 'comment2')->TeamID,
332
			),
333
			2=>
334
			array(
335
				'ClassName'=>'DataObjectTest_TeamComment',
336
				'Name'=>'Phil',
337
				'Comment'=>'Phil is a unique guy, and comments on team2',
338
				'TeamID'=> $this->objFromFixture('DataObjectTest_TeamComment', 'comment3')->TeamID,
339
			),
340
		);
341
		$this->assertEquals(3, count($nestedArray));
342
		$this->assertEquals($expected[0]['Name'], $nestedArray[0]['Name']);
343
		$this->assertEquals($expected[1]['Comment'], $nestedArray[1]['Comment']);
344
		$this->assertEquals($expected[2]['TeamID'], $nestedArray[2]['TeamID']);
345
	}
346
347
	public function testMap() {
348
		$map = DataObjectTest_TeamComment::get()->map()->toArray();
349
		$expected = array(
350
			$this->idFromFixture('DataObjectTest_TeamComment', 'comment1') => 'Joe',
351
			$this->idFromFixture('DataObjectTest_TeamComment', 'comment2') => 'Bob',
352
			$this->idFromFixture('DataObjectTest_TeamComment', 'comment3') => 'Phil'
353
		);
354
355
		$this->assertEquals($expected, $map);
356
		$otherMap = DataObjectTest_TeamComment::get()->map('Name', 'TeamID')->toArray();
357
		$otherExpected = array(
358
			'Joe' => $this->objFromFixture('DataObjectTest_TeamComment', 'comment1')->TeamID,
359
			'Bob' => $this->objFromFixture('DataObjectTest_TeamComment', 'comment2')->TeamID,
360
			'Phil' => $this->objFromFixture('DataObjectTest_TeamComment', 'comment3')->TeamID
361
		);
362
363
		$this->assertEquals($otherExpected, $otherMap);
364
	}
365
366
	public function testAmbiguousAggregate() {
367
		// Test that we avoid ambiguity error when a field exists on two joined tables
368
		// Fetch the sponsors in a round-about way to simulate this
369
		$teamID = $this->idFromFixture('DataObjectTest_Team','team2');
370
		$sponsors = DataObjectTest_EquipmentCompany::get()->filter('SponsoredTeams.ID', $teamID);
371
		$this->assertNotNull($sponsors->Max('ID'));
372
		$this->assertNotNull($sponsors->Min('ID'));
373
		$this->assertNotNull($sponsors->Avg('ID'));
374
		$this->assertNotNull($sponsors->Sum('ID'));
375
	}
376
377
	public function testEach() {
378
		$list = DataObjectTest_TeamComment::get();
379
380
		$count = 0;
381
		$test = $this;
382
383
		$list->each(function($item) use (&$count, $test) {
384
			$count++;
385
386
			$test->assertTrue(is_a($item, "DataObjectTest_TeamComment"));
387
		});
388
389
		$this->assertEquals($list->Count(), $count);
390
	}
391
392
	public function testWhere() {
393
		// We can use raw SQL queries with where.  This is only recommended for advanced uses;
394
		// if you can, you should use filter().
395
		$list = DataObjectTest_TeamComment::get();
396
397
		// where() returns a new DataList, like all the other modifiers, so it can be chained.
398
		$list2 = $list->where('"Name" = \'Joe\'');
399
		$this->assertEquals(array('This is a team comment by Joe'), $list2->column('Comment'));
400
401
		// The where() clauses are chained together with AND
402
		$list3 = $list2->where('"Name" = \'Bob\'');
403
		$this->assertEquals(array(), $list3->column('Comment'));
404
	}
405
406
	/**
407
	 * Test DataList->byID()
408
	 */
409
	public function testByID() {
410
		// We can get a single item by ID.
411
		$id = $this->idFromFixture('DataObjectTest_Team','team2');
412
		$team = DataObjectTest_Team::get()->byID($id);
413
414
		// byID() returns a DataObject, rather than a DataList
415
		$this->assertInstanceOf('DataObjectTest_Team', $team);
416
		$this->assertEquals('Team 2', $team->Title);
417
418
		// Assert that filtering on ID searches by the base table, not the child table field
419
		$query = DataObjectTest_SubTeam::get()->filter('ID', 4)->sql($parameters);
420
		$this->assertContains('WHERE ("DataObjectTest_Team"."ID" = ?)', $query);
421
		$this->assertNotContains('WHERE ("DataObjectTest_SubTeam"."ID" = ?)', $query);
422
	}
423
424
	public function testByIDs() {
425
		$knownIDs = $this->allFixtureIDs('DataObjectTest_Player');
426
		$removedID = array_pop($knownIDs);
427
		$filteredPlayers = DataObjectTest_Player::get()->byIDs($knownIDs);
428
		foreach ($filteredPlayers as $player) {
429
			$this->assertContains($player->ID, $knownIDs);
430
			$this->assertNotEquals($removedID, $player->ID);
431
		}
432
	}
433
434
	/**
435
	 * Test DataList->removeByID()
436
	 */
437
	public function testRemoveByID() {
438
		$list = DataObjectTest_Team::get();
439
		$id = $this->idFromFixture('DataObjectTest_Team','team2');
440
441
		$this->assertNotNull($list->byID($id));
442
		$list->removeByID($id);
443
		$this->assertNull($list->byID($id));
444
	}
445
446
	/**
447
	 * Test DataList->canSortBy()
448
	 */
449
	public function testCanSortBy() {
450
		// Basic check
451
		$team = DataObjectTest_Team::get();
452
		$this->assertTrue($team->canSortBy("Title"));
453
		$this->assertFalse($team->canSortBy("SomethingElse"));
454
455
		// Subclasses
456
		$subteam = DataObjectTest_SubTeam::get();
457
		$this->assertTrue($subteam->canSortBy("Title"));
458
		$this->assertTrue($subteam->canSortBy("SubclassDatabaseField"));
459
	}
460
461
	public function testDataListArrayAccess() {
462
		$list = DataObjectTest_Team::get()->sort('Title');
463
464
		// We can use array access to refer to single items in the DataList, as if it were an array
465
		$this->assertEquals("Subteam 1", $list[0]->Title);
466
		$this->assertEquals("Subteam 3", $list[2]->Title);
467
		$this->assertEquals("Team 2", $list[4]->Title);
468
	}
469
470
	public function testFind() {
471
		$list = DataObjectTest_Team::get();
472
		$record = $list->find('Title', 'Team 1');
473
		$this->assertEquals($this->idFromFixture('DataObjectTest_Team', 'team1'), $record->ID);
474
	}
475
476
	public function testFindById() {
477
		$list = DataObjectTest_Team::get();
478
		$record = $list->find('ID', $this->idFromFixture('DataObjectTest_Team', 'team1'));
479
		$this->assertEquals('Team 1', $record->Title);
480
		// Test that you can call it twice on the same list
481
		$record = $list->find('ID', $this->idFromFixture('DataObjectTest_Team', 'team2'));
482
		$this->assertEquals('Team 2', $record->Title);
483
	}
484
485
	public function testSimpleSort() {
486
		$list = DataObjectTest_TeamComment::get();
487
		$list = $list->sort('Name');
488
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
489
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
490
	}
491
492
	public function testSimpleSortOneArgumentASC() {
493
		$list = DataObjectTest_TeamComment::get();
494
		$list = $list->sort('Name ASC');
495
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
496
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
497
	}
498
499
	public function testSimpleSortOneArgumentDESC() {
500
		$list = DataObjectTest_TeamComment::get();
501
		$list = $list->sort('Name DESC');
502
		$this->assertEquals('Phil', $list->first()->Name, 'Last comment should be from Phil');
503
		$this->assertEquals('Bob', $list->last()->Name, 'First comment should be from Bob');
504
	}
505
506
	public function testSortOneArgumentMultipleColumns() {
507
		$list = DataObjectTest_TeamComment::get();
508
		$list = $list->sort('TeamID ASC, Name DESC');
509
		$this->assertEquals('Joe', $list->first()->Name, 'First comment should be from Bob');
510
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
511
	}
512
513
	public function testSimpleSortASC() {
514
		$list = DataObjectTest_TeamComment::get();
515
		$list = $list->sort('Name', 'asc');
516
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
517
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
518
	}
519
520
	public function testSimpleSortDESC() {
521
		$list = DataObjectTest_TeamComment::get();
522
		$list = $list->sort('Name', 'desc');
523
		$this->assertEquals('Phil', $list->first()->Name, 'Last comment should be from Phil');
524
		$this->assertEquals('Bob', $list->last()->Name, 'First comment should be from Bob');
525
	}
526
527
	public function testSortWithArraySyntaxSortASC() {
528
		$list = DataObjectTest_TeamComment::get();
529
		$list = $list->sort(array('Name'=>'asc'));
530
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
531
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
532
	}
533
534
	public function testSortWithArraySyntaxSortDESC() {
535
		$list = DataObjectTest_TeamComment::get();
536
		$list = $list->sort(array('Name'=>'desc'));
537
		$this->assertEquals('Phil', $list->first()->Name, 'Last comment should be from Phil');
538
		$this->assertEquals('Bob', $list->last()->Name, 'First comment should be from Bob');
539
	}
540
541
	public function testSortWithMultipleArraySyntaxSort() {
542
		$list = DataObjectTest_TeamComment::get();
543
		$list = $list->sort(array('TeamID'=>'asc','Name'=>'desc'));
544
		$this->assertEquals('Joe', $list->first()->Name, 'First comment should be from Bob');
545
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
546
	}
547
548
	public function testSortNumeric() {
549
		$list = DataObjectTest_Sortable::get();
550
		$list1 = $list->sort('Sort', 'ASC');
551
		$this->assertEquals(array(
552
			-10,
553
			-2,
554
			-1,
555
			0,
556
			1,
557
			2,
558
			10
559
		), $list1->column('Sort'));
560
	}
561
562
	public function testSortMixedCase() {
563
		$list = DataObjectTest_Sortable::get();
564
		$list1 = $list->sort('Name', 'ASC');
565
		$this->assertEquals(array(
566
            'Bob',
567
            'bonny',
568
            'jane',
569
            'John',
570
            'sam',
571
            'Steve',
572
            'steven'
573
		), $list1->column('Name'));
574
	}
575
576
	/**
577
	 * Test DataList->canFilterBy()
578
	 */
579
	public function testCanFilterBy() {
580
		// Basic check
581
		$team = DataObjectTest_Team::get();
582
		$this->assertTrue($team->canFilterBy("Title"));
583
		$this->assertFalse($team->canFilterBy("SomethingElse"));
584
585
		// Has one
586
		$this->assertTrue($team->canFilterBy("CaptainID"));
587
		$this->assertTrue($team->canFilterBy("Captain.ShirtNumber"));
588
		$this->assertFalse($team->canFilterBy("SomethingElse.ShirtNumber"));
589
		$this->assertFalse($team->canFilterBy("Captain.SomethingElse"));
590
		$this->assertTrue($team->canFilterBy("Captain.FavouriteTeam.Captain.ShirtNumber"));
591
592
		// Has many
593
		$this->assertTrue($team->canFilterBy("Fans.Name"));
594
		$this->assertFalse($team->canFilterBy("SomethingElse.Name"));
595
		$this->assertFalse($team->canFilterBy("Fans.SomethingElse"));
596
597
		// Many many
598
		$this->assertTrue($team->canFilterBy("Players.FirstName"));
599
		$this->assertFalse($team->canFilterBy("SomethingElse.FirstName"));
600
		$this->assertFalse($team->canFilterBy("Players.SomethingElse"));
601
602
		// Subclasses
603
		$subteam = DataObjectTest_SubTeam::get();
604
		$this->assertTrue($subteam->canFilterBy("Title"));
605
		$this->assertTrue($subteam->canFilterBy("SubclassDatabaseField"));
606
	}
607
608
	/**
609
	 * $list->filter('Name', 'bob'); // only bob in the list
610
	 */
611
	public function testSimpleFilter() {
612
		$list = DataObjectTest_Team::get();
613
		$list = $list->filter('Title','Team 2');
614
		$this->assertEquals(1, $list->count());
615
		$this->assertEquals('Team 2', $list->first()->Title, 'List should only contain Team 2');
616
		$this->assertEquals('Team 2', $list->last()->Title, 'Last should only contain Team 2');
617
	}
618
619
	public function testSimpleFilterEndsWith() {
620
		$list = DataObjectTest_TeamComment::get();
621
		$list = $list->filter('Name:EndsWith', 'b');
622
		$this->assertEquals(1, $list->count());
623
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
624
	}
625
626
	public function testSimpleFilterExactMatchFilter() {
627
		$list = DataObjectTest_TeamComment::get();
628
		$list = $list->filter('Name:ExactMatch', 'Bob');
629
		$this->assertEquals(1, $list->count());
630
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
631
	}
632
633
	public function testSimpleFilterGreaterThanFilter() {
634
		$list = DataObjectTest_TeamComment::get();
635
		$list = $list->filter('TeamID:GreaterThan', $this->idFromFixture('DataObjectTest_Team', 'team1'));
636
		$this->assertEquals(1, $list->count());
637
		$this->assertEquals('Phil', $list->first()->Name, 'First comment should be from Phil');
638
	}
639
640
	public function testSimpleFilterGreaterThanOrEqualFilter() {
641
		$list = DataObjectTest_TeamComment::get();
642
		$list = $list->filter('TeamID:GreaterThanOrEqual',
643
			$this->idFromFixture('DataObjectTest_Team', 'team1'))->sort("ID");
644
		$this->assertEquals(3, $list->count());
645
		$this->assertEquals('Joe', $list->first()->Name, 'First comment should be from Joe');
646
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
647
	}
648
649
	public function testSimpleFilterLessThanFilter() {
650
		$list = DataObjectTest_TeamComment::get();
651
		$list = $list->filter('TeamID:LessThan',
652
			$this->idFromFixture('DataObjectTest_Team', 'team2'))->sort('Name');
653
		$this->assertEquals(2, $list->count());
654
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
655
		$this->assertEquals('Joe', $list->Last()->Name, 'Last comment should be from Joe');
656
	}
657
658
	public function testSimpleFilterLessThanOrEqualFilter() {
659
		$list = DataObjectTest_TeamComment::get();
660
		$list = $list->filter('TeamID:LessThanOrEqual',
661
			$this->idFromFixture('DataObjectTest_Team', 'team1'))->sort('ID');
662
		$this->assertEquals(2, $list->count());
663
		$this->assertEquals('Joe', $list->first()->Name, 'First comment should be from Joe');
664
		$this->assertEquals('Bob', $list->Last()->Name, 'Last comment should be from Bob');
665
	}
666
667
	public function testSimplePartialMatchFilter() {
668
		$list = DataObjectTest_TeamComment::get();
669
		$list = $list->filter('Name:PartialMatch', 'o')->sort('Name');
670
		$this->assertEquals(2, $list->count());
671
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
672
		$this->assertEquals('Joe', $list->last()->Name, 'First comment should be from Joe');
673
	}
674
675
	public function testSimpleFilterStartsWith() {
676
		$list = DataObjectTest_TeamComment::get();
677
		$list = $list->filter('Name:StartsWith', 'B');
678
		$this->assertEquals(1, $list->count());
679
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
680
	}
681
682
	public function testSimpleFilterWithNonExistingComparisator() {
683
		$this->setExpectedException('InvalidArgumentException');
684
		$list = DataObjectTest_TeamComment::get();
685
		$list = $list->filter('Comment:Bogus', 'team comment');
686
	}
687
688
	/**
689
	 * $list->filter('Name', array('aziz', 'bob'); // aziz and bob in list
690
	 */
691
	public function testSimpleFilterWithMultiple() {
692
		$list = DataObjectTest_TeamComment::get();
693
		$list = $list->filter('Name', array('Bob','Phil'));
694
		$list = $list->sort('Name', 'ASC');
695
		$this->assertEquals(2, $list->count());
696
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
697
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
698
	}
699
700
	public function testMultipleFilterWithNoMatch() {
701
		$list = DataObjectTest_TeamComment::get();
702
		$list = $list->filter(array('Name'=>'Bob', 'Comment'=>'Phil is a unique guy, and comments on team2'));
703
		$this->assertEquals(0, $list->count());
704
	}
705
706
	/**
707
	 *  $list->filter(array('Name'=>'bob, 'Age'=>21)); // bob with the age 21
708
	 */
709
	public function testFilterMultipleArray() {
710
		$list = DataObjectTest_TeamComment::get();
711
		$list = $list->filter(array('Name'=>'Bob', 'Comment'=>'This is a team comment by Bob'));
712
		$list = $list->sort('Name', 'ASC');
713
		$this->assertEquals(1, $list->count());
714
		$this->assertEquals('Bob', $list->first()->Name, 'Only comment should be from Bob');
715
	}
716
717
	public function testFilterMultipleWithTwoMatches() {
718
		$list = DataObjectTest_TeamComment::get();
719
		$list = $list->filter(array('TeamID'=>$this->idFromFixture('DataObjectTest_Team', 'team1')));
720
		$this->assertEquals(2, $list->count());
721
	}
722
723
	public function testFilterMultipleWithArrayFilter() {
724
		$list = DataObjectTest_TeamComment::get();
725
		$list = $list->filter(array('Name'=>array('Bob','Phil')));
726
		$list = $list->sort('Name', 'ASC');
727
		$this->assertEquals(2, $list->count(), 'There should be two comments');
728
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
729
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
730
	}
731
732
	public function testFilterMultipleWithArrayFilterAndModifiers() {
733
		$list = DataObjectTest_TeamComment::get();
734
		$list = $list->filter(array('Name:StartsWith'=>array('Bo', 'Jo')));
735
		$list = $list->sort('Name', 'ASC');
736
		$this->assertEquals(2, $list->count());
737
		$this->assertEquals('Bob', $list->first()->Name);
738
		$this->assertEquals('Joe', $list->last()->Name);
739
	}
740
741
	/**
742
	 * $list->filter(array('Name'=>array('aziz','bob'), 'Age'=>array(21, 43)));
743
	 */
744
	public function testFilterArrayInArray() {
745
		$list = DataObjectTest_TeamComment::get();
746
		$list = $list->filter(array(
747
			'Name'=>array('Bob','Phil'),
748
			'TeamID'=>array($this->idFromFixture('DataObjectTest_Team', 'team1'))));
749
		$this->assertEquals(1, $list->count(), 'There should be one comment');
750
		$this->assertEquals('Bob', $list->first()->Name, 'Only comment should be from Bob');
751
	}
752
753
	public function testFilterWithModifiers() {
754
		$list = DataObjectTest_TeamComment::get();
755
		$nocaseList = $list->filter('Name:nocase', 'bob');
756
		$this->assertEquals(1, $nocaseList->count(), 'There should be one comment');
757
		$caseList = $list->filter('Name:case', 'bob');
758
		$this->assertEquals(0, $caseList->count(), 'There should be no comments');
759
		$gtList = $list->filter('TeamID:GreaterThan:not',
760
			$this->idFromFixture('DataObjectTest_Team', 'team1'));
761
		$this->assertEquals(2, $gtList->count());
762
	}
763
764
	public function testFilterAny() {
765
		$list = DataObjectTest_TeamComment::get();
766
		$list = $list->filterAny('Name', 'Bob');
767
		$this->assertEquals(1, $list->count());
768
	}
769
770
	public function testFilterAnyMultipleArray() {
771
		$list = DataObjectTest_TeamComment::get();
772
		$list = $list->filterAny(array('Name'=>'Bob', 'Comment'=>'This is a team comment by Bob'));
773
		$this->assertEquals(1, $list->count());
774
		$this->assertEquals('Bob', $list->first()->Name, 'Only comment should be from Bob');
775
	}
776
777
	public function testFilterAnyOnFilter() {
778
		$list = DataObjectTest_TeamComment::get();
779
		$list = $list->filter(array(
780
			'TeamID'=>$this->idFromFixture('DataObjectTest_Team', 'team1')
781
		));
782
		$list = $list->filterAny(array(
783
			'Name'=>array('Phil', 'Joe'),
784
			'Comment'=>'This is a team comment by Bob'
785
		));
786
		$list = $list->sort('Name');
787
		$this->assertEquals(2, $list->count());
788
		$this->assertEquals(
789
			'Bob',
790
			$list->offsetGet(0)->Name,
791
			'Results should include comments from Bob, matched by comment and team'
792
		);
793
		$this->assertEquals(
794
			'Joe',
795
			$list->offsetGet(1)->Name,
796
			'Results should include comments by Joe, matched by name and team (not by comment)'
797
		);
798
799
		$list = DataObjectTest_TeamComment::get();
800
		$list = $list->filter(array(
801
			'TeamID'=>$this->idFromFixture('DataObjectTest_Team', 'team1')
802
		));
803
		$list = $list->filterAny(array(
804
			'Name'=>array('Phil', 'Joe'),
805
			'Comment'=>'This is a team comment by Bob'
806
		));
807
		$list = $list->sort('Name');
808
		$list = $list->filter(array('Name' => 'Bob'));
809
		$this->assertEquals(1, $list->count());
810
		$this->assertEquals(
811
			'Bob',
812
			$list->offsetGet(0)->Name,
813
			'Results should include comments from Bob, matched by name and team'
814
		);
815
	}
816
817
	public function testFilterAnyMultipleWithArrayFilter() {
818
		$list = DataObjectTest_TeamComment::get();
819
		$list = $list->filterAny(array('Name'=>array('Bob','Phil')));
820
		$this->assertEquals(2, $list->count(), 'There should be two comments');
821
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
822
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
823
	}
824
825
	public function testFilterAnyArrayInArray() {
826
		$list = DataObjectTest_TeamComment::get();
827
		$list = $list->filterAny(array(
828
			'Name'=>array('Bob','Phil'),
829
			'TeamID'=>array($this->idFromFixture('DataObjectTest_Team', 'team1'))))
830
			->sort('Name');
831
		$this->assertEquals(3, $list->count());
832
		$this->assertEquals(
833
			'Bob',
834
			$list->offsetGet(0)->Name,
835
			'Results should include comments from Bob, matched by name and team'
836
		);
837
		$this->assertEquals(
838
			'Joe',
839
			$list->offsetGet(1)->Name,
840
			'Results should include comments by Joe, matched by team (not by name)'
841
		);
842
		$this->assertEquals(
843
			'Phil',
844
			$list->offsetGet(2)->Name,
845
			'Results should include comments from Phil, matched by name (even if he\'s not in Team1)'
846
		);
847
	}
848
849
	public function testFilterOnJoin() {
850
		$list = DataObjectTest_TeamComment::get()
851
			->leftJoin('DataObjectTest_Team',
852
				'"DataObjectTest_Team"."ID" = "DataObjectTest_TeamComment"."TeamID"'
853
			)->filter(array(
854
				'Title' => 'Team 1'
855
			));
856
857
		$this->assertEquals(2, $list->count());
858
		$values = $list->column('Name');
859
		$this->assertEquals(array_intersect($values, array('Joe', 'Bob')), $values);
860
	}
861
862
	public function testFilterOnImplicitJoin() {
863
		// Many to many
864
		$list = DataObjectTest_Team::get()
865
			->filter('Players.FirstName', array('Captain', 'Captain 2'));
866
867
		$this->assertEquals(2, $list->count());
868
869
		// Has many
870
		$list = DataObjectTest_Team::get()
871
			->filter('Comments.Name', array('Joe', 'Phil'));
872
873
		$this->assertEquals(2, $list->count());
874
875
		// Has one
876
		$list = DataObjectTest_Player::get()
877
			->filter('FavouriteTeam.Title', 'Team 1');
878
879
		$this->assertEquals(1, $list->count());
880
		$this->assertEquals('007', $list->first()->ShirtNumber);
881
	}
882
883
	public function testFilterAndExcludeById() {
884
		$id = $this->idFromFixture('DataObjectTest_SubTeam', 'subteam1');
885
		$list = DataObjectTest_SubTeam::get()->filter('ID', $id);
886
		$this->assertEquals($id, $list->first()->ID);
887
888
		$list = DataObjectTest_SubTeam::get();
889
		$this->assertEquals(3, count($list));
890
		$this->assertEquals(2, count($list->exclude('ID', $id)));
891
892
		// Check that classes with namespaces work.
893
		$obj = new DataObjectTest\NamespacedClass();
894
		$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...
895
		$obj->write();
896
897
		$list = DataObjectTest\NamespacedClass::get()->filter('ID', $obj->ID);
898
		$this->assertEquals('Test', $list->First()->Name);
899
		$this->assertEquals(0, $list->exclude('ID', $obj->ID)->count());
900
	}
901
902
	/**
903
	 * $list = $list->filterByCallback(function($item, $list) { return $item->Age == 21; })
904
	 */
905
	public function testFilterByCallback() {
906
		$team1ID = $this->idFromFixture('DataObjectTest_Team', 'team1');
907
		$list = DataObjectTest_TeamComment::get();
908
		$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...
909
			return $item->TeamID == $team1ID;
910
		});
911
912
		$result = $list->column('Name');
913
		$expected = array_intersect($result, array('Joe', 'Bob'));
914
915
		$this->assertEquals(2, $list->count());
916
		$this->assertEquals($expected, $result, 'List should only contain comments from Team 1 (Joe and Bob)');
917
		$this->assertTrue($list instanceof SS_Filterable, 'The List should be of type SS_Filterable');
918
	}
919
920
	/**
921
	 * $list->exclude('Name', 'bob'); // exclude bob from list
922
	 */
923
	public function testSimpleExclude() {
924
		$list = DataObjectTest_TeamComment::get();
925
		$list = $list->exclude('Name', 'Bob');
926
		$list = $list->sort('Name');
927
		$this->assertEquals(2, $list->count());
928
		$this->assertEquals('Joe', $list->first()->Name, 'First comment should be from Joe');
929
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
930
	}
931
//
932
	/**
933
	 * $list->exclude('Name', array('aziz', 'bob'); // exclude aziz and bob from list
934
	 */
935
	public function testSimpleExcludeWithMultiple() {
936
		$list = DataObjectTest_TeamComment::get();
937
		$list = $list->exclude('Name', array('Joe','Phil'));
938
		$this->assertEquals(1, $list->count());
939
		$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
940
	}
941
942
	/**
943
	 * $list->exclude(array('Name'=>'bob, 'Age'=>21)); // negative version
944
	 */
945
	public function testMultipleExcludeWithMiss() {
946
		$list = DataObjectTest_TeamComment::get();
947
		$list = $list->exclude(array('Name'=>'Bob', 'Comment'=>'Does not match any comments'));
948
		$this->assertEquals(3, $list->count());
949
	}
950
951
	/**
952
	 * $list->exclude(array('Name'=>'bob, 'Age'=>21)); // exclude bob that has Age 21
953
	 */
954
	public function testMultipleExclude() {
955
		$list = DataObjectTest_TeamComment::get();
956
		$list = $list->exclude(array('Name'=>'Bob', 'Comment'=>'This is a team comment by Bob'));
957
		$this->assertEquals(2, $list->count());
958
	}
959
960
	/**
961
	 * Test that if an exclude() is applied to a filter(), the filter() is still preserved.
962
	 */
963
	public function testExcludeOnFilter() {
964
		$list = DataObjectTest_TeamComment::get();
965
		$list = $list->filter('Comment', 'Phil is a unique guy, and comments on team2');
966
		$list = $list->exclude('Name', 'Bob');
967
968
		$sql = $list->sql($parameters);
969
		$this->assertSQLContains(
970
			'WHERE ("DataObjectTest_TeamComment"."Comment" = ?) AND (("DataObjectTest_TeamComment"."Name" != ?))',
971
			$sql);
972
		$this->assertEquals(array('Phil is a unique guy, and comments on team2', 'Bob'), $parameters);
973
	}
974
975
	public function testExcludeWithSearchFilter() {
976
		$list = DataObjectTest_TeamComment::get();
977
		$list = $list->exclude('Name:LessThan', 'Bob');
978
979
		$sql = $list->sql($parameters);
980
		$this->assertSQLContains('WHERE (("DataObjectTest_TeamComment"."Name" >= ?))', $sql);
981
		$this->assertEquals(array('Bob'), $parameters);
982
	}
983
984
	/**
985
	 * Test exact match filter with empty array items
986
	 */
987
	public function testEmptyFilter() {
988
		$list = DataObjectTest_TeamComment::get();
989
		$list = $list->exclude('Name', array());
990
991
		$sql = $list->sql($parameters);
992
		$this->assertSQLContains('WHERE (("DataObjectTest_TeamComment"."Name" NOT IN (?)))', $sql);
993
		$this->assertEquals(array(''), $parameters);
994
995
996
		$list = DataObjectTest_TeamComment::get();
997
		$list = $list->filter('Name', array());
998
999
		$sql = $list->sql($parameters);
1000
		$this->assertSQLContains('WHERE ("DataObjectTest_TeamComment"."Name" IN (?))', $sql);
1001
		$this->assertEquals(array(''), $parameters);
1002
	}
1003
1004
	/**
1005
	 * $list->exclude(array('Name'=>'bob, 'Age'=>array(21, 43))); // exclude bob with Age 21 or 43
1006
	 */
1007
	public function testMultipleExcludeWithMultipleThatCheersEitherTeam() {
1008
		$list = DataObjectTest_TeamComment::get();
1009
		$list = $list->exclude(array('Name'=>'Bob', 'TeamID'=>array(
1010
			$this->idFromFixture('DataObjectTest_Team', 'team1'),
1011
			$this->idFromFixture('DataObjectTest_Team', 'team2')
1012
		)));
1013
		$list = $list->sort('Name');
1014
		$this->assertEquals(2, $list->count());
1015
		$this->assertEquals('Joe', $list->first()->Name, 'First comment should be from Phil');
1016
		$this->assertEquals('Phil', $list->last()->Name, 'First comment should be from Phil');
1017
	}
1018
1019
	/**
1020
	 * $list->exclude(array('Name'=>'bob, 'Age'=>array(21, 43))); // negative version
1021
	 */
1022
	public function testMultipleExcludeWithMultipleThatCheersOnNonExistingTeam() {
1023
		$list = DataObjectTest_TeamComment::get();
1024
		$list = $list->exclude(array('Name'=>'Bob', 'TeamID'=>array(3)));
1025
		$this->assertEquals(3, $list->count());
1026
	}
1027
1028
	/**
1029
	 * $list->exclude(array('Name'=>array('bob','phil'), 'Age'=>array(21, 43))); //negative version
1030
	 */
1031
	public function testMultipleExcludeWithNoExclusion() {
1032
		$list = DataObjectTest_TeamComment::get();
1033
		$list = $list->exclude(array(
1034
			'Name'=>array('Bob','Joe'),
1035
			'Comment' => 'Phil is a unique guy, and comments on team2'));
1036
		$this->assertEquals(3, $list->count());
1037
	}
1038
1039
	/**
1040
	 *  $list->exclude(array('Name'=>array('bob','phil'), 'Age'=>array(21, 43)));
1041
	 */
1042
	public function testMultipleExcludeWithTwoArray() {
1043
		$list = DataObjectTest_TeamComment::get();
1044
		$list = $list->exclude(array('Name' => array('Bob','Joe'), 'TeamID' => array(
1045
			$this->idFromFixture('DataObjectTest_Team', 'team1'),
1046
			$this->idFromFixture('DataObjectTest_Team', 'team2')
1047
		)));
1048
		$this->assertEquals(1, $list->count());
1049
		$this->assertEquals('Phil', $list->last()->Name, 'Only comment should be from Phil');
1050
	}
1051
1052
	/**
1053
	 *  $list->exclude(array('Name'=>array('bob','phil'), 'Age'=>array(21, 43)));
1054
	 */
1055
	public function testMultipleExcludeWithTwoArrayOneTeam() {
1056
		$list = DataObjectTest_TeamComment::get();
1057
		$list = $list->exclude(array(
1058
			'Name' => array('Bob', 'Phil'),
1059
			'TeamID' => array($this->idFromFixture('DataObjectTest_Team', 'team1'))));
1060
		$list = $list->sort('Name');
1061
		$this->assertEquals(2, $list->count());
1062
		$this->assertEquals('Joe', $list->first()->Name, 'First comment should be from Joe');
1063
		$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
1064
	}
1065
1066
	/**
1067
	 *
1068
	 */
1069
	public function testSortByRelation() {
1070
		$list = DataObjectTest_TeamComment::get();
1071
		$list = $list->sort(array('Team.Title' => 'DESC'));
1072
		$this->assertEquals(3, $list->count());
1073
		$this->assertEquals($this->idFromFixture('DataObjectTest_Team', 'team2'), $list->first()->TeamID,
1074
			'First comment should be for Team 2');
1075
		$this->assertEquals($this->idFromFixture('DataObjectTest_Team', 'team1'), $list->last()->TeamID,
1076
			'Last comment should be for Team 1');
1077
	}
1078
1079
	public function testReverse() {
1080
		$list = DataObjectTest_TeamComment::get();
1081
		$list = $list->sort('Name');
1082
		$list = $list->reverse();
1083
1084
		$this->assertEquals('Bob', $list->last()->Name, 'Last comment should be from Bob');
1085
		$this->assertEquals('Phil', $list->first()->Name, 'First comment should be from Phil');
1086
	}
1087
1088
	public function testSortByComplexExpression() {
1089
		// Test an expression with both spaces and commas. This test also tests that column() can be called
1090
		// with a complex sort expression, so keep using column() below
1091
		$list = DataObjectTest_Team::get()->sort(
1092
			'CASE WHEN "DataObjectTest_Team"."ClassName" = \'DataObjectTest_SubTeam\' THEN 0 ELSE 1 END, "Title" DESC'
1093
		);
1094
		$this->assertEquals(array(
1095
			'Subteam 3',
1096
			'Subteam 2',
1097
			'Subteam 1',
1098
			'Team 3',
1099
			'Team 2',
1100
			'Team 1',
1101
		), $list->column("Title"));
1102
	}
1103
}
1104