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

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:

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:

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:

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.

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;
    }
}

Comments

lance.gliser’s picture

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:

  if (! ( empty($location['street']) || empty($location['postal_code']) ) ){
SeanBannister’s picture

+1 been trying to get this working :)

pacesolutions’s picture

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.

lance.gliser’s picture

I'm not entirely sure you have understood want I was after, pacesolutions.

You're suggesting that the user:

Double click on the map to place the marker and auto fill the Latitude & Longitude

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:

There is no need for CCK or any other module to work around. CCK module is not working.

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.

ajevans85’s picture

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.

pacesolutions’s picture

Above fixes seems to work with CCK and Location module.

I have a working copy solution. I'm trying to give back since the developers did the majority of the heavy lifting.

If you can provide the complete location.module file, that will be more helpful.

lance.gliser’s picture

StatusFileSize
new59.11 KB
new28.9 KB

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.

yesct’s picture

Issue tags: +location bdragon check

the idea in the original post about messages seems reasonable.

kvvnn’s picture

Subscribing - will edit w/ results

kvvnn’s picture

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.

socialnicheguru’s picture

subscribing

wretched sinner - saved by grace’s picture

Version: 6.x-3.1-rc1 » 6.x-3.x-dev
Status: Needs review » Reviewed & tested by the community

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...

summit’s picture

Yes please, roll a patch!
Thanks in advance! Greetings, Martijn

wretched sinner - saved by grace’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new64.9 KB

I have attached a patch for the files in #411360-7: Node Locations not geocoding, no errors given.

jax’s picture

Status: Needs review » Needs work

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.

wretched sinner - saved by grace’s picture

Status: Needs work » Needs review
StatusFileSize
new9.21 KB

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.

jax’s picture

Status: Needs review » Needs work

This is meaningless:

 function 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:

+ // emfluence
mvc’s picture

i agree with all of lance.gliser's suggested changes described above in the original post. however, as i understand it, form_set_error() can only be called from a form validation function. all of the above changes including warnings are very useful, but if you want to force your users to choose a valid location either by geocoding or by clicking on the map, those aren't sufficient. the geocoding isn't even attempted until $op 'save' case of location_node's nodeapi hook, by which point all validation is supposed to be completed.

i personally solved this via a custom module which we'll call my_custom_module shown here acting on a custom content type we'll call test:

function my_custom_module_form_alter(&$form, &$form_state, $form_id) {
  switch($form_id) {
    case 'test_node_form':
      $form['validate'][] = 'my_custom_module_location_element_validate';
  }
}

function my_custom_module_location_element_validate() {
  $args = func_get_args();
  $locations = $args[1]['values']['locations'];
  if ( is_array($locations) ) {
    foreach ( $locations as $loc_form ) {
      if ((! $loc_form['locpick']['user_latitude']) || (! $loc_form['locpick']['user_longitude'])) {
        // test exact geocoding
        if ($data = location_latlon_exact($loc_form)) {
          drupal_set_message(t('Site location automatically determined from address; please set a location on the map if this is inaccurate'));
        }
        // test inexact geocoding against a local postcode database
        elseif ($data = location_get_postalcode_data($loc_form)) {
          drupal_set_message(t('Approximate site location determined from postal code; please set a location on the map if this is inaccurate'));
        }
        else {
          if (! ( empty($loc_form['street']) && empty($loc_form['postal_code']) ) ){
            form_set_error('locations', t('The location could not be identified based on the address or postal code provided.'));
          }
          else {
            form_set_error('locations', t('Please set a location on the map or enter an address.'));
          }
        }
      }
    }
  }
}

the correct solution would be to add the validation hook to location_node and a setting someplace specifying whether users should be forced to submit a valid location via one of these two strategies. i wasn't sure where to put this UI code so i just used a separate module but hopefully this is a good starting point for anyone wanting to do this properly. ideally the geocoding functions themselves wouldn't have to be called twice, but that would be a more drastic change to this module then i currently have the time for.

osopolar’s picture

I came here while I was looking for a way to validate the postal code in the cck address field. Maybe it would be useful to know that there is a hook_locationapi which allows form validation. It's especially useful if you have to validate the same field in different forms. Here a short example:

/**
 * Implementation of hook_locationapi().
 */
function custom_helper_locationapi(&$obj, $op, $a3 = NULL, $a4 = NULL, $a5 = NULL) {
  switch ($op) {
    case 'validate':
      // example: validate postal code, just check if it's numeric
      if (!is_numeric($obj['postal_code'])) {
        form_error($a3['postal_code'], t('Please provide a valid postal code.'));
      }
      break;
  }
}
reubenavery’s picture

Now this is what I call a handsome bug issue thread. Subscribing :-) patch #16 solved things for me, btw.

hadsie’s picture

StatusFileSize
new5.62 KB

I've re-rolled the patch against the latest dev version. There were a couple things I didn't understand in the patch though:
* The part starting with "case 'instance_links':", where is this called from? I see it's added in the patch, but don't see any code that the patch adds that would evaluate this.
* You remove the _location_patch_locpick() function... why is this?

yesct’s picture

Someone please post a summary of the current status of this issue, like for example does the patch in #21 address the concerns brought up in #16 and #17?

If someone can provide a good summary and review, it will make it much more likely that a maintainer will take a look at the proposed solution and we might have a chance of getting a commit. Post the summary assuming someone is coming in fresh and has not been following every step of the way.

hadsie’s picture

The patch I created in #21 does not take into account #17. It does take into account #16.

nickbits’s picture

Hi,

The patch from #21 works for me on newly created nodes just fine for me.

Nick

Anonymous’s picture

With the newest 6.x-3.x-dev version geocoding does not work for me. Providing a manual location via the map does work fine, but geocoding from an address does not. All the necessary api keys are there.

Second thing which I do not understand is that once I enter a manual lat/long I cannot delete it anymore. It can be removed, but as soon as the the node is saved the old location is back.

Any suggestions?

Thanks and best regards

SkyWombat

EDIT: Patch #21 works as far as error messages are concerned, but geocoding still is not working properly. The error message reads: "The support file for: es found at sites/all/modules/location/supported/location.es.inc. does not have a function to support zip code look ups. Missing funtion: location_get_postalcode_data_es"
But according to the settings a Spanish address should be geocoded via google, so why do I need a zip look up function? Is there some misunderstanding on my side?

EDIT2: It works for Germany without any issue, but for Spain it does not. Any ideas?

yesct’s picture

in your edit #2, do you mean that it works for germany without the patch?

yesct’s picture

Issue tags: +location geo-coding

tagging.

Anonymous’s picture

I did not try it for Germany without the patch. But it worked with the patch.
For Australia it did not work without the patch, but it works with the patch.
Oddly enough, after some hacking of location.es.inc it did not work immediately, but after one day waiting it is now working fine. Maybe there was an issue with caching the location function or there was an issue with the connection to google maps. I have no clue.

Currently everything seems fine and I' happy.

Hacking of location.es.inc was just copying the routines of location.de.inc and adjusting names and country specific points.

bryancasler’s picture

subscribing, any update would be helpful

webwriter’s picture

Subscribe. Sometimes I get a geolocation from an adddress, sometimes I do not. I can't seem to find a pattern to it.

UNarmed’s picture

This geocode things is a nightmare i simply cant get it to work.

Josephnewyork’s picture

I figured it out! It must be a particular order of when the geocoding options are set and what other options are also set...

If the geocoding doesn't auto-fill the long/lat, go to admin/settings/location/geocoding, and click "Reset to default". Then, choose your geocoder again, (im my case, USA:google) and "Save configuration"

Now its working :)

alexborsody’s picture

I was having the same problem. I was able to fix this by uploading a list of area codes and searching by proximity

summit’s picture

Hi, @F.E.M. COUld you elaborate more on this. Somehow I do not get geocoding working anymore..
Thanks a lot in advance. Greetings, Martijn

marleo’s picture

In my case it was being stopped by the "State/Province" field being filled by people using a commonly-used abbreviation. The correct name for the state is "Victoria", but it's very common here (Aus) for people to enter abbreviated state names, eg "VIC". Choosing the auto-lookup "Victoria" as offered by the field made it work.

Marc Storms’s picture

I was having the same problems. The patch helped me to get the error "Google geocoding returned status code: 610" and googling this I found on comment 40 of http://drupal.org/node/1940474 the patch that solved my day (I am using Location 6.x.3.2).
Thanks to all of you.

legolasbo’s picture

Status: Needs work » Closed (outdated)

Closing old D6 issues as D6 is end of life