diff --git a/plugins/Irc/extlib/phergie/Phergie/Autoload.php b/plugins/Irc/extlib/phergie/Phergie/Autoload.php index b03fe2ae10..0004f44e22 100755 --- a/plugins/Irc/extlib/phergie/Phergie/Autoload.php +++ b/plugins/Irc/extlib/phergie/Phergie/Autoload.php @@ -1,6 +1,6 @@ * @copyright 2008-2010 Phergie Development Team (http://phergie.org) @@ -22,7 +22,7 @@ /** * Autoloader for Phergie classes. * - * @category Phergie + * @category Phergie * @package Phergie * @author Phergie Development Team * @license http://phergie.org/license New BSD License @@ -37,9 +37,9 @@ class Phergie_Autoload */ public function __construct() { - $path = dirname(__FILE__); + $path = realpath(dirname(__FILE__) . '/..'); $includePath = get_include_path(); - $includePathList = explode(PATH_SEPARATOR, $includePath); + $includePathList = explode(PATH_SEPARATOR, $includePath); if (!in_array($path, $includePathList)) { self::addPath($path); } @@ -54,9 +54,6 @@ class Phergie_Autoload */ public function load($class) { - if (substr($class, 0, 8) == 'Phergie_') { - $class = substr($class, 8); - } include str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php'; } diff --git a/plugins/Irc/extlib/phergie/Phergie/Bot.php b/plugins/Irc/extlib/phergie/Phergie/Bot.php index 153bd55905..85e8a00fc9 100755 --- a/plugins/Irc/extlib/phergie/Phergie/Bot.php +++ b/plugins/Irc/extlib/phergie/Phergie/Bot.php @@ -1,6 +1,6 @@ * @copyright 2008-2010 Phergie Development Team (http://phergie.org) @@ -22,7 +22,7 @@ /** * Composite class for other components to represent the bot. * - * @category Phergie + * @category Phergie * @package Phergie * @author Phergie Development Team * @license http://phergie.org/license New BSD License @@ -50,9 +50,9 @@ class Phergie_Bot protected $config; /** - * Current connection handler instance + * Current connection handler instance * - * @var Phergie_Connection_Handler + * @var Phergie_Connection_Handler */ protected $connections; @@ -85,7 +85,7 @@ class Phergie_Bot protected $processor; /** - * Returns a driver instance, creating one of the default class if + * Returns a driver instance, creating one of the default class if * none has been set. * * @return Phergie_Driver_Abstract @@ -135,14 +135,14 @@ class Phergie_Bot } /** - * Returns the entire configuration in use or the value of a specific + * Returns the entire configuration in use or the value of a specific * configuration setting. * - * @param string $index Optional index of a specific configuration + * @param string $index Optional index of a specific configuration * setting for which the corresponding value should be returned * @param mixed $default Value to return if no match is found for $index * - * @return mixed Value corresponding to $index or the entire + * @return mixed Value corresponding to $index or the entire * configuration if $index is not specified */ public function getConfig($index = null, $default = null) @@ -219,7 +219,7 @@ class Phergie_Bot } /** - * Returns a connection handler instance, creating it if it does not + * Returns a connection handler instance, creating it if it does not * already exist and using a default class if none has been set. * * @return Phergie_Connection_Handler @@ -246,7 +246,7 @@ class Phergie_Bot } /** - * Returns an end-user interface instance, creating it if it does not + * Returns an end-user interface instance, creating it if it does not * already exist and using a default class if none has been set. * * @return Phergie_Ui_Abstract @@ -273,7 +273,7 @@ class Phergie_Bot } /** - * Returns a processer instance, creating one if none exists. + * Returns a processer instance, creating one if none exists. * * @return Phergie_Process_Abstract */ @@ -281,14 +281,14 @@ class Phergie_Bot { if (empty($this->processor)) { $class = 'Phergie_Process_Standard'; - + $type = $this->getConfig('processor'); if (!empty($type)) { $class = 'Phergie_Process_' . ucfirst($type); } $this->processor = new $class( - $this, + $this, $this->getConfig('processor.options', array()) ); } @@ -318,7 +318,7 @@ class Phergie_Bot $config = $this->getConfig(); $plugins = $this->getPluginHandler(); $ui = $this->getUi(); - + $plugins->setAutoload($config['plugins.autoload']); foreach ($config['plugins'] as $name) { try { @@ -358,15 +358,15 @@ class Phergie_Bot } /** - * Establishes server connections and initiates an execution loop to + * Establishes server connections and initiates an execution loop to * continuously receive and process events. * - * @return Phergie_Bot Provides a fluent interface + * @return Phergie_Bot Provides a fluent interface */ public function run() { set_time_limit(0); - + $timezone = $this->getConfig('timezone', 'UTC'); date_default_timezone_set($timezone); diff --git a/plugins/Irc/extlib/phergie/Phergie/Connection.php b/plugins/Irc/extlib/phergie/Phergie/Connection.php index 80f91e8da5..d6c89ea801 100755 --- a/plugins/Irc/extlib/phergie/Phergie/Connection.php +++ b/plugins/Irc/extlib/phergie/Phergie/Connection.php @@ -1,6 +1,6 @@ * @copyright 2008-2010 Phergie Development Team (http://phergie.org) @@ -22,7 +22,7 @@ /** * Data structure for connection metadata. * - * @category Phergie + * @category Phergie * @package Phergie * @author Phergie Development Team * @license http://phergie.org/license New BSD License @@ -38,7 +38,7 @@ class Phergie_Connection protected $host; /** - * Port on which the client will connect, defaults to the standard IRC + * Port on which the client will connect, defaults to the standard IRC * port * * @var int @@ -46,13 +46,21 @@ class Phergie_Connection protected $port; /** - * Transport for the connection, defaults to tcp but can be set to ssl + * Transport for the connection, defaults to tcp but can be set to ssl * or variations thereof to connect over SSL * - * @var string + * @var string */ protected $transport; + /** + * Encoding method for the connection, defaults to ISO-8859-1 but can + * be set to UTF8 if necessary + * + * @var strng + */ + protected $encoding; + /** * Nick that the client will use * @@ -91,7 +99,7 @@ class Phergie_Connection /** * Constructor to initialize instance properties. * - * @param array $options Optional associative array of property values + * @param array $options Optional associative array of property values * to initialize * * @return void @@ -99,6 +107,9 @@ class Phergie_Connection public function __construct(array $options = array()) { $this->transport = 'tcp'; + $this->encoding = 'ISO-8859-1'; + // @note this may need changed to something different, for broader support. + // @note also may need to make use of http://us.php.net/manual/en/function.stream-encoding.php $this->setOptions($options); } @@ -120,7 +131,7 @@ class Phergie_Connection ); } } - + /** * Returns a hostmask that uniquely identifies the connection. * @@ -136,7 +147,7 @@ class Phergie_Connection ); } - return $this->hostmask; + return $this->hostmask; } /** @@ -144,7 +155,7 @@ class Phergie_Connection * * @param string $host Hostname * - * @return Phergie_Connection Provides a fluent interface + * @return Phergie_Connection Provides a fluent interface */ public function setHost($host) { @@ -154,9 +165,9 @@ class Phergie_Connection return $this; } - + /** - * Returns the host to which the client will connect if it is set or + * Returns the host to which the client will connect if it is set or * emits an error if it is not set. * * @return string @@ -173,7 +184,7 @@ class Phergie_Connection * * @param int $port Port * - * @return Phergie_Connection Provides a fluent interface + * @return Phergie_Connection Provides a fluent interface */ public function setPort($port) { @@ -199,9 +210,9 @@ class Phergie_Connection } /** - * Sets the transport for the connection to use. + * Sets the transport for the connection to use. * - * @param string $transport Transport (ex: tcp, ssl, etc.) + * @param string $transport Transport (ex: tcp, ssl, etc.) * * @return Phergie_Connection Provides a fluent interface */ @@ -220,21 +231,52 @@ class Phergie_Connection } /** - * Returns the transport in use by the connection. + * Returns the transport in use by the connection. * - * @return string Transport (ex: tcp, ssl, etc.) + * @return string Transport (ex: tcp, ssl, etc.) */ public function getTransport() { return $this->transport; } + /** + * Sets the encoding for the connection to use. + * + * @param string $encoding Encoding to use (ex: ASCII, ISO-8859-1, UTF8, etc.) + * + * @return Phergie_Connection Provides a fluent interface + */ + public function setEncoding($encoding) + { + $this->encoding = (string) $encoding; + + if (!in_array($this->encoding, mb_list_encodings())) { + throw new Phergie_Connection_Exception( + 'Encoding ' . $this->encoding . ' is not supported', + Phergie_Connection_Exception::ENCODING_NOT_SUPPORTED + ); + } + + return $this; + } + + /** + * Returns the encoding in use by the connection. + * + * @return string Encoding (ex: ASCII, ISO-8859-1, UTF8, etc.) + */ + public function getEncoding() + { + return $this->encoding; + } + /** * Sets the nick that the client will use. * * @param string $nick Nickname * - * @return Phergie_Connection Provides a fluent interface + * @return Phergie_Connection Provides a fluent interface */ public function setNick($nick) { @@ -262,7 +304,7 @@ class Phergie_Connection * * @param string $username Username * - * @return Phergie_Connection Provides a fluent interface + * @return Phergie_Connection Provides a fluent interface */ public function setUsername($username) { @@ -290,7 +332,7 @@ class Phergie_Connection * * @param string $realname Real name * - * @return Phergie_Connection Provides a fluent interface + * @return Phergie_Connection Provides a fluent interface */ public function setRealname($realname) { @@ -318,7 +360,7 @@ class Phergie_Connection * * @param string $password Password * - * @return Phergie_Connection Provides a fluent interface + * @return Phergie_Connection Provides a fluent interface */ public function setPassword($password) { @@ -342,10 +384,10 @@ class Phergie_Connection /** * Sets multiple connection settings using an array. * - * @param array $options Associative array of setting names mapped to + * @param array $options Associative array of setting names mapped to * corresponding values * - * @return Phergie_Connection Provides a fluent interface + * @return Phergie_Connection Provides a fluent interface */ public function setOptions(array $options) { diff --git a/plugins/Irc/extlib/phergie/Phergie/Db/Exception.php b/plugins/Irc/extlib/phergie/Phergie/Db/Exception.php new file mode 100644 index 0000000000..77421108ad --- /dev/null +++ b/plugins/Irc/extlib/phergie/Phergie/Db/Exception.php @@ -0,0 +1,39 @@ + + * @copyright 2008-2010 Phergie Development Team (http://phergie.org) + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie + */ + +/** + * Exceptions related to handling databases for plugins. + * + * @category Phergie + * @package Phergie + * @author Phergie Development Team + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie + */ + +class Phergie_Db_Exception extends Phergie_Exception +{ + /** + * Error indicating that a directory needed to support database + * functionality was unable to be created. + */ + const ERR_UNABLE_TO_CREATE_DIRECTORY = 1; +} diff --git a/plugins/Irc/extlib/phergie/Phergie/Db/Manager.php b/plugins/Irc/extlib/phergie/Phergie/Db/Manager.php new file mode 100755 index 0000000000..2a8215e96d --- /dev/null +++ b/plugins/Irc/extlib/phergie/Phergie/Db/Manager.php @@ -0,0 +1,49 @@ + + * @copyright 2008-2010 Phergie Development Team (http://phergie.org) + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie_Command + */ + +/** + * Database management class. Provides a base API for managing databases + * within + * + * @category Phergie + * @package Phergie + * @author Phergie Development Team + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie_Db_Manager + */ +abstract class Phergie_Db_Manager +{ + /** + * Returns a connection to the database. + * + * @return object + */ + public abstract function getDb(); + + /** + * Checks if a table/collection exists within the database. + * + * @param string $table Table/collection name to check for + * + * @return boolean + */ + public abstract function hasTable($table); +} diff --git a/plugins/Irc/extlib/phergie/Phergie/Db/Sqlite.php b/plugins/Irc/extlib/phergie/Phergie/Db/Sqlite.php new file mode 100644 index 0000000000..14ee520fd1 --- /dev/null +++ b/plugins/Irc/extlib/phergie/Phergie/Db/Sqlite.php @@ -0,0 +1,117 @@ + + * @copyright 2008-2010 Phergie Development Team (http://phergie.org) + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie + */ + +/** + * Provides basic management for SQLite databases + * + * @category Phergie + * @package Phergie + * @author Phergie Development Team + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie + */ +class Phergie_Db_Sqlite extends Phergie_Db_Manager +{ + /** + * Database connection + * + * @var PDO + */ + protected $db; + + /** + * Database file path + * + * @var string + */ + protected $dbFile; + + /** + * Allows setting of the database file path when creating the class. + * + * @param string $dbFile database file path (optional) + * + * @return void + */ + public function __construct($dbFile = null) + { + if ($dbFile != null) { + $this->setDbFile($dbFile); + } + } + + /** + * Sets the database file path. + * + * @param string $dbFile SQLite database file path + * + * @return null + */ + public function setDbFile($dbFile) + { + if (is_string($dbFile) && !empty($dbFile)) { + $this->dbFile = $dbFile; + } + } + + /** + * Returns a configured database connection. + * + * @return PDO + */ + public function getDb() + { + if (!empty($this->db)) { + return $this->db; + } + + $dir = dirname($this->dbFile); + if (!is_dir($dir) && !mkdir($dir, 0755, true)) { + throw new Phergie_Db_Exception( + 'Unable to create directory', + Phergie_Db_Exception::ERR_UNABLE_TO_CREATE_DIRECTORY + ); + } + + $this->db = new PDO('sqlite:' . $this->dbFile); + + return $this->db; + } + + + /** + * Returns whether a given table exists in the database. + * + * @param string $table Name of the table to check for + * + * @return boolean TRUE if the table exists, FALSE otherwise + */ + public function hasTable($table) + { + $db = $this->getDb(); + + return (bool) $db->query( + 'SELECT COUNT(*) FROM sqlite_master WHERE name = ' + . $db->quote($table) + )->fetchColumn(); + } +} diff --git a/plugins/Irc/extlib/phergie/Phergie/Driver/Exception.php b/plugins/Irc/extlib/phergie/Phergie/Driver/Exception.php index c405522292..aa2b838f7e 100755 --- a/plugins/Irc/extlib/phergie/Phergie/Driver/Exception.php +++ b/plugins/Irc/extlib/phergie/Phergie/Driver/Exception.php @@ -46,4 +46,9 @@ class Phergie_Driver_Exception extends Phergie_Exception * Error indicating that an attempt to initiate a connection failed */ const ERR_CONNECTION_ATTEMPT_FAILED = 3; + + /** + * Error indicating that an attempt to send data via a connection failed + */ + const ERR_CONNECTION_WRITE_FAILED = 4; } diff --git a/plugins/Irc/extlib/phergie/Phergie/Driver/Streams.php b/plugins/Irc/extlib/phergie/Phergie/Driver/Streams.php index 8fe53aaa2f..bb0c611aa3 100755 --- a/plugins/Irc/extlib/phergie/Phergie/Driver/Streams.php +++ b/plugins/Irc/extlib/phergie/Phergie/Driver/Streams.php @@ -1,6 +1,6 @@ * @copyright 2008-2010 Phergie Development Team (http://phergie.org) @@ -20,11 +20,11 @@ */ /** - * Driver that uses the sockets wrapper of the streams extension for - * communicating with the server and handles formatting and parsing of + * Driver that uses the sockets wrapper of the streams extension for + * communicating with the server and handles formatting and parsing of * events using PHP. * - * @category Phergie + * @category Phergie * @package Phergie * @author Phergie Development Team * @license http://phergie.org/license New BSD License @@ -47,26 +47,29 @@ class Phergie_Driver_Streams extends Phergie_Driver_Abstract protected $socket; /** - * Amount of time in seconds to wait to receive an event each time the + * Amount of time in seconds to wait to receive an event each time the * socket is polled * - * @var float + * @var float */ protected $timeout = 0.1; /** - * Handles construction of command strings and their transmission to the + * Handles construction of command strings and their transmission to the * server. * * @param string $command Command to send - * @param string|array $args Optional string or array of sequential + * @param string|array $args Optional string or array of sequential * arguments * - * @return string Command string that was sent + * @return string Command string that was sent * @throws Phergie_Driver_Exception */ protected function send($command, $args = '') { + $connection = $this->getConnection(); + $encoding = $connection->getEncoding(); + // Require an open socket connection to continue if (empty($this->socket)) { throw new Phergie_Driver_Exception( @@ -86,20 +89,40 @@ class Phergie_Driver_Streams extends Phergie_Driver_Abstract $end = count($args) - 1; $args[$end] = ':' . $args[$end]; $args = implode(' ', $args); + } else { + $args = ':' . $args; } $buffer .= ' ' . $args; } // Transmit the command over the socket connection - fwrite($this->socket, $buffer . "\r\n"); + $attempts = $written = 0; + $temp = $buffer . "\r\n"; + $is_multibyte = !substr($encoding, 0, 8) === 'ISO-8859' && $encoding !== 'ASCII' && $encoding !== 'CP1252'; + $length = ($is_multibyte) ? mb_strlen($buffer, '8bit') : strlen($buffer); + while (true) { + $written += (int) fwrite($this->socket, $temp); + if ($written < $length) { + $temp = substr($temp, $written); + $attempts++; + if ($attempts == 3) { + throw new Phergie_Driver_Exception( + 'Unable to write to socket', + Phergie_Driver_Exception::ERR_CONNECTION_WRITE_FAILED + ); + } + } else { + break; + } + } // Return the command string that was transmitted return $buffer; } /** - * Overrides the parent class to set the currently active socket handler + * Overrides the parent class to set the currently active socket handler * when the active connection is changed. * * @param Phergie_Connection $connection Active connection @@ -120,11 +143,11 @@ class Phergie_Driver_Streams extends Phergie_Driver_Abstract /** * Returns a list of hostmasks corresponding to sockets with data to read. - * + * * @param int $sec Length of time to wait for new data (seconds) * @param int $usec Length of time to wait for new data (microseconds) * - * @return array List of hostmasks or an empty array if none were found + * @return array List of hostmasks or an empty array if none were found * to have data to read */ public function getActiveReadSockets($sec = 0, $usec = 200000) @@ -147,7 +170,7 @@ class Phergie_Driver_Streams extends Phergie_Driver_Abstract } /** - * Sets the amount of time to wait for a new event each time the socket + * Sets the amount of time to wait for a new event each time the socket * is polled. * * @param float $timeout Amount of time in seconds @@ -164,7 +187,7 @@ class Phergie_Driver_Streams extends Phergie_Driver_Abstract } /** - * Returns the amount of time to wait for a new event each time the + * Returns the amount of time to wait for a new event each time the * socket is polled. * * @return float Amount of time in seconds @@ -175,7 +198,7 @@ class Phergie_Driver_Streams extends Phergie_Driver_Abstract } /** - * Supporting method to parse event argument strings where the last + * Supporting method to parse event argument strings where the last * argument may contain a colon. * * @param string $args Argument string to parse @@ -191,7 +214,7 @@ class Phergie_Driver_Streams extends Phergie_Driver_Abstract /** * Listens for an event on the current connection. * - * @return Phergie_Event_Interface|null Event instance if an event was + * @return Phergie_Event_Interface|null Event instance if an event was * received, NULL otherwise */ public function getEvent() @@ -217,7 +240,7 @@ class Phergie_Driver_Streams extends Phergie_Driver_Abstract // If the event could be from the server or a user... // Parse the server hostname or user hostmask, command, and arguments - list($prefix, $cmd, $args) + list($prefix, $cmd, $args) = array_pad(explode(' ', ltrim($buffer, ':'), 3), 3, null); if (strpos($prefix, '@') !== false) { $hostmask = Phergie_Hostmask::fromString($prefix); @@ -279,17 +302,17 @@ class Phergie_Driver_Streams extends Phergie_Driver_Abstract case 'oper': case 'topic': case 'mode': - $args = $this->parseArguments($args); + $args = $this->parseArguments($args); break; case 'part': case 'kill': case 'invite': - $args = $this->parseArguments($args, 2); + $args = $this->parseArguments($args, 2); break; case 'kick': - $args = $this->parseArguments($args, 3); + $args = $this->parseArguments($args, 3); break; // Remove the target from responses @@ -360,14 +383,14 @@ class Phergie_Driver_Streams extends Phergie_Driver_Abstract $this->send( 'USER', array( - $username, - $hostname, - $hostname, + $username, + $hostname, + $hostname, $realname ) ); - $this->send('NICK', $nick); + $this->send('NICK', $nick); // Add the socket handler to the internal array for socket handlers $this->sockets[(string) $connection->getHostmask()] = $this->socket; @@ -395,7 +418,7 @@ class Phergie_Driver_Streams extends Phergie_Driver_Abstract /** * Joins a channel. * - * @param string $channels Comma-delimited list of channels to join + * @param string $channels Comma-delimited list of channels to join * @param string $keys Optional comma-delimited list of channel keys * * @return void @@ -414,7 +437,7 @@ class Phergie_Driver_Streams extends Phergie_Driver_Abstract /** * Leaves a channel. * - * @param string $channels Comma-delimited list of channels to leave + * @param string $channels Comma-delimited list of channels to leave * * @return void */ @@ -600,9 +623,9 @@ class Phergie_Driver_Streams extends Phergie_Driver_Abstract /** * Sends a CTCP response to a user. * - * @param string $nick User nick + * @param string $nick User nick * @param string $command Command to send - * @param string|array $args String or array of sequential arguments + * @param string|array $args String or array of sequential arguments * (optional) * * @return void @@ -615,7 +638,7 @@ class Phergie_Driver_Streams extends Phergie_Driver_Abstract $buffer = rtrim(strtoupper($command) . ' ' . $args); - $this->doNotice($nick, chr(1) . $buffer . chr(1)); + $this->doNotice($nick, chr(1) . $buffer . chr(1)); } /** @@ -652,7 +675,7 @@ class Phergie_Driver_Streams extends Phergie_Driver_Abstract * Sends a CTCP TIME request to a user. * * @param string $nick User nick - * @param string $time Time string to send for a response + * @param string $time Time string to send for a response * * @return void */ diff --git a/plugins/Irc/extlib/phergie/Phergie/Event/Handler.php b/plugins/Irc/extlib/phergie/Phergie/Event/Handler.php index 7df1fca35a..e308df8a56 100644 --- a/plugins/Irc/extlib/phergie/Phergie/Event/Handler.php +++ b/plugins/Irc/extlib/phergie/Phergie/Event/Handler.php @@ -1,6 +1,6 @@ * @copyright 2008-2010 Phergie Development Team (http://phergie.org) @@ -20,9 +20,9 @@ */ /** - * Handles events initiated by plugins. + * Handles events initiated by plugins. * - * @category Phergie + * @category Phergie * @package Phergie * @author Phergie Development Team * @license http://phergie.org/license New BSD License @@ -51,13 +51,13 @@ class Phergie_Event_Handler implements IteratorAggregate, Countable * Adds an event to the queue. * * @param Phergie_Plugin_Abstract $plugin Plugin originating the event - * @param string $type Event type, corresponding to a + * @param string $type Event type, corresponding to a * Phergie_Event_Command::TYPE_* constant * @param array $args Optional event arguments * * @return Phergie_Event_Handler Provides a fluent interface */ - public function addEvent(Phergie_Plugin_Abstract $plugin, $type, + public function addEvent(Phergie_Plugin_Abstract $plugin, $type, array $args = array() ) { if (!defined('Phergie_Event_Command::TYPE_' . strtoupper($type))) { @@ -102,7 +102,7 @@ class Phergie_Event_Handler implements IteratorAggregate, Countable /** * Replaces the current event queue with a given queue of events. * - * @param array $events Ordered list of objects of the class + * @param array $events Ordered list of objects of the class * Phergie_Event_Command * * @return Phergie_Event_Handler Provides a fluent interface @@ -116,10 +116,10 @@ class Phergie_Event_Handler implements IteratorAggregate, Countable /** * Returns whether an event of the given type exists in the queue. * - * @param string $type Event type from Phergie_Event_Request::TYPE_* + * @param string $type Event type from Phergie_Event_Request::TYPE_* * constants * - * @return bool TRUE if an event of the specified type exists in the + * @return bool TRUE if an event of the specified type exists in the * queue, FALSE otherwise */ public function hasEventOfType($type) @@ -135,10 +135,10 @@ class Phergie_Event_Handler implements IteratorAggregate, Countable /** * Returns a list of events of a specified type. * - * @param string $type Event type from Phergie_Event_Request::TYPE_* + * @param string $type Event type from Phergie_Event_Request::TYPE_* * constants * - * @return array Array containing event instances of the specified type + * @return array Array containing event instances of the specified type * or an empty array if no such events were found */ public function getEventsOfType($type) @@ -152,6 +152,22 @@ class Phergie_Event_Handler implements IteratorAggregate, Countable return $events; } + /** + * Removes a single event from the event queue. + * + * @param Phergie_Event_Command $event Event to remove + * + * @return Phergie_Event_Handler Provides a fluent interface + */ + public function removeEvent(Phergie_Event_Command $event) + { + $key = array_search($event, $this->events); + if ($key !== false) { + unset($this->events[$key]); + } + return $this; + } + /** * Returns an iterator for the current event queue. * diff --git a/plugins/Irc/extlib/phergie/Phergie/Event/Request.php b/plugins/Irc/extlib/phergie/Phergie/Event/Request.php index a559d9dbe5..647b5acb87 100755 --- a/plugins/Irc/extlib/phergie/Phergie/Event/Request.php +++ b/plugins/Irc/extlib/phergie/Phergie/Event/Request.php @@ -1,6 +1,6 @@ * @copyright 2008-2010 Phergie Development Team (http://phergie.org) @@ -22,15 +22,15 @@ /** * Autonomous event originating from a user or the server. * - * @category Phergie + * @category Phergie * @package Phergie * @author Phergie Development Team * @license http://phergie.org/license New BSD License * @link http://pear.phergie.org/package/Phergie * @link http://www.irchelp.org/irchelp/rfc/chapter4.html */ -class Phergie_Event_Request - extends Phergie_Event_Abstract +class Phergie_Event_Request + extends Phergie_Event_Abstract implements ArrayAccess { /** @@ -240,6 +240,24 @@ class Phergie_Event_Request return $this; } + /** + * Sets the value of a single argument for the request. + * + * @param mixed $argument Integer position (starting from 0) or the + * equivalent string name of the argument from self::$map + * @param string $value Value to assign to the argument + * + * @return Phergie_Event_Request Provides a fluent interface + */ + public function setArgument($argument, $value) + { + $argument = $this->resolveArgument($argument); + if ($argument !== null) { + $this->arguments[$argument] = (string) $value; + } + return $this; + } + /** * Returns the arguments for the request. * @@ -256,13 +274,13 @@ class Phergie_Event_Request * @param mixed $argument Integer position (starting from 0) or the * equivalent string name of the argument from self::$map * - * @return int|null Integer position of the argument or NULL if no + * @return int|null Integer position of the argument or NULL if no * corresponding argument was found */ protected function resolveArgument($argument) { if (isset($this->arguments[$argument])) { - return $argument; + return $argument; } else { $argument = strtolower($argument); if (isset(self::$map[$this->type][$argument]) @@ -285,7 +303,7 @@ class Phergie_Event_Request public function getArgument($argument) { $argument = $this->resolveArgument($argument); - if ($argument !== null) { + if ($argument !== null) { return $this->arguments[$argument]; } return null; @@ -325,9 +343,9 @@ class Phergie_Event_Request } /** - * Returns the channel name if the event occurred in a channel or the - * user nick if the event was a private message directed at the bot by a - * user. + * Returns the channel name if the event occurred in a channel or the + * user nick if the event was a private message directed at the bot by a + * user. * * @return string */ @@ -395,7 +413,7 @@ class Phergie_Event_Request * * @param string|int $offset Argument name or position beginning from 0 * - * @return bool TRUE if the argument has a value, FALSE otherwise + * @return bool TRUE if the argument has a value, FALSE otherwise * @see ArrayAccess::offsetExists() */ public function offsetExists($offset) @@ -428,7 +446,7 @@ class Phergie_Event_Request public function offsetSet($offset, $value) { $offset = $this->resolveArgument($offset); - if ($offset !== null) { + if ($offset !== null) { $this->arguments[$offset] = $value; } } diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Abstract.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Abstract.php index 294c04ce52..d7e0d351af 100755 --- a/plugins/Irc/extlib/phergie/Phergie/Plugin/Abstract.php +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Abstract.php @@ -1,6 +1,6 @@ * @copyright 2008-2010 Phergie Development Team (http://phergie.org) @@ -23,7 +23,7 @@ * Base class for plugins to provide event handler stubs and commonly needed * functionality. * - * @category Phergie + * @category Phergie * @package Phergie * @author Phergie Development Team * @license http://phergie.org/license New BSD License @@ -66,6 +66,13 @@ abstract class Phergie_Plugin_Abstract */ protected $event; + /** + * Plugin short name + * + * @var string + */ + protected $name; + /** * Returns the short name for the plugin based on its class name. * @@ -73,14 +80,30 @@ abstract class Phergie_Plugin_Abstract */ public function getName() { - return substr(strrchr(get_class($this), '_'), 1); + if (empty($this->name)) { + $this->name = substr(strrchr(get_class($this), '_'), 1); + } + return $this->name; } /** - * Indicates that the plugin failed to load due to an unsatisfied + * Sets the short name for the plugin. + * + * @param string $name Plugin short name + * + * @return Phergie_Plugin_Abstract Provides a fluent interface + */ + public function setName($name) + { + $this->name = (string) $name; + return $this; + } + + /** + * Indicates that the plugin failed to load due to an unsatisfied * runtime requirement, such as a missing dependency. * - * @param string $message Error message to provide more information + * @param string $message Error message to provide more information * about the reason for the failure * * @return Phergie_Plugin_Abstract Provides a fluent interface @@ -108,17 +131,17 @@ abstract class Phergie_Plugin_Abstract } /** - * Returns the current configuration handler or the value of a single + * Returns the current configuration handler or the value of a single * setting from it. * - * @param string $name Optional name of a setting for which the value + * @param string $name Optional name of a setting for which the value * should be returned instead of the entire configuration handler - * @param mixed $default Optional default value to return if no value + * @param mixed $default Optional default value to return if no value * is set for the setting indicated by $name * - * @return Phergie_Config|mixed Configuration handler or value of the + * @return Phergie_Config|mixed Configuration handler or value of the * setting specified by $name - * @throws Phergie_Plugin_Exception No configuration handler has been set + * @throws Phergie_Plugin_Exception No configuration handler has been set */ public function getConfig($name = null, $default = null) { @@ -154,7 +177,7 @@ abstract class Phergie_Plugin_Abstract * Returns the current plugin handler. * * @return Phergie_Plugin_Handler - * @throws Phergie_Plugin_Exception No plugin handler has been set + * @throws Phergie_Plugin_Exception No plugin handler has been set */ public function getPluginHandler() { @@ -184,7 +207,7 @@ abstract class Phergie_Plugin_Abstract * Returns the current event handler. * * @return Phergie_Event_Handler - * @throws Phergie_Plugin_Exception No event handler has been set + * @throws Phergie_Plugin_Exception No event handler has been set */ public function getEventHandler() { @@ -214,7 +237,7 @@ abstract class Phergie_Plugin_Abstract * Returns the current event connection. * * @return Phergie_Connection - * @throws Phergie_Plugin_Exception No connection has been set + * @throws Phergie_Plugin_Exception No connection has been set */ public function getConnection() { @@ -281,8 +304,8 @@ abstract class Phergie_Plugin_Abstract } /** - * Handler for when the plugin is initially loaded - useful for checking - * runtime dependencies or performing any setup necessary for the plugin + * Handler for when the plugin is initially loaded - useful for checking + * runtime dependencies or performing any setup necessary for the plugin * to function properly such as initializing a database. * * @return void @@ -301,8 +324,8 @@ abstract class Phergie_Plugin_Abstract } /** - * Handler for each tick, a single iteration of the continuous loop - * executed by the bot to receive, handle, and send events - useful for + * Handler for each tick, a single iteration of the continuous loop + * executed by the bot to receive, handle, and send events - useful for * repeated execution of tasks on a time interval. * * @return void @@ -312,10 +335,10 @@ abstract class Phergie_Plugin_Abstract } /** - * Handler for when any event is received but has not yet been dispatched + * Handler for when any event is received but has not yet been dispatched * to the plugin handler method specific to its event type. * - * @return bool|null|void FALSE to short-circuit further event + * @return bool|null|void FALSE to short-circuit further event * processing, TRUE or NULL otherwise */ public function preEvent() @@ -323,8 +346,8 @@ abstract class Phergie_Plugin_Abstract } /** - * Handler for after plugin processing of an event has concluded but - * before any events triggered in response by plugins are sent to the + * Handler for after plugin processing of an event has concluded but + * before any events triggered in response by plugins are sent to the * server - useful for modifying outgoing events before they are sent. * * @return void @@ -334,8 +357,8 @@ abstract class Phergie_Plugin_Abstract } /** - * Handler for after any events triggered by plugins in response to a - * received event are sent to the server. + * Handler for after any events triggered by plugins in response to a + * received event are sent to the server. * * @return void */ @@ -454,12 +477,12 @@ abstract class Phergie_Plugin_Abstract } /** - * Handler for when the bot receives a ping event from a server, at - * which point it is expected to respond with a pong request within + * Handler for when the bot receives a ping event from a server, at + * which point it is expected to respond with a pong request within * a short period else the server may terminate its connection. * * @return void - * @link http://irchelp.org/irchelp/rfc/chapter4.html#c4_6_2 + * @link http://irchelp.org/irchelp/rfc/chapter4.html#c4_6_2 */ public function onPing() { @@ -496,7 +519,7 @@ abstract class Phergie_Plugin_Abstract } /** - * Handler for when the bot receives a CTCP request of an unknown type. + * Handler for when the bot receives a CTCP request of an unknown type. * * @return void * @link http://www.invlogic.com/irc/ctcp.html @@ -506,7 +529,7 @@ abstract class Phergie_Plugin_Abstract } /** - * Handler for when a reply is received for a CTCP PING request sent by + * Handler for when a reply is received for a CTCP PING request sent by * the bot. * * @return void @@ -517,7 +540,7 @@ abstract class Phergie_Plugin_Abstract } /** - * Handler for when a reply is received for a CTCP TIME request sent by + * Handler for when a reply is received for a CTCP TIME request sent by * the bot. * * @return void @@ -528,7 +551,7 @@ abstract class Phergie_Plugin_Abstract } /** - * Handler for when a reply is received for a CTCP VERSION request sent + * Handler for when a reply is received for a CTCP VERSION request sent * by the bot. * * @return void @@ -539,7 +562,7 @@ abstract class Phergie_Plugin_Abstract } /** - * Handler for when a reply received for a CTCP request of an unknown + * Handler for when a reply received for a CTCP request of an unknown * type. * * @return void @@ -560,7 +583,7 @@ abstract class Phergie_Plugin_Abstract } /** - * Handler for when the bot receives an invitation to join a channel. + * Handler for when the bot receives an invitation to join a channel. * * @return void * @link http://irchelp.org/irchelp/rfc/chapter4.html#c4_2_7 @@ -570,7 +593,7 @@ abstract class Phergie_Plugin_Abstract } /** - * Handler for when a server response is received to a command issued by + * Handler for when a server response is received to a command issued by * the bot. * * @return void diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Censor.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Censor.php new file mode 100755 index 0000000000..3206bdd288 --- /dev/null +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Censor.php @@ -0,0 +1,108 @@ + + * @copyright 2008-2010 Phergie Development Team (http://phergie.org) + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie_Plugin_Censor + */ + +/** + * Facilitates censoring of event content or discardment of events + * containing potentially offensive phrases depending on the value of the + * configuration setting censor.mode ('off', 'censor', 'discard'). Also + * provides access to a web service for detecting censored words so that + * other plugins may optionally integrate and adjust behavior accordingly to + * prevent discardment of events. + * + * @category Phergie + * @package Phergie_Plugin_Censor + * @author Phergie Development Team + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie_Plugin_Censor + * @uses extension soap + */ +class Phergie_Plugin_Censor extends Phergie_Plugin_Abstract +{ + /** + * SOAP client to interact with the CDYNE Profanity Filter API + * + * @var SoapClient + */ + protected $soap; + + /** + * Checks for dependencies. + * + * @return void + */ + public function onLoad() + { + if (!extension_loaded('soap')) { + $this->fail('The PHP soap extension is required'); + } + + if (!in_array($this->config['censor.mode'], array('censor', 'discard'))) { + $this->plugins->removePlugin($this); + } + } + + /** + * Returns a "clean" version of a given string. + * + * @param string $string String to clean + * + * @return string Cleaned string + */ + public function cleanString($string) + { + if (empty($this->soap)) { + $this->soap = new SoapClient('http://ws.cdyne.com/ProfanityWS/Profanity.asmx?wsdl'); + } + $params = array('Text' => $string); + $response = $this->soap->SimpleProfanityFilter($params); + return $response->SimpleProfanityFilterResult->CleanText; + } + + /** + * Processes events before they are dispatched and either censors their + * content or discards them if they contain potentially offensive + * content. + * + * @return void + */ + public function preDispatch() + { + $events = $this->events->getEvents(); + + foreach ($events as $event) { + switch ($event->getType()) { + case Phergie_Event_Request::TYPE_PRIVMSG: + case Phergie_Event_Request::TYPE_ACTION: + case Phergie_Event_Request::TYPE_NOTICE: + $text = $event->getArgument(1); + $clean = $this->cleanString($text); + if ($text != $clean) { + if ($this->config['censor.mode'] == 'censor') { + $event->setArgument(1, $clean); + } else { + $this->events->removeEvent($event); + } + } + break; + } + } + } +} diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Cron.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Cron.php new file mode 100644 index 0000000000..1c27f97842 --- /dev/null +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Cron.php @@ -0,0 +1,147 @@ + + * @copyright 2008-2010 Phergie Development Team (http://phergie.org) + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie_Plugin_Cron + */ + +/** + * Allows callbacks to be registered for asynchronous execution. + * + * @category Phergie + * @package Phergie_Plugin_Cron + * @author Phergie Development Team + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie_Plugin_Cron + */ +class Phergie_Plugin_Cron extends Phergie_Plugin_Abstract +{ + /** + * Array of all registered callbacks with delays and arguments + * + * @var array + */ + protected $callbacks; + + /** + * Returns a human-readable representation of a callback for debugging + * purposes. + * + * @param callback $callback Callback to analyze + * + * @return string|boolean String representation of the callback or FALSE + * if the specified value is not a valid callback + */ + protected function getCallbackString($callback) + { + if (!is_callable($callback)) { + return false; + } + + if (is_array($callback)) { + $class = is_string($callback[0]) ? + $callback[0] : get_class($callback[0]); + $method = $class . '::' . $callback[1]; + return $method; + } + + return $callback; + } + + /** + * Registers a callback for execution sometime after a given delay + * relative to now. + * + * @param callback $callback Callback to be registered + * @param int $delay Delay in seconds from now when the callback + * will be executed + * @param array $arguments Arguments to pass to the callback when + * it's executed + * @param bool $repeat TRUE to automatically re-register the + * callback for the same delay after it's executed, FALSE + * otherwise + * + * @return void + */ + public function registerCallback($callback, $delay, + array $arguments = array(), $repeat = false) + { + $callbackString = $this->getCallbackString($callback); + if ($callbackString === false) { + echo 'DEBUG(Cron): Invalid callback specified - ', + var_export($callback, true), PHP_EOL; + return; + } + + $registered = time(); + $scheduled = $registered + $delay; + + $this->callbacks[] = array( + 'callback' => $callback, + 'delay' => $delay, + 'arguments' => $arguments, + 'registered' => $registered, + 'scheduled' => $scheduled, + 'repeat' => $repeat, + ); + + echo 'DEBUG(Cron): Callback ', $callbackString, + ' scheduled for ', date('H:i:s', $scheduled), PHP_EOL; + } + + /** + * Handles callback execution. + * + * @return void + */ + public function onTick() + { + $now = time(); + foreach ($this->callbacks as $key => &$callback) { + $callbackString = $this->getCallbackString($callback); + + $scheduled = $callback['scheduled']; + if ($time < $scheduled) { + continue; + } + + if (empty($callback['arguments'])) { + call_user_func($callback['callback']); + } else { + call_user_func_array( + $callback['callback'], + $callback['arguments'] + ); + } + + echo 'DEBUG(Cron): Callback ', $callbackString, + ' scheduled for ', date('H:i:s', $scheduled), ',', + ' executed at ', date('H:i:s', $now), PHP_EOL; + + if ($callback['repeat']) { + $callback['scheduled'] = $time + $callback['delay']; + echo 'DEBUG(Cron): Callback ', $callbackString, + ' scheduled for ', date('H:i:s', $callback['scheduled']), + PHP_EOL; + } else { + echo 'DEBUG(Cron): Callback ', $callbackString, + ' removed from callback list', PHP_EOL; + unset($this->callbacks[$key]); + } + } + } +} diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Exception.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Exception.php index e58734bef9..fd07d9d5ea 100755 --- a/plugins/Irc/extlib/phergie/Phergie/Plugin/Exception.php +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Exception.php @@ -1,6 +1,6 @@ * @copyright 2008-2010 Phergie Development Team (http://phergie.org) @@ -22,7 +22,7 @@ /** * Exception related to plugin handling. * - * @category Phergie + * @category Phergie * @package Phergie * @author Phergie Development Team * @license http://phergie.org/license New BSD License @@ -31,82 +31,82 @@ class Phergie_Plugin_Exception extends Phergie_Exception { /** - * Error indicating that a path containing plugins was specified, but + * Error indicating that a path containing plugins was specified, but * did not reference a readable directory */ const ERR_DIRECTORY_NOT_READABLE = 1; /** - * Error indicating that an attempt was made to locate the class for a + * Error indicating that an attempt was made to locate the class for a * specified plugin, but the class could not be found */ const ERR_CLASS_NOT_FOUND = 2; /** - * Error indicating that an attempt was made to locate the class for a - * specified plugin, but that the found class did not extend the base + * Error indicating that an attempt was made to locate the class for a + * specified plugin, but that the found class did not extend the base * plugin class */ const ERR_INCORRECT_BASE_CLASS = 3; /** - * Error indicating that an attempt was made to locate the class for a + * Error indicating that an attempt was made to locate the class for a * specified plugin, but that the found class cannot be instantiated */ const ERR_CLASS_NOT_INSTANTIABLE = 4; /** - * Error indicating that an attempt was made to access a plugin that had + * Error indicating that an attempt was made to access a plugin that had * not been loaded and autoloading was not enabled to load it */ const ERR_PLUGIN_NOT_LOADED = 5; /** - * Error indicating that an attempt was made to access the configuration + * Error indicating that an attempt was made to access the configuration * handler before one had been set */ const ERR_NO_CONFIG_HANDLER = 6; /** - * Error indicating that an attempt was made to access the plugin + * Error indicating that an attempt was made to access the plugin * handler before one had been set */ const ERR_NO_PLUGIN_HANDLER = 7; /** - * Error indicating that an attempt was made to access the event + * Error indicating that an attempt was made to access the event * handler before one had been set */ const ERR_NO_EVENT_HANDLER = 8; /** - * Error indicating that an attempt was made to access the connection + * Error indicating that an attempt was made to access the connection * before one had been set */ const ERR_NO_CONNECTION = 9; /** - * Error indicating that an attempt was made to access the current + * Error indicating that an attempt was made to access the current * incoming event before one had been set */ const ERR_NO_EVENT = 10; /** - * Error indicating that a dependency of the plugin was unavailable at + * Error indicating that a dependency of the plugin was unavailable at * the time that an attempt was made to load it */ const ERR_REQUIREMENT_UNSATISFIED = 11; /** - * Error indicating that a call was made to a nonexistent plugin method - * and that its __call() implementation did not process that call as an - * attempt to trigger an event - this is intended to aid in debugging of + * Error indicating that a call was made to a nonexistent plugin method + * and that its __call() implementation did not process that call as an + * attempt to trigger an event - this is intended to aid in debugging of * such situations */ const ERR_INVALID_CALL = 12; /** - * Error indicating that a fatal runtime issue was encountered within a + * Error indicating that a fatal runtime issue was encountered within a * plugin */ const ERR_FATAL_ERROR = 13; diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Google.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Google.php index 413a936075..40c203a672 100644 --- a/plugins/Irc/extlib/phergie/Phergie/Plugin/Google.php +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Google.php @@ -222,7 +222,11 @@ class Phergie_Plugin_Google extends Phergie_Plugin_Abstract * @pluginCmd [location] Get the location from Google Maps to the location specified */ public function onCommandGmap($location) - { + { + $event = $this->getEvent(); + $source = $event->getSource(); + $nick = $event->getNick(); + $location = utf8_encode($location); $url = 'http://maps.google.com/maps/geo'; $params = array( @@ -232,20 +236,17 @@ class Phergie_Plugin_Google extends Phergie_Plugin_Abstract 'sensor' => 'false', 'oe' => 'utf8', 'mrt' => 'all', - 'key' => $this->_config['google.key'] + 'key' => $this->getConfig('google.key') ); $response = $this->http->get($url, $params); - $json = (array) $response->getContent(); - $event = $this->getEvent(); - $source = $event->getSource(); - $nick = $event->getNick(); + $json = $response->getContent(); if (!empty($json)) { - $qtd = count($json['Placemark']); + $qtd = count($json->Placemark); if ($qtd > 1) { if ($qtd <= 3) { - foreach ($json['Placemark'] as $places) { - $xy = $places['Point']['coordinates']; - $address = utf8_decode($places['address']); + foreach ($json->Placemark as $places) { + $xy = $places->Point->coordinates; + $address = utf8_decode($places->address); $url = 'http://maps.google.com/maps?sll=' . $xy[1] . ',' . $xy[0] . '&z=15'; $msg = $nick . ' -> ' . $address . ' - ' . $url; @@ -259,8 +260,8 @@ class Phergie_Plugin_Google extends Phergie_Plugin_Abstract $this->doPrivmsg($source, $msg); } } elseif ($qtd == 1) { - $xy = $json['Placemark'][0]['Point']['coordinates']; - $address = utf8_decode($json['Placemark'][0]['address']); + $xy = $json->Placemark[0]->Point->coordinates; + $address = utf8_decode($json->Placemark[0]->address); $url = 'http://maps.google.com/maps?sll=' . $xy[1] . ',' . $xy[0] . '&z=15'; $msg = $nick . ' -> ' . $address . ' - ' . $url; @@ -322,54 +323,44 @@ class Phergie_Plugin_Google extends Phergie_Plugin_Abstract /** * Performs a Google search to convert a value from one unit to another. * - * @param string $unit Source metric - * @param string $to Value to be converted - * @param string $unit2 Destination metric + * @param string $query Query of the form "[quantity] [unit] to [unit2]" * * @return void * - * @pluginCmd [unit] [to] [unit2] Convert a value from one metric to another + * @pluginCmd [quantity] [unit] to [unit2] Convert a value from one + * metric to another */ - public function onCommandConvert($unit, $to, $unit2) + public function onCommandConvert($query) { - $url = 'http://www.google.com/search?q=' - . urlencode($unit . ' ' . $to . ' ' . $unit2); + $url = 'http://www.google.com/search?q=' . urlencode($query); $response = $this->http->get($url); $contents = $response->getContent(); $event = $this->getEvent(); $source = $event->getSource(); $nick = $event->getNick(); - if (empty($contents)) { - $this->doPrivmsg( - $target, - $nick . ', sorry, I can\'t give you an answer right now.' - ); + if ($response->isError()) { + $code = $response->getCode(); + $message = $response->getMessage(); + $this->doNotice($nick, 'ERROR: ' . $code . ' ' . $message); return; } - $doc = new DomDocument; - $doc->loadHTML($contents); - foreach ($doc->getElementsByTagName('h2') as $element) { - if ($element->getAttribute('class') == 'r') { - $children = $element->childNodes; - $text = str_replace( - array(chr(195), chr(151), chr(160)), - array('x', '', ' '), - $children->item(0)->nodeValue - ); - if ($children->length >= 3) { - $text - .= '^' . $children->item(1)->nodeValue - . $children->item(2)->nodeValue; - } - } + $start = strpos($contents, '

'); + if ($start !== false) { + $end = strpos($contents, '', $start); + $text = strip_tags(substr($contents, $start, $end - $start)); + $text = str_replace( + array(chr(195), chr(151), chr(160)), + array('x', '', ' '), + $text + ); } if (isset($text)) { $this->doPrivmsg($source, $nick . ': ' . $text); } else { - $this->doPrivmsg($target, $nick . ', sorry I can\'t do that.'); + $this->doNotice($nick, 'Sorry I couldn\'t find an answer.'); } } } diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Handler.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Handler.php index ee03ae9581..b2ef089b44 100755 --- a/plugins/Irc/extlib/phergie/Phergie/Plugin/Handler.php +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Handler.php @@ -1,6 +1,6 @@ * @copyright 2008-2010 Phergie Development Team (http://phergie.org) @@ -22,13 +22,13 @@ /** * Handles on-demand loading of, iteration over, and access to plugins. * - * @category Phergie + * @category Phergie * @package Phergie * @author Phergie Development Team * @license http://phergie.org/license New BSD License * @link http://pear.phergie.org/package/Phergie */ -class Phergie_Plugin_Handler implements IteratorAggregate +class Phergie_Plugin_Handler implements IteratorAggregate, Countable { /** * Current list of plugin instances @@ -45,7 +45,7 @@ class Phergie_Plugin_Handler implements IteratorAggregate protected $paths; /** - * Flag indicating whether plugin classes should be instantiated on + * Flag indicating whether plugin classes should be instantiated on * demand if they are requested but no instance currently exists * * @var bool @@ -69,13 +69,13 @@ class Phergie_Plugin_Handler implements IteratorAggregate protected $events; /** - * Constructor to initialize class properties and add the path for core + * Constructor to initialize class properties and add the path for core * plugins. * * @param Phergie_Config $config configuration to pass to any - * instantiated plugin + * instantiated plugin * @param Phergie_Event_Handler $events event handler to pass to any - * instantiated plugin + * instantiated plugin * * @return void */ @@ -99,7 +99,7 @@ class Phergie_Plugin_Handler implements IteratorAggregate * the reverse order in which they are added. * * @param string $path Filesystem directory path - * @param string $prefix Optional class name prefix corresponding to the + * @param string $prefix Optional class name prefix corresponding to the * path * * @return Phergie_Plugin_Handler Provides a fluent interface @@ -123,12 +123,43 @@ class Phergie_Plugin_Handler implements IteratorAggregate } /** - * Adds a plugin instance to the handler. + * Returns metadata corresponding to a specified plugin. * - * @param string|Phergie_Plugin_Abstract $plugin Short name of the + * @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 + * @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 @@ -143,30 +174,21 @@ class Phergie_Plugin_Handler implements IteratorAggregate } // Attempt to locate and load the class - foreach (array_reverse($this->paths) as $path) { - $file = $path['path'] . $plugin . '.php'; - if (file_exists($file)) { - include_once $file; - $class = $path['prefix'] . $plugin; - if (class_exists($class)) { - break; - } - unset($class); - } - } - - // If the class can't be found, display an error - if (!isset($class)) { + $info = $this->getPluginInfo($plugin); + $file = $info['file']; + $class = $info['class']; + include_once $file; + if (!class_exists($class, false)) { throw new Phergie_Plugin_Exception( - 'Class file for plugin "' . $plugin . '" cannot be found', + 'File "' . $file . '" does not contain class "' . $class . '"', Phergie_Plugin_Exception::ERR_CLASS_NOT_FOUND ); } - // Check to ensure the class is a plugin class + // Check to ensure the class is a plugin class if (!is_subclass_of($class, 'Phergie_Plugin_Abstract')) { $msg - = 'Class for plugin "' . $plugin . + = 'Class for plugin "' . $plugin . '" does not extend Phergie_Plugin_Abstract'; throw new Phergie_Plugin_Exception( $msg, @@ -190,11 +212,7 @@ class Phergie_Plugin_Handler implements IteratorAggregate $instance = new $class; } - // Configure and add the instance - $instance->setPluginHandler($this); - $instance->setConfig($this->config); - $instance->setEventHandler($this->events); - $instance->onLoad(); + // Store the instance $this->plugins[$index] = $instance; $plugin = $instance; @@ -205,14 +223,20 @@ class Phergie_Plugin_Handler implements IteratorAggregate $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, + * @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 @@ -233,7 +257,7 @@ class Phergie_Plugin_Handler implements IteratorAggregate /** * Removes a plugin instance from the handler. * - * @param string|Phergie_Plugin_Abstract $plugin Short name of the + * @param string|Phergie_Plugin_Abstract $plugin Short name of the * plugin class or a plugin object * * @return Phergie_Plugin_Handler Provides a fluent interface @@ -251,7 +275,7 @@ class Phergie_Plugin_Handler implements IteratorAggregate } /** - * Returns the corresponding instance for a specified plugin, loading it + * 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 @@ -268,8 +292,8 @@ class Phergie_Plugin_Handler implements IteratorAggregate // If autoloading is disabled, display an error if (!$this->autoload) { - $msg - = 'Plugin "' . $name . '" has been requested, ' . + $msg + = 'Plugin "' . $name . '" has been requested, ' . 'is not loaded, and autoload is disabled'; throw new Phergie_Plugin_Exception( $msg, @@ -285,17 +309,23 @@ class Phergie_Plugin_Handler implements IteratorAggregate } /** - * Returns the corresponding instances for multiple specified plugins, - * loading them if they are not already loaded and autoloading is + * Returns the corresponding instances for multiple specified plugins, + * loading them if they are not already loaded and autoloading is * enabled. * - * @param array $names List of short names of the plugin classes + * @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 plugin class short names to - * corresponding plugin instances + * @return array Associative array mapping lowercased plugin class short + * names to corresponding plugin instances */ - public function getPlugins(array $names) + public function getPlugins(array $names = array()) { + if (empty($names)) { + return $this->plugins; + } + $plugins = array(); foreach ($names as $name) { $plugins[$name] = $this->getPlugin($name); @@ -304,7 +334,7 @@ class Phergie_Plugin_Handler implements IteratorAggregate } /** - * Returns whether or not at least one instance of a specified plugin + * Returns whether or not at least one instance of a specified plugin * class is loaded. * * @param string $name Short name of the plugin class @@ -317,10 +347,10 @@ class Phergie_Plugin_Handler implements IteratorAggregate } /** - * Sets a flag used to determine whether plugins should be loaded + * 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 + * @param bool $flag TRUE to have plugins autoload (default), FALSE * otherwise * * @return Phergie_Plugin_Handler Provides a fluent interface. @@ -333,7 +363,7 @@ class Phergie_Plugin_Handler implements IteratorAggregate } /** - * Returns the value of a flag used to determine whether plugins should + * 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 @@ -344,7 +374,7 @@ class Phergie_Plugin_Handler implements IteratorAggregate } /** - * Allows plugin instances to be accessed as properties of the handler. + * Allows plugin instances to be accessed as properties of the handler. * * @param string $name Short name of the plugin * @@ -352,7 +382,7 @@ class Phergie_Plugin_Handler implements IteratorAggregate */ public function __get($name) { - return $this->getPlugin($name); + return $this->getPlugin($name); } /** @@ -390,14 +420,14 @@ class Phergie_Plugin_Handler implements IteratorAggregate } /** - * Proxies method calls to all plugins containing the called method. An - * individual plugin may short-circuit this process by explicitly + * Proxies method calls to all plugins containing the called method. An + * individual plugin may short-circuit this process by explicitly * returning FALSE. * * @param string $name Name of the method called * @param array $args Arguments passed in the method call * - * @return bool FALSE if a plugin short-circuits processing by returning + * @return bool FALSE if a plugin short-circuits processing by returning * FALSE, TRUE otherwise */ public function __call($name, array $args) @@ -409,4 +439,14 @@ class Phergie_Plugin_Handler implements IteratorAggregate } return true; } + + /** + * Returns the number of plugins contained within the handler. + * + * @return int Plugin count + */ + public function count() + { + return count($this->plugins); + } } diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Help.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Help.php index 0de13308db..7cc8349571 100644 --- a/plugins/Irc/extlib/phergie/Phergie/Plugin/Help.php +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Help.php @@ -1,6 +1,6 @@ * @copyright 2008-2010 Phergie Development Team (http://phergie.org) @@ -22,7 +22,7 @@ /** * Provides access to descriptions of plugins and the commands they provide. * - * @category Phergie + * @category Phergie * @package Phergie_Plugin_Help * @author Phergie Development Team * @license http://phergie.org/license New BSD License @@ -60,11 +60,11 @@ class Phergie_Plugin_Help extends Phergie_Plugin_Abstract } /** - * Displays a list of plugins with help information available or + * Displays a list of plugins with help information available or * commands available for a specific plugin. * - * @param string $plugin Short name of the plugin for which commands - * should be returned, else a list of plugins with help + * @param string $plugin Short name of the plugin for which commands + * should be returned, else a list of plugins with help * information available is returned * * @return void @@ -94,13 +94,13 @@ class Phergie_Plugin_Help extends Phergie_Plugin_Abstract && isset($this->registry[strtolower($plugin)]['cmd']) ) { $msg - = 'The ' . - $plugin . + = 'The ' . + $plugin . ' plugin exposes the commands shown below.'; $this->doPrivMsg($nick, $msg); if ($this->getConfig('command.prefix')) { $msg - = 'Note that these commands must be prefixed with "' . + = 'Note that these commands must be prefixed with "' . $this->getConfig('command.prefix') . '" (without quotes) when issued in a public channel.'; $this->doPrivMsg($nick, $msg); @@ -122,10 +122,10 @@ class Phergie_Plugin_Help extends Phergie_Plugin_Abstract /** * Sets the description for the plugin instance - * + * * @param Phergie_Plugin_Abstract $plugin plugin instance * @param string $description plugin description - * + * * @return void */ public function setPluginDescription( @@ -138,7 +138,7 @@ class Phergie_Plugin_Help extends Phergie_Plugin_Abstract /** * Sets the description for the command on the plugin instance - * + * * @param Phergie_Plugin_Abstract $plugin plugin instance * @param string $command from onCommand method * @param string $description command description @@ -158,7 +158,7 @@ class Phergie_Plugin_Help extends Phergie_Plugin_Abstract * registers the plugin with the help plugin. this will parse the docblocks * for specific annotations that this plugin will respond with when * queried. - * + * * @param Phergie_Plugin_Abstract $plugin plugin instance * * @return void @@ -191,7 +191,8 @@ class Phergie_Plugin_Help extends Phergie_Plugin_Abstract } /** - * Taken from PHPUnit/Util/Test.php:436 + * Taken from PHPUnit/Util/Test.php:243 and modified to fix an issue + * with tag content spanning multiple lines. * * PHPUnit * @@ -235,13 +236,16 @@ class Phergie_Plugin_Help extends Phergie_Plugin_Abstract { $annotations = array(); - $regex = '/@(?P[A-Za-z_-]+)(?:[ \t]+(?P.*?))?[ \t]*\r?$/m'; + $regex = '/@(?P[A-Za-z_-]+)(?:[ \t]+(?P.*?))?(?:\*\/|\* @)/ms'; if (preg_match_all($regex, $docblock, $matches)) { $numMatches = count($matches[0]); for ($i = 0; $i < $numMatches; ++$i) { - $annotations[$matches['name'][$i]][] = $matches['value'][$i]; + $annotation = $matches['value'][$i]; + $annotation = preg_replace('/\s*\v+\s*\*\s*/', ' ', $annotation); + $annotation = rtrim($annotation); + $annotations[$matches['name'][$i]][] = $annotation; } } diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Http/Response.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Http/Response.php index def9d81c26..80d16c4b85 100644 --- a/plugins/Irc/extlib/phergie/Phergie/Plugin/Http/Response.php +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Http/Response.php @@ -37,6 +37,43 @@ class Phergie_Plugin_Http_Response */ protected $code; + /** + * HTTP response strings + * + * @var array + */ + protected $codeStrings = array( + 0 => 'No Response', + 100 => 'Continue', + 200 => 'OK', + 201 => 'Created', + 204 => 'No Content', + 206 => 'Partial Content', + 300 => 'Multiple Choices', + 301 => 'Moved Permanently', + 302 => 'Found', + 303 => 'See Other', + 304 => 'Not Modified', + 307 => 'Temporary Redirect', + 400 => 'Bad Request', + 401 => 'Unauthorized', + 403 => 'Forbidden', + 404 => 'Not Found', + 405 => 'Method Not Allowed', + 406 => 'Not Acceptable', + 408 => 'Request Timeout', + 410 => 'Gone', + 413 => 'Request Entity Too Large', + 414 => 'Request URI Too Long', + 415 => 'Unsupported Media Type', + 416 => 'Requested Range Not Satisfiable', + 417 => 'Expectation Failed', + 500 => 'Internal Server Error', + 501 => 'Method Not Implemented', + 503 => 'Service Unavailable', + 506 => 'Variant Also Negotiates' + ); + /** * Description of the HTTP response code or the error message if no HTTP * response was received @@ -89,6 +126,22 @@ class Phergie_Plugin_Http_Response return $this->code; } + /** + * Returns the HTTP response code text. + * + * @return string Response code text + */ + public function getCodeAsString() + { + $code = $this->code; + + if (!isset($this->codeStrings[$code])) { + return 'Unkown HTTP Status'; + } + + return $this->codeStrings[$code]; + } + /** * Returns whether the response indicates a client- or server-side error. * diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Php.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Php.php index 29d5118023..94abfb031c 100644 --- a/plugins/Irc/extlib/phergie/Phergie/Plugin/Php.php +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Php.php @@ -62,7 +62,6 @@ class Phergie_Plugin_Php extends Phergie_Plugin_Abstract */ public function onConnect() { - // Construct a new data source $this->source = new Phergie_Plugin_Php_Source_Local; } @@ -75,14 +74,13 @@ class Phergie_Plugin_Php extends Phergie_Plugin_Abstract */ public function onCommandPhp($functionName) { - // Search for the function + $nick = $this->event->getNick(); if ($function = $this->source->findFunction($functionName)) { - $msg = 'PHP ' . $function['name'] . ': ' . $function['description']; + $msg = $nick . ': ' . $function['description']; + $this->doPrivmsg($this->event->getSource(), $msg); } else { $msg = 'Search for function ' . $functionName . ' returned no results.'; + $this->doNotice($nick, $msg); } - - // Return the result to the source - $this->doPrivmsg($this->getEvent()->getSource(), $msg); } } diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Php/Source/Local.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Php/Source/Local.php index b72443c2e5..9292bea848 100644 --- a/plugins/Irc/extlib/phergie/Phergie/Plugin/Php/Source/Local.php +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Php/Source/Local.php @@ -65,7 +65,8 @@ class Phergie_Plugin_Php_Source_Local implements Phergie_Plugin_Php_Source // @todo Modify this to be rethrown as an appropriate // Phergie_Plugin_Exception and handled in Phergie_Plugin_Php } catch (PDOException $e) { - } + echo 'PDO failure: '.$e->getMessage(); + } } /** @@ -114,12 +115,16 @@ class Phergie_Plugin_Php_Source_Local implements Phergie_Plugin_Php_Source protected function buildDatabase($rebuild = false) { // Check to see if the functions table exists - $table = $this->database->exec("SELECT COUNT(*) FROM `sqlite_master` WHERE `name` = 'functions'"); - + $checkstmt = $this->database->query("SELECT COUNT(*) FROM `sqlite_master` WHERE `name` = 'functions'"); + $checkstmt->execute(); + $result = $checkstmt->fetch(PDO::FETCH_ASSOC); + unset( $checkstmt ); + $table = $result['COUNT(*)']; + unset( $result ); // If the table doesn't exist, create it if (!$table) { - $this->database->exec('CREATE TABLE `functions` (`name` VARCHAR(255), `description` TEXT)'); - $this->database->exec('CREATE UNIQUE INDEX `functions_name` ON `functions` (`name`)'); + $this->database->exec('CREATE TABLE `functions` (`name` VARCHAR(255), `description` TEXT)'); + $this->database->exec('CREATE UNIQUE INDEX `functions_name` ON `functions` (`name`)'); } // If we created a new table, fill it with data @@ -160,7 +165,7 @@ class Phergie_Plugin_Php_Source_Local implements Phergie_Plugin_Php_Source // ... it's the last part of the complete function description $completeLine = $firstPart . ' ' . $line; $firstPart = ''; - if (preg_match('{^([^\s]*)[\s]?([^)]*)\(([^\)]*)\)[\sU]+([\sa-zA-Z0-9\.\-_]*)$}', $completeLine, $matches)) { + if (preg_match('{^([^\s]*)[\s]?([^)]*)\(([^\)]*)\)[\sU]+([\sa-zA-Z0-9\.,\-_()]*)$}', $completeLine, $matches)) { $valid[] = $matches; } } diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Reload.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Reload.php new file mode 100755 index 0000000000..a2d680d7aa --- /dev/null +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Reload.php @@ -0,0 +1,96 @@ + + * @copyright 2008-2010 Phergie Development Team (http://phergie.org) + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie_Plugin_Reload + */ + +/** + * Facilitates reloading of individual plugins for development purposes. + * Note that, because existing class definitions cannot be removed from + * memory, increased memory usage is an expected result of using this plugin. + * + * @category Phergie + * @package Phergie_Plugin_Reload + * @author Phergie Development Team + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie_Plugin_Reload + * @uses Phergie_Plugin_Command pear.phergie.org + */ +class Phergie_Plugin_Reload extends Phergie_Plugin_Abstract +{ + /** + * Checks for dependencies. + * + * @return void + */ + public function onLoad() + { + $this->getPluginHandler()->getPlugin('Command'); + } + + /** + * Reloads a specified plugin. + * + * @param string $plugin Short name of the plugin to reload + * + * @return void + */ + public function onCommandReload($plugin) + { + $plugin = ucfirst($plugin); + + if (!$this->plugins->hasPlugin($plugin)) { + echo 'DEBUG(Reload): ' . ucfirst($plugin) . ' is not loaded yet, loading', PHP_EOL; + $this->plugins->getPlugin($plugin); + return; + } + + try { + $info = $this->plugins->getPluginInfo($plugin); + } catch (Phergie_Plugin_Exception $e) { + $source = $this->event->getSource(); + $nick = $this->event->getNick(); + $this->doNotice($source, $nick . ': ' . $e->getMessage()); + return; + } + + $class = $info['class']; + $contents = file_get_contents($info['file']); + $newClass = $class . '_' . sha1($contents); + + if (class_exists($newClass, false)) { + echo 'DEBUG(Reload): Class ', $class, ' has not changed since last reload', PHP_EOL; + return; + } + + $contents = preg_replace( + array('/<\?(?:php)?/', '/class\s+' . $class . '/i'), + array('', 'class ' . $newClass), + $contents + ); + eval($contents); + + $instance = new $newClass; + $instance->setName($plugin); + $this->plugins + ->removePlugin($plugin) + ->addPlugin($instance); + + echo 'DEBUG(Reload): Reloaded ', $class, ' to ', $newClass, PHP_EOL; + } +} diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Remind.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Remind.php index bfd5333674..cfb3c07e8c 100644 --- a/plugins/Irc/extlib/phergie/Phergie/Plugin/Remind.php +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Remind.php @@ -27,16 +27,16 @@ * @package Phergie_Plugin_Remind * @author Phergie Development Team * @license http://phergie.org/license New BSD License - * @link http://pear.phergie.org/package/Phergie_Plugin_Drink + * @link http://pear.phergie.org/package/Phergie_Plugin_Remind * @uses Phergie_Plugin_Command pear.phergie.org - * @uses Phergie_Plugin_Helper_Time pear.phergie.org + * @uses Phergie_Plugin_Time pear.phergie.org */ class Phergie_Plugin_Remind extends Phergie_Plugin_Abstract { /** * Number of reminders to show in public. */ - const PUBLIC_REMINDERS = 3; + protected $publicReminders = 3; /** * PDO resource for a SQLite database containing the reminders. @@ -64,11 +64,31 @@ class Phergie_Plugin_Remind extends Phergie_Plugin_Abstract */ public function onLoad() { - $this->getPluginHandler()->getPlugin('Command'); - $path = dirname(__FILE__) . '/reminder.db'; + $plugins = $this->getPluginHandler(); + $plugins->getPlugin('Command'); + $plugins->getPlugin('Time'); + } + + /** + * Creates the database if it does not already exist. + * + * @return void + */ + public function onConnect() + { + $dir = dirname(__FILE__) . '/' . $this->getName(); + $path = $dir . '/reminder.db'; + if (!file_exists($dir)) { + mkdir($dir); + } if (isset($this->config['remind.use_memory'])) { - $this->keepListInMemory = (bool)$this->config['remind.use_memory']; + $this->keepListInMemory = (bool) $this->config['remind.use_memory']; + } + + if (isset($this->config['remind.public_reminders'])) { + $this->publicReminders = (int) $this->config['remind.public_reminders']; + $this->publicReminders = max($this->publicReminders, 0); } try { @@ -222,19 +242,19 @@ class Phergie_Plugin_Remind extends Phergie_Plugin_Abstract // fetch and deliver messages $reminders = $this->fetchMessages($channel, $nick); - if (count($reminders) > self::PUBLIC_REMINDERS) { - $msgs = array_slice($reminders, 0, self::PUBLIC_REMINDERS); - $privmsgs = array_slice($reminders, self::PUBLIC_REMINDERS); + if (count($reminders) > $this->publicReminders) { + $msgs = array_slice($reminders, 0, $this->publicReminders); + $privmsgs = array_slice($reminders, $this->publicReminders); } else { $msgs = $reminders; $privmsgs = false; } foreach ($msgs as $msg) { - $ts = new Phergie_Plugin_Helper_Time($msg['time']); + $ts = $this->plugins->time->getCountdown($msg['time']); $formatted = sprintf( '%s: (from %s, %s ago) %s', - $nick, $msg['sender'], $ts->getCountdown(), $msg['message'] + $nick, $msg['sender'], $ts, $msg['message'] ); $this->doPrivmsg($channel, $formatted); $this->deleteMessage($msg['rowid'], $channel, $nick); @@ -242,10 +262,10 @@ class Phergie_Plugin_Remind extends Phergie_Plugin_Abstract if ($privmsgs) { foreach ($privmsgs as $msg) { - $ts = new Phergie_Plugin_Helper_Time($msg['time']); + $ts = $this->plugins->time->getCountdown($msg['time']); $formatted = sprintf( 'from %s, %s ago: %s', - $msg['sender'], $ts->getCountdown(), $msg['message'] + $msg['sender'], $ts, $msg['message'] ); $this->doPrivmsg($nick, $formatted); $this->deleteMessage($msg['rowid'], $channel, $nick); diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/SpellCheck.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/SpellCheck.php new file mode 100644 index 0000000000..33240829d8 --- /dev/null +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/SpellCheck.php @@ -0,0 +1,120 @@ + + * @copyright 2008-2010 Phergie Development Team (http://phergie.org) + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie_Plugin_TerryChay + */ + +/** + * Handles requests for checking spelling of specified words and returning + * either confirmation of correctly spelled words or potential correct + * spellings for misspelled words. + * + * @category Phergie + * @package Phergie_Plugin_SpellCheck + * @author Phergie Development Team + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie_Plugin_TerryChay + * @uses Phergie_Plugin_Command pear.phergie.org + * @uses extension pspell + */ +class Phergie_Plugin_SpellCheck extends Phergie_Plugin_Abstract +{ + + /** + * Spell check dictionary handler + * + * @var resource + */ + protected $pspell; + + /** + * Limit on the number of potential correct spellings returned + * + * @var int + */ + protected $limit; + + /** + * Check for dependencies. + * + * @return void + */ + public function onLoad() + { + if (!extension_loaded('pspell')) { + $this->fail('pspell php extension is required'); + } + + if (!$this->getConfig('spellcheck.lang')) { + $this->fail('Setting spellcheck.lang must be filled-in'); + } + + $this->plugins->getPlugin('Command'); + + set_error_handler(array($this, 'loadDictionaryError')); + $this->pspell = pspell_new($this->getConfig('spellcheck.lang')); + restore_error_handler(); + + $this->limit = $this->getConfig('spellcheck.limit', 5); + } + + /** + * Intercepts and handles requests for spell checks. + * + * @param string $word the string to perform checks against + * + * @return void + */ + public function onCommandSpell($word) + { + $source = $this->event->getSource(); + $target = $this->event->getNick(); + + $message = $target . ': The word "' . $word; + $message .= '" seems to be spelt correctly.'; + if (!pspell_check($this->pspell, $word)) { + $suggestions = pspell_suggest($this->pspell, $word); + + $message = $target; + $message .= ': I could not find any suggestions for "' . $word . '".'; + if (!empty($suggestions)) { + $suggestions = array_splice($suggestions, 0, $this->limit); + $message = $target . ': Suggestions for "'; + $message .= $word . '": ' . implode(', ', $suggestions) . '.'; + } + } + + $this->doPrivmsg($source, $message); + } + + /** + * Handle any errors from loading dictionary + * + * @param integer $errno Error code + * @param string $errstr Error message + * @param string $errfile File that errored + * @param integer $errline Line where the error happened + * + * @return void + */ + protected function loadDictionaryError($errno, $errstr, $errfile, $errline) + { + $this->fail($errstr); + } + +} diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Tld.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Tld.php new file mode 100644 index 0000000000..21ba1e6719 --- /dev/null +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Tld.php @@ -0,0 +1,261 @@ + + * @copyright 2008-2010 Phergie Development Team (http://phergie.org) + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie_Plugin_Url + */ + +/** + * Responds to a request for a TLD (formatted as .tld where tld is the TLD to + * be looked up) with its corresponding description. + * + * @category Phergie + * @package Phergie_Plugin_Tld + * @author Phergie Development Team + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie_Plugin_Tld + * @uses Phergie_Plugin_Http pear.phergie.org + * + * @pluginDesc Provides information for a top level domain. + */ +class Phergie_Plugin_Tld extends Phergie_Plugin_Abstract +{ + /** + * connection to the database + * @var PDO + */ + protected $db; + /** + * Some fixed TLD values, keys must be lowercase + * @var array + */ + protected static $fixedTlds; + + /** + * Prepared statement for selecting a single tld + * @var PDOStatement + */ + protected $select; + + /** + * Prepared statement for selecting all tlds + * @var PDOStatement + */ + protected $selectAll; + + /** + * Checks for dependencies, sets up database and hard coded values + * + * @return void + */ + public function onLoad() + { + $help = $this->getPluginHandler()->getPlugin('Help'); + $help->register($this); + + if (!is_array(self::$fixedTlds)) { + self::$fixedTlds = array( + 'phergie' => 'You can find Phergie at http://www.phergie.org', + 'spoon' => 'Don\'t you know? There is no spoon!', + 'poo' => 'Do you really think that\'s funny?', + 'root' => 'Diagnostic marker to indicate ' + . 'a root zone load was not truncated.' + ); + } + + try { + $dbFile = dirname(__FILE__) . '/Tld/tld.db'; + $dbManager = new Phergie_Db_Sqlite($dbFile); + $this->db = $dbManager->getDb(); + if (!$dbManager->hasTable('tld')) { + $query = 'CREATE TABLE tld (' + . 'tld VARCHAR(20), ' + . 'type VARCHAR(20), ' + . 'description VARCHAR(255))'; + + $this->db->exec($query); + + // prepare a statement to populate the table with + // tld information + $insert = $this->db->prepare( + 'INSERT INTO tld + (tld, type, description) + VALUES (:tld, :type, :description)' + ); + + // grab tld data from iana.org... + $contents = file_get_contents( + 'http://www.iana.org/domains/root/db/' + ); + + // ...and then parse it out + $regex = '{getEvent()->getNick()}: .{$tld} -> " + . ($description ? $description : 'Unknown TLD') + ); + } + + /** + * Retrieves the definition for a given TLD if it exists + * + * @param string $tld TLD to search for + * + * @return string Definition of the given TLD + */ + public function getTld($tld) + { + $tld = trim(strtolower($tld)); + if (isset(self::$fixedTlds[$tld])) { + return self::$fixedTlds[$tld]; + } else { + if ($this->select->execute(array('tld' => $tld))) { + $tlds = $this->select->fetch(); + if (is_array($tlds)) { + return '(' . $tlds['type'] . ') ' . $tlds['description']; + } + } + } + return false; + } + + /** + * Retrieves a list of all the TLDs and their definitions + * + * @return array Array of all the TLDs and their definitions + */ + public function getTlds() + { + if ($this->selectAll->execute()) { + $tlds = $this->selectAll->fetchAll(); + if (is_array($tlds)) { + $tldinfo = array(); + foreach ($tlds as $key => $tld) { + if (!empty($tld['tld'])) { + $tldinfo[$tld['tld']] = "({$tld['type']}) " + . $tld['description']; + } + } + unset($tlds); + return $tldinfo; + } + } + return false; + } +} + diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Url.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Url.php index 8fc1c3538e..2ea33befdf 100644 --- a/plugins/Irc/extlib/phergie/Phergie/Plugin/Url.php +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Url.php @@ -1,6 +1,6 @@ * @copyright 2008-2010 Phergie Development Team (http://phergie.org) @@ -23,30 +23,31 @@ * Monitors incoming messages for instances of URLs and responds with messages * containing relevant information about detected URLs. * - * Has an utility method accessible via + * Has an utility method accessible via * $this->getPlugin('Url')->getTitle('http://foo..'). * - * @category Phergie + * @category Phergie * @package Phergie_Plugin_Url * @author Phergie Development Team * @license http://phergie.org/license New BSD License * @link http://pear.phergie.org/package/Phergie_Plugin_Url + * @uses Phergie_Plugin_Http pear.phergie.org */ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract { /** * Links output format * - * Can use the variables %nick%, %title% and %link% in it to display + * Can use the variables %nick%, %title% and %link% in it to display * page titles and links * * @var string */ - protected $baseFormat = '%nick%: %message%'; + protected $baseFormat = '%message%'; protected $messageFormat = '[ %link% ] %title%'; /** - * Flag indicating whether a single response should be sent for a single + * Flag indicating whether a single response should be sent for a single * message containing multiple links * * @var bool @@ -61,7 +62,7 @@ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract protected $titleLength = 40; /** - * Url cache to prevent spamming, especially with multiple bots on the + * Url cache to prevent spamming, especially with multiple bots on the * same channel * * @var array @@ -88,16 +89,16 @@ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract protected $limit = 10; /** - * Flag that determines if the plugin will fall back to using an HTTP - * stream when a URL using SSL is detected and OpenSSL support isn't - * available in the PHP installation in use + * Flag that determines if the plugin will fall back to using an HTTP + * stream when a URL using SSL is detected and OpenSSL support isn't + * available in the PHP installation in use * * @var bool */ protected $sslFallback = true; /** - * Flag that is set to true by the custom error handler if an HTTP error + * Flag that is set to true by the custom error handler if an HTTP error * code has been received * * @var boolean @@ -106,7 +107,7 @@ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract protected $errorMessage = null; /** - * Flag indicating whether or not to display error messages as the title + * Flag indicating whether or not to display error messages as the title * if a link posted encounters an error * * @var boolean @@ -121,7 +122,7 @@ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract protected $detectSchemeless = false; /** - * List of error messages to return when the requested URL returns an + * List of error messages to return when the requested URL returns an * HTTP error * * @var array @@ -184,7 +185,7 @@ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract // make the shortener configurable $shortener = $this->getConfig('url.shortener', 'Trim'); $shortener = "Phergie_Plugin_Url_Shorten_{$shortener}"; - $this->shortener = new $shortener; + $this->shortener = new $shortener($this->plugins->getPlugin('Http')); if (!$this->shortener instanceof Phergie_Plugin_Url_Shorten_Abstract) { $this->fail("Declared shortener class {$shortener} is not of proper ancestry"); @@ -192,17 +193,9 @@ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract // Get a list of valid TLDs if (!is_array($this->tldList) || count($this->tldList) <= 6) { - /* Omitted for port - if ($this->pluginLoaded('Tld')) { - $this->tldList = Phergie_Plugin_Tld::getTlds(); - if (is_array($this->tldList)) { - $this->tldList = array_keys($this->tldList); - } - } - */ - if (!is_array($this->tldList) || count($this->tldList) <= 0) { - $this->tldList = array('ac', 'ad', 'ae', 'aero', 'af', 'ag', 'ai', 'al', 'am', 'an', 'ao', 'aq', 'ar', 'arpa', 'as', 'asia', 'at', 'au', 'aw', 'ax', 'az', 'ba', 'bb', 'bd', 'be', 'bf', 'bg', 'bh', 'bi', 'biz', 'bj', 'bl', 'bm', 'bn', 'bo', 'br', 'bs', 'bt', 'bv', 'bw', 'by', 'bz', 'ca', 'cat', 'cc', 'cd', 'cf', 'cg', 'ch', 'ci', 'ck', 'cl', 'cm', 'cn', 'co', 'com', 'coop', 'cr', 'cu', 'cv', 'cx', 'cy', 'cz', 'de', 'dj', 'dk', 'dm', 'do', 'dz', 'ec', 'edu', 'ee', 'eg', 'eh', 'er', 'es', 'et', 'eu', 'fi', 'fj', 'fk', 'fm', 'fo', 'fr', 'ga', 'gb', 'gd', 'ge', 'gf', 'gg', 'gh', 'gi', 'gl', 'gm', 'gn', 'gov', 'gp', 'gq', 'gr', 'gs', 'gt', 'gu', 'gw', 'gy', 'hk', 'hm', 'hn', 'hr', 'ht', 'hu', 'id', 'ie', 'il', 'im', 'in', 'info', 'int', 'io', 'iq', 'ir', 'is', 'it', 'je', 'jm', 'jo', 'jobs', 'jp', 'ke', 'kg', 'kh', 'ki', 'km', 'kn', 'kp', 'kr', 'kw', 'ky', 'kz', 'la', 'lb', 'lc', 'li', 'lk', 'lr', 'ls', 'lt', 'lu', 'lv', 'ly', 'ma', 'mc', 'md', 'me', 'mf', 'mg', 'mh', 'mil', 'mk', 'ml', 'mm', 'mn', 'mo', 'mobi', 'mp', 'mq', 'mr', 'ms', 'mt', 'mu', 'museum', 'mv', 'mw', 'mx', 'my', 'mz', 'na', 'name', 'nc', 'ne', 'net', 'nf', 'ng', 'ni', 'nl', 'no', 'np', 'nr', 'nu', 'nz', 'om', 'org', 'pa', 'pe', 'pf', 'pg', 'ph', 'pk', 'pl', 'pm', 'pn', 'pr', 'pro', 'ps', 'pt', 'pw', 'py', 'qa', 're', 'ro', 'rs', 'ru', 'rw', 'sa', 'sb', 'sc', 'sd', 'se', 'sg', 'sh', 'si', 'sj', 'sk', 'sl', 'sm', 'sn', 'so', 'sr', 'st', 'su', 'sv', 'sy', 'sz', 'tc', 'td', 'tel', 'tf', 'tg', 'th', 'tj', 'tk', 'tl', 'tm', 'tn', 'to', 'tp', 'tr', 'travel', 'tt', 'tv', 'tw', 'tz', 'ua', 'ug', 'uk', 'um', 'us', 'uy', 'uz', 'va', 'vc', 've', 'vg', 'vi', 'vn', 'vu', 'wf', 'ws', 'ye', 'yt', 'yu', 'za', 'zm', 'zw'); - } + $tldPath = dirname(__FILE__) . '/Url/url.tld.txt'; + $this->tldList = explode("\n", file_get_contents($tldPath)); + $this->debug('Loaded ' . count($this->tldList) . ' tlds'); rsort($this->tldList); } @@ -215,6 +208,7 @@ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract 'merge_links' => 'mergeLinks', 'title_length' => 'titleLength', 'show_errors' => 'showErrors', + 'expire' => 'expire', ) as $config => $local) { if (isset($this->config["url.{$config}"])) { $this->$local = $this->config["uri.{$config}"]; @@ -227,7 +221,7 @@ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract * found, responds with its title if it is an HTML document and the * shortened equivalent of its original URL if it meets length requirements. * - * @todo Update this to pull configuration settings from $this->config + * @todo Update this to pull configuration settings from $this->config * rather than caching them as class properties * @return void */ @@ -306,6 +300,10 @@ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract // Convert url $shortenedUrl = $this->shortener->shorten($url); + if (!$shortenedUrl) { + $this->debug('Invalid Url: Unable to shorten. (' . $url . ')'); + continue; + } // Prevent spamfest if ($this->checkUrlCache($url, $shortenedUrl)) { @@ -624,73 +622,29 @@ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract */ public function getTitle($url) { - $opts = array( - 'http' => array( - 'timeout' => 3.5, - 'method' => 'GET', - 'user_agent' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.12) Gecko/20080201 Firefox/2.0.0.12' - ) + $http = $this->plugins->getPlugin('Http'); + $options = array( + 'timeout' => 3.5, + 'user_agent' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.12) Gecko/20080201 Firefox/2.0.0.12' ); - $context = stream_context_create($opts); - if ($page = fopen($url, 'r', false, $context)) { - stream_set_timeout($page, 3.5); - $data = stream_get_meta_data($page); - foreach ($data['wrapper_data'] as $header) { - if (preg_match('/^Content-Type: ([^;]+)/', $header, $match) - && !preg_match('#^(text/x?html|application/xhtml+xml)$#', $match[1]) - ) { - $title = $match[1]; - } - } - if (!isset($title)) { - $content = ''; - $tstamp = time() + 5; + $response = $http->get($url, array(), $options); - while ($chunk = fread($page, 64)) { - $data = stream_get_meta_data($page); - if ($data['timed_out']) { - $this->debug('Url Timed Out: ' . $url); - $this->errorStatus = true; - break; - } - $content .= $chunk; - // Check for timeout - if (time() > $tstamp) break; - // Try to read title - if (preg_match('#]*>(.*)#is', $content, $m)) { - // Start another loop to grab some more data in order to be sure we have the complete title - $content = $m[1]; - $loop = 2; - while (($chunk = fread($page, 64)) && $loop-- && !strstr($content, '<')) { - $content .= $chunk; - // Check for timeout - if (time() > $tstamp) break; - } - preg_match('#^([^<]*)#is', $content, $m); - $title = preg_replace('#\s+#', ' ', $m[1]); - $title = trim($this->decode($title, $this->titleLength)); - break; - } - // Title won't appear beyond that point so stop parsing - if (preg_match('#|getHeaders('Content-Type'); + if (!preg_match('#^(text/x?html|application/xhtml+xml)(?:;.*)?$#', $header)) { + $title = $header; + } + + $content = $response->getContent(); + if (empty($title)) { + if (preg_match('#]*>(.*?)#is', $content, $match)) { + $title = html_entity_decode(trim($match[1])); } - fclose($page); - } else if (!$this->errorStatus) { - $this->debug('Couldn\t Open Url: ' . $url); } if (empty($title)) { - if ($this->errorStatus) { - if (!$this->showErrors || empty($this->errorMessage)) { - return; - } - $title = $this->errorMessage; - $this->errorStatus = false; - $this->errorMessage = null; + if ($response->isError()) { + $title = $response->getCodeAsString(); } else { $title = 'No Title'; } diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Url/Shorten/Abstract.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Url/Shorten/Abstract.php index bf5dff0d3b..607d1654c4 100644 --- a/plugins/Irc/extlib/phergie/Phergie/Plugin/Url/Shorten/Abstract.php +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Url/Shorten/Abstract.php @@ -27,15 +27,79 @@ * @author Phergie Development Team * @license http://phergie.org/license New BSD License * @link http://pear.phergie.org/package/Phergie_Plugin_Url + * @uses Phergie_Plugin_Http pear.phergie.org */ abstract class Phergie_Plugin_Url_Shorten_Abstract { + protected $http; + /** - * Takes a long url and returns a shortened link + * Constructor + * + * @param Phergie_Plugin_Http $http instance of the http plugin + */ + public function __construct(Phergie_Plugin_Http $http) + { + $this->http = $http; + } + + /** + * Returns an array of request parameters given a url to shorten. The + * following keys are valid request parameters: + * + * * 'uri': the URI for the request (required) + * * 'query': an array of key-value pairs sent in a GET request + * * 'post': an array of key-value pairs sent in a POST request + * * 'callback': to be called after the request is finished. Should accept + * a Phergie_Plugin_Http_Response object and return either the shortened + * url or false if an error has occured. + * + * If the 'post' key is present a POST request shall be made; otherwise + * a GET request will be made. The 'post' key can be an empty array and + * a post request will still be made. + * + * If no callback is provided the contents of the response will be returned. * * @param string $url the url to shorten * - * @return string string the shortened url + * @return array the request parameters */ - public abstract function shorten($url); + protected abstract function getRequestParams($url); + + /** + * Shortens a given url. + * + * @param string $url the url to shorten + * + * @return string the shortened url or false on a failure + */ + public function shorten($url) + { + $defaults = array('get' => array(), 'post' => array(), 'callback' => null); + $options = array('timeout' => 2); + $params = $this->getRequestParams($url) + $defaults; + + // Should some kind of notice be thrown? Maybe just if getRequestParams does not return an array? + if (!is_array($params) || empty($params['uri'])) { + return $url; + } + + if (!empty($params['post'])) { + $response = $this->http->post($params['uri'], $params['get'], $params['post'], $options); + } else { + $response = $this->http->get($params['uri'], $params['get'], $options); + } + + if (is_callable($params['callback'])) { + return call_user_func($params['callback'], $response); + } + + $code = $response->getCode(); + $content = trim($response->getContent); + if ($code < 200 || $code >= 300 || empty($content)) { + return false; + } + + return $response->getContent(); + } } diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Url/Shorten/Trim.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Url/Shorten/Trim.php index a90459b37e..af7e8a514f 100644 --- a/plugins/Irc/extlib/phergie/Phergie/Plugin/Url/Shorten/Trim.php +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Url/Shorten/Trim.php @@ -31,14 +31,34 @@ class Phergie_Plugin_Url_Shorten_Trim extends Phergie_Plugin_Url_Shorten_Abstract { /** - * Short a URL through the tr.im api + * Returns an array of request parameters given a url to shorten. The + * following keys are valid request parameters: * * @param string $url the url to shorten * - * @return string string the shortened url + * @return array the request parameters */ - public function shorten($url) + protected function getRequestParams($url) { - return file_get_contents('http://api.tr.im/v1/trim_simple?url=' . rawurlencode($url)); + return array( + 'uri' => 'http://api.tr.im/v1/trim_simple?url=' . rawurlencode($url), + 'callback' => array($this, 'onComplete') + ); + } + + /** + * Callback for when the URL has been shortened. Checks for error messages. + * + * @param Phergie_Plugin_Http_Response $response the response object + * + * @return string|bool the shortened url or false on failure + */ + protected function onComplete($response) + { + if (strpos($response->getContent(), 'Error: ') === 0) { + return false; + } + + return $response->getContent(); } } diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Url/url.tld.txt b/plugins/Irc/extlib/phergie/Phergie/Plugin/Url/url.tld.txt new file mode 100644 index 0000000000..cc46fdd620 --- /dev/null +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Url/url.tld.txt @@ -0,0 +1,273 @@ +ac +ad +ae +aero +af +ag +ai +al +am +an +ao +aq +ar +arpa +as +asia +at +au +aw +ax +az +ba +bb +bd +be +bf +bg +bh +bi +biz +bj +bl +bm +bn +bo +br +bs +bt +bv +bw +by +bz +ca +cat +cc +cd +cf +cg +ch +ci +ck +cl +cm +cn +co +com +coop +cr +cu +cv +cx +cy +cz +de +dj +dk +dm +do +dz +ec +edu +ee +eg +eh +er +es +et +eu +fi +fj +fk +fm +fo +fr +ga +gb +gd +ge +gf +gg +gh +gi +gl +gm +gn +gov +gp +gq +gr +gs +gt +gu +gw +gy +hk +hm +hn +hr +ht +hu +id +ie +il +im +in +info +int +io +iq +ir +is +it +je +jm +jo +jobs +jp +ke +kg +kh +ki +km +kn +kp +kr +kw +ky +kz +la +lb +lc +li +lk +lr +ls +lt +lu +lv +ly +ma +mc +md +me +mf +mg +mh +mil +mk +ml +mm +mn +mo +mobi +mp +mq +mr +ms +mt +mu +museum +mv +mw +mx +my +mz +na +name +nc +ne +net +nf +ng +ni +nl +no +np +nr +nu +nz +om +org +pa +pe +pf +pg +ph +pk +pl +pm +pn +pr +pro +ps +pt +pw +py +qa +re +ro +rs +ru +rw +sa +sb +sc +sd +se +sg +sh +si +sj +sk +sl +sm +sn +so +sr +st +su +sv +sy +sz +tc +td +tel +tf +tg +th +tj +tk +tl +tm +tn +to +tp +tr +travel +tt +tv +tw +tz +ua +ug +uk +um +us +uy +uz +va +vc +ve +vg +vi +vn +vu +wf +ws +ye +yt +yu +za +zm +zw diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Weather.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Weather.php new file mode 100755 index 0000000000..7d3cc1de03 --- /dev/null +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Weather.php @@ -0,0 +1,132 @@ + + * @copyright 2008-2010 Phergie Development Team (http://phergie.org) + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie_Plugin_Weather + */ + +/** + * Detects and responds to requests for current weather conditions in a + * particular location using data from a web service. Requires registering + * with weather.com to obtain authentication credentials, which must be + * stored in the configuration settings weather.partner_id and + * weather.license_key for the plugin to function. + * + * @category Phergie + * @package Phergie_Plugin_Weather + * @author Phergie Development Team + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie_Plugin_Weather + * @link http://www.weather.com/services/xmloap.html + * @uses Phergie_Plugin_Command pear.phergie.org + * @uses Phergie_Plugin_Http pear.phergie.org + * @uses extension SimpleXML + */ +class Phergie_Plugin_Weather extends Phergie_Plugin_Abstract +{ + /** + * Checks for dependencies. + * + * @return void + */ + public function onLoad() + { + $plugins = $this->getPluginHandler(); + $plugins->getPlugin('Command'); + $plugins->getPlugin('Http'); + + if (empty($this->config['weather.partner_id']) + || empty($this->config['weather.license_key'])) { + $this->fail('weather.partner_id and weather.license_key must be specified'); + } + } + + /** + * Returns a weather report for a specified location. + * + * @param string $location Zip code or city/state/country specification + * + * @return void + */ + public function onCommandWeather($location) + { + $response = $this->plugins->http->get( + 'http://xoap.weather.com/search/search', + array('where' => $location) + ); + + if ($response->isError()) { + $this->doNotice( + $this->event->getNick(), + 'ERROR: ' . $response->getCode() . ' ' . $response->getMessage() + ); + return; + } + + $nick = $this->event->getNick(); + + $xml = $response->getContent(); + if (count($xml->loc) == 0) { + $this->doNotice($nick, 'No results for that location.'); + return; + } + + $where = (string) $xml->loc[0]['id']; + $response = $this->plugins->http->get( + 'http://xoap.weather.com/weather/local/' . $where, + array( + 'cc' => '*', + 'link' => 'xoap', + 'prod' => 'xoap', + 'par' => $this->config['weather.partner_id'], + 'key' => $this->config['weather.license_key'], + ) + ); + + if ($response->isError()) { + $this->doNotice( + $this->event->getNick(), + 'ERROR: ' . $response->getCode() . ' ' . $response->getMessage() + ); + return; + } + + $xml = $response->getContent(); + $weather = 'Weather for ' . (string) $xml->loc->dnam . ' - '; + $weather .= 'Current temperature ' . + (string) $xml->cc->tmp . + (string) $xml->head->ut . ' / '; + if ((string) $xml->head->ut == 'F') { + $weather .= round(((((int) $xml->cc->tmp - 32) * 5) / 9)) . 'C'; + } else { + $weather .= round(((((int) $xml->cc->tmp * 9) / 5) + 32)) . 'F'; + } + $weather .= + ', Relative humidity ' . (string) $xml->cc->hmid . '%' . + ', Current conditions ' . (string) $xml->cc->t . + ', Last update ' . (string) $xml->cc->lsup . + ' [ http://weather.com/weather/today/' . + str_replace( + array('(', ')', ',', ' '), + array('', '', '', '+'), + (string) $xml->loc->dnam + ) . + ' ]'; + + $this->doPrivmsg($this->event->getSource(), $nick . ': ' . $weather); + } +} diff --git a/plugins/Irc/extlib/phergie/Settings.php.dist b/plugins/Irc/extlib/phergie/Settings.php.dist index b0450a4bb2..87b4a95c68 100755 --- a/plugins/Irc/extlib/phergie/Settings.php.dist +++ b/plugins/Irc/extlib/phergie/Settings.php.dist @@ -12,61 +12,62 @@ return array( 'realname' => 'Matthew Turland', 'nick' => 'Phergie2', // 'password' => 'password goes here if needed', - // 'transport' => 'ssl' // uncomment to connect using SSL + // 'transport' => 'ssl', // uncomment to connect using SSL + // 'encoding' => 'UTF8', // uncomment if using UTF8 ) ), - - 'processor' => 'async', + + 'processor' => 'async', 'processor.options' => array('usec' => 200000), // Time zone. See: http://www.php.net/manual/en/timezones.php 'timezone' => 'UTC', // Whitelist of plugins to load 'plugins' => array( - // To enable a plugin, simply add a string to this array containing - // the short name of the plugin as shown below. + // To enable a plugin, simply add a string to this array containing + // the short name of the plugin as shown below. // 'ShortPluginName', - // Below is an example of enabling the AutoJoin plugin, for which - // the corresponding PEAR package is Phergie_Plugin_AutoJoin. This - // plugin allows you to set a list of channels in this configuration - // file that the bot will automatically join when it connects to a - // server. If you'd like to enable this plugin, simply install it, - // uncomment the line below, and set a value for the setting - // autojoin.channels (examples for which are located further down in + // Below is an example of enabling the AutoJoin plugin, for which + // the corresponding PEAR package is Phergie_Plugin_AutoJoin. This + // plugin allows you to set a list of channels in this configuration + // file that the bot will automatically join when it connects to a + // server. If you'd like to enable this plugin, simply install it, + // uncomment the line below, and set a value for the setting + // autojoin.channels (examples for which are located further down in // this file). // 'AutoJoin', // A few other recommended plugins: - // Servers randomly send PING events to clients to ensure that - // they're still connected and will eventually terminate the - - // connection if a PONG response is not received. The Pong plugin + // Servers randomly send PING events to clients to ensure that + // they're still connected and will eventually terminate the + + // connection if a PONG response is not received. The Pong plugin // handles sending these responses. - // 'Pong', + // 'Pong', - // It's sometimes difficult to distinguish between a lack of - // activity on a server and the client not receiving data even - // though a connection remains open. The Ping plugin performs a self - // CTCP PING sporadically to ensure that its connection is still + // It's sometimes difficult to distinguish between a lack of + // activity on a server and the client not receiving data even + // though a connection remains open. The Ping plugin performs a self + // CTCP PING sporadically to ensure that its connection is still // functioning and, if not, terminates the bot. // 'Ping', - // Sometimes it's desirable to have the bot disconnect gracefully - // when issued a command to do so via a PRIVMSG event. The Quit - // plugin implements this using the Command plugin to intercept the + // Sometimes it's desirable to have the bot disconnect gracefully + // when issued a command to do so via a PRIVMSG event. The Quit + // plugin implements this using the Command plugin to intercept the // command. // 'Quit', ), - // If set to true, this allows any plugin dependencies for plugins - // listed in the 'plugins' option to be loaded even if they are not + // If set to true, this allows any plugin dependencies for plugins + // listed in the 'plugins' option to be loaded even if they are not // explicitly included in that list 'plugins.autoload' => true, @@ -83,13 +84,13 @@ return array( // Examples of setting values for Ping plugin settings - // This is the amount of time in seconds that the Ping plugin will wait - // to receive an event from the server before it initiates a self-ping + // This is the amount of time in seconds that the Ping plugin will wait + // to receive an event from the server before it initiates a self-ping // 'ping.event' => 300, // 5 minutes - // This is the amount of time in seconds that the Ping plugin will wait - // following a self-ping attempt before it assumes that a response will + // This is the amount of time in seconds that the Ping plugin will wait + // following a self-ping attempt before it assumes that a response will // never be received and terminates the connection // 'ping.ping' => 10, // 10 seconds diff --git a/plugins/Irc/extlib/phergie/Tests/Phergie/Plugin/HandlerTest.php b/plugins/Irc/extlib/phergie/Tests/Phergie/Plugin/HandlerTest.php index b359c11554..0d6ac454a8 100644 --- a/plugins/Irc/extlib/phergie/Tests/Phergie/Plugin/HandlerTest.php +++ b/plugins/Irc/extlib/phergie/Tests/Phergie/Plugin/HandlerTest.php @@ -37,6 +37,41 @@ class Phergie_Plugin_HandlerTest extends PHPUnit_Framework_TestCase */ protected $handler; + /** + * Mock Phergie_Config instance passed to the plugin handler constructor + * + * @var Phergie_Config + */ + protected $config; + + /** + * Mock Phergie_Event_Handler instance passed to the plugin handler + * constructor + * + * @var Phergie_Event_Handler + */ + protected $events; + + /** + * Returns a mock plugin instance. + * + * @param string $name Optional short name for the mock plugin, defaults + * to 'TestPlugin' + * @param array $methods Optional list of methods to override + * + * @return Phergie_Plugin_Abstract + */ + protected function getMockPlugin($name = 'TestPlugin', array $methods = array()) + { + $methods[] = 'getName'; + $plugin = $this->getMock('Phergie_Plugin_Abstract', $methods); + $plugin + ->expects($this->any()) + ->method('getName') + ->will($this->returnValue($name)); + return $plugin; + } + /** * Sets up a new handler instance before each test. * @@ -44,69 +79,191 @@ class Phergie_Plugin_HandlerTest extends PHPUnit_Framework_TestCase */ public function setUp() { + $this->config = $this->getMock('Phergie_Config'); + $this->events = $this->getMock('Phergie_Event_Handler'); $this->handler = new Phergie_Plugin_Handler( - new Phergie_Config(), - new Phergie_Event_Handler() + $this->config, + $this->events ); } /** - * Destroys the handler instance after each test + * Tests iterability of the plugin handler. * * @return void */ - public function tearDown() - { - unset($this->handler); - } - - /** - * Ensures that we can iterate over the handler - * - * @return void - */ - public function testImplementsIterator() + public function testImplementsIteratorAggregate() { $reflection = new ReflectionObject($this->handler); + $this->assertTrue( - $reflection->implementsInterface('IteratorAggregate') + $reflection->implementsInterface('IteratorAggregate'), + 'Handler does not implement IteratorAggregate' ); $this->assertType( - 'Iterator', $this->handler->getIterator(), - 'getIterator() must actually return an Iterator' + 'Iterator', + $this->handler->getIterator(), + 'getIterator() must return an iterator' ); } /** - * Ensures a newly instantiated handler does not have plugins associated - * with it + * Tests countability of the plugin handler. * - * @depends testImplementsIterator + * @return void + */ + public function testImplementsCountable() + { + $reflection = new ReflectionObject($this->handler); + + $this->assertTrue( + $reflection->implementsInterface('Countable'), + 'Handler does not implement Countable' + ); + + $this->assertType( + 'int', + count($this->handler), + 'count() must return an integer' + ); + } + + /** + * Tests the plugin handler exposing added plugins as instance + * properties of the handler via isset(). + * + * @return void + */ + public function testImplementsIsset() + { + $pluginName = 'TestPlugin'; + $this->assertFalse(isset($this->handler->{$pluginName})); + $plugin = $this->getMockPlugin($pluginName); + $this->handler->addPlugin($plugin); + $this->assertTrue(isset($this->handler->{$pluginName})); + } + + /** + * Tests the plugin handler exposing added plugins as instance + * properties of the handler. + * + * @depends testImplementsIsset + * @return void + */ + public function testImplementsGet() + { + $plugin = $this->getMockPlugin(); + $this->handler->addPlugin($plugin); + $name = $plugin->getName(); + $getPlugin = $this->handler->getPlugin($name); + $this->assertTrue(isset($this->handler->$name)); + $get = $this->handler->$name; + $this->assertSame($getPlugin, $get); + } + + /** + * Tests the plugin handler allowing for plugin removal via unset(). + * + * @depends testImplementsGet + * @return void + */ + public function testImplementsUnset() + { + $plugin = $this->getMockPlugin(); + $this->handler->addPlugin($plugin); + unset($this->handler->{$plugin->getName()}); + $this->assertFalse($this->handler->hasPlugin($plugin->getName())); + } + + /** + * Tests the plugin handler executing a callback on all contained + * plugins where one plugin short-circuits the process. + * + * @return void + */ + public function testImplementsCallWithShortCircuit() + { + $plugin1 = $this->getMockPlugin('TestPlugin1', array('callback')); + $plugin1 + ->expects($this->once()) + ->method('callback') + ->will($this->returnValue(false)); + $this->handler->addPlugin($plugin1); + + $plugin2 = $this->getMockPlugin('TestPlugin2', array('callback')); + $plugin2 + ->expects($this->exactly(0)) + ->method('callback'); + $this->handler->addPlugin($plugin2); + + $this->assertFalse($this->handler->callback()); + } + + /** + * Tests the plugin handler executing a callback on all contained + * plugins where no plugins short-circuit the process. + * + * @return void + */ + public function testImplementsCallWithoutShortCircuit() + { + foreach (range(1, 2) as $index) { + $plugin = $this->getMockPlugin('TestPlugin' . $index, array('callback')); + $plugin + ->expects($this->once()) + ->method('callback'); + $this->handler->addPlugin($plugin); + } + + $this->assertTrue($this->handler->callback()); + } + + /** + * Tests a newly instantiated handler not having plugins associated with + * it. + * + * @depends testImplementsCountable * @return void */ public function testEmptyHandlerHasNoPlugins() { - $count = 0; - foreach ($this->handler as $plugin) { - $count++; - } - - $this->assertEquals(0, $count); + $this->assertEquals(0, count($this->handler)); } - + /** - * Ensures a newly instantiated handler does not default to autoload + * Tests a newly instantiated handler not having autoloading enabled by + * default. * * @return void */ - public function testDefaultsToNotAutoload() + public function testGetAutoloadDefaultsToNotAutoload() { $this->assertFalse($this->handler->getAutoload()); } /** - * addPath provides a fluent interface + * Tests setAutoload(). + * + * @depends testGetAutoloadDefaultsToNotAutoload + * @return void + */ + public function testSetAutoload() + { + $this->assertSame( + $this->handler->setAutoload(true), + $this->handler, + 'setAutoload() does not provide a fluent interface' + ); + + $this->assertTrue( + $this->handler->getAutoload(), + 'setAutoload() had no effect on getAutoload()' + ); + } + + /** + * Tests addPath() providing a fluent interface. * * @return void */ @@ -117,7 +274,8 @@ class Phergie_Plugin_HandlerTest extends PHPUnit_Framework_TestCase } /** - * addPath throws an exception when it cannot read the directory + * Tests addPath() throwing an exception when it cannot read the + * directory. * * @return void */ @@ -133,122 +291,113 @@ class Phergie_Plugin_HandlerTest extends PHPUnit_Framework_TestCase return; } - $this->fail('An expected exception has not been raised.'); + $this->fail('An expected exception has not been raised'); } /** - * adds a path into the plugin handler and then ensures that files - * in that location can be found + * Tests adding a path to the plugin handler. * * @return void */ public function testAddPath() { - $plugin_name = 'Mock'; + $pluginName = 'Mock'; + try { - $this->handler->addPlugin($plugin_name); + $this->handler->addPlugin($pluginName); } catch(Phergie_Plugin_Exception $e) { $this->assertEquals( Phergie_Plugin_Exception::ERR_CLASS_NOT_FOUND, $e->getCode() ); - - $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_'); - - try { - $this->handler->addPlugin($plugin_name); - } catch(Phergie_Plugin_Exception $e) { - $this->fail( - 'After adding the directory, the plugin was still ' - . 'not found.' - ); - } - - return; } - $this->fail( - 'Before adding the directory, an expected exception ' - . 'was not raised' - ); - } + if (!isset($e)) { + $this->fail('Plugin loaded, path was already present'); + } - /** - * addPlugin returns the plugin instance that was added - * - * @return void - */ - public function testAddPluginByInstanceReturnsPluginInstance() { - $plugin = $this->getMock('Phergie_Plugin_Abstract'); - $plugin - ->expects($this->any()) - ->method('getName') - ->will($this->returnValue('TestPlugin')); - - $returned_plugin = $this->handler->addPlugin($plugin); - $this->assertSame( - $returned_plugin, - $plugin, - 'addPlugin returns the same instance that is passed to it' - ); - } - - /** - * Can add a plugin to the handler by shortname - * - * @return void - */ - public function testAddPluginToHandlerByShortname() - { - $plugin_name = 'Mock'; $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_'); - $returned_plugin = $this->handler->addPlugin($plugin_name); - $this->assertTrue($this->handler->hasPlugin($plugin_name)); + try { + $this->handler->addPlugin($pluginName); + } catch(Phergie_Plugin_Exception $e) { + $this->fail('Added path, plugin still not found'); + } + } + + /** + * Tests addPlugin() returning an added plugin instance. + * + * @return void + */ + public function testAddPluginByInstanceReturnsPluginInstance() + { + $plugin = $this->getMockPlugin(); + $returnedPlugin = $this->handler->addPlugin($plugin); + $this->assertSame( + $returnedPlugin, + $plugin, + 'addPlugin() does not return the instance passed to it' + ); + } + + /** + * Tests adding a plugin to the handler using the plugin's short name. + * + * @return void + */ + public function testAddPluginByShortName() + { + $pluginName = 'Mock'; + $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_'); + + $returnedPlugin = $this->handler->addPlugin($pluginName); + $this->assertTrue($this->handler->hasPlugin($pluginName)); + $this->assertType( 'Phergie_Plugin_Mock', - $this->handler->getPlugin($plugin_name) + $this->handler->getPlugin($pluginName) ); + $this->assertSame( - $this->handler->getPlugin($plugin_name), - $returned_plugin, - 'Handler contains plugin when added by shortname.' + $this->handler->getPlugin($pluginName), + $returnedPlugin, + 'Handler does not contain added plugin' ); } /** - * Can add a plugin to the handler by instance + * Tests adding a plugin instance to the handler. * * @return void */ - public function testAddPluginToHandlerByInstance() + public function testAddPluginByInstance() { - $plugin = $this->getMock('Phergie_Plugin_Abstract'); - $plugin - ->expects($this->any()) - ->method('getName') - ->will($this->returnValue('TestPlugin')); - - $returned_plugin = $this->handler->addPlugin($plugin); - + $plugin = $this->getMockPlugin(); + $returnedPlugin = $this->handler->addPlugin($plugin); $this->assertTrue($this->handler->hasPlugin('TestPlugin')); + $this->assertSame( - $plugin, $returned_plugin, - 'addPlugin returns the same plugin' + $plugin, + $returnedPlugin, + 'addPlugin() does not return added plugin instance' ); + $this->assertSame( - $plugin, $this->handler->getPlugin('TestPlugin'), - 'getPlugin returns the same plugin' + $plugin, + $this->handler->getPlugin('TestPlugin'), + 'getPlugin() does not return added plugin instance' ); } /** - * addPlugin throws an exception when it can't find the plugin + * Tests addPlugin() throwing an exception when the plugin class file + * can't be found. * * @return void */ - public function testAddPluginThrowsExceptionIfCannotFindPlugin() + public function testAddPluginThrowsExceptionWhenPluginFileNotFound() { try { $this->handler->addPlugin('TestPlugin'); @@ -260,12 +409,68 @@ class Phergie_Plugin_HandlerTest extends PHPUnit_Framework_TestCase return; } - $this->fail('An expected exception has not been raised.'); + $this->fail('An expected exception has not been raised'); } /** - * addPlugin throws an exception when trying to instantiate a - * class that doesn't extend from Phergie_Plugin_Abstract + * Recursively removes all files and subdirectories in a directory. + * + * @param string $path Directory path + * @return void + */ + private function removeDirectory($path) + { + if (file_exists($path)) { + $it = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($path), + RecursiveIteratorIterator::CHILD_FIRST + ); + foreach ($it as $entry) { + if ($it->isDot()) { + continue; + } + if ($entry->isDir()) { + rmdir($entry->getPathname()); + } else { + unlink($entry->getPathname()); + } + } + } + } + + /** + * Tests addPlugin() throwing an exception when the plugin class file is + * found, but does not contain the plugin class as expected. + * + * @return void + */ + public function testAddPluginThrowsExceptionWhenPluginClassNotFound() + { + $path = sys_get_temp_dir() . '/Phergie/Plugin'; + $this->removeDirectory(dirname($path)); + mkdir($path, 0777, true); + touch($path . '/TestPlugin.php'); + $this->handler->addPath($path, 'Phergie_Plugin_'); + + try { + $this->handler->addPlugin('TestPlugin'); + } catch(Phergie_Plugin_Exception $e) { } + + if (isset($e)) { + $this->assertEquals( + Phergie_Plugin_Exception::ERR_CLASS_NOT_FOUND, + $e->getCode() + ); + } else { + $this->fail('An expected exception has not been raised'); + } + + $this->removeDirectory(dirname($path)); + } + + /** + * Tests addPlugin() throwing an exception when trying to instantiate a + * class that doesn't extend Phergie_Plugin_Abstract. * * @return void */ @@ -281,11 +486,11 @@ class Phergie_Plugin_HandlerTest extends PHPUnit_Framework_TestCase return; } - $this->fail('An expected exception has not been raised.'); + $this->fail('An expected exception has not been raised'); } /** - * addPlugin throws an exception when trying to instantiate a + * Tests addPlugin() throwing an exception when trying to instantiate a * class that can't be instantiated. * * @return void @@ -303,143 +508,88 @@ class Phergie_Plugin_HandlerTest extends PHPUnit_Framework_TestCase return; } - $this->fail('An expected exception has not been raised.'); + $this->fail('An expected exception has not been raised'); } /** - * addPlugin with shortname and arguments passes args to constructor - * - * @return null - */ - public function testAddPluginShortnamePassesArgsToConstructor() - { - $plugin_name = 'Mock'; - $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_'); - - $arguments = array('a', 'b', 'c'); - - $plugin = $this->handler->addPlugin($plugin_name, $arguments); - $this->assertAttributeSame( - $arguments, - 'args', - $plugin, - 'Arguments passed in to addPlugin match the arguments ' - . 'the Mock plugin constructor received' - ); - } - - /** - * addPlugin passes Phergie_Config to instantiated plugin - * - * @return null - */ - public function testAddPluginPassesPhergieConfigToInstantiatedPlugin() - { - $my_config = new Phergie_Config(); - $my_config['my_option'] = 'my_value'; - - // create a new handler with this config - unset($this->handler); - $this->handler = new Phergie_Plugin_Handler( - $my_config, - new Phergie_Event_Handler() - ); - - $plugin_name = 'Mock'; - $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_'); - - $plugin = $this->handler->addPlugin($plugin_name); - - $this->assertSame( - $my_config, - $plugin->getConfig(), - 'addPlugin passes Phergie_Config to instantiated plugin' - ); - } - - /** - * addPlugin passes Phergie_Event_Handler to instantiated plugin - * - * @return null - */ - public function testAddPluginPassesPhergieEventHandlerToInstantiatedPlugin() - { - $plugin = $this->getMock('Phergie_Plugin_Abstract'); - $plugin - ->expects($this->any()) - ->method('getName') - ->will($this->returnValue('TestPlugin')); - - $my_event_handler = new Phergie_Event_Handler(); - $my_event_handler->addEvent($plugin, 'ping'); - - // create a new plugin handler with this event handler - unset($this->handler); - $this->handler = new Phergie_Plugin_Handler( - new Phergie_Config(), - $my_event_handler - ); - - $plugin_name = 'Mock'; - $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_'); - - $plugin = $this->handler->addPlugin($plugin_name); - - $this->assertSame( - $my_event_handler, - $plugin->getEventHandler(), - 'addPlugin passes Phergie_Event_Handler to instantiated plugin' - ); - } - - /** - * @todo addPlugin calls onLoad() to instantiated plugin - */ - - /** - * implements __isset + * Tests adding a plugin by its short name with arguments passed to the + * plugin constructor. * * @return void */ - public function testPluginHandlerImplementsIsset() + public function testAddPluginShortNamePassesArgsToConstructor() { - $plugin_name = 'TestPlugin'; + $pluginName = 'Mock'; + $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_'); - $this->assertFalse(isset($this->handler->{$plugin_name})); - - $plugin = $this->getMock('Phergie_Plugin_Abstract'); - $plugin - ->expects($this->any()) - ->method('getName') - ->will($this->returnValue($plugin_name)); - - $this->handler->addPlugin($plugin); - - $this->assertTrue(isset($this->handler->{$plugin_name})); + $arguments = array('a', 'b', 'c'); + $plugin = $this->handler->addPlugin($pluginName, $arguments); + $this->assertAttributeSame( + $arguments, + 'arguments', + $plugin, + 'Arguments do not match' + ); } /** - * addPlugin() returns the same plugin when requested twice + * Tests addPlugin() passing Phergie_Config to an instantiated plugin. + * + * @return void + */ + public function testAddPluginPassesConstructorArguments() + { + $pluginName = 'Mock'; + $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_'); + $plugin = $this->handler->addPlugin($pluginName); + + $this->assertSame( + $this->config, + $plugin->getConfig(), + 'Phergie_Config instances do not match' + ); + + $this->assertSame( + $this->events, + $plugin->getEventHandler(), + 'Phergie_Event_Handler instances do not match' + ); + } + + /** + * Tests addPlugin() calling onLoad() on an instantiated plugin. + * + * @return void + */ + public function testAddPluginCallsOnLoadOnInstantiatedPlugin() + { + $plugin = $this->getMockPlugin(null, array('onLoad')); + $plugin + ->expects($this->once()) + ->method('onLoad'); + $this->handler->addPlugin($plugin); + } + + /** + * Tests addPlugin() returning the same plugin when called twice. * * @return void */ public function testAddPluginReturnsSamePluginWhenAskedTwice() { - $plugin_name = 'Mock'; + $pluginName = 'Mock'; $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_'); - - $plugin1 = $this->handler->addPlugin($plugin_name); - $plugin2 = $this->handler->addPlugin($plugin_name); + $plugin1 = $this->handler->addPlugin($pluginName); + $plugin2 = $this->handler->addPlugin($pluginName); $this->assertSame($plugin1, $plugin2); } - /** - * Tests an exception is thrown when trying to get a plugin - * that is not already loaded and autoload is off + * Tests getPlugin() throwing an exception when trying to get an + * unloaded plugin with autoload disabled. * - * @depends testDefaultsToNotAutoload + * @depends testGetAutoloadDefaultsToNotAutoload * @return void */ public function testExceptionThrownWhenLoadingPluginWithoutAutoload() @@ -456,6 +606,134 @@ class Phergie_Plugin_HandlerTest extends PHPUnit_Framework_TestCase return; } - $this->fail('An expected exception has not been raised.'); + $this->fail('An expected exception has not been raised'); + } + + /** + * Tests addPlugins() with a plugin short name and no plugin constructor + * arguments. + * + * @depends testAddPluginByShortName + * @depends testAddPluginByInstance + * @return void + */ + public function testAddPluginsWithoutArguments() + { + $prefix = 'Phergie_Plugin_'; + $this->handler->addPath(dirname(__FILE__), $prefix); + + $plugin = 'Mock'; + $this->handler->addPlugins(array($plugin)); + $returnedPlugin = $this->handler->getPlugin($plugin); + $this->assertContains( + get_class($returnedPlugin), + $prefix . $plugin, + 'Short name plugin not of expected class' + ); + } + + /** + * Tests addPlugins() with a plugin short name and plugin constructor + * arguments. + * + * @depends testAddPluginByShortName + * @depends testAddPluginByInstance + * @return void + */ + public function testAddPluginsWithArguments() + { + $prefix = 'Phergie_Plugin_'; + $this->handler->addPath(dirname(__FILE__), $prefix); + + $arguments = array(1, 2, 3); + $plugin = array('Mock', $arguments); + $this->handler->addPlugins(array($plugin)); + $returnedPlugin = $this->handler->getPlugin('Mock'); + $this->assertEquals( + $arguments, + $returnedPlugin->getArguments(), + 'Constructor arguments for instance plugin do not match' + ); + } + + /** + * Tests removePlugin() with a plugin instance. + * + * @depends testAddPluginByInstance + * @return void + */ + public function testRemovePluginByInstance() + { + $plugin = $this->getMockPlugin(); + $this->handler->addPlugin($plugin); + $this->handler->removePlugin($plugin); + $this->assertFalse( + $this->handler->hasPlugin($plugin->getName()), + 'Plugin was not removed' + ); + } + + /** + * Tests removePlugin() with a plugin short name. + * + * @depends testAddPluginByShortName + * @return void + */ + public function testRemovePluginByShortName() + { + $plugin = 'Mock'; + $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_'); + + $this->handler->addPlugin($plugin); + $this->handler->removePlugin($plugin); + $this->assertFalse( + $this->handler->hasPlugin($plugin), + 'Plugin was not removed' + ); + } + + /** + * Tests getPlugin() when the plugin is not already loaded and + * autoloading is disabled. + * + * @depends testSetAutoload + * @return void + */ + public function testGetPluginWithAutoloadEnabled() + { + $this->handler->setAutoload(true); + $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_'); + $plugin = $this->handler->getPlugin('Mock'); + $this->assertType( + 'Phergie_Plugin_Mock', + $plugin, + 'Retrieved plugin not of expected class' + ); + } + + /** + * Tests getPlugins(). + * + * @depends testGetPluginWithAutoloadEnabled + * @return void + */ + public function testGetPlugins() + { + $plugin1 = $this->getMockPlugin('TestPlugin1'); + $this->handler->addPlugin($plugin1); + + $plugin2 = $this->getMockPlugin('TestPlugin2'); + $this->handler->addPlugin($plugin2); + + $expected = array( + 'testplugin1' => $plugin1, + 'testplugin2' => $plugin2, + ); + + $actual = $this->handler->getPlugins(); + $this->assertEquals($expected, $actual); + + $actual = $this->handler->getPlugins(array('testplugin1', 'testplugin2')); + $this->assertEquals($expected, $actual); } } diff --git a/plugins/Irc/extlib/phergie/Tests/Phergie/Plugin/Mock.php b/plugins/Irc/extlib/phergie/Tests/Phergie/Plugin/Mock.php index 714e3d9a44..44a5d11c7c 100755 --- a/plugins/Irc/extlib/phergie/Tests/Phergie/Plugin/Mock.php +++ b/plugins/Irc/extlib/phergie/Tests/Phergie/Plugin/Mock.php @@ -21,7 +21,7 @@ /** * Creates a plugin on the filesystem that can be used by - * Phergie_Plugin_Handler's addPath utility to be located and loaded. + * Phergie_Plugin_Handler::addPath() to be located and loaded. * * @category Phergie * @package Phergie_Tests @@ -32,18 +32,30 @@ class Phergie_Plugin_Mock extends Phergie_Plugin_Abstract { /** - * holds the arguments that were passed in to the constructor + * Arguments passed to the constructor + * * @var array */ - protected $args; + protected $arguments; /** - * processes a variable number of arguments into the args property + * Stores all arguments for later use. * - * @return null + * @return void */ public function __construct() { - $this->args = func_get_args(); + $this->arguments = func_get_args(); + } + + /** + * Returns all constructor arguments. + * + * @return array Enumerated array containing the arguments passed to the + * constructor in order + */ + public function getArguments() + { + return $this->arguments; } } diff --git a/plugins/Irc/extlib/phergie/Tests/Phergie/Plugin/SpellCheckTest.php b/plugins/Irc/extlib/phergie/Tests/Phergie/Plugin/SpellCheckTest.php new file mode 100644 index 0000000000..8ed9f0d36d --- /dev/null +++ b/plugins/Irc/extlib/phergie/Tests/Phergie/Plugin/SpellCheckTest.php @@ -0,0 +1,205 @@ + + * @copyright 2008-2010 Phergie Development Team (http://phergie.org) + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie + */ + +require_once dirname(__FILE__) . '/TestCase.php'; + +/** + * Unit test suite for Pherge_Plugin_SpellCheck. + * + * @category Phergie + * @package Phergie_Tests + * @author Phergie Development Team + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie + */ +class Phergie_Plugin_SpellCheckTest extends Phergie_Plugin_TestCase +{ + + /** + * Current SpellCheck plugin instance + * + * @var Phergie_Plugin_SpellCheck + */ + protected $spell; + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + * + * @return void + */ + protected function setUp() + { + $this->config = array('spellcheck.lang' => 'en'); + + $this->spell = new Phergie_Plugin_SpellCheck(); + $this->setPlugin(new Phergie_Plugin_Command()); + + $config = $this->plugin->getConfig(); + + $handler = new Phergie_Plugin_Handler($config, $this->handler); + $this->plugin->setPluginHandler($handler); + + $handler->addPlugin($this->plugin); + $handler->addPlugin($this->spell); + + $this->spell->setEventHandler($this->handler); + $this->spell->setConnection($this->connection); + } + + /** + * @event Phergie_Event_Request::privmsg + * @eventArg #zftalk + * @eventArg spell + */ + public function testSpell() + { + $this->spell->onLoad(); + + $this->copyEvent(); + $this->plugin->onPrivMsg(); + $this->assertDoesNotHaveEvent(Phergie_Event_Command::TYPE_PRIVMSG); + } + + /** + * @event Phergie_Event_Request::privmsg + * @eventArg #phergie + * @eventArg spell test + */ + public function testSpellTest() + { + $this->spell->onLoad(); + + $this->copyEvent(); + $this->plugin->onPrivMsg(); + + $events = $this->getResponseEvents(Phergie_Event_Command::TYPE_PRIVMSG); + + $this->assertEquals(1, count($events)); + foreach ($events as $event) { + $args = $event->getArguments(); + + $this->assertEquals('#phergie', $args[0]); + + $this->assertContains('CheckSpellUser:', $args[1]); + $this->assertContains('test', $args[1]); + $this->assertContains('correct', $args[1]); + } + } + + /** + * @event Phergie_Event_Request::privmsg + * @eventArg #phergie + * @eventArg spell testz + */ + public function testSpellTestz() + { + $this->spell->onLoad(); + + $this->copyEvent(); + $this->plugin->onPrivMsg(); + + $events = $this->getResponseEvents(Phergie_Event_Command::TYPE_PRIVMSG); + + $this->assertEquals(1, count($events)); + foreach ($events as $event) { + $args = $event->getArguments(); + + $this->assertEquals('#phergie', $args[0]); + + $this->assertContains('CheckSpellUser:', $args[1]); + $this->assertRegExp('/([a-z]+, ){4}/', $args[1]); + $this->assertContains('testz', $args[1]); + $this->assertContains('test,', $args[1]); + } + } + + /** + * @event Phergie_Event_Request::privmsg + * @eventArg #phergie + * @eventArg spell testz + */ + public function testSpellMoreSuggestions() + { + $config = $this->spell->getConfig(); + + $this->copyEvent(); + $config['spellcheck.limit'] = 6; + + $this->spell->onLoad(); + $this->plugin->onPrivMsg(); + + $events = $this->getResponseEvents(Phergie_Event_Command::TYPE_PRIVMSG); + + $this->assertEquals(1, count($events)); + foreach ($events as $event) { + $args = $event->getArguments(); + + $this->assertEquals('#phergie', $args[0]); + + $this->assertContains('CheckSpellUser:', $args[1]); + $this->assertRegExp('/([a-z]+, ){5}/', $args[1]); + $this->assertContains('testz', $args[1]); + $this->assertContains('test,', $args[1]); + } + } + + /** + * @event Phergie_Event_Request::privmsg + * @eventArg #phergie + * @eventArg spell qwertyuiopasdfghjklzxcvbnm + */ + public function testSpellNoSuggestions() + { + $this->spell->onLoad(); + + $this->copyEvent(); + $this->plugin->onPrivMsg(); + + $events = $this->getResponseEvents(Phergie_Event_Command::TYPE_PRIVMSG); + + $this->assertEquals(1, count($events)); + foreach ($events as $event) { + $args = $event->getArguments(); + + $this->assertEquals('#phergie', $args[0]); + + $this->assertContains('CheckSpellUser:', $args[1]); + $this->assertContains('find any suggestions', $args[1]); + } + } + + /** + * Copy event from command to spell plugin + * + * @return void + */ + protected function copyEvent() + { + $hostmask = Phergie_Hostmask::fromString('CheckSpellUser!test@testing.org'); + + $event = $this->plugin->getEvent(); + $event->setHostmask($hostmask); + + $this->spell->setEvent($event); + } + +} diff --git a/plugins/Irc/extlib/phergie/Tests/TestHelper.php b/plugins/Irc/extlib/phergie/Tests/TestHelper.php index 6593539bc1..e70af44562 100644 --- a/plugins/Irc/extlib/phergie/Tests/TestHelper.php +++ b/plugins/Irc/extlib/phergie/Tests/TestHelper.php @@ -12,7 +12,7 @@ * http://phergie.org/license * * @category Phergie - * @package Phergie_Tests + * @package Phergie_Tests * @author Phergie Development Team * @copyright 2008-2010 Phergie Development Team (http://phergie.org) * @license http://phergie.org/license New BSD License diff --git a/plugins/Irc/extlib/phergie/build.xml b/plugins/Irc/extlib/phergie/build.xml index 9b84014ed5..7510c75a15 100644 --- a/plugins/Irc/extlib/phergie/build.xml +++ b/plugins/Irc/extlib/phergie/build.xml @@ -45,6 +45,9 @@ + + +