Skip to content

Commit

Permalink
CvPlugins - Add a CiviCRM event to let extensions load plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
totten committed Sep 24, 2024
1 parent f557b68 commit ed59c8f
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 2 deletions.
35 changes: 33 additions & 2 deletions lib/src/CvPlugins.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ class CvPlugins {
* Ex: ['appName' => 'cv', 'appVersion' => '0.3.50']
*/
public function init(array $pluginEnv) {
require_once __DIR__ . '/cvplugin_loader.php';

$this->pluginEnv = $pluginEnv;
if (getenv('CV_PLUGIN_PATH')) {
$this->paths = explode(PATH_SEPARATOR, getenv('CV_PLUGIN_PATH'));
Expand Down Expand Up @@ -68,11 +70,28 @@ public function init(array $pluginEnv) {
$this->loadAll($plugins);
}

/**
* Like CvPlugins::init(), this searches for and loads plugins. This is effectively
* the second phase of plugin-loading. It focuses on CiviCRM extensions
* which embed extra plugins.
*/
public function initExtensions(): void {
$plugins = [];
$event = GenericHookEvent::create([
'plugins' => &$plugins,
'pluginEnv' => $this->pluginEnv + ['protocol' => self::PROTOCOL_VERSION],
]);
\Civi::dispatcher()->dispatch('civi.cv-lib.plugins', $event);

$this->loadAll($plugins);
}

/**
* @param array $plugins
* Ex: ['helloworld' => '/etc/cv/plugin/helloworld.php']
* @internal
*/
protected function loadAll(array $plugins): void {
public function loadAll(array $plugins): void {
ksort($plugins);
foreach ($plugins as $pluginName => $pluginFile) {
$this->load($this->pluginEnv + [
Expand All @@ -90,9 +109,21 @@ protected function loadAll(array $plugins): void {
* - version: Protocol version (ex: "1")
* - name: Basenemae of the plugin (eg `hello.php`)
* - file: Logic filename (eg `/etc/cv/plugin/hello.php`)
*
* @return void
* @internal
*/
protected function load(array $CV_PLUGIN) {
public function load(array $CV_PLUGIN) {
if (isset($this->plugins[$CV_PLUGIN['name']])) {
if ($this->plugins[$CV_PLUGIN['name']] === $CV_PLUGIN['file']) {
return;
}
else {
fprintf(STDERR, "WARNING: Plugin %s has already been loaded from %s. Ignore duplicate %s.\n",
$CV_PLUGIN['name'], $this->plugins[$CV_PLUGIN['name']], $CV_PLUGIN['file']);
return;
}
}
$this->plugins[$CV_PLUGIN['name']] = $CV_PLUGIN['file'];
include $CV_PLUGIN['file'];
}
Expand Down
27 changes: 27 additions & 0 deletions lib/src/cvplugin_loader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

use Civi\Cv\Cv;

if (defined('CIVICRM_DSN')) {
fprintf(STDERR, "WARNING: Cv plugins initialized after CiviCRM booted. Second stage loading may not work as expected.\n");
}

// Define the hook listener before Civi boots.
$GLOBALS['CIVICRM_FORCE_MODULES'][] = 'cvplugin_loader';

/**
* @param $config
* @param array|NULL $flags
* Only defined on 5.65+.
* @return void
* @see \CRM_Utils_Hook::config()
*/
function cvplugin_loader_civicrm_config($config, $flags = NULL): void {
static $loaded = FALSE;
if (!$loaded) {
if ($flags === NULL || !empty($flags['civicrm'])) {
$loaded = TRUE;
Cv::plugins()->initExtensions();
}
}
}

0 comments on commit ed59c8f

Please # to comment.