diff --git a/field_collection.install b/field_collection.install index d2b1892..a670a23 100644 --- a/field_collection.install +++ b/field_collection.install @@ -217,20 +217,69 @@ function field_collection_update_7001() { /** * Remove orphaned field collection item entities. */ -function field_collection_update_7002() { - // Loop over all fields and delete any orphaned field collection items. - foreach (field_read_fields(array('type' => 'field_collection')) as $field_name => $field) { +function field_collection_update_7002(&$sandbox) { + $limit = drupal_is_cli() ? 500 : 50; + + if (!isset($sandbox['removed'])) { + // Found total items to remove. + $total = 0; + foreach (field_read_fields(array('type' => 'field_collection')) as $field_name => $field) { + // Add an index otherwise this takes *hours*. + if (!db_index_exists('field_data_' . $field_name, 'idx_value')) { + db_add_index('field_data_' . $field_name, 'idx_value', array($field_name.'_value')); + } + $select = db_select('field_collection_item', 'fci') + ->fields('fci', array('item_id')) + ->condition('field_name', $field_name) + ->condition('archived', 0); + $select->leftJoin('field_data_' . $field_name, 'field', "field.{$field_name}_value = fci.item_id "); + $select->isNull('field.entity_id'); + + $total += $select->execute()->rowCount(); + } + + + $sandbox['removed'] = 0; + $sandbox['total_to_remove'] = $total; + } + // Assume that it will be finished right away. + $sandbox['#finished'] = TRUE; + // Loop over all fields and delete any orphaned field collection items. + $fields_to_process = field_read_fields(array('type' => 'field_collection')); + foreach ($fields_to_process as $field_name => $field) { $select = db_select('field_collection_item', 'fci') ->fields('fci', array('item_id')) ->condition('field_name', $field_name) ->condition('archived', 0); $select->leftJoin('field_data_' . $field_name, 'field', "field.{$field_name}_value = fci.item_id "); $select->isNull('field.entity_id'); - $ids = $select->execute()->fetchCol(0); - entity_delete_multiple('field_collection_item', $ids); - drupal_set_message(t('Deleted @count orphaned field collection items.', array('@count' => count($ids)))); + $query = clone $select; + $ids = $query->range(0, $limit)->execute()->fetchCol(0); + + if (!empty($ids)) { + entity_delete_multiple('field_collection_item', $ids); + watchdog('field_collection', 'Deleted @count orphaned field collection items.', array('@count' => count($ids))); + $sandbox['removed'] += count($ids); + + // Set progress to FALSE (not finished). + // $sandbox['#finished'] = $sandbox['removed'] / $sandbox['total_to_remove']; + $sandbox['#finished'] = FALSE; + } + } + + if ($sandbox['#finished']) { + if (drupal_is_cli()) { + drupal_set_message(t('Removed @count_removed orphaned field collection item entities in total.', array('@count_removed' => $sandbox['removed']))); + } + // Remove tempory indexes. + foreach ($fields_to_process as $field_name => $field) { + // May as well remove the index. + if (db_index_exists('field_data_' . $field_name, 'idx_value')) { + db_drop_index('field_data_' . $field_name, 'idx_value'); + } + } } }