Issue #2436835 by amateescu, alexpott: Unable to create config schema for entity type specific entity reference selection plugin

8.0.x
Alex Pott 2015-03-17 09:55:45 +00:00
parent eaffcfc511
commit ae4848f51d
15 changed files with 178 additions and 81 deletions

View File

@ -552,7 +552,7 @@ field.value.changed:
field.storage_settings.entity_reference:
type: mapping
label: 'Entity reference settings'
label: 'Entity reference field storage settings'
mapping:
target_type:
type: string
@ -560,14 +560,14 @@ field.storage_settings.entity_reference:
field.field_settings.entity_reference:
type: mapping
label: 'Entity reference settings'
label: 'Entity reference field settings'
mapping:
handler:
type: string
label: 'Reference method'
handler_settings:
type: entity_reference.[%parent.handler].handler_settings
label: 'Reference method settings'
type: entity_reference_selection.[%parent.handler]
label: 'Entity reference selection plugin settings'
field.value.entity_reference:
type: mapping
@ -750,3 +750,32 @@ text_format:
label: 'Text format'
# The text format should not be translated as part of the string
# translation system, so this is not marked as translatable.
# Schema for the configuration of the Entity reference selection plugins.
entity_reference_selection:
type: mapping
label: 'Entity reference selection plugin configuration'
mapping:
target_bundles:
type: sequence
label: 'types'
sequence:
type: string
label: 'Type'
sort:
type: mapping
label: 'Sort settings'
mapping:
field:
type: string
label: 'Sort by'
direction:
type: string
label: 'Sort direction'
auto_create:
type: boolean
label: 'Create referenced entities if they don''t already exist'
entity_reference_selection.*:
type: entity_reference_selection

View File

@ -45,21 +45,37 @@ class SelectionPluginManager extends DefaultPluginManager implements SelectionPl
// Initialize default options.
$options += array(
'handler' => 'default',
'handler' => $this->getPluginId($options['target_type'], 'default'),
'handler_settings' => array(),
);
// Get all available selection plugins for this entity type.
$selection_handler_groups = $this->getSelectionGroups($options['target_type']);
// Sort the selection plugins by weight and select the best match.
uasort($selection_handler_groups[$options['handler']], array('Drupal\Component\Utility\SortArray', 'sortByWeightElement'));
end($selection_handler_groups[$options['handler']]);
$plugin_id = key($selection_handler_groups[$options['handler']]);
// A specific selection plugin ID was already specified.
if (strpos($options['handler'], ':') !== FALSE) {
$plugin_id = $options['handler'];
}
// Only a selection group name was specified.
else {
$plugin_id = $this->getPluginId($options['target_type'], $options['handler']);
}
return $this->createInstance($plugin_id, $options);
}
/**
* {@inheritdoc}
*/
public function getPluginId($target_type, $base_plugin_id) {
// Get all available selection plugins for this entity type.
$selection_handler_groups = $this->getSelectionGroups($target_type);
// Sort the selection plugins by weight and select the best match.
uasort($selection_handler_groups[$base_plugin_id], array('Drupal\Component\Utility\SortArray', 'sortByWeightElement'));
end($selection_handler_groups[$base_plugin_id]);
$plugin_id = key($selection_handler_groups[$base_plugin_id]);
return $plugin_id;
}
/**
* {@inheritdoc}
*/
@ -86,7 +102,7 @@ class SelectionPluginManager extends DefaultPluginManager implements SelectionPl
$options = array(
'target_type' => $field_definition->getFieldStorageDefinition()->getSetting('target_type'),
'handler' => $field_definition->getSetting('handler'),
'handler_settings' => $field_definition->getSetting('handler_settings'),
'handler_settings' => $field_definition->getSetting('handler_settings') ?: array(),
'entity' => $entity,
);
return $this->getInstance($options);

View File

