Problem/Motivation

Module weights are from a time before autoloaded code and the ability to sort by dependency.

Proposed resolution

Deprecate module_set_weight() and remove it's usage in core.

Remaining tasks

User interface changes

None

API changes

Data model changes

None

Issue fork drupal-2968232

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

alexpott created an issue. See original summary.

alexpott’s picture

Issue summary: View changes
Status: Active » Needs review
StatusFileSize
new11.43 KB

Let's see what breaks.

alexpott’s picture

  1. +++ b/core/modules/content_translation/content_translation.install
    @@ -13,10 +13,6 @@
    -  // Assign a fairly low weight to ensure our implementation of
    -  // hook_module_implements_alter() is run among the last ones.
    -  module_set_weight('content_translation', 10);
    

    This one is quite a big concern.

  2. +++ b/core/modules/views/views.install
    @@ -8,13 +8,6 @@
    -/**
    - * Implements hook_install().
    - */
    -function views_install() {
    -  module_set_weight('views', 10);
    -}
    

    Discussed with @dawehner and he thought this might be a hangover from d6 days when views was doing a lot with hook_menu().

tr’s picture

Module weights are from a time before autoloaded code and the ability to sort by dependency.

So are you saying that currently in Drupal 8, the order of execution of hooks is deterministic and guaranteed by the dependency declarations in the .info.yml files? And that this execution order is both documented and tested in core so we can be sure it works as intended?

What about two modules A and B which both depend on module C (the hook provider) but not on each other? Which gets fired first, module A's hook or module B's hook? Is the execution order currently guaranteed in this case? (And what IS the order? Alphabetical? Or depends on the class loader and can vary from system to system? Documented and tested?) Do we now have some mechanism other than module weights to alter this execution order if the default order is a problem?

What about conditional dependencies? For example, module A can use module B if it happens to be available, but module A is not dependent upon module B. And IF module B is installed, module A's hook must fire after module B's hook. How can we guarantee this order of execution since there is no dependency declaration involved?

I've never liked the module weight system, but it has been necessary in the past for situations like these, and will continue to be necessary unless there is some equivalent means to alter the default order of execution of hooks, no matter how that order is calculated. In the mean time, even the current module weight system is broken because there is no longer a way to set a module's weight relative to another module (other than to poke into the config directly - module_get_weight() was removed and nothing has replaced it).

alexpott’s picture

So are you saying that currently in Drupal 8, the order of execution of hooks is deterministic and guaranteed by the dependency declarations in the .info.yml files? And that this execution order is both documented and tested in core so we can be sure it works as intended?

Nope not yet. I'm saying it should be determined by dependencies because this is what each module says it requires.

I think in all the complex situations you list above we should be using hook_module_implements_alter() and declaring what exactly you need to come after. However I also think autoloading solves a number of the issues that module_set_weight() used to.

I don't think the class loader has much to do with this. .module files are not loaded via the class loader and autoloading means that module_set_weight() can't now be used to solve problems in that anyway - also what are the problems? There aren't anyone. Once a module's path is registered with the autolaoder its code can be loaded by the autoloader regardless of pretty much anything.

tr’s picture

Status: Needs review » Needs work

Well, if by "autoloader" you're not referring to the PSR-4 autoloader (also known as 'class loader'), then I don't know what you mean. And googling "drupal autoloader" doesn't tell me anything that I don't know - it just tells me about the PSR-4 autoloader or the D7 autoloader module which implements PSR-4 under Drupal 7.

Regardless, your patch doesn't eliminate the concept of module weight, it just makes it inaccessible to the developer. That's not a solution - that's just a hindrance.

If you want to deprecate module_set_weight(), then:
1) You need documentation which explains exactly how hook execution order is determined, and exactly how to modify that execution order.
2) You need tests to show that the execution order is deterministic - i.e. that the order is exactly the same in every environment and is completely controlled by Drupal core, not by external factors like PHP version or Symfony version.
3) You need a change notice to explain how the Drupal core module weight system has changed, and how to use the new system.
4) You need to remove the concept of module weight from the core.extension configuration, and provide an upgrade path for all the contributed modules which currently use the module weight stored in this configuration.

And as far as hook_module_implements_alter() is concerned - how is the order of execution of this hook determined? Seems like a circular reference here - the only way to specify the execution order of hooks is to define a hook which is executed in an unknown order ...

In the meantime, we're left with a dysfunctional module weight system where contributed modules can't find out the current weights so they specify arbitrarily large or arbitrarily small weights in the hope that they will be enabled after/before other modules.

