function field_invoke_method_multiple

Invokes a method across fields on multiple entities.

Parameters

string $method: The name of the method to invoke.

callable $target_function: A function that receives an $instance object and returns the object on which the method should be invoked.

array $entities: An array of entities, keyed by entity ID.

mixed $a: (optional) A parameter for the invoked method. Defaults to NULL.

mixed $b: (optional) A parameter for the invoked method. Defaults to NULL.

$options: (optional) An associative array of additional options, with the following keys:

  • field_name: The name of the field whose operation should be invoked. By default, the operation is invoked on all the fields in the entity's bundle. NOTE: This option is not compatible with the 'deleted' option; the 'field_id' option should be used instead.
  • field_id: The ID of the field whose operation should be invoked. By default, the operation is invoked on all the fields in the entity's' bundles.
  • deleted: If TRUE, the function will operate on deleted fields as well as non-deleted fields. If unset or FALSE, only non-deleted fields are operated on.
  • langcode: A language code or an array of language codes keyed by field name. It will be used to narrow down to a single value the available languages to act on.

Return value

array An array of returned values keyed by entity ID.

See also

field_invoke_method()

Related topics

1 call to field_invoke_method_multiple()
field_attach_prepare_view in drupal/core/modules/field/field.attach.inc
Prepares field data prior to display.

File

drupal/core/modules/field/field.attach.inc, line 245
Field attach API, allowing entities (nodes, users, ...) to be 'fieldable'.

Code

function field_invoke_method_multiple($method, $target_function, array $entities, &$a = NULL, &$b = NULL, array $options = array()) {

  // Merge default options.
  $default_options = array(
    'deleted' => FALSE,
    'langcode' => NULL,
  );
  $options += $default_options;
  $instances = array();
  $grouped_entities = array();
  $grouped_items = array();
  $grouped_targets = array();
  $return = array();

  // Go through the entities and collect the instances on which the method
  // should be called.
  foreach ($entities as $entity) {
    $id = $entity
      ->id();
    $entity_type = $entity
      ->entityType();

    // Determine the list of instances to iterate on.
    $entity_instances = _field_invoke_get_instances($entity_type, $entity
      ->bundle(), $options);
    foreach ($entity_instances as $instance) {
      $instance_id = $instance['id'];
      $field_name = $instance['field_name'];

      // Let the closure determine the target object on which the method should
      // be called.
      if (empty($grouped_targets[$instance_id])) {
        $grouped_targets[$instance_id] = call_user_func($target_function, $instance);
      }
      if (method_exists($grouped_targets[$instance_id], $method)) {

        // Add the instance to the list of instances to invoke the hook on.
        if (!isset($instances[$instance_id])) {
          $instances[$instance_id] = $instance;
        }

        // Unless a language code suggestion is provided we iterate on all the
        // available language codes.
        $field = field_info_field_by_id($instance['field_id']);
        $available_langcodes = field_available_languages($entity_type, $field);
        $langcode = !empty($options['langcode'][$id]) ? $options['langcode'][$id] : $options['langcode'];
        $langcodes = _field_language_suggestion($available_langcodes, $langcode, $field_name);
        foreach ($langcodes as $langcode) {

          // Group the entities and items corresponding to the current field.
          $grouped_entities[$instance_id][$langcode][$id] = $entities[$id];
          $grouped_items[$instance_id][$langcode][$id] = isset($entity->{$field_name}[$langcode]) ? $entity->{$field_name}[$langcode] : array();
        }
      }
    }

    // Initialize the return value for each entity.
    $return[$id] = array();
  }

  // For each instance, invoke the method and collect results.
  foreach ($instances as $instance_id => $instance) {
    $field_name = $instance['field_name'];

    // Iterate over all the field translations.
    foreach ($grouped_items[$instance_id] as $langcode => &$items) {
      $entities = $grouped_entities[$instance_id][$langcode];
      $results = $grouped_targets[$instance_id]
        ->{$method}($entities, $langcode, $items, $a, $b);
      if (isset($results)) {

        // Collect results by entity.
        // For hooks with array results, we merge results together.
        // For hooks with scalar results, we collect results in an array.
        foreach ($results as $id => $result) {
          if (is_array($result)) {
            $return[$id] = array_merge($return[$id], $result);
          }
          else {
            $return[$id][] = $result;
          }
        }
      }
    }

    // Populate field values back in the entities, but avoid replacing missing
    // fields with an empty array (those are not equivalent on update).
    foreach ($grouped_entities[$instance_id] as $langcode => $entities) {
      foreach ($entities as $id => $entity) {
        if ($grouped_items[$instance_id][$langcode][$id] !== array() || isset($entity->{$field_name}[$langcode])) {
          $entity->{$field_name}[$langcode] = $grouped_items[$instance_id][$langcode][$id];
        }
      }
    }
  }
  return $return;
}