diff --git a/CRM/Core/Component.php b/CRM/Core/Component.php
index a837ca92ab83..f9f91e8a086c 100644
--- a/CRM/Core/Component.php
+++ b/CRM/Core/Component.php
@@ -416,7 +416,44 @@ public static function isEnabled(string $component): bool {
}
/**
- * 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 @@ public static function isEnabled(string $component): bool {
*
* @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 d4e3b07e3e63..b445c964a3ad 100644
--- a/CRM/Extension/Upgrader/Component.php
+++ b/CRM/Extension/Upgrader/Component.php
@@ -1,5 +1,4 @@
setting-php@1.0.0
+
+ civi_contribute
+
CRM/Financialacls
23.02.1
diff --git a/settings/Core.setting.php b/settings/Core.setting.php
index 9106338b1eb9..2864da74d7ba 100644
--- a/settings/Core.setting.php
+++ b/settings/Core.setting.php
@@ -800,9 +800,10 @@
'help_text' => 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',