You are here

function field_collection_update_7009 in Field collection 7

Update revisions created before revision support was implemented.

File

./field_collection.install, line 406
Install, update and uninstall functions for the field_collection module.

Code

function field_collection_update_7009(&$sandbox) {
  $items_per_pass = 10;
  $field_collection_fields = field_read_fields(array(
    'type' => 'field_collection',
  ));

  // If you don't have any field_collecton fields then skip this update.
  if (empty($field_collection_fields)) {
    return;
  }
  if (!isset($sandbox['current_field'])) {
    $sandbox['field_collection_fields'] = array_keys($field_collection_fields);
    $sandbox['current_field'] = 0;
    $sandbox['current_field_collection_item'] = 0;
    $sandbox['field_name'] = $sandbox['field_collection_fields'][$sandbox['current_field']];
    $sandbox['inner_fields'] = field_read_instances(array(
      'entity_type' => 'field_collection_item',
      'bundle' => $sandbox['field_name'],
    ));
  }

  // Find field collection items with duplicate revision ids.
  $query = db_select("field_revision_{$sandbox['field_name']}", 't')
    ->fields('t', array(
    "{$sandbox['field_name']}_revision_id",
  ))
    ->range($sandbox['current_field_collection_item'], $items_per_pass)
    ->groupBy("t.{$sandbox['field_name']}_revision_id");
  $query
    ->having("COUNT(t.{$sandbox['field_name']}_revision_id) >= 2");
  $vids = $query
    ->execute()
    ->fetchCol();

  // Each revision ID that occurs more than once.
  foreach ($vids as $field_collection_duplicated_revision_id) {

    // Find every instance of this revision ID.
    $copies = db_select("field_revision_{$sandbox['field_name']}", 't')
      ->fields('t')
      ->condition("{$sandbox['field_name']}_revision_id", $field_collection_duplicated_revision_id)
      ->execute()
      ->fetchAllAssoc('revision_id');
    $first_copy = reset($copies);
    $field_collection_item_id = $first_copy->{"{$sandbox['field_name']}_value"};

    // Find the currently used revision of this field collection item.
    $field_collection_item_current_revision = db_select('field_collection_item', 'fci')
      ->fields('fci', array(
      'revision_id',
    ))
      ->condition('item_id', $field_collection_item_id)
      ->execute()
      ->fetchField();

    // Find new revisions of this field collection item that were made after
    // revisions were enabled in update_7003.
    $modern_revisions = db_select("field_revision_{$sandbox['field_name']}", 't')
      ->fields('t')
      ->condition("{$sandbox['field_name']}_revision_id", $field_collection_duplicated_revision_id, '<>')
      ->condition("{$sandbox['field_name']}_value", $field_collection_item_id)
      ->orderBy('revision_id')
      ->execute()
      ->fetchAllAssoc('revision_id');

    // Intentionally skip the first instance as it doesn't need to be modified.
    while (FALSE !== ($row_to_replace = next($copies))) {
      $new_revision_id = _field_collection_update_7009_new_revision($field_collection_item_id, $row_to_replace, $sandbox['inner_fields'], $sandbox['field_name']);

      // Create copies of inner fields with new revision number.
      foreach ($sandbox['inner_fields'] as $field) {

        // Get the data to copy.
        $data_rows = db_select("field_revision_{$field['field_name']}", 't')
          ->fields('t')
          ->condition('entity_type', 'field_collection_item')
          ->condition('revision_id', $field_collection_duplicated_revision_id)
          ->execute();

        // Add new copy of data with new revision id.
        while ($each_row = $data_rows
          ->fetchAssoc()) {
          $each_row['revision_id'] = $new_revision_id;
          db_insert("field_revision_{$field['field_name']}")
            ->fields(array_keys($each_row), array_values($each_row))
            ->execute();
        }
      }

      // Update the host's field data with new revision number.
      db_update("field_revision_{$sandbox['field_name']}")
        ->fields(array(
        "{$sandbox['field_name']}_revision_id" => $new_revision_id,
      ))
        ->condition('entity_type', $row_to_replace->entity_type)
        ->condition('revision_id', $row_to_replace->revision_id)
        ->condition('delta', $row_to_replace->delta)
        ->condition('language', $row_to_replace->language)
        ->execute();
      if ($field_collection_item_current_revision == $field_collection_duplicated_revision_id) {
        _field_collection_update_7009_update_data($new_revision_id, $field_collection_duplicated_revision_id);

        // Update the current field collection item data in its host.
        db_update("field_data_{$sandbox['field_name']}")
          ->fields(array(
          'revision_id' => $new_revision_id,
        ))
          ->condition('revision_id', $field_collection_duplicated_revision_id)
          ->condition('entity_type', $row_to_replace->entity_type)
          ->execute();
      }
    }
    foreach ($modern_revisions as $each_modern_revision) {
      $new_revision_id = _field_collection_update_7009_new_revision($field_collection_item_id, $each_modern_revision, $sandbox['inner_fields'], $sandbox['field_name']);

      // Update inner fields with new revision number.
      foreach ($sandbox['inner_fields'] as $field) {
        db_update("field_revision_{$field['field_name']}")
          ->fields(array(
          'revision_id' => $new_revision_id,
        ))
          ->condition('revision_id', $each_modern_revision->{$sandbox['field_name'] . '_revision_id'})
          ->condition('entity_type', 'field_collection_item')
          ->execute();
      }

      // Update the host's field data with new revision number.
      db_update("field_revision_{$sandbox['field_name']}")
        ->fields(array(
        "{$sandbox['field_name']}_revision_id" => $new_revision_id,
      ))
        ->condition('entity_type', $each_modern_revision->entity_type)
        ->condition('revision_id', $each_modern_revision->revision_id)
        ->condition('delta', $each_modern_revision->delta)
        ->condition('language', $each_modern_revision->language)
        ->execute();
      if ($field_collection_item_current_revision == $each_modern_revision->{"{$sandbox['field_name']}_revision_id"}) {
        _field_collection_update_7009_update_data($new_revision_id, $field_collection_item_current_revision);

        // Update the current field collection item data in its host.
        db_update("field_data_{$sandbox['field_name']}")
          ->fields(array(
          'revision_id' => $new_revision_id,
        ))
          ->condition('revision_id', $field_collection_item_current_revision)
          ->condition('entity_type', $each_modern_revision->entity_type)
          ->execute();
      }

      // Remove old copy of revision.
      db_delete('field_collection_item_revision')
        ->condition('revision_id', $each_modern_revision->revision_id)
        ->execute();
    }
    $sandbox['current_field_collection_item']++;
  }
  $sandbox['#finished'] = 0;
  if (count($vids) < $items_per_pass) {
    $sandbox['current_field']++;
    if ($sandbox['current_field'] == count($sandbox['field_collection_fields'])) {
      $sandbox['#finished'] = 1;
      return;
    }
    $sandbox['current_field_collection_item'] = 0;
    $sandbox['field_name'] = $sandbox['field_collection_fields'][$sandbox['current_field']];
    $sandbox['inner_fields'] = field_read_instances(array(
      'entity_type' => 'field_collection_item',
      'bundle' => $sandbox['field_name'],
    ));
  }
}