10 use Symfony\Component\Console\Exception\RuntimeException;
11 use Symfony\Component\Console\Formatter\OutputFormatter;
12 use Symfony\Component\Console\Helper\Helper;
13 use Symfony\Component\Console\Helper\ProgressBar;
14 use Symfony\Component\Console\Helper\SymfonyQuestionHelper;
15 use Symfony\Component\Console\Helper\Table;
16 use Symfony\Component\Console\Input\InputInterface;
17 use Symfony\Component\Console\Output\BufferedOutput;
18 use Symfony\Component\Console\Output\OutputInterface;
19 use Symfony\Component\Console\Question\ChoiceQuestion;
20 use Symfony\Component\Console\Question\ConfirmationQuestion;
21 use Symfony\Component\Console\Question\Question;
22 use Symfony\Component\Console\Style\OutputStyle;
23 use Symfony\Component\Console\Terminal;
48 private $questionHelper;
69 private $bufferedOutput;
79 $this->input = $input;
80 $this->bufferedOutput =
new BufferedOutput(
$output->getVerbosity(),
false, clone
$output->getFormatter());
82 $currentLength = $this->getTerminalWidth() - (int)(DIRECTORY_SEPARATOR ===
'\\');
83 $this->lineLength = min($currentLength, self::MAX_LINE_LENGTH);
100 string $style =
null,
102 bool $padding =
false 104 $messages = is_array($messages) ? array_values($messages) : [$messages];
105 $this->autoPrependBlock();
115 $this->autoPrependBlock();
116 $bar = str_repeat(
'=', Helper::strlenWithoutDecoration($this->getFormatter(),
$message));
118 sprintf(
' <options=bold>%s</>', OutputFormatter::escapeTrailingBackslash(
$message)),
119 sprintf(
' <options=bold>%s</>', $bar),
129 $this->autoPrependBlock();
130 $bar = str_repeat(
'-', Helper::strlenWithoutDecoration($this->getFormatter(),
$message));
132 sprintf(
' <fg=white>%s</>', OutputFormatter::escapeTrailingBackslash(
$message)),
133 sprintf(
' <fg=white>%s</>', $bar),
143 $this->autoPrependText();
144 $elements = array_map(
function (
$element) {
157 $this->autoPrependText();
159 foreach ($messages as $singleMessage) {
160 $this->
writeln(sprintf(
' %s', $singleMessage));
181 $this->
block(
$message,
'SUCCESS',
'fg=black;bg=green',
' ', $padding);
189 $this->
block(
$message,
'ERROR',
'fg=white;bg=red',
' ', $padding);
197 $this->
block(
$message,
'WARNING',
'fg=black;bg=yellow',
' ', $padding);
213 $this->
block(
$message,
'CAUTION',
'fg=black;bg=yellow',
' ! ', $padding);
219 public function table(array $headers, array $rows)
221 $style = clone Table::getStyleDefinition(
'symfony-style-guide');
222 $style->setCellHeaderFormat(
'<info>%s</info>');
224 $table =
new Table($this);
225 $table->setHeaders($headers);
237 public function ask($question, $default =
null, $validator =
null, $maxAttempts =
null)
239 $question =
new Question($question, $default);
240 $question->setValidator($validator);
241 $question->setMaxAttempts($maxAttempts);
252 $question =
new Question($question);
254 $question->setHidden(
true);
255 $question->setValidator($validator);
263 public function confirm($question, $default =
true)
265 return $this->
askQuestion(
new ConfirmationQuestion($question, $default));
271 public function choice($question, array $choices, $default =
null)
273 if (
null !== $default) {
274 $values = array_flip($choices);
278 return $this->
askQuestion(
new ChoiceQuestion($question, $choices, $default));
287 $this->progressBar->start();
297 $this->getProgressBar()->advance($step);
306 $this->getProgressBar()->finish();
308 $this->progressBar =
null;
316 $progressBar = parent::createProgressBar($max);
317 $progressBar->setEmptyBarCharacter(
' ');
318 $progressBar->setProgressCharacter(
'>');
319 $progressBar->setBarCharacter(
'=');
333 if ($this->input->isInteractive()) {
334 $this->autoPrependBlock();
337 if (!$this->questionHelper) {
338 $this->questionHelper =
new SymfonyQuestionHelper();
341 $answer = $this->questionHelper->ask($this->input, $this, $question);
343 if ($this->input->isInteractive()) {
345 $this->bufferedOutput->write(PHP_EOL);
366 string $default =
null,
367 callable $validator =
null,
368 int $maxAttempts =
null,
369 bool $comment =
null,
370 string $commentFormat =
'Argument [%s] set to: %s' 373 if ($this->input->getArgument($argument) ===
null) {
374 $this->input->setArgument($argument, $this->
ask($question, $default, $validator, $maxAttempts));
376 $argumentValue = $this->input->getArgument($argument);
377 $validated = (is_callable($validator) ? $validator($argumentValue) : $argumentValue);
378 if ((
bool)($comment ?? $this->isDebug())) {
379 $this->
comment(sprintf($commentFormat, $argument, $validated));
382 $this->
error(
'Validation Error: ' . $e->getMessage());
410 string $default =
null,
411 callable $validator =
null,
412 int $maxAttempts =
null,
413 bool $comment =
null,
414 string $commentFormat =
'Option [%s] set to: %s' 417 if (
null === $this->input->getOption(
$option)) {
418 $this->input->setOption(
$option, $this->
ask($question, $default, $validator, $maxAttempts));
422 if ((
bool)($comment ?? $this->isDebug())) {
426 $this->
error(
'Validation Error: ' . $e->getMessage());
444 parent::writeln($messages,
$type);
445 $this->bufferedOutput->writeln($this->reduceBuffer($messages),
$type);
451 public function write($messages, $newline =
false,
$type = self::OUTPUT_NORMAL)
453 parent::write($messages, $newline,
$type);
454 $this->bufferedOutput->write($this->reduceBuffer($messages), $newline,
$type);
463 $this->bufferedOutput->write(str_repeat(PHP_EOL,
$count));
472 private function getProgressBar()
474 if (!$this->progressBar) {
475 throw new RuntimeException(
'The ProgressBar is not started.');
478 return $this->progressBar;
484 private function getTerminalWidth()
486 $terminal =
new Terminal();
487 $width = $terminal->getWidth();
497 private function autoPrependBlock()
499 $chars = substr($this->bufferedOutput->fetch(), -2);
500 if (!isset($chars[0])) {
504 $this->
newLine(2 - substr_count($chars, PHP_EOL));
512 private function autoPrependText()
514 $fetched = $this->bufferedOutput->fetch();
516 if (PHP_EOL !== substr($fetched, -1)) {
525 private function reduceBuffer($messages)
529 return array_map(
function (
$value) {
530 return substr(
$value, -4);
531 }, array_merge([$this->bufferedOutput->fetch()], (array)$messages));
544 private function createBlock(
547 string $style =
null,
549 bool $padding =
false 552 $prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(),
$prefix);
553 if (
null !==
$type) {
555 $indentLength = strlen(
$type);
556 $lineIndentation = str_repeat(
' ', $indentLength);
558 $lines = $this->getBlockLines($messages, $prefixLength, $indentLength);
560 if ($padding && $this->isDecorated()) {
562 array_unshift($lines,
'');
565 foreach ($lines as
$i => &$line) {
566 if (
null !==
$type) {
567 $line = $firstLineIndex ===
$i ?
$type . $line : $lineIndentation . $line;
570 $multiplier = $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line);
571 $line .= str_repeat(
' ', $multiplier);
573 $line = sprintf(
'<%s>%s</>', $style, $line);
588 private function getBlockLines(
594 foreach ($messages as $key =>
$message) {
596 $wordwrap = wordwrap(
$message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL,
true);
597 $lines[] = explode(PHP_EOL, $wordwrap);
598 if (count($messages) > 1 && $key < count($messages) - 1) {
602 $lines = array_merge(...$lines);
__construct(InputInterface $input, OutputInterface $output)
askForMissingOption(string $option, string $question, string $default=null, callable $validator=null, int $maxAttempts=null, bool $comment=null, string $commentFormat='Option [%s] set to:%s')
askForMissingArgument(string $argument, string $question, string $default=null, callable $validator=null, int $maxAttempts=null, bool $comment=null, string $commentFormat='Argument [%s] set to:%s')
confirm($question, $default=true)
write($messages, $newline=false, $type=self::OUTPUT_NORMAL)
comment($message, $padding=false)
writeln($messages, $type=self::OUTPUT_NORMAL)
ask($question, $default=null, $validator=null, $maxAttempts=null)
caution($message, $padding=true)
success($message, $padding=true)
createProgressBar($max=0)
note($message, $padding=false)
askHidden($question, $validator=null)
block( $messages, string $type=null, string $style=null, string $prefix=' ', bool $padding=false)
askQuestion(Question $question)
warning($message, $padding=true)
choice($question, array $choices, $default=null)
table(array $headers, array $rows)
error($message, $padding=true)