diff --git a/composer.lock b/composer.lock index fa4c6f0cd..1567f59eb 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "50ff0b633d24bd1c19f48e4040029abe", + "content-hash": "04e565def42bc44b8e7bf85153a4d11b", "packages": [ { "name": "access/drupal_seamless_cilogon", @@ -32,7 +32,7 @@ "source": { "type": "git", "url": "https://github.com/access-ci-org/infrastructure_news", - "reference": "b846d04298ddb8a802f84b76189d63e0d2f34678" + "reference": "39a6603bd41fb9383c18e8ddc7814236273e383a" }, "require": { "access/operations_cider": "*", @@ -60,7 +60,7 @@ "issues": "https://github.com/access-ci-org/infrastructure_news/issues", "source": "https://github.com/access-ci-org/infrastructure_news" }, - "time": "2024-06-10T05:03:45+00:00" + "time": "2024-11-21T18:25:10+00:00" }, { "name": "access/operations_cider", @@ -295,7 +295,7 @@ "source": { "type": "git", "url": "https://github.com/necyberteam/access.git", - "reference": "02d24017172f1a54056d6e61bc590d44d9769bc0" + "reference": "4f35a2e5f1e336aa888ac4a03ae53880a3f3c467" }, "require": { "gioni06/gpt3-tokenizer": "^1.2", @@ -317,7 +317,7 @@ "issues": "https://github.com/necyberteam/access/issues", "source": "https://github.com/necyberteam/access" }, - "time": "2024-11-15T01:30:29+00:00" + "time": "2024-11-20T16:59:36+00:00" }, { "name": "arthurkushman/query-path", @@ -12066,7 +12066,7 @@ "source": { "type": "git", "url": "https://github.com/necyberteam/aspTheme.git", - "reference": "126efef04daae08151f34c2e4ffdedef7143ed7a" + "reference": "83fc21dc3050bb77ad0655ff1edaef857284fece" }, "default-branch": true, "type": "drupal-theme", @@ -12084,7 +12084,7 @@ "issues": "https://github.com/necyberteam/aspTheme/issues", "source": "https://github.com/necyberteam/aspTheme" }, - "time": "2024-10-24T19:46:24+00:00" + "time": "2024-11-15T16:51:59+00:00" }, { "name": "necyberteam/campus-champions-theme", diff --git a/composer.patches.json b/composer.patches.json index 2760009b8..a6d0c4d23 100755 --- a/composer.patches.json +++ b/composer.patches.json @@ -1,6 +1,7 @@ { "patches": { "drupal/core": { + "ModuleHandler skips all hook implementations when invoked before the module files have been loaded": "patches/3207813-27.patch", "More link is missing in pager...": "https://www.drupal.org/files/issues/2023-10-09/3381979-13.patch", "big_pipe.js' checkMutation() does not check if node exists before using it": "https://www.drupal.org/files/issues/2024-01-21/drupal-big_pipe_does_not_check_before_using_node_object-3416141.patch", "entity bundled fields in views": "https://www.drupal.org/files/issues/2024-05-08/2981047-190.patch" diff --git a/patches/3207813-27.patch b/patches/3207813-27.patch new file mode 100644 index 000000000..9b042d4ea --- /dev/null +++ b/patches/3207813-27.patch @@ -0,0 +1,82 @@ +diff --git a/core/lib/Drupal/Core/Extension/ModuleHandler.php b/core/lib/Drupal/Core/Extension/ModuleHandler.php +index 262865403e6..46c8ed3fa46 100644 +--- a/core/lib/Drupal/Core/Extension/ModuleHandler.php ++++ b/core/lib/Drupal/Core/Extension/ModuleHandler.php +@@ -629,6 +629,12 @@ protected function getImplementationInfo($hook) { + protected function buildImplementationInfo($hook) { + $implementations = []; + $hook_info = $this->getHookInfo(); ++ ++ // In case it's an early stage and the hook info was loaded from cache, the ++ // module files are not yet loaded at this point and discovery below ++ // produces an empty list. ++ $this->loadAll(); ++ + foreach ($this->moduleList as $module => $extension) { + $include_file = isset($hook_info[$hook]['group']) && $this->loadInclude($module, 'inc', $module . '.' . $hook_info[$hook]['group']); + // Since $this->implementsHook() may needlessly try to load the include +@@ -676,6 +682,17 @@ protected function buildImplementationInfo($hook) { + * from the cache. + */ + protected function verifyImplementations(&$implementations, $hook) { ++ // Under certain circumstances the module files are not yet loaded. This ++ // happens for example when invoking a hook inside the constructor of a ++ // http_middleware service; these services are constructed very early as ++ // a dependency of http_kernel service. A more concrete example is a ++ // middleware service using the entity_type.manager. Most of the times ++ // the entity type information is retrieved from cache (stored in the ++ // discovery cache bin). When this cache however is missing, hooks ++ // like hook_entity_type_build() and hook_entity_type_alter() need to be ++ // invoked at this early stage. ++ $this->loadAll(); ++ + $all_valid = TRUE; + foreach ($implementations as $module => $group) { + // If this hook implementation is stored in a lazy-loaded file, include +diff --git a/core/tests/Drupal/Tests/Core/Extension/ModuleHandlerTest.php b/core/tests/Drupal/Tests/Core/Extension/ModuleHandlerTest.php +index c989ea870db..64122069129 100644 +--- a/core/tests/Drupal/Tests/Core/Extension/ModuleHandlerTest.php ++++ b/core/tests/Drupal/Tests/Core/Extension/ModuleHandlerTest.php +@@ -391,6 +391,7 @@ function (callable $hook, string $module) use (&$implementors) { + * Tests getImplementations. + * + * @covers ::invokeAllWith ++ * @covers ::verifyImplementations + */ + public function testCachedGetImplementationsMissingMethod() { + $this->cacheBackend->expects($this->exactly(1)) +@@ -417,7 +418,6 @@ public function testCachedGetImplementationsMissingMethod() { + ]) + ->onlyMethods(['buildImplementationInfo']) + ->getMock(); +- $module_handler->load('module_handler_test'); + + $module_handler->expects($this->never())->method('buildImplementationInfo'); + $implementors = []; +@@ -533,4 +533,26 @@ public function testGetModuleDirectories() { + $this->assertEquals(['node' => $this->root . '/core/modules/node'], $module_handler->getModuleDirectories()); + } + ++ /** ++ * Tests that modules are included in case of a partial cache miss. ++ * ++ * @covers ::hasImplementations ++ * @covers ::getImplementationInfo ++ * @covers ::buildImplementationInfo ++ */ ++ public function testMissingHookImplementationCache() { ++ // Simulate missing cache entry for hook implementations, but existing one ++ // for hook info. ++ $this->cacheBackend ++ ->expects($this->exactly(2)) ++ ->method('get') ++ ->willReturnMap([ ++ ['hook_info', FALSE, (object) ['data' => []]], ++ ['module_implements', FALSE, FALSE], ++ ]); ++ ++ $module_handler = $this->getModuleHandler(); ++ $this->assertTrue($module_handler->hasImplementations('hook', 'module_handler_test')); ++ } ++ + }