Completed
Push — namespace-template ( 7967f2...367a36 )
by Sam
10:48
created

testComparisonClauseDateStartsWith()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 6

Duplication

Lines 7
Ratio 100 %
Metric Value
dl 7
loc 7
rs 9.4285
cc 1
eloc 6
nc 1
nop 0
1
<?php
2
3
class DataQueryTest extends SapphireTest {
4
5
	protected static $fixture_file = 'DataQueryTest.yml';
6
7
	protected $extraDataObjects = array(
8
		'DataQueryTest_A',
9
		'DataQueryTest_B',
10
		'DataQueryTest_C',
11
		'DataQueryTest_D',
12
		'DataQueryTest_E',
13
		'DataQueryTest_F',
14
		'DataQueryTest_G',
15
	);
16
17
18
	public function testSortByJoinedFieldRetainsSourceInformation() {
19
		$bar = new DataQueryTest_C();
20
		$bar->Title = "Bar";
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<DataQueryTest_C>. 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...
21
		$bar->write();
22
23
		$foo = new DataQueryTest_B();
24
		$foo->Title = "Foo";
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<DataQueryTest_B>. 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...
25
		$foo->TestC = $bar->ID;
0 ignored issues
show
Documentation introduced by
The property TestC does not exist on object<DataQueryTest_B>. 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...
26
		$foo->write();
27
28
		$query = new DataQuery('DataQueryTest_B');
29
		$result = $query->leftJoin(
30
			'DataQueryTest_C',
31
			"\"DataQueryTest_B\".\"TestCID\" = \"DataQueryTest_B\".\"ID\""
32
		)->sort('"DataQueryTest_B"."Title"', 'ASC');
33
34
		$result = $result->execute()->record();
35
		$this->assertEquals('Foo', $result['Title']);
36
	}
37
38
	/**
39
	 * Test the leftJoin() and innerJoin method of the DataQuery object
40
	 */
41
	public function testJoins() {
42
		$dq = new DataQuery('Member');
43
		$dq->innerJoin("Group_Members", "\"Group_Members\".\"MemberID\" = \"Member\".\"ID\"");
44
		$this->assertSQLContains("INNER JOIN \"Group_Members\" ON \"Group_Members\".\"MemberID\" = \"Member\".\"ID\"",
45
			$dq->sql($parameters));
46
47
		$dq = new DataQuery('Member');
48
		$dq->leftJoin("Group_Members", "\"Group_Members\".\"MemberID\" = \"Member\".\"ID\"");
49
		$this->assertSQLContains("LEFT JOIN \"Group_Members\" ON \"Group_Members\".\"MemberID\" = \"Member\".\"ID\"",
50
			$dq->sql($parameters));
51
	}
52
53
	public function testApplyRelation() {
54
		// Test applyRelation with two has_ones pointing to the same class
55
		$dq = new DataQuery('DataQueryTest_B');
56
		$dq->applyRelation('TestC');
57
		$this->assertTrue($dq->query()->isJoinedTo('DataQueryTest_C'));
58
		$this->assertContains('"DataQueryTest_C"."ID" = "DataQueryTest_B"."TestCID"', $dq->sql());
59
60
		$dq = new DataQuery('DataQueryTest_B');
61
		$dq->applyRelation('TestCTwo');
62
		$this->assertTrue($dq->query()->isJoinedTo('DataQueryTest_C'));
63
		$this->assertContains('"DataQueryTest_C"."ID" = "DataQueryTest_B"."TestCTwoID"', $dq->sql());
64
	}
65
66
	public function testApplyReplationDeepInheretence() {
67
		//test has_one relation
68
		$newDQ = new DataQuery('DataQueryTest_E');
69
		//apply a relation to a relation from an ancestor class
70
		$newDQ->applyRelation('TestA');
71
		$this->assertTrue($newDQ->query()->isJoinedTo('DataQueryTest_C'));
72
		$this->assertContains('"DataQueryTest_A"."ID" = "DataQueryTest_C"."TestAID"', $newDQ->sql($params));
73
74
		//test many_many relation
75
76
		//test many_many with separate inheritance
77
		$newDQ = new DataQuery('DataQueryTest_C');
78
		$baseDBTable = ClassInfo::baseDataClass('DataQueryTest_C');
79
		$newDQ->applyRelation('ManyTestAs');
80
		//check we are "joined" to the DataObject's table (there is no distinction between FROM or JOIN clauses)
81
		$this->assertTrue($newDQ->query()->isJoinedTo($baseDBTable));
82
		//check we are explicitly selecting "FROM" the DO's table
83
		$this->assertContains("FROM \"$baseDBTable\"", $newDQ->sql());
84
85
		//test many_many with shared inheritance
86
		$newDQ = new DataQuery('DataQueryTest_E');
87
		$baseDBTable = ClassInfo::baseDataClass('DataQueryTest_E');
88
		//check we are "joined" to the DataObject's table (there is no distinction between FROM or JOIN clauses)
89
		$this->assertTrue($newDQ->query()->isJoinedTo($baseDBTable));
90
		//check we are explicitly selecting "FROM" the DO's table
91
		$this->assertContains("FROM \"$baseDBTable\"", $newDQ->sql(), 'The FROM clause is missing from the query');
92
		$newDQ->applyRelation('ManyTestGs');
93
		//confirm we are still joined to the base table
94
		$this->assertTrue($newDQ->query()->isJoinedTo($baseDBTable));
95
		//double check it is the "FROM" clause
96
		$this->assertContains("FROM \"$baseDBTable\"", $newDQ->sql(), 'The FROM clause has been removed from the query');
97
		//another (potentially less crude check) for checking "FROM" clause
98
		$fromTables = $newDQ->query()->getFrom();
99
		$this->assertEquals('"' . $baseDBTable . '"', $fromTables[$baseDBTable]);
100
	}
101
102
	public function testRelationReturn() {
103
		$dq = new DataQuery('DataQueryTest_C');
104
		$this->assertEquals('DataQueryTest_A', $dq->applyRelation('TestA'),
105
			'DataQuery::applyRelation should return the name of the related object.');
106
		$this->assertEquals('DataQueryTest_A', $dq->applyRelation('TestAs'),
107
			'DataQuery::applyRelation should return the name of the related object.');
108
		$this->assertEquals('DataQueryTest_A', $dq->applyRelation('ManyTestAs'),
109
			'DataQuery::applyRelation should return the name of the related object.');
110
111
		$this->assertEquals('DataQueryTest_B', $dq->applyRelation('TestB'),
112
			'DataQuery::applyRelation should return the name of the related object.');
113
		$this->assertEquals('DataQueryTest_B', $dq->applyRelation('TestBs'),
114
			'DataQuery::applyRelation should return the name of the related object.');
115
		$this->assertEquals('DataQueryTest_B', $dq->applyRelation('ManyTestBs'),
116
			'DataQuery::applyRelation should return the name of the related object.');
117
		$newDQ = new DataQuery('DataQueryTest_E');
118
		$this->assertEquals('DataQueryTest_A', $newDQ->applyRelation('TestA'),
119
			'DataQuery::applyRelation should return the name of the related object.');
120
	}
121
122
	public function testRelationOrderWithCustomJoin() {
123
		$dataQuery = new DataQuery('DataQueryTest_B');
124
		$dataQuery->innerJoin('DataQueryTest_D', '"DataQueryTest_D"."RelationID" = "DataQueryTest_B"."ID"');
125
		$dataQuery->execute();
126
	}
127
128 View Code Duplication
	public function testDisjunctiveGroup() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
129
		$dq = new DataQuery('DataQueryTest_A');
130
131
		$dq->where('DataQueryTest_A.ID = 2');
132
		$subDq = $dq->disjunctiveGroup();
133
		$subDq->where('DataQueryTest_A.Name = \'John\'');
134
		$subDq->where('DataQueryTest_A.Name = \'Bob\'');
135
136
		$this->assertSQLContains(
137
			"WHERE (DataQueryTest_A.ID = 2) AND ((DataQueryTest_A.Name = 'John') OR (DataQueryTest_A.Name = 'Bob'))",
138
			$dq->sql($parameters)
139
		);
140
	}
