There are modules (e.g., Entity Plus, Entity UI) that didn't exist in D7 and are required by Backdrop versions of D7 modules. Examples of B modules that need Entity Plus (E+, for short), for example, are Rules, Ubercart, and the modules in this list.

A problem arises when upgrading a D7 site that uses those modules. If the user merely adds the E+ module to the B codebase (the logical thing to do), when trying to upgrade the site, B sees that there was no enabled version of the D7 module, so it assumes the B version is not enabled, and therefore disables it and all of the downstream modules (like Rules, Ubercart, and their submodules), and so doesn't run their update hooks, and the user ends up with a site with only partially upgraded and a bunch of disabled modules. (This is particularly problematic with Ubercart, which has about 20 submodules, plus further contrib sub-submodules.)

The current solution, which has been recommended for Rules and Ubercart for a while, has been stub modules, basically fake/empty D7 modules that you enable before performing the upgrade. See here and here.

More recently, it was suggested to enable the B modules in an update hook. We can't actually do this during hook_update_N(), because by the time that would get called, the damage is done: the downstream modules are already disabled, so their update hooks don't get called. However, it can be done during hook_requirements('update') (suggested example here, PR that does this for Rules module here). So that works, but it's not ideal, for a couple of reasons:

  • If this is the preferred solution, (nearly) the same chunk of code would need to be implemented by each contrib module that requires E+, E-UI, etc.
  • More importantly, if we enable the required module by calling module_enable() as part of hook_requirements() (as in the PR), this results in calling hook_enable() for the module, and hook_modules_enabled() for all other modules, and this happens before the whole series of hook_update_N() calls has happened; so these hooks, which might be expecting fully-configured B modules, will be fired before the B modules are upgraded from D7.
  • Also, if multiple modules are doing this, there's no particular control over the order in which the modules are enabled. (If that matters.)

So, it would be nice if Backdrop core was able to provide support for this situation: when an enabled D7 module is being upgraded to B and depends on a B module that didn't exist in D7.

Some possibilities:

  • Add a module_enable_lite() function that lets the client module "enable" the dependency B-only module (i.e., create the appropriate entry in the system table) without firing the enable hooks, for use by the contrib modules in their hook_requirements() call.
  • Add a new updating hook that lets client modules declare dependency B-only modules that ought to be treated as enabled if they exist in the codebase, and then core handles the "lite" enablement of the B-only modules.

We could also just put E+ (which is currently the most popular contrib module) and E-UI into core, so that they're already enabled in new installs. (But this wouldn't be a total solution; B Ubercart still has a B-only module that isn't in D7.)

This issue arose from discussions and issues with @argiepiano and @laryn; please add anything I've missed, and everyone else, please give your thoughts. (H/T also to @indigoxela, who raised the issue for Rules.)

Advocate: @bugfolder PR:

GitHub Issue #: