diff --git a/app/Config/Events.php b/app/Config/Events.php
index 0c0ef5b44..26fe93841 100644
--- a/app/Config/Events.php
+++ b/app/Config/Events.php
@@ -8,7 +8,6 @@ use CodeIgniter\HotReloader\HotReloader;
use App\Events\Db_log;
use App\Events\Load_config;
use App\Events\Method;
-use App\Libraries\Plugins\PluginManager;
/*
* --------------------------------------------------------------------
@@ -57,14 +56,7 @@ Events::on('pre_system', static function (): void {
});
Events::on('post_controller_constructor', static function (): void {
- $pluginManager = new PluginManager();
-
- if ($pluginManager->canLoadPlugins()) {
- $pluginManager->discoverPlugins();
- $pluginManager->registerPluginEvents();
- } else {
- log_message('debug', 'Plugin loading is disabled until after migration has been run.');
- }
+ service('pluginManager');
}, 10);
$config = new Load_config();
diff --git a/app/Config/Services.php b/app/Config/Services.php
index fb4d7bc89..dd06674aa 100644
--- a/app/Config/Services.php
+++ b/app/Config/Services.php
@@ -3,6 +3,7 @@
namespace Config;
use App\Libraries\MY_Language;
+use App\Libraries\Plugins\PluginManager;
use Locale;
use HTMLPurifier;
use HTMLPurifier_Config;
@@ -61,6 +62,24 @@ class Services extends BaseService
return new MY_Language($locale);
}
+ public static function pluginManager(bool $getShared = true): PluginManager
+ {
+ if ($getShared) {
+ return static::getSharedInstance('pluginManager');
+ }
+
+ $manager = new PluginManager();
+
+ if ($manager->canLoadPlugins()) {
+ $manager->discoverPlugins();
+ $manager->registerPluginEvents();
+ } else {
+ log_message('debug', 'PluginManager: skipping init, plugin_config table not found.');
+ }
+
+ return $manager;
+ }
+
private static HTMLPurifier $htmlPurifier;
public static function htmlPurifier($getShared = true): object
diff --git a/app/Controllers/Plugins.php b/app/Controllers/Plugins.php
index ce133351e..4c7d485f2 100644
--- a/app/Controllers/Plugins.php
+++ b/app/Controllers/Plugins.php
@@ -12,8 +12,7 @@ class Plugins extends Secure_Controller
public function __construct()
{
parent::__construct('plugins');
- $this->pluginManager = new PluginManager();
- $this->pluginManager->discoverPlugins();
+ $this->pluginManager = service('pluginManager');
}
public function getIndex(): string
diff --git a/app/Libraries/Plugins/BasePlugin.php b/app/Libraries/Plugins/BasePlugin.php
index b4c9b097d..c9290dd28 100644
--- a/app/Libraries/Plugins/BasePlugin.php
+++ b/app/Libraries/Plugins/BasePlugin.php
@@ -25,7 +25,7 @@ abstract class BasePlugin implements PluginInterface
public function isEnabled(): bool
{
- $enabled = $this->configModel->getValue("{$this->getPluginId()}_enabled");
+ $enabled = $this->configModel->getValue("{$this->getPluginId()}__enabled");
return $enabled === '1' || $enabled === 'true';
}
diff --git a/app/Libraries/Plugins/PluginManager.php b/app/Libraries/Plugins/PluginManager.php
index b4cac009a..9fa4a2492 100644
--- a/app/Libraries/Plugins/PluginManager.php
+++ b/app/Libraries/Plugins/PluginManager.php
@@ -16,6 +16,8 @@ class PluginManager
private PluginConfig $configModel;
private string $pluginsPath;
private bool $eventsRegistered = false;
+ private static bool $discovered = false;
+ private static array $registeredNamespaces = [];
public function __construct()
{
@@ -25,6 +27,11 @@ class PluginManager
public function discoverPlugins(): void
{
+ if (self::$discovered) {
+ log_message('debug', 'Plugin discovery already completed, skipping');
+ return;
+ }
+
if (!is_dir($this->pluginsPath)) {
log_message('debug', 'Plugins directory does not exist: ' . $this->pluginsPath);
return;
@@ -59,15 +66,14 @@ class PluginManager
$this->plugins[$plugin->getPluginId()] = $plugin;
if ($this->isPluginEnabled($plugin->getPluginId())) {
- $loader = Services::autoloader();
- $loader->addNamespace(
- "App\\Plugins\\{$plugin->getPluginId()}",
- APPPATH . "Plugins/{$plugin->getPluginId()}"
- );
+ $this->registerNamespace($plugin->getPluginId());
}
log_message('debug', "Discovered plugin: {$plugin->getPluginName()}");
}
+
+ self::$discovered = true;
+ log_message('debug', 'Plugin discovery completed');
}
private function getClassNameFromFile(string $pathname): ?string
@@ -141,11 +147,7 @@ class PluginManager
$this->configModel->setValue($this->getEnabledKey($pluginId), '1');
- $loader = Services::autoloader();
- $loader->addNamespace(
- "App\\Plugins\\{$pluginId}",
- APPPATH . "Plugins/{$pluginId}"
- );
+ $this->registerNamespace($pluginId);
log_message('info', "Plugin enabled: {$pluginId}");
@@ -193,6 +195,24 @@ class PluginManager
return $this->configModel->setValue("{$pluginId}_{$key}", $value);
}
+ public static function resetStatic(): void
+ {
+ self::$discovered = false;
+ self::$registeredNamespaces = [];
+ }
+
+ private function registerNamespace(string $pluginId): void
+ {
+ $namespace = "App\\Plugins\\{$pluginId}";
+
+ if (!in_array($namespace, self::$registeredNamespaces, true)) {
+ $loader = Services::autoloader();
+ $loader->addNamespace($namespace, APPPATH . "Plugins/{$pluginId}");
+ self::$registeredNamespaces[] = $namespace;
+ log_message('debug', "Registered namespace for plugin: {$pluginId}");
+ }
+ }
+
private function getEnabledKey(string $pluginId): string
{
return "{$pluginId}__enabled";
diff --git a/app/Plugins/MailchimpPlugin/MailchimpPlugin.php b/app/Plugins/MailchimpPlugin/MailchimpPlugin.php
index 298747ceb..f103f8191 100644
--- a/app/Plugins/MailchimpPlugin/MailchimpPlugin.php
+++ b/app/Plugins/MailchimpPlugin/MailchimpPlugin.php
@@ -60,7 +60,6 @@ class MailchimpPlugin extends BasePlugin
$this->setSetting('api_key', '');
$this->setSetting('list_id', '');
$this->setSetting('sync_on_save', '1');
- $this->setSetting('enabled', '0');
return true;
}
diff --git a/app/Views/plugins/manage.php b/app/Views/plugins/manage.php
index f4928ce04..130bf73d0 100644
--- a/app/Views/plugins/manage.php
+++ b/app/Views/plugins/manage.php
@@ -55,7 +55,7 @@
= lang('Plugins.enable') ?>
-
+