Use interface instead of abstract classes for plugins

This commit is contained in:
Dmitriy Simushev 2014-02-26 10:48:08 +00:00
parent 9598f0db42
commit bb4e935303
3 changed files with 77 additions and 88 deletions

View File

@ -1,70 +0,0 @@
<?php
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace Mibew;
/**
* Base plugin class
*/
abstract class Plugin
{
/**
* Constructor must set this value to true after successful initialization
* failures
* @var boolean
*/
public $initialized = false;
/**
* An array of plugin configuration
* @var array
*/
protected $config = array();
/**
* Returns plugin weight. Weight is used for determine loading order and as
* default listner priority.
*
* @return int Plugin weight
*/
abstract public function getWeight();
/**
* Register listeners
*
* Event listener take one argument by reference. For example:
* <code>
* public function testListener(&$arguments) {
* $arguments['result'] = 'Test string';
* }
* </code>
*/
abstract public function registerListeners();
/**
* Returns list of plugin's dependences.
*
* Each element of dependenses list is a string with a plugin name.
* If plugin have no dependenses do not override this method.
*
* @return array List of plugin's dependences.
*/
public static function getDependences()
{
return array();
}
}

View File

@ -63,22 +63,22 @@ class Manager
* Loads plugins. * Loads plugins.
* *
* The method checks dependences and plugin avaiulability before loading and * The method checks dependences and plugin avaiulability before loading and
* invokes Plugin::registerListeners() after loading. * invokes PluginInterface::run() after loading.
* *
* @param array $plugins_list List of plugins' names and configurations. * @param array $plugins_list List of plugins' names and configurations.
* For example: * For example:
* <code> * <code>
* $plugins_list = array(); * $plugins_list = array();
* $plugins_list[] = array( * $plugins_list[] = array(
* 'name' => 'plugin_name', // Obligatory value * 'name' => 'plugin_name', // Obligatory value
* 'config' => array( // Pass to plugin constructor * 'config' => array( // Pass to plugin constructor
* 'weight' => 100, * 'weight' => 100,
* 'some_configurable_value' => 'value' * 'some_configurable_value' => 'value'
* ) * )
* ) * )
* </code> * </code>
* *
* @see Plugin::registerListeners() * @see \Mibew\Plugin\PluginInterface::run()
*/ */
public static function loadPlugins($plugins_list) public static function loadPlugins($plugins_list)
{ {
@ -116,22 +116,22 @@ class Manager
continue; continue;
} }
// Check if plugin extends abstract 'Plugin' class // Check if plugin extends abstract 'Plugin' class
if ('Mibew\\Plugin' != get_parent_class($plugin_classname)) { if (!in_array('Mibew\\Plugin\\PluginInterface', class_implements($plugin_classname))) {
$error_essage = "Plugin class '{$plugin_classname}' does not " $error_essage = "Plugin class '{$plugin_classname}' does not "
. "extend abstract '\\Mibew\\Plugin' class!"; . "implement '\\Mibew\\Plugin\\PluginInterface' interface!";
trigger_error($error_essage, E_USER_WARNING); trigger_error($error_essage, E_USER_WARNING);
continue; continue;
} }
// Check plugin dependences // Check plugin dependencies
$plugin_dependences = call_user_func(array( $plugin_dependencies = call_user_func(array(
$plugin_classname, $plugin_classname,
'getDependences', 'getDependencies',
)); ));
foreach ($plugin_dependences as $dependence) { foreach ($plugin_dependencies as $dependency) {
if (empty(self::$loadedPlugins[$dependence])) { if (empty(self::$loadedPlugins[$dependency])) {
$error_essage = "Plugin '{$dependence}' was not loaded " $error_essage = "Plugin '{$dependency}' was not loaded "
. "yet, but exists in '{$plugin_name}' dependences list!"; . "yet, but exists in '{$plugin_name}' dependencies list!";
trigger_error($error_essage, E_USER_WARNING); trigger_error($error_essage, E_USER_WARNING);
continue 2; continue 2;
} }
@ -139,7 +139,7 @@ class Manager
// Add plugin to loading queue // Add plugin to loading queue
$plugin_instance = new $plugin_classname($plugin_config); $plugin_instance = new $plugin_classname($plugin_config);
if ($plugin_instance->initialized) { if ($plugin_instance->initialized()) {
// Store plugin instance // Store plugin instance
self::$loadedPlugins[$plugin_name] = $plugin_instance; self::$loadedPlugins[$plugin_name] = $plugin_instance;
$loading_queue[$plugin_instance->getWeight() . "_" . $offset] = $plugin_instance; $loading_queue[$plugin_instance->getWeight() . "_" . $offset] = $plugin_instance;
@ -155,7 +155,7 @@ class Manager
uksort($loading_queue, 'strnatcmp'); uksort($loading_queue, 'strnatcmp');
// Add events and listeners // Add events and listeners
foreach ($loading_queue as $plugin) { foreach ($loading_queue as $plugin) {
$plugin->registerListeners(); $plugin->run();
} }
} }
} }

View File

@ -0,0 +1,59 @@
<?php
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace Mibew\Plugin;
/**
* Interface that must be implemented by all plugins.
*/
interface PluginInterface
{
/**
* Returns plugin weight. Weight is used to determine run priority.
*
* @return int Plugin weight
*/
public function getWeight();
/**
* Indicates if plugin has been initialized correctly or not.
*
* A concrete plugin can return false if something go wrong and it cannot be
* used but the whole system should works anyway.
*
* @return boolean
*/
public function initialized();
/**
* This method will be executed when all plugins have been initialized.
*
* The order based on weights and order in the main configuration file will
* be preserved.
*/
public function run();
/**
* Returns list of plugin's dependencies.
*
* Each element in the list is a string with a plugin name. If plugin have
* no dependencies an empty array should be returned.
*
* @return array List of plugin's dependencies.
*/
public static function getDependencies();
}