Node Locations not geocoding, no errors given.
| Project: | Location |
| Version: | 6.x-3.x-dev |
| Component: | Code |
| Category: | bug report |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | needs work |
| Issue tags: | location bdragon check |
I truly hope I'm not duplicating on you with this. I was having trouble with my site's geocoding failing to run automatically. I googled for a few issues and found multiple people never quite got their answers. I believe the issue is caused by 3 separate bugs, or maybe I just thing the module should work differently. For people looking for answers, it's important you understand that the location module is attempting to run for you if the coordinates are not user submitted. It just doesn't return any information about success or failures. This leads to a lot of head scratching for people. To that end, I recommend adding some drupal set messages. I've added them in the code I'll post here. First, a generic fallback:
In location.module, function: _location_geo_logic
<?php
else {
$location['source'] = LOCATION_LATLON_UNDEFINED;
$location['latitude'] = 0;
$location['longitude'] = 0;
//A generic fall back for when address geolocation fails
drupal_set_message(t('The location could not be identified based on the address, or zip code provided.'), 'warning');
}
?>But the actual bugs need to be addressed more than messages. In location.module, function: _location_geo_logic, an if statement currently reads:
<?php
if ($changed['street'] || $changed['additional'] || $changed['city'] || $changed['province'] || $changed['country'] || $changed['postal_code'] || $location['source'] == LOCATION_LATLON_USER_SUBMITTED) {
?>But later in the file it sets $location['source'] to LOCATION_LATLON_UNDEFINED (0). If the user saves the node again, without changing the address hoping to fire geoencoding, the if statement does not allow for the check (and gives no warning). I would suggest adding LOCATION_LATLON_UNDEFINED to the if statement. I know that it will only come up while testing like I am, or maybe if you hit your limit on geoencodes from google for a day, but it keeps the behavior more predicable. New if statement:
<?php
if ($changed['street'] || $changed['additional'] || $changed['city'] || $changed['province'] || $changed['country'] || $changed['postal_code'] || $location['source'] == LOCATION_LATLON_USER_SUBMITTED || $location['source'] == LOCATION_LATLON_UNDEFINED) {
?>Also in location.module, function: location_strip, the current stripping patterns were removing the ['locpick'], ['user_latitude'], and ['user_longitude'] arrays. If those are stripped out, the checks for differences that fire geoencoding fail to see a difference from the merged location array to the old location array. Please consider altering $tmp or changing the function to something similar to:
<?php
function location_strip(&$location) {
static $tmp;
if (!isset($tmp)) {
$tmp = array();
$defaults = location_invoke_locationapi($location, 'defaults');
foreach ($defaults as $k => $v) {
if (!isset($v['nodiff'])) {
$tmp[$k] = TRUE;
}
}
}
foreach ($location as $k => $v) {
if (!isset($tmp[$k])) {
if(!($location[$k] == "locpick" || $location[$k] == "user_latitude" || $location[$k] == "user_longitude")) {
unset($location[$k]);
}
}
}
}
?>In location.inc, function: location_get_postalcode_data, I found that the $country_specific_function was failing everytime. For me, at least, the required location.xx.inc file was not loaded at the time the function checked for it's existence. All that needed done was to include_once the country file. I've got code for that below, along with the drupal_set_messages if there are errors.
<?php
function location_get_postalcode_data($location = array()) {
$location['country'] = isset($location['country']) ? trim($location['country']) : NULL;
$location['postal_code'] = isset($location['postal_code']) ? trim($location['postal_code']) : NULL;
if (is_null($location['postal_code']) || is_null($location['country']) || empty($location['country']) || empty($location['postal_code']) || $location['postal_code'] == 'xx') {
return NULL;
}
$country_specific_function = 'location_get_postalcode_data_'. $location['country'];
if (function_exists($country_specific_function)) {
return $country_specific_function($location);
}
else {
if ($cache = cache_get('location:supported-countries', 'cache_location')) {
$country = $location['country'];
if ($cache->data[$country]) {
$include = drupal_get_path('module', 'location') .'/supported/location.'. $location['country'] .'.inc';
if (file_exists($include)){
include_once($include);
if (function_exists($country_specific_function)) {
return $country_specific_function($location);
} else {
drupal_set_message(t('The support file for: ' . $location['country']. ' found at <i>' . $include .'</i>. does not have a function to support zip code look ups. Missing funtion: <i>' . $country_specific_function . '</i>'), 'error');
}
} else {
drupal_set_message(t('The support file for: ' . $location['country']. ' could not be found at <i>' . $include .'</i>.'), 'error');
}
} else {
drupal_set_message(t('The country code requested: ' . $location['country']. ' is not supported by this site.'), 'warning');
}
} else {
drupal_set_message(t('There are no supported countries in the site cache.'), 'warning');
}
return NULL;
}
}
?>
#1
My generic fallback message has an issue.
If you set the location as optional, and the user fills in nothing, the message prints warning them it wasn't saved.
It needs an if statement checking if the user even entered a zip or street. Something like:
<?phpif (! ( empty($location['street']) || empty($location['postal_code']) ) ){
?>
#2
+1 been trying to get this working :)
#3
As per my installation I did not found any problems. Everything is working as it suppose to work. Here how you can work around the problem.
Packages:
- Latest Drupal - http://ftp.drupal.org/files/projects/drupal-6.10.tar.gz
- Latest Location Module - http://drupal.org/project/location (6.x-3.1-rc1)
- Latest GMap Module - http://drupal.org/project/gmap (6.x-1.1-rc1)
- Install or Upgrade to latest Drupal 6.10
- Download and place modules in the modules directory of your Drupal.
- Now activate the following modules from Administrator section (admin/build/modules)
* User Locations
* Node Locations
* Location Search
* Location
* GMap
* GMap Location
- Once modules are enabled. Get Google Maps API and configure the Location module (admin/settings/location).
* In Main settings tab, make sure you select United States as default country.
* Toggle location display: Enable
* Use a Google Map to set latitude and longitude is checked.
* Now in Geocoding Options tab, under United States choose Google Maps.
* Hit saves Configuration
* Now again under United States choose Configure Parameters (This is where you put your Google API key).
- Now configure GMap module (admin/settings/gmap).
* Put your API key here (If not already there.)
* Set default width & height as you like and choose also the default center (e.g.: 39.9434364619742,-77.2998046875), you can also configure more settings as you like.
* Now hit Save Configurations to save them.
- Now configure GMap Location (admin/settings/gmap_location)
* For each Macro put something like this: [gmap zoom=3 |center=39.9434364619742,-77.2998046875 |width=100% |height=300px |control=Small |type=Physical]
- Now most important part is to enable Location block in the content or sidebar to display the map correctly.
* Enable 'Location map' block (admin/build/block) and set to display in sidebar or content - now a small map will be displayed next to nodes that have a location.
- You can create a new content type or modify the existing to display and enter the location/map data. I will modify the default Page content type (admin/content/node-type/page)
* Under Locative Information click on Number of locations
* Set 1 for Minimum number of locations, Maximum number of locations and Number of locations that can be added at once.
* Under Collection Settings, choose the fields you want to display in the form for adding/editing.
* Now hit Save Content Type.
- Now create a new test page (node/add/page) to see if Google maps are working or not.
* Fill the details as you like,
* Double click on the map to place the marker and auto fill the Latitude & Longitude
* Save the Page node.
- You should be able to see the Google Map with marker in right place under your block. You can free place Location block anywhere as you like.
There is no need for CCK or any other module to work around. CCK module is not working.
#4
I'm not entirely sure you have understood want I was after, pacesolutions.
You're suggesting that the user:
My current goal is let the user choose their own coordinates, like you suggest, or leave them unselected to fire geolocation automatically based off their address.
Your solution would end with all user entered coordinates, not what I'm after.
Also the purpose of this posting is to address your last line:
I have posted solutions to multiple bugs in the location module.
When fixed, the CCK module does work. I user multiple working CCK Location fields over multiple content types on the site I'm building. And they all work fantastically. (Well... it get's sketchy when you try to pull the view.)
I have a working copy solution. I'm trying to give back since the developers did the majority of the heavy lifting.
#5
Just trying this module and was unable to get automatic population of lng/lat fields.
Applying the patch from lance.gliser lead me to track the issue down to the location.uk.inc not having the function 'location_get_postalcode_data_uk' . Thats only half my problem as 'location_get_postalcode_data_uk' should be a fallback function if geocaching isn't working (and i had set up geocaching). I haven't had chance to implement 'location_get_postalcode_data_uk' yet as I am more concerned with the google geocaching and feasability of integrating this module with the apache solr module with solr local searching. As I am uk based and things are looking promising when just playing about with this I'll probably have a patch soon as it's fairly trivial.
Any way back to my problem... further tracking lead me to the '_google_geocode_flatten' function. It was generating a invalid query string for uk geo caching. The function applies the province code 'CHS' for Cheshire, this meant nothing to Google as 'CHS' it's not a valid UK county (province). Changing the flatten function to use province name also didn't work, it was a valid address but google was still providing a status 602 (no valid address found). Dropping the province filed worked so my function now looks like:
<?php
function _google_geocode_flatten($location = array()) {
// Check if its a valid address
if (empty($location)) {
return '';
}
$query= array();
if (!empty($location['street'])) {
$query[] = $location['street'];
}
if (!empty($location['city'])) {
$query[]= $location['city'];
}
if ($location['country'] != 'uk' && !empty($location['province'])) {
// @@@ Fix this!
if (substr($location['province'], 0, 3) == $location['country'] .'-') {
$query[]= substr($location['province'], 3);
watchdog('Location', 'BUG: Country found in province attribute.');
}
else {
$query[]= $location['province_name']; //Google doesn't map CHS back to Cheshire for uk so we get a 602 error
}
}
if (!empty($location['postal_code'])) {
$query[]=$location['postal_code'];
}
return implode(',', $query);
}
?>
Works for me but not that elegant considering theres 242 supported locations in the supported directory and they may all need to structure the query sting differently. What would probably be better is checking if a function such as 'location_geocode_flatten_$country' exists to flattern the string otherwise fall back to the default implementation.
I agree with lance that some error messages are needed and without his patch it probably would of took me longer tracking down my issue.
#6
Above fixes seems to work with CCK and Location module.
If you can provide the complete location.module file, that will be more helpful.
#7
I'll upload the two file's I've altered.
Look for //emfluence on the functions I've altered.
Also, to get CCK working with views I had to do the work around in http://drupal.org/node/366880
It's a nasty hack, acknowledged by the author and myself. You have to theme out locations and theme in location CCK.
I'm waiting for his proper fix. But for now it all works when you put it together.
#8
the idea in the original post about messages seems reasonable.
#9
Subscribing - will edit w/ results
#10
Prompting the User , and preventing the form from being submitted if (latitude, longitude) can not be found
Line 574, location.module
//Test if city is valid - ADDED BY TIM 9/6
if (!empty($obj['city'])) {
//Create Array
$location = array("city"=>$obj['city'], "province"=>$obj['province'], "country"=>$obj['country']);
if ($data = location_latlon_exact($location)) { //City is valid - don't do anything right now
} else { //City is not valid
form_error($a3['city'], t('We were not able to geocode your location.'));
}
}
I prefer this to the #1's initial code sample, because it stops the form from saving information in the database. Obviously, it would be best to have a map for the user to manually enter a location after this, instead of not allowing non-supported cities.
#11
subscribing
#12
I have tested the replacement files from lance in #7, and my maps are now displaying (I'm in Australia)
I can roll a patch if required...
#13
Yes please, roll a patch!
Thanks in advance! Greetings, Martijn
#14
I have attached a patch for the files in #411360-7: Node Locations not geocoding, no errors given.
#15
The patch completely replaces location.inc with lines that end in CR LF in stead of only LF. Please configure your text editor correctly and reroll the patch.
#16
Sorry about that. I just copied the files in #411360-7: Node Locations not geocoding, no errors given. over and diffed from there. I didn't think to check the line endings, and that would explain the trouble I had last time.
Attached is a patch with correct line endings.
#17
This is meaningless:
<?phpfunction location_map_link($location = array(), $link_text = 'See map: ') {
- if (!isset($location['country']) || $location['country'] == 'xx') {
+ if (!isset($location['country']) && $location['country'] != 'xx') {
return '';
}
?>
Is $location['country'] is not set then $location['country'] will be different than 'xx' … Also I'm not sure this even should be modified.
Please remove:
<?php+ // emfluence
?>