Problem/Motivation

I built a small module (see https://gist.github.com/rachellawson/36f7c8d99085d98ab561a263834ac304) that adds a new tab to content. It has a _custom_access function to determine whether it should be shown and, for some reason, only when content moderation is enabled and in use, creates the exception below:

The website encountered an unexpected error. Please try again later.
TypeError: Argument 1 passed to Drupal\content_moderation\ModerationInformation::isModeratedEntity() must implement interface Drupal\Core\Entity\EntityInterface, string given, called in /var/www/drupalvm/web/core/modules/content_moderation/src/Plugin/Menu/EditTab.php on line 81 in Drupal\content_moderation\ModerationInformation->isModeratedEntity() (line 37 of core/modules/content_moderation/src/ModerationInformation.php).
Drupal\content_moderation\ModerationInformation->isModeratedEntity('12336') (Line: 81)
Drupal\content_moderation\Plugin\Menu\EditTab->getTitle()
call_user_func_array(Array, Array) (Line: 174)
Drupal\Core\Menu\LocalTaskManager->getTitle(Object) (Line: 323)
Drupal\Core\Menu\LocalTaskManager->getTasksBuild('social_commentary.social_comment', Object) (Line: 358)
Drupal\Core\Menu\LocalTaskManager->getLocalTasks('social_commentary.social_comment', 0) (Line: 94)
Drupal\Core\Menu\Plugin\Block\LocalTasksBlock->build() (Line: 203)
Drupal\block\BlockViewBuilder::preRender(Array)

etc ...

Steps to reproduce include having code to add a tab as above. Once enabled and a content type including a field_facebook_comment boolean field is included, visiting content *seems* to be fine *until* a new draft is added and then published. Visiting the social tab then causes the exception.

Obviously, the exception is not apparent when content moderation is not enabled on the content type.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

rachel_norfolk created an issue. See original summary.

rachel_norfolk’s picture

Issue summary: View changes

just a little more info

rachel_norfolk’s picture

After a loooong conversation with timmillwood and jp_stacey on IRC, we determined that the drupal_moderation module was struggling to find the $node entity when working it magic on the routes surrounding the node.

In the end, I resolved *my* issues and had a working Social tab again by changing the method signature of my \Drupal\social_commentary\Controller\DefaultController::content controller such that it specified the type of object for $node.

Changing

public function content($node) {}

to

public function content(\Drupal\node\NodeInterface $node) {}

Made everything work just fine.

The question remaining is whether this is something we need to document or whether we can work around this?

jp.stacey’s picture

What is it that convinces content moderation to believe that it *ought* to be trying to moderate a non-entity (string) parameter in the first place? I would expect content moderation to not even be invoked, if the parameter in question weren't an entity.

timmillwood’s picture

I'm wondering if we need a check in Content Moderation EntityTab class that $this->entity is actually an entity.

Sam152’s picture

I've hit this exact issue with creating a tab which was a view. In that case you can't hint Node on a controller because views has it's own controller and argument processing. The solution in the end was a route subscriber which altered the route definition like so:

  protected function alterRoutes(RouteCollection $collection) {
    $route = $collection->get($views_route_id);
    $options = $route->getOptions();
    $options['parameters']['node']['type'] = 'entity:node';
    $route->setOptions($options);
  }

A check would be good, because even if the label becomes inconsistent on some routes created by the user, it doesn't fatal. Then some good docs around making this work when the tabs are extended should be enough.

larowlan’s picture

pretty sure the issue here is the access controller runs before the paramconverter has upcast the ID to an entity.

timmillwood’s picture

Issue tags: +Novice, +Workflow Initiative

I think as a quick fix for this we should just update \Drupal\content_moderation\Plugin\Menu\EditTab to check $this->entity is an instance of EntityInterface.

Ada Hernandez’s picture

Assigned: Unassigned » Ada Hernandez
Ada Hernandez’s picture

Status: Active » Needs review
FileSize
1.64 KB
Ada Hernandez’s picture

Assigned: Ada Hernandez » Unassigned

Status: Needs review » Needs work

The last submitted patch, 10: exception_when_adding-2828438-10.patch, failed testing.

The last submitted patch, 10: exception_when_adding-2828438-10.patch, failed testing.

Ada Hernandez’s picture

I have previously removed for Drupal\content_moderation\ModerationInformation this

 if (!$entity instanceof ContentEntityInterface) {
      return FALSE;
    }

but it's necessary for other calls.

Ada Hernandez’s picture

Status: Needs work » Needs review
Sam152’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests
  1. +++ b/core/modules/content_moderation/src/Plugin/Menu/EditTab.php
    @@ -78,9 +78,11 @@ public function getRouteParameters(RouteMatchInterface $route_match) {
       public function getTitle() {
    

    Classes need to be imported at the top of the file.

  2. +++ b/core/modules/content_moderation/src/Plugin/Menu/EditTab.php
    @@ -78,9 +78,11 @@ public function getRouteParameters(RouteMatchInterface $route_match) {
    +    if ($this->entity instanceof \Drupal\Core\Entity\EntityInterface) {
    +      if (!$this->moderationInfo->isModeratedEntity($this->entity)) {
    +        // Moderation isn't enabled.
    +        return parent::getTitle();
    +      }
    

    If this check fails and the entity is null it still falls through the the following lines:

    return $this->moderationInfo->isLiveRevision($this->entity)

    ..which reading the code, will still fatal.

Perhaps a test for this is needed after all.

Ada Hernandez’s picture

Ada Hernandez’s picture

Status: Needs work » Needs review
timmillwood’s picture

+++ b/core/modules/content_moderation/src/Plugin/Menu/EditTab.php
@@ -78,15 +80,19 @@ public function getRouteParameters(RouteMatchInterface $route_match) {
+    if ($this->entity instanceof EntityInterface) {
+      if (!$this->moderationInfo->isModeratedEntity($this->entity)) {

Could this be merged into a single if?

Sam152’s picture

Status: Needs review » Needs work

Also, if the entity can't be determined we probably should return something generic like "Edit", not null.

Also NW based on tests.

rachel_norfolk’s picture

Also, I've noticed the following exception on a view added as a tab, after applying the current patch at #17.

The website encountered an unexpected error. Please try again later.
Error: Call to a member function getCacheTags() on string in Drupal\content_moderation\Plugin\Menu\EditTab->getCacheTags() (line 105 of core/modules/content_moderation/src/Plugin/Menu/EditTab.php).
Drupal\content_moderation\Plugin\Menu\EditTab->getCacheTags() (Line: 58)
Drupal\Core\Cache\CacheableMetadata->addCacheableDependency(Object) (Line: 335)
Drupal\Core\Menu\LocalTaskManager->getTasksBuild('view.hubb_posts_for_this_content.page_1', Object) (Line: 358)
Drupal\Core\Menu\LocalTaskManager->getLocalTasks('view.hubb_posts_for_this_content.page_1', 0) (Line: 94)
Drupal\Core\Menu\Plugin\Block\LocalTasksBlock->build() (Line: 203)
Drupal\block\BlockViewBuilder::preRender(Array)
call_user_func('Drupal\block\BlockViewBuilder::preRender', Array) (Line: 376)
Drupal\Core\Render\Renderer->doRender(Array) (Line: 448)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 195)
Drupal\Core\Render\Renderer->render(Array) (Line: 468)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 353)
__TwigTemplate_a9d17d92a9493431860c2276c1b0ea9253ac7ee53b48ee64bd0257699e6e3e56->block_content(Array, Array) (Line: 189)
Twig_Template->displayBlock('content', Array, Array) (Line: 256)
__TwigTemplate_a9d17d92a9493431860c2276c1b0ea9253ac7ee53b48ee64bd0257699e6e3e56->block_main(Array, Array) (Line: 189)
Twig_Template->displayBlock('main', Array, Array) (Line: 74)
__TwigTemplate_a9d17d92a9493431860c2276c1b0ea9253ac7ee53b48ee64bd0257699e6e3e56->doDisplay(Array, Array) (Line: 382)
Twig_Template->displayWithErrorHandling(Array, Array) (Line: 350)
Twig_Template->display(Array) (Line: 361)
Twig_Template->render(Array) (Line: 64)
twig_render_template('themes/custom/hu_boot/templates/system/page.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('page', Array) (Line: 435)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 195)
Drupal\Core\Render\Renderer->render(Array) (Line: 468)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 99)
__TwigTemplate_401e916db8d9ad14e3d012cda3d16bb545318d2930e59f3d4a3324a6d87d9786->doDisplay(Array, Array) (Line: 382)
Twig_Template->displayWithErrorHandling(Array, Array) (Line: 350)
Twig_Template->display(Array) (Line: 361)
Twig_Template->render(Array) (Line: 64)
twig_render_template('themes/custom/hu_boot/templates/system/html.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('html', Array) (Line: 435)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 195)
Drupal\Core\Render\Renderer->render(Array) (Line: 147)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 574)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 148)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object) (Line: 111)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.view', Object) (Line: 149)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 64)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 99)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 78)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 50)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 651)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
Sam152’s picture

Status: Needs work » Needs review
FileSize
7.6 KB
4.98 KB

Here is a test and fix for this which I think is correct. Originally it looked like we could just load the entity ourselves if it wasn't upcast, we have access to the ID and the entity_type_id, but a few things made me think this is possibly wrong:

  • Possible route access control issue?
  • The assumption that a non-upcast parameter named after an entity type ID is always going to load a valid entity to use.

Overall I think it's safest just to ignore non ContentEntityInterface params.

Status: Needs review » Needs work

The last submitted patch, 22: 2828438-22--test-only.patch, failed testing.

Sam152’s picture

Status: Needs work » Needs review
rachel_norfolk’s picture

Just tried the latest patch in #22 and it is stopping the exception being thrown on both my own code-created tab and one added via Views.

Timmillwood's comment in #19 also appear to have been dealt with (though an interdiff would have been useful! :) )

Sam152’s picture

Sorry, didn't start from the original patch, hence no interdiff.

Sam152’s picture

Issue tags: -Needs tests
rachel_norfolk’s picture

Issue tags: +Needs Review
timmillwood’s picture

Status: Needs review » Reviewed & tested by the community

Looks like a nice solution to me!

  • catch committed debf5fc on 8.3.x
    Issue #2828438 by Adita, Sam152, rachel_norfolk, timmillwood, jp.stacey...

  • catch committed d0271bd on 8.2.x
    Issue #2828438 by Adita, Sam152, rachel_norfolk, timmillwood, jp.stacey...
catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.3.x and 8.2.x, thanks!

  • xjm committed 5e0a62d on 8.2.x
    Revert "Issue #2828438 by Adita, Sam152, rachel_norfolk, timmillwood, jp...
xjm’s picture

Status: Fixed » Needs work

The test introduced by this issue is failing in HEAD:
https://www.drupal.org/pift-ci-job/553399

  • xjm committed b53de59 on 8.3.x
    Revert "Issue #2828438 by Adita, Sam152, rachel_norfolk, timmillwood, jp...
timmillwood’s picture

Version: 8.2.x-dev » 8.3.x-dev
FileSize
8.21 KB
1.6 KB

The patch in #22 is still fine for 8.2.x, but here's a patch for 8.3.x

rachel_norfolk’s picture

+++ b/core/modules/content_moderation/src/ViewsData.php
@@ -88,7 +88,7 @@ public function getViewsData() {
       'field' => [
         'id' => 'standard',
       ],
-      'filter' => [
+      'filter' => [lo
         'id' => 'language',
       ],

What is the "lo" for??

timmillwood’s picture

Status: Needs work » Needs review
FileSize
7.74 KB
473 bytes

What is the "lo" for??

No idea! Where'd that come from? Re-rolled without it.

Sam152’s picture

Status: Needs review » Reviewed & tested by the community

Interdiff LGTM

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 38: 2828438-38.patch, failed testing.

timmillwood’s picture

Status: Needs work » Reviewed & tested by the community

Putting back to RTBC

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 38: 2828438-38.patch, failed testing.

timmillwood’s picture

Status: Needs work » Reviewed & tested by the community

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 38: 2828438-38.patch, failed testing.

timmillwood’s picture

Status: Needs work » Reviewed & tested by the community
rachel_norfolk’s picture

I don't think testbot likes timmillwood...

Sam152’s picture

Fails look unrelated, running again.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 38: 2828438-38.patch, failed testing.

Sam152’s picture

Status: Needs work » Reviewed & tested by the community

Should have been RTBC.

Sam152’s picture

#38 is green again against 8.3.x so I think this is ready.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed
Issue tags: -Needs Review
Related issues: +#2843083: Select entity type / bundle in workflow settings

I don't think this code will last but it is good to have it fixed just in case we don't do #2843083: Select entity type / bundle in workflow settings.

Committed 0391e31 and pushed to 8.2.x. Thanks!

diff --git a/core/modules/content_moderation/src/Plugin/Menu/EditTab.php b/core/modules/content_moderation/src/Plugin/Menu/EditTab.php
index 6c30934..3a80879 100644
--- a/core/modules/content_moderation/src/Plugin/Menu/EditTab.php
+++ b/core/modules/content_moderation/src/Plugin/Menu/EditTab.php
@@ -3,7 +3,6 @@
 namespace Drupal\content_moderation\Plugin\Menu;
 
 use Drupal\Core\Entity\ContentEntityInterface;
-use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Menu\LocalTaskDefault;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
 use Drupal\Core\Routing\RouteMatchInterface;

Fixed unused use on commit.

  • alexpott committed 0391e31 on 8.2.x
    Issue #2828438 by Adita, timmillwood, Sam152, rachel_norfolk, jp.stacey...

  • alexpott committed a716dcb on 8.2.x
    Revert "Issue #2828438 by Adita, timmillwood, Sam152, rachel_norfolk, jp...
Sam152’s picture

This isn't for the field API tabs, but the tabs you see when you are looking at a full node page, so I think this will actually stick around? Since #38 this applies, passes and is needed for 8.3.x as well.

alexpott’s picture

Ah that explains it - I was surprised when this got committed to 8.2.x - I thought I had committed it there #51 - I assumed I'd messed up by committing it to both branches. Committed a76eef7 and pushed to 8.3.x. Thanks!

diff --git a/core/modules/content_moderation/src/Plugin/Menu/EditTab.php b/core/modules/content_moderation/src/Plugin/Menu/EditTab.php
index 6c30934..3a80879 100644
--- a/core/modules/content_moderation/src/Plugin/Menu/EditTab.php
+++ b/core/modules/content_moderation/src/Plugin/Menu/EditTab.php
@@ -3,7 +3,6 @@
 namespace Drupal\content_moderation\Plugin\Menu;
 
 use Drupal\Core\Entity\ContentEntityInterface;
-use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Menu\LocalTaskDefault;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
 use Drupal\Core\Routing\RouteMatchInterface;

Unused use fixed on commit.

  • alexpott committed a76eef7 on 8.3.x
    Issue #2828438 by Adita, timmillwood, Sam152, rachel_norfolk, jp.stacey...

  • xjm committed b53de59 on 8.4.x
    Revert "Issue #2828438 by Adita, Sam152, rachel_norfolk, timmillwood, jp...
  • catch committed debf5fc on 8.4.x
    Issue #2828438 by Adita, Sam152, rachel_norfolk, timmillwood, jp.stacey...
  • alexpott committed a76eef7 on 8.4.x
    Issue #2828438 by Adita, timmillwood, Sam152, rachel_norfolk, jp.stacey...

  • xjm committed b53de59 on 8.4.x
    Revert "Issue #2828438 by Adita, Sam152, rachel_norfolk, timmillwood, jp...
  • catch committed debf5fc on 8.4.x
    Issue #2828438 by Adita, Sam152, rachel_norfolk, timmillwood, jp.stacey...
  • alexpott committed a76eef7 on 8.4.x
    Issue #2828438 by Adita, timmillwood, Sam152, rachel_norfolk, jp.stacey...

Status: Fixed » Closed (fixed)

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