summaryrefslogtreecommitdiff
path: root/plugins/Irc/extlib/phergie/Phergie/Plugin/Karma.php
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/Irc/extlib/phergie/Phergie/Plugin/Karma.php')
-rw-r--r--plugins/Irc/extlib/phergie/Phergie/Plugin/Karma.php451
1 files changed, 451 insertions, 0 deletions
diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Karma.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Karma.php
new file mode 100644
index 000000000..27b4a087d
--- /dev/null
+++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Karma.php
@@ -0,0 +1,451 @@
+<?php
+/**
+ * Phergie
+ *
+ * PHP version 5
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.
+ * It is also available through the world-wide-web at this URL:
+ * http://phergie.org/license
+ *
+ * @category Phergie
+ * @package Phergie_Plugin_Karma
+ * @author Phergie Development Team <team@phergie.org>
+ * @copyright 2008-2010 Phergie Development Team (http://phergie.org)
+ * @license http://phergie.org/license New BSD License
+ * @link http://pear.phergie.org/package/Phergie_Plugin_Karma
+ */
+
+/**
+ * Handles requests for incrementation or decrementation of a maintained list
+ * of counters for specified terms.
+ *
+ * @category Phergie
+ * @package Phergie_Plugin_Karma
+ * @author Phergie Development Team <team@phergie.org>
+ * @license http://phergie.org/license New BSD License
+ * @link http://pear.phergie.org/package/Phergie_Plugin_Karma
+ * @uses extension PDO
+ * @uses extension pdo_sqlite
+ * @uses Phergie_Plugin_Command pear.phergie.org
+ */
+class Phergie_Plugin_Karma extends Phergie_Plugin_Abstract
+{
+ /**
+ * SQLite object
+ *
+ * @var resource
+ */
+ protected $db = null;
+
+ /**
+ * Prepared statement to add a new karma record
+ *
+ * @var PDOStatement
+ */
+ protected $insertKarma;
+
+ /**
+ * Prepared statement to update an existing karma record
+ *
+ * @var PDOStatement
+ */
+ protected $updateKarma;
+
+ /**
+ * Retrieves an existing karma record
+ *
+ * @var PDOStatement
+ */
+ protected $fetchKarma;
+
+ /**
+ * Retrieves an existing fixed karma record
+ *
+ * @var PDOStatement
+ */
+ protected $fetchFixedKarma;
+
+ /**
+ * Retrieves a positive answer for a karma comparison
+ *
+ * @var PDOStatement
+ */
+ protected $fetchPositiveAnswer;
+
+ /**
+ * Retrieves a negative answer for a karma comparison
+ *
+ * @var PDOStatement
+ */
+ protected $fetchNegativeAnswer;
+
+ /**
+ * Check for dependencies and initializes a database connection and
+ * prepared statements.
+ *
+ * @return void
+ */
+ public function onLoad()
+ {
+ $plugins = $this->getPluginHandler();
+ $plugins->getPlugin('Command');
+ $this->getDb();
+ }
+
+ /**
+ * Initializes prepared statements used by the plugin.
+ *
+ * @return void
+ */
+ protected function initializePreparedStatements()
+ {
+ $this->fetchKarma = $this->db->prepare('
+ SELECT karma
+ FROM karmas
+ WHERE term = :term
+ LIMIT 1
+ ');
+
+ $this->insertKarma = $this->db->prepare('
+ INSERT INTO karmas (term, karma)
+ VALUES (:term, :karma)
+ ');
+
+ $this->updateKarma = $this->db->prepare('
+ UPDATE karmas
+ SET karma = :karma
+ WHERE term = :term
+ ');
+
+ $this->fetchFixedKarma = $this->db->prepare('
+ SELECT karma
+ FROM fixed_karmas
+ WHERE term = :term
+ LIMIT 1
+ ');
+
+ $this->fetchPositiveAnswer = $this->db->prepare('
+ SELECT answer
+ FROM positive_answers
+ ORDER BY RANDOM()
+ LIMIT 1
+ ');
+
+ $this->fetchNegativeAnswer = $this->db->prepare('
+ SELECT answer
+ FROM negative_answers
+ ORDER BY RANDOM()
+ LIMIT 1
+ ');
+ }
+
+ /**
+ * Returns a connection to the plugin database, initializing one if none
+ * is explicitly set.
+ *
+ * @return PDO Database connection
+ */
+ public function getDb()
+ {
+ if (empty($this->db)) {
+ $this->db = new PDO('sqlite:' . dirname(__FILE__) . '/Karma/karma.db');
+ $this->initializePreparedStatements();
+ }
+ return $this->db;
+ }
+
+ /**
+ * Sets the connection to the plugin database, mainly intended for unit
+ * testing.
+ *
+ * @param PDO $db Database connection
+ *
+ * @return Phergie_Plugin_Karma Provides a fluent interface
+ */
+ public function setDb(PDO $db)
+ {
+ $this->db = $db;
+ $this->initializePreparedStatements();
+ return $this;
+ }
+
+ /**
+ * Get the canonical form of a given term.
+ *
+ * In the canonical form all sequences of whitespace
+ * are replaced by a single space and all characters
+ * are lowercased.
+ *
+ * @param string $term Term for which a canonical form is required
+ *
+ * @return string Canonical term
+ */
+ protected function getCanonicalTerm($term)
+ {
+ $canonicalTerm = strtolower(preg_replace('|\s+|', ' ', trim($term, '()')));
+ switch ($canonicalTerm) {
+ case 'me':
+ $canonicalTerm = strtolower($this->event->getNick());
+ break;
+ case 'all':
+ case '*':
+ case 'everything':
+ $canonicalTerm = 'everything';
+ break;
+ }
+ return $canonicalTerm;
+ }
+
+ /**
+ * Intercepts a message and processes any contained recognized commands.
+ *
+ * @return void
+ */
+ public function onPrivmsg()
+ {
+ $message = $this->getEvent()->getText();
+
+ $termPattern = '\S+?|\([^<>]+?\)+';
+ $actionPattern = '(?P<action>\+\+|--)';
+
+ $modifyPattern = <<<REGEX
+ {^
+ (?J) # allow overwriting capture names
+ \s* # ignore leading whitespace
+
+ (?: # start with ++ or -- before the term
+ $actionPattern
+ (?P<term>$termPattern)
+ | # follow the term with ++ or --
+ (?P<term>$termPattern)
+ $actionPattern # allow no whitespace between the term and the action
+ )
+ $}ix
+REGEX;
+
+ $versusPattern = <<<REGEX
+ {^
+ (?P<term0>$termPattern)
+ \s+(?P<method><|>)\s+
+ (?P<term1>$termPattern)$#
+ $}ix
+REGEX;
+
+ $match = null;
+
+ if (preg_match($modifyPattern, $message, $match)) {
+ $action = $match['action'];
+ $term = $this->getCanonicalTerm($match['term']);
+ $this->modifyKarma($term, $action);
+ } elseif (preg_match($versusPattern, $message, $match)) {
+ $term0 = trim($match['term0']);
+ $term1 = trim($match['term1']);
+ $method = $match['method'];
+ $this->compareKarma($term0, $term1, $method);
+ }
+ }
+
+ /**
+ * Get the karma rating for a given term.
+ *
+ * @param string $term Term for which the karma rating needs to be
+ * retrieved
+ *
+ * @return void
+ */
+ public function onCommandKarma($term)
+ {
+ $source = $this->getEvent()->getSource();
+ $nick = $this->getEvent()->getNick();
+
+ $canonicalTerm = $this->getCanonicalTerm($term);
+
+ $fixedKarma = $this->fetchFixedKarma($canonicalTerm);
+ if ($fixedKarma) {
+ $message = $nick . ': ' . $term . ' ' . $fixedKarma;
+ $this->doPrivmsg($source, $message);
+ return;
+ }
+
+ $karma = $this->fetchKarma($canonicalTerm);
+
+ $message = $nick . ': ';
+
+ if ($term == 'me') {
+ $message .= 'You have';
+ } else {
+ $message .= $term . ' has';
+ }
+
+ $message .= ' ';
+
+ if ($karma) {
+ $message .= 'karma of ' . $karma;
+ } else {
+ $message .= 'neutral karma';
+ }
+
+ $message .= '.';
+
+ $this->doPrivmsg($source, $message);
+ }
+
+ /**
+ * Resets the karma for a term to 0.
+ *
+ * @param string $term Term for which to reset the karma rating
+ *
+ * @return void
+ */
+ public function onCommandReincarnate($term)
+ {
+ $data = array(
+ ':term' => $term,
+ ':karma' => 0
+ );
+ $this->updateKarma->execute($data);
+ }
+
+ /**
+ * Compares the karma between two terms. Optionally increases/decreases
+ * the karma of either term.
+ *
+ * @param string $term0 First term
+ * @param string $term1 Second term
+ * @param string $method Comparison method (< or >)
+ *
+ * @return void
+ */
+ protected function compareKarma($term0, $term1, $method)
+ {
+ $event = $this->getEvent();
+ $nick = $event->getNick();
+ $source = $event->getSource();
+
+ $canonicalTerm0 = $this->getCanonicalTerm($term0);
+ $canonicalTerm1 = $this->getCanonicalTerm($term1);
+
+ $fixedKarma0 = $this->fetchFixedKarma($canonicalTerm0);
+ $fixedKarma1 = $this->fetchFixedKarma($canonicalTerm1);
+
+ if ($fixedKarma0 || $fixedKarma1) {
+ return;
+ }
+
+ if ($canonicalTerm0 == 'everything') {
+ $change = $method == '<' ? '++' : '--';
+ $karma0 = 0;
+ $karma1 = $this->modifyKarma($canonicalTerm1, $change);
+ } elseif ($canonicalTerm1 == 'everything') {
+ $change = $method == '<' ? '--' : '++';
+ $karma0 = $this->modifyKarma($canonicalTerm0, $change);
+ $karma1 = 0;
+ } else {
+ $karma0 = $this->fetchKarma($canonicalTerm0);
+ $karma1 = $this->fetchKarma($canonicalTerm1);
+ }
+
+ // Combining the first and second branches here causes an odd
+ // single-line lapse in code coverage, but the lapse disappears if
+ // they're separated
+ if ($method == '<' && $karma0 < $karma1) {
+ $replies = $this->fetchPositiveAnswer;
+ } elseif ($method == '>' && $karma0 > $karma1) {
+ $replies = $this->fetchPositiveAnswer;
+ } else {
+ $replies = $this->fetchNegativeAnswer;
+ }
+ $replies->execute();
+ $reply = $replies->fetchColumn();
+
+ if (max($karma0, $karma1) == $karma1) {
+ list($canonicalTerm0, $canonicalTerm1) =
+ array($canonicalTerm1, $canonicalTerm0);
+ }
+
+ $message = str_replace(
+ array('%owner%','%owned%'),
+ array($canonicalTerm0, $canonicalTerm1),
+ $reply
+ );
+
+ $this->doPrivmsg($source, $message);
+ }
+
+ /**
+ * Modifes a term's karma.
+ *
+ * @param string $term Term to modify
+ * @param string $action Karma action (either ++ or --)
+ *
+ * @return int Modified karma rating
+ */
+ protected function modifyKarma($term, $action)
+ {
+ $karma = $this->fetchKarma($term);
+ if ($karma !== false) {
+ $statement = $this->updateKarma;
+ } else {
+ $statement = $this->insertKarma;
+ }
+
+ $karma += ($action == '++') ? 1 : -1;
+
+ $args = array(
+ ':term' => $term,
+ ':karma' => $karma
+ );
+ $statement->execute($args);
+
+ return $karma;
+ }
+
+ /**
+ * Returns the karma rating for a specified term for which the karma
+ * rating can be modified.
+ *
+ * @param string $term Term for which to fetch the corresponding karma
+ * rating
+ *
+ * @return integer|boolean Integer value denoting the term's karma or
+ * FALSE if there is the specified term has no associated karma
+ * rating
+ */
+ protected function fetchKarma($term)
+ {
+ $this->fetchKarma->execute(array(':term' => $term));
+ $result = $this->fetchKarma->fetch(PDO::FETCH_ASSOC);
+
+ if ($result === false) {
+ return false;
+ }
+
+ return (int) $result['karma'];
+ }
+
+ /**
+ * Returns a phrase describing the karma rating for a specified term for
+ * which the karma rating is fixed.
+ *
+ * @param string $term Term for which to fetch the corresponding karma
+ * rating
+ *
+ * @return string Phrase describing the karma rating, which may be append
+ * to the term to form a complete response
+ */
+ protected function fetchFixedKarma($term)
+ {
+ $this->fetchFixedKarma->execute(array(':term' => $term));
+ $result = $this->fetchFixedKarma->fetch(PDO::FETCH_ASSOC);
+
+ if ($result === false) {
+ return false;
+ }
+
+ return $result['karma'];
+ }
+}