X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=CRM%2FExtension%2FMixinLoader.php;h=edb67a0814d1a946f8051ba59fba34c1d88081a3;hb=dedb7e7a49668f62177976deeb2f9f084e91f3fa;hp=391eddf141ac8702ba52e8f4861d118dab6ef27d;hpb=1795aaf579e610cec8bb775bc0c0cf119832a662;p=civicrm-core.git diff --git a/CRM/Extension/MixinLoader.php b/CRM/Extension/MixinLoader.php index 391eddf141..edb67a0814 100644 --- a/CRM/Extension/MixinLoader.php +++ b/CRM/Extension/MixinLoader.php @@ -10,28 +10,44 @@ */ /** - * The MixinLoader tracks a list of extensions and mixins. + * The MixinLoader gets a list of extensions and mixins - then loads them. */ class CRM_Extension_MixinLoader { /** - * Load all extensions and call their respective function-files. + * List extension-mixins that have been loaded already. * - * @throws \CRM_Core_Exception + * @var array */ - public function run(CRM_Extension_BootCache $bootCache, array $liveFuncFiles, array $mixInfos): void { - // == WIP == - // - //Do mixins run strictly once (during boot)? Or could they run twice? Or incrementally? Some edge-cases: - // - Mixins should make changes via dispatcher() and container(). If there's a Civi::reset(), then these things go away. We'll need to - // re-register. (Example scenario: unit-testing) - // - Mixins register for every active module. If a new module is enabled, then we haven't had a chance to run on the new extension. - // - Mixins register for every active module. If an old module is disabled, then there may be old listeners/services lingering. - if (!isset(\Civi::$statics[__CLASS__]['done'])) { - \Civi::$statics[__CLASS__]['done'] = []; + protected $done = []; + + public function run($force = FALSE) { + $system = CRM_Extension_System::singleton(); + $cache = $system->getCache(); + + $cachedScan = $force ? NULL : $cache->get('mixinScan'); + $cachedBootData = $force ? NULL : $cache->get('mixinBoot'); + + [$funcFiles, $mixInfos] = $cachedScan ?: (new CRM_Extension_MixinScanner($system->getMapper(), $system->getManager(), TRUE))->build(); + $bootData = $cachedBootData ?: new CRM_Extension_BootCache(); + + $this->loadMixins($bootData, $funcFiles, $mixInfos); + + if ($cachedScan === NULL) { + $cache->set('mixinScan', [$funcFiles, $mixInfos], 24 * 60 * 60); } - $done = &\Civi::$statics[__CLASS__]['done']; + if ($cachedBootData === NULL) { + $bootData->lock(); + $cache->set('mixinBoot', $bootData, 24 * 60 * 60); + } + } + /** + * Load all extensions and call their respective function-files. + * + * @throws \CRM_Core_Exception + */ + protected function loadMixins(CRM_Extension_BootCache $bootCache, array $liveFuncFiles, array $mixInfos): void { // Read each live func-file once, even if there's some kind of Civi::reset(). This avoids hard-crash where the func-file registers a PHP class/function/interface. // Granted, PHP symbols require care to avoid conflicts between `mymixin@1.0` and `mymixin@2.0` -- but you can deal with that. For minor-versions, you're // safe because we deduplicate. @@ -52,12 +68,12 @@ class CRM_Extension_MixinLoader { /** @var \CRM_Extension_MixInfo $ext */ foreach ($ext->mixins as $verExpr) { $doneId = $ext->longName . '::' . $verExpr; - if (isset($done[$doneId])) { + if (isset($this->done[$doneId])) { continue; } if (isset($funcsByFile[$liveFuncFiles[$verExpr]])) { call_user_func($funcsByFile[$liveFuncFiles[$verExpr]], $ext, $bootCache); - $done[$doneId] = 1; + $this->done[$doneId] = 1; } else { error_log(sprintf('MixinLoader: Failed to load "%s" for extension "%s"', $verExpr, $ext->longName));