Skip to content

And / Nor Query #419

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 96 additions & 6 deletions src/Parse/ParseQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,62 @@ public function doesNotMatchKeyInQuery($key, $queryKey, $query)
* @return ParseQuery The query that is the OR of the passed in queries.
*/
public static function orQueries($queryObjects)
{
$className = self::_matchClassName($queryObjects);
$query = new self($className);
$query->_or($queryObjects);

return $query;
}

/**
* Constructs a ParseQuery object that is the NOR of the passed in queries objects.
* All queries must have same class name.
*
* @param array $queryObjects Array of ParseQuery objects to NOR.
*
* @throws \Exception If all queries don't have same class.
*
* @return ParseQuery The query that is the NOR of the passed in queries.
*/
public static function norQueries($queryObjects)
{
$className = self::_matchClassName($queryObjects);
$query = new self($className);
$query->_nor($queryObjects);

return $query;
}

/**
* Constructs a ParseQuery object that is the AND of the passed in queries objects.
* All queries must have same class name.
*
* @param array $queryObjects Array of ParseQuery objects to AND.
*
* @throws \Exception If all queries don't have same class.
*
* @return ParseQuery The query that is the AND of the passed in queries.
*/
public static function andQueries($queryObjects)
{
$className = self::_matchClassName($queryObjects);
$query = new self($className);
$query->_and($queryObjects);

return $query;
}

/**
* All queries must have same class name.
*
* @param array $queryObjects Array of ParseQuery objects.
*
* @throws \Exception If all queries don't have same class.
*
* @return string class name.
*/
private static function _matchClassname($queryObjects)
{
$className = null;
$length = count($queryObjects);
Expand All @@ -1051,10 +1107,7 @@ public static function orQueries($queryObjects)
throw new Exception('All queries must be for the same class', 103);
}
}
$query = new self($className);
$query->_or($queryObjects);

return $query;
return $className;
}

/**
Expand All @@ -1066,10 +1119,47 @@ public static function orQueries($queryObjects)
*/
private function _or($queries)
{
$this->where['$or'] = [];
return $this->_mergeQueries('$or', $queries);
}

/**
* Add constraint that at none of the passed in queries matches.
*
* @param array $queries The list of queries to NOR.
*
* @return ParseQuery Returns the query, so you can chain this call.
*/
private function _nor($queries)
{
return $this->_mergeQueries('$nor', $queries);
}

/**
* Add constraint that at all of the passed in queries matches.
*
* @param array $queries The list of queries to OR.
*
* @return ParseQuery Returns the query, so you can chain this call.
*/
private function _and($queries)
{
return $this->_mergeQueries('$and', $queries);
}

/**
* Combines queries for NOR, AND, OR queries.
*
* @param string $key The condition $and, $or, $nor.
* @param array $queries The list of queries to combine.
*
* @return ParseQuery Returns the query, so you can chain this call.
*/
private function _mergeQueries($key, $queries)
{
$this->where[$key] = [];
$length = count($queries);
for ($i = 0; $i < $length; $i++) {
$this->where['$or'][] = $queries[$i]->where;
$this->where[$key][] = $queries[$i]->where;
}

return $this;
Expand Down
74 changes: 73 additions & 1 deletion tests/Parse/ParseQueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,54 @@ public function testOrQueries()
}
}

public function testNorQueries()
{
$this->provideTestObjects(10);
$subQuery1 = new ParseQuery('TestObject');
$subQuery1->lessThan('foo', 'bar3');
$subQuery2 = new ParseQuery('TestObject');
$subQuery2->greaterThan('foo', 'bar5');

$mainQuery = ParseQuery::norQueries([$subQuery1, $subQuery2]);
$results = $mainQuery->find();
$length = count($results);
$this->assertEquals(
3,
$length,
'Did not return correct number of objects.'
);
for ($i = 0; $i < $length; ++$i) {
$this->assertTrue(
$results[$i]->get('foo') >= 'bar3' ||
$results[$i]->get('foo') <= 'bar5',
'Did not return the correct object.'
);
}
}

public function testAndQueries()
{
Helper::clearClass('ChildObject');
Helper::clearClass('ParentObject');
$this->provideTestObjectsForQuery(10);
$subQuery = new ParseQuery('ChildObject');
$subQuery->equalTo('x', 4);
$q1 = new ParseQuery('ParentObject');
$q1->matchesQuery('child', $subQuery);
$q2 = new ParseQuery('ParentObject');
$q2->equalTo('x', 14);

$mainQuery = ParseQuery::andQueries([$q1, $q2]);
$results = $mainQuery->find();
$length = count($results);
$this->assertEquals(
1,
$length,
'Did not return correct number of objects.'
);
$this->assertTrue($results[0]->get('x') == 14);
}

public function testComplexQueries()
{
Helper::clearClass('Child');
Expand Down Expand Up @@ -2249,6 +2297,30 @@ public function testOrQueriesVaryingClasses()
]);
}

public function testNorQueriesVaryingClasses()
{
$this->setExpectedException(
'\Exception',
'All queries must be for the same class'
);
ParseQuery::norQueries([
new ParseQuery('Class1'),
new ParseQuery('Class2')
]);
}

public function testAndQueriesVaryingClasses()
{
$this->setExpectedException(
'\Exception',
'All queries must be for the same class'
);
ParseQuery::andQueries([
new ParseQuery('Class1'),
new ParseQuery('Class2')
]);
}

/**
* @group query-set-conditions
*/
Expand Down Expand Up @@ -2338,7 +2410,7 @@ public function testUnknownCondition()
'\Parse\ParseException',
'Unknown condition to set'
);

$query = new ParseQuery('TestObject');
$query->_setConditions([
'unrecognized' => 1
Expand Down