diff options
Diffstat (limited to 'engine/lib/location.php')
| -rw-r--r-- | engine/lib/location.php | 157 | 
1 files changed, 157 insertions, 0 deletions
| diff --git a/engine/lib/location.php b/engine/lib/location.php new file mode 100644 index 000000000..1534c7d7b --- /dev/null +++ b/engine/lib/location.php @@ -0,0 +1,157 @@ +<?php +/** + * Elgg geo-location tagging library. + * + * @package Elgg.Core + * @subpackage Location + */ + +/** + * Encode a location into a latitude and longitude, caching the result. + * + * Works by triggering the 'geocode' 'location' plugin + * hook, and requires a geocoding plugin to be installed. + * + * @param string $location The location, e.g. "London", or "24 Foobar Street, Gotham City" + * @return string|false + */ +function elgg_geocode_location($location) { +	global $CONFIG; + +	if (is_array($location)) { +		return false; +	} + +	$location = sanitise_string($location); + +	// Look for cached version +	$query = "SELECT * from {$CONFIG->dbprefix}geocode_cache WHERE location='$location'"; +	$cached_location = get_data_row($query); + +	if ($cached_location) { +		return array('lat' => $cached_location->lat, 'long' => $cached_location->long); +	} + +	// Trigger geocode event if not cached +	$return = false; +	$return = elgg_trigger_plugin_hook('geocode', 'location', array('location' => $location), $return); + +	// If returned, cache and return value +	if (($return) && (is_array($return))) { +		$lat = (float)$return['lat']; +		$long = (float)$return['long']; + +		// Put into cache at the end of the page since we don't really care that much +		$query = "INSERT DELAYED INTO {$CONFIG->dbprefix}geocode_cache " +			. " (location, lat, `long`) VALUES ('$location', '{$lat}', '{$long}')" +			. " ON DUPLICATE KEY UPDATE lat='{$lat}', `long`='{$long}'"; +		execute_delayed_write_query($query); +	} + +	return $return; +} + +/** + * 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 mixed If count, int. If not count, array. false on errors. + * @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; + +	$wheres = 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); +} + +/** + * Returns a viewable list of entities from location + * + * @param array $options Options array + * + * @see elgg_list_entities() + * @see elgg_get_entities_from_location() + * + * @return string The viewable list of entities + * @since 1.8.0 + */ +function elgg_list_entities_from_location(array $options = array()) { +	return elgg_list_entities($options, 'elgg_get_entities_from_location'); +} + +// Some distances in degrees (approximate) +// @todo huh? see warning on elgg_get_entities_from_location() +define("MILE", 0.01515); +define("KILOMETER", 0.00932); | 
