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