1: <?php
2: /**
3: * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
4: * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
5: *
6: * Licensed under The MIT License
7: * For full copyright and license information, please see the LICENSE.txt
8: * Redistributions of files must retain the above copyright notice.
9: *
10: * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
11: * @link https://cakephp.org CakePHP(tm) Project
12: * @since 2.0.0
13: * @license https://opensource.org/licenses/mit-license.php MIT License
14: */
15: namespace Cake\Console;
16:
17: use Cake\Console\Exception\ConsoleException;
18: use SimpleXMLElement;
19:
20: /**
21: * An object to represent a single option used in the command line.
22: * ConsoleOptionParser creates these when you use addOption()
23: *
24: * @see \Cake\Console\ConsoleOptionParser::addOption()
25: */
26: class ConsoleInputOption
27: {
28: /**
29: * Name of the option
30: *
31: * @var string
32: */
33: protected $_name;
34:
35: /**
36: * Short (1 character) alias for the option.
37: *
38: * @var string
39: */
40: protected $_short;
41:
42: /**
43: * Help text for the option.
44: *
45: * @var string
46: */
47: protected $_help;
48:
49: /**
50: * Is the option a boolean option. Boolean options do not consume a parameter.
51: *
52: * @var bool
53: */
54: protected $_boolean;
55:
56: /**
57: * Default value for the option
58: *
59: * @var string|bool
60: */
61: protected $_default;
62:
63: /**
64: * Can the option accept multiple value definition.
65: *
66: * @var bool
67: */
68: protected $_multiple;
69:
70: /**
71: * An array of choices for the option.
72: *
73: * @var string[]
74: */
75: protected $_choices;
76:
77: /**
78: * Make a new Input Option
79: *
80: * @param string|array $name The long name of the option, or an array with all the properties.
81: * @param string $short The short alias for this option
82: * @param string $help The help text for this option
83: * @param bool $boolean Whether this option is a boolean option. Boolean options don't consume extra tokens
84: * @param string|bool $default The default value for this option.
85: * @param string[] $choices Valid choices for this option.
86: * @param bool $multiple Whether this option can accept multiple value definition.
87: * @throws \Cake\Console\Exception\ConsoleException
88: */
89: public function __construct(
90: $name,
91: $short = '',
92: $help = '',
93: $boolean = false,
94: $default = '',
95: $choices = [],
96: $multiple = false
97: ) {
98: if (is_array($name) && isset($name['name'])) {
99: foreach ($name as $key => $value) {
100: $this->{'_' . $key} = $value;
101: }
102: } else {
103: $this->_name = $name;
104: $this->_short = $short;
105: $this->_help = $help;
106: $this->_boolean = $boolean;
107: $this->_default = $default;
108: $this->_choices = $choices;
109: $this->_multiple = $multiple;
110: }
111: if (strlen($this->_short) > 1) {
112: throw new ConsoleException(
113: sprintf('Short option "%s" is invalid, short options must be one letter.', $this->_short)
114: );
115: }
116: }
117:
118: /**
119: * Get the value of the name attribute.
120: *
121: * @return string Value of this->_name.
122: */
123: public function name()
124: {
125: return $this->_name;
126: }
127:
128: /**
129: * Get the value of the short attribute.
130: *
131: * @return string Value of this->_short.
132: */
133: public function short()
134: {
135: return $this->_short;
136: }
137:
138: /**
139: * Generate the help for this this option.
140: *
141: * @param int $width The width to make the name of the option.
142: * @return string
143: */
144: public function help($width = 0)
145: {
146: $default = $short = '';
147: if ($this->_default && $this->_default !== true) {
148: $default = sprintf(' <comment>(default: %s)</comment>', $this->_default);
149: }
150: if ($this->_choices) {
151: $default .= sprintf(' <comment>(choices: %s)</comment>', implode('|', $this->_choices));
152: }
153: if (strlen($this->_short) > 0) {
154: $short = ', -' . $this->_short;
155: }
156: $name = sprintf('--%s%s', $this->_name, $short);
157: if (strlen($name) < $width) {
158: $name = str_pad($name, $width, ' ');
159: }
160:
161: return sprintf('%s%s%s', $name, $this->_help, $default);
162: }
163:
164: /**
165: * Get the usage value for this option
166: *
167: * @return string
168: */
169: public function usage()
170: {
171: $name = (strlen($this->_short) > 0) ? ('-' . $this->_short) : ('--' . $this->_name);
172: $default = '';
173: if (strlen($this->_default) > 0 && $this->_default !== true) {
174: $default = ' ' . $this->_default;
175: }
176: if ($this->_choices) {
177: $default = ' ' . implode('|', $this->_choices);
178: }
179:
180: return sprintf('[%s%s]', $name, $default);
181: }
182:
183: /**
184: * Get the default value for this option
185: *
186: * @return mixed
187: */
188: public function defaultValue()
189: {
190: return $this->_default;
191: }
192:
193: /**
194: * Check if this option is a boolean option
195: *
196: * @return bool
197: */
198: public function isBoolean()
199: {
200: return (bool)$this->_boolean;
201: }
202:
203: /**
204: * Check if this option accepts multiple values.
205: *
206: * @return bool
207: */
208: public function acceptsMultiple()
209: {
210: return (bool)$this->_multiple;
211: }
212:
213: /**
214: * Check that a value is a valid choice for this option.
215: *
216: * @param string|bool $value The choice to validate.
217: * @return true
218: * @throws \Cake\Console\Exception\ConsoleException
219: */
220: public function validChoice($value)
221: {
222: if (empty($this->_choices)) {
223: return true;
224: }
225: if (!in_array($value, $this->_choices, true)) {
226: throw new ConsoleException(
227: sprintf(
228: '"%s" is not a valid value for --%s. Please use one of "%s"',
229: $value,
230: $this->_name,
231: implode(', ', $this->_choices)
232: )
233: );
234: }
235:
236: return true;
237: }
238:
239: /**
240: * Append the option's xml into the parent.
241: *
242: * @param \SimpleXMLElement $parent The parent element.
243: * @return \SimpleXMLElement The parent with this option appended.
244: */
245: public function xml(SimpleXMLElement $parent)
246: {
247: $option = $parent->addChild('option');
248: $option->addAttribute('name', '--' . $this->_name);
249: $short = '';
250: if (strlen($this->_short) > 0) {
251: $short = '-' . $this->_short;
252: }
253: $option->addAttribute('short', $short);
254: $option->addAttribute('help', $this->_help);
255: $option->addAttribute('boolean', (int)$this->_boolean);
256: $option->addChild('default', $this->_default);
257: $choices = $option->addChild('choices');
258: foreach ($this->_choices as $valid) {
259: $choices->addChild('choice', $valid);
260: }
261:
262: return $parent;
263: }
264: }
265: