[TASK] Remove unneeded parenthesis on array-access
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Controller / CommandLineController.php
1 <?php
2 namespace TYPO3\CMS\Core\Controller;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 /**
18 * TYPO3 cli script basis
19 */
20 class CommandLineController
21 {
22 /**
23 * Command line arguments, exploded into key => value-array pairs
24 *
25 * @var array
26 */
27 public $cli_args = array();
28
29 /**
30 * @var array
31 */
32 public $cli_options = array(
33 array('-s', 'Silent operation, will only output errors and important messages.'),
34 array('--silent', 'Same as -s'),
35 array('-ss', 'Super silent, will not even output errors or important messages.')
36 );
37
38 /**
39 * @var array
40 */
41 public $cli_help = array(
42 'name' => 'CLI base class (overwrite this...)',
43 'synopsis' => '###OPTIONS###',
44 'description' => 'Class with basic functionality for CLI scripts (overwrite this...)',
45 'examples' => 'Give examples...',
46 'options' => '',
47 'license' => 'GNU GPL - free software!',
48 'author' => '[Author name]'
49 );
50
51 /**
52 * @var resource
53 */
54 public $stdin = null;
55
56 /**
57 * Constructor
58 * Make sure child classes also call this!
59 *
60 * @return void
61 */
62 public function __construct()
63 {
64 // Loads the cli_args array with command line arguments
65 $this->cli_setArguments($_SERVER['argv']);
66 }
67
68 /**
69 * Finds the arg token (like "-s") in argv and returns the rest of argv from that point on.
70 * This should only be used in special cases since this->cli_args should already be prepared with an index of values!
71 *
72 * @param string $option Option string, eg. "-s
73 * @param array $argv Input argv array
74 * @return array Output argv array with all options AFTER the found option.
75 */
76 public function cli_getArgArray($option, $argv)
77 {
78 while (count($argv) && (string)$argv[0] !== (string)$option) {
79 array_shift($argv);
80 }
81 if ((string)$argv[0] === (string)$option) {
82 array_shift($argv);
83 return !empty($argv) ? $argv : array('');
84 }
85 }
86
87 /**
88 * Return TRUE if option is found
89 *
90 * @param string $option Option string, eg. "-s
91 * @return bool TRUE if option found
92 */
93 public function cli_isArg($option)
94 {
95 return isset($this->cli_args[$option]);
96 }
97
98 /**
99 * Return argument value
100 *
101 * @param string $option Option string, eg. "-s
102 * @param int $idx Value index, default is 0 (zero) = the first one...
103 * @return bool TRUE if option found
104 */
105 public function cli_argValue($option, $idx = 0)
106 {
107 return is_array($this->cli_args[$option]) ? $this->cli_args[$option][$idx] : '';
108 }
109
110 /**
111 * Will parse "_SERVER[argv]" into an index of options and values
112 * Argument names (eg. "-s") will be keys and values after (eg. "-s value1 value2 ..." or "-s=value1") will be in the array.
113 * Array is empty if no values
114 *
115 * @param array $argv Configuration options
116 * @return array
117 */
118 public function cli_getArgIndex(array $argv = array())
119 {
120 $cli_options = array();
121 $index = '_DEFAULT';
122 foreach ($argv as $token) {
123 // Options starting with a number is invalid - they could be negative values!
124 if ($token[0] === '-' && !\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($token[1])) {
125 list($index, $opt) = explode('=', $token, 2);
126 if (isset($cli_options[$index])) {
127 echo 'ERROR: Option ' . $index . ' was used twice!' . LF;
128 die;
129 }
130 $cli_options[$index] = array();
131 if (isset($opt)) {
132 $cli_options[$index][] = $opt;
133 }
134 } else {
135 $cli_options[$index][] = $token;
136 }
137 }
138 return $cli_options;
139 }
140
141 /**
142 * Validates if the input arguments in this->cli_args are all listed in this->cli_options and if not,
143 * will exit with an error.
144 *
145 */
146 public function cli_validateArgs()
147 {
148 $cli_args_copy = $this->cli_args;
149 unset($cli_args_copy['_DEFAULT']);
150 $allOptions = array();
151 foreach ($this->cli_options as $cfg) {
152 $allOptions[] = $cfg[0];
153 $argSplit = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(' ', $cfg[0], true);
154 if (isset($cli_args_copy[$argSplit[0]])) {
155 foreach ($argSplit as $i => $v) {
156 $ii = $i;
157 if ($i > 0) {
158 if (!isset($cli_args_copy[$argSplit[0]][$i - 1]) && $v[0] != '[') {
159 // Using "[]" around a parameter makes it optional
160 echo 'ERROR: Option "' . $argSplit[0] . '" requires a value ("' . $v . '") on position ' . $i . LF;
161 die;
162 }
163 }
164 }
165 $ii++;
166 if (isset($cli_args_copy[$argSplit[0]][$ii - 1])) {
167 echo 'ERROR: Option "' . $argSplit[0] . '" does not support a value on position ' . $ii . LF;
168 die;
169 }
170 unset($cli_args_copy[$argSplit[0]]);
171 }
172 }
173 if (!empty($cli_args_copy)) {
174 echo wordwrap('ERROR: Option ' . implode(',', array_keys($cli_args_copy)) . ' was unknown to this script!' . LF . '(Options are: ' . implode(', ', $allOptions) . ')' . LF);
175 die;
176 }
177 }
178
179 /**
180 * Set environment array to $cli_args
181 *
182 * @param array $argv Configuration options
183 * @return void
184 */
185 public function cli_setArguments(array $argv = array())
186 {
187 $this->cli_args = $this->cli_getArgIndex($argv);
188 }
189
190 /**
191 * Asks stdin for keyboard input and returns the line (after enter is pressed)
192 *
193 * @return string
194 */
195 public function cli_keyboardInput()
196 {
197 // Have to open the stdin stream only ONCE! otherwise I cannot read multiple lines from it... :
198 if (!$this->stdin) {
199 $this->stdin = fopen('php://stdin', 'r');
200 }
201 while (false == ($line = fgets($this->stdin, 1000))) {
202 }
203 return trim($line);
204 }
205
206 /**
207 * Asks for Yes/No from shell and returns TRUE if "y" or "yes" is found as input.
208 *
209 * @param string $msg String to ask before...
210 * @return bool TRUE if "y" or "yes" is the input (case insensitive)
211 */
212 public function cli_keyboardInput_yes($msg = '')
213 {
214 // ONLY makes sense to echo it out since we are awaiting keyboard input - that cannot be silenced
215 echo $msg . ' (Yes/No + return): ';
216 return \TYPO3\CMS\Core\Utility\GeneralUtility::inList('y,yes', strtolower($this->cli_keyboardInput()));
217 }
218
219 /**
220 * Echos strings to shell, but respective silent-modes
221 *
222 * @param string $string The string
223 * @param bool $force If string should be written even if -s is set (-ss will subdue it!)
224 * @return bool Returns TRUE if string was outputted.
225 */
226 public function cli_echo($string = '', $force = false)
227 {
228 if (isset($this->cli_args['-ss'])) {
229 } elseif (isset($this->cli_args['-s']) || isset($this->cli_args['--silent'])) {
230 if ($force) {
231 echo $string;
232 return true;
233 }
234 } else {
235 echo $string;
236 return true;
237 }
238 return false;
239 }
240
241 /**
242 * Prints help-output from ->cli_help array
243 *
244 * @return void
245 */
246 public function cli_help()
247 {
248 foreach ($this->cli_help as $key => $value) {
249 $this->cli_echo(strtoupper($key) . ':
250 ');
251 switch ($key) {
252 case 'synopsis':
253 $optStr = '';
254 foreach ($this->cli_options as $v) {
255 $optStr .= ' [' . $v[0] . ']';
256 }
257 $this->cli_echo($this->cli_indent(str_replace('###OPTIONS###', trim($optStr), $value), 4) . '
258
259 ');
260 break;
261 case 'options':
262 $this->cli_echo($this->cli_indent($value, 4) . LF);
263 $maxLen = 0;
264 foreach ($this->cli_options as $v) {
265 if (strlen($v[0]) > $maxLen) {
266 $maxLen = strlen($v[0]);
267 }
268 }
269 foreach ($this->cli_options as $v) {
270 $this->cli_echo($v[0] . substr($this->cli_indent(rtrim($v[1] . LF . $v[2]), $maxLen + 4), strlen($v[0])) . LF);
271 }
272 $this->cli_echo(LF);
273 break;
274 default:
275 $this->cli_echo($this->cli_indent($value, 4) . '
276
277 ');
278 }
279 }
280 }
281
282 /**
283 * Indentation function for 75 char wide lines.
284 *
285 * @param string $str String to break and indent.
286 * @param int $indent Number of space chars to indent.
287 * @return string Result
288 */
289 public function cli_indent($str, $indent)
290 {
291 $lines = explode(LF, wordwrap($str, 75 - $indent));
292 $indentStr = str_pad('', $indent, ' ');
293 foreach ($lines as $k => $v) {
294 $lines[$k] = $indentStr . $lines[$k];
295 }
296 return implode(LF, $lines);
297 }
298 }