Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 88

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 215

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 216

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 217

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 218

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 219

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 220
PK!iäÒ¢ììInspectorHelper.phpnu„[µü¤fileExists($filePath) && str_contains($fs->read($filePath), $searchString); } } PK!J^˜ÞÞProcessHelper.phpnuÕIw¶´ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Process\Exception\ProcessFailedException; use Symfony\Component\Process\Process; /** * The ProcessHelper class provides helpers to run external processes. * * @author Fabien Potencier * * @final */ class ProcessHelper extends Helper { /** * Runs an external process. * * @param array|Process $cmd An instance of Process or an array of the command and arguments * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR * * @return Process The process that ran */ public function run(OutputInterface $output, $cmd, string $error = null, callable $callback = null, int $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE): Process { if (!class_exists(Process::class)) { throw new \LogicException('The ProcessHelper cannot be run as the Process component is not installed. Try running "compose require symfony/process".'); } if ($output instanceof ConsoleOutputInterface) { $output = $output->getErrorOutput(); } $formatter = $this->getHelperSet()->get('debug_formatter'); if ($cmd instanceof Process) { $cmd = [$cmd]; } if (!\is_array($cmd)) { throw new \TypeError(sprintf('The "command" argument of "%s()" must be an array or a "%s" instance, "%s" given.', __METHOD__, Process::class, get_debug_type($cmd))); } if (\is_string($cmd[0] ?? null)) { $process = new Process($cmd); $cmd = []; } elseif (($cmd[0] ?? null) instanceof Process) { $process = $cmd[0]; unset($cmd[0]); } else { throw new \InvalidArgumentException(sprintf('Invalid command provided to "%s()": the command should be an array whose first element is either the path to the binary to run or a "Process" object.', __METHOD__)); } if ($verbosity <= $output->getVerbosity()) { $output->write($formatter->start(spl_object_hash($process), $this->escapeString($process->getCommandLine()))); } if ($output->isDebug()) { $callback = $this->wrapCallback($output, $process, $callback); } $process->run($callback, $cmd); if ($verbosity <= $output->getVerbosity()) { $message = $process->isSuccessful() ? 'Command ran successfully' : sprintf('%s Command did not run successfully', $process->getExitCode()); $output->write($formatter->stop(spl_object_hash($process), $message, $process->isSuccessful())); } if (!$process->isSuccessful() && null !== $error) { $output->writeln(sprintf('%s', $this->escapeString($error))); } return $process; } /** * Runs the process. * * This is identical to run() except that an exception is thrown if the process * exits with a non-zero exit code. * * @param string|Process $cmd An instance of Process or a command to run * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR * * @return Process The process that ran * * @throws ProcessFailedException * * @see run() */ public function mustRun(OutputInterface $output, $cmd, string $error = null, callable $callback = null): Process { $process = $this->run($output, $cmd, $error, $callback); if (!$process->isSuccessful()) { throw new ProcessFailedException($process); } return $process; } /** * Wraps a Process callback to add debugging output. */ public function wrapCallback(OutputInterface $output, Process $process, callable $callback = null): callable { if ($output instanceof ConsoleOutputInterface) { $output = $output->getErrorOutput(); } $formatter = $this->getHelperSet()->get('debug_formatter'); return function ($type, $buffer) use ($output, $process, $callback, $formatter) { $output->write($formatter->progress(spl_object_hash($process), $this->escapeString($buffer), Process::ERR === $type)); if (null !== $callback) { $callback($type, $buffer); } }; } private function escapeString(string $str): string { return str_replace('<', '\\<', $str); } /** * {@inheritdoc} */ public function getName(): string { return 'process'; } } PK! z…×óóHelperInterface.phpnu„[µü¤ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; /** * HelperInterface is the interface all helpers must implement. * * @author Fabien Potencier * * @api */ interface HelperInterface { /** * Sets the helper set associated with this helper. * * @param HelperSet $helperSet A HelperSet instance * * @api */ public function setHelperSet(HelperSet $helperSet = null); /** * Gets the helper set associated with this helper. * * @return HelperSet A HelperSet instance * * @api */ public function getHelperSet(); /** * Returns the canonical name of this helper. * * @return string The canonical name * * @api */ public function getName(); } PK!B¶Ý%Ãà TableCell.phpnuÕIw¶´ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Exception\InvalidArgumentException; /** * @author Abdellatif Ait boudad */ class TableCell { private $value; private $options = [ 'rowspan' => 1, 'colspan' => 1, ]; public function __construct(string $value = '', array $options = []) { $this->value = $value; // check option names if ($diff = array_diff(array_keys($options), array_keys($this->options))) { throw new InvalidArgumentException(sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff))); } $this->options = array_merge($this->options, $options); } /** * Returns the cell value. * * @return string */ public function __toString() { return $this->value; } /** * Gets number of colspan. * * @return int */ public function getColspan() { return (int) $this->options['colspan']; } /** * Gets number of rowspan. * * @return int */ public function getRowspan() { return (int) $this->options['rowspan']; } } PK!+'šfèè Dumper.phpnuÕIw¶´ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\VarDumper\Cloner\ClonerInterface; use Symfony\Component\VarDumper\Cloner\VarCloner; use Symfony\Component\VarDumper\Dumper\CliDumper; /** * @author Roland Franssen */ final class Dumper { private $output; private $dumper; private $cloner; private $handler; public function __construct(OutputInterface $output, CliDumper $dumper = null, ClonerInterface $cloner = null) { $this->output = $output; $this->dumper = $dumper; $this->cloner = $cloner; if (class_exists(CliDumper::class)) { $this->handler = function ($var): string { $dumper = $this->dumper ?? $this->dumper = new CliDumper(null, null, CliDumper::DUMP_LIGHT_ARRAY | CliDumper::DUMP_COMMA_SEPARATOR); $dumper->setColors($this->output->isDecorated()); return rtrim($dumper->dump(($this->cloner ?? $this->cloner = new VarCloner())->cloneVar($var)->withRefHandles(false), true)); }; } else { $this->handler = function ($var): string { switch (true) { case null === $var: return 'null'; case true === $var: return 'true'; case false === $var: return 'false'; case \is_string($var): return '"'.$var.'"'; default: return rtrim(print_r($var, true)); } }; } } public function __invoke($var): string { return ($this->handler)($var); } } PK!?*èlElEProgressBar.phpnuÕIw¶´ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Cursor; use Symfony\Component\Console\Exception\LogicException; use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\ConsoleSectionOutput; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Terminal; /** * The ProgressBar provides helpers to display progress output. * * @author Fabien Potencier * @author Chris Jones */ final class ProgressBar { private $barWidth = 28; private $barChar; private $emptyBarChar = '-'; private $progressChar = '>'; private $format; private $internalFormat; private $redrawFreq = 1; private $writeCount; private $lastWriteTime; private $minSecondsBetweenRedraws = 0; private $maxSecondsBetweenRedraws = 1; private $output; private $step = 0; private $max; private $startTime; private $stepWidth; private $percent = 0.0; private $formatLineCount; private $messages = []; private $overwrite = true; private $terminal; private $previousMessage; private $cursor; private static $formatters; private static $formats; /** * @param int $max Maximum steps (0 if unknown) */ public function __construct(OutputInterface $output, int $max = 0, float $minSecondsBetweenRedraws = 0.1) { if ($output instanceof ConsoleOutputInterface) { $output = $output->getErrorOutput(); } $this->output = $output; $this->setMaxSteps($max); $this->terminal = new Terminal(); if (0 < $minSecondsBetweenRedraws) { $this->redrawFreq = null; $this->minSecondsBetweenRedraws = $minSecondsBetweenRedraws; } if (!$this->output->isDecorated()) { // disable overwrite when output does not support ANSI codes. $this->overwrite = false; // set a reasonable redraw frequency so output isn't flooded $this->redrawFreq = null; } $this->startTime = time(); $this->cursor = new Cursor($output); } /** * Sets a placeholder formatter for a given name. * * This method also allow you to override an existing placeholder. * * @param string $name The placeholder name (including the delimiter char like %) * @param callable $callable A PHP callable */ public static function setPlaceholderFormatterDefinition(string $name, callable $callable): void { if (!self::$formatters) { self::$formatters = self::initPlaceholderFormatters(); } self::$formatters[$name] = $callable; } /** * Gets the placeholder formatter for a given name. * * @param string $name The placeholder name (including the delimiter char like %) * * @return callable|null A PHP callable */ public static function getPlaceholderFormatterDefinition(string $name): ?callable { if (!self::$formatters) { self::$formatters = self::initPlaceholderFormatters(); } return isset(self::$formatters[$name]) ? self::$formatters[$name] : null; } /** * Sets a format for a given name. * * This method also allow you to override an existing format. * * @param string $name The format name * @param string $format A format string */ public static function setFormatDefinition(string $name, string $format): void { if (!self::$formats) { self::$formats = self::initFormats(); } self::$formats[$name] = $format; } /** * Gets the format for a given name. * * @param string $name The format name * * @return string|null A format string */ public static function getFormatDefinition(string $name): ?string { if (!self::$formats) { self::$formats = self::initFormats(); } return isset(self::$formats[$name]) ? self::$formats[$name] : null; } /** * Associates a text with a named placeholder. * * The text is displayed when the progress bar is rendered but only * when the corresponding placeholder is part of the custom format line * (by wrapping the name with %). * * @param string $message The text to associate with the placeholder * @param string $name The name of the placeholder */ public function setMessage(string $message, string $name = 'message') { $this->messages[$name] = $message; } public function getMessage(string $name = 'message') { return $this->messages[$name]; } public function getStartTime(): int { return $this->startTime; } public function getMaxSteps(): int { return $this->max; } public function getProgress(): int { return $this->step; } private function getStepWidth(): int { return $this->stepWidth; } public function getProgressPercent(): float { return $this->percent; } public function getBarOffset(): float { return floor($this->max ? $this->percent * $this->barWidth : (null === $this->redrawFreq ? min(5, $this->barWidth / 15) * $this->writeCount : $this->step) % $this->barWidth); } public function getEstimated(): float { if (!$this->step) { return 0; } return round((time() - $this->startTime) / $this->step * $this->max); } public function getRemaining(): float { if (!$this->step) { return 0; } return round((time() - $this->startTime) / $this->step * ($this->max - $this->step)); } public function setBarWidth(int $size) { $this->barWidth = max(1, $size); } public function getBarWidth(): int { return $this->barWidth; } public function setBarCharacter(string $char) { $this->barChar = $char; } public function getBarCharacter(): string { if (null === $this->barChar) { return $this->max ? '=' : $this->emptyBarChar; } return $this->barChar; } public function setEmptyBarCharacter(string $char) { $this->emptyBarChar = $char; } public function getEmptyBarCharacter(): string { return $this->emptyBarChar; } public function setProgressCharacter(string $char) { $this->progressChar = $char; } public function getProgressCharacter(): string { return $this->progressChar; } public function setFormat(string $format) { $this->format = null; $this->internalFormat = $format; } /** * Sets the redraw frequency. * * @param int|float $freq The frequency in steps */ public function setRedrawFrequency(?int $freq) { $this->redrawFreq = null !== $freq ? max(1, $freq) : null; } public function minSecondsBetweenRedraws(float $seconds): void { $this->minSecondsBetweenRedraws = $seconds; } public function maxSecondsBetweenRedraws(float $seconds): void { $this->maxSecondsBetweenRedraws = $seconds; } /** * Returns an iterator that will automatically update the progress bar when iterated. * * @param int|null $max Number of steps to complete the bar (0 if indeterminate), if null it will be inferred from $iterable */ public function iterate(iterable $iterable, int $max = null): iterable { $this->start($max ?? (is_countable($iterable) ? \count($iterable) : 0)); foreach ($iterable as $key => $value) { yield $key => $value; $this->advance(); } $this->finish(); } /** * Starts the progress output. * * @param int|null $max Number of steps to complete the bar (0 if indeterminate), null to leave unchanged */ public function start(int $max = null) { $this->startTime = time(); $this->step = 0; $this->percent = 0.0; if (null !== $max) { $this->setMaxSteps($max); } $this->display(); } /** * Advances the progress output X steps. * * @param int $step Number of steps to advance */ public function advance(int $step = 1) { $this->setProgress($this->step + $step); } /** * Sets whether to overwrite the progressbar, false for new line. */ public function setOverwrite(bool $overwrite) { $this->overwrite = $overwrite; } public function setProgress(int $step) { if ($this->max && $step > $this->max) { $this->max = $step; } elseif ($step < 0) { $step = 0; } $redrawFreq = $this->redrawFreq ?? (($this->max ?: 10) / 10); $prevPeriod = (int) ($this->step / $redrawFreq); $currPeriod = (int) ($step / $redrawFreq); $this->step = $step; $this->percent = $this->max ? (float) $this->step / $this->max : 0; $timeInterval = microtime(true) - $this->lastWriteTime; // Draw regardless of other limits if ($this->max === $step) { $this->display(); return; } // Throttling if ($timeInterval < $this->minSecondsBetweenRedraws) { return; } // Draw each step period, but not too late if ($prevPeriod !== $currPeriod || $timeInterval >= $this->maxSecondsBetweenRedraws) { $this->display(); } } public function setMaxSteps(int $max) { $this->format = null; $this->max = max(0, $max); $this->stepWidth = $this->max ? Helper::strlen((string) $this->max) : 4; } /** * Finishes the progress output. */ public function finish(): void { if (!$this->max) { $this->max = $this->step; } if ($this->step === $this->max && !$this->overwrite) { // prevent double 100% output return; } $this->setProgress($this->max); } /** * Outputs the current progress string. */ public function display(): void { if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) { return; } if (null === $this->format) { $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat()); } $this->overwrite($this->buildLine()); } /** * Removes the progress bar from the current line. * * This is useful if you wish to write some output * while a progress bar is running. * Call display() to show the progress bar again. */ public function clear(): void { if (!$this->overwrite) { return; } if (null === $this->format) { $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat()); } $this->overwrite(''); } private function setRealFormat(string $format) { // try to use the _nomax variant if available if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) { $this->format = self::getFormatDefinition($format.'_nomax'); } elseif (null !== self::getFormatDefinition($format)) { $this->format = self::getFormatDefinition($format); } else { $this->format = $format; } $this->formatLineCount = substr_count($this->format, "\n"); } /** * Overwrites a previous message to the output. */ private function overwrite(string $message): void { if ($this->previousMessage === $message) { return; } $originalMessage = $message; if ($this->overwrite) { if (null !== $this->previousMessage) { if ($this->output instanceof ConsoleSectionOutput) { $lines = floor(Helper::strlen($message) / $this->terminal->getWidth()) + $this->formatLineCount + 1; $this->output->clear($lines); } else { if ($this->formatLineCount > 0) { $this->cursor->moveUp($this->formatLineCount); } $this->cursor->moveToColumn(1); $this->cursor->clearLine(); } } } elseif ($this->step > 0) { $message = \PHP_EOL.$message; } $this->previousMessage = $originalMessage; $this->lastWriteTime = microtime(true); $this->output->write($message); ++$this->writeCount; } private function determineBestFormat(): string { switch ($this->output->getVerbosity()) { // OutputInterface::VERBOSITY_QUIET: display is disabled anyway case OutputInterface::VERBOSITY_VERBOSE: return $this->max ? 'verbose' : 'verbose_nomax'; case OutputInterface::VERBOSITY_VERY_VERBOSE: return $this->max ? 'very_verbose' : 'very_verbose_nomax'; case OutputInterface::VERBOSITY_DEBUG: return $this->max ? 'debug' : 'debug_nomax'; default: return $this->max ? 'normal' : 'normal_nomax'; } } private static function initPlaceholderFormatters(): array { return [ 'bar' => function (self $bar, OutputInterface $output) { $completeBars = $bar->getBarOffset(); $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 (self $bar) { return Helper::formatTime(time() - $bar->getStartTime()); }, 'remaining' => function (self $bar) { if (!$bar->getMaxSteps()) { throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.'); } return Helper::formatTime($bar->getRemaining()); }, 'estimated' => function (self $bar) { if (!$bar->getMaxSteps()) { throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.'); } return Helper::formatTime($bar->getEstimated()); }, 'memory' => function (self $bar) { return Helper::formatMemory(memory_get_usage(true)); }, 'current' => function (self $bar) { return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', \STR_PAD_LEFT); }, 'max' => function (self $bar) { return $bar->getMaxSteps(); }, 'percent' => function (self $bar) { return floor($bar->getProgressPercent() * 100); }, ]; } private static function initFormats(): array { return [ 'normal' => ' %current%/%max% [%bar%] %percent:3s%%', 'normal_nomax' => ' %current% [%bar%]', 'verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%', 'verbose_nomax' => ' %current% [%bar%] %elapsed:6s%', 'very_verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%', 'very_verbose_nomax' => ' %current% [%bar%] %elapsed:6s%', 'debug' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%', 'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%', ]; } private function buildLine(): string { $regex = "{%([a-z\-_]+)(?:\:([^%]+))?%}i"; $callback = function ($matches) { if ($formatter = $this::getPlaceholderFormatterDefinition($matches[1])) { $text = $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); // gets string length for each sub line with multiline format $linesLength = array_map(function ($subLine) { return Helper::strlenWithoutDecoration($this->output->getFormatter(), rtrim($subLine, "\r")); }, explode("\n", $line)); $linesWidth = max($linesLength); $terminalWidth = $this->terminal->getWidth(); if ($linesWidth <= $terminalWidth) { return $line; } $this->setBarWidth($this->barWidth - $linesWidth + $terminalWidth); return preg_replace_callback($regex, $callback, $this->format); } } PK!g¶se¼¼FormatterHelper.phpnu„[µü¤ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Formatter\OutputFormatter; /** * The Formatter class provides helpers to format messages. * * @author Fabien Potencier */ class FormatterHelper extends Helper { /** * Formats a message within a section. * * @param string $section The section name * @param string $message The message * @param string $style The style to apply to the section * * @return string The format section */ public function formatSection($section, $message, $style = 'info') { return sprintf('<%s>[%s] %s', $style, $section, $style, $message); } /** * Formats a message as a block of text. * * @param string|array $messages The message to write in the block * @param string $style The style to apply to the whole block * @param Boolean $large Whether to return a large block * * @return string The formatter message */ public function formatBlock($messages, $style, $large = false) { $messages = (array) $messages; $len = 0; $lines = array(); foreach ($messages as $message) { $message = OutputFormatter::escape($message); $lines[] = sprintf($large ? ' %s ' : ' %s ', $message); $len = max($this->strlen($message) + ($large ? 4 : 2), $len); } $messages = $large ? array(str_repeat(' ', $len)) : array(); foreach ($lines as $line) { $messages[] = $line.str_repeat(' ', $len - $this->strlen($line)); } if ($large) { $messages[] = str_repeat(' ', $len); } foreach ($messages as &$message) { $message = sprintf('<%s>%s', $style, $message, $style); } return implode("\n", $messages); } /** * {@inheritDoc} */ public function getName() { return 'formatter'; } } PK!@/®é0é0TableStyle.phpnuÕIw¶´ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Exception\LogicException; /** * Defines the styles for a Table. * * @author Fabien Potencier * @author Саша Стаменковић * @author Dany Maillard */ class TableStyle { private $paddingChar = ' '; private $horizontalOutsideBorderChar = '-'; private $horizontalInsideBorderChar = '-'; private $verticalOutsideBorderChar = '|'; private $verticalInsideBorderChar = '|'; private $crossingChar = '+'; private $crossingTopRightChar = '+'; private $crossingTopMidChar = '+'; private $crossingTopLeftChar = '+'; private $crossingMidRightChar = '+'; private $crossingBottomRightChar = '+'; private $crossingBottomMidChar = '+'; private $crossingBottomLeftChar = '+'; private $crossingMidLeftChar = '+'; private $crossingTopLeftBottomChar = '+'; private $crossingTopMidBottomChar = '+'; private $crossingTopRightBottomChar = '+'; private $headerTitleFormat = ' %s '; private $footerTitleFormat = ' %s '; private $cellHeaderFormat = '%s'; private $cellRowFormat = '%s'; private $cellRowContentFormat = ' %s '; private $borderFormat = '%s'; private $padType = \STR_PAD_RIGHT; /** * Sets padding character, used for cell padding. * * @return $this */ public function setPaddingChar(string $paddingChar) { if (!$paddingChar) { throw new LogicException('The padding char must not be empty.'); } $this->paddingChar = $paddingChar; return $this; } /** * Gets padding character, used for cell padding. * * @return string */ public function getPaddingChar() { return $this->paddingChar; } /** * Sets horizontal border characters. * * * â•”â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•╤â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•╤â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•— * 1 ISBN 2 Title │ Author â•‘ * â• â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•╪â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•╪â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•£ * â•‘ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri â•‘ * â•‘ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens â•‘ * â•‘ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien â•‘ * â•‘ 80-902734-1-6 │ And Then There Were None │ Agatha Christie â•‘ * ╚â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•§â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•§â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â• * */ public function setHorizontalBorderChars(string $outside, string $inside = null): self { $this->horizontalOutsideBorderChar = $outside; $this->horizontalInsideBorderChar = $inside ?? $outside; return $this; } /** * Sets vertical border characters. * * * â•”â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•╤â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•╤â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•— * â•‘ ISBN │ Title │ Author â•‘ * â• â•â•â•â•â•â•â•1â•â•â•â•â•â•â•╪â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•╪â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•£ * â•‘ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri â•‘ * â•‘ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens â•‘ * ╟───────2───────┼──────────────────────────┼──────────────────╢ * â•‘ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien â•‘ * â•‘ 80-902734-1-6 │ And Then There Were None │ Agatha Christie â•‘ * ╚â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•§â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•§â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â• * */ public function setVerticalBorderChars(string $outside, string $inside = null): self { $this->verticalOutsideBorderChar = $outside; $this->verticalInsideBorderChar = $inside ?? $outside; return $this; } /** * Gets border characters. * * @internal */ public function getBorderChars(): array { return [ $this->horizontalOutsideBorderChar, $this->verticalOutsideBorderChar, $this->horizontalInsideBorderChar, $this->verticalInsideBorderChar, ]; } /** * Sets crossing characters. * * Example: * * 1â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•2â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•2â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•3 * â•‘ ISBN │ Title │ Author â•‘ * 8'â•â•â•â•â•â•â•â•â•â•â•â•â•â•0'â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•0'â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•4' * â•‘ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri â•‘ * â•‘ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens â•‘ * 8───────────────0──────────────────────────0──────────────────4 * â•‘ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien â•‘ * â•‘ 80-902734-1-6 │ And Then There Were None │ Agatha Christie â•‘ * 7â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•6â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•6â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•5 * * * @param string $cross Crossing char (see #0 of example) * @param string $topLeft Top left char (see #1 of example) * @param string $topMid Top mid char (see #2 of example) * @param string $topRight Top right char (see #3 of example) * @param string $midRight Mid right char (see #4 of example) * @param string $bottomRight Bottom right char (see #5 of example) * @param string $bottomMid Bottom mid char (see #6 of example) * @param string $bottomLeft Bottom left char (see #7 of example) * @param string $midLeft Mid left char (see #8 of example) * @param string|null $topLeftBottom Top left bottom char (see #8' of example), equals to $midLeft if null * @param string|null $topMidBottom Top mid bottom char (see #0' of example), equals to $cross if null * @param string|null $topRightBottom Top right bottom char (see #4' of example), equals to $midRight if null */ public function setCrossingChars(string $cross, string $topLeft, string $topMid, string $topRight, string $midRight, string $bottomRight, string $bottomMid, string $bottomLeft, string $midLeft, string $topLeftBottom = null, string $topMidBottom = null, string $topRightBottom = null): self { $this->crossingChar = $cross; $this->crossingTopLeftChar = $topLeft; $this->crossingTopMidChar = $topMid; $this->crossingTopRightChar = $topRight; $this->crossingMidRightChar = $midRight; $this->crossingBottomRightChar = $bottomRight; $this->crossingBottomMidChar = $bottomMid; $this->crossingBottomLeftChar = $bottomLeft; $this->crossingMidLeftChar = $midLeft; $this->crossingTopLeftBottomChar = $topLeftBottom ?? $midLeft; $this->crossingTopMidBottomChar = $topMidBottom ?? $cross; $this->crossingTopRightBottomChar = $topRightBottom ?? $midRight; return $this; } /** * Sets default crossing character used for each cross. * * @see {@link setCrossingChars()} for setting each crossing individually. */ public function setDefaultCrossingChar(string $char): self { return $this->setCrossingChars($char, $char, $char, $char, $char, $char, $char, $char, $char); } /** * Gets crossing character. * * @return string */ public function getCrossingChar() { return $this->crossingChar; } /** * Gets crossing characters. * * @internal */ public function getCrossingChars(): array { return [ $this->crossingChar, $this->crossingTopLeftChar, $this->crossingTopMidChar, $this->crossingTopRightChar, $this->crossingMidRightChar, $this->crossingBottomRightChar, $this->crossingBottomMidChar, $this->crossingBottomLeftChar, $this->crossingMidLeftChar, $this->crossingTopLeftBottomChar, $this->crossingTopMidBottomChar, $this->crossingTopRightBottomChar, ]; } /** * Sets header cell format. * * @return $this */ public function setCellHeaderFormat(string $cellHeaderFormat) { $this->cellHeaderFormat = $cellHeaderFormat; return $this; } /** * Gets header cell format. * * @return string */ public function getCellHeaderFormat() { return $this->cellHeaderFormat; } /** * Sets row cell format. * * @return $this */ public function setCellRowFormat(string $cellRowFormat) { $this->cellRowFormat = $cellRowFormat; return $this; } /** * Gets row cell format. * * @return string */ public function getCellRowFormat() { return $this->cellRowFormat; } /** * Sets row cell content format. * * @return $this */ public function setCellRowContentFormat(string $cellRowContentFormat) { $this->cellRowContentFormat = $cellRowContentFormat; return $this; } /** * Gets row cell content format. * * @return string */ public function getCellRowContentFormat() { return $this->cellRowContentFormat; } /** * Sets table border format. * * @return $this */ public function setBorderFormat(string $borderFormat) { $this->borderFormat = $borderFormat; return $this; } /** * Gets table border format. * * @return string */ public function getBorderFormat() { return $this->borderFormat; } /** * Sets cell padding type. * * @return $this */ public function setPadType(int $padType) { if (!\in_array($padType, [\STR_PAD_LEFT, \STR_PAD_RIGHT, \STR_PAD_BOTH], true)) { throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).'); } $this->padType = $padType; return $this; } /** * Gets cell padding type. * * @return int */ public function getPadType() { return $this->padType; } public function getHeaderTitleFormat(): string { return $this->headerTitleFormat; } public function setHeaderTitleFormat(string $format): self { $this->headerTitleFormat = $format; return $this; } public function getFooterTitleFormat(): string { return $this->footerTitleFormat; } public function setFooterTitleFormat(string $format): self { $this->footerTitleFormat = $format; return $this; } } PK!âñs%WjWj Table.phpnuÕIw¶´ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Formatter\WrappableOutputFormatterInterface; use Symfony\Component\Console\Output\ConsoleSectionOutput; use Symfony\Component\Console\Output\OutputInterface; /** * Provides helpers to display a table. * * @author Fabien Potencier * @author Саша Стаменковић * @author Abdellatif Ait boudad * @author Max Grigorian * @author Dany Maillard */ class Table { private const SEPARATOR_TOP = 0; private const SEPARATOR_TOP_BOTTOM = 1; private const SEPARATOR_MID = 2; private const SEPARATOR_BOTTOM = 3; private const BORDER_OUTSIDE = 0; private const BORDER_INSIDE = 1; private $headerTitle; private $footerTitle; /** * Table headers. */ private $headers = []; /** * Table rows. */ private $rows = []; private $horizontal = false; /** * Column widths cache. */ private $effectiveColumnWidths = []; /** * Number of columns cache. * * @var int */ private $numberOfColumns; /** * @var OutputInterface */ private $output; /** * @var TableStyle */ private $style; /** * @var array */ private $columnStyles = []; /** * User set column widths. * * @var array */ private $columnWidths = []; private $columnMaxWidths = []; private static $styles; private $rendered = false; public function __construct(OutputInterface $output) { $this->output = $output; if (!self::$styles) { self::$styles = self::initStyles(); } $this->setStyle('default'); } /** * Sets a style definition. */ public static function setStyleDefinition(string $name, TableStyle $style) { if (!self::$styles) { self::$styles = self::initStyles(); } self::$styles[$name] = $style; } /** * Gets a style definition by name. * * @return TableStyle */ public static function getStyleDefinition(string $name) { if (!self::$styles) { self::$styles = self::initStyles(); } if (isset(self::$styles[$name])) { return self::$styles[$name]; } throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name)); } /** * Sets table style. * * @param TableStyle|string $name The style name or a TableStyle instance * * @return $this */ public function setStyle($name) { $this->style = $this->resolveStyle($name); return $this; } /** * Gets the current table style. * * @return TableStyle */ public function getStyle() { return $this->style; } /** * Sets table column style. * * @param TableStyle|string $name The style name or a TableStyle instance * * @return $this */ public function setColumnStyle(int $columnIndex, $name) { $this->columnStyles[$columnIndex] = $this->resolveStyle($name); return $this; } /** * Gets the current style for a column. * * If style was not set, it returns the global table style. * * @return TableStyle */ public function getColumnStyle(int $columnIndex) { return $this->columnStyles[$columnIndex] ?? $this->getStyle(); } /** * Sets the minimum width of a column. * * @return $this */ public function setColumnWidth(int $columnIndex, int $width) { $this->columnWidths[$columnIndex] = $width; return $this; } /** * Sets the minimum width of all columns. * * @return $this */ public function setColumnWidths(array $widths) { $this->columnWidths = []; foreach ($widths as $index => $width) { $this->setColumnWidth($index, $width); } return $this; } /** * Sets the maximum width of a column. * * Any cell within this column which contents exceeds the specified width will be wrapped into multiple lines, while * formatted strings are preserved. * * @return $this */ public function setColumnMaxWidth(int $columnIndex, int $width): self { if (!$this->output->getFormatter() instanceof WrappableOutputFormatterInterface) { throw new \LogicException(sprintf('Setting a maximum column width is only supported when using a "%s" formatter, got "%s".', WrappableOutputFormatterInterface::class, get_debug_type($this->output->getFormatter()))); } $this->columnMaxWidths[$columnIndex] = $width; return $this; } public function setHeaders(array $headers) { $headers = array_values($headers); if (!empty($headers) && !\is_array($headers[0])) { $headers = [$headers]; } $this->headers = $headers; return $this; } public function setRows(array $rows) { $this->rows = []; return $this->addRows($rows); } public function addRows(array $rows) { foreach ($rows as $row) { $this->addRow($row); } return $this; } public function addRow($row) { if ($row instanceof TableSeparator) { $this->rows[] = $row; return $this; } if (!\is_array($row)) { throw new InvalidArgumentException('A row must be an array or a TableSeparator instance.'); } $this->rows[] = array_values($row); return $this; } /** * Adds a row to the table, and re-renders the table. */ public function appendRow($row): self { if (!$this->output instanceof ConsoleSectionOutput) { throw new RuntimeException(sprintf('Output should be an instance of "%s" when calling "%s".', ConsoleSectionOutput::class, __METHOD__)); } if ($this->rendered) { $this->output->clear($this->calculateRowCount()); } $this->addRow($row); $this->render(); return $this; } public function setRow($column, array $row) { $this->rows[$column] = $row; return $this; } public function setHeaderTitle(?string $title): self { $this->headerTitle = $title; return $this; } public function setFooterTitle(?string $title): self { $this->footerTitle = $title; return $this; } public function setHorizontal(bool $horizontal = true): self { $this->horizontal = $horizontal; return $this; } /** * Renders table to output. * * Example: * * +---------------+-----------------------+------------------+ * | ISBN | Title | Author | * +---------------+-----------------------+------------------+ * | 99921-58-10-7 | Divine Comedy | Dante Alighieri | * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | * +---------------+-----------------------+------------------+ */ public function render() { $divider = new TableSeparator(); if ($this->horizontal) { $rows = []; foreach ($this->headers[0] ?? [] as $i => $header) { $rows[$i] = [$header]; foreach ($this->rows as $row) { if ($row instanceof TableSeparator) { continue; } if (isset($row[$i])) { $rows[$i][] = $row[$i]; } elseif ($rows[$i][0] instanceof TableCell && $rows[$i][0]->getColspan() >= 2) { // Noop, there is a "title" } else { $rows[$i][] = null; } } } } else { $rows = array_merge($this->headers, [$divider], $this->rows); } $this->calculateNumberOfColumns($rows); $rows = $this->buildTableRows($rows); $this->calculateColumnsWidth($rows); $isHeader = !$this->horizontal; $isFirstRow = $this->horizontal; foreach ($rows as $row) { if ($divider === $row) { $isHeader = false; $isFirstRow = true; continue; } if ($row instanceof TableSeparator) { $this->renderRowSeparator(); continue; } if (!$row) { continue; } if ($isHeader || $isFirstRow) { if ($isFirstRow) { $this->renderRowSeparator(self::SEPARATOR_TOP_BOTTOM); $isFirstRow = false; } else { $this->renderRowSeparator(self::SEPARATOR_TOP, $this->headerTitle, $this->style->getHeaderTitleFormat()); } } if ($this->horizontal) { $this->renderRow($row, $this->style->getCellRowFormat(), $this->style->getCellHeaderFormat()); } else { $this->renderRow($row, $isHeader ? $this->style->getCellHeaderFormat() : $this->style->getCellRowFormat()); } } $this->renderRowSeparator(self::SEPARATOR_BOTTOM, $this->footerTitle, $this->style->getFooterTitleFormat()); $this->cleanup(); $this->rendered = true; } /** * Renders horizontal header separator. * * Example: * * +-----+-----------+-------+ */ private function renderRowSeparator(int $type = self::SEPARATOR_MID, string $title = null, string $titleFormat = null) { if (0 === $count = $this->numberOfColumns) { return; } $borders = $this->style->getBorderChars(); if (!$borders[0] && !$borders[2] && !$this->style->getCrossingChar()) { return; } $crossings = $this->style->getCrossingChars(); if (self::SEPARATOR_MID === $type) { [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[2], $crossings[8], $crossings[0], $crossings[4]]; } elseif (self::SEPARATOR_TOP === $type) { [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[1], $crossings[2], $crossings[3]]; } elseif (self::SEPARATOR_TOP_BOTTOM === $type) { [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[9], $crossings[10], $crossings[11]]; } else { [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[7], $crossings[6], $crossings[5]]; } $markup = $leftChar; for ($column = 0; $column < $count; ++$column) { $markup .= str_repeat($horizontal, $this->effectiveColumnWidths[$column]); $markup .= $column === $count - 1 ? $rightChar : $midChar; } if (null !== $title) { $titleLength = Helper::strlenWithoutDecoration($formatter = $this->output->getFormatter(), $formattedTitle = sprintf($titleFormat, $title)); $markupLength = Helper::strlen($markup); if ($titleLength > $limit = $markupLength - 4) { $titleLength = $limit; $formatLength = Helper::strlenWithoutDecoration($formatter, sprintf($titleFormat, '')); $formattedTitle = sprintf($titleFormat, Helper::substr($title, 0, $limit - $formatLength - 3).'...'); } $titleStart = ($markupLength - $titleLength) / 2; if (false === mb_detect_encoding($markup, null, true)) { $markup = substr_replace($markup, $formattedTitle, $titleStart, $titleLength); } else { $markup = mb_substr($markup, 0, $titleStart).$formattedTitle.mb_substr($markup, $titleStart + $titleLength); } } $this->output->writeln(sprintf($this->style->getBorderFormat(), $markup)); } /** * Renders vertical column separator. */ private function renderColumnSeparator(int $type = self::BORDER_OUTSIDE): string { $borders = $this->style->getBorderChars(); return sprintf($this->style->getBorderFormat(), self::BORDER_OUTSIDE === $type ? $borders[1] : $borders[3]); } /** * Renders table row. * * Example: * * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | */ private function renderRow(array $row, string $cellFormat, string $firstCellFormat = null) { $rowContent = $this->renderColumnSeparator(self::BORDER_OUTSIDE); $columns = $this->getRowColumns($row); $last = \count($columns) - 1; foreach ($columns as $i => $column) { if ($firstCellFormat && 0 === $i) { $rowContent .= $this->renderCell($row, $column, $firstCellFormat); } else { $rowContent .= $this->renderCell($row, $column, $cellFormat); } $rowContent .= $this->renderColumnSeparator($last === $i ? self::BORDER_OUTSIDE : self::BORDER_INSIDE); } $this->output->writeln($rowContent); } /** * Renders table cell with padding. */ private function renderCell(array $row, int $column, string $cellFormat): string { $cell = isset($row[$column]) ? $row[$column] : ''; $width = $this->effectiveColumnWidths[$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->effectiveColumnWidths[$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) { return sprintf($style->getBorderFormat(), str_repeat($style->getBorderChars()[2], $width)); } $width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell); $content = sprintf($style->getCellRowContentFormat(), $cell); return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType())); } /** * Calculate number of columns for this table. */ private function calculateNumberOfColumns(array $rows) { $columns = [0]; foreach ($rows as $row) { if ($row instanceof TableSeparator) { continue; } $columns[] = $this->getNumberOfColumns($row); } $this->numberOfColumns = max($columns); } private function buildTableRows(array $rows): TableRows { /** @var WrappableOutputFormatterInterface $formatter */ $formatter = $this->output->getFormatter(); $unmergedRows = []; for ($rowKey = 0; $rowKey < \count($rows); ++$rowKey) { $rows = $this->fillNextRows($rows, $rowKey); // Remove any new line breaks and replace it with a new line foreach ($rows[$rowKey] as $column => $cell) { $colspan = $cell instanceof TableCell ? $cell->getColspan() : 1; if (isset($this->columnMaxWidths[$column]) && Helper::strlenWithoutDecoration($formatter, $cell) > $this->columnMaxWidths[$column]) { $cell = $formatter->formatAndWrap($cell, $this->columnMaxWidths[$column] * $colspan); } if (!strstr($cell, "\n")) { continue; } $escaped = implode("\n", array_map([OutputFormatter::class, 'escapeTrailingBackslash'], explode("\n", $cell))); $cell = $cell instanceof TableCell ? new TableCell($escaped, ['colspan' => $cell->getColspan()]) : $escaped; $lines = explode("\n", str_replace("\n", "\n", $cell)); foreach ($lines as $lineKey => $line) { if ($colspan > 1) { $line = new TableCell($line, ['colspan' => $colspan]); } if (0 === $lineKey) { $rows[$rowKey][$column] = $line; } else { if (!\array_key_exists($rowKey, $unmergedRows) || !\array_key_exists($lineKey, $unmergedRows[$rowKey])) { $unmergedRows[$rowKey][$lineKey] = $this->copyRow($rows, $rowKey); } $unmergedRows[$rowKey][$lineKey][$column] = $line; } } } } return new TableRows(function () use ($rows, $unmergedRows): \Traversable { foreach ($rows as $rowKey => $row) { yield $this->fillCells($row); if (isset($unmergedRows[$rowKey])) { foreach ($unmergedRows[$rowKey] as $unmergedRow) { yield $this->fillCells($unmergedRow); } } } }); } private function calculateRowCount(): int { $numberOfRows = \count(iterator_to_array($this->buildTableRows(array_merge($this->headers, [new TableSeparator()], $this->rows)))); if ($this->headers) { ++$numberOfRows; // Add row for header separator } if (\count($this->rows) > 0) { ++$numberOfRows; // Add row for footer separator } return $numberOfRows; } /** * fill rows that contains rowspan > 1. * * @throws InvalidArgumentException */ private function fillNextRows(array $rows, int $line): array { $unmergedRows = []; foreach ($rows[$line] as $column => $cell) { if (null !== $cell && !$cell instanceof TableCell && !is_scalar($cell) && !(\is_object($cell) && method_exists($cell, '__toString'))) { throw new InvalidArgumentException(sprintf('A cell must be a TableCell, a scalar or an object implementing "__toString()", "%s" given.', get_debug_type($cell))); } if ($cell instanceof TableCell && $cell->getRowspan() > 1) { $nbLines = $cell->getRowspan() - 1; $lines = [$cell]; if (strstr($cell, "\n")) { $lines = explode("\n", str_replace("\n", "\n", $cell)); $nbLines = \count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines; $rows[$line][$column] = new TableCell($lines[0], ['colspan' => $cell->getColspan()]); unset($lines[0]); } // create a two dimensional array (rowspan x colspan) $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, []), $unmergedRows); foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) { $value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : ''; $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, ['colspan' => $cell->getColspan()]); if ($nbLines === $unmergedRowKey - $line) { break; } } } } foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) { // we need to know if $unmergedRow will be merged or inserted into $rows if (isset($rows[$unmergedRowKey]) && \is_array($rows[$unmergedRowKey]) && ($this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns)) { foreach ($unmergedRow as $cellKey => $cell) { // insert cell into row at cellKey position array_splice($rows[$unmergedRowKey], $cellKey, 0, [$cell]); } } else { $row = $this->copyRow($rows, $unmergedRowKey - 1); foreach ($unmergedRow as $column => $cell) { if (!empty($cell)) { $row[$column] = $unmergedRow[$column]; } } array_splice($rows, $unmergedRowKey, 0, [$row]); } } return $rows; } /** * fill cells for a row that contains colspan > 1. */ private function fillCells($row) { $newRow = []; foreach ($row as $column => $cell) { $newRow[] = $cell; if ($cell instanceof TableCell && $cell->getColspan() > 1) { foreach (range($column + 1, $column + $cell->getColspan() - 1) as $position) { // insert empty value at column position $newRow[] = ''; } } } return $newRow ?: $row; } private function copyRow(array $rows, int $line): array { $row = $rows[$line]; foreach ($row as $cellKey => $cellValue) { $row[$cellKey] = ''; if ($cellValue instanceof TableCell) { $row[$cellKey] = new TableCell('', ['colspan' => $cellValue->getColspan()]); } } return $row; } /** * Gets number of columns by row. */ private function getNumberOfColumns(array $row): int { $columns = \count($row); foreach ($row as $column) { $columns += $column instanceof TableCell ? ($column->getColspan() - 1) : 0; } return $columns; } /** * Gets list of columns for the given row. */ private function getRowColumns(array $row): array { $columns = range(0, $this->numberOfColumns - 1); foreach ($row as $cellKey => $cell) { if ($cell instanceof TableCell && $cell->getColspan() > 1) { // exclude grouped columns. $columns = array_diff($columns, range($cellKey + 1, $cellKey + $cell->getColspan() - 1)); } } return $columns; } /** * Calculates columns widths. */ private function calculateColumnsWidth(iterable $rows) { for ($column = 0; $column < $this->numberOfColumns; ++$column) { $lengths = []; foreach ($rows as $row) { if ($row instanceof TableSeparator) { continue; } foreach ($row as $i => $cell) { if ($cell instanceof TableCell) { $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell); $textLength = Helper::strlen($textContent); if ($textLength > 0) { $contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan())); foreach ($contentColumns as $position => $content) { $row[$i + $position] = $content; } } } } $lengths[] = $this->getCellWidth($row, $column); } $this->effectiveColumnWidths[$column] = max($lengths) + Helper::strlen($this->style->getCellRowContentFormat()) - 2; } } private function getColumnSeparatorWidth(): int { return Helper::strlen(sprintf($this->style->getBorderFormat(), $this->style->getBorderChars()[3])); } private function getCellWidth(array $row, int $column): int { $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; $cellWidth = max($cellWidth, $columnWidth); return isset($this->columnMaxWidths[$column]) ? min($this->columnMaxWidths[$column], $cellWidth) : $cellWidth; } /** * Called after rendering to cleanup cache data. */ private function cleanup() { $this->effectiveColumnWidths = []; $this->numberOfColumns = null; } private static function initStyles(): array { $borderless = new TableStyle(); $borderless ->setHorizontalBorderChars('=') ->setVerticalBorderChars(' ') ->setDefaultCrossingChar(' ') ; $compact = new TableStyle(); $compact ->setHorizontalBorderChars('') ->setVerticalBorderChars(' ') ->setDefaultCrossingChar('') ->setCellRowContentFormat('%s') ; $styleGuide = new TableStyle(); $styleGuide ->setHorizontalBorderChars('-') ->setVerticalBorderChars(' ') ->setDefaultCrossingChar(' ') ->setCellHeaderFormat('%s') ; $box = (new TableStyle()) ->setHorizontalBorderChars('─') ->setVerticalBorderChars('│') ->setCrossingChars('┼', '┌', '┬', 'â”', '┤', '┘', 'â”´', 'â””', '├') ; $boxDouble = (new TableStyle()) ->setHorizontalBorderChars('â•', '─') ->setVerticalBorderChars('â•‘', '│') ->setCrossingChars('┼', 'â•”', '╤', 'â•—', 'â•¢', 'â•', 'â•§', '╚', '╟', 'â• ', '╪', 'â•£') ; return [ 'default' => new TableStyle(), 'borderless' => $borderless, 'compact' => $compact, 'symfony-style-guide' => $styleGuide, 'box' => $box, 'box-double' => $boxDouble, ]; } private function resolveStyle($name): TableStyle { if ($name instanceof TableStyle) { return $name; } if (isset(self::$styles[$name])) { return self::$styles[$name]; } throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name)); } } PK!øOºy y SymfonyQuestionHelper.phpnuÕIw¶´ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Question\Question; use Symfony\Component\Console\Style\SymfonyStyle; /** * Symfony Style Guide compliant question helper. * * @author Kevin Bond */ class SymfonyQuestionHelper extends QuestionHelper { /** * {@inheritdoc} */ protected function writePrompt(OutputInterface $output, Question $question) { $text = OutputFormatter::escapeTrailingBackslash($question->getQuestion()); $default = $question->getDefault(); switch (true) { case null === $default: $text = sprintf(' %s:', $text); break; case $question instanceof ConfirmationQuestion: $text = sprintf(' %s (yes/no) [%s]:', $text, $default ? 'yes' : 'no'); break; case $question instanceof ChoiceQuestion && $question->isMultiselect(): $choices = $question->getChoices(); $default = explode(',', $default); foreach ($default as $key => $value) { $default[$key] = $choices[trim($value)]; } $text = sprintf(' %s [%s]:', $text, OutputFormatter::escape(implode(', ', $default))); break; case $question instanceof ChoiceQuestion: $choices = $question->getChoices(); $text = sprintf(' %s [%s]:', $text, OutputFormatter::escape(isset($choices[$default]) ? $choices[$default] : $default)); break; default: $text = sprintf(' %s [%s]:', $text, OutputFormatter::escape($default)); } $output->writeln($text); $prompt = ' > '; if ($question instanceof ChoiceQuestion) { $output->writeln($this->formatChoiceQuestionChoices($question, 'comment')); $prompt = $question->getPrompt(); } $output->write($prompt); } /** * {@inheritdoc} */ protected function writeError(OutputInterface $output, \Exception $error) { if ($output instanceof SymfonyStyle) { $output->newLine(); $output->error($error->getMessage()); return; } parent::writeError($output, $error); } } PK!sß HëëInputAwareHelper.phpnu„[µü¤ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputAwareInterface; /** * An implementation of InputAwareInterface for Helpers. * * @author Wouter J */ abstract class InputAwareHelper extends Helper implements InputAwareInterface { protected $input; /** * {@inheritDoc} */ public function setInput(InputInterface $input) { $this->input = $input; } } PK!aí­©G G DebugFormatterHelper.phpnuÕIw¶´ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; /** * Helps outputting debug information when running an external program from a command. * * An external program can be a Process, an HTTP request, or anything else. * * @author Fabien Potencier */ class DebugFormatterHelper extends Helper { private $colors = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default']; private $started = []; private $count = -1; /** * Starts a debug formatting session. * * @return string */ public function start(string $id, string $message, string $prefix = 'RUN') { $this->started[$id] = ['border' => ++$this->count % \count($this->colors)]; return sprintf("%s %s %s\n", $this->getBorder($id), $prefix, $message); } /** * Adds progress to a formatting session. * * @return string */ public function progress(string $id, string $buffer, bool $error = false, string $prefix = 'OUT', string $errorPrefix = 'ERR') { $message = ''; if ($error) { if (isset($this->started[$id]['out'])) { $message .= "\n"; unset($this->started[$id]['out']); } if (!isset($this->started[$id]['err'])) { $message .= sprintf('%s %s ', $this->getBorder($id), $errorPrefix); $this->started[$id]['err'] = true; } $message .= str_replace("\n", sprintf("\n%s %s ", $this->getBorder($id), $errorPrefix), $buffer); } else { if (isset($this->started[$id]['err'])) { $message .= "\n"; unset($this->started[$id]['err']); } if (!isset($this->started[$id]['out'])) { $message .= sprintf('%s %s ', $this->getBorder($id), $prefix); $this->started[$id]['out'] = true; } $message .= str_replace("\n", sprintf("\n%s %s ", $this->getBorder($id), $prefix), $buffer); } return $message; } /** * Stops a formatting session. * * @return string */ public function stop(string $id, string $message, bool $successful, string $prefix = 'RES') { $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : ''; if ($successful) { return sprintf("%s%s %s %s\n", $trailingEOL, $this->getBorder($id), $prefix, $message); } $message = sprintf("%s%s %s %s\n", $trailingEOL, $this->getBorder($id), $prefix, $message); unset($this->started[$id]['out'], $this->started[$id]['err']); return $message; } private function getBorder(string $id): string { return sprintf(' ', $this->colors[$this->started[$id]['border']]); } /** * {@inheritdoc} */ public function getName() { return 'debug_formatter'; } } PK!"U¥1  DescriptorHelper.phpnu„[µü¤ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Descriptor\DescriptorInterface; use Symfony\Component\Console\Descriptor\JsonDescriptor; use Symfony\Component\Console\Descriptor\MarkdownDescriptor; use Symfony\Component\Console\Descriptor\TextDescriptor; use Symfony\Component\Console\Descriptor\XmlDescriptor; use Symfony\Component\Console\Output\OutputInterface; /** * This class adds helper method to describe objects in various formats. * * @author Jean-François Simon */ class DescriptorHelper extends Helper { /** * @var DescriptorInterface[] */ private $descriptors = array(); /** * Constructor. */ public function __construct() { $this ->register('txt', new TextDescriptor()) ->register('xml', new XmlDescriptor()) ->register('json', new JsonDescriptor()) ->register('md', new MarkdownDescriptor()) ; } /** * Describes an object if supported. * * Available options are: * * format: string, the output format name * * raw_text: boolean, sets output type as raw * * @param OutputInterface $output * @param object $object * @param array $options * * @throws \InvalidArgumentException */ public function describe(OutputInterface $output, $object, array $options = array()) { $options = array_merge(array( 'raw_text' => false, 'format' => 'txt', ), $options); if (!isset($this->descriptors[$options['format']])) { throw new \InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format'])); } $descriptor = $this->descriptors[$options['format']]; $descriptor->describe($output, $object, $options); } /** * Registers a descriptor. * * @param string $format * @param DescriptorInterface $descriptor * * @return DescriptorHelper */ public function register($format, DescriptorInterface $descriptor) { $this->descriptors[$format] = $descriptor; return $this; } /** * {@inheritdoc} */ public function getName() { return 'descriptor'; } } PK!$ÖÿUU TableRows.phpnuÕIw¶´ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; /** * @internal */ class TableRows implements \IteratorAggregate { private $generator; public function __construct(callable $generator) { $this->generator = $generator; } public function getIterator(): \Traversable { $g = $this->generator; return $g(); } } PK!½ûsû?û?QuestionHelper.phpnuÕIw¶´ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Cursor; use Symfony\Component\Console\Exception\MissingInputException; use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Formatter\OutputFormatterStyle; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\StreamableInputInterface; use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\ConsoleSectionOutput; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Console\Question\Question; use Symfony\Component\Console\Terminal; use function Symfony\Component\String\s; /** * The QuestionHelper class provides helpers to interact with the user. * * @author Fabien Potencier */ class QuestionHelper extends Helper { private $inputStream; private static $shell; private static $stty = true; private static $stdinIsInteractive; /** * Asks a question to the user. * * @return mixed The user answer * * @throws RuntimeException If there is no data to read in the input stream */ public function ask(InputInterface $input, OutputInterface $output, Question $question) { if ($output instanceof ConsoleOutputInterface) { $output = $output->getErrorOutput(); } if (!$input->isInteractive()) { return $this->getDefaultAnswer($question); } if ($input instanceof StreamableInputInterface && $stream = $input->getStream()) { $this->inputStream = $stream; } try { if (!$question->getValidator()) { return $this->doAsk($output, $question); } $interviewer = function () use ($output, $question) { return $this->doAsk($output, $question); }; return $this->validateAttempts($interviewer, $output, $question); } catch (MissingInputException $exception) { $input->setInteractive(false); if (null === $fallbackOutput = $this->getDefaultAnswer($question)) { throw $exception; } return $fallbackOutput; } } /** * {@inheritdoc} */ public function getName() { return 'question'; } /** * Prevents usage of stty. */ public static function disableStty() { self::$stty = false; } /** * Asks the question to the user. * * @return bool|mixed|string|null * * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden */ private function doAsk(OutputInterface $output, Question $question) { $this->writePrompt($output, $question); $inputStream = $this->inputStream ?: \STDIN; $autocomplete = $question->getAutocompleterCallback(); if (\function_exists('sapi_windows_cp_set')) { // Codepage used by cmd.exe on Windows to allow special characters (éàüñ). @sapi_windows_cp_set(1252); } if (null === $autocomplete || !self::$stty || !Terminal::hasSttyAvailable()) { $ret = false; if ($question->isHidden()) { try { $hiddenResponse = $this->getHiddenResponse($output, $inputStream, $question->isTrimmable()); $ret = $question->isTrimmable() ? trim($hiddenResponse) : $hiddenResponse; } catch (RuntimeException $e) { if (!$question->isHiddenFallback()) { throw $e; } } } if (false === $ret) { $ret = fgets($inputStream, 4096); if (false === $ret) { throw new MissingInputException('Aborted.'); } if ($question->isTrimmable()) { $ret = trim($ret); } } } else { $autocomplete = $this->autocomplete($output, $question, $inputStream, $autocomplete); $ret = $question->isTrimmable() ? trim($autocomplete) : $autocomplete; } if ($output instanceof ConsoleSectionOutput) { $output->addContent($ret); } $ret = \strlen($ret) > 0 ? $ret : $question->getDefault(); if ($normalizer = $question->getNormalizer()) { return $normalizer($ret); } return $ret; } /** * @return mixed */ private function getDefaultAnswer(Question $question) { $default = $question->getDefault(); if (null === $default) { return $default; } if ($validator = $question->getValidator()) { return \call_user_func($question->getValidator(), $default); } elseif ($question instanceof ChoiceQuestion) { $choices = $question->getChoices(); if (!$question->isMultiselect()) { return isset($choices[$default]) ? $choices[$default] : $default; } $default = explode(',', $default); foreach ($default as $k => $v) { $v = $question->isTrimmable() ? trim($v) : $v; $default[$k] = isset($choices[$v]) ? $choices[$v] : $v; } } return $default; } /** * Outputs the question prompt. */ protected function writePrompt(OutputInterface $output, Question $question) { $message = $question->getQuestion(); if ($question instanceof ChoiceQuestion) { $output->writeln(array_merge([ $question->getQuestion(), ], $this->formatChoiceQuestionChoices($question, 'info'))); $message = $question->getPrompt(); } $output->write($message); } /** * @return string[] */ protected function formatChoiceQuestionChoices(ChoiceQuestion $question, string $tag) { $messages = []; $maxWidth = max(array_map('self::strlen', array_keys($choices = $question->getChoices()))); foreach ($choices as $key => $value) { $padding = str_repeat(' ', $maxWidth - self::strlen($key)); $messages[] = sprintf(" [<$tag>%s$padding] %s", $key, $value); } return $messages; } /** * Outputs an error message. */ protected function writeError(OutputInterface $output, \Exception $error) { if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) { $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error'); } else { $message = ''.$error->getMessage().''; } $output->writeln($message); } /** * Autocompletes a question. * * @param resource $inputStream */ private function autocomplete(OutputInterface $output, Question $question, $inputStream, callable $autocomplete): string { $cursor = new Cursor($output, $inputStream); $fullChoice = ''; $ret = ''; $i = 0; $ofs = -1; $matches = $autocomplete($ret); $numMatches = \count($matches); $sttyMode = shell_exec('stty -g'); // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead) shell_exec('stty -icanon -echo'); // Add highlighted text style $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white')); // Read a keypress while (!feof($inputStream)) { $c = fread($inputStream, 1); // as opposed to fgets(), fread() returns an empty string when the stream content is empty, not false. if (false === $c || ('' === $ret && '' === $c && null === $question->getDefault())) { shell_exec(sprintf('stty %s', $sttyMode)); throw new MissingInputException('Aborted.'); } elseif ("\177" === $c) { // Backspace Character if (0 === $numMatches && 0 !== $i) { --$i; $cursor->moveLeft(s($fullChoice)->slice(-1)->width(false)); $fullChoice = self::substr($fullChoice, 0, $i); } if (0 === $i) { $ofs = -1; $matches = $autocomplete($ret); $numMatches = \count($matches); } else { $numMatches = 0; } // Pop the last character off the end of our string $ret = self::substr($ret, 0, $i); } elseif ("\033" === $c) { // Did we read an escape sequence? $c .= fread($inputStream, 2); // A = Up Arrow. B = Down Arrow if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) { if ('A' === $c[2] && -1 === $ofs) { $ofs = 0; } if (0 === $numMatches) { continue; } $ofs += ('A' === $c[2]) ? -1 : 1; $ofs = ($numMatches + $ofs) % $numMatches; } } elseif (\ord($c) < 32) { if ("\t" === $c || "\n" === $c) { if ($numMatches > 0 && -1 !== $ofs) { $ret = (string) $matches[$ofs]; // Echo out remaining chars for current match $remainingCharacters = substr($ret, \strlen(trim($this->mostRecentlyEnteredValue($fullChoice)))); $output->write($remainingCharacters); $fullChoice .= $remainingCharacters; $i = self::strlen($fullChoice); $matches = array_filter( $autocomplete($ret), function ($match) use ($ret) { return '' === $ret || 0 === strpos($match, $ret); } ); $numMatches = \count($matches); $ofs = -1; } if ("\n" === $c) { $output->write($c); break; } $numMatches = 0; } continue; } else { if ("\x80" <= $c) { $c .= fread($inputStream, ["\xC0" => 1, "\xD0" => 1, "\xE0" => 2, "\xF0" => 3][$c & "\xF0"]); } $output->write($c); $ret .= $c; $fullChoice .= $c; ++$i; $tempRet = $ret; if ($question instanceof ChoiceQuestion && $question->isMultiselect()) { $tempRet = $this->mostRecentlyEnteredValue($fullChoice); } $numMatches = 0; $ofs = 0; foreach ($autocomplete($ret) as $value) { // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle) if (0 === strpos($value, $tempRet)) { $matches[$numMatches++] = $value; } } } $cursor->clearLineAfter(); if ($numMatches > 0 && -1 !== $ofs) { $cursor->savePosition(); // Write highlighted text, complete the partially entered response $charactersEntered = \strlen(trim($this->mostRecentlyEnteredValue($fullChoice))); $output->write(''.OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $charactersEntered)).''); $cursor->restorePosition(); } } // Reset stty so it behaves normally again shell_exec(sprintf('stty %s', $sttyMode)); return $fullChoice; } private function mostRecentlyEnteredValue(string $entered): string { // Determine the most recent value that the user entered if (false === strpos($entered, ',')) { return $entered; } $choices = explode(',', $entered); if (\strlen($lastChoice = trim($choices[\count($choices) - 1])) > 0) { return $lastChoice; } return $entered; } /** * Gets a hidden response from user. * * @param resource $inputStream The handler resource * @param bool $trimmable Is the answer trimmable * * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden */ private function getHiddenResponse(OutputInterface $output, $inputStream, bool $trimmable = true): string { if ('\\' === \DIRECTORY_SEPARATOR) { $exe = __DIR__.'/../Resources/bin/hiddeninput.exe'; // handle code running from a phar if ('phar:' === substr(__FILE__, 0, 5)) { $tmpExe = sys_get_temp_dir().'/hiddeninput.exe'; copy($exe, $tmpExe); $exe = $tmpExe; } $sExec = shell_exec($exe); $value = $trimmable ? rtrim($sExec) : $sExec; $output->writeln(''); if (isset($tmpExe)) { unlink($tmpExe); } return $value; } if (self::$stty && Terminal::hasSttyAvailable()) { $sttyMode = shell_exec('stty -g'); shell_exec('stty -echo'); } elseif ($this->isInteractiveInput($inputStream)) { throw new RuntimeException('Unable to hide the response.'); } $value = fgets($inputStream, 4096); if (self::$stty && Terminal::hasSttyAvailable()) { shell_exec(sprintf('stty %s', $sttyMode)); } if (false === $value) { throw new MissingInputException('Aborted.'); } if ($trimmable) { $value = trim($value); } $output->writeln(''); return $value; } /** * Validates an attempt. * * @param callable $interviewer A callable that will ask for a question and return the result * * @return mixed The validated response * * @throws \Exception In case the max number of attempts has been reached and no valid response has been given */ private function validateAttempts(callable $interviewer, OutputInterface $output, Question $question) { $error = null; $attempts = $question->getMaxAttempts(); while (null === $attempts || $attempts--) { if (null !== $error) { $this->writeError($output, $error); } try { return $question->getValidator()($interviewer()); } catch (RuntimeException $e) { throw $e; } catch (\Exception $error) { } } throw $error; } private function isInteractiveInput($inputStream): bool { if ('php://stdin' !== (stream_get_meta_data($inputStream)['uri'] ?? null)) { return false; } if (null !== self::$stdinIsInteractive) { return self::$stdinIsInteractive; } if (\function_exists('stream_isatty')) { return self::$stdinIsInteractive = stream_isatty(fopen('php://stdin', 'r')); } if (\function_exists('posix_isatty')) { return self::$stdinIsInteractive = posix_isatty(fopen('php://stdin', 'r')); } if (!\function_exists('exec')) { return self::$stdinIsInteractive = true; } exec('stty 2> /dev/null', $output, $status); return self::$stdinIsInteractive = 1 !== $status; } } PK!Z\§«« Helper.phpnu„[µü¤ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; /** * Helper is the base class for all helper classes. * * @author Fabien Potencier */ abstract class Helper implements HelperInterface { protected $helperSet = null; /** * Sets the helper set associated with this helper. * * @param HelperSet $helperSet A HelperSet instance */ public function setHelperSet(HelperSet $helperSet = null) { $this->helperSet = $helperSet; } /** * Gets the helper set associated with this helper. * * @return HelperSet A HelperSet instance */ public function getHelperSet() { return $this->helperSet; } /** * Returns the length of a string, using mb_strlen if it is available. * * @param string $string The string to check its length * * @return integer The length of the string */ protected function strlen($string) { if (!function_exists('mb_strlen')) { return strlen($string); } if (false === $encoding = mb_detect_encoding($string)) { return strlen($string); } return mb_strlen($string, $encoding); } } PK!&Šª TableSeparator.phpnuÕIw¶´ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; /** * Marks a row as being a separator. * * @author Fabien Potencier */ class TableSeparator extends TableCell { public function __construct(array $options = []) { parent::__construct('', $options); } } PK!•¹Þ Þ HelperSet.phpnu„[µü¤ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Command\Command; /** * HelperSet represents a set of helpers to be used with a command. * * @author Fabien Potencier */ class HelperSet implements \IteratorAggregate { private $helpers = array(); private $command; /** * Constructor. * * @param Helper[] $helpers An array of helper. */ public function __construct(array $helpers = array()) { foreach ($helpers as $alias => $helper) { $this->set($helper, is_int($alias) ? null : $alias); } } /** * Sets a helper. * * @param HelperInterface $helper The helper instance * @param string $alias An alias */ public function set(HelperInterface $helper, $alias = null) { $this->helpers[$helper->getName()] = $helper; if (null !== $alias) { $this->helpers[$alias] = $helper; } $helper->setHelperSet($this); } /** * Returns true if the helper if defined. * * @param string $name The helper name * * @return Boolean true if the helper is defined, false otherwise */ public function has($name) { return isset($this->helpers[$name]); } /** * Gets a helper value. * * @param string $name The helper name * * @return HelperInterface The helper instance * * @throws \InvalidArgumentException if the helper is not defined */ public function get($name) { if (!$this->has($name)) { throw new \InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name)); } return $this->helpers[$name]; } /** * Sets the command associated with this helper set. * * @param Command $command A Command instance */ public function setCommand(Command $command = null) { $this->command = $command; } /** * Gets the command associated with this helper set. * * @return Command A Command instance */ public function getCommand() { return $this->command; } public function getIterator() { return new \ArrayIterator($this->helpers); } } PK!ŠùR ProgressIndicator.phpnuÕIw¶´ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Exception\LogicException; use Symfony\Component\Console\Output\OutputInterface; /** * @author Kevin Bond */ class ProgressIndicator { private $output; private $startTime; private $format; private $message; private $indicatorValues; private $indicatorCurrent; private $indicatorChangeInterval; private $indicatorUpdateTime; private $started = false; private static $formatters; private static $formats; /** * @param int $indicatorChangeInterval Change interval in milliseconds * @param array|null $indicatorValues Animated indicator characters */ public function __construct(OutputInterface $output, string $format = null, int $indicatorChangeInterval = 100, array $indicatorValues = null) { $this->output = $output; if (null === $format) { $format = $this->determineBestFormat(); } if (null === $indicatorValues) { $indicatorValues = ['-', '\\', '|', '/']; } $indicatorValues = array_values($indicatorValues); if (2 > \count($indicatorValues)) { throw new InvalidArgumentException('Must have at least 2 indicator value characters.'); } $this->format = self::getFormatDefinition($format); $this->indicatorChangeInterval = $indicatorChangeInterval; $this->indicatorValues = $indicatorValues; $this->startTime = time(); } /** * Sets the current indicator message. */ public function setMessage(?string $message) { $this->message = $message; $this->display(); } /** * Starts the indicator output. */ public function start(string $message) { if ($this->started) { throw new LogicException('Progress indicator already started.'); } $this->message = $message; $this->started = true; $this->startTime = time(); $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval; $this->indicatorCurrent = 0; $this->display(); } /** * Advances the indicator. */ public function advance() { if (!$this->started) { throw new LogicException('Progress indicator has not yet been started.'); } if (!$this->output->isDecorated()) { return; } $currentTime = $this->getCurrentTimeInMilliseconds(); if ($currentTime < $this->indicatorUpdateTime) { return; } $this->indicatorUpdateTime = $currentTime + $this->indicatorChangeInterval; ++$this->indicatorCurrent; $this->display(); } /** * Finish the indicator with message. * * @param $message */ public function finish(string $message) { if (!$this->started) { throw new LogicException('Progress indicator has not yet been started.'); } $this->message = $message; $this->display(); $this->output->writeln(''); $this->started = false; } /** * Gets the format for a given name. * * @return string|null A format string */ public static function getFormatDefinition(string $name) { if (!self::$formats) { self::$formats = self::initFormats(); } return isset(self::$formats[$name]) ? self::$formats[$name] : null; } /** * Sets a placeholder formatter for a given name. * * This method also allow you to override an existing placeholder. */ public static function setPlaceholderFormatterDefinition(string $name, callable $callable) { if (!self::$formatters) { self::$formatters = self::initPlaceholderFormatters(); } self::$formatters[$name] = $callable; } /** * Gets the placeholder formatter for a given name (including the delimiter char like %). * * @return callable|null A PHP callable */ public static function getPlaceholderFormatterDefinition(string $name) { if (!self::$formatters) { self::$formatters = self::initPlaceholderFormatters(); } return isset(self::$formatters[$name]) ? self::$formatters[$name] : null; } private function display() { if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) { return; } $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) { if ($formatter = self::getPlaceholderFormatterDefinition($matches[1])) { return $formatter($this); } return $matches[0]; }, $this->format)); } private function determineBestFormat(): string { switch ($this->output->getVerbosity()) { // OutputInterface::VERBOSITY_QUIET: display is disabled anyway case OutputInterface::VERBOSITY_VERBOSE: return $this->output->isDecorated() ? 'verbose' : 'verbose_no_ansi'; case OutputInterface::VERBOSITY_VERY_VERBOSE: case OutputInterface::VERBOSITY_DEBUG: return $this->output->isDecorated() ? 'very_verbose' : 'very_verbose_no_ansi'; default: return $this->output->isDecorated() ? 'normal' : 'normal_no_ansi'; } } /** * Overwrites a previous message to the output. */ private function overwrite(string $message) { if ($this->output->isDecorated()) { $this->output->write("\x0D\x1B[2K"); $this->output->write($message); } else { $this->output->writeln($message); } } private function getCurrentTimeInMilliseconds(): float { return round(microtime(true) * 1000); } private static function initPlaceholderFormatters(): array { return [ 'indicator' => function (self $indicator) { return $indicator->indicatorValues[$indicator->indicatorCurrent % \count($indicator->indicatorValues)]; }, 'message' => function (self $indicator) { return $indicator->message; }, 'elapsed' => function (self $indicator) { return Helper::formatTime(time() - $indicator->startTime); }, 'memory' => function () { return Helper::formatMemory(memory_get_usage(true)); }, ]; } private static function initFormats(): array { return [ 'normal' => ' %indicator% %message%', 'normal_no_ansi' => ' %message%', 'verbose' => ' %indicator% %message% (%elapsed:6s%)', 'verbose_no_ansi' => ' %message% (%elapsed:6s%)', 'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)', 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)', ]; } } PK!Cï[Ü`Ü`HTML.phpnu„[µü¤ 'f0f8ff', 'antiquewhite' => 'faebd7', 'antiquewhite1' => 'ffefdb', 'antiquewhite2' => 'eedfcc', 'antiquewhite3' => 'cdc0b0', 'antiquewhite4' => '8b8378', 'aqua' => '00ffff', 'aquamarine1' => '7fffd4', 'aquamarine2' => '76eec6', 'aquamarine4' => '458b74', 'azure1' => 'f0ffff', 'azure2' => 'e0eeee', 'azure3' => 'c1cdcd', 'azure4' => '838b8b', 'beige' => 'f5f5dc', 'bisque1' => 'ffe4c4', 'bisque2' => 'eed5b7', 'bisque3' => 'cdb79e', 'bisque4' => '8b7d6b', 'black' => '000000', 'blanchedalmond' => 'ffebcd', 'blue' => '0000ff', 'blue1' => '0000ff', 'blue2' => '0000ee', 'blue4' => '00008b', 'blueviolet' => '8a2be2', 'brown' => 'a52a2a', 'brown1' => 'ff4040', 'brown2' => 'ee3b3b', 'brown3' => 'cd3333', 'brown4' => '8b2323', 'burlywood' => 'deb887', 'burlywood1' => 'ffd39b', 'burlywood2' => 'eec591', 'burlywood3' => 'cdaa7d', 'burlywood4' => '8b7355', 'cadetblue' => '5f9ea0', 'cadetblue1' => '98f5ff', 'cadetblue2' => '8ee5ee', 'cadetblue3' => '7ac5cd', 'cadetblue4' => '53868b', 'chartreuse1' => '7fff00', 'chartreuse2' => '76ee00', 'chartreuse3' => '66cd00', 'chartreuse4' => '458b00', 'chocolate' => 'd2691e', 'chocolate1' => 'ff7f24', 'chocolate2' => 'ee7621', 'chocolate3' => 'cd661d', 'coral' => 'ff7f50', 'coral1' => 'ff7256', 'coral2' => 'ee6a50', 'coral3' => 'cd5b45', 'coral4' => '8b3e2f', 'cornflowerblue' => '6495ed', 'cornsilk1' => 'fff8dc', 'cornsilk2' => 'eee8cd', 'cornsilk3' => 'cdc8b1', 'cornsilk4' => '8b8878', 'cyan1' => '00ffff', 'cyan2' => '00eeee', 'cyan3' => '00cdcd', 'cyan4' => '008b8b', 'darkgoldenrod' => 'b8860b', 'darkgoldenrod1' => 'ffb90f', 'darkgoldenrod2' => 'eead0e', 'darkgoldenrod3' => 'cd950c', 'darkgoldenrod4' => '8b6508', 'darkgreen' => '006400', 'darkkhaki' => 'bdb76b', 'darkolivegreen' => '556b2f', 'darkolivegreen1' => 'caff70', 'darkolivegreen2' => 'bcee68', 'darkolivegreen3' => 'a2cd5a', 'darkolivegreen4' => '6e8b3d', 'darkorange' => 'ff8c00', 'darkorange1' => 'ff7f00', 'darkorange2' => 'ee7600', 'darkorange3' => 'cd6600', 'darkorange4' => '8b4500', 'darkorchid' => '9932cc', 'darkorchid1' => 'bf3eff', 'darkorchid2' => 'b23aee', 'darkorchid3' => '9a32cd', 'darkorchid4' => '68228b', 'darksalmon' => 'e9967a', 'darkseagreen' => '8fbc8f', 'darkseagreen1' => 'c1ffc1', 'darkseagreen2' => 'b4eeb4', 'darkseagreen3' => '9bcd9b', 'darkseagreen4' => '698b69', 'darkslateblue' => '483d8b', 'darkslategray' => '2f4f4f', 'darkslategray1' => '97ffff', 'darkslategray2' => '8deeee', 'darkslategray3' => '79cdcd', 'darkslategray4' => '528b8b', 'darkturquoise' => '00ced1', 'darkviolet' => '9400d3', 'deeppink1' => 'ff1493', 'deeppink2' => 'ee1289', 'deeppink3' => 'cd1076', 'deeppink4' => '8b0a50', 'deepskyblue1' => '00bfff', 'deepskyblue2' => '00b2ee', 'deepskyblue3' => '009acd', 'deepskyblue4' => '00688b', 'dimgray' => '696969', 'dodgerblue1' => '1e90ff', 'dodgerblue2' => '1c86ee', 'dodgerblue3' => '1874cd', 'dodgerblue4' => '104e8b', 'firebrick' => 'b22222', 'firebrick1' => 'ff3030', 'firebrick2' => 'ee2c2c', 'firebrick3' => 'cd2626', 'firebrick4' => '8b1a1a', 'floralwhite' => 'fffaf0', 'forestgreen' => '228b22', 'fuchsia' => 'ff00ff', 'gainsboro' => 'dcdcdc', 'ghostwhite' => 'f8f8ff', 'gold1' => 'ffd700', 'gold2' => 'eec900', 'gold3' => 'cdad00', 'gold4' => '8b7500', 'goldenrod' => 'daa520', 'goldenrod1' => 'ffc125', 'goldenrod2' => 'eeb422', 'goldenrod3' => 'cd9b1d', 'goldenrod4' => '8b6914', 'gray' => 'bebebe', 'gray1' => '030303', 'gray10' => '1a1a1a', 'gray11' => '1c1c1c', 'gray12' => '1f1f1f', 'gray13' => '212121', 'gray14' => '242424', 'gray15' => '262626', 'gray16' => '292929', 'gray17' => '2b2b2b', 'gray18' => '2e2e2e', 'gray19' => '303030', 'gray2' => '050505', 'gray20' => '333333', 'gray21' => '363636', 'gray22' => '383838', 'gray23' => '3b3b3b', 'gray24' => '3d3d3d', 'gray25' => '404040', 'gray26' => '424242', 'gray27' => '454545', 'gray28' => '474747', 'gray29' => '4a4a4a', 'gray3' => '080808', 'gray30' => '4d4d4d', 'gray31' => '4f4f4f', 'gray32' => '525252', 'gray33' => '545454', 'gray34' => '575757', 'gray35' => '595959', 'gray36' => '5c5c5c', 'gray37' => '5e5e5e', 'gray38' => '616161', 'gray39' => '636363', 'gray4' => '0a0a0a', 'gray40' => '666666', 'gray41' => '696969', 'gray42' => '6b6b6b', 'gray43' => '6e6e6e', 'gray44' => '707070', 'gray45' => '737373', 'gray46' => '757575', 'gray47' => '787878', 'gray48' => '7a7a7a', 'gray49' => '7d7d7d', 'gray5' => '0d0d0d', 'gray50' => '7f7f7f', 'gray51' => '828282', 'gray52' => '858585', 'gray53' => '878787', 'gray54' => '8a8a8a', 'gray55' => '8c8c8c', 'gray56' => '8f8f8f', 'gray57' => '919191', 'gray58' => '949494', 'gray59' => '969696', 'gray6' => '0f0f0f', 'gray60' => '999999', 'gray61' => '9c9c9c', 'gray62' => '9e9e9e', 'gray63' => 'a1a1a1', 'gray64' => 'a3a3a3', 'gray65' => 'a6a6a6', 'gray66' => 'a8a8a8', 'gray67' => 'ababab', 'gray68' => 'adadad', 'gray69' => 'b0b0b0', 'gray7' => '121212', 'gray70' => 'b3b3b3', 'gray71' => 'b5b5b5', 'gray72' => 'b8b8b8', 'gray73' => 'bababa', 'gray74' => 'bdbdbd', 'gray75' => 'bfbfbf', 'gray76' => 'c2c2c2', 'gray77' => 'c4c4c4', 'gray78' => 'c7c7c7', 'gray79' => 'c9c9c9', 'gray8' => '141414', 'gray80' => 'cccccc', 'gray81' => 'cfcfcf', 'gray82' => 'd1d1d1', 'gray83' => 'd4d4d4', 'gray84' => 'd6d6d6', 'gray85' => 'd9d9d9', 'gray86' => 'dbdbdb', 'gray87' => 'dedede', 'gray88' => 'e0e0e0', 'gray89' => 'e3e3e3', 'gray9' => '171717', 'gray90' => 'e5e5e5', 'gray91' => 'e8e8e8', 'gray92' => 'ebebeb', 'gray93' => 'ededed', 'gray94' => 'f0f0f0', 'gray95' => 'f2f2f2', 'gray97' => 'f7f7f7', 'gray98' => 'fafafa', 'gray99' => 'fcfcfc', 'green' => '00ff00', 'green1' => '00ff00', 'green2' => '00ee00', 'green3' => '00cd00', 'green4' => '008b00', 'greenyellow' => 'adff2f', 'honeydew1' => 'f0fff0', 'honeydew2' => 'e0eee0', 'honeydew3' => 'c1cdc1', 'honeydew4' => '838b83', 'hotpink' => 'ff69b4', 'hotpink1' => 'ff6eb4', 'hotpink2' => 'ee6aa7', 'hotpink3' => 'cd6090', 'hotpink4' => '8b3a62', 'indianred' => 'cd5c5c', 'indianred1' => 'ff6a6a', 'indianred2' => 'ee6363', 'indianred3' => 'cd5555', 'indianred4' => '8b3a3a', 'ivory1' => 'fffff0', 'ivory2' => 'eeeee0', 'ivory3' => 'cdcdc1', 'ivory4' => '8b8b83', 'khaki' => 'f0e68c', 'khaki1' => 'fff68f', 'khaki2' => 'eee685', 'khaki3' => 'cdc673', 'khaki4' => '8b864e', 'lavender' => 'e6e6fa', 'lavenderblush1' => 'fff0f5', 'lavenderblush2' => 'eee0e5', 'lavenderblush3' => 'cdc1c5', 'lavenderblush4' => '8b8386', 'lawngreen' => '7cfc00', 'lemonchiffon1' => 'fffacd', 'lemonchiffon2' => 'eee9bf', 'lemonchiffon3' => 'cdc9a5', 'lemonchiffon4' => '8b8970', 'light' => 'eedd82', 'lightblue' => 'add8e6', 'lightblue1' => 'bfefff', 'lightblue2' => 'b2dfee', 'lightblue3' => '9ac0cd', 'lightblue4' => '68838b', 'lightcoral' => 'f08080', 'lightcyan1' => 'e0ffff', 'lightcyan2' => 'd1eeee', 'lightcyan3' => 'b4cdcd', 'lightcyan4' => '7a8b8b', 'lightgoldenrod1' => 'ffec8b', 'lightgoldenrod2' => 'eedc82', 'lightgoldenrod3' => 'cdbe70', 'lightgoldenrod4' => '8b814c', 'lightgoldenrodyellow' => 'fafad2', 'lightgray' => 'd3d3d3', 'lightpink' => 'ffb6c1', 'lightpink1' => 'ffaeb9', 'lightpink2' => 'eea2ad', 'lightpink3' => 'cd8c95', 'lightpink4' => '8b5f65', 'lightsalmon1' => 'ffa07a', 'lightsalmon2' => 'ee9572', 'lightsalmon3' => 'cd8162', 'lightsalmon4' => '8b5742', 'lightseagreen' => '20b2aa', 'lightskyblue' => '87cefa', 'lightskyblue1' => 'b0e2ff', 'lightskyblue2' => 'a4d3ee', 'lightskyblue3' => '8db6cd', 'lightskyblue4' => '607b8b', 'lightslateblue' => '8470ff', 'lightslategray' => '778899', 'lightsteelblue' => 'b0c4de', 'lightsteelblue1' => 'cae1ff', 'lightsteelblue2' => 'bcd2ee', 'lightsteelblue3' => 'a2b5cd', 'lightsteelblue4' => '6e7b8b', 'lightyellow1' => 'ffffe0', 'lightyellow2' => 'eeeed1', 'lightyellow3' => 'cdcdb4', 'lightyellow4' => '8b8b7a', 'lime' => '00ff00', 'limegreen' => '32cd32', 'linen' => 'faf0e6', 'magenta' => 'ff00ff', 'magenta2' => 'ee00ee', 'magenta3' => 'cd00cd', 'magenta4' => '8b008b', 'maroon' => 'b03060', 'maroon1' => 'ff34b3', 'maroon2' => 'ee30a7', 'maroon3' => 'cd2990', 'maroon4' => '8b1c62', 'medium' => '66cdaa', 'mediumaquamarine' => '66cdaa', 'mediumblue' => '0000cd', 'mediumorchid' => 'ba55d3', 'mediumorchid1' => 'e066ff', 'mediumorchid2' => 'd15fee', 'mediumorchid3' => 'b452cd', 'mediumorchid4' => '7a378b', 'mediumpurple' => '9370db', 'mediumpurple1' => 'ab82ff', 'mediumpurple2' => '9f79ee', 'mediumpurple3' => '8968cd', 'mediumpurple4' => '5d478b', 'mediumseagreen' => '3cb371', 'mediumslateblue' => '7b68ee', 'mediumspringgreen' => '00fa9a', 'mediumturquoise' => '48d1cc', 'mediumvioletred' => 'c71585', 'midnightblue' => '191970', 'mintcream' => 'f5fffa', 'mistyrose1' => 'ffe4e1', 'mistyrose2' => 'eed5d2', 'mistyrose3' => 'cdb7b5', 'mistyrose4' => '8b7d7b', 'moccasin' => 'ffe4b5', 'navajowhite1' => 'ffdead', 'navajowhite2' => 'eecfa1', 'navajowhite3' => 'cdb38b', 'navajowhite4' => '8b795e', 'navy' => '000080', 'navyblue' => '000080', 'oldlace' => 'fdf5e6', 'olive' => '808000', 'olivedrab' => '6b8e23', 'olivedrab1' => 'c0ff3e', 'olivedrab2' => 'b3ee3a', 'olivedrab4' => '698b22', 'orange' => 'ffa500', 'orange1' => 'ffa500', 'orange2' => 'ee9a00', 'orange3' => 'cd8500', 'orange4' => '8b5a00', 'orangered1' => 'ff4500', 'orangered2' => 'ee4000', 'orangered3' => 'cd3700', 'orangered4' => '8b2500', 'orchid' => 'da70d6', 'orchid1' => 'ff83fa', 'orchid2' => 'ee7ae9', 'orchid3' => 'cd69c9', 'orchid4' => '8b4789', 'pale' => 'db7093', 'palegoldenrod' => 'eee8aa', 'palegreen' => '98fb98', 'palegreen1' => '9aff9a', 'palegreen2' => '90ee90', 'palegreen3' => '7ccd7c', 'palegreen4' => '548b54', 'paleturquoise' => 'afeeee', 'paleturquoise1' => 'bbffff', 'paleturquoise2' => 'aeeeee', 'paleturquoise3' => '96cdcd', 'paleturquoise4' => '668b8b', 'palevioletred' => 'db7093', 'palevioletred1' => 'ff82ab', 'palevioletred2' => 'ee799f', 'palevioletred3' => 'cd6889', 'palevioletred4' => '8b475d', 'papayawhip' => 'ffefd5', 'peachpuff1' => 'ffdab9', 'peachpuff2' => 'eecbad', 'peachpuff3' => 'cdaf95', 'peachpuff4' => '8b7765', 'pink' => 'ffc0cb', 'pink1' => 'ffb5c5', 'pink2' => 'eea9b8', 'pink3' => 'cd919e', 'pink4' => '8b636c', 'plum' => 'dda0dd', 'plum1' => 'ffbbff', 'plum2' => 'eeaeee', 'plum3' => 'cd96cd', 'plum4' => '8b668b', 'powderblue' => 'b0e0e6', 'purple' => 'a020f0', 'rebeccapurple' => '663399', 'purple1' => '9b30ff', 'purple2' => '912cee', 'purple3' => '7d26cd', 'purple4' => '551a8b', 'red' => 'ff0000', 'red1' => 'ff0000', 'red2' => 'ee0000', 'red3' => 'cd0000', 'red4' => '8b0000', 'rosybrown' => 'bc8f8f', 'rosybrown1' => 'ffc1c1', 'rosybrown2' => 'eeb4b4', 'rosybrown3' => 'cd9b9b', 'rosybrown4' => '8b6969', 'royalblue' => '4169e1', 'royalblue1' => '4876ff', 'royalblue2' => '436eee', 'royalblue3' => '3a5fcd', 'royalblue4' => '27408b', 'saddlebrown' => '8b4513', 'salmon' => 'fa8072', 'salmon1' => 'ff8c69', 'salmon2' => 'ee8262', 'salmon3' => 'cd7054', 'salmon4' => '8b4c39', 'sandybrown' => 'f4a460', 'seagreen1' => '54ff9f', 'seagreen2' => '4eee94', 'seagreen3' => '43cd80', 'seagreen4' => '2e8b57', 'seashell1' => 'fff5ee', 'seashell2' => 'eee5de', 'seashell3' => 'cdc5bf', 'seashell4' => '8b8682', 'sienna' => 'a0522d', 'sienna1' => 'ff8247', 'sienna2' => 'ee7942', 'sienna3' => 'cd6839', 'sienna4' => '8b4726', 'silver' => 'c0c0c0', 'skyblue' => '87ceeb', 'skyblue1' => '87ceff', 'skyblue2' => '7ec0ee', 'skyblue3' => '6ca6cd', 'skyblue4' => '4a708b', 'slateblue' => '6a5acd', 'slateblue1' => '836fff', 'slateblue2' => '7a67ee', 'slateblue3' => '6959cd', 'slateblue4' => '473c8b', 'slategray' => '708090', 'slategray1' => 'c6e2ff', 'slategray2' => 'b9d3ee', 'slategray3' => '9fb6cd', 'slategray4' => '6c7b8b', 'snow1' => 'fffafa', 'snow2' => 'eee9e9', 'snow3' => 'cdc9c9', 'snow4' => '8b8989', 'springgreen1' => '00ff7f', 'springgreen2' => '00ee76', 'springgreen3' => '00cd66', 'springgreen4' => '008b45', 'steelblue' => '4682b4', 'steelblue1' => '63b8ff', 'steelblue2' => '5cacee', 'steelblue3' => '4f94cd', 'steelblue4' => '36648b', 'tan' => 'd2b48c', 'tan1' => 'ffa54f', 'tan2' => 'ee9a49', 'tan3' => 'cd853f', 'tan4' => '8b5a2b', 'teal' => '008080', 'thistle' => 'd8bfd8', 'thistle1' => 'ffe1ff', 'thistle2' => 'eed2ee', 'thistle3' => 'cdb5cd', 'thistle4' => '8b7b8b', 'tomato1' => 'ff6347', 'tomato2' => 'ee5c42', 'tomato3' => 'cd4f39', 'tomato4' => '8b3626', 'turquoise' => '40e0d0', 'turquoise1' => '00f5ff', 'turquoise2' => '00e5ee', 'turquoise3' => '00c5cd', 'turquoise4' => '00868b', 'violet' => 'ee82ee', 'violetred' => 'd02090', 'violetred1' => 'ff3e96', 'violetred2' => 'ee3a8c', 'violetred3' => 'cd3278', 'violetred4' => '8b2252', 'wheat' => 'f5deb3', 'wheat1' => 'ffe7ba', 'wheat2' => 'eed8ae', 'wheat3' => 'cdba96', 'wheat4' => '8b7e66', 'white' => 'ffffff', 'whitesmoke' => 'f5f5f5', 'yellow' => 'ffff00', 'yellow1' => 'ffff00', 'yellow2' => 'eeee00', 'yellow3' => 'cdcd00', 'yellow4' => '8b8b00', 'yellowgreen' => '9acd32', ); protected $face; protected $size; protected $color; protected $bold = false; protected $italic = false; protected $underline = false; protected $superscript = false; protected $subscript = false; protected $strikethrough = false; protected $startTagCallbacks = array( 'font' => 'startFontTag', 'b' => 'startBoldTag', 'strong' => 'startBoldTag', 'i' => 'startItalicTag', 'em' => 'startItalicTag', 'u' => 'startUnderlineTag', 'ins' => 'startUnderlineTag', 'del' => 'startStrikethruTag', 'sup' => 'startSuperscriptTag', 'sub' => 'startSubscriptTag', ); protected $endTagCallbacks = array( 'font' => 'endFontTag', 'b' => 'endBoldTag', 'strong' => 'endBoldTag', 'i' => 'endItalicTag', 'em' => 'endItalicTag', 'u' => 'endUnderlineTag', 'ins' => 'endUnderlineTag', 'del' => 'endStrikethruTag', 'sup' => 'endSuperscriptTag', 'sub' => 'endSubscriptTag', 'br' => 'breakTag', 'p' => 'breakTag', 'h1' => 'breakTag', 'h2' => 'breakTag', 'h3' => 'breakTag', 'h4' => 'breakTag', 'h5' => 'breakTag', 'h6' => 'breakTag', ); protected $stack = array(); protected $stringData = ''; protected $richTextObject; protected function initialise() { $this->face = $this->size = $this->color = null; $this->bold = $this->italic = $this->underline = $this->superscript = $this->subscript = $this->strikethrough = false; $this->stack = array(); $this->stringData = ''; } public function toRichTextObject($html) { $this->initialise(); // Create a new DOM object $dom = new \DOMDocument; // Load the HTML file into the DOM object // Note the use of error suppression, because typically this will be an html fragment, so not fully valid markup $loaded = @$dom->loadHTML($html); // Discard excess white space $dom->preserveWhiteSpace = false; $this->richTextObject = new PHPExcel_RichText();; $this->parseElements($dom); // Clean any further spurious whitespace $this->cleanWhitespace(); return $this->richTextObject; } protected function cleanWhitespace() { foreach ($this->richTextObject->getRichTextElements() as $key => $element) { $text = $element->getText(); // Trim any leading spaces on the first run if ($key == 0) { $text = ltrim($text); } // Trim any spaces immediately after a line break $text = preg_replace('/\n */mu', "\n", $text); $element->setText($text); } } protected function buildTextRun() { $text = $this->stringData; if (trim($text) === '') { return; } $richtextRun = $this->richTextObject->createTextRun($this->stringData); if ($this->face) { $richtextRun->getFont()->setName($this->face); } if ($this->size) { $richtextRun->getFont()->setSize($this->size); } if ($this->color) { $richtextRun->getFont()->setColor(new PHPExcel_Style_Color('ff' . $this->color)); } if ($this->bold) { $richtextRun->getFont()->setBold(true); } if ($this->italic) { $richtextRun->getFont()->setItalic(true); } if ($this->underline) { $richtextRun->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLE); } if ($this->superscript) { $richtextRun->getFont()->setSuperScript(true); } if ($this->subscript) { $richtextRun->getFont()->setSubScript(true); } if ($this->strikethrough) { $richtextRun->getFont()->setStrikethrough(true); } $this->stringData = ''; } protected function rgbToColour($rgb) { preg_match_all('/\d+/', $rgb, $values); foreach ($values[0] as &$value) { $value = str_pad(dechex($value), 2, '0', STR_PAD_LEFT); } return implode($values[0]); } protected function colourNameLookup($rgb) { return self::$colourMap[$rgb]; } protected function startFontTag($tag) { foreach ($tag->attributes as $attribute) { $attributeName = strtolower($attribute->name); $attributeValue = $attribute->value; if ($attributeName == 'color') { if (preg_match('/rgb\s*\(/', $attributeValue)) { $this->$attributeName = $this->rgbToColour($attributeValue); } elseif (strpos(trim($attributeValue), '#') === 0) { $this->$attributeName = ltrim($attributeValue, '#'); } else { $this->$attributeName = $this->colourNameLookup($attributeValue); } } else { $this->$attributeName = $attributeValue; } } } protected function endFontTag() { $this->face = $this->size = $this->color = null; } protected function startBoldTag() { $this->bold = true; } protected function endBoldTag() { $this->bold = false; } protected function startItalicTag() { $this->italic = true; } protected function endItalicTag() { $this->italic = false; } protected function startUnderlineTag() { $this->underline = true; } protected function endUnderlineTag() { $this->underline = false; } protected function startSubscriptTag() { $this->subscript = true; } protected function endSubscriptTag() { $this->subscript = false; } protected function startSuperscriptTag() { $this->superscript = true; } protected function endSuperscriptTag() { $this->superscript = false; } protected function startStrikethruTag() { $this->strikethrough = true; } protected function endStrikethruTag() { $this->strikethrough = false; } protected function breakTag() { $this->stringData .= "\n"; } protected function parseTextNode(DOMText $textNode) { $domText = preg_replace( '/\s+/u', ' ', str_replace(array("\r", "\n"), ' ', $textNode->nodeValue) ); $this->stringData .= $domText; $this->buildTextRun(); } protected function handleCallback($element, $callbackTag, $callbacks) { if (isset($callbacks[$callbackTag])) { $elementHandler = $callbacks[$callbackTag]; if (method_exists($this, $elementHandler)) { call_user_func(array($this, $elementHandler), $element); } } } protected function parseElementNode(DOMElement $element) { $callbackTag = strtolower($element->nodeName); $this->stack[] = $callbackTag; $this->handleCallback($element, $callbackTag, $this->startTagCallbacks); $this->parseElements($element); array_pop($this->stack); $this->handleCallback($element, $callbackTag, $this->endTagCallbacks); } protected function parseElements(DOMNode $element) { foreach ($element->childNodes as $child) { if ($child instanceof DOMText) { $this->parseTextNode($child); } elseif ($child instanceof DOMElement) { $this->parseElementNode($child); } } } } PK!ë¡¿22TableHelper.phpnu„[µü¤ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Output\OutputInterface; use InvalidArgumentException; /** * Provides helpers to display table output. * * @author Саша Стаменковић */ class TableHelper extends Helper { const LAYOUT_DEFAULT = 0; const LAYOUT_BORDERLESS = 1; const LAYOUT_COMPACT = 2; /** * Table headers. * * @var array */ private $headers = array(); /** * Table rows. * * @var array */ private $rows = array(); // Rendering options private $paddingChar; private $horizontalBorderChar; private $verticalBorderChar; private $crossingChar; private $cellHeaderFormat; private $cellRowFormat; private $cellRowContentFormat; private $borderFormat; private $padType; /** * Column widths cache. * * @var array */ private $columnWidths = array(); /** * Number of columns cache. * * @var array */ private $numberOfColumns; /** * @var OutputInterface */ private $output; public function __construct() { $this->setLayout(self::LAYOUT_DEFAULT); } /** * Sets table layout type. * * @param int $layout self::LAYOUT_* * * @return TableHelper */ public function setLayout($layout) { switch ($layout) { case self::LAYOUT_BORDERLESS: $this ->setPaddingChar(' ') ->setHorizontalBorderChar('=') ->setVerticalBorderChar(' ') ->setCrossingChar(' ') ->setCellHeaderFormat('%s') ->setCellRowFormat('%s') ->setCellRowContentFormat(' %s ') ->setBorderFormat('%s') ->setPadType(STR_PAD_RIGHT) ; break; case self::LAYOUT_COMPACT: $this ->setPaddingChar(' ') ->setHorizontalBorderChar('') ->setVerticalBorderChar(' ') ->setCrossingChar('') ->setCellHeaderFormat('%s') ->setCellRowFormat('%s') ->setCellRowContentFormat('%s') ->setBorderFormat('%s') ->setPadType(STR_PAD_RIGHT) ; break; case self::LAYOUT_DEFAULT: $this ->setPaddingChar(' ') ->setHorizontalBorderChar('-') ->setVerticalBorderChar('|') ->setCrossingChar('+') ->setCellHeaderFormat('%s') ->setCellRowFormat('%s') ->setCellRowContentFormat(' %s ') ->setBorderFormat('%s') ->setPadType(STR_PAD_RIGHT) ; break; default: throw new InvalidArgumentException(sprintf('Invalid table layout "%s".', $layout)); break; }; return $this; } public function setHeaders(array $headers) { $this->headers = array_values($headers); return $this; } public function setRows(array $rows) { $this->rows = array(); return $this->addRows($rows); } public function addRows(array $rows) { foreach ($rows as $row) { $this->addRow($row); } return $this; } public function addRow(array $row) { $this->rows[] = array_values($row); $keys = array_keys($this->rows); $rowKey = array_pop($keys); foreach ($row as $key => $cellValue) { if (!strstr($cellValue, "\n")) { continue; } $lines = explode("\n", $cellValue); $this->rows[$rowKey][$key] = $lines[0]; unset($lines[0]); foreach ($lines as $lineKey => $line) { $nextRowKey = $rowKey + $lineKey + 1; if (isset($this->rows[$nextRowKey])) { $this->rows[$nextRowKey][$key] = $line; } else { $this->rows[$nextRowKey] = array($key => $line); } } } return $this; } public function setRow($column, array $row) { $this->rows[$column] = $row; return $this; } /** * Sets padding character, used for cell padding. * * @param string $paddingChar * * @return TableHelper */ public function setPaddingChar($paddingChar) { if (!$paddingChar) { throw new \LogicException('The padding char must not be empty'); } $this->paddingChar = $paddingChar; return $this; } /** * Sets horizontal border character. * * @param string $horizontalBorderChar * * @return TableHelper */ public function setHorizontalBorderChar($horizontalBorderChar) { $this->horizontalBorderChar = $horizontalBorderChar; return $this; } /** * Sets vertical border character. * * @param string $verticalBorderChar * * @return TableHelper */ public function setVerticalBorderChar($verticalBorderChar) { $this->verticalBorderChar = $verticalBorderChar; return $this; } /** * Sets crossing character. * * @param string $crossingChar * * @return TableHelper */ public function setCrossingChar($crossingChar) { $this->crossingChar = $crossingChar; return $this; } /** * Sets header cell format. * * @param string $cellHeaderFormat * * @return TableHelper */ public function setCellHeaderFormat($cellHeaderFormat) { $this->cellHeaderFormat = $cellHeaderFormat; return $this; } /** * Sets row cell format. * * @param string $cellRowFormat * * @return TableHelper */ public function setCellRowFormat($cellRowFormat) { $this->cellRowFormat = $cellRowFormat; return $this; } /** * Sets row cell content format. * * @param string $cellRowContentFormat * * @return TableHelper */ public function setCellRowContentFormat($cellRowContentFormat) { $this->cellRowContentFormat = $cellRowContentFormat; return $this; } /** * Sets table border format. * * @param string $borderFormat * * @return TableHelper */ public function setBorderFormat($borderFormat) { $this->borderFormat = $borderFormat; return $this; } /** * Sets cell padding type. * * @param integer $padType STR_PAD_* * * @return TableHelper */ public function setPadType($padType) { $this->padType = $padType; return $this; } /** * Renders table to output. * * Example: * +---------------+-----------------------+------------------+ * | ISBN | Title | Author | * +---------------+-----------------------+------------------+ * | 99921-58-10-7 | Divine Comedy | Dante Alighieri | * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | * +---------------+-----------------------+------------------+ * * @param OutputInterface $output */ public function render(OutputInterface $output) { $this->output = $output; $this->renderRowSeparator(); $this->renderRow($this->headers, $this->cellHeaderFormat); if (!empty($this->headers)) { $this->renderRowSeparator(); } foreach ($this->rows as $row) { $this->renderRow($row, $this->cellRowFormat); } if (!empty($this->rows)) { $this->renderRowSeparator(); } $this->cleanup(); } /** * Renders horizontal header separator. * * Example: +-----+-----------+-------+ */ private function renderRowSeparator() { if (0 === $count = $this->getNumberOfColumns()) { return; } if (!$this->horizontalBorderChar && !$this->crossingChar) { return; } $markup = $this->crossingChar; for ($column = 0; $column < $count; $column++) { $markup .= str_repeat($this->horizontalBorderChar, $this->getColumnWidth($column)).$this->crossingChar; } $this->output->writeln(sprintf($this->borderFormat, $markup)); } /** * Renders vertical column separator. */ private function renderColumnSeparator() { $this->output->write(sprintf($this->borderFormat, $this->verticalBorderChar)); } /** * Renders table row. * * Example: | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | * * @param array $row * @param string $cellFormat */ private function renderRow(array $row, $cellFormat) { if (empty($row)) { return; } $this->renderColumnSeparator(); for ($column = 0, $count = $this->getNumberOfColumns(); $column < $count; $column++) { $this->renderCell($row, $column, $cellFormat); $this->renderColumnSeparator(); } $this->output->writeln(''); } /** * Renders table cell with padding. * * @param array $row * @param integer $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_strlen') && false !== $encoding = mb_detect_encoding($cell)) { $width += strlen($cell) - mb_strlen($cell, $encoding); } $width += $this->strlen($cell) - $this->computeLengthWithoutDecoration($cell); $content = sprintf($this->cellRowContentFormat, $cell); $this->output->write(sprintf($cellFormat, str_pad($content, $width, $this->paddingChar, $this->padType))); } /** * Gets number of columns for this table. * * @return int */ private function getNumberOfColumns() { if (null !== $this->numberOfColumns) { return $this->numberOfColumns; } $columns = array(0); $columns[] = count($this->headers); foreach ($this->rows as $row) { $columns[] = count($row); } return $this->numberOfColumns = max($columns); } /** * Gets column width. * * @param integer $column * * @return int */ private function getColumnWidth($column) { if (isset($this->columnWidths[$column])) { return $this->columnWidths[$column]; } $lengths = array(0); $lengths[] = $this->getCellWidth($this->headers, $column); foreach ($this->rows as $row) { $lengths[] = $this->getCellWidth($row, $column); } return $this->columnWidths[$column] = max($lengths) + strlen($this->cellRowContentFormat) - 2; } /** * Gets cell width. * * @param array $row * @param integer $column * * @return int */ private function getCellWidth(array $row, $column) { return isset($row[$column]) ? $this->computeLengthWithoutDecoration($row[$column]) : 0; } /** * Called after rendering to cleanup cache data. */ private function cleanup() { $this->columnWidths = array(); $this->numberOfColumns = null; } private function computeLengthWithoutDecoration($string) { $formatter = $this->output->getFormatter(); $isDecorated = $formatter->isDecorated(); $formatter->setDecorated(false); $string = $formatter->format($string); $formatter->setDecorated($isDecorated); return $this->strlen($string); } /** * {@inheritDoc} */ public function getName() { return 'table'; } } PK!|po.o.ProgressHelper.phpnu„[µü¤ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Output\OutputInterface; /** * The Progress class provides helpers to display progress output. * * @author Chris Jones * @author Fabien Potencier */ class ProgressHelper extends Helper { const FORMAT_QUIET = ' %percent%%'; const FORMAT_NORMAL = ' %current%/%max% [%bar%] %percent%%'; const FORMAT_VERBOSE = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%'; const FORMAT_QUIET_NOMAX = ' %current%'; const FORMAT_NORMAL_NOMAX = ' %current% [%bar%]'; const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%'; // options private $barWidth = 28; private $barChar = '='; private $emptyBarChar = '-'; private $progressChar = '>'; private $format = null; private $redrawFreq = 1; private $lastMessagesLength; private $barCharOriginal; /** * @var OutputInterface */ private $output; /** * Current step * * @var integer */ private $current; /** * Maximum number of steps * * @var integer */ private $max; /** * Start time of the progress bar * * @var integer */ private $startTime; /** * List of formatting variables * * @var array */ private $defaultFormatVars = array( 'current', 'max', 'bar', 'percent', 'elapsed', ); /** * Available formatting variables * * @var array */ private $formatVars; /** * Stored format part widths (used for padding) * * @var array */ private $widths = array( 'current' => 4, 'max' => 4, 'percent' => 3, 'elapsed' => 6, ); /** * Various time formats * * @var array */ private $timeFormats = array( array(0, '???'), array(2, '1 sec'), array(59, 'secs', 1), array(60, '1 min'), array(3600, 'mins', 60), array(5400, '1 hr'), array(86400, 'hrs', 3600), array(129600, '1 day'), array(604800, 'days', 86400), ); /** * Sets the progress bar width. * * @param int $size The progress bar size */ public function setBarWidth($size) { $this->barWidth = (int) $size; } /** * Sets the bar character. * * @param string $char A character */ public function setBarCharacter($char) { $this->barChar = $char; } /** * Sets the empty bar character. * * @param string $char A character */ public function setEmptyBarCharacter($char) { $this->emptyBarChar = $char; } /** * Sets the progress bar character. * * @param string $char A character */ public function setProgressCharacter($char) { $this->progressChar = $char; } /** * Sets the progress bar format. * * @param string $format The format */ public function setFormat($format) { $this->format = $format; } /** * Sets the redraw frequency. * * @param int $freq The frequency in steps */ public function setRedrawFrequency($freq) { $this->redrawFreq = (int) $freq; } /** * Starts the progress output. * * @param OutputInterface $output An Output instance * @param integer|null $max Maximum steps */ public function start(OutputInterface $output, $max = null) { $this->startTime = time(); $this->current = 0; $this->max = (int) $max; $this->output = $output; $this->lastMessagesLength = 0; $this->barCharOriginal = ''; if (null === $this->format) { switch ($output->getVerbosity()) { case OutputInterface::VERBOSITY_QUIET: $this->format = self::FORMAT_QUIET_NOMAX; if ($this->max > 0) { $this->format = self::FORMAT_QUIET; } break; case OutputInterface::VERBOSITY_VERBOSE: case OutputInterface::VERBOSITY_VERY_VERBOSE: case OutputInterface::VERBOSITY_DEBUG: $this->format = self::FORMAT_VERBOSE_NOMAX; if ($this->max > 0) { $this->format = self::FORMAT_VERBOSE; } break; default: $this->format = self::FORMAT_NORMAL_NOMAX; if ($this->max > 0) { $this->format = self::FORMAT_NORMAL; } break; } } $this->initialize(); } /** * Advances the progress output X steps. * * @param integer $step Number of steps to advance * @param Boolean $redraw Whether to redraw or not * * @throws \LogicException */ public function advance($step = 1, $redraw = false) { $this->setCurrent($this->current + $step, $redraw); } /** * Sets the current progress. * * @param integer $current The current progress * @param Boolean $redraw Whether to redraw or not * * @throws \LogicException */ public function setCurrent($current, $redraw = false) { if (null === $this->startTime) { throw new \LogicException('You must start the progress bar before calling setCurrent().'); } $current = (int) $current; if ($current < $this->current) { throw new \LogicException('You can\'t regress the progress bar'); } if (0 === $this->current) { $redraw = true; } $prevPeriod = intval($this->current / $this->redrawFreq); $this->current = $current; $currPeriod = intval($this->current / $this->redrawFreq); if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) { $this->display(); } } /** * Outputs the current progress string. * * @param Boolean $finish Forces the end result * * @throws \LogicException */ public function display($finish = false) { if (null === $this->startTime) { throw new \LogicException('You must start the progress bar before calling display().'); } $message = $this->format; foreach ($this->generate($finish) as $name => $value) { $message = str_replace("%{$name}%", $value, $message); } $this->overwrite($this->output, $message); } /** * Removes the progress bar from the current line. * * This is useful if you wish to write some output * while a progress bar is running. * Call display() to show the progress bar again. */ public function clear() { $this->overwrite($this->output, ''); } /** * Finishes the progress output. */ public function finish() { if (null === $this->startTime) { throw new \LogicException('You must start the progress bar before calling finish().'); } if (null !== $this->startTime) { if (!$this->max) { $this->barChar = $this->barCharOriginal; $this->display(true); } $this->startTime = null; $this->output->writeln(''); $this->output = null; } } /** * Initializes the progress helper. */ private function initialize() { $this->formatVars = array(); foreach ($this->defaultFormatVars as $var) { if (false !== strpos($this->format, "%{$var}%")) { $this->formatVars[$var] = true; } } if ($this->max > 0) { $this->widths['max'] = $this->strlen($this->max); $this->widths['current'] = $this->widths['max']; } else { $this->barCharOriginal = $this->barChar; $this->barChar = $this->emptyBarChar; } } /** * Generates the array map of format variables to values. * * @param Boolean $finish Forces the end result * * @return array Array of format vars and values */ private function generate($finish = false) { $vars = array(); $percent = 0; if ($this->max > 0) { $percent = (float) $this->current / $this->max; } if (isset($this->formatVars['bar'])) { $completeBars = 0; if ($this->max > 0) { $completeBars = floor($percent * $this->barWidth); } else { if (!$finish) { $completeBars = floor($this->current % $this->barWidth); } else { $completeBars = $this->barWidth; } } $emptyBars = $this->barWidth - $completeBars - $this->strlen($this->progressChar); $bar = str_repeat($this->barChar, $completeBars); if ($completeBars < $this->barWidth) { $bar .= $this->progressChar; $bar .= str_repeat($this->emptyBarChar, $emptyBars); } $vars['bar'] = $bar; } if (isset($this->formatVars['elapsed'])) { $elapsed = time() - $this->startTime; $vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT); } if (isset($this->formatVars['current'])) { $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT); } if (isset($this->formatVars['max'])) { $vars['max'] = $this->max; } if (isset($this->formatVars['percent'])) { $vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT); } return $vars; } /** * Converts seconds into human-readable format. * * @param integer $secs Number of seconds * * @return string Time in readable format */ private function humaneTime($secs) { $text = ''; foreach ($this->timeFormats as $format) { if ($secs < $format[0]) { if (count($format) == 2) { $text = $format[1]; break; } else { $text = ceil($secs / $format[2]).' '.$format[1]; break; } } } return $text; } /** * Overwrites a previous message to the output. * * @param OutputInterface $output An Output instance * @param string $message The message */ private function overwrite(OutputInterface $output, $message) { $length = $this->strlen($message); // append whitespace to match the last line's length if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) { $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT); } // carriage return $output->write("\x0D"); $output->write($message); $this->lastMessagesLength = $this->strlen($message); } /** * {@inheritDoc} */ public function getName() { return 'progress'; } } PK!&â>@>@DialogHelper.phpnu„[µü¤ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Formatter\OutputFormatterStyle; /** * The Dialog class provides helpers to interact with the user. * * @author Fabien Potencier */ class DialogHelper extends InputAwareHelper { private $inputStream; private static $shell; private static $stty; /** * Asks the user to select a value. * * @param OutputInterface $output An Output instance * @param string|array $question The question to ask * @param array $choices List of choices to pick from * @param Boolean|string $default The default answer if the user enters nothing * @param Boolean|integer $attempts Max number of times to ask before giving up (false by default, which means infinite) * @param string $errorMessage Message which will be shown if invalid value from choice list would be picked * @param Boolean $multiselect Select more than one value separated by comma * * @return integer|string|array The selected value or values (the key of the choices array) * * @throws \InvalidArgumentException */ public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false) { $width = max(array_map('strlen', array_keys($choices))); $messages = (array) $question; foreach ($choices as $key => $value) { $messages[] = sprintf(" [%-${width}s] %s", $key, $value); } $output->writeln($messages); $result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage, $multiselect) { // Collapse all spaces. $selectedChoices = str_replace(" ", "", $picked); if ($multiselect) { // Check for a separated comma values if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) { throw new \InvalidArgumentException(sprintf($errorMessage, $picked)); } $selectedChoices = explode(",", $selectedChoices); } else { $selectedChoices = array($picked); } $multiselectChoices = array(); foreach ($selectedChoices as $value) { if (empty($choices[$value])) { throw new \InvalidArgumentException(sprintf($errorMessage, $value)); } array_push($multiselectChoices, $value); } if ($multiselect) { return $multiselectChoices; } return $picked; }, $attempts, $default); return $result; } /** * Asks a question to the user. * * @param OutputInterface $output An Output instance * @param string|array $question The question to ask * @param string $default The default answer if none is given by the user * @param array $autocomplete List of values to autocomplete * * @return string The user answer * * @throws \RuntimeException If there is no data to read in the input stream */ public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null) { if ($this->input && !$this->input->isInteractive()) { return $default; } $output->write($question); $inputStream = $this->inputStream ?: STDIN; if (null === $autocomplete || !$this->hasSttyAvailable()) { $ret = fgets($inputStream, 4096); if (false === $ret) { throw new \RuntimeException('Aborted'); } $ret = trim($ret); } else { $ret = ''; $i = 0; $ofs = -1; $matches = $autocomplete; $numMatches = count($matches); $sttyMode = shell_exec('stty -g'); // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead) shell_exec('stty -icanon -echo'); // Add highlighted text style $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white')); // Read a keypress while (!feof($inputStream)) { $c = fread($inputStream, 1); // Backspace Character if ("\177" === $c) { if (0 === $numMatches && 0 !== $i) { $i--; // Move cursor backwards $output->write("\033[1D"); } if ($i === 0) { $ofs = -1; $matches = $autocomplete; $numMatches = count($matches); } else { $numMatches = 0; } // Pop the last character off the end of our string $ret = substr($ret, 0, $i); } elseif ("\033" === $c) { // Did we read an escape sequence? $c .= fread($inputStream, 2); // A = Up Arrow. B = Down Arrow if ('A' === $c[2] || 'B' === $c[2]) { if ('A' === $c[2] && -1 === $ofs) { $ofs = 0; } if (0 === $numMatches) { continue; } $ofs += ('A' === $c[2]) ? -1 : 1; $ofs = ($numMatches + $ofs) % $numMatches; } } elseif (ord($c) < 32) { if ("\t" === $c || "\n" === $c) { if ($numMatches > 0 && -1 !== $ofs) { $ret = $matches[$ofs]; // Echo out remaining chars for current match $output->write(substr($ret, $i)); $i = strlen($ret); } if ("\n" === $c) { $output->write($c); break; } $numMatches = 0; } continue; } else { $output->write($c); $ret .= $c; $i++; $numMatches = 0; $ofs = 0; foreach ($autocomplete as $value) { // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle) if (0 === strpos($value, $ret) && $i !== strlen($value)) { $matches[$numMatches++] = $value; } } } // Erase characters from cursor to end of line $output->write("\033[K"); if ($numMatches > 0 && -1 !== $ofs) { // Save cursor position $output->write("\0337"); // Write highlighted text $output->write(''.substr($matches[$ofs], $i).''); // Restore cursor position $output->write("\0338"); } } // Reset stty so it behaves normally again shell_exec(sprintf('stty %s', $sttyMode)); } return strlen($ret) > 0 ? $ret : $default; } /** * Asks a confirmation to the user. * * The question will be asked until the user answers by nothing, yes, or no. * * @param OutputInterface $output An Output instance * @param string|array $question The question to ask * @param Boolean $default The default answer if the user enters nothing * * @return Boolean true if the user has confirmed, false otherwise */ public function askConfirmation(OutputInterface $output, $question, $default = true) { $answer = 'z'; while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) { $answer = $this->ask($output, $question); } if (false === $default) { return $answer && 'y' == strtolower($answer[0]); } return !$answer || 'y' == strtolower($answer[0]); } /** * Asks a question to the user, the response is hidden * * @param OutputInterface $output An Output instance * @param string|array $question The question * @param Boolean $fallback In case the response can not be hidden, whether to fallback on non-hidden question or not * * @return string The answer * * @throws \RuntimeException In case the fallback is deactivated and the response can not be hidden */ public function askHiddenResponse(OutputInterface $output, $question, $fallback = true) { if (defined('PHP_WINDOWS_VERSION_BUILD')) { $exe = __DIR__.'/../Resources/bin/hiddeninput.exe'; // handle code running from a phar if ('phar:' === substr(__FILE__, 0, 5)) { $tmpExe = sys_get_temp_dir().'/hiddeninput.exe'; copy($exe, $tmpExe); $exe = $tmpExe; } $output->write($question); $value = rtrim(shell_exec($exe)); $output->writeln(''); if (isset($tmpExe)) { unlink($tmpExe); } return $value; } if ($this->hasSttyAvailable()) { $output->write($question); $sttyMode = shell_exec('stty -g'); shell_exec('stty -echo'); $value = fgets($this->inputStream ?: STDIN, 4096); shell_exec(sprintf('stty %s', $sttyMode)); if (false === $value) { throw new \RuntimeException('Aborted'); } $value = trim($value); $output->writeln(''); return $value; } if (false !== $shell = $this->getShell()) { $output->write($question); $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword'; $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd); $value = rtrim(shell_exec($command)); $output->writeln(''); return $value; } if ($fallback) { return $this->ask($output, $question); } throw new \RuntimeException('Unable to hide the response'); } /** * Asks for a value and validates the response. * * The validator receives the data to validate. It must return the * validated data when the data is valid and throw an exception * otherwise. * * @param OutputInterface $output An Output instance * @param string|array $question The question to ask * @param callable $validator A PHP callback * @param integer $attempts Max number of times to ask before giving up (false by default, which means infinite) * @param string $default The default answer if none is given by the user * @param array $autocomplete List of values to autocomplete * * @return mixed * * @throws \Exception When any of the validators return an error */ public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null, array $autocomplete = null) { $that = $this; $interviewer = function () use ($output, $question, $default, $autocomplete, $that) { return $that->ask($output, $question, $default, $autocomplete); }; return $this->validateAttempts($interviewer, $output, $validator, $attempts); } /** * Asks for a value, hide and validates the response. * * The validator receives the data to validate. It must return the * validated data when the data is valid and throw an exception * otherwise. * * @param OutputInterface $output An Output instance * @param string|array $question The question to ask * @param callable $validator A PHP callback * @param integer $attempts Max number of times to ask before giving up (false by default, which means infinite) * @param Boolean $fallback In case the response can not be hidden, whether to fallback on non-hidden question or not * * @return string The response * * @throws \Exception When any of the validators return an error * @throws \RuntimeException In case the fallback is deactivated and the response can not be hidden * */ public function askHiddenResponseAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $fallback = true) { $that = $this; $interviewer = function () use ($output, $question, $fallback, $that) { return $that->askHiddenResponse($output, $question, $fallback); }; return $this->validateAttempts($interviewer, $output, $validator, $attempts); } /** * Sets the input stream to read from when interacting with the user. * * This is mainly useful for testing purpose. * * @param resource $stream The input stream */ public function setInputStream($stream) { $this->inputStream = $stream; } /** * Returns the helper's input stream * * @return string */ public function getInputStream() { return $this->inputStream; } /** * {@inheritDoc} */ public function getName() { return 'dialog'; } /** * Return a valid Unix shell * * @return string|Boolean The valid shell name, false in case no valid shell is found */ private function getShell() { if (null !== self::$shell) { return self::$shell; } self::$shell = false; if (file_exists('/usr/bin/env')) { // handle other OSs with bash/zsh/ksh/csh if available to hide the answer $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null"; foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) { if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) { self::$shell = $sh; break; } } } return self::$shell; } private function hasSttyAvailable() { if (null !== self::$stty) { return self::$stty; } exec('stty 2>&1', $output, $exitcode); return self::$stty = $exitcode === 0; } /** * Validate an attempt * * @param callable $interviewer A callable that will ask for a question and return the result * @param OutputInterface $output An Output instance * @param callable $validator A PHP callback * @param integer $attempts Max number of times to ask before giving up ; false will ask infinitely * * @return string The validated response * * @throws \Exception In case the max number of attempts has been reached and no valid response has been given */ private function validateAttempts($interviewer, OutputInterface $output, $validator, $attempts) { $error = null; while (false === $attempts || $attempts--) { if (null !== $error) { $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error')); } try { return call_user_func($validator, $interviewer()); } catch (\Exception $error) { } } throw $error; } } PK!iäÒ¢ììInspectorHelper.phpnu„[µü¤PK!J^˜ÞÞ/ProcessHelper.phpnuÕIw¶´PK! z…×óóNHelperInterface.phpnu„[µü¤PK!B¶Ý%Ãà „TableCell.phpnuÕIw¶´PK!+'šfèè „!Dumper.phpnuÕIw¶´PK!?*èlElE¦)ProgressBar.phpnuÕIw¶´PK!g¶se¼¼QoFormatterHelper.phpnu„[µü¤PK!@/®é0é0PxTableStyle.phpnuÕIw¶´PK!âñs%WjWj w©Table.phpnuÕIw¶´PK!øOºy y SymfonyQuestionHelper.phpnuÕIw¶´PK!sß HëëÉInputAwareHelper.phpnu„[µü¤PK!aí­©G G ø"DebugFormatterHelper.phpnuÕIw¶´PK!"U¥1  ‡0DescriptorHelper.phpnu„[µü¤PK!$ÖÿUU Ì:TableRows.phpnuÕIw¶´PK!½ûsû?û?^=QuestionHelper.phpnuÕIw¶´PK!Z\§«« ›}Helper.phpnu„[µü¤PK!&Šª €ƒTableSeparator.phpnuÕIw¶´PK!•¹Þ Þ Õ…HelperSet.phpnu„[µü¤PK!ŠùR ðProgressIndicator.phpnuÕIw¶´PK!Cï[Ü`Ü`S­HTML.phpnu„[µü¤PK!ë¡¿22gTableHelper.phpnu„[µü¤PK!|po.o.º@ProgressHelper.phpnu„[µü¤PK!&â>@>@koDialogHelper.phpnu„[µü¤PK6é¯