Skip to content

Commit

Permalink
Add Within Polygon to Query (#320)
Browse files Browse the repository at this point in the history
* Add Within Polygon to Query

* lint

* added test for open and closed paths

* remove helper
  • Loading branch information
dplewis authored and Benjamin Wilson Friedman committed Jun 21, 2017
1 parent 6da58c7 commit 20dd7a5
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 9 deletions.
23 changes: 23 additions & 0 deletions src/Parse/ParseQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,29 @@ public function withinGeoBox($key, $southwest, $northeast)
return $this;
}

/**
* Add a constraint to the query that requires a particular key's
* coordinates be contained within and on the bounds of a given polygon
* Supports closed and open (last point is connected to first) paths
*
* Polygon must have at least 3 points
*
* @param string $key The key of the ParseGeoPoint
* @param array $points Array of ParseGeoPoint
*
* @return ParseQuery Returns this query, so you can chain this call.
*/
public function withinPolygon($key, $points)
{
$this->addCondition(
$key,
'$geoWithin',
['$polygon' => $points]
);

return $this;
}

/**
* Add a constraint to the query that requires a particular key's value to
* be contained in the provided list of values.
Expand Down
2 changes: 1 addition & 1 deletion tests/Parse/Helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,4 @@ public static function setUpWithoutCURLExceptions()
);

}
}
}
132 changes: 124 additions & 8 deletions tests/Parse/ParseGeoPointTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -200,20 +200,136 @@ public function testGeoMaxDistanceWithUnits()
$query->withinMiles('location', $point, 10.0);
$results = $query->find();
$this->assertEquals(0, count($results));

}

public function testBadLatitude() {
$this->setExpectedException('\Parse\ParseException',
'Latitude must be within range [-90.0, 90.0]');
public function testBadLatitude()
{
$this->setExpectedException(
'\Parse\ParseException',
'Latitude must be within range [-90.0, 90.0]'
);
new ParseGeoPoint(-180, 32);

}

public function testBadLongitude() {
$this->setExpectedException('\Parse\ParseException',
'Longitude must be within range [-180.0, 180.0]');
public function testBadLongitude()
{
$this->setExpectedException(
'\Parse\ParseException',
'Longitude must be within range [-180.0, 180.0]'
);
new ParseGeoPoint(32, -360);
}

public function testWithinPolygonOpenPath()
{
$inbound = ParseObject::create('TestObject');
$onbound = ParseObject::create('TestObject');
$outbound = ParseObject::create('TestObject');

$inbound->set('location', new ParseGeoPoint(1, 1));
$onbound->set('location', new ParseGeoPoint(10, 10));
$outbound->set('location', new ParseGeoPoint(20, 20));

ParseObject::saveAll([$inbound, $onbound, $outbound]);

$points = [
new ParseGeoPoint(0, 0),
new ParseGeoPoint(0, 10),
new ParseGeoPoint(10, 10),
new ParseGeoPoint(10, 0)
];
$query = new ParseQuery('TestObject');
$query->withinPolygon('location', $points);
$results = $query->find();
$this->assertEquals(2, count($results));
}

public function testWithinPolygonClosedPath()
{
$inbound = ParseObject::create('TestObject');
$onbound = ParseObject::create('TestObject');
$outbound = ParseObject::create('TestObject');

$inbound->set('location', new ParseGeoPoint(1, 1));
$onbound->set('location', new ParseGeoPoint(10, 10));
$outbound->set('location', new ParseGeoPoint(20, 20));

ParseObject::saveAll([$inbound, $onbound, $outbound]);

$points = [
new ParseGeoPoint(0, 0),
new ParseGeoPoint(0, 10),
new ParseGeoPoint(10, 10),
new ParseGeoPoint(10, 0),
new ParseGeoPoint(0, 0)
];
$query = new ParseQuery('TestObject');
$query->withinPolygon('location', $points);
$results = $query->find();
$this->assertEquals(2, count($results));
}

public function testWithinPolygonEmpty()
{
$obj = ParseObject::create('TestObject');
$obj->set('location', new ParseGeoPoint(1.5, 1.5));
$obj->save();

$this->setExpectedException(
'\Parse\ParseException',
'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'
);
$query = new ParseQuery('TestObject');
$query->withinPolygon('location', []);
$query->find();
}

public function testWithinPolygonTwoGeoPoints()
{
$obj = ParseObject::create('TestObject');
$obj->set('location', new ParseGeoPoint(1.5, 1.5));
$obj->save();

$this->setExpectedException(
'\Parse\ParseException',
'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'
);
$points = [
new ParseGeoPoint(0, 0),
new ParseGeoPoint(10, 10)
];
$query = new ParseQuery('TestObject');
$query->withinPolygon('location', $points);
$query->find();
}

public function testWithinPolygonNonArray()
{
$obj = ParseObject::create('TestObject');
$obj->set('location', new ParseGeoPoint(1.5, 1.5));
$obj->save();

$this->setExpectedException(
'\Parse\ParseException',
'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'
);
$query = new ParseQuery('TestObject');
$query->withinPolygon('location', 1234);
$query->find();
}

public function testWithinPolygonInvalidArray()
{
$obj = ParseObject::create('TestObject');
$obj->set('location', new ParseGeoPoint(1.5, 1.5));
$obj->save();

$this->setExpectedException(
'\Parse\ParseException',
'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'
);
$query = new ParseQuery('TestObject');
$query->withinPolygon('location', [$obj]);
$query->find();
}
}

0 comments on commit 20dd7a5

Please sign in to comment.