diff --git a/core/lib/Drupal/Core/Config/ConfigImporter.php b/core/lib/Drupal/Core/Config/ConfigImporter.php index 090b883..24d5e71 100644 --- a/core/lib/Drupal/Core/Config/ConfigImporter.php +++ b/core/lib/Drupal/Core/Config/ConfigImporter.php @@ -8,8 +8,6 @@ namespace Drupal\Core\Config; use Drupal\Component\Utility\String; -use Drupal\Core\Config\ConfigEvents; -use Drupal\Core\Config\Entity\ConfigStorageControllerInterface; use Drupal\Core\Config\Entity\ImportableEntityStorageInterface; use Drupal\Core\DependencyInjection\DependencySerialization; use Drupal\Core\Entity\EntityStorageException; diff --git a/core/lib/Drupal/Core/Config/StorageComparer.php b/core/lib/Drupal/Core/Config/StorageComparer.php index 02cd64f..36031ab 100644 --- a/core/lib/Drupal/Core/Config/StorageComparer.php +++ b/core/lib/Drupal/Core/Config/StorageComparer.php @@ -170,11 +170,27 @@ protected function addChangelistCreate() { * should be updated before field instances. */ protected function addChangelistUpdate() { + $recreates = array(); foreach (array_intersect($this->sourceNames, $this->targetNames) as $name) { if ($this->sourceData[$name] !== $this->targetData[$name]) { - $this->addChangeList('update', array($name)); + if (isset($this->sourceData[$name]['uuid']) && $this->sourceData[$name]['uuid'] != $this->targetData[$name]['uuid']) { + // The entity has the same file as an existing entity but the UUIDs do + // not match. This means that the the entity has been recreated so + // config synchronisation should do the same. + $recreates[] = $name; + } + else { + $this->addChangeList('update', array($name)); + } } } + + if (!empty($recreates)) { + // Recreates should become deletes and creates. Deletes should be ordered + // so that dependencies are deleted first. + $this->addChangeList('create', $recreates); + $this->addChangeList('delete', array_reverse($recreates)); + } } /** diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigImportRecreateTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigImportRecreateTest.php new file mode 100644 index 0000000..89134db --- /dev/null +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigImportRecreateTest.php @@ -0,0 +1,102 @@ + 'Import renamed configuration', + 'description' => 'Tests importing renamed configuration.', + 'group' => 'Configuration', + ); + } + + public function setUp() { + parent::setUp(); + + $this->installSchema('system', 'config_snapshot'); + $this->installSchema('node', 'node'); + + // Set up the ConfigImporter object for testing. + $storage_comparer = new StorageComparer( + $this->container->get('config.storage.staging'), + $this->container->get('config.storage') + ); + $this->configImporter = new ConfigImporter( + $storage_comparer->createChangelist(), + $this->container->get('event_dispatcher'), + $this->container->get('config.manager'), + $this->container->get('lock'), + $this->container->get('config.typed') + ); + $this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.staging')); + } + + public function testRecreateEntity() { + $type_name = Unicode::strtolower($this->randomName(16)); + $content_type = entity_create('node_type', array( + 'type' => $type_name, + 'name' => 'first node type', + )); + $content_type->save(); + /** @var \Drupal\Core\Config\StorageInterface $active */ + $active = $this->container->get('config.storage'); + /** @var \Drupal\Core\Config\StorageInterface $staging */ + $staging = $this->container->get('config.storage.staging'); + + $config_name = $content_type->getEntityType()->getConfigPrefix() . '.' . $content_type->id(); + $this->copyConfig($active, $staging); + + $content_type->delete(); + $this->assertFalse($active->exists($config_name), 'Content type\'s old name does not exist active store.'); + // Recreate with the same type - this will have a different UUID. + $content_type = entity_create('node_type', array( + 'type' => $type_name, + 'name' => 'second node type', + )); + $content_type->save(); + + $this->configImporter->reset(); + $this->assertEqual(6, count($this->configImporter->getUnprocessed('create')), 'There are 6 configuration items to create.'); + $this->assertEqual(6, count($this->configImporter->getUnprocessed('delete')), 'There are 6 configuration items to delete.'); + $this->assertEqual(0, count($this->configImporter->getUnprocessed('update')), 'There are no configuration items to update.'); + + $this->configImporter->import(); + + // Verify that there is nothing more to import. + $this->assertFalse($this->configImporter->reset()->hasUnprocessedChanges()); + $content_type = entity_load('node_type', $type_name); + $this->assertEqual('first node type', $content_type->label()); + } + + +} + diff --git a/core/modules/field/field.module b/core/modules/field/field.module index 0c173c2..7c258c5 100644 --- a/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -223,6 +223,15 @@ function field_entity_bundle_rename($entity_type, $bundle_old, $bundle_new) { * simple DELETE query). */ function field_entity_bundle_delete($entity_type, $bundle) { + $view_displays = entity_load_multiple_by_properties('entity_view_display', array('targetEntityType' => $entity_type, 'bundle' => $bundle)); + foreach ($view_displays as $view_display) { + $view_display->delete(); + } + $form_displays = entity_load_multiple_by_properties('entity_form_display', array('targetEntityType' => $entity_type, 'bundle' => $bundle)); + foreach ($form_displays as $form_display) { + $form_display->delete(); + } + // Get the instances on the bundle. entity_load_multiple_by_properties() must // be used here since field_info_instances() does not return instances for // disabled entity types or bundles.