alexpott’s picture

@TR

Let's see what breaks.

is hardly a statement that this work is finished. It's just a start to see what in core was relying on this behaviour. Autoloader in my comment does refer to the class loader. My point about the classloader is that is reduces the original need for module_set_weight() because one of the big usages of it was to ensure another modules .module file is loaded. If the code can be autoloader that is not a concern anymore. Another usage is to ensure your hooks come after some other modules hooks. We've had a replacement for that for quite some time - that's hook_module_implements_alter().

I agree with all the points you make about stuff that needs to happen on this issue. I just disagree that I need to have all that in place on the day I open the issue.

The statement

dysfunctional module weight system where contributed modules can't find out the current weights

is not really correct by the way. Just read the core.extension configuration file and be done. The module_set_weight function and it's replacement in #1808132: Move module_set_weight() into ModuleHandler::setWeight(), add ModuleHandler::getWeight() to replace missing functionality isn;t really right. I'll leave a comment on that issue.

dawehner’s picture

I tried to collect some usecases for changing the weight:

  • mcapi.install: Alters local tasks
  • smart_ip_ban.module: Does a module_set_weight in the .module file :(
  • new_relic_rpm:
      // Set New Relic RPM module's weight to very low so we can trigger job state
      // changes early. This can be important in cases like hook_cron().
      module_set_weight('new_relic_rpm', -20);
    
  • workspaces.install:
      // Set workspace earlier to alter entities before anyone else does.
      module_set_weight('workspace', 10);
    
    
  • comment_notify:
      // Set module weight low so that other modules act on the comment first.
      module_set_weight('comment_notify', 10);
    
  • date_repeat:
      // Make sure this module loads after date_api.
      module_set_weight('date_repeat', 1);
    

Reading through all of them I cannot find yet an instance where module_implements_alter wouldn't be the better way to handle that.

Note: module_implements_alter is not triggered on module_implements_alter, see \Drupal\Core\Extension\ModuleHandler::buildImplementationInfo

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.

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.

andypost’s picture

Maybe instead of setWeight() for extension we can convince developer to use only "weight/order" for hooks via hook_module_implements_alter()

andypost’s picture

Issue tags: +@deprecated, +Kill includes
andypost’s picture

Issue tags: +Needs change record
andypost’s picture

Issue tags: +Needs reroll
karishmaamin’s picture

Status: Needs work » Needs review
StatusFileSize
new10.58 KB

Re-rolled patch against 9.4.x

daffie’s picture

Status: Needs review » Needs work

The function module_set_weight() does not properly get deprecated.

The patch has style guide violations.

ranjith_kumar_k_u’s picture

StatusFileSize
new9.97 KB
new2.6 KB

Fixed CS errors.

elber’s picture

Hello! I didn't understand what's the objective of these issue now. Could you please explain me ?

andypost’s picture

immaculatexavier’s picture

StatusFileSize
new0 bytes
new0 bytes

Rerolled patch against #22

immaculatexavier’s picture

Status: Needs work » Needs review

Rerolled patch against #22

longwave’s picture

Status: Needs review » Needs work

#26 is an empty file.

immaculatexavier’s picture

@longwave

Sorry , unfortunately it was an empty file. I will upload the patch in a while.

immaculatexavier’s picture

StatusFileSize
new10.53 KB
new1.39 KB

Sorry , unfortunately #26 it was an empty file.
Again Rerolled patch against #21 with diff

immaculatexavier’s picture

Status: Needs work » Needs review
StatusFileSize
new10.6 KB
new558 bytes

Rerolled patch against #30, worked on Custom Commands Failed issues

Status: Needs review » Needs work

The last submitted patch, 31: 2968232-31.patch, failed testing. View results

immaculatexavier’s picture

Status: Needs work » Needs review
StatusFileSize
new10.64 KB
new850 bytes

Rerolled patch against #31, worked on Failed issues

Status: Needs review » Needs work

The last submitted patch, 33: 2968232-33.patch, failed testing. View results

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.

medha kumari’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
StatusFileSize
new10.1 KB

Reroll the patch #33 with Drupal 9.5.x

longwave’s picture

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

We cannot add new deprecations to 9.5.x since beta1 was released, this will have to go into 10.1.x now.

medha kumari’s picture

StatusFileSize
new10.1 KB

Reroll the patch #36 with Drupal 10.1.x

The last submitted patch, 36: 2968232-36.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 38: 2968232-38.patch, failed testing. View results

rob230’s picture

Can someone explain to me how you can control the order of hooks when two modules both implement hook_module_implements_alter()? I have tried making one module a dependency of the other but it didn't help. It seems the only thing I can do is to set the weight of my module to ensure my hook_module_implements_alter() runs before the other module's hook_module_implements_alter().

voleger’s picture

andypost’s picture

kim.pepper’s picture

Version: 10.1.x-dev » 11.x-dev
Status: Needs work » Needs review
StatusFileSize
new16.57 KB
new6.48 KB

I don't think #7 is saying that other issue has to go in before this one. I think it's just saying it's wrong.

  • I rerolled #38 for 11.x
  • removed a few more usages which can be handled with hook_module_implements_alter()
  • added the trigger error for the deprecation
  • added a legacy deprecation test
kim.pepper’s picture

StatusFileSize
new16.66 KB
new1.19 KB

Fixed phpstan issue.

Status: Needs review » Needs work

The last submitted patch, 45: 2968232-45.patch, failed testing. View results

kim.pepper’s picture

Status: Needs work » Needs review
StatusFileSize
new17.13 KB
new1.85 KB

Fix page cache tests.

Status: Needs review » Needs work

The last submitted patch, 47: 2968232-47.patch, failed testing. View results

ey’s picture

Status: Needs work » Closed (works as designed)

Once again a non-sense no value adding issue to kill a function. Why? Why the whole discussion, wasted man-hours? The suggested alternative hook_module_implements_alter is not a replacement, you cannot have control of the module weights implementing this hook. There's no way to make sure the execution order if multiple modules implements the same hook and try to change the execution order.

Please re-read TR's comment #2968232-6: Deprecate module_set_weight(). He listed imported use cases

I'm not convinced that this function should be removed. I also don't see any reason. Why remove something that doesn't break anything, only to break things?

borisson_’s picture

Status: Closed (works as designed) » Needs work

I'm not convinced that this function should be removed. I also don't see any reason. Why remove something that doesn't break anything, only to break things?

It's not because you disagree with an issue that it should be closed, I mean I think it needs to be discussed still.

I agree with @alexpott and @dawehner in the initial patches here, that having an explicit weight system is not the most robust and that it would be a lot better for modules to decide what other modules they should be fired after/before as that is a lot more explicit, manually setting weights can lead to conflicts and if I understand this issue correctly, we should see if we can module weight system not have explicit numbers but rather be configured on their dependencies instead, as the research by @dawehner suggests.

Back to needs work for a reroll and to fix the remaining test fails.

elber’s picture

StatusFileSize
new25.83 KB
elber’s picture

Status: Needs work » Needs review

Hi added a reroll using patch #2 as @borisson said. Please revise.

elber’s picture

StatusFileSize
new10.58 KB
smustgrave’s picture

Status: Needs review » Needs work

For CC failures.

joshf’s picture

we should see if we can module weight system not have explicit numbers but rather be configured on their dependencies instead

Is that work being done somewhere? If so, that work should block this, right? If not, this work definitely shouldn't be merged, right? Until that refactor is done, module_set_weight() is critical functionality with no replacement.

Right? I'm not missing anything?

sorlov’s picture

Status: Needs work » Needs review
StatusFileSize
new10.69 KB
new1.94 KB

Fixed issues in #53 according to https://www.drupal.org/pift-ci-job/2690801

smustgrave’s picture

Status: Needs review » Needs work

Seems to have test failure.

kim.pepper’s picture

Assigned: Unassigned » kim.pepper

I took #47 and turned it into a MR. I'm going to look at some of the test fails.

kim.pepper’s picture

Assigned: kim.pepper » Unassigned
Issue tags: +Needs framework manager review

I think we need sign-off from a framework manager that we want to remove this API.

vacho’s picture

StatusFileSize
new12.96 KB
new1.69 KB

This patch removes some another uses of the function module_set_weight

vacho’s picture

Needds to review more in deep testing fail for d7 migration

johnpitcairn’s picture

Note hook_module_implements_alter() will not work if you need your hook_preprocess_HOOK() to run after some other module's preprocess hook. Preprocess hooks are not invoked by the module handler and are not present in hook_module_implements_alter().

So removing this API will be problematic if you have a soft dependency on another module's preprocess hook, ie the module is not a requirement, but if it is present you need to preprocess something it also preprocesses, after it has done so. You don't want to declare a hard dependency in module .info. Altering module weight is the only way this will work, right?

andypost’s picture

Related issues: +#3485896: Hook ordering across OOP, procedural and with extra types i.e replace hook_module_implements_alter
nicxvan’s picture

@johnpitcairn I am pretty sure you're supposed to use this https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Render%21... for preprocess.

nicxvan’s picture

This needs a pretty thorough recollection.

hook_module_implements_alter is now deprecated so we should use the hook ordering parameters.

joshf’s picture

As elin yordanov, johnpitcairn, myself and others have pointed out, module_set_weight() does not have a replacement. hook_module_implements_alter() is not a replacement. hook_theme_registry_alter() is definitely not a replacement. There is no reason to remove this function, especially when it has no replacement. I genuinely don't understand why so many people are gunning for this function. The "problem/motivation" is simply a non sequitur:

Module weights are from a time before autoloaded code and the ability to sort by dependency.

Lots of things are "from a time before autoloaded code". Just being old does not mean it should be removed. This issue should be closed or at least postponed until a real replacement that actually handles all of its functionality is in place. Or any rationale is provided for why it should be removed.

donquixote’s picture

Module weights are still relevant

hook_module_implements_alter is now deprecated so we should use the hook ordering parameters.

We have hook ordering attributes, but the order in which these are discovered and applied still depends on module order, and thus module weight. We may introduce new metta ordering mechanisms, but for now we are still in the same situation as with hook_module_implements_alter().

There are also other subsystems (plugin discovery, service discovery, event subscribers) that depend on module order and thus module weight. Event subscribers have their own weight/priority system, but the base order is still module order.

This said: It is not clear to me that configuration is the best place to set these weights.
Instead, there could be a system to declare module weights programmatically and not store explicit weights in config.

Dependency order is brittle

It was suggested here that modules should be ordered based on their dependencies. I don't like it, I suspect it to be brittle/fragile. If a new version of a module adds or drops a dependency, suddenly event subscribers are invoked in a different order.

Unclear issue goal

Also, the issue description proposes to deprecate and remove module_set_weight(), but it does not mention removing the actual weights the in core.extension.yml configuration. But then we find arguments as if we actually plan to remove these stored weights in the configuration.

Proposal: Keep module weights, provide alternative ways to set it

What we could do is o provide a service method to set a module weight, to use instead of the function.
This could be part of ModuleInstaller, and it could have a similar effect as installing or uninstalling a module, with a container rebuild.
However, as long as install and update hooks are procedural, there is no further damage from module_set_weight() being procedural too.

We could also provide a way for a module to set its own weight in its *.info.yml, instead of having to call something in hook_install().

nicxvan’s picture

First of all, part of deprecating this is identifying use cases and providing replacements if possible. We are not trying to pull the rug out from under you. I honestly believe the use cases have been replaced.

Second, hook_module_implements_alter was explicitly for the situations identified above, you would just need some module exists checks.

Hook theme registry alter is the hook explicitly to reorder preprocess hooks.

There have not been any ordering scenarios identified that cannot be managed with modern solutions.

The only time that hmia or htra fall down is when two modules order the same implementation, but there is nothing preventing the other modules from changing their weight too causing module set weight to fail too.
The ordering parameters on hooks will resolve 99% of all cases, ReorderHook will solve 90%of the remaining.

Beyond that we can use service providers.

If you have a use case that isn't covered by these please write a test here showing that case, that would be the only thing we need to make the case to keep module set weight on module handler.

As I mentioned in my comment hmia itself has been deprecated so it's not a replacement, but the replacements should conver your cases as well.

If you can show with a test a scenario where this is needed it's easy to preserve, but we do need an explicit test for that functionality before adding it back to the public api.

As for the overarching question why.

It is because includes are hard to test, generally fairly fragile and the weight system is more of a work around than a solution. If you show your use cases we can improve the overall system.

Further we don't take module weight into account during runtime so I'm not sure it does what you expect.

nicxvan’s picture

Proposal: Keep module weights, provide alternative ways to set it

As usual I think donquixote hit the root of the issue. This no longer has any effect runtime on hook order without a container rebuild.

I'm not sure we want a runtime way to rebuild the container like that.

I've still not seen a real example where order, reorder and a service provider won't work.

Also since we now store the implementations in keyvalue there is yet another escape hatch for ordering even if it is not covered by the bc promise.

I wonder if that means we move the weight to .info and remove module set weight without replacement and mention the tools for ordering mentioned here.

That gives modules a way to set default weight and we have the other tools for ordering hooks.

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.