Issue #2436835 by amateescu, alexpott: Unable to create config schema for entity type specific entity reference selection plugin
parent
eaffcfc511
commit
ae4848f51d
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.'
|
||||
|
|
@ -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.
|
||||
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;
|
||||
}
|
||||
|
||||
$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);
|
||||
$field->settings['handler_settings'] = array();
|
||||
$field->save();
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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']);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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.'
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Reference in New Issue