Problem/Motivation
The main content overview page /admin/content is provided by the "Content" view that ships with core's node module. This view provides a default menu tab "content" only:

Other modules want to provide menu tasks below this main "Content" tab. For example, the Content Moderation module does this so it can provide a task menu link for "Moderated Content":

When creating menu tasks like this, there needs to be a default task item defined which represents the same content as the main menu tab. In this case, that's what the "Overview" menu task is.
The problem is that Drupal core (or more specifically, the node module), is not providing this default menu task. The Content Moderation module does it in content_moderation.links.task.yml:
content_moderation.content:
title: 'Overview'
route_name: system.admin_content
parent_id: system.admin_content
content_moderation.moderated_content:
title: 'Moderated content'
route_name: content_moderation.admin_moderated_content
parent_id: system.admin_content
weight: 1
As a result, if there are OTHER modules that want to provide task menu items beneath content, they also need to provide this default "Overview" item. If you have Content Moderation enabled with any other module that does this, you end up with duplicate task menu links for the overview page. This is a problem encountered in the Scheduler module: #3167193: Move "Scheduled" menu tab so it's a task under "Content"
Proposed resolution
Have the node module create a default menu task for the content overview page so core modules like Content Moderation and contrib modules like Scheduler don't need to.
Drupal's menu system is intelligent enough to not show it if it's the only tab defined which is perfect. It will only show if there's some other task defined by another module.
We can just move the definition for this task out of content moderation and into node.
Remaining tasks
None
User interface changes
API changes
Data model changes
Release notes snippet
The "Overview" local task, previously defined in the content_moderation module, is now moved to the system module in core. This change centralizes the content administration interface, making it more consistent across different sites regardless of whether content_moderation is enabled.
| Comment | File | Size | Author |
|---|---|---|---|
| #11 | 3199682-11-9-2-x.patch | 1.96 KB | joegraduate |
| #11 | 3199682-11-9-4-x.patch | 1.83 KB | joegraduate |
Issue fork drupal-3199682
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:
- 3199682-11.x
changes, plain diff MR !9148
- 3199682-create-a-default
changes, plain diff MR !1805
Comments
Comment #2
jonathan1055 commentedThanks @bkosborne you have explained the problem and the solution perfectly. This is exactly what we need in Scheduler. Can you provide a patch here?
Comment #5
joegraduateComment #6
joegraduateComment #7
jonathan1055 commentedHi joegraduate,
If you are going to work on this, I can point you towards the code I added in Scheduler to create the task.
Or from the issue summary: "We can just move the definition for this task out of content moderation and into node."
Jonathan
Comment #9
joegraduateMR !1805 moves the 'Overview' local task from content_moderation.links.task.yml to system.links.task.yml.
I verified the following in the Tugboat live preview:
Without content_moderation:

With content_moderation:

Comment #10
joegraduateComment #11
joegraduateAdding patches for use in composer projects.
The attached 9.4.x patch is a copy of the current changes from MR !1805 and should be compatible with 9.4.x or 9.3.x.
Also included a 9.2.x compatible patch.
Comment #12
trackleft2If I understand this correctly, this just fixes a glitch, and any module relying on system.admin_content as a parent route will still function.
Unless they were relying on it being disabled until the workflow module was enabled, in which case it could cause problems, but I also think that is fine. RTBC
Comment #13
jonathan1055 commented@trackleft2 thanks for the feedback and for raising the question
I think that it is very unlikely that a 3rd-party module would rely on something not existing unless another module is enabled without taking the precaution of making sure of the situation. For exampe in Scheduler we added the missing parent only if Content Moderation was not enabled. If that module was enabled we did not add the parent. Even if the 3rd-party module did not do that check, the worst that would happen is that you get the 'overview' local task link unnecessarily repeated.
@joegraduate, nice work. Marking this RTBC from me, but obviously needs a core maintainer to review it too.
Comment #14
alexpottThe thunder_article module also provides:
... this is very similar code to the scheduler module...
Sites which use these modules are going to see additional links until the modules update. And then the new versions will only work best with Drupal 9.4
I'm not sure how to proceed with respect to BC. The right option here might be proceed and accept that some sites might have duplicate overview links until the modules are updated. However, regardless of that, because at least those two modules need changing and I'd guess that this is more - we need a change record for this issue which tells people what to do.
I also wonder if this behaviour can be improved and when a child task is added there could be automatically a child task created for the parent. I could be something like:
If the child key was present and there were children then we could automatically create a child using this info. I think in the long run this would make it much easier to work out BC implications. But I'm not sure...
Comment #15
jonathan1055 commentedYes the simple solution is to accept that the sites where modules have added their own get duplicate local task links. The timing of core changes vs contrib would never work precisely. I tried to avoid duplicates in Scheduler's
DynamicLocalTasksby checking for the existence of the known module (eg content moderation or media) which add their own. But it would be better to check the existence of the local task, not the module (a module) which creates it. However I cannot find how to access this within the DynamicLocalTasks. I can get the plugin.manager.menu.local_task but running getLocalTasks('system.admin_content') always returns one item, regardless of whether the patches above are applied or not.So an alternative idea is to use
hook_local_tasks_alterto remove the additional task if a duplicate is provided by core. This seems clumsy because Scheduler adds the task then removes it later if the duplicate is found. But it does mean that sites running Scheduler would not have two 'Overview' links whenever the change gets committed to core. Other contrib modules could do likewise.Comment #21
mlncn commentedThis is needs review now? Looks great to me! So many contrib modules need to try to add this, not knowing if another module already has; having core do it would be so much better!
Comment #22
smustgrave commented#14 mentions a change record so moving to NW for that.
Thanks for keeping this one going.
Comment #23
trackleft2Added a draft change record https://www.drupal.org/node/3468153, Hopefully I understand the issue well enough.
Comment #24
smustgrave commentedThink that's probably one of the most detailed CR's I've seen nice!
Tested the MR to make sure no task appears when just 1 and everything still works when a module like content moderation is installed.
LGTM
Comment #25
jonathan1055 commentedThank you for pushing this forward. Just a few points:
Comment #26
trackleft21 + 2 Deleted the credits on the change record.
3. Whatever you all decide is fine with me in terms of backporting. If we are willing to make this kind of change in a patch release for 11.x why not for 10.x
Comment #27
quietone commentedThanks for the details change record!
I read the issue summary, comments, MR and CR. Everything is in good order. There is just one question here, about BC, mentioned in #15. There is nothing about this is the 'how to deprecate'.
I updated the credit here.
Comment #28
larowlanThere's been a couple of mentions of BC here for sites using contrib modules or profiles that provide their own version of this.
I think we can easily add code to
\Drupal\Core\Menu\LocalTaskManager::getDefinitionsthat filters the definitions where parent_id = system.admin_content, title = 'Overview' and route_name: = system.admin_content. If it finds more than one, it can trigger a deprecation error.Question is, is that overkill?
Setting back to NR for second opinions on this.
Comment #29
smustgrave commentedProbably the more "proper" way to officially throw a deprecation error.