TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
CommandLineController.php
Go to the documentation of this file.
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 
21 {
27  public $cli_args = [];
28 
32  public $cli_options = [
33  ['-s', 'Silent operation, will only output errors and important messages.'],
34  ['--silent', 'Same as -s'],
35  ['-ss', 'Super silent, will not even output errors or important messages.']
36  ];
37 
41  public $cli_help = [
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 
54  public $stdin = null;
55 
62  public function __construct()
63  {
64  // Loads the cli_args array with command line arguments
65  $this->cli_setArguments($_SERVER['argv']);
66  }
67 
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 : [''];
84  }
85  }
86 
93  public function cli_isArg($option)
94  {
95  return isset($this->cli_args[$option]);
96  }
97 
105  public function cli_argValue($option, $idx = 0)
106  {
107  return is_array($this->cli_args[$option]) ? $this->cli_args[$option][$idx] : '';
108  }
109 
118  public function cli_getArgIndex(array $argv = [])
119  {
120  $cli_options = [];
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] = [];
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 
146  public function cli_validateArgs()
147  {
148  $cli_args_copy = $this->cli_args;
149  unset($cli_args_copy['_DEFAULT']);
150  $allOptions = [];
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 
185  public function cli_setArguments(array $argv = [])
186  {
187  $this->cli_args = $this->cli_getArgIndex($argv);
188  }
189 
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 
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  $input = strtolower($this->cli_keyboardInput());
217  return $input === 'y' || $input === 'yes';
218  }
219 
227  public function cli_echo($string = '', $force = false)
228  {
229  if (isset($this->cli_args['-ss'])) {
230  } elseif (isset($this->cli_args['-s']) || isset($this->cli_args['--silent'])) {
231  if ($force) {
232  echo $string;
233  return true;
234  }
235  } else {
236  echo $string;
237  return true;
238  }
239  return false;
240  }
241 
247  public function cli_help()
248  {
249  foreach ($this->cli_help as $key => $value) {
250  $this->cli_echo(strtoupper($key) . ':
251 ');
252  switch ($key) {
253  case 'synopsis':
254  $optStr = '';
255  foreach ($this->cli_options as $v) {
256  $optStr .= ' [' . $v[0] . ']';
257  }
258  $this->cli_echo($this->cli_indent(str_replace('###OPTIONS###', trim($optStr), $value), 4) . '
259 
260 ');
261  break;
262  case 'options':
263  $this->cli_echo($this->cli_indent($value, 4) . LF);
264  $maxLen = 0;
265  foreach ($this->cli_options as $v) {
266  if (strlen($v[0]) > $maxLen) {
267  $maxLen = strlen($v[0]);
268  }
269  }
270  foreach ($this->cli_options as $v) {
271  $this->cli_echo($v[0] . substr($this->cli_indent(rtrim($v[1] . LF . $v[2]), $maxLen + 4), strlen($v[0])) . LF);
272  }
273  $this->cli_echo(LF);
274  break;
275  default:
276  $this->cli_echo($this->cli_indent($value, 4) . '
277 
278 ');
279  }
280  }
281  }
282 
290  public function cli_indent($str, $indent)
291  {
292  $lines = explode(LF, wordwrap($str, 75 - $indent));
293  $indentStr = str_pad('', $indent, ' ');
294  foreach ($lines as $k => $v) {
295  $lines[$k] = $indentStr . $lines[$k];
296  }
297  return implode(LF, $lines);
298  }
299 }
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)