Commit d5d37e06 authored by cilefen's avatar cilefen
Browse files

Revert "Issue #2787873 by claudiu.cristea, amateescu, jibran, dawehner, catch:...

Revert "Issue #2787873 by claudiu.cristea, amateescu, jibran, dawehner, catch: Add a base class for entity reference selection handlers and fix the structure of their configuration"

This reverts commit b0900c73.
parent 05ffa70c
......@@ -780,24 +780,11 @@ text_format:
# The text format should not be translated as part of the string
# translation system, so this is not marked as translatable.
# Base schema for all entity reference selection handler schemas.
# Schema for the configuration of the Entity reference selection plugins.
entity_reference_selection:
type: mapping
label: 'Entity reference selection handler settings'
mapping:
target_type:
type: string
label: 'Type of item to reference'
# Schema for all entity reference selection handlers that are not providing a
# specific schema.
entity_reference_selection.*:
type: entity_reference_selection
# Schema for the entity reference 'default' selection handler settings.
entity_reference_selection.default:
type: entity_reference_selection
label: 'Default selection handler settings'
label: 'Entity reference selection plugin configuration'
mapping:
target_bundles:
type: sequence
......@@ -805,7 +792,7 @@ entity_reference_selection.default:
nullable: true
sequence:
type: string
label: 'Bundle'
label: 'Type'
sort:
type: mapping
label: 'Sort settings'
......@@ -823,7 +810,5 @@ entity_reference_selection.default:
type: string
label: 'Bundle assigned to the auto-created entities.'
# Schema for all entity reference 'default:*' selection handlers that are not
# providing a specific schema.
entity_reference_selection.default:*:
type: entity_reference_selection.default
entity_reference_selection.*:
type: entity_reference_selection
......@@ -152,9 +152,10 @@ public static function validateEntityAutocomplete(array &$element, FormStateInte
$value = NULL;
if (!empty($element['#value'])) {
$options = $element['#selection_settings'] + [
$options = [
'target_type' => $element['#target_type'],
'handler' => $element['#selection_handler'],
'handler_settings' => $element['#selection_settings'],
];
/** @var /Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface $handler */
$handler = \Drupal::service('plugin.manager.entity_reference_selection')->getInstance($options);
......
......@@ -52,9 +52,10 @@ public function __construct(SelectionPluginManagerInterface $selection_manager)
public function getMatches($target_type, $selection_handler, $selection_settings, $string = '') {
$matches = [];
$options = $selection_settings + [
$options = [
'target_type' => $target_type,
'handler' => $selection_handler,
'handler_settings' => $selection_settings,
];
$handler = $this->selectionManager->getInstance($options);
......
<?php
namespace Drupal\Core\Entity\EntityReferenceSelection;
use Drupal\Component\Plugin\ConfigurablePluginInterface;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Database\Query\SelectInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\PluginBase;
/**
* Provides a base class for configurable selection handlers.
*/
abstract class SelectionPluginBase extends PluginBase implements SelectionInterface, ConfigurablePluginInterface {
/**
* Constructs a new selection object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->setConfiguration($configuration);
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return [
'target_type' => NULL,
// @todo Remove this key in Drupal 9.0.x.
'handler' => $this->getPluginId(),
'entity' => NULL,
];
}
/**
* {@inheritdoc}
*/
public function getConfiguration() {
return $this->configuration;
}
/**
* {@inheritdoc}
*/
public function setConfiguration(array $configuration) {
// Resolve backward compatibility level configurations, if any.
$this->resolveBackwardCompatibilityConfiguration($configuration);
// Merge in defaults.
$this->configuration = NestedArray::mergeDeep(
$this->defaultConfiguration(),
$configuration
);
// Ensure a backward compatibility level configuration.
$this->ensureBackwardCompatibilityConfiguration();
}
/**
* {@inheritdoc}
*/
public function calculateDependencies() {
return [];
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
return $form;
}
/**
* {@inheritdoc}
*/
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) { }
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { }
/**
* {@inheritdoc}
*/
public function entityQueryAlter(SelectInterface $query) { }
/**
* Moves the backward compatibility level configurations in the right place.
*
* In order to keep backward compatibility, we copy all settings, except
* 'target_type', 'handler' and 'entity' under 'handler_settings', following
* the structure from the field config. If the plugin was instantiated using
* the 'handler_settings' level, those values will be used. In case of
* conflict, the root level settings will take precedence. The backward
* compatibility aware configuration will have the next structure:
* - target_type
* - handler (will be removed in Drupal 9.0.x, it's the plugin id)
* - entity
* - setting_1
* - setting_2
* ...
* - setting_N
* - handler_settings: (will be removed in Drupal 9.0.x)
* - setting_1
* - setting_2
* ...
* - setting_N
*
* @param array $configuration
* The configuration array to be altered.
*
* @deprecated Scheduled for removal in Drupal 9.0.x.
*
* @see https://www.drupal.org/node/2870971
*/
protected function resolveBackwardCompatibilityConfiguration(array &$configuration) {
if (isset($this->defaultConfiguration()['handler_settings'])) {
throw new \InvalidArgumentException("{$this->getPluginDefinition()['class']}::defaultConfiguration() should not contain a 'handler_settings' key. All settings should be placed in the root level.");
}
// Extract the BC level from the passed configuration, if any.
if (array_key_exists('handler_settings', $configuration)) {
if (!is_array($configuration['handler_settings'])) {
throw new \InvalidArgumentException("The setting 'handler_settings' is reserved and cannot be used.");
}
@trigger_error("Providing settings under 'handler_settings' is deprecated and will be removed before 9.0.0. Move the settings in the root of the configuration array. See https://www.drupal.org/node/2870971.", E_USER_DEPRECATED);
// Settings passed in the root level take precedence over BC settings.
$configuration += $configuration['handler_settings'];
unset($configuration['handler_settings']);
}
}
/**
* Ensures a backward compatibility level configuration.
*
* @deprecated Scheduled for removal in Drupal 9.0.x.
*
* @see https://www.drupal.org/node/2870971
*/
protected function ensureBackwardCompatibilityConfiguration() {
// Synchronize back 'handler_settings'.
foreach ($this->configuration as $key => $value) {
// Filter out keys that belong strictly to the root level.
if (!in_array($key, ['handler', 'target_type', 'entity', 'handler_settings'])) {
$this->configuration['handler_settings'][$key] = $value;
}
}
}
}
......@@ -39,6 +39,7 @@ public function getInstance(array $options) {
// Initialize default options.
$options += [
'handler' => $this->getPluginId($options['target_type'], 'default'),
'handler_settings' => [],
];
// A specific selection plugin ID was already specified.
......@@ -49,7 +50,6 @@ public function getInstance(array $options) {
else {
$plugin_id = $this->getPluginId($options['target_type'], $options['handler']);
}
unset($options['handler']);
return $this->createInstance($plugin_id, $options);
}
......@@ -92,10 +92,10 @@ public function getSelectionGroups($entity_type_id) {
* {@inheritdoc}
*/
public function getSelectionHandler(FieldDefinitionInterface $field_definition, EntityInterface $entity = NULL) {
$options = $field_definition->getSetting('handler_settings') ?: [];
$options += [
$options = [
'target_type' => $field_definition->getFieldStorageDefinition()->getSetting('target_type'),
'handler' => $field_definition->getSetting('handler'),
'handler_settings' => $field_definition->getSetting('handler_settings') ?: [],
'entity' => $entity,
];
return $this->getInstance($options);
......
<?php
namespace Drupal\Core\Entity\EntityReferenceSelection;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides common methods and injects services for core selection handlers.
*/
trait SelectionTrait {
/**
* The entity manager service.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
*/
protected $entityManager;
/**
* The module handler service.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* Constructs a new selection object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager service.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler service.
* @param \Drupal\Core\Session\AccountInterface $current_user
* The current user.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, AccountInterface $current_user) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->entityManager = $entity_manager;
$this->moduleHandler = $module_handler;
$this->currentUser = $current_user;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('entity.manager'),
$container->get('module_handler'),
$container->get('current_user')
);
}
}
......@@ -2,7 +2,8 @@
namespace Drupal\Core\Entity\Plugin\EntityReferenceSelection;
use Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginBase;
use Drupal\Core\Database\Query\SelectInterface;
use Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface;
use Drupal\Core\Form\FormStateInterface;
/**
......@@ -13,19 +14,28 @@
* label = @Translation("Broken/Missing")
* )
*/
class Broken extends SelectionPluginBase {
class Broken implements SelectionInterface {
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form = parent::buildConfigurationForm($form, $form_state);
$form['selection_handler'] = [
'#markup' => t('The selected selection handler is broken.'),
];
return $form;
}
/**
* {@inheritdoc}
*/
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) { }
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { }
/**
* {@inheritdoc}
*/
......@@ -47,4 +57,9 @@ public function validateReferenceableEntities(array $ids) {
return [];
}
/**
* {@inheritdoc}
*/
public function entityQueryAlter(SelectInterface $query) { }
}
......@@ -4,14 +4,19 @@
use Drupal\Component\Utility\Html;
use Drupal\Core\Database\Query\AlterableInterface;
use Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginBase;
use Drupal\Core\Entity\EntityReferenceSelection\SelectionTrait;
use Drupal\Core\Database\Query\SelectInterface;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityReferenceSelection\SelectionWithAutocreateInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\PluginBase;
use Drupal\Core\Session\AccountInterface;
use Drupal\user\EntityOwnerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Default plugin implementation of the Entity Reference Selection plugin.
......@@ -33,38 +38,88 @@
* deriver = "Drupal\Core\Entity\Plugin\Derivative\DefaultSelectionDeriver"
* )
*/
class DefaultSelection extends SelectionPluginBase implements ContainerFactoryPluginInterface, SelectionWithAutocreateInterface {
class DefaultSelection extends PluginBase implements SelectionInterface, SelectionWithAutocreateInterface, ContainerFactoryPluginInterface {
use SelectionTrait;
/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
*/
protected $entityManager;
/**
* The module handler service.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* Constructs a new SelectionBase object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager service.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler service.
* @param \Drupal\Core\Session\AccountInterface $current_user
* The current user.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, AccountInterface $current_user) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->entityManager = $entity_manager;
$this->moduleHandler = $module_handler;
$this->currentUser = $current_user;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('entity.manager'),
$container->get('module_handler'),
$container->get('current_user')
);
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return [
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$entity_type_id = $this->configuration['target_type'];
$selection_handler_settings = $this->configuration['handler_settings'];
$entity_type = $this->entityManager->getDefinition($entity_type_id);
$bundles = $this->entityManager->getBundleInfo($entity_type_id);
// Merge-in default values.
$selection_handler_settings += [
// For the 'target_bundles' setting, a NULL value is equivalent to "allow
// entities from any bundle to be referenced" and an empty array value is
// equivalent to "no entities from any bundle can be referenced".
'target_bundles' => NULL,
'sort' => [
'field' => '_none',
'direction' => 'ASC',
],
'auto_create' => FALSE,
'auto_create_bundle' => NULL,
] + parent::defaultConfiguration();
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form = parent::buildConfigurationForm($form, $form_state);
$configuration = $this->getConfiguration();
$entity_type_id = $configuration['target_type'];
$entity_type = $this->entityManager->getDefinition($entity_type_id);
$bundles = $this->entityManager->getBundleInfo($entity_type_id);
];
if ($entity_type->hasKey('bundle')) {
$bundle_options = [];
......@@ -77,7 +132,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
'#type' => 'checkboxes',
'#title' => $this->t('Bundles'),
'#options' => $bundle_options,
'#default_value' => (array) $configuration['target_bundles'],
'#default_value' => (array) $selection_handler_settings['target_bundles'],
'#required' => TRUE,
'#size' => 6,
'#multiple' => TRUE,
......@@ -134,7 +189,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
] + $fields,
'#ajax' => TRUE,
'#limit_validation_errors' => [],
'#default_value' => $configuration['sort']['field'],
'#default_value' => $selection_handler_settings['sort']['field'],
];
$form['sort']['settings'] = [
......@@ -143,7 +198,12 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
'#process' => [[EntityReferenceItem::class, 'formProcessMergeParent']],
];
if ($configuration['sort']['field'] != '_none') {
if ($selection_handler_settings['sort']['field'] != '_none') {
// Merge-in default values.
$selection_handler_settings['sort'] += [
'direction' => 'ASC',
];
$form['sort']['settings']['direction'] = [
'#type' => 'select',
'#title' => $this->t('Sort direction'),
......@@ -152,7 +212,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
'ASC' => $this->t('Ascending'),
'DESC' => $this->t('Descending'),
],
'#default_value' => $configuration['sort']['direction'],
'#default_value' => $selection_handler_settings['sort']['direction'],
];
}
}
......@@ -160,17 +220,17 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
$form['auto_create'] = [
'#type' => 'checkbox',
'#title' => $this->t("Create referenced entities if they don't already exist"),
'#default_value' => $configuration['auto_create'],
'#default_value' => $selection_handler_settings['auto_create'],
'#weight' => -2,
];
if ($entity_type->hasKey('bundle')) {
$bundles = array_intersect_key($bundle_options, array_filter((array) $configuration['target_bundles']));
$bundles = array_intersect_key($bundle_options, array_filter((array) $selection_handler_settings['target_bundles']));
$form['auto_create_bundle'] = [
'#type' => 'select',
'#title' => $this->t('Store new items in'),
'#options' => $bundles,
'#default_value' => $configuration['auto_create_bundle'],
'#default_value' => $selection_handler_settings['auto_create_bundle'],
'#access' => count($bundles) > 1,
'#states' => [
'visible' => [
......@@ -188,8 +248,6 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
* {@inheritdoc}
*/
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
parent::validateConfigurationForm($form, $form_state);
// If no checkboxes were checked for 'target_bundles', store NULL ("all
// bundles are referenceable") rather than empty array ("no bundle is
// referenceable" - typically happens when all referenceable bundles have
......@@ -203,6 +261,11 @@ public function validateConfigurationForm(array &$form, FormStateInterface $form
$form_state->unsetValue(['settings', 'handler_settings', 'target_bundles_update']);
}
/**