Issue #2172843 by fgm, marthinal, pfrenssen, amateescu, andypost, Wim Leers, stefan.r, pwieck, deepak_123: Remove ability to update entity bundle machine names
parent
10626d87a3
commit
03bd7fc75b
|
@ -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 @@ use Drupal\Core\Entity\EntityStorageInterface;
|
|||
*/
|
||||
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 @@ abstract class ConfigEntityBundleBase extends ConfigEntityBase {
|
|||
}
|
||||
// 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 @@ abstract class ConfigEntityBundleBase extends ConfigEntityBase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -1367,31 +1367,6 @@ class EntityManager extends DefaultPluginManager implements EntityManagerInterfa
|
|||
$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}
|
||||
*/
|
||||
|
|
|
@ -1493,40 +1493,6 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
|
|||
*/
|
||||
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}
|
||||
*/
|
||||
|
|
|
@ -139,8 +139,8 @@ use Drupal\node\Entity\NodeType;
|
|||
* - 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 @@ use Drupal\node\Entity\NodeType;
|
|||
* '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().
|
||||
*
|
||||
|
|
|
@ -163,8 +163,7 @@ class BaseFieldOverride extends FieldConfigBase {
|
|||
* {@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 @@ class BaseFieldOverride extends FieldConfigBase {
|
|||
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;
|
||||
|
|
|
@ -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 @@ abstract class FieldConfigBase extends ConfigEntityBase implements FieldConfigIn
|
|||
// 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 @@ abstract class FieldConfigBase extends ConfigEntityBase implements FieldConfigIn
|
|||
return $this->itemDefinition;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function allowBundleRename() {
|
||||
$this->bundleRenameAllowed = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -282,13 +282,4 @@ interface FieldConfigInterface extends FieldDefinitionInterface, ConfigEntityInt
|
|||
*/
|
||||
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();
|
||||
|
||||
}
|
||||
|
|
|
@ -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 @@ use Drupal\language\Entity\ContentLanguageSettings;
|
|||
/**
|
||||
* Base form for category edit forms.
|
||||
*/
|
||||
class BlockContentTypeForm extends EntityForm {
|
||||
class BlockContentTypeForm extends BundleEntityFormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
@ -48,7 +48,6 @@ class BlockContentTypeForm extends EntityForm {
|
|||
'exists' => '\Drupal\block_content\Entity\BlockContentType::load',
|
||||
),
|
||||
'#maxlength' => EntityTypeInterface::BUNDLE_MAX_LENGTH,
|
||||
'#disabled' => !$block_type->isNew(),
|
||||
);
|
||||
|
||||
$form['description'] = array(
|
||||
|
@ -62,7 +61,7 @@ class BlockContentTypeForm extends EntityForm {
|
|||
'#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 @@ class BlockContentTypeForm extends EntityForm {
|
|||
'#value' => t('Save'),
|
||||
);
|
||||
|
||||
return $form;
|
||||
return $this->protectBundleIdElement($form);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -497,99 +497,6 @@ class BookTest extends WebTestBase {
|
|||
$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.
|
||||
*/
|
||||
|
|
|
@ -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().
|
||||
*
|
||||
|
|
|
@ -167,7 +167,7 @@ class FieldConfig extends FieldConfigBase implements FieldConfigInterface {
|
|||
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()) {
|
||||
|
|
|
@ -275,9 +275,9 @@ class FieldAttachStorageTest extends FieldUnitTestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* 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 @@ class FieldAttachStorageTest extends FieldUnitTestBase {
|
|||
// 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");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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().
|
||||
*
|
||||
|
|
|
@ -300,9 +300,9 @@ class EntityDisplayTest extends KernelTestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* 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 @@ class EntityDisplayTest extends KernelTestBase {
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -590,19 +590,6 @@ class ManageFieldsTest extends WebTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
|
|
@ -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().
|
||||
*/
|
||||
|
|
|
@ -152,7 +152,7 @@ class LanguageConfigurationElementTest extends WebTestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* 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 @@ class LanguageConfigurationElementTest extends WebTestBase {
|
|||
$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 @@ class LanguageConfigurationElementTest extends WebTestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* 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 @@ class LanguageConfigurationElementTest extends WebTestBase {
|
|||
$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.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 @@ class NodeTypeForm extends EntityForm {
|
|||
// 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 @@ class NodeTypeForm extends EntityForm {
|
|||
'#default_value' => $type->displaySubmitted(),
|
||||
'#description' => t('Author username and publish date will be displayed.'),
|
||||
);
|
||||
return $form;
|
||||
|
||||
return $this->protectBundleIdElement($form);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -247,7 +248,7 @@ class NodeTypeForm extends EntityForm {
|
|||
// @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();
|
||||
|
|
|
@ -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.');
|
||||
}
|
||||
|
||||
}
|
|
@ -99,10 +99,9 @@ class NodeTypeTest extends NodeTestBase {
|
|||
$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 @@ class NodeTypeTest extends NodeTestBase {
|
|||
$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.');
|
||||
}
|
||||
|
||||
|
|
|
@ -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 @@ class ShortcutSetForm extends EntityForm {
|
|||
'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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -469,35 +469,6 @@ class FieldSqlStorageTest extends EntityUnitTestBase {
|
|||
$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.
|
||||
*/
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -122,48 +122,6 @@ class Vocabulary extends ConfigEntityBundleBase implements VocabularyInterface {
|
|||
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}
|
||||
*/
|
||||
|
|
|
@ -142,37 +142,6 @@ class VocabularyCrudTest extends TaxonomyTestBase {
|
|||
$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.
|
||||
*/
|
||||
|
|
|
@ -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 @@ class VocabularyForm extends EntityForm {
|
|||
'#value' => '0',
|
||||
);
|
||||
|
||||
return parent::form($form, $form_state, $vocabulary);
|
||||
$form = parent::form($form, $form_state);
|
||||
return $this->protectBundleIdElement($form);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -147,14 +147,14 @@ class VocabularyForm extends EntityForm {
|
|||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue