Verify the existence of the command file before loading in bot
[irbot.git] / sources / Plugins.php
blob7457bdd835a1950c35ac1a67b06d86732897761d
1 <?php
2 /**
3 * This file is part of IrBot, irc robot.
4 * Copyright (C) 2007-2008 Bellière Ludovic
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 * @category IrBot
20 * @package IrBot_Plugins
21 * @copyright Copyright (c) 2008 Bellière Ludovic
22 * @license http://www.gnu.org/licenses/gpl-3.0.html
25 class plugins extends RecursiveDirectoryIterator {
26 const EVENT_PRIVMSG = "privmsg";
27 const EVENT_NOTICE = "notice";
29 private $ircmain;
30 protected $text_format;
32 protected $_events = array(
33 self::EVENT_NOTICE => true,
34 self::EVENT_PRIVMSG => true
37 protected $commands = array();
39 public function __construct(IRCMain $ircmain) {
40 $this->ircmain = $ircmain;
41 parent::__construct(BASE_DIR.'plugins/');
43 while(self::valid()) {
44 if (self::isDot()) {
45 self::next();
47 if (self::isFile()) {
48 if (self::isReadable()) {
49 $pluginFileName = self::getFilename();
52 self::next();
57 public function addPlugin(Plugins_Abstract $plugin) {
60 public function add_command($plugin_name,Plugins_Command_Abstract $method_to_add,$do_on) {
61 if (isset($this->commands[$plugin][$method_to_add])) {
62 echo debug() ? 'plugins::add_command() -> ' . "$plugin -> $method_to_add\t\t\ALREADY LOADED\n" : '';
63 return true;
66 if (!in_array($do_on,$this->accepted_event)) {
67 echo debug() ? 'plugins::add_command() -> ' . "$plugin -> $method_to_add\t\t\tFAILED\n" : '';
68 return false;
71 $this->commands[$plugin][$method_to_add] = array(
72 'requier_args' => $method_to_add->requieredArgs,
73 'accepted_args' => $method_to_add->acceptedArgs,
74 'help' => $method_to_add->helpMessage(),
75 'type' => $method_to_add->commandVisibility,
76 'do_on' => $do_on,
79 echo debug() ? 'plugins::add_command() -> ' . "$plugin -> $method_to_add\t\t\LOADED\n" : '';
80 return true;
86 class plugins {
88 public $plugin_list = array();
89 private $ircmain;
91 public $commands;
92 public $command_list;
93 public $method_on = array();
94 public $accepted_event = array();
96 function __construct() {
97 $this->ircmain = bot::GetInstance();
98 $this->text_format = text_format::GetInstance();
99 $this->accepted_event = array('PRIVMSG','NOTICE');
102 public function Init() {
103 self::build_command_list();
104 self::build_buffer();
107 public function load_plugin($plugin_name) {
108 if ( !array_key_exists ( $plugin_name, $this->plugin_list ) ) {
109 if ( is_readable('./plugins/'.$plugin_name.'-plugin.inc.php') ) {
110 if (debug()) {
111 echo "plugins::load_plugin()[$plugin_name]\n";
113 require_once './plugins/'.$plugin_name.'-plugin.inc.php';
114 $this->plugin_list[$plugin_name] = new $plugin_name($this);
115 self::plugin_register_cmd($plugin_name, $this->plugin_list[$plugin_name]->commands_list());
116 } else {
117 throw new Exception("Class '$plugin_name' not found",0);
122 protected function plugin_register_cmd($plugin,$commands) {
123 foreach ($commands as $method => $info) {
124 if (!method_exists($this->plugin_list[$plugin],$method) || !is_callable(array($this->plugin_list[$plugin],$method))) {
125 trigger_error("method '$plugin:$method' in the commands list is not callable.\n",E_USER_WARNING);
126 } else {
127 self::add_command($plugin,$method,$info['accepted_args'],$info['help'],$info['type'],$info['requier_args'],$info['do_on']);
132 public function unload_plugin($plugin_name) {
133 if ($plugin_name == '_all') {
134 echo "Unload all plugins ...";
135 foreach($this->plugin_list as $pname => $tmp) {
136 unset ($this->plugin_list[$pname]);
138 echo "\t\t\tdone.\n";
140 if ( array_key_exists ( $plugin_name, $this->plugin_list ) ) {
141 unset( $this->plugin_list[$plugin_name] );
145 public function do_command ($msg_info,$plugin,$method) {
146 $all_args = array_slice(func_get_args(), 3);
148 if (isset($this->commands[$plugin])) {
149 foreach ($this->commands[$plugin] as $method_name => $methods) {
150 if ($method_name == $method) {
151 $accepted_args = $methods['accepted_args'];
153 if ( $accepted_args >= 1 )
154 $the_args = array_slice($all_args, 0, $accepted_args);
155 elseif ( $accepted_args == 0 )
156 $the_args = NULL;
157 else
158 $the_args = $all_args;
160 $call_args = count($all_args);
162 if (debug()) {
163 echo "plugins::do_command()[$plugin::$method_name] -> type : {$methods['type']}\n";
164 echo "plugins::do_command()[$plugin::$method_name] -> accepted_args : $accepted_args, requier_args : {$methods['requier_args']}, args : ".$call_args."\n\n\n";
167 $dest_error_prototype = "This command must be called in %s mode. Try /msg %s !$plugin $method_name";
168 $fail = false;
170 switch ($methods['type']) {
171 case 'private':
172 if ($msg_info['to'] != bot::$myBotName) {
173 $msg = sprintf($dest_error_prototype,'private',bot::$myBotName);
174 $fail = true;
176 break;
177 case 'public':
178 if ($msg_info['to'] != bot::$channel) {
179 $msg = sprintf($dest_error_prototype,'public', bot::$channel);
180 $fail = true;
182 break;
183 case 'mixed':
184 // no reason to match this...
185 break;
188 if ($fail == true) {
189 if ($methods['requier_args'] > 1) {
190 $i=0;
191 while ($i<$methods['requier_args']) {
192 $msg.= " arg,";
193 $i++;
195 $msg = substr($msg,0,-1);
196 $msg.= "\n".text_format::bold('You must enter '.$methods['requier_args'].' arguments.');
198 $this->ircmain->mprivmsg($msg_info['from'],text_format::paragraphe($msg));
199 return false;
202 if ($call_args < $methods['requier_args']) {
203 $msg = "There is an error with the number of arguments. You need to enter on minimum {$methods['requier_args']} arguments for this command.";
204 $this->ircmain->privmsg($msg_info['from'],$msg);
205 //call_user_func_array(array($this->plugin_list[$plugin],'error'),array($msg,$method_name));
206 return false;
207 } elseif ($call_args > $accepted_args) {
208 $msg = "There is an error with the number of arguments. You need to enter on maximum {$methods['requier_args']} arguments for this command.";
209 $this->ircmain->privmsg($msg_info['from'],$msg);
210 //call_user_func_array(array($this->plugin_list[$plugin],'error'),array($msg,$method_name));
211 //$this->ircmain->privmsg($msg_info['from'],"Error with num args");
212 return false;
215 // echo "Args :\n";
216 // print_r($the_args);
217 // echo "\n";
219 if ($plugin == 'core') {
220 call_user_func_array(array($this->ircmain,$method_name),$the_args);
221 } else {
222 $this->plugin_list[$plugin]->current_message($msg_info);
223 call_user_func_array(array($this->plugin_list[$plugin],$method_name),$the_args);
225 return true;
231 public function add_command($plugin,$method_to_add,$accepted_args=0,$help='',$type='public',$requier_args=0,$do_on) {
232 if (isset($this->commands[$plugin][$method_to_add])) {
233 echo debug() ? 'plugins_controller::add_command() -> ' . "$plugin -> $method_to_add\t\t\ALREADY LOADED\n" : '';
234 return true;
237 if (!in_array($do_on,$this->accepted_event)) {
238 echo debug() ? 'plugins_controller::add_command() -> ' . "$plugin -> $method_to_add\t\t\tFAILED\n" : '';
239 return false;
242 $this->commands[$plugin][$method_to_add] = array(
243 'requier_args' => $requier_args,
244 'accepted_args' => $accepted_args,
245 'help' => $help,
246 'type' => $type,
247 'do_on' => $do_on,
250 echo debug() ? 'plugins_controller::add_command() -> ' . "$plugin -> $method_to_add\t\t\LOADED\n" : '';
251 return true;
254 public function remove_command($plugin,$method_to_remove) {
255 if ($method_to_remove == '_all_method') {
256 unset($this->commands[$plugin]);
257 } elseif (isset($this->commands[$plugin][$method_to_remove])) {
258 unset($this->commands[$plugin][$method_to_remove]);
260 $this->commands[$plugin] = $new_method_list;
262 self::build_command_list();
263 return true;
266 public function list_command($plugin) {
267 if (isset($this->commands[$plugin])) {
268 foreach ($this->commands[$plugin] as $method_name => $method_info) {
269 $command_list[] = array_merge(array('method'=>$method_name),$method_info);
271 return $command_list;
273 return false;
276 public function command_exist($command) {
277 if (isset($this->command_list[$command])) {
278 return true;
279 } else {
280 return false;
284 public function set_event($data) {
285 switch ($data['type']) {
286 case 'PRIVMSG':
287 self::do_on_privmsg($data);
288 break;
289 case 'NOTICE':
290 self::do_on_notice($data);
291 break;
294 return;
296 if ($data['message'][0] == '!') {
297 $message = substr($data['message'],1);
298 $query = explode(' ',$message);
299 $query_count = count($query);
301 if (isset($this->plugins->commands[$query[0]])) {
302 if ($query_count > 1) {
303 if (isset($this->plugins->commands[$query[0]][$query[1]])) {
304 call_user_func_array(array($this->plugins,'do_command'),array_merge(array('msg_info'=>$msg_info),$query));
305 } else {
306 bot::GetInstance()->privmsg($data['from'],"This command do not exist. Try !{$query[0]} for the list of commands avaiable with this plugin.");
308 } else {
309 // no method : need a list of commands
310 $plugin = $message;
312 $commands = $this->plugins->list_command($plugin);
313 foreach ($commands as $command_info) {
314 if ($command_info['type'] == 'public') {
315 $get_plugin_method = '!'.$plugin;
316 } else {
317 $get_plugin_method = '/msg ' . bot::$myBotName . ' !' . $plugin;
320 $msg = array_merge(array(bot::GetInstance()->formater->bold('Command :')." $get_plugin_method {$command_info['method']}".(($command_info['accepted_args']>0)?' [some args...]':'')),text_format::paragraphe($command_info['help']));
321 bot::GetInstance()->mprivmsg($msg_info['from'],$msg);
324 } else {
325 //var_dump($this->plugins->commands);
330 private function do_on_privmsg() {
331 foreach ($this->method_on['privmsg'] as $method_name) {
335 private function do_on_notice() {
336 foreach ($this->method_on['notice'] as $method_name) {
341 private function build_command_list() {
342 foreach ($this->commands as $plugin => $method_data) {
343 foreach ($method_data as $method_name => $method_info) {
344 $this->command_list = array(
345 $method_name => array(
346 'plugin' => $plugin,
347 'method_info' => $method_info,
350 switch($method_info['do_on']) {
351 case 'PRIVMSG':
352 $this->method_on['privmsg'] = $method_name;
353 break;
354 case 'NOTICE':
355 $this->method_on['privmsg'] = $method_name;
356 break;
360 return true;