mirror of
https://github.com/Mibew/mibew.git
synced 2024-11-16 00:54:12 +03:00
Added classes that implements plugin system and tests for them
This commit is contained in:
parent
3e121c675f
commit
66a0d6ddca
157
src/messenger/tests/webim/libs/classes/EventDispatcherTest.php
Normal file
157
src/messenger/tests/webim/libs/classes/EventDispatcherTest.php
Normal file
@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
require_once dirname(__FILE__) . '/../../../../webim/libs/classes/event_dispatcher.php';
|
||||
require_once dirname(__FILE__) . '/../../../../webim/libs/classes/plugin.php';
|
||||
require_once dirname(__FILE__) . '/phpunit_autotest_plugin_manager/plugin.mibew.inc.php';
|
||||
|
||||
/**
|
||||
* Test class for EventDispatcher.
|
||||
* Generated by PHPUnit on 2012-07-17 at 16:09:00.
|
||||
*/
|
||||
class EventDispatcherTest extends PHPUnit_Framework_TestCase {
|
||||
|
||||
protected static $plugin = null;
|
||||
|
||||
public static function setUpBeforeClass() {
|
||||
self::$plugin = new Phpunit_autotest_plugin_managerPlugin();
|
||||
}
|
||||
|
||||
public static function tearDownAfterClass() {
|
||||
self::$plugin = null;
|
||||
}
|
||||
|
||||
public function testGetInstance() {
|
||||
$dispatcher = EventDispatcher::getInstance();
|
||||
$another_dispatcher = EventDispatcher::getInstance();
|
||||
$this->assertSame($dispatcher, $another_dispatcher);
|
||||
unset($another_dispatcher);
|
||||
return $dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testGetInstance
|
||||
*/
|
||||
public function testRegisterEvent($dispatcher) {
|
||||
// Try to register new event
|
||||
$this->assertTrue($dispatcher->registerEvent('some_test_event'));
|
||||
$this->assertTrue($dispatcher->registerEvent('some_another_test_event'));
|
||||
|
||||
// Try to register already registered event
|
||||
// Following code wait for trigger user error, which converts by PHPUnit to an
|
||||
// Exception
|
||||
try{
|
||||
$dispatcher->registerEvent('some_test_event');
|
||||
$this->fail("Error expected!");
|
||||
} catch(Exception $e) {}
|
||||
return $dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testRegisterEvent
|
||||
*/
|
||||
public function testAttachListener($dispatcher) {
|
||||
// Try to attach listener to unregistered event
|
||||
// Following code wait for trigger user error, which converts by PHPUnit to an
|
||||
// Exception
|
||||
try{
|
||||
$dispatcher->attachListener(
|
||||
'unreginstered_event',
|
||||
self::$plugin,
|
||||
'testEventListener'
|
||||
);
|
||||
$this->fail("Error expected!");
|
||||
} catch(Exception $e) {}
|
||||
|
||||
// Try to Attach wrong method as listener to event
|
||||
// Following code wait for trigger user error, which converts by PHPUnit to an
|
||||
// Exception
|
||||
try{
|
||||
$dispatcher->attachListener(
|
||||
'some_test_event',
|
||||
self::$plugin,
|
||||
'wrongEventListener'
|
||||
);
|
||||
$this->fail("Error expected!");
|
||||
} catch(Exception $e) {}
|
||||
|
||||
// Try to attach listener to registered event
|
||||
$this->assertTrue(
|
||||
$dispatcher->attachListener(
|
||||
'some_test_event',
|
||||
self::$plugin,
|
||||
'testEventListener'
|
||||
)
|
||||
);
|
||||
|
||||
// Try to attach listener to registered event
|
||||
$this->assertTrue(
|
||||
$dispatcher->attachListener(
|
||||
'some_another_test_event',
|
||||
self::$plugin,
|
||||
'testEventListener'
|
||||
)
|
||||
);
|
||||
|
||||
return $dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testAttachListener
|
||||
*/
|
||||
public function testDetachListener($dispatcher) {
|
||||
// Try to detach listener for unregistered event.
|
||||
// Following code wait for trigger user error, which converts by PHPUnit to an
|
||||
// Exception
|
||||
try{
|
||||
$dispatcher->detachListener(
|
||||
'unreginstered_event',
|
||||
self::$plugin,
|
||||
'testEventListener'
|
||||
);
|
||||
$this->fail("Error expected!");
|
||||
} catch(Exception $e) {}
|
||||
|
||||
// Try to detach listner that was not attached to registerd event
|
||||
$this->assertFalse(
|
||||
$dispatcher->detachListener(
|
||||
'some_test_event',
|
||||
self::$plugin,
|
||||
'wrongEventListener'
|
||||
)
|
||||
);
|
||||
|
||||
// Try to detach listener that was attached to registered
|
||||
$this->assertTrue(
|
||||
$dispatcher->detachListener(
|
||||
'some_test_event',
|
||||
self::$plugin,
|
||||
'testEventListener'
|
||||
)
|
||||
);
|
||||
return $dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testDetachListener
|
||||
*/
|
||||
public function testTriggerEvent($dispatcher) {
|
||||
// Try to trigger unregistered event
|
||||
// Following code wait for trigger user error, which converts by PHPUnit to an
|
||||
// Exception
|
||||
try{
|
||||
$dispatcher->triggerEvent('unregistered_event', array());
|
||||
$this->fail("Error expected!");
|
||||
} catch(Exception $e) {}
|
||||
|
||||
// Try to thrigger registered event
|
||||
// Wait for exception thrown by
|
||||
// Phpunit_autotest_plugin_managerPlugin::testEventListener()
|
||||
try{
|
||||
$dispatcher->triggerEvent('some_another_test_event', array());
|
||||
$this->fail("Exception excpected!");
|
||||
} catch(Exception $e) {}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
28
src/messenger/tests/webim/libs/classes/PluginManagerTest.php
Normal file
28
src/messenger/tests/webim/libs/classes/PluginManagerTest.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
require_once dirname(__FILE__) . '/../../../../webim/libs/classes/plugin_manager.php';
|
||||
require_once dirname(__FILE__) . '/../../../../webim/libs/classes/plugin.php';
|
||||
|
||||
/**
|
||||
* Test class for PluginManager.
|
||||
* Generated by PHPUnit on 2012-07-17 at 16:09:18.
|
||||
*/
|
||||
class PluginManagerTest extends PHPUnit_Framework_TestCase {
|
||||
|
||||
public function testLoadPlugins() {
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__));
|
||||
PluginManager::loadPlugins(
|
||||
array(
|
||||
array(
|
||||
'name' => 'phpunit_autotest_plugin_manager'
|
||||
)
|
||||
)
|
||||
);
|
||||
if(empty($GLOBALS['phpunit_autotest_plugin_manager'])) {
|
||||
$this->fail('Plugin not loaded and initialize correctly');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Test plugin for PHPUnit tests
|
||||
*/
|
||||
Class Phpunit_autotest_plugin_managerPlugin implements Plugin{
|
||||
|
||||
public $eventsRegistered = false;
|
||||
public $listenersRegistered = false;
|
||||
|
||||
public function getWeight() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
public function registerEvents() {
|
||||
$this->eventsRegistered = true;
|
||||
$this->checkRegistration();
|
||||
}
|
||||
|
||||
public function registerListeners() {
|
||||
$this->listenersRegistered = true;
|
||||
$this->checkRegistration();
|
||||
}
|
||||
|
||||
public function checkRegistration() {
|
||||
if ($this->eventsRegistered && $this->listenersRegistered) {
|
||||
$GLOBALS['phpunit_autotest_plugin_manager'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
public function testEventListener($vars) {
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
1
src/messenger/webim/libs/classes/.htaccess
Normal file
1
src/messenger/webim/libs/classes/.htaccess
Normal file
@ -0,0 +1 @@
|
||||
Deny from all
|
163
src/messenger/webim/libs/classes/event_dispatcher.php
Normal file
163
src/messenger/webim/libs/classes/event_dispatcher.php
Normal file
@ -0,0 +1,163 @@
|
||||
<?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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provide event-related functionality.
|
||||
* Implements singleton pattern.
|
||||
*/
|
||||
Class EventDispatcher {
|
||||
|
||||
/**
|
||||
* An instance of EventDispatcher class.
|
||||
* @var EventDispatcher
|
||||
*/
|
||||
protected static $instance = null;
|
||||
|
||||
/**
|
||||
* Events and listeners array.
|
||||
* @var array
|
||||
*/
|
||||
protected $events = array();
|
||||
|
||||
/**
|
||||
* Increments any time when plugin adds. Use for determine plugins order for plugins with
|
||||
* equal priority.
|
||||
* @var int
|
||||
*/
|
||||
protected $offset = 0;
|
||||
|
||||
/**
|
||||
* Returns an instance of EventDispatcher class.
|
||||
*
|
||||
* @return EventDispatcher
|
||||
*/
|
||||
public static function getInstance(){
|
||||
if (self::$instance === null) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make constructor unavailable for client code
|
||||
*/
|
||||
protected function __constructor() {}
|
||||
|
||||
/**
|
||||
* Attaches listener function to event.
|
||||
*
|
||||
* @param string $event_name Event's name
|
||||
* @param Plugin $plugin Plugin object, that handles the event
|
||||
* @param string $listener Plugins method, that handles the event
|
||||
* @param int $priority Priority of listener. If $priority = null, the plugin weight will
|
||||
* use instead.
|
||||
* @return boolean true on success or false on failure.
|
||||
*
|
||||
* @see Plugin::getWeight()
|
||||
*/
|
||||
public function attachListener($event_name, Plugin $plugin, $listener, $priority = null){
|
||||
// Check event exists
|
||||
if (! array_key_exists($event_name, $this->events)) {
|
||||
trigger_error("Event '{$event_name}' does not exists!", E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
// Check method is callable
|
||||
if (! is_callable(array($plugin, $listener))) {
|
||||
trigger_error("Method '{$listener}' is not callable!", E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
// Check priority
|
||||
if (is_null($priority)) {
|
||||
$priority = $plugin->getWeight();
|
||||
}
|
||||
// Attach listener
|
||||
$this->events[$event_name][$priority . "_" . $this->offset] = array(
|
||||
'plugin' => $plugin,
|
||||
'listener' => $listener
|
||||
);
|
||||
$this->offset++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detach listener function from event
|
||||
*
|
||||
* @param string $event_name Event's name
|
||||
* @param Plugin $plugin Plugin object, that handles the event
|
||||
* @param string $listener Plugins method, that handles the event
|
||||
* @return boolean true on success or false on failure.
|
||||
*/
|
||||
public function detachListener($event_name, Plugin $plugin, $listener){
|
||||
// Check event exists
|
||||
if (! array_key_exists($event_name, $this->events)) {
|
||||
trigger_error("Event '{$event_name}' does not exists!", E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
// Search event and $plugin->$listener
|
||||
foreach ($this->events[$event_name] as $index => $event) {
|
||||
if ($event['plugin'] === $plugin && $event['listener'] == $listener) {
|
||||
// Detach listener
|
||||
unset($this->events[$event_name][$index]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers new event
|
||||
*
|
||||
* @param string $event_name Event's name
|
||||
* @return boolean true on success or false on failure
|
||||
*/
|
||||
public function registerEvent($event_name){
|
||||
// Check event exists
|
||||
if (array_key_exists($event_name, $this->events)) {
|
||||
trigger_error("Event '{$event_name}' already exists!", E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
// register event
|
||||
$this->events[$event_name] = array();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the event
|
||||
*
|
||||
* @param string $event_name Event's name
|
||||
* @param array $arguments Arguments passed to listener
|
||||
* @return boolean true on success or false on failure
|
||||
*/
|
||||
public function triggerEvent($event_name, $arguments = array()){
|
||||
// Check event exists
|
||||
if (! array_key_exists($event_name, $this->events)) {
|
||||
trigger_error("Event '{$event_name}' does not exists!", E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
// Sorting listeners by priority
|
||||
uksort($this->events[$event_name], 'strnatcmp');
|
||||
// Invoke listeners
|
||||
foreach ($this->events[$event_name] as $event) {
|
||||
$plugin = $event['plugin'];
|
||||
$listener = $event['listener'];
|
||||
$plugin->$listener($arguments);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
43
src/messenger/webim/libs/classes/plugin.php
Normal file
43
src/messenger/webim/libs/classes/plugin.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base plugin interface
|
||||
*/
|
||||
interface Plugin {
|
||||
|
||||
/**
|
||||
* Returns plugin weight. Weight is used for determine loading order and as default
|
||||
* listner priority.
|
||||
*
|
||||
* @return int Plugin weight
|
||||
*/
|
||||
public function getWeight();
|
||||
|
||||
/**
|
||||
* Register events
|
||||
*/
|
||||
public function registerEvents();
|
||||
|
||||
/**
|
||||
* Register listeners
|
||||
*/
|
||||
public function registerListeners();
|
||||
|
||||
}
|
||||
|
||||
?>
|
94
src/messenger/webim/libs/classes/plugin_manager.php
Normal file
94
src/messenger/webim/libs/classes/plugin_manager.php
Normal file
@ -0,0 +1,94 @@
|
||||
<?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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Manage plugins
|
||||
*/
|
||||
Class PluginManager {
|
||||
|
||||
/**
|
||||
* Loads plugins and invokes Plugin::registerEvents() and Plugin::registerListeners()
|
||||
*
|
||||
* @param array $plugins_list List of plugins' names and configurations. For example:
|
||||
* <code>
|
||||
* $plugins_list = array();
|
||||
* $plugins_list[] = array(
|
||||
* 'name' => 'plugin_name', // Obligatory value
|
||||
* 'config' => array( // Pass to plugin constructor
|
||||
* 'weight' => 100,
|
||||
* 'some_configurable_value' => 'value'
|
||||
* )
|
||||
* )
|
||||
* </code>
|
||||
*
|
||||
* @see Plugin::registerEvents()
|
||||
* @see Plugin::registerListeners()
|
||||
*/
|
||||
public static function loadPlugins($plugins_list){
|
||||
// Add include path
|
||||
$include_path = get_include_path();
|
||||
$include_path .= empty($include_path) ? '' : PATH_SEPARATOR ;
|
||||
set_include_path($include_path . realpath(dirname(__FILE__) . "/../../plugins/"));
|
||||
|
||||
// Load plugins
|
||||
$loading_queue = array();
|
||||
$offset = 0;
|
||||
foreach ($plugins_list as $plugin) {
|
||||
if (empty($plugin['name'])) {
|
||||
trigger_error("Plugin name undefined!", E_USER_WARNING);
|
||||
continue;
|
||||
}
|
||||
$plugin_name = $plugin['name'];
|
||||
$plugin_config = isset($plugin['config']) ? $plugin['config'] : array();
|
||||
$plugin_classname = ucfirst($plugin_name) . "Plugin";
|
||||
// Try to load plugin file
|
||||
if (! (include_once $plugin_name."/plugin.mibew.inc.php")) {
|
||||
trigger_error("Cannot load plugin file!", E_USER_ERROR);
|
||||
}
|
||||
// Check plugin class name
|
||||
if (! class_exists($plugin_classname)) {
|
||||
trigger_error(
|
||||
"Plugin class '{$plugin_classname}' does not defined!",
|
||||
E_USER_WARNING
|
||||
);
|
||||
continue;
|
||||
}
|
||||
// Check if plugin implements 'Plugin' interface
|
||||
if (! in_array('Plugin', class_implements($plugin_classname))) {
|
||||
trigger_error(
|
||||
"Plugin class '{$plugin_classname}' does not implement " .
|
||||
"'Plugin' interface!",
|
||||
E_USER_WARNING
|
||||
);
|
||||
continue;
|
||||
}
|
||||
// Add plugin to loading queue
|
||||
$plugin_instance = new $plugin_classname($plugin_config);
|
||||
$loading_queue[$plugin_instance->getWeight() . "_" . $offset] = $plugin_instance;
|
||||
$offset++;
|
||||
}
|
||||
// Sort queue in order to plugins' weights
|
||||
uksort($loading_queue, 'strnatcmp');
|
||||
// Add events and listeners
|
||||
foreach ($loading_queue as $plugin) {
|
||||
$plugin->registerEvents();
|
||||
$plugin->registerListeners();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
1
src/messenger/webim/plugins/.htaccess
Normal file
1
src/messenger/webim/plugins/.htaccess
Normal file
@ -0,0 +1 @@
|
||||
Deny from all
|
Loading…
Reference in New Issue
Block a user