You are here

field_extract.module in Field Extract Values 7

Field extract - Extension of the Field API to allow proper extraction of field values from entities

File

field_extract.module
View source
<?php

/**
 * @file
 * Field extract - Extension of the Field API to allow proper extraction of field values from entities
 */

/**
 * Fetch a single field value from an entity
 *
 * @param $entity_type
 * The type of the entity from which the value is being extracted.
 *
 * @param $entity
 * The entity the field is part of, from which to extract the value.
 *
 * @param $field_name
 * The field_name of the field to extract the value from.
 *
 * @param $delta
 * Optional delta of value to extracted, defaults to 0, which is the first value, and only
 * value for single value fields.
 *
 * @param $options
 * Optional other options that could be applied to the value being extracted. See field_extract_values()
 */
function field_extract_value($entity_type, $entity, $field_name, $delta = 0, array $options = array()) {
  $options['delta'] = $delta;
  return field_extract_values($entity_type, $entity, $field_name, $options);
}

/**
 * Fetch values of an entity's field
 *
 * @param $entity_type
 * The type of the entity from which the values are being extracted.
 *
 * @param $entity
 * The entity the field is part of, from which to extract the values.
 *
 * @param $field_name
 * The field_name of the field to extract the values from.
 *
 * @param $options
 * An optional array of options that control what and how the values are extracted
 *  - delta     if included returns only the specified value from a multi-value field
 *              otherwise all values are returned (in the form specified later).
 *  - key       returns a specific array element of the item, rather than the default
 *              value for the type. So for a 'body' field you could specify 'safe_summary'.
 *              When there is a 'formatter' has no effect.
 *  - formatter Forces a formatted version of the field to be returned, unlike field_view_field()
 *              onely the formatted value is returned, without a label attached.
 *  - langcode  the language to use if not using the default for the entity or site.
 *  - [other]   any other field type specific value. For example the date field type
 *              can have a 'format' field.
 *
 * If the value being fetched is an entity the whole entity will be fetched by default.
 */
function field_extract_values($entity_type, $entity, $field_name, array $options = array()) {
  if (!is_object($entity)) {
    return FALSE;
  }
  if (!property_exists($entity, $field_name)) {
    return FALSE;
  }
  if (empty($entity->{$field_name})) {
    return FALSE;
  }

  // Fetch the field type information for this field
  $field_info = field_info_field($field_name);
  $field_type_info = field_info_field_types($field_info['type']);
  if (!isset($field_type_info['extractor'])) {

    // if there is no extractor information just exit
    return FALSE;
  }
  list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
  $field_instance = field_read_instance($entity_type, $field_name, $bundle);
  $extractor = $field_type_info['extractor'];

  // Include the extractor's default options
  $options += $extractor['options'];

  // Include the generic default options
  $options += array(
    'delta' => NULL,
    'key' => NULL,
    'langcode' => NULL,
    'formatter' => NULL,
    'entity_type' => NULL,
    'format' => 'default',
    // The formatter and some extractors need this stuff
    'parent_entity_type' => $entity_type,
    'parent_entity' => $entity,
    'parent_entity_info' => entity_get_info($entity_type),
    'parent_bundle' => $bundle,
    'field_name' => $field_name,
    'field_type_info' => $field_type_info,
    'field_info' => $field_info,
    'instance_info' => $field_instance,
  );

  // Do we want to use a formatter rather than an extractor?
  if (is_string($options['formatter'])) {
    return field_extract_formatted($options);
  }

  // Get entity info
  $entity_info = $options['entity_type'] ? entity_get_info($options['entity_type']) : FALSE;

  // Do we need to load the file containing the extractor?
  if (isset($extractor['filepath'])) {
    include_once $extractor['filepath'];
  }

  // Check the function for the extractor actually exists
  // Or use the standard hook, or the default hook.
  $function = isset($extractor['callback']) ? $extractor['callback'] : NULL;
  if (!$function) {
    $function = "{$field_info['module']}_field_extract";
    if (!function_exists($function)) {
      $function = 'field_extract_field_extract';
    }
  }

  // Fetch the items out of the entity
  $items = field_get_items($entity_type, $entity, $field_name, $options['langcode']);
  if (empty($items)) {
    $items = array();
  }

  // Are we doing just one value or all of them?
  if (is_numeric($options['delta'])) {

    // If delta is set make sure it exists before processing it
    if (isset($items[$options['delta']])) {

      // if this has an entity_type, fetch the entity
      if (!isset($options['key']) && $options['entity_type']) {
        $id = $items[$options['delta']][$entity_info['entity keys']['id']];
        $fetched_entity = array_shift(entity_load($options['entity_type'], array(
          $id,
        )));
        foreach ($items[$options['delta']] as $key => $value) {
          if (!property_exists($fetched_entity, $key)) {
            $fetched_entity->{$key} = $value;
          }
        }
        return $fetched_entity;
      }

      // ...otherwise extract it, returning the result
      return $function($items[$options['delta']], $options);
    }
    else {
      return NULL;
    }
  }
  else {

    // if this has an entity_type, fetch all the entities
    if (!isset($options['key']) && $options['entity_type']) {
      $ids = $map = array();
      $id_key = $entity_info['entity keys']['id'];
      foreach ($items as $delta => $item) {
        $ids[] = $item[$id_key];
        $map[$item[$id_key]] = $delta;
      }
      $fetched_entities = entity_load($options['entity_type'], $ids);
      foreach ($fetched_entities as $id => $fetched_entity) {
        foreach ($items[$map[$id]] as $key => $value) {
          if (!property_exists($fetched_entity, $key)) {
            $fetched_entity->{$key} = $value;
          }
        }
      }
      return $fetched_entities;
    }

    // ...otherwise extract each value in turn
    $values = array();
    foreach ($items as $delta => $item) {
      $values[$delta] = $function($item, $options);
    }

    // and return them all.
    return $values;
  }
  return FALSE;
}

/**
 * Implements hook_field_extract().
 *
 * This is the default hook which does the minimum.
 */
function field_extract_field_extract($item, $options) {
  if (isset($item[$options['key']])) {
    return $item[$options['key']];
  }
}

/**
 * Finds and invokes the required formatter for the field
 */
function field_extract_formatted($options) {
  extract($options);
  $parent_entity_id = $parent_entity->{$parent_entity_info['entity keys']['id']};
  $langcode = isset($langcode) ? $langcode : $parent_entity->language;
  $delta_flag = FALSE;
  $items = field_get_items($parent_entity_type, $parent_entity, $field_name);
  if (isset($items[$delta])) {
    $items = array(
      $items[$delta],
    );
    $delta_flag = TRUE;
  }
  $display = array(
    'type' => isset($formatter) ? $formatter : 'default',
  );

  // Prepare the field items for display
  $itemz = array(
    $parent_entity_id => &$items,
  );
  $args = array(
    $parent_entity_type,
    array(
      $parent_entity_id => $parent_entity,
    ),
    $field_info,
    array(
      $parent_entity_id => $instance_info,
    ),
    $langcode,
    &$itemz,
  );
  $function = "{$field_type_info['module']}_field_prepare_view";
  if (function_exists($function)) {
    call_user_func_array($function, $args);
  }
  $results = module_invoke($field_type_info['module'], 'field_formatter_view', $parent_entity_type, $parent_entity, $field_info, $instance_info, $langcode, $items, $display);
  if ($delta_flag) {
    $results = array_pop($results);
  }
  return $results;
}

/**
 * Implements hook_field_info_alter().
 *
 * Add the extractor information to the field_info,
 * the primary use for this is for the field_extract
 * module itself to add extractors to all standard
 * field types.
 */
function field_extract_field_info_alter(&$info) {

  // Fetch extractor information
  $extractors = module_invoke_all('field_extract_info');

  // allow other modules a look in to change them
  drupal_alter('field_extract_info', $extractors);

  // Run through each extractor we've found and
  // match it up with a field type
  foreach ($extractors as $name => $extractor) {

    // Only try to add this extractor info
    // if the field_info has this type of field
    // which does not already have an extractor
    if (isset($info[$name]) && !isset($info[$name]['extractor'])) {

      // Set up the default options if none exist
      if (!isset($extractor['options'])) {
        $extractor['options'] = array();
      }
      $info[$name]['extractor'] = $extractor;
    }
  }
}

/**
 * Implements hook_field_extract_info().
 */
function field_extract_field_extract_info() {
  $extractors = array();

  // Find all the extractors for the standard field types
  $includes = file_scan_directory(drupal_get_path('module', 'field_extract') . '/includes', '/^[a-zA-Z0-9_]*.inc?/', array(
    'key' => 'name',
  ));
  foreach ($includes as $name => $include) {

    // for each one found, load the file
    require_once $include->uri;

    // and get the information, if available
    $function = "field_extract_{$name}_info";
    if (function_exists($function)) {
      $extractors[$name] = $function();
    }
  }
  return $extractors;
}

Functions

Namesort descending Description
field_extract_field_extract Implements hook_field_extract().
field_extract_field_extract_info Implements hook_field_extract_info().
field_extract_field_info_alter Implements hook_field_info_alter().
field_extract_formatted Finds and invokes the required formatter for the field
field_extract_value Fetch a single field value from an entity
field_extract_values Fetch values of an entity's field