Commit 03ddf8c2 authored by Dries's avatar Dries

Issue #2198377 by alexpott: Enforce UUID key name in configuration entities.

parent 3a5c3b32
......@@ -240,7 +240,12 @@ function entity_revision_delete($entity_type, $revision_id) {
*/
function entity_load_by_uuid($entity_type_id, $uuid, $reset = FALSE) {
$entity_type = \Drupal::entityManager()->getDefinition($entity_type_id);
if (!$uuid_key = $entity_type->getKey('uuid')) {
// Configuration entities do not use annotations to set the UUID key.
if ($entity_type->isSubclassOf('Drupal\Core\Config\Entity\ConfigEntityInterface')) {
$uuid_key = 'uuid';
}
elseif (!$uuid_key = $entity_type->getKey('uuid')) {
throw new EntityStorageException("Entity type $entity_type_id does not support UUIDs.");
}
......
......@@ -174,7 +174,12 @@ public function isSyncing() {
* {@inheritdoc}
*/
public function createDuplicate() {
$duplicate = parent::createDuplicate();
$duplicate = clone $this;
$duplicate->set($this->getEntityType()->getKey('id'), NULL);
// @todo Inject the UUID service into the Entity class once possible.
$duplicate->set('uuid', \Drupal::service('uuid')->generate());
// Prevent the new duplicate from being misinterpreted as a rename.
$duplicate->setOriginalId(NULL);
return $duplicate;
......
......@@ -37,13 +37,6 @@
*/
class ConfigStorageController extends EntityStorageControllerBase implements ConfigStorageControllerInterface {
/**
* Name of the entity's UUID property.
*
* @var string
*/
protected $uuidKey = 'uuid';
/**
* The UUID service.
*
......@@ -261,8 +254,8 @@ public function create(array $values = array()) {
$entity->enforceIsNew();
// Assign a new UUID if there is none yet.
if (!isset($entity->{$this->uuidKey})) {
$entity->{$this->uuidKey} = $this->uuidService->generate();
if (!$entity->uuid()) {
$entity->set('uuid', $this->uuidService->generate());
}
$entity->postCreate($this);
......
......@@ -31,8 +31,7 @@
* bundle_of = "custom_block",
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "uuid" = "uuid"
* "label" = "label"
* },
* links = {
* "delete-form" = "custom_block.type_delete",
......
......@@ -31,8 +31,7 @@
* fieldable = FALSE,
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "uuid" = "uuid"
* "label" = "label"
* },
* links = {
* "delete-form" = "block.admin_block_delete",
......
......@@ -23,8 +23,7 @@
* label = @Translation("Breakpoint"),
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "uuid" = "uuid"
* "label" = "label"
* }
* )
*/
......
......@@ -20,8 +20,7 @@
* label = @Translation("Breakpoint group"),
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "uuid" = "uuid"
* "label" = "label"
* }
* )
*/
......
......@@ -75,7 +75,7 @@ public function getFormID() {
*/
public function buildForm(array $form, array &$form_state, $config_type = NULL, $config_name = NULL) {
foreach ($this->entityManager->getDefinitions() as $entity_type => $definition) {
if ($definition->getConfigPrefix() && $definition->hasKey('uuid')) {
if ($definition->isSubclassOf('Drupal\Core\Config\Entity\ConfigEntityInterface')) {
$this->definitions[$entity_type] = $definition;
}
}
......
......@@ -122,7 +122,7 @@ public function buildForm(array $form, array &$form_state) {
$entity_types = array();
foreach ($this->entityManager->getDefinitions() as $entity_type => $definition) {
if ($definition->getConfigPrefix() && $definition->hasKey('uuid')) {
if ($definition->isSubclassOf('Drupal\Core\Config\Entity\ConfigEntityInterface')) {
$entity_types[$entity_type] = $definition->getLabel();
}
}
......@@ -187,21 +187,20 @@ public function validateForm(array &$form, array &$form_state) {
$this->setFormError('import', $form_state, $this->t('Missing ID key "@id_key" for this @entity_type import.', array('@id_key' => $id_key, '@entity_type' => $definition->getLabel())));
return;
}
$uuid_key = $definition->getKey('uuid');
// If there is an existing entity, ensure matching ID and UUID.
if ($entity = $entity_storage->load($data[$id_key])) {
$this->configExists = $entity;
if (!isset($data[$uuid_key])) {
if (!isset($data['uuid'])) {
$this->setFormError('import', $form_state, $this->t('An entity with this machine name already exists but the import did not specify a UUID.'));
return;
}
if ($data[$uuid_key] !== $entity->uuid()) {
if ($data['uuid'] !== $entity->uuid()) {
$this->setFormError('import', $form_state, $this->t('An entity with this machine name already exists but the UUID does not match.'));
return;
}
}
// If there is no entity with a matching ID, check for a UUID match.
elseif (isset($data[$uuid_key]) && $entity_storage->loadByProperties(array($uuid_key => $data[$uuid_key]))) {
elseif (isset($data['uuid']) && $entity_storage->loadByProperties(array('uuid' => $data['uuid']))) {
$this->setFormError('import', $form_state, $this->t('An entity with this UUID already exists but the machine name does not match.'));
}
}
......
......@@ -78,6 +78,13 @@ public function testStorageControllerMethods() {
));
$entity->save();
// Ensure that the configuration entity can be loaded by UUID.
$entity_loaded_by_uuid = entity_load_by_uuid($entity_type->id(), $entity->uuid());
// Compare UUIDs as the objects are not identical since
// $entity->enforceIsNew is FALSE and $entity_loaded_by_uuid->enforceIsNew
// is NULL.
$this->assertIdentical($entity->uuid(), $entity_loaded_by_uuid->uuid());
$entities = $this->storage->loadByProperties();
$this->assertEqual(count($entities), 3, 'Three entities are loaded when no properties are specified.');
......
......@@ -124,7 +124,7 @@ public function testExport() {
$this->drupalLogin($this->drupalCreateUser(array('export configuration')));
$this->drupalGet('admin/config/development/configuration/single/export/system.simple');
$this->assertFieldByXPath('//select[@name="config_type"]//option', t('Date format'), 'The date format entity type is selected when specified in the URL.');
$this->assertFieldByXPath('//select[@name="config_type"]//option[@selected="selected"]', t('Simple configuration'), 'The simple configuration option is selected when specified in the URL.');
// Spot check several known simple configuration files.
$element = $this->xpath('//select[@name="config_name"]');
$options = $this->getAllOptions($element[0]);
......@@ -138,10 +138,10 @@ public function testExport() {
$this->assertFieldByXPath('//textarea[@name="export"]', "toolkit: gd\n", 'The expected system configuration is displayed.');
$this->drupalGet('admin/config/development/configuration/single/export/date_format');
$this->assertFieldByXPath('//select[@name="config_type"]//option', t('Date format'), 'The date format entity type is selected when specified in the URL.');
$this->assertFieldByXPath('//select[@name="config_type"]//option[@selected="selected"]', t('Date format'), 'The date format entity type is selected when specified in the URL.');
$this->drupalGet('admin/config/development/configuration/single/export/date_format/fallback');
$this->assertFieldByXPath('//select[@name="config_name"]//option', t('Fallback date format'), 'The fallback date format config entity is selected when specified in the URL.');
$this->assertFieldByXPath('//select[@name="config_name"]//option[@selected="selected"]', t('Fallback date format'), 'The fallback date format config entity is selected when specified in the URL.');
$fallback_date = \Drupal::entityManager()->getStorageController('date_format')->load('fallback');
$data = \Drupal::service('config.storage')->encode($fallback_date->getExportProperties());
......
......@@ -23,8 +23,7 @@
* config_prefix = "query",
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "uuid" = "uuid"
* "label" = "label"
* }
* )
*
......
......@@ -29,7 +29,6 @@
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "uuid" = "uuid",
* "status" = "status"
* },
* links = {
......
......@@ -31,8 +31,7 @@
* bundle_of = "contact_message",
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "uuid" = "uuid"
* "label" = "label"
* },
* links = {
* "delete-form" = "contact.category_delete",
......
......@@ -17,8 +17,7 @@
* id = "editor",
* label = @Translation("Editor"),
* entity_keys = {
* "id" = "format",
* "uuid" = "uuid"
* "id" = "format"
* }
* )
*/
......
......@@ -20,7 +20,6 @@
* config_prefix = "form_display",
* entity_keys = {
* "id" = "id",
* "uuid" = "uuid",
* "status" = "status"
* }
* )
......
......@@ -42,8 +42,7 @@
* admin_permission = "administer display modes",
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "uuid" = "uuid"
* "label" = "label"
* },
* links = {
* "delete-form" = "entity.form_mode_delete",
......
......@@ -25,7 +25,6 @@
* config_prefix = "view_display",
* entity_keys = {
* "id" = "id",
* "uuid" = "uuid",
* "status" = "status"
* }
* )
......
......@@ -42,8 +42,7 @@
* admin_permission = "administer display modes",
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "uuid" = "uuid"
* "label" = "label"
* },
* links = {
* "delete-form" = "entity.view_mode_delete",
......
......@@ -28,8 +28,7 @@
* config_prefix = "field",
* entity_keys = {
* "id" = "id",
* "label" = "id",
* "uuid" = "uuid"
* "label" = "id"
* }
* )
*/
......
......@@ -27,8 +27,7 @@
* config_prefix = "instance",
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "uuid" = "uuid"
* "label" = "label"
* }
* )
*/
......
......@@ -35,7 +35,6 @@
* entity_keys = {
* "id" = "format",
* "label" = "name",
* "uuid" = "uuid",
* "weight" = "weight",
* "status" = "status"
* },
......
......@@ -36,8 +36,7 @@
* config_prefix = "style",
* entity_keys = {
* "id" = "name",
* "label" = "label",
* "uuid" = "uuid"
* "label" = "label"
* },
* links = {
* "flush-form" = "image.style_flush",
......
......@@ -32,8 +32,7 @@
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "weight" = "weight",
* "uuid" = "uuid"
* "weight" = "weight"
* },
* links = {
* "delete-form" = "language.delete",
......
......@@ -32,8 +32,7 @@
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "weight" = "weight",
* "uuid" = "uuid"
* "weight" = "weight"
* }
* )
*/
......
......@@ -33,8 +33,7 @@
* bundle_of = "node",
* entity_keys = {
* "id" = "type",
* "label" = "name",
* "uuid" = "uuid"
* "label" = "name"
* },
* links = {
* "add-form" = "node.add",
......
......@@ -30,8 +30,7 @@
* config_prefix = "mappings",
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "uuid" = "uuid"
* "label" = "label"
* },
* links = {
* "edit-form" = "picture.mapping_page_edit",
......
......@@ -19,8 +19,7 @@
* label = @Translation("RDF mapping"),
* config_prefix = "mapping",
* entity_keys = {
* "id" = "id",
* "uuid" = "uuid"
* "id" = "id"
* }
* )
*/
......
......@@ -44,7 +44,6 @@
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "uuid" = "uuid",
* "weight" = "weight",
* "status" = "status"
* }
......
......@@ -33,8 +33,7 @@
* config_prefix = "set",
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "uuid" = "uuid"
* "label" = "label"
* },
* links = {
* "customize-form" = "shortcut.set_customize",
......
......@@ -22,8 +22,7 @@
* admin_permission = "administer actions",
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "uuid" = "uuid"
* "label" = "label"
* }
* )
*/
......
......@@ -29,8 +29,7 @@
* },
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "uuid" = "uuid"
* "label" = "label"
* },
* admin_permission = "administer site configuration",
* links = {
......
......@@ -24,8 +24,7 @@
* admin_permission = "administer menu",
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "uuid" = "uuid"
* "label" = "label"
* }
* )
*/
......
......@@ -32,8 +32,7 @@
* entity_keys = {
* "id" = "vid",
* "label" = "name",
* "weight" = "weight",
* "uuid" = "uuid"
* "weight" = "weight"
* },
* links = {
* "add-form" = "taxonomy.term_add",
......
......@@ -22,8 +22,7 @@
* },
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "uuid" = "uuid"
* "label" = "label"
* }
* )
*/
......
......@@ -31,7 +31,6 @@
* config_prefix = "role",
* entity_keys = {
* "id" = "id",
* "uuid" = "uuid",
* "weight" = "weight",
* "label" = "label"
* },
......
......@@ -29,7 +29,6 @@
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "uuid" = "uuid",
* "status" = "status"
* }
* )
......
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