3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
13 * The MixinLoader gets a list of extensions and mixins - then loads them.
15 class CRM_Extension_MixinLoader
{
18 * List extension-mixins that have been loaded already.
24 public function run($force = FALSE) {
25 $system = CRM_Extension_System
::singleton();
26 $cache = $system->getCache();
28 $cachedScan = $force ?
NULL : $cache->get('mixinScan');
29 $cachedBootData = $force ?
NULL : $cache->get('mixinBoot');
31 [$funcFiles, $mixInfos] = $cachedScan ?
: (new CRM_Extension_MixinScanner($system->getMapper(), $system->getManager(), TRUE))->build();
32 $bootData = $cachedBootData ?
: new CRM_Extension_BootCache();
34 $this->loadMixins($bootData, $funcFiles, $mixInfos);
36 if ($cachedScan === NULL) {
37 $cache->set('mixinScan', [$funcFiles, $mixInfos], 24 * 60 * 60);
39 if ($cachedBootData === NULL) {
41 $cache->set('mixinBoot', $bootData, 24 * 60 * 60);
46 * Load all extensions and call their respective function-files.
48 * @throws \CRM_Core_Exception
50 protected function loadMixins(CRM_Extension_BootCache
$bootCache, array $liveFuncFiles, array $mixInfos): void
{
51 // 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.
52 // 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
53 // safe because we deduplicate.
54 static $funcsByFile = [];
55 foreach ($liveFuncFiles as $verExpr => $file) {
56 if (!isset($funcsByFile[$file])) {
57 $func = include_once $file;
58 if (is_callable($func)) {
59 $funcsByFile[$file] = $func;
62 error_log(sprintf('MixinLoader: Received invalid callback from \"%s\"', $file));
67 foreach ($mixInfos as $ext) {
68 /** @var \CRM_Extension_MixInfo $ext */
69 foreach ($ext->mixins
as $verExpr) {
70 $doneId = $ext->longName
. '::' . $verExpr;
71 if (isset($this->done
[$doneId])) {
74 if (isset($funcsByFile[$liveFuncFiles[$verExpr]])) {
75 call_user_func($funcsByFile[$liveFuncFiles[$verExpr]], $ext, $bootCache);
76 $this->done
[$doneId] = 1;
79 error_log(sprintf('MixinLoader: Failed to load "%s" for extension "%s"', $verExpr, $ext->longName
));