Index: includes/module.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/module.inc,v retrieving revision 1.165 diff -u -p -r1.165 module.inc --- includes/module.inc 5 Nov 2009 16:19:25 -0000 1.165 +++ includes/module.inc 5 Nov 2009 22:57:28 -0000 @@ -564,3 +564,67 @@ function drupal_required_modules() { return $required; } + +/** + * Return a list of modules defining a given .info file property. + * + * This function builds a list of all modules that are currently registered, + * including disabled modules. It can be used to easily find all modules that + * define a certain .info file property. For example: + * @code + * module_list_by_info(TRUE, array('required')); + * @endcode + * would list all required Drupal core modules. + * + * @code + * module_list_by_info('taxonomy', array('dependencies')); + * @endcode + * would list all modules that require Taxonomy module. + * + * @param $value + * The value to search for, for example 'TRUE'. If the last parent key defined + * in $parents is an array (such as the 'dependencies' definition), then + * $value is searched in the array of values defined by a module. + * @param $parents + * A list of .info file property keys to search $value in, for example + * array('hidden'). + * @param $simple + * (optional) Boolean whether to return human-readable module names as values + * (TRUE) or fully populated module objects including .info file information + * as values (FALSE). Defaults to TRUE. + * + * @return + * An associative array containing the machine-readable module name as key, + * and the human-readable module name as value if $simple is TRUE, or a fully + * populated module object if $simple is FALSE. + */ +function module_list_by_info($value, $parents, $simple = TRUE) { + $modules = array(); + // @todo Add a fallback to filesystem + .info file parsing if DB is unavailable? + $result = db_query("SELECT * FROM {system} WHERE type = 'module'")->fetchAllAssoc('name'); + foreach ($result as $name => $module) { + $module->info = unserialize($module->info); + $info = $module->info; + foreach ($parents as $parent) { + // If the (next) parent is not found, skip to the next module. + if (!isset($info[$parent])) { + continue 2; + } + $info = $info[$parent]; + } + // Check whether $info is an array first. + if (is_array($info)) { + if (in_array($value, $info)) { + $modules[$name] = ($simple ? $module->info['name'] : $module); + } + } + // Otherwise, look whether $info matches $value. + else { + if ($info == $value) { + $modules[$name] = ($simple ? $module->info['name'] : $module); + } + } + } + return $modules; +} +