Problem/Motivation

When modules are installed, plugin definitions are cleared.
Breakpoints and Layouts also allow themes to provide plugins, they need to be cleared as well.

Any manager using YamlDiscovery has to pass in the list of directories to search, and these are not updated.
Additionally, the %container.namespaces% parameter is updated by the DrupalKernel, but is also cached by the discovery

Proposed resolution

Reset the discovery in \Drupal\Core\Plugin\DefaultPluginManager::clearCachedDefinitions()
Adjust \Drupal\Core\Extension\ThemeInstaller::resetSystem() to match \Drupal\Core\Extension\ModuleInstaller

Remaining tasks

Reroll
Review
Commit

User interface changes

N/A

API changes

N/A

Data model changes

N/A

Comments

tim.plunkett created an issue. See original summary.

tim.plunkett’s picture

Status: Active » Needs review
StatusFileSize
new689 bytes
new2.26 KB
tim.plunkett’s picture

Status: Needs work » Needs review
StatusFileSize
new3.88 KB
new1.62 KB
dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Nice fix!

+++ b/core/lib/Drupal/Core/Entity/EntityTypeManager.php
@@ -79,7 +80,6 @@ public function __construct(\Traversable $namespaces, ModuleHandlerInterface $mo
 
-    $this->discovery = new AnnotatedClassDiscovery('Entity', $namespaces, 'Drupal\Core\Entity\Annotation\EntityType');
     $this->stringTranslation = $string_translation;
     $this->classResolver = $class_resolver;
   }
@@ -87,6 +87,16 @@ public function __construct(\Traversable $namespaces, ModuleHandlerInterface $mo

@@ -87,6 +87,16 @@ public function __construct(\Traversable $namespaces, ModuleHandlerInterface $mo
   /**
    * {@inheritdoc}
    */
+  protected function getDiscovery() {
+    if (!$this->discovery) {
+      $this->discovery = new AnnotatedClassDiscovery('Entity', $this->namespaces, EntityType::class);
+    }
+    return $this->discovery;
+  }
+
+  /**

Does this maybe fixes https://twitter.com/weitzman/status/839605704243691521 ?

tim.plunkett’s picture

Title: Reset plugin discovery that uses extension directories when a theme is installed » Reset plugin discovery when a module/theme is installed

That half and the other half in conjunction should fix that!

alexpott’s picture

Status: Reviewed & tested by the community » Needs review
  1. +++ b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php
    @@ -191,6 +191,7 @@ public function clearCachedDefinitions() {
    +    $this->discovery = NULL;
    

    Does this change mean that we might break contrib/custom plugin managers if they, like EntityTypeManager, do some custom discovery and don't implement getDiscovery()? And if so how are we going to prevent them breaking?

  2. +++ b/core/modules/breakpoint/tests/src/Kernel/BreakpointDiscoveryTest.php
    @@ -20,6 +20,9 @@ class BreakpointDiscoveryTest extends KernelTestBase {
    +    // Fetch the definitions before installing the theme to prime the cache.
    

    I think this comment could do with being fleshed out a bit to explain that this is to test that theme installation clears the breakpoint definitions - right?

tim.plunkett’s picture

1) If we made this change to \Drupal\Component\Plugin\PluginManagerBase, that would indeed be a huge issue.
But \Drupal\Core\Plugin\DefaultPluginManager will be just fine, and anyone (like EntityTypeManager) not using it is currently broken.
ETM explicitly opts out of using derivatives, but it is not documented. To enable derivatives would be a simple as deleting the new getDiscovery override added here.
But the real bug with ETM was that it did not pass the $plugin_definition_annotation_name to parent::__construct()

2) Yep

Uploading 2 patches, the first just simplified ETM while leaving getDiscovery in place, with an interdiff against #4.
The second removes ETM::getDiscovery, with an interdiff against the other patch.

alexpott’s picture

I don't think we should open up entity types to derivatives. Feels a bit out-of-scope here and would need further consideration.

tim.plunkett’s picture

Okay, so the second patch attached is fine?

dawehner’s picture

I don't get the entire discussion about derivatives of entity types. We have them effectively already with hook_entity_type_build()

tim.plunkett’s picture

Regardless of what it could be used for, or what other approaches exist, the question here is: should EntityTypeManager use ContainerDerivativeDiscoveryDecorator?

tim.plunkett’s picture

Or more accurately: is there a reason to have EntityTypeManager explicitly opt out of using ContainerDerivativeDiscoveryDecorator?

dawehner’s picture

I don't see a reason to opt out.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

This looks great for me

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 8: 2860346-discovery-8.patch, failed testing.

naveenvalecha’s picture

Status: Needs work » Reviewed & tested by the community

Back to RTBC per #15

alexpott’s picture

I don't see a reason to opt out.

The only reason I see is that is opted out in HEAD and this patch is opting it in. Yes we get plugin discovery resetting but we also get more functionality. In my opinion the entity API does not need more ways to achieve the same thing. This is why I think https://www.drupal.org/files/issues/2860346-discovery-8.patch is the safer patch to go for.

wim leers’s picture

As somebody who knows the plugin system implementation details not very well: why not rely on the config:core.extension cache tag?

Basically:

diff --git a/core/lib/Drupal/Core/Entity/EntityTypeManager.php b/core/lib/Drupal/Core/Entity/EntityTypeManager.php
index abe96a5..9a95cd7 100644
--- a/core/lib/Drupal/Core/Entity/EntityTypeManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityTypeManager.php
@@ -76,7 +76,7 @@ class EntityTypeManager extends DefaultPluginManager implements EntityTypeManage
   public function __construct(\Traversable $namespaces, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, TranslationInterface $string_translation, ClassResolverInterface $class_resolver) {
     parent::__construct('Entity', $namespaces, $module_handler, 'Drupal\Core\Entity\EntityInterface');
 
-    $this->setCacheBackend($cache, 'entity_type', ['entity_types']);
+    $this->setCacheBackend($cache, 'entity_type', ['entity_types', 'config:core.extension']);
     $this->alterInfo('entity_type');
 
     $this->discovery = new AnnotatedClassDiscovery('Entity', $namespaces, 'Drupal\Core\Entity\Annotation\EntityType');
alexpott’s picture

Status: Reviewed & tested by the community » Needs work

Setting back to needs work for #19 - that sounds like a really good solution imo - easily the most robust.

tim.plunkett’s picture

Status: Needs work » Needs review

That will clear the cache of definitions, which is fine. But that already happens due to a call to \Drupal::service('plugin.cache_clearer')->clearCachedDefinitions();.
This issue is about the actual discovery object itself.

dawehner’s picture

@tim.plunkett
Just to understand you correctly, this is some static caching, right? I'd have expected that every service is reseetted properly on module install / theme install ...

Version: 8.4.x-dev » 8.5.x-dev

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

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

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

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.

tim.plunkett’s picture

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.

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

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

smustgrave’s picture

Issue summary: View changes
Issue tags: +Bug Smash Initiative
StatusFileSize
new4.02 KB

This came up as daily bug smash target.

This appears like it could still be relevant in D9.5 (but someone correct me if I'm wrong)

Sounds like the issue brought up in #19 was addressed in #21

Rerolled for 9.5. Tried generating interdiff but had an issue since the original patch was from a while ago. But used 2860346-discovery-8.patch to start.

Had merge conflicts in

core/lib/Drupal/Core/Entity/EntityTypeManager.php
core/lib/Drupal/Core/Extension/ThemeInstaller.php
core/modules/breakpoint/tests/src/Kernel/BreakpointDiscoveryTest

That I had to manually resolve.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new144 bytes

The Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

nikhil_110’s picture

StatusFileSize
new4.91 KB

Attached patch against Drupal 10.1.x

Patch #34 is not applied for Drupal 10.1.x so Inter-diff file is not added.

Checking patch core/lib/Drupal/Core/Entity/EntityTypeManager.php...
Checking patch core/lib/Drupal/Core/Extension/ThemeInstaller.php...
Hunk #1 succeeded at 300 (offset -4 lines).
Checking patch core/lib/Drupal/Core/Plugin/DefaultPluginManager.php...
Hunk #1 succeeded at 198 (offset 6 lines).
Checking patch core/modules/breakpoint/tests/src/Kernel/BreakpointDiscoveryTest.php...
error: while searching for:

  protected function setUp(): void {
    parent::setUp();
    \Drupal::service('theme_installer')->install(['breakpoint_theme_test']);
  }


error: patch failed: core/modules/breakpoint/tests/src/Kernel/BreakpointDiscoveryTest.php:24
error: core/modules/breakpoint/tests/src/Kernel/BreakpointDiscoveryTest.php: patch does not apply
alexpott’s picture

  1. +++ b/core/lib/Drupal/Core/Extension/ThemeInstaller.php
    @@ -300,6 +300,13 @@ public function uninstall(array $theme_list) {
    +    // Clear plugin manager caches.
    +    \Drupal::getContainer()
    +      ->get('plugin.cache_clearer')
    +      ->clearCachedDefinitions();
    

    This dependency should be injected - all the others are in class already.

  2. +++ b/core/lib/Drupal/Core/Extension/ThemeInstaller.php
    @@ -300,6 +300,13 @@ public function uninstall(array $theme_list) {
    +
    +    $this->themeHandler->refreshInfo();
    

    Why is this necessary? Both install and uninstall are already calling $this->themeHandler->reset();

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

alex.skrypnyk’s picture

#34 states that #19 was addressed in #21, but it is not actually clear whether #21 meant that in a context of initially provided patch or in general:

That will clear the cache of definitions, which is fine. But that already happens due to a call to \Drupal::service('plugin.cache_clearer')->clearCachedDefinitions();.
This issue is about the actual discovery object itself.

So #19 is not actually addressed if the patch is not applied and it can be an easier solution.

https://www.drupal.org/node/3204271 has a similar issue that is possible caused by already cached definitions.

For example, for LayoutPluginManager, adding of the cache tag based on the installed extensions resolves the issue

$this->setCacheBackend($cache_backend, $type, ['config:core.extension']);

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.