Problem/Motivation

There's no views sort handler for sorting on the moderation state field. In #2862041: Provide useful Views filters for Content Moderation State fields, a filter handler was added for filtering on moderation state. It would be useful to have this so results could be ordered by their current moderation state.

Steps to reproduce this:

  • Install content moderation.
  • Go to Content > Moderated content.
  • Click on the "Moderation state" column.
  • Exception should appear.

Proposed resolution

Add the appropriate handlers to make sorting work.

Remaining tasks

Review patch.

User interface changes

Fixes exception that bubbles up to the UI.

API changes

None.

Data model changes

None.

CommentFileSizeAuthor
#67 2953331-67.patch36.52 KBalexpott
#67 65-67-interdiff.txt1.99 KBalexpott
#65 2953331-65.patch36.37 KBManuel Garcia
#65 interdiff-2953331-56-65.txt2.44 KBManuel Garcia
#59 2953331-56.patch37.99 KBSam152
#57 2953331-56-d8_6_x.patch38.29 KBazinck
#56 2953331-56.patch37.99 KBManuel Garcia
#56 interdiff-2953331-54-56.txt3.32 KBManuel Garcia
#54 2953331-54.patch37.45 KBSam152
#48 2953331-48.patch37.51 KBSam152
#48 interdiff.txt1.88 KBSam152
#44 2953331-43.patch37.36 KBSam152
#37 2953331-37.patch59.17 KBSam152
#37 interdiff.txt2.41 KBSam152
#34 2953331-34.patch58.09 KBSam152
#34 interdiff.txt1.24 KBSam152
#32 2953331-32.patch57.72 KBSam152
#30 2953331-30.patch57.74 KBSam152
#23 2953331-23.patch57.95 KBSam152
#23 interdiff.txt1.67 KBSam152
#20 2953331-20.patch57.76 KBSam152
#20 interdiff.txt2.7 KBSam152
#18 interdiff.txt45.86 KBSam152
#18 2953331-18.patch57.06 KBSam152
#17 interdiff.txt26.36 KBSam152
#17 2953331-17.patch58.42 KBSam152
#10 2953331-10.patch32.06 KBSam152
#10 interdiff.txt677 bytesSam152
#7 2953331-6.patch31.92 KBSam152
#7 interdiff.txt625 bytesSam152
#5 2953331-5.patch31.91 KBSam152
#2 moderation.png9.4 KBanish.a
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

bkosborne created an issue. See original summary.

anish.a’s picture

FileSize
9.4 KB

Moderation

Assuming this is the issue. There is no table sorter for headers.

bkosborne’s picture

The issue is that there's no underlying support for any view to sort by the moderation state. RE: your screenshot, indeed, none of those headers are click-sortable, but that's not directly related to this issue.

steven.wichers’s picture

Workaround: Add a "Content moderation state" relationship to your view. Add a "Moderation state" field that uses the relationship. Enable the field overwrite functionality and use the output for the original moderation state field. Hide the original moderation state field.

This will give you a sortable moderation state column that uses the correct display label.

Sam152’s picture

Category: Feature request » Bug report
Issue summary: View changes
Status: Active » Needs review
FileSize
31.91 KB

Finally got around to addressing this. This patch:

  • Adds support for sorting on the field (exposed or otherwise).
  • Click sorting via the table display type.
  • Tests for both these types of sorting, with normal base table and the revision base table.

Status: Needs review » Needs work

The last submitted patch, 5: 2953331-5.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Sam152’s picture

Status: Needs work » Needs review
FileSize
625 bytes
31.92 KB

Fixing docblock.

amateescu’s picture

Status: Needs review » Reviewed & tested by the community

The patch looks great to me!

+++ b/core/modules/content_moderation/src/Plugin/views/field/ModerationStateField.php
@@ -0,0 +1,48 @@
+    $this->entityTypeManager = $entity_manager;

I was a bit unsure about this part, but we're only using the entityTypeManager property internally in ModerationStateJoinViewsHandlerTrait, so maybe it's ok to do it like this.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/content_moderation/src/Plugin/views/field/ModerationStateField.php
@@ -0,0 +1,48 @@
+    $this->entityTypeManager = $entity_manager;

This property is declared dynamically so it'll be public. We need to define it on this class - or somehow fix EntityField to use the specific entity manager services - which feels unlikely in this issue.

Sam152’s picture

Status: Needs work » Needs review
FileSize
677 bytes
32.06 KB

Thanks for the review, good catch.

Manuel Garcia’s picture

Just dropping by here out of curiosity, and because I think its a good idea :)

Patch is looking great, my only concern is this change:

