Download & Extend

Provide API for "Is this module /really/ in use?" reporting

Project:Drupal core
Version:8.x-dev
Component:base system
Category:feature request
Priority:normal
Assigned:smokris
Status:needs work
Issue tags:admin-revamp, administer, ux

Issue Summary

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():

<?php
/**
* 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?

Comments

#1

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).

#2

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

#3

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.

#4

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?

#5

Status:active» needs review

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'.
AttachmentSizeStatusTest resultOperations
usage-01.patch5.12 KBIdleFailed: Failed to apply patch.View details | Re-test
usage-01.png42.68 KBIgnored: Check issue status.NoneNone

#6

Status:needs review» needs work

The last submitted patch failed testing.

#7

Status:needs work» needs review

Take 2, trying a different diff format..

AttachmentSizeStatusTest resultOperations
usage-02.patch5.97 KBIdleFailed: Failed to apply patch.View details | Re-test

#8

(tagging)

#9

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 ;)

#10

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.. :^] )

#11

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.

#12

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

#13

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.

#14

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.

#15

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.

#16

Status:needs review» needs work

The last submitted patch failed testing.

#17

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.

#18

Issue tags:+ux

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

nobody click here