View source
<?php
namespace Drupal\better_exposed_filters\Plugin\better_exposed_filters\filter;
use Drupal\better_exposed_filters\BetterExposedFiltersHelper;
use Drupal\better_exposed_filters\Plugin\BetterExposedFiltersWidgetBase;
use Drupal\better_exposed_filters\Plugin\BetterExposedFiltersWidgetInterface;
use Drupal\Core\Form\FormState;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\views\Plugin\views\filter\NumericFilter;
use Drupal\views\Plugin\views\filter\StringFilter;
abstract class FilterWidgetBase extends BetterExposedFiltersWidgetBase implements BetterExposedFiltersWidgetInterface {
use StringTranslationTrait;
public static function isApplicable($filter = NULL, array $filter_options = []) {
$is_applicable = FALSE;
if (!isset($filter)) {
return $is_applicable;
}
if (is_a($filter, 'Drupal\\views\\Plugin\\views\\filter\\StringFilter') || is_a($filter, 'Drupal\\views\\Plugin\\views\\filter\\InOperator')) {
if (in_array($filter->operator, [
'in',
'or',
'and',
'not',
])) {
$is_applicable = TRUE;
}
if (in_array($filter->operator, [
'empty',
'not empty',
])) {
$is_applicable = TRUE;
}
}
if (is_a($filter, 'Drupal\\views\\Plugin\\views\\filter\\BooleanOperator')) {
$is_applicable = TRUE;
}
if (is_a($filter, 'Drupal\\taxonomy\\Plugin\\views\\filter\\TaxonomyIndexTid')) {
if ($filter_options['type'] == 'select') {
$is_applicable = TRUE;
}
}
if ($filter
->isAGroup()) {
$is_applicable = TRUE;
}
if (is_a($filter, 'Drupal\\search_api\\Plugin\\views\\filter\\SearchApiFulltext')) {
$is_applicable = TRUE;
}
return $is_applicable;
}
public function defaultConfiguration() {
return parent::defaultConfiguration() + [
'advanced' => [
'collapsible' => FALSE,
'is_secondary' => FALSE,
'placeholder_text' => '',
'rewrite' => [
'filter_rewrite_values' => '',
],
'sort_options' => FALSE,
],
];
}
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$filter = $this->handler;
$filter_widget_type = $this
->getExposedFilterWidgetType();
$form['advanced'] = [
'#type' => 'details',
'#title' => $this
->t('Advanced filter options'),
'#weight' => 10,
];
$supported_types = [
'select',
];
if (in_array($filter_widget_type, $supported_types)) {
$form['advanced']['sort_options'] = [
'#type' => 'checkbox',
'#title' => 'Sort filter options',
'#default_value' => !empty($this->configuration['advanced']['sort_options']),
'#description' => $this
->t('The options will be sorted alphabetically.'),
];
}
$supported_types = [
'entity_autocomplete',
'textfield',
];
if (in_array($filter_widget_type, $supported_types)) {
$form['advanced']['placeholder_text'] = [
'#type' => 'textfield',
'#title' => $this
->t('Placeholder text'),
'#description' => $this
->t('Text to be shown in the text field until it is edited. Leave blank for no placeholder to be set.'),
'#default_value' => $this
->t($this->configuration['advanced']['placeholder_text']),
];
}
if (!$filter instanceof StringFilter && !$filter instanceof NumericFilter || $filter
->isAGroup()) {
$form['advanced']['rewrite']['filter_rewrite_values'] = [
'#type' => 'textarea',
'#title' => $this
->t('Rewrite the text displayed'),
'#default_value' => $this->configuration['advanced']['rewrite']['filter_rewrite_values'],
'#description' => $this
->t('Use this field to rewrite the filter options displayed. Use the format of current_text|replacement_text, one replacement per line. For example: <pre>
Current|Replacement
On|Yes
Off|No
</pre> Leave the replacement text blank to remove an option altogether. If using hierarchical taxonomy filters, do not including leading hyphens in the current text.
'),
];
}
$form['advanced']['collapsible'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Make filter options collapsible'),
'#default_value' => !empty($this->configuration['advanced']['collapsible']),
'#description' => $this
->t('Puts the filter options in a collapsible details element.'),
];
$form['advanced']['is_secondary'] = [
'#type' => 'checkbox',
'#title' => $this
->t('This is a secondary option'),
'#default_value' => !empty($this->configuration['advanced']['is_secondary']),
'#states' => [
'visible' => [
':input[name="exposed_form_options[bef][general][allow_secondary]"]' => [
'checked' => TRUE,
],
],
],
'#description' => $this
->t('Places this element in the secondary options portion of the exposed form.'),
];
return $form;
}
public function exposedFormAlter(array &$form, FormStateInterface $form_state) {
$filter = $this->handler;
$filter_id = $filter->options['expose']['identifier'];
$field_id = $this
->getExposedFilterFieldId();
$is_collapsible = $this->configuration['advanced']['collapsible'];
$is_secondary = !empty($form['secondary']) && $this->configuration['advanced']['is_secondary'];
if ($this->configuration['advanced']['sort_options']) {
$form[$field_id]['#nested'] = $filter->options['hierarchy'] ?? FALSE;
$form[$field_id]['#nested_delimiter'] = '-';
$form[$field_id]['#pre_process'][] = [
$this,
'processSortedOptions',
];
}
if (!empty($this->configuration['advanced']['placeholder_text'])) {
$form[$field_id]['#placeholder'] = $this
->t($this->configuration['advanced']['placeholder_text']);
}
if ($this->configuration['advanced']['rewrite']['filter_rewrite_values']) {
$form[$field_id]['#options'] = BetterExposedFiltersHelper::rewriteOptions($form[$field_id]['#options'], $this->configuration['advanced']['rewrite']['filter_rewrite_values'], !$this->configuration['advanced']['sort_options']);
}
$identifier = $filter_id;
$exposed_label = $filter->options['expose']['label'];
$exposed_description = $filter->options['expose']['description'];
if ($filter
->isAGroup()) {
$identifier = $filter->options['group_info']['identifier'];
$exposed_label = $filter->options['group_info']['label'];
$exposed_description = $filter->options['group_info']['description'];
}
if ($is_collapsible) {
$form[$field_id . '_collapsible'] = [
'#type' => 'details',
'#title' => $exposed_label,
'#description' => $exposed_description,
'#attributes' => [
'class' => [
'form-item',
],
],
];
if ($is_secondary) {
$this
->addElementToGroup($form, $form_state, $field_id . '_collapsible', 'secondary');
}
}
$filter_elements = [
$identifier,
$filter->options['expose']['operator_id'],
];
foreach ($filter_elements as $element) {
if (empty($form[$element])) {
continue;
}
if ($is_collapsible) {
$this
->addElementToGroup($form, $form_state, $element, $field_id . '_collapsible');
}
else {
$form[$element]['#title'] = $exposed_label;
$form[$element]['#description'] = $exposed_description;
if ($is_secondary) {
$this
->addElementToGroup($form, $form_state, $element, 'secondary');
}
}
$this
->addContext($form[$element]);
}
}
public function processSortedOptions(array $element, FormStateInterface $form_state) {
$options =& $element['#options'];
$any_option = FALSE;
if (empty($element['#required'])) {
$any_option = array_slice($options, 0, 1, TRUE);
unset($options[key($any_option)]);
}
if (!empty($element['#nested'])) {
$delimiter = $element['#nested_delimiter'] ?? '-';
$options = BetterExposedFiltersHelper::sortNestedOptions($options, $delimiter);
}
else {
$options = BetterExposedFiltersHelper::sortOptions($options);
}
if ($any_option) {
$options = $any_option + $options;
}
return $element;
}
protected function getExposedFilterFieldId() {
$filter = $this->handler;
$field_id = $filter->options['expose']['identifier'];
$is_grouped_filter = $filter->options['is_grouped'] ?: FALSE;
if ($is_grouped_filter) {
$field_id = $filter->options['group_info']['identifier'];
}
return $field_id;
}
protected function getExposedFilterWidgetType() {
$form = [];
$form_state = new FormState();
$form_state
->set('exposed', TRUE);
$filter = $this->handler;
$filter
->buildExposedForm($form, $form_state);
$filter_id = $filter->options['expose']['identifier'];
return $form[$filter_id]['#type'] ?? $form[$filter_id]['value']['#type'] ?? '';
}
}