+++ b/core/modules/content_moderation/src/ViewsData.php
@@ -79,11 +79,12 @@ public function getViewsData() {
-          'id' => 'field',
+          'id' => 'moderation_state_field',

@@ -103,11 +104,12 @@ public function getViewsData() {
-          'id' => 'field',
+          'id' => 'moderation_state_field',

Does this mean we need an upgrade path for existing views?

jibran’s picture

Status: Needs review » Needs work

Yes!

jibran’s picture

Tagging.

amateescu’s picture

+++ b/core/modules/content_moderation/src/Plugin/views/field/ModerationStateField.php
@@ -0,0 +1,55 @@
+   * The entity manager service.
+   *
+   * @var \Drupal\Core\Entity\EntityManagerInterface
+   */
+  protected $entityTypeManager;

The mismatch here makes me want to have the proper entity type service even more :/

Sam152’s picture

Yeah, I agree. Lets inject the proper service here in addition to looking into #11.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Sam152’s picture

Status: Needs work » Needs review
FileSize
58.42 KB
26.36 KB

Adding the upgrade path and tests for that.

Sam152’s picture

+++ b/core/modules/content_moderation/tests/fixtures/update/drupal-8.4.0-content_moderation_installed.php
@@ -31,6 +31,11 @@
+  ->values(array(
+    'collection' => '',
+    'name' => 'views.view.moderated_content',
...
+  ))

Realising why this view wasn't in the fixture originally: it was introduced in 8.5. To ensure the integrity of the 8.4 fixture, we should add this is another fixture.

Updating.

The last submitted patch, 17: 2953331-17.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Sam152’s picture

Addressing #14.

amateescu’s picture

The latest patch looks very good, I spotted just a couple of minor things:

  1. +++ b/core/modules/content_moderation/src/Plugin/views/field/ModerationStateField.php
    @@ -0,0 +1,74 @@
    +    // This could be derived from the content_moderation_state entity table
    +    // mapping, however this is an internal entity type whose storage should
    +    // remain constant.
    

    That's not necessarily true, for example the JSON entity storage could store the whole entity data in a single table column, so we should do to the right thing and get the column name from the table mapping :)

  2. +++ b/core/modules/content_moderation/tests/src/Functional/ModerationStateViewsFieldUpdateTest.php
    @@ -0,0 +1,41 @@
    + * @group legacy
    + * @see content_moderation_post_update_views_field_plugin_id
    

    Let's add an empty line between these, and append () to the post update function name :)

Sam152’s picture

Status: Needs review » Needs work

Good catch, thanks for the review.

Sam152’s picture

Status: Needs work » Needs review
FileSize
1.67 KB
57.95 KB

Addressing feedback from #21.

jibran’s picture

Status: Needs review » Reviewed & tested by the community

This looks ready to me.

amateescu’s picture

+1, looks good to me as well.

Manuel Garcia’s picture

Thanks @Sam152 - upgrade path & tests look good to me, RTBC++

Sam152’s picture

@jibran pinged me and made me aware of #2810485: Allow more maintainers to grant credit. He answered some questions for me in slack when I was writing the upgrade path, so granting request for credit here. Adding @amateescu, @Manuel Garcia and @alexpott for reviews while I'm at it.

The last submitted patch, 10: 2953331-10.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

larowlan’s picture

Issue tags: +Needs reroll
error: patch failed: core/modules/content_moderation/content_moderation.post_update.php:5
error: core/modules/content_moderation/content_moderation.post_update.php: patch does not apply

No longer applies :(

Sam152’s picture

Status: Reviewed & tested by the community » Needs review
Issue tags: -Needs reroll
FileSize
57.74 KB

Rerolling

Status: Needs review » Needs work

The last submitted patch, 30: 2953331-30.patch, failed testing. View results

Sam152’s picture

Status: Needs work » Needs review
FileSize
57.72 KB

Another reroll, this time with less syntax errors guaranteed!

Status: Needs review » Needs work

The last submitted patch, 32: 2953331-32.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Sam152’s picture

Status: Needs work » Needs review
FileSize
1.24 KB
58.09 KB

Adding a secondary sort criteria of the langcode. I think the two different language revisions were sorting inconsistently locally and on the bot when they had the same state name.

Status: Needs review » Needs work

The last submitted patch, 34: 2953331-34.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Sam152’s picture

Hm, it's possible views doesn't support secondary sort criteria mixed with exposed input. This will possibly make testing this in a flexible way tricky.

Sam152’s picture

Status: Needs work » Needs review
FileSize
2.41 KB
59.17 KB

After digging into this, I believe this is the only way to maintain the same level of test coverage with consistent builds.

Sam152’s picture

This was already RTBC before a reroll and the interdiff in #37 in case anyone is interested in reviewing the changes since then.

sorabh.v6’s picture

Status: Needs review » Needs work

Hi @Sam512,

I applied the patch in #37 and now I am able to sort the content using the state but when I did the drush updb, I got this error -

[error]  Class "ConfigEntityUpdater" does not exist.
 [error]  Update failed: content_moderation_post_update_views_field_plugin_id
 [error]  Update aborted by: content_moderation_post_update_views_field_plugin_id
Sam152’s picture

Status: Needs work » Needs review

Please test this on 8.7.x HEAD if you are reviewing the issue. This patch hasn't been backported to previous versions, so if you're running 8.6 or 8.5, you'll manually have to backport this if you are evaluating it.

It's likely in your case the ConfigEntityUpdater wasn't use'd at the top of the file, since it was probably included by another update hook that hasn't made it into the release you are running.

sorabh.v6’s picture

Status: Needs review » Reviewed & tested by the community

Ahh! yes I was using that patch on 8.6. Thanks, adding use statement made it work. I believe that was the only missing thing for 8.6 compatibility, if not please tell me I can work on patch for 8.6 backport.

Manuel Garcia’s picture

FWIW, RTBC++ on #37

Wim Leers’s picture

I reviewed #2862041: Provide useful Views filters for Content Moderation State fields for cacheability, so I figured I'd do the same here.

  1. +++ b/core/modules/content_moderation/src/Plugin/views/field/ModerationStateField.php
    @@ -0,0 +1,75 @@
    +class ModerationStateField extends EntityField {
    

    👍 This inherits \Drupal\Core\Plugin\ContextAwarePluginBase::getCacheTags(), which inspects the used contexts to determine the cache tags.

    EntityField is known to handle cache tags correctly, which means this should too.

  2. +++ b/core/modules/content_moderation/tests/src/Kernel/ViewsModerationStateSortTest.php
    @@ -0,0 +1,187 @@
    +    // Ascending order will see 'published' followed by 'zz_draft'.
    +    $this->assertSortResults('test_content_moderation_state_sort_base_table', 'nid', 'ASC', [
    +      ['nid' => $second_node->id()],
    +      ['nid' => $first_node->id()],
    +    ]);
    +    // Descending will reverse the order.
    +    $this->assertSortResults('test_content_moderation_state_sort_base_table', 'nid', 'DESC', [
    +      ['nid' => $first_node->id()],
    +      ['nid' => $second_node->id()],
    +    ]);
    

    🤔 It would be nice if this were to verify that modifying the moderation state of either node would invalidate the cached response. (And that both previous requests resulted in cacheable responses.)

    Since this is only ever going to be used for admin views, I'm not sure how valuable this is though. I'll leave that to core committers to decide.

Sam152’s picture

This needed a reroll because we already introduced the drupal-8.5.0-content_moderation_installed fixture in #2983958: Users expect the "latest translation affected revision" not the "latest revision" in the views UI when moderating content.

  1. Nice, clicking through to these, they don't really have an intersection with the kind of customisations we're making in the subclass, so I think we're covered.
  2. I don't really know if it should be the concern or if it would even be possible to test the cacheability of these handlers, if they have very plain cacheability requirements (that is, changes are only ever correlated with changes in the entity field data) and don't leverage any tags that aren't already covered by the "{$entity_type}_list" tag.

    My line of thinking is: how would you ever isolate that the invalidation came from the sort plugin vs the tags that are already present from the other views subsystems (such as the display plugins) that ensure the "{$entity_type}_list" tag is already part of the built output of the page.

    In short, I don't think you could ever produce a failing test by overriding this particular plugin and returning NULL for all the cacheability methods.

    Not sure if I'm missing anything though.

Wim Leers’s picture

  1. Indeed!
  2. Very good point. I think you're right. That, combined with the fact that this will likely only ever be used for admin views, is sufficiently convincing IMHO. I already didn't feel strongly about this point anyway, hopefully I made that clear :)
Sam152’s picture

Thanks for following up, all sounds great to me :)

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 44: 2953331-43.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Sam152’s picture

Status: Needs review » Reviewed & tested by the community

This was only rerolled and it looks like #45 is a sign-off from @Wim? :)

Sam152’s picture

Queued this on a bunch of different DBs, looking solid. The sqlite fail was after it had reached the nightwatch tests: Error retrieving a new session from the selenium server.

dawehner’s picture

  1. +++ b/core/modules/content_moderation/src/Plugin/views/field/ModerationStateField.php
    @@ -0,0 +1,75 @@
    +    if (!isset($this->aliases[$column_name])) {
    +      $this->aliases[$column_name] = $this->tableAlias . '.' . $column_name;
    +    }
    

    🔧 I would have actually dropped the if condition. It is potentially unlikely that the aliases is set already, but even if it is, we don't really save anything by adding this condition. It rather opens up the question, why it might or might not be set yet.

  2. +++ b/core/modules/content_moderation/src/Plugin/views/filter/ModerationStateFilter.php
    @@ -21,6 +22,8 @@
      */
     class ModerationStateFilter extends InOperator implements DependentWithRemovalPluginInterface {
     
    +  use ModerationStateJoinViewsHandlerTrait;
    +
       /**
        * {@inheritdoc}
        */
    @@ -109,45 +112,6 @@ public function getValueOptions() {
    
    @@ -109,45 +112,6 @@ public function getValueOptions() {
         return $this->valueOptions;
       }
     
    -  /**
    -   * {@inheritdoc}
    

    Nice extraction of logic.

  3. +++ b/core/modules/content_moderation/tests/modules/content_moderation_test_views/content_moderation_test_views.module
    @@ -0,0 +1,22 @@
    +
    +/**
    + * Implements hook_views_query_alter().
    + *
    + * @see \Drupal\Tests\content_moderation\Kernel\ViewsModerationStateSortTest::testSortRevisionBaseTable()
    + */
    +function content_moderation_test_views_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
    +  // Add a secondary sort order to ensure consistent builds when testing click
    +  // and table sorting.
    +  if ($view->id() === 'test_content_moderation_state_sort_revision_table') {
    +    $query->addOrderBy('node_field_revision', 'vid', 'ASC');
    +  }
    +}
    

    I would have rather expected that the view itself has an additional sort configured, instead of altering the query, given that the sort might or might not be added at the front/back.
    Adding the hook_views_query_alter() seems to make it much harder to understand.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 48: 2953331-48.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Sam152’s picture

Hey @dawehner, thanks for the review.

1. I'm fine with that change. Lets see what the bot says.
2. :)
3. I tried this in #34, but these secondary sorts are ignored when click sorting or accepting exposed input, both of which need to be tested because click sorting is integrated via the field plugin, not the sort plugin.

Sam152’s picture

Whoops, missed the interdiff somehow, but the only change made was addressing point 1.

Manuel Garcia’s picture

Patch is looking great to me, awesome work - RTBC++
Did a minor cleanup related to CS / docblocks while I was looking at it.

azinck’s picture

Here's a backport of #56 to 8.6.x

Status: Needs review » Needs work

The last submitted patch, 57: 2953331-56-d8_6_x.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Sam152’s picture

Status: Needs work » Needs review
FileSize
37.99 KB

Reuploading #56 so it's clear which patch needs review.

Sam152’s picture

Status: Needs review » Reviewed & tested by the community

Failing another follow-up review, RTBC for the interdiff in #56 + the scope of changes made as a result of #52 was the feedback in #52.1, so very minor.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 59: 2953331-56.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

oheller’s picture

After applying the patch via composer after running drush updb I get the following error:

[notice] Update started: content_moderation_post_update_views_field_plugin_id
[error] Class "ConfigEntityUpdater" does not exist.
[error] Update failed: content_moderation_post_update_views_field_plugin_id
[error] Update aborted by: content_moderation_post_update_views_field_plugin_id
[error] Finished performing updates.

I suggest adding use Drupal\Core\Config\Entity\ConfigEntityUpdater to the top of content_moderation.post_update.php.

Manuel Garcia’s picture

Re #63 - that is already in the file since 8.7.x (see https://cgit.drupalcode.org/drupal/tree/core/modules/content_moderation/...) - it's also still there on 8.8.x.

Manuel Garcia’s picture

Status: Needs work » Needs review
FileSize
2.44 KB
36.37 KB

I believe the tests were failing due to #3023981: Add @trigger_error() to deprecated EntityManager->EntityRepository methods, which means we can simplify ModerationStateField, so yay.

Sam152’s picture

Status: Needs review » Reviewed & tested by the community

Great clean up, thanks for making this green again.

alexpott’s picture

We have a deprecation test that is failing. Keeping up with HEAD and fixing coding standards.

larowlan’s picture

Adding review credits

larowlan’s picture

Version: 8.8.x-dev » 8.7.x-dev

Committed 81d8e2a and pushed to 8.8.x. Thanks!

Not back-porting immediately because I think the update hook is disruptive at this stage of the 8.7 cycle.

  • larowlan committed 81d8e2a on 8.8.x
    Issue #2953331 by Sam152, Manuel Garcia, alexpott, azinck, anish.a,...
Manuel Garcia’s picture

Yay!

So is this fixed then or is a backport a possibility?

xjm’s picture

Version: 8.7.x-dev » 8.8.x-dev
Category: Bug report » Feature request
Status: Reviewed & tested by the community » Fixed

@larowlan, @catch, and I discussed this and agreed that it's more of a missing feature than a bug per se. It's a smidge disruptive and includes lots of additions that are only typically allowed in minor releases. So, setting fixed against 8.8.x.

Thanks everyone!

Manuel Garcia’s picture

Fair enough, thanks for the update @xjm!

Status: Fixed » Closed (fixed)

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