@ -16,6 +16,19 @@ use Drupal\Core\Field\FieldDefinitionInterface;
*/
interface SelectionPluginManagerInterface extends PluginManagerInterface {
/**
* Gets the plugin ID for a given target entity type and base plugin ID.
*
* @param string $target_type
* The target entity type.
* @param string $base_plugin_id
* The base plugin ID (e.g. 'default' or 'views').
*
* @return string
* The plugin ID.
*/
public function getPluginId($target_type, $base_plugin_id);
/**
* Returns selection plugins that can reference a specific entity type.
*

View File

@ -59,7 +59,8 @@ class EntityReferenceItem extends FieldItemBase {
*/
public static function defaultFieldSettings() {
return array(
'handler' => 'default',
'handler' => 'default:' . (\Drupal::moduleHandler()->moduleExists('node') ? 'node' : 'user'),
'handler_settings' => array(),
) + parent::defaultFieldSettings();
}

View File

@ -1,41 +0,0 @@
# Schema for the configuration files of the Entity Reference module.
entity_reference.default.handler_settings:
type: mapping
label: 'View handler settings'
mapping:
target_bundles:
type: sequence
label: 'types'
sequence:
type: string
label: 'Type'
sort:
type: mapping
label: 'Sort settings'
mapping:
field:
type: string
label: 'Sort by'
direction:
type: string
label: 'Sort direction'
filter:
type: mapping
label: 'Filter settings'
mapping:
type:
type: string
label: 'Filter by'
role:
type: sequence
label: 'Restrict to the selected roles'
sequence:
type: string
label: 'Role'
auto_create:
type: boolean
label: 'Create referenced entities if they don''t already exist'
include_anonymous:
type: boolean
label: 'Include the anonymous user in the matched entities.'

View File

@ -13,6 +13,7 @@ use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\FieldStorageConfigInterface;
use Drupal\field\FieldConfigInterface;
/**
* Implements hook_help().
@ -84,20 +85,33 @@ function entity_reference_field_storage_config_update(FieldStorageConfigInterfac
return;
}
if (empty($field_storage->bundles)) {
// Field storage has no fields.
return;
}
$field_name = $field_storage->getName();
foreach ($field_storage->bundles() as $entity_type => $bundles) {
foreach ($bundles as $bundle) {
$field = FieldConfig::loadByName($entity_type, $bundle, $field_name);
foreach ($field_storage->getBundles() as $bundle) {
$field = FieldConfig::loadByName($field_storage->getTargetEntityTypeId(), $bundle, $field_storage->getName());
$field->settings['handler_settings'] = array();
$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->settings['handler'] = $selection_manager->getPluginId($target_type, $current_handler);
}
/**

View File

@ -42,15 +42,6 @@ class ConfigurableEntityReferenceItem extends EntityReferenceItem implements Opt
return $settings;
}
/**
* {@inheritdoc}
*/
public static function defaultFieldSettings() {
return array(
'handler_settings' => array(),
) + parent::defaultFieldSettings();
}
/**
* {@inheritdoc}
*/
@ -149,7 +140,7 @@ class ConfigurableEntityReferenceItem extends EntityReferenceItem implements Opt
}
elseif (array_key_exists($selection_group_id . ':' . $this->getSetting('target_type'), $selection_plugins[$selection_group_id])) {
$selection_group_plugin = $selection_group_id . ':' . $this->getSetting('target_type');
$handlers_options[$selection_group_id] = String::checkPlain($selection_plugins[$selection_group_id][$selection_group_plugin]['base_plugin_label']);
$handlers_options[$selection_group_plugin] = String::checkPlain($selection_plugins[$selection_group_id][$selection_group_plugin]['base_plugin_label']);
}
}

View File

