Problem/Motivation
Checking access to /admin/structure/comment/manage/comment/display
logs the warning message
Entity view display 'node.article.default': Component 'comment' was disabled because its settings depend on removed dependencies.
Using Drupal 10.3 and the contrib admin_toolbar
module, the access check and the warning message are triggered on every page load for an admin user.
Here is a partial stack trace for the warning message:
Drupal\Core\Entity\EntityDisplayBase->onDependencyRemoval()
Drupal\Core\Config\ConfigManager->callOnDependencyRemoval()
Drupal\Core\Config\ConfigManager->getConfigEntitiesToChangeOnDependencyRemoval()
Drupal\user\Form\EntityPermissionsForm->permissionsByProvider()
Drupal\user\Form\EntityPermissionsForm->access()
Steps to reproduce
These steps trigger the warning once, since Drupal 9.4.0:
- Install Drupal with the
standard
profile. - Browse to Administration > Structure > Comment types > Default comments > Manage display:
/admin/structure/comment/manage/comment/display
- Check error logs:
/admin/reports/dblog
These steps trigger the warning on every page load:
- Install Drupal 10.3 with the
standard
profile. - Add the Admin Toolbar module.
- Enable the
admin_toolbar
andadmin_toolbar_tools
modules. - Log in as an admin user.
- Visit
/admin/reports/dblog
and reload the page a few times.
This only happens on Drupal 10.3 (and 11.x) thanks to #2463753: [regression] Do not bypass route access with 'link to any page' permissions for menu links.
Proposed resolution
In Drupal\user\Form\EntityPermissionsForm::permissionsByProvider()
, call Drupal\Core\Config\ConfigManager::findConfigEntityDependencies()
or Drupal\Core\Config\ConfigManager::findConfigEntityDependenciesAsEntities()
instead of Drupal\Core\Config\ConfigManager::getConfigEntitiesToChangeOnDependencyRemoval()
.
Remaining tasks
We might want to add follow-up issues for the following:
- Update
Drupal\Core\Entity\EntityDisplayBase::onDependencyRemoval()
so that it does not log warning messages, or find a way to suppress those messages. See Comment #66. - Update
Drupal\comment\Tests\CommentTestTrait::addDefaultCommentField()
to use the'default'
view mode by default, not'full'
. See Comment #61.
User interface changes
None
API changes
None, unless (2) from the Remaining tasks is done as part of this issue.
Data model changes
None
Release notes snippet
N/A
Original report by DYdave
Initial investigation
After doing an initial investigation, the error message would seem to come from the following piece of code:
https://git.drupalcode.org/project/drupal/-/blob/9.4.5/core/lib/Drupal/C...
// If there are unresolved deleted dependencies left, disable this
// component to avoid the removal of the entire display entity.
if ($this->getPluginRemovedDependencies($renderer->calculateDependencies(), $dependencies)) {
$this->removeComponent($name);
$arguments = [
'@display' => (string) $this->getEntityType()->getLabel(),
'@id' => $this->id(),
'@name' => $name,
];
$this->getLogger()->warning("@display '@id': Component '@name' was disabled because its settings depend on removed dependencies.", $arguments);
$changed = TRUE;
}
It would seem a lot of this code relates to issue: #2562107-77: EntityDisplayBase should react on removal of its components dependencies.
After doing some basic debugging, breaking at this point in code resulted in the following stack trace:
array:55 [▼ 0 => array:7 [▼ "file" => "/web/core/lib/Drupal/Core/Config/ConfigManager.php""line" => 497 "function" => "onDependencyRemoval""class" => "Drupal\Core\Entity\EntityDisplayBase""object" => Drupal\Core\Entity\Entity\EntityViewDisplay {#2650 ▶} "type" => "->""args" => array:1 [▶] ] 1 => array:7 [▼ "file" => "/web/core/lib/Drupal/Core/Config/ConfigManager.php""line" => 360 "function" => "callOnDependencyRemoval""class" => "Drupal\Core\Config\ConfigManager""object" => Drupal\Core\Config\ConfigManager {#857 ▶} "type" => "->""args" => array:4 [▶] ] 2 => array:7 [▼ "file" => "/web/core/modules/user/src/Form/EntityPermissionsForm.php""line" => 88 "function" => "getConfigEntitiesToChangeOnDependencyRemoval""class" => "Drupal\Core\Config\ConfigManager""object" => Drupal\Core\Config\ConfigManager {#857 ▶} "type" => "->""args" => array:2 [▶] ] 3 => array:7 [▼ "file" => "/web/core/modules/user/src/Form/EntityPermissionsForm.php""line" => 173 "function" => "permissionsByProvider""class" => "Drupal\user\Form\EntityPermissionsForm""object" => Drupal\user\Form\EntityPermissionsForm {#2057 ▶} "type" => "->""args" => [] ] 4 => array:5 [▼ "function" => "access""class" => "Drupal\user\Form\EntityPermissionsForm""object" => Drupal\user\Form\EntityPermissionsForm {#2057 ▶} "type" => "->""args" => array:3 [▶] ...
Mostly, with this chain of calls:
[... Multiple calls before ...] Drupal\user\Form\EntityPermissionsForm:permissionsByProvider Drupal\Core\Config\ConfigManager:getConfigEntitiesToChangeOnDependencyRemoval Drupal\Core\Config\ConfigManager:callOnDependencyRemoval Drupal\Core\Entity\EntityDisplayBase:onDependencyRemoval
The code of these functions seems to be related to #2850973: ConfigEntityInterface::onDependencyRemoval() called with incorrect dependency list.
In short, the reason the problem happens is because:
When the Manage Display Comment page is displayed, a list of all config depending on 'comment.type.comment' is created.
Since the default display of comments 'core.entity_view_display.comment.comment.default' depends on 'comment.type.comment' and since 'core.entity_view_display.node.article.default' depends on 'core.entity_view_display.comment.comment.default' it is also added to the list of dependencies.
core.entity_view_display.node.article.default > core.entity_view_display.comment.comment.default > comment.type.comment
The affected "cross" dependency is due to the fact the Node, type Article, default display 'core.entity_view_display.node.article.default' uses the default comment formatter (to display the Comment field), which points to the default display of the Comment, type Comment 'core.entity_view_display.comment.comment.default', see:
https://git.drupalcode.org/project/drupal/-/blob/9.4.5/core/modules/comm...
In particular lines around 270:
if ($display = EntityViewDisplay::load("comment.$bundle.$mode")) {
$dependencies[$display->getConfigDependencyKey()][] = $display->getConfigDependencyName();
}
From a logic perspective it certainly makes sense to allow the default comment formatter, and Plugins in general to react to configuration changes on Entity Displays.
For example, it would probably make sense adding a specific handling case for the default comment formatter: Drupal\comment\Plugin\Field\FieldFormatter\CommentDefaultFormatter:onDependencyRemoval, to check whether the referenced display still exists and capture any changes to the settings, much like it's currently done for the 'ImageFormatter', see:
https://git.drupalcode.org/project/drupal/-/blob/9.4.5/core/modules/imag...
Work-around/Temporary solution
Note the problem can be fixed temporarily by removing the config dependency either programmatically, or by importing the modified config through the backend (at '/admin/config/development/configuration/single/import/') or from its file (edit file 'config/sync/core.entity_view_display.node.article.default.yml', remove the line 'core.entity_view_display.comment.comment.default' under 'config' and import).
But of course the config is added back the next time the Node Article display 'core.entity_view_display.node.article.default' is saved.
Lastly, since we're really unsure how to approach the problem and the config dependency system seems to have a lot of moving parts, we found the following issues that could potentially be related or where some work is carried around Plugins 'getPluginRemovedDependencies' and 'getPluginRemovedDependencies':
- #2786841: Entity reference fields should add selection handler config dependencies
- #2865710: Dependencies from only one instance of a widget are used in display modes
- #2579743: Config entities implementing EntityWithPluginCollectionInterface should ask the plugins to react when their dependencies are removed
We would greatly appreciate to have your feedback and more particularly, if anyone would have any pointers or guidance on what could be the best approach to finding a solution to the problem.
Feel free to let us know if you have any questions, if anything is unclear or if more information would be needed, we would surely be glad to help.
Thanks in advance.