What is the correct way to modify the location data during an update/insert?
You can't modify the data during the save, as the geocoding hasn't occured yet, so it has to be during update/insert...
The method below I'm trying has the effect of creating _extra_ locations, despite my attempts to fix this...

Background: using zipcode geocoding, all of the items are given identical lat/lon, leading to a map with all of the items stacked in one place.
A random 'peppering' effect is desired, once geocoding occurs, I want to modify the lat/long automagically, adding a random factor.
I ONLY want one location, and the content type is set to only allow one location.


function CUSTOMMODULE_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {

// copied from location module, for code clarity
define('LOCATION_LATLON_UNDEFINED', 0);
define('LOCATION_LATLON_USER_SUBMITTED', 1);
define('LOCATION_LATLON_GEOCODED_APPROX', 2);
define('LOCATION_LATLON_GEOCODED_EXACT', 3);


// if the nodetype allows locations
  if (!variable_get('location_maxnum_'. $node->type, 0)) {
    return;
  }
// only if it's the desired nodes, pepper the geocoding
  if ($node->type == "item1" OR $node->type == "item2") {
    switch ($op) {
      case 'insert':
      case 'update':
          
          $node->locations[0] = location_form2api($node->locations[0]);
          $node->locations[0]['latitude'] = trim($node->locations[0]['latitude']);
          $node->locations[0]['longitude'] = trim($node->locations[0]['longitude']);
          // submitted lat/lons are either blank or valid numbers.  Now, we need to find out determine
          // the source of these lat/lons since they can either be prefilled from postalcode data
          // or manually entered by the user.
          if (!empty($node->locations[0]['latitude']) && !empty($node->locations[0]['longitude']) && ($node->locations[0]['source'] > 1) ) {

// add a random variation, plus or minus a bit, to 'pepper' the values.
              $node->locations[0]['lat'] = (float)$node->locations[0]['latitude'] + ((.5 - ((float)rand()/(float)getrandmax())) *.1);
              $node->locations[0]['lon'] = (float)$node->locations[0]['longitude'] + ((.5 - ((float)rand()/(float)getrandmax())) *.1);
              $node->locations[0]['source'] = LOCATION_LATLON_USER_SUBMITTED;


// added in attempt to deal with dupes, but didn't... 

              if ($node->locations[0]['lid']) {
                db_query('DELETE FROM {location} WHERE lid = %d', $node->locations[0]['lid']);
                location_invoke_locationapi($node->locations[0], 'delete'); 
              }

//without the save, the data isn't saved.
              _location_save($node->locations[0] ? $node->locations[0] : array(), $node, 'node');
          }
      break;
      default:
      break;
    }  
  }

  return;
}

So what am I doing wrong here? And if there is a better way to do this, what is it?

Comments

sethcohn’s picture

Found a better way... I'll post it in the next day or 3...

essentially, I needed to reload the node (to get an lid) and then used SQL to directly update the location table.

sethcohn’s picture

Status: Active » Closed (fixed)

This is the major difference from the above code... except this works.

Fixes:
a) reload the node... it's stale already, location has changed the contents, and added fields.
b) don't try and use the save, do a direct SQL update.


      case 'insert':
      case 'update':
      
          // must reload the node to get the correct info...
          $node = node_load($node->nid);

          $location_node_obj = location_form2api($node->location);
          $location_node_obj['latitude'] = trim($location_node_obj['latitude']);
          $location_node_obj['longitude'] = trim($location_node_obj['longitude']);

          // submitted lat/lons are either blank or valid numbers.  Now, we need to find out determine
          // the source of these lat/lons since they can either be prefilled from postalcode data
          // or manually entered by the user.

          if (!empty($location_node_obj['latitude']) && !empty($location_node_obj['longitude']) && ($location_node_obj['source'] > 1) ) {
              $node->location['latitude'] = (float)$location_node_obj['latitude'] + ((.5 - ((float)rand()/(float)getrandmax())) *.1);
              $node->location['longitude'] = (float)$location_node_obj['longitude'] + ((.5 - ((float)rand()/(float)getrandmax())) *.1);

              $node->location['lat'] =  $node->location['latitude'];
              $node->location['lon'] =  $node->location['longitude'];

              $node->location['source'] = LOCATION_LATLON_USER_SUBMITTED;

              if ($node->location['lid']) {
                db_query('UPDATE {location} SET latitude = %f, longitude = %f,  source = %d WHERE lid = %d', $node->location['lat'], $node->location['lon'], LOCATION_LATLON_USER_SUBMITTED, $node->location['lid']);
              }
          }
      break;

summit’s picture

Will this also help in D6, greetings, Martijn