Command.php 12 KB

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