Commit 682a214a authored by catch's avatar catch
Browse files

Issue #2224873 by alexpott: Handle a config entity with the same name but...

Issue #2224873 by alexpott: Handle a config entity with the same name but different UUID being imported.
parent 4c109a59
......@@ -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;
......
......@@ -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 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));
}
}
/**
......
<?php
/**
* @file
* Contains \Drupal\config\Tests\ConfigImportRecreateTest.
*/
namespace Drupal\config\Tests;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Config\ConfigImporter;
use Drupal\Core\Config\StorageComparer;
use Drupal\simpletest\DrupalUnitTestBase;
/**
* Tests importing recreated configuration entities.
*/
class ConfigImportRecreateTest extends DrupalUnitTestBase {
/**
* Config Importer object used for testing.
*
* @var \Drupal\Core\Config\ConfigImporter
*/
protected $configImporter;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('system', 'entity', 'field', 'text', 'node');
public static function getInfo() {
return array(
'name' => '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' => 'Node type one',
));
$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);
// Delete the content type. This will also delete a field, a field instance,
// an entity view display and an entity form display.
$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' => 'Node type two',
));
$content_type->save();
$this->configImporter->reset();
// A node type, a field, a field instance an entity view display and an
// entity form display will be recreated.
$creates = $this->configImporter->getUnprocessed('create');
$deletes = $this->configImporter->getUnprocessed('delete');
$this->assertEqual(5, count($creates), 'There are 5 configuration items to create.');
$this->assertEqual(5, count($deletes), 'There are 5 configuration items to delete.');
$this->assertEqual(0, count($this->configImporter->getUnprocessed('update')), 'There are no configuration items to update.');
$this->assertIdentical($creates, array_reverse($deletes), 'Deletes and creates contain the same configuration names in opposite orders due to dependencies.');
$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('Node type one', $content_type->label());
}
}
......@@ -429,6 +429,13 @@ public static function postDelete(EntityStorageControllerInterface $storage_cont
}
}
// If this is part of a configuration synchronization then the following
// configuration updates are not necessary.
$entity = reset($instances);
if ($entity->isSyncing()) {
return;
}
// Delete fields that have no more instances.
$fields_to_delete = array();
foreach ($instances as $instance) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment