Commit 4ed33dc1 authored by catch's avatar catch
Browse files

Issue #2997748 by amateescu, maseyuk, vijaycs85, daffie: Views query alter for...

Issue #2997748 by amateescu, maseyuk, vijaycs85, daffie: Views query alter for fields stored in dedicated tables is not working properly
parent c609c06b
......@@ -37,6 +37,30 @@
* Note that the default join type is a LEFT join when 'type' is not supplied in
* the join plugin configuration.
*
* If an SQL expression is needed for the first part of the left table join
* condition, 'left_formula' can be used instead of 'left_field'.
* For this SQL:
* @code
* LEFT JOIN {two} ON MAX(one.field_a) = two.field_b AND one.field_c = 'some_val'
* @endcode
* Use this configuration:
* @code
* $configuration = array(
* 'table' => 'two',
* 'field' => 'field_b',
* 'left_table' => 'one',
* 'left_formula' => 'MAX(one.field_a)',
* 'operator' => '=',
* 'extra' => array(
* 0 => array(
* 'left_field' => 'field_c',
* 'value' => 'some_val',
* ),
* ),
* );
* $join = Views::pluginManager('join')->createInstance('standard', $configuration);
* @endcode
*
* For this SQL:
* @code
* INNER JOIN {two} ON one.field_a = two.field_b AND one.field_c = 'some_val'
......@@ -156,6 +180,13 @@ class JoinPluginBase extends PluginBase implements JoinPluginInterface {
*/
public $leftField;
/**
* A formula to be used instead of the left field.
*
* @var string
*/
public $leftFormula;
/**
* An array of extra conditions on the join.
*
......@@ -238,6 +269,10 @@ public function __construct(array $configuration, $plugin_id, $plugin_definition
$this->leftField = $configuration['left_field'];
$this->field = $configuration['field'];
if (!empty($configuration['left_formula'])) {
$this->leftFormula = $configuration['left_formula'];
}
if (!empty($configuration['extra'])) {
$this->extra = $configuration['extra'];
}
......@@ -263,7 +298,7 @@ public function buildJoin($select_query, $table, $view_query) {
if ($this->leftTable) {
$left_table = $view_query->getTableInfo($this->leftTable);
$left_field = "$left_table[alias].$this->leftField";
$left_field = $this->leftFormula ?: "$left_table[alias].$this->leftField";
}
else {
// This can be used if left_field is a formula or something. It should be used only *very* rarely.
......
......@@ -202,6 +202,20 @@ public function testBasePlugin() {
$this->assertTrue(strpos($join_info['condition'], "views_test_data.status = :views_join_condition_5") !== FALSE, 'Make sure the second extra join condition appears in the query.');
$this->assertTrue(strpos($join_info['condition'], "users5.name = views_test_data.name") !== FALSE, 'Make sure the third extra join condition appears in the query.');
$this->assertEqual(array_values($join_info['arguments']), ['en', 0], 'Make sure the arguments are in the right order');
// Test that joins using 'left_formula' are properly built.
$configuration['left_formula'] = 'MAX(views_test_data.uid)';
$join = $this->manager->createInstance('standard', $configuration);
$table = ['alias' => 'users6'];
$join->buildJoin($query, $table, $view->query);
$tables = $query->getTables();
$join_info = $tables['users6'];
$this->assertTrue(strpos($join_info['condition'], "MAX(views_test_data.uid) = users6.uid") !== FALSE, 'Make sure the join condition appears in the query.');
$this->assertTrue(strpos($join_info['condition'], "users6.langcode = :views_join_condition_7") !== FALSE, 'Make sure the first extra join condition appears in the query.');
$this->assertTrue(strpos($join_info['condition'], "views_test_data.status = :views_join_condition_8") !== FALSE, 'Make sure the second extra join condition appears in the query.');
$this->assertTrue(strpos($join_info['condition'], "users6.name = views_test_data.name") !== FALSE, 'Make sure the third extra join condition appears in the query.');
$this->assertEqual(array_values($join_info['arguments']), ['en', 0], 'Make sure the arguments are in the right order');
}
}
......@@ -187,8 +187,7 @@ protected function alterQueryForEntityType(Sql $query, EntityTypeInterface $enti
// Update the join to use our COALESCE.
$revision_field = $entity_type->getKey('revision');
$table_info['join']->leftTable = NULL;
$table_info['join']->leftField = "COALESCE($workspace_association_table.target_entity_revision_id, $relationship.$revision_field)";
$table_info['join']->leftFormula = "COALESCE($workspace_association_table.target_entity_revision_id, $relationship.$revision_field)";
// Update the join and the table info to our new table name, and to join
// on the revision key.
......
......@@ -101,8 +101,8 @@ protected function setUp(): void {
// Create two nodes, a published and an unpublished one, so we can test the
// behavior of the module with default/existing content.
$this->createdTimestamp = \Drupal::time()->getRequestTime();
$this->nodes[] = $this->createNode(['title' => 'live - 1 - r1 - published', 'created' => $this->createdTimestamp++, 'status' => TRUE]);
$this->nodes[] = $this->createNode(['title' => 'live - 2 - r2 - unpublished', 'created' => $this->createdTimestamp++, 'status' => FALSE]);
$this->nodes[] = $this->createNode(['title' => 'live - 1 - r1 - published', 'body' => 'node 1', 'created' => $this->createdTimestamp++, 'status' => TRUE]);
$this->nodes[] = $this->createNode(['title' => 'live - 2 - r2 - unpublished', 'body' => 'node 2', 'created' => $this->createdTimestamp++, 'status' => FALSE]);
$translation = $this->nodes[0]->addTranslation('de');
$translation->setTitle('live - 1 - r1 - published - de');
......@@ -794,6 +794,23 @@ protected function assertWorkspaceStatus(array $expected, $entity_type_id) {
$this->assertNoRaw($expected_entity_values[$entity_keys['label']]);
}
}
// Add a filter on a field that is stored in a dedicated table in order to
// test field joins with extra conditions (e.g. 'deleted' and 'langcode').
$view->destroy();
$view->setDisplay('page_1');
$filters = $view->displayHandlers->get('page_1')->getOption('filters');
$view->displayHandlers->get('page_1')->overrideOption('filters', $filters + [
'body_value' => [
'id' => 'body_value',
'table' => 'node__body',
'field' => 'body_value',
'operator' => 'not empty',
'plugin_id' => 'string',
],
]);
$view->execute();
$this->assertIdenticalResultset($view, $expected_frontpage, ['nid' => 'nid']);
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment