Problem/Motivation

The method ModuleHandler::addModule() allows to add a module, and then ModuleHandler::add() attempts to add hook implementations for that module.
The methods were deprecated in #3481778: Deprecate functions using ModuleHandler::add(), and will be removed in Drupal 12.
We can assume that currently these method are rarely used, but their usage is still possible.

We already understand some limitations:
- Only procedural implementations are added.
- The resulting combined list of implementations is not properly ordered.

However, there is a bigger problem:
Calling ->add() removes existing implementations, and also prevents regular implementations from being added later.
Also, when ->resetImplementations() is called, the new implementations are lost.

This is much worse than simply not adding any new implementations.

Steps to reproduce

We can produce a KernelTest with code like this:

$module_handler = \Drupal::service(ModuleHandlerInterface::class);
// Assume that modules 'module_a' and 'module_b' are currently installed.
// Assume that implementations of test_hook return the respective module names.
$this->assertSame(['module_a', 'module_b'], $module_handler->invokeAll('test_hook'));
$module_handler->addModule('module_c');
$this->assertSame(['module_c'], $module_handler->invokeAll('test_hook'));  // ouch!!!
$module_handler->resetImplementations();
$this->assertSame(['module_a', 'module_b'], $module_handler->invokeAll('test_hook'));  // Implementation from module_c is forgotten.

One problem is the `->resetImplementations()` called within `->add()`.
We could remove this, but then it would still be problematic, if we call ->add() before ->invokeAll():

$module_handler = \Drupal::service(ModuleHandlerInterface::class);
// Assume that modules 'module_a' and 'module_b' are currently installed.
// Assume that implementations of test_hook return the respective module names.
$this->assertSame(['module_a', 'module_b'], $module_handler->invokeAll('test_hook'));
$module_handler->addModule('module_c');
// If we remove ->resetImplementations() from within ->add(), the old implementations are not lost.
$this->assertSame(['module_a', 'module_b', 'module_c'], $module_handler->invokeAll('test_hook'));  // nice, I guess..
$module_handler->resetImplementations();
$this->assertSame(['module_a', 'module_b'], $module_handler->invokeAll('test_hook'));  // Implementation from module_c is forgotten.

and

$module_handler = \Drupal::service(ModuleHandlerInterface::class);
// Assume that modules 'module_a' and 'module_b' are currently installed.
// Assume that implementations of test_hook return the respective module names.
// Assume that ->invokeAll('test_hook') was not called yet, so the list is not initialized.
$module_handler->addModule('module_c');
$this->assertSame(['module_c'], $module_handler->invokeAll('test_hook'));  // ouch!!!
$module_handler->resetImplementations();
// Now the list can be properly initialized.
$this->assertSame(['module_a', 'module_b'], $module_handler->invokeAll('test_hook'));

Proposed resolution

Remove module add chain of methods and just empty them.

Remaining tasks

Review

User interface changes

N/A

Introduced terminology

N/A

API changes

Technically - I can add a CR for this.

Data model changes

N/A

Release notes snippet

N/A

Issue fork drupal-3528899

Command icon 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

donquixote created an issue. See original summary.

donquixote’s picture

Title: ModuleHandler::add() can prevent existing implementations from being added » ModuleHandler::add() removes implementations from other modules
Related issues: +#3506930: Separate hooks from events, +#3519561: Introduce ImplementationList objects per hook, to simplify ModuleHandler
nicxvan’s picture

Component: base system » extension system

I really don't think people are using this.

It was a helper for Drupal install and updating and wasn't even working there for ages.

We can track it though.

Unless someone pops up though with a valid use case this is already deprecated. I'm not sure it's worth the effort to change.

nicxvan’s picture

In fact I'm considering marking this postponed maintainer needs more info on an example of someone actually using this.

donquixote’s picture

My main concern here is whenever we refactor this, e.g. in #3519561: Introduce ImplementationList objects per hook, to simplify ModuleHandler, we are replicating severely broken functionality.

