Commit 155a314b authored by alexpott's avatar alexpott

Issue #2378729 by jibran: JoinPluginBase doesn't allow extra conditions on left table

parent 0a301aa8
......@@ -21,8 +21,8 @@
* They must be annotated with \Drupal\views\Annotation\ViewsJoin annotation,
* and they must be in namespace directory Plugin\views\join.
*
* Here is an example of how to join from table one to table two so it produces
* the following SQL:
* Here are some examples of how to join from table one to table two so it
* produces the following SQL:
* @code
* INNER JOIN {two} ON one.field_a = two.field_b
* @endcode
......@@ -33,7 +33,67 @@
* 'field' => 'field_b',
* 'left_table' => 'one',
* 'left_field' => 'field_a',
* 'operator' => '='
* 'operator' => '=',
* );
* $join = Views::pluginManager('join')->createInstance('standard', $configuration);
* @endcode
* @code
* INNER JOIN {two} ON one.field_a = two.field_b AND one.field_c = 'some_val'
* @endcode
* The required php code for this kind of functionality is the following:
* @code
* $configuration = array(
* 'table' => 'two',
* 'field' => 'field_b',
* 'left_table' => 'one',
* 'left_field' => 'field_a',
* 'operator' => '=',
* 'extra' => array(
* 0 => array(
* 'left_field' => 'field_c',
* 'value' => 'some_val',
* ),
* ),
* );
* $join = Views::pluginManager('join')->createInstance('standard', $configuration);
* @endcode
* @code
* INNER JOIN {two} ON one.field_a = two.field_b AND two.field_d = 'other_val'
* @endcode
* The required php code for this kind of functionality is the following:
* @code
* $configuration = array(
* 'table' => 'two',
* 'field' => 'field_b',
* 'left_table' => 'one',
* 'left_field' => 'field_a',
* 'operator' => '=',
* 'extra' => array(
* 0 => array(
* 'field' => 'field_d',
* 'value' => 'other_val',
* ),
* ),
* );
* $join = Views::pluginManager('join')->createInstance('standard', $configuration);
* @endcode
* @code
* INNER JOIN {two} ON one.field_a = two.field_b AND one.field_c = two.field_d
* @endcode
* The required php code for this kind of functionality is the following:
* @code
* $configuration = array(
* 'table' => 'two',
* 'field' => 'field_b',
* 'left_table' => 'one',
* 'left_field' => 'field_a',
* 'operator' => '=',
* 'extra' => array(
* 0 => array(
* 'left_field' => 'field_c',
* 'field' => 'field_d',
* ),
* ),
* );
* $join = Views::pluginManager('join')->createInstance('standard', $configuration);
* @endcode
......@@ -98,6 +158,8 @@ class JoinPluginBase extends PluginBase implements JoinPluginInterface {
* existing alias. If you use realtime joins, it works better.
* - field(optional): Field or formula. In formulas we can reference the
* right table by using %alias.
* - left_field(optional): Field or formula. In formulas we can reference
* the left table by using %alias.
* - operator(optional): The operator used, Defaults to "=".
* - value: Must be set. If an array, operator will be defaulted to IN.
* - numeric: If true, the value will not be surrounded in quotes.
......@@ -257,18 +319,27 @@ public function buildJoin($select_query, $table, $view_query) {
else {
// With a single value, the '=' operator is implicit.
$operator = !empty($info['operator']) ? $info['operator'] : '=';
$placeholder = ':views_join_condition_' . $select_query->nextPlaceholder();
}
// Set 'field' as join table field if available or set 'left field' as
// join table field is not set.
if (isset($info['field'])) {
$join_table_field = "$join_table$info[field]";
// Allow the value to be set either with the 'value' element or
// with 'left_field'.
if (isset($info['left_field'])) {
$placeholder = "$left[alias].$info[left_field]";
}
else {
$placeholder = ':views_join_condition_' . $select_query->nextPlaceholder();
$arguments[$placeholder] = $info['value'];
}
}
$extras[] = "$join_table$info[field] $operator $placeholder";
// Set 'left field' as join table field is not set.
else {
$join_table_field = "$left[alias].$info[left_field]";
$arguments[$placeholder] = $info['value'];
}
$extras[] = "$join_table_field $operator $placeholder";
}
if ($extras) {
......
......@@ -149,6 +149,7 @@ public function testBasePlugin() {
$tables = $query->getTables();
$join_info = $tables['users3'];
$this->assertTrue(strpos($join_info['condition'], "views_test_data.uid = users3.uid") !== FALSE, 'Make sure the join condition appears in the query.');
$this->assertTrue(strpos($join_info['condition'], "users3.name = :views_join_condition_0") !== FALSE, 'Make sure the first extra join condition appears in the query and uses the first placeholder.');
$this->assertTrue(strpos($join_info['condition'], "users3.name <> :views_join_condition_1") !== FALSE, 'Make sure the second extra join condition appears in the query and uses the second placeholder.');
$this->assertEqual(array_values($join_info['arguments']), array($random_name_1, $random_name_2), 'Make sure the arguments are in the right order');
......@@ -174,7 +175,37 @@ public function testBasePlugin() {
$tables = $query->getTables();
$join_info = $tables['users4'];
$this->assertTrue(strpos($join_info['condition'], "views_test_data.uid = users4.uid") !== FALSE, 'Make sure the join condition appears in the query.');
$this->assertTrue(strpos($join_info['condition'], "users4.name = :views_join_condition_2") !== FALSE, 'Make sure the first extra join condition appears in the query.');
$this->assertTrue(strpos($join_info['condition'], "users4.name IN ( :views_join_condition_3, :views_join_condition_4, :views_join_condition_5 )") !== FALSE, 'The IN condition for the join is properly formed.');
// Test that all the conditions are properly built.
$configuration['extra'] = array(
array(
'field' => 'langcode',
'value' => 'en'
),
array(
'left_field' => 'status',
'value' => 0,
'numeric' => TRUE,
),
array(
'field' => 'name',
'left_field' => 'name'
),
);
$join = $this->manager->createInstance('standard', $configuration);
$table = array('alias' => 'users5');
$join->buildJoin($query, $table, $view->query);
$tables = $query->getTables();
$join_info = $tables['users5'];
$this->assertTrue(strpos($join_info['condition'], "views_test_data.uid = users5.uid") !== FALSE, 'Make sure the join condition appears in the query.');
$this->assertTrue(strpos($join_info['condition'], "users5.langcode = :views_join_condition_6") !== 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_7") !== 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']), array('en', 0), 'Make sure the arguments are in the right order');
}
}
......@@ -188,6 +188,28 @@ function hook_views_data() {
'left_field' => 'nid',
// Foreign key field in example_table to use in the join.
'field' => 'nid',
// An array of extra conditions on the join.
'extra' => array(
0 => array(
// Adds AND node.published = TRUE to the join.
'field' => 'published',
'value' => TRUE,
),
1 => array(
// Adds AND example_table.numeric_field = 1 to the join.
'left_field' => 'numeric_field',
'value' => 1,
// If true, the value will not be surrounded in quotes.
'numeric' => TRUE,
),
2 => array(
// Adds AND example_table.boolean_field <> node.published to the join.
'field' => 'published',
'left_field' => 'boolean_field',
// The operator used, Defaults to "=".
'operator' => '!=',
),
),
),
);
......
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