You are here

function location_save in Location 7.3

Same name and namespace in other branches
  1. 5.3 location.module \location_save()
  2. 6.3 location.module \location_save()
  3. 7.5 location.module \location_save()
  4. 7.4 location.module \location_save()

Save a location.

This is the central function for saving a location.

Parameters

array $location: Location array to save.

bool $cow: Copy-on-write, i.e. whether or not to assign a new lid if something changes.

array $criteria: Instance criteria. If the only instances known by location match the criteria, the lid will be reused, regardless of $cow status. If no criteria is provided, there will be no attempt to reuse lids.

Return value

int|bool The lid of the saved location, or FALSE if the location is considered "empty."

3 calls to location_save()
la_geocode_worker in contrib/location_autofill/la.module
Handler to process single location per batch run.
location_save_locations in ./location.module
Save associated locations.
MigrateLocationFieldHandler::prepare in ./location.migrate.inc

File

./location.module, line 1479
Location module main routines. An implementation of a universal API for location manipulation. Provides functions for postal_code proximity searching, deep-linking into online mapping services. Currently, some options are configured through an…

Code

function location_save(&$location, $cow = TRUE, $criteria = array()) {

  // Quick settings fixup.
  if (!isset($location['location_settings'])) {
    $location['location_settings'] = array();
  }
  location_normalize_settings($location['location_settings']);
  $inhibit_geocode = FALSE;
  if (isset($location['inhibit_geocode']) && $location['inhibit_geocode']) {

    // Workaround for people importing / generating locations.
    // Allows things like location_generate.module to work properly.
    $inhibit_geocode = TRUE;
    unset($location['inhibit_geocode']);
  }
  $force_geocode = FALSE;
  if (isset($location['re_geocode_location']) && $location['re_geocode_location']) {
    $force_geocode = TRUE;
  }
  if (isset($location['delete_location']) && $location['delete_location']) {

    // Location is being deleted.
    // Consider it empty and return early.
    $location['lid'] = FALSE;
    return FALSE;
  }

  // If there's already a lid, we're editing an old location. Load it in.
  $oldloc = location_empty_location($location['location_settings']);
  if (isset($location['lid']) && !empty($location['lid'])) {
    $oldloc = (array) location_load_location($location['lid']);
  }
  if (_location_patch_locpick($location)) {
    $inhibit_geocode = TRUE;
  }

  // Pull in fields that hold data currently not editable directly by the user.
  $location = array_merge($oldloc, $location);

  // Note: If the user clears all the fields, the location can still
  // be non-empty if the user didn't have access to everything..
  $filled = array();
  if (location_is_empty($location, $filled)) {

    // This location was empty, we don't need to continue.
    $location['lid'] = FALSE;
  }
  $changed = array();
  if (!location_calc_difference($oldloc, $location, $changed) && !$force_geocode) {

    // We didn't actually need to save anything.
    if (!empty($location['lid'])) {
      return $location['lid'];
    }
    else {

      // Unfilled location (@@@ Then how did we get here?)
      $location['lid'] = FALSE;
    }
  }

  // Perform geocoding logic, coordinate normalization, etc.
  _location_geo_logic($location, $changed, $filled, $inhibit_geocode, $force_geocode);

  // If we are in COW mode, we *probabaly* need to make a new lid.
  if ($cow) {
    if (isset($location['lid']) && $location['lid']) {
      if (!empty($criteria)) {

        // Check for other instances.
        // See #306171 for more information.
        $query = db_select('location_instance', 'l');
        foreach ($criteria as $key => $value) {
          $query
            ->condition($key, $value);
        }
        $associated = $query
          ->countQuery()
          ->execute()
          ->fetchField();
        $all = db_query("SELECT COUNT(*) FROM {location_instance} WHERE lid = :lid", array(
          ':lid' => $location['lid'],
        ))
          ->fetchField();
        if ($associated != $all) {

          // If there were a different number of instances than instances matching the criteria,
          // we need a new LID.
          unset($location['lid']);
        }
      }
      else {

        // Criteria was not provided, we need a new LID.
        unset($location['lid']);
      }
    }
  }
  if (!empty($location['lid'])) {
    watchdog('location', 'Conserving lid %lid due to uniqueness.', array(
      '%lid' => $location['lid'],
    ));

    // Using a merge query instead of drupal_write_record to prevent failing to save
    // if the lid happens to not exist in {location}, which has been seen in the wild.
    // Tested in mysql, sqlite, and postgresql.
    $fields = array();
    foreach (array(
      'name',
      'street',
      'additional',
      'city',
      'province',
      'postal_code',
      'country',
      'latitude',
      'longitude',
      'source',
    ) as $key) {
      if (isset($location[$key])) {
        $fields[$key] = $location[$key];
      }
    }
    db_merge('location')
      ->key(array(
      'lid' => $location['lid'],
    ))
      ->fields($fields)
      ->execute();
  }
  else {
    unset($location['lid']);
    drupal_write_record('location', $location);
  }
  location_invoke_locationapi($location, 'save');
  return $location['lid'];
}