[5146] | 1 | <?php |
---|
| 2 | /** |
---|
| 3 | * PEAR_Command, command pattern class |
---|
| 4 | * |
---|
| 5 | * PHP versions 4 and 5 |
---|
| 6 | * |
---|
| 7 | * @category pear |
---|
| 8 | * @package PEAR |
---|
| 9 | * @author Stig Bakken <ssb@php.net> |
---|
| 10 | * @author Greg Beaver <cellog@php.net> |
---|
| 11 | * @copyright 1997-2009 The Authors |
---|
| 12 | * @license http://opensource.org/licenses/bsd-license.php New BSD License |
---|
| 13 | * @version CVS: $Id: Command.php 313023 2011-07-06 19:17:11Z dufuz $ |
---|
| 14 | * @link http://pear.php.net/package/PEAR |
---|
| 15 | * @since File available since Release 0.1 |
---|
| 16 | */ |
---|
| 17 | |
---|
| 18 | /** |
---|
| 19 | * Needed for error handling |
---|
| 20 | */ |
---|
| 21 | require_once 'PEAR.php'; |
---|
| 22 | require_once 'PEAR/Frontend.php'; |
---|
| 23 | require_once 'PEAR/XMLParser.php'; |
---|
| 24 | |
---|
| 25 | /** |
---|
| 26 | * List of commands and what classes they are implemented in. |
---|
| 27 | * @var array command => implementing class |
---|
| 28 | */ |
---|
| 29 | $GLOBALS['_PEAR_Command_commandlist'] = array(); |
---|
| 30 | |
---|
| 31 | /** |
---|
| 32 | * List of commands and their descriptions |
---|
| 33 | * @var array command => description |
---|
| 34 | */ |
---|
| 35 | $GLOBALS['_PEAR_Command_commanddesc'] = 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-2009 The Authors |
---|
| 96 | * @license http://opensource.org/licenses/bsd-license.php New BSD License |
---|
| 97 | * @version Release: 1.9.4 |
---|
| 98 | * @link http://pear.php.net/package/PEAR |
---|
| 99 | * @since Class available since Release 0.1 |
---|
| 100 | */ |
---|
| 101 | class 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 | if (!is_dir($dir)) { |
---|
| 235 | return PEAR::raiseError("registerCommands: opendir($dir) '$dir' does not exist or is not a directory"); |
---|
| 236 | } |
---|
| 237 | $dp = @opendir($dir); |
---|
| 238 | if (empty($dp)) { |
---|
| 239 | return PEAR::raiseError("registerCommands: opendir($dir) failed"); |
---|
| 240 | } |
---|
| 241 | if (!$merge) { |
---|
| 242 | $GLOBALS['_PEAR_Command_commandlist'] = array(); |
---|
| 243 | } |
---|
| 244 | |
---|
| 245 | while ($file = readdir($dp)) { |
---|
| 246 | if ($file{0} == '.' || substr($file, -4) != '.xml') { |
---|
| 247 | continue; |
---|
| 248 | } |
---|
| 249 | |
---|
| 250 | $f = substr($file, 0, -4); |
---|
| 251 | $class = "PEAR_Command_" . $f; |
---|
| 252 | // List of commands |
---|
| 253 | if (empty($GLOBALS['_PEAR_Command_objects'][$class])) { |
---|
| 254 | $GLOBALS['_PEAR_Command_objects'][$class] = "$dir/" . $f . '.php'; |
---|
| 255 | } |
---|
| 256 | |
---|
| 257 | $parser->parse(file_get_contents("$dir/$file")); |
---|
| 258 | $implements = $parser->getData(); |
---|
| 259 | foreach ($implements as $command => $desc) { |
---|
| 260 | if ($command == 'attribs') { |
---|
| 261 | continue; |
---|
| 262 | } |
---|
| 263 | |
---|
| 264 | if (isset($GLOBALS['_PEAR_Command_commandlist'][$command])) { |
---|
| 265 | return PEAR::raiseError('Command "' . $command . '" already registered in ' . |
---|
| 266 | 'class "' . $GLOBALS['_PEAR_Command_commandlist'][$command] . '"'); |
---|
| 267 | } |
---|
| 268 | |
---|
| 269 | $GLOBALS['_PEAR_Command_commandlist'][$command] = $class; |
---|
| 270 | $GLOBALS['_PEAR_Command_commanddesc'][$command] = $desc['summary']; |
---|
| 271 | if (isset($desc['shortcut'])) { |
---|
| 272 | $shortcut = $desc['shortcut']; |
---|
| 273 | if (isset($GLOBALS['_PEAR_Command_shortcuts'][$shortcut])) { |
---|
| 274 | return PEAR::raiseError('Command shortcut "' . $shortcut . '" already ' . |
---|
| 275 | 'registered to command "' . $command . '" in class "' . |
---|
| 276 | $GLOBALS['_PEAR_Command_commandlist'][$command] . '"'); |
---|
| 277 | } |
---|
| 278 | $GLOBALS['_PEAR_Command_shortcuts'][$shortcut] = $command; |
---|
| 279 | } |
---|
| 280 | |
---|
| 281 | if (isset($desc['options']) && $desc['options']) { |
---|
| 282 | foreach ($desc['options'] as $oname => $option) { |
---|
| 283 | if (isset($option['shortopt']) && strlen($option['shortopt']) > 1) { |
---|
| 284 | return PEAR::raiseError('Option "' . $oname . '" short option "' . |
---|
| 285 | $option['shortopt'] . '" must be ' . |
---|
| 286 | 'only 1 character in Command "' . $command . '" in class "' . |
---|
| 287 | $class . '"'); |
---|
| 288 | } |
---|
| 289 | } |
---|
| 290 | } |
---|
| 291 | } |
---|
| 292 | } |
---|
| 293 | |
---|
| 294 | ksort($GLOBALS['_PEAR_Command_shortcuts']); |
---|
| 295 | ksort($GLOBALS['_PEAR_Command_commandlist']); |
---|
| 296 | @closedir($dp); |
---|
| 297 | return true; |
---|
| 298 | } |
---|
| 299 | |
---|
| 300 | // }}} |
---|
| 301 | // {{{ getCommands() |
---|
| 302 | |
---|
| 303 | /** |
---|
| 304 | * Get the list of currently supported commands, and what |
---|
| 305 | * classes implement them. |
---|
| 306 | * |
---|
| 307 | * @return array command => implementing class |
---|
| 308 | * |
---|
| 309 | * @access public |
---|
| 310 | * @static |
---|
| 311 | */ |
---|
| 312 | function getCommands() |
---|
| 313 | { |
---|
| 314 | if (empty($GLOBALS['_PEAR_Command_commandlist'])) { |
---|
| 315 | PEAR_Command::registerCommands(); |
---|
| 316 | } |
---|
| 317 | return $GLOBALS['_PEAR_Command_commandlist']; |
---|
| 318 | } |
---|
| 319 | |
---|
| 320 | // }}} |
---|
| 321 | // {{{ getShortcuts() |
---|
| 322 | |
---|
| 323 | /** |
---|
| 324 | * Get the list of command shortcuts. |
---|
| 325 | * |
---|
| 326 | * @return array shortcut => command |
---|
| 327 | * |
---|
| 328 | * @access public |
---|
| 329 | * @static |
---|
| 330 | */ |
---|
| 331 | function getShortcuts() |
---|
| 332 | { |
---|
| 333 | if (empty($GLOBALS['_PEAR_Command_shortcuts'])) { |
---|
| 334 | PEAR_Command::registerCommands(); |
---|
| 335 | } |
---|
| 336 | return $GLOBALS['_PEAR_Command_shortcuts']; |
---|
| 337 | } |
---|
| 338 | |
---|
| 339 | // }}} |
---|
| 340 | // {{{ getGetoptArgs() |
---|
| 341 | |
---|
| 342 | /** |
---|
| 343 | * Compiles arguments for getopt. |
---|
| 344 | * |
---|
| 345 | * @param string $command command to get optstring for |
---|
| 346 | * @param string $short_args (reference) short getopt format |
---|
| 347 | * @param array $long_args (reference) long getopt format |
---|
| 348 | * |
---|
| 349 | * @return void |
---|
| 350 | * |
---|
| 351 | * @access public |
---|
| 352 | * @static |
---|
| 353 | */ |
---|
| 354 | function getGetoptArgs($command, &$short_args, &$long_args) |
---|
| 355 | { |
---|
| 356 | if (empty($GLOBALS['_PEAR_Command_commandlist'])) { |
---|
| 357 | PEAR_Command::registerCommands(); |
---|
| 358 | } |
---|
| 359 | if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) { |
---|
| 360 | $command = $GLOBALS['_PEAR_Command_shortcuts'][$command]; |
---|
| 361 | } |
---|
| 362 | if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) { |
---|
| 363 | return null; |
---|
| 364 | } |
---|
| 365 | $obj = &PEAR_Command::getObject($command); |
---|
| 366 | return $obj->getGetoptArgs($command, $short_args, $long_args); |
---|
| 367 | } |
---|
| 368 | |
---|
| 369 | // }}} |
---|
| 370 | // {{{ getDescription() |
---|
| 371 | |
---|
| 372 | /** |
---|
| 373 | * Get description for a command. |
---|
| 374 | * |
---|
| 375 | * @param string $command Name of the command |
---|
| 376 | * |
---|
| 377 | * @return string command description |
---|
| 378 | * |
---|
| 379 | * @access public |
---|
| 380 | * @static |
---|
| 381 | */ |
---|
| 382 | function getDescription($command) |
---|
| 383 | { |
---|
| 384 | if (!isset($GLOBALS['_PEAR_Command_commanddesc'][$command])) { |
---|
| 385 | return null; |
---|
| 386 | } |
---|
| 387 | return $GLOBALS['_PEAR_Command_commanddesc'][$command]; |
---|
| 388 | } |
---|
| 389 | |
---|
| 390 | // }}} |
---|
| 391 | // {{{ getHelp() |
---|
| 392 | |
---|
| 393 | /** |
---|
| 394 | * Get help for command. |
---|
| 395 | * |
---|
| 396 | * @param string $command Name of the command to return help for |
---|
| 397 | * |
---|
| 398 | * @access public |
---|
| 399 | * @static |
---|
| 400 | */ |
---|
| 401 | function getHelp($command) |
---|
| 402 | { |
---|
| 403 | $cmds = PEAR_Command::getCommands(); |
---|
| 404 | if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) { |
---|
| 405 | $command = $GLOBALS['_PEAR_Command_shortcuts'][$command]; |
---|
| 406 | } |
---|
| 407 | if (isset($cmds[$command])) { |
---|
| 408 | $obj = &PEAR_Command::getObject($command); |
---|
| 409 | return $obj->getHelp($command); |
---|
| 410 | } |
---|
| 411 | return false; |
---|
| 412 | } |
---|
| 413 | // }}} |
---|
| 414 | } |
---|