@ -78,7 +78,7 @@ class EntityReferenceAdminTest extends WebTestBase {
$this->drupalPostForm(NULL, array(), t('Save field settings'));
// The base handler should be selected by default.
$this->assertFieldByName('field[settings][handler]', 'default');
$this->assertFieldByName('field[settings][handler]', 'default:node');
// The base handler settings should be displayed.
$entity_type_id = 'node';

View File

@ -11,6 +11,8 @@ use Drupal\Component\Utility\Unicode;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FieldItemInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\Tests\FieldUnitTestBase;
use Drupal\taxonomy\Entity\Term;
use Drupal\taxonomy\Entity\Vocabulary;
@ -27,7 +29,7 @@ class EntityReferenceItemTest extends FieldUnitTestBase {
*
* @var array
*/
public static $modules = array('entity_reference', 'taxonomy', 'text', 'filter');
public static $modules = array('entity_reference', 'taxonomy', 'text', 'filter', 'views');
/**
* The taxonomy vocabulary to test with.
@ -214,4 +216,36 @@ class EntityReferenceItemTest extends FieldUnitTestBase {
$this->assertEqual($entity->field_test_taxonomy_term->entity->id(), $term->id());
}
/**
* Tests that the 'handler' field setting stores the proper plugin ID.
*/
public function testSelectionHandlerSettings() {
$field_name = Unicode::strtolower($this->randomMachineName());
$field_storage = FieldStorageConfig::create(array(
'field_name' => $field_name,
'entity_type' => 'entity_test',
'type' => 'entity_reference',
'settings' => array(
'target_type' => 'entity_test'
),
));
$field_storage->save();
// Do not specify any value for the 'handler' setting in order to verify
// that the default value is properly used.
$field = FieldConfig::create(array(
'field_storage' => $field_storage,
'bundle' => 'entity_test',
));
$field->save();
$field = FieldConfig::load($field->id());
$this->assertTrue($field->getSetting('handler') == 'default:entity_test');
$field->settings['handler'] = 'views';
$field->save();
$field = FieldConfig::load($field->id());
$this->assertTrue($field->getSetting('handler') == 'views');
}
}

View File

@ -46,6 +46,9 @@ base_file_field_field_settings:
handler:
type: string
label: 'Reference method'
handler_settings:
type: entity_reference_selection.[%parent.handler]
label: 'Entity reference selection settings'
file_directory:
type: string
label: 'File directory'

View File

@ -134,12 +134,17 @@ class MigrateFieldInstanceTest extends MigrateDrupal6TestBase {
'display_field' => FALSE,
'display_default' => FALSE,
'uri_scheme' => 'public',
'handler' => 'default',
// 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_settings' => array(),
'target_bundle' => NULL,
);
$field_settings = $field->getSettings();
ksort($expected);
ksort($field_settings);
// This is the only way to compare arrays.
$this->assertFalse(array_diff_assoc($field->getSettings(), $expected));
$this->assertFalse(array_diff_assoc($expected, $field->getSettings()));
$this->assertIdentical($expected, $field_settings);
// Test a link field.
$field = FieldConfig::load('node.story.field_test_link');

View File

@ -62,6 +62,9 @@ field.field_settings.taxonomy_term_reference:
handler:
type: string
label: 'Reference method'
handler_settings:
type: entity_reference_selection.[%parent.handler]
label: 'Entity reference selection settings'
field.value.taxonomy_term_reference:
type: mapping

View File

@ -47,6 +47,15 @@ class TaxonomyTermReferenceItem extends EntityReferenceItem implements OptionsPr
) + parent::defaultStorageSettings();
}
/**
* {@inheritdoc}
*/
public static function defaultFieldSettings() {
return array(
'handler' => 'default:taxonomy_term',
) + parent::defaultFieldSettings();
}
/**
* {@inheritdoc}
*/

View File

@ -174,3 +174,23 @@ condition.plugin.user_role:
type: sequence
sequence:
type: string
entity_reference_selection.default:user:
type: entity_reference_selection
mapping:
filter:
type: mapping
label: 'Filter settings'
mapping:
type:
type: string
label: 'Filter by'
role:
type: sequence
label: 'Restrict to the selected roles'
sequence:
type: string
label: 'Role'
include_anonymous:
type: boolean
label: 'Include the anonymous user in the matched entities.'

View File

@ -1,6 +1,6 @@
# Schema for the views entity reference selection plugins.
entity_reference.views.handler_settings:
entity_reference_selection.views:
type: mapping
label: 'View handler settings'
mapping: