You are here

function location_nodeapi in Location 5

Implementation of hook_nodeapi().

File

./location.module, line 783

Code

function location_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
  if (!variable_get('location_maxnum_' . $node->type, 0)) {
    return;
  }
  switch ($op) {
    case 'validate':
      foreach ($node->locations as $index => $location) {

        // 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 (location_field_names() as $field_name => $display_name) {
          $workflow_setting = variable_get('location_' . $field_name . '_' . $node->type, $field_name == 'country' ? 1 : 0);

          // We only enforce required fields on the first location if there are multiple locations
          if ($index == 0) {
            if (variable_get('location_' . $field_name . '_' . $node->type, 0) == 2) {
              if (isset($node->locations[$index][$field_name]) && !strlen(trim($node->locations[$index][$field_name]))) {
                form_set_error('locations][' . $index . '][' . $field_name, t('The field %field is required.', array(
                  '%field' => $display_name,
                )));
              }
            }
          }
          $node->locations[$index][$field_name] = trim($node->locations[$index][$field_name]);
        }

        // Check if the (province, country) pair is valid
        if (isset($node->locations[$index]['province']) && !empty($node->locations[$index]['province']) && $node->locations[$index]['province'] != 'xx' && isset($node->locations[$index]['country']) && !empty($node->locations[$index]['country']) && $node->locations[$index]['country'] != 'xx') {
          $province_list_function = 'location_province_list_' . $node->locations[$index]['country'];
          if (function_exists($province_list_function)) {
            $translated_location = location_form2api($node->locations[$index]);
            if (!in_array($translated_location['province'], array_keys($province_list_function()))) {
              form_set_error('locations][' . $index . '][province', t('Please make sure to select a state/province from the country you have selected.'));
            }
          }
        }

        // Check if submitted lat/lon are valid
        if (user_access('submit latitude/longitude')) {
          if (!strlen(trim($node->locations[$index]['latitude'])) && strlen(trim($node->locations[$index]['longitude'])) || strlen(trim($node->locations[$index]['latitude'])) && !strlen(trim($node->locations[$index]['longitude']))) {
            form_set_error('locations][' . $index . '][latitude', t('You must fill out both longitude and latitude or you must leave them both blank.'));
            form_set_error('locations][' . $index . '][longitude', NULL);
          }
          elseif (strlen(trim($node->locations[$index]['latitude'])) && strlen(trim($node->locations[$index]['longitude']))) {
            if (!is_numeric($node->locations[$index]['latitude']) || $node->locations[$index]['latitude'] > 90.0 || $node->locations[$index]['latitude'] < -90.0) {
              form_set_error('locations][' . $index . '][latitude', t('Your latitude must be a numeric value between -90.0 and 90.0.'));
            }
            if (!is_numeric($node->locations[$index]['longitude']) || $node->locations[$index]['longitude'] > 180.0 || $node->locations[$index]['longitude'] < -180.0) {
              form_set_error('locations][' . $index . '][longitude', t('Your longitude must be a numeric value between -180.0 and 180.0.'));
            }
          }
        }
      }
      break;
    case 'insert':
    case 'update':

      // handy to have these field names later
      $location_fields = array();
      $required_fields = array();
      foreach (array_keys(location_field_names()) as $field_name) {
        $workflow_setting = variable_get('location_' . $field_name . '_' . $node->type, $field_name == 'country' ? 1 : 0);
        if ($workflow_setting) {
          $location_fields[] = $field_name;
          if ($workflow_setting == 2) {
            $required_fields[] = $field_name;
          }
        }
      }
      foreach ($node->locations as $index => $location) {
        $node->locations[$index] = location_form2api($node->locations[$index]);
        if (user_access('submit latitude/longitude')) {
          $node->locations[$index]['latitude'] = trim($node->locations[$index]['latitude']);
          $node->locations[$index]['longitude'] = trim($node->locations[$index]['longitude']);

          // At this point, we know that the user has permission to submit lat/lons and that the
          // 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[$index]['latitude']) && !empty($node->locations[$index]['longitude'])) {
            if (($data = location_latlon_exact($node->locations[$index])) && _location_floats_are_equal(floatval($node->locations[$index]['latitude']), floatval($data['lat'])) && _location_floats_are_equal(floatval($node->locations[$index]['longitude']), floatval($data['lon']))) {
              $node->locations[$index]['lat'] = $node->locations[$index]['latitude'];
              $node->locations[$index]['lon'] = $node->locations[$index]['longitude'];
              $node->locations[$index]['source'] = LOCATION_LATLON_GEOCODED_EXACT;
            }
            elseif (($data = location_get_postalcode_data($node->locations[$index])) && _location_floats_are_equal(floatval($node->locations[$index]['latitude']), floatval($data['lat'])) && _location_floats_are_equal(floatval($node->locations[$index]['longitude']), floatval($data['lon']))) {
              $node->locations[$index]['lat'] = $node->locations[$index]['latitude'];
              $node->locations[$index]['lon'] = $node->locations[$index]['longitude'];
              $node->locations[$index]['source'] = LOCATION_LATLON_GEOCODED_APPROX;
            }
            else {
              $node->locations[$index]['lat'] = $node->locations[$index]['latitude'];
              $node->locations[$index]['lon'] = $node->locations[$index]['longitude'];
              $node->locations[$index]['source'] = LOCATION_LATLON_USER_SUBMITTED;
            }
          }
          else {
            if ($data = location_latlon_exact($node->locations[$index])) {
              $node->locations[$index]['latitude'] = $data['lat'];
              $node->locations[$index]['longitude'] = $data['lon'];
              $node->locations[$index]['lat'] = $data['lat'];
              $node->locations[$index]['lon'] = $data['lon'];
              $node->locations[$index]['source'] = LOCATION_LATLON_GEOCODED_EXACT;
            }
            elseif ($data = location_get_postalcode_data($node->locations[$index])) {
              $node->locations[$index]['latitude'] = $data['lat'];
              $node->locations[$index]['longitude'] = $data['lon'];
              $node->locations[$index]['lat'] = $data['lat'];
              $node->locations[$index]['lon'] = $data['lon'];
              $node->locations[$index]['source'] = LOCATION_LATLON_GEOCODED_APPROX;
            }
            else {
              unset($node->locations[$index]['latitude']);
              unset($node->locations[$index]['longitude']);
              unset($node->locations[$index]['lat']);
              unset($node->locations[$index]['lon']);
              $node->locations[$index]['source'] = LOCATION_LATLON_UNDEFINED;
            }
          }
        }
        else {

          // If the user does NOT have permission to explicitly set a lat/lon for the given location, we still want to check
          // whether this location was previously assigned a lat/lon manually or whether it was determined via geocoding.
          // If the lat/lon was determined from geocoding, then we will want to update the lat/lon using postal codes.
          // If the lat/lon was user-submitted, then we don't want to allow the current editor to change the lat/lon
          if ($node->nid) {
            $result = db_query("SELECT * FROM {location} WHERE type = 'node' AND eid = %d", $node->nid);
            if ($location = db_fetch_object($result)) {
              if ($location->source != LOCATION_LATLON_USER_SUBMITTED) {
                if ($data = location_latlon_exact($node->locations[$index])) {
                  $node->locations[$index]['lat'] = $data['lat'];
                  $node->locations[$index]['lon'] = $data['lon'];
                  $node->locations[$index]['latitude'] = $data['lat'];
                  $node->locations[$index]['longitude'] = $data['lon'];
                  $node->locations[$index]['source'] = LOCATION_LATLON_GEOCODED_EXACT;
                }
                elseif ($data = location_get_postalcode_data($node->location)) {
                  $node->locations[$index]['lat'] = $data['lat'];
                  $node->locations[$index]['lon'] = $data['lon'];
                  $node->locations[$index]['latitude'] = $data['lat'];
                  $node->locations[$index]['longitude'] = $data['lon'];
                  $node->locations[$index]['source'] = LOCATION_LATLON_GEOCODED_APPROX;
                }
                else {
                  unset($node->locations[$index]['lat']);
                  unset($node->locations[$index]['lon']);
                  unset($node->locations[$index]['latitude']);
                  unset($node->locations[$index]['longitude']);
                  $node->locations[$index]['source'] = LOCATION_LATLON_UNDEFINED;
                }
              }
            }
          }
          elseif ($data = location_latlon_exact($node->locations[$index])) {
            $node->locations[$index]['lat'] = $data['lat'];
            $node->locations[$index]['lon'] = $data['lon'];
            $node->locations[$index]['latitude'] = $data['lat'];
            $node->locations[$index]['longitude'] = $data['lon'];
            $node->locations[$index]['source'] = LOCATION_LATLON_GEOCODED_EXACT;
          }
          elseif ($data = location_get_postalcode_data($node->location)) {
            $node->locations[$index]['lat'] = $data['lat'];
            $node->locations[$index]['lon'] = $data['lon'];
            $node->locations[$index]['latitude'] = $data['lat'];
            $node->locations[$index]['longitude'] = $data['lon'];
            $node->locations[$index]['source'] = LOCATION_LATLON_GEOCODED_APPROX;
          }
          else {
            unset($node->locations[$index]['lat']);
            unset($node->locations[$index]['lon']);
            unset($node->locations[$index]['latitude']);
            unset($node->locations[$index]['longitude']);
            $node->locations[$index]['source'] = LOCATION_LATLON_UNDEFINED;
          }
        }

        // If no city and/or province were supplied in the address (whether the user left it blank or whether the user did not have the option
        // of entering them) then we want to use the data we have based strictly on the postal code.
        if ($data = location_get_postalcode_data($node->locations[$index])) {
          $node->locations[$index]['city'] = !isset($node->locations[$index]['city']) || strlen($node->locations[$index]['city']) == 0 ? $data['city'] : $node->locations[$index]['city'];
          $node->locations[$index]['province'] = !isset($node->locations[$index]['province']) || strlen($node->locations[$index]['province']) == 0 ? $data['province'] : $node->locations[$index]['province'];
        }

        // Finally, if there are multiple forms, it's possible for the default country to still be selected with all the other fields blank, and
        // very possible that the user didn't intend to fill out that default country value.  So, we use the following rules to determine whether
        // a location is bogus or not:
        // IF $index == 0, then
        //   --> if no other fields are enabled, we consider the country to be important and save the location
        //   --> if other fields are enabled, but are all left blank, we consider the location empty and don't save
        //   --> if latitude and longitude coordinates are entered then we save the location
        // IF $index != 1, then
        //   --> if country is default and no other fields are saved, we don't save
        //   --> if latitude and longitude coordinates are entered then we save the location
        $keep = FALSE;
        if (!empty($node->locations[$index]['country']) || !empty($node->locations[$index]['latitude']) && !empty($node->locations[$index]['longitude'])) {
          if ($index == 0) {

            // first location
            if (in_array('country', $required_fields)) {
              $keep = TRUE;
            }
            if (isset($node->locations[$index]['latitude']) && isset($node->locations[$index]['longitude'])) {
              $keep = TRUE;
            }
            elseif (count($location_fields) == 1) {
              $keep = TRUE;
            }
            else {

              // Else we have to check all the other fields to make sure they're not empty
              foreach ($location_fields as $field) {
                if ($field != 'country' && !empty($node->locations[$index][$field])) {
                  $keep = TRUE;
                  break;
                }
              }
            }
          }
          else {

            // not first location
            foreach ($location_fields as $field) {
              if ($field == 'country' && $node->locations[$index][$field] != variable_get('location_default_country', 'us')) {
                $keep = TRUE;
                break;
              }
              elseif (!empty($node->locations[$index]['latitude']) && !empty($node->locations[$index]['longitude'])) {
                $keep = TRUE;
                break;
              }
              elseif ($field != 'country' && !empty($node->locations[$index][$field])) {
                $keep = TRUE;
                break;
              }
            }
          }
        }
        if ($keep) {
          _location_save($node->locations[$index] ? $node->locations[$index] : array(), $node, 'node');
        }
        else {
          if ($node->locations[$index]['lid']) {
            db_query('DELETE FROM {location} WHERE lid = %d', $node->locations[$index]['lid']);
            location_invoke_locationapi($node->locations[$index], 'delete');
          }
        }
      }
      break;
    case 'load':
      $loaded_data = location_load_locations('node', $node);
      return $loaded_data;
    case 'view':
      if (variable_get('location_display_location', 1)) {
        if (isset($_POST) && ($_POST['op'] == t('Preview') || $_POST['op'] == t('Submit') && form_get_errors())) {
          $posted_locations = array();
          foreach ($node->locations as $index => $location) {
            if (count($node->locations[$index])) {
              $posted_locations[$index] = location_form2api($node->locations[$index]);
              if (!isset($posted_locations[$index]['city']) || strlen(trim($posted_locations[$index]['city'])) == 0) {
                $postal_data = location_get_postalcode_data($posted_locations[$index]);
                $posted_locations[$index]['city'] = isset($postal_data['city']) ? $postal_data['city'] : '';
              }
              if (!isset($posted_locations[$index]['province']) || strlen(trim($posted_locations[$index]['province'])) == 0) {
                $postal_data = isset($postal_data) ? $postal_data : location_get_postalcode_data($posted_locations[$index]);
                $posted_locations[$index]['province'] = isset($postal_data['province']) ? $postal_data['province'] : '';
              }
            }
          }
          if ($output = theme('locations', $posted_locations, variable_get('location_suppress_country', 0) ? array(
            'country',
          ) : array())) {
            $node->content['locations']['#value'] .= $output;
          }
        }
        else {
          if ($themed_locations = theme('locations', $node->locations, variable_get('location_suppress_country', 0) ? array(
            'country',
          ) : array())) {
            $node->content['locations']['#value'] .= $themed_locations;
          }

          //if (!$teaser) {

          //drupal_set_html_head(location_geocode_meta_tags($node->location));

          //}
        }
      }
      if (variable_get('location_addanother_' . $node->type, 0) && count($node->locations) < variable_get('location_maxnum_' . $node->type, 0) && !$teaser && node_access('update', $node)) {
        $node->content['locations']['#value'] .= drupal_get_form('location_extra_form', $node);
      }
      break;
    case 'rss item':
      $items = array();
      if (is_array($node->locations)) {
        foreach ($node->locations as $index => $location) {
          if (!is_null($node->locations[$index]['lat']) && !is_null($node->locations[$index]['lon'])) {

            //$items[] = array('key' => 'geo:Point', 'value' => "<geo:lat>\n  ". $node->locations[$index]['lat'] ."</geo:lat>\n  <geo:long>". $node->locations[$index]['lon'] ."</geo:long>\n", 'namespace' => array('geo' => 'xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"'));
            $items[] = array(
              'key' => 'geo:Point',
              'namespace' => array(
                'geo' => 'xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"',
              ),
              'value' => array(
                array(
                  'key' => 'geo:lat',
                  'value' => $node->locations[$index]['lat'],
                ),
                array(
                  'key' => 'geo:lon',
                  'value' => $node->locations[$index]['lon'],
                ),
              ),
            );

            //$items[] = array('key' => 'geourl:latitude', 'value' => $node->locations[$index]['lat'], 'namespace' => array('geourl' => 'xmlns:geourl="http://geourl.org/rss/module/"'));

            //$items[] = array('key' => 'geourl:longitude', 'value' => $node->locations[$index]['lon']);
          }
        }
      }
      return $items;
      break;
  }
}