Problem/Motivation

The "moderation_state_filter" views filter defined in "core/modules/content_moderation/src/Plugin/views/filter/ModerationStateFilter.php" does not correctly join the entity's base table when the views filter is using a views relationship that relates the entity's revision data table.
Relate code in "ModerationStateFilter::opSimple()":

        $entity_base_table_alias = $this->relationship ?: $this->table;

        // The bundle field of an entity type is not revisionable so we need to
        // join the base table.
        $entity_base_table = $entity_type->getBaseTable();
        $entity_revision_base_table = $entity_type->isTranslatable() ? $entity_type->getRevisionDataTable() : $entity_type->getRevisionTable();
        if ($this->table === $entity_revision_base_table) {
          $configuration = [
            'table' => $entity_base_table,
            'field' => $entity_type->getKey('id'),
            'left_table' => $entity_revision_base_table,
            'left_field' => $entity_type->getKey('id'),
            'type' => 'INNER',
          ];

          $join = Views::pluginManager('join')->createInstance('standard', $configuration);
          $entity_base_table_alias = $this->query->addRelationship($entity_base_table, $join, $entity_revision_base_table);
        }

BUG: Using the 'left_table' as $entity_revision_base_table only works if the view's base table is the entity's revision base table, example "node_field_revision".
This bug results in the following error and WSOD:

Warning: Trying to access array offset on value of type null in Drupal\views\Plugin\views\join\JoinPluginBase->buildJoin() (line 311 of {WEBROOT]/core/modules/views/src/Plugin/views/join/JoinPluginBase.php) 

The 'left_table' should be $entity_base_table_alias which is the $this->relationship or the $this->table, which at this point $this->table is $entity_revision_base_table.

Currently, there is no test coverage for this bug. The current "Drupal\Tests\content_moderation\Kernel\ViewsModerationStateFilterTest" uses a "node_field_data" relationship so it will not test the code within if ($this->table === $entity_revision_base_table) {.

Steps to reproduce

  1. Using a hook_views_data_alter, add a view relationship for the views data of a table that can join to the entity's revision data table. Example: A new relationship from "user_field_data.uid" to "node_field_revision.uid").
  2. Create a view for the User
  3. Add the new relationship to relate the "node_field_revision".
  4. Add an exposed views filter for "Moderation State" that uses the relationship for the "node_field_revision".
  5. Add a page display with a path
  6. Save the view.
  7. View the page for this view.
  8. Select "Draft" for the Moderation State filter
  9. Submit the views form
  10. RESULT: BUG - WSOD with a log message of "Warning: Trying to access array offset on value of type null in Drupal\views\Plugin\views\join\JoinPluginBase->buildJoin() (line 311 ..."

Proposed resolution

The 'left_table' should be $entity_base_table_alias which is the $this->relationship or the $this->table, which at this point $this->table is $entity_revision_base_table.

Remaining tasks

None

User interface changes

None

API changes

None

Data model changes

None

Release notes snippet

TBD

Issue fork drupal-3396741

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

recrit created an issue. See original summary.

recrit’s picture

The attached "3396741-moderation_state_filter-11.x-2.patch" changes the 'left_table' to use "$entity_base_table_alias" and uses the same in the "addRelationship()".

The attached "3396741-moderation_state_filter-11.x-2--tests-only.patch" should fail. This only includes the new tests in order to demonstrate the bug.

recrit’s picture

Status: Active » Needs review
recrit’s picture

StatusFileSize
new14.91 KB
new1.55 KB

Added a new $entity_revision_base_table_alias to avoid semantics with the $entity_base_table_alias being used for the actual base table join.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Was tough to verify think I saw the issue following the steps. Also the test case think shows the issue.

Patch #4 seemed to solve the problem.

needs-review-queue-bot’s picture

Status: Reviewed & tested by the community » Needs work

The Needs Review Queue Bot tested this issue.

While you are making the above changes, we recommend that you convert this patch to a merge request. Merge requests are preferred over patches. Be sure to hide the old patch files as well. (Converting an issue to a merge request without other contributions to the issue will not receive credit.)

recrit’s picture

Status: Needs work » Reviewed & tested by the community

Converted patches to an MR - https://git.drupalcode.org/project/drupal/-/merge_requests/5381.
Moving back to "Reviewed & tested by the community"

  • catch committed 98882c4f on 10.2.x
    Issue #3396741 by recrit, smustgrave: Content Moderation...

  • catch committed 87bc567b on 10.3.x
    Issue #3396741 by recrit, smustgrave: Content Moderation...

  • catch committed f742d155 on 11.x
    Issue #3396741 by recrit, smustgrave: Content Moderation...
catch’s picture

Version: 11.x-dev » 10.2.x-dev
Status: Reviewed & tested by the community » Fixed

Committed/pushed to 11.x, cherry-picked to 10.3.x and 10.2.x, thanks!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.