/** * 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 process(array &$context, ConfigImporter $config_importer) { if (!isset($context['sandbox']['field'])) { static::initializeSandbox($context, $config_importer); } // Get the list of field storages to purge. $field_storages = static::getFieldStoragesToPurge($context['sandbox']['field']['extensions'], $config_importer->getUnprocessedConfiguration('delete')); // Get the first field storage to process. $field_storage = reset($field_storages); if (!isset($context['sandbox']['field']['current_storage_id']) || $context['sandbox']['field']['current_storage_id'] != $field_storage->id()) { $context['sandbox']['field']['current_storage_id'] = $field_storage->id(); // If the storage has not been deleted yet we need to do that. This is the // case when the storage deletion is staged. if (!$field_storage->isDeleted()) { $field_storage->delete(); } } field_purge_batch($context['sandbox']['field']['purge_batch_size'], $field_storage->uuid()); $context['sandbox']['field']['current_progress']++; $fields_to_delete_count = count(static::getFieldStoragesToPurge($context['sandbox']['field']['extensions'], $config_importer->getUnprocessedConfiguration('delete'))); if ($fields_to_delete_count == 0) { $context['finished'] = 1; } else { $context['finished'] = $context['sandbox']['field']['current_progress'] / $context['sandbox']['field']['steps_to_delete']; $context['message'] = \Drupal::translation()->translate('Purging field @field_label', array('@field_label' => $field_storage->label())); } }
/** * Purges a field data. */ public static function purgeFieldData() { do { field_purge_batch(1000); $properties = array('deleted' => TRUE, 'include_deleted' => TRUE); $fields = entity_load_multiple_by_properties('field_config', $properties); } while ($fields); }
/** * Tests entityCount() and hadData() methods. */ public function testEntityCountAndHasData() { // Create a field with a cardinality of 2 to show that we are counting // entities and not rows in a table. /** @var \Drupal\field\Entity\FieldStorageConfig $field_storage */ $field_storage = entity_create('field_storage_config', array('field_name' => 'field_int', 'entity_type' => 'entity_test', 'type' => 'integer', 'cardinality' => 2)); $field_storage->save(); entity_create('field_config', array('field_storage' => $field_storage, 'bundle' => 'entity_test'))->save(); $this->assertIdentical($field_storage->hasdata(), FALSE, 'There are no entities with field data.'); $this->assertIdentical($this->storage->countFieldData($field_storage), 0, 'There are 0 entities with field data.'); // Create 1 entity without the field. $entity = entity_create('entity_test'); $entity->name->value = $this->randomMachineName(); $entity->save(); $this->assertIdentical($field_storage->hasdata(), FALSE, 'There are no entities with field data.'); $this->assertIdentical($this->storage->countFieldData($field_storage), 0, 'There are 0 entities with field data.'); // Create 12 entities to ensure that the purging works as expected. for ($i = 0; $i < 12; $i++) { $entity = entity_create('entity_test'); $value = mt_rand(1, 99); $value2 = mt_rand(1, 99); $entity->field_int[0]->value = $value; $entity->field_int[1]->value = $value2; $entity->name->value = $this->randomMachineName(); $entity->save(); } $storage = \Drupal::entityManager()->getStorage('entity_test'); if ($storage instanceof SqlContentEntityStorage) { // Count the actual number of rows in the field table. $table_mapping = $storage->getTableMapping(); $field_table_name = $table_mapping->getDedicatedDataTableName($field_storage); $result = db_select($field_table_name, 't')->fields('t')->countQuery()->execute()->fetchField(); $this->assertEqual($result, 24, 'The field table has 24 rows.'); } $this->assertIdentical($field_storage->hasdata(), TRUE, 'There are entities with field data.'); $this->assertEqual($this->storage->countFieldData($field_storage), 12, 'There are 12 entities with field data.'); // Ensure the methods work on deleted fields. $field_storage->delete(); $this->assertIdentical($field_storage->hasdata(), TRUE, 'There are entities with deleted field data.'); $this->assertEqual($this->storage->countFieldData($field_storage), 12, 'There are 12 entities with deleted field data.'); field_purge_batch(6); $this->assertIdentical($field_storage->hasdata(), TRUE, 'There are entities with deleted field data.'); $this->assertEqual($this->storage->countFieldData($field_storage), 6, 'There are 6 entities with deleted field data.'); }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { $field_storage = $this->entity->getFieldStorageDefinition(); $bundles = entity_get_bundles(); $bundle_label = $bundles[$this->entity->entity_type][$this->entity->bundle]['label']; if ($field_storage && !$field_storage->locked) { $this->entity->delete(); drupal_set_message($this->t('The field %field has been deleted from the %type content type.', array('%field' => $this->entity->label(), '%type' => $bundle_label))); } else { drupal_set_message($this->t('There was a problem removing the %field from the %type content type.', array('%field' => $this->entity->label(), '%type' => $bundle_label)), 'error'); } $form_state->setRedirectUrl($this->getCancelUrl()); // Fields are purged on cron. However field module prevents disabling modules // when field types they provided are used in a field until it is fully // purged. In the case that a field has minimal or no content, a single call // to field_purge_batch() will remove it from the system. Call this with a // low batch limit to avoid administrators having to wait for cron runs when // removing fields that meet this criteria. field_purge_batch(10); }
/** * Tests that comment module works when installed after a content module. */ function testCommentInstallAfterContentModule() { // Create a user to do module administration. $this->admin_user = $this->drupalCreateUser(array('access administration pages', 'administer modules')); $this->drupalLogin($this->admin_user); // Drop default comment field added in CommentTestBase::setup(). FieldStorageConfig::loadByName('node', 'comment')->delete(); if ($field_storage = FieldStorageConfig::loadByName('node', 'comment_forum')) { $field_storage->delete(); } // Purge field data now to allow comment module to be uninstalled once the // field has been deleted. field_purge_batch(10); // Disable the comment module. $edit = array(); $edit['uninstall[comment]'] = TRUE; $this->drupalPostForm('admin/modules/uninstall', $edit, t('Uninstall')); $this->drupalPostForm(NULL, array(), t('Uninstall')); $this->rebuildContainer(); $this->assertFalse($this->container->get('module_handler')->moduleExists('comment'), 'Comment module uninstalled.'); // Enable core content type module (book). $edit = array(); $edit['modules[Core][book][enable]'] = 'book'; $this->drupalPostForm('admin/modules', $edit, t('Save configuration')); // Now install the comment module. $edit = array(); $edit['modules[Core][comment][enable]'] = 'comment'; $this->drupalPostForm('admin/modules', $edit, t('Save configuration')); $this->rebuildContainer(); $this->assertTrue($this->container->get('module_handler')->moduleExists('comment'), 'Comment module enabled.'); // Create nodes of each type. $this->container->get('comment.manager')->addDefaultField('node', 'book'); $book_node = $this->drupalCreateNode(array('type' => 'book')); $this->drupalLogout(); // Try to post a comment on each node. A failure will be triggered if the // comment body is missing on one of these forms, due to postComment() // asserting that the body is actually posted correctly. $this->web_user = $this->drupalCreateUser(array('access content', 'access comments', 'post comments', 'skip comment approval')); $this->drupalLogin($this->web_user); $this->postComment($book_node, $this->randomMachineName(), $this->randomMachineName()); }
/** * Tests if uninstallation succeeds if the field has been deleted beforehand. */ function testCommentUninstallWithoutField() { // Manually delete the comment_body field before module uninstallation. $field_storage = FieldStorageConfig::loadByName('comment', 'comment_body'); $this->assertNotNull($field_storage, 'The comment_body field exists.'); $field_storage->delete(); // Check that the field is now deleted. $field_storage = FieldStorageConfig::loadByName('comment', 'comment_body'); $this->assertNull($field_storage, 'The comment_body field has been deleted.'); // Manually delete the comment field on the node before module uninstallation. $field_storage = FieldStorageConfig::loadByName('node', 'comment'); $this->assertNotNull($field_storage, 'The comment field exists.'); $field_storage->delete(); // Check that the field is now deleted. $field_storage = FieldStorageConfig::loadByName('node', 'comment'); $this->assertNull($field_storage, 'The comment field has been deleted.'); field_purge_batch(10); // Ensure that uninstallation succeeds even if the field has already been // deleted manually beforehand. $this->container->get('module_installer')->uninstall(array('comment')); }
/** * Tests deleting field storages and fields as part of config import. */ public function testImportDelete() { $this->installConfig(['field_test_config']); // At this point there are 5 field configuration objects in the active // storage. // - field.storage.entity_test.field_test_import // - field.storage.entity_test.field_test_import_2 // - field.field.entity_test.entity_test.field_test_import // - field.field.entity_test.entity_test.field_test_import_2 // - field.field.entity_test.test_bundle.field_test_import_2 $field_name = 'field_test_import'; $field_storage_id = "entity_test.{$field_name}"; $field_name_2 = 'field_test_import_2'; $field_storage_id_2 = "entity_test.{$field_name_2}"; $field_id = "entity_test.entity_test.{$field_name}"; $field_id_2a = "entity_test.entity_test.{$field_name_2}"; $field_id_2b = "entity_test.test_bundle.{$field_name_2}"; $field_storage_config_name = "field.storage.{$field_storage_id}"; $field_storage_config_name_2 = "field.storage.{$field_storage_id_2}"; $field_config_name = "field.field.{$field_id}"; $field_config_name_2a = "field.field.{$field_id_2a}"; $field_config_name_2b = "field.field.{$field_id_2b}"; // Create a second bundle for the 'Entity test' entity type. entity_test_create_bundle('test_bundle'); // Get the uuid's for the field storages. $field_storage_uuid = FieldStorageConfig::load($field_storage_id)->uuid(); $field_storage_uuid_2 = FieldStorageConfig::load($field_storage_id_2)->uuid(); $active = $this->container->get('config.storage'); $staging = $this->container->get('config.storage.staging'); $this->copyConfig($active, $staging); $this->assertTrue($staging->delete($field_storage_config_name), String::format('Deleted field storage: !field_storage', array('!field_storage' => $field_storage_config_name))); $this->assertTrue($staging->delete($field_storage_config_name_2), String::format('Deleted field storage: !field_storage', array('!field_storage' => $field_storage_config_name_2))); $this->assertTrue($staging->delete($field_config_name), String::format('Deleted field: !field', array('!field' => $field_config_name))); $this->assertTrue($staging->delete($field_config_name_2a), String::format('Deleted field: !field', array('!field' => $field_config_name_2a))); $this->assertTrue($staging->delete($field_config_name_2b), String::format('Deleted field: !field', array('!field' => $field_config_name_2b))); $deletes = $this->configImporter()->getUnprocessedConfiguration('delete'); $this->assertEqual(count($deletes), 5, 'Importing configuration will delete 3 fields and 2 field storages.'); // Import the content of the staging directory. $this->configImporter()->import(); // Check that the field storages and fields are gone. \Drupal::entityManager()->getStorage('field_storage_config')->resetCache(array($field_storage_id)); $field_storage = FieldStorageConfig::load($field_storage_id); $this->assertFalse($field_storage, 'The field storage was deleted.'); \Drupal::entityManager()->getStorage('field_storage_config')->resetCache(array($field_storage_id_2)); $field_storage_2 = FieldStorageConfig::load($field_storage_id_2); $this->assertFalse($field_storage_2, 'The second field storage was deleted.'); \Drupal::entityManager()->getStorage('field_config')->resetCache(array($field_id)); $field = FieldConfig::load($field_id); $this->assertFalse($field, 'The field was deleted.'); \Drupal::entityManager()->getStorage('field_config')->resetCache(array($field_id_2a)); $field_2a = FieldConfig::load($field_id_2a); $this->assertFalse($field_2a, 'The second field on test bundle was deleted.'); \Drupal::entityManager()->getStorage('field_config')->resetCache(array($field_id_2b)); $field_2b = FieldConfig::load($field_id_2b); $this->assertFalse($field_2b, 'The second field on test bundle 2 was deleted.'); // Check that all config files are gone. $active = $this->container->get('config.storage'); $this->assertIdentical($active->listAll($field_storage_config_name), array()); $this->assertIdentical($active->listAll($field_storage_config_name_2), array()); $this->assertIdentical($active->listAll($field_config_name), array()); $this->assertIdentical($active->listAll($field_config_name_2a), array()); $this->assertIdentical($active->listAll($field_config_name_2b), array()); // Check that the storage definition is preserved in state. $deleted_storages = \Drupal::state()->get('field.storage.deleted') ?: array(); $this->assertTrue(isset($deleted_storages[$field_storage_uuid])); $this->assertTrue(isset($deleted_storages[$field_storage_uuid_2])); // Purge field data, and check that the storage definition has been // completely removed once the data is purged. field_purge_batch(10); $deleted_storages = \Drupal::state()->get('field.storage.deleted') ?: array(); $this->assertTrue(empty($deleted_storages), 'Fields are deleted'); }
<?php // Delete fields. $fields_to_delete = array('field_one', 'field_two', 'field_three'); foreach ($fields_to_delete as $field_name) { field_delete_field($field_name); } // Increase batch size for safe measure. field_purge_batch(10); // Confirm the fields have been removed from field_config and field_config_instance tables in database.
/** * Verify that field storages are preserved and purged correctly as multiple * fields are deleted and purged. */ function testPurgeFieldStorage() { // Start recording hook invocations. field_test_memorize(); $field_storage = reset($this->fieldStorages); $field_name = $field_storage->getName(); // Delete the first field. $bundle = reset($this->bundles); $field = FieldConfig::loadByName($this->entityTypeId, $bundle, $field_name); $field->delete(); // Assert that FieldItemInterface::delete() was not called yet. $mem = field_test_memorize(); $this->assertEqual(count($mem), 0, 'No field hooks were called.'); // Purge the data. field_purge_batch(10); // Check hooks invocations. // FieldItemInterface::delete() should have been called once for each entity in the // bundle. $actual_hooks = field_test_memorize(); $hooks = array(); $entities = $this->entitiesByBundles[$bundle]; foreach ($entities as $id => $entity) { $hooks['field_test_field_delete'][] = $entity; } $this->checkHooksInvocations($hooks, $actual_hooks); // The field still exists, deleted. $fields = entity_load_multiple_by_properties('field_config', array('uuid' => $field->uuid(), 'include_deleted' => TRUE)); $this->assertTrue(isset($fields[$field->uuid()]) && $fields[$field->uuid()]->isDeleted(), 'The field exists and is deleted'); // Purge again to purge the field. field_purge_batch(0); // The field is gone. $fields = entity_load_multiple_by_properties('field_config', array('uuid' => $field->uuid(), 'include_deleted' => TRUE)); $this->assertEqual(count($fields), 0, 'The field is purged.'); // The field storage still exists, not deleted. $storages = entity_load_multiple_by_properties('field_storage_config', array('uuid' => $field_storage->uuid(), 'include_deleted' => TRUE)); $this->assertTrue(isset($storages[$field_storage->uuid()]) && !$storages[$field_storage->uuid()]->isDeleted(), 'The field storage exists and is not deleted'); // Delete the second field. $bundle = next($this->bundles); $field = FieldConfig::loadByName($this->entityTypeId, $bundle, $field_name); $field->delete(); // Assert that FieldItemInterface::delete() was not called yet. $mem = field_test_memorize(); $this->assertEqual(count($mem), 0, 'No field hooks were called.'); // Purge the data. field_purge_batch(10); // Check hooks invocations (same as above, for the 2nd bundle). $actual_hooks = field_test_memorize(); $hooks = array(); $entities = $this->entitiesByBundles[$bundle]; foreach ($entities as $id => $entity) { $hooks['field_test_field_delete'][] = $entity; } $this->checkHooksInvocations($hooks, $actual_hooks); // The field and the storage still exist, deleted. $fields = entity_load_multiple_by_properties('field_config', array('uuid' => $field->uuid(), 'include_deleted' => TRUE)); $this->assertTrue(isset($fields[$field->uuid()]) && $fields[$field->uuid()]->isDeleted(), 'The field exists and is deleted'); $storages = entity_load_multiple_by_properties('field_storage_config', array('uuid' => $field_storage->uuid(), 'include_deleted' => TRUE)); $this->assertTrue(isset($storages[$field_storage->uuid()]) && $storages[$field_storage->uuid()]->isDeleted(), 'The field storage exists and is deleted'); // Purge again to purge the field and the storage. field_purge_batch(0); // The field and the storage are gone. $fields = entity_load_multiple_by_properties('field_config', array('uuid' => $field->uuid(), 'include_deleted' => TRUE)); $this->assertEqual(count($fields), 0, 'The field is purged.'); $storages = entity_load_multiple_by_properties('field_storage_config', array('uuid' => $field_storage->uuid(), 'include_deleted' => TRUE)); $this->assertEqual(count($storages), 0, 'The field storage is purged.'); }
/** * Tests entityCount() and hadData() methods. */ public function testEntityCountAndHasData() { // Create a field with a cardinality of 2 to show that we are counting // entities and not rows in a table. /** @var \Drupal\field\Entity\FieldStorageConfig $field_storage */ $field_storage = entity_create('field_storage_config', array('field_name' => 'field_int', 'entity_type' => 'entity_test', 'type' => 'integer', 'cardinality' => 2)); $field_storage->save(); entity_create('field_config', array('field_storage' => $field_storage, 'bundle' => 'entity_test'))->save(); $this->assertIdentical($field_storage->hasdata(), FALSE, 'There are no entities with field data.'); $this->assertIdentical($this->storage->countFieldData($field_storage), 0, 'There are 0 entities with field data.'); // Create 1 entity without the field. $entity = entity_create('entity_test'); $entity->name->value = $this->randomMachineName(); $entity->save(); $this->assertIdentical($field_storage->hasdata(), FALSE, 'There are no entities with field data.'); $this->assertIdentical($this->storage->countFieldData($field_storage), 0, 'There are 0 entities with field data.'); // Create 12 entities to ensure that the purging works as expected. for ($i = 0; $i < 12; $i++) { $entity = entity_create('entity_test'); $entity->field_int[] = mt_rand(1, 99); $entity->field_int[] = mt_rand(1, 99); $entity->name[] = $this->randomMachineName(); $entity->save(); } $storage = \Drupal::entityManager()->getStorage('entity_test'); if ($storage instanceof SqlContentEntityStorage) { // Count the actual number of rows in the field table. $table_mapping = $storage->getTableMapping(); $field_table_name = $table_mapping->getDedicatedDataTableName($field_storage); $result = db_select($field_table_name, 't')->fields('t')->countQuery()->execute()->fetchField(); $this->assertEqual($result, 24, 'The field table has 24 rows.'); } $this->assertIdentical($field_storage->hasdata(), TRUE, 'There are entities with field data.'); $this->assertEqual($this->storage->countFieldData($field_storage), 12, 'There are 12 entities with field data.'); // Ensure the methods work on deleted fields. $field_storage->delete(); $this->assertIdentical($field_storage->hasdata(), TRUE, 'There are entities with deleted field data.'); $this->assertEqual($this->storage->countFieldData($field_storage), 12, 'There are 12 entities with deleted field data.'); field_purge_batch(6); $this->assertIdentical($field_storage->hasdata(), TRUE, 'There are entities with deleted field data.'); $this->assertEqual($this->storage->countFieldData($field_storage), 6, 'There are 6 entities with deleted field data.'); $entity_type = 'entity_test_rev'; $this->createFieldWithStorage('_2', $entity_type); $entity_init = entity_create($entity_type, array('type' => $entity_type)); $cardinality = $this->fieldTestData->field_storage_2->getCardinality(); $this->assertIdentical($this->fieldTestData->field_storage_2->hasData(), FALSE, 'There are no entities with field data.'); $this->assertIdentical($this->storageRev->countFieldData($this->fieldTestData->field_storage_2), 0, 'There are 0 entities with field data.'); // Create 1 entity with the field. $entity = clone $entity_init; $values = $this->_generateTestFieldValues($this->fieldTestData->field_storage_2->getCardinality()); $entity->{$this->fieldTestData->field_name_2} = $values; $entity->setNewRevision(); $entity->save(); $first_revision = $entity->getRevisionId(); $this->assertIdentical($this->fieldTestData->field_storage_2->hasData(), TRUE, 'There are entities with field data.'); $this->assertIdentical($this->storageRev->countFieldData($this->fieldTestData->field_storage_2), 1, 'There is 1 entity with field data.'); $entity->{$this->fieldTestData->field_name_2} = array(); $entity->setNewRevision(); $entity->save(); $this->assertIdentical($this->fieldTestData->field_storage_2->hasData(), TRUE, 'There are entities with field data.'); $storage = $this->container->get('entity.manager')->getStorage($entity_type); $entity = $storage->loadRevision($first_revision); $this->assertEqual(count($entity->{$this->fieldTestData->field_name_2}), $cardinality, format_string('Revision %revision_id: expected number of values.', array('%revision_id' => $first_revision))); }
/** * Tests that a fixed set of modules can be installed and uninstalled. */ public function testInstallUninstall() { // Get a list of modules to enable. $all_modules = system_rebuild_module_data(); $all_modules = array_filter($all_modules, function ($module) { // Filter contrib, hidden, already enabled modules and modules in the // Testing package. if ($module->origin !== 'core' || !empty($module->info['hidden']) || $module->status == TRUE || $module->info['package'] == 'Testing') { return FALSE; } return TRUE; }); // Install every module possible. \Drupal::service('module_installer')->install(array_keys($all_modules)); $this->assertModules(array_keys($all_modules), TRUE); foreach ($all_modules as $module => $info) { $this->assertModuleConfig($module); $this->assertModuleTablesExist($module); } // Export active config to sync. $this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.sync')); system_list_reset(); $this->resetAll(); // Delete every field on the site so all modules can be uninstalled. For // example, if a comment field exists then module becomes required and can // not be uninstalled. $field_storages = \Drupal::entityManager()->getStorage('field_storage_config')->loadMultiple(); \Drupal::entityManager()->getStorage('field_storage_config')->delete($field_storages); // Purge the data. field_purge_batch(1000); // Delete all terms. $terms = Term::loadMultiple(); entity_delete_multiple('taxonomy_term', array_keys($terms)); // Delete all filter formats. $filters = FilterFormat::loadMultiple(); entity_delete_multiple('filter_format', array_keys($filters)); // Delete any shortcuts so the shortcut module can be uninstalled. $shortcuts = Shortcut::loadMultiple(); entity_delete_multiple('shortcut', array_keys($shortcuts)); system_list_reset(); $all_modules = system_rebuild_module_data(); // Ensure that only core required modules and the install profile can not be uninstalled. $validation_reasons = \Drupal::service('module_installer')->validateUninstall(array_keys($all_modules)); $this->assertEqual(['standard', 'system', 'user'], array_keys($validation_reasons)); $modules_to_uninstall = array_filter($all_modules, function ($module) use($validation_reasons) { // Filter required and not enabled modules. if (!empty($module->info['required']) || $module->status == FALSE) { return FALSE; } return TRUE; }); // Can not uninstall config and use admin/config/development/configuration! unset($modules_to_uninstall['config']); $this->assertTrue(isset($modules_to_uninstall['comment']), 'The comment module will be disabled'); $this->assertTrue(isset($modules_to_uninstall['file']), 'The File module will be disabled'); $this->assertTrue(isset($modules_to_uninstall['editor']), 'The Editor module will be disabled'); // Uninstall all modules that can be uninstalled. \Drupal::service('module_installer')->uninstall(array_keys($modules_to_uninstall)); $this->assertModules(array_keys($modules_to_uninstall), FALSE); foreach ($modules_to_uninstall as $module => $info) { $this->assertNoModuleConfig($module); $this->assertModuleTablesDoNotExist($module); } // Import the configuration thereby re-installing all the modules. $this->drupalPostForm('admin/config/development/configuration', array(), t('Import all')); // Modules have been installed that have services. $this->rebuildContainer(); // Check that there are no errors. $this->assertIdentical($this->configImporter()->getErrors(), array()); // Check that all modules that were uninstalled are now reinstalled. $this->assertModules(array_keys($modules_to_uninstall), TRUE); foreach ($modules_to_uninstall as $module => $info) { $this->assertModuleConfig($module); $this->assertModuleTablesExist($module); } // Ensure that we have no configuration changes to import. $storage_comparer = new StorageComparer($this->container->get('config.storage.sync'), $this->container->get('config.storage'), $this->container->get('config.manager')); $this->assertIdentical($storage_comparer->createChangelist()->getChangelist(), $storage_comparer->getEmptyChangelist()); // Now we have all configuration imported, test all of them for schema // conformance. Ensures all imported default configuration is valid when // all modules are enabled. $names = $this->container->get('config.storage')->listAll(); /** @var \Drupal\Core\Config\TypedConfigManagerInterface $typed_config */ $typed_config = $this->container->get('config.typed'); foreach ($names as $name) { $config = $this->config($name); $this->assertConfigSchema($typed_config, $name, $config->get()); } }
/** * Tests that a fixed set of modules can be installed and uninstalled. */ public function testInstallUninstall() { // Get a list of modules to enable. $all_modules = system_rebuild_module_data(); $all_modules = array_filter($all_modules, function ($module) { // Filter hidden, already enabled modules and modules in the Testing // package. if (!empty($module->info['hidden']) || $module->status == TRUE || $module->info['package'] == 'Testing') { return FALSE; } return TRUE; }); // Install every module possible. \Drupal::moduleHandler()->install(array_keys($all_modules)); $this->assertModules(array_keys($all_modules), TRUE); foreach ($all_modules as $module => $info) { $this->assertModuleConfig($module); $this->assertModuleTablesExist($module); } // Export active config to staging $this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.staging')); system_list_reset(); $this->resetAll(); // Delete every field on the site so all modules can be uninstalled. For // example, if a comment field exists then module becomes required and can // not be uninstalled. $field_storages = \Drupal::entityManager()->getStorage('field_storage_config')->loadMultiple(); \Drupal::entityManager()->getStorage('field_storage_config')->delete($field_storages); // Purge the data. field_purge_batch(1000); // Delete any forum terms so it can be uninstalled. $vid = \Drupal::config('forum.settings')->get('vocabulary'); $terms = entity_load_multiple_by_properties('taxonomy_term', ['vid' => $vid]); foreach ($terms as $term) { $term->delete(); } system_list_reset(); $all_modules = system_rebuild_module_data(); $modules_to_uninstall = array_filter($all_modules, function ($module) { // Filter required and not enabled modules. if (!empty($module->info['required']) || $module->status == FALSE) { return FALSE; } return TRUE; }); // Can not uninstall config and use admin/config/development/configuration! unset($modules_to_uninstall['config']); $this->assertTrue(isset($modules_to_uninstall['comment']), 'The comment module will be disabled'); // Uninstall all modules that can be uninstalled. \Drupal::moduleHandler()->uninstall(array_keys($modules_to_uninstall)); $this->assertModules(array_keys($modules_to_uninstall), FALSE); foreach ($modules_to_uninstall as $module => $info) { $this->assertNoModuleConfig($module); $this->assertModuleTablesDoNotExist($module); } // Import the configuration thereby re-installing all the modules. $this->drupalPostForm('admin/config/development/configuration', array(), t('Import all')); // Check that there are no errors. $this->assertIdentical($this->configImporter()->getErrors(), array()); // Check that all modules that were uninstalled are now reinstalled. $this->assertModules(array_keys($modules_to_uninstall), TRUE); foreach ($modules_to_uninstall as $module => $info) { $this->assertModuleConfig($module); $this->assertModuleTablesExist($module); } // Ensure that we have no configuration changes to import. $storage_comparer = new StorageComparer($this->container->get('config.storage.staging'), $this->container->get('config.storage'), $this->container->get('config.manager')); $this->assertIdentical($storage_comparer->createChangelist()->getChangelist(), $storage_comparer->getEmptyChangelist()); // Now we have all configuration imported, test all of them for schema // conformance. Ensures all imported default configuration is valid when // all modules are enabled. $names = $this->container->get('config.storage')->listAll(); $factory = $this->container->get('config.factory'); /** @var \Drupal\Core\Config\TypedConfigManagerInterface $typed_config */ $typed_config = $this->container->get('config.typed'); foreach ($names as $name) { $config = $factory->get($name); $this->assertConfigSchema($typed_config, $name, $config->get()); } }
<?php // Remove 'video' field, comment out to run field_delete_field('field_featured_'); field_purge_batch(1);
/** * Reinitialize some Community environment settings. * * @AfterFeature @cleanCommunityEnvironment */ public static function cleanCommunityEnvironment() { // Delete 'community' node type. _node_types_build(TRUE); node_type_delete('community'); field_purge_batch(1); // Delete community's variables. $feature = features_load_feature('nexteuropa_communities'); if (isset($feature->info['features']['variable'])) { foreach ($feature->info['features']['variable'] as $varname) { variable_del($varname); } } // Delete community's menu_links. if (isset($feature->info['features']['menu_links'])) { foreach ($feature->info['features']['menu_links'] as $menulinks) { menu_link_delete(NULL, $menulinks); } } // Delete community's menu_custom. if (isset($feature->info['features']['menu_custom'])) { foreach ($feature->info['features']['menu_custom'] as $menucustom) { $menu = menu_load($menucustom); menu_delete($menu); } } drupal_flush_all_caches(); }
/** * Revert to previous settings after scenario execution. * * @AfterScenario */ public function removeFields() { // Remove the fields. foreach ($this->fields as $field) { field_delete_field($field['field_name']); } field_purge_batch(100); }