[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/vendor/symfony/console/Style/ -> SymfonyStyle.php (source)

   1  <?php
   2  
   3  /*
   4   * This file is part of the Symfony package.
   5   *
   6   * (c) Fabien Potencier <[email protected]>
   7   *
   8   * For the full copyright and license information, please view the LICENSE
   9   * file that was distributed with this source code.
  10   */
  11  
  12  namespace Symfony\Component\Console\Style;
  13  
  14  use Symfony\Component\Console\Exception\InvalidArgumentException;
  15  use Symfony\Component\Console\Exception\RuntimeException;
  16  use Symfony\Component\Console\Formatter\OutputFormatter;
  17  use Symfony\Component\Console\Helper\Helper;
  18  use Symfony\Component\Console\Helper\ProgressBar;
  19  use Symfony\Component\Console\Helper\SymfonyQuestionHelper;
  20  use Symfony\Component\Console\Helper\Table;
  21  use Symfony\Component\Console\Helper\TableCell;
  22  use Symfony\Component\Console\Helper\TableSeparator;
  23  use Symfony\Component\Console\Input\InputInterface;
  24  use Symfony\Component\Console\Output\ConsoleOutputInterface;
  25  use Symfony\Component\Console\Output\OutputInterface;
  26  use Symfony\Component\Console\Output\TrimmedBufferOutput;
  27  use Symfony\Component\Console\Question\ChoiceQuestion;
  28  use Symfony\Component\Console\Question\ConfirmationQuestion;
  29  use Symfony\Component\Console\Question\Question;
  30  use Symfony\Component\Console\Terminal;
  31  
  32  /**
  33   * Output decorator helpers for the Symfony Style Guide.
  34   *
  35   * @author Kevin Bond <[email protected]>
  36   */
  37  class SymfonyStyle extends OutputStyle
  38  {
  39      public const MAX_LINE_LENGTH = 120;
  40  
  41      private $input;
  42      private $output;
  43      private $questionHelper;
  44      private $progressBar;
  45      private $lineLength;
  46      private $bufferedOutput;
  47  
  48      public function __construct(InputInterface $input, OutputInterface $output)
  49      {
  50          $this->input = $input;
  51          $this->bufferedOutput = new TrimmedBufferOutput(\DIRECTORY_SEPARATOR === '\\' ? 4 : 2, $output->getVerbosity(), false, clone $output->getFormatter());
  52          // Windows cmd wraps lines as soon as the terminal width is reached, whether there are following chars or not.
  53          $width = (new Terminal())->getWidth() ?: self::MAX_LINE_LENGTH;
  54          $this->lineLength = min($width - (int) (\DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);
  55  
  56          parent::__construct($this->output = $output);
  57      }
  58  
  59      /**
  60       * Formats a message as a block of text.
  61       *
  62       * @param string|array $messages The message to write in the block
  63       */
  64      public function block($messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = true)
  65      {
  66          $messages = \is_array($messages) ? array_values($messages) : [$messages];
  67  
  68          $this->autoPrependBlock();
  69          $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, $escape));
  70          $this->newLine();
  71      }
  72  
  73      /**
  74       * {@inheritdoc}
  75       */
  76      public function title(string $message)
  77      {
  78          $this->autoPrependBlock();
  79          $this->writeln([
  80              sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
  81              sprintf('<comment>%s</>', str_repeat('=', Helper::width(Helper::removeDecoration($this->getFormatter(), $message)))),
  82          ]);
  83          $this->newLine();
  84      }
  85  
  86      /**
  87       * {@inheritdoc}
  88       */
  89      public function section(string $message)
  90      {
  91          $this->autoPrependBlock();
  92          $this->writeln([
  93              sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
  94              sprintf('<comment>%s</>', str_repeat('-', Helper::width(Helper::removeDecoration($this->getFormatter(), $message)))),
  95          ]);
  96          $this->newLine();
  97      }
  98  
  99      /**
 100       * {@inheritdoc}
 101       */
 102      public function listing(array $elements)
 103      {
 104          $this->autoPrependText();
 105          $elements = array_map(function ($element) {
 106              return sprintf(' * %s', $element);
 107          }, $elements);
 108  
 109          $this->writeln($elements);
 110          $this->newLine();
 111      }
 112  
 113      /**
 114       * {@inheritdoc}
 115       */
 116      public function text($message)
 117      {
 118          $this->autoPrependText();
 119  
 120          $messages = \is_array($message) ? array_values($message) : [$message];
 121          foreach ($messages as $message) {
 122              $this->writeln(sprintf(' %s', $message));
 123          }
 124      }
 125  
 126      /**
 127       * Formats a command comment.
 128       *
 129       * @param string|array $message
 130       */
 131      public function comment($message)
 132      {
 133          $this->block($message, null, null, '<fg=default;bg=default> // </>', false, false);
 134      }
 135  
 136      /**
 137       * {@inheritdoc}
 138       */
 139      public function success($message)
 140      {
 141          $this->block($message, 'OK', 'fg=black;bg=green', ' ', true);
 142      }
 143  
 144      /**
 145       * {@inheritdoc}
 146       */
 147      public function error($message)
 148      {
 149          $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', true);
 150      }
 151  
 152      /**
 153       * {@inheritdoc}
 154       */
 155      public function warning($message)
 156      {
 157          $this->block($message, 'WARNING', 'fg=black;bg=yellow', ' ', true);
 158      }
 159  
 160      /**
 161       * {@inheritdoc}
 162       */
 163      public function note($message)
 164      {
 165          $this->block($message, 'NOTE', 'fg=yellow', ' ! ');
 166      }
 167  
 168      /**
 169       * Formats an info message.
 170       *
 171       * @param string|array $message
 172       */
 173      public function info($message)
 174      {
 175          $this->block($message, 'INFO', 'fg=green', ' ', true);
 176      }
 177  
 178      /**
 179       * {@inheritdoc}
 180       */
 181      public function caution($message)
 182      {
 183          $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', true);
 184      }
 185  
 186      /**
 187       * {@inheritdoc}
 188       */
 189      public function table(array $headers, array $rows)
 190      {
 191          $this->createTable()
 192              ->setHeaders($headers)
 193              ->setRows($rows)
 194              ->render()
 195          ;
 196  
 197          $this->newLine();
 198      }
 199  
 200      /**
 201       * Formats a horizontal table.
 202       */
 203      public function horizontalTable(array $headers, array $rows)
 204      {
 205          $this->createTable()
 206              ->setHorizontal(true)
 207              ->setHeaders($headers)
 208              ->setRows($rows)
 209              ->render()
 210          ;
 211  
 212          $this->newLine();
 213      }
 214  
 215      /**
 216       * Formats a list of key/value horizontally.
 217       *
 218       * Each row can be one of:
 219       * * 'A title'
 220       * * ['key' => 'value']
 221       * * new TableSeparator()
 222       *
 223       * @param string|array|TableSeparator ...$list
 224       */
 225      public function definitionList(...$list)
 226      {
 227          $headers = [];
 228          $row = [];
 229          foreach ($list as $value) {
 230              if ($value instanceof TableSeparator) {
 231                  $headers[] = $value;
 232                  $row[] = $value;
 233                  continue;
 234              }
 235              if (\is_string($value)) {
 236                  $headers[] = new TableCell($value, ['colspan' => 2]);
 237                  $row[] = null;
 238                  continue;
 239              }
 240              if (!\is_array($value)) {
 241                  throw new InvalidArgumentException('Value should be an array, string, or an instance of TableSeparator.');
 242              }
 243              $headers[] = key($value);
 244              $row[] = current($value);
 245          }
 246  
 247          $this->horizontalTable($headers, [$row]);
 248      }
 249  
 250      /**
 251       * {@inheritdoc}
 252       */
 253      public function ask(string $question, string $default = null, callable $validator = null)
 254      {
 255          $question = new Question($question, $default);
 256          $question->setValidator($validator);
 257  
 258          return $this->askQuestion($question);
 259      }
 260  
 261      /**
 262       * {@inheritdoc}
 263       */
 264      public function askHidden(string $question, callable $validator = null)
 265      {
 266          $question = new Question($question);
 267  
 268          $question->setHidden(true);
 269          $question->setValidator($validator);
 270  
 271          return $this->askQuestion($question);
 272      }
 273  
 274      /**
 275       * {@inheritdoc}
 276       */
 277      public function confirm(string $question, bool $default = true)
 278      {
 279          return $this->askQuestion(new ConfirmationQuestion($question, $default));
 280      }
 281  
 282      /**
 283       * {@inheritdoc}
 284       */
 285      public function choice(string $question, array $choices, $default = null)
 286      {
 287          if (null !== $default) {
 288              $values = array_flip($choices);
 289              $default = $values[$default] ?? $default;
 290          }
 291  
 292          return $this->askQuestion(new ChoiceQuestion($question, $choices, $default));
 293      }
 294  
 295      /**
 296       * {@inheritdoc}
 297       */
 298      public function progressStart(int $max = 0)
 299      {
 300          $this->progressBar = $this->createProgressBar($max);
 301          $this->progressBar->start();
 302      }
 303  
 304      /**
 305       * {@inheritdoc}
 306       */
 307      public function progressAdvance(int $step = 1)
 308      {
 309          $this->getProgressBar()->advance($step);
 310      }
 311  
 312      /**
 313       * {@inheritdoc}
 314       */
 315      public function progressFinish()
 316      {
 317          $this->getProgressBar()->finish();
 318          $this->newLine(2);
 319          $this->progressBar = null;
 320      }
 321  
 322      /**
 323       * {@inheritdoc}
 324       */
 325      public function createProgressBar(int $max = 0)
 326      {
 327          $progressBar = parent::createProgressBar($max);
 328  
 329          if ('\\' !== \DIRECTORY_SEPARATOR || 'Hyper' === getenv('TERM_PROGRAM')) {
 330              $progressBar->setEmptyBarCharacter('â–‘'); // light shade character \u2591
 331              $progressBar->setProgressCharacter('');
 332              $progressBar->setBarCharacter('â–“'); // dark shade character \u2593
 333          }
 334  
 335          return $progressBar;
 336      }
 337  
 338      /**
 339       * @see ProgressBar::iterate()
 340       */
 341      public function progressIterate(iterable $iterable, int $max = null): iterable
 342      {
 343          yield from $this->createProgressBar()->iterate($iterable, $max);
 344  
 345          $this->newLine(2);
 346      }
 347  
 348      /**
 349       * @return mixed
 350       */
 351      public function askQuestion(Question $question)
 352      {
 353          if ($this->input->isInteractive()) {
 354              $this->autoPrependBlock();
 355          }
 356  
 357          if (!$this->questionHelper) {
 358              $this->questionHelper = new SymfonyQuestionHelper();
 359          }
 360  
 361          $answer = $this->questionHelper->ask($this->input, $this, $question);
 362  
 363          if ($this->input->isInteractive()) {
 364              $this->newLine();
 365              $this->bufferedOutput->write("\n");
 366          }
 367  
 368          return $answer;
 369      }
 370  
 371      /**
 372       * {@inheritdoc}
 373       */
 374      public function writeln($messages, int $type = self::OUTPUT_NORMAL)
 375      {
 376          if (!is_iterable($messages)) {
 377              $messages = [$messages];
 378          }
 379  
 380          foreach ($messages as $message) {
 381              parent::writeln($message, $type);
 382              $this->writeBuffer($message, true, $type);
 383          }
 384      }
 385  
 386      /**
 387       * {@inheritdoc}
 388       */
 389      public function write($messages, bool $newline = false, int $type = self::OUTPUT_NORMAL)
 390      {
 391          if (!is_iterable($messages)) {
 392              $messages = [$messages];
 393          }
 394  
 395          foreach ($messages as $message) {
 396              parent::write($message, $newline, $type);
 397              $this->writeBuffer($message, $newline, $type);
 398          }
 399      }
 400  
 401      /**
 402       * {@inheritdoc}
 403       */
 404      public function newLine(int $count = 1)
 405      {
 406          parent::newLine($count);
 407          $this->bufferedOutput->write(str_repeat("\n", $count));
 408      }
 409  
 410      /**
 411       * Returns a new instance which makes use of stderr if available.
 412       *
 413       * @return self
 414       */
 415      public function getErrorStyle()
 416      {
 417          return new self($this->input, $this->getErrorOutput());
 418      }
 419  
 420      public function createTable(): Table
 421      {
 422          $output = $this->output instanceof ConsoleOutputInterface ? $this->output->section() : $this->output;
 423          $style = clone Table::getStyleDefinition('symfony-style-guide');
 424          $style->setCellHeaderFormat('<info>%s</info>');
 425  
 426          return (new Table($output))->setStyle($style);
 427      }
 428  
 429      private function getProgressBar(): ProgressBar
 430      {
 431          if (!$this->progressBar) {
 432              throw new RuntimeException('The ProgressBar is not started.');
 433          }
 434  
 435          return $this->progressBar;
 436      }
 437  
 438      private function autoPrependBlock(): void
 439      {
 440          $chars = substr(str_replace(\PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);
 441  
 442          if (!isset($chars[0])) {
 443              $this->newLine(); //empty history, so we should start with a new line.
 444  
 445              return;
 446          }
 447          //Prepend new line for each non LF chars (This means no blank line was output before)
 448          $this->newLine(2 - substr_count($chars, "\n"));
 449      }
 450  
 451      private function autoPrependText(): void
 452      {
 453          $fetched = $this->bufferedOutput->fetch();
 454          //Prepend new line if last char isn't EOL:
 455          if (!str_ends_with($fetched, "\n")) {
 456              $this->newLine();
 457          }
 458      }
 459  
 460      private function writeBuffer(string $message, bool $newLine, int $type): void
 461      {
 462          // We need to know if the last chars are PHP_EOL
 463          $this->bufferedOutput->write($message, $newLine, $type);
 464      }
 465  
 466      private function createBlock(iterable $messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = false): array
 467      {
 468          $indentLength = 0;
 469          $prefixLength = Helper::width(Helper::removeDecoration($this->getFormatter(), $prefix));
 470          $lines = [];
 471  
 472          if (null !== $type) {
 473              $type = sprintf('[%s] ', $type);
 474              $indentLength = \strlen($type);
 475              $lineIndentation = str_repeat(' ', $indentLength);
 476          }
 477  
 478          // wrap and add newlines for each element
 479          foreach ($messages as $key => $message) {
 480              if ($escape) {
 481                  $message = OutputFormatter::escape($message);
 482              }
 483  
 484              $decorationLength = Helper::width($message) - Helper::width(Helper::removeDecoration($this->getFormatter(), $message));
 485              $messageLineLength = min($this->lineLength - $prefixLength - $indentLength + $decorationLength, $this->lineLength);
 486              $messageLines = explode(\PHP_EOL, wordwrap($message, $messageLineLength, \PHP_EOL, true));
 487              foreach ($messageLines as $messageLine) {
 488                  $lines[] = $messageLine;
 489              }
 490  
 491              if (\count($messages) > 1 && $key < \count($messages) - 1) {
 492                  $lines[] = '';
 493              }
 494          }
 495  
 496          $firstLineIndex = 0;
 497          if ($padding && $this->isDecorated()) {
 498              $firstLineIndex = 1;
 499              array_unshift($lines, '');
 500              $lines[] = '';
 501          }
 502  
 503          foreach ($lines as $i => &$line) {
 504              if (null !== $type) {
 505                  $line = $firstLineIndex === $i ? $type.$line : $lineIndentation.$line;
 506              }
 507  
 508              $line = $prefix.$line;
 509              $line .= str_repeat(' ', max($this->lineLength - Helper::width(Helper::removeDecoration($this->getFormatter(), $line)), 0));
 510  
 511              if ($style) {
 512                  $line = sprintf('<%s>%s</>', $style, $line);
 513              }
 514          }
 515  
 516          return $lines;
 517      }
 518  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer