diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php b/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php index d8e2ed5..31df36c 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php @@ -317,8 +317,14 @@ public function create(array $values) { $values += array('langcode' => language_default()->id); $entity = new $class($values, $this->entityType); - // Mark this entity as new, so isNew() returns TRUE. This does not check - // whether a configuration entity with the same ID (if any) already exists. + if (!$entity->isNew()) { + // Check to see if an entity already exists. + $config = config($this->getConfigPrefix() . $entity->id()); + if (!$config->isNew()) { + throw new EntityMalformedException(format_string('The @type entity ID (@id) is not unique.', array('@type' => $this->entityType, '@id' => $entity->id()))); + } + } + // Mark this entity as new, so isNew() returns TRUE. $entity->enforceIsNew(); // Assign a new UUID if there is none yet. diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockStorageUnitTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockStorageUnitTest.php index 41b5f4d..9eb8f99 100644 --- a/core/modules/block/lib/Drupal/block/Tests/BlockStorageUnitTest.php +++ b/core/modules/block/lib/Drupal/block/Tests/BlockStorageUnitTest.php @@ -133,7 +133,7 @@ protected function loadTests() { */ protected function renderTests() { // Test the rendering of a block. - $entity = entity_load('block', 'stark.test_block'); + $entity = $this->controller->load('stark.test_block'); $output = entity_view($entity, 'block'); $expected = array(); $expected[] = '
'; diff --git a/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointThemeTest.php b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointThemeTest.php index 0091300..228cb69 100644 --- a/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointThemeTest.php +++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointThemeTest.php @@ -40,19 +40,7 @@ public function setUp() { */ public function testThemeBreakpoints() { // Verify the breakpoint group for breakpoint_test_theme was created. - $breakpoint_group_obj = entity_create('breakpoint_group', array( - 'label' => 'Breakpoint test theme', - 'name' => 'breakpoint_test_theme', - 'source' => 'breakpoint_test_theme', - 'sourceType' => Breakpoint::SOURCE_TYPE_THEME, - 'id' => Breakpoint::SOURCE_TYPE_THEME . '.breakpoint_test_theme.breakpoint_test_theme', - )); - $breakpoint_group_obj->breakpoints = array( - 'theme.breakpoint_test_theme.mobile' => array(), - 'theme.breakpoint_test_theme.narrow' => array(), - 'theme.breakpoint_test_theme.wide' => array(), - 'theme.breakpoint_test_theme.tv' => array(), - ); + $breakpoint_group_obj = entity_load('breakpoint_group', Breakpoint::SOURCE_TYPE_THEME . '.breakpoint_test_theme.breakpoint_test_theme'); // Verify we can load this breakpoint defined by the theme. $this->verifyBreakpointGroup($breakpoint_group_obj); @@ -67,18 +55,7 @@ public function testThemeBreakpoints() { */ public function testThemeBreakpointGroup() { // Verify the breakpoint group 'test' was created by breakpoint_test_theme. - $breakpoint_group_obj = entity_create('breakpoint_group', array( - 'label' => 'Test Theme', - 'name' => 'test', - 'sourceType' => Breakpoint::SOURCE_TYPE_THEME, - 'source' => 'breakpoint_test_theme', - 'id' => Breakpoint::SOURCE_TYPE_THEME . '.breakpoint_test_theme.test', - )); - $breakpoint_group_obj->breakpoints = array( - 'theme.breakpoint_test_theme.mobile' => array('1.5x', '2.x'), - 'theme.breakpoint_test_theme.narrow' => array(), - 'theme.breakpoint_test_theme.wide' => array(), - ); + $breakpoint_group_obj = entity_load('breakpoint_group', Breakpoint::SOURCE_TYPE_THEME . '.breakpoint_test_theme.test'); // Verify we can load this breakpoint defined by the theme. $this->verifyBreakpointGroup($breakpoint_group_obj); @@ -92,24 +69,9 @@ public function testThemeBreakpointGroup() { * Test the breakpoints defined by the custom group in the module. */ public function testThemeBreakpointGroupModule() { - // Call the import manually, since the testbot needs to enable the module - // first, otherwise the theme isn't detected. - _breakpoint_import_breakpoint_groups('breakpoint_theme_test', Breakpoint::SOURCE_TYPE_MODULE); - - // Verify the breakpoint group 'module_test' was created by + // Verify the breakpoint group 'module_test' was created by the // breakpoint_theme_test module. - $breakpoint_group_obj = entity_create('breakpoint_group', array( - 'label' => 'Test Module', - 'name' => 'module_test', - 'sourceType' => Breakpoint::SOURCE_TYPE_MODULE, - 'source' => 'breakpoint_theme_test', - 'id' => Breakpoint::SOURCE_TYPE_MODULE . '.breakpoint_theme_test.module_test', - )); - $breakpoint_group_obj->breakpoints = array( - 'theme.breakpoint_test_theme.mobile' => array(), - 'theme.breakpoint_test_theme.narrow' => array(), - 'theme.breakpoint_test_theme.wide' => array(), - ); + $breakpoint_group_obj = entity_load('breakpoint_group', Breakpoint::SOURCE_TYPE_MODULE . '.breakpoint_theme_test.module_test'); // Verify we can load this breakpoint defined by the theme. $this->verifyBreakpointGroup($breakpoint_group_obj); diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityTest.php index faaccde..59568df 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityTest.php @@ -139,26 +139,6 @@ function testCRUD() { $this->assertIdentical($config_test->isNew(), FALSE); $this->assertIdentical($config_test->getOriginalID(), $expected['id']); - // Re-create the entity with the same ID and verify updated status. - $same_id = entity_create('config_test', array( - 'id' => $config_test->id(), - )); - $this->assertIdentical($same_id->isNew(), TRUE); - $status = $same_id->save(); - $this->assertIdentical($status, SAVED_UPDATED); - - // Verify that the entity was overwritten. - $same_id = entity_load('config_test', $config_test->id()); - $this->assertIdentical($same_id->id(), $config_test->id()); - // Note: Reloading loads from FileStorage, and FileStorage enforces strings. - $this->assertIdentical($same_id->label(), ''); - $this->assertNotEqual($same_id->uuid(), $config_test->uuid()); - - // Delete the overridden entity first. - $same_id->delete(); - // Revert to previous state. - $config_test->save(); - // Verify that renaming the ID returns correct status and properties. $ids = array($expected['id'], 'second_' . $this->randomName(4), 'third_' . $this->randomName(4)); for ($i = 1; $i < 3; $i++) { diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php index 8be1055..029e239 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php @@ -8,6 +8,7 @@ namespace Drupal\config\Tests; use Drupal\simpletest\DrupalUnitTestBase; +use Drupal\Core\Entity\EntityMalformedException; /** * Unit tests for configuration controllers and objects. @@ -69,5 +70,30 @@ public function testStorageControllerMethods() { $this->assertEqual(count($entities), 2, 'Two entities are loaded when the style property is specified.'); $this->assertEqual(reset($entities)->get('style'), $style, 'The loaded entities have the style value specified.'); } + + /** + * Tests the behavior of creating conflicting entities. + * + * @todo Add tests for renaming and saving an existing config entity to + * another existing ID. + */ + public function testUniqueID() { + // Create an entity with a label. + $entity = entity_create('config_test', array('id' => 'foo', 'label' => 'Foo', 'style' => 'foo')); + $entity->save(); + + // Create an entity with the same ID, but a different label. + try { + $entity = entity_create('config_test', array('id' => 'foo', 'label' => 'Bananas')); + $entity->save(); + $this->fail('EntityMalformedException was thrown.'); + } + catch (EntityMalformedException $e) { + $this->pass('EntityMalformedException was thrown.'); + } + // Creating an entity with the same machine name should not succeed. + $this->assertEqual($entity->label(), 'Foo', 'The entity label was not overwritten.'); + $this->assertEqual($entity->style, 'foo', 'The entity style was not overwritten.'); + } } diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigInstallTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigInstallTest.php index 3d4093d..dd18cba 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigInstallTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigInstallTest.php @@ -8,6 +8,7 @@ namespace Drupal\config\Tests; use Drupal\simpletest\DrupalUnitTestBase; +use Drupal\Core\Entity\EntityMalformedException; /** * Tests installation of configuration objects in installation functionality. @@ -65,4 +66,19 @@ function testModuleInstallation() { $this->assertFalse(isset($GLOBALS['hook_config_test']['predelete'])); $this->assertFalse(isset($GLOBALS['hook_config_test']['delete'])); } + + /** + * Tests enabling a module with a duplicate configuration entity. + */ + function testDuplicate() { + $this->enableModules(array('config_test')); + $this->assertEqual(config('config_test.dynamic.default')->get('label'), 'Default', "Configuration object label is 'Default'."); + try { + $this->enableModules(array('config_test_duplicate')); + } + catch (EntityMalformedException $e) { + } + $this->assertEqual(config('config_test.dynamic.default')->get('label'), 'Default', 'Configuration object is not silently overwritten on import.'); + } + } diff --git a/core/modules/config/tests/config_test_duplicate/config/config_test.dynamic.default.yml b/core/modules/config/tests/config_test_duplicate/config/config_test.dynamic.default.yml new file mode 100644 index 0000000..deaa6b0 --- /dev/null +++ b/core/modules/config/tests/config_test_duplicate/config/config_test.dynamic.default.yml @@ -0,0 +1,4 @@ +# This purposefully duplicates config_test.dynamic.default.yml from +# config_test.module, with different values. +id: default +label: Not default diff --git a/core/modules/config/tests/config_test_duplicate/config_test_duplicate.info.yml b/core/modules/config/tests/config_test_duplicate/config_test_duplicate.info.yml new file mode 100644 index 0000000..a3ef637 --- /dev/null +++ b/core/modules/config/tests/config_test_duplicate/config_test_duplicate.info.yml @@ -0,0 +1,6 @@ +name: Duplicate default configuration +type: module +package: Testing +version: VERSION +core: 8.x +hidden: TRUE diff --git a/core/modules/config/tests/config_test_duplicate/config_test_duplicate.module b/core/modules/config/tests/config_test_duplicate/config_test_duplicate.module new file mode 100644 index 0000000..f6c2685 --- /dev/null +++ b/core/modules/config/tests/config_test_duplicate/config_test_duplicate.module @@ -0,0 +1,6 @@ +get(); + // Change the machine name to prevent a conflict. + $values['name'] = strtolower($this->randomName(8)); $created = $this->controller->create($values); $this->assertTrue($created instanceof View, 'Created object is a View.');