Problem/Motivation
The way hook_implementations_map is created alongside adding kernel.event_listener tags makes it difficult for other compiler passes to conditionally undefine hook classes with their own criteria. If you want to undefine the hooks class, you must also update the hook_implementations_map parameter at the same time. And doing so requires either either: hardcoding the unsets for each method, use reflection to find the hooks to undefine, or loop through all implementations which is very non-performant.
See also thread at https://git.drupalcode.org/project/drupal/-/merge_requests/12156#note_51... . A code comment has been added to that MR, referencing this issue.
Proposed resolution
Generating hook_implementations_map should be deferred to very late in the container building process since it is just a memoization of what was discovered, at least with a very late weight/priority in the current compiler pass order. Or perhaps use a different compiler pass later than the existing existing\Symfony\Component\DependencyInjection\Compiler\PassConfig::TYPE_BEFORE_OPTIMIZATION. See \Symfony\Component\DependencyInjection\ContainerBuilder::addCompilerPass. This call currently happens in \Drupal\Core\CoreServiceProvider::register.
If a parameter is still used, it should be renamed and prefixed with a `dot`, to signify it's internal. Combined with a [class] constant of some kind to keep things referential. From Symfony docs:
By convention, parameters whose names start with a dot . (for example, .mailer.transport), are available only during the container compilation. They are useful when working with Compiler Passes to declare some temporary parameters that won't be available later in the application.
I Imagine this kind of internal parameter doesn't have BC, so existing can be reworked.
Better yet, undefine the parameter after using it. Or, not use a parameter
My suggestion is:
- Remove map in
\Drupal\Core\Hook\HookCollectorPass::writeImplementationsToContainer - Remove parameter
- Tag the service with the origin $module. The other metadata, $priority & $method, is already in kernel.event_listener. $class is the service itself.
- Late in service compilation, create a map from service tags and set the parameter value in
\Drupal\Core\Extension\ModuleHandler::$hookImplementationsMapdirectly, instead of via a service container parameter.
Remaining tasks
Implement suggested.
User interface changes
None.
Introduced terminology
None.
API changes
Removed parameter.
Data model changes
None.
Release notes snippet
None.
Issue fork drupal-3526411
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:
Comments
Comment #2
dpiComment #3
dpiComment #4
dpiCreated a changelog @ https://www.drupal.org/node/3526421
Comment #6
dpiComment #7
nicxvan commentedComment #8
dpiMR!12220 posted with my suggested solution: deprecating the juggling of a parameter.
Comment #9
dpiComment #10
nicxvan commentedI wonder if we want to do this first: #3506930: Separate hooks from events
Comment #11
dpiThanks @nicxvan for the first pass review, left a note there.
Comment #12
smustgrave commentedSeems to be 1 open thread for some feedback
If you are another contributor eager to jump in, please allow the previous poster(s) at least 48 hours to respond to feedback first, so they have the opportunity to finish what they started!
Comment #13
nicxvan commentedI think we definitely want to decouple from the event system first.
We also have another way to manage the situation that prompted you to create this issue.
I have to look at adding a second compiler pass just for this.
Comment #14
nicxvan commentedGonna officially postpone this.
Comment #15
nicxvan commentedI'm going to close this as outdated, I think you'll find #3506930: Separate hooks from events does everything you were looking for.
Note the structure is considered internal so it's not strictly supported editing the parameter even if it will work.
Closed issues now get credit.
Please feel free to comment and reopen if you think I missed something.