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