Issue #2459407 by jhodgdon, jhedstrom: SQL syntax error when using the search_keywords filter or argument
parent
2847b5980b
commit
bc23d0119a
|
@ -378,8 +378,9 @@ class NodeViewsData extends EntityViewsData {
|
||||||
);
|
);
|
||||||
|
|
||||||
$data['node_search_dataset']['table']['join'] = array(
|
$data['node_search_dataset']['table']['join'] = array(
|
||||||
'node_search_index' => array(
|
'node_field_data' => array(
|
||||||
'left_field' => 'sid',
|
'left_field' => 'sid',
|
||||||
|
'left_table' => 'node_search_index',
|
||||||
'field' => 'sid',
|
'field' => 'sid',
|
||||||
'table' => 'search_dataset',
|
'table' => 'search_dataset',
|
||||||
'extra' => 'node_search_index.type = node_search_dataset.type AND node_search_index.langcode = node_search_dataset.langcode',
|
'extra' => 'node_search_index.type = node_search_dataset.type AND node_search_index.langcode = node_search_dataset.langcode',
|
||||||
|
|
|
@ -93,12 +93,11 @@ class Search extends ArgumentPluginBase {
|
||||||
$join = Views::pluginManager('join')->createInstance('standard', $definition);
|
$join = Views::pluginManager('join')->createInstance('standard', $definition);
|
||||||
$search_total = $this->query->addRelationship('search_total', $join, $search_index);
|
$search_total = $this->query->addRelationship('search_total', $join, $search_index);
|
||||||
|
|
||||||
$this->search_score = $this->query->addField('', "SUM($search_index.score * $search_total.count)", 'score', array('aggregate' => TRUE));
|
$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_condition->condition("$search_index.type", $this->searchType);
|
||||||
|
|
||||||
if (!$this->searchQuery->simple()) {
|
$search_dataset = $this->query->addTable('node_search_dataset');
|
||||||
$search_dataset = $this->query->addTable('search_dataset');
|
|
||||||
$conditions = $this->searchQuery->conditions();
|
$conditions = $this->searchQuery->conditions();
|
||||||
$condition_conditions =& $conditions->conditions();
|
$condition_conditions =& $conditions->conditions();
|
||||||
foreach ($condition_conditions as $key => &$condition) {
|
foreach ($condition_conditions as $key => &$condition) {
|
||||||
|
@ -110,16 +109,6 @@ class Search extends ArgumentPluginBase {
|
||||||
}
|
}
|
||||||
$search_conditions =& $search_condition->conditions();
|
$search_conditions =& $search_condition->conditions();
|
||||||
$search_conditions = array_merge($search_conditions, $condition_conditions);
|
$search_conditions = array_merge($search_conditions, $condition_conditions);
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Stores each condition, so and/or on the filter level will still work.
|
|
||||||
$or = db_or();
|
|
||||||
foreach ($words as $word) {
|
|
||||||
$or->condition("$search_index.word", $word);
|
|
||||||
}
|
|
||||||
|
|
||||||
$search_condition->condition($or);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->query->addWhere(0, $search_condition);
|
$this->query->addWhere(0, $search_condition);
|
||||||
$this->query->addGroupBy("$search_index.sid");
|
$this->query->addGroupBy("$search_index.sid");
|
||||||
|
|
|
@ -169,11 +169,10 @@ class Search extends FilterPluginBase {
|
||||||
|
|
||||||
$search_total = $this->query->addRelationship('search_total', $join, $search_index);
|
$search_total = $this->query->addRelationship('search_total', $join, $search_index);
|
||||||
|
|
||||||
$this->search_score = $this->query->addField('', "SUM($search_index.score * $search_total.count)", 'score', array('aggregate' => TRUE));
|
$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_condition->condition("$search_index.type", $this->searchType);
|
||||||
if (!$this->searchQuery->simple()) {
|
$search_dataset = $this->query->addTable('node_search_dataset');
|
||||||
$search_dataset = $this->query->addTable('search_dataset');
|
|
||||||
$conditions = $this->searchQuery->conditions();
|
$conditions = $this->searchQuery->conditions();
|
||||||
$condition_conditions =& $conditions->conditions();
|
$condition_conditions =& $conditions->conditions();
|
||||||
foreach ($condition_conditions as $key => &$condition) {
|
foreach ($condition_conditions as $key => &$condition) {
|
||||||
|
@ -185,16 +184,6 @@ class Search extends FilterPluginBase {
|
||||||
}
|
}
|
||||||
$search_conditions =& $search_condition->conditions();
|
$search_conditions =& $search_condition->conditions();
|
||||||
$search_conditions = array_merge($search_conditions, $condition_conditions);
|
$search_conditions = array_merge($search_conditions, $condition_conditions);
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Stores each condition, so and/or on the filter level will still work.
|
|
||||||
$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->addWhere($this->options['group'], $search_condition);
|
||||||
$this->query->addGroupBy("$search_index.sid");
|
$this->query->addGroupBy("$search_index.sid");
|
||||||
|
|
|
@ -722,7 +722,11 @@ class Sql extends QueryPluginBase {
|
||||||
* alias be used.
|
* alias be used.
|
||||||
* @param $params
|
* @param $params
|
||||||
* An array of parameters additional to the field that will control items
|
* An array of parameters additional to the field that will control items
|
||||||
* such as aggregation functions and DISTINCT.
|
* such as aggregation functions and DISTINCT. Some values that are
|
||||||
|
* recognized:
|
||||||
|
* - function: An aggregation function to apply, such as SUM.
|
||||||
|
* - aggregate: Set to TRUE to indicate that this value should be
|
||||||
|
* aggregated in a GROUP BY.
|
||||||
*
|
*
|
||||||
* @return $name
|
* @return $name
|
||||||
* The name that this field can be referred to as. Usually this is the alias.
|
* The name that this field can be referred to as. Usually this is the alias.
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
namespace Drupal\views\Tests;
|
namespace Drupal\views\Tests;
|
||||||
|
|
||||||
|
use Drupal\Component\Utility\SafeMarkup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests search integration filters.
|
* Tests search integration filters.
|
||||||
*
|
*
|
||||||
|
@ -35,8 +37,9 @@ class SearchIntegrationTest extends ViewTestBase {
|
||||||
// Create a content type.
|
// Create a content type.
|
||||||
$type = $this->drupalCreateContentType();
|
$type = $this->drupalCreateContentType();
|
||||||
|
|
||||||
// Add two nodes, one containing the word "pizza" and the other
|
// Add three nodes, one containing the word "pizza", one containing
|
||||||
// with the word "sandwich". Make the second node link to the first.
|
// "sandwich", and one containing "cola is good with pizza". Make the
|
||||||
|
// second node link to the first.
|
||||||
$node['title'] = 'pizza';
|
$node['title'] = 'pizza';
|
||||||
$node['body'] = array(array('value' => 'pizza'));
|
$node['body'] = array(array('value' => 'pizza'));
|
||||||
$node['type'] = $type->id();
|
$node['type'] = $type->id();
|
||||||
|
@ -49,6 +52,11 @@ class SearchIntegrationTest extends ViewTestBase {
|
||||||
$node['body'] = array(array('value' => 'sandwich with a <a href="' . $node_url . '">link to first node</a>'));
|
$node['body'] = array(array('value' => 'sandwich with a <a href="' . $node_url . '">link to first node</a>'));
|
||||||
$this->drupalCreateNode($node);
|
$this->drupalCreateNode($node);
|
||||||
|
|
||||||
|
$node['title'] = 'cola';
|
||||||
|
$node['body'] = array(array('value' => 'cola is good with pizza'));
|
||||||
|
$node['type'] = $type->id();
|
||||||
|
$this->drupalCreateNode($node);
|
||||||
|
|
||||||
// Run cron so that the search index tables are updated.
|
// Run cron so that the search index tables are updated.
|
||||||
$this->cronRun();
|
$this->cronRun();
|
||||||
|
|
||||||
|
@ -58,17 +66,56 @@ class SearchIntegrationTest extends ViewTestBase {
|
||||||
|
|
||||||
// Page with a keyword filter of 'pizza'.
|
// Page with a keyword filter of 'pizza'.
|
||||||
$this->drupalGet('test-filter');
|
$this->drupalGet('test-filter');
|
||||||
$this->assertLink('pizza', 0, 'Pizza page is on Filter page');
|
$this->assertLink('pizza');
|
||||||
$this->assertNoLink('sandwich', 'Sandwich page is not on Filter page');
|
$this->assertNoLink('sandwich');
|
||||||
|
$this->assertLink('cola');
|
||||||
|
|
||||||
// Page with a keyword argument.
|
// Page with a keyword argument, various argument values.
|
||||||
|
// Verify that the correct nodes are shown, and only once.
|
||||||
$this->drupalGet('test-arg/pizza');
|
$this->drupalGet('test-arg/pizza');
|
||||||
$this->assertLink('pizza', 0, 'Pizza page is on argument page');
|
$this->assertOneLink('pizza');
|
||||||
$this->assertNoLink('sandwich', 'Sandwich page is not on argument page');
|
$this->assertNoLink('sandwich');
|
||||||
|
$this->assertOneLink('cola');
|
||||||
|
|
||||||
$this->drupalGet('test-arg/sandwich');
|
$this->drupalGet('test-arg/sandwich');
|
||||||
$this->assertNoLink('pizza', 'Pizza page is not on argument page');
|
$this->assertNoLink('pizza');
|
||||||
$this->assertLink('sandwich', 0, 'Sandwich page is on argument page');
|
$this->assertOneLink('sandwich');
|
||||||
|
$this->assertNoLink('cola');
|
||||||
|
|
||||||
|
$this->drupalGet('test-arg/pizza OR sandwich');
|
||||||
|
$this->assertOneLink('pizza');
|
||||||
|
$this->assertOneLink('sandwich');
|
||||||
|
$this->assertOneLink('cola');
|
||||||
|
|
||||||
|
$this->drupalGet('test-arg/pizza sandwich OR cola');
|
||||||
|
$this->assertNoLink('pizza');
|
||||||
|
$this->assertNoLink('sandwich');
|
||||||
|
$this->assertOneLink('cola');
|
||||||
|
|
||||||
|
$this->drupalGet('test-arg/cola pizza');
|
||||||
|
$this->assertNoLink('pizza');
|
||||||
|
$this->assertNoLink('sandwich');
|
||||||
|
$this->assertOneLink('cola');
|
||||||
|
|
||||||
|
$this->drupalGet('test-arg/"cola is good"');
|
||||||
|
$this->assertNoLink('pizza');
|
||||||
|
$this->assertNoLink('sandwich');
|
||||||
|
$this->assertOneLink('cola');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that exactly one link exists with the given text.
|
||||||
|
*
|
||||||
|
* @param string $label
|
||||||
|
* Link label to assert.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* TRUE if the assertion succeeded, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
protected function assertOneLink($label) {
|
||||||
|
$links = $this->xpath('//a[normalize-space(text())=:label]', array(':label' => $label));
|
||||||
|
$message = SafeMarkup::format('Link with label %label found once.', array('%label' => $label));
|
||||||
|
return $this->assert(isset($links[0]) && !isset($links[1]), $message);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue