Skip to content
location.module 29.2 KiB
Newer Older
<?php

define('LOCATION_PATH', drupal_get_path('module', 'location'));

include_once LOCATION_PATH.'/location.inc';


function location_menu($may_cache = FALSE) {
  $items = array();
  if ($may_cache) {
    $items[] = array('path' => 'search/location', 'title' => t('by location'), 'callback' => 'location_search_form_page', 'access' => user_access('search content'), 'type' => MENU_LOCAL_TASK, 'weight' => 9);
  }
Ankur Rishi's avatar
Ankur Rishi committed
  else {
    drupal_set_html_head(location_form_html_head());
  }
  return $items;
}

/**
 * Implementation of hook_help.
 *
 *
 *
 */
function location_help($section) {
  switch ($section) {
    case 'admin/modules#description':
      return t('Enables the location system and allow users to attach locative information to content.');
    case 'admin/help#location':
      return t('
               <p>The location module allows you to associate a geographic location with content and users. Users can do proximity searches by postal code.  This is useful for organizing communities that have a geographic presence.</p>
               <p>To administer locative information for content, use the content type administration page.  To support most location enabled features, you will need to install the country specific include file.  To support postal code proximity searches for a particular country, you will need a database dump of postal code data for that country.  As of June 2005 only U.S. postal codes are supported.</p>
               <p>You can</p>
               <ul>
                 <li>administer locative information at <a href = "%administercontenttypeslocativeinformation" title = "administer content types locative information"> administer >> content types</a> to configure a type and see the locative information.</li>
                 <li>administer location at <a href = "%administerlocation" title = "administer location">administer >> settings >> location</a></li>
                 <li>use a database dump for a U.S. postal codes table that can be found at <a href = "http://trac.civicspacelabs.com/cgi-bin/trac.cgi/file/trunk/database/zipcodes.mysql" title = "zipcode database">zipcode database</a>.</li>
               </ul>
               <p>For more information, read the configuration and customization handbook <a href="http://drupal.org/handbook/modules/Location" title="Location page"> Location page</a></p>', 
               array('%administercontenttypeslocativeinformation' => url('admin/node/configure/types'), '%administerlocation' => url('admin/settings/location'))
/**
 * Serves a search-by-location page for nodes.
 * On $_POST, displays searh form + search results.
 * Otherwise, just displays search form.
 */
function location_search_form_page() {
  $from_get = FALSE; // boolean to remember if variables came from a get
  
  $prefilled_values = array();
  if ($edit = $_POST['edit']) {
Ankur Rishi's avatar
Ankur Rishi committed
    $prefilled_values['postal_code'] = trim($edit['location']['postal_code']);
    $prefilled_values['country'] = trim($edit['location']['country']);
  }
  elseif (isset($_GET['postal_code']) || isset($_GET['country']) || isset($_GET['distance']) || isset($_GET['distance_unit'])) {
    $from_get = TRUE;
Ankur Rishi's avatar
Ankur Rishi committed
    $prefilled_values['postal_code'] = isset($_GET['postal_code']) ? trim($_GET['postal_code']) : '';
    $prefilled_values['country'] = isset($_GET['country']) ? $_GET['country'] : '';
    $prefilled_values['distance'] = isset($_GET['distance']) ? $_GET['distance'] : '';
    $prefilled_values['distance_unit'] = isset($_GET['distance_unit']) ? $_GET['distance_unit'] : '';
    $edit = array();
    $edit['location'] = $prefilled_values;
  }
  
  $location_form = location_form(array('postal_code', 'country'), $prefilled_values, array('postal_code', 'country'), variable_get('location_suppress_country', 0) ? array('country' => variable_get('location_default_country', 'us')) : array(), '', 'location', 'nearby_postalcodes_bylocation');
  
  $form = location_proximity_form($location_form,
                                 t('Search for content within a specified geographical area.'), 
                                 '',
                                 array('distance' => (isset($edit['location']['distance']) ? $edit['location']['distance'] : 25), 'distance_unit' => (isset($edit['location']['distance_unit']) ? $edit['location']['distance_unit'] : 'mile')),
                                 variable_get('location_search_distance_unit', 0) ? array('distance_unit' => variable_get('location_search_distance_unit', 0)) : array()
                                );

  $form .= form_submit(t('Search'));
  $form = form($form);
  $search_results = '';
  if ($edit) {
    //$start_time = microtime();
    $edit['location']['postal_code'] = trim($edit['location']['postal_code']);
    if (strlen($edit['location']['postal_code']) && strlen($edit['location']['country']) && $edit['location']['country'] != 'xx') {
      // DEBUG: commented code for testing/debugging purposes
      //$search_results .= 'serialize($edit[\'location\']) == '. serialize($edit['location']) ."<br/>\n";
      $edit['location'] = location_form2api($edit['location']);

      // Find all postal codes within search radius, sorted in ascending order by distance from search point  
      $postal_codes = location_nearby_postalcodes_bylocation($edit['location'], $edit['location']['distance'], $edit['location']['distance_unit']);

      // Want to get just the postal_codes and implode them into a portion of the final query      
      // Want to be able to key each postal_codes distance from the search point.  Keying done by country/postal_code combination.
      if (count($postal_codes)) {
        $query_fragment = "'". implode(array_keys($postal_codes), ',') ."'";
Ankur Rishi's avatar
Ankur Rishi committed
        
        $sql = "SELECT n.nid, a.postal_code, a.city, a.province, a.country, n.title, n.teaser, n.type, n.created, n.nid, u.name, FIND_IN_SET(CONCAT(country, postal_code), ". $query_fragment .") AS search_rank FROM {location} a INNER JOIN {node} n ON a.oid = n.nid INNER JOIN {users} u ON n.uid = u.uid WHERE a.type = 'node' AND FIND_IN_SET(CONCAT(a.country, a.postal_code), ". $query_fragment .") > 0 ORDER BY search_rank ASC, created DESC";
        $count_sql = "SELECT COUNT(*) FROM {location} a INNER JOIN {node} n ON a.oid = n.nid INNER JOIN {users} u ON n.uid = u.uid WHERE a.type = 'node' AND FIND_IN_SET(CONCAT(a.country, a.postal_code), ". $query_fragment .") > 0";
        $count_display_sql = "SELECT COUNT(*) as result_count FROM {location} a INNER JOIN {node} n ON a.oid = n.nid INNER JOIN {users} u ON n.uid = u.uid WHERE FIND_IN_SET(CONCAT(a.country, a.postal_code), ". $query_fragment .") > 0";
        $res = pager_query($sql, 15, 0, $count_sql);

        $count = db_fetch_object(db_query($count_display_sql));
        
        if ($count->result_count) {
          $page_count = db_num_rows($res);
          $results_offset = isset($_GET['from']) ? $_GET['from'] : 0;
          $postal_data = location_get_postalcode_data($edit['location']);
          $search_results_message = t('Displaying results %a - %b of %count for search on %c', array('%a' => $results_offset + 1, '%b' => $results_offset + $page_count, '%count' => $count->result_count, '%c' => '<em>'. $edit['location']['postal_code'] .'</em> ('. $postal_data['city'] . ', '. $postal_data['province'] .')'));
        }
        else {
          if (isset($_POST['edit']) && !isset($_GET['from'])) {
            $search_results .= theme('box', t('Your search yielded no results.'), '');
            print theme('page', $form . $search_results);
            return;
          }
        }
        

        $country_index = location_configured_countries();
        
        while ($row = db_fetch_object($res)) {
          $city_index_key = $row->country . $row->postal_code;
Ankur Rishi's avatar
Ankur Rishi committed
          $result_location = array('street' => !empty($row->street) ? $row->street : '',
                                  'additional' => !empty($row->additional) ? $row->additional : '',
                                  'city' => !empty($row->city) ? $row->city : $postal_codes[$city_index_key]['city'],
                                  'province' => !empty($row->province) ? $row->province : $postal_codes[$city_index_key]['province'],
                                  'postal_code' => $row->postal_code,
                                  'country' => $row->country,
                                  'distance' => $postal_codes[$city_index_key]['distance'],
                                 );
                               
Ankur Rishi's avatar
Ankur Rishi committed
          $extra = t('Local to ') . $result_location['postal_code'] .', ' . $result_location['city'] . ', '. $result_location['province'] .', '. $country_index[$result_location['country']] .' - '. $result_location['distance'] . ' ' . $edit['location']['distance_unit'] .' away.';
Ankur Rishi's avatar
Ankur Rishi committed
          $extra['location'] = t('Local to %place', array('%place' => l($result_location['city'] . ', '. $result_location['province'] .', '. $country_index[$result_location['country']], 'search/location', array(), 'postal_code='. urlencode($result_location['postal_code']) . '&country='. urlencode($result_location['country']) .'&distance='. urlencode($edit['location']['distance']) .'&distance_unit='. urlencode($edit['location']['distance_unit']))));
          if ($result_location['postal_code'] == $edit['location']['postal_code'] && $result_location['country'] == $edit['location']['country']) {
            $extra['distance'] = t('Result is <strong>also from %postal_code</strong>', array('%postal_code' => $result_location['postal_code']));
          }
          else {
            if (round($result_location['distance']) != 1) {
              $distance_unit = ($edit['location']['distance_unit'] == 'km') ? t('km') : t('miles');
            }
            else {
              $distance_unit = ($edit['location']['distance_unit'] == 'km') ? t('km') : t('mile');
            }
            $extra['distance'] = t('Approximately %distance from %location', array('%distance' => '<strong>'. round($result_location['distance']) .' '. $distance_unit .'</strong>', '%location' => $edit['location']['postal_code']));
          }
          
          
          $item = array('link' => url('node/'. $row->nid), 
                        'title' => $row->title, 
                        'type' => node_invoke($row, 'node_name'),
                        'user' => format_name($row), 
                        'date' => $row->created,
                        'snippet' => $row->teaser,
                        'extra' => $extra,
                        );
          $search_results .= theme('search_item', $item, $item->type);
        }
        
Ankur Rishi's avatar
Ankur Rishi committed
        if (empty($search_results)) {
          $search_results .= theme('box', t('Your search yielded no results.'), '');
        }
        else {
          $search_results = '<dl class="search-results">'. theme('box', $search_results_message, $search_results) .'</dl>';
          $search_results .= theme('pager', NULL, 15, 0, $edit['location']);
        }
        
      }
      else {
        $search_results .= theme('box', t('Your search yielded no results.'), '');
      }
    
    }
    else {
      if (!strlen($edit['location']['postal_code'])) {
        form_set_error('location][postal_code', t('For this search, you must enter a postal code.'));
      }
      if (!strlen($edit['location']['country']) || $edit['location']['country'] == 'xx') {
        form_set_error('location][country', t('For this search, you must select a country from the list.  If your country is not listed, then it is not supportable for this search.'));
      }
    }
  }
  //$end_time = microtime();
  //print 'Time for this NODE search to complete: '. _location_time_difference($end_time, $start_time) ."<br/>\n";
  print theme('page', $form . $search_results);
}

function location_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
  
  if ($op == 'validate' || $op == 'settings' || $op == 'validate' || $op == 'form post' || $op == 'insert' || $op == 'load' || $op == 'view') {
    // Determine strings that can be used in more than one place below.
    // Set the default workflow setting for all location fields for an 'event' node: 1... optional
    // This will only be used if the user hasn't gone into the default workflow page for events and changed it to something else
    // for each field.
    $field_names = array('name' => 'Location name', 'street' => 'Street location', 'city' => 'City', 'province' => 'State/Province', 'postal_code' => 'Postal code', 'country' => 'Country');
    $variable_prefix = 'location_';
    $variable_suffix = '_'. $node->type;
    $enabled = variable_get('location_'. $node->type, 0);
    
      $form  = form_checkbox(t('Enable for locations'), 'location_'. $node->type, 1, variable_get('location_'. $node->type, 0), t('Enable the submission of a location for content of this node type.  By checking this box and selecting fields for collection below, users will be able to add a full or partial address to each node of this type (depending on which fields you enable or require here).'));
      $form .= '<div style="margin-left: 40px">';
      $form .= form_radios(t('Location names'), 'location_name_'. $node->type, variable_get('location_name_'. $node->type, $default), array(t('Do not collect location names (e.g. place of business) for this node type.'), t('Allow location names for content of this type.'), t('Require location names for content of this type.')));
      $form .= form_radios(t('Street locations'), 'location_street_'. $node->type, variable_get('location_street_'. $node->type, $default), array(t('Do not collect a street location for content of this type.'), t('Allow street locations to be submitted for content of this type.'), t('Require street locations to be submitted for content of this type.')));
      $form .= form_radios(t('City names'), 'location_city_'. $node->type, variable_get('location_city_'. $node->type, 0), array(t('Do not collect city names for content of this type.'), t('Allow city names to be submitted for content of this type.'), t('Require city names to be submitted for content of this type.')));
      $form .=  form_radios('State/Province names', 'location_province_'. $node->type, variable_get('location_province_'. $node->type, 0), array(t('Do not collect state/province names for content of this type.'), t('Allow state/province names to be submitted for content of this type.'), t('Require state/province names to be submitted for content of this type.')));
      $form .= form_radios('Postal codes', 'location_postal_code_'. $node->type, variable_get('location_postal_code_'. $node->type, 0), array(t('Do not collect postal codes for content of this type.'), t('Allow postal codes to be submitted for content of this type.'), t('Require postal codes to be submitted for content of this type.')));
      $form .= form_radios('Country names', 'location_country_'. $node->type, variable_get('location_country_'. $node->type, 1), array(1 => t('Allow country names to be submitted for content of this type.'), 2 => t('Require country names to be submitted for content of this type.')), t('The selection of a country can be hidden and/or forced to a default country selection by going to the %location_settings and checking the box marked "Hide country selection" and selecting a country from the drop down select labelled "Default country selection".', array('%location_settings' => l(t('location settings page'), 'admin/settings/location'))));
      $form .= '</div>';
      $form = form_group(t('Locative information'), $form);
      return array(t('Locations') => $form);
    case 'form post':
      $location_fields = array();
      $required_fields = array();
      foreach (array_keys($field_names) as $field_name) {
        $workflow_setting = variable_get($variable_prefix . $field_name . $variable_suffix, $field_name == 'country' ? 1 : 0);
        if ($workflow_setting) {
          $location_fields[] = $field_name;
          if ($workflow_setting == 2) {
            $required_fields[] = $field_name;
          }
        }
      }
      
      if (!isset($node->location['country']) || $node->location['country'] == '') {
        $node->location['country'] = variable_get('location_default_country', 'us');
      }
      $suppressed_values = variable_get('location_suppress_country', 0) ? array('country' => variable_get('location_default_country', 'us')) : array();
      if ($_POST['op'] == t('Preview') || ($_POST['op'] == t('Submit') && form_get_errors())) {
        return location_form($location_fields, $node->location ? $node->location : array(), $required_fields, $suppressed_values);
        return location_form($location_fields, $node->location ? location_api2form($node->location) : array(), $required_fields, $suppressed_values);
      
    case 'validate':
      // For now, validation just makes sure that required fields have any value
      // If syntax specific checks are implemented for locations in the future, they can be called as well.
      foreach (array_keys($field_names) as $field_name => $display_name) {
        $workflow_setting = variable_get($variable_prefix . $field_name . $variable_suffix, $field_name == 'country' ? 1 : 0);
        if (variable_get($variable_prefix . $field_name . $variable_suffix, 0) == 2) {
          if (isset($node->location[$field_name]) && !strlen(trim($node->location[$field_name]))) {
            form_set_error('location]['. $field_name, t('The field %field is required.', array('%field' => "<em>$display_name</em>")));
          }
        }
      }
      break;
      
    case 'insert':
    case 'update':
      _location_save($node->location ? $node->location : array(), $node, 'node');
      $res = db_query("SELECT * FROM {location} WHERE type = 'node' AND oid = %d", $node->nid);
      $location = array();
      if ($node_location = db_fetch_object($res)) {
        //$location = object2array($node_location);
        unset($node_location->nid);
        $location = object2array($node_location);
      }

      if (count($location)) {
        if (isset($location['latitude'])) {
          $location['lat'] = $location['latitude'];
          $location['lon'] = $location['longitude'];
          unset($location['latitude']);
          unset($location['longitude']);
        }
      }
      return array('location' => $location);
      
    case 'view':
      if (variable_get('location_display_location', 1)) {
        if (isset($_POST) && ($_POST['op'] == t('Preview') || ($_POST['op'] == t('Submit') && form_get_errors()))) {
          if (count($node->location)) {
            $posted_location = location_form2api($node->location);
            if (!isset($posted_location['city']) || strlen(trim($posted_location['city'])) == 0) {
              $postal_data = location_get_postalcode_data($posted_location);
              $posted_location['city'] = isset($postal_data['city']) ? $postal_data['city'] : '';
            }
            if (!isset($posted_location['province']) || strlen(trim($posted_location['province'])) == 0) {
              $postal_data = isset($postal_data) ? $postal_data : location_get_postalcode_data($posted_location);
              $posted_location['province'] = isset($postal_data['province']) ? $postal_data['province'] : '';
            }
            $node->body .= theme('location', $posted_location, variable_get('location_suppress_country', 0) ? array('country') : array());
        else {
          if (count($node->location)) {
            $node->body .= theme('location', $node->location, variable_get('location_suppress_country', 0) ? array('country') : array());
          }
          if (!$teaser) {
            drupal_set_html_head(location_geocode_meta_tags($node->location));
          }
    case 'rss item':
      $items = array();
      if (!is_null($node->location['lat']) && !is_null($node->location['lon'])) {
        $items[] = array('key' => 'geo:Point', 'value' => "<geo:lat>\n  ". $node->location['lat'] ."</geo:lat>\n  <geo:long>". $node->location['lon'] ."</geo:long>\n");
        $items[] = array('key' => 'icbm:latitude', 'value' => $node->location['lat']);
        $items[] = array('key' => 'icbm:longitude', 'value' => $node->location['lon']);
Ankur Rishi's avatar
Ankur Rishi committed
        $items[] = array('key' => 'geourl:latitude', 'value' => $node->location['lat']);
        $items[] = array('key' => 'geourl:longitude', 'value' => $node->location['lon']);
        $items[] = array('key' => 'latitude', 'value' => $node->location['lat']);
        $items[] = array('key' => 'longitude', 'value' => $node->location['lon']);
      }
      return $items;
      break;
 * Returns an array of countries whose locations will be allowed entry
 * into the site's location system.  The array returned is an associative
 * array where the keys are the ISO codes (see location.inc) and the values
 * are the shortened English names.
 */
function location_get_configured_countries() {
  $configured_countries = variable_get('location_configured_countries', array('us'));
  $configured_countries = is_array($configured_countries) ? $configured_countries : array('us');
  return $configured_countries;
}


/**
 * Implementation of hook_settings().
 *
 */
function location_settings() {
  
  $supported_countries = _location_supported_countries();

  $default_country = variable_get('location_default_country', '');
  
  $configured_countries = location_get_configured_countries();
  
  $iso_list_sorted = _location_get_iso3166_list();
  array_multisort($iso_list_sorted);
  $iso_list_sorted = array_merge(array('' => ''), $iso_list_sorted);
  
  if ($default_country && in_array($default_country, array_keys($supported_countries)) && !in_array($default_country, $configured_countries)) {
    variable_get('location_configured_countries', array('us'));
    $configured_countries[] = $default_country;
    variable_set('location_configured_countries', $configured_countries);
  }

  $form .= form_select(t('Default country selection'), 'location_default_country', variable_get('location_default_country', 'us'), $iso_list_sorted, t('This will be the country that is automatically selected when a location form is served for a new location.'));
  //print 'variable_get(\'location_search_distance_unit\', 0) == '. variable_get('location_search_distance_unit', 0) ."<br/>\n";
  $form .= form_checkbox(t('Hide country selection'), 'location_suppress_country', 1, variable_get('location_suppress_country', 0), t('If your site is specific to a country and you would like to hide the country field on search forms and content creation forms, check this box.  Doing so will automatically assume the country to be the country you have chosen for the \'default country selection\' above.'));
  
  $form .= form_radios(t('Distance unit for location-based searches'), 'location_search_distance_unit', variable_get('location_search_distance_unit', 0), array(0 => t('Allow both miles and kilometers.'), 'mile' => t('Only allow a search-radius to be specified in miles'), 'km' => t('Only allow a search-radius to be specified in kilometers')), t('Select the distance unit that applies when users search for content by a specified location and search-radius.'));
  
  $form .= form_radios(t('Toggle location display'), 'location_display_location', variable_get('location_display_location', 1), array(0 => t('Disable the display of locations.'), 1 => t('Enable the display of locations locations.')), t('If you are interested in turning off locations and having a custom theme control their display, you may want to disable the display of locations so your theme can take over them.'));
  
  $form .= form_radios('User locations', 'location_user', variable_get('location_user', 0), array('Disable', 'Enable'), t('Collect user addresses (partial or full) if users wish to submit them for their user accounts.'));
  $form .= form_checkboxes(t('Enable all <em>available</em> features for locations from the following countries'), 'location_configured_countries', location_get_configured_countries(), $supported_countries, 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.'));
function location_user($op, &$edit, &$user, $category = NULL) {
  if (!variable_get('location_user', 0)) {
    return;
  }
  
  if ($op == 'form' && $category == 'account') {
    return array(t('location') => array('title' => t('Location'), 'data' => location_form(array('street', 'city', 'province', 'postal_code', 'country'), (isset($user->location) && !_location_is_empty($user->location)) ? location_api2form($user->location) : array('country' => variable_get('location_default_country', 'us')), array(), array(), t('Enter as much of your address as you are comfortable with.  Your address will only be viewable by those who have the appropriate permissions.  The site will be able to automatically link you to driving directions and other features if it already knows your address.')), 'weight' => 1));
    $res = db_query("SELECT * FROM {location} WHERE type = 'user' AND oid = %d", $user->uid);
    if ($location = db_fetch_object($res)) {
      $user->location = object2array($location);
    }
    else {
      $user->location = array();
    }
  }
  
  
  if ($op == 'update' || $op == 'insert') {
    _location_save($edit['location'] ? $edit['location'] : array(), $user, 'user');
    unset($edit['location']);
  if ($op == 'view' && (user_access('administer users') || $GLOBALS['user']->uid == $user->uid) && variable_get('location_display_location', 1)) {
    return array('' => theme('location', $user->location));
  }
  
/**
 * Saves a location.  Needs a $user or $node object.
 * 
 * @param $posted_location
function _location_save($posted_location, &$user_or_node, $type = 'node') {
  $field = ($type == 'node' ? 'nid': 'uid');
  if (isset($posted_location) && count($posted_location)) {
    foreach ($posted_location as $posted_field => $posted_value) {
      $posted_location[$posted_field] = trim(strip_tags($posted_location[$posted_field]));
    }
    $posted_location = location_form2api($posted_location);

    if (isset($posted_location['postal_code']) && isset($posted_location['country'])) {
      if ($data = location_get_postalcode_data($posted_location)) {
        $posted_location['lat'] = $data['lat'];
        $posted_location['lon'] = $data['lon'];
        $posted_location['city'] = (!isset($posted_location['city']) || strlen($posted_location['city']) == 0) ? $data['city'] : $posted_location['city'];
        $posted_location['province'] = (!isset($posted_location['province']) || strlen($posted_location['province']) == 0) ? $data['province'] : $posted_location['province'];
      }
    }
              
    if (isset($posted_location['lat']) && isset($posted_location['lon'])) {
       db_query("REPLACE INTO {location} (type, oid, name, street, additional, city, province, postal_code, country, latitude, longitude) VALUES ('%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%f', '%f')",
              $type, 
              $user_or_node->$field, 
              (!isset($posted_location['name']) || is_null($posted_location['name'])) ? '' : $posted_location['name'],
              (!isset($posted_location['street']) || is_null($posted_location['street'])) ? '' : $posted_location['street'],
              (!isset($posted_location['additional']) || is_null($posted_location['additional'])) ? '' : $posted_location['additional'],
              (!isset($posted_location['city']) || is_null($posted_location['city'])) ? '' : $posted_location['city'],
              (!isset($posted_location['province']) || is_null($posted_location['province'])) ? '' : $posted_location['province'],
              (!isset($posted_location['postal_code']) || is_null($posted_location['postal_code'])) ? '' : $posted_location['postal_code'],
              (!isset($posted_location['country']) || is_null($posted_location['country'])) ? NULL : $posted_location['country'],
              $posted_location['lat'],
              $posted_location['lon']
            );     
    }
    else {
      db_query("REPLACE INTO {location} (type, oid, name, street, additional, city, province, postal_code, country) VALUES ('%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s')",
              $type,
              $user_or_node->$field, 
              (!isset($posted_location['name']) || is_null($posted_location['name'])) ? '' : $posted_location['name'],
              (!isset($posted_location['street']) || is_null($posted_location['street'])) ? '' : $posted_location['street'],
              (!isset($posted_location['additional']) || is_null($posted_location['additional'])) ? '' : $posted_location['additional'],
              (!isset($posted_location['city']) || is_null($posted_location['city'])) ? '' : $posted_location['city'],
              (!isset($posted_location['province']) || is_null($posted_location['province'])) ? '' : $posted_location['province'],
              (!isset($posted_location['postal_code']) || is_null($posted_location['postal_code'])) ? '' : $posted_location['postal_code'],
              (!isset($posted_location['country']) || is_null($posted_location['country'])) ? NULL : $posted_location['country']
            );
    }
  }
}