Offer the possibility to define version compatibility from plugins

This commit is contained in:
Frederic Guillot
2017-01-08 17:02:31 -05:00
parent 17ac414d74
commit 07f9700179
11 changed files with 186 additions and 28 deletions

View File

@@ -23,6 +23,7 @@ class PluginController extends BaseController
{
$this->response->html($this->helper->layout->plugin('plugin/show', array(
'plugins' => $this->pluginLoader->getPlugins(),
'incompatible_plugins' => $this->pluginLoader->getIncompatiblePlugins(),
'title' => t('Installed Plugins'),
'is_configured' => Installer::isConfigured(),
)));

View File

@@ -131,4 +131,17 @@ abstract class Base extends \Kanboard\Core\Base
{
return '';
}
/**
* Get application compatibility version
*
* Examples: >=1.0.36, 1.0.37, APP_VERSION
*
* @access public
* @return string
*/
public function getCompatibleVersion()
{
return APP_VERSION;
}
}

View File

@@ -36,18 +36,7 @@ class Directory extends BaseCore
*/
public function isCompatible(array $plugin, $appVersion = APP_VERSION)
{
if (strpos($appVersion, 'master') !== false) {
return true;
}
foreach (array('>=', '>') as $operator) {
if (strpos($plugin['compatible_version'], $operator) === 0) {
$pluginVersion = substr($plugin['compatible_version'], strlen($operator));
return version_compare($appVersion, $pluginVersion, $operator);
}
}
return $plugin['compatible_version'] === $appVersion;
return Version::isCompatible($plugin['compatible_version'], $appVersion);
}
/**

View File

@@ -4,6 +4,7 @@ namespace Kanboard\Core\Plugin;
use Composer\Autoload\ClassLoader;
use DirectoryIterator;
use Exception;
use LogicException;
use Kanboard\Core\Tool;
@@ -22,6 +23,7 @@ class Loader extends \Kanboard\Core\Base
* @var array
*/
protected $plugins = array();
protected $incompatiblePlugins = array();
/**
* Get list of loaded plugins
@@ -34,6 +36,17 @@ class Loader extends \Kanboard\Core\Base
return $this->plugins;
}
/**
* Get list of not compatible plugins
*
* @access public
* @return Base[]
*/
public function getIncompatiblePlugins()
{
return $this->incompatiblePlugins;
}
/**
* Scan plugin folder and load plugins
*
@@ -51,8 +64,7 @@ class Loader extends \Kanboard\Core\Base
foreach ($dir as $fileInfo) {
if ($fileInfo->isDir() && substr($fileInfo->getFilename(), 0, 1) !== '.') {
$pluginName = $fileInfo->getFilename();
$this->loadSchema($pluginName);
$this->initializePlugin($pluginName, $this->loadPlugin($pluginName));
$this->initializePlugin($pluginName);
}
}
}
@@ -85,7 +97,7 @@ class Loader extends \Kanboard\Core\Base
$className = '\Kanboard\Plugin\\'.$pluginName.'\\Plugin';
if (! class_exists($className)) {
throw new LogicException('Unable to load this plugin class '.$className);
throw new LogicException('Unable to load this plugin class: '.$className);
}
return new $className($this->container);
@@ -96,18 +108,30 @@ class Loader extends \Kanboard\Core\Base
*
* @access public
* @param string $pluginName
* @param Base $plugin
*/
public function initializePlugin($pluginName, Base $plugin)
public function initializePlugin($pluginName)
{
if (method_exists($plugin, 'onStartup')) {
$this->dispatcher->addListener('app.bootstrap', array($plugin, 'onStartup'));
try {
$plugin = $this->loadPlugin($pluginName);
if (Version::isCompatible($plugin->getCompatibleVersion(), APP_VERSION)) {
$this->loadSchema($pluginName);
if (method_exists($plugin, 'onStartup')) {
$this->dispatcher->addListener('app.bootstrap', array($plugin, 'onStartup'));
}
Tool::buildDIC($this->container, $plugin->getClasses());
Tool::buildDICHelpers($this->container, $plugin->getHelpers());
$plugin->initialize();
$this->plugins[$pluginName] = $plugin;
} else {
$this->incompatiblePlugins[$pluginName] = $plugin;
$this->logger->error($pluginName.' is not compatible with this version');
}
} catch (Exception $e) {
$this->logger->critical($pluginName.': '.$e->getMessage());
}
Tool::buildDIC($this->container, $plugin->getClasses());
Tool::buildDICHelpers($this->container, $plugin->getHelpers());
$plugin->initialize();
$this->plugins[$pluginName] = $plugin;
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace Kanboard\Core\Plugin;
use Exception;
/**
* Class PluginException
*
* @package Kanboard\Core\Plugin
* @author Frederic Guillot
*/
class PluginException extends Exception
{
}

View File

@@ -2,14 +2,12 @@
namespace Kanboard\Core\Plugin;
use Exception;
/**
* Class PluginInstallerException
*
* @package Kanboard\Core\Plugin
* @author Frederic Guillot
*/
class PluginInstallerException extends Exception
class PluginInstallerException extends PluginException
{
}

View File

@@ -0,0 +1,38 @@
<?php
namespace Kanboard\Core\Plugin;
/**
* Class Version
*
* @package Kanboard\Core\Plugin
* @author Frederic Guillot
*/
class Version
{
/**
* Check plugin version compatibility with application version
*
* @param string $pluginCompatibleVersion
* @param string $appVersion
* @return bool
*/
public static function isCompatible($pluginCompatibleVersion, $appVersion = APP_VERSION)
{
if (strpos($appVersion, 'master') !== false) {
return true;
}
$appVersion = str_replace('v', '', $appVersion);
$pluginCompatibleVersion = str_replace('v', '', $pluginCompatibleVersion);
foreach (array('>=', '>', '<=', '<') as $operator) {
if (strpos($pluginCompatibleVersion, $operator) === 0) {
$pluginVersion = substr($pluginCompatibleVersion, strlen($operator));
return version_compare($appVersion, $pluginVersion, $operator);
}
}
return $pluginCompatibleVersion === $appVersion;
}
}

View File

@@ -1,3 +1,43 @@
<?php if (! empty($incompatible_plugins)): ?>
<div class="page-header">
<h2><?= t('Incompatible Plugins') ?></h2>
</div>
<table>
<tr>
<th class="column-35"><?= t('Name') ?></th>
<th class="column-25"><?= t('Author') ?></th>
<th class="column-10"><?= t('Version') ?></th>
<th class="column-12"><?= t('Compatibility') ?></th>
<?php if ($is_configured): ?>
<th><?= t('Action') ?></th>
<?php endif ?>
</tr>
<?php foreach ($incompatible_plugins as $pluginFolder => $plugin): ?>
<tr>
<td>
<?php if ($plugin->getPluginHomepage()): ?>
<a href="<?= $plugin->getPluginHomepage() ?>" target="_blank" rel="noreferrer"><?= $this->text->e($plugin->getPluginName()) ?></a>
<?php else: ?>
<?= $this->text->e($plugin->getPluginName()) ?>
<?php endif ?>
</td>
<td><?= $this->text->e($plugin->getPluginAuthor()) ?></td>
<td><?= $this->text->e($plugin->getPluginVersion()) ?></td>
<td><?= $this->text->e($plugin->getCompatibleVersion()) ?></td>
<?php if ($is_configured): ?>
<td>
<?= $this->modal->confirm('trash-o', t('Uninstall'), 'PluginController', 'confirm', array('pluginId' => $pluginFolder)) ?>
</td>
<?php endif ?>
</tr>
<tr>
<td colspan="<?= $is_configured ? 6 : 5 ?>"><?= $this->text->e($plugin->getPluginDescription()) ?></td>
</tr>
<?php endforeach ?>
</table>
<?php endif ?>
<div class="page-header">
<h2><?= t('Installed Plugins') ?></h2>
</div>