PageRenderTime 26ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Console/ConsoleInputDefinition.php

https://github.com/Proudio-Interactive/phpUnderControl
PHP | 414 lines | 220 code | 28 blank | 166 comment | 15 complexity | f5675b614d08fd5bc3a7202670583f82 MD5 | raw file
  1. <?php
  2. /**
  3. * This file is part of phpUnderControl.
  4. *
  5. * PHP Version 5.2.0
  6. *
  7. * Copyright (c) 2007-2010, Manuel Pichler <mapi@phpundercontrol.org>.
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. *
  14. * * Redistributions of source code must retain the above copyright
  15. * notice, this list of conditions and the following disclaimer.
  16. *
  17. * * Redistributions in binary form must reproduce the above copyright
  18. * notice, this list of conditions and the following disclaimer in
  19. * the documentation and/or other materials provided with the
  20. * distribution.
  21. *
  22. * * Neither the name of Manuel Pichler nor the names of his
  23. * contributors may be used to endorse or promote products derived
  24. * from this software without specific prior written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  27. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  28. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  29. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  30. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  31. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  32. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  33. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  34. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  35. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  36. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  37. * POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. * @category QualityAssurance
  40. * @package Console
  41. * @author Manuel Pichler <mapi@phpundercontrol.org>
  42. * @copyright 2007-2010 Manuel Pichler. All rights reserved.
  43. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  44. * @version SVN: $Id$
  45. * @link http://www.phpundercontrol.org/
  46. */
  47. /**
  48. * Collection with all available commands and options.
  49. *
  50. * @category QualityAssurance
  51. * @package Console
  52. * @author Manuel Pichler <mapi@phpundercontrol.org>
  53. * @copyright 2007-2010 Manuel Pichler. All rights reserved.
  54. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  55. * @version Release: @package_version@
  56. * @link http://www.phpundercontrol.org/
  57. */
  58. class phpucConsoleInputDefinition implements ArrayAccess, IteratorAggregate
  59. {
  60. /**
  61. * Marks a normal command or option that shows up in the cli help.
  62. */
  63. const MODE_NORMAL = 0;
  64. /**
  65. * Marks a hidden command or option. This means a command is not shown in
  66. * the cli help.
  67. */
  68. const MODE_HIDDEN = 1;
  69. /**
  70. * List of valid modes.
  71. *
  72. * @var array(string=>array)
  73. */
  74. private $definition = array(
  75. );
  76. /**
  77. * Constructs a new input definition and asks the command implementations
  78. * for their input definition.
  79. *
  80. */
  81. public function __construct()
  82. {
  83. $this->registerCommands();
  84. }
  85. /**
  86. * Checks if a command with the given <b>$cmd</b> identifier already exists.
  87. *
  88. * @param string $cmd The unique command identifier.
  89. *
  90. * @return boolean
  91. */
  92. public function hasCommand( $cmd )
  93. {
  94. return isset( $this->definition[$cmd] );
  95. }
  96. /**
  97. * Adds a new command to the input definition.
  98. *
  99. * @param string $cmd The unique command identifier.
  100. * @param string $help The command help text.
  101. * @param integer $mode The command mode, hidden or visible(normal).
  102. *
  103. * @return void
  104. * throws phpucErrorException
  105. * If a command for the given command idenfier already exists or an
  106. * input value has an invalid format.
  107. */
  108. public function addCommand( $cmd, $help, $mode = self::MODE_NORMAL )
  109. {
  110. if ( isset( $this->definition[$cmd] ) )
  111. {
  112. throw new phpucErrorException(
  113. "The command name '{$cmd}' is already in use."
  114. );
  115. }
  116. if ( !in_array( $mode, array( self::MODE_NORMAL, self::MODE_HIDDEN ) ) )
  117. {
  118. throw new phpucErrorException( 'Invalid value for mode given.' );
  119. }
  120. $this->definition[$cmd] = array(
  121. 'mode' => $mode,
  122. 'help' => $help,
  123. 'args' => array(),
  124. 'options' => array(),
  125. );
  126. }
  127. /**
  128. * Checks if an argument named <b>$arg</b> for the given command <b>$cmd</b>
  129. * exists.
  130. *
  131. * @param string $cmd The command identifier.
  132. * @param string $arg The argument identifier.
  133. *
  134. * @return boolean
  135. */
  136. public function hasArgument( $cmd, $arg )
  137. {
  138. return isset( $this->definition[$cmd]['args'][$arg] );
  139. }
  140. /**
  141. * Adds a new command line argument for the specified <b>$cmd</b>.
  142. *
  143. * @param string $cmd The associated command identifier.
  144. * @param string $arg The argument identifier.
  145. * @param string $help The help text for the argument.
  146. * @param boolean $mandatory Marks this argument as mandatory.
  147. *
  148. * @return void
  149. * @throws phpucErrorException
  150. * If no command for the given identifier exists. If an argument with
  151. * an equal argument identifier exists. If the mandatory parameter
  152. * is not of type <b>boolean</b>.
  153. */
  154. public function addArgument( $cmd, $arg, $help, $mandatory = true )
  155. {
  156. if ( !isset( $this->definition[$cmd] ) )
  157. {
  158. throw new phpucErrorException(
  159. "The command '{$cmd}' for '{$arg}' doesn't exist."
  160. );
  161. }
  162. if ( isset( $this->definition[$cmd]['args'][$arg] ) )
  163. {
  164. throw new phpucErrorException(
  165. "An argument '{$arg}' for command '{$cmd}' already exists."
  166. );
  167. }
  168. if ( !is_bool( $mandatory ) )
  169. {
  170. throw new phpucErrorException(
  171. 'The mandatory parameter must be of type boolean.'
  172. );
  173. }
  174. $this->definition[$cmd]['args'][$arg] = array(
  175. 'help' => $help,
  176. 'mandatory' => $mandatory
  177. );
  178. }
  179. /**
  180. * Checks if an option named <b>$opt</b> for the given command <b>$cmd</b>
  181. * exists.
  182. *
  183. * @param string $cmd The command identifier.
  184. * @param string $opt The option identifier.
  185. *
  186. * @return boolean
  187. */
  188. public function hasOption( $cmd, $opt )
  189. {
  190. foreach ( $this->definition[$cmd]['options'] as $option )
  191. {
  192. if ( $option['short'] === $opt || $option['long'] === $opt )
  193. {
  194. return true;
  195. }
  196. }
  197. return false;
  198. }
  199. /**
  200. * Adds a new option to the given command <b>$cmd</b>.
  201. *
  202. * @param string $cmd
  203. * The command identifier.
  204. * @param string $short
  205. * The short cli identifier for this option.
  206. * @param string $long
  207. * The long cli identifier for this option.
  208. * @param string $help
  209. * The cli help text for this option.
  210. * @param boolean|string|array|null $arg
  211. * Defines if this option has an argument and what it should be. If
  212. * this parameter is of type <b>string</b> it is used as a regular
  213. * expression for input validation. If this parameter is an <b>array</b>
  214. * it is used as whitelist.
  215. * @param string|null $default
  216. * An optional default value for this option.
  217. * @param boolean $mandatory
  218. * Marks this option as mandatory.
  219. * @param integer $mode
  220. * The command mode, hidden or visible(normal).
  221. *
  222. * @return void
  223. * @throws phpucErrorException
  224. * If no command for the given identifier exists. If an option with
  225. * an equal <b>$long</b> or <b>$short</b> identifier exists. If the
  226. * mandatory parameter is not of type <b>boolean</b>. If the
  227. * <b>$mode</b> parameter has an invalid format.
  228. */
  229. public function addOption(
  230. $cmd,
  231. $short,
  232. $long,
  233. $help,
  234. $arg = null,
  235. $default = null,
  236. $mandatory = false,
  237. $mode = self::MODE_NORMAL
  238. ) {
  239. if ( !isset( $this->definition[$cmd] ) )
  240. {
  241. throw new phpucErrorException(
  242. "The command '{$cmd}' for option '{$long}' doesn't exist."
  243. );
  244. }
  245. if ( $this->hasOption( $cmd, $short ) )
  246. {
  247. throw new phpucErrorException(
  248. "An option '{$short}' already exists for command '{$cmd}'."
  249. );
  250. }
  251. if ( $this->hasOption( $cmd, $long ) )
  252. {
  253. throw new phpucErrorException(
  254. "An option '{$long}' already exists for command '{$cmd}'."
  255. );
  256. }
  257. if ( !is_bool( $mandatory ) )
  258. {
  259. throw new phpucErrorException(
  260. 'The mandatory parameter must be of type boolean.'
  261. );
  262. }
  263. if ( !in_array( $mode, array( self::MODE_NORMAL, self::MODE_HIDDEN ) ) )
  264. {
  265. throw new phpucErrorException( 'Invalid value for mode given.' );
  266. }
  267. $this->definition[$cmd]['options'][] = array(
  268. 'short' => $short,
  269. 'long' => $long,
  270. 'arg' => $arg,
  271. 'help' => $help,
  272. 'mode' => $mode,
  273. 'default' => $default,
  274. 'mandatory' => $mandatory,
  275. );
  276. }
  277. /**
  278. * Returns an iterator with all registered cli commands.
  279. *
  280. * @return Iterator
  281. */
  282. public function getIterator()
  283. {
  284. return new ArrayIterator( $this->definition );
  285. }
  286. /**
  287. * Array access method for isset.
  288. *
  289. * @param string $name The command name to look up.
  290. *
  291. * @return boolean
  292. */
  293. public function offsetExists( $name )
  294. {
  295. return ( isset( $this->definition[$name] ) );
  296. }
  297. /**
  298. * Returns the command definition for the given name.
  299. *
  300. * If no command for the given <b>$name</b> exists, this method will throw
  301. * an <b>OutOfRangeException</b>.
  302. *
  303. * @param string $name The name of the requested command.
  304. *
  305. * @return array
  306. * @throws OutOfRangeException If the requested command doesn't exist.
  307. * @todo TODO: Change to a an instance of phpucConsoleCommandDefintion
  308. */
  309. public function offsetGet( $name )
  310. {
  311. if ( $this->offsetExists( $name ) )
  312. {
  313. return $this->definition[$name];
  314. }
  315. throw new OutOfRangeException( "Unknown index '{$name}'." );
  316. }
  317. /**
  318. * Adds a new command definition.
  319. *
  320. * @param string $name The command name.
  321. * @param array $value The command array.
  322. *
  323. * @return void
  324. * @throws InvalidArgumentException If the $value is not an array.
  325. * @todo TODO: Change to a an instance of phpucConsoleCommandDefintion
  326. */
  327. public function offsetSet( $name, $value )
  328. {
  329. // Nothing todo here
  330. }
  331. /**
  332. * Does nothing here!?!?
  333. *
  334. * @param string $name The command name.
  335. *
  336. * @return void
  337. */
  338. public function offsetUnset( $name )
  339. {
  340. // Nothing todo here
  341. }
  342. /**
  343. * Registers the available phpUnderControl commands and their options.
  344. *
  345. * @return void
  346. */
  347. protected function registerCommands()
  348. {
  349. $files = new phpucPhpFileFilterIterator(
  350. new DirectoryIterator( PHPUC_INSTALL_DIR . '/Commands' )
  351. );
  352. $commands = array();
  353. foreach ( $files as $file )
  354. {
  355. // Load reflection class
  356. $refClass = new ReflectionClass( $files->getClassName() );
  357. // Skip abstract classes and interfaces
  358. if ( $refClass->isInterface() || $refClass->isAbstract() )
  359. {
  360. continue;
  361. }
  362. // Check for extension interface
  363. if ( !$refClass->implementsInterface( 'phpucConsoleCommandI' ) )
  364. {
  365. continue;
  366. }
  367. $command = $refClass->newInstance();
  368. $command->registerCommand( $this );
  369. $commands[] = $command;
  370. }
  371. foreach ( $commands as $command )
  372. {
  373. foreach ( $command->createTasks() as $task )
  374. {
  375. if ( $task instanceof phpucConsoleExtensionI )
  376. {
  377. $task->registerCommandExtension( $this, $command );
  378. }
  379. }
  380. }
  381. ksort( $this->definition );
  382. }
  383. }