[TASK] Cleanup double-paranthesis in calls to trim()
[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 // Loads the cli_args array with command line arguments
64 $this->cli_setArguments($_SERVER['argv']);
65 }
66
67 /**
68 * Finds the arg token (like "-s") in argv and returns the rest of argv from that point on.
69 * This should only be used in special cases since this->cli_args should already be prepared with an index of values!
70 *
71 * @param string $option Option string, eg. "-s
72 * @param array $argv Input argv array
73 * @return array Output argv array with all options AFTER the found option.
74 */
75 public function cli_getArgArray($option, $argv) {
76 while (count($argv) && (string)$argv[0] !== (string)$option) {
77 array_shift($argv);
78 }
79 if ((string)$argv[0] === (string)$option) {
80 array_shift($argv);
81 return !empty($argv) ? $argv : array('');
82 }
83 }
84
85 /**
86 * Return TRUE if option is found
87 *
88 * @param string $option Option string, eg. "-s
89 * @return bool TRUE if option found
90 */
91 public function cli_isArg($option) {
92 return isset($this->cli_args[$option]);
93 }
94
95 /**
96 * Return argument value
97 *
98 * @param string $option Option string, eg. "-s
99 * @param int $idx Value index, default is 0 (zero) = the first one...
100 * @return bool TRUE if option found
101 */
102 public function cli_argValue($option, $idx = 0) {
103 return is_array($this->cli_args[$option]) ? $this->cli_args[$option][$idx] : '';
104 }
105
106 /**
107 * Will parse "_SERVER[argv]" into an index of options and values
108 * Argument names (eg. "-s") will be keys and values after (eg. "-s value1 value2 ..." or "-s=value1") will be in the array.
109 * Array is empty if no values
110 *
111 * @param array $argv Configuration options
112 * @return array
113 */
114 public function cli_getArgIndex(array $argv = array()) {
115 $cli_options = array();
116 $index = '_DEFAULT';
117 foreach ($argv as $token) {
118 // Options starting with a number is invalid - they could be negative values!
119 if ($token[0] === '-' && !\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($token[1])) {
120 list($index, $opt) = explode('=', $token, 2);
121 if (isset($cli_options[$index])) {
122 echo 'ERROR: Option ' . $index . ' was used twice!' . LF;
123 die;
124 }
125 $cli_options[$index] = array();
126 if (isset($opt)) {
127 $cli_options[$index][] = $opt;
128 }
129 } else {
130 $cli_options[$index][] = $token;
131 }
132 }
133 return $cli_options;
134 }
135
136 /**
137 * Validates if the input arguments in this->cli_args are all listed in this->cli_options and if not,
138 * will exit with an error.
139 *
140 */
141 public function cli_validateArgs() {
142 $cli_args_copy = $this->cli_args;
143 unset($cli_args_copy['_DEFAULT']);
144 $allOptions = array();
145 foreach ($this->cli_options as $cfg) {
146 $allOptions[] = $cfg[0];
147 $argSplit = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(' ', $cfg[0], TRUE);
148 if (isset($cli_args_copy[$argSplit[0]])) {
149 foreach ($argSplit as $i => $v) {
150 $ii = $i;
151 if ($i > 0) {
152 if (!isset($cli_args_copy[$argSplit[0]][($i - 1)]) && $v[0] != '[') {
153 // Using "[]" around a parameter makes it optional
154 echo 'ERROR: Option "' . $argSplit[0] . '" requires a value ("' . $v . '") on position ' . $i . LF;
155 die;
156 }
157 }
158 }
159 $ii++;
160 if (isset($cli_args_copy[$argSplit[0]][$ii - 1])) {
161 echo 'ERROR: Option "' . $argSplit[0] . '" does not support a value on position ' . $ii . LF;
162 die;
163 }
164 unset($cli_args_copy[$argSplit[0]]);
165 }
166 }
167 if (!empty($cli_args_copy)) {
168 echo wordwrap('ERROR: Option ' . implode(',', array_keys($cli_args_copy)) . ' was unknown to this script!' . LF . '(Options are: ' . implode(', ', $allOptions) . ')' . LF);
169 die;
170 }
171 }
172
173 /**
174 * Set environment array to $cli_args
175 *
176 * @param array $argv Configuration options
177 * @return void
178 */
179 public function cli_setArguments(array $argv = array()) {
180 $this->cli_args = $this->cli_getArgIndex($argv);
181 }
182
183 /**
184 * Asks stdin for keyboard input and returns the line (after enter is pressed)
185 *
186 * @return string
187 */
188 public function cli_keyboardInput() {
189 // Have to open the stdin stream only ONCE! otherwise I cannot read multiple lines from it... :
190 if (!$this->stdin) {
191 $this->stdin = fopen('php://stdin', 'r');
192 }
193 while (FALSE == ($line = fgets($this->stdin, 1000))) {
194
195 }
196 return trim($line);
197 }
198
199 /**
200 * Asks for Yes/No from shell and returns TRUE if "y" or "yes" is found as input.
201 *
202 * @param string $msg String to ask before...
203 * @return bool TRUE if "y" or "yes" is the input (case insensitive)
204 */
205 public function cli_keyboardInput_yes($msg = '') {
206 // ONLY makes sense to echo it out since we are awaiting keyboard input - that cannot be silenced
207 echo $msg . ' (Yes/No + return): ';
208 return \TYPO3\CMS\Core\Utility\GeneralUtility::inList('y,yes', strtolower($this->cli_keyboardInput()));
209 }
210
211 /**
212 * Echos strings to shell, but respective silent-modes
213 *
214 * @param string $string The string
215 * @param bool $force If string should be written even if -s is set (-ss will subdue it!)
216 * @return bool Returns TRUE if string was outputted.
217 */
218 public function cli_echo($string = '', $force = FALSE) {
219 if (isset($this->cli_args['-ss'])) {
220
221 } elseif (isset($this->cli_args['-s']) || isset($this->cli_args['--silent'])) {
222 if ($force) {
223 echo $string;
224 return TRUE;
225 }
226 } else {
227 echo $string;
228 return TRUE;
229 }
230 return FALSE;
231 }
232
233 /**
234 * Prints help-output from ->cli_help array
235 *
236 * @return void
237 */
238 public function cli_help() {
239 foreach ($this->cli_help as $key => $value) {
240 $this->cli_echo(strtoupper($key) . ':
241 ');
242 switch ($key) {
243 case 'synopsis':
244 $optStr = '';
245 foreach ($this->cli_options as $v) {
246 $optStr .= ' [' . $v[0] . ']';
247 }
248 $this->cli_echo($this->cli_indent(str_replace('###OPTIONS###', trim($optStr), $value), 4) . '
249
250 ');
251 break;
252 case 'options':
253 $this->cli_echo($this->cli_indent($value, 4) . LF);
254 $maxLen = 0;
255 foreach ($this->cli_options as $v) {
256 if (strlen($v[0]) > $maxLen) {
257 $maxLen = strlen($v[0]);
258 }
259 }
260 foreach ($this->cli_options as $v) {
261 $this->cli_echo($v[0] . substr($this->cli_indent(rtrim($v[1] . LF . $v[2]), $maxLen + 4), strlen($v[0])) . LF);
262 }
263 $this->cli_echo(LF);
264 break;
265 default:
266 $this->cli_echo($this->cli_indent($value, 4) . '
267
268 ');
269 }
270 }
271 }
272
273 /**
274 * Indentation function for 75 char wide lines.
275 *
276 * @param string $str String to break and indent.
277 * @param int $indent Number of space chars to indent.
278 * @return string Result
279 */
280 public function cli_indent($str, $indent) {
281 $lines = explode(LF, wordwrap($str, 75 - $indent));
282 $indentStr = str_pad('', $indent, ' ');
283 foreach ($lines as $k => $v) {
284 $lines[$k] = $indentStr . $lines[$k];
285 }
286 return implode(LF, $lines);
287 }
288
289 }