the street portion of the location * 'supplemental' => additional street portion of the location * 'province' => the province, state, or territory * 'country' => lower-cased two-letter ISO code (REQUIRED) * 'postal_code' => the international postal code for this location (REQUIRED) * * @return * An associative array where * 'lat' => approximate latitude of the center of the postal code's area * 'lon' => approximate longitude of the center of the postal code's area * */ function location_latlon_rough_zz($location = array()) { if (!isset($location['postal_code'])) { return NULL; } $results = _location_latlon_zz_geonames($location); if($results['lat'] AND $results['lon']) { return array('lat' => $results['lat'], 'lon' => $results['lon']); } else { return NULL; } } /** * Returns a lat/lon pair of the approximate center of the given postal code in the given country * * @param $location * An associative array $location where only postal code and country are necessary, but can have the keys: * 'street' => the street portion of the location * 'supplemental' => additional street portion of the location * 'province' => the province, state, or territory * 'country' => lower-cased two-letter ISO code (REQUIRED) * 'postal_code' => the international postal code for this location (REQUIRED) * * @return * An associative array where * 'lat' => approximate latitude of the center of the postal code's area * 'lon' => approximate longitude of the center of the postal code's area * */ function location_get_postalcode_data_zz($location = array()) { $dash_index = strpos($location['postal_code'], '-'); // First we strip slash off if we're dealing with a 9-digit US zipcode if (!($dash_index === FALSE)) { $location['postal_code'] = substr($location['postal_code'], 0, $dash_index); } //Lets use Geonames... $results = _location_latlon_zz_geonames($location); if($results['lat'] AND $results['lon']) { return array('lat' => $results['lat'], 'lon' => $results['lon']); } else { return NULL; } } /** * Parameters: * An associative array $location where * 'street' => the street portion of the location * 'supplemental' => additional street portion of the location * 'province' => the province, state, or territory * 'country' => lower-cased two-letter ISO code (REQUIRED) * 'postal_code' => the international postal code for this location (REQUIRED) * * */ function location_latlon_exact_zz($location = array()) { return NULL; // By uncommenting the line of code below, you legally acknowledge that you understand that you can only // do so under the terms of the Non-Commercial Share-alike license described at http://creativecommons.org/licenses/by-nc-sa/2.0/ //return _location_latlon_exact_uk_geocoder($location); } /** * Calls up the Geonames web-service to retrieve a lat/lon pair for many different countries... * http://www.geonames.org/export/free-geocoding.html * * @param $location * An associative array that represents an location where * 'street' => is the street location * 'supplemental' => any supplemental portion to the street location * 'city' => city name * 'province' => state, province, or territorial abbreviation * 'postal_code' => postal code * 'country' => lower-cased two-letter ISO code (REQUIRED) * * * @return * An associative array where * 'lat' => Is a float value in latitude * 'lon' => Is a float value in longitude * If the location supplied does not provide enough information, NULL is returned. * "Enough information" means that at least a country has been specified, along with a postcode, or a city name */ function _location_latlon_zz_geonames($location = array()) { $location_string = ''; if(!isset($location['country'])) { return NULL; //We can't do anything without a country code, so return null } $location_string = 'country='.$location['country'] . '&postalcode=' . $location['postal_code'] . '&placename=' . $location['city'] . '&maxRows=1&style=short'; $result = drupal_http_request('http://ws.geonames.org/postalCodeSearch?' . $location_string); //TODO: Need to include ERROR HANDLING for when the http_request doens't work... $data = $result->data; $xml_parser = drupal_xml_parser_create($data); xml_parse_into_struct($xml_parser, $data, $vals, $index); xml_parser_free($xml_parser); $params = array(); $level = array(); foreach ($vals as $xml_elem) { if ($xml_elem['type'] == 'open') { if (array_key_exists('attributes',$xml_elem)) { list($level[$xml_elem['level']],$extra) = array_values($xml_elem['attributes']); } else { $level[$xml_elem['level']] = $xml_elem['tag'].$id++; //Note modification to handle Geonames structure (number each code block...) } } if ($xml_elem['type'] == 'complete') { $start_level = 1; $php_stmt = '$params'; while($start_level < $xml_elem['level']) { $php_stmt .= '[$level['.$start_level.']]'; $start_level++; } $php_stmt .= '[$xml_elem[\'tag\']] = $xml_elem[\'value\'];'; eval($php_stmt); } } /*Note: Geonames doesn't have province data for the UK... but for other countries we might now like to perform an extra look up from the Lat, Long to find out the province... See: http://www.geonames.org/export/index.html#countrysubdiv */ IF($params['GEONAMES']['CODE1']['LAT']) { return array('lat' => floatval($params['GEONAMES']['CODE1']['LAT']), 'lon' => floatval($params['GEONAMES']['CODE1']['LNG']), 'postal_code' => $params['GEONAMES']['CODE1']['POSTALCODE'], 'city' => $params['GEONAMES']['CODE1']['NAME']); } else { return NULL; } } ?>