- #1776830: Installation and uninstallation of configuration provided by a module that belongs to another module's API
- #1881630: [meta] Determine how to respond to invalid plugins (plugin dependencies)
- Disabled modules cause data to be lost or get stale/unmaintained.
- Data of disabled modules cannot be staged.
- References from or to data in disabled modules are broken.
- The key concept here is data integrity.
- All data that isn't exclusively owned by a disabled module needs to go through APIs of other modules, and those modules have to make hard decisions in order to keep the system running.
If you disable a module, data integrity is no longer maintained; i.e., disabling a module means to uninstall it step by step under the hood:
- Field types disappear; all field values get stale.
- Entity types disappear; all references are unresolvable, data is lost.
- Plugin types disappear, and along with it, all plugin IDs; all unresolvable plugin references get orphaned.
- Configuration, content, and data of disabled modules cannot be staged. The system is unable to know how to deal with the data, since it is impossible to serialize/export and import it.
- The current transitional disable » uninstall state in itself means that the API of a module is not invoked when its data is deleted, which consequently means that data integrity gets broken in enabled modules.
- Users are currently required to use the dangerous facility of disabling modules and the system makes it look as if it was a safe and sane thing to do.
- Disabled modules worked well in a time when every module was an atomic, isolated isle, mostly doing its own thing, with its own data, and its own functionality. Today, the world of Drupal modules is too abstract, too modular, and too integrated, in order for that concept to work.
Today, a "disabled module" means two totally different things:
- The module's functionality disappears from the user interface.
- The module's functionality disappears from the API (the code isn't loaded, its hook implementations aren't invoked, etc).
By merging 1) and 2) in the concept of disabled modules, instead of just doing 1), we've created a high number of critical/major bugs in the past couple of years. Some of those include:
#943772: field_delete_field() and others fail for inactive fields
#1029606: Regression: Not loading the .module file causes a fatal error when uninstalling some modules (as does loading it)
#1115510: Entity providing modules must call field_attach_delete_bundle() in hook_uninstall()
#773828: Upgrade of disabled modules fails
#895014: All fields of a node type are lost on module disable
#1017672: D6 to D7 update process permanently deletes comment bodies and other data, and throws fatal SQL errors
#1451072: Deleting a comment author while the Comment module is disabled leads to an EntityMalformedException error after it's reenabled
#1227966: Dynamically-defined blocks are never removed from the site, even when they disappear from hook_block_info()
#1887904: update_retrieve_dependencies() only considers enabled modules
#737816: user_role_grant_permissions() throws PDOException when used for a disabled module's permission or with non-existent permissions
Proposed solution A
Remove the concept of disabled modules, including its UI. All installed modules are always installed/enabled and always loaded.
hook_modules_disabled()are removed, without replacement.
hook_modules_uninstalled()remain to exist.
Consider to introduce a new facility that allows site builders/developers to temporarily remove (!= disable) a module from the system via Devel module, or even a core module.
Removing a module is piece of cake: Remove its entry from the
system.module:enabledconiguration. Flush all caches.
Make it clear in that new facility's UI that this is a dangerous operation, which may involve data loss. Educate users that modules should only be removed temporarily, for a very short time, for the sake of debugging. Clarify that users might have to restore their site to a backup created before modules got removed.
Proposed solution B
Note: Mostly obsolete, since Drupal 8 is no longer abouts hooks only. There are services, classes, plugins, etc in addition to hooks now, so this approach would have to be baked into the entire infrastructure.
- All installed modules are always loaded, not just enabled ones.
All modules can declare hook names that are essential for maintaining data integrity via
These hooks are e.g.
hook_entity_load(), etc. - Basically, anything relating to CRUD and providing "building blocks."
When invoking a hook via
module_implements(), hooks are invoked in enabled modules, and if the hook is declared as "essential", it is invoked in disabled modules as well.
So when a module is disabled, its
hook_views_data()and other "UI level" hooks don't fire, it disappears from the UI. However, if it implements some of the essential hooks, then those hooks still run.
Introduce a new "Disable module" facility that means to disable its user interface aspects only.
- All code of disabled modules remains to be loaded.
- Services of disabled modules remain to be functional.
- Routes, plugins, info hooks, etc. remain to be available.
- Access to all data items that support any notion of access is denied for all users.
...since it might no longer be necessary to maintain the active status, if all fields and storage engines would be active?