diff options
author | Gábor Hojtsy <gabor@hojtsy.hu> | 2007-12-13 10:46:43 +0000 |
---|---|---|
committer | Gábor Hojtsy <gabor@hojtsy.hu> | 2007-12-13 10:46:43 +0000 |
commit | 050008410d34a78d93cac155476d359669a3cad7 (patch) | |
tree | d99fdabceb910603294b92b23be24c56cb62b033 /includes | |
parent | a64e5f38d1d662756ce9190db028773c7f90ddff (diff) | |
download | brdo-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.inc | 18 | ||||
-rw-r--r-- | includes/module.inc | 70 |
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; } |