toolshed-8.x-1.x-dev/modules/toolshed_search/src/Plugin/views/filter/IncludeDatasourceFilter.php
modules/toolshed_search/src/Plugin/views/filter/IncludeDatasourceFilter.php
<?php
namespace Drupal\toolshed_search\Plugin\views\filter;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\Form\FormStateInterface;
use Drupal\search_api\Plugin\views\filter\SearchApiFilterTrait;
use Drupal\search_api\SearchApiException;
use Drupal\views\Plugin\views\filter\FilterPluginBase;
/**
* A Search API datasource filter to toggle a datasource.
*
* This filter is mostly only useful when used as exposed input, when you want
* to allow users to remove a datasource. An example would be a checkbox
* for controlling including "media" into search results.
*
* @ViewsFilter("toolshed_datasource_filter")
*/
class IncludeDatasourceFilter extends FilterPluginBase {
use SearchApiFilterTrait;
/**
* {@inheritdoc}
*/
public function adminSummary(): \Stringable|string {
try {
$datasource = $this
->getIndex()
->getDatasource($this->options['search_api_datasource']);
$srcName = $datasource->getPluginDefinition()['label'] ?? $this->options['search_api_datasource'];
return new FormattableMarkup('@source=@status', [
'@source' => $srcName,
'@status' => $this->value ? $this->t('on') : $this->t('off'),
]);
}
catch (SearchApiException $e) {
return $this->t('datasource');
}
}
/**
* {@inheritdoc}
*/
public function acceptExposedInput($input): bool {
if (empty($this->options['exposed'])) {
return TRUE;
}
$filterKey = $this->options['expose']['identifier'];
$this->value = !empty($input[$filterKey]);
return TRUE;
}
/**
* {@inheritdoc}
*/
public function buildExposedForm(&$form, FormStateInterface $form_state): void {
if (empty($this->options['exposed'])) {
return;
}
$input = $form_state->getUserInput();
$exposeInfo = $this->exposedInfo();
$filterKey = $this->options['expose']['identifier'];
// Check if form has been submitted. If not submitted we need to apply
// the default plugin value. Note that this only needs to be updated
// when the value is "TRUE" since "FALSE" is empty input.
if (empty($input)) {
if ($this->value) {
$input[$filterKey] = $this->value;
$form_state->setUserInput($input);
}
}
$form[$filterKey] = [
'#type' => 'checkbox',
'#title' => $exposeInfo['label'] ?? $this->t('Include datasource'),
'#default_value' => $this->value,
];
// A hack which allows us to know if the form was submitted as opposed to
// on initial load, and the current value should be used.
// This happens because unchecked boxes, don't appear in the URL query for
// GET request, therefore we're faking some input that will appear. If this
// was an input already using this key, purpose is still served.
// This issue happens when this checkbox is without other exposed filters.
//
// @todo find way to resolve get filter to set query param even when 'off'
// or only use this when there are no other exposed filters.
if (!isset($form['ds']) && $this->options['value']) {
$form['ds'] = [
'#type' => 'hidden',
'#default_value' => 0,
];
}
}
/**
* {@inheritdoc}
*/
protected function defineOptions(): array {
$options = parent::defineOptions();
$options['exposed']['default'] = TRUE;
$options['search_api_datasource'] = ['default' => NULL];
return $options;
}
/**
* {@inheritdoc}
*/
protected function setOptionDefaults(array &$storage, array $options): void {
parent::setOptionDefaults($storage, $options);
// For this filter, it is only effective if it is exposed, and cannot
// be required.
if (isset($storage['exposed'])) {
$storage['exposed'] = TRUE;
$storage['expose']['required'] = FALSE;
$storage['expose']['multiple'] = FALSE;
}
}
/**
* {@inheritdoc}
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state): void {
parent::buildOptionsForm($form, $form_state);
$form['expose_button']['#access'] = FALSE;
$form['expose']['required']['#access'] = FALSE;
$form['expose']['multiple']['#access'] = FALSE;
$srcOptions = [];
foreach ($this->getIndex()->getDatasources() as $did => $datasource) {
$sourceDef = $datasource->getPluginDefinition();
$srcOptions[$did] = $sourceDef['label'] ?? $did;
}
// Generally use the value form to set this value, however, due to some
// views options form layout issues, create in the options form and
// reassign the value to the proper options value after submit.
$form['enabled_by_default'] = [
'#type' => 'checkbox',
'#title' => $this->t('Enable datasource by default'),
'#default_value' => $this->options['value'],
];
$form['search_api_datasource'] = [
'#type' => 'select',
'#title' => $this->t('Datasource to toggle'),
'#required' => TRUE,
'#options' => $srcOptions,
'#default_value' => $this->options['search_api_datasource'],
];
}
/**
* {@inheritdoc}
*/
public function submitOptionsForm(&$form, FormStateInterface $form_state): void {
parent::submitOptionsForm($form, $form_state);
$this->options['value'] = $form_state->getValue([
'options',
'enabled_by_default',
]);
}
/**
* {@inheritdoc}
*/
public function query(): void {
$datasource = $this->options['search_api_datasource'] ?? NULL;
if ($this->value || !$datasource) {
return;
}
$group = $this->options['group'];
$field = "{$this->tableAlias}.{$this->realField}";
$this->ensureMyTable();
$this->getQuery()->addWhere($group, $field, $datasource, '<>');
}
}
