diff --git a/core/modules/field/field.module b/core/modules/field/field.module index 2044815..f497cec 100644 --- a/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -372,11 +372,11 @@ function field_config_import_steps_alter(&$sync_steps, ConfigImporter $config_im $config_importer->getStorageComparer()->getSourceStorage()->read('core.extension'), $config_importer->getStorageComparer()->getChangelist('delete') ); - if (count($fields)) { + if ($fields) { // Add a step to the beginning of the configuration synchronization process // to purge field data where the module that provides the field is being // uninstalled. - array_unshift($sync_steps, array('\Drupal\field\ConfigImporterFieldPurger', 'processDeletedFields')); + array_unshift($sync_steps, array('\Drupal\field\ConfigImporterFieldPurger', 'process')); }; } @@ -384,7 +384,7 @@ function field_config_import_steps_alter(&$sync_steps, ConfigImporter $config_im * Implements hook_form_FORM_ID_alter(). * * Adds a warning if field data will be permanently removed by the configuration - * synchronisation. + * synchronization. * * @see \Drupal\field\ConfigImporterFieldPurger */ @@ -396,9 +396,8 @@ function field_form_config_admin_import_form_alter(&$form, &$form_state) { $form_state['storage_comparer']->getSourceStorage()->read('core.extension'), $form_state['storage_comparer']->getChangelist('delete') ); - if (count($fields)) { - // @todo improve message and don't use dsm. - drupal_set_message(t('Field data will be deleted by this synchronisation.'), 'warning'); + if ($fields) { + drupal_set_message(t('Field data will be deleted by this synchronization.'), 'warning'); } } } diff --git a/core/modules/field/field.purge.inc b/core/modules/field/field.purge.inc index 9d81a17..6a3347b 100644 --- a/core/modules/field/field.purge.inc +++ b/core/modules/field/field.purge.inc @@ -129,7 +129,7 @@ function field_purge_batch($batch_size, $field_uuid = NULL) { foreach ($deleted_fields as $field) { $field = new FieldConfig($field); if ($field_uuid && $field->uuid() != $field_uuid) { - // If a specific UUID provided only operate on that UUID. + // If a specific UUID is provided, only purge the corresponding field. continue; } diff --git a/core/modules/field/lib/Drupal/field/ConfigImporterFieldPurger.php b/core/modules/field/lib/Drupal/field/ConfigImporterFieldPurger.php index d88ce17..db3d8b9 100644 --- a/core/modules/field/lib/Drupal/field/ConfigImporterFieldPurger.php +++ b/core/modules/field/lib/Drupal/field/ConfigImporterFieldPurger.php @@ -9,24 +9,26 @@ use Drupal\Core\Config\ConfigImporter; use Drupal\Core\Config\Entity\ConfigEntityStorage; -use Drupal\Core\Config\StorageComparerInterface; /** - * Processes field deletions before configuration synchronization. + * Processes field purges before a configuration synchronization. */ class ConfigImporterFieldPurger { /** - * Processes deleted fields. + * Processes fields targeted for purge as part of a configuration sync. + * + * This takes care of deleting the field if necessary, and purging the data on + * the fly. * * @param array $context * The batch context. * @param \Drupal\Core\Config\ConfigImporter $config_importer * The config importer. */ - public static function processDeletedFields(&$context, ConfigImporter $config_importer) { + public static function process(array &$context, ConfigImporter $config_importer) { if (!isset($context['sandbox']['field'])) { - static::calculateNumberOfBatchSteps($context, $config_importer); + static::initializeSandbox($context, $config_importer); } // Get the list of fields to purge. @@ -54,23 +56,24 @@ public static function processDeletedFields(&$context, ConfigImporter $config_im } /** - * Calculates the number of steps necessary to purge all the field data. + * Initializes the batch context sandbox for processing field deletions. + * + * This calculates the number of steps necessary to purge all the field data + * and saves data for later use. * * @param array $context * The batch context. * @param \Drupal\Core\Config\ConfigImporter $config_importer * The config importer. */ - protected static function calculateNumberOfBatchSteps(&$context, ConfigImporter $config_importer) { - // @todo should we use the staged batch size or the currently active? + protected static function initializeSandbox(array &$context, ConfigImporter $config_importer) { $context['sandbox']['field']['purge_batch_size'] = \Drupal::config('field.settings')->get('purge_batch_size'); // Save the future list of installed extensions to limit the amount of times // the configuration is read from disk. $context['sandbox']['field']['extensions'] = $config_importer->getStorageComparer()->getSourceStorage()->read('core.extension'); + $context['sandbox']['field']['steps_to_delete'] = 0; $fields = static::getFieldsToPurge($context['sandbox']['field']['extensions'], $config_importer->getUnprocessedConfiguration('delete')); - // There will be one step to delete the instances and field. - $context['sandbox']['field']['steps_to_delete'] = count($fields); foreach ($fields as $field) { $row_count = $field->entityCount(); if ($row_count > 0) { @@ -81,11 +84,15 @@ protected static function calculateNumberOfBatchSteps(&$context, ConfigImporter $context['sandbox']['field']['steps_to_delete'] += $how_many_steps; } } + // Each field needs one last field_purge_batch() call to remove the last + // instance and the field itself. + $context['sandbox']['field']['steps_to_delete'] += count($fields); + $context['sandbox']['field']['current_progress'] = 0; } /** - * Gets the list of fields to purge before configuration synchronisation. + * Gets the list of fields to purge before configuration synchronization. * * If, during a configuration synchronization, a field is being deleted and * the module that provides the field type is being uninstalled then the field @@ -97,12 +104,12 @@ protected static function calculateNumberOfBatchSteps(&$context, ConfigImporter * The list of extensions that will be enabled after the configuration * synchronization has finished. * @param array $deletes - * The configuration that delete will be deleted by the configuration - * synchronisation. + * The configuration that will be deleted by the configuration + * synchronization. * * @return \Drupal\field\Entity\FieldConfig[] * An array of fields that need purging before configuration can be - * synchronised. + * synchronized. */ public static function getFieldsToPurge(array $extensions, array $deletes) { $providers = array_keys($extensions['module']); @@ -129,11 +136,12 @@ public static function getFieldsToPurge(array $extensions, array $deletes) { // Gather deleted fields from modules that are being uninstalled. $fields = entity_load_multiple_by_properties('field_config', array('deleted' => TRUE, 'include_deleted' => TRUE)); - foreach($fields as $field) { + foreach ($fields as $field) { if (!in_array($field->module, $providers)) { $fields_to_delete[$field->id()] = $field; } } return $fields_to_delete; } + } diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldImportDeleteUninstallTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldImportDeleteUninstallTest.php index bf7d4b0..102c525 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldImportDeleteUninstallTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldImportDeleteUninstallTest.php @@ -25,7 +25,7 @@ class FieldImportDeleteUninstallTest extends FieldUnitTestBase { public static function getInfo() { return array( 'name' => 'Field config delete and uninstall tests', - 'description' => 'Delete field and instances during config synchronsiaton and uninstall module that provides the field type.', + 'description' => 'Delete field and instances during config synchronization and uninstall module that provides the field type.', 'group' => 'Field API', ); } @@ -105,7 +105,7 @@ public function testImportDeleteUninstall() { $staging->delete('field.instance.entity_test.entity_test.field_test'); $steps = $this->configImporter()->initialize(); - $this->assertIdentical($steps[0], array('\Drupal\field\ConfigImporterFieldPurger', 'processDeletedFields'), 'The additional processDeletedFields configuration synchronization step has been added.'); + $this->assertIdentical($steps[0], array('\Drupal\field\ConfigImporterFieldPurger', 'process'), 'The additional process configuration synchronization step has been added.'); $this->configImporter()->import(); @@ -120,7 +120,7 @@ public function testImportDeleteUninstall() { } /** - * Tests purging already fields and instances as part of config import. + * Tests purging already deleted fields and instances during a config import. */ public function testImportAlreadyDeletedUninstall() { // Create a telephone field and instance for validation. @@ -167,7 +167,7 @@ public function testImportAlreadyDeletedUninstall() { $this->assertTrue(isset($deleted_fields[$field_uuid]), 'Field has been deleted and needs purging before configuration synchronization.'); $steps = $this->configImporter()->initialize(); - $this->assertIdentical($steps[0], array('\Drupal\field\ConfigImporterFieldPurger', 'processDeletedFields'), 'The additional processDeletedFields configuration synchronization step has been added.'); + $this->assertIdentical($steps[0], array('\Drupal\field\ConfigImporterFieldPurger', 'process'), 'The additional process configuration synchronization step has been added.'); $this->configImporter()->import(); @@ -178,4 +178,5 @@ public function testImportAlreadyDeletedUninstall() { $deleted_fields = \Drupal::state()->get('field.field.deleted') ?: array(); $this->assertFalse(isset($deleted_fields[$field_uuid]), 'Field has been completed removed from the system.'); } + } diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldImportDeleteUninstallUiTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldImportDeleteUninstallUiTest.php index 6f8ae71..2f33dee 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldImportDeleteUninstallUiTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldImportDeleteUninstallUiTest.php @@ -26,7 +26,7 @@ class FieldImportDeleteUninstallUiTest extends FieldTestBase { public static function getInfo() { return array( 'name' => 'Field config delete and uninstall UI tests', - 'description' => 'Delete field and instances during config synchronsiaton and uninstall module that provides the field type through the UI.', + 'description' => 'Delete field and instances during config synchronization and uninstall module that provides the field type through the UI.', 'group' => 'Field API', ); } @@ -83,9 +83,9 @@ public function testImportDeleteUninstall() { $staging->delete('field.instance.entity_test.entity_test.field_test'); $this->drupalGet('admin/config/development/configuration'); - $this->assertText('Field data will be deleted by this synchronisation.'); + $this->assertText('Field data will be deleted by this synchronization.'); $this->drupalPostForm(NULL, array(), t('Import all')); - $this->assertNoText('Field data will be deleted by this synchronisation.'); + $this->assertNoText('Field data will be deleted by this synchronization.'); // This will purge all the data, delete the field and uninstall the // Telephone module. $this->rebuildContainer();