View source
<?php
namespace Drupal\search\Plugin\views\filter;
use Drupal\Core\Form\FormStateInterface;
use Drupal\views\Plugin\views\filter\FilterPluginBase;
use Drupal\views\Plugin\views\display\DisplayPluginBase;
use Drupal\views\ViewExecutable;
use Drupal\views\Views;
class Search extends FilterPluginBase {
protected $alwaysMultiple = TRUE;
protected $searchQuery = NULL;
protected $parsed = FALSE;
protected $searchType;
public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
parent::init($view, $display, $options);
$this->searchType = $this->definition['search_type'];
}
protected function defineOptions() {
$options = parent::defineOptions();
$options['operator']['default'] = 'optional';
return $options;
}
protected function operatorForm(&$form, FormStateInterface $form_state) {
$form['operator'] = array(
'#type' => 'radios',
'#title' => $this
->t('On empty input'),
'#default_value' => $this->operator,
'#options' => array(
'optional' => $this
->t('Show All'),
'required' => $this
->t('Show None'),
),
);
}
protected function valueForm(&$form, FormStateInterface $form_state) {
$form['value'] = array(
'#type' => 'textfield',
'#size' => 15,
'#default_value' => $this->value,
'#attributes' => array(
'title' => $this
->t('Search keywords'),
),
'#title' => !$form_state
->get('exposed') ? $this
->t('Keywords') : '',
);
}
public function validateExposed(&$form, FormStateInterface $form_state) {
if (!isset($this->options['expose']['identifier'])) {
return;
}
$key = $this->options['expose']['identifier'];
if (!$form_state
->isValueEmpty($key)) {
$this
->queryParseSearchExpression($form_state
->getValue($key));
if (count($this->searchQuery
->words()) == 0) {
$form_state
->setErrorByName($key, $this
->formatPlural(\Drupal::config('search.settings')
->get('index.minimum_word_size'), 'You must include at least one keyword to match in the content, and punctuation is ignored.', 'You must include at least one keyword to match in the content. Keywords must be at least @count characters, and punctuation is ignored.'));
}
}
}
protected function queryParseSearchExpression($input) {
if (!isset($this->searchQuery)) {
$this->parsed = TRUE;
$this->searchQuery = db_select('search_index', 'i', array(
'target' => 'replica',
))
->extend('Drupal\\search\\ViewsSearchQuery');
$this->searchQuery
->searchExpression($input, $this->searchType);
$this->searchQuery
->publicParseSearchExpression();
}
}
public function query() {
if (!$this->parsed) {
$this
->queryParseSearchExpression($this->value);
}
$required = FALSE;
if (!isset($this->searchQuery)) {
$required = TRUE;
}
else {
$words = $this->searchQuery
->words();
if (empty($words)) {
$required = TRUE;
}
}
if ($required) {
if ($this->operator == 'required') {
$this->query
->addWhere($this->options['group'], 'FALSE');
}
}
else {
$search_index = $this
->ensureMyTable();
$search_condition = db_and();
$definition = array(
'table' => 'search_total',
'field' => 'word',
'left_table' => $search_index,
'left_field' => 'word',
);
$join = Views::pluginManager('join')
->createInstance('standard', $definition);
$search_total = $this->query
->addRelationship('search_total', $join, $search_index);
$this->search_score = $this->query
->addField('', "{$search_index}.score * {$search_total}.count", 'score', array(
'function' => 'sum',
));
$search_condition
->condition("{$search_index}.type", $this->searchType);
$search_dataset = $this->query
->addTable('node_search_dataset');
$conditions = $this->searchQuery
->conditions();
$condition_conditions =& $conditions
->conditions();
foreach ($condition_conditions as $key => &$condition) {
if (is_numeric($key)) {
$this->searchQuery
->conditionReplaceString('d.', "{$search_dataset}.", $condition);
}
}
$search_conditions =& $search_condition
->conditions();
$search_conditions = array_merge($search_conditions, $condition_conditions);
$or = db_or();
foreach ($words as $word) {
$or
->condition("{$search_index}.word", $word);
}
$search_condition
->condition($or);
$this->query
->addWhere($this->options['group'], $search_condition);
$this->query
->addGroupBy("{$search_index}.sid");
$matches = $this->searchQuery
->matches();
$placeholder = $this
->placeholder();
$this->query
->addHavingExpression($this->options['group'], "COUNT(*) >= {$placeholder}", array(
$placeholder => $matches,
));
}
$this->searchQuery = NULL;
}
}