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
Loading
Loading
Loading
Loading
+36 −1
Original line number Diff line number Diff line
@@ -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.
+14 −0
Original line number Diff line number Diff line
@@ -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');
  }

}
+1 −2
Original line number Diff line number Diff line
@@ -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.
+19 −2
Original line number Diff line number Diff line
@@ -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']);
    }
  }