From 17e7e2eec9fb065440b9d58dd5d4c13888b38384 Mon Sep 17 00:00:00 2001 From: Eli Lisseck Date: Thu, 26 Sep 2024 23:17:48 -0700 Subject: [PATCH 1/4] Add functions copied from Backdrop core module_enable() and module_disable() functions, and utilize them when enabling and disabling modules to notify the user of dependent and/or required modules that are being disabled/enabled in addition to the named modules. Issue #164 --- commands/projects.bee.inc | 53 +++++++++++++++++++++ includes/miscellaneous.inc | 95 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+) diff --git a/commands/projects.bee.inc b/commands/projects.bee.inc index cdf9a265..b80e17d3 100644 --- a/commands/projects.bee.inc +++ b/commands/projects.bee.inc @@ -197,6 +197,7 @@ function enable_bee_callback($arguments, $options) { $disabled_layouts = array(); $enable_dependencies = !isset($options['no-dependency-checking']); $flush_caches = FALSE; + $unique_dependencies = $unique_successful_dependencies = $arguments['projects']; foreach ($arguments['projects'] as $project) { $already_enabled = FALSE; @@ -222,9 +223,33 @@ function enable_bee_callback($arguments, $options) { break; } + if ($enable_dependencies) { + $dependencies = bee_get_required_modules($modules, [$module->name]); + // Don't report twice because we're checking projects one by one + foreach ($dependencies as $key => $dependency) { + if (!in_array($dependency, $unique_dependencies)) { + // Report info on dependencies to be enabled + bee_message(bt("The '!dependency' module will also be enabled, as it is required by the '!current' module.", [ + '!dependency' => $modules[$dependency]->info['name'], + '!current' => $module->info['name'] + ]), 'info'); + $unique_dependencies[] = $dependency; + } + } + } + // Enable module. if (module_enable(array($project), $enable_dependencies)) { $success = TRUE; + // Report success on dependencies enabled + foreach ($dependencies as $key => $enabled_module) { + if (!in_array($enabled_module, $unique_successful_dependencies)) { + bee_message(bt("The '!dependency' module was enabled.", [ + '!dependency' => $modules[$enabled_module]->info['name'], + ]), 'success'); + $unique_successful_dependencies[] = $enabled_module; + } + } } else { bee_message(bt("The '!name' module could not be enabled due to missing dependencies.", array( @@ -310,6 +335,7 @@ function disable_bee_callback($arguments, $options) { $disabled_layouts = array(); $disable_dependents = !isset($options['no-dependency-checking']); $flush_caches = FALSE; + $unique_dependencies = $unique_successful_dependencies = $arguments['projects']; foreach ($arguments['projects'] as $project) { $already_disabled = FALSE; @@ -335,8 +361,34 @@ function disable_bee_callback($arguments, $options) { break; } + if ($disable_dependents) { + $dependencies = bee_get_dependent_modules($modules, [$module->name]); + // Don't report twice because we're checking projects one by one + foreach ($dependencies as $key => $dependency) { + if (!in_array($dependency, $unique_dependencies)) { + // Report info on dependencies to be disabled + bee_message(bt("The '!dependency' module will also be disabled, as it depends on the '!current' module.", [ + '!dependency' => $modules[$dependency]->info['name'], + '!current' => $module->info['name'] + ]), 'info'); + $unique_dependencies[] = $dependency; + } + } + } + // Disable module. module_disable(array($project), $disable_dependents); + + // Report success on dependencies disabled + $dependencies = array_unique($dependencies); + foreach ($dependencies as $disabled_module) { + if (!in_array($disabled_module, $unique_successful_dependencies)) { + bee_message(bt("The '!dependency' module was disabled.", [ + '!dependency' => $modules[$disabled_module]->info['name'], + ]), 'success'); + $unique_successful_dependencies[] = $disabled_module; + } + } $success = TRUE; break; @@ -353,6 +405,7 @@ function disable_bee_callback($arguments, $options) { // Disable theme. theme_disable(array($project)); + $success = TRUE; break; diff --git a/includes/miscellaneous.inc b/includes/miscellaneous.inc index 1cd84efb..9415ae15 100644 --- a/includes/miscellaneous.inc +++ b/includes/miscellaneous.inc @@ -206,3 +206,98 @@ function bee_format_date($timestamp, $format = 'Y-m-d H:i:s T', $timezone = NULL } return $date->format($format); } + +/** + * Builds the full list of dependent modules based on input. + * This function is copied from Backdrop Core module_disable() + * until its functionality can be broken out for contrib access. + * + * @param array $module_data + * A list of all installed modules. + * @param array $module_list + * A list of modules for which to check dependencies. + * + * @return array $module_list + * A list of modules and their dependent modules. + */ +function bee_get_dependent_modules($module_data, $module_list) { + // Create an associative array with weights as values. + $module_list = array_flip(array_values($module_list)); + + $profile = backdrop_get_profile(); + // The array is iterated over manually (instead of using a foreach) because + // modules may be added to the list within the loop and we need to process + // them. + while ($module = key($module_list)) { + next($module_list); + if (!isset($module_data[$module]) || !$module_data[$module]->status) { + // This module doesn't exist or is already disabled, skip it. + unset($module_list[$module]); + continue; + } + $module_list[$module] = $module_data[$module]->sort; + + // Add dependent modules to the list, with a placeholder weight. + // The new modules will be processed as the while loop continues. + foreach ($module_data[$module]->required_by as $dependent => $dependent_data) { + if (!isset($module_list[$dependent]) && $dependent != $profile) { + $module_list[$dependent] = 0; + } + } + } + + // Sort the module list by pre-calculated weights. + asort($module_list); + $module_list = array_keys($module_list); + + return $module_list; +} + +/** + * Builds the full list of module requirements based on input. + * This function is copied from Backdrop Core module_able() + * until its functionality can be broken out for contrib access. + * + * @param array $module_data + * A list of all installed modules. + * @param array $module_list + * A list of modules for which to check requirements. + * + * @return array $module_list + * A list of modules and their required modules. + */ +function bee_get_required_modules($module_data, $module_list) { + // Create an associative array with weights as values. + $module_list = array_flip(array_values($module_list)); + + // The array is iterated over manually (instead of using a foreach) because + // modules may be added to the list within the loop and we need to process + // them. + while ($module = key($module_list)) { + next($module_list); + if (!isset($module_data[$module])) { + // This module is not found in the filesystem, abort. + return FALSE; + } + if ($module_data[$module]->status) { + // Skip already enabled modules. + unset($module_list[$module]); + continue; + } + $module_list[$module] = $module_data[$module]->sort; + + // Add dependencies to the list, with a placeholder weight. + // The new modules will be processed as the while loop continues. + foreach (array_keys($module_data[$module]->requires) as $dependency) { + if (!isset($module_list[$dependency])) { + $module_list[$dependency] = 0; + } + } + } + + // Sort the module list by pre-calculated weights. + arsort($module_list); + $module_list = array_keys($module_list); + + return $module_list; +} \ No newline at end of file From 1e49a66b82ee9672895c974bf17c44baceb92cd8 Mon Sep 17 00:00:00 2001 From: Eli Lisseck Date: Thu, 26 Sep 2024 23:34:18 -0700 Subject: [PATCH 2/4] Appease phpcs --- commands/projects.bee.inc | 16 ++++++++-------- includes/miscellaneous.inc | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/commands/projects.bee.inc b/commands/projects.bee.inc index b80e17d3..fc3fb5a0 100644 --- a/commands/projects.bee.inc +++ b/commands/projects.bee.inc @@ -225,13 +225,13 @@ function enable_bee_callback($arguments, $options) { if ($enable_dependencies) { $dependencies = bee_get_required_modules($modules, [$module->name]); - // Don't report twice because we're checking projects one by one + // Don't report twice because we're checking projects one by one. foreach ($dependencies as $key => $dependency) { if (!in_array($dependency, $unique_dependencies)) { - // Report info on dependencies to be enabled + // Report info on dependencies to be enabled. bee_message(bt("The '!dependency' module will also be enabled, as it is required by the '!current' module.", [ '!dependency' => $modules[$dependency]->info['name'], - '!current' => $module->info['name'] + '!current' => $module->info['name'], ]), 'info'); $unique_dependencies[] = $dependency; } @@ -241,7 +241,7 @@ function enable_bee_callback($arguments, $options) { // Enable module. if (module_enable(array($project), $enable_dependencies)) { $success = TRUE; - // Report success on dependencies enabled + // Report success on dependencies enabled. foreach ($dependencies as $key => $enabled_module) { if (!in_array($enabled_module, $unique_successful_dependencies)) { bee_message(bt("The '!dependency' module was enabled.", [ @@ -363,13 +363,13 @@ function disable_bee_callback($arguments, $options) { if ($disable_dependents) { $dependencies = bee_get_dependent_modules($modules, [$module->name]); - // Don't report twice because we're checking projects one by one + // Don't report twice because we're checking projects one by one. foreach ($dependencies as $key => $dependency) { if (!in_array($dependency, $unique_dependencies)) { - // Report info on dependencies to be disabled + // Report info on dependencies to be disabled. bee_message(bt("The '!dependency' module will also be disabled, as it depends on the '!current' module.", [ '!dependency' => $modules[$dependency]->info['name'], - '!current' => $module->info['name'] + '!current' => $module->info['name'], ]), 'info'); $unique_dependencies[] = $dependency; } @@ -379,7 +379,7 @@ function disable_bee_callback($arguments, $options) { // Disable module. module_disable(array($project), $disable_dependents); - // Report success on dependencies disabled + // Report success on dependencies disabled. $dependencies = array_unique($dependencies); foreach ($dependencies as $disabled_module) { if (!in_array($disabled_module, $unique_successful_dependencies)) { diff --git a/includes/miscellaneous.inc b/includes/miscellaneous.inc index 9415ae15..212c294a 100644 --- a/includes/miscellaneous.inc +++ b/includes/miscellaneous.inc @@ -220,7 +220,7 @@ function bee_format_date($timestamp, $format = 'Y-m-d H:i:s T', $timezone = NULL * @return array $module_list * A list of modules and their dependent modules. */ -function bee_get_dependent_modules($module_data, $module_list) { +function bee_get_dependent_modules(array $module_data, array $module_list) { // Create an associative array with weights as values. $module_list = array_flip(array_values($module_list)); @@ -266,7 +266,7 @@ function bee_get_dependent_modules($module_data, $module_list) { * @return array $module_list * A list of modules and their required modules. */ -function bee_get_required_modules($module_data, $module_list) { +function bee_get_required_modules(array $module_data, array $module_list) { // Create an associative array with weights as values. $module_list = array_flip(array_values($module_list)); @@ -300,4 +300,4 @@ function bee_get_required_modules($module_data, $module_list) { $module_list = array_keys($module_list); return $module_list; -} \ No newline at end of file +} From 79cf5cb644eeaf3996036d1aacbeb0cd391c1526 Mon Sep 17 00:00:00 2001 From: Eli Lisseck Date: Wed, 9 Oct 2024 16:58:54 -0700 Subject: [PATCH 3/4] Address feedback from review of pull/445: - Pull temporary code into its own file includes/dependencies.inc - Make use of bee_instant_message() where appropriate - Add clarity to user message when a dependency of a dependency is disabled - Fix code comment typo abled() -> enabled() - Updated changelog Issue #164 --- CHANGELOG.md | 6 ++- bee.php | 1 + commands/projects.bee.inc | 4 +- includes/dependencies.inc | 100 +++++++++++++++++++++++++++++++++++++ includes/miscellaneous.inc | 95 ----------------------------------- 5 files changed, 108 insertions(+), 98 deletions(-) create mode 100644 includes/dependencies.inc diff --git a/CHANGELOG.md b/CHANGELOG.md index 688ba5d7..c5dc3bef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project follows the which is based on the major version of Backdrop CMS with a semantic version system for each contributed module, theme and layout. -## [Unreleased] - 2024-09-25 +## [Unreleased] - 2024-10-09 ### Added - An option for the `db-import` command to allow import from newer MariaDB @@ -20,6 +20,10 @@ database or client does not support it. - Unhandled errors and warnings if commands run outside Backdrop root and/or before installing Backdrop. +### Changed +- Bee will now notify the user of additional modules that will be enabled or disabled +based on module dependencies when using the enable and disable commands. + ## [1.x-1.1.0] - 2024-09-07 ### Added diff --git a/bee.php b/bee.php index df2742f2..5cea220a 100755 --- a/bee.php +++ b/bee.php @@ -23,6 +23,7 @@ require_once __DIR__ . '/includes/input.inc'; require_once __DIR__ . '/includes/globals.inc'; require_once __DIR__ . '/includes/telemetry.inc'; +require_once __DIR__ . '/includes/dependencies.inc'; // Main execution code. bee_initialize_server(); diff --git a/commands/projects.bee.inc b/commands/projects.bee.inc index fc3fb5a0..487185e5 100644 --- a/commands/projects.bee.inc +++ b/commands/projects.bee.inc @@ -229,7 +229,7 @@ function enable_bee_callback($arguments, $options) { foreach ($dependencies as $key => $dependency) { if (!in_array($dependency, $unique_dependencies)) { // Report info on dependencies to be enabled. - bee_message(bt("The '!dependency' module will also be enabled, as it is required by the '!current' module.", [ + bee_instant_message(bt("The '!dependency' module will also be enabled, as it is required by the '!current' module or one of the modules it requires.", [ '!dependency' => $modules[$dependency]->info['name'], '!current' => $module->info['name'], ]), 'info'); @@ -367,7 +367,7 @@ function disable_bee_callback($arguments, $options) { foreach ($dependencies as $key => $dependency) { if (!in_array($dependency, $unique_dependencies)) { // Report info on dependencies to be disabled. - bee_message(bt("The '!dependency' module will also be disabled, as it depends on the '!current' module.", [ + bee_instant_message(bt("The '!dependency' module will also be disabled, as it depends on the '!current' module or one of the modules it requires.", [ '!dependency' => $modules[$dependency]->info['name'], '!current' => $module->info['name'], ]), 'info'); diff --git a/includes/dependencies.inc b/includes/dependencies.inc new file mode 100644 index 00000000..c1e3b99e --- /dev/null +++ b/includes/dependencies.inc @@ -0,0 +1,100 @@ +status) { + // This module doesn't exist or is already disabled, skip it. + unset($module_list[$module]); + continue; + } + $module_list[$module] = $module_data[$module]->sort; + + // Add dependent modules to the list, with a placeholder weight. + // The new modules will be processed as the while loop continues. + foreach ($module_data[$module]->required_by as $dependent => $dependent_data) { + if (!isset($module_list[$dependent]) && $dependent != $profile) { + $module_list[$dependent] = 0; + } + } + } + // Sort the module list by pre-calculated weights. + asort($module_list); + $module_list = array_keys($module_list); + + return $module_list; +} + +/** + * Builds the full list of module requirements based on input. + * This function is copied from Backdrop Core module_enable() + * until its functionality can be broken out for contrib access. + * + * @param array $module_data + * A list of all installed modules. + * @param array $module_list + * A list of modules for which to check requirements. + * + * @return array $module_list + * A list of modules and their required modules. + */ +function bee_get_required_modules(array $module_data, array $module_list) { + // Create an associative array with weights as values. + $module_list = array_flip(array_values($module_list)); + + // The array is iterated over manually (instead of using a foreach) because + // modules may be added to the list within the loop and we need to process + // them. + while ($module = key($module_list)) { + next($module_list); + if (!isset($module_data[$module])) { + // This module is not found in the filesystem, abort. + return FALSE; + } + if ($module_data[$module]->status) { + // Skip already enabled modules. + unset($module_list[$module]); + continue; + } + $module_list[$module] = $module_data[$module]->sort; + + // Add dependencies to the list, with a placeholder weight. + // The new modules will be processed as the while loop continues. + foreach (array_keys($module_data[$module]->requires) as $dependency) { + if (!isset($module_list[$dependency])) { + $module_list[$dependency] = 0; + } + } + } + + // Sort the module list by pre-calculated weights. + arsort($module_list); + $module_list = array_keys($module_list); + + return $module_list; +} diff --git a/includes/miscellaneous.inc b/includes/miscellaneous.inc index 212c294a..1cd84efb 100644 --- a/includes/miscellaneous.inc +++ b/includes/miscellaneous.inc @@ -206,98 +206,3 @@ function bee_format_date($timestamp, $format = 'Y-m-d H:i:s T', $timezone = NULL } return $date->format($format); } - -/** - * Builds the full list of dependent modules based on input. - * This function is copied from Backdrop Core module_disable() - * until its functionality can be broken out for contrib access. - * - * @param array $module_data - * A list of all installed modules. - * @param array $module_list - * A list of modules for which to check dependencies. - * - * @return array $module_list - * A list of modules and their dependent modules. - */ -function bee_get_dependent_modules(array $module_data, array $module_list) { - // Create an associative array with weights as values. - $module_list = array_flip(array_values($module_list)); - - $profile = backdrop_get_profile(); - // The array is iterated over manually (instead of using a foreach) because - // modules may be added to the list within the loop and we need to process - // them. - while ($module = key($module_list)) { - next($module_list); - if (!isset($module_data[$module]) || !$module_data[$module]->status) { - // This module doesn't exist or is already disabled, skip it. - unset($module_list[$module]); - continue; - } - $module_list[$module] = $module_data[$module]->sort; - - // Add dependent modules to the list, with a placeholder weight. - // The new modules will be processed as the while loop continues. - foreach ($module_data[$module]->required_by as $dependent => $dependent_data) { - if (!isset($module_list[$dependent]) && $dependent != $profile) { - $module_list[$dependent] = 0; - } - } - } - - // Sort the module list by pre-calculated weights. - asort($module_list); - $module_list = array_keys($module_list); - - return $module_list; -} - -/** - * Builds the full list of module requirements based on input. - * This function is copied from Backdrop Core module_able() - * until its functionality can be broken out for contrib access. - * - * @param array $module_data - * A list of all installed modules. - * @param array $module_list - * A list of modules for which to check requirements. - * - * @return array $module_list - * A list of modules and their required modules. - */ -function bee_get_required_modules(array $module_data, array $module_list) { - // Create an associative array with weights as values. - $module_list = array_flip(array_values($module_list)); - - // The array is iterated over manually (instead of using a foreach) because - // modules may be added to the list within the loop and we need to process - // them. - while ($module = key($module_list)) { - next($module_list); - if (!isset($module_data[$module])) { - // This module is not found in the filesystem, abort. - return FALSE; - } - if ($module_data[$module]->status) { - // Skip already enabled modules. - unset($module_list[$module]); - continue; - } - $module_list[$module] = $module_data[$module]->sort; - - // Add dependencies to the list, with a placeholder weight. - // The new modules will be processed as the while loop continues. - foreach (array_keys($module_data[$module]->requires) as $dependency) { - if (!isset($module_list[$dependency])) { - $module_list[$dependency] = 0; - } - } - } - - // Sort the module list by pre-calculated weights. - arsort($module_list); - $module_list = array_keys($module_list); - - return $module_list; -} From 55ccc87a7e41c956021f0f37c27ecda8bd2b9700 Mon Sep 17 00:00:00 2001 From: Martin Price Date: Thu, 10 Oct 2024 08:59:26 +0100 Subject: [PATCH 4/4] Update date --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5dc3bef..055719e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project follows the which is based on the major version of Backdrop CMS with a semantic version system for each contributed module, theme and layout. -## [Unreleased] - 2024-10-09 +## [Unreleased] - 2024-10-10 ### Added - An option for the `db-import` command to allow import from newer MariaDB