You are here

location_feeds.module in Location Feeds 7

Same filename and directory in other branches
  1. 6 location_feeds.module

This module provides location mappers to feed importers.

@author: Elliott Foster

File

location_feeds.module
View source
<?php

/**
 * @file
 *
 * This module provides location mappers to feed importers.
 *
 * @author: Elliott Foster
 */

/**
 * Implements hook_enable().
 */
function location_feeds_enable() {
  cache_clear_all('plugins:feeds:plugins', 'cache');
}

/**
 * Implements feeds_node_processor_target_alter().
 *
 * @param $targets array of target fields
 * @param $entity_type
 * @param $bundle_name
 */
function location_feeds_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
  if ($entity_type == 'node') {

    // location.module logic
    $settings = variable_get('location_settings_node_' . $bundle_name, array());

    // Only add fields when collecting locations
    if (isset($settings['multiple']['max']) && $settings['multiple']['max'] > 0) {
      _location_feeds_location($targets, $settings);
    }

    // Location cck logic.
    if (module_exists('location_cck')) {
      $fields = field_read_fields(array(
        'module' => 'location_cck',
      ));
      $location_fields = _location_feeds_fields();
      foreach ($fields as $field_name => $field) {
        _location_feeds_fill_targets($targets, 'location_cck', $field_name, $location_fields);
      }
    }
  }
  else {
    if ($entity_type == 'user') {
      $settings = variable_get('location_settings_user', array());

      // Only add fields when collecting locations
      if (isset($settings['multiple']['max']) && $settings['multiple']['max'] > 0) {
        _location_feeds_location($targets, $settings);
      }
    }
  }
}

/**
 * Helper function to handle node and user locations
 *
 * For sub elements we use the '][' construct
 *
 * @param $targets
 * @param $settings
 */
function _location_feeds_location(&$targets, $settings) {
  $location_fields = _location_feeds_fields();

  // We need the collect settings
  $fields = $settings['form']['fields'];

  // locpick is a compound field. So split it
  $fields['locpick][user_latitude'] = $fields['locpick'];
  $fields['locpick][user_longitude'] = $fields['locpick'];
  unset($fields['locpick']);
  foreach ($fields as $field => $values) {
    if (!$values['collect']) {
      unset($location_fields[$field]);
    }
  }
  _location_feeds_fill_targets($targets, 'location', 'locations', $location_fields);
}

/**
 * Helper function to add target fields
 *
 * @param $targets
 * @param $module
 *   Module name providing the field.
 * @param $field_name
 *   Field name where values are supposed to get stored to.
 * @param $sub_fields
 *   Location elements for the given $field_name
 */
function _location_feeds_fill_targets(&$targets, $module, $field_name, $sub_fields) {
  foreach ($sub_fields as $sub_field => $value) {
    $callback = 'location_feeds_set_target';
    if ($sub_field == 'country') {
      $callback = 'location_feeds_set_country';
    }
    else {
      if (strpos($sub_field, 'locpick]') !== FALSE) {
        $callback = 'location_feeds_set_point';
      }
    }
    $targets[$field_name . ':' . $sub_field] = array(
      'name' => $module . " module: " . $field_name . '.' . t('@label', array(
        '@label' => $value,
      )),
      'callback' => $callback,
      'description' => t('The @label for the location of the node.', array(
        '@label' => $sub_field,
      )),
    );
  }

  // support georss
  $targets[$field_name . ':georss:point'] = array(
    'name' => $module . " module:" . $field_name . " georss:point",
    'callback' => 'location_feeds_set_georss_point',
    'description' => t('Map a georss point to location points'),
  );
}

/**
 * Helper function to get to manage target fields
 *
 * @return array of key/value field name/field label
 */
function _location_feeds_fields() {
  static $fields;
  if (isset($fields)) {
    return $fields;
  }
  $fields = location_field_names(TRUE);
  unset($fields['locpick']);
  $fields['locpick][user_latitude'] = t("Latitude");
  $fields['locpick][user_longitude'] = t("Longitude");

  // province_name / country_name / map_link are display fields
  unset($fields['province_name']);
  unset($fields['country_name']);
  unset($fields['map_link']);
  return $fields;
}

