summaryrefslogtreecommitdiff
path: root/vendor/symfony/console/Helper
diff options
context:
space:
mode:
authorFrederic Guillot <fred@kanboard.net>2017-10-25 16:22:10 -0700
committerFrederic Guillot <fred@kanboard.net>2017-10-25 16:22:10 -0700
commit9e2b2a32fd0e967ad3184e9a5d091a29953acb91 (patch)
tree00822e24aa1110c73ca455a8d096ef296c008cbc /vendor/symfony/console/Helper
parentc507c5416251c505cb3e088a03c6664bed73c812 (diff)
Include composer dependencies in repo
Diffstat (limited to 'vendor/symfony/console/Helper')
-rw-r--r--vendor/symfony/console/Helper/DebugFormatterHelper.php127
-rw-r--r--vendor/symfony/console/Helper/DescriptorHelper.php97
-rw-r--r--vendor/symfony/console/Helper/DialogHelper.php502
-rw-r--r--vendor/symfony/console/Helper/FormatterHelper.php82
-rw-r--r--vendor/symfony/console/Helper/Helper.php119
-rw-r--r--vendor/symfony/console/Helper/HelperInterface.php41
-rw-r--r--vendor/symfony/console/Helper/HelperSet.php117
-rw-r--r--vendor/symfony/console/Helper/InputAwareHelper.php33
-rw-r--r--vendor/symfony/console/Helper/ProcessHelper.php151
-rw-r--r--vendor/symfony/console/Helper/ProgressBar.php621
-rw-r--r--vendor/symfony/console/Helper/ProgressHelper.php471
-rw-r--r--vendor/symfony/console/Helper/ProgressIndicator.php324
-rw-r--r--vendor/symfony/console/Helper/QuestionHelper.php449
-rw-r--r--vendor/symfony/console/Helper/SymfonyQuestionHelper.php107
-rw-r--r--vendor/symfony/console/Helper/Table.php663
-rw-r--r--vendor/symfony/console/Helper/TableCell.php79
-rw-r--r--vendor/symfony/console/Helper/TableHelper.php269
-rw-r--r--vendor/symfony/console/Helper/TableSeparator.php29
-rw-r--r--vendor/symfony/console/Helper/TableStyle.php258
19 files changed, 4539 insertions, 0 deletions
diff --git a/vendor/symfony/console/Helper/DebugFormatterHelper.php b/vendor/symfony/console/Helper/DebugFormatterHelper.php
new file mode 100644
index 00000000..1119b795
--- /dev/null
+++ b/vendor/symfony/console/Helper/DebugFormatterHelper.php
@@ -0,0 +1,127 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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 <fabien@symfony.com>
+ */
+class DebugFormatterHelper extends Helper
+{
+ private $colors = array('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default');
+ private $started = array();
+ private $count = -1;
+
+ /**
+ * Starts a debug formatting session.
+ *
+ * @param string $id The id of the formatting session
+ * @param string $message The message to display
+ * @param string $prefix The prefix to use
+ *
+ * @return string
+ */
+ public function start($id, $message, $prefix = 'RUN')
+ {
+ $this->started[$id] = array('border' => ++$this->count % count($this->colors));
+
+ return sprintf("%s<bg=blue;fg=white> %s </> <fg=blue>%s</>\n", $this->getBorder($id), $prefix, $message);
+ }
+
+ /**
+ * Adds progress to a formatting session.
+ *
+ * @param string $id The id of the formatting session
+ * @param string $buffer The message to display
+ * @param bool $error Whether to consider the buffer as error
+ * @param string $prefix The prefix for output
+ * @param string $errorPrefix The prefix for error output
+ *
+ * @return string
+ */
+ public function progress($id, $buffer, $error = false, $prefix = 'OUT', $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<bg=red;fg=white> %s </> ', $this->getBorder($id), $errorPrefix);
+ $this->started[$id]['err'] = true;
+ }
+
+ $message .= str_replace("\n", sprintf("\n%s<bg=red;fg=white> %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<bg=green;fg=white> %s </> ', $this->getBorder($id), $prefix);
+ $this->started[$id]['out'] = true;
+ }
+
+ $message .= str_replace("\n", sprintf("\n%s<bg=green;fg=white> %s </> ", $this->getBorder($id), $prefix), $buffer);
+ }
+
+ return $message;
+ }
+
+ /**
+ * Stops a formatting session.
+ *
+ * @param string $id The id of the formatting session
+ * @param string $message The message to display
+ * @param bool $successful Whether to consider the result as success
+ * @param string $prefix The prefix for the end output
+ *
+ * @return string
+ */
+ public function stop($id, $message, $successful, $prefix = 'RES')
+ {
+ $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : '';
+
+ if ($successful) {
+ return sprintf("%s%s<bg=green;fg=white> %s </> <fg=green>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
+ }
+
+ $message = sprintf("%s%s<bg=red;fg=white> %s </> <fg=red>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
+
+ unset($this->started[$id]['out'], $this->started[$id]['err']);
+
+ return $message;
+ }
+
+ /**
+ * @param string $id The id of the formatting session
+ *
+ * @return string
+ */
+ private function getBorder($id)
+ {
+ return sprintf('<bg=%s> </>', $this->colors[$this->started[$id]['border']]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'debug_formatter';
+ }
+}
diff --git a/vendor/symfony/console/Helper/DescriptorHelper.php b/vendor/symfony/console/Helper/DescriptorHelper.php
new file mode 100644
index 00000000..a53b476b
--- /dev/null
+++ b/vendor/symfony/console/Helper/DescriptorHelper.php
@@ -0,0 +1,97 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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;
+use Symfony\Component\Console\Exception\InvalidArgumentException;
+
+/**
+ * This class adds helper method to describe objects in various formats.
+ *
+ * @author Jean-François Simon <contact@jfsimon.fr>
+ */
+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 when the given format is not supported
+ */
+ 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';
+ }
+}
diff --git a/vendor/symfony/console/Helper/DialogHelper.php b/vendor/symfony/console/Helper/DialogHelper.php
new file mode 100644
index 00000000..9ce9f661
--- /dev/null
+++ b/vendor/symfony/console/Helper/DialogHelper.php
@@ -0,0 +1,502 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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\Output\ConsoleOutputInterface;
+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 <fabien@symfony.com>
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Use {@link \Symfony\Component\Console\Helper\QuestionHelper} instead.
+ */
+class DialogHelper extends InputAwareHelper
+{
+ private $inputStream;
+ private static $shell;
+ private static $stty;
+
+ public function __construct($triggerDeprecationError = true)
+ {
+ if ($triggerDeprecationError) {
+ @trigger_error('"Symfony\Component\Console\Helper\DialogHelper" is deprecated since version 2.5 and will be removed in 3.0. Use "Symfony\Component\Console\Helper\QuestionHelper" instead.', E_USER_DEPRECATED);
+ }
+ }
+
+ /**
+ * 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 bool|string $default The default answer if the user enters nothing
+ * @param bool|int $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 bool $multiselect Select more than one value separated by comma
+ *
+ * @return int|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)
+ {
+ if ($output instanceof ConsoleOutputInterface) {
+ $output = $output->getErrorOutput();
+ }
+
+ $width = max(array_map('strlen', array_keys($choices)));
+
+ $messages = (array) $question;
+ foreach ($choices as $key => $value) {
+ $messages[] = sprintf(" [<info>%-{$width}s</info>] %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));
+ }
+ $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;
+ }
+
+ if ($output instanceof ConsoleOutputInterface) {
+ $output = $output->getErrorOutput();
+ }
+
+ $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 (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 = $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('<hl>'.substr($matches[$ofs], $i).'</hl>');
+ // 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 bool $default The default answer if the user enters nothing
+ *
+ * @return bool 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 bool $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 ($output instanceof ConsoleOutputInterface) {
+ $output = $output->getErrorOutput();
+ }
+
+ 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;
+ }
+
+ $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 int|false $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 int|false $attempts Max number of times to ask before giving up (false by default, which means infinite)
+ * @param bool $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 resource|null The input stream or null if the default STDIN is used
+ */
+ public function getInputStream()
+ {
+ return $this->inputStream;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'dialog';
+ }
+
+ /**
+ * Return a valid Unix shell.
+ *
+ * @return string|bool 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 int|false $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)
+ {
+ if ($output instanceof ConsoleOutputInterface) {
+ $output = $output->getErrorOutput();
+ }
+
+ $e = null;
+ while (false === $attempts || $attempts--) {
+ if (null !== $e) {
+ $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($e->getMessage(), 'error'));
+ }
+
+ try {
+ return call_user_func($validator, $interviewer());
+ } catch (\Exception $e) {
+ }
+ }
+
+ throw $e;
+ }
+}
diff --git a/vendor/symfony/console/Helper/FormatterHelper.php b/vendor/symfony/console/Helper/FormatterHelper.php
new file mode 100644
index 00000000..ac736f98
--- /dev/null
+++ b/vendor/symfony/console/Helper/FormatterHelper.php
@@ -0,0 +1,82 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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 <fabien@symfony.com>
+ */
+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> %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 bool $large Whether to return a large block
+ *
+ * @return string The formatter message
+ */
+ public function formatBlock($messages, $style, $large = false)
+ {
+ if (!is_array($messages)) {
+ $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();
+ for ($i = 0; isset($lines[$i]); ++$i) {
+ $messages[] = $lines[$i].str_repeat(' ', $len - $this->strlen($lines[$i]));
+ }
+ if ($large) {
+ $messages[] = str_repeat(' ', $len);
+ }
+
+ for ($i = 0; isset($messages[$i]); ++$i) {
+ $messages[$i] = sprintf('<%s>%s</%s>', $style, $messages[$i], $style);
+ }
+
+ return implode("\n", $messages);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'formatter';
+ }
+}
diff --git a/vendor/symfony/console/Helper/Helper.php b/vendor/symfony/console/Helper/Helper.php
new file mode 100644
index 00000000..43f9a169
--- /dev/null
+++ b/vendor/symfony/console/Helper/Helper.php
@@ -0,0 +1,119 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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\OutputFormatterInterface;
+
+/**
+ * Helper is the base class for all helper classes.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+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_strwidth if it is available.
+ *
+ * @param string $string The string to check its length
+ *
+ * @return int The length of the string
+ */
+ public static function strlen($string)
+ {
+ if (false === $encoding = mb_detect_encoding($string, null, true)) {
+ return strlen($string);
+ }
+
+ return mb_strwidth($string, $encoding);
+ }
+
+ public static function formatTime($secs)
+ {
+ static $timeFormats = array(
+ array(0, '< 1 sec'),
+ array(1, '1 sec'),
+ array(2, 'secs', 1),
+ array(60, '1 min'),
+ array(120, 'mins', 60),
+ array(3600, '1 hr'),
+ array(7200, 'hrs', 3600),
+ array(86400, '1 day'),
+ array(172800, 'days', 86400),
+ );
+
+ foreach ($timeFormats as $index => $format) {
+ if ($secs >= $format[0]) {
+ if ((isset($timeFormats[$index + 1]) && $secs < $timeFormats[$index + 1][0])
+ || $index == count($timeFormats) - 1
+ ) {
+ if (2 == count($format)) {
+ return $format[1];
+ }
+
+ return floor($secs / $format[2]).' '.$format[1];
+ }
+ }
+ }
+ }
+
+ public static function formatMemory($memory)
+ {
+ if ($memory >= 1024 * 1024 * 1024) {
+ return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024);
+ }
+
+ if ($memory >= 1024 * 1024) {
+ return sprintf('%.1f MiB', $memory / 1024 / 1024);
+ }
+
+ if ($memory >= 1024) {
+ return sprintf('%d KiB', $memory / 1024);
+ }
+
+ return sprintf('%d B', $memory);
+ }
+
+ public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string)
+ {
+ $isDecorated = $formatter->isDecorated();
+ $formatter->setDecorated(false);
+ // remove <...> formatting
+ $string = $formatter->format($string);
+ // remove already formatted characters
+ $string = preg_replace("/\033\[[^m]*m/", '', $string);
+ $formatter->setDecorated($isDecorated);
+
+ return self::strlen($string);
+ }
+}
diff --git a/vendor/symfony/console/Helper/HelperInterface.php b/vendor/symfony/console/Helper/HelperInterface.php
new file mode 100644
index 00000000..5a923e0a
--- /dev/null
+++ b/vendor/symfony/console/Helper/HelperInterface.php
@@ -0,0 +1,41 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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 <fabien@symfony.com>
+ */
+interface HelperInterface
+{
+ /**
+ * Sets the helper set associated with this helper.
+ *
+ * @param HelperSet $helperSet A HelperSet instance
+ */
+ public function setHelperSet(HelperSet $helperSet = null);
+
+ /**
+ * Gets the helper set associated with this helper.
+ *
+ * @return HelperSet A HelperSet instance
+ */
+ public function getHelperSet();
+
+ /**
+ * Returns the canonical name of this helper.
+ *
+ * @return string The canonical name
+ */
+ public function getName();
+}
diff --git a/vendor/symfony/console/Helper/HelperSet.php b/vendor/symfony/console/Helper/HelperSet.php
new file mode 100644
index 00000000..27fedcf7
--- /dev/null
+++ b/vendor/symfony/console/Helper/HelperSet.php
@@ -0,0 +1,117 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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;
+use Symfony\Component\Console\Exception\InvalidArgumentException;
+
+/**
+ * HelperSet represents a set of helpers to be used with a command.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+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 bool 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));
+ }
+
+ if ('dialog' === $name && $this->helpers[$name] instanceof DialogHelper) {
+ @trigger_error('"Symfony\Component\Console\Helper\DialogHelper" is deprecated since version 2.5 and will be removed in 3.0. Use "Symfony\Component\Console\Helper\QuestionHelper" instead.', E_USER_DEPRECATED);
+ } elseif ('progress' === $name && $this->helpers[$name] instanceof ProgressHelper) {
+ @trigger_error('"Symfony\Component\Console\Helper\ProgressHelper" is deprecated since version 2.5 and will be removed in 3.0. Use "Symfony\Component\Console\Helper\ProgressBar" instead.', E_USER_DEPRECATED);
+ } elseif ('table' === $name && $this->helpers[$name] instanceof TableHelper) {
+ @trigger_error('"Symfony\Component\Console\Helper\TableHelper" is deprecated since version 2.5 and will be removed in 3.0. Use "Symfony\Component\Console\Helper\Table" instead.', E_USER_DEPRECATED);
+ }
+
+ 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);
+ }
+}
diff --git a/vendor/symfony/console/Helper/InputAwareHelper.php b/vendor/symfony/console/Helper/InputAwareHelper.php
new file mode 100644
index 00000000..42617674
--- /dev/null
+++ b/vendor/symfony/console/Helper/InputAwareHelper.php
@@ -0,0 +1,33 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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 <waldio.webdesign@gmail.com>
+ */
+abstract class InputAwareHelper extends Helper implements InputAwareInterface
+{
+ protected $input;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setInput(InputInterface $input)
+ {
+ $this->input = $input;
+ }
+}
diff --git a/vendor/symfony/console/Helper/ProcessHelper.php b/vendor/symfony/console/Helper/ProcessHelper.php
new file mode 100644
index 00000000..a811eb48
--- /dev/null
+++ b/vendor/symfony/console/Helper/ProcessHelper.php
@@ -0,0 +1,151 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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;
+use Symfony\Component\Process\ProcessBuilder;
+
+/**
+ * The ProcessHelper class provides helpers to run external processes.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ProcessHelper extends Helper
+{
+ /**
+ * Runs an external process.
+ *
+ * @param OutputInterface $output An OutputInterface instance
+ * @param string|array|Process $cmd An instance of Process or an array of arguments to escape and run or a command to run
+ * @param string|null $error An error message that must be displayed if something went wrong
+ * @param callable|null $callback A PHP callback to run whenever there is some
+ * output available on STDOUT or STDERR
+ * @param int $verbosity The threshold for verbosity
+ *
+ * @return Process The process that ran
+ */
+ public function run(OutputInterface $output, $cmd, $error = null, $callback = null, $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE)
+ {
+ if ($output instanceof ConsoleOutputInterface) {
+ $output = $output->getErrorOutput();
+ }
+
+ $formatter = $this->getHelperSet()->get('debug_formatter');
+
+ if (is_array($cmd)) {
+ $process = ProcessBuilder::create($cmd)->getProcess();
+ } elseif ($cmd instanceof Process) {
+ $process = $cmd;
+ } else {
+ $process = new Process($cmd);
+ }
+
+ 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);
+
+ 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('<error>%s</error>', $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 OutputInterface $output An OutputInterface instance
+ * @param string|Process $cmd An instance of Process or a command to run
+ * @param string|null $error An error message that must be displayed if something went wrong
+ * @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, $error = null, $callback = null)
+ {
+ $process = $this->run($output, $cmd, $error, $callback);
+
+ if (!$process->isSuccessful()) {
+ throw new ProcessFailedException($process);
+ }
+
+ return $process;
+ }
+
+ /**
+ * Wraps a Process callback to add debugging output.
+ *
+ * @param OutputInterface $output An OutputInterface interface
+ * @param Process $process The Process
+ * @param callable|null $callback A PHP callable
+ *
+ * @return callable
+ */
+ public function wrapCallback(OutputInterface $output, Process $process, $callback = null)
+ {
+ if ($output instanceof ConsoleOutputInterface) {
+ $output = $output->getErrorOutput();
+ }
+
+ $formatter = $this->getHelperSet()->get('debug_formatter');
+
+ $that = $this;
+
+ return function ($type, $buffer) use ($output, $process, $callback, $formatter, $that) {
+ $output->write($formatter->progress(spl_object_hash($process), $that->escapeString($buffer), Process::ERR === $type));
+
+ if (null !== $callback) {
+ call_user_func($callback, $type, $buffer);
+ }
+ };
+ }
+
+ /**
+ * This method is public for PHP 5.3 compatibility, it should be private.
+ *
+ * @internal
+ */
+ public function escapeString($str)
+ {
+ return str_replace('<', '\\<', $str);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'process';
+ }
+}
diff --git a/vendor/symfony/console/Helper/ProgressBar.php b/vendor/symfony/console/Helper/ProgressBar.php
new file mode 100644
index 00000000..e7717a52
--- /dev/null
+++ b/vendor/symfony/console/Helper/ProgressBar.php
@@ -0,0 +1,621 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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\Console\Exception\LogicException;
+
+/**
+ * The ProgressBar provides helpers to display progress output.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Chris Jones <leeked@gmail.com>
+ */
+class ProgressBar
+{
+ // options
+ private $barWidth = 28;
+ private $barChar;
+ private $emptyBarChar = '-';
+ private $progressChar = '>';
+ private $format;
+ private $internalFormat;
+ private $redrawFreq = 1;
+
+ /**
+ * @var OutputInterface
+ */
+ private $output;
+ private $step = 0;
+ private $max;
+ private $startTime;
+ private $stepWidth;
+ private $percent = 0.0;
+ private $formatLineCount;
+ private $messages;
+ private $overwrite = true;
+
+ private static $formatters;
+ private static $formats;
+
+ /**
+ * Constructor.
+ *
+ * @param OutputInterface $output An OutputInterface instance
+ * @param int $max Maximum steps (0 if unknown)
+ */
+ public function __construct(OutputInterface $output, $max = 0)
+ {
+ if ($output instanceof ConsoleOutputInterface) {
+ $output = $output->getErrorOutput();
+ }
+
+ $this->output = $output;
+ $this->setMaxSteps($max);
+
+ 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->setRedrawFrequency($max / 10);
+ }
+
+ $this->startTime = time();
+ }
+
+ /**
+ * 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($name, $callable)
+ {
+ 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($name)
+ {
+ 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($name, $format)
+ {
+ 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($name)
+ {
+ if (!self::$formats) {
+ self::$formats = self::initFormats();
+ }
+
+ return isset(self::$formats[$name]) ? self::$formats[$name] : null;
+ }
+
+ public function setMessage($message, $name = 'message')
+ {
+ $this->messages[$name] = $message;
+ }
+
+ public function getMessage($name = 'message')
+ {
+ return $this->messages[$name];
+ }
+
+ /**
+ * Gets the progress bar start time.
+ *
+ * @return int The progress bar start time
+ */
+ public function getStartTime()
+ {
+ return $this->startTime;
+ }
+
+ /**
+ * Gets the progress bar maximal steps.
+ *
+ * @return int The progress bar max steps
+ */
+ public function getMaxSteps()
+ {
+ return $this->max;
+ }
+
+ /**
+ * Gets the progress bar step.
+ *
+ * @deprecated since version 2.6, to be removed in 3.0. Use {@link getProgress()} instead.
+ *
+ * @return int The progress bar step
+ */
+ public function getStep()
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since version 2.6 and will be removed in 3.0. Use the getProgress() method instead.', E_USER_DEPRECATED);
+
+ return $this->getProgress();
+ }
+
+ /**
+ * Gets the current step position.
+ *
+ * @return int The progress bar step
+ */
+ public function getProgress()
+ {
+ return $this->step;
+ }
+
+ /**
+ * Gets the progress bar step width.
+ *
+ * @internal This method is public for PHP 5.3 compatibility, it should not be used.
+ *
+ * @return int The progress bar step width
+ */
+ public function getStepWidth()
+ {
+ return $this->stepWidth;
+ }
+
+ /**
+ * Gets the current progress bar percent.
+ *
+ * @return float The current progress bar percent
+ */
+ public function getProgressPercent()
+ {
+ return $this->percent;
+ }
+
+ /**
+ * Sets the progress bar width.
+ *
+ * @param int $size The progress bar size
+ */
+ public function setBarWidth($size)
+ {
+ $this->barWidth = (int) $size;
+ }
+
+ /**
+ * Gets the progress bar width.
+ *
+ * @return int The progress bar size
+ */
+ public function getBarWidth()
+ {
+ return $this->barWidth;
+ }
+
+ /**
+ * Sets the bar character.
+ *
+ * @param string $char A character
+ */
+ public function setBarCharacter($char)
+ {
+ $this->barChar = $char;
+ }
+
+ /**
+ * Gets the bar character.
+ *
+ * @return string A character
+ */
+ public function getBarCharacter()
+ {
+ if (null === $this->barChar) {
+ return $this->max ? '=' : $this->emptyBarChar;
+ }
+
+ return $this->barChar;
+ }
+
+ /**
+ * Sets the empty bar character.
+ *
+ * @param string $char A character
+ */
+ public function setEmptyBarCharacter($char)
+ {
+ $this->emptyBarChar = $char;
+ }
+
+ /**
+ * Gets the empty bar character.
+ *
+ * @return string A character
+ */
+ public function getEmptyBarCharacter()
+ {
+ return $this->emptyBarChar;
+ }
+
+ /**
+ * Sets the progress bar character.
+ *
+ * @param string $char A character
+ */
+ public function setProgressCharacter($char)
+ {
+ $this->progressChar = $char;
+ }
+
+ /**
+ * Gets the progress bar character.
+ *
+ * @return string A character
+ */
+ public function getProgressCharacter()
+ {
+ return $this->progressChar;
+ }
+
+ /**
+ * Sets the progress bar format.
+ *
+ * @param string $format The format
+ */
+ public function setFormat($format)
+ {
+ $this->format = null;
+ $this->internalFormat = $format;
+ }
+
+ /**
+ * Sets the redraw frequency.
+ *
+ * @param int|float $freq The frequency in steps
+ */
+ public function setRedrawFrequency($freq)
+ {
+ $this->redrawFreq = max((int) $freq, 1);
+ }
+
+ /**
+ * 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($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
+ *
+ * @throws LogicException
+ */
+ public function advance($step = 1)
+ {
+ $this->setProgress($this->step + $step);
+ }
+
+ /**
+ * Sets the current progress.
+ *
+ * @deprecated since version 2.6, to be removed in 3.0. Use {@link setProgress()} instead.
+ *
+ * @param int $step The current progress
+ *
+ * @throws LogicException
+ */
+ public function setCurrent($step)
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since version 2.6 and will be removed in 3.0. Use the setProgress() method instead.', E_USER_DEPRECATED);
+
+ $this->setProgress($step);
+ }
+
+ /**
+ * Sets whether to overwrite the progressbar, false for new line.
+ *
+ * @param bool $overwrite
+ */
+ public function setOverwrite($overwrite)
+ {
+ $this->overwrite = (bool) $overwrite;
+ }
+
+ /**
+ * Sets the current progress.
+ *
+ * @param int $step The current progress
+ *
+ * @throws LogicException
+ */
+ public function setProgress($step)
+ {
+ $step = (int) $step;
+ if ($step < $this->step) {
+ throw new LogicException('You can\'t regress the progress bar.');
+ }
+
+ if ($this->max && $step > $this->max) {
+ $this->max = $step;
+ }
+
+ $prevPeriod = (int) ($this->step / $this->redrawFreq);
+ $currPeriod = (int) ($step / $this->redrawFreq);
+ $this->step = $step;
+ $this->percent = $this->max ? (float) $this->step / $this->max : 0;
+ if ($prevPeriod !== $currPeriod || $this->max === $step) {
+ $this->display();
+ }
+ }
+
+ /**
+ * Finishes the progress output.
+ */
+ public function finish()
+ {
+ 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()
+ {
+ if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
+ return;
+ }
+
+ if (null === $this->format) {
+ $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
+ }
+
+ // these 3 variables can be removed in favor of using $this in the closure when support for PHP 5.3 will be dropped.
+ $self = $this;
+ $output = $this->output;
+ $messages = $this->messages;
+ $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self, $output, $messages) {
+ if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
+ $text = call_user_func($formatter, $self, $output);
+ } elseif (isset($messages[$matches[1]])) {
+ $text = $messages[$matches[1]];
+ } else {
+ return $matches[0];
+ }
+
+ if (isset($matches[2])) {
+ $text = sprintf('%'.$matches[2], $text);
+ }
+
+ return $text;
+ }, $this->format));
+ }
+
+ /**
+ * 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()
+ {
+ if (!$this->overwrite) {
+ return;
+ }
+
+ if (null === $this->format) {
+ $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
+ }
+
+ $this->overwrite('');
+ }
+
+ /**
+ * Sets the progress bar format.
+ *
+ * @param string $format The format
+ */
+ private function setRealFormat($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");
+ }
+
+ /**
+ * Sets the progress bar maximal steps.
+ *
+ * @param int $max The progress bar max steps
+ */
+ private function setMaxSteps($max)
+ {
+ $this->max = max(0, (int) $max);
+ $this->stepWidth = $this->max ? Helper::strlen($this->max) : 4;
+ }
+
+ /**
+ * Overwrites a previous message to the output.
+ *
+ * @param string $message The message
+ */
+ private function overwrite($message)
+ {
+ if ($this->overwrite) {
+ // Move the cursor to the beginning of the line
+ $this->output->write("\x0D");
+
+ // Erase the line
+ $this->output->write("\x1B[2K");
+
+ // Erase previous lines
+ if ($this->formatLineCount > 0) {
+ $this->output->write(str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount));
+ }
+ } elseif ($this->step > 0) {
+ $this->output->writeln('');
+ }
+
+ $this->output->write($message);
+ }
+
+ private function determineBestFormat()
+ {
+ 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()
+ {
+ return array(
+ 'bar' => function (ProgressBar $bar, OutputInterface $output) {
+ $completeBars = floor($bar->getMaxSteps() > 0 ? $bar->getProgressPercent() * $bar->getBarWidth() : $bar->getProgress() % $bar->getBarWidth());
+ $display = str_repeat($bar->getBarCharacter(), $completeBars);
+ if ($completeBars < $bar->getBarWidth()) {
+ $emptyBars = $bar->getBarWidth() - $completeBars - Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter());
+ $display .= $bar->getProgressCharacter().str_repeat($bar->getEmptyBarCharacter(), $emptyBars);
+ }
+
+ return $display;
+ },
+ 'elapsed' => function (ProgressBar $bar) {
+ return Helper::formatTime(time() - $bar->getStartTime());
+ },
+ 'remaining' => function (ProgressBar $bar) {
+ if (!$bar->getMaxSteps()) {
+ throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.');
+ }
+
+ if (!$bar->getProgress()) {
+ $remaining = 0;
+ } else {
+ $remaining = round((time() - $bar->getStartTime()) / $bar->getProgress() * ($bar->getMaxSteps() - $bar->getProgress()));
+ }
+
+ return Helper::formatTime($remaining);
+ },
+ 'estimated' => function (ProgressBar $bar) {
+ if (!$bar->getMaxSteps()) {
+ throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.');
+ }
+
+ if (!$bar->getProgress()) {
+ $estimated = 0;
+ } else {
+ $estimated = round((time() - $bar->getStartTime()) / $bar->getProgress() * $bar->getMaxSteps());
+ }
+
+ return Helper::formatTime($estimated);
+ },
+ 'memory' => function (ProgressBar $bar) {
+ return Helper::formatMemory(memory_get_usage(true));
+ },
+ 'current' => function (ProgressBar $bar) {
+ return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', STR_PAD_LEFT);
+ },
+ 'max' => function (ProgressBar $bar) {
+ return $bar->getMaxSteps();
+ },
+ 'percent' => function (ProgressBar $bar) {
+ return floor($bar->getProgressPercent() * 100);
+ },
+ );
+ }
+
+ private static function initFormats()
+ {
+ return array(
+ '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%',
+ );
+ }
+}
diff --git a/vendor/symfony/console/Helper/ProgressHelper.php b/vendor/symfony/console/Helper/ProgressHelper.php
new file mode 100644
index 00000000..96b6202c
--- /dev/null
+++ b/vendor/symfony/console/Helper/ProgressHelper.php
@@ -0,0 +1,471 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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\NullOutput;
+use Symfony\Component\Console\Output\ConsoleOutputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Exception\LogicException;
+
+/**
+ * The Progress class provides helpers to display progress output.
+ *
+ * @author Chris Jones <leeked@gmail.com>
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @deprecated since version 2.5, to be removed in 3.0
+ * Use {@link ProgressBar} instead.
+ */
+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 int
+ */
+ private $current;
+
+ /**
+ * Maximum number of steps.
+ *
+ * @var int
+ */
+ private $max;
+
+ /**
+ * Start time of the progress bar.
+ *
+ * @var int
+ */
+ 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),
+ );
+
+ public function __construct($triggerDeprecationError = true)
+ {
+ if ($triggerDeprecationError) {
+ @trigger_error('The '.__CLASS__.' class is deprecated since version 2.5 and will be removed in 3.0. Use the Symfony\Component\Console\Helper\ProgressBar class instead.', E_USER_DEPRECATED);
+ }
+ }
+
+ /**
+ * 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 int|null $max Maximum steps
+ */
+ public function start(OutputInterface $output, $max = null)
+ {
+ if ($output instanceof ConsoleOutputInterface) {
+ $output = $output->getErrorOutput();
+ }
+
+ $this->startTime = time();
+ $this->current = 0;
+ $this->max = (int) $max;
+
+ // Disabling output when it does not support ANSI codes as it would result in a broken display anyway.
+ $this->output = $output->isDecorated() ? $output : new NullOutput();
+ $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 int $step Number of steps to advance
+ * @param bool $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 int $current The current progress
+ * @param bool $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 = (int) ($this->current / $this->redrawFreq);
+
+ $this->current = $current;
+
+ $currPeriod = (int) ($this->current / $this->redrawFreq);
+ if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) {
+ $this->display();
+ }
+ }
+
+ /**
+ * Outputs the current progress string.
+ *
+ * @param bool $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 bool $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 int $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';
+ }
+}
diff --git a/vendor/symfony/console/Helper/ProgressIndicator.php b/vendor/symfony/console/Helper/ProgressIndicator.php
new file mode 100644
index 00000000..ccf9771b
--- /dev/null
+++ b/vendor/symfony/console/Helper/ProgressIndicator.php
@@ -0,0 +1,324 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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 <kevinbond@gmail.com>
+ */
+class ProgressIndicator
+{
+ private $output;
+ private $startTime;
+ private $format;
+ private $message;
+ private $indicatorValues;
+ private $indicatorCurrent;
+ private $indicatorChangeInterval;
+ private $indicatorUpdateTime;
+ private $lastMessagesLength;
+ private $started = false;
+
+ private static $formatters;
+ private static $formats;
+
+ /**
+ * @param OutputInterface $output
+ * @param string|null $format Indicator format
+ * @param int $indicatorChangeInterval Change interval in milliseconds
+ * @param array|null $indicatorValues Animated indicator characters
+ */
+ public function __construct(OutputInterface $output, $format = null, $indicatorChangeInterval = 100, $indicatorValues = null)
+ {
+ $this->output = $output;
+
+ if (null === $format) {
+ $format = $this->determineBestFormat();
+ }
+
+ if (null === $indicatorValues) {
+ $indicatorValues = array('-', '\\', '|', '/');
+ }
+
+ $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.
+ *
+ * @param string|null $message
+ */
+ public function setMessage($message)
+ {
+ $this->message = $message;
+
+ $this->display();
+ }
+
+ /**
+ * Gets the current indicator message.
+ *
+ * @return string|null
+ *
+ * @internal for PHP 5.3 compatibility
+ */
+ public function getMessage()
+ {
+ return $this->message;
+ }
+
+ /**
+ * Gets the progress bar start time.
+ *
+ * @return int The progress bar start time
+ *
+ * @internal for PHP 5.3 compatibility
+ */
+ public function getStartTime()
+ {
+ return $this->startTime;
+ }
+
+ /**
+ * Gets the current animated indicator character.
+ *
+ * @return string
+ *
+ * @internal for PHP 5.3 compatibility
+ */
+ public function getCurrentValue()
+ {
+ return $this->indicatorValues[$this->indicatorCurrent % count($this->indicatorValues)];
+ }
+
+ /**
+ * Starts the indicator output.
+ *
+ * @param $message
+ */
+ public function start($message)
+ {
+ if ($this->started) {
+ throw new LogicException('Progress indicator already started.');
+ }
+
+ $this->message = $message;
+ $this->started = true;
+ $this->lastMessagesLength = 0;
+ $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($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.
+ *
+ * @param string $name The format name
+ *
+ * @return string|null A format string
+ */
+ public static function getFormatDefinition($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.
+ *
+ * @param string $name The placeholder name (including the delimiter char like %)
+ * @param callable $callable A PHP callable
+ */
+ public static function setPlaceholderFormatterDefinition($name, $callable)
+ {
+ 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($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;
+ }
+
+ $self = $this;
+
+ $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self) {
+ if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
+ return call_user_func($formatter, $self);
+ }
+
+ return $matches[0];
+ }, $this->format));
+ }
+
+ private function determineBestFormat()
+ {
+ 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.
+ *
+ * @param string $message The message
+ */
+ private function overwrite($message)
+ {
+ // append whitespace to match the line's length
+ if (null !== $this->lastMessagesLength) {
+ if ($this->lastMessagesLength > Helper::strlenWithoutDecoration($this->output->getFormatter(), $message)) {
+ $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
+ }
+ }
+
+ if ($this->output->isDecorated()) {
+ $this->output->write("\x0D");
+ $this->output->write($message);
+ } else {
+ $this->output->writeln($message);
+ }
+
+ $this->lastMessagesLength = 0;
+
+ $len = Helper::strlenWithoutDecoration($this->output->getFormatter(), $message);
+
+ if ($len > $this->lastMessagesLength) {
+ $this->lastMessagesLength = $len;
+ }
+ }
+
+ private function getCurrentTimeInMilliseconds()
+ {
+ return round(microtime(true) * 1000);
+ }
+
+ private static function initPlaceholderFormatters()
+ {
+ return array(
+ 'indicator' => function (ProgressIndicator $indicator) {
+ return $indicator->getCurrentValue();
+ },
+ 'message' => function (ProgressIndicator $indicator) {
+ return $indicator->getMessage();
+ },
+ 'elapsed' => function (ProgressIndicator $indicator) {
+ return Helper::formatTime(time() - $indicator->getStartTime());
+ },
+ 'memory' => function () {
+ return Helper::formatMemory(memory_get_usage(true));
+ },
+ );
+ }
+
+ private static function initFormats()
+ {
+ return array(
+ '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%)',
+ );
+ }
+}
diff --git a/vendor/symfony/console/Helper/QuestionHelper.php b/vendor/symfony/console/Helper/QuestionHelper.php
new file mode 100644
index 00000000..5bb30df8
--- /dev/null
+++ b/vendor/symfony/console/Helper/QuestionHelper.php
@@ -0,0 +1,449 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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\Input\InputInterface;
+use Symfony\Component\Console\Output\ConsoleOutputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Formatter\OutputFormatterStyle;
+use Symfony\Component\Console\Question\Question;
+use Symfony\Component\Console\Question\ChoiceQuestion;
+
+/**
+ * The QuestionHelper class provides helpers to interact with the user.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class QuestionHelper extends Helper
+{
+ private $inputStream;
+ private static $shell;
+ private static $stty;
+
+ /**
+ * Asks a question to the user.
+ *
+ * @param InputInterface $input An InputInterface instance
+ * @param OutputInterface $output An OutputInterface instance
+ * @param Question $question The question to ask
+ *
+ * @return string 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 $question->getDefault();
+ }
+
+ if (!$question->getValidator()) {
+ return $this->doAsk($output, $question);
+ }
+
+ $that = $this;
+
+ $interviewer = function () use ($output, $question, $that) {
+ return $that->doAsk($output, $question);
+ };
+
+ return $this->validateAttempts($interviewer, $output, $question);
+ }
+
+ /**
+ * 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
+ *
+ * @throws InvalidArgumentException In case the stream is not a resource
+ */
+ public function setInputStream($stream)
+ {
+ if (!is_resource($stream)) {
+ throw new InvalidArgumentException('Input stream must be a valid resource.');
+ }
+
+ $this->inputStream = $stream;
+ }
+
+ /**
+ * Returns the helper's input stream.
+ *
+ * @return resource
+ */
+ public function getInputStream()
+ {
+ return $this->inputStream;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'question';
+ }
+
+ /**
+ * Asks the question to the user.
+ *
+ * This method is public for PHP 5.3 compatibility, it should be private.
+ *
+ * @param OutputInterface $output
+ * @param Question $question
+ *
+ * @return bool|mixed|null|string
+ *
+ * @throws \Exception
+ * @throws \RuntimeException
+ */
+ public function doAsk(OutputInterface $output, Question $question)
+ {
+ $this->writePrompt($output, $question);
+
+ $inputStream = $this->inputStream ?: STDIN;
+ $autocomplete = $question->getAutocompleterValues();
+
+ if (null === $autocomplete || !$this->hasSttyAvailable()) {
+ $ret = false;
+ if ($question->isHidden()) {
+ try {
+ $ret = trim($this->getHiddenResponse($output, $inputStream));
+ } catch (\RuntimeException $e) {
+ if (!$question->isHiddenFallback()) {
+ throw $e;
+ }
+ }
+ }
+
+ if (false === $ret) {
+ $ret = fgets($inputStream, 4096);
+ if (false === $ret) {
+ throw new \RuntimeException('Aborted');
+ }
+ $ret = trim($ret);
+ }
+ } else {
+ $ret = trim($this->autocomplete($output, $question, $inputStream));
+ }
+
+ $ret = strlen($ret) > 0 ? $ret : $question->getDefault();
+
+ if ($normalizer = $question->getNormalizer()) {
+ return $normalizer($ret);
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Outputs the question prompt.
+ *
+ * @param OutputInterface $output
+ * @param Question $question
+ */
+ protected function writePrompt(OutputInterface $output, Question $question)
+ {
+ $message = $question->getQuestion();
+
+ if ($question instanceof ChoiceQuestion) {
+ $maxWidth = max(array_map(array($this, 'strlen'), array_keys($question->getChoices())));
+
+ $messages = (array) $question->getQuestion();
+ foreach ($question->getChoices() as $key => $value) {
+ $width = $maxWidth - $this->strlen($key);
+ $messages[] = ' [<info>'.$key.str_repeat(' ', $width).'</info>] '.$value;
+ }
+
+ $output->writeln($messages);
+
+ $message = $question->getPrompt();
+ }
+
+ $output->write($message);
+ }
+
+ /**
+ * Outputs an error message.
+ *
+ * @param OutputInterface $output
+ * @param \Exception $error
+ */
+ 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>'.$error->getMessage().'</error>';
+ }
+
+ $output->writeln($message);
+ }
+
+ /**
+ * Autocompletes a question.
+ *
+ * @param OutputInterface $output
+ * @param Question $question
+ *
+ * @return string
+ */
+ private function autocomplete(OutputInterface $output, Question $question, $inputStream)
+ {
+ $autocomplete = $question->getAutocompleterValues();
+ $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 (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 = $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('<hl>'.substr($matches[$ofs], $i).'</hl>');
+ // Restore cursor position
+ $output->write("\0338");
+ }
+ }
+
+ // Reset stty so it behaves normally again
+ shell_exec(sprintf('stty %s', $sttyMode));
+
+ return $ret;
+ }
+
+ /**
+ * Gets a hidden response from user.
+ *
+ * @param OutputInterface $output An Output instance
+ *
+ * @return string The answer
+ *
+ * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden
+ */
+ private function getHiddenResponse(OutputInterface $output, $inputStream)
+ {
+ 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;
+ }
+
+ $value = rtrim(shell_exec($exe));
+ $output->writeln('');
+
+ if (isset($tmpExe)) {
+ unlink($tmpExe);
+ }
+
+ return $value;
+ }
+
+ if ($this->hasSttyAvailable()) {
+ $sttyMode = shell_exec('stty -g');
+
+ shell_exec('stty -echo');
+ $value = fgets($inputStream, 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()) {
+ $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;
+ }
+
+ throw new RuntimeException('Unable to hide the response.');
+ }
+
+ /**
+ * Validates an attempt.
+ *
+ * @param callable $interviewer A callable that will ask for a question and return the result
+ * @param OutputInterface $output An Output instance
+ * @param Question $question A Question instance
+ *
+ * @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, Question $question)
+ {
+ $error = null;
+ $attempts = $question->getMaxAttempts();
+ while (null === $attempts || $attempts--) {
+ if (null !== $error) {
+ $this->writeError($output, $error);
+ }
+
+ try {
+ return call_user_func($question->getValidator(), $interviewer());
+ } catch (\Exception $error) {
+ }
+ }
+
+ throw $error;
+ }
+
+ /**
+ * Returns a valid unix shell.
+ *
+ * @return string|bool 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;
+ }
+
+ /**
+ * Returns whether Stty is available or not.
+ *
+ * @return bool
+ */
+ private function hasSttyAvailable()
+ {
+ if (null !== self::$stty) {
+ return self::$stty;
+ }
+
+ exec('stty 2>&1', $output, $exitcode);
+
+ return self::$stty = $exitcode === 0;
+ }
+}
diff --git a/vendor/symfony/console/Helper/SymfonyQuestionHelper.php b/vendor/symfony/console/Helper/SymfonyQuestionHelper.php
new file mode 100644
index 00000000..942278bd
--- /dev/null
+++ b/vendor/symfony/console/Helper/SymfonyQuestionHelper.php
@@ -0,0 +1,107 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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\LogicException;
+use Symfony\Component\Console\Input\InputInterface;
+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 <kevinbond@gmail.com>
+ */
+class SymfonyQuestionHelper extends QuestionHelper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function ask(InputInterface $input, OutputInterface $output, Question $question)
+ {
+ $validator = $question->getValidator();
+ $question->setValidator(function ($value) use ($validator) {
+ if (null !== $validator) {
+ $value = $validator($value);
+ }
+
+ // make required
+ if (!is_array($value) && !is_bool($value) && 0 === strlen($value)) {
+ throw new LogicException('A value is required.');
+ }
+
+ return $value;
+ });
+
+ return parent::ask($input, $output, $question);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function writePrompt(OutputInterface $output, Question $question)
+ {
+ $text = $question->getQuestion();
+ $default = $question->getDefault();
+
+ switch (true) {
+ case null === $default:
+ $text = sprintf(' <info>%s</info>:', $text);
+
+ break;
+
+ case $question instanceof ConfirmationQuestion:
+ $text = sprintf(' <info>%s (yes/no)</info> [<comment>%s</comment>]:', $text, $default ? 'yes' : 'no');
+
+ break;
+
+ case $question instanceof ChoiceQuestion:
+ $choices = $question->getChoices();
+ $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, $choices[$default]);
+
+ break;
+
+ default:
+ $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, $default);
+ }
+
+ $output->writeln($text);
+
+ if ($question instanceof ChoiceQuestion) {
+ $width = max(array_map('strlen', array_keys($question->getChoices())));
+
+ foreach ($question->getChoices() as $key => $value) {
+ $output->writeln(sprintf(" [<comment>%-${width}s</comment>] %s", $key, $value));
+ }
+ }
+
+ $output->write(' > ');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function writeError(OutputInterface $output, \Exception $error)
+ {
+ if ($output instanceof SymfonyStyle) {
+ $output->newLine();
+ $output->error($error->getMessage());
+
+ return;
+ }
+
+ parent::writeError($output, $error);
+ }
+}
diff --git a/vendor/symfony/console/Helper/Table.php b/vendor/symfony/console/Helper/Table.php
new file mode 100644
index 00000000..13e4c3cf
--- /dev/null
+++ b/vendor/symfony/console/Helper/Table.php
@@ -0,0 +1,663 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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\Exception\InvalidArgumentException;
+
+/**
+ * Provides helpers to display a table.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Саша Стаменковић <umpirsky@gmail.com>
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ * @author Max Grigorian <maxakawizard@gmail.com>
+ */
+class Table
+{
+ /**
+ * Table headers.
+ *
+ * @var array
+ */
+ private $headers = array();
+
+ /**
+ * Table rows.
+ *
+ * @var array
+ */
+ private $rows = array();
+
+ /**
+ * Column widths cache.
+ *
+ * @var array
+ */
+ private $columnWidths = array();
+
+ /**
+ * Number of columns cache.
+ *
+ * @var array
+ */
+ private $numberOfColumns;
+
+ /**
+ * @var OutputInterface
+ */
+ private $output;
+
+ /**
+ * @var TableStyle
+ */
+ private $style;
+
+ /**
+ * @var array
+ */
+ private $columnStyles = array();
+
+ private static $styles;
+
+ public function __construct(OutputInterface $output)
+ {
+ $this->output = $output;
+
+ if (!self::$styles) {
+ self::$styles = self::initStyles();
+ }
+
+ $this->setStyle('default');
+ }
+
+ /**
+ * Sets a style definition.
+ *
+ * @param string $name The style name
+ * @param TableStyle $style A TableStyle instance
+ */
+ public static function setStyleDefinition($name, TableStyle $style)
+ {
+ if (!self::$styles) {
+ self::$styles = self::initStyles();
+ }
+
+ self::$styles[$name] = $style;
+ }
+
+ /**
+ * Gets a style definition by name.
+ *
+ * @param string $name The style name
+ *
+ * @return TableStyle A TableStyle instance
+ */
+ public static function getStyleDefinition($name)
+ {
+ if (!self::$styles) {
+ self::$styles = self::initStyles();
+ }
+
+ if (!self::$styles[$name]) {
+ throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
+ }
+
+ return self::$styles[$name];
+ }
+
+ /**
+ * Sets table style.
+ *
+ * @param TableStyle|string $name The style name or a TableStyle instance
+ *
+ * @return Table
+ */
+ public function setStyle($name)
+ {
+ if ($name instanceof TableStyle) {
+ $this->style = $name;
+ } elseif (isset(self::$styles[$name])) {
+ $this->style = self::$styles[$name];
+ } else {
+ throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
+ }
+
+ return $this;
+ }
+
+ /**
+ * Gets the current table style.
+ *
+ * @return TableStyle
+ */
+ public function getStyle()
+ {
+ return $this->style;
+ }
+
+ /**
+ * Sets table column style.
+ *
+ * @param int $columnIndex Column index
+ * @param TableStyle|string $name The style name or a TableStyle instance
+ *
+ * @return Table
+ */
+ public function setColumnStyle($columnIndex, $name)
+ {
+ $columnIndex = intval($columnIndex);
+
+ if ($name instanceof TableStyle) {
+ $this->columnStyles[$columnIndex] = $name;
+ } elseif (isset(self::$styles[$name])) {
+ $this->columnStyles[$columnIndex] = self::$styles[$name];
+ } else {
+ throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
+ }
+
+ return $this;
+ }
+
+ /**
+ * Gets the current style for a column.
+ *
+ * If style was not set, it returns the global table style.
+ *
+ * @param int $columnIndex Column index
+ *
+ * @return TableStyle
+ */
+ public function getColumnStyle($columnIndex)
+ {
+ if (isset($this->columnStyles[$columnIndex])) {
+ return $this->columnStyles[$columnIndex];
+ }
+
+ return $this->getStyle();
+ }
+
+ public function setHeaders(array $headers)
+ {
+ $headers = array_values($headers);
+ if (!empty($headers) && !is_array($headers[0])) {
+ $headers = array($headers);
+ }
+
+ $this->headers = $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($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;
+ }
+
+ public function setRow($column, array $row)
+ {
+ $this->rows[$column] = $row;
+
+ 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()
+ {
+ $this->calculateNumberOfColumns();
+ $rows = $this->buildTableRows($this->rows);
+ $headers = $this->buildTableRows($this->headers);
+
+ $this->calculateColumnsWidth(array_merge($headers, $rows));
+
+ $this->renderRowSeparator();
+ if (!empty($headers)) {
+ foreach ($headers as $header) {
+ $this->renderRow($header, $this->style->getCellHeaderFormat());
+ $this->renderRowSeparator();
+ }
+ }
+ foreach ($rows as $row) {
+ if ($row instanceof TableSeparator) {
+ $this->renderRowSeparator();
+ } else {
+ $this->renderRow($row, $this->style->getCellRowFormat());
+ }
+ }
+ if (!empty($rows)) {
+ $this->renderRowSeparator();
+ }
+
+ $this->cleanup();
+ }
+
+ /**
+ * Renders horizontal header separator.
+ *
+ * Example: +-----+-----------+-------+
+ */
+ private function renderRowSeparator()
+ {
+ if (0 === $count = $this->numberOfColumns) {
+ return;
+ }
+
+ if (!$this->style->getHorizontalBorderChar() && !$this->style->getCrossingChar()) {
+ return;
+ }
+
+ $markup = $this->style->getCrossingChar();
+ for ($column = 0; $column < $count; ++$column) {
+ $markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->columnWidths[$column]).$this->style->getCrossingChar();
+ }
+
+ $this->output->writeln(sprintf($this->style->getBorderFormat(), $markup));
+ }
+
+ /**
+ * Renders vertical column separator.
+ */
+ private function renderColumnSeparator()
+ {
+ return sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar());
+ }
+
+ /**
+ * 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;
+ }
+
+ $rowContent = $this->renderColumnSeparator();
+ foreach ($this->getRowColumns($row) as $column) {
+ $rowContent .= $this->renderCell($row, $column, $cellFormat);
+ $rowContent .= $this->renderColumnSeparator();
+ }
+ $this->output->writeln($rowContent);
+ }
+
+ /**
+ * Renders table cell with padding.
+ *
+ * @param array $row
+ * @param int $column
+ * @param string $cellFormat
+ */
+ private function renderCell(array $row, $column, $cellFormat)
+ {
+ $cell = isset($row[$column]) ? $row[$column] : '';
+ $width = $this->columnWidths[$column];
+ if ($cell instanceof TableCell && $cell->getColspan() > 1) {
+ // add the width of the following columns(numbers of colspan).
+ foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) {
+ $width += $this->getColumnSeparatorWidth() + $this->columnWidths[$nextColumn];
+ }
+ }
+
+ // str_pad won't work properly with multi-byte strings, we need to fix the padding
+ if (false !== $encoding = mb_detect_encoding($cell, null, true)) {
+ $width += strlen($cell) - mb_strwidth($cell, $encoding);
+ }
+
+ $style = $this->getColumnStyle($column);
+
+ if ($cell instanceof TableSeparator) {
+ return sprintf($style->getBorderFormat(), str_repeat($style->getHorizontalBorderChar(), $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()
+ {
+ if (null !== $this->numberOfColumns) {
+ return;
+ }
+
+ $columns = array(0);
+ foreach (array_merge($this->headers, $this->rows) as $row) {
+ if ($row instanceof TableSeparator) {
+ continue;
+ }
+
+ $columns[] = $this->getNumberOfColumns($row);
+ }
+
+ $this->numberOfColumns = max($columns);
+ }
+
+ private function buildTableRows($rows)
+ {
+ $unmergedRows = array();
+ 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) {
+ if (!strstr($cell, "\n")) {
+ continue;
+ }
+ $lines = explode("\n", $cell);
+ foreach ($lines as $lineKey => $line) {
+ if ($cell instanceof TableCell) {
+ $line = new TableCell($line, array('colspan' => $cell->getColspan()));
+ }
+ if (0 === $lineKey) {
+ $rows[$rowKey][$column] = $line;
+ } else {
+ $unmergedRows[$rowKey][$lineKey][$column] = $line;
+ }
+ }
+ }
+ }
+
+ $tableRows = array();
+ foreach ($rows as $rowKey => $row) {
+ $tableRows[] = $this->fillCells($row);
+ if (isset($unmergedRows[$rowKey])) {
+ $tableRows = array_merge($tableRows, $unmergedRows[$rowKey]);
+ }
+ }
+
+ return $tableRows;
+ }
+
+ /**
+ * fill rows that contains rowspan > 1.
+ *
+ * @param array $rows
+ * @param int $line
+ *
+ * @return array
+ */
+ private function fillNextRows($rows, $line)
+ {
+ $unmergedRows = array();
+ foreach ($rows[$line] as $column => $cell) {
+ if ($cell instanceof TableCell && $cell->getRowspan() > 1) {
+ $nbLines = $cell->getRowspan() - 1;
+ $lines = array($cell);
+ if (strstr($cell, "\n")) {
+ $lines = explode("\n", $cell);
+ $nbLines = count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines;
+
+ $rows[$line][$column] = new TableCell($lines[0], array('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, array('colspan' => $cell->getColspan()));
+ }
+ }
+ }
+
+ 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, array($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, array($row));
+ }
+ }
+
+ return $rows;
+ }
+
+ /**
+ * fill cells for a row that contains colspan > 1.
+ *
+ * @param array $row
+ *
+ * @return array
+ */
+ private function fillCells($row)
+ {
+ $newRow = array();
+ 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;
+ }
+
+ /**
+ * @param array $rows
+ * @param int $line
+ *
+ * @return array
+ */
+ private function copyRow($rows, $line)
+ {
+ $row = $rows[$line];
+ foreach ($row as $cellKey => $cellValue) {
+ $row[$cellKey] = '';
+ if ($cellValue instanceof TableCell) {
+ $row[$cellKey] = new TableCell('', array('colspan' => $cellValue->getColspan()));
+ }
+ }
+
+ return $row;
+ }
+
+ /**
+ * Gets number of columns by row.
+ *
+ * @param array $row
+ *
+ * @return int
+ */
+ private function getNumberOfColumns(array $row)
+ {
+ $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.
+ *
+ * @param array $row
+ *
+ * @return array
+ */
+ private function getRowColumns($row)
+ {
+ $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.
+ *
+ * @param array $rows
+ */
+ private function calculateColumnsWidth($rows)
+ {
+ for ($column = 0; $column < $this->numberOfColumns; ++$column) {
+ $lengths = array();
+ foreach ($rows as $row) {
+ if ($row instanceof TableSeparator) {
+ continue;
+ }
+
+ foreach ($row as $i => $cell) {
+ if ($cell instanceof TableCell) {
+ $textLength = strlen($cell);
+ if ($textLength > 0) {
+ $contentColumns = str_split($cell, ceil($textLength / $cell->getColspan()));
+ foreach ($contentColumns as $position => $content) {
+ $row[$i + $position] = $content;
+ }
+ }
+ }
+ }
+
+ $lengths[] = $this->getCellWidth($row, $column);
+ }
+
+ $this->columnWidths[$column] = max($lengths) + strlen($this->style->getCellRowContentFormat()) - 2;
+ }
+ }
+
+ /**
+ * Gets column width.
+ *
+ * @return int
+ */
+ private function getColumnSeparatorWidth()
+ {
+ return strlen(sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar()));
+ }
+
+ /**
+ * Gets cell width.
+ *
+ * @param array $row
+ * @param int $column
+ *
+ * @return int
+ */
+ private function getCellWidth(array $row, $column)
+ {
+ if (isset($row[$column])) {
+ $cell = $row[$column];
+ $cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
+
+ return $cellWidth;
+ }
+
+ return 0;
+ }
+
+ /**
+ * Called after rendering to cleanup cache data.
+ */
+ private function cleanup()
+ {
+ $this->columnWidths = array();
+ $this->numberOfColumns = null;
+ }
+
+ private static function initStyles()
+ {
+ $borderless = new TableStyle();
+ $borderless
+ ->setHorizontalBorderChar('=')
+ ->setVerticalBorderChar(' ')
+ ->setCrossingChar(' ')
+ ;
+
+ $compact = new TableStyle();
+ $compact
+ ->setHorizontalBorderChar('')
+ ->setVerticalBorderChar(' ')
+ ->setCrossingChar('')
+ ->setCellRowContentFormat('%s')
+ ;
+
+ $styleGuide = new TableStyle();
+ $styleGuide
+ ->setHorizontalBorderChar('-')
+ ->setVerticalBorderChar(' ')
+ ->setCrossingChar(' ')
+ ->setCellHeaderFormat('%s')
+ ;
+
+ return array(
+ 'default' => new TableStyle(),
+ 'borderless' => $borderless,
+ 'compact' => $compact,
+ 'symfony-style-guide' => $styleGuide,
+ );
+ }
+}
diff --git a/vendor/symfony/console/Helper/TableCell.php b/vendor/symfony/console/Helper/TableCell.php
new file mode 100644
index 00000000..69442d42
--- /dev/null
+++ b/vendor/symfony/console/Helper/TableCell.php
@@ -0,0 +1,79 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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 <a.aitboudad@gmail.com>
+ */
+class TableCell
+{
+ /**
+ * @var string
+ */
+ private $value;
+
+ /**
+ * @var array
+ */
+ private $options = array(
+ 'rowspan' => 1,
+ 'colspan' => 1,
+ );
+
+ /**
+ * @param string $value
+ * @param array $options
+ */
+ public function __construct($value = '', array $options = array())
+ {
+ $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'];
+ }
+}
diff --git a/vendor/symfony/console/Helper/TableHelper.php b/vendor/symfony/console/Helper/TableHelper.php
new file mode 100644
index 00000000..3c7a1a78
--- /dev/null
+++ b/vendor/symfony/console/Helper/TableHelper.php
@@ -0,0 +1,269 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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\Output\NullOutput;
+use Symfony\Component\Console\Exception\InvalidArgumentException;
+
+/**
+ * Provides helpers to display table output.
+ *
+ * @author Саша Стаменковић <umpirsky@gmail.com>
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @deprecated since version 2.5, to be removed in 3.0
+ * Use {@link Table} instead.
+ */
+class TableHelper extends Helper
+{
+ const LAYOUT_DEFAULT = 0;
+ const LAYOUT_BORDERLESS = 1;
+ const LAYOUT_COMPACT = 2;
+
+ /**
+ * @var Table
+ */
+ private $table;
+
+ public function __construct($triggerDeprecationError = true)
+ {
+ if ($triggerDeprecationError) {
+ @trigger_error('The '.__CLASS__.' class is deprecated since version 2.5 and will be removed in 3.0. Use the Symfony\Component\Console\Helper\Table class instead.', E_USER_DEPRECATED);
+ }
+
+ $this->table = new Table(new NullOutput());
+ }
+
+ /**
+ * Sets table layout type.
+ *
+ * @param int $layout self::LAYOUT_*
+ *
+ * @return TableHelper
+ *
+ * @throws InvalidArgumentException when the table layout is not known
+ */
+ public function setLayout($layout)
+ {
+ switch ($layout) {
+ case self::LAYOUT_BORDERLESS:
+ $this->table->setStyle('borderless');
+ break;
+
+ case self::LAYOUT_COMPACT:
+ $this->table->setStyle('compact');
+ break;
+
+ case self::LAYOUT_DEFAULT:
+ $this->table->setStyle('default');
+ break;
+
+ default:
+ throw new InvalidArgumentException(sprintf('Invalid table layout "%s".', $layout));
+ }
+
+ return $this;
+ }
+
+ public function setHeaders(array $headers)
+ {
+ $this->table->setHeaders($headers);
+
+ return $this;
+ }
+
+ public function setRows(array $rows)
+ {
+ $this->table->setRows($rows);
+
+ return $this;
+ }
+
+ public function addRows(array $rows)
+ {
+ $this->table->addRows($rows);
+
+ return $this;
+ }
+
+ public function addRow(array $row)
+ {
+ $this->table->addRow($row);
+
+ return $this;
+ }
+
+ public function setRow($column, array $row)
+ {
+ $this->table->setRow($column, $row);
+
+ return $this;
+ }
+
+ /**
+ * Sets padding character, used for cell padding.
+ *
+ * @param string $paddingChar
+ *
+ * @return TableHelper
+ */
+ public function setPaddingChar($paddingChar)
+ {
+ $this->table->getStyle()->setPaddingChar($paddingChar);
+
+ return $this;
+ }
+
+ /**
+ * Sets horizontal border character.
+ *
+ * @param string $horizontalBorderChar
+ *
+ * @return TableHelper
+ */
+ public function setHorizontalBorderChar($horizontalBorderChar)
+ {
+ $this->table->getStyle()->setHorizontalBorderChar($horizontalBorderChar);
+
+ return $this;
+ }
+
+ /**
+ * Sets vertical border character.
+ *
+ * @param string $verticalBorderChar
+ *
+ * @return TableHelper
+ */
+ public function setVerticalBorderChar($verticalBorderChar)
+ {
+ $this->table->getStyle()->setVerticalBorderChar($verticalBorderChar);
+
+ return $this;
+ }
+
+ /**
+ * Sets crossing character.
+ *
+ * @param string $crossingChar
+ *
+ * @return TableHelper
+ */
+ public function setCrossingChar($crossingChar)
+ {
+ $this->table->getStyle()->setCrossingChar($crossingChar);
+
+ return $this;
+ }
+
+ /**
+ * Sets header cell format.
+ *
+ * @param string $cellHeaderFormat
+ *
+ * @return TableHelper
+ */
+ public function setCellHeaderFormat($cellHeaderFormat)
+ {
+ $this->table->getStyle()->setCellHeaderFormat($cellHeaderFormat);
+
+ return $this;
+ }
+
+ /**
+ * Sets row cell format.
+ *
+ * @param string $cellRowFormat
+ *
+ * @return TableHelper
+ */
+ public function setCellRowFormat($cellRowFormat)
+ {
+ $this->table->getStyle()->setCellHeaderFormat($cellRowFormat);
+
+ return $this;
+ }
+
+ /**
+ * Sets row cell content format.
+ *
+ * @param string $cellRowContentFormat
+ *
+ * @return TableHelper
+ */
+ public function setCellRowContentFormat($cellRowContentFormat)
+ {
+ $this->table->getStyle()->setCellRowContentFormat($cellRowContentFormat);
+
+ return $this;
+ }
+
+ /**
+ * Sets table border format.
+ *
+ * @param string $borderFormat
+ *
+ * @return TableHelper
+ */
+ public function setBorderFormat($borderFormat)
+ {
+ $this->table->getStyle()->setBorderFormat($borderFormat);
+
+ return $this;
+ }
+
+ /**
+ * Sets cell padding type.
+ *
+ * @param int $padType STR_PAD_*
+ *
+ * @return TableHelper
+ */
+ public function setPadType($padType)
+ {
+ $this->table->getStyle()->setPadType($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)
+ {
+ $p = new \ReflectionProperty($this->table, 'output');
+ $p->setAccessible(true);
+ $p->setValue($this->table, $output);
+
+ $this->table->render();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'table';
+ }
+}
diff --git a/vendor/symfony/console/Helper/TableSeparator.php b/vendor/symfony/console/Helper/TableSeparator.php
new file mode 100644
index 00000000..8cbbc661
--- /dev/null
+++ b/vendor/symfony/console/Helper/TableSeparator.php
@@ -0,0 +1,29 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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 <fabien@symfony.com>
+ */
+class TableSeparator extends TableCell
+{
+ /**
+ * @param string $value
+ * @param array $options
+ */
+ public function __construct(array $options = array())
+ {
+ parent::__construct('', $options);
+ }
+}
diff --git a/vendor/symfony/console/Helper/TableStyle.php b/vendor/symfony/console/Helper/TableStyle.php
new file mode 100644
index 00000000..d7e28ff2
--- /dev/null
+++ b/vendor/symfony/console/Helper/TableStyle.php
@@ -0,0 +1,258 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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 <fabien@symfony.com>
+ * @author Саша Стаменковић <umpirsky@gmail.com>
+ */
+class TableStyle
+{
+ private $paddingChar = ' ';
+ private $horizontalBorderChar = '-';
+ private $verticalBorderChar = '|';
+ private $crossingChar = '+';
+ private $cellHeaderFormat = '<info>%s</info>';
+ private $cellRowFormat = '%s';
+ private $cellRowContentFormat = ' %s ';
+ private $borderFormat = '%s';
+ private $padType = STR_PAD_RIGHT;
+
+ /**
+ * Sets padding character, used for cell padding.
+ *
+ * @param string $paddingChar
+ *
+ * @return TableStyle
+ */
+ public function setPaddingChar($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 character.
+ *
+ * @param string $horizontalBorderChar
+ *
+ * @return TableStyle
+ */
+ public function setHorizontalBorderChar($horizontalBorderChar)
+ {
+ $this->horizontalBorderChar = $horizontalBorderChar;
+
+ return $this;
+ }
+
+ /**
+ * Gets horizontal border character.
+ *
+ * @return string
+ */
+ public function getHorizontalBorderChar()
+ {
+ return $this->horizontalBorderChar;
+ }
+
+ /**
+ * Sets vertical border character.
+ *
+ * @param string $verticalBorderChar
+ *
+ * @return TableStyle
+ */
+ public function setVerticalBorderChar($verticalBorderChar)
+ {
+ $this->verticalBorderChar = $verticalBorderChar;
+
+ return $this;
+ }
+
+ /**
+ * Gets vertical border character.
+ *
+ * @return string
+ */
+ public function getVerticalBorderChar()
+ {
+ return $this->verticalBorderChar;
+ }
+
+ /**
+ * Sets crossing character.
+ *
+ * @param string $crossingChar
+ *
+ * @return TableStyle
+ */
+ public function setCrossingChar($crossingChar)
+ {
+ $this->crossingChar = $crossingChar;
+
+ return $this;
+ }
+
+ /**
+ * Gets crossing character.
+ *
+ * @return string $crossingChar
+ */
+ public function getCrossingChar()
+ {
+ return $this->crossingChar;
+ }
+
+ /**
+ * Sets header cell format.
+ *
+ * @param string $cellHeaderFormat
+ *
+ * @return TableStyle
+ */
+ public function setCellHeaderFormat($cellHeaderFormat)
+ {
+ $this->cellHeaderFormat = $cellHeaderFormat;
+
+ return $this;
+ }
+
+ /**
+ * Gets header cell format.
+ *
+ * @return string
+ */
+ public function getCellHeaderFormat()
+ {
+ return $this->cellHeaderFormat;
+ }
+
+ /**
+ * Sets row cell format.
+ *
+ * @param string $cellRowFormat
+ *
+ * @return TableStyle
+ */
+ public function setCellRowFormat($cellRowFormat)
+ {
+ $this->cellRowFormat = $cellRowFormat;
+
+ return $this;
+ }
+
+ /**
+ * Gets row cell format.
+ *
+ * @return string
+ */
+ public function getCellRowFormat()
+ {
+ return $this->cellRowFormat;
+ }
+
+ /**
+ * Sets row cell content format.
+ *
+ * @param string $cellRowContentFormat
+ *
+ * @return TableStyle
+ */
+ public function setCellRowContentFormat($cellRowContentFormat)
+ {
+ $this->cellRowContentFormat = $cellRowContentFormat;
+
+ return $this;
+ }
+
+ /**
+ * Gets row cell content format.
+ *
+ * @return string
+ */
+ public function getCellRowContentFormat()
+ {
+ return $this->cellRowContentFormat;
+ }
+
+ /**
+ * Sets table border format.
+ *
+ * @param string $borderFormat
+ *
+ * @return TableStyle
+ */
+ public function setBorderFormat($borderFormat)
+ {
+ $this->borderFormat = $borderFormat;
+
+ return $this;
+ }
+
+ /**
+ * Gets table border format.
+ *
+ * @return string
+ */
+ public function getBorderFormat()
+ {
+ return $this->borderFormat;
+ }
+
+ /**
+ * Sets cell padding type.
+ *
+ * @param int $padType STR_PAD_*
+ *
+ * @return TableStyle
+ */
+ public function setPadType($padType)
+ {
+ if (!in_array($padType, array(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;
+ }
+}