Problem/Motivation

Sometimes you want to invoke a hook for a single module. Currently you need to use invoke which restricts to one implementation or a really awkward invokeAllWith:

    $requirements = [];
    \Drupal::moduleHandler()->invokeAllWith('runtime_requirements', function (callable $hook, string $module) use (&$requirements) {
      if ($module === 'system') {
        $requirements = array_merge($requirements, $hook());
      }
    });
    return $requirements;

Steps to reproduce

Add two hooks in one module and execute them with invoke()

Proposed resolution

Add a check for array if there are more than one listener, and merge them before returning.

Remaining tasks

Review

User interface changes

Introduced terminology

API changes

Data model changes

Release notes snippet

Issue fork drupal-3583153

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

nicxvan created an issue. See original summary.

berdir’s picture

Quoting myself from https://git.drupalcode.org/project/drupal/-/merge_requests/15190:

> (I think my recommendation would be to only throw an exception when there are results that can't be merged. Meaning anything except array and null/void, but, separate issue)

In other words, we extend invoke() to support multiple callbacks as long as they don't return results that we can't merge.

I think the current situation is problematic, because you can write code that works until an arbitrary module decides to add more than one hook implementation and then it explodes. ultimate_cron for example is struggling with that right now and I'll need to adopt the pattern in the issue summary there I think.

There are still edge cases, but I think hooks that return something that isn't an array is pretty rare.

nicxvan’s picture

Issue summary: View changes
nicxvan’s picture

Status: Active » Needs review
smustgrave’s picture

1 small comment for consideration.

nicxvan’s picture

I addressed your feedback I think.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Thanks for humoring me. No objection to the rest of the changes.

catch’s picture

Status: Reviewed & tested by the community » Needs work

Couple of comments on the MR.

nicxvan’s picture

Status: Needs work » Needs review

I updated the comments and added some test coverage for objects and ArrayObject.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new91 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

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

nicxvan’s picture

Status: Needs work » Needs review
needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new91 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

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

nicxvan’s picture

Status: Needs work » Needs review

Rebased

smustgrave’s picture

Does this need a CR?

berdir’s picture

Title: Create single module invoke that does not restrict to a single implementation » Allow to invoke multiple implementations of a specific module with ModuleHandler::invoke()
Status: Needs review » Needs work

Not sure, no code needs to be adjusted for this, it will just work now in cases where it can work.

It means that I can close #3501360: Multiple crons task should be possible in the same module as that's no longer a problem for example.

I tried adjusting the title a bit. We're not introducing a new API here, we just allow the existing invoke() to work in more cases than it did before. We could use the CR to explain this, but we already have some adjustments on the interface docs, for which I just added a suggestion to update it.

nicxvan’s picture

Status: Needs work » Needs review

Thanks! I addressed your feedback and updated the comment.

berdir’s picture

Status: Needs review » Reviewed & tested by the community

Back to RTBC then.

amateescu’s picture

Posted a comment on the MR. That point might've been discussed and agreed upon already and I haven't seen it, so leaving at RTBC for now.

  • amateescu committed bdf4b395 on 11.x
    task: #3583153 Allow to invoke multiple implementations of a specific...

  • amateescu committed 1b4da6db on main
    task: #3583153 Allow to invoke multiple implementations of a specific...
amateescu’s picture

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

Committed and pushed 1b4da6d to main and bdf4b395e8c to 11.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.