141
142 View Code Duplication
	public function testConjunctiveGroup() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
143
		$dq = new DataQuery('DataQueryTest_A');
144
145
		$dq->where('DataQueryTest_A.ID = 2');
146
		$subDq = $dq->conjunctiveGroup();
147
		$subDq->where('DataQueryTest_A.Name = \'John\'');
148
		$subDq->where('DataQueryTest_A.Name = \'Bob\'');
149
150
		$this->assertSQLContains(
151
			"WHERE (DataQueryTest_A.ID = 2) AND ((DataQueryTest_A.Name = 'John') AND (DataQueryTest_A.Name = 'Bob'))",
152
			$dq->sql($parameters)
153
		);
154
	}
155
156
	/**
157
	 * @todo Test paramaterised
158
	 */
159
	public function testNestedGroups() {
160
		$dq = new DataQuery('DataQueryTest_A');
161
162
		$dq->where('DataQueryTest_A.ID = 2');
163
		$subDq = $dq->disjunctiveGroup();
164
		$subDq->where('DataQueryTest_A.Name = \'John\'');
165
		$subSubDq = $subDq->conjunctiveGroup();
166
		$subSubDq->where('DataQueryTest_A.Age = 18');
167
		$subSubDq->where('DataQueryTest_A.Age = 50');
168
		$subDq->where('DataQueryTest_A.Name = \'Bob\'');
169
170
		$this->assertSQLContains(
171
			"WHERE (DataQueryTest_A.ID = 2) AND ((DataQueryTest_A.Name = 'John') OR ((DataQueryTest_A.Age = 18) "
172
				. "AND (DataQueryTest_A.Age = 50)) OR (DataQueryTest_A.Name = 'Bob'))",
173
			$dq->sql($parameters)
174
		);
175
	}
176
177
	public function testEmptySubgroup() {
178
		$dq = new DataQuery('DataQueryTest_A');
179
		$dq->conjunctiveGroup();
180
181
		// Empty groups should have no where condition at all
182
		$this->assertSQLNotContains('WHERE', $dq->sql($parameters));
183
	}
184
185
	public function testSubgroupHandoff() {
186
		$dq = new DataQuery('DataQueryTest_A');
187
		$subDq = $dq->disjunctiveGroup();
188
189
		$orgDq = clone $dq;
190
191
		$subDq->sort('"DataQueryTest_A"."Name"');
192
		$orgDq->sort('"DataQueryTest_A"."Name"');
193
194
		$this->assertSQLEquals($dq->sql($parameters), $orgDq->sql($parameters));
195
196
		$subDq->limit(5, 7);
197
		$orgDq->limit(5, 7);
198
199
		$this->assertSQLEquals($dq->sql($parameters), $orgDq->sql($parameters));
200
	}
201
202
	public function testOrderByMultiple() {
203
		$dq = new DataQuery('SQLSelectTest_DO');
204
		$dq = $dq->sort('"Name" ASC, MID("Name", 8, 1) DESC');
205
		$this->assertContains(
206
			'ORDER BY "SQLSelectTest_DO"."Name" ASC, "_SortColumn0" DESC',
207
			$dq->sql($parameters)
208
		);
209
	}
210
211
	public function testDefaultSort() {
212
		$query = new DataQuery('DataQueryTest_E');
213
		$result = $query->column('Title');
214
		$this->assertEquals(array('First', 'Second', 'Last'), $result);
215
	}
216
217
	public function testDistinct() {
218
		$query = new DataQuery('DataQueryTest_E');
219
		$this->assertContains('SELECT DISTINCT', $query->sql($params), 'Query is set as distinct by default');
220
221
		$query = $query->distinct(false);
222
		$this->assertNotContains('SELECT DISTINCT', $query->sql($params), 'Query does not contain distinct');
223
224
		$query = $query->distinct(true);
225
		$this->assertContains('SELECT DISTINCT', $query->sql($params), 'Query contains distinct');
226
 	}
227
228 View Code Duplication
	public function testComparisonClauseInt() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
229
		DB::query("INSERT INTO \"DataQueryTest_F\" (\"SortOrder\") VALUES (2)");
230
		$query = new DataQuery('DataQueryTest_F');
231
		$query->where(DB::get_conn()->comparisonClause('"SortOrder"', '2'));
232
		$this->assertGreaterThan(0, $query->count(), "Couldn't find SortOrder");
233
		$this->resetDBSchema(true);
234
	}
235
236 View Code Duplication
	public function testComparisonClauseDateFull() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
237
		DB::query("INSERT INTO \"DataQueryTest_F\" (\"MyDate\") VALUES ('1988-03-04 06:30')");
238
		$query = new DataQuery('DataQueryTest_F');
239
		$query->where(DB::get_conn()->comparisonClause('"MyDate"', '1988-03-04%'));
240
		$this->assertGreaterThan(0, $query->count(), "Couldn't find MyDate");
241
		$this->resetDBSchema(true);
242
	}
243
244 View Code Duplication
	public function testComparisonClauseDateStartsWith() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
245
		DB::query("INSERT INTO \"DataQueryTest_F\" (\"MyDate\") VALUES ('1988-03-04 06:30')");
246
		$query = new DataQuery('DataQueryTest_F');
247
		$query->where(DB::get_conn()->comparisonClause('"MyDate"', '1988%'));
248
		$this->assertGreaterThan(0, $query->count(), "Couldn't find MyDate");
249
		$this->resetDBSchema(true);
250
	}
251
252 View Code Duplication
	public function testComparisonClauseDateStartsPartial() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
253
		DB::query("INSERT INTO \"DataQueryTest_F\" (\"MyDate\") VALUES ('1988-03-04 06:30')");
254
		$query = new DataQuery('DataQueryTest_F');
255
		$query->where(DB::get_conn()->comparisonClause('"MyDate"', '%03-04%'));
256
		$this->assertGreaterThan(0, $query->count(), "Couldn't find MyDate");
257
		$this->resetDBSchema(true);
258
	}
259
260 View Code Duplication
	public function testComparisonClauseTextCaseInsensitive() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
261
		DB::query("INSERT INTO \"DataQueryTest_F\" (\"MyString\") VALUES ('HelloWorld')");
262
		$query = new DataQuery('DataQueryTest_F');
263
		$query->where(DB::get_conn()->comparisonClause('"MyString"', 'helloworld'));
264
		$this->assertGreaterThan(0, $query->count(), "Couldn't find MyString");
265
		$this->resetDBSchema(true);
266
	}
267
268
	public function testComparisonClauseTextCaseSensitive() {
269
		DB::query("INSERT INTO \"DataQueryTest_F\" (\"MyString\") VALUES ('HelloWorld')");
270
		$query = new DataQuery('DataQueryTest_F');
271
		$query->where(DB::get_conn()->comparisonClause('"MyString"', 'HelloWorld', false, false, true));
272
		$this->assertGreaterThan(0, $query->count(), "Couldn't find MyString");
273
274
		$query2 = new DataQuery('DataQueryTest_F');
275
		$query2->where(DB::get_conn()->comparisonClause('"MyString"', 'helloworld', false, false, true));
276
		$this->assertEquals(0, $query2->count(), "Found mystring. Shouldn't be able too.");
277
		$this->resetDBSchema(true);
278
	}
279
280
}
281
282
283
class DataQueryTest_A extends DataObject implements TestOnly {
284
285
	private static $db = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
286
		'Name' => 'Varchar',
287
	);
288
289
	private static $has_one = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
290
		'TestC' => 'DataQueryTest_C',
291
	);
292
}
293
294
class DataQueryTest_B extends DataObject implements TestOnly {
295
296
	private static $db = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
297
		'Title' => 'Varchar',
298
	);
299
300
	private static $has_one = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
301
		'TestC' => 'DataQueryTest_C',
302
		'TestCTwo' => 'DataQueryTest_C',
303
	);
304
}
305
306
class DataQueryTest_C extends DataObject implements TestOnly {
307
308
	private static $db = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
309
		'Title' => 'Varchar'
310
	);
311
312
	private static $has_one = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
313
		'TestA' => 'DataQueryTest_A',
314
		'TestB' => 'DataQueryTest_B',
315
	);
316
317
	private static $has_many = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
318
		'TestAs' => 'DataQueryTest_A',
319
		'TestBs' => 'DataQueryTest_B.TestC',
320
		'TestBsTwo' => 'DataQueryTest_B.TestCTwo',
321
	);
322
323
	private static $many_many = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
324
		'ManyTestAs' => 'DataQueryTest_A',
325
		'ManyTestBs' => 'DataQueryTest_B',
326
	);
327
}
328
329
class DataQueryTest_D extends DataObject implements TestOnly {
330
331
	private static $has_one = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
332
		'Relation' => 'DataQueryTest_B',
333
	);
334
}
335
336
class DataQueryTest_E extends DataQueryTest_C implements TestOnly {
337
338
	private static $db = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
339
		'SortOrder' => 'Int'
340
	);
341
342
	private static $many_many = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
343
		'ManyTestGs' => 'DataQueryTest_G',
344
	);
345
346
	private static $default_sort = '"DataQueryTest_E"."SortOrder" ASC';
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
347
}
348
349
class DataQueryTest_F extends DataObject implements TestOnly {
350
351
	private static $db = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
352
		'SortOrder' => 'Int',
353
		'MyDate' => 'SS_Datetime',
354
		'MyString' => 'Text'
355
	);
356
}
357
358
class DataQueryTest_G extends DataQueryTest_C implements TestOnly {
359
360
	private static $belongs_many_many = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
361
		'ManyTestEs' => 'DataQueryTest_E',
362
	);
363
364
}
365