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:
|
field.storage_settings.entity_reference:
|
||||||
type: mapping
|
type: mapping
|
||||||
label: 'Entity reference settings'
|
label: 'Entity reference field storage settings'
|
||||||
mapping:
|
mapping:
|
||||||
target_type:
|
target_type:
|
||||||
type: string
|
type: string
|
||||||
|
|
@ -560,14 +560,14 @@ field.storage_settings.entity_reference:
|
||||||
|
|
||||||
field.field_settings.entity_reference:
|
field.field_settings.entity_reference:
|
||||||
type: mapping
|
type: mapping
|
||||||
label: 'Entity reference settings'
|
label: 'Entity reference field settings'
|
||||||
mapping:
|
mapping:
|
||||||
handler:
|
handler:
|
||||||
type: string
|
type: string
|
||||||
label: 'Reference method'
|
label: 'Reference method'
|
||||||
handler_settings:
|
handler_settings:
|
||||||
type: entity_reference.[%parent.handler].handler_settings
|
type: entity_reference_selection.[%parent.handler]
|
||||||
label: 'Reference method settings'
|
label: 'Entity reference selection plugin settings'
|
||||||
|
|
||||||
field.value.entity_reference:
|
field.value.entity_reference:
|
||||||
type: mapping
|
type: mapping
|
||||||
|
|
@ -750,3 +750,32 @@ text_format:
|
||||||
label: 'Text format'
|
label: 'Text format'
|
||||||
# The text format should not be translated as part of the string
|
# The text format should not be translated as part of the string
|
||||||
# translation system, so this is not marked as translatable.
|
# 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.
|
// Initialize default options.
|
||||||
$options += array(
|
$options += array(
|
||||||
'handler' => 'default',
|
'handler' => $this->getPluginId($options['target_type'], 'default'),
|
||||||
'handler_settings' => array(),
|
'handler_settings' => array(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Get all available selection plugins for this entity type.
|
// A specific selection plugin ID was already specified.
|
||||||
$selection_handler_groups = $this->getSelectionGroups($options['target_type']);
|
if (strpos($options['handler'], ':') !== FALSE) {
|
||||||
|
$plugin_id = $options['handler'];
|
||||||
// Sort the selection plugins by weight and select the best match.
|
}
|
||||||
uasort($selection_handler_groups[$options['handler']], array('Drupal\Component\Utility\SortArray', 'sortByWeightElement'));
|
// Only a selection group name was specified.
|
||||||
end($selection_handler_groups[$options['handler']]);
|
else {
|
||||||
$plugin_id = key($selection_handler_groups[$options['handler']]);
|
$plugin_id = $this->getPluginId($options['target_type'], $options['handler']);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->createInstance($plugin_id, $options);
|
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}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
|
|
@ -86,7 +102,7 @@ class SelectionPluginManager extends DefaultPluginManager implements SelectionPl
|
||||||
$options = array(
|
$options = array(
|
||||||
'target_type' => $field_definition->getFieldStorageDefinition()->getSetting('target_type'),
|
'target_type' => $field_definition->getFieldStorageDefinition()->getSetting('target_type'),
|
||||||
'handler' => $field_definition->getSetting('handler'),
|
'handler' => $field_definition->getSetting('handler'),
|
||||||
'handler_settings' => $field_definition->getSetting('handler_settings'),
|
'handler_settings' => $field_definition->getSetting('handler_settings') ?: array(),
|
||||||
'entity' => $entity,
|
'entity' => $entity,
|
||||||
);
|
);
|
||||||
return $this->getInstance($options);
|
return $this->getInstance($options);
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,19 @@ use Drupal\Core\Field\FieldDefinitionInterface;
|
||||||
*/
|
*/
|
||||||
interface SelectionPluginManagerInterface extends PluginManagerInterface {
|
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.
|
* Returns selection plugins that can reference a specific entity type.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,8 @@ class EntityReferenceItem extends FieldItemBase {
|
||||||
*/
|
*/
|
||||||
public static function defaultFieldSettings() {
|
public static function defaultFieldSettings() {
|
||||||
return array(
|
return array(
|
||||||
'handler' => 'default',
|
'handler' => 'default:' . (\Drupal::moduleHandler()->moduleExists('node') ? 'node' : 'user'),
|
||||||
|
'handler_settings' => array(),
|
||||||
) + parent::defaultFieldSettings();
|
) + 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\FieldStorageConfig;
|
||||||
use Drupal\field\Entity\FieldConfig;
|
use Drupal\field\Entity\FieldConfig;
|
||||||
use Drupal\field\FieldStorageConfigInterface;
|
use Drupal\field\FieldStorageConfigInterface;
|
||||||
|
use Drupal\field\FieldConfigInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements hook_help().
|
* Implements hook_help().
|
||||||
|
|
@ -84,20 +85,33 @@ function entity_reference_field_storage_config_update(FieldStorageConfigInterfac
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($field_storage->bundles)) {
|
foreach ($field_storage->getBundles() as $bundle) {
|
||||||
// Field storage has no fields.
|
$field = FieldConfig::loadByName($field_storage->getTargetEntityTypeId(), $bundle, $field_storage->getName());
|
||||||
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->settings['handler_settings'] = array();
|
||||||
$field->save();
|
$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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -42,15 +42,6 @@ class ConfigurableEntityReferenceItem extends EntityReferenceItem implements Opt
|
||||||
return $settings;
|
return $settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public static function defaultFieldSettings() {
|
|
||||||
return array(
|
|
||||||
'handler_settings' => array(),
|
|
||||||
) + parent::defaultFieldSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@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])) {
|
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');
|
$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'));
|
$this->drupalPostForm(NULL, array(), t('Save field settings'));
|
||||||
|
|
||||||
// The base handler should be selected by default.
|
// 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.
|
// The base handler settings should be displayed.
|
||||||
$entity_type_id = 'node';
|
$entity_type_id = 'node';
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ use Drupal\Component\Utility\Unicode;
|
||||||
use Drupal\Core\Field\FieldItemListInterface;
|
use Drupal\Core\Field\FieldItemListInterface;
|
||||||
use Drupal\Core\Field\FieldItemInterface;
|
use Drupal\Core\Field\FieldItemInterface;
|
||||||
use Drupal\Core\Language\LanguageInterface;
|
use Drupal\Core\Language\LanguageInterface;
|
||||||
|
use Drupal\field\Entity\FieldConfig;
|
||||||
|
use Drupal\field\Entity\FieldStorageConfig;
|
||||||
use Drupal\field\Tests\FieldUnitTestBase;
|
use Drupal\field\Tests\FieldUnitTestBase;
|
||||||
use Drupal\taxonomy\Entity\Term;
|
use Drupal\taxonomy\Entity\Term;
|
||||||
use Drupal\taxonomy\Entity\Vocabulary;
|
use Drupal\taxonomy\Entity\Vocabulary;
|
||||||
|
|
@ -27,7 +29,7 @@ class EntityReferenceItemTest extends FieldUnitTestBase {
|
||||||
*
|
*
|
||||||
* @var array
|
* @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.
|
* 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());
|
$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:
|
handler:
|
||||||
type: string
|
type: string
|
||||||
label: 'Reference method'
|
label: 'Reference method'
|
||||||
|
handler_settings:
|
||||||
|
type: entity_reference_selection.[%parent.handler]
|
||||||
|
label: 'Entity reference selection settings'
|
||||||
file_directory:
|
file_directory:
|
||||||
type: string
|
type: string
|
||||||
label: 'File directory'
|
label: 'File directory'
|
||||||
|
|
|
||||||
|
|
@ -134,12 +134,17 @@ class MigrateFieldInstanceTest extends MigrateDrupal6TestBase {
|
||||||
'display_field' => FALSE,
|
'display_field' => FALSE,
|
||||||
'display_default' => FALSE,
|
'display_default' => FALSE,
|
||||||
'uri_scheme' => 'public',
|
'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,
|
'target_bundle' => NULL,
|
||||||
);
|
);
|
||||||
|
$field_settings = $field->getSettings();
|
||||||
|
ksort($expected);
|
||||||
|
ksort($field_settings);
|
||||||
// This is the only way to compare arrays.
|
// This is the only way to compare arrays.
|
||||||
$this->assertFalse(array_diff_assoc($field->getSettings(), $expected));
|
$this->assertIdentical($expected, $field_settings);
|
||||||
$this->assertFalse(array_diff_assoc($expected, $field->getSettings()));
|
|
||||||
|
|
||||||
// Test a link field.
|
// Test a link field.
|
||||||
$field = FieldConfig::load('node.story.field_test_link');
|
$field = FieldConfig::load('node.story.field_test_link');
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,9 @@ field.field_settings.taxonomy_term_reference:
|
||||||
handler:
|
handler:
|
||||||
type: string
|
type: string
|
||||||
label: 'Reference method'
|
label: 'Reference method'
|
||||||
|
handler_settings:
|
||||||
|
type: entity_reference_selection.[%parent.handler]
|
||||||
|
label: 'Entity reference selection settings'
|
||||||
|
|
||||||
field.value.taxonomy_term_reference:
|
field.value.taxonomy_term_reference:
|
||||||
type: mapping
|
type: mapping
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,15 @@ class TaxonomyTermReferenceItem extends EntityReferenceItem implements OptionsPr
|
||||||
) + parent::defaultStorageSettings();
|
) + parent::defaultStorageSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public static function defaultFieldSettings() {
|
||||||
|
return array(
|
||||||
|
'handler' => 'default:taxonomy_term',
|
||||||
|
) + parent::defaultFieldSettings();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -174,3 +174,23 @@ condition.plugin.user_role:
|
||||||
type: sequence
|
type: sequence
|
||||||
sequence:
|
sequence:
|
||||||
type: string
|
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.
|
# Schema for the views entity reference selection plugins.
|
||||||
|
|
||||||
entity_reference.views.handler_settings:
|
entity_reference_selection.views:
|
||||||
type: mapping
|
type: mapping
|
||||||
label: 'View handler settings'
|
label: 'View handler settings'
|
||||||
mapping:
|
mapping:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue