Commit 60b75a2d authored by alexpott's avatar alexpott

Issue #2578249 by yched: Some e_r fields get the wrong Selection handler

parent 47e6ecfc
......@@ -51,7 +51,7 @@ public static function defaultStorageSettings() {
*/
public static function defaultFieldSettings() {
return array(
'handler' => 'default:' . (\Drupal::moduleHandler()->moduleExists('node') ? 'node' : 'user'),
'handler' => 'default',
'handler_settings' => array(),
) + parent::defaultFieldSettings();
}
......
......@@ -11,8 +11,6 @@
use Drupal\Core\Render\Element;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\FieldStorageConfigInterface;
use Drupal\field\FieldConfigInterface;
/**
* Implements hook_help().
......@@ -71,56 +69,6 @@ function entity_reference_field_widget_info_alter(&$info) {
}
}
/**
* Implements hook_ENTITY_TYPE_update() for 'field_storage_config'.
*
* Reset the instance handler settings, when the target type is changed.
*/
function entity_reference_field_storage_config_update(FieldStorageConfigInterface $field_storage) {
if ($field_storage->getType() != 'entity_reference') {
// Only act on entity reference fields.
return;
}
if ($field_storage->isSyncing()) {
// Don't change anything during a configuration sync.
return;
}
if ($field_storage->getSetting('target_type') == $field_storage->original->getSetting('target_type')) {
// Target type didn't change.
return;
}
foreach ($field_storage->getBundles() as $bundle) {
$field = FieldConfig::loadByName($field_storage->getTargetEntityTypeId(), $bundle, $field_storage->getName());
$field->setSetting('handler_settings', []);
$field->save();
}
}
/**
* Implements hook_ENTITY_TYPE_presave() for 'field_config'.
*
* Determine the selection handler plugin ID for an entity reference field.
*/
function entity_reference_field_config_presave(FieldConfigInterface $field) {
if ($field->getType() != 'entity_reference') {
// Only act on entity reference fields.
return;
}
if ($field->isSyncing()) {
// Don't change anything during a configuration sync.
return;
}
$target_type = $field->getFieldStorageDefinition()->getSetting('target_type');
$selection_manager = \Drupal::service('plugin.manager.entity_reference_selection');
list($current_handler) = explode(':', $field->getSetting('handler'), 2);
$field->setSetting('handler', $selection_manager->getPluginId($target_type, $current_handler));
}
/**
* Implements hook_form_FORM_ID_alter() for 'field_ui_field_storage_add_form'.
*/
......
......@@ -8,10 +8,12 @@
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\DynamicallyFieldableEntityStorageInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\FieldConfigInterface;
use Drupal\field\FieldStorageConfigInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
use Drupal\field\Entity\FieldStorageConfig;
/*
* Load all public Field API functions. Drupal currently has no
......@@ -280,3 +282,65 @@ function field_form_config_admin_import_form_alter(&$form, FormStateInterface $f
}
}
}
/**
* Implements hook_ENTITY_TYPE_update() for 'field_storage_config'.
*
* Reset the field handler settings, when the storage target_type is changed on
* an entity reference field.
*/
function field_field_storage_config_update(FieldStorageConfigInterface $field_storage) {
if ($field_storage->isSyncing()) {
// Don't change anything during a configuration sync.
return;
}
// Act on all sub-types of the entity_reference field type.
/** @var \Drupal\Core\Field\FieldTypePluginManager $field_type_manager */
$field_type_manager = \Drupal::service('plugin.manager.field.field_type');
$item_class = 'Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem';
$class = $field_type_manager->getPluginClass($field_storage->getType());
if ($class !== $item_class && !is_subclass_of($class, $item_class)) {
return;
}
// If target_type changed, reset the handler in the fields using that storage.
if ($field_storage->getSetting('target_type') !== $field_storage->original->getSetting('target_type')) {
foreach ($field_storage->getBundles() as $bundle) {
$field = FieldConfig::loadByName($field_storage->getTargetEntityTypeId(), $bundle, $field_storage->getName());
// Reset the handler settings. This triggers field_field_config_presave(),
// which will take care of reassigning the handler to the correct
// derivative for the new target_type.
$field->setSetting('handler_settings', []);
$field->save();
}
}
}
/**
* Implements hook_ENTITY_TYPE_presave() for 'field_config'.
*
* Determine the selection handler plugin ID for an entity reference field.
*/
function field_field_config_presave(FieldConfigInterface $field) {
// Don't change anything during a configuration sync.
if ($field->isSyncing()) {
return;
}
// Act on all sub-types of the entity_reference field type.
/** @var \Drupal\Core\Field\FieldTypePluginManager $field_type_manager */
$field_type_manager = \Drupal::service('plugin.manager.field.field_type');
$item_class = 'Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem';
$class = $field_type_manager->getPluginClass($field->getType());
if ($class !== $item_class && !is_subclass_of($class, $item_class)) {
return;
}
// Make sure the selection handler plugin is the correct derivative for the
// target entity type.
$target_type = $field->getFieldStorageDefinition()->getSetting('target_type');
$selection_manager = \Drupal::service('plugin.manager.entity_reference_selection');
list($current_handler) = explode(':', $field->getSetting('handler'), 2);
$field->setSetting('handler', $selection_manager->getPluginId($target_type, $current_handler));
}
......@@ -2,10 +2,11 @@
/**
* @file
* Post update functions for Field.
* Post update functions for Field module.
*/
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\Entity\FieldConfig;
/**
* @addtogroup updates-8.0.0-beta
......@@ -23,6 +24,23 @@ function field_post_update_save_custom_storage_property() {
return t('All field storage configuration objects re-saved.');
}
/**
* Fixes the 'handler' setting for entity reference fields.
*/
function field_post_update_entity_reference_handler_setting() {
foreach (FieldConfig::loadMultiple() as $field_config) {
$field_type_manager = \Drupal::service('plugin.manager.field.field_type');
$item_class = 'Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem';
$class = $field_type_manager->getPluginClass($field_config->getType());
if ($class === $item_class || is_subclass_of($class, $item_class)) {
// field_field_config_presave() will fix the 'handler' setting on save.
$field_config->save();
}
}
return t('Selection handler for entity reference fields have been adjusted.');
}
/**
* @} End of "addtogroup updates-8.0.0-beta".
*/
......@@ -303,20 +303,34 @@ public function testSelectionHandlerSettings() {
$field_storage->save();
// Do not specify any value for the 'handler' setting in order to verify
// that the default value is properly used.
// that the default handler with the correct derivative is used.
$field = FieldConfig::create(array(
'field_storage' => $field_storage,
'bundle' => 'entity_test',
));
$field->save();
$field = FieldConfig::load($field->id());
$this->assertEqual($field->getSetting('handler'), 'default:entity_test');
// Change the target_type in the field storage, and check that the handler
// was correctly reassigned in the field.
$field_storage->setSetting('target_type', 'entity_test_rev');
$field_storage->save();
$field = FieldConfig::load($field->id());
$this->assertTrue($field->getSetting('handler') == 'default:entity_test');
$this->assertEqual($field->getSetting('handler'), 'default:entity_test_rev');
// Change the handler to another, non-derivative plugin.
$field->setSetting('handler', 'views');
$field->save();
$field = FieldConfig::load($field->id());
$this->assertTrue($field->getSetting('handler') == 'views');
$this->assertEqual($field->getSetting('handler'), 'views');
// Change the target_type in the field storage again, and check that the
// non-derivative handler was unchanged.
$field_storage->setSetting('target_type', 'entity_test_rev');
$field_storage->save();
$field = FieldConfig::load($field->id());
$this->assertEqual($field->getSetting('handler'), 'views');
}
/**
......
......@@ -79,9 +79,7 @@ public function testFieldInstanceSettings() {
'display_field' => FALSE,
'display_default' => FALSE,
'uri_scheme' => 'public',
// This value should be 'default:file' but the test does not migrate field
// storages so we end up with the default value for this setting.
'handler' => 'default:node',
'handler' => 'default:file',
'handler_settings' => array(),
);
$field_settings = $field->getSettings();
......
<?php
/**
* @file
* Contains \Drupal\field\Tests\Update\EntityReferenceHandlerSettingUpdateTest.
*/
namespace Drupal\field\Tests\Update;
use Drupal\system\Tests\Update\UpdatePathTestBase;
/**
* Tests the update for the entity reference 'handler' setting.
*
* @group field
*/
class EntityReferenceHandlerSettingUpdateTest extends UpdatePathTestBase {
/**
* {@inheritdoc}
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
];
}
/**
* Tests field_post_update_entity_reference_handler_setting().
*
* @see field_post_update_entity_reference_handler_setting()
*/
public function testFieldPostUpdateERHandlerSetting() {
$configFactory = $this->container->get('config.factory');
// Load the 'node.article.field_image' field config, and check that its
// 'handler' setting is wrong.
/** @var \Drupal\Core\Config\Config */
$config = $configFactory->get('field.field.node.article.field_image');
$settings = $config->get('settings');
$this->assertEqual($settings['handler'], 'default:node');
// Run updates.
$this->runUpdates();
// Reload the config, and check that the 'handler' setting has been fixed.
$config = $configFactory->get('field.field.node.article.field_image');
$settings = $config->get('settings');
$this->assertEqual($settings['handler'], 'default:file');
}
}
......@@ -10,6 +10,7 @@
use Drupal\Core\Field\FieldItemInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Tests\FieldUnitTestBase;
/**
......@@ -70,6 +71,12 @@ protected function setUp() {
* Tests using entity fields of the file field type.
*/
public function testFileItem() {
// Check that the selection handler was automatically assigned to
// 'default:file'.
$field_definition = FieldConfig::load('entity_test.entity_test.file_test');
$handler_id = $field_definition->getSetting('handler');
$this->assertEqual($handler_id, 'default:file');
// Create a test entity with the
$entity = entity_create('entity_test');
$entity->file_test->target_id = $this->file->id();
......
......@@ -402,7 +402,6 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
->setDescription(t('The username of the content author.'))
->setRevisionable(TRUE)
->setSetting('target_type', 'user')
->setSetting('handler', 'default')
->setDefaultValueCallback('Drupal\node\Entity\Node::getCurrentUserId')
->setTranslatable(TRUE)
->setDisplayOptions('view', array(
......
......@@ -62,6 +62,7 @@ public function testPostUpdate() {
$updates = array_merge([
'block_post_update_disable_blocks_with_missing_contexts',
'field_post_update_save_custom_storage_property',
'field_post_update_entity_reference_handler_setting',
'system_post_update_fix_enforced_dependencies',
'views_post_update_update_cacheability_metadata',
], $updates);
......
......@@ -32,6 +32,6 @@ settings:
title: ''
width: null
height: null
handler: 'default:node'
handler: 'default:file'
handler_settings: { }
field_type: image
......@@ -32,6 +32,6 @@ settings:
height: null
alt_field_required: false
title_field_required: false
handler: 'default:node'
handler: 'default:file'
handler_settings: { }
field_type: image
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment