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 tracks a list of extensions and mixins.
15 class CRM_Extension_MixinLoader
{
18 * Load all extensions and call their respective function-files.
20 * @throws \CRM_Core_Exception
22 public function run(CRM_Extension_BootCache
$bootCache, array $liveFuncFiles, array $mixInfos): void
{
25 //Do mixins run strictly once (during boot)? Or could they run twice? Or incrementally? Some edge-cases:
26 // - Mixins should make changes via dispatcher() and container(). If there's a Civi::reset(), then these things go away. We'll need to
27 // re-register. (Example scenario: unit-testing)
28 // - 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.
29 // - Mixins register for every active module. If an old module is disabled, then there may be old listeners/services lingering.
30 if (!isset(\Civi
::$statics[__CLASS__
]['done'])) {
31 \Civi
::$statics[__CLASS__
]['done'] = [];
33 $done = &\Civi
::$statics[__CLASS__
]['done'];
35 // 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.
36 // 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
37 // safe because we deduplicate.
38 static $funcsByFile = [];
39 foreach ($liveFuncFiles as $verExpr => $file) {
40 if (!isset($funcsByFile[$file])) {
41 $func = include_once $file;
42 if (is_callable($func)) {
43 $funcsByFile[$file] = $func;
46 error_log(sprintf('MixinLoader: Received invalid callback from \"%s\"', $file));
51 foreach ($mixInfos as $ext) {
52 /** @var \CRM_Extension_MixInfo $ext */
53 foreach ($ext->mixins
as $verExpr) {
54 $doneId = $ext->longName
. '::' . $verExpr;
55 if (isset($done[$doneId])) {
58 if (isset($funcsByFile[$liveFuncFiles[$verExpr]])) {
59 call_user_func($funcsByFile[$liveFuncFiles[$verExpr]], $ext, $bootCache);
63 error_log(sprintf('MixinLoader: Failed to load "%s" for extension "%s"', $verExpr, $ext->longName
));