diff --git a/core/modules/node/lib/Drupal/node/Plugin/Search/NodeSearch.php b/core/modules/node/lib/Drupal/node/Plugin/Search/NodeSearch.php index 560c772..a2064a5 100644 --- a/core/modules/node/lib/Drupal/node/Plugin/Search/NodeSearch.php +++ b/core/modules/node/lib/Drupal/node/Plugin/Search/NodeSearch.php @@ -79,7 +79,7 @@ class NodeSearch extends SearchPluginBase implements AccessibleInterface, Search /** * The list of options and info for advanced search filters. - * + * * Each entry in the array has the option as key and and info array that * determines how the value is matched in the databse query. The possible keys * in the info array are: @@ -87,14 +87,14 @@ class NodeSearch extends SearchPluginBase implements AccessibleInterface, Search * - join: (optional) information on a table to join. By default the data * is matched against the {node_field_data} table. * - operator: (optional) OR or AND, defaults to OR - * + * * @var array */ protected $advanced = array( 'type' => array('column' => 'n.type'), 'langcode' => array('column' => 'n.langcode'), 'author' => array('column' => 'n.uid'), - 'term', array('column' => 'ti.tid', 'join' => array('table' => 'taxonomy_index', 'alias' => 'ti', 'condition' => 'n.nid = ti.nid')), + 'term' => array('column' => 'ti.tid', 'join' => array('table' => 'taxonomy_index', 'alias' => 'ti', 'condition' => 'n.nid = ti.nid')), ); /** @@ -172,34 +172,30 @@ public function execute() { ->addTag('node_access') ->searchExpression($keys, $this->getPluginId()); + // Handle advanced search filters in the f query string. $parameters = $this->getParameters(); - // Combine the f query strings into one string to simplify matching by - // field and combining each field into one condition clause. The - // $parameters['f'] variable is expected to be an array of options and - // values separated by a ':' like - // array('type:page', 'term:27', 'term:13', 'langcode:en') - // so $f is a string of such values like - // 'type:page term:27 term:13 langcode:en' - // and using preg_match_all() for each option in the pattern collects all - // the values that need to be added to a single condition object. - $f = !empty($parameters['f']) ? implode(' ', (array) $parameters['f']) : ''; - if ($f) { - $found = array(); - foreach ($this->advanced as $option => $info) { - $matches = array(); - $pattern = '/(^| )' . $option . ':([^ ]*)( |$)/i'; - if (preg_match_all($pattern, $f, $matches)) { - $found[$option] = $matches[2]; - // Insert additional conditions. By default, all use the OR operator. - $operator = empty($info['operator']) ? 'OR' : $info['operator']; - $where = new Condition($operator); - foreach ($matches[2] as $value) { - $where->condition($info['column'], $value); - } - $query->condition($where); - if (!empty($info['join'])) { - $query->join($info['join']['table'], $info['join']['alias'], $info['join']['condition']); - } + if (!empty($parameters['f']) && is_array($parameters['f'])) { + $filters = array(); + // Match any query value that is an expected option and a value + // separated by ':' like 'term:27'. + $pattern = '/(' . implode('|', array_keys($this->advanced)) . '):([^ ]*)/i'; + foreach ($parameters['f'] as $item) { + if (preg_match($pattern, $item, $m)) { + // Use the matched value as the array key to eliminate duplicates. + $filters[$m[1]][$m[2]] = $m[2]; + } + } + foreach ($filters as $option => $matched) { + $info = $this->advanced[$option]; + // Insert additional conditions. By default, all use the OR operator. + $operator = empty($info['operator']) ? 'OR' : $info['operator']; + $where = new Condition($operator); + foreach ($matched as $value) { + $where->condition($info['column'], $value); + } + $query->condition($where); + if (!empty($info['join'])) { + $query->join($info['join']['table'], $info['join']['alias'], $info['join']['condition']); } } }