A problem my team frequently faces is revisiting a Drupal site that was developed by a third party (or developed by us in a previous lifetime) and figuring out whether modules that are enabled are really being used, and if so, where and how — to devise a strategy for site cleanup and upgrade.

Modules vary widely in functionality, and determining a module's behavior in a generic sense reduces to the Halting Problem, so this isn't really tractable to solve within a single contrib module or core — but rather it could be reasonably handled by specifying a light API in core, and asking modules to self-report their usage.

I'm defining in use as true when any of the following conditions are true:

  • The module is storing user-generated data in its own schema or variables.
  • End-users (i.e., not uid 1) have the ability (permission or other configuration) to potentially generate data the module will store.
  • Other modules depending on this module are in use.

Perhaps modules could implement a hook such as the following in the .install file, next to the similar hook_requirements():

/**
 * Report Comment module usage.
 *
 * @return
 *   An array describing the current usage of the Comment module.
 */
function comment_usage() {
  $aspects = array();

  // The Comment module is 'in use' if:
  //    - there are rows in {comment}
  //        (i.e., comments have actually been submitted, regardless of moderation)
  //    - or there are rows in {node} for which the comment field is COMMENT_NODE_OPEN
  //        (i.e., nodes exist upon which comments could be submitted)

  $comments = db_query('SELECT COUNT(*) FROM {comment}')->fetchField();
  $aspects['comments']['description'] = format_plural($count,'1 comment','@count comments');
  if ($comments) {
    $aspects['comments']['usage'] = USAGE_USED;
  }
  else {
    $aspects['comments']['usage'] = USAGE_UNUSED;
  }

  $comments_allowed_on_nodes = db_query('SELECT COUNT(*) FROM {node} WHERE comment = :open', array(':open' => COMMENT_NODE_OPEN))->fetchField();
  $aspects['comments_allowed_on_nodes']['description'] = format_plural($count,'1 commentable node','@count commentable nodes');
  if ($comments_allowed_on_nodes) {
    $aspects['comments_allowed_on_nodes']['usage'] = USAGE_USED;
  }
  else {
    $aspects['comments_allowed_on_nodes']['usage'] = USAGE_UNUSED;
  }


  $usage = array();
  $usage['comment'] = array(
    'title' => t('Comment'),
    'aspects' => $aspects,
  );
  return $usage;
}

...and then core could module_invoke_all() and summarize the information either on admin/build/modules or a MENU_LOCAL_TASK thereunder. Perhaps an additional warning could be raised when the user tries to disable or uninstall a module that's USAGE_USED.

A module-wide verdict could be established according to the following rules:

  • If any of the aspects of the module are USAGE_USED, or any of the aspects of the modules depending on this module are USAGE_USED, the module-wide verdict is USAGE_USED.
  • If none of the aspects of the module are USAGE_USED, the module-wide verdict is USAGE_UNUSED.

Thoughts?

CommentFileSizeAuthor
#7 usage-02.patch5.97 KBsmokris
#5 usage-01.patch5.12 KBsmokris
#5 usage-01.png42.68 KBsmokris

Comments

olarin’s picture

I think this is a great idea (unsurprising as a discussion between myself and smokris led to the posting of this issue), but the definition of "in use" is going to be trickier than that. For instance, a module might not store any user data but might instead affect the content or appearance of all nodes when installed - such a module could always be considered "in use" as long as it is enabled - or it might enable functionality that does not result in the storage of data specifically related to that module. Ultimately it's up to the module developer to develop a suitable definition of "in use" for their module, and to create well-written comments that will make it clear to the administrator how the module is interpreting "use". So, for instance, a module that simply alters the display of every node - as a trivial example, that inserts a static text string into every node - would always flag itself as "in use" when it's enabled, but its "in use" description would make clear to the administrator that it does not store any user data (and thus no data would be lost if it was uninstalled).

smokris’s picture

Good point. However the "modifies every node" module could be degenerate when there are zero nodes and normal users are unable to create nodes — in this case the module wouldn't be in use since it wouldn't be modifying any nodes. Of course, this particular situation is highly unlikely on a Drupal site, but I think it's a general case for which we should account — for example, with a "modifies every comment" module, there could be no comments and no commentable nodes.

Perhaps this system should be tri-state?

  • USAGE_UNUSED
  • USAGE_USED
  • USAGE_USED_STORAGE — module is in use and is persisting user data
danielb’s picture

I cannot imagine how to accomplish this completely automatically. Some modules do nothing more than implement a hook from another module, or provide extra features that another module checks for (but is not dependent on). They might just modify some value in an array, provide a new option somewhere, alter a query, change a variable value....

I wonder if there is some way to keep track of code coverage like in PHP unit testing, and if there is any module with code amount or coverage under a certain threshold, it will give more details feedback to the admin, so they may decide if this code looks important.

olarin’s picture

To be clear - we're not trying to accomplish this "completely automatically" (Steve noted in the first post that this is impossible). The idea is to provide a hook for module developers to allow their module to provide this data. However, I can see where there are times where even the module itself would be incapable of knowing whether it is currently capable of being used. Still, the idea is that, for whatever usage information the module provides, it also provides a suitable explanation of that information - for instance, if the module provides optional extra features to another module, it could keep track of and report the last time any of its functions were called upon, or how often they've been called for over the last week, month, or year, or something like that.

No matter what you do, this system would always be incomplete, for several reasons, but most importantly because you'd always have new module developers who were unaware of it and didn't implement the hooks (and veteran developers who just didn't bother). However, if even half of contrib could implement this reliably, I think it could be quite handy for admins.

Re: smokris's tri-state suggestion: that's not a bad idea, but you might want to be careful about extending the number of possible states, because you could end up overcomplicating things. As I said, it's ultimately up to the module to define - and explain to you how it defines - use. I think the most important part is that the UNUSED state be taken seriously, and that modules are careful only to mark themselves as unused if they definitely aren't contributing any functionality to the site. This state is the most important because it says you can disable or uninstall that module without consequences. The rest of the modules you'd have to take a closer look at anyway, but the more "usage" information they can provide, the better. That being said, I can see where, specifically, "used but not storing any data" would be good, as it would make it clear that disabling or uninstalling the module would affect the site but not destroy any data - maybe the state name could be a little more descriptive, like USAGE_USED_PASSIVE ("passively" in use), or something?

smokris’s picture

Status: Active » Needs review
StatusFileSize
new42.68 KB
new5.12 KB

Attached is my first attempt at an API for this, along with a screenshot of the information it provides.

The admin/build/modules page is modified as follows:

  1. Module names are now only bold if they are 'in use'.
  2. A summary of module usage information is included in the module description.

Caveat:

  • Usage information is only reported by comment.module. More module reporting to be added as the API (and our working definition of 'in use') solidifies.
  • I decided to keep it simple and stick with just two states: USAGE_UNUSED and USAGE_USED.
  • Module usage dependency (as described in the initial post) is not yet taken into account.
  • Warnings are not yet issued when disabling or uninstalling modules that are 'in use'.

Status: Needs review » Needs work

The last submitted patch failed testing.

smokris’s picture

Status: Needs work » Needs review
StatusFileSize
new5.97 KB

Take 2, trying a different diff format..

smokris’s picture

(tagging)

damien tournoud’s picture

Issue tags: -D7UX

I don't believe this is related to D7UX ;)

That idea does make sense, and delegating to the modules themselves the task of determining if they are "in use" does make sense.

But big -1 for inserting this information into the already over-stuffed module admin page. Enough is enough ;)

smokris’s picture

Damien -

Thanks for your response. Agreed about admin/build/modules being over-stuffed, but I was thinking that having this information available in proximity to the module's enable/disable checkbox would be valuable. Any suggestions about better placement?

(And sorry for misunderstanding the d7ux tag.. My user experience isn't very typical I guess.. :^] )

moshe weitzman’s picture

IMO, this does not provide enough value because modules themselves don't know. Does Views know if you any of the 12 views that are setup? Are there extra fields on a content type that are unused? What if you have 2 nodes on your site of a given type that are no longer cared about? is that content type in use? WHat about fields on a content type.

Bojhan’s picture

I am not sure that this issue should be exposed in the interface.

smokris’s picture

Moshe -

Modules themselves do know if they are storing user-generated data, and they do know whether non-admin users have permission to use the functionality they provide, which are the two factors I'm proposing that modules report for themselves (as stated in the original post).

For Views, I'm thinking the usage aspect list could look something like this:

  • n View Displays appear in active Pages, Blocks, and Feeds.
  • n Normal Views (i accessible by anonymous users, j by authenticated users).
  • n Overridden Views.
  • n Default Views enabled.

...summarizing the degree to which the administrator has made use of the module and purveyed it to normal users.

If Nodes exist, I'm thinking the Node module would be designated "in use," since disabling it would cause the data to become inaccessible, and uninstalling would remove the data. (Hypothetically — this particular question is moot since the Node module is now hidden via #319699.)

But I digress — the purpose of this feature request is not to determine usage criteria for every contrib module, but to consider providing a standardized means for modules to report this information to administrative users and eventually to provide some sensible default responses for optional core modules. Debating exactly how each contrib module should respond to this API should be the eventual domain of individual contrib issue queues.

danielb’s picture

There are plenty of modules that do not provide functionality to the user, do not store any data, and have no way of knowing if they're being used or not. A lot of modules could also believe the function they provide or data they track is useful or being used, when it is not. Sure, there are a lot of modules that can, but this would have to be an entirely optional feature for each module.

smokris’s picture

danielb -

Definitely. I'm intending this to be totally optional — contrib modules should only implement hook_usage if they have usage information to report to the administrator. Drupal's module_invoke properly handles the situation in which a module doesn't implement the hook, and my patch responds accordingly.

Currently this patch makes the assumption that an enabled module is "in use" if no usage information is reported by that module, but I'm leaning toward modifying it to just not report anything if the module doesn't implement hook_usage.

Status: Needs review » Needs work

The last submitted patch failed testing.

catch’s picture

Version: 7.x-dev » 8.x-dev

This seems more contrib territory to me, but brand new API like this is Drupal 8 now either way.

lut4rp’s picture

Issue tags: +UX

IMO this should be a part of core and a part of the UX "movement".

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

xjm’s picture

Version: 8.1.x-dev » 8.2.x-dev

So part of this is addressed in Drupal 8 by configuration dependencies. It doesn't cover the usecase of "Let modules define cases that mean they are in use", but it does already provide a mechanism to say (e.g.) "Uninstalling this module will delete all this stuff on your site!" So if a module has defined its config dependencies correctly, then at least a subset of "yep, this is used" can be identified through that.

I am not sure how this is related to UX though -- I guess maybe the UX part is "Give site admins a way to help understand what modules on admin/extend are doing or not" or such?

xjm’s picture

Also, I agree with #17 that this could be implemented in contrib to start.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.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.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.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.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.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.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.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.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.

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.

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

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

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

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

quietone’s picture

Status: Needs work » Closed (works as designed)

Two core committers think this is best done in contrib. And combined with the lack of discussion for eight years I am closing this.

Thanks for the idea!