1<?php 2/** 3 * PEAR_Command, command pattern class 4 * 5 * PHP versions 4 and 5 6 * 7 * LICENSE: This source file is subject to version 3.0 of the PHP license 8 * that is available through the world-wide-web at the following URI: 9 * http://www.php.net/license/3_0.txt. If you did not receive a copy of 10 * the PHP License and are unable to obtain it through the web, please 11 * send a note to license@php.net so we can mail you a copy immediately. 12 * 13 * @category pear 14 * @package PEAR 15 * @author Stig Bakken <ssb@php.net> 16 * @author Greg Beaver <cellog@php.net> 17 * @copyright 1997-2006 The PHP Group 18 * @license http://www.php.net/license/3_0.txt PHP License 3.0 19 * @version CVS: $Id: Command.php,v 1.36.2.1 2006/06/16 13:01:59 pajoye Exp $ 20 * @link http://pear.php.net/package/PEAR 21 * @since File available since Release 0.1 22 */ 23 24/** 25 * Needed for error handling 26 */ 27require_once 'PEAR.php'; 28require_once 'PEAR/Frontend.php'; 29require_once 'PEAR/XMLParser.php'; 30 31/** 32 * List of commands and what classes they are implemented in. 33 * @var array command => implementing class 34 */ 35$GLOBALS['_PEAR_Command_commandlist'] = array(); 36 37/** 38 * List of shortcuts to common commands. 39 * @var array shortcut => command 40 */ 41$GLOBALS['_PEAR_Command_shortcuts'] = array(); 42 43/** 44 * Array of command objects 45 * @var array class => object 46 */ 47$GLOBALS['_PEAR_Command_objects'] = array(); 48 49/** 50 * PEAR command class, a simple factory class for administrative 51 * commands. 52 * 53 * How to implement command classes: 54 * 55 * - The class must be called PEAR_Command_Nnn, installed in the 56 * "PEAR/Common" subdir, with a method called getCommands() that 57 * returns an array of the commands implemented by the class (see 58 * PEAR/Command/Install.php for an example). 59 * 60 * - The class must implement a run() function that is called with three 61 * params: 62 * 63 * (string) command name 64 * (array) assoc array with options, freely defined by each 65 * command, for example: 66 * array('force' => true) 67 * (array) list of the other parameters 68 * 69 * The run() function returns a PEAR_CommandResponse object. Use 70 * these methods to get information: 71 * 72 * int getStatus() Returns PEAR_COMMAND_(SUCCESS|FAILURE|PARTIAL) 73 * *_PARTIAL means that you need to issue at least 74 * one more command to complete the operation 75 * (used for example for validation steps). 76 * 77 * string getMessage() Returns a message for the user. Remember, 78 * no HTML or other interface-specific markup. 79 * 80 * If something unexpected happens, run() returns a PEAR error. 81 * 82 * - DON'T OUTPUT ANYTHING! Return text for output instead. 83 * 84 * - DON'T USE HTML! The text you return will be used from both Gtk, 85 * web and command-line interfaces, so for now, keep everything to 86 * plain text. 87 * 88 * - DON'T USE EXIT OR DIE! Always use pear errors. From static 89 * classes do PEAR::raiseError(), from other classes do 90 * $this->raiseError(). 91 * @category pear 92 * @package PEAR 93 * @author Stig Bakken <ssb@php.net> 94 * @author Greg Beaver <cellog@php.net> 95 * @copyright 1997-2006 The PHP Group 96 * @license http://www.php.net/license/3_0.txt PHP License 3.0 97 * @version Release: 1.4.11 98 * @link http://pear.php.net/package/PEAR 99 * @since Class available since Release 0.1 100 */ 101class PEAR_Command 102{ 103 // {{{ factory() 104 105 /** 106 * Get the right object for executing a command. 107 * 108 * @param string $command The name of the command 109 * @param object $config Instance of PEAR_Config object 110 * 111 * @return object the command object or a PEAR error 112 * 113 * @access public 114 * @static 115 */ 116 function &factory($command, &$config) 117 { 118 if (empty($GLOBALS['_PEAR_Command_commandlist'])) { 119 PEAR_Command::registerCommands(); 120 } 121 if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) { 122 $command = $GLOBALS['_PEAR_Command_shortcuts'][$command]; 123 } 124 if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) { 125 $a = PEAR::raiseError("unknown command `$command'"); 126 return $a; 127 } 128 $class = $GLOBALS['_PEAR_Command_commandlist'][$command]; 129 if (!class_exists($class)) { 130 require_once $GLOBALS['_PEAR_Command_objects'][$class]; 131 } 132 if (!class_exists($class)) { 133 $a = PEAR::raiseError("unknown command `$command'"); 134 return $a; 135 } 136 $ui =& PEAR_Command::getFrontendObject(); 137 $obj = &new $class($ui, $config); 138 return $obj; 139 } 140 141 // }}} 142 // {{{ & getObject() 143 function &getObject($command) 144 { 145 $class = $GLOBALS['_PEAR_Command_commandlist'][$command]; 146 if (!class_exists($class)) { 147 require_once $GLOBALS['_PEAR_Command_objects'][$class]; 148 } 149 if (!class_exists($class)) { 150 return PEAR::raiseError("unknown command `$command'"); 151 } 152 $ui =& PEAR_Command::getFrontendObject(); 153 $config = &PEAR_Config::singleton(); 154 $obj = &new $class($ui, $config); 155 return $obj; 156 } 157 158 // }}} 159 // {{{ & getFrontendObject() 160 161 /** 162 * Get instance of frontend object. 163 * 164 * @return object|PEAR_Error 165 * @static 166 */ 167 function &getFrontendObject() 168 { 169 $a = &PEAR_Frontend::singleton(); 170 return $a; 171 } 172 173 // }}} 174 // {{{ & setFrontendClass() 175 176 /** 177 * Load current frontend class. 178 * 179 * @param string $uiclass Name of class implementing the frontend 180 * 181 * @return object the frontend object, or a PEAR error 182 * @static 183 */ 184 function &setFrontendClass($uiclass) 185 { 186 $a = &PEAR_Frontend::setFrontendClass($uiclass); 187 return $a; 188 } 189 190 // }}} 191 // {{{ setFrontendType() 192 193 /** 194 * Set current frontend. 195 * 196 * @param string $uitype Name of the frontend type (for example "CLI") 197 * 198 * @return object the frontend object, or a PEAR error 199 * @static 200 */ 201 function setFrontendType($uitype) 202 { 203 $uiclass = 'PEAR_Frontend_' . $uitype; 204 return PEAR_Command::setFrontendClass($uiclass); 205 } 206 207 // }}} 208 // {{{ registerCommands() 209 210 /** 211 * Scan through the Command directory looking for classes 212 * and see what commands they implement. 213 * 214 * @param bool (optional) if FALSE (default), the new list of 215 * commands should replace the current one. If TRUE, 216 * new entries will be merged with old. 217 * 218 * @param string (optional) where (what directory) to look for 219 * classes, defaults to the Command subdirectory of 220 * the directory from where this file (__FILE__) is 221 * included. 222 * 223 * @return bool TRUE on success, a PEAR error on failure 224 * 225 * @access public 226 * @static 227 */ 228 function registerCommands($merge = false, $dir = null) 229 { 230 $parser = new PEAR_XMLParser; 231 if ($dir === null) { 232 $dir = dirname(__FILE__) . '/Command'; 233 } 234 235 if (!@is_dir($dir)) { 236 return PEAR::raiseError("registerCommands: opendir($dir) '$dir' does not exist or is not a directory"); 237 } 238 239 $dp = @opendir($dir); 240 if (empty($dp)) { 241 return PEAR::raiseError("registerCommands: opendir($dir) failed"); 242 } 243 if (!$merge) { 244 $GLOBALS['_PEAR_Command_commandlist'] = array(); 245 } 246 while ($entry = readdir($dp)) { 247 if ($entry{0} == '.' || substr($entry, -4) != '.xml') { 248 continue; 249 } 250 $class = "PEAR_Command_".substr($entry, 0, -4); 251 $file = "$dir/$entry"; 252 $parser->parse(file_get_contents($file)); 253 $implements = $parser->getData(); 254 // List of commands 255 if (empty($GLOBALS['_PEAR_Command_objects'][$class])) { 256 $GLOBALS['_PEAR_Command_objects'][$class] = "$dir/" . substr($entry, 0, -4) . 257 '.php'; 258 } 259 foreach ($implements as $command => $desc) { 260 if ($command == 'attribs') { 261 continue; 262 } 263 if (isset($GLOBALS['_PEAR_Command_commandlist'][$command])) { 264 return PEAR::raiseError('Command "' . $command . '" already registered in ' . 265 'class "' . $GLOBALS['_PEAR_Command_commandlist'][$command] . '"'); 266 } 267 $GLOBALS['_PEAR_Command_commandlist'][$command] = $class; 268 $GLOBALS['_PEAR_Command_commanddesc'][$command] = $desc['summary']; 269 if (isset($desc['shortcut'])) { 270 $shortcut = $desc['shortcut']; 271 if (isset($GLOBALS['_PEAR_Command_shortcuts'][$shortcut])) { 272 return PEAR::raiseError('Command shortcut "' . $shortcut . '" already ' . 273 'registered to command "' . $command . '" in class "' . 274 $GLOBALS['_PEAR_Command_commandlist'][$command] . '"'); 275 } 276 $GLOBALS['_PEAR_Command_shortcuts'][$shortcut] = $command; 277 } 278 if (isset($desc['options']) && $desc['options']) { 279 foreach ($desc['options'] as $oname => $option) { 280 if (isset($option['shortopt']) && strlen($option['shortopt']) > 1) { 281 return PEAR::raiseError('Option "' . $oname . '" short option "' . 282 $option['shortopt'] . '" must be ' . 283 'only 1 character in Command "' . $command . '" in class "' . 284 $class . '"'); 285 } 286 } 287 } 288 } 289 } 290 ksort($GLOBALS['_PEAR_Command_shortcuts']); 291 ksort($GLOBALS['_PEAR_Command_commandlist']); 292 @closedir($dp); 293 return true; 294 } 295 296 // }}} 297 // {{{ getCommands() 298 299 /** 300 * Get the list of currently supported commands, and what 301 * classes implement them. 302 * 303 * @return array command => implementing class 304 * 305 * @access public 306 * @static 307 */ 308 function getCommands() 309 { 310 if (empty($GLOBALS['_PEAR_Command_commandlist'])) { 311 PEAR_Command::registerCommands(); 312 } 313 return $GLOBALS['_PEAR_Command_commandlist']; 314 } 315 316 // }}} 317 // {{{ getShortcuts() 318 319 /** 320 * Get the list of command shortcuts. 321 * 322 * @return array shortcut => command 323 * 324 * @access public 325 * @static 326 */ 327 function getShortcuts() 328 { 329 if (empty($GLOBALS['_PEAR_Command_shortcuts'])) { 330 PEAR_Command::registerCommands(); 331 } 332 return $GLOBALS['_PEAR_Command_shortcuts']; 333 } 334 335 // }}} 336 // {{{ getGetoptArgs() 337 338 /** 339 * Compiles arguments for getopt. 340 * 341 * @param string $command command to get optstring for 342 * @param string $short_args (reference) short getopt format 343 * @param array $long_args (reference) long getopt format 344 * 345 * @return void 346 * 347 * @access public 348 * @static 349 */ 350 function getGetoptArgs($command, &$short_args, &$long_args) 351 { 352 if (empty($GLOBALS['_PEAR_Command_commandlist'])) { 353 PEAR_Command::registerCommands(); 354 } 355 if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) { 356 $command = $GLOBALS['_PEAR_Command_shortcuts'][$command]; 357 } 358 if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) { 359 return null; 360 } 361 $obj = &PEAR_Command::getObject($command); 362 return $obj->getGetoptArgs($command, $short_args, $long_args); 363 } 364 365 // }}} 366 // {{{ getDescription() 367 368 /** 369 * Get description for a command. 370 * 371 * @param string $command Name of the command 372 * 373 * @return string command description 374 * 375 * @access public 376 * @static 377 */ 378 function getDescription($command) 379 { 380 if (!isset($GLOBALS['_PEAR_Command_commanddesc'][$command])) { 381 return null; 382 } 383 return $GLOBALS['_PEAR_Command_commanddesc'][$command]; 384 } 385 386 // }}} 387 // {{{ getHelp() 388 389 /** 390 * Get help for command. 391 * 392 * @param string $command Name of the command to return help for 393 * 394 * @access public 395 * @static 396 */ 397 function getHelp($command) 398 { 399 $cmds = PEAR_Command::getCommands(); 400 if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) { 401 $command = $GLOBALS['_PEAR_Command_shortcuts'][$command]; 402 } 403 if (isset($cmds[$command])) { 404 $obj = &PEAR_Command::getObject($command); 405 return $obj->getHelp($command); 406 } 407 return false; 408 } 409 // }}} 410} 411 412?> 413