1. sfCommandManager.class.php
  2. /** * Class to manage command line arguments and options. * * @package symfony * @subpackage command * @author Fabien Potencier * @version SVN: $Id: sfCommandManager.class.php 21908 2009-09-11 12:06:21Z fabien $ */
  3. class sfCommandManager
  4. {
  5. protected
  6. $arguments = '',
  7. $errors = array(),
  8. $optionSet = null,
  9. $argumentSet = array(),
  10. $optionValues = array(),
  11. $argumentValues = array(),
  12. $parsedArgumentValues = array();
  13. /**
  14. * Constructor.
  15. *
  16. * @param sfCommandArgumentSet $argumentSet A sfCommandArgumentSet object
  17. * @param sfCommandOptionSet $optionSet A setOptionSet object
  18. */
  19. public function __construct(sfCommandArgumentSet $argumentSet = null, sfCommandOptionSet $optionSet = null)
  20. {
  21. if (null === $argumentSet)
  22. {
  23. $argumentSet = new sfCommandArgumentSet();
  24. }
  25. $this->setArgumentSet($argumentSet);
  26. if (null === $optionSet)
  27. {
  28. $optionSet = new sfCommandOptionSet();
  29. }
  30. $this->setOptionSet($optionSet);
  31. }
  32. /**
  33. * Sets the argument set.
  34. *
  35. * @param sfCommandArgumentSet $argumentSet A sfCommandArgumentSet object
  36. */
  37. public function setArgumentSet(sfCommandArgumentSet $argumentSet)
  38. {
  39. $this->argumentSet = $argumentSet;
  40. }
  41. /**
  42. * Gets the argument set.
  43. *
  44. * @return sfCommandArgumentSet A sfCommandArgumentSet object
  45. */
  46. public function getArgumentSet()
  47. {
  48. return $this->argumentSet;
  49. }
  50. /**
  51. * Sets the option set.
  52. *
  53. * @param sfCommandOptionSet $optionSet A sfCommandOptionSet object
  54. */
  55. public function setOptionSet(sfCommandOptionSet $optionSet)
  56. {
  57. $this->optionSet = $optionSet;
  58. }
  59. /**
  60. * Gets the option set.
  61. *
  62. * @return sfCommandOptionSet A sfCommandOptionSet object
  63. */
  64. public function getOptionSet()
  65. {
  66. return $this->optionSet;
  67. }
  68. /**
  69. * Processes command line arguments.
  70. *
  71. * @param mixed $arguments A string or an array of command line parameters
  72. */
  73. public function process($arguments = null)
  74. {
  75. if (null === $arguments)
  76. {
  77. $arguments = $_SERVER['argv'];
  78. // we strip command line program
  79. if (isset($arguments[0]) && '-' != $arguments[0][0])
  80. {
  81. array_shift($arguments);
  82. }
  83. }
  84. else if (!is_array($arguments))
  85. {
  86. // hack to split arguments with spaces : --test="with some spaces"
  87. $arguments = preg_replace('/(\'|")(.+?)\\1/e', "str_replace(' ', '=PLACEHOLDER=', '\\2')", $arguments);
  88. $arguments = preg_split('/\s+/', $arguments);
  89. $arguments = str_replace('=PLACEHOLDER=', ' ', $arguments);
  90. }
  91. $this->arguments = $arguments;
  92. $this->optionValues = $this->optionSet->getDefaults();
  93. $this->argumentValues = $this->argumentSet->getDefaults();
  94. $this->parsedArgumentValues = array();
  95. $this->errors = array();
  96. while (!in_array($argument = array_shift($this->arguments), array('', null)))
  97. {
  98. if ('--' == $argument)
  99. {
  100. // stop options parsing
  101. $this->parsedArgumentValues = array_merge($this->parsedArgumentValues, $this->arguments);
  102. break;
  103. }
  104. if ('--' == substr($argument, 0, 2))
  105. {
  106. $this->parseLongOption(substr($argument, 2));
  107. }
  108. else if ('-' == $argument[0])
  109. {
  110. $this->parseShortOption(substr($argument, 1));
  111. }
  112. else
  113. {
  114. $this->parsedArgumentValues[] = $argument;
  115. }
  116. }
  117. $position = 0;
  118. foreach ($this->argumentSet->getArguments() as $argument)
  119. {
  120. if (array_key_exists($position, $this->parsedArgumentValues))
  121. {
  122. if ($argument->isArray())
  123. {
  124. $this->argumentValues[$argument->getName()] = array_slice($this->parsedArgumentValues, $position);
  125. break;
  126. }
  127. else
  128. {
  129. $this->argumentValues[$argument->getName()] = $this->parsedArgumentValues[$position];
  130. }
  131. }
  132. ++$position;
  133. }
  134. $this->arguments = $arguments;
  135. if (count($this->parsedArgumentValues) < $this->argumentSet->getArgumentRequiredCount())
  136. {
  137. $this->errors[] = 'Not enough arguments.';
  138. }
  139. else if (count($this->parsedArgumentValues) > $this->argumentSet->getArgumentCount())
  140. {
  141. $this->errors[] = sprintf('Too many arguments ("%s" given).', implode(' ', $this->parsedArgumentValues));
  142. }
  143. }
  144. /**
  145. * Returns true if the current command line options validate the argument and option sets.
  146. *
  147. * @return true if there are some validation errors, false otherwise
  148. */
  149. public function isValid()
  150. {
  151. return count($this->errors) ? false : true;
  152. }
  153. /**
  154. * Gets the current errors.
  155. *
  156. * @return array An array of errors
  157. */
  158. public function getErrors()
  159. {
  160. return $this->errors;
  161. }
  162. /**
  163. * Returns the argument values.
  164. *
  165. * @return array An array of argument values
  166. */
  167. public function getArgumentValues()
  168. {
  169. return $this->argumentValues;
  170. }
  171. /**
  172. * Returns the argument value for a given argument name.
  173. *
  174. * @param string $name The argument name
  175. *
  176. * @return mixed The argument value
  177. */
  178. public function getArgumentValue($name)
  179. {
  180. if (!$this->argumentSet->hasArgument($name))
  181. {
  182. throw new sfCommandException(sprintf('The "%s" argument does not exist.', $name));
  183. }
  184. return $this->argumentValues[$name];
  185. }
  186. /**
  187. * Returns the options values.
  188. *
  189. * @return array An array of option values
  190. */
  191. public function getOptionValues()
  192. {
  193. return $this->optionValues;
  194. }
  195. /**
  196. * Returns the option value for a given option name.
  197. *
  198. * @param string $name The option name
  199. *
  200. * @return mixed The option value
  201. */
  202. public function getOptionValue($name)
  203. {
  204. if (!$this->optionSet->hasOption($name))
  205. {
  206. throw new sfCommandException(sprintf('The "%s" option does not exist.', $name));
  207. }
  208. return $this->optionValues[$name];
  209. }
  210. /**
  211. * Parses a short option.
  212. *
  213. * @param string $argument The option argument
  214. */
  215. protected function parseShortOption($argument)
  216. {
  217. // short option can be aggregated like in -vd (== -v -d)
  218. for ($i = 0, $count = strlen($argument); $i < $count; $i++)
  219. {
  220. $shortcut = $argument[$i];
  221. $value = true;
  222. if (!$this->optionSet->hasShortcut($shortcut))
  223. {
  224. $this->errors[] = sprintf('The option "-%s" does not exist.', $shortcut);
  225. continue;
  226. }
  227. $option = $this->optionSet->getOptionForShortcut($shortcut);
  228. // required argument?
  229. if ($option->isParameterRequired())
  230. {
  231. if ($i + 1 < strlen($argument))
  232. {
  233. $value = substr($argument, $i + 1);
  234. $this->setOption($option, $value);
  235. break;
  236. }
  237. else
  238. {
  239. // take next element as argument (if it doesn't start with a -)
  240. if (count($this->arguments) && $this->arguments[0][0] != '-')
  241. {
  242. $value = array_shift($this->arguments);
  243. $this->setOption($option, $value);
  244. break;
  245. }
  246. else
  247. {
  248. $this->errors[] = sprintf('Option "-%s" requires an argument', $shortcut);
  249. $value = null;
  250. }
  251. }
  252. }
  253. else if ($option->isParameterOptional())
  254. {
  255. if (substr($argument, $i + 1) != '')
  256. {
  257. $value = substr($argument, $i + 1);
  258. }
  259. else
  260. {
  261. // take next element as argument (if it doesn't start with a -)
  262. if (count($this->arguments) && $this->arguments[0][0] != '-')
  263. {
  264. $value = array_shift($this->arguments);
  265. }
  266. else
  267. {
  268. $value = $option->getDefault();
  269. }
  270. }
  271. $this->setOption($option, $value);
  272. break;
  273. }
  274. $this->setOption($option, $value);
  275. }
  276. }
  277. /**
  278. * Parses a long option.
  279. *
  280. * @param string $argument The option argument
  281. */
  282. protected function parseLongOption($argument)
  283. {
  284. if (false !== strpos($argument, '='))
  285. {
  286. list($name, $value) = explode('=', $argument, 2);
  287. if (!$this->optionSet->hasOption($name))
  288. {
  289. $this->errors[] = sprintf('The "--%s" option does not exist.', $name);
  290. return;
  291. }
  292. $option = $this->optionSet->getOption($name);
  293. if (!$option->acceptParameter())
  294. {
  295. $this->errors[] = sprintf('Option "--%s" does not take an argument.', $name);
  296. $value = true;
  297. }
  298. }
  299. else
  300. {
  301. $name = $argument;
  302. if (!$this->optionSet->hasOption($name))
  303. {
  304. $this->errors[] = sprintf('The "--%s" option does not exist.', $name);
  305. return;
  306. }
  307. $option = $this->optionSet->getOption($name);
  308. if ($option->isParameterRequired())
  309. {
  310. $this->errors[] = sprintf('Option "--%s" requires an argument.', $name);
  311. }
  312. $value = $option->acceptParameter() ? $option->getDefault() : true;
  313. }
  314. $this->setOption($option, $value);
  315. }
  316. public function setOption(sfCommandOption $option, $value)
  317. {
  318. if ($option->isArray())
  319. {
  320. $this->optionValues[$option->getName()][] = $value;
  321. }
  322. else
  323. {
  324. $this->optionValues[$option->getName()] = $value;
  325. }
  326. }
  327. }

Debug toolbar