pluginreference-2.0.0/src/Plugin/PluginReferenceSelection/FilteredSelection.php
src/Plugin/PluginReferenceSelection/FilteredSelection.php
<?php
namespace Drupal\pluginreference\Plugin\PluginReferenceSelection;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\pluginreference\Attribute\PluginReferenceSelection;
/**
* Provides the default selection for block plugins.
*/
#[PluginReferenceSelection(
id: 'filtered',
label: new TranslatableMarkup('Filtered selection'),
group: 'filtered',
weight: 0,
deriver: 'Drupal\pluginreference\Plugin\Derivative\DefaultSelectionDeriver',
)]
class FilteredSelection extends DefaultSelection {
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return [
'filter' => [
'key' => 'id',
'negate' => FALSE,
'target_values' => [],
],
] + parent::defaultConfiguration();
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form = parent::buildConfigurationForm($form, $form_state);
$configuration = $this->getConfiguration();
$form['filter'] = [
'#type' => 'fieldset',
'#title' => $this->t('Filter options'),
'#weight' => -1,
];
$form['filter']['key'] = [
'#type' => 'select',
'#title' => $this->t('Filter by'),
'#options' => $this->getFilterableKeys(),
'#default_value' => $configuration['filter']['key'],
'#ajax' => TRUE,
];
$form['filter']['negate'] = [
'#type' => 'radios',
'#title' => $this->t('Filter by'),
'#options' => [
FALSE => $this->t('Include the selected below'),
TRUE => $this->t('Exclude the selected below'),
],
'#default_value' => (int) $configuration['filter']['negate'],
];
$form['filter']['target_values'] = $this->buildTargetValuesElement($form, $form_state);
return $form;
}
/**
* Build the target values form element.
*
* @param array $form
* An associative array containing the initial structure of the plugin form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*
* @return array
* The target values form element.
*/
protected function buildTargetValuesElement(array $form, FormStateInterface $form_state): array {
$configuration = $this->getConfiguration();
$filter_key = $form_state->getValue([
'settings',
'handler_settings',
'filter',
'key',
]) ?? $configuration['filter']['key'];
if (empty($filter_key)) {
return [];
}
if ($filter_key === 'id') {
$element = [
'#type' => 'tableselect',
'#header' => [
$this->t('Label/ID'),
$this->t('Provider'),
],
'#js_select' => TRUE,
'#empty_option' => $this->t('No options available.'),
];
}
else {
$element = [
'#type' => 'checkboxes',
];
}
$element += [
'#title' => $this->t('Filter values'),
'#options' => $this->getTargetValuesOptions($filter_key),
'#required' => TRUE,
'#default_value' => $configuration['filter']['target_values'],
'#element_validate' => [[static::class, 'elementValidateFilter']],
];
return $element;
}
/**
* Helper method that builds an array of target values.
*
* @param string $filter_key
* The key on which the plugins will be filtered.
*
* @return array
* An array of target values.
*/
protected function getTargetValuesOptions(string $filter_key) {
$options = [];
$target_type = $this->getConfiguration()['target_type'];
$plugin_definitions = $this->pluginTypeHelper->getPluginDefinitions($target_type);
foreach ($plugin_definitions as $plugin_id => $plugin_definition) {
switch ($filter_key) {
case 'id':
$options[$plugin_id] = [
['label' => $this->pluginTypeHelper->getPluginLabel($plugin_definition) . ' (' . $plugin_id . ')'],
['provider' => $plugin_definition['provider']],
];
break;
case 'provider':
$options[$plugin_definition[$filter_key]] = $this->pluginTypeHelper->getProviderName($plugin_definition[$filter_key]);
break;
default:
if ($plugin_definition[$filter_key] instanceof TranslatableMarkup) {
$options[$plugin_definition[$filter_key]->getUntranslatedString()] = $plugin_definition[$filter_key];
}
else {
$options[$plugin_definition[$filter_key]] = $plugin_definition[$filter_key];
}
}
}
ksort($options);
return $options;
}
/**
* Get all keys that are supported to filter on.
*
* @return array
* An array of keys that are allowed to filter on.
*/
protected function getFilterableKeys(): array {
return [
'id' => $this->t('Plugin'),
'provider' => $this->t('Provider'),
];
}
/**
* {@inheritdoc}
*/
protected function filterReferenceablePluginDefinitions(array &$plugin_definitions): void {
$filter_key = $this->getConfiguration()['filter']['key'];
$filter_negate = $this->getConfiguration()['filter']['negate'];
$filter_target_values = $this->getConfiguration()['filter']['target_values'];
foreach ($plugin_definitions as $plugin_id => $plugin_definition) {
if ($filter_negate === FALSE && !in_array($plugin_definition[$filter_key], $filter_target_values, TRUE)) {
unset($plugin_definitions[$plugin_id]);
}
elseif ($filter_negate === TRUE && in_array($plugin_definition[$filter_key], $filter_target_values, TRUE)) {
unset($plugin_definitions[$plugin_id]);
}
}
}
/**
* Form element validation handler; Filters the #value property of an element.
*/
public static function elementValidateFilter(array &$element, FormStateInterface $form_state): void {
$element['#value'] = array_filter($element['#value']);
$form_state->setValueForElement($element, $element['#value']);
}
}