nicxvan’s picture

Just to clarify you mean replicating broken functionality only within the add method right?

donquixote’s picture

yes.

donquixote’s picture

It was a helper for Drupal install and updating and wasn't even working there for ages.

It was working before the OOP hooks via EventDispatcher. So in 11.0.

Unless someone pops up though with a valid use case this is already deprecated. I'm not sure it's worth the effort to change.

Normally "deprecated" code still works as advertised or as expected, you should stop using it to prepare for the next major version.

nicxvan’s picture

Status: Active » Postponed (maintainer needs more info)

Postponing until we have someone impacted by this.

Contrib projects that use this method would be most helpful, but I've not been able to find any contrib using it.

Feel free to set back to active if you find contrib using it and we can take another look.

nicxvan’s picture

I searched http://codcontrib.hank.vps-private.net/search?text=Drupal%3A%3Aservice%2...

And the other common ways this could be called and all returned 0 usages.

nicxvan changed the visibility of the branch 11.x to hidden.

nicxvan changed the visibility of the branch 3528899-ModuleHandler-add-is-destructive to hidden.

nicxvan’s picture

Issue summary: View changes
Status: Postponed (maintainer needs more info) » Needs review
catch’s picture

I think we are probably OK to make these a no-op in Drupal 11.3 with an updated deprecation message if we're confident they're not being called in contrib, which it sounds like we are. I can't see any runtime use case for ever calling them so the most likely case would be a very custom installer or some test code maybe, if at all.

nicxvan’s picture

I have done another careful search and I found one module using it in a test.
I think it was created after this issue, I've opened an issue in that module to update it: #3549416: Update call to addModule

There is no release and no sites using it yet.

Do we need a CR?

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Since this seemed to get sign off from @catch in #16 going to mark. Don't think we need a new CR but maybe update https://www.drupal.org/node/3491200 ?

nicxvan’s picture

I created a tentative CR and we can link the old one to the new one once this gets in.

nicxvan’s picture

Adding related issue that can be closed when this lands.

nicxvan’s picture

Title: ModuleHandler::add() removes implementations from other modules » [pp-1] ModuleHandler::add() removes implementations from other modules
Status: Reviewed & tested by the community » Postponed (maintainer needs more info)

Let's postpone this on the separate hooks issue since that is now rtbc and far more important.

That will also require a reroll here.

donquixote’s picture

Actually I would like this to go in asap, I don't see a big conflict with the other issue.

donquixote’s picture

Status: Postponed (maintainer needs more info) » Reviewed & tested by the community

The other one will be super easy to rebase if this gets in first.

nicxvan’s picture

The reverse is also true, and the other one has a few other issues dependent on it so I really think this should be postponed on that one.

I'm trying to remove roadblocks for the other one and forcing a rebase for this is a roadblock.

catch’s picture

Title: [pp-1] ModuleHandler::add() removes implementations from other modules » ModuleHandler::add() removes implementations from other modules
Status: Reviewed & tested by the community » Needs work

Needs a rebase :)

nicxvan’s picture

Issue summary: View changes
Status: Needs work » Needs review

This is ready for review again.

berdir’s picture

Status: Needs review » Reviewed & tested by the community

New MR as the code has changed a lot. This just removes the code and I think still looks good. I haven't carefully reviewed the issues but it's almost never used and was already RTBC, with agreement on the direction, so...

  • catch committed 5dd72977 on 11.3.x
    Issue #3528899 by donquixote, nicxvan, catch: ModuleHandler::add()...

  • catch committed 1e8dd010 on 11.x
    Issue #3528899 by donquixote, nicxvan, catch: ModuleHandler::add()...
catch’s picture

Version: 11.x-dev » 11.3.x-dev
Status: Reviewed & tested by the community » Fixed

Committed/pushed to 11.x and cherry-picked to 11.3.x, thanks!

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.