Pico::loadPlugins(): Add plugin blacklist and allow disabling local plugins

This commit is contained in:
Daniel Rudolf 2017-10-13 21:02:51 +02:00
parent 867f81a443
commit 709416328a
No known key found for this signature in database
GPG key ID: A061F02CD8DE4538

View file

@ -135,6 +135,15 @@ class Pico
*/ */
protected $nativePlugins = array(); protected $nativePlugins = array();
/**
* Boolean indicating whether Pico loads plugins from the filesystem
*
* @see Pico::loadPlugins()
* @see Pico::loadLocalPlugins()
* @var bool
*/
protected $enableLocalPlugins = true;
/** /**
* Current configuration of this Pico instance * Current configuration of this Pico instance
* *
@ -276,18 +285,21 @@ class Pico
* *
* To carry out all the processing in Pico, call {@see Pico::run()}. * To carry out all the processing in Pico, call {@see Pico::run()}.
* *
* @param string $rootDir root directory of this Pico instance * @param string $rootDir root dir of this Pico instance
* @param string $configDir config directory of this Pico instance * @param string $configDir config dir of this Pico instance
* @param string $pluginsDir plugins directory of this Pico instance * @param string $pluginsDir plugins dir of this Pico instance
* @param string $themesDir themes directory of this Pico instance * @param string $themesDir themes dir of this Pico instance
* @param bool $enableLocalPlugins enables (TRUE; default) or disables
* (FALSE) loading plugins from the filesystem
*/ */
public function __construct($rootDir, $configDir, $pluginsDir, $themesDir) public function __construct($rootDir, $configDir, $pluginsDir, $themesDir, $enableLocalPlugins = true)
{ {
$this->rootDir = rtrim($rootDir, '/\\') . '/'; $this->rootDir = rtrim($rootDir, '/\\') . '/';
$this->vendorDir = dirname(__DIR__) . '/'; $this->vendorDir = dirname(__DIR__) . '/';
$this->configDir = $this->getAbsolutePath($configDir); $this->configDir = $this->getAbsolutePath($configDir);
$this->pluginsDir = $this->getAbsolutePath($pluginsDir); $this->pluginsDir = $this->getAbsolutePath($pluginsDir);
$this->themesDir = $this->getAbsolutePath($themesDir); $this->themesDir = $this->getAbsolutePath($themesDir);
$this->enableLocalPlugins = (bool) $enableLocalPlugins;
} }
/** /**
@ -447,7 +459,9 @@ class Pico
* See {@see Pico::loadComposerPlugins()} for details about plugins loaded * See {@see Pico::loadComposerPlugins()} for details about plugins loaded
* from `vendor/pico-plugin.php` (i.e. plugins that were installed using * from `vendor/pico-plugin.php` (i.e. plugins that were installed using
* `composer`), and {@see Pico::loadLocalPlugins()} for details about * `composer`), and {@see Pico::loadLocalPlugins()} for details about
* plugins installed to {@see Pico::$pluginsDir}. * plugins installed to {@see Pico::$pluginsDir}. Pico loads plugins from
* the filesystem only if {@see Pico::$enableLocalPlugins} is set to TRUE
* (this is the default).
* *
* Pico always loads plugins from `vendor/pico-plugin.php` first and * Pico always loads plugins from `vendor/pico-plugin.php` first and
* ignores conflicting plugins in {@see Pico::$pluginsDir}. * ignores conflicting plugins in {@see Pico::$pluginsDir}.
@ -464,8 +478,11 @@ class Pico
*/ */
protected function loadPlugins() protected function loadPlugins()
{ {
$this->loadComposerPlugins(); $composerPlugins = $this->loadComposerPlugins();
$this->loadLocalPlugins();
if ($this->enableLocalPlugins) {
$this->loadLocalPlugins($composerPlugins);
}
} }
/** /**
@ -477,9 +494,10 @@ class Pico
* *
* @see Pico::loadPlugins() * @see Pico::loadPlugins()
* @see Pico::loadLocalPlugins() * @see Pico::loadLocalPlugins()
* @return void * @param string[] $pluginBlacklist class names of plugins not to load
* @return string[] installer names of the loaded plugins
*/ */
protected function loadComposerPlugins() protected function loadComposerPlugins(array $pluginBlacklist = array())
{ {
$composerPlugins = array(); $composerPlugins = array();
if (file_exists($this->getVendorDir() . 'vendor/pico-plugin.php')) { if (file_exists($this->getVendorDir() . 'vendor/pico-plugin.php')) {
@ -490,12 +508,17 @@ class Pico
$composerPlugins = require($this->getVendorDir() . '../../../vendor/pico-plugin.php') ?: array(); $composerPlugins = require($this->getVendorDir() . '../../../vendor/pico-plugin.php') ?: array();
} }
foreach ($composerPlugins as $package => $classNames) { $pluginBlacklist = array_fill_keys($pluginBlacklist, true);
foreach ($classNames as $className) {
$loadedPlugins = array();
foreach ($composerPlugins as $package => $pluginData) {
$loadedPlugins[] = $pluginData['installerName'];
foreach ($pluginData['classNames'] as $className) {
$plugin = new $className($this); $plugin = new $className($this);
$className = get_class($plugin); $className = get_class($plugin);
if (isset($this->plugins[$className])) { if (isset($this->plugins[$className]) || isset($pluginBlacklist[$className])) {
continue; continue;
} }
@ -513,6 +536,8 @@ class Pico
} }
} }
} }
return $loadedPlugins;
} }
/** /**
@ -535,10 +560,11 @@ class Pico
* *
* @see Pico::loadPlugins() * @see Pico::loadPlugins()
* @see Pico::loadComposerPlugins() * @see Pico::loadComposerPlugins()
* @param string[] $pluginBlacklist class names of plugins not to load
* @return void * @return void
* @throws RuntimeException thrown when a plugin couldn't be loaded * @throws RuntimeException thrown when a plugin couldn't be loaded
*/ */
protected function loadLocalPlugins() protected function loadLocalPlugins(array $pluginBlacklist = array())
{ {
// scope isolated require() // scope isolated require()
$includeClosure = function ($pluginFile) { $includeClosure = function ($pluginFile) {
@ -548,7 +574,8 @@ class Pico
$includeClosure = $includeClosure->bindTo(null); $includeClosure = $includeClosure->bindTo(null);
} }
$pluginFiles = array(); $pluginBlacklist = array_fill_keys($pluginBlacklist, true);
$files = scandir($this->getPluginsDir()) ?: array(); $files = scandir($this->getPluginsDir()) ?: array();
foreach ($files as $file) { foreach ($files as $file) {
if ($file[0] === '.') { if ($file[0] === '.') {
@ -572,7 +599,7 @@ class Pico
throw new RuntimeException("Unable to load plugin from '" . $file . "': Not a valid plugin file"); throw new RuntimeException("Unable to load plugin from '" . $file . "': Not a valid plugin file");
} }
if (isset($this->plugins[$className])) { if (isset($this->plugins[$className]) || isset($pluginBlacklist[$className])) {
continue; continue;
} }