From 8ddd56636154e5e55892fbb5ac9a5fe186b8df1f Mon Sep 17 00:00:00 2001
From: Frederic Guillot <fred@kanboard.net>
Date: Sat, 7 May 2016 19:35:06 -0400
Subject: Improve plugin loading

---
 app/Core/Plugin/Loader.php | 137 ++++++++++++++-------------------------------
 1 file changed, 42 insertions(+), 95 deletions(-)

(limited to 'app/Core/Plugin/Loader.php')

diff --git a/app/Core/Plugin/Loader.php b/app/Core/Plugin/Loader.php
index 3482b7ee..400517b7 100644
--- a/app/Core/Plugin/Loader.php
+++ b/app/Core/Plugin/Loader.php
@@ -4,33 +4,35 @@ namespace Kanboard\Core\Plugin;
 
 use Composer\Autoload\ClassLoader;
 use DirectoryIterator;
-use PDOException;
 use LogicException;
-use RuntimeException;
 use Kanboard\Core\Tool;
 
 /**
  * Plugin Loader
  *
- * @package  plugin
- * @author   Frederic Guillot
+ * @package Kanboard\Core\Plugin
+ * @author  Frederic Guillot
  */
 class Loader extends \Kanboard\Core\Base
 {
     /**
-     * Schema version table for plugins
+     * Plugin instances
      *
-     * @var string
+     * @access public
+     * @var array
      */
-    const TABLE_SCHEMA = 'plugin_schema_versions';
+    public $plugins = array();
 
     /**
-     * Plugin instances
+     * Get list of loaded plugins
      *
      * @access public
-     * @var array
+     * @return array
      */
-    public $plugins = array();
+    public function getPlugins()
+    {
+        return $this->plugins;
+    }
 
     /**
      * Scan plugin folder and load plugins
@@ -46,120 +48,65 @@ class Loader extends \Kanboard\Core\Base
 
             $dir = new DirectoryIterator(PLUGINS_DIR);
 
-            foreach ($dir as $fileinfo) {
-                if (! $fileinfo->isDot() && $fileinfo->isDir()) {
-                    $plugin = $fileinfo->getFilename();
-                    $this->loadSchema($plugin);
-                    $this->load($plugin);
+            foreach ($dir as $fileInfo) {
+                if ($fileInfo->isDir() && substr($fileInfo->getFilename(), 0, 1) !== '.') {
+                    $pluginName = $fileInfo->getFilename();
+                    $this->loadSchema($pluginName);
+                    $this->initializePlugin($this->loadPlugin($pluginName));
                 }
             }
         }
     }
 
-    /**
-     * Load plugin
-     *
-     * @access public
-     * @throws LogicException
-     * @param  string $plugin
-     */
-    public function load($plugin)
-    {
-        $class = '\Kanboard\Plugin\\'.$plugin.'\\Plugin';
-
-        if (! class_exists($class)) {
-            throw new LogicException('Unable to load this plugin class '.$class);
-        }
-
-        $instance = new $class($this->container);
-
-        Tool::buildDIC($this->container, $instance->getClasses());
-        Tool::buildDICHelpers($this->container, $instance->getHelpers());
-
-        $instance->initialize();
-
-        if (method_exists($instance, 'onStartup')) {
-            $this->dispatcher->addListener('app.bootstrap', array($instance, 'onStartup'));
-        }
-
-        $this->plugins[] = $instance;
-    }
-
     /**
      * Load plugin schema
      *
      * @access public
-     * @param  string  $plugin
+     * @param  string $pluginName
      */
-    public function loadSchema($plugin)
+    public function loadSchema($pluginName)
     {
-        $filename = PLUGINS_DIR.'/'.$plugin.'/Schema/'.ucfirst(DB_DRIVER).'.php';
-
-        if (file_exists($filename)) {
-            require_once($filename);
-            $this->migrateSchema($plugin);
+        if (SchemaHandler::hasSchema($pluginName)) {
+            $schemaHandler = new SchemaHandler($this->container);
+            $schemaHandler->loadSchema($pluginName);
         }
     }
 
     /**
-     * Execute plugin schema migrations
+     * Load plugin
      *
      * @access public
-     * @param  string  $plugin
+     * @throws LogicException
+     * @param  string $pluginName
+     * @return Base
      */
-    public function migrateSchema($plugin)
+    public function loadPlugin($pluginName)
     {
-        $last_version = constant('\Kanboard\Plugin\\'.$plugin.'\Schema\VERSION');
-        $current_version = $this->getSchemaVersion($plugin);
-
-        try {
-            $this->db->startTransaction();
-            $this->db->getDriver()->disableForeignKeys();
+        $className = '\Kanboard\Plugin\\'.$pluginName.'\\Plugin';
 
-            for ($i = $current_version + 1; $i <= $last_version; $i++) {
-                $function_name = '\Kanboard\Plugin\\'.$plugin.'\Schema\version_'.$i;
-
-                if (function_exists($function_name)) {
-                    call_user_func($function_name, $this->db->getConnection());
-                }
-            }
-
-            $this->db->getDriver()->enableForeignKeys();
-            $this->db->closeTransaction();
-            $this->setSchemaVersion($plugin, $i - 1);
-        } catch (PDOException $e) {
-            $this->db->cancelTransaction();
-            $this->db->getDriver()->enableForeignKeys();
-            throw new RuntimeException('Unable to migrate schema for the plugin: '.$plugin.' => '.$e->getMessage());
+        if (! class_exists($className)) {
+            throw new LogicException('Unable to load this plugin class '.$className);
         }
-    }
 
-    /**
-     * Get current plugin schema version
-     *
-     * @access public
-     * @param  string  $plugin
-     * @return integer
-     */
-    public function getSchemaVersion($plugin)
-    {
-        return (int) $this->db->table(self::TABLE_SCHEMA)->eq('plugin', strtolower($plugin))->findOneColumn('version');
+        return new $className($this->container);
     }
 
     /**
-     * Save last plugin schema version
+     * Initialize plugin
      *
      * @access public
-     * @param  string   $plugin
-     * @param  integer  $version
-     * @return boolean
+     * @param  Base $plugin
      */
-    public function setSchemaVersion($plugin, $version)
+    public function initializePlugin(Base $plugin)
     {
-        $dictionary = array(
-            strtolower($plugin) => $version
-        );
+        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());
 
-        return $this->db->getDriver()->upsert(self::TABLE_SCHEMA, 'plugin', 'version', $dictionary);
+        $plugin->initialize();
+        $this->plugins[] = $plugin;
     }
 }
-- 
cgit v1.2.3