Assembla home | Assembla project page
 

root/trunk/Phergie/Plugin/Toggle.php

Revision 273, 10.7 kB (checked in by Seldaek, 2 months ago)

* Plugins that can't load now return error messages to say why
fixes #35

Line 
1 <?php
2
3 /**
4  * Handles requests from administrators for the bot to disable or silence plugins
5  */
6 class Phergie_Plugin_Toggle extends Phergie_Plugin_Abstract_Command
7 {
8     /**
9      * Flag indicating whether or not the plugin is an admin plugin or not
10      *
11      * @var bool
12      */
13     public $needsAdmin = true;
14
15     /**
16      * Indicates that a local directory is required for this plugin
17      *
18      * @var bool
19      */
20     protected $needsDir = true;
21
22     /**
23      * PDO instance for the database
24      *
25      * @var PDO
26      */
27     protected $db;
28
29     /**
30      * Prepared PDO statements
31      *
32      * @var PDOStatement
33      */
34     protected $fetchState;
35     protected $inset;
36     protected $update;
37     protected $delete;
38
39     /**
40      * Creates the database if needed, connects to it, and sets up prepared
41      * statements for common operations.
42      *
43      * @return void
44      */
45     public function onInit()
46     {
47         // Check to see if PDO and Sqlite is available
48         if (!extension_loaded('PDO') || !extension_loaded('pdo_sqlite')) {
49             return;
50         }
51
52         try {
53             // Initialize the database connection
54             $this->db = new PDO('sqlite:' . $this->dir . 'toggle.db');
55             if (!$this->db) {
56                 return;
57             }
58
59             // Check to see if the table exists
60             $table = $this->db->query('SELECT COUNT(*) FROM sqlite_master WHERE name = ' . $this->db->quote('toggle'))->fetchColumn();
61
62             // Create database tables if necessary
63             if (!$table) {
64                 $this->debug('Creating the database schema');
65                 $this->db->exec('
66                     CREATE TABLE toggle (plugin VARCHAR(50), chan VARCHAR(50), state INTEGER(1));
67                 ');
68             }
69             unset($table);
70
71             // Initialize prepared statements for common operations
72             $this->fetchState = $this->db->prepare('
73                 SELECT state, ROWID id FROM toggle WHERE LOWER(plugin) = LOWER(:plugin) AND LOWER(chan) = LOWER(:chan) LIMIT 1
74             ');
75             $this->insert = $this->db->prepare('
76                 INSERT INTO toggle (plugin, chan, state) VALUES (:plugin, :chan, :state)
77             ');
78             $this->update = $this->db->prepare('
79                 UPDATE toggle SET state = :state WHERE LOWER(plugin) = LOWER(:plugin) AND LOWER(chan) = LOWER(:chan)
80             ');
81             $this->delete = $this->db->prepare('
82                 DELETE FROM toggle WHERE LOWER(plugin) = LOWER(:plugin) AND LOWER(chan) = LOWER(:chan)
83             ');
84         } catch (PDOException $e) { }
85     }
86
87     /**
88      * All the plugins are loaded and we're connected to the server so load up
89      * the toggle database cache and import the settings
90      *
91      * @return void
92      */
93     public function onConnect()
94     {
95         try {
96             if (!$this->db) {
97                 return;
98             }
99
100             $states = $this->db->query('SELECT plugin, chan, state FROM toggle')->fetchAll();
101
102             if (count($states) > 0) {
103                 foreach($states as $state) {
104                     $plugin = trim(strtolower($state['plugin']));
105                     $chan = trim(strtolower($state['chan']));
106                     $status = intval($state['state']);
107
108                     if ($plugin = $this->getPlugin($plugin)) {
109                         if (empty($chan)) {
110                             $plugin->enabled = $status;
111                         } else {
112                             $plugin->muted[$chan] = $status;
113                         }
114                     }
115                 }
116             }
117             unset($states, $chan, $status);
118         } catch (PDOException $e) { }
119     }
120
121     /**
122      * Disables a given plugin
123      */
124     public function onDoDisable($plugin)
125     {
126         // Check to see if the admin is a hostmask admin only and not an op
127         if ($this->fromAdmin(true)) {
128             $user = $this->event->getNick();
129             if (($instance = $this->getPlugin($plugin)) && $instance != $this) {
130                 if ($instance->enabled) {
131                     $instance->enabled = false;
132                     $this->updateToggleState($plugin, null, false);
133                     $this->doNotice($user, 'Disabled ' . $plugin . '.');
134                 } else {
135                     $this->doNotice($user, $plugin . ' is already disabled.');
136                 }
137             } else {
138                 $this->doNotice($user, 'Plugin ' . $plugin . ' is not loaded.');
139             }
140         } else {
141             $this->doNotice($user, 'You do not have permission to disable plugins.');
142         }
143     }
144
145     /**
146      * Enables a given plugin or loads it if its not already loaded
147      */
148     public function onDoEnable($plugin)
149     {
150         // Check to see if the admin is a hostmask admin only and not an op
151         if ($this->fromAdmin(true)) {
152             $user = $this->event->getNick();
153             // Plugin is loaded already
154             if ($instance = $this->getPlugin($plugin)) {
155                 // Already enabled
156                 if ($instance->enabled) {
157                     $this->doNotice($user, 'Plugin ' . $plugin . ' is already enabled.');
158                     // Not yet enabled, enable
159
160                 } else {
161                     $instance->enabled = true;
162                     $this->updateToggleState($plugin, null, true);
163                     $this->doNotice($user, 'Enabled ' . $plugin . '.');
164                 }
165             // Plugin was not loaded, try to see if we can load it
166             } else {
167                 // Build loaded plugin list to pass to the checkDependencies method
168                 $plugins = $this->getPluginList(true);
169                 // Plugin file was found, check if it can be loaded
170                 if (in_array($plugin, $plugins)) {
171                     $class = 'Phergie_Plugin_' . $plugin;
172                     $result = call_user_func(array($class, 'checkDependencies'), $this->client, $plugins);
173                     if ($result === true) {
174                         $instance = new $class($this->client);
175                         $this->client->addPlugin($instance);
176                         $this->debug('Loaded ' . $plugin);
177                         $this->doNotice($user, 'Plugin ' . $plugin . ' loaded.');
178                     } else {
179                         if ($plugin === false) {
180                             $this->doNotice($user, 'Plugin ' . $plugin . ' can not be loaded, missing dependencies.');
181                         } else {
182                             $this->doNotice($user, 'Plugin ' . $plugin . ' can not be loaded : '. implode(', ', (array) $plugin));
183                         }
184                     }
185                 // Plugin file not found
186                 } else {
187                     $this->doNotice($user, 'Plugin ' . $plugin . ' not found, could not enable.');
188                 }
189             }
190         } else {
191             $this->doNotice($user, 'You do not have permission to enable plugins.');
192         }
193     }
194
195     /**
196      * Mutes s given plugin for a given channel or the current channel if empty
197      */
198     public function onDoMute($plugin, $target = '')
199     {
200         $user = $this->event->getNick();
201         if (substr(strtolower($target), 0, 3) == 'for') {
202             $target = trim(substr($target, 3));
203         }
204         $target = strtolower(trim((!empty($target) && $this->fromAdmin(true)) ? $target : $this->event->getSource()));
205         if (!empty($target)) {
206             if ($instance = $this->getPlugin($plugin)) {
207                 $for = ($target == strtolower($this->event->getSource()) ? 'for this channel' : ($target == 'global' ? 'globally' : 'for ' . $target));
208                 if (empty($instance->muted[$target])) {
209                     $instance->muted[$target] = true;
210                     $this->updateToggleState($plugin, $target, true);
211                     $this->doNotice($user, 'Muted ' . $plugin . ' ' . $for . '.');
212                 } else {
213                     $this->doNotice($user, $plugin . ' is already muted ' . $for . '.');
214                 }
215             } else {
216                 $this->doNotice($user, 'Plugin ' . $plugin . ' not found, could not mute.');
217             }
218         }
219     }
220
221     /**
222      * Unmutes s given plugin for a given channel or the current channel if empty
223      */
224     public function onDoUnmute($plugin, $target = '')
225     {
226         $user = $this->event->getNick();
227         if (substr(strtolower($target), 0, 3) == 'for') {
228             $target = trim(substr($target, 3));
229         }
230         $target = strtolower(trim((!empty($target) && $this->fromAdmin(true)) ? $target : $this->event->getSource()));
231         if (!empty($target)) {
232             $for = ($target == strtolower($this->event->getSource()) ? 'for this channel' : ($target == 'global' ? 'globally' : 'for ' . $target));
233             if ($instance = $this->getPlugin($plugin)) {
234                 if (!empty($instance->muted[$target])) {
235                     $instance->muted[$target] = false;
236                     $this->updateToggleState($plugin, $target, false);
237                     $this->doNotice($user, 'Unmuted ' . $plugin . ' ' . $for . '.');
238                 } else {
239                     $this->doNotice($user, $plugin . ' is already unmuted ' . $for . '.');
240                 }
241             } else {
242                 $this->doNotice($user, 'Plugin ' . $plugin . ' not found, could not unmute.');
243             }
244         }
245     }
246
247     /**
248      * Handle whether to delete, insert or update a row based on the toggle status
249      */
250     public function updateToggleState($plugin, $chan, $state)
251     {
252         if (!$this->db) {
253             return;
254         }
255
256         $plugin = trim(strtolower($plugin));
257         $chan = trim(strtolower($chan));
258         $state = intval($state);
259
260         // Delete the row if enabling or unmuting a plugin
261         if ((empty($chan) && $state) || (!empty($chan) && !$state)) {
262             $this->delete->execute(array(':plugin' => $plugin, ':chan' => $chan));
263             $this->debug('Deleted toggle status for plugin "' . $plugin . '"' . (!empty($chan) ? ' and scope "' . $chan . '"' : ''));
264         } else {
265             $this->fetchState->execute(array(':plugin' => $plugin, ':chan' => $chan));
266             $res = $this->fetchState->fetch(PDO::FETCH_ASSOC);
267             // Insert a row if the given plugin and channel doesn't exist
268             if ($res) {
269                 $this->update->execute(array(':plugin' => $plugin, ':chan' => $chan, ':state' => $state));
270                 $this->debug('Updated toggle status for plugin "' . $plugin . '"' . (!empty($chan) ? ' and scope "' . $chan . '"' : ''));
271             // Update a row if the given plugin and channel exists
272             } else {
273                 $this->insert->execute(array(':plugin' => $plugin, ':chan' => $chan, ':state' => $state));
274                 $this->debug('Inserted toggle status for plugin "' . $plugin . '"' . (!empty($chan) ? ' and scope "' . $chan . '"' : ''));
275             }
276         }
277     }
278 }
279
Note: See TracBrowser for help on using the browser.