/**
 * Implements feed_set_target().
 *
 * @param $source
 *  Field mapper source settings.
 * @param $entity
 *   Either a user or node object dpending on where this is called
 * @param $target
 *   When targeting sub arrays the '][' is used to drill down.
 *   Note that this implementation is lazy ... we assume just depth=2
 * @param $value
 * @return object
 */
function location_feeds_set_target($source, $entity, $target, $value) {
  list($field_name, $sub_field) = explode(':', $target);
  if (strpos($sub_field, '][') !== FALSE) {
    list($sub_field, $last_field) = explode('][', $sub_field, 2);
  }
  if (!is_array($value)) {
    $value = array(
      $value,
    );
  }

  // Check if this is a cck field since they're added to the node
  // differently.
  $cck = preg_match('/^field_.+/', $target);
  foreach ($value as $i => $val) {
    $val = trim($val);

    // location_cck has issues with empty fields, so bail if we find one.
    if ($val !== FALSE && $val !== 0 && empty($val)) {
      continue;
    }
    if (isset($last_field)) {
      if ($cck) {
        if (!isset($entity->{$field_name}['und'][$i]['location_settings'])) {
          $entity->{$field_name}['und'][$i]['location_settings'] = location_feeds_get_field_info($field_name);
        }
        $entity->{$field_name}['und'][$i][$sub_field][$last_field] = $val;
      }
      else {
        $entity->{$field_name}[$i][$sub_field][$last_field] = $val;
      }
    }
    else {
      if ($cck) {
        if (!isset($entity->{$field_name}['und'][$i]['location_settings'])) {
          $entity->{$field_name}['und'][$i]['location_settings'] = location_feeds_get_field_info($field_name);
        }
        $entity->{$field_name}['und'][$i][$sub_field] = $val;
      }
      else {
        $entity->{$field_name}[$i][$sub_field] = $val;
      }
    }
  }
  return $entity;
}

/**
 * Set the country and attempt to support non-iso country imports
 *
 * @param $source
 *  Field mapper source settings.
 * @param $entity
 *   Either a user or node object dpending on where this is called
 * @param $target
 *   When targeting sub arrays the '][' is used to drill down.
 *   Note that this implementation is lazy ... we assume just depth=2
 * @param $value
 * @return object
 */
function location_feeds_set_country($source, $entity, $target, $value) {
  module_load_include('inc', 'location', 'location');
  list($field_name, $sub_field) = explode(':', $target);
  static $iso_list = array();
  if (!is_array($value)) {
    $value = array(
      $value,
    );
  }

  // Check if this is a cck field since they're added to the node
  // differently.
  $cck = preg_match('/^field_.+/', $target);
  foreach ($value as $i => $val) {
    $val = trim($val);

    // if the country is in iso format or close to it, store
    // it, else try to figure out the iso format
    $isoval = $val;
    if (location_standardize_country_code($isoval)) {
      if ($cck) {
        if (!isset($entity->{$field_name}['und'][$i]['location_settings'])) {
          $entity->{$field_name}['und'][$i]['location_settings'] = location_feeds_get_field_info($field_name);
        }
        $entity->{$field_name}['und'][$i][$sub_field] = $isoval;
      }
      else {
        $entity->{$field_name}[$i][$sub_field] = $isoval;
      }
    }
    else {

      // only load this once...
      if (sizeof($iso_list) == 0) {
        $iso_list = location_get_iso3166_list();
      }
      $keys = array_keys($iso_list, $val);
      if (isset($keys[0])) {
        if ($cck) {
          if (!isset($entity->{$field_name}['und'][$i]['location_settings'])) {
            $entity->{$field_name}['und'][$i]['location_settings'] = location_feeds_get_field_info($field_name);
          }
          $entity->{$field_name}['und'][$i][$sub_field] = $keys[0];
        }
        else {
          $entity->{$field_name}[$i][$sub_field] = $keys[0];
        }
      }
    }
  }
  return $entity;
}

/**
 * Sets a latitude or longitude point for the node
 *  and attempts to recognize either decimal or DMS
 *  notation.
 *
 * @param $source
 *  Field mapper source settings.
 * @param object $entity
 * @param string $target
 *  The target that invoked this
 * @param $value
 * @return $entity
 */
