summaryrefslogtreecommitdiff
path: root/plugins/Irc/extlib/phergie/Phergie/Plugin/Handler.php
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/Irc/extlib/phergie/Phergie/Plugin/Handler.php')
-rwxr-xr-xplugins/Irc/extlib/phergie/Phergie/Plugin/Handler.php501
1 files changed, 501 insertions, 0 deletions
diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Handler.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Handler.php
new file mode 100755
index 000000000..c3086587b
--- /dev/null
+++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Handler.php
@@ -0,0 +1,501 @@
+<?php
+/**
+ * Phergie
+ *
+ * PHP version 5
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.
+ * It is also available through the world-wide-web at this URL:
+ * http://phergie.org/license
+ *
+ * @category Phergie
+ * @package Phergie
+ * @author Phergie Development Team <team@phergie.org>
+ * @copyright 2008-2010 Phergie Development Team (http://phergie.org)
+ * @license http://phergie.org/license New BSD License
+ * @link http://pear.phergie.org/package/Phergie
+ */
+
+/**
+ * Handles on-demand loading of, iteration over, and access to plugins.
+ *
+ * @category Phergie
+ * @package Phergie
+ * @author Phergie Development Team <team@phergie.org>
+ * @license http://phergie.org/license New BSD License
+ * @link http://pear.phergie.org/package/Phergie
+ */
+class Phergie_Plugin_Handler implements IteratorAggregate, Countable
+{
+ /**
+ * Current list of plugin instances
+ *
+ * @var array
+ */
+ protected $plugins;
+
+ /**
+ * Paths in which to search for plugin class files
+ *
+ * @var array
+ */
+ protected $paths;
+
+ /**
+ * Flag indicating whether plugin classes should be instantiated on
+ * demand if they are requested but no instance currently exists
+ *
+ * @var bool
+ */
+ protected $autoload;
+
+ /**
+ * Phergie_Config instance that should be passed in to any plugin
+ * instantiated within the handler
+ *
+ * @var Phergie_Config
+ */
+ protected $config;
+
+ /**
+ * Phergie_Event_Handler instance that should be passed in to any plugin
+ * instantiated within the handler
+ *
+ * @var Phergie_Event_Handler
+ */
+ protected $events;
+
+ /**
+ * Name of the class to use for iterating over all currently loaded
+ * plugins
+ *
+ * @var string
+ */
+ protected $iteratorClass = 'Phergie_Plugin_Iterator';
+
+ /**
+ * Constructor to initialize class properties and add the path for core
+ * plugins.
+ *
+ * @param Phergie_Config $config configuration to pass to any
+ * instantiated plugin
+ * @param Phergie_Event_Handler $events event handler to pass to any
+ * instantiated plugin
+ *
+ * @return void
+ */
+ public function __construct(
+ Phergie_Config $config,
+ Phergie_Event_Handler $events
+ ) {
+ $this->config = $config;
+ $this->events = $events;
+
+ $this->plugins = array();
+ $this->paths = array();
+ $this->autoload = false;
+
+ if (!empty($config['plugins.paths'])) {
+ foreach ($config['plugins.paths'] as $dir => $prefix) {
+ $this->addPath($dir, $prefix);
+ }
+ }
+
+ $this->addPath(dirname(__FILE__), 'Phergie_Plugin_');
+ }
+
+
+ /**
+ * Adds a path to search for plugin class files. Paths are searched in
+ * the reverse order in which they are added.
+ *
+ * @param string $path Filesystem directory path
+ * @param string $prefix Optional class name prefix corresponding to the
+ * path
+ *
+ * @return Phergie_Plugin_Handler Provides a fluent interface
+ * @throws Phergie_Plugin_Exception
+ */
+ public function addPath($path, $prefix = '')
+ {
+ if (!is_readable($path)) {
+ throw new Phergie_Plugin_Exception(
+ 'Path "' . $path . '" does not reference a readable directory',
+ Phergie_Plugin_Exception::ERR_DIRECTORY_NOT_READABLE
+ );
+ }
+
+ $this->paths[] = array(
+ 'path' => rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR,
+ 'prefix' => $prefix
+ );
+
+ return $this;
+ }
+
+ /**
+ * Returns metadata corresponding to a specified plugin.
+ *
+ * @param string $plugin Short name of the plugin class
+ *
+ * @throws Phergie_Plugin_Exception Class file can't be found
+ *
+ * @return array|boolean Associative array containing the path to the
+ * class file and its containing directory as well as the full
+ * class name
+ */
+ public function getPluginInfo($plugin)
+ {
+ foreach (array_reverse($this->paths) as $path) {
+ $file = $path['path'] . $plugin . '.php';
+ if (file_exists($file)) {
+ $path = array(
+ 'dir' => $path['path'],
+ 'file' => $file,
+ 'class' => $path['prefix'] . $plugin,
+ );
+ return $path;
+ }
+ }
+
+ // If the class can't be found, display an error
+ throw new Phergie_Plugin_Exception(
+ 'Class file for plugin "' . $plugin . '" cannot be found',
+ Phergie_Plugin_Exception::ERR_CLASS_NOT_FOUND
+ );
+ }
+
+ /**
+ * Adds a plugin instance to the handler.
+ *
+ * @param string|Phergie_Plugin_Abstract $plugin Short name of the
+ * plugin class or a plugin object
+ * @param array $args Optional array of
+ * arguments to pass to the plugin constructor if a short name is
+ * passed for $plugin
+ *
+ * @return Phergie_Plugin_Abstract New plugin instance
+ */
+ public function addPlugin($plugin, array $args = null)
+ {
+ // If a short plugin name is specified...
+ if (is_string($plugin)) {
+ $index = strtolower($plugin);
+ if (isset($this->plugins[$index])) {
+ return $this->plugins[$index];
+ }
+
+ // Attempt to locate and load the class
+ $info = $this->getPluginInfo($plugin);
+ $file = $info['file'];
+ $class = $info['class'];
+ include_once $file;
+ if (!class_exists($class, false)) {
+ throw new Phergie_Plugin_Exception(
+ 'File "' . $file . '" does not contain class "' . $class . '"',
+ Phergie_Plugin_Exception::ERR_CLASS_NOT_FOUND
+ );
+ }
+
+ // Check to ensure the class is a plugin class
+ if (!is_subclass_of($class, 'Phergie_Plugin_Abstract')) {
+ $msg
+ = 'Class for plugin "' . $plugin .
+ '" does not extend Phergie_Plugin_Abstract';
+ throw new Phergie_Plugin_Exception(
+ $msg,
+ Phergie_Plugin_Exception::ERR_INCORRECT_BASE_CLASS
+ );
+ }
+
+ // Check to ensure the class can be instantiated
+ $reflection = new ReflectionClass($class);
+ if (!$reflection->isInstantiable()) {
+ throw new Phergie_Plugin_Exception(
+ 'Class for plugin "' . $plugin . '" cannot be instantiated',
+ Phergie_Plugin_Exception::ERR_CLASS_NOT_INSTANTIABLE
+ );
+ }
+
+ // If the class is found, instantiate it
+ if (!empty($args)) {
+ $instance = $reflection->newInstanceArgs($args);
+ } else {
+ $instance = new $class;
+ }
+
+ // Store the instance
+ $this->plugins[$index] = $instance;
+ $plugin = $instance;
+
+ } elseif ($plugin instanceof Phergie_Plugin_Abstract) {
+ // If a plugin instance is specified...
+
+ // Add the plugin instance to the list of plugins
+ $this->plugins[strtolower($plugin->getName())] = $plugin;
+ }
+
+ // Configure and initialize the instance
+ $plugin->setPluginHandler($this);
+ $plugin->setConfig($this->config);
+ $plugin->setEventHandler($this->events);
+ $plugin->onLoad();
+
+ return $plugin;
+ }
+
+ /**
+ * Adds multiple plugin instances to the handler.
+ *
+ * @param array $plugins List of elements where each is of the form
+ * 'ShortPluginName' or array('ShortPluginName', array($arg1,
+ * ..., $argN))
+ *
+ * @return Phergie_Plugin_Handler Provides a fluent interface
+ */
+ public function addPlugins(array $plugins)
+ {
+ foreach ($plugins as $plugin) {
+ if (is_array($plugin)) {
+ $this->addPlugin($plugin[0], $plugin[1]);
+ } else {
+ $this->addPlugin($plugin);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Removes a plugin instance from the handler.
+ *
+ * @param string|Phergie_Plugin_Abstract $plugin Short name of the
+ * plugin class or a plugin object
+ *
+ * @return Phergie_Plugin_Handler Provides a fluent interface
+ */
+ public function removePlugin($plugin)
+ {
+ if ($plugin instanceof Phergie_Plugin_Abstract) {
+ $plugin = $plugin->getName();
+ }
+ $plugin = strtolower($plugin);
+
+ unset($this->plugins[$plugin]);
+
+ return $this;
+ }
+
+ /**
+ * Returns the corresponding instance for a specified plugin, loading it
+ * if it is not already loaded and autoloading is enabled.
+ *
+ * @param string $name Short name of the plugin class
+ *
+ * @return Phergie_Plugin_Abstract Plugin instance
+ */
+ public function getPlugin($name)
+ {
+ // If the plugin is loaded, return the instance
+ $lower = strtolower($name);
+ if (isset($this->plugins[$lower])) {
+ return $this->plugins[$lower];
+ }
+
+ // If autoloading is disabled, display an error
+ if (!$this->autoload) {
+ $msg
+ = 'Plugin "' . $name . '" has been requested, ' .
+ 'is not loaded, and autoload is disabled';
+ throw new Phergie_Plugin_Exception(
+ $msg,
+ Phergie_Plugin_Exception::ERR_PLUGIN_NOT_LOADED
+ );
+ }
+
+ // If autoloading is enabled, attempt to load the plugin
+ $plugin = $this->addPlugin($name);
+
+ // Return the added plugin
+ return $plugin;
+ }
+
+ /**
+ * Returns the corresponding instances for multiple specified plugins,
+ * loading them if they are not already loaded and autoloading is
+ * enabled.
+ *
+ * @param array $names Optional list of short names of the plugin
+ * classes to which the returned plugin list will be limited,
+ * defaults to all presently loaded plugins
+ *
+ * @return array Associative array mapping lowercased plugin class short
+ * names to corresponding plugin instances
+ */
+ public function getPlugins(array $names = array())
+ {
+ if (empty($names)) {
+ return $this->plugins;
+ }
+
+ $plugins = array();
+ foreach ($names as $name) {
+ $plugins[strtolower($name)] = $this->getPlugin($name);
+ }
+ return $plugins;
+ }
+
+ /**
+ * Returns whether or not at least one instance of a specified plugin
+ * class is loaded.
+ *
+ * @param string $name Short name of the plugin class
+ *
+ * @return bool TRUE if an instance exists, FALSE otherwise
+ */
+ public function hasPlugin($name)
+ {
+ return isset($this->plugins[strtolower($name)]);
+ }
+
+ /**
+ * Sets a flag used to determine whether plugins should be loaded
+ * automatically if they have not been explicitly loaded.
+ *
+ * @param bool $flag TRUE to have plugins autoload (default), FALSE
+ * otherwise
+ *
+ * @return Phergie_Plugin_Handler Provides a fluent interface.
+ */
+ public function setAutoload($flag = true)
+ {
+ $this->autoload = $flag;
+
+ return $this;
+ }
+
+ /**
+ * Returns the value of a flag used to determine whether plugins should
+ * be loaded automatically if they have not been explicitly loaded.
+ *
+ * @return bool TRUE if autoloading is enabled, FALSE otherwise
+ */
+ public function getAutoload()
+ {
+ return $this->autoload;
+ }
+
+ /**
+ * Allows plugin instances to be accessed as properties of the handler.
+ *
+ * @param string $name Short name of the plugin
+ *
+ * @return Phergie_Plugin_Abstract Requested plugin instance
+ */
+ public function __get($name)
+ {
+ return $this->getPlugin($name);
+ }
+
+ /**
+ * Allows plugin instances to be detected as properties of the handler.
+ *
+ * @param string $name Short name of the plugin
+ *
+ * @return bool TRUE if the plugin is loaded, FALSE otherwise
+ */
+ public function __isset($name)
+ {
+ return $this->hasPlugin($name);
+ }
+
+ /**
+ * Allows plugin instances to be removed as properties of handler.
+ *
+ * @param string $name Short name of the plugin
+ *
+ * @return void
+ */
+ public function __unset($name)
+ {
+ $this->removePlugin($name);
+ }
+
+ /**
+ * Returns an iterator for all currently loaded plugin instances.
+ *
+ * @return ArrayIterator
+ */
+ public function getIterator()
+ {
+ return new $this->iteratorClass(
+ new ArrayIterator($this->plugins)
+ );
+ }
+
+ /**
+ * Sets the iterator class used for all currently loaded plugin
+ * instances.
+ *
+ * @param string $class Name of a class that extends FilterIterator
+ *
+ * @return Phergie_Plugin_Handler Provides a fluent API
+ * @throws Phergie_Plugin_Exception Class cannot be found or is not an
+ * FilterIterator-based class
+ */
+ public function setIteratorClass($class)
+ {
+ $valid = true;
+
+ try {
+ $error_reporting = error_reporting(0); // ignore autoloader errors
+ $r = new ReflectionClass($class);
+ error_reporting($error_reporting);
+ if (!$r->isSubclassOf('FilterIterator')) {
+ $message = 'Class ' . $class . ' is not a subclass of FilterIterator';
+ $valid = false;
+ }
+ } catch (ReflectionException $e) {
+ $message = $e->getMessage();
+ $valid = false;
+ }
+
+ if (!$valid) {
+ throw new Phergie_Plugin_Exception(
+ $message,
+ Phergie_Plugin_Exception::ERR_INVALID_ITERATOR_CLASS
+ );
+ }
+
+ $this->iteratorClass = $class;
+ }
+
+ /**
+ * Proxies method calls to all plugins containing the called method.
+ *
+ * @param string $name Name of the method called
+ * @param array $args Arguments passed in the method call
+ *
+ * @return void
+ */
+ public function __call($name, array $args)
+ {
+ foreach ($this->getIterator() as $plugin) {
+ call_user_func_array(array($plugin, $name), $args);
+ }
+ return true;
+ }
+
+ /**
+ * Returns the number of plugins contained within the handler.
+ *
+ * @return int Plugin count
+ */
+ public function count()
+ {
+ return count($this->plugins);
+ }
+}