TYPO3 CMS  TYPO3_8-7
CommandLineController.php
Go to the documentation of this file.
1 <?php
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 
18 
24 {
30  public $cli_args = [];
31 
35  public $cli_options = [
36  ['-s', 'Silent operation, will only output errors and important messages.'],
37  ['--silent', 'Same as -s'],
38  ['-ss', 'Super silent, will not even output errors or important messages.']
39  ];
40 
44  public $cli_help = [
45  'name' => 'CLI base class (overwrite this...)',
46  'synopsis' => '###OPTIONS###',
47  'description' => 'Class with basic functionality for CLI scripts (overwrite this...)',
48  'examples' => 'Give examples...',
49  'options' => '',
50  'license' => 'GNU GPL - free software!',
51  'author' => '[Author name]'
52  ];
53 
57  public $stdin = null;
58 
65  public function __construct()
66  {
68  // Loads the cli_args array with command line arguments
69  $this->cli_setArguments($_SERVER['argv']);
70  }
71 
80  public function cli_getArgArray($option, $argv)
81  {
82  while (count($argv) && (string)$argv[0] !== (string)$option) {
83  array_shift($argv);
84  }
85  if ((string)$argv[0] === (string)$option) {
86  array_shift($argv);
87  return !empty($argv) ? $argv : [''];
88  }
89  }
90 
97  public function cli_isArg($option)
98  {
99  return isset($this->cli_args[$option]);
100  }
101 
109  public function cli_argValue($option, $idx = 0)
110  {
111  return is_array($this->cli_args[$option]) ? $this->cli_args[$option][$idx] : '';
112  }
113 
122  public function cli_getArgIndex(array $argv = [])
123  {
124  $cli_options = [];
125  $index = '_DEFAULT';
126  foreach ($argv as $token) {
127  // Options starting with a number is invalid - they could be negative values!
128  if ($token[0] === '-' && !\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($token[1])) {
129  list($index, $opt) = explode('=', $token, 2);
130  if (isset($cli_options[$index])) {
131  echo 'ERROR: Option ' . $index . ' was used twice!' . LF;
132  die;
133  }
134  $cli_options[$index] = [];
135  if (isset($opt)) {
136  $cli_options[$index][] = $opt;
137  }
138  } else {
139  $cli_options[$index][] = $token;
140  }
141  }
142  return $cli_options;
143  }
144 
149  public function cli_validateArgs()
150  {
151  $cli_args_copy = $this->cli_args;
152  unset($cli_args_copy['_DEFAULT']);
153  $allOptions = [];
154  foreach ($this->cli_options as $cfg) {
155  $allOptions[] = $cfg[0];
156  $argSplit = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(' ', $cfg[0], true);
157  if (isset($cli_args_copy[$argSplit[0]])) {
158  $ii = 0;
159  foreach ($argSplit as $i => $v) {
160  $ii = $i;
161  if ($i > 0) {
162  if (!isset($cli_args_copy[$argSplit[0]][$i - 1]) && $v[0] !== '[') {
163  // Using "[]" around a parameter makes it optional
164  echo 'ERROR: Option "' . $argSplit[0] . '" requires a value ("' . $v . '") on position ' . $i . LF;
165  die;
166  }
167  }
168  }
169  $ii++;
170  if (isset($cli_args_copy[$argSplit[0]][$ii - 1])) {
171  echo 'ERROR: Option "' . $argSplit[0] . '" does not support a value on position ' . $ii . LF;
172  die;
173  }
174  unset($cli_args_copy[$argSplit[0]]);
175  }
176  }
177  if (!empty($cli_args_copy)) {
178  echo wordwrap('ERROR: Option ' . implode(',', array_keys($cli_args_copy)) . ' was unknown to this script!' . LF . '(Options are: ' . implode(', ', $allOptions) . ')' . LF);
179  die;
180  }
181  }
182 
188  public function cli_setArguments(array $argv = [])
189  {
190  $this->cli_args = $this->cli_getArgIndex($argv);
191  }
192 
198  public function cli_keyboardInput()
199  {
200  // Have to open the stdin stream only ONCE! otherwise I cannot read multiple lines from it... :
201  if (!$this->stdin) {
202  $this->stdin = fopen('php://stdin', 'r');
203  }
204  while (false == ($line = fgets($this->stdin, 1000))) {
205  }
206  return trim($line);
207  }
208 
215  public function cli_keyboardInput_yes($msg = '')
216  {
217  // ONLY makes sense to echo it out since we are awaiting keyboard input - that cannot be silenced
218  echo $msg . ' (Yes/No + return): ';
219  $input = strtolower($this->cli_keyboardInput());
220  return $input === 'y' || $input === 'yes';
221  }
222 
230  public function cli_echo($string = '', $force = false)
231  {
232  if (isset($this->cli_args['-ss'])) {
233  } elseif (isset($this->cli_args['-s']) || isset($this->cli_args['--silent'])) {
234  if ($force) {
235  echo $string;
236  return true;
237  }
238  } else {
239  echo $string;
240  return true;
241  }
242  return false;
243  }
244 
248  public function cli_help()
249  {
250  foreach ($this->cli_help as $key => $value) {
251  $this->cli_echo(strtoupper($key) . ':
252 ');
253  switch ($key) {
254  case 'synopsis':
255  $optStr = '';
256  foreach ($this->cli_options as $v) {
257  $optStr .= ' [' . $v[0] . ']';
258  }
259  $this->cli_echo($this->cli_indent(str_replace('###OPTIONS###', trim($optStr), $value), 4) . '
260 
261 ');
262  break;
263  case 'options':
264  $this->cli_echo($this->cli_indent($value, 4) . LF);
265  $maxLen = 0;
266  foreach ($this->cli_options as $v) {
267  if (strlen($v[0]) > $maxLen) {
268  $maxLen = strlen($v[0]);
269  }
270  }
271  foreach ($this->cli_options as $v) {
272  $this->cli_echo($v[0] . substr($this->cli_indent(rtrim($v[1] . LF . $v[2]), $maxLen + 4), strlen($v[0])) . LF);
273  }
274  $this->cli_echo(LF);
275  break;
276  default:
277  $this->cli_echo($this->cli_indent($value, 4) . '
278 
279 ');
280  }
281  }
282  }
283 
291  public function cli_indent($str, $indent)
292  {
293  $lines = explode(LF, wordwrap($str, 75 - $indent));
294  $indentStr = str_pad('', $indent, ' ');
295  foreach ($lines as $k => $v) {
296  $lines[$k] = $indentStr . $lines[$k];
297  }
298  return implode(LF, $lines);
299  }
300 }
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)