You are here

function field_collection_field_update in Field collection 7

Implements hook_field_update().

Care about removed field collection items.

Support saving field collection items in

$item['entity'];

. This may be used to seamlessly create field collection items during host-entity creation or to save changes to the host entity and its collections at once.

File

./field_collection.module, line 558
Module implementing field collection field type.

Code

function field_collection_field_update($host_entity_type, $host_entity, $field, $instance, $langcode, &$items) {

  // When entity language is changed field values are moved to the new language
  // and old values are marked as removed. We need to avoid processing them in
  // this case.
  $entity_langcode = field_collection_entity_language($host_entity_type, $host_entity);
  $original = isset($host_entity->original) ? $host_entity->original : $host_entity;
  $original_langcode = field_collection_entity_language($host_entity_type, $original);
  $langcode = $langcode == $original_langcode ? $entity_langcode : $langcode;
  $top_host = $host_entity;
  while (method_exists($top_host, 'hostEntity')) {
    $top_host = $top_host
      ->hostEntity();
  }

  // Prevent workbench moderation from deleting field collections or paragraphs
  // on node_save() during workbench_moderation_store(), when
  // $host_entity->revision == 0.
  if (!empty($top_host->workbench_moderation['updating_live_revision'])) {
    return;
  }

  // Don't modify the field collections if using drafty and this is not a
  // draft revision.
  if (module_exists('drafty') && empty($top_host->is_draft_revision)) {
    return;
  }

  // Load items from the original entity.
  $items_original = !empty($original->{$field['field_name']}[$langcode]) ? $original->{$field['field_name']}[$langcode] : array();
  $original_by_id = array_flip(field_collection_field_item_to_ids($items_original));
  foreach ($items as $delta => &$item) {

    // In case the entity has been changed / created, save it and set the id.
    // If the host entity creates a new revision, save new item-revisions as
    // well.
    if (!empty($host_entity->revision) || isset($item['entity'])) {
      if ($entity = field_collection_field_get_entity($item)) {

        // If the host entity is saved as new revision, do the same for the item.
        if (!empty($host_entity->revision) || !empty($host_entity->is_new_revision)) {
          $entity->revision = TRUE;

          // Without this cache clear entity_revision_is_default will
          // incorrectly return false here when creating a new published
          // revision.
          if (!isset($cleared_host_entity_cache)) {
            list($entity_id) = entity_extract_ids($host_entity_type, $host_entity);
            entity_get_controller($host_entity_type)
              ->resetCache(array(
              $entity_id,
            ));
            $cleared_host_entity_cache = TRUE;
          }
          $is_default = entity_revision_is_default($host_entity_type, $host_entity);

          // If an entity type does not support saving non-default entities,
          // assume it will be saved as default.
          if (!isset($is_default) || $is_default) {
            $entity->default_revision = TRUE;
            $entity->archived = FALSE;
          }
          else {
            $entity->default_revision = FALSE;
          }
        }
        if (!empty($entity->is_new)) {
          $entity
            ->setHostEntity($host_entity_type, $host_entity, $langcode, FALSE);
        }
        else {
          $entity
            ->updateHostEntity($host_entity, $host_entity_type);
        }
        $entity
          ->save(TRUE);
        $item = array(
          'value' => $entity->item_id,
          'revision_id' => $entity->revision_id,
        );
        if (module_exists('pathauto')) {
          module_load_include('inc', 'field_collection', 'field_collection.pathauto');
          field_collection_pathauto_create_alias($host_entity, $entity, 'update');
        }
      }
    }
    unset($original_by_id[$item['value']]);
  }

  // If there are removed items, care about deleting the item entities.
  if ($original_by_id) {
    $ids = array_flip($original_by_id);

    // If we are creating a new revision, the old-items should be kept but get
    // marked as archived now.
    if (!empty($host_entity->revision)) {
      db_update('field_collection_item')
        ->fields(array(
        'archived' => 1,
      ))
        ->condition('item_id', $ids, 'IN')
        ->execute();

      // Let other modules know about the archived items.
      foreach (field_collection_item_load_multiple($ids) as $un_item) {
        entity_get_controller('field_collection_item')
          ->invoke('archive', $un_item);
        entity_get_controller('field_collection_item')
          ->resetCache(array(
          $un_item->item_id,
        ));
      }
    }
    else {

      // Load items from the original entity from all languages checking which
      // are the unused items.
      $current_items = array();
      $languages = language_list();
      foreach ($languages as $langcode_value) {
        $current_items += !empty($host_entity->{$field['field_name']}[$langcode_value->language]) ? $host_entity->{$field['field_name']}[$langcode_value->language] : array();
        $current_by_id = field_collection_field_item_to_ids($current_items);
      }
      $items_to_remove = array_diff($ids, $current_by_id);

      // Delete unused field collection items now.
      foreach (field_collection_item_load_multiple($items_to_remove) as $un_item) {
        $un_item
          ->updateHostEntity($host_entity, $host_entity_type);
        $un_item
          ->deleteRevision(TRUE);
        if (module_exists('pathauto')) {
          pathauto_entity_path_delete_all('field_collection_item', $un_item);
        }
      }
    }
  }
}