Skip to content

Commit 20dd7a5

Browse files
dplewisBenjamin Wilson Friedman
authored and
Benjamin Wilson Friedman
committed
Add Within Polygon to Query (#320)
* Add Within Polygon to Query * lint * added test for open and closed paths * remove helper
1 parent 6da58c7 commit 20dd7a5

File tree

3 files changed

+148
-9
lines changed

3 files changed

+148
-9
lines changed

src/Parse/ParseQuery.php

+23
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,29 @@ public function withinGeoBox($key, $southwest, $northeast)
622622
return $this;
623623
}
624624

625+
/**
626+
* Add a constraint to the query that requires a particular key's
627+
* coordinates be contained within and on the bounds of a given polygon
628+
* Supports closed and open (last point is connected to first) paths
629+
*
630+
* Polygon must have at least 3 points
631+
*
632+
* @param string $key The key of the ParseGeoPoint
633+
* @param array $points Array of ParseGeoPoint
634+
*
635+
* @return ParseQuery Returns this query, so you can chain this call.
636+
*/
637+
public function withinPolygon($key, $points)
638+
{
639+
$this->addCondition(
640+
$key,
641+
'$geoWithin',
642+
['$polygon' => $points]
643+
);
644+
645+
return $this;
646+
}
647+
625648
/**
626649
* Add a constraint to the query that requires a particular key's value to
627650
* be contained in the provided list of values.

tests/Parse/Helper.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,4 @@ public static function setUpWithoutCURLExceptions()
106106
);
107107

108108
}
109-
}
109+
}

tests/Parse/ParseGeoPointTest.php

+124-8
Original file line numberDiff line numberDiff line change
@@ -200,20 +200,136 @@ public function testGeoMaxDistanceWithUnits()
200200
$query->withinMiles('location', $point, 10.0);
201201
$results = $query->find();
202202
$this->assertEquals(0, count($results));
203-
204203
}
205204

206-
public function testBadLatitude() {
207-
$this->setExpectedException('\Parse\ParseException',
208-
'Latitude must be within range [-90.0, 90.0]');
205+
public function testBadLatitude()
206+
{
207+
$this->setExpectedException(
208+
'\Parse\ParseException',
209+
'Latitude must be within range [-90.0, 90.0]'
210+
);
209211
new ParseGeoPoint(-180, 32);
210-
211212
}
212213

213-
public function testBadLongitude() {
214-
$this->setExpectedException('\Parse\ParseException',
215-
'Longitude must be within range [-180.0, 180.0]');
214+
public function testBadLongitude()
215+
{
216+
$this->setExpectedException(
217+
'\Parse\ParseException',
218+
'Longitude must be within range [-180.0, 180.0]'
219+
);
216220
new ParseGeoPoint(32, -360);
221+
}
222+
223+
public function testWithinPolygonOpenPath()
224+
{
225+
$inbound = ParseObject::create('TestObject');
226+
$onbound = ParseObject::create('TestObject');
227+
$outbound = ParseObject::create('TestObject');
228+
229+
$inbound->set('location', new ParseGeoPoint(1, 1));
230+
$onbound->set('location', new ParseGeoPoint(10, 10));
231+
$outbound->set('location', new ParseGeoPoint(20, 20));
232+
233+
ParseObject::saveAll([$inbound, $onbound, $outbound]);
234+
235+
$points = [
236+
new ParseGeoPoint(0, 0),
237+
new ParseGeoPoint(0, 10),
238+
new ParseGeoPoint(10, 10),
239+
new ParseGeoPoint(10, 0)
240+
];
241+
$query = new ParseQuery('TestObject');
242+
$query->withinPolygon('location', $points);
243+
$results = $query->find();
244+
$this->assertEquals(2, count($results));
245+
}
217246

247+
public function testWithinPolygonClosedPath()
248+
{
249+
$inbound = ParseObject::create('TestObject');
250+
$onbound = ParseObject::create('TestObject');
251+
$outbound = ParseObject::create('TestObject');
252+
253+
$inbound->set('location', new ParseGeoPoint(1, 1));
254+
$onbound->set('location', new ParseGeoPoint(10, 10));
255+
$outbound->set('location', new ParseGeoPoint(20, 20));
256+
257+
ParseObject::saveAll([$inbound, $onbound, $outbound]);
258+
259+
$points = [
260+
new ParseGeoPoint(0, 0),
261+
new ParseGeoPoint(0, 10),
262+
new ParseGeoPoint(10, 10),
263+
new ParseGeoPoint(10, 0),
264+
new ParseGeoPoint(0, 0)
265+
];
266+
$query = new ParseQuery('TestObject');
267+
$query->withinPolygon('location', $points);
268+
$results = $query->find();
269+
$this->assertEquals(2, count($results));
270+
}
271+
272+
public function testWithinPolygonEmpty()
273+
{
274+
$obj = ParseObject::create('TestObject');
275+
$obj->set('location', new ParseGeoPoint(1.5, 1.5));
276+
$obj->save();
277+
278+
$this->setExpectedException(
279+
'\Parse\ParseException',
280+
'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'
281+
);
282+
$query = new ParseQuery('TestObject');
283+
$query->withinPolygon('location', []);
284+
$query->find();
285+
}
286+
287+
public function testWithinPolygonTwoGeoPoints()
288+
{
289+
$obj = ParseObject::create('TestObject');
290+
$obj->set('location', new ParseGeoPoint(1.5, 1.5));
291+
$obj->save();
292+
293+
$this->setExpectedException(
294+
'\Parse\ParseException',
295+
'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'
296+
);
297+
$points = [
298+
new ParseGeoPoint(0, 0),
299+
new ParseGeoPoint(10, 10)
300+
];
301+
$query = new ParseQuery('TestObject');
302+
$query->withinPolygon('location', $points);
303+
$query->find();
304+
}
305+
306+
public function testWithinPolygonNonArray()
307+
{
308+
$obj = ParseObject::create('TestObject');
309+
$obj->set('location', new ParseGeoPoint(1.5, 1.5));
310+
$obj->save();
311+
312+
$this->setExpectedException(
313+
'\Parse\ParseException',
314+
'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'
315+
);
316+
$query = new ParseQuery('TestObject');
317+
$query->withinPolygon('location', 1234);
318+
$query->find();
319+
}
320+
321+
public function testWithinPolygonInvalidArray()
322+
{
323+
$obj = ParseObject::create('TestObject');
324+
$obj->set('location', new ParseGeoPoint(1.5, 1.5));
325+
$obj->save();
326+
327+
$this->setExpectedException(
328+
'\Parse\ParseException',
329+
'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'
330+
);
331+
$query = new ParseQuery('TestObject');
332+
$query->withinPolygon('location', [$obj]);
333+
$query->find();
218334
}
219335
}

0 commit comments

Comments
 (0)