Assembla home | Assembla project page
 

root/trunk/Phergie/Plugin/Logging.php

Revision 278, 8.7 kB (checked in by Seldaek, 2 months ago)

* Fixed a bug in staticPluginLoaded() and updated all calls to it

Line 
1 <?php
2
3 /**
4  * Logs all channel events and stores them to the database and also provides
5  * an API for other plugins to retrieve this information.
6  */
7 class Phergie_Plugin_Logging extends Phergie_Plugin_Abstract_Command
8 {
9     /**
10      * Determines if the plugin is a passive plugin or not
11      *
12      * @var bool
13      */
14     public $passive = true;
15
16     /**
17      * Indicates that a local directory is required for this plugin
18      *
19      * @var bool
20      */
21     protected $needsDir = true;
22
23     /**
24      * Indicates a JOIN event in the type column of the logs table
25      *
26      * @const int
27      */
28     const JOIN = 1;
29
30     /**
31      * Indicates a PART event in the type column of the logs table
32      *
33      * @const int
34      */
35     const PART = 2;
36
37     /**
38      * Indicates a QUIT event in the type column of the logs table
39      *
40      * @const int
41      */
42     const QUIT = 3;
43
44     /**
45      * Indicates a PRIVMSG event in the type column of the logs table
46      *
47      * @const int
48      */
49     const PRIVMSG = 4;
50
51     /**
52      * Indicates a CTCP ACTION event in the type column of the logs table
53      *
54      * @const int
55      */
56     const ACTION = 5;
57
58     /**
59      * Indicates a NICK event in the type column of the logs table
60      *
61      * @const int
62      */
63     const NICK = 6;
64
65     /**
66      * Indicates a KICK event in the type column of the logs table
67      *
68      * @const int
69      */
70     const KICK = 7;
71
72     /**
73      * Indicates a MODE event in the type column of the logs table
74      *
75      * @const int
76      */
77     const MODE = 8;
78
79     /**
80      * Indicates a TOPIC event in the type column of the logs table
81      *
82      * @const int
83      */
84     const TOPIC = 9;
85
86     /**
87      * Indicates a QUERY event in the type column of the logs table
88      * This indicates that the message type is a PM
89      *
90      * @const int
91      */
92     const QUERY = 10;
93
94     /**
95      * PDO instance for the database
96      *
97      * @var PDO
98      */
99     protected $db = null;
100
101     /**
102      * Prepared statement for inserting new log entries
103      *
104      * @var PDOStatement
105      */
106     protected $insert;
107
108     /**
109      * Static PDO instance for the database
110      *
111      * @var PDO
112      */
113     protected static $staticDB;
114
115     /**
116      * Initializes the database.
117      *
118      * @return void
119      */
120     public function onInit()
121     {
122         try {
123             // Initialize the database connection
124             $this->db = new PDO('sqlite:' . $this->dir . 'logging.db');
125             if (!is_object($this->db)) {
126                 return;
127             }
128
129             // Check to see if the table exists
130             $table = $this->db->query('SELECT COUNT(*) FROM sqlite_master WHERE name = ' . $this->db->quote('logs'))->fetchColumn();
131
132             // Create database tables if necessary
133             if (!$table) {
134                 $this->debug('Creating the database schema');
135                 $result = $this->db->exec('
136                     CREATE TABLE logs (
137                         tstamp VARCHAR(19),
138                         type SHORTINT,
139                         chan VARCHAR(45),
140                         nick VARCHAR(25),
141                         message VARCHAR(255)
142                     );
143                     CREATE INDEX channicktype ON logs (tstamp, type, chan, nick);
144                     CREATE INDEX channick ON logs (tstamp, chan, nick);
145                 ');
146             }
147
148             $this->insert = $this->db->prepare('
149                 INSERT INTO logs (tstamp,type,chan,nick,message) VALUES (:tstamp,:type,:chan,:nick,:message)
150             ');
151         } catch (PDOException $e) { }
152         self::$staticDB = $this->db;
153     }
154
155     /**
156      * Returns whether or not the plugin's dependencies are met.
157      *
158      * @param Phergie_Driver_Abstract $client Client instance
159      * @param array $plugins List of short names for plugins that the
160      *                       bootstrap file intends to instantiate
161      * @see Phergie_Plugin_Abstract_Base::checkDependencies()
162      * @return bool TRUE if dependencies are met, FALSE otherwise
163      */
164     public static function checkDependencies(Phergie_Driver_Abstract $client, array $plugins)
165     {
166         $errors = array();
167
168         if (!self::staticPluginLoaded('ServerInfo', $client, $plugins)) {
169             $errors[] = 'ServerInfo plugin must be enabled';
170         }
171         if (!extension_loaded('PDO')) {
172             $errors[] = 'PDO php extension is required';
173         }
174         if (!extension_loaded('pdo_sqlite')) {
175             $errors[] = 'pdo_sqlite php extension is required';
176         }
177
178         return empty($errors) ? true : $errors;
179     }
180
181     /**
182      * Inserts a new entry in the log database.
183      *
184      * @param int $type Class constant representing the event type
185      * @param string $chan Name of the channel in which the event occurs
186      * @param string $nick Nick of the user from which the event originates
187      * @param string $message Message associated with the event if applicable
188      *                        (optional)
189      * @return void
190      */
191     protected function insertEvent($type, $chan, $nick, $message = null)
192     {
193         if (!is_object($this->db)) {
194             return;
195         }
196
197         $params = array(
198             ':tstamp' => date('Y-m-d H:i:s'),
199             ':type' => $type,
200             ':chan' => $chan,
201             ':nick' => $nick,
202             ':message' => trim($message)
203         );
204
205         $result = $this->insert->execute($params);
206     }
207
208     /**
209      * Logs incoming messages.
210      *
211      * @return void
212      */
213     public function onPrivmsg()
214     {
215         // Allow the Command plugin to process command calls
216         parent::onPrivmsg();
217
218         $this->insertEvent(
219             ($this->event->isInChannel() ? self::PRIVMSG : self::QUERY),
220             $this->event->getSource(),
221             $this->event->getNick(),
222             $this->event->getArgument(1)
223         );
224     }
225
226     /**
227      * Logics incoming actions.
228      *
229      * @return void
230      */
231     public function onAction()
232     {
233         if ($this->event->isInChannel()) {
234             $this->insertEvent(
235                 self::ACTION,
236                 $this->event->getSource(),
237                 $this->event->getNick(),
238                 $this->event->getArgument(1)
239             );
240         }
241     }
242
243     /**
244      * Tracks users joining.
245      *
246      * @return void
247      */
248     public function onJoin()
249     {
250         $this->insertEvent(
251             self::JOIN,
252             $this->event->getSource(),
253             $this->event->getNick(),
254             NULL
255         );
256     }
257
258     /**
259      * Tracks users parting.
260      *
261      * @return void
262      */
263     public function onPart()
264     {
265         $this->insertEvent(
266             self::PART,
267             $this->event->getSource(),
268             $this->event->getNick(),
269             $this->event->getArgument(1)
270         );
271     }
272
273     /**
274      * Tracks users being kicked.
275      *
276      * @return void
277      */
278     public function onKick()
279     {
280         $this->insertEvent(
281             self::KICK,
282             $this->event->getSource(),
283             $this->event->getNick(),
284             $this->event->getArgument(1)
285         );
286     }
287
288     /**
289      * Tracks users changing modes.
290      *
291      * @return void
292      */
293     public function onMode()
294     {
295         $this->insertEvent(
296             self::MODE,
297             $this->event->getSource(),
298             $this->event->getNick(),
299             implode(' ', array_slice($this->event->getArguments(), 1))
300         );
301     }
302
303     /**
304      * Tracks channel topic changes.
305      *
306      * @return void
307      */
308     public function onTopic()
309     {
310         $this->insertEvent(
311             self::TOPIC,
312             $this->event->getSource(),
313             $this->event->getNick(),
314             $this->event->getArgument(1)
315         );
316     }
317
318     /**
319      * Tracks users quitting.
320      *
321      * @return void
322      */
323     public function onQuit()
324     {
325         $nick = $this->event->getNick();
326
327         foreach(Phergie_Plugin_ServerInfo::getChannels($nick) as $chan) {
328             $this->insertEvent(
329                 self::QUIT,
330                 $chan,
331                 $this->event->getNick(),
332                 $this->event->getArgument(0)
333             );
334         }
335     }
336
337     /**
338      * Tracks users changing nicks.
339      *
340      * @return void
341      */
342     public function onNick()
343     {
344         $nick = $this->event->getNick();
345
346         foreach(Phergie_Plugin_ServerInfo::getChannels($nick) as $chan) {
347             $this->insertEvent(
348                 self::NICK,
349                 $chan,
350                 $this->event->getNick(),
351                 $this->event->getArgument(0)
352             );
353         }
354     }
355
356     public static function databaseExists()
357     {
358         return (is_object(self::$staticDB) ? true : false);
359     }
360
361     public static function prepare($query)
362     {
363         if (!is_object(self::$staticDB)) {
364             return false;
365         }
366
367         return self::$staticDB->prepare($query);
368     }
369 }
370
Note: See TracBrowser for help on using the browser.