1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Symfony\Component\Console\Input;
13:
14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27:
28: class InputDefinition
29: {
30: private $arguments;
31: private $requiredCount;
32: private $hasAnArrayArgument = false;
33: private $hasOptional;
34: private $options;
35: private $shortcuts;
36:
37: 38: 39: 40: 41: 42: 43:
44: public function __construct(array $definition = array())
45: {
46: $this->setDefinition($definition);
47: }
48:
49: 50: 51: 52: 53: 54: 55:
56: public function setDefinition(array $definition)
57: {
58: $arguments = array();
59: $options = array();
60: foreach ($definition as $item) {
61: if ($item instanceof InputOption) {
62: $options[] = $item;
63: } else {
64: $arguments[] = $item;
65: }
66: }
67:
68: $this->setArguments($arguments);
69: $this->setOptions($options);
70: }
71:
72: 73: 74: 75: 76: 77: 78:
79: public function setArguments($arguments = array())
80: {
81: $this->arguments = array();
82: $this->requiredCount = 0;
83: $this->hasOptional = false;
84: $this->hasAnArrayArgument = false;
85: $this->addArguments($arguments);
86: }
87:
88: 89: 90: 91: 92: 93: 94:
95: public function addArguments($arguments = array())
96: {
97: if (null !== $arguments) {
98: foreach ($arguments as $argument) {
99: $this->addArgument($argument);
100: }
101: }
102: }
103:
104: 105: 106: 107: 108: 109: 110: 111: 112:
113: public function addArgument(InputArgument $argument)
114: {
115: if (isset($this->arguments[$argument->getName()])) {
116: throw new \LogicException(sprintf('An argument with name "%s" already exist.', $argument->getName()));
117: }
118:
119: if ($this->hasAnArrayArgument) {
120: throw new \LogicException('Cannot add an argument after an array argument.');
121: }
122:
123: if ($argument->isRequired() && $this->hasOptional) {
124: throw new \LogicException('Cannot add a required argument after an optional one.');
125: }
126:
127: if ($argument->isArray()) {
128: $this->hasAnArrayArgument = true;
129: }
130:
131: if ($argument->isRequired()) {
132: ++$this->requiredCount;
133: } else {
134: $this->hasOptional = true;
135: }
136:
137: $this->arguments[$argument->getName()] = $argument;
138: }
139:
140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150:
151: public function getArgument($name)
152: {
153: $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
154:
155: if (!$this->hasArgument($name)) {
156: throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
157: }
158:
159: return $arguments[$name];
160: }
161:
162: 163: 164: 165: 166: 167: 168: 169: 170:
171: public function hasArgument($name)
172: {
173: $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
174:
175: return isset($arguments[$name]);
176: }
177:
178: 179: 180: 181: 182: 183: 184:
185: public function getArguments()
186: {
187: return $this->arguments;
188: }
189:
190: 191: 192: 193: 194:
195: public function getArgumentCount()
196: {
197: return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments);
198: }
199:
200: 201: 202: 203: 204:
205: public function getArgumentRequiredCount()
206: {
207: return $this->requiredCount;
208: }
209:
210: 211: 212: 213: 214:
215: public function getArgumentDefaults()
216: {
217: $values = array();
218: foreach ($this->arguments as $argument) {
219: $values[$argument->getName()] = $argument->getDefault();
220: }
221:
222: return $values;
223: }
224:
225: 226: 227: 228: 229: 230: 231:
232: public function setOptions($options = array())
233: {
234: $this->options = array();
235: $this->shortcuts = array();
236: $this->addOptions($options);
237: }
238:
239: 240: 241: 242: 243: 244: 245:
246: public function addOptions($options = array())
247: {
248: foreach ($options as $option) {
249: $this->addOption($option);
250: }
251: }
252:
253: 254: 255: 256: 257: 258: 259: 260: 261:
262: public function addOption(InputOption $option)
263: {
264: if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
265: throw new \LogicException(sprintf('An option named "%s" already exist.', $option->getName()));
266: } elseif (isset($this->shortcuts[$option->getShortcut()]) && !$option->equals($this->options[$this->shortcuts[$option->getShortcut()]])) {
267: throw new \LogicException(sprintf('An option with shortcut "%s" already exist.', $option->getShortcut()));
268: }
269:
270: $this->options[$option->getName()] = $option;
271: if ($option->getShortcut()) {
272: $this->shortcuts[$option->getShortcut()] = $option->getName();
273: }
274: }
275:
276: 277: 278: 279: 280: 281: 282: 283: 284:
285: public function getOption($name)
286: {
287: if (!$this->hasOption($name)) {
288: throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
289: }
290:
291: return $this->options[$name];
292: }
293:
294: 295: 296: 297: 298: 299: 300: 301: 302:
303: public function hasOption($name)
304: {
305: return isset($this->options[$name]);
306: }
307:
308: 309: 310: 311: 312: 313: 314:
315: public function getOptions()
316: {
317: return $this->options;
318: }
319:
320: 321: 322: 323: 324: 325: 326:
327: public function hasShortcut($name)
328: {
329: return isset($this->shortcuts[$name]);
330: }
331:
332: 333: 334: 335: 336: 337: 338:
339: public function getOptionForShortcut($shortcut)
340: {
341: return $this->getOption($this->shortcutToName($shortcut));
342: }
343:
344: 345: 346: 347: 348:
349: public function getOptionDefaults()
350: {
351: $values = array();
352: foreach ($this->options as $option) {
353: $values[$option->getName()] = $option->getDefault();
354: }
355:
356: return $values;
357: }
358:
359: 360: 361: 362: 363: 364: 365: 366: 367:
368: private function shortcutToName($shortcut)
369: {
370: if (!isset($this->shortcuts[$shortcut])) {
371: throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
372: }
373:
374: return $this->shortcuts[$shortcut];
375: }
376:
377: 378: 379: 380: 381:
382: public function getSynopsis()
383: {
384: $elements = array();
385: foreach ($this->getOptions() as $option) {
386: $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
387: $elements[] = sprintf('['.($option->isValueRequired() ? '%s--%s="..."' : ($option->isValueOptional() ? '%s--%s[="..."]' : '%s--%s')).']', $shortcut, $option->getName());
388: }
389:
390: foreach ($this->getArguments() as $argument) {
391: $elements[] = sprintf($argument->isRequired() ? '%s' : '[%s]', $argument->getName().($argument->isArray() ? '1' : ''));
392:
393: if ($argument->isArray()) {
394: $elements[] = sprintf('... [%sN]', $argument->getName());
395: }
396: }
397:
398: return implode(' ', $elements);
399: }
400:
401: 402: 403: 404: 405:
406: public function asText()
407: {
408:
409: $max = 0;
410: foreach ($this->getOptions() as $option) {
411: $nameLength = strlen($option->getName()) + 2;
412: if ($option->getShortcut()) {
413: $nameLength += strlen($option->getShortcut()) + 3;
414: }
415:
416: $max = max($max, $nameLength);
417: }
418: foreach ($this->getArguments() as $argument) {
419: $max = max($max, strlen($argument->getName()));
420: }
421: ++$max;
422:
423: $text = array();
424:
425: if ($this->getArguments()) {
426: $text[] = '<comment>Arguments:</comment>';
427: foreach ($this->getArguments() as $argument) {
428: if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
429: $default = sprintf('<comment> (default: %s)</comment>', $this->formatDefaultValue($argument->getDefault()));
430: } else {
431: $default = '';
432: }
433:
434: $description = str_replace("\n", "\n".str_pad('', $max + 2, ' '), $argument->getDescription());
435:
436: $text[] = sprintf(" <info>%-${max}s</info> %s%s", $argument->getName(), $description, $default);
437: }
438:
439: $text[] = '';
440: }
441:
442: if ($this->getOptions()) {
443: $text[] = '<comment>Options:</comment>';
444:
445: foreach ($this->getOptions() as $option) {
446: if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
447: $default = sprintf('<comment> (default: %s)</comment>', $this->formatDefaultValue($option->getDefault()));
448: } else {
449: $default = '';
450: }
451:
452: $multiple = $option->isArray() ? '<comment> (multiple values allowed)</comment>' : '';
453: $description = str_replace("\n", "\n".str_pad('', $max + 2, ' '), $option->getDescription());
454:
455: $optionMax = $max - strlen($option->getName()) - 2;
456: $text[] = sprintf(" <info>%s</info> %-${optionMax}s%s%s%s",
457: '--'.$option->getName(),
458: $option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '',
459: $description,
460: $default,
461: $multiple
462: );
463: }
464:
465: $text[] = '';
466: }
467:
468: return implode("\n", $text);
469: }
470:
471: 472: 473: 474: 475: 476: 477:
478: public function asXml($asDom = false)
479: {
480: $dom = new \DOMDocument('1.0', 'UTF-8');
481: $dom->formatOutput = true;
482: $dom->appendChild($definitionXML = $dom->createElement('definition'));
483:
484: $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
485: foreach ($this->getArguments() as $argument) {
486: $argumentsXML->appendChild($argumentXML = $dom->createElement('argument'));
487: $argumentXML->setAttribute('name', $argument->getName());
488: $argumentXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
489: $argumentXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
490: $argumentXML->appendChild($descriptionXML = $dom->createElement('description'));
491: $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
492:
493: $argumentXML->appendChild($defaultsXML = $dom->createElement('defaults'));
494: $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : (is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array()));
495: foreach ($defaults as $default) {
496: $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
497: $defaultXML->appendChild($dom->createTextNode($default));
498: }
499: }
500:
501: $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
502: foreach ($this->getOptions() as $option) {
503: $optionsXML->appendChild($optionXML = $dom->createElement('option'));
504: $optionXML->setAttribute('name', '--'.$option->getName());
505: $optionXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
506: $optionXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
507: $optionXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
508: $optionXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
509: $optionXML->appendChild($descriptionXML = $dom->createElement('description'));
510: $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
511:
512: if ($option->acceptValue()) {
513: $optionXML->appendChild($defaultsXML = $dom->createElement('defaults'));
514: $defaults = is_array($option->getDefault()) ? $option->getDefault() : (is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array()));
515: foreach ($defaults as $default) {
516: $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
517: $defaultXML->appendChild($dom->createTextNode($default));
518: }
519: }
520: }
521:
522: return $asDom ? $dom : $dom->saveXml();
523: }
524:
525: private function formatDefaultValue($default)
526: {
527: if (is_array($default) && $default === array_values($default)) {
528: return sprintf("array('%s')", implode("', '", $default));
529: }
530:
531: return str_replace("\n", '', var_export($default, true));
532: }
533: }
534: