From: Tim Otten Date: Fri, 17 Jun 2022 00:00:48 +0000 (-0700) Subject: (dev/core#3660) Ensure that rebuildMenuAndCaches has current mixins+classloaders X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=c24dd7db;p=civicrm-core.git (dev/core#3660) Ensure that rebuildMenuAndCaches has current mixins+classloaders Overview -------- This fixes an issue in transitioning from `hook_managed` to `mixin/mgd-php@1`, wherein managed-entities are briefly deleted (but later recreated). Steps to Reproduce ------------------ 1. (Web) Install an extension with a revision that uses `hook_managed` 2. (CLI) Switch the extension to a revision that uses `mixin/mgd-php@1` 3. (CLI) View contents of `civicrm_managed` 4. (Web) Run `civicrm/menu/rebuild` 5. (CLI) View contents of `civicrm_managed` 6. (Web) Run `civicrm/menu/rebuild` 7. (CLI) View contents of `civicrm_managed` Before ------ While processing step 4 (`civicrm/menu/rebuild`), it fails to run the hooks for `mgd-php`. Consequently, the list of managed-entities is lost and will disappear at step 5. After ----- While processing step 4 (`civicrm/menu/rebuild`), it activates the hooks for `mgd-php`. Technical Details ------------------ When processing `civicrm/menu/rebuild`, there are a couple big substeps: * `Civi\Core\Container::boot()` - During this process, it loads extensions. As usual, this reads cached metadata, sets up classloaders, sets up mixins/hooks, etc. * `CRM_Core_Invoke::rebuildMenuAndCaches()` - During this process, it clears out caches and rebuilds several things (menus, managed-entities, etc). The problem is this: * The cache used during `boot()` has stale metadata (specifically, `civicrm_cache` has old values of `mixinScan` and `mixinBoot`). So it doesn't setup any new mixins/hooks. * Then `rebuildMenuAndCaches()` depends on the mixins/hooks that are already setup. While the function does clear persistent caches, it assumes that the PHP runtime environment is up-to-spec. But it's not -- becuase our hooks were based on the caches. The patch uses the same `refresh()` mechanism as the extension-administration subsystem (which has to reset the classloaders+mixins after enabling or disabling an extension). --- diff --git a/CRM/Core/Invoke.php b/CRM/Core/Invoke.php index 1255fd3285..c2d8d5ac71 100644 --- a/CRM/Core/Invoke.php +++ b/CRM/Core/Invoke.php @@ -379,6 +379,10 @@ class CRM_Core_Invoke { $config = CRM_Core_Config::singleton(); $config->clearModuleList(); + // dev/core#3660 - Activate any new classloaders/mixins/etc before re-hydrating any data-structures. + CRM_Extension_System::singleton()->getClassLoader()->refresh(); + CRM_Extension_System::singleton()->getMixinLoader()->run(TRUE); + // also cleanup all caches $config->cleanupCaches($sessionReset || CRM_Utils_Request::retrieve('sessionReset', 'Boolean', CRM_Core_DAO::$_nullObject, FALSE, 0, 'GET'));