82afbbfe6ad2c0f6f2ec09d67af4c26f54ac9d5d
[yaffs-website] / web / core / modules / search / src / Plugin / views / argument / Search.php
1 <?php
2
3 namespace Drupal\search\Plugin\views\argument;
4
5 use Drupal\views\Plugin\views\argument\ArgumentPluginBase;
6 use Drupal\views\Plugin\views\display\DisplayPluginBase;
7 use Drupal\views\ViewExecutable;
8 use Drupal\views\Views;
9
10 /**
11  * Argument handler for search keywords.
12  *
13  * @ingroup views_argument_handlers
14  *
15  * @ViewsArgument("search")
16  */
17 class Search extends ArgumentPluginBase {
18
19   /**
20    * A search query to use for parsing search keywords.
21    *
22    * @var \Drupal\search\ViewsSearchQuery
23    */
24   protected $searchQuery = NULL;
25
26   /**
27    * The search type name (value of {search_index}.type in the database).
28    *
29    * @var string
30    */
31   protected $searchType;
32
33   /**
34    * {@inheritdoc}
35    */
36   public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
37     parent::init($view, $display, $options);
38
39     $this->searchType = $this->definition['search_type'];
40   }
41
42   /**
43    * Sets up and parses the search query.
44    *
45    * @param string $input
46    *   The search keywords entered by the user.
47    */
48   protected function queryParseSearchExpression($input) {
49     if (!isset($this->searchQuery)) {
50       $this->searchQuery = db_select('search_index', 'i', ['target' => 'replica'])->extend('Drupal\search\ViewsSearchQuery');
51       $this->searchQuery->searchExpression($input, $this->searchType);
52       $this->searchQuery->publicParseSearchExpression();
53     }
54   }
55
56   /**
57    * {@inheritdoc}
58    */
59   public function query($group_by = FALSE) {
60     $required = FALSE;
61     $this->queryParseSearchExpression($this->argument);
62     if (!isset($this->searchQuery)) {
63       $required = TRUE;
64     }
65     else {
66       $words = $this->searchQuery->words();
67       if (empty($words)) {
68         $required = TRUE;
69       }
70     }
71     if ($required) {
72       if ($this->operator == 'required') {
73         $this->query->addWhere(0, 'FALSE');
74       }
75     }
76     else {
77       $search_index = $this->ensureMyTable();
78
79       $search_condition = db_and();
80
81       // Create a new join to relate the 'search_total' table to our current 'search_index' table.
82       $definition = [
83         'table' => 'search_total',
84         'field' => 'word',
85         'left_table' => $search_index,
86         'left_field' => 'word',
87       ];
88       $join = Views::pluginManager('join')->createInstance('standard', $definition);
89       $search_total = $this->query->addRelationship('search_total', $join, $search_index);
90
91       // Add the search score field to the query.
92       $this->search_score = $this->query->addField('', "$search_index.score * $search_total.count", 'score', ['function' => 'sum']);
93
94       // Add the conditions set up by the search query to the views query.
95       $search_condition->condition("$search_index.type", $this->searchType);
96       $search_dataset = $this->query->addTable('node_search_dataset');
97       $conditions = $this->searchQuery->conditions();
98       $condition_conditions =& $conditions->conditions();
99       foreach ($condition_conditions  as $key => &$condition) {
100         // Make sure we just look at real conditions.
101         if (is_numeric($key)) {
102           // Replace the conditions with the table alias of views.
103           $this->searchQuery->conditionReplaceString('d.', "$search_dataset.", $condition);
104         }
105       }
106       $search_conditions =& $search_condition->conditions();
107       $search_conditions = array_merge($search_conditions, $condition_conditions);
108
109       // Add the keyword conditions, as is done in
110       // SearchQuery::prepareAndNormalize(), but simplified because we are
111       // only concerned with relevance ranking so we do not need to normalize.
112       $or = db_or();
113       foreach ($words as $word) {
114         $or->condition("$search_index.word", $word);
115       }
116       $search_condition->condition($or);
117
118       // Add the GROUP BY and HAVING expressions to the query.
119       $this->query->addWhere(0, $search_condition);
120       $this->query->addGroupBy("$search_index.sid");
121       $matches = $this->searchQuery->matches();
122       $placeholder = $this->placeholder();
123       $this->query->addHavingExpression(0, "COUNT(*) >= $placeholder", [$placeholder => $matches]);
124     }
125
126     // Set to NULL to prevent PDO exception when views object is cached
127     // and to clear out memory.
128     $this->searchQuery = NULL;
129   }
130
131 }