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.');