diff -urNp location_old/location.inc location/location.inc --- location_old/location.inc 2007-04-09 11:00:50.000000000 +0100 +++ location/location.inc 2007-04-09 11:06:58.000000000 +0100 @@ -13,6 +13,11 @@ define('LOCATION_PATH', drupal_get_path( include_once LOCATION_PATH.'/earth.inc'; _location_include_configured(); +if(variable_get('location_generic_fallback',0)) { + include_once LOCATION_PATH.'/supported/location.generic.inc'; +} + + /** * Get a deep-link to a mapping service such as Yahoo! Maps or MapPoint given an location. The * call is delegated based on the 'country' value in the $location parameter. @@ -1130,13 +1135,30 @@ function _location_format_search_result_ * 'lon' => A floating point number for the longitude coordinate of the parameter location * 'lat' => A floating point number for the latitude coordinate of the parameter location */ -function location_latlon_exact($location = array()) { +function location_latlon_exact($location = array(),$force_generic = FALSE) { + $country = trim($location['country']); $service = variable_get('location_geocode_'. $country, 'none'); + + + if(($service == 'none' || $force_generic) && variable_get('location_generic_fallback',0)) { + $service = variable_get('location_geocode_generic','none'); + $force_generic = TRUE; + $country = 'generic'; + } + if (!empty($country) && $service != 'none') { $exact_latlon_function = 'location_geocode_'. $country .'_'. $service; if (function_exists($exact_latlon_function)) { - return $exact_latlon_function($location); + $latlong = $exact_latlon_function($location); + + if(is_array($latlong)) { //If we got a value back then we're happy... + return $latlong; + } elseif(variable_get('location_generic_fallback',0) && !$force_generic) { //If nothing was returned by the country specific geocoder... then lets give$ + return location_latlon_exact($location,TRUE); //Call with 'force_generic == TRUE'... + } else { + return NULL; + } } else { return NULL; @@ -1213,6 +1235,12 @@ function location_configured_countries() asort($configured_countries_associative); } + + if(variable_get('location_generic_fallback',0)) { + $configured_countries_associative = array_merge(array('generic' => 'generic'),$configured_countries_associative); + } + + return $configured_countries_associative; } diff -urNp location_old/location.module location/location.module --- location_old/location.module 2007-04-09 11:00:50.000000000 +0100 +++ location/location.module 2007-04-09 11:08:13.000000000 +0100 @@ -1390,7 +1390,19 @@ function location_configure() { '#description' => t('Currently, your CivicSpace site is capable of supporting extra features (e.g., postal code proximity searches) for locations from this list of countries. Please narrow the list down to countries for which you want to support these extra features. It may be useful for performance to narrow down this list if most the locations in your system are from only a handful of the listed countries.') ); + + + $form['location_generic_fallback'] = array( + '#type' => 'checkbox', + '#title' => t('Use generic location function fallbacks.'), + '#return_value' => 1, + '#default_value' => variable_get('location_generic_fallback',0), + '#description' => t('If any of the countries enabled below do not have their own geocoding functions, should we use a gazeteer web server (e.g. Geoname$ + ); + return system_settings_form('location_configure_settings', $form); + + } @@ -1583,4 +1595,4 @@ function location_invoke_locationapi(&$l } } return $return; -} \ No newline at end of file +} diff -urNp location_old/supported/location.generic.inc location/supported/location.generic.inc --- location_old/supported/location.generic.inc 1970-01-01 01:00:00.000000000 +0100 +++ location/supported/location.generic.inc 2007-04-09 11:09:36.000000000 +0100 @@ -0,0 +1,90 @@ + array('name' => 'Geonames Webservice', 'url' => 'http://www.geonames.org/export/', 'tos' => 'http://creativecommons.org/licenses/by/2.5/') + ); +} + +/** + * 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_geocode_generic_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; + } + +} + + + + + + +