From 5959aaf7e344e16568cf0a7979a2e1fff2cc2817 Mon Sep 17 00:00:00 2001 From: colemanw Date: Sun, 26 Nov 2023 12:21:50 -0500 Subject: [PATCH] Components - Disable reverse dependencies when disabling --- CRM/Core/Component.php | 41 ++++++++++++++++++++++++++-- CRM/Extension/Upgrader/Component.php | 3 +- settings/Core.setting.php | 3 +- 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/CRM/Core/Component.php b/CRM/Core/Component.php index a837ca92ab..f9f91e8a08 100644 --- a/CRM/Core/Component.php +++ b/CRM/Core/Component.php @@ -416,7 +416,44 @@ class CRM_Core_Component { } /** - * Callback for the "enable_components" setting + * Callback for the "enable_components" setting (pre change) + * + * Before a component is disabled, disable reverse-dependencies (all extensions dependent on it). + * + * This is imperfect because it only goes one-level deep: + * it doesn't deal with any extensions that depend on the ones being disabled. + * The proper fix for that would probably be something like a CASCADE mode for + * disabling an extension with all its reverse dependencies (which would render this function moot). + * + * @param array $oldValue + * List of component names. + * @param array $newValue + * List of component names. + * + * @throws \CRM_Core_Exception. + */ + public static function preToggleComponents($oldValue, $newValue): void { + if (is_array($oldValue) && is_array($newValue)) { + $disabledComponents = array_diff($oldValue, $newValue); + } + if (empty($disabledComponents)) { + return; + } + $disabledExtensions = array_map(['CRM_Utils_String', 'convertStringToSnakeCase'], $disabledComponents); + $manager = CRM_Extension_System::singleton()->getManager(); + $extensions = $manager->getStatuses(); + foreach ($extensions as $extension => $status) { + if ($status === CRM_Extension_Manager::STATUS_INSTALLED) { + $info = $manager->mapper->keyToInfo($extension); + if (array_intersect($info->requires, $disabledExtensions)) { + $manager->disable($extension); + } + } + } + } + + /** + * Callback for the "enable_components" setting (post change) * * When a component is enabled or disabled, ensure the corresponding module-extension is also enabled/disabled. * @@ -427,7 +464,7 @@ class CRM_Core_Component { * * @throws \CRM_Core_Exception. */ - public static function onToggleComponents($oldValue, $newValue): void { + public static function postToggleComponents($oldValue, $newValue): void { if (CRM_Core_Config::isUpgradeMode()) { return; } diff --git a/CRM/Extension/Upgrader/Component.php b/CRM/Extension/Upgrader/Component.php index d4e3b07e3e..b445c964a3 100644 --- a/CRM/Extension/Upgrader/Component.php +++ b/CRM/Extension/Upgrader/Component.php @@ -1,5 +1,4 @@ NULL, 'on_change' => [ 'CRM_Case_Info::onToggleComponents', + 'CRM_Core_Component::preToggleComponents', ], 'post_change' => [ - 'CRM_Core_Component::onToggleComponents', + 'CRM_Core_Component::postToggleComponents', ], 'pseudoconstant' => [ 'callback' => 'CRM_Core_SelectValues::getComponentSelectValues', -- 2.25.1