From 03bd7fc75b824e3eceeb7172d8d79a42d9389b2b Mon Sep 17 00:00:00 2001 From: Nathaniel Catchpole <catch@35733.no-reply.drupal.org> Date: Thu, 1 Oct 2015 19:43:05 +0100 Subject: [PATCH] Issue #2172843 by fgm, marthinal, pfrenssen, amateescu, andypost, Wim Leers, stefan.r, pwieck, deepak_123: Remove ability to update entity bundle machine names --- .../Config/Entity/ConfigEntityBundleBase.php | 61 ++++---- .../Core/Entity/BundleEntityFormBase.php | 41 +++++ .../Entity/EntityBundleListenerInterface.php | 16 +- core/lib/Drupal/Core/Entity/EntityManager.php | 25 --- .../Entity/Sql/SqlContentEntityStorage.php | 34 ---- core/lib/Drupal/Core/Entity/entity.api.php | 30 +--- .../Core/Field/Entity/BaseFieldOverride.php | 5 +- .../lib/Drupal/Core/Field/FieldConfigBase.php | 16 +- .../Core/Field/FieldConfigInterface.php | 9 -- .../src/BlockContentTypeForm.php | 9 +- core/modules/book/src/Tests/BookTest.php | 93 ----------- core/modules/field/field.module | 24 --- core/modules/field/src/Entity/FieldConfig.php | 2 +- .../src/Tests/FieldAttachStorageTest.php | 18 +-- core/modules/field_ui/field_ui.module | 9 -- .../field_ui/src/Tests/EntityDisplayTest.php | 41 +---- .../field_ui/src/Tests/ManageFieldsTest.php | 13 -- core/modules/language/language.module | 9 -- .../LanguageConfigurationElementTest.php | 32 ++-- core/modules/node/src/NodeTypeForm.php | 15 +- .../Tests/NodeTypeRenameConfigImportTest.php | 145 ------------------ core/modules/node/src/Tests/NodeTypeTest.php | 10 +- core/modules/shortcut/src/ShortcutSetForm.php | 7 +- .../src/Tests/Entity/FieldSqlStorageTest.php | 29 ---- .../modules/entity_test/entity_test.module | 20 --- .../taxonomy/src/Entity/Vocabulary.php | 42 ----- .../taxonomy/src/Tests/VocabularyCrudTest.php | 31 ---- core/modules/taxonomy/src/VocabularyForm.php | 16 +- 28 files changed, 126 insertions(+), 676 deletions(-) create mode 100644 core/lib/Drupal/Core/Entity/BundleEntityFormBase.php delete mode 100644 core/modules/node/src/Tests/NodeTypeRenameConfigImportTest.php diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBundleBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBundleBase.php index b2fd1719e343..8e27aef731dd 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBundleBase.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBundleBase.php @@ -7,8 +7,7 @@ namespace Drupal\Core\Config\Entity; -use Drupal\Core\Entity\Entity\EntityFormDisplay; -use Drupal\Core\Entity\Entity\EntityViewDisplay; +use Drupal\Core\Config\ConfigNameException; use Drupal\Core\Entity\EntityStorageInterface; /** @@ -19,31 +18,6 @@ */ abstract class ConfigEntityBundleBase extends ConfigEntityBase { - /** - * Renames displays when a bundle is renamed. - */ - protected function renameDisplays() { - // Rename entity displays. - if ($this->getOriginalId() !== $this->id()) { - foreach ($this->loadDisplays('entity_view_display') as $display) { - $new_id = $this->getEntityType()->getBundleOf() . '.' . $this->id() . '.' . $display->getMode(); - $display->set('id', $new_id); - $display->setTargetBundle($this->id()); - $display->save(); - } - } - - // Rename entity form displays. - if ($this->getOriginalId() !== $this->id()) { - foreach ($this->loadDisplays('entity_form_display') as $form_display) { - $new_id = $this->getEntityType()->getBundleOf() . '.' . $this->id() . '.' . $form_display->getMode(); - $form_display->set('id', $new_id); - $form_display->setTargetBundle($this->id()); - $form_display->save(); - } - } - } - /** * Deletes display if a bundle is deleted. */ @@ -80,12 +54,6 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) { } // Entity bundle field definitions may depend on bundle settings. $entity_manager->clearCachedFieldDefinitions(); - - if ($this->getOriginalId() != $this->id()) { - // If the entity was renamed, update the displays. - $this->renameDisplays(); - $entity_manager->onBundleRename($this->getOriginalId(), $this->id(), $bundle_of); - } } } @@ -101,6 +69,33 @@ public static function postDelete(EntityStorageInterface $storage, array $entiti } } + /** + * Acts on an entity before the presave hook is invoked. + * + * Used before the entity is saved and before invoking the presave hook. + * + * Ensure that config entities which are bundles of other entities cannot have + * their ID changed. + * + * @param \Drupal\Core\Entity\EntityStorageInterface $storage + * The entity storage object. + * + * @throws \Drupal\Core\Config\ConfigNameException + * Thrown when attempting to rename a bundle entity. + */ + public function preSave(EntityStorageInterface $storage) { + parent::preSave($storage); + + // Only handle renames, not creations. + if (!$this->isNew() && $this->getOriginalId() !== $this->id()) { + $bundle_type = $this->getEntityType(); + $bundle_of = $bundle_type->getBundleOf(); + if (!empty($bundle_of)) { + throw new ConfigNameException("The machine name of the '{$bundle_type->getLabel()}' bundle cannot be changed."); + } + } + } + /** * Returns view or form displays for this bundle. * diff --git a/core/lib/Drupal/Core/Entity/BundleEntityFormBase.php b/core/lib/Drupal/Core/Entity/BundleEntityFormBase.php new file mode 100644 index 000000000000..88ad30cbd756 --- /dev/null +++ b/core/lib/Drupal/Core/Entity/BundleEntityFormBase.php @@ -0,0 +1,41 @@ +<?php + +/** + * @file + * Contains \Drupal\Core\Entity\BundleEntityFormBase. + */ + +namespace Drupal\Core\Entity; + +/** + * Class BundleEntityFormBase is a base form for bundle config entities. + */ +class BundleEntityFormBase extends EntityForm { + + /** + * Protects the bundle entity's ID property's form element against changes. + * + * This method is assumed to be called on a completely built entity form, + * including a form element for the bundle config entity's ID property. + * + * @param array $form + * The completely built entity bundle form array. + * + * @return array + * The updated entity bundle form array. + */ + protected function protectBundleIdElement(array $form) { + $entity = $this->getEntity(); + $id_key = $entity->getEntityType()->getKey('id'); + assert('isset($form[$id_key])'); + $element = &$form[$id_key]; + + // Make sure the element is not accidentally re-enabled if it has already + // been disabled. + if (empty($element['#disabled'])) { + $element['#disabled'] = !$entity->isNew(); + } + return $form; + } + +} diff --git a/core/lib/Drupal/Core/Entity/EntityBundleListenerInterface.php b/core/lib/Drupal/Core/Entity/EntityBundleListenerInterface.php index cbe96b394933..f1ad9a973ede 100644 --- a/core/lib/Drupal/Core/Entity/EntityBundleListenerInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityBundleListenerInterface.php @@ -8,7 +8,7 @@ namespace Drupal\Core\Entity; /** - * An interface for reacting to entity bundle creation, deletion, and renames. + * An interface for reacting to entity bundle creation and deletion. * * @todo Convert to Symfony events: https://www.drupal.org/node/2332935 */ @@ -24,20 +24,6 @@ interface EntityBundleListenerInterface { */ public function onBundleCreate($bundle, $entity_type_id); - /** - * Reacts to a bundle being renamed. - * - * This method runs before fields are updated with the new bundle name. - * - * @param string $bundle - * The name of the bundle being renamed. - * @param string $bundle_new - * The new name of the bundle. - * @param string $entity_type_id - * The entity type to which the bundle is bound; e.g. 'node' or 'user'. - */ - public function onBundleRename($bundle, $bundle_new, $entity_type_id); - /** * Reacts to a bundle being deleted. * diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php index e4e0f8daced7..f00fd2cf956e 100644 --- a/core/lib/Drupal/Core/Entity/EntityManager.php +++ b/core/lib/Drupal/Core/Entity/EntityManager.php @@ -1367,31 +1367,6 @@ public function onBundleCreate($bundle, $entity_type_id) { $this->moduleHandler->invokeAll('entity_bundle_create', array($entity_type_id, $bundle)); } - /** - * {@inheritdoc} - */ - public function onBundleRename($bundle_old, $bundle_new, $entity_type_id) { - $this->clearCachedBundles(); - // Notify the entity storage. - $storage = $this->getStorage($entity_type_id); - if ($storage instanceof EntityBundleListenerInterface) { - $storage->onBundleRename($bundle_old, $bundle_new, $entity_type_id); - } - - // Rename existing base field bundle overrides. - $overrides = $this->getStorage('base_field_override')->loadByProperties(array('entity_type' => $entity_type_id, 'bundle' => $bundle_old)); - foreach ($overrides as $override) { - $override->set('id', $entity_type_id . '.' . $bundle_new . '.' . $override->getName()); - $override->set('bundle', $bundle_new); - $override->allowBundleRename(); - $override->save(); - } - - // Invoke hook_entity_bundle_rename() hook. - $this->moduleHandler->invokeAll('entity_bundle_rename', array($entity_type_id, $bundle_old, $bundle_new)); - $this->clearCachedFieldDefinitions(); - } - /** * {@inheritdoc} */ diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php index e1283be5c518..12184dffe4dd 100644 --- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php +++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php @@ -1493,40 +1493,6 @@ public function onBundleCreate($bundle, $entity_type_id) { } */ public function onBundleDelete($bundle, $entity_type_id) { } - /** - * {@inheritdoc} - */ - public function onBundleRename($bundle, $bundle_new, $entity_type_id) { - // The method runs before the field definitions are updated, so we use the - // old bundle name. - $field_definitions = $this->entityManager->getFieldDefinitions($this->entityTypeId, $bundle); - // We need to handle deleted fields too. For now, this only makes sense for - // configurable fields, so we use the specific API. - // @todo Use the unified store of deleted field definitions instead in - // https://www.drupal.org/node/2282119 - $field_definitions += entity_load_multiple_by_properties('field_config', array('entity_type' => $this->entityTypeId, 'bundle' => $bundle, 'deleted' => TRUE, 'include_deleted' => TRUE)); - $table_mapping = $this->getTableMapping(); - - foreach ($field_definitions as $field_definition) { - $storage_definition = $field_definition->getFieldStorageDefinition(); - if ($table_mapping->requiresDedicatedTableStorage($storage_definition)) { - $is_deleted = $this->storageDefinitionIsDeleted($storage_definition); - $table_name = $table_mapping->getDedicatedDataTableName($storage_definition, $is_deleted); - $revision_name = $table_mapping->getDedicatedRevisionTableName($storage_definition, $is_deleted); - $this->database->update($table_name) - ->fields(array('bundle' => $bundle_new)) - ->condition('bundle', $bundle) - ->execute(); - if ($this->entityType->isRevisionable()) { - $this->database->update($revision_name) - ->fields(array('bundle' => $bundle_new)) - ->condition('bundle', $bundle) - ->execute(); - } - } - } - } - /** * {@inheritdoc} */ diff --git a/core/lib/Drupal/Core/Entity/entity.api.php b/core/lib/Drupal/Core/Entity/entity.api.php index 6bdde075e0a3..f6ac3841463a 100644 --- a/core/lib/Drupal/Core/Entity/entity.api.php +++ b/core/lib/Drupal/Core/Entity/entity.api.php @@ -139,8 +139,8 @@ * - Field configuration preSave(): hook_field_storage_config_update_forbid() * - Node postSave(): hook_node_access_records() and * hook_node_access_records_alter() - * - Config entities that are acting as entity bundles, in postSave(): - * hook_entity_bundle_create() or hook_entity_bundle_rename() as appropriate + * - Config entities that are acting as entity bundles in postSave(): + * hook_entity_bundle_create() * - Comment: hook_comment_publish() and hook_comment_unpublish() as * appropriate. * @@ -350,6 +350,7 @@ * 'bundle_entity_type' on the \Drupal\node\Entity\Node class. Also, the * bundle config entity type annotation must have a 'bundle_of' entry, * giving the machine name of the entity type it is acting as a bundle for. + * These machine names are considered permanent, they may not be renamed. * - Additional annotations can be seen on entity class examples such as * \Drupal\node\Entity\Node (content) and \Drupal\user\Entity\Role * (configuration). These annotations are documented on @@ -740,31 +741,6 @@ function hook_entity_bundle_create($entity_type_id, $bundle) { \Drupal::service('router.builder')->setRebuildNeeded(); } -/** - * Act on entity_bundle_rename(). - * - * This hook is invoked after the operation has been performed. - * - * @param string $entity_type_id - * The entity type to which the bundle is bound. - * @param string $bundle_old - * The previous name of the bundle. - * @param string $bundle_new - * The new name of the bundle. - * - * @see entity_crud - */ -function hook_entity_bundle_rename($entity_type_id, $bundle_old, $bundle_new) { - // Update the settings associated with the bundle in my_module.settings. - $config = \Drupal::config('my_module.settings'); - $bundle_settings = $config->get('bundle_settings'); - if (isset($bundle_settings[$entity_type_id][$bundle_old])) { - $bundle_settings[$entity_type_id][$bundle_new] = $bundle_settings[$entity_type_id][$bundle_old]; - unset($bundle_settings[$entity_type_id][$bundle_old]); - $config->set('bundle_settings', $bundle_settings); - } -} - /** * Act on entity_bundle_delete(). * diff --git a/core/lib/Drupal/Core/Field/Entity/BaseFieldOverride.php b/core/lib/Drupal/Core/Field/Entity/BaseFieldOverride.php index 751693dbaf35..4a4deb3c9ddf 100644 --- a/core/lib/Drupal/Core/Field/Entity/BaseFieldOverride.php +++ b/core/lib/Drupal/Core/Field/Entity/BaseFieldOverride.php @@ -163,8 +163,7 @@ protected function getBaseFieldDefinition() { * {@inheritdoc} * * @throws \Drupal\Core\Field\FieldException - * If the bundle is being changed and - * BaseFieldOverride::allowBundleRename() has not been called. + * If the bundle is being changed. */ public function preSave(EntityStorageInterface $storage) { // Filter out unknown settings and make sure all settings are present, so @@ -189,7 +188,7 @@ public function preSave(EntityStorageInterface $storage) { if ($this->entity_type != $this->original->entity_type) { throw new FieldException("Cannot change the entity_type of an existing base field bundle override (entity type:{$this->entity_type}, bundle:{$this->original->bundle}, field name: {$this->field_name})"); } - if ($this->bundle != $this->original->bundle && empty($this->bundleRenameAllowed)) { + if ($this->bundle != $this->original->bundle) { throw new FieldException("Cannot change the bundle of an existing base field bundle override (entity type:{$this->entity_type}, bundle:{$this->original->bundle}, field name: {$this->field_name})"); } $previous_definition = $this->original; diff --git a/core/lib/Drupal/Core/Field/FieldConfigBase.php b/core/lib/Drupal/Core/Field/FieldConfigBase.php index da0bca8035f1..e9fbaca654fc 100644 --- a/core/lib/Drupal/Core/Field/FieldConfigBase.php +++ b/core/lib/Drupal/Core/Field/FieldConfigBase.php @@ -179,13 +179,6 @@ abstract class FieldConfigBase extends ConfigEntityBase implements FieldConfigIn */ protected $itemDefinition; - /** - * Flag indicating whether the bundle name can be renamed or not. - * - * @var bool - */ - protected $bundleRenameAllowed = FALSE; - /** * Array of constraint options keyed by constraint plugin ID. * @@ -456,7 +449,7 @@ public function __sleep() { // Only serialize necessary properties, excluding those that can be // recalculated. $properties = get_object_vars($this); - unset($properties['fieldStorage'], $properties['itemDefinition'], $properties['bundleRenameAllowed'], $properties['original']); + unset($properties['fieldStorage'], $properties['itemDefinition'], $properties['original']); return array_keys($properties); } @@ -528,13 +521,6 @@ public function getItemDefinition() { return $this->itemDefinition; } - /** - * {@inheritdoc} - */ - public function allowBundleRename() { - $this->bundleRenameAllowed = TRUE; - } - /** * {@inheritdoc} */ diff --git a/core/lib/Drupal/Core/Field/FieldConfigInterface.php b/core/lib/Drupal/Core/Field/FieldConfigInterface.php index 8b3d21f43a99..ff8501f6a2e5 100644 --- a/core/lib/Drupal/Core/Field/FieldConfigInterface.php +++ b/core/lib/Drupal/Core/Field/FieldConfigInterface.php @@ -282,13 +282,4 @@ public function addConstraint($constraint_name, $options = NULL); */ public function setConstraints(array $constraints); - /** - * Allows a bundle to be renamed. - * - * Renaming a bundle on the instance is allowed when an entity's bundle - * is renamed and when field_entity_bundle_rename() does internal - * housekeeping. - */ - public function allowBundleRename(); - } diff --git a/core/modules/block_content/src/BlockContentTypeForm.php b/core/modules/block_content/src/BlockContentTypeForm.php index 74473cfcc912..9474ccc63c5a 100644 --- a/core/modules/block_content/src/BlockContentTypeForm.php +++ b/core/modules/block_content/src/BlockContentTypeForm.php @@ -7,7 +7,7 @@ namespace Drupal\block_content; -use Drupal\Core\Entity\EntityForm; +use Drupal\Core\Entity\BundleEntityFormBase; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\language\Entity\ContentLanguageSettings; @@ -15,7 +15,7 @@ /** * Base form for category edit forms. */ -class BlockContentTypeForm extends EntityForm { +class BlockContentTypeForm extends BundleEntityFormBase { /** * {@inheritdoc} @@ -48,7 +48,6 @@ public function form(array $form, FormStateInterface $form_state) { 'exists' => '\Drupal\block_content\Entity\BlockContentType::load', ), '#maxlength' => EntityTypeInterface::BUNDLE_MAX_LENGTH, - '#disabled' => !$block_type->isNew(), ); $form['description'] = array( @@ -62,7 +61,7 @@ public function form(array $form, FormStateInterface $form_state) { '#type' => 'checkbox', '#title' => t('Create new revision'), '#default_value' => $block_type->shouldCreateNewRevision(), - '#description' => t('Create a new revision by default for this block type.') + '#description' => t('Create a new revision by default for this block type.'), ); if ($this->moduleHandler->moduleExists('language')) { @@ -91,7 +90,7 @@ public function form(array $form, FormStateInterface $form_state) { '#value' => t('Save'), ); - return $form; + return $this->protectBundleIdElement($form); } /** diff --git a/core/modules/book/src/Tests/BookTest.php b/core/modules/book/src/Tests/BookTest.php index 86c23be4d1a8..b1c9fa3f2893 100644 --- a/core/modules/book/src/Tests/BookTest.php +++ b/core/modules/book/src/Tests/BookTest.php @@ -497,99 +497,6 @@ function testBookDelete() { $this->assertTrue(empty($node->book), 'Deleting childless top-level book node properly allowed.'); } - /* - * Tests node type changing machine name when type is a book allowed type. - */ - function testBookNodeTypeChange() { - $this->drupalLogin($this->adminUser); - // Change the name, machine name and description. - $edit = array( - 'name' => 'Bar', - 'type' => 'bar', - ); - $this->drupalPostForm('admin/structure/types/manage/book', $edit, t('Save content type')); - - // Ensure that the config book.settings:allowed_types has been updated with - // the new machine and the old one has been removed. - $this->assertTrue(book_type_is_allowed('bar'), 'Config book.settings:allowed_types contains the updated node type machine name "bar".'); - $this->assertFalse(book_type_is_allowed('book'), 'Config book.settings:allowed_types does not contain the old node type machine name "book".'); - - $edit = array( - 'name' => 'Basic page', - 'title_label' => 'Title for basic page', - 'type' => 'page', - ); - $this->drupalPostForm('admin/structure/types/add', $edit, t('Save content type')); - - // Add page to the allowed node types. - $edit = array( - 'book_allowed_types[page]' => 'page', - 'book_allowed_types[bar]' => 'bar', - ); - - $this->drupalPostForm('admin/structure/book/settings', $edit, t('Save configuration')); - $this->assertTrue(book_type_is_allowed('bar'), 'Config book.settings:allowed_types contains the bar node type.'); - $this->assertTrue(book_type_is_allowed('page'), 'Config book.settings:allowed_types contains the page node type.'); - - // Test the order of the book.settings::allowed_types configuration is as - // expected. The point of this test is to prove that after changing a node - // type going to admin/structure/book/settings and pressing save without - // changing anything should not alter the book.settings configuration. The - // order will be: - // @code - // array( - // 'bar', - // 'page', - // ); - // @endcode - $current_config = $this->config('book.settings')->get(); - $this->drupalPostForm('admin/structure/book/settings', array(), t('Save configuration')); - $this->assertIdentical($current_config, $this->config('book.settings')->get()); - - // Change the name, machine name and description. - $edit = array( - 'name' => 'Zebra book', - 'type' => 'zebra', - ); - $this->drupalPostForm('admin/structure/types/manage/bar', $edit, t('Save content type')); - $this->assertTrue(book_type_is_allowed('zebra'), 'Config book.settings:allowed_types contains the zebra node type.'); - $this->assertTrue(book_type_is_allowed('page'), 'Config book.settings:allowed_types contains the page node type.'); - - // Test the order of the book.settings::allowed_types configuration is as - // expected. The order should be: - // @code - // array( - // 'page', - // 'zebra', - // ); - // @endcode - $current_config = $this->config('book.settings')->get(); - $this->drupalPostForm('admin/structure/book/settings', array(), t('Save configuration')); - $this->assertIdentical($current_config, $this->config('book.settings')->get()); - - $edit = array( - 'name' => 'Animal book', - 'type' => 'zebra', - ); - $this->drupalPostForm('admin/structure/types/manage/zebra', $edit, t('Save content type')); - - // Test the order of the book.settings::allowed_types configuration is as - // expected. The order should be: - // @code - // array( - // 'page', - // 'zebra', - // ); - // @endcode - $current_config = $this->config('book.settings')->get(); - $this->drupalPostForm('admin/structure/book/settings', array(), t('Save configuration')); - $this->assertIdentical($current_config, $this->config('book.settings')->get()); - - // Ensure that after all the node type changes book.settings:child_type has - // the expected value. - $this->assertEqual($this->config('book.settings')->get('child_type'), 'zebra'); - } - /** * Tests re-ordering of books. */ diff --git a/core/modules/field/field.module b/core/modules/field/field.module index 64a24f6ceff7..666917cd0b24 100644 --- a/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -186,30 +186,6 @@ function field_entity_bundle_field_info(EntityTypeInterface $entity_type, $bundl } } -/** - * Implements hook_entity_bundle_rename(). - */ -function field_entity_bundle_rename($entity_type, $bundle_old, $bundle_new) { - $fields = entity_load_multiple_by_properties('field_config', array('entity_type' => $entity_type, 'bundle' => $bundle_old, 'include_deleted' => TRUE)); - foreach ($fields as $field) { - $id_new = $field->getTargetEntityTypeId() . '.' . $bundle_new . '.' . $field->getName(); - $field->set('id', $id_new); - $field->set('bundle', $bundle_new); - // Save non-deleted fields. - if (!$field->isDeleted()) { - $field->allowBundleRename(); - $field->save(); - } - // Update deleted fields directly in the state storage. - else { - $state = \Drupal::state(); - $deleted_fields = $state->get('field.field.deleted') ?: array(); - $deleted_fields[$field->uuid] = $field->toArray(); - $state->set('field.field.deleted', $deleted_fields); - } - } -} - /** * Implements hook_entity_bundle_delete(). * diff --git a/core/modules/field/src/Entity/FieldConfig.php b/core/modules/field/src/Entity/FieldConfig.php index a889803b480f..1493e41fcd71 100644 --- a/core/modules/field/src/Entity/FieldConfig.php +++ b/core/modules/field/src/Entity/FieldConfig.php @@ -167,7 +167,7 @@ public function preSave(EntityStorageInterface $storage) { if ($this->entity_type != $this->original->entity_type) { throw new FieldException("Cannot change an existing field's entity_type."); } - if ($this->bundle != $this->original->bundle && empty($this->bundleRenameAllowed)) { + if ($this->bundle != $this->original->bundle) { throw new FieldException("Cannot change an existing field's bundle."); } if ($storage_definition->uuid() != $this->original->getFieldStorageDefinition()->uuid()) { diff --git a/core/modules/field/src/Tests/FieldAttachStorageTest.php b/core/modules/field/src/Tests/FieldAttachStorageTest.php index 77c7bacfe9a0..a7c72178e871 100644 --- a/core/modules/field/src/Tests/FieldAttachStorageTest.php +++ b/core/modules/field/src/Tests/FieldAttachStorageTest.php @@ -275,9 +275,9 @@ function testFieldAttachDelete() { } /** - * Test entity_bundle_create() and entity_bundle_rename(). + * Test entity_bundle_create(). */ - function testEntityCreateRenameBundle() { + function testEntityCreateBundle() { $entity_type = 'entity_test_rev'; $this->createFieldWithStorage('', $entity_type); $cardinality = $this->fieldTestData->field_storage->getCardinality(); @@ -298,20 +298,6 @@ function testEntityCreateRenameBundle() { // Verify the field data is present on load. $entity = $this->entitySaveReload($entity); $this->assertEqual(count($entity->{$this->fieldTestData->field_name}), $cardinality, "Data is retrieved for the new bundle"); - - // Rename the bundle. - $new_bundle = 'test_bundle_' . Unicode::strtolower($this->randomMachineName()); - entity_test_rename_bundle($this->fieldTestData->field_definition['bundle'], $new_bundle, $entity_type); - - // Check that the field definition has been updated. - $this->fieldTestData->field = FieldConfig::loadByName($entity_type, $new_bundle, $this->fieldTestData->field_name); - $this->assertIdentical($this->fieldTestData->field->getTargetBundle(), $new_bundle, "Bundle name has been updated in the field."); - - // Verify the field data is present on load. - $controller = $this->container->get('entity.manager')->getStorage($entity->getEntityTypeId()); - $controller->resetCache(); - $entity = $controller->load($entity->id()); - $this->assertEqual(count($entity->{$this->fieldTestData->field_name}), $cardinality, "Bundle name has been updated in the field storage"); } /** diff --git a/core/modules/field_ui/field_ui.module b/core/modules/field_ui/field_ui.module index 2193bc4d1093..3008b3763376 100644 --- a/core/modules/field_ui/field_ui.module +++ b/core/modules/field_ui/field_ui.module @@ -107,15 +107,6 @@ function field_ui_entity_bundle_create($entity_type, $bundle) { \Drupal::service('router.builder')->setRebuildNeeded(); } -/** - * Implements hook_entity_bundle_rename(). - */ -function field_ui_entity_bundle_rename($entity_type, $bundle_old, $bundle_new) { - // When a bundle is renamed, the menu needs to be rebuilt to add our - // menu item tabs. - \Drupal::service('router.builder')->setRebuildNeeded(); -} - /** * Implements hook_form_FORM_ID_alter(). * diff --git a/core/modules/field_ui/src/Tests/EntityDisplayTest.php b/core/modules/field_ui/src/Tests/EntityDisplayTest.php index 53a8639fba68..abb16eb282b9 100644 --- a/core/modules/field_ui/src/Tests/EntityDisplayTest.php +++ b/core/modules/field_ui/src/Tests/EntityDisplayTest.php @@ -300,9 +300,9 @@ public function testBaseFieldComponent() { } /** - * Tests renaming and deleting a bundle. + * Tests deleting a bundle. */ - public function testRenameDeleteBundle() { + public function testDeleteBundle() { // Create a node bundle, display and form display object. $type = NodeType::create(array('type' => 'article')); $type->save(); @@ -310,44 +310,11 @@ public function testRenameDeleteBundle() { entity_get_display('node', 'article', 'default')->save(); entity_get_form_display('node', 'article', 'default')->save(); - // Rename the article bundle and assert the entity display is renamed. - $type->old_type = 'article'; - $type->set('type', 'article_rename'); - $type->save(); - $old_display = entity_load('entity_view_display', 'node.article.default'); - $this->assertFalse((bool) $old_display); - $old_form_display = entity_load('entity_form_display', 'node.article.default'); - $this->assertFalse((bool) $old_form_display); - $new_display = entity_load('entity_view_display', 'node.article_rename.default'); - $this->assertEqual('article_rename', $new_display->getTargetBundle()); - $this->assertEqual('node.article_rename.default', $new_display->id()); - $new_form_display = entity_load('entity_form_display', 'node.article_rename.default'); - $this->assertEqual('article_rename', $new_form_display->getTargetBundle()); - $this->assertEqual('node.article_rename.default', $new_form_display->id()); - - $expected_view_dependencies = array( - 'config' => array('field.field.node.article_rename.body', 'node.type.article_rename'), - 'module' => array('entity_test', 'text', 'user') - ); - // Check that the display has dependencies on the bundle, fields and the - // modules that provide the formatters. - $dependencies = $new_display->calculateDependencies(); - $this->assertEqual($expected_view_dependencies, $dependencies); - - // Check that the form display has dependencies on the bundle, fields and - // the modules that provide the formatters. - $dependencies = $new_form_display->calculateDependencies(); - $expected_form_dependencies = array( - 'config' => array('field.field.node.article_rename.body', 'node.type.article_rename'), - 'module' => array('text') - ); - $this->assertEqual($expected_form_dependencies, $dependencies); - // Delete the bundle. $type->delete(); - $display = entity_load('entity_view_display', 'node.article_rename.default'); + $display = entity_load('entity_view_display', 'node.article.default'); $this->assertFalse((bool) $display); - $form_display = entity_load('entity_form_display', 'node.article_rename.default'); + $form_display = entity_load('entity_form_display', 'node.article.default'); $this->assertFalse((bool) $form_display); } diff --git a/core/modules/field_ui/src/Tests/ManageFieldsTest.php b/core/modules/field_ui/src/Tests/ManageFieldsTest.php index e4e99813a8e5..48ae2a241ee5 100644 --- a/core/modules/field_ui/src/Tests/ManageFieldsTest.php +++ b/core/modules/field_ui/src/Tests/ManageFieldsTest.php @@ -590,19 +590,6 @@ function testHiddenFields() { } } - /** - * Tests renaming a bundle. - */ - function testRenameBundle() { - $type2 = strtolower($this->randomMachineName(8)) . '_test'; - - $options = array( - 'type' => $type2, - ); - $this->drupalPostForm('admin/structure/types/manage/' . $this->contentType, $options, t('Save content type')); - $this->manageFieldsPage($type2); - } - /** * Tests that a duplicate field name is caught by validation. */ diff --git a/core/modules/language/language.module b/core/modules/language/language.module index 34a433aa599e..30fedc6e3b68 100644 --- a/core/modules/language/language.module +++ b/core/modules/language/language.module @@ -217,15 +217,6 @@ function language_configuration_element_submit(&$form, FormStateInterface $form_ } } -/** - * Implements hook_entity_bundle_rename(). - */ -function language_entity_bundle_rename($entity_type_id, $bundle_old, $bundle_new) { - ContentLanguageSettings::loadByEntityTypeBundle($entity_type_id, $bundle_old) - ->setTargetBundle($bundle_new) - ->save(); -} - /** * Implements hook_entity_bundle_delete(). */ diff --git a/core/modules/language/src/Tests/LanguageConfigurationElementTest.php b/core/modules/language/src/Tests/LanguageConfigurationElementTest.php index a8f33aa2d45d..9591618fc39c 100644 --- a/core/modules/language/src/Tests/LanguageConfigurationElementTest.php +++ b/core/modules/language/src/Tests/LanguageConfigurationElementTest.php @@ -152,7 +152,7 @@ public function testDefaultLangcode() { } /** - * Tests that the configuration is updated when the node type is changed. + * Tests that the configuration is retained when the node type is updated. */ public function testNodeTypeUpdate() { // Create the article content type first if the profile used is not the @@ -172,16 +172,16 @@ public function testNodeTypeUpdate() { $uuid = $configuration->uuid(); $this->assertEqual($configuration->getDefaultLangcode(), 'current_interface', 'The default language configuration has been saved on the Article content type.'); $this->assertTrue($configuration->isLanguageAlterable(), 'The alterable language configuration has been saved on the Article content type.'); - // Rename the article content type. + // Update the article content type by changing the title label. $edit = array( - 'type' => 'article_2' + 'title_label' => 'Name' ); $this->drupalPostForm('admin/structure/types/manage/article', $edit, t('Save content type')); - // Check that we still have the settings for the new node type. - $configuration = ContentLanguageSettings::loadByEntityTypeBundle('node', 'article_2'); - $this->assertEqual($configuration->getDefaultLangcode(), 'current_interface', 'The default language configuration has been kept on the new Article content type.'); - $this->assertTrue($configuration->isLanguageAlterable(), 'The alterable language configuration has been kept on the new Article content type.'); - $this->assertEqual($configuration->uuid(), $uuid, 'The language configuration uuid has been kept on the new Article content type.'); + // Check that we still have the settings for the updated node type. + $configuration = ContentLanguageSettings::loadByEntityTypeBundle('node', 'article'); + $this->assertEqual($configuration->getDefaultLangcode(), 'current_interface', 'The default language configuration has been kept on the updated Article content type.'); + $this->assertTrue($configuration->isLanguageAlterable(), 'The alterable language configuration has been kept on the updated Article content type.'); + $this->assertEqual($configuration->uuid(), $uuid, 'The language configuration uuid has been kept on the updated Article content type.'); } /** @@ -220,7 +220,7 @@ public function testNodeTypeDelete() { } /** - * Tests that the configuration is updated when a vocabulary is changed. + * Tests that the configuration is retained when a vocabulary is updated. */ public function testTaxonomyVocabularyUpdate() { $vocabulary = entity_create('taxonomy_vocabulary', array( @@ -242,16 +242,16 @@ public function testTaxonomyVocabularyUpdate() { $uuid = $configuration->uuid(); $this->assertEqual($configuration->getDefaultLangcode(), 'current_interface', 'The default language configuration has been saved on the Country vocabulary.'); $this->assertTrue($configuration->isLanguageAlterable(), 'The alterable language configuration has been saved on the Country vocabulary.'); - // Rename the vocabulary. + // Update the vocabulary. $edit = array( - 'vid' => 'nation' + 'name' => 'Nation' ); $this->drupalPostForm('admin/structure/taxonomy/manage/country', $edit, t('Save')); - // Check that we still have the settings for the new vocabulary. - $configuration = ContentLanguageSettings::loadByEntityTypeBundle('taxonomy_term', 'nation'); - $this->assertEqual($configuration->getDefaultLangcode(), 'current_interface', 'The default language configuration has been kept on the new Country vocabulary.'); - $this->assertTrue($configuration->isLanguageAlterable(), 'The alterable language configuration has been kept on the new Country vocabulary.'); - $this->assertEqual($configuration->uuid(), $uuid, 'The language configuration uuid has been kept on the new Country vocabulary.'); + // Check that we still have the settings for the updated vocabulary. + $configuration = ContentLanguageSettings::loadByEntityTypeBundle('taxonomy_term', 'country'); + $this->assertEqual($configuration->getDefaultLangcode(), 'current_interface', 'The default language configuration has been kept on the updated Country vocabulary.'); + $this->assertTrue($configuration->isLanguageAlterable(), 'The alterable language configuration has been kept on the updated Country vocabulary.'); + $this->assertEqual($configuration->uuid(), $uuid, 'The language configuration uuid has been kept on the updated Country vocabulary.'); } } diff --git a/core/modules/node/src/NodeTypeForm.php b/core/modules/node/src/NodeTypeForm.php index 1c1a5884d69c..e4f8cf570ac4 100644 --- a/core/modules/node/src/NodeTypeForm.php +++ b/core/modules/node/src/NodeTypeForm.php @@ -7,18 +7,17 @@ namespace Drupal\node; -use Drupal\Core\Entity\EntityForm; +use Drupal\Core\Entity\BundleEntityFormBase; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Url; use Drupal\language\Entity\ContentLanguageSettings; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Form controller for node type forms. */ -class NodeTypeForm extends EntityForm { +class NodeTypeForm extends BundleEntityFormBase { /** * The entity manager. @@ -31,7 +30,7 @@ class NodeTypeForm extends EntityForm { * Constructs the NodeTypeForm object. * * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager - * The entity manager + * The entity manager. */ public function __construct(EntityManagerInterface $entity_manager) { $this->entityManager = $entity_manager; @@ -148,7 +147,8 @@ public function form(array $form, FormStateInterface $form_state) { // Prepare workflow options to be used for 'checkboxes' form element. $keys = array_keys(array_filter($workflow_options)); $workflow_options = array_combine($keys, $keys); - $form['workflow']['options'] = array('#type' => 'checkboxes', + $form['workflow']['options'] = array( + '#type' => 'checkboxes', '#title' => t('Default options'), '#default_value' => $workflow_options, '#options' => array( @@ -187,7 +187,8 @@ public function form(array $form, FormStateInterface $form_state) { '#default_value' => $type->displaySubmitted(), '#description' => t('Author username and publish date will be displayed.'), ); - return $form; + + return $this->protectBundleIdElement($form); } /** @@ -247,7 +248,7 @@ public function save(array $form, FormStateInterface $form_state) { // @todo Make it possible to get default values without an entity. // https://www.drupal.org/node/2318187 $node = $this->entityManager->getStorage('node')->create(array('type' => $type->id())); - foreach (array('status', 'promote', 'sticky') as $field_name) { + foreach (array('status', 'promote', 'sticky') as $field_name) { $value = (bool) $form_state->getValue(['options', $field_name]); if ($node->$field_name->value != $value) { $fields[$field_name]->getConfig($type->id())->setDefaultValue($value)->save(); diff --git a/core/modules/node/src/Tests/NodeTypeRenameConfigImportTest.php b/core/modules/node/src/Tests/NodeTypeRenameConfigImportTest.php deleted file mode 100644 index 75e4f0da7c75..000000000000 --- a/core/modules/node/src/Tests/NodeTypeRenameConfigImportTest.php +++ /dev/null @@ -1,145 +0,0 @@ -<?php - -/** - * @file - * Contains \Drupal\node\Tests\NodeTypeRenameConfigImportTest. - */ - -namespace Drupal\node\Tests; - -use Drupal\Component\Utility\SafeMarkup; -use Drupal\Component\Utility\Unicode; -use Drupal\Core\Config\Entity\ConfigEntityStorage; -use Drupal\simpletest\WebTestBase; -use Drupal\node\Entity\NodeType; - -/** - * Tests importing renamed node type via configuration synchronization. - * - * @group node - */ -class NodeTypeRenameConfigImportTest extends WebTestBase { - - /** - * Modules to enable. - * - * @var array - */ - public static $modules = array('node', 'text', 'config'); - - /** - * A normal logged in user. - * - * @var \Drupal\user\UserInterface - */ - protected $webUser; - - /** - * {@inheritdoc} - */ - protected function setUp() { - parent::setUp(); - $this->webUser = $this->drupalCreateUser(array('synchronize configuration')); - $this->drupalLogin($this->webUser); - } - - /** - * Tests configuration renaming. - */ - public function testConfigurationRename() { - $content_type = $this->drupalCreateContentType(array( - 'type' => Unicode::strtolower($this->randomMachineName(16)), - 'name' => $this->randomMachineName(), - )); - $staged_type = $content_type->id(); - - // Check the default status value for a node of this type. - $node = entity_create('node', array('type' => $staged_type)); - $this->assertTrue($node->status->value, 'Node status defaults to TRUE.'); - - // Override a core base field. - $fields = \Drupal::entityManager()->getFieldDefinitions($content_type->getEntityType()->getBundleOf(), $content_type->id()); - $fields['status']->getConfig($content_type->id())->setDefaultValue(FALSE)->save(); - - $active = $this->container->get('config.storage'); - $staging = $this->container->get('config.storage.staging'); - - $config_name = $content_type->getEntityType()->getConfigPrefix() . '.' . $content_type->id(); - // Emulate a staging operation. - $this->copyConfig($active, $staging); - - // Change the machine name of the content type. - $content_type->set('type', Unicode::strtolower($this->randomMachineName(8))); - $content_type->save(); - $active_type = $content_type->id(); - - // Ensure the base field override has been renamed and the value is correct. - $node = entity_create('node', array('type' => $active_type)); - $this->assertFalse($node->status->value, 'Node status defaults to FALSE.'); - - $renamed_config_name = $content_type->getEntityType()->getConfigPrefix() . '.' . $content_type->id(); - $this->assertTrue($active->exists($renamed_config_name), 'The content type has the new name in the active store.'); - $this->assertFalse($active->exists($config_name), "The content type's old name does not exist active store."); - - $this->configImporter()->reset(); - $this->assertEqual(0, count($this->configImporter()->getUnprocessedConfiguration('create')), 'There are no configuration items to create.'); - $this->assertEqual(0, count($this->configImporter()->getUnprocessedConfiguration('delete')), 'There are no configuration items to delete.'); - $this->assertEqual(0, count($this->configImporter()->getUnprocessedConfiguration('update')), 'There are no configuration items to update.'); - - // We expect that changing the machine name of the content type will - // rename five configuration entities: the node type, the body field - // instance, two entity form displays, and the entity view display. - // @see \Drupal\node\Entity\NodeType::postSave() - $expected = array( - 'node.type.' . $active_type . '::node.type.' . $staged_type, - 'core.base_field_override.node.' . $active_type . '.status::core.base_field_override.node.' . $staged_type . '.status', - 'core.entity_form_display.node.' . $active_type . '.default::core.entity_form_display.node.' . $staged_type . '.default', - 'core.entity_view_display.node.' . $active_type . '.default::core.entity_view_display.node.' . $staged_type . '.default', - 'core.entity_view_display.node.' . $active_type . '.teaser::core.entity_view_display.node.' . $staged_type . '.teaser', - 'field.field.node.' . $active_type . '.body::field.field.node.' . $staged_type . '.body', - ); - $renames = $this->configImporter()->getUnprocessedConfiguration('rename'); - $this->assertIdentical($expected, $renames); - - $this->drupalGet('admin/config/development/configuration'); - foreach ($expected as $rename) { - $names = $this->configImporter()->getStorageComparer()->extractRenameNames($rename); - $this->assertText(SafeMarkup::format('@source_name to @target_name', array('@source_name' => $names['old_name'], '@target_name' => $names['new_name']))); - // Test that the diff link is present for each renamed item. - $href = \Drupal::urlGenerator()->getPathFromRoute('config.diff', array('source_name' => $names['old_name'], 'target_name' => $names['new_name'])); - $this->assertLinkByHref($href); - $hrefs[$rename] = $href; - } - - // Ensure that the diff works for each renamed item. - foreach ($hrefs as $rename => $href) { - $this->drupalGet($href); - $names = $this->configImporter()->getStorageComparer()->extractRenameNames($rename); - $config_entity_type = \Drupal::service('config.manager')->getEntityTypeIdByName($names['old_name']); - $entity_type = \Drupal::entityManager()->getDefinition($config_entity_type); - $old_id = ConfigEntityStorage::getIDFromConfigName($names['old_name'], $entity_type->getConfigPrefix()); - $new_id = ConfigEntityStorage::getIDFromConfigName($names['new_name'], $entity_type->getConfigPrefix()); - - // Because table columns can be on multiple lines, need to assert a regex - // pattern rather than normal text. - $id_key = $entity_type->getKey('id'); - $text = "$id_key: $old_id"; - $this->assertTextPattern('/\-\s+' . preg_quote($text, '/') . '/', "'-$text' found."); - $text = "$id_key: $new_id"; - $this->assertTextPattern('/\+\s+' . preg_quote($text, '/') . '/', "'+$text' found."); - } - - // Run the import. - $this->drupalPostForm('admin/config/development/configuration', array(), t('Import all')); - $this->assertText(t('There are no configuration changes to import.')); - - $this->assertFalse(NodeType::load($active_type), 'The content no longer exists with the old name.'); - $content_type = NodeType::load($staged_type); - $this->assertIdentical($staged_type, $content_type->id()); - - // Ensure the base field override has been renamed and the value is correct. - $node = entity_create('node', array('type' => $staged_type)); - $this->assertFALSE($node->status->value, 'Node status defaults to FALSE.'); - } - -} diff --git a/core/modules/node/src/Tests/NodeTypeTest.php b/core/modules/node/src/Tests/NodeTypeTest.php index 11d939a4f58d..c30b424daf95 100644 --- a/core/modules/node/src/Tests/NodeTypeTest.php +++ b/core/modules/node/src/Tests/NodeTypeTest.php @@ -99,10 +99,9 @@ function testNodeTypeEditing() { $this->assertRaw('Foo', 'New title label was displayed.'); $this->assertNoRaw('Title', 'Old title label was not displayed.'); - // Change the name, machine name and description. + // Change the name and the description. $edit = array( 'name' => 'Bar', - 'type' => 'bar', 'description' => 'Lorem ipsum.', ); $this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type')); @@ -111,16 +110,15 @@ function testNodeTypeEditing() { $this->assertRaw('Bar', 'New name was displayed.'); $this->assertRaw('Lorem ipsum', 'New description was displayed.'); $this->clickLink('Bar'); - $this->assertUrl(\Drupal::url('node.add', ['node_type' => 'bar'], ['absolute' => TRUE]), [], 'New machine name was used in URL.'); $this->assertRaw('Foo', 'Title field was found.'); $this->assertRaw('Body', 'Body field was found.'); // Remove the body field. - $this->drupalPostForm('admin/structure/types/manage/bar/fields/node.bar.body/delete', array(), t('Delete')); + $this->drupalPostForm('admin/structure/types/manage/page/fields/node.page.body/delete', array(), t('Delete')); // Resave the settings for this type. - $this->drupalPostForm('admin/structure/types/manage/bar', array(), t('Save content type')); + $this->drupalPostForm('admin/structure/types/manage/page', array(), t('Save content type')); // Check that the body field doesn't exist. - $this->drupalGet('node/add/bar'); + $this->drupalGet('node/add/page'); $this->assertNoRaw('Body', 'Body field was not found.'); } diff --git a/core/modules/shortcut/src/ShortcutSetForm.php b/core/modules/shortcut/src/ShortcutSetForm.php index 9708aee611d4..fd21f7c77624 100644 --- a/core/modules/shortcut/src/ShortcutSetForm.php +++ b/core/modules/shortcut/src/ShortcutSetForm.php @@ -7,13 +7,13 @@ namespace Drupal\shortcut; -use Drupal\Core\Entity\EntityForm; +use Drupal\Core\Entity\BundleEntityFormBase; use Drupal\Core\Form\FormStateInterface; /** * Form controller for the shortcut set entity edit forms. */ -class ShortcutSetForm extends EntityForm { +class ShortcutSetForm extends BundleEntityFormBase { /** * {@inheritdoc} @@ -38,14 +38,13 @@ public function form(array $form, FormStateInterface $form_state) { 'replace' => '-', ), '#default_value' => $entity->id(), - '#disabled' => !$entity->isNew(), // This id could be used for menu name. '#maxlength' => 23, ); $form['actions']['submit']['#value'] = t('Create new set'); - return $form; + return $this->protectBundleIdElement($form); } /** diff --git a/core/modules/system/src/Tests/Entity/FieldSqlStorageTest.php b/core/modules/system/src/Tests/Entity/FieldSqlStorageTest.php index 549c17ae9f94..67b0e9490a35 100644 --- a/core/modules/system/src/Tests/Entity/FieldSqlStorageTest.php +++ b/core/modules/system/src/Tests/Entity/FieldSqlStorageTest.php @@ -469,35 +469,6 @@ function testFieldSqlStorageForeignKeys() { $this->assertEqual($schema['foreign keys'][$foreign_key_name]['columns'][$foreign_key_name], 'id', 'Foreign key column name modified after update'); } - /** - * Tests reacting to a bundle being renamed. - */ - function testFieldSqlStorageBundleRename() { - $entity_type = $bundle = 'entity_test_rev'; - $field_name = $this->fieldStorage->getName(); - - // Create an entity. - $value = mt_rand(1, 127); - $entity = entity_create($entity_type, array( - 'type' => $bundle, - $field_name => $value, - )); - $entity->save(); - - // Rename the bundle. - $bundle_new = $bundle . '_renamed'; - entity_test_rename_bundle($bundle, $bundle_new, $entity_type); - - // Check that the 'bundle' column has been updated in storage. - $row = db_select($this->table, 't') - ->fields('t', array('bundle', $field_name . '_value')) - ->condition('entity_id', $entity->id()) - ->execute() - ->fetch(); - $this->assertEqual($row->bundle, $bundle_new); - $this->assertEqual($row->{$field_name . '_value'}, $value); - } - /** * Tests table name generation. */ diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module index eea78e82a4ed..101a466e1de7 100644 --- a/core/modules/system/tests/modules/entity_test/entity_test.module +++ b/core/modules/system/tests/modules/entity_test/entity_test.module @@ -170,26 +170,6 @@ function entity_test_create_bundle($bundle, $text = NULL, $entity_type = 'entity \Drupal::entityManager()->onBundleCreate($bundle, $entity_type); } -/** - * Renames a bundle for entity_test entities. - * - * @param string $bundle_old - * The machine-readable name of the bundle to rename. - * @param string $bundle_new - * The new machine-readable name of the bundle. - * @param string $entity_type - * (optional) The entity type for which the bundle is renamed. Defaults to - * 'entity_test'. - */ -function entity_test_rename_bundle($bundle_old, $bundle_new, $entity_type = 'entity_test') { - $bundles = \Drupal::state()->get($entity_type . '.bundles') ?: array($entity_type => array('label' => 'Entity Test Bundle')); - $bundles[$bundle_new] = $bundles[$bundle_old]; - unset($bundles[$bundle_old]); - \Drupal::state()->set($entity_type . '.bundles', $bundles); - - \Drupal::entityManager()->onBundleRename($bundle_old, $bundle_new, $entity_type); -} - /** * Deletes a bundle for entity_test entities. * diff --git a/core/modules/taxonomy/src/Entity/Vocabulary.php b/core/modules/taxonomy/src/Entity/Vocabulary.php index 2855c6596c51..c8cc1c0e96a6 100644 --- a/core/modules/taxonomy/src/Entity/Vocabulary.php +++ b/core/modules/taxonomy/src/Entity/Vocabulary.php @@ -122,48 +122,6 @@ public function getDescription() { return $this->description; } - /** - * {@inheritdoc} - */ - public function postSave(EntityStorageInterface $storage, $update = TRUE) { - parent::postSave($storage, $update); - - if ($update && $this->getOriginalId() != $this->id() && !$this->isSyncing()) { - // Reflect machine name changes in the definitions of existing 'taxonomy' - // fields. - $field_ids = array(); - $field_map = \Drupal::entityManager()->getFieldMapByFieldType('entity_reference'); - foreach ($field_map as $entity_type => $field_storages) { - foreach ($field_storages as $field_storage => $info) { - $field_ids[] = $entity_type . '.' . $field_storage; - } - } - - $field_storages = \Drupal::entityManager()->getStorage('field_storage_config')->loadMultiple($field_ids); - $taxonomy_fields = array_filter($field_storages, function ($field_storage) { - return $field_storage->getType() == 'entity_reference' && $field_storage->getSetting('target_type') == 'taxonomy_term'; - }); - - foreach ($taxonomy_fields as $field_storage) { - $update_storage = FALSE; - - $allowed_values = $field_storage->getSetting('allowed_values'); - foreach ($allowed_values as &$value) { - if ($value['vocabulary'] == $this->getOriginalId()) { - $value['vocabulary'] = $this->id(); - $update_storage = TRUE; - } - } - $field_storage->setSetting('allowed_values', $allowed_values); - - if ($update_storage) { - $field_storage->save(); - } - } - } - $storage->resetCache($update ? array($this->getOriginalId()) : array()); - } - /** * {@inheritdoc} */ diff --git a/core/modules/taxonomy/src/Tests/VocabularyCrudTest.php b/core/modules/taxonomy/src/Tests/VocabularyCrudTest.php index 1c174d4b62ee..a46a47e541fc 100644 --- a/core/modules/taxonomy/src/Tests/VocabularyCrudTest.php +++ b/core/modules/taxonomy/src/Tests/VocabularyCrudTest.php @@ -142,37 +142,6 @@ function testTaxonomyVocabularyLoadMultiple() { $this->assertEqual($vocabulary->id(), $vocabulary2->id(), 'Vocabulary loaded successfully by name and ID.'); } - /** - * Tests that machine name changes are properly reflected. - */ - function testTaxonomyVocabularyChangeMachineName() { - // Add a field to the vocabulary. - entity_create('field_storage_config', array( - 'field_name' => 'field_test', - 'entity_type' => 'taxonomy_term', - 'type' => 'test_field', - ))->save(); - entity_create('field_config', array( - 'field_name' => 'field_test', - 'entity_type' => 'taxonomy_term', - 'bundle' => $this->vocabulary->id(), - ))->save(); - - // Change the machine name. - $old_name = $this->vocabulary->id(); - $new_name = Unicode::strtolower($this->randomMachineName()); - $this->vocabulary->set('vid', $new_name); - $this->vocabulary->save(); - - // Check that entity bundles are properly updated. - $info = entity_get_bundles('taxonomy_term'); - $this->assertFalse(isset($info[$old_name]), 'The old bundle name does not appear in entity_get_bundles().'); - $this->assertTrue(isset($info[$new_name]), 'The new bundle name appears in entity_get_bundles().'); - - // Check that the field is still attached to the vocabulary. - $this->assertTrue(FieldConfig::loadByName('taxonomy_term', $new_name, 'field_test'), 'The bundle name was updated correctly.'); - } - /** * Test uninstall and reinstall of the taxonomy module. */ diff --git a/core/modules/taxonomy/src/VocabularyForm.php b/core/modules/taxonomy/src/VocabularyForm.php index dd2c1d82f451..e175af70c5ad 100644 --- a/core/modules/taxonomy/src/VocabularyForm.php +++ b/core/modules/taxonomy/src/VocabularyForm.php @@ -7,18 +7,17 @@ namespace Drupal\taxonomy; -use Drupal\Core\Entity\EntityForm; +use Drupal\Core\Entity\BundleEntityFormBase; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Language\LanguageInterface; use Drupal\language\Entity\ContentLanguageSettings; -use Drupal\taxonomy\VocabularyStorageInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Base form for vocabulary edit forms. */ -class VocabularyForm extends EntityForm { +class VocabularyForm extends BundleEntityFormBase { /** * The vocabulary storage. @@ -112,7 +111,8 @@ public function form(array $form, FormStateInterface $form_state) { '#value' => '0', ); - return parent::form($form, $form_state, $vocabulary); + $form = parent::form($form, $form_state); + return $this->protectBundleIdElement($form); } /** @@ -147,14 +147,14 @@ public function save(array $form, FormStateInterface $form_state) { /** * Determines if the vocabulary already exists. * - * @param string $id - * The vocabulary ID + * @param string $vid + * The vocabulary ID. * * @return bool * TRUE if the vocabulary exists, FALSE otherwise. */ - public function exists($id) { - $action = $this->vocabularyStorage->load($id); + public function exists($vid) { + $action = $this->vocabularyStorage->load($vid); return !empty($action); } -- GitLab