function location_feeds_set_point($source, $entity, $target, $value) {
  list($field_name, $sub_field) = explode(':', $target);
  if (strpos($sub_field, '][') !== FALSE) {
    list($sub_field, $last_field) = explode('][', $sub_field, 2);
  }
  if (!is_array($value)) {
    $value = array(
      $value,
    );
  }

  // Check if this is a cck field since they're added to the node
  // differently.
  $cck = preg_match('/^field_.+/', $target);
  foreach ($value as $i => $val) {
    $val = trim($val);

    // Attempt to set a value for DMS notation.
    if (!is_numeric($val)) {
      $neg = FALSE;
      if (strpos($val, '-') === 0) {
        $neg = TRUE;
      }
      $val = trim(preg_replace('/[^\\d\\s\\.WSws]/', '', $val));
      $dms = explode(' ', $val);

      // Account for '77° 02' 15.691" W' format.
      if (count($dms) == 4) {
        if ($dms[3] == 'W' || $dms[3] == 'w' || $dms[3] == 'S' || $dms[3] == 's') {
          $neg = TRUE;
          unset($dms[3]);
        }
      }
      if (count($dms) == 3) {
        $val = (abs($dms[0]) + $dms[1] / 60 + $dms[2] / 3600) * ($neg ? -1 : 1);
      }
    }
    if (isset($last_field)) {
      if ($cck) {
        if (!isset($entity->{$field_name}['und'][$i]['location_settings'])) {
          $entity->{$field_name}['und'][$i]['location_settings'] = location_feeds_get_field_info($field_name);
        }
        $entity->{$field_name}['und'][$i][$sub_field][$last_field] = $val;
      }
      else {
        $entity->{$field_name}[$i][$sub_field][$last_field] = $val;
      }
    }
    else {
      if ($cck) {
        if (!isset($entity->{$field_name}['und'][$i]['location_settings'])) {
          $entity->{$field_name}['und'][$i]['location_settings'] = location_feeds_get_field_info($field_name);
        }
        $entity->{$field_name}['und'][$i][$sub_field] = $val;
      }
      else {
        $entity->{$field_name}[$i][$sub_field] = $val;
      }
    }
  }
  return $entity;
}

/**
 * Sets a georss:point value for the node
 *
 * @param $source
 *  Field mapper source settings.
 * @param $entity
 *  Either a user or node object depending on where this is called
 * @param $target
 *  The target that invoked this
 * @param $value
 * @return object
 */
function location_feeds_set_georss_point($source, $entity, $target, $value) {
  list($field_name, $georss, $point) = explode(':', $target);
  if (!is_array($value)) {
    $value = array(
      $value,
    );
  }

  // Check if this is a cck field since they're added to the node
  // differently.
  $cck = preg_match('/^field_.+/', $target);
  foreach ($value as $i => $val) {
    $val = trim($val);
    list($lat, $long) = explode(' ', $val);
    if ($cck) {
      if (!isset($entity->{$field_name}['und'][$i]['location_settings'])) {
        $entity->{$field_name}['und'][$i]['location_settings'] = location_feeds_get_field_info($field_name);
      }
      $entity->{$field_name}['und'][$i]['latitude'] = $lat;
      $entity->{$field_name}['und'][$i]['longitude'] = $long;
    }
    else {
      $entity->{$field_name}[$i]['latitude'] = $lat;
      $entity->{$field_name}[$i]['longitude'] = $long;
    }
  }
  return $entity;
}

/**
 * Returns location field level settings.
 *
 * @param $field_name
 *  The field name to return info for.
 * @retrun
 *  The field info array.
 */
function location_feeds_get_field_info($field_name) {
  $field_settings = field_info_field($field_name);
  return $field_settings['settings']['location_settings'];
}

Functions

Namesort descending Description
location_feeds_enable Implements hook_enable().
location_feeds_feeds_processor_targets_alter Implements feeds_node_processor_target_alter().
location_feeds_get_field_info Returns location field level settings.
location_feeds_set_country Set the country and attempt to support non-iso country imports
location_feeds_set_georss_point Sets a georss:point value for the node
location_feeds_set_point Sets a latitude or longitude point for the node and attempts to recognize either decimal or DMS notation.
location_feeds_set_target Implements feed_set_target().
_location_feeds_fields Helper function to get to manage target fields
_location_feeds_fill_targets Helper function to add target fields
_location_feeds_location Helper function to handle node and user locations