/** * Formats a message as a block of text. * * @param string|array $messages The message to write in the block * @param string|null $type The block type (added in [] on first line) * @param string|null $style The style to apply to the whole block * @param string $prefix The prefix for the block * @param bool $padding Whether to add vertical padding */ public function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false) { $this->autoPrependBlock(); $messages = is_array($messages) ? array_values($messages) : array($messages); $lines = array(); // add type if (null !== $type) { $messages[0] = sprintf('[%s] %s', $type, $messages[0]); } // wrap and add newlines for each element foreach ($messages as $key => $message) { $message = OutputFormatter::escape($message); $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - Helper::strlen($prefix), PHP_EOL, true))); if (count($messages) > 1 && $key < count($messages) - 1) { $lines[] = ''; } } if ($padding && $this->isDecorated()) { array_unshift($lines, ''); $lines[] = ''; } foreach ($lines as &$line) { $line = sprintf('%s%s', $prefix, $line); $line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line)); if ($style) { $line = sprintf('<%s>%s</>', $style, $line); } } $this->writeln($lines); $this->newLine(); }
protected function getProgressBar($nbIteration, $message) { $bar = new ProgressBar($this->output, $nbIteration); ProgressBar::setPlaceholderFormatterDefinition('memory', function (ProgressBar $bar) { static $i = 0; $mem = memory_get_usage(); $colors = $i++ ? '41;37' : '44;37'; return "[" . $colors . 'm ' . Helper::formatMemory($mem) . " [0m"; }); $bar->setFormat(" [44;37m %title:-38s% [0m\n %current%/%max% %bar% %percent:3s%%\n 🏁 %remaining:-10s% %memory:37s%\n"); $bar->setBarCharacter("[32m●[0m"); $bar->setEmptyBarCharacter("[31m●[0m"); $bar->setMessage($message, 'title'); $bar->start(); return $bar; }
/** * Renders the title block to output. */ public function render() { $this->output->writeln(''); $lineLength = $this->getTerminalWidth(); $lines = explode(PHP_EOL, wordwrap($this->message, $lineLength - (strlen($this->blockStyles[$this->style]['prefix']) + 3), PHP_EOL, true)); array_unshift($lines, ' '); array_push($lines, ' '); foreach ($lines as $i => $line) { $prefix = str_repeat(' ', strlen($this->blockStyles[$this->style]['prefix'])); if ($i === 1) { $prefix = $this->blockStyles[$this->style]['prefix']; } $line = sprintf(' %s %s', $prefix, $line); $this->output->writeln(sprintf('<%s>%s%s</>', $this->blockStyles[$this->style]['style'], $line, str_repeat(' ', $lineLength - Helper::strlenWithoutDecoration($this->output->getFormatter(), $line)))); } $this->output->writeln(''); }
/** * Gets cell width. * * @param array $row * @param int $column * * @return int */ private function getCellWidth(array $row, $column) { if (isset($row[$column])) { $cell = $row[$column]; $cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell); return $cellWidth; } return 0; }
/** * Get password and validate. * * @param Helper $helper * @param string $question * @param callable $validator * * @return string */ protected function askForPassword(Helper $helper, $question, callable $validator) { $question = new Question($question); $question->setValidator($validator); $question->setHidden(true); $question->setHiddenFallback(true); return $helper->ask($this->input, $this->output, $question); }
/** * @param StopwatchEvent $event * * @return string */ private function formatStopwatchEvent(StopwatchEvent $event) { return sprintf('Time: %s, Memory: %s.', Helper::formatTime($event->getDuration() / 1000), Helper::formatMemory($event->getMemory())); }
/** * Gets cell width. * * @param array $row * @param int $column * * @return int */ private function getCellWidth(array $row, $column) { if (isset($row[$column])) { $cell = $row[$column]; $cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell); if ($cell instanceof TableCell && $cell->getColspan() > 1) { // we assume that cell value will be across more than one column. $cellWidth = $cellWidth / $cell->getColspan(); } return $cellWidth; } return 0; }
private static function initPlaceholderFormatters() { return array('indicator' => function (ProgressIndicator $indicator) { return $indicator->indicatorValues[$indicator->indicatorCurrent % count($indicator->indicatorValues)]; }, 'message' => function (ProgressIndicator $indicator) { return $indicator->message; }, 'elapsed' => function (ProgressIndicator $indicator) { return Helper::formatTime(time() - $indicator->startTime); }, 'memory' => function () { return Helper::formatMemory(memory_get_usage(true)); }); }
protected function displayAvancement($options, $done, $size, $showProgress, $output, $progress) { //advance $done += $options['slice']; if ($done > $size) { $done = $size; } //showing where we're at. if ($showProgress) { if ($output->isDecorated()) { $progress->advance(); } else { $output->writeln("did " . $done . " over (" . $size . ") memory: " . Helper::formatMemory(memory_get_usage(true))); } } return $done; }
/** * Finds a command by name or alias. * * Contrary to get, this command tries to find the best * match if you give it an abbreviation of a name or alias. * * @param string $name A command name or a command alias * * @return Command A Command instance * * @throws CommandNotFoundException When command name is incorrect or ambiguous */ public function find($name) { $allCommands = array_keys($this->commands); $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]) . '[^:]*'; }, $name); $commands = preg_grep('{^' . $expr . '}', $allCommands); if (empty($commands) || count(preg_grep('{^' . $expr . '$}', $commands)) < 1) { if (false !== ($pos = strrpos($name, ':'))) { // check if a namespace exists and contains commands $this->findNamespace(substr($name, 0, $pos)); } $message = sprintf('Command "%s" is not defined.', $name); if ($alternatives = $this->findAlternatives($name, $allCommands)) { if (1 == count($alternatives)) { $message .= "\n\nDid you mean this?\n "; } else { $message .= "\n\nDid you mean one of these?\n "; } $message .= implode("\n ", $alternatives); } throw new CommandNotFoundException($message, $alternatives); } // filter out aliases for commands which are already on the list if (count($commands) > 1) { $commandList = $this->commands; $commands = array_filter($commands, function ($nameOrAlias) use($commandList, $commands) { $commandName = $commandList[$nameOrAlias]->getName(); return $commandName === $nameOrAlias || !in_array($commandName, $commands); }); } $exact = in_array($name, $commands, true); if (count($commands) > 1 && !$exact) { $usableWidth = $this->terminal->getWidth() - 10; $abbrevs = array_values($commands); $maxLen = 0; foreach ($abbrevs as $abbrev) { $maxLen = max(Helper::strlen($abbrev), $maxLen); } $abbrevs = array_map(function ($cmd) use($commandList, $usableWidth, $maxLen) { $abbrev = str_pad($cmd, $maxLen, ' ') . ' ' . $commandList[$cmd]->getDescription(); return Helper::strlen($abbrev) > $usableWidth ? Helper::substr($abbrev, 0, $usableWidth - 3) . '...' : $abbrev; }, array_values($commands)); $suggestions = $this->getAbbreviationSuggestions($abbrevs); throw new CommandNotFoundException(sprintf("Command \"%s\" is ambiguous.\nDid you mean one of these?\n%s", $name, $suggestions), array_values($commands)); } return $this->get($exact ? $name : reset($commands)); }
/** * @return string */ public function getRemaining() { if (!$this->getMaxSteps()) { return '???'; } if (!$this->getProgress()) { $remaining = 0; } else { $remaining = round((time() - $this->getStartTime()) / $this->getProgress() * ($this->getMaxSteps() - $this->getProgress())); } return Helper::formatTime($remaining); }
/** * Renders the title to output. */ public function render() { $this->output->writeln(array('', sprintf('<title>%s</>', $this->message), sprintf('<title>%s</>', str_repeat('=', Helper::strlenWithoutDecoration($this->output->getFormatter(), $this->message))), '')); }
private function createBlock($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = false) { $indentLength = 0; $prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(), $prefix); $lines = array(); if (null !== $type) { $type = sprintf('[%s] ', $type); $indentLength = strlen($type); $lineIndentation = str_repeat(' ', $indentLength); } // wrap and add newlines for each element foreach ($messages as $key => $message) { if ($escape) { $message = OutputFormatter::escape($message); } $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL, true))); if (count($messages) > 1 && $key < count($messages) - 1) { $lines[] = ''; } } foreach ($lines as $i => &$line) { if (null !== $type) { $line = 0 === $i ? $type . $line : $lineIndentation . $line; } $line = $prefix . $line; $line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line)); if ($style) { $line = sprintf('<%s>%s</>', $style, $line); } } if ($padding && $this->isDecorated()) { array_unshift($lines, ''); $lines[] = ''; } return $lines; }
/** * Renders table cell with padding. * * @param array $row * @param int $column * @param string $cellFormat */ private function renderCell(array $row, $column, $cellFormat) { $cell = isset($row[$column]) ? $row[$column] : ''; $width = $this->columnWidths[$column]; if ($cell instanceof TableCell && $cell->getColspan() > 1) { // add the width of the following columns(numbers of colspan). foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) { $width += $this->getColumnSeparatorWidth() + $this->columnWidths[$nextColumn]; } } // str_pad won't work properly with multi-byte strings, we need to fix the padding if (false !== ($encoding = mb_detect_encoding($cell, null, true))) { $width += strlen($cell) - mb_strwidth($cell, $encoding); } $style = $this->getColumnStyle($column); if ($cell instanceof TableSeparator) { $this->output->write(sprintf($style->getBorderFormat(), str_repeat($style->getHorizontalBorderChar(), $width))); } else { $width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell); $content = sprintf($style->getCellRowContentFormat(), $cell); $this->output->write(sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType()))); } }
/** * @param string $message */ public function subSection($message) { $padLength = $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $message) - 6; $padLeft = round($padLength / 2); $padRight = $padLength - $padLeft; $this->autoPrependBlock(); $this->writeln([sprintf('<bg=yellow;fg=black> %s[ %s ]%s </>', str_repeat(' ', $padLeft), $message, str_repeat(' ', $padRight))]); $this->newLine(); }
/** * Executes the current command. * * This method is not abstract because you can use this class * as a concrete class. In this case, instead of defining the * execute() method, you set the code to execute by passing * a Closure to the setCode() method. * * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance * * @throws LogicException When this abstract method is not implemented * * @return null|int null or 0 if everything went fine, or an error code * * @see setCode() */ protected function execute(InputInterface $input, OutputInterface $output) { $startTime = microtime(true); $startMemUsage = memory_get_usage(true); $output->writeln($this->getApplication()->getLongVersion() . " by overtrue and contributors.\n"); $options = $this->mergeOptions(); $verbosity = $output->getVerbosity(); if ($verbosity >= OutputInterface::VERBOSITY_DEBUG) { $output->writeln('Options: ' . json_encode($options)); } $linter = new Linter($options['path'], $options['exclude'], $options['extensions']); $linter->setProcessLimit($options['jobs']); if (!$input->getOption('no-cache') && Cache::isCached()) { $output->writeln('Using cache.'); $linter->setCache(Cache::get()); } $fileCount = count($linter->getFiles()); if ($fileCount <= 0) { $output->writeln('<info>Could not find files to lint</info>'); return 0; } $errors = $this->executeLint($linter, $output, $fileCount, !$input->getOption('no-cache')); $timeUsage = Helper::formatTime(microtime(true) - $startTime); $memUsage = Helper::formatMemory(memory_get_usage(true) - $startMemUsage); $code = 0; $errCount = count($errors); $output->writeln("\n\nTime: {$timeUsage}, Memory: {$memUsage}MB\n"); if ($errCount > 0) { $output->writeln('<error>FAILURES!</error>'); $output->writeln("<error>Files: {$fileCount}, Failures: {$errCount}</error>"); $this->showErrors($errors); $code = 1; } else { $output->writeln("<info>OK! (Files: {$fileCount}, Success: {$fileCount})</info>"); } return $code; }
/** * Overwrites a previous message to the output. * * @param string $message The message */ private function overwrite($message) { $lines = explode("\n", $message); // append whitespace to match the line's length if (null !== $this->lastMessagesLength) { foreach ($lines as $i => $line) { if ($this->lastMessagesLength > Helper::strlenWithoutDecoration($this->output->getFormatter(), $line)) { $lines[$i] = str_pad($line, $this->lastMessagesLength, " ", STR_PAD_RIGHT); } } } if ($this->overwrite) { // move back to the beginning of the progress bar before redrawing it $this->output->write("\r"); } elseif ($this->step > 0) { // move to new line $this->output->writeln(''); } if ($this->formatLineCount) { $this->output->write(sprintf("[%dA", $this->formatLineCount)); } $this->output->write(implode("\n", $lines)); $this->lastMessagesLength = 0; foreach ($lines as $line) { $len = Helper::strlenWithoutDecoration($this->output->getFormatter(), $line); if ($len > $this->lastMessagesLength) { $this->lastMessagesLength = $len; } } }
/** * {@inheritdoc} */ public function subSection($message) { $this->writeln(array(sprintf('<comment>%s</comment>', $message), sprintf('<comment>%s</comment>', str_repeat('.', Helper::strlenWithoutDecoration($this->getFormatter(), $message))))); $this->newLine(); }
private function askToDownloadFromCartoDB(Input $input, Output $output, Helper $helper) { $question = new ConfirmationQuestion("\n<ask>Do you want to download the data form <high>CartoDB</high>? (yes/no): </ask>", false); return $helper->ask($input, $output, $question); }
private static function initPlaceholderFormatters() { return array('bar' => function (ProgressBar $bar, OutputInterface $output) { $completeBars = floor($bar->getMaxSteps() > 0 ? $bar->getProgressPercent() * $bar->getBarWidth() : $bar->getProgress() % $bar->getBarWidth()); $display = str_repeat($bar->getBarCharacter(), $completeBars); if ($completeBars < $bar->getBarWidth()) { $emptyBars = $bar->getBarWidth() - $completeBars - Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter()); $display .= $bar->getProgressCharacter() . str_repeat($bar->getEmptyBarCharacter(), $emptyBars); } return $display; }, 'elapsed' => function (ProgressBar $bar) { return Helper::formatTime(time() - $bar->getStartTime()); }, 'remaining' => function (ProgressBar $bar) { if (!$bar->getMaxSteps()) { throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.'); } if (!$bar->getProgress()) { $remaining = 0; } else { $remaining = round((time() - $bar->getStartTime()) / $bar->getProgress() * ($bar->getMaxSteps() - $bar->getProgress())); } return Helper::formatTime($remaining); }, 'estimated' => function (ProgressBar $bar) { if (!$bar->getMaxSteps()) { throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.'); } if (!$bar->getProgress()) { $estimated = 0; } else { $estimated = round((time() - $bar->getStartTime()) / $bar->getProgress() * $bar->getMaxSteps()); } return Helper::formatTime($estimated); }, 'memory' => function (ProgressBar $bar) { return Helper::formatMemory(memory_get_usage(true)); }, 'current' => function (ProgressBar $bar) { return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', STR_PAD_LEFT); }, 'max' => function (ProgressBar $bar) { return $bar->getMaxSteps(); }, 'percent' => function (ProgressBar $bar) { return floor($bar->getProgressPercent() * 100); }); }
/** * @return string */ private function buildLine() { $regex = "{%([a-z\\-_]+)(?:\\:([^%]+))?%}i"; $callback = function ($matches) { if ($formatter = $this::getPlaceholderFormatterDefinition($matches[1])) { $text = call_user_func($formatter, $this, $this->output); } elseif (isset($this->messages[$matches[1]])) { $text = $this->messages[$matches[1]]; } else { return $matches[0]; } if (isset($matches[2])) { $text = sprintf('%' . $matches[2], $text); } return $text; }; $line = preg_replace_callback($regex, $callback, $this->format); $lineLength = Helper::strlenWithoutDecoration($this->output->getFormatter(), $line); $terminalWidth = $this->terminal->getWidth(); if ($lineLength <= $terminalWidth) { return $line; } $this->setBarWidth($this->barWidth - $lineLength + $terminalWidth); return preg_replace_callback($regex, $callback, $this->format); }
/** * Chooses the best compressed file format to download (ZIP or TGZ) depending upon the * available operating system uncompressing commands and the enabled PHP extensions * and it downloads the file. * * @return $this * * @throws \RuntimeException If the Symfony archive could not be downloaded */ protected function download() { $this->output->writeln(sprintf("\n Downloading %s...\n", $this->getDownloadedApplicationType())); // decide which is the best compressed version to download $distill = new Distill(); $symfonyArchiveFile = $distill->getChooser()->setStrategy(new MinimumSize())->addFilesWithDifferentExtensions($this->getRemoteFileUrl(), ['tgz', 'zip'])->getPreferredFile(); /** @var ProgressBar|null $progressBar */ $progressBar = null; $downloadCallback = function (ProgressEvent $event) use(&$progressBar) { $downloadSize = $event->downloadSize; $downloaded = $event->downloaded; // progress bar is only displayed for files larger than 1MB if ($downloadSize < 1 * 1024 * 1024) { return; } if (null === $progressBar) { ProgressBar::setPlaceholderFormatterDefinition('max', function (ProgressBar $bar) { return Helper::formatMemory($bar->getMaxSteps()); }); ProgressBar::setPlaceholderFormatterDefinition('current', function (ProgressBar $bar) { return str_pad(Helper::formatMemory($bar->getProgress()), 11, ' ', STR_PAD_LEFT); }); $progressBar = new ProgressBar($this->output, $downloadSize); $progressBar->setFormat('%current%/%max% %bar% %percent:3s%%'); $progressBar->setRedrawFrequency(max(1, floor($downloadSize / 1000))); $progressBar->setBarWidth(60); if (!defined('PHP_WINDOWS_VERSION_BUILD')) { $progressBar->setEmptyBarCharacter('░'); // light shade character \u2591 $progressBar->setProgressCharacter(''); $progressBar->setBarCharacter('▓'); // dark shade character \u2593 } $progressBar->start(); } $progressBar->setProgress($downloaded); }; $client = $this->getGuzzleClient(); // store the file in a temporary hidden directory with a random name $this->downloadedFilePath = rtrim(getcwd(), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . '.' . uniqid(time()) . DIRECTORY_SEPARATOR . 'symfony.' . pathinfo($symfonyArchiveFile, PATHINFO_EXTENSION); try { $request = $client->createRequest('GET', $symfonyArchiveFile); $request->getEmitter()->on('progress', $downloadCallback); $response = $client->send($request); } catch (ClientException $e) { if ('new' === $this->getName() && ($e->getCode() === 403 || $e->getCode() === 404)) { throw new \RuntimeException(sprintf("The selected version (%s) cannot be installed because it does not exist.\n" . "Execute the following command to install the latest stable Symfony release:\n" . '%s new %s', $this->version, $_SERVER['PHP_SELF'], str_replace(getcwd() . DIRECTORY_SEPARATOR, '', $this->projectDir))); } else { throw new \RuntimeException(sprintf("There was an error downloading %s from symfony.com server:\n%s", $this->getDownloadedApplicationType(), $e->getMessage()), null, $e); } } $this->fs->dumpFile($this->downloadedFilePath, $response->getBody()); if (null !== $progressBar) { $progressBar->finish(); $this->output->writeln("\n"); } return $this; }
public function testAnsiColorsAndEmojis() { $bar = new ProgressBar($output = $this->getOutputStream(), 15); ProgressBar::setPlaceholderFormatterDefinition('memory', function (ProgressBar $bar) { static $i = 0; $mem = 100000 * $i; $colors = $i++ ? '41;37' : '44;37'; return "[" . $colors . 'm ' . Helper::formatMemory($mem) . " [0m"; }); $bar->setFormat(" [44;37m %title:-37s% [0m\n %current%/%max% %bar% %percent:3s%%\n 🏁 %remaining:-10s% %memory:37s%"); $bar->setBarCharacter($done = "[32m●[0m"); $bar->setEmptyBarCharacter($empty = "[31m●[0m"); $bar->setProgressCharacter($progress = "[32m➤ [0m"); $bar->setMessage('Starting the demo... fingers crossed', 'title'); $bar->start(); $bar->setMessage('Looks good to me...', 'title'); $bar->advance(4); $bar->setMessage('Thanks, bye', 'title'); $bar->finish(); rewind($output->getStream()); $this->assertEquals($this->generateOutput(" [44;37m Starting the demo... fingers crossed [0m\n" . ' 0/15 ' . $progress . str_repeat($empty, 26) . " 0%\n" . " 🏁 1 sec [44;37m 0 B [0m") . $this->generateOutput(" [44;37m Looks good to me... [0m\n" . ' 4/15 ' . str_repeat($done, 7) . $progress . str_repeat($empty, 19) . " 26%\n" . " 🏁 1 sec [41;37m 97 KiB [0m") . $this->generateOutput(" [44;37m Thanks, bye [0m\n" . ' 15/15 ' . str_repeat($done, 28) . " 100%\n" . " 🏁 1 sec [41;37m 195 KiB [0m"), stream_get_contents($output->getStream())); }
/** * Renders table cell with padding. * * @param array $row * @param int $column * @param string $cellFormat */ private function renderCell(array $row, $column, $cellFormat) { $cell = isset($row[$column]) ? $row[$column] : ''; $width = $this->getColumnWidth($column); // str_pad won't work properly with multi-byte strings, we need to fix the padding if (function_exists('mb_strwidth') && false !== ($encoding = mb_detect_encoding($cell))) { $width += strlen($cell) - mb_strwidth($cell, $encoding); } $width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell); $content = sprintf($this->style->getCellRowContentFormat(), $cell); $this->output->write(sprintf($cellFormat, str_pad($content, $width, $this->style->getPaddingChar(), $this->style->getPadType()))); }
private static function initPlaceholderFormatters() { return array('indicator' => function (ProgressIndicator $indicator) { return $indicator->getCurrentValue(); }, 'message' => function (ProgressIndicator $indicator) { return $indicator->getMessage(); }, 'elapsed' => function (ProgressIndicator $indicator) { return Helper::formatTime(time() - $indicator->getStartTime()); }, 'memory' => function () { return Helper::formatMemory(memory_get_usage(true)); }); }
/** * @dataProvider formatTimeProvider * * @param int $secs * @param string $expectedFormat */ public function testFormatTime($secs, $expectedFormat) { $this->assertEquals($expectedFormat, Helper::formatTime($secs)); }
/** * Gets cell width. * * @param array $row * @param int $column * * @return int */ private function getCellWidth(array $row, $column) { return isset($row[$column]) ? Helper::strlenWithoutDecoration($this->output->getFormatter(), $row[$column]) : 0; }
/** * Formats a message as a block of text. * * @param string|array $messages The message to write in the block * @param string|null $type The block type (added in [] on first line) * @param string|null $style The style to apply to the whole block * @param string $prefix The prefix for the block * @param bool $padding Whether to add vertical padding */ public function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false) { $this->autoPrependBlock(); $messages = is_array($messages) ? array_values($messages) : array($messages); $indentLength = 0; $lines = array(); if (null !== $type) { $typePrefix = sprintf('[%s] ', $type); $indentLength = strlen($typePrefix); $lineIndentation = str_repeat(' ', $indentLength); } // wrap and add newlines for each element foreach ($messages as $key => $message) { $message = OutputFormatter::escape($message); $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - Helper::strlen($prefix) - $indentLength, PHP_EOL, true))); // prefix each line with a number of spaces equivalent to the type length if (null !== $type) { foreach ($lines as &$line) { $line = $lineIndentation === substr($line, 0, $indentLength) ? $line : $lineIndentation . $line; } } if (count($messages) > 1 && $key < count($messages) - 1) { $lines[] = ''; } } if (null !== $type) { $lines[0] = substr_replace($lines[0], $typePrefix, 0, $indentLength); } if ($padding && $this->isDecorated()) { array_unshift($lines, ''); $lines[] = ''; } foreach ($lines as &$line) { $line = sprintf('%s%s', $prefix, $line); $line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line)); if ($style) { $line = sprintf('<%s>%s</>', $style, $line); } } $this->writeln($lines); $this->newLine(); }
/** * Gets cell width. * * @param array $row * @param int $column * * @return int */ private function getCellWidth(array $row, $column) { $cellWidth = 0; if (isset($row[$column])) { $cell = $row[$column]; $cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell); } $columnWidth = isset($this->columnWidths[$column]) ? $this->columnWidths[$column] : 0; return max($cellWidth, $columnWidth); }
/** * Get the default width of a table cell (the length of its longest line). * * This is inspired by Table->getCellWidth(), but this also accounts for * multi-line cells. * * @param string|TableCell $cell * * @return float|int */ private function getCellWidth($cell) { $lineWidths = [0]; foreach (explode(PHP_EOL, $cell) as $line) { $lineWidths[] = Helper::strlenWithoutDecoration($this->outputCopy->getFormatter(), $line); } $cellWidth = max($lineWidths); if ($cell instanceof TableCell && $cell->getColspan() > 1) { $cellWidth /= $cell->getColspan(); } return $cellWidth; }