Skip to content

Commit 7204282

Browse files
authored
And / Nor Query (#419)
1 parent 3fc6766 commit 7204282

File tree

2 files changed

+168
-6
lines changed

2 files changed

+168
-6
lines changed

src/Parse/ParseQuery.php

+96-6
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,62 @@ public function doesNotMatchKeyInQuery($key, $queryKey, $query)
10561056
* @return ParseQuery The query that is the OR of the passed in queries.
10571057
*/
10581058
public static function orQueries($queryObjects)
1059+
{
1060+
$className = self::_matchClassName($queryObjects);
1061+
$query = new self($className);
1062+
$query->_or($queryObjects);
1063+
1064+
return $query;
1065+
}
1066+
1067+
/**
1068+
* Constructs a ParseQuery object that is the NOR of the passed in queries objects.
1069+
* All queries must have same class name.
1070+
*
1071+
* @param array $queryObjects Array of ParseQuery objects to NOR.
1072+
*
1073+
* @throws \Exception If all queries don't have same class.
1074+
*
1075+
* @return ParseQuery The query that is the NOR of the passed in queries.
1076+
*/
1077+
public static function norQueries($queryObjects)
1078+
{
1079+
$className = self::_matchClassName($queryObjects);
1080+
$query = new self($className);
1081+
$query->_nor($queryObjects);
1082+
1083+
return $query;
1084+
}
1085+
1086+
/**
1087+
* Constructs a ParseQuery object that is the AND of the passed in queries objects.
1088+
* All queries must have same class name.
1089+
*
1090+
* @param array $queryObjects Array of ParseQuery objects to AND.
1091+
*
1092+
* @throws \Exception If all queries don't have same class.
1093+
*
1094+
* @return ParseQuery The query that is the AND of the passed in queries.
1095+
*/
1096+
public static function andQueries($queryObjects)
1097+
{
1098+
$className = self::_matchClassName($queryObjects);
1099+
$query = new self($className);
1100+
$query->_and($queryObjects);
1101+
1102+
return $query;
1103+
}
1104+
1105+
/**
1106+
* All queries must have same class name.
1107+
*
1108+
* @param array $queryObjects Array of ParseQuery objects.
1109+
*
1110+
* @throws \Exception If all queries don't have same class.
1111+
*
1112+
* @return string class name.
1113+
*/
1114+
private static function _matchClassname($queryObjects)
10591115
{
10601116
$className = null;
10611117
$length = count($queryObjects);
@@ -1067,10 +1123,7 @@ public static function orQueries($queryObjects)
10671123
throw new Exception('All queries must be for the same class', 103);
10681124
}
10691125
}
1070-
$query = new self($className);
1071-
$query->_or($queryObjects);
1072-
1073-
return $query;
1126+
return $className;
10741127
}
10751128

10761129
/**
@@ -1082,10 +1135,47 @@ public static function orQueries($queryObjects)
10821135
*/
10831136
private function _or($queries)
10841137
{
1085-
$this->where['$or'] = [];
1138+
return $this->_mergeQueries('$or', $queries);
1139+
}
1140+
1141+
/**
1142+
* Add constraint that at none of the passed in queries matches.
1143+
*
1144+
* @param array $queries The list of queries to NOR.
1145+
*
1146+
* @return ParseQuery Returns the query, so you can chain this call.
1147+
*/
1148+
private function _nor($queries)
1149+
{
1150+
return $this->_mergeQueries('$nor', $queries);
1151+
}
1152+
1153+
/**
1154+
* Add constraint that at all of the passed in queries matches.
1155+
*
1156+
* @param array $queries The list of queries to OR.
1157+
*
1158+
* @return ParseQuery Returns the query, so you can chain this call.
1159+
*/
1160+
private function _and($queries)
1161+
{
1162+
return $this->_mergeQueries('$and', $queries);
1163+
}
1164+
1165+
/**
1166+
* Combines queries for NOR, AND, OR queries.
1167+
*
1168+
* @param string $key The condition $and, $or, $nor.
1169+
* @param array $queries The list of queries to combine.
1170+
*
1171+
* @return ParseQuery Returns the query, so you can chain this call.
1172+
*/
1173+
private function _mergeQueries($key, $queries)
1174+
{
1175+
$this->where[$key] = [];
10861176
$length = count($queries);
10871177
for ($i = 0; $i < $length; $i++) {
1088-
$this->where['$or'][] = $queries[$i]->where;
1178+
$this->where[$key][] = $queries[$i]->where;
10891179
}
10901180

10911181
return $this;

tests/Parse/ParseQueryTest.php

+72
Original file line numberDiff line numberDiff line change
@@ -1053,6 +1053,54 @@ public function testOrQueries()
10531053
}
10541054
}
10551055

1056+
public function testNorQueries()
1057+
{
1058+
$this->provideTestObjects(10);
1059+
$subQuery1 = new ParseQuery('TestObject');
1060+
$subQuery1->lessThan('foo', 'bar3');
1061+
$subQuery2 = new ParseQuery('TestObject');
1062+
$subQuery2->greaterThan('foo', 'bar5');
1063+
1064+
$mainQuery = ParseQuery::norQueries([$subQuery1, $subQuery2]);
1065+
$results = $mainQuery->find();
1066+
$length = count($results);
1067+
$this->assertEquals(
1068+
3,
1069+
$length,
1070+
'Did not return correct number of objects.'
1071+
);
1072+
for ($i = 0; $i < $length; ++$i) {
1073+
$this->assertTrue(
1074+
$results[$i]->get('foo') >= 'bar3' ||
1075+
$results[$i]->get('foo') <= 'bar5',
1076+
'Did not return the correct object.'
1077+
);
1078+
}
1079+
}
1080+
1081+
public function testAndQueries()
1082+
{
1083+
Helper::clearClass('ChildObject');
1084+
Helper::clearClass('ParentObject');
1085+
$this->provideTestObjectsForQuery(10);
1086+
$subQuery = new ParseQuery('ChildObject');
1087+
$subQuery->equalTo('x', 4);
1088+
$q1 = new ParseQuery('ParentObject');
1089+
$q1->matchesQuery('child', $subQuery);
1090+
$q2 = new ParseQuery('ParentObject');
1091+
$q2->equalTo('x', 14);
1092+
1093+
$mainQuery = ParseQuery::andQueries([$q1, $q2]);
1094+
$results = $mainQuery->find();
1095+
$length = count($results);
1096+
$this->assertEquals(
1097+
1,
1098+
$length,
1099+
'Did not return correct number of objects.'
1100+
);
1101+
$this->assertTrue($results[0]->get('x') == 14);
1102+
}
1103+
10561104
public function testComplexQueries()
10571105
{
10581106
Helper::clearClass('Child');
@@ -2272,6 +2320,30 @@ public function testOrQueriesVaryingClasses()
22722320
]);
22732321
}
22742322

2323+
public function testNorQueriesVaryingClasses()
2324+
{
2325+
$this->setExpectedException(
2326+
'\Exception',
2327+
'All queries must be for the same class'
2328+
);
2329+
ParseQuery::norQueries([
2330+
new ParseQuery('Class1'),
2331+
new ParseQuery('Class2')
2332+
]);
2333+
}
2334+
2335+
public function testAndQueriesVaryingClasses()
2336+
{
2337+
$this->setExpectedException(
2338+
'\Exception',
2339+
'All queries must be for the same class'
2340+
);
2341+
ParseQuery::andQueries([
2342+
new ParseQuery('Class1'),
2343+
new ParseQuery('Class2')
2344+
]);
2345+
}
2346+
22752347
/**
22762348
* @group query-set-conditions
22772349
*/

0 commit comments

Comments
 (0)