Browse Source

Add Pico::API_VERSION

Daniel Rudolf 8 years ago
parent
commit
7b222b03e4
3 changed files with 84 additions and 11 deletions
  1. 41 0
      lib/AbstractPicoPlugin.php
  2. 36 11
      lib/Pico.php
  3. 7 0
      plugins/DummyPlugin.php

+ 41 - 0
lib/AbstractPicoPlugin.php

@@ -37,6 +37,14 @@ abstract class AbstractPicoPlugin implements PicoPluginInterface
      */
      */
     protected $statusChanged = false;
     protected $statusChanged = false;
 
 
+    /**
+     * Boolean indicating whether this plugin matches Pico's API version
+     *
+     * @see AbstractPicoPlugin::checkCompatibility()
+     * @var boolean|null
+     */
+    protected $nativePlugin;
+
     /**
     /**
      * List of plugins which this plugin depends on
      * List of plugins which this plugin depends on
      *
      *
@@ -81,6 +89,7 @@ abstract class AbstractPicoPlugin implements PicoPluginInterface
                     // make sure dependencies are already fulfilled,
                     // make sure dependencies are already fulfilled,
                     // otherwise the plugin needs to be enabled manually
                     // otherwise the plugin needs to be enabled manually
                     try {
                     try {
+                        $this->checkCompatibility();
                         $this->checkDependencies(false);
                         $this->checkDependencies(false);
                     } catch (RuntimeException $e) {
                     } catch (RuntimeException $e) {
                         $this->enabled = false;
                         $this->enabled = false;
@@ -105,6 +114,7 @@ abstract class AbstractPicoPlugin implements PicoPluginInterface
         $this->enabled = (bool) $enabled;
         $this->enabled = (bool) $enabled;
 
 
         if ($enabled) {
         if ($enabled) {
+            $this->checkCompatibility();
             $this->checkDependencies($recursive);
             $this->checkDependencies($recursive);
         } else {
         } else {
             $this->checkDependants($recursive);
             $this->checkDependants($recursive);
@@ -283,4 +293,35 @@ abstract class AbstractPicoPlugin implements PicoPluginInterface
 
 
         return $this->dependants;
         return $this->dependants;
     }
     }
+
+    /**
+     * Checks compatibility with Pico's API version
+     *
+     * Pico automatically adds a dependency to {@see PicoDeprecated} when the
+     * plugin's API is older than Pico's API. {@see PicoDeprecated} furthermore
+     * throws a exception when it can't provide compatibility in such cases.
+     * However, we still have to decide whether this plugin is compatible to
+     * newer API versions, what defaults to "no" by default.
+     *
+     * @return void
+     * @throws RuntimeException thrown when the plugin's and Pico's API
+     *     aren't compatible
+     */
+    protected function checkCompatibility()
+    {
+        if ($this->nativePlugin === null) {
+            $picoClassName = get_class($this->pico);
+            $picoApiVersion = defined($picoClassName . '::API_VERSION') ? $picoClassName::API_VERSION : 1;
+            $pluginApiVersion = defined('static::API_VERSION') ? static::API_VERSION : 1;
+
+            $this->nativePlugin = ($pluginApiVersion === $picoApiVersion);
+
+            if (!$this->nativePlugin && ($pluginApiVersion > $picoApiVersion)) {
+                throw new RuntimeException(
+                    "Unable to enable plugin '" . get_called_class() . "': The plugin's API (version "
+                    . $pluginApiVersion . ") isn't compatible with Pico's API (version " . $picoApiVersion . ")"
+                );
+            }
+        }
+    }
 }
 }

+ 36 - 11
lib/Pico.php

@@ -42,6 +42,13 @@ class Pico
      */
      */
     const VERSION_ID = 20000;
     const VERSION_ID = 20000;
 
 
+    /**
+     * Pico API version
+     *
+     * @var int
+     */
+    const API_VERSION = 2;
+
     /**
     /**
      * Sort files in alphabetical ascending order
      * Sort files in alphabetical ascending order
      *
      *
@@ -121,6 +128,13 @@ class Pico
      */
      */
     protected $plugins = array();
     protected $plugins = array();
 
 
+    /**
+     * List of loaded plugins using the current API version
+     *
+     * @var object[]
+     */
+    protected $nativePlugins = array();
+
     /**
     /**
      * Current configuration of this Pico instance
      * Current configuration of this Pico instance
      *
      *
@@ -523,6 +537,12 @@ class Pico
                 }
                 }
 
 
                 $this->plugins[$className] = $plugin;
                 $this->plugins[$className] = $plugin;
+
+                if ($plugin instanceof PicoPluginInterface) {
+                    if (defined($className . '::API_VERSION') && ($className::API_VERSION >= static::API_VERSION)) {
+                        $this->nativePlugins[$className] = $plugin;
+                    }
+                }
             } else {
             } else {
                 throw new RuntimeException(
                 throw new RuntimeException(
                     "Unable to load plugin '" . $className . "' "
                     "Unable to load plugin '" . $className . "' "
@@ -567,6 +587,10 @@ class Pico
 
 
         $this->plugins[$className] = $plugin;
         $this->plugins[$className] = $plugin;
 
 
+        if (defined($className . '::API_VERSION') && ($className::API_VERSION >= static::API_VERSION)) {
+            $this->nativePlugins[$className] = $plugin;
+        }
+
         return $plugin;
         return $plugin;
     }
     }
 
 
@@ -613,8 +637,9 @@ class Pico
                 $dependencies = array();
                 $dependencies = array();
                 if ($plugin instanceof PicoPluginInterface) {
                 if ($plugin instanceof PicoPluginInterface) {
                     $dependencies = $plugin->getDependencies();
                     $dependencies = $plugin->getDependencies();
-                } else {
-                    $dependencies = array('PicoDeprecated');
+                }
+                if (!isset($this->nativePlugins[$pluginName])) {
+                    $dependencies[] = 'PicoDeprecated';
                 }
                 }
 
 
                 foreach ($dependencies as $dependency) {
                 foreach ($dependencies as $dependency) {
@@ -1996,10 +2021,14 @@ class Pico
     }
     }
 
 
     /**
     /**
-     * Triggers events on plugins which implement PicoPluginInterface
+     * Triggers events on plugins using the current API version
+     *
+     * Plugins using older API versions are handled by {@see PicoDeprecated}.
+     * Please note that {@see PicoDeprecated} also triggers custom events on
+     * plugins using older API versions, thus you can safely use this method
+     * to trigger custom events on all loaded plugins, no matter what API
+     * version - the event will be triggered in any case
      *
      *
-     * Deprecated events (as used by plugins not implementing
-     * {@link PicoPluginInterface}) are triggered by {@link PicoDeprecated}.
      * You MUST NOT trigger events of Pico's core with a plugin!
      * You MUST NOT trigger events of Pico's core with a plugin!
      *
      *
      * @see    PicoPluginInterface
      * @see    PicoPluginInterface
@@ -2011,12 +2040,8 @@ class Pico
      */
      */
     public function triggerEvent($eventName, array $params = array())
     public function triggerEvent($eventName, array $params = array())
     {
     {
-        foreach ($this->plugins as $plugin) {
-            // only trigger events for plugins that implement PicoPluginInterface
-            // deprecated events (plugins for Pico 0.9 and older) will be triggered by `PicoDeprecated`
-            if ($plugin instanceof PicoPluginInterface) {
-                $plugin->handleEvent($eventName, $params);
-            }
+        foreach ($this->nativePlugins as $plugin) {
+            $plugin->handleEvent($eventName, $params);
         }
         }
     }
     }
 }
 }

+ 7 - 0
plugins/DummyPlugin.php

@@ -13,6 +13,13 @@
  */
  */
 class DummyPlugin extends AbstractPicoPlugin
 class DummyPlugin extends AbstractPicoPlugin
 {
 {
+    /**
+     * API version used by this plugin
+     *
+     * @var int
+     */
+    const API_VERSION = 2;
+
     /**
     /**
      * This plugin is disabled by default
      * This plugin is disabled by default
      *
      *