[BUGFIX] Executing Extbase commands as scheduler task
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Mvc / Cli / ConsoleOutput.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Mvc\Cli;
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 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
18 use Symfony\Component\Console\Helper\FormatterHelper;
19 use Symfony\Component\Console\Helper\HelperSet;
20 use Symfony\Component\Console\Helper\ProgressBar;
21 use Symfony\Component\Console\Helper\QuestionHelper;
22 use Symfony\Component\Console\Helper\Table;
23 use Symfony\Component\Console\Input\ArgvInput;
24 use Symfony\Component\Console\Output\ConsoleOutput as SymfonyConsoleOutput;
25 use Symfony\Component\Console\Question\ChoiceQuestion;
26 use Symfony\Component\Console\Question\ConfirmationQuestion;
27 use Symfony\Component\Console\Question\Question;
28
29 /**
30 * A wrapper for Symfony ConsoleOutput and related helpers
31 */
32 class ConsoleOutput
33 {
34 /**
35 * @var ArgvInput
36 */
37 protected $input;
38
39 /**
40 * @var SymfonyConsoleOutput
41 */
42 protected $output;
43
44 /**
45 * @var QuestionHelper
46 */
47 protected $questionHelper;
48
49 /**
50 * @var ProgressBar
51 */
52 protected $progressBar;
53
54 /**
55 * @var Table
56 */
57 protected $table;
58
59 /**
60 * Creates and initializes the Symfony I/O instances
61 *
62 * @return void
63 */
64 public function __construct()
65 {
66 $this->output = new SymfonyConsoleOutput();
67 $this->output->getFormatter()->setStyle('b', new OutputFormatterStyle(null, null, array('bold')));
68 $this->output->getFormatter()->setStyle('i', new OutputFormatterStyle('black', 'white'));
69 $this->output->getFormatter()->setStyle('u', new OutputFormatterStyle(null, null, array('underscore')));
70 $this->output->getFormatter()->setStyle('em', new OutputFormatterStyle(null, null, array('reverse')));
71 $this->output->getFormatter()->setStyle('strike', new OutputFormatterStyle(null, null, array('conceal')));
72 }
73
74 /**
75 * Returns the desired maximum line length for console output.
76 *
77 * @return int
78 */
79 public function getMaximumLineLength()
80 {
81 return 79;
82 }
83
84 /**
85 * Outputs specified text to the console window
86 * You can specify arguments that will be passed to the text via sprintf
87 * @see http://www.php.net/sprintf
88 *
89 * @param string $text Text to output
90 * @param array $arguments Optional arguments to use for sprintf
91 * @return void
92 */
93 public function output($text, array $arguments = array())
94 {
95 if ($arguments !== array()) {
96 $text = vsprintf($text, $arguments);
97 }
98 $this->output->write($text);
99 }
100
101 /**
102 * Outputs specified text to the console window and appends a line break
103 *
104 * @param string $text Text to output
105 * @param array $arguments Optional arguments to use for sprintf
106 * @return void
107 * @see output()
108 * @see outputLines()
109 */
110 public function outputLine($text = '', array $arguments = array())
111 {
112 $this->output($text . PHP_EOL, $arguments);
113 }
114
115 /**
116 * Formats the given text to fit into the maximum line length and outputs it to the
117 * console window
118 *
119 * @param string $text Text to output
120 * @param array $arguments Optional arguments to use for sprintf
121 * @param int $leftPadding The number of spaces to use for indentation
122 * @return void
123 * @see outputLine()
124 */
125 public function outputFormatted($text = '', array $arguments = array(), $leftPadding = 0)
126 {
127 $lines = explode(PHP_EOL, $text);
128 foreach ($lines as $line) {
129 $formattedText = str_repeat(' ', $leftPadding) . wordwrap($line, $this->getMaximumLineLength() - $leftPadding, PHP_EOL . str_repeat(' ', $leftPadding), true);
130 $this->outputLine($formattedText, $arguments);
131 }
132 }
133
134 /**
135 * Renders a table like output of the given $rows
136 *
137 * @param array $rows
138 * @param array $headers
139 */
140 public function outputTable($rows, $headers = null)
141 {
142 $table = $this->getTable();
143 if ($headers !== null) {
144 $table->setHeaders($headers);
145 }
146 $table->setRows($rows);
147 $table->render();
148 }
149
150 /**
151 * Asks the user to select a value
152 *
153 * @param string|array $question The question to ask. If an array each array item is turned into one line of a multi-line question
154 * @param array $choices List of choices to pick from
155 * @param bool $default The default answer if the user enters nothing
156 * @param bool $multiSelect If TRUE the result will be an array with the selected options. Multiple options can be given separated by commas
157 * @param bool|int $attempts Max number of times to ask before giving up (false by default, which means infinite)
158 * @return int|string|array The selected value or values (the key of the choices array)
159 * @throws \InvalidArgumentException
160 */
161 public function select($question, $choices, $default = null, $multiSelect = false, $attempts = false)
162 {
163 $question = (new ChoiceQuestion($question, $choices, $default))
164 ->setMultiselect($multiSelect)
165 ->setMaxAttempts($attempts)
166 ->setErrorMessage('Value "%s" is invalid');
167
168 return $this->getQuestionHelper()->ask($this->getInput(), $this->output, $question);
169 }
170
171 /**
172 * Asks a question to the user
173 *
174 * @param string|array $question The question to ask. If an array each array item is turned into one line of a multi-line question
175 * @param string $default The default answer if none is given by the user
176 * @param array $autocomplete List of values to autocomplete. This only works if "stty" is installed
177 * @return string The user answer
178 * @throws \RuntimeException If there is no data to read in the input stream
179 */
180 public function ask($question, $default = null, array $autocomplete = null)
181 {
182 $question = (new Question($question, $default))
183 ->setAutocompleterValues($autocomplete);
184
185 return $this->getQuestionHelper()->ask($this->getInput(), $this->output, $question);
186 }
187
188 /**
189 * Asks a confirmation to the user.
190 *
191 * The question will be asked until the user answers by nothing, yes, or no.
192 *
193 * @param string|array $question The question to ask. If an array each array item is turned into one line of a multi-line question
194 * @param bool $default The default answer if the user enters nothing
195 * @return bool true if the user has confirmed, false otherwise
196 */
197 public function askConfirmation($question, $default = true)
198 {
199 $question = new ConfirmationQuestion($question, $default);
200
201 return $this->getQuestionHelper()->ask($this->getInput(), $this->output, $question);
202 }
203
204 /**
205 * Asks a question to the user, the response is hidden
206 *
207 * @param string|array $question The question. If an array each array item is turned into one line of a multi-line question
208 * @param bool $fallback In case the response can not be hidden, whether to fallback on non-hidden question or not
209 * @return string The answer
210 * @throws \RuntimeException In case the fallback is deactivated and the response can not be hidden
211 */
212 public function askHiddenResponse($question, $fallback = true)
213 {
214 $question = (new Question($question))
215 ->setHidden(true)
216 ->setHiddenFallback($fallback);
217
218 return $this->getQuestionHelper()->ask($this->getInput(), $this->output, $question);
219 }
220
221 /**
222 * Asks for a value and validates the response
223 *
224 * The validator receives the data to validate. It must return the
225 * validated data when the data is valid and throw an exception
226 * otherwise.
227 *
228 * @param string|array $question The question to ask. If an array each array item is turned into one line of a multi-line question
229 * @param callable $validator A PHP callback that gets a value and is expected to return the (transformed) value or throw an exception if it wasn't valid
230 * @param int|bool $attempts Max number of times to ask before giving up (false by default, which means infinite)
231 * @param string $default The default answer if none is given by the user
232 * @param array $autocomplete List of values to autocomplete. This only works if "stty" is installed
233 * @return mixed
234 * @throws \Exception When any of the validators return an error
235 */
236 public function askAndValidate($question, $validator, $attempts = false, $default = null, array $autocomplete = null)
237 {
238 $question = (new Question($question, $default))
239 ->setValidator($validator)
240 ->setMaxAttempts($attempts)
241 ->setAutocompleterValues($autocomplete);
242
243 return $this->getQuestionHelper()->ask($this->getInput(), $this->output, $question);
244 }
245
246 /**
247 * Asks for a value, hide and validates the response
248 *
249 * The validator receives the data to validate. It must return the
250 * validated data when the data is valid and throw an exception
251 * otherwise.
252 *
253 * @param string|array $question The question to ask. If an array each array item is turned into one line of a multi-line question
254 * @param callable $validator A PHP callback that gets a value and is expected to return the (transformed) value or throw an exception if it wasn't valid
255 * @param int|bool $attempts Max number of times to ask before giving up (false by default, which means infinite)
256 * @param bool $fallback In case the response can not be hidden, whether to fallback on non-hidden question or not
257 * @return string The response
258 * @throws \Exception When any of the validators return an error
259 * @throws \RuntimeException In case the fallback is deactivated and the response can not be hidden
260 */
261 public function askHiddenResponseAndValidate($question, $validator, $attempts = false, $fallback = true)
262 {
263 $question = (new Question($question))
264 ->setValidator($validator)
265 ->setMaxAttempts($attempts)
266 ->setHidden(true)
267 ->setHiddenFallback($fallback);
268
269 return $this->getQuestionHelper()->ask($this->getInput(), $this->output, $question);
270 }
271
272 /**
273 * Starts the progress output
274 *
275 * @param int $max Maximum steps. If NULL an indeterminate progress bar is rendered
276 * @return void
277 */
278 public function progressStart($max = null)
279 {
280 $this->getProgressBar()->start($max);
281 }
282
283 /**
284 * Advances the progress output X steps
285 *
286 * @param int $step Number of steps to advance
287 * @return void
288 * @throws \LogicException
289 */
290 public function progressAdvance($step = 1)
291 {
292 $this->getProgressBar()->advance($step);
293 }
294
295 /**
296 * Sets the current progress
297 *
298 * @param int $current The current progress
299 * @return void
300 * @throws \LogicException
301 */
302 public function progressSet($current)
303 {
304 $this->getProgressBar()->setProgress($current);
305 }
306
307 /**
308 * Finishes the progress output
309 *
310 * @return void
311 */
312 public function progressFinish()
313 {
314 $this->getProgressBar()->finish();
315 }
316
317 /**
318 * @return ArgvInput
319 * @throws \RuntimeException
320 */
321 protected function getInput() {
322 if ($this->input === null) {
323 if (!isset($_SERVER['argv'])) {
324 throw new \RuntimeException('Cannot initialize ArgvInput object without CLI context.', 1456914444);
325 }
326 $this->input = new ArgvInput();
327 }
328
329 return $this->input;
330 }
331
332 /**
333 * Returns or initializes the symfony/console QuestionHelper
334 *
335 * @return QuestionHelper
336 */
337 protected function getQuestionHelper()
338 {
339 if ($this->questionHelper === null) {
340 $this->questionHelper = new QuestionHelper();
341 $helperSet = new HelperSet(array(new FormatterHelper()));
342 $this->questionHelper->setHelperSet($helperSet);
343 }
344 return $this->questionHelper;
345 }
346
347 /**
348 * Returns or initializes the symfony/console ProgressBar
349 *
350 * @return ProgressBar
351 */
352 protected function getProgressBar()
353 {
354 if ($this->progressBar === null) {
355 $this->progressBar = new ProgressBar($this->output);
356 }
357 return $this->progressBar;
358 }
359
360 /**
361 * Returns or initializes the symfony/console Table
362 *
363 * @return Table
364 */
365 protected function getTable()
366 {
367 if ($this->table === null) {
368 $this->table = new Table($this->output);
369 }
370 return $this->table;
371 }
372 }