Skip to content
Snippets Groups Projects
Commit f6ed3674 authored by Marcus Eibrink-Lunzenauer's avatar Marcus Eibrink-Lunzenauer
Browse files

Throw an exception when loading a plugin that is already loading.

If a plugin used an API in its constructor that also loading the same plugin, the caching mechanism of
`PluginManager#getCachedPlugin` were bypassed and the protection against instantiating a plugin class more than once was
disabled.

This fix throws a better exception to explain the situation and provides a better way to use for example the
`Navigation` API inside of a constructor.

Fixes #4317
parent 5e017590
No related branches found
No related tags found
No related merge requests found
<?php
/**
* This exception is thrown, if a plugin is already loading.
*
* There should always only be one instance of a plugin class.
*/
class PluginAlreadyLoadingException extends Exception
{
public function __construct($pluginClassName)
{
return parent::__construct(
sprintf(
_("Plugin '%s' wird bereits geladen."),
$pluginClassName
)
);
}
}
...@@ -60,6 +60,7 @@ class PluginEngine ...@@ -60,6 +60,7 @@ class PluginEngine
if (is_object($user) && $perm->have_perm('admin')) { if (is_object($user) && $perm->have_perm('admin')) {
self::getPlugins(AdministrationPlugin::class); self::getPlugins(AdministrationPlugin::class);
} }
NotificationCenter::postNotification('PluginsDidLoad', PluginManager::getInstance());
} }
/** /**
......
...@@ -586,9 +586,14 @@ class PluginManager ...@@ -586,9 +586,14 @@ class PluginManager
$plugin_class = ''; $plugin_class = '';
$plugin = null; $plugin = null;
if (isset($this->plugin_cache[$class])) { if (array_key_exists($class, $this->plugin_cache)) {
if ($this->plugin_cache[$class] !== null) {
return $this->plugin_cache[$class]; return $this->plugin_cache[$class];
} }
throw new PluginAlreadyLoadingException($class);
}
$this->plugin_cache[$class] = null;
if ($plugin_info['core'] || !$this->isPluginsDisabled()) { if ($plugin_info['core'] || !$this->isPluginsDisabled()) {
$plugin_class = $this->loadPlugin($class, $path); $plugin_class = $this->loadPlugin($class, $path);
...@@ -596,6 +601,7 @@ class PluginManager ...@@ -596,6 +601,7 @@ class PluginManager
if ($plugin_class) { if ($plugin_class) {
$plugin = app()->get($class); $plugin = app()->get($class);
NotificationCenter::postNotification('PluginDidLoad', $this, compact('class', 'plugin'));
} }
return $this->plugin_cache[$class] = $plugin; return $this->plugin_cache[$class] = $plugin;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment