summaryrefslogtreecommitdiff
path: root/includes
diff options
context:
space:
mode:
authorGábor Hojtsy <gabor@hojtsy.hu>2007-12-13 10:46:43 +0000
committerGábor Hojtsy <gabor@hojtsy.hu>2007-12-13 10:46:43 +0000
commit050008410d34a78d93cac155476d359669a3cad7 (patch)
treed99fdabceb910603294b92b23be24c56cb62b033 /includes
parenta64e5f38d1d662756ce9190db028773c7f90ddff (diff)
downloadbrdo-050008410d34a78d93cac155476d359669a3cad7.tar.gz
brdo-050008410d34a78d93cac155476d359669a3cad7.tar.bz2
#194010 by chx: Proper recursive dependency checking and ordering module installation in dependency order, so later installed modules can use previously installed module functionality
Diffstat (limited to 'includes')
-rw-r--r--includes/install.inc18
-rw-r--r--includes/module.inc70
2 files changed, 75 insertions, 13 deletions
diff --git a/includes/install.inc b/includes/install.inc
index d68185e91..2ce311ee5 100644
--- a/includes/install.inc
+++ b/includes/install.inc
@@ -301,6 +301,24 @@ function drupal_verify_profile($profile, $locale) {
* The modules to install.
*/
function drupal_install_modules($module_list = array()) {
+ $files = module_rebuild_cache();
+ $module_list = array_flip(array_values($module_list));
+ do {
+ $moved = FALSE;
+ foreach ($module_list as $module => $weight) {
+ $file = $files[$module];
+ if (isset($file->info['dependencies']) && is_array($file->info['dependencies'])) {
+ foreach ($file->info['dependencies'] as $dependency) {
+ if (isset($module_list[$dependency]) && $module_list[$module] < $module_list[$dependency] +1) {
+ $module_list[$module] = $module_list[$dependency] +1;
+ $moved = TRUE;
+ }
+ }
+ }
+ }
+ } while ($moved);
+ asort($module_list);
+ $module_list = array_keys($module_list);
array_filter($module_list, '_drupal_install_module');
module_enable($module_list);
}
diff --git a/includes/module.inc b/includes/module.inc
index c249a4175..651680b3b 100644
--- a/includes/module.inc
+++ b/includes/module.inc
@@ -147,30 +147,74 @@ function module_rebuild_cache() {
db_query("INSERT INTO {system} (name, info, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', %d, %d, %d)", $file->name, serialize($files[$filename]->info), 'module', $file->filename, 0, 0, $bootstrap);
}
}
- $files = _module_build_dependents($files);
+ $files = _module_build_dependencies($files);
return $files;
}
/**
- * Find dependents; modules that are required by other modules.
- * Adds an array of dependents to the $file->info array.
+ * Find dependencies any level deep and fill in dependents information too.
*
+ * If module A depends on B which in turn depends on C then this function will
+ * add C to the list of modules A depends on. This will be repeated until
+ * module A has a list of all modules it depends on. If it depends on itself,
+ * called a circular dependency, that's marked by adding a nonexistent module,
+ * called -circular- to this list of modules. Because this does not exist,
+ * it'll be impossible to switch module A on.
+ *
+ * Also we fill in a dependents array in $file->info. Using the names above,
+ * the dependents array of module B lists A.
+ *
+ * @param $files
+ * The array of filesystem objects used to rebuild the cache.
* @return
- * The list of files array with dependents added where applicable.
+ * The same array with dependencies and dependents added where applicable.
*/
-function _module_build_dependents($files) {
- foreach ($files as $filename => $file) {
- if (isset($file->info['dependencies']) && is_array($file->info['dependencies'])) {
- foreach ($file->info['dependencies'] as $dependency) {
- if (!empty($files[$dependency]) && is_array($files[$dependency]->info)) {
- if (!isset($files[$dependency]->info['dependents'])) {
- $files[$dependency]->info['dependents'] = array();
+function _module_build_dependencies($files) {
+ do {
+ $new_dependency = FALSE;
+ foreach ($files as $filename => $file) {
+ // We will modify this object (module A, see doxygen for module A, B, C).
+ $file = &$files[$filename];
+ if (isset($file->info['dependencies']) && is_array($file->info['dependencies'])) {
+ foreach ($file->info['dependencies'] as $dependency_name) {
+ // This is a nonexistent module.
+ if ($dependency_name == '-circular-') {
+ continue;
+ }
+ // $dependency_name is module B (again, see doxygen).
+ $files[$dependency_name]->info['dependents'][$filename] = $filename;
+ $dependency = $files[$dependency_name];
+ if (isset($dependency->info['dependencies']) && is_array($dependency->info['dependencies'])) {
+ // Let's find possible C modules.
+ foreach ($dependency->info['dependencies'] as $candidate) {
+ if (array_search($candidate, $file->info['dependencies']) === FALSE) {
+ // Is this a circular dependency?
+ if ($candidate == $filename) {
+ // As a module name can not contain dashes, this makes
+ // impossible to switch on the module.
+ $candidate = '-circular-';
+ // Do not display the message or add -circular- more than once.
+ if (array_search($candidate, $file->info['dependencies']) !== FALSE) {
+ continue;
+ }
+ drupal_set_message(t('%module is part of a circular dependency. This is not supported and you will not be able to switch it on.', array('%module' => $file->info['name'])), 'error');
+ }
+ else {
+ // We added a new dependency to module A. The next loop will
+ // be able to use this as "B module" thus finding even
+ // deeper dependencies.
+ $new_dependency = TRUE;
+ }
+ $file->info['dependencies'][] = $candidate;
+ }
+ }
}
- $files[$dependency]->info['dependents'][] = $filename;
}
}
+ // Don't forget to break the reference.
+ unset($file);
}
- }
+ } while ($new_dependency);
return $files;
}