View source
<?php
namespace Drupal\views\Plugin\views\filter;
use Drupal\Component\Render\MarkupInterface;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Form\FormStateInterface;
use Drupal\views\Plugin\views\display\DisplayPluginBase;
use Drupal\views\ViewExecutable;
use Drupal\Core\Form\OptGroup;
class InOperator extends FilterPluginBase {
protected $valueFormType = 'checkboxes';
protected $valueOptions = NULL;
protected $valueTitle;
public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
parent::init($view, $display, $options);
$this->valueTitle = $this
->t('Options');
$this->valueOptions = NULL;
}
public function getValueOptions() {
if (isset($this->valueOptions)) {
return $this->valueOptions;
}
if (isset($this->definition['options callback']) && is_callable($this->definition['options callback'])) {
if (isset($this->definition['options arguments']) && is_array($this->definition['options arguments'])) {
$this->valueOptions = call_user_func_array($this->definition['options callback'], $this->definition['options arguments']);
}
else {
$this->valueOptions = call_user_func($this->definition['options callback']);
}
}
else {
$this->valueOptions = [
t('Yes'),
$this
->t('No'),
];
}
return $this->valueOptions;
}
public function defaultExposeOptions() {
parent::defaultExposeOptions();
$this->options['expose']['reduce'] = FALSE;
}
public function buildExposeForm(&$form, FormStateInterface $form_state) {
parent::buildExposeForm($form, $form_state);
$form['expose']['reduce'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Limit list to selected items'),
'#description' => $this
->t('If checked, the only items presented to the user will be the ones selected here.'),
'#default_value' => !empty($this->options['expose']['reduce']),
];
}
protected function defineOptions() {
$options = parent::defineOptions();
$options['operator']['default'] = 'in';
$options['value']['default'] = [];
$options['expose']['contains']['reduce'] = [
'default' => FALSE,
];
return $options;
}
public function operators() {
$operators = [
'in' => [
'title' => $this
->t('Is one of'),
'short' => $this
->t('in'),
'short_single' => $this
->t('='),
'method' => 'opSimple',
'values' => 1,
],
'not in' => [
'title' => $this
->t('Is not one of'),
'short' => $this
->t('not in'),
'short_single' => $this
->t('<>'),
'method' => 'opSimple',
'values' => 1,
],
];
if (!empty($this->definition['allow empty'])) {
$operators += [
'empty' => [
'title' => $this
->t('Is empty (NULL)'),
'method' => 'opEmpty',
'short' => $this
->t('empty'),
'values' => 0,
],
'not empty' => [
'title' => $this
->t('Is not empty (NOT NULL)'),
'method' => 'opEmpty',
'short' => $this
->t('not empty'),
'values' => 0,
],
];
}
return $operators;
}
public function operatorOptions($which = 'title') {
$options = [];
foreach ($this
->operators() as $id => $info) {
$options[$id] = $info[$which];
}
return $options;
}
protected function operatorValues($values = 1) {
$options = [];
foreach ($this
->operators() as $id => $info) {
if (isset($info['values']) && $info['values'] == $values) {
$options[] = $id;
}
}
return $options;
}
protected function valueForm(&$form, FormStateInterface $form_state) {
$form['value'] = [];
$options = [];
$exposed = $form_state
->get('exposed');
if (!$exposed) {
$options = [
'all' => $this
->t('Select all'),
];
}
$this
->getValueOptions();
$options += $this->valueOptions;
$default_value = (array) $this->value;
$which = 'all';
if (!empty($form['operator'])) {
$source = ':input[name="options[operator]"]';
}
if ($exposed) {
$identifier = $this->options['expose']['identifier'];
if (empty($this->options['expose']['use_operator']) || empty($this->options['expose']['operator_id'])) {
$which = in_array($this->operator, $this
->operatorValues(1)) ? 'value' : 'none';
}
else {
$source = ':input[name="' . $this->options['expose']['operator_id'] . '"]';
}
if (!empty($this->options['expose']['reduce'])) {
$options = $this
->reduceValueOptions();
if (!empty($this->options['expose']['multiple']) && empty($this->options['expose']['required'])) {
$default_value = [];
}
}
if (empty($this->options['expose']['multiple'])) {
if (empty($this->options['expose']['required']) && (empty($default_value) || !empty($this->options['expose']['reduce'])) || isset($this->options['value']['all'])) {
$default_value = 'All';
}
elseif (empty($default_value)) {
$keys = array_keys($options);
$default_value = array_shift($keys);
}
else {
$copy = $default_value;
$default_value = array_shift($copy);
}
}
}
if ($which == 'all' || $which == 'value') {
$form['value'] = [
'#type' => $this->valueFormType,
'#title' => $this->valueTitle,
'#options' => $options,
'#default_value' => $default_value,
'#multiple' => TRUE,
'#size' => min(count($options, COUNT_RECURSIVE), 8),
];
$user_input = $form_state
->getUserInput();
if ($exposed && !isset($user_input[$identifier])) {
$user_input[$identifier] = $default_value;
$form_state
->setUserInput($user_input);
}
if ($which == 'all') {
if (!$exposed && in_array($this->valueFormType, [
'checkbox',
'checkboxes',
'radios',
'select',
])) {
$form['value']['#prefix'] = '<div id="edit-options-value-wrapper">';
$form['value']['#suffix'] = '</div>';
}
foreach ($this
->operatorValues(1) as $operator) {
$form['value']['#states']['visible'][] = [
$source => [
'value' => $operator,
],
];
}
}
}
}
public function reduceValueOptions($input = NULL) {
if (!isset($input)) {
$input = $this->valueOptions;
}
$options = [];
foreach ($input as $id => $option) {
if (is_array($option)) {
$options[$id] = $this
->reduceValueOptions($option);
continue;
}
elseif (is_object($option) && !$option instanceof MarkupInterface) {
$keys = array_keys($option->option);
$key = array_shift($keys);
if (isset($this->options['value'][$key])) {
$options[$id] = $option;
}
}
elseif (isset($this->options['value'][$id])) {
$options[$id] = $option;
}
}
return $options;
}
public function acceptExposedInput($input) {
if (empty($this->options['exposed'])) {
return TRUE;
}
if (empty($this->options['expose']['multiple']) && empty($this->options['expose']['required']) && !empty($this->options['expose']['limit'])) {
$identifier = $this->options['expose']['identifier'];
if ($input[$identifier] == 'All') {
return TRUE;
}
}
return parent::acceptExposedInput($input);
}
protected function valueSubmit($form, FormStateInterface $form_state) {
$form_state
->setValue([
'options',
'value',
], $form['value']['#value']);
}
public function adminSummary() {
if ($this
->isAGroup()) {
return $this
->t('grouped');
}
if (!empty($this->options['exposed'])) {
return $this
->t('exposed');
}
$info = $this
->operators();
$this
->getValueOptions();
$flat_options = OptGroup::flattenOptions($this->valueOptions);
if (!is_array($this->value)) {
return;
}
$operator = $info[$this->operator]['short'];
$values = '';
if (in_array($this->operator, $this
->operatorValues(1))) {
foreach ($this->value as $value) {
if (!isset($flat_options[$value])) {
unset($this->value[$value]);
}
}
if (count($this->value) == 0) {
$values = $this
->t('Unknown');
}
elseif (count($this->value) == 1) {
if (isset($info[$this->operator]['short_single'])) {
$operator = $info[$this->operator]['short_single'];
}
$keys = $this->value;
$value = array_shift($keys);
if (isset($flat_options[$value])) {
$values = $flat_options[$value];
}
else {
$values = '';
}
}
else {
foreach ($this->value as $value) {
if ($values !== '') {
$values .= ', ';
}
if (mb_strlen($values) > 8) {
$values = Unicode::truncate($values, 8, FALSE, TRUE);
break;
}
if (isset($flat_options[$value])) {
$values .= $flat_options[$value];
}
}
}
}
return $operator . ($values !== '' ? ' ' . $values : '');
}
public function query() {
$info = $this
->operators();
if (!empty($info[$this->operator]['method'])) {
$this
->{$info[$this->operator]['method']}();
}
}
protected function opSimple() {
if (empty($this->value)) {
return;
}
$this
->ensureMyTable();
$this->query
->addWhere($this->options['group'], "{$this->tableAlias}.{$this->realField}", array_values($this->value), $this->operator);
}
protected function opEmpty() {
$this
->ensureMyTable();
if ($this->operator == 'empty') {
$operator = "IS NULL";
}
else {
$operator = "IS NOT NULL";
}
$this->query
->addWhere($this->options['group'], "{$this->tableAlias}.{$this->realField}", NULL, $operator);
}
public function validate() {
$this
->getValueOptions();
$errors = parent::validate();
if (in_array($this->operator, $this
->operatorValues(0))) {
return [];
}
if (!in_array($this->operator, $this
->operatorValues(1))) {
$errors[] = $this
->t('The operator is invalid on filter: @filter.', [
'@filter' => $this
->adminLabel(TRUE),
]);
}
if (is_array($this->value)) {
if (!isset($this->valueOptions)) {
return $errors;
}
if ($this->options['exposed'] && !$this->options['expose']['required'] && empty($this->value)) {
return $errors;
}
$flat_options = OptGroup::flattenOptions($this->valueOptions);
foreach ($this->value as $value) {
if (!isset($flat_options[$value])) {
unset($this->value[$value]);
}
}
if (count($this->value) == 0) {
$errors[] = $this
->t('No valid values found on filter: @filter.', [
'@filter' => $this
->adminLabel(TRUE),
]);
}
}
elseif (!empty($this->value) && ($this->operator == 'in' || $this->operator == 'not in')) {
$errors[] = $this
->t('The value @value is not an array for @operator on filter: @filter', [
'@value' => var_export($this->value, TRUE),
'@operator' => $this->operator,
'@filter' => $this
->adminLabel(TRUE),
]);
}
return $errors;
}
}