diff options
-rw-r--r-- | engine/lib/location.php | 88 | ||||
-rw-r--r-- | engine/tests/api/entity_getter_functions.php | 63 |
2 files changed, 149 insertions, 2 deletions
diff --git a/engine/lib/location.php b/engine/lib/location.php index 039bb5ee0..517650e5c 100644 --- a/engine/lib/location.php +++ b/engine/lib/location.php @@ -212,6 +212,91 @@ $order_by = "", $limit = 10, $offset = 0, $count = false, $site_guid = 0, $conta } /** + * Return entities within a given geographic area. + * + * Also accepts all options available to elgg_get_entities(). + * + * @see elgg_get_entities + * + * @param array $options Array in format: + * + * latitude => FLOAT Latitude of the location + * + * longitude => FLOAT Longitude of the location + * + * distance => FLOAT/ARR ( + * latitude => float, + * longitude => float, + * ) + * The distance in degrees that determines the search box. A + * single float will result in a square in degrees. + * @warning The Earth is round. + * + * @see ElggEntity::setLatLong() + * + * @return array + * @since 1.8.0 + */ +function elgg_get_entities_from_location(array $options = array()) { + + global $CONFIG; + + if (!isset($options['latitude']) || !isset($options['longitude']) || + !isset($options['distance'])) { + return false; + } + + if (!is_array($options['distance'])) { + $lat_distance = (float)$options['distance']; + $long_distance = (float)$options['distance']; + } else { + $lat_distance = (float)$options['distance']['latitude']; + $long_distance = (float)$options['distance']['longitude']; + } + + $lat = (float)$options['latitude']; + $long = (float)$options['longitude']; + $lat_min = $lat - $lat_distance; + $lat_max = $lat + $lat_distance; + $long_min = $long - $long_distance; + $long_max = $long + $long_distance; + + $where = array(); + $wheres[] = "lat_name.string='geo:lat'"; + $wheres[] = "lat_value.string >= $lat_min"; + $wheres[] = "lat_value.string <= $lat_max"; + $wheres[] = "lon_name.string='geo:long'"; + $wheres[] = "lon_value.string >= $long_min"; + $wheres[] = "lon_value.string <= $long_max"; + + $joins = array(); + $joins[] = "JOIN {$CONFIG->dbprefix}metadata lat on e.guid=lat.entity_guid"; + $joins[] = "JOIN {$CONFIG->dbprefix}metastrings lat_name on lat.name_id=lat_name.id"; + $joins[] = "JOIN {$CONFIG->dbprefix}metastrings lat_value on lat.value_id=lat_value.id"; + $joins[] = "JOIN {$CONFIG->dbprefix}metadata lon on e.guid=lon.entity_guid"; + $joins[] = "JOIN {$CONFIG->dbprefix}metastrings lon_name on lon.name_id=lon_name.id"; + $joins[] = "JOIN {$CONFIG->dbprefix}metastrings lon_value on lon.value_id=lon_value.id"; + + // merge wheres to pass to get_entities() + if (isset($options['wheres']) && !is_array($options['wheres'])) { + $options['wheres'] = array($options['wheres']); + } elseif (!isset($options['wheres'])) { + $options['wheres'] = array(); + } + $options['wheres'] = array_merge($options['wheres'], $wheres); + + // merge joins to pass to get_entities() + if (isset($options['joins']) && !is_array($options['joins'])) { + $options['joins'] = array($options['joins']); + } elseif (!isset($options['joins'])) { + $options['joins'] = array(); + } + $options['joins'] = array_merge($options['joins'], $joins); + + return elgg_get_entities_from_relationship($options); +} + +/** * List entities in a given location * * @param string $location Location @@ -262,9 +347,8 @@ $limit = 10, $fullview = true, $listtypetoggle = false, $navigation = true) { } // Some distances in degrees (approximate) +// @todo huh? see warning on elgg_get_entities_from_location() define("MILE", 0.01515); define("KILOMETER", 0.00932); // @todo get objects within x miles by entities, metadata and relationship - -// @todo List
\ No newline at end of file diff --git a/engine/tests/api/entity_getter_functions.php b/engine/tests/api/entity_getter_functions.php index 07fb1fd8c..7a2943c0e 100644 --- a/engine/tests/api/entity_getter_functions.php +++ b/engine/tests/api/entity_getter_functions.php @@ -2446,4 +2446,67 @@ class ElggCoreEntityGetterFunctionsTest extends ElggCoreUnitTest { } } } + + /** + * Location + */ + public function testElggApiGettersEntitiesFromLocation() { + + // a test location that is out of this world + $lat = 500; + $long = 500; + $delta = 5; + + $subtypes = $this->getRandomValidSubtypes(array('object'), 1); + $subtype = $subtypes[0]; + $guids = array(); + + // our objects + $valid = new ElggObject(); + $valid->subtype = $subtype; + $valid->save(); + $guids[] = $valid->getGUID(); + $valid->setLatLong($lat, $long); + + $valid2 = new ElggObject(); + $valid2->subtype = $subtype; + $valid2->save(); + $guids[] = $valid2->getGUID(); + $valid2->setLatLong($lat + 2 * $delta, $long + 2 * $delta); + + // limit to first object + $options = array( + 'latitude' => $lat, + 'longitude' => $long, + 'distance' => $delta + ); + + //global $CONFIG; + //$CONFIG->debug = 'NOTICE'; + $entities = elgg_get_entities_from_location($options); + //unset($CONFIG->debug); + + $this->assertEqual(1, count($entities)); + $this->assertEqual($entities[0]->getGUID(), $valid->getGUID()); + + // get both objects + $options = array( + 'latitude' => $lat, + 'longitude' => $long, + 'distance' => array('latitude' => 2 * $delta, 'longitude' => 2 * $delta) + ); + + $entities = elgg_get_entities_from_location($options); + + $this->assertEqual(2, count($entities)); + foreach ($entities as $entity) { + $this->assertTrue(in_array($entity->getGUID(), $guids)); + } + + foreach ($guids as $guid) { + if ($e = get_entity($guid)) { + $e->delete(); + } + } + } } |