Browse Source

added classloader and console symfony components.

Taylor Otwell 12 years ago
parent
commit
f4258f7759
42 changed files with 6667 additions and 0 deletions
  1. 96 0
      vendor/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php
  2. 222 0
      vendor/Symfony/Component/ClassLoader/ClassCollectionLoader.php
  3. 133 0
      vendor/Symfony/Component/ClassLoader/ClassMapGenerator.php
  4. 63 0
      vendor/Symfony/Component/ClassLoader/DebugUniversalClassLoader.php
  5. 19 0
      vendor/Symfony/Component/ClassLoader/LICENSE
  6. 76 0
      vendor/Symfony/Component/ClassLoader/MapClassLoader.php
  7. 60 0
      vendor/Symfony/Component/ClassLoader/README.md
  8. 319 0
      vendor/Symfony/Component/ClassLoader/UniversalClassLoader.php
  9. 30 0
      vendor/Symfony/Component/ClassLoader/composer.json
  10. 1007 0
      vendor/Symfony/Component/Console/Application.php
  11. 612 0
      vendor/Symfony/Component/Console/Command/Command.php
  12. 84 0
      vendor/Symfony/Component/Console/Command/HelpCommand.php
  13. 87 0
      vendor/Symfony/Component/Console/Command/ListCommand.php
  14. 192 0
      vendor/Symfony/Component/Console/Formatter/OutputFormatter.php
  15. 83 0
      vendor/Symfony/Component/Console/Formatter/OutputFormatterInterface.php
  16. 218 0
      vendor/Symfony/Component/Console/Formatter/OutputFormatterStyle.php
  17. 72 0
      vendor/Symfony/Component/Console/Formatter/OutputFormatterStyleInterface.php
  18. 139 0
      vendor/Symfony/Component/Console/Helper/DialogHelper.php
  19. 97 0
      vendor/Symfony/Component/Console/Helper/FormatterHelper.php
  20. 42 0
      vendor/Symfony/Component/Console/Helper/Helper.php
  21. 49 0
      vendor/Symfony/Component/Console/Helper/HelperInterface.php
  22. 104 0
      vendor/Symfony/Component/Console/Helper/HelperSet.php
  23. 311 0
      vendor/Symfony/Component/Console/Input/ArgvInput.php
  24. 190 0
      vendor/Symfony/Component/Console/Input/ArrayInput.php
  25. 211 0
      vendor/Symfony/Component/Console/Input/Input.php
  26. 132 0
      vendor/Symfony/Component/Console/Input/InputArgument.php
  27. 533 0
      vendor/Symfony/Component/Console/Input/InputDefinition.php
  28. 152 0
      vendor/Symfony/Component/Console/Input/InputInterface.php
  29. 201 0
      vendor/Symfony/Component/Console/Input/InputOption.php
  30. 79 0
      vendor/Symfony/Component/Console/Input/StringInput.php
  31. 19 0
      vendor/Symfony/Component/Console/LICENSE
  32. 83 0
      vendor/Symfony/Component/Console/Output/ConsoleOutput.php
  33. 30 0
      vendor/Symfony/Component/Console/Output/ConsoleOutputInterface.php
  34. 34 0
      vendor/Symfony/Component/Console/Output/NullOutput.php
  35. 180 0
      vendor/Symfony/Component/Console/Output/Output.php
  36. 109 0
      vendor/Symfony/Component/Console/Output/OutputInterface.php
  37. 113 0
      vendor/Symfony/Component/Console/Output/StreamOutput.php
  38. 48 0
      vendor/Symfony/Component/Console/README.md
  39. 206 0
      vendor/Symfony/Component/Console/Shell.php
  40. 102 0
      vendor/Symfony/Component/Console/Tester/ApplicationTester.php
  41. 100 0
      vendor/Symfony/Component/Console/Tester/CommandTester.php
  42. 30 0
      vendor/Symfony/Component/Console/composer.json

+ 96 - 0
vendor/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php

@@ -0,0 +1,96 @@
+<?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\ClassLoader;
+
+/**
+ * ApcUniversalClassLoader implements a "universal" autoloader cached in APC for PHP 5.3.
+ *
+ * It is able to load classes that use either:
+ *
+ *  * The technical interoperability standards for PHP 5.3 namespaces and
+ *    class names (https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md);
+ *
+ *  * The PEAR naming convention for classes (http://pear.php.net/).
+ *
+ * Classes from a sub-namespace or a sub-hierarchy of PEAR classes can be
+ * looked for in a list of locations to ease the vendoring of a sub-set of
+ * classes for large projects.
+ *
+ * Example usage:
+ *
+ *     require 'vendor/symfony/src/Symfony/Component/ClassLoader/UniversalClassLoader.php';
+ *     require 'vendor/symfony/src/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php';
+ *
+ *     use Symfony\Component\ClassLoader\ApcUniversalClassLoader;
+ *
+ *     $loader = new ApcUniversalClassLoader('apc.prefix.');
+ *
+ *     // register classes with namespaces
+ *     $loader->registerNamespaces(array(
+ *         'Symfony\Component' => __DIR__.'/component',
+ *         'Symfony'           => __DIR__.'/framework',
+ *         'Sensio'            => array(__DIR__.'/src', __DIR__.'/vendor'),
+ *     ));
+ *
+ *     // register a library using the PEAR naming convention
+ *     $loader->registerPrefixes(array(
+ *         'Swift_' => __DIR__.'/Swift',
+ *     ));
+ *
+ *     // activate the autoloader
+ *     $loader->register();
+ *
+ * In this example, if you try to use a class in the Symfony\Component
+ * namespace or one of its children (Symfony\Component\Console for instance),
+ * the autoloader will first look for the class under the component/
+ * directory, and it will then fallback to the framework/ directory if not
+ * found before giving up.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Kris Wallsmith <kris@symfony.com>
+ *
+ * @api
+ */
+class ApcUniversalClassLoader extends UniversalClassLoader
+{
+    private $prefix;
+
+    /**
+     * Constructor.
+     *
+     * @param string $prefix A prefix to create a namespace in APC
+     *
+     * @api
+     */
+    public function __construct($prefix)
+    {
+        if (!extension_loaded('apc')) {
+            throw new \RuntimeException('Unable to use ApcUniversalClassLoader as APC is not enabled.');
+        }
+
+        $this->prefix = $prefix;
+    }
+
+    /**
+     * Finds a file by class name while caching lookups to APC.
+     *
+     * @param string $class A class name to resolve to file
+     */
+    public function findFile($class)
+    {
+        if (false === $file = apc_fetch($this->prefix.$class)) {
+            apc_store($this->prefix.$class, $file = parent::findFile($class));
+        }
+
+        return $file;
+    }
+}

+ 222 - 0
vendor/Symfony/Component/ClassLoader/ClassCollectionLoader.php

@@ -0,0 +1,222 @@
+<?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\ClassLoader;
+
+/**
+ * ClassCollectionLoader.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ClassCollectionLoader
+{
+    static private $loaded;
+
+    /**
+     * Loads a list of classes and caches them in one big file.
+     *
+     * @param array   $classes    An array of classes to load
+     * @param string  $cacheDir   A cache directory
+     * @param string  $name       The cache name prefix
+     * @param Boolean $autoReload Whether to flush the cache when the cache is stale or not
+     * @param Boolean $adaptive   Whether to remove already declared classes or not
+     * @param string  $extension  File extension of the resulting file
+     *
+     * @throws \InvalidArgumentException When class can't be loaded
+     */
+    static public function load($classes, $cacheDir, $name, $autoReload, $adaptive = false, $extension = '.php')
+    {
+        // each $name can only be loaded once per PHP process
+        if (isset(self::$loaded[$name])) {
+            return;
+        }
+
+        self::$loaded[$name] = true;
+
+        if ($adaptive) {
+            // don't include already declared classes
+            $classes = array_diff($classes, get_declared_classes(), get_declared_interfaces());
+
+            // the cache is different depending on which classes are already declared
+            $name = $name.'-'.substr(md5(implode('|', $classes)), 0, 5);
+        }
+
+        $cache = $cacheDir.'/'.$name.$extension;
+
+        // auto-reload
+        $reload = false;
+        if ($autoReload) {
+            $metadata = $cacheDir.'/'.$name.$extension.'.meta';
+            if (!is_file($metadata) || !is_file($cache)) {
+                $reload = true;
+            } else {
+                $time = filemtime($cache);
+                $meta = unserialize(file_get_contents($metadata));
+
+                if ($meta[1] != $classes) {
+                    $reload = true;
+                } else {
+                    foreach ($meta[0] as $resource) {
+                        if (!is_file($resource) || filemtime($resource) > $time) {
+                            $reload = true;
+
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        if (!$reload && is_file($cache)) {
+            require_once $cache;
+
+            return;
+        }
+
+        $files = array();
+        $content = '';
+        foreach ($classes as $class) {
+            if (!class_exists($class) && !interface_exists($class) && (!function_exists('trait_exists') || !trait_exists($class))) {
+                throw new \InvalidArgumentException(sprintf('Unable to load class "%s"', $class));
+            }
+
+            $r = new \ReflectionClass($class);
+            $files[] = $r->getFileName();
+
+            $c = preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($r->getFileName()));
+
+            // add namespace declaration for global code
+            if (!$r->inNamespace()) {
+                $c = "\nnamespace\n{\n".self::stripComments($c)."\n}\n";
+            } else {
+                $c = self::fixNamespaceDeclarations('<?php '.$c);
+                $c = preg_replace('/^\s*<\?php/', '', $c);
+            }
+
+            $content .= $c;
+        }
+
+        // cache the core classes
+        if (!is_dir(dirname($cache))) {
+            mkdir(dirname($cache), 0777, true);
+        }
+        self::writeCacheFile($cache, '<?php '.$content);
+
+        if ($autoReload) {
+            // save the resources
+            self::writeCacheFile($metadata, serialize(array($files, $classes)));
+        }
+    }
+
+    /**
+     * Adds brackets around each namespace if it's not already the case.
+     *
+     * @param string $source Namespace string
+     *
+     * @return string Namespaces with brackets
+     */
+    static public function fixNamespaceDeclarations($source)
+    {
+        if (!function_exists('token_get_all')) {
+            return $source;
+        }
+
+        $output = '';
+        $inNamespace = false;
+        $tokens = token_get_all($source);
+
+        for ($i = 0, $max = count($tokens); $i < $max; $i++) {
+            $token = $tokens[$i];
+            if (is_string($token)) {
+                $output .= $token;
+            } elseif (in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
+                // strip comments
+                continue;
+            } elseif (T_NAMESPACE === $token[0]) {
+                if ($inNamespace) {
+                    $output .= "}\n";
+                }
+                $output .= $token[1];
+
+                // namespace name and whitespaces
+                while (($t = $tokens[++$i]) && is_array($t) && in_array($t[0], array(T_WHITESPACE, T_NS_SEPARATOR, T_STRING))) {
+                    $output .= $t[1];
+                }
+                if (is_string($t) && '{' === $t) {
+                    $inNamespace = false;
+                    --$i;
+                } else {
+                    $output .= "\n{";
+                    $inNamespace = true;
+                }
+            } else {
+                $output .= $token[1];
+            }
+        }
+
+        if ($inNamespace) {
+            $output .= "}\n";
+        }
+
+        return $output;
+    }
+
+    /**
+     * Writes a cache file.
+     *
+     * @param string $file Filename
+     * @param string $content Temporary file content
+     *
+     * @throws \RuntimeException when a cache file cannot be written
+     */
+    static private function writeCacheFile($file, $content)
+    {
+        $tmpFile = tempnam(dirname($file), basename($file));
+        if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) {
+            chmod($file, 0644);
+
+            return;
+        }
+
+        throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $file));
+    }
+
+    /**
+     * Removes comments from a PHP source string.
+     *
+     * We don't use the PHP php_strip_whitespace() function
+     * as we want the content to be readable and well-formatted.
+     *
+     * @param string $source A PHP string
+     *
+     * @return string The PHP string with the comments removed
+     */
+    static private function stripComments($source)
+    {
+        if (!function_exists('token_get_all')) {
+            return $source;
+        }
+
+        $output = '';
+        foreach (token_get_all($source) as $token) {
+            if (is_string($token)) {
+                $output .= $token;
+            } elseif (!in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
+                $output .= $token[1];
+            }
+        }
+
+        // replace multiple new lines with a single newline
+        $output = preg_replace(array('/\s+$/Sm', '/\n+/S'), "\n", $output);
+
+        return $output;
+    }
+}

+ 133 - 0
vendor/Symfony/Component/ClassLoader/ClassMapGenerator.php

@@ -0,0 +1,133 @@
+<?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\ClassLoader;
+
+/**
+ * ClassMapGenerator
+ *
+ * @author Gyula Sallai <salla016@gmail.com>
+ */
+class ClassMapGenerator
+{
+    /**
+     * Generate a class map file
+     *
+     * @param array|string $dirs Directories or a single path to search in
+     * @param string $file The name of the class map file
+     */
+    static public function dump($dirs, $file)
+    {
+        $dirs = (array) $dirs;
+        $maps = array();
+
+        foreach ($dirs as $dir) {
+            $maps = array_merge($maps, static::createMap($dir));
+        }
+
+        file_put_contents($file, sprintf('<?php return %s;', var_export($maps, true)));
+    }
+
+    /**
+     * Iterate over all files in the given directory searching for classes
+     *
+     * @param Iterator|string $dir The directory to search in or an iterator
+     *
+     * @return array A class map array
+     */
+    static public function createMap($dir)
+    {
+        if (is_string($dir)) {
+            $dir = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir));
+        }
+
+        $map = array();
+
+        foreach ($dir as $file) {
+            if (!$file->isFile()) {
+                continue;
+            }
+
+            $path = $file->getRealPath();
+
+            if (pathinfo($path, PATHINFO_EXTENSION) !== 'php') {
+                continue;
+            }
+
+            $classes = self::findClasses($path);
+
+            foreach ($classes as $class) {
+                $map[$class] = $path;
+            }
+
+        }
+
+        return $map;
+    }
+
+    /**
+     * Extract the classes in the given file
+     *
+     * @param string $path The file to check
+     *
+     * @return array The found classes
+     */
+    static private function findClasses($path)
+    {
+        $contents = file_get_contents($path);
+        $tokens   = token_get_all($contents);
+        $T_TRAIT  = version_compare(PHP_VERSION, '5.4', '<') ? -1 : T_TRAIT;
+
+        $classes = array();
+
+        $namespace = '';
+        for ($i = 0, $max = count($tokens); $i < $max; $i++) {
+            $token = $tokens[$i];
+
+            if (is_string($token)) {
+                continue;
+            }
+
+            $class = '';
+
+            switch ($token[0]) {
+                case T_NAMESPACE:
+                    $namespace = '';
+                    // If there is a namespace, extract it
+                    while (($t = $tokens[++$i]) && is_array($t)) {
+                        if (in_array($t[0], array(T_STRING, T_NS_SEPARATOR))) {
+                            $namespace .= $t[1];
+                        }
+                    }
+                    $namespace .= '\\';
+                    break;
+                case T_CLASS:
+                case T_INTERFACE:
+                case $T_TRAIT:
+                    // Find the classname
+                    while (($t = $tokens[++$i]) && is_array($t)) {
+                        if (T_STRING === $t[0]) {
+                            $class .= $t[1];
+                        } elseif ($class !== '' && T_WHITESPACE == $t[0]) {
+                            break;
+                        }
+                    }
+
+                    $classes[] = ltrim($namespace . $class, '\\');
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        return $classes;
+    }
+}

+ 63 - 0
vendor/Symfony/Component/ClassLoader/DebugUniversalClassLoader.php

@@ -0,0 +1,63 @@
+<?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\ClassLoader;
+
+/**
+ * Checks that the class is actually declared in the included file.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class DebugUniversalClassLoader extends UniversalClassLoader
+{
+    /**
+     * Replaces all regular UniversalClassLoader instances by a DebugUniversalClassLoader ones.
+     */
+    static public function enable()
+    {
+        if (!is_array($functions = spl_autoload_functions())) {
+            return;
+        }
+
+        foreach ($functions as $function) {
+            spl_autoload_unregister($function);
+        }
+
+        foreach ($functions as $function) {
+            if (is_array($function) && $function[0] instanceof UniversalClassLoader) {
+                $loader = new static();
+                $loader->registerNamespaceFallbacks($function[0]->getNamespaceFallbacks());
+                $loader->registerPrefixFallbacks($function[0]->getPrefixFallbacks());
+                $loader->registerNamespaces($function[0]->getNamespaces());
+                $loader->registerPrefixes($function[0]->getPrefixes());
+                $loader->useIncludePath($function[0]->getUseIncludePath());
+
+                $function[0] = $loader;
+            }
+
+            spl_autoload_register($function);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function loadClass($class)
+    {
+        if ($file = $this->findFile($class)) {
+            require $file;
+
+            if (!class_exists($class, false) && !interface_exists($class, false) && (!function_exists('trait_exists') || !trait_exists($class, false))) {
+                throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file));
+            }
+        }
+    }
+}

+ 19 - 0
vendor/Symfony/Component/ClassLoader/LICENSE

@@ -0,0 +1,19 @@
+Copyright (c) 2004-2012 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 76 - 0
vendor/Symfony/Component/ClassLoader/MapClassLoader.php

@@ -0,0 +1,76 @@
+<?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\ClassLoader;
+
+/**
+ * A class loader that uses a mapping file to look up paths.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class MapClassLoader
+{
+    private $map = array();
+
+    /**
+     * Constructor.
+     *
+     * @param array $map A map where keys are classes and values the absolute file path
+     */
+    public function __construct(array $map)
+    {
+        $this->map = $map;
+    }
+
+    /**
+     * Registers this instance as an autoloader.
+     *
+     * @param Boolean $prepend Whether to prepend the autoloader or not
+     */
+    public function register($prepend = false)
+    {
+        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+    }
+
+    /**
+     * Loads the given class or interface.
+     *
+     * @param string $class The name of the class
+     */
+    public function loadClass($class)
+    {
+        if ('\\' === $class[0]) {
+            $class = substr($class, 1);
+        }
+
+        if (isset($this->map[$class])) {
+            require $this->map[$class];
+        }
+    }
+
+    /**
+     * Finds the path to the file where the class is defined.
+     *
+     * @param string $class The name of the class
+     *
+     * @return string|null The path, if found
+     */
+    public function findFile($class)
+    {
+        if ('\\' === $class[0]) {
+            $class = substr($class, 1);
+        }
+
+        if (isset($this->map[$class])) {
+            return $this->map[$class];
+        }
+    }
+}

+ 60 - 0
vendor/Symfony/Component/ClassLoader/README.md

@@ -0,0 +1,60 @@
+ClassLoader Component
+=====================
+
+ClassLoader loads your project classes automatically if they follow some
+standard PHP conventions.
+
+The Universal ClassLoader is able to autoload classes that implement the PSR-0
+standard or the PEAR naming convention.
+
+First, register the autoloader:
+
+    require_once __DIR__.'/src/Symfony/Component/ClassLoader/UniversalClassLoader.php';
+
+    use Symfony\Component\ClassLoader\UniversalClassLoader;
+
+    $loader = new UniversalClassLoader();
+    $loader->register();
+
+Then, register some namespaces with the `registerNamespace()` method:
+
+    $loader->registerNamespace('Symfony', __DIR__.'/src');
+    $loader->registerNamespace('Monolog', __DIR__.'/vendor/monolog/src');
+
+The `registerNamespace()` method takes a namespace prefix and a path where to
+look for the classes as arguments.
+
+You can also register a sub-namespaces:
+
+    $loader->registerNamespace('Doctrine\\Common', __DIR__.'/vendor/doctrine-common/lib');
+
+The order of registration is significant and the first registered namespace
+takes precedence over later registered one.
+
+You can also register more than one path for a given namespace:
+
+    $loader->registerNamespace('Symfony', array(__DIR__.'/src', __DIR__.'/symfony/src'));
+
+Alternatively, you can use the `registerNamespaces()` method to register more
+than one namespace at once:
+
+    $loader->registerNamespaces(array(
+        'Symfony'          => array(__DIR__.'/src', __DIR__.'/symfony/src'),
+        'Doctrine\\Common' => __DIR__.'/vendor/doctrine-common/lib',
+        'Doctrine'         => __DIR__.'/vendor/doctrine/lib',
+        'Monolog'          => __DIR__.'/vendor/monolog/src',
+    ));
+
+For better performance, you can use the APC based version of the universal
+class loader:
+
+    require_once __DIR__.'/src/Symfony/Component/ClassLoader/UniversalClassLoader.php';
+    require_once __DIR__.'/src/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php';
+
+    use Symfony\Component\ClassLoader\ApcUniversalClassLoader;
+
+    $loader = new ApcUniversalClassLoader('apc.prefix.');
+
+Furthermore, the component provides tools to aggregate classes into a single
+file, which is especially useful to improve performance on servers that do not
+provide byte caches.

+ 319 - 0
vendor/Symfony/Component/ClassLoader/UniversalClassLoader.php

@@ -0,0 +1,319 @@
+<?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\ClassLoader;
+
+/**
+ * UniversalClassLoader implements a "universal" autoloader for PHP 5.3.
+ *
+ * It is able to load classes that use either:
+ *
+ *  * The technical interoperability standards for PHP 5.3 namespaces and
+ *    class names (https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md);
+ *
+ *  * The PEAR naming convention for classes (http://pear.php.net/).
+ *
+ * Classes from a sub-namespace or a sub-hierarchy of PEAR classes can be
+ * looked for in a list of locations to ease the vendoring of a sub-set of
+ * classes for large projects.
+ *
+ * Example usage:
+ *
+ *     $loader = new UniversalClassLoader();
+ *
+ *     // register classes with namespaces
+ *     $loader->registerNamespaces(array(
+ *         'Symfony\Component' => __DIR__.'/component',
+ *         'Symfony'           => __DIR__.'/framework',
+ *         'Sensio'            => array(__DIR__.'/src', __DIR__.'/vendor'),
+ *     ));
+ *
+ *     // register a library using the PEAR naming convention
+ *     $loader->registerPrefixes(array(
+ *         'Swift_' => __DIR__.'/Swift',
+ *     ));
+ *
+ *
+ *     // to enable searching the include path (eg. for PEAR packages)
+ *     $loader->useIncludePath(true);
+ *
+ *     // activate the autoloader
+ *     $loader->register();
+ *
+ * In this example, if you try to use a class in the Symfony\Component
+ * namespace or one of its children (Symfony\Component\Console for instance),
+ * the autoloader will first look for the class under the component/
+ * directory, and it will then fallback to the framework/ directory if not
+ * found before giving up.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class UniversalClassLoader
+{
+    private $namespaces = array();
+    private $prefixes = array();
+    private $namespaceFallbacks = array();
+    private $prefixFallbacks = array();
+    private $useIncludePath = false;
+
+    /**
+     * Turns on searching the include for class files. Allows easy loading
+     * of installed PEAR packages
+     *
+     * @param Boolean $useIncludePath
+     */
+    public function useIncludePath($useIncludePath)
+    {
+        $this->useIncludePath = $useIncludePath;
+    }
+
+    /**
+     * Can be used to check if the autoloader uses the include path to check
+     * for classes.
+     *
+     * @return Boolean
+     */
+    public function getUseIncludePath()
+    {
+        return $this->useIncludePath;
+    }
+
+    /**
+     * Gets the configured namespaces.
+     *
+     * @return array A hash with namespaces as keys and directories as values
+     */
+    public function getNamespaces()
+    {
+        return $this->namespaces;
+    }
+
+    /**
+     * Gets the configured class prefixes.
+     *
+     * @return array A hash with class prefixes as keys and directories as values
+     */
+    public function getPrefixes()
+    {
+        return $this->prefixes;
+    }
+
+    /**
+     * Gets the directory(ies) to use as a fallback for namespaces.
+     *
+     * @return array An array of directories
+     */
+    public function getNamespaceFallbacks()
+    {
+        return $this->namespaceFallbacks;
+    }
+
+    /**
+     * Gets the directory(ies) to use as a fallback for class prefixes.
+     *
+     * @return array An array of directories
+     */
+    public function getPrefixFallbacks()
+    {
+        return $this->prefixFallbacks;
+    }
+
+    /**
+     * Registers the directory to use as a fallback for namespaces.
+     *
+     * @param array $dirs An array of directories
+     *
+     * @api
+     */
+    public function registerNamespaceFallbacks(array $dirs)
+    {
+        $this->namespaceFallbacks = $dirs;
+    }
+
+    /**
+     * Registers a directory to use as a fallback for namespaces.
+     *
+     * @param string $dir A directory
+     */
+    public function registerNamespaceFallback($dir)
+    {
+        $this->namespaceFallbacks[] = $dir;
+    }
+
+    /**
+     * Registers directories to use as a fallback for class prefixes.
+     *
+     * @param array $dirs An array of directories
+     *
+     * @api
+     */
+    public function registerPrefixFallbacks(array $dirs)
+    {
+        $this->prefixFallbacks = $dirs;
+    }
+
+    /**
+     * Registers a directory to use as a fallback for class prefixes.
+     *
+     * @param string $dir A directory
+     */
+    public function registerPrefixFallback($dir)
+    {
+        $this->prefixFallbacks[] = $dir;
+    }
+
+    /**
+     * Registers an array of namespaces
+     *
+     * @param array $namespaces An array of namespaces (namespaces as keys and locations as values)
+     *
+     * @api
+     */
+    public function registerNamespaces(array $namespaces)
+    {
+        foreach ($namespaces as $namespace => $locations) {
+            $this->namespaces[$namespace] = (array) $locations;
+        }
+    }
+
+    /**
+     * Registers a namespace.
+     *
+     * @param string       $namespace The namespace
+     * @param array|string $paths     The location(s) of the namespace
+     *
+     * @api
+     */
+    public function registerNamespace($namespace, $paths)
+    {
+        $this->namespaces[$namespace] = (array) $paths;
+    }
+
+    /**
+     * Registers an array of classes using the PEAR naming convention.
+     *
+     * @param array $classes An array of classes (prefixes as keys and locations as values)
+     *
+     * @api
+     */
+    public function registerPrefixes(array $classes)
+    {
+        foreach ($classes as $prefix => $locations) {
+            $this->prefixes[$prefix] = (array) $locations;
+        }
+    }
+
+    /**
+     * Registers a set of classes using the PEAR naming convention.
+     *
+     * @param string       $prefix  The classes prefix
+     * @param array|string $paths   The location(s) of the classes
+     *
+     * @api
+     */
+    public function registerPrefix($prefix, $paths)
+    {
+        $this->prefixes[$prefix] = (array) $paths;
+    }
+
+    /**
+     * Registers this instance as an autoloader.
+     *
+     * @param Boolean $prepend Whether to prepend the autoloader or not
+     *
+     * @api
+     */
+    public function register($prepend = false)
+    {
+        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+    }
+
+    /**
+     * Loads the given class or interface.
+     *
+     * @param string $class The name of the class
+     */
+    public function loadClass($class)
+    {
+        if ($file = $this->findFile($class)) {
+            require $file;
+        }
+    }
+
+    /**
+     * Finds the path to the file where the class is defined.
+     *
+     * @param string $class The name of the class
+     *
+     * @return string|null The path, if found
+     */
+    public function findFile($class)
+    {
+        if ('\\' == $class[0]) {
+            $class = substr($class, 1);
+        }
+
+        if (false !== $pos = strrpos($class, '\\')) {
+            // namespaced class name
+            $namespace = substr($class, 0, $pos);
+            $className = substr($class, $pos + 1);
+            $normalizedClass = str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $className).'.php';
+            foreach ($this->namespaces as $ns => $dirs) {
+                if (0 !== strpos($namespace, $ns)) {
+                    continue;
+                }
+
+                foreach ($dirs as $dir) {
+                    $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass;
+                    if (is_file($file)) {
+                        return $file;
+                    }
+                }
+            }
+
+            foreach ($this->namespaceFallbacks as $dir) {
+                $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass;
+                if (is_file($file)) {
+                    return $file;
+                }
+            }
+
+        } else {
+            // PEAR-like class name
+            $normalizedClass = str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';
+            foreach ($this->prefixes as $prefix => $dirs) {
+                if (0 !== strpos($class, $prefix)) {
+                    continue;
+                }
+
+                foreach ($dirs as $dir) {
+                    $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass;
+                    if (is_file($file)) {
+                        return $file;
+                    }
+                }
+            }
+
+            foreach ($this->prefixFallbacks as $dir) {
+                $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass;
+                if (is_file($file)) {
+                    return $file;
+                }
+            }
+        }
+
+        if ($this->useIncludePath && $file = stream_resolve_include_path($normalizedClass)) {
+            return $file;
+        }
+    }
+}

+ 30 - 0
vendor/Symfony/Component/ClassLoader/composer.json

@@ -0,0 +1,30 @@
+{
+    "name": "symfony/class-loader",
+    "type": "library",
+    "description": "Symfony ClassLoader Component",
+    "keywords": [],
+    "homepage": "http://symfony.com",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Fabien Potencier",
+            "email": "fabien@symfony.com"
+        },
+        {
+            "name": "Symfony Community",
+            "homepage": "http://symfony.com/contributors"
+        }
+    ],
+    "require": {
+        "php": ">=5.3.2"
+    },
+    "autoload": {
+        "psr-0": { "Symfony\\Component\\ClassLoader": "" }
+    },
+    "target-dir": "Symfony/Component/ClassLoader",
+    "extra": {
+        "branch-alias": {
+            "dev-master": "2.1-dev"
+        }
+    }
+}

+ 1007 - 0
vendor/Symfony/Component/Console/Application.php

@@ -0,0 +1,1007 @@
+<?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;
+
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\ArgvInput;
+use Symfony\Component\Console\Input\ArrayInput;
+use Symfony\Component\Console\Input\InputDefinition;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Output\Output;
+use Symfony\Component\Console\Output\ConsoleOutput;
+use Symfony\Component\Console\Output\ConsoleOutputInterface;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Command\HelpCommand;
+use Symfony\Component\Console\Command\ListCommand;
+use Symfony\Component\Console\Helper\HelperSet;
+use Symfony\Component\Console\Helper\FormatterHelper;
+use Symfony\Component\Console\Helper\DialogHelper;
+
+/**
+ * An Application is the container for a collection of commands.
+ *
+ * It is the main entry point of a Console application.
+ *
+ * This class is optimized for a standard CLI environment.
+ *
+ * Usage:
+ *
+ *     $app = new Application('myapp', '1.0 (stable)');
+ *     $app->add(new SimpleCommand());
+ *     $app->run();
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class Application
+{
+    private $commands;
+    private $wantHelps = false;
+    private $runningCommand;
+    private $name;
+    private $version;
+    private $catchExceptions;
+    private $autoExit;
+    private $definition;
+    private $helperSet;
+
+    /**
+     * Constructor.
+     *
+     * @param string  $name    The name of the application
+     * @param string  $version The version of the application
+     *
+     * @api
+     */
+    public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
+    {
+        $this->name = $name;
+        $this->version = $version;
+        $this->catchExceptions = true;
+        $this->autoExit = true;
+        $this->commands = array();
+        $this->helperSet = $this->getDefaultHelperSet();
+        $this->definition = $this->getDefaultInputDefinition();
+
+        foreach ($this->getDefaultCommands() as $command) {
+            $this->add($command);
+        }
+    }
+
+    /**
+     * Runs the current application.
+     *
+     * @param InputInterface  $input  An Input instance
+     * @param OutputInterface $output An Output instance
+     *
+     * @return integer 0 if everything went fine, or an error code
+     *
+     * @throws \Exception When doRun returns Exception
+     *
+     * @api
+     */
+    public function run(InputInterface $input = null, OutputInterface $output = null)
+    {
+        if (null === $input) {
+            $input = new ArgvInput();
+        }
+
+        if (null === $output) {
+            $output = new ConsoleOutput();
+        }
+
+        try {
+            $statusCode = $this->doRun($input, $output);
+        } catch (\Exception $e) {
+            if (!$this->catchExceptions) {
+                throw $e;
+            }
+
+            if ($output instanceof ConsoleOutputInterface) {
+                $this->renderException($e, $output->getErrorOutput());
+            } else {
+                $this->renderException($e, $output);
+            }
+            $statusCode = $e->getCode();
+
+            $statusCode = is_numeric($statusCode) && $statusCode ? $statusCode : 1;
+        }
+
+        if ($this->autoExit) {
+            if ($statusCode > 255) {
+                $statusCode = 255;
+            }
+            // @codeCoverageIgnoreStart
+            exit($statusCode);
+            // @codeCoverageIgnoreEnd
+        }
+
+        return $statusCode;
+    }
+
+    /**
+     * Runs the current application.
+     *
+     * @param InputInterface  $input  An Input instance
+     * @param OutputInterface $output An Output instance
+     *
+     * @return integer 0 if everything went fine, or an error code
+     */
+    public function doRun(InputInterface $input, OutputInterface $output)
+    {
+        $name = $this->getCommandName($input);
+
+        if (true === $input->hasParameterOption(array('--ansi'))) {
+            $output->setDecorated(true);
+        } elseif (true === $input->hasParameterOption(array('--no-ansi'))) {
+            $output->setDecorated(false);
+        }
+
+        if (true === $input->hasParameterOption(array('--help', '-h'))) {
+            if (!$name) {
+                $name = 'help';
+                $input = new ArrayInput(array('command' => 'help'));
+            } else {
+                $this->wantHelps = true;
+            }
+        }
+
+        if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) {
+            $input->setInteractive(false);
+        }
+
+        if (function_exists('posix_isatty') && $this->getHelperSet()->has('dialog')) {
+            $inputStream = $this->getHelperSet()->get('dialog')->getInputStream();
+            if (!posix_isatty($inputStream)) {
+                $input->setInteractive(false);
+            }
+        }
+
+        if (true === $input->hasParameterOption(array('--quiet', '-q'))) {
+            $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
+        } elseif (true === $input->hasParameterOption(array('--verbose', '-v'))) {
+            $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
+        }
+
+        if (true === $input->hasParameterOption(array('--version', '-V'))) {
+            $output->writeln($this->getLongVersion());
+
+            return 0;
+        }
+
+        if (!$name) {
+            $name = 'list';
+            $input = new ArrayInput(array('command' => 'list'));
+        }
+
+        // the command name MUST be the first element of the input
+        $command = $this->find($name);
+
+        $this->runningCommand = $command;
+        $statusCode = $command->run($input, $output);
+        $this->runningCommand = null;
+
+        return is_numeric($statusCode) ? $statusCode : 0;
+    }
+
+    /**
+     * Set a helper set to be used with the command.
+     *
+     * @param HelperSet $helperSet The helper set
+     *
+     * @api
+     */
+    public function setHelperSet(HelperSet $helperSet)
+    {
+        $this->helperSet = $helperSet;
+    }
+
+    /**
+     * Get the helper set associated with the command.
+     *
+     * @return HelperSet The HelperSet instance associated with this command
+     *
+     * @api
+     */
+    public function getHelperSet()
+    {
+        return $this->helperSet;
+    }
+
+    /**
+     * Gets the InputDefinition related to this Application.
+     *
+     * @return InputDefinition The InputDefinition instance
+     */
+    public function getDefinition()
+    {
+        return $this->definition;
+    }
+
+    /**
+     * Gets the help message.
+     *
+     * @return string A help message.
+     */
+    public function getHelp()
+    {
+        $messages = array(
+            $this->getLongVersion(),
+            '',
+            '<comment>Usage:</comment>',
+            sprintf("  [options] command [arguments]\n"),
+            '<comment>Options:</comment>',
+        );
+
+        foreach ($this->getDefinition()->getOptions() as $option) {
+            $messages[] = sprintf('  %-29s %s %s',
+                '<info>--'.$option->getName().'</info>',
+                $option->getShortcut() ? '<info>-'.$option->getShortcut().'</info>' : '  ',
+                $option->getDescription()
+            );
+        }
+
+        return implode(PHP_EOL, $messages);
+    }
+
+    /**
+     * Sets whether to catch exceptions or not during commands execution.
+     *
+     * @param Boolean $boolean Whether to catch exceptions or not during commands execution
+     *
+     * @api
+     */
+    public function setCatchExceptions($boolean)
+    {
+        $this->catchExceptions = (Boolean) $boolean;
+    }
+
+    /**
+     * Sets whether to automatically exit after a command execution or not.
+     *
+     * @param Boolean $boolean Whether to automatically exit after a command execution or not
+     *
+     * @api
+     */
+    public function setAutoExit($boolean)
+    {
+        $this->autoExit = (Boolean) $boolean;
+    }
+
+    /**
+     * Gets the name of the application.
+     *
+     * @return string The application name
+     *
+     * @api
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * Sets the application name.
+     *
+     * @param string $name The application name
+     *
+     * @api
+     */
+    public function setName($name)
+    {
+        $this->name = $name;
+    }
+
+    /**
+     * Gets the application version.
+     *
+     * @return string The application version
+     *
+     * @api
+     */
+    public function getVersion()
+    {
+        return $this->version;
+    }
+
+    /**
+     * Sets the application version.
+     *
+     * @param string $version The application version
+     *
+     * @api
+     */
+    public function setVersion($version)
+    {
+        $this->version = $version;
+    }
+
+    /**
+     * Returns the long version of the application.
+     *
+     * @return string The long application version
+     *
+     * @api
+     */
+    public function getLongVersion()
+    {
+        if ('UNKNOWN' !== $this->getName() && 'UNKNOWN' !== $this->getVersion()) {
+            return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion());
+        }
+
+        return '<info>Console Tool</info>';
+    }
+
+    /**
+     * Registers a new command.
+     *
+     * @param string $name The command name
+     *
+     * @return Command The newly created command
+     *
+     * @api
+     */
+    public function register($name)
+    {
+        return $this->add(new Command($name));
+    }
+
+    /**
+     * Adds an array of command objects.
+     *
+     * @param Command[] $commands An array of commands
+     *
+     * @api
+     */
+    public function addCommands(array $commands)
+    {
+        foreach ($commands as $command) {
+            $this->add($command);
+        }
+    }
+
+    /**
+     * Adds a command object.
+     *
+     * If a command with the same name already exists, it will be overridden.
+     *
+     * @param Command $command A Command object
+     *
+     * @return Command The registered command
+     *
+     * @api
+     */
+    public function add(Command $command)
+    {
+        $command->setApplication($this);
+
+        if (!$command->isEnabled()) {
+            $command->setApplication(null);
+
+            return;
+        }
+
+        $this->commands[$command->getName()] = $command;
+
+        foreach ($command->getAliases() as $alias) {
+            $this->commands[$alias] = $command;
+        }
+
+        return $command;
+    }
+
+    /**
+     * Returns a registered command by name or alias.
+     *
+     * @param string $name The command name or alias
+     *
+     * @return Command A Command object
+     *
+     * @throws \InvalidArgumentException When command name given does not exist
+     *
+     * @api
+     */
+    public function get($name)
+    {
+        if (!isset($this->commands[$name])) {
+            throw new \InvalidArgumentException(sprintf('The command "%s" does not exist.', $name));
+        }
+
+        $command = $this->commands[$name];
+
+        if ($this->wantHelps) {
+            $this->wantHelps = false;
+
+            $helpCommand = $this->get('help');
+            $helpCommand->setCommand($command);
+
+            return $helpCommand;
+        }
+
+        return $command;
+    }
+
+    /**
+     * Returns true if the command exists, false otherwise.
+     *
+     * @param string $name The command name or alias
+     *
+     * @return Boolean true if the command exists, false otherwise
+     *
+     * @api
+     */
+    public function has($name)
+    {
+        return isset($this->commands[$name]);
+    }
+
+    /**
+     * Returns an array of all unique namespaces used by currently registered commands.
+     *
+     * It does not returns the global namespace which always exists.
+     *
+     * @return array An array of namespaces
+     */
+    public function getNamespaces()
+    {
+        $namespaces = array();
+        foreach ($this->commands as $command) {
+            $namespaces[] = $this->extractNamespace($command->getName());
+
+            foreach ($command->getAliases() as $alias) {
+                $namespaces[] = $this->extractNamespace($alias);
+            }
+        }
+
+        return array_values(array_unique(array_filter($namespaces)));
+    }
+
+    /**
+     * Finds a registered namespace by a name or an abbreviation.
+     *
+     * @param string $namespace A namespace or abbreviation to search for
+     *
+     * @return string A registered namespace
+     *
+     * @throws \InvalidArgumentException When namespace is incorrect or ambiguous
+     */
+    public function findNamespace($namespace)
+    {
+        $allNamespaces = array();
+        foreach ($this->getNamespaces() as $n) {
+            $allNamespaces[$n] = explode(':', $n);
+        }
+
+        $found = array();
+        foreach (explode(':', $namespace) as $i => $part) {
+            $abbrevs = static::getAbbreviations(array_unique(array_values(array_filter(array_map(function ($p) use ($i) { return isset($p[$i]) ? $p[$i] : ''; }, $allNamespaces)))));
+
+            if (!isset($abbrevs[$part])) {
+                $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
+
+                if (1 <= $i) {
+                    $part = implode(':', $found).':'.$part;
+                }
+
+                if ($alternatives = $this->findAlternativeNamespace($part, $abbrevs)) {
+                    $message .= "\n\nDid you mean one of these?\n    ";
+                    $message .= implode("\n    ", $alternatives);
+                }
+
+                throw new \InvalidArgumentException($message);
+            }
+
+            if (count($abbrevs[$part]) > 1) {
+                throw new \InvalidArgumentException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions($abbrevs[$part])));
+            }
+
+            $found[] = $abbrevs[$part][0];
+        }
+
+        return implode(':', $found);
+    }
+
+    /**
+     * Finds a command by name or alias.
+     *
+     * Contrary to get, this command tries to find the best
+     * match if you give it an abbreviation of a name or alias.
+     *
+     * @param  string $name A command name or a command alias
+     *
+     * @return Command A Command instance
+     *
+     * @throws \InvalidArgumentException When command name is incorrect or ambiguous
+     *
+     * @api
+     */
+    public function find($name)
+    {
+        // namespace
+        $namespace = '';
+        $searchName = $name;
+        if (false !== $pos = strrpos($name, ':')) {
+            $namespace = $this->findNamespace(substr($name, 0, $pos));
+            $searchName = $namespace.substr($name, $pos);
+        }
+
+        // name
+        $commands = array();
+        foreach ($this->commands as $command) {
+            if ($this->extractNamespace($command->getName()) == $namespace) {
+                $commands[] = $command->getName();
+            }
+        }
+
+        $abbrevs = static::getAbbreviations(array_unique($commands));
+        if (isset($abbrevs[$searchName]) && 1 == count($abbrevs[$searchName])) {
+            return $this->get($abbrevs[$searchName][0]);
+        }
+
+        if (isset($abbrevs[$searchName]) && count($abbrevs[$searchName]) > 1) {
+            $suggestions = $this->getAbbreviationSuggestions($abbrevs[$searchName]);
+
+            throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions));
+        }
+
+        // aliases
+        $aliases = array();
+        foreach ($this->commands as $command) {
+            foreach ($command->getAliases() as $alias) {
+                if ($this->extractNamespace($alias) == $namespace) {
+                    $aliases[] = $alias;
+                }
+            }
+        }
+
+        $aliases = static::getAbbreviations(array_unique($aliases));
+        if (!isset($aliases[$searchName])) {
+            $message = sprintf('Command "%s" is not defined.', $name);
+
+            if ($alternatives = $this->findAlternativeCommands($searchName, $abbrevs)) {
+                $message .= "\n\nDid you mean one of these?\n    ";
+                $message .= implode("\n    ", $alternatives);
+            }
+
+            throw new \InvalidArgumentException($message);
+        }
+
+        if (count($aliases[$searchName]) > 1) {
+            throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $this->getAbbreviationSuggestions($aliases[$searchName])));
+        }
+
+        return $this->get($aliases[$searchName][0]);
+    }
+
+    /**
+     * Gets the commands (registered in the given namespace if provided).
+     *
+     * The array keys are the full names and the values the command instances.
+     *
+     * @param  string  $namespace A namespace name
+     *
+     * @return array An array of Command instances
+     *
+     * @api
+     */
+    public function all($namespace = null)
+    {
+        if (null === $namespace) {
+            return $this->commands;
+        }
+
+        $commands = array();
+        foreach ($this->commands as $name => $command) {
+            if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
+                $commands[$name] = $command;
+            }
+        }
+
+        return $commands;
+    }
+
+    /**
+     * Returns an array of possible abbreviations given a set of names.
+     *
+     * @param array $names An array of names
+     *
+     * @return array An array of abbreviations
+     */
+    static public function getAbbreviations($names)
+    {
+        $abbrevs = array();
+        foreach ($names as $name) {
+            for ($len = strlen($name) - 1; $len > 0; --$len) {
+                $abbrev = substr($name, 0, $len);
+                if (!isset($abbrevs[$abbrev])) {
+                    $abbrevs[$abbrev] = array($name);
+                } else {
+                    $abbrevs[$abbrev][] = $name;
+                }
+            }
+        }
+
+        // Non-abbreviations always get entered, even if they aren't unique
+        foreach ($names as $name) {
+            $abbrevs[$name] = array($name);
+        }
+
+        return $abbrevs;
+    }
+
+    /**
+     * Returns a text representation of the Application.
+     *
+     * @param string  $namespace An optional namespace name
+     * @param boolean $raw       Whether to return raw command list
+     *
+     * @return string A string representing the Application
+     */
+    public function asText($namespace = null, $raw = false)
+    {
+        $commands = $namespace ? $this->all($this->findNamespace($namespace)) : $this->commands;
+
+        $width = 0;
+        foreach ($commands as $command) {
+            $width = strlen($command->getName()) > $width ? strlen($command->getName()) : $width;
+        }
+        $width += 2;
+
+        if ($raw) {
+            $messages = array();
+            foreach ($this->sortCommands($commands) as $space => $commands) {
+                foreach ($commands as $name => $command) {
+                    $messages[] = sprintf("%-${width}s %s", $name, $command->getDescription());
+                }
+            }
+
+            return implode(PHP_EOL, $messages);
+        }
+
+        $messages = array($this->getHelp(), '');
+        if ($namespace) {
+            $messages[] = sprintf("<comment>Available commands for the \"%s\" namespace:</comment>", $namespace);
+        } else {
+            $messages[] = '<comment>Available commands:</comment>';
+        }
+
+        // add commands by namespace
+        foreach ($this->sortCommands($commands) as $space => $commands) {
+            if (!$namespace && '_global' !== $space) {
+                $messages[] = '<comment>'.$space.'</comment>';
+            }
+
+            foreach ($commands as $name => $command) {
+                $messages[] = sprintf("  <info>%-${width}s</info> %s", $name, $command->getDescription());
+            }
+        }
+
+        return implode(PHP_EOL, $messages);
+    }
+
+    /**
+     * Returns an XML representation of the Application.
+     *
+     * @param string  $namespace An optional namespace name
+     * @param Boolean $asDom     Whether to return a DOM or an XML string
+     *
+     * @return string|DOMDocument An XML string representing the Application
+     */
+    public function asXml($namespace = null, $asDom = false)
+    {
+        $commands = $namespace ? $this->all($this->findNamespace($namespace)) : $this->commands;
+
+        $dom = new \DOMDocument('1.0', 'UTF-8');
+        $dom->formatOutput = true;
+        $dom->appendChild($xml = $dom->createElement('symfony'));
+
+        $xml->appendChild($commandsXML = $dom->createElement('commands'));
+
+        if ($namespace) {
+            $commandsXML->setAttribute('namespace', $namespace);
+        } else {
+            $namespacesXML = $dom->createElement('namespaces');
+            $xml->appendChild($namespacesXML);
+        }
+
+        // add commands by namespace
+        foreach ($this->sortCommands($commands) as $space => $commands) {
+            if (!$namespace) {
+                $namespaceArrayXML = $dom->createElement('namespace');
+                $namespacesXML->appendChild($namespaceArrayXML);
+                $namespaceArrayXML->setAttribute('id', $space);
+            }
+
+            foreach ($commands as $name => $command) {
+                if ($name !== $command->getName()) {
+                    continue;
+                }
+
+                if (!$namespace) {
+                    $commandXML = $dom->createElement('command');
+                    $namespaceArrayXML->appendChild($commandXML);
+                    $commandXML->appendChild($dom->createTextNode($name));
+                }
+
+                $node = $command->asXml(true)->getElementsByTagName('command')->item(0);
+                $node = $dom->importNode($node, true);
+
+                $commandsXML->appendChild($node);
+            }
+        }
+
+        return $asDom ? $dom : $dom->saveXml();
+    }
+
+    /**
+     * Renders a catched exception.
+     *
+     * @param Exception       $e      An exception instance
+     * @param OutputInterface $output An OutputInterface instance
+     */
+    public function renderException($e, $output)
+    {
+        $strlen = function ($string) {
+            if (!function_exists('mb_strlen')) {
+                return strlen($string);
+            }
+
+            if (false === $encoding = mb_detect_encoding($string)) {
+                return strlen($string);
+            }
+
+            return mb_strlen($string, $encoding);
+        };
+
+        do {
+            $title = sprintf('  [%s]  ', get_class($e));
+            $len = $strlen($title);
+            $lines = array();
+            foreach (explode("\n", $e->getMessage()) as $line) {
+                $lines[] = sprintf('  %s  ', $line);
+                $len = max($strlen($line) + 4, $len);
+            }
+
+            $messages = array(str_repeat(' ', $len), $title.str_repeat(' ', $len - $strlen($title)));
+
+            foreach ($lines as $line) {
+                $messages[] = $line.str_repeat(' ', $len - $strlen($line));
+            }
+
+            $messages[] = str_repeat(' ', $len);
+
+            $output->writeln("");
+            $output->writeln("");
+            foreach ($messages as $message) {
+                $output->writeln('<error>'.$message.'</error>');
+            }
+            $output->writeln("");
+            $output->writeln("");
+
+            if (OutputInterface::VERBOSITY_VERBOSE === $output->getVerbosity()) {
+                $output->writeln('<comment>Exception trace:</comment>');
+
+                // exception related properties
+                $trace = $e->getTrace();
+                array_unshift($trace, array(
+                    'function' => '',
+                    'file'     => $e->getFile() != null ? $e->getFile() : 'n/a',
+                    'line'     => $e->getLine() != null ? $e->getLine() : 'n/a',
+                    'args'     => array(),
+                ));
+
+                for ($i = 0, $count = count($trace); $i < $count; $i++) {
+                    $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
+                    $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
+                    $function = $trace[$i]['function'];
+                    $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
+                    $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';
+
+                    $output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line));
+                }
+
+                $output->writeln("");
+                $output->writeln("");
+            }
+        } while ($e = $e->getPrevious());
+
+        if (null !== $this->runningCommand) {
+            $output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())));
+            $output->writeln("");
+            $output->writeln("");
+        }
+    }
+
+    /**
+     * Gets the name of the command based on input.
+     *
+     * @param InputInterface $input The input interface
+     *
+     * @return string The command name
+     */
+    protected function getCommandName(InputInterface $input)
+    {
+        return $input->getFirstArgument('command');
+    }
+
+    /**
+     * Gets the default input definition.
+     *
+     * @return InputDefinition An InputDefinition instance
+     */
+    protected function getDefaultInputDefinition()
+    {
+        return new InputDefinition(array(
+            new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
+
+            new InputOption('--help',           '-h', InputOption::VALUE_NONE, 'Display this help message.'),
+            new InputOption('--quiet',          '-q', InputOption::VALUE_NONE, 'Do not output any message.'),
+            new InputOption('--verbose',        '-v', InputOption::VALUE_NONE, 'Increase verbosity of messages.'),
+            new InputOption('--version',        '-V', InputOption::VALUE_NONE, 'Display this application version.'),
+            new InputOption('--ansi',           '',   InputOption::VALUE_NONE, 'Force ANSI output.'),
+            new InputOption('--no-ansi',        '',   InputOption::VALUE_NONE, 'Disable ANSI output.'),
+            new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question.'),
+        ));
+    }
+
+    /**
+     * Gets the default commands that should always be available.
+     *
+     * @return array An array of default Command instances
+     */
+    protected function getDefaultCommands()
+    {
+        return array(new HelpCommand(), new ListCommand());
+    }
+
+    /**
+     * Gets the default helper set with the helpers that should always be available.
+     *
+     * @return HelperSet A HelperSet instance
+     */
+    protected function getDefaultHelperSet()
+    {
+        return new HelperSet(array(
+            new FormatterHelper(),
+            new DialogHelper(),
+        ));
+    }
+
+    /**
+     * Sorts commands in alphabetical order.
+     *
+     * @param array $commands An associative array of commands to sort
+     *
+     * @return array A sorted array of commands
+     */
+    private function sortCommands($commands)
+    {
+        $namespacedCommands = array();
+        foreach ($commands as $name => $command) {
+            $key = $this->extractNamespace($name, 1);
+            if (!$key) {
+                $key = '_global';
+            }
+
+            $namespacedCommands[$key][$name] = $command;
+        }
+        ksort($namespacedCommands);
+
+        foreach ($namespacedCommands as &$commands) {
+            ksort($commands);
+        }
+
+        return $namespacedCommands;
+    }
+
+    /**
+     * Returns abbreviated suggestions in string format.
+     *
+     * @param array $abbrevs Abbreviated suggestions to convert
+     *
+     * @return string A formatted string of abbreviated suggestions
+     */
+    private function getAbbreviationSuggestions($abbrevs)
+    {
+        return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : '');
+    }
+
+    /**
+     * Returns the namespace part of the command name.
+     *
+     * @param string $name  The full name of the command
+     * @param string $limit The maximum number of parts of the namespace
+     *
+     * @return string The namespace of the command
+     */
+    private function extractNamespace($name, $limit = null)
+    {
+        $parts = explode(':', $name);
+        array_pop($parts);
+
+        return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit));
+    }
+
+    /**
+     * Finds alternative commands of $name
+     *
+     * @param string $name      The full name of the command
+     * @param array  $abbrevs   The abbreviations
+     *
+     * @return array A sorted array of similar commands
+     */
+    private function findAlternativeCommands($name, $abbrevs)
+    {
+        $callback = function($item) {
+            return $item->getName();
+        };
+
+        return $this->findAlternatives($name, $this->commands, $abbrevs, $callback);
+    }
+
+    /**
+     * Finds alternative namespace of $name
+     *
+     * @param string $name      The full name of the namespace
+     * @param array  $abbrevs   The abbreviations
+     *
+     * @return array A sorted array of similar namespace
+     */
+    private function findAlternativeNamespace($name, $abbrevs)
+    {
+        return $this->findAlternatives($name, $this->getNamespaces(), $abbrevs);
+    }
+
+    /**
+     * Finds alternative of $name among $collection,
+     * if nothing is found in $collection, try in $abbrevs
+     *
+     * @param string                $name       The string
+     * @param array|Traversable     $collection The collecion
+     * @param array                 $abbrevs    The abbreviations
+     * @param Closure|string|array  $callback   The callable to transform collection item before comparison
+     *
+     * @return array A sorted array of similar string
+     */
+    private function findAlternatives($name, $collection, $abbrevs, $callback = null) {
+        $alternatives = array();
+
+        foreach ($collection as $item) {
+            if (null !== $callback) {
+                $item = call_user_func($callback, $item);
+            }
+
+            $lev = levenshtein($name, $item);
+            if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
+                $alternatives[$item] = $lev;
+            }
+        }
+
+        if (!$alternatives) {
+            foreach ($abbrevs as $key => $values) {
+                $lev = levenshtein($name, $key);
+                if ($lev <= strlen($name) / 3 || false !== strpos($key, $name)) {
+                    foreach ($values as $value) {
+                        $alternatives[$value] = $lev;
+                    }
+                }
+            }
+        }
+
+        asort($alternatives);
+
+        return array_keys($alternatives);
+    }
+}

+ 612 - 0
vendor/Symfony/Component/Console/Command/Command.php

@@ -0,0 +1,612 @@
+<?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\Command;
+
+use Symfony\Component\Console\Input\InputDefinition;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Helper\HelperSet;
+
+/**
+ * Base class for all commands.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class Command
+{
+    private $application;
+    private $name;
+    private $aliases;
+    private $definition;
+    private $help;
+    private $description;
+    private $ignoreValidationErrors;
+    private $applicationDefinitionMerged;
+    private $code;
+    private $synopsis;
+    private $helperSet;
+
+    /**
+     * Constructor.
+     *
+     * @param string $name The name of the command
+     *
+     * @throws \LogicException When the command name is empty
+     *
+     * @api
+     */
+    public function __construct($name = null)
+    {
+        $this->definition = new InputDefinition();
+        $this->ignoreValidationErrors = false;
+        $this->applicationDefinitionMerged = false;
+        $this->aliases = array();
+
+        if (null !== $name) {
+            $this->setName($name);
+        }
+
+        $this->configure();
+
+        if (!$this->name) {
+            throw new \LogicException('The command name cannot be empty.');
+        }
+    }
+
+    /**
+     * Ignores validation errors.
+     *
+     * This is mainly useful for the help command.
+     */
+    public function ignoreValidationErrors()
+    {
+        $this->ignoreValidationErrors = true;
+    }
+
+    /**
+     * Sets the application instance for this command.
+     *
+     * @param Application $application An Application instance
+     *
+     * @api
+     */
+    public function setApplication(Application $application = null)
+    {
+        $this->application = $application;
+        if ($application) {
+            $this->setHelperSet($application->getHelperSet());
+        } else {
+            $this->helperSet = null;
+        }
+    }
+
+    /**
+     * Sets the helper set.
+     *
+     * @param HelperSet $helperSet A HelperSet instance
+     */
+    public function setHelperSet(HelperSet $helperSet)
+    {
+        $this->helperSet = $helperSet;
+    }
+
+    /**
+     * Gets the helper set.
+     *
+     * @return HelperSet A HelperSet instance
+     */
+    public function getHelperSet()
+    {
+        return $this->helperSet;
+    }
+
+    /**
+     * Gets the application instance for this command.
+     *
+     * @return Application An Application instance
+     *
+     * @api
+     */
+    public function getApplication()
+    {
+        return $this->application;
+    }
+
+    /**
+     * Checks whether the command is enabled or not in the current environment
+     *
+     * Override this to check for x or y and return false if the command can not
+     * run properly under the current conditions.
+     *
+     * @return Boolean
+     */
+    public function isEnabled()
+    {
+        return true;
+    }
+
+    /**
+     * Configures the current command.
+     */
+    protected function configure()
+    {
+    }
+
+    /**
+     * Executes the current command.
+     *
+     * This method is not abstract because you can use this class
+     * as a concrete class. In this case, instead of defining the
+     * execute() method, you set the code to execute by passing
+     * a Closure to the setCode() method.
+     *
+     * @param InputInterface  $input  An InputInterface instance
+     * @param OutputInterface $output An OutputInterface instance
+     *
+     * @return integer 0 if everything went fine, or an error code
+     *
+     * @throws \LogicException When this abstract method is not implemented
+     * @see    setCode()
+     */
+    protected function execute(InputInterface $input, OutputInterface $output)
+    {
+        throw new \LogicException('You must override the execute() method in the concrete command class.');
+    }
+
+    /**
+     * Interacts with the user.
+     *
+     * @param InputInterface  $input  An InputInterface instance
+     * @param OutputInterface $output An OutputInterface instance
+     */
+    protected function interact(InputInterface $input, OutputInterface $output)
+    {
+    }
+
+    /**
+     * Initializes the command just after the input has been validated.
+     *
+     * This is mainly useful when a lot of commands extends one main command
+     * where some things need to be initialized based on the input arguments and options.
+     *
+     * @param InputInterface  $input  An InputInterface instance
+     * @param OutputInterface $output An OutputInterface instance
+     */
+    protected function initialize(InputInterface $input, OutputInterface $output)
+    {
+    }
+
+    /**
+     * Runs the command.
+     *
+     * The code to execute is either defined directly with the
+     * setCode() method or by overriding the execute() method
+     * in a sub-class.
+     *
+     * @param InputInterface  $input  An InputInterface instance
+     * @param OutputInterface $output An OutputInterface instance
+     *
+     * @see setCode()
+     * @see execute()
+     *
+     * @api
+     */
+    public function run(InputInterface $input, OutputInterface $output)
+    {
+        // force the creation of the synopsis before the merge with the app definition
+        $this->getSynopsis();
+
+        // add the application arguments and options
+        $this->mergeApplicationDefinition();
+
+        // bind the input against the command specific arguments/options
+        try {
+            $input->bind($this->definition);
+        } catch (\Exception $e) {
+            if (!$this->ignoreValidationErrors) {
+                throw $e;
+            }
+        }
+
+        $this->initialize($input, $output);
+
+        if ($input->isInteractive()) {
+            $this->interact($input, $output);
+        }
+
+        $input->validate();
+
+        if ($this->code) {
+            return call_user_func($this->code, $input, $output);
+        }
+
+        return $this->execute($input, $output);
+    }
+
+    /**
+     * Sets the code to execute when running this command.
+     *
+     * If this method is used, it overrides the code defined
+     * in the execute() method.
+     *
+     * @param \Closure $code A \Closure
+     *
+     * @return Command The current instance
+     *
+     * @see execute()
+     *
+     * @api
+     */
+    public function setCode(\Closure $code)
+    {
+        $this->code = $code;
+
+        return $this;
+    }
+
+    /**
+     * Merges the application definition with the command definition.
+     */
+    private function mergeApplicationDefinition()
+    {
+        if (null === $this->application || true === $this->applicationDefinitionMerged) {
+            return;
+        }
+
+        $currentArguments = $this->definition->getArguments();
+        $this->definition->setArguments($this->application->getDefinition()->getArguments());
+        $this->definition->addArguments($currentArguments);
+
+        $this->definition->addOptions($this->application->getDefinition()->getOptions());
+
+        $this->applicationDefinitionMerged = true;
+    }
+
+    /**
+     * Sets an array of argument and option instances.
+     *
+     * @param array|InputDefinition $definition An array of argument and option instances or a definition instance
+     *
+     * @return Command The current instance
+     *
+     * @api
+     */
+    public function setDefinition($definition)
+    {
+        if ($definition instanceof InputDefinition) {
+            $this->definition = $definition;
+        } else {
+            $this->definition->setDefinition($definition);
+        }
+
+        $this->applicationDefinitionMerged = false;
+
+        return $this;
+    }
+
+    /**
+     * Gets the InputDefinition attached to this Command.
+     *
+     * @return InputDefinition An InputDefinition instance
+     *
+     * @api
+     */
+    public function getDefinition()
+    {
+        return $this->definition;
+    }
+
+    /**
+     * Gets the InputDefinition to be used to create XML and Text representations of this Command.
+     *
+     * Can be overridden to provide the original command representation when it would otherwise
+     * be changed by merging with the application InputDefinition.
+     *
+     * @return InputDefinition An InputDefinition instance
+     */
+    protected function getNativeDefinition()
+    {
+        return $this->getDefinition();
+    }
+
+    /**
+     * Adds an argument.
+     *
+     * @param string  $name        The argument name
+     * @param integer $mode        The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL
+     * @param string  $description A description text
+     * @param mixed   $default     The default value (for InputArgument::OPTIONAL mode only)
+     *
+     * @return Command The current instance
+     *
+     * @api
+     */
+    public function addArgument($name, $mode = null, $description = '', $default = null)
+    {
+        $this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
+
+        return $this;
+    }
+
+    /**
+     * Adds an option.
+     *
+     * @param string  $name        The option name
+     * @param string  $shortcut    The shortcut (can be null)
+     * @param integer $mode        The option mode: One of the InputOption::VALUE_* constants
+     * @param string  $description A description text
+     * @param mixed   $default     The default value (must be null for InputOption::VALUE_REQUIRED or InputOption::VALUE_NONE)
+     *
+     * @return Command The current instance
+     *
+     * @api
+     */
+    public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
+    {
+        $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
+
+        return $this;
+    }
+
+    /**
+     * Sets the name of the command.
+     *
+     * This method can set both the namespace and the name if
+     * you separate them by a colon (:)
+     *
+     *     $command->setName('foo:bar');
+     *
+     * @param string $name The command name
+     *
+     * @return Command The current instance
+     *
+     * @throws \InvalidArgumentException When command name given is empty
+     *
+     * @api
+     */
+    public function setName($name)
+    {
+        $this->validateName($name);
+
+        $this->name = $name;
+
+        return $this;
+    }
+
+    /**
+     * Returns the command name.
+     *
+     * @return string The command name
+     *
+     * @api
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * Sets the description for the command.
+     *
+     * @param string $description The description for the command
+     *
+     * @return Command The current instance
+     *
+     * @api
+     */
+    public function setDescription($description)
+    {
+        $this->description = $description;
+
+        return $this;
+    }
+
+    /**
+     * Returns the description for the command.
+     *
+     * @return string The description for the command
+     *
+     * @api
+     */
+    public function getDescription()
+    {
+        return $this->description;
+    }
+
+    /**
+     * Sets the help for the command.
+     *
+     * @param string $help The help for the command
+     *
+     * @return Command The current instance
+     *
+     * @api
+     */
+    public function setHelp($help)
+    {
+        $this->help = $help;
+
+        return $this;
+    }
+
+    /**
+     * Returns the help for the command.
+     *
+     * @return string The help for the command
+     *
+     * @api
+     */
+    public function getHelp()
+    {
+        return $this->help;
+    }
+
+    /**
+     * Returns the processed help for the command replacing the %command.name% and
+     * %command.full_name% patterns with the real values dynamically.
+     *
+     * @return string  The processed help for the command
+     */
+    public function getProcessedHelp()
+    {
+        $name = $this->name;
+
+        $placeholders = array(
+            '%command.name%',
+            '%command.full_name%'
+        );
+        $replacements = array(
+            $name,
+            $_SERVER['PHP_SELF'].' '.$name
+        );
+
+        return str_replace($placeholders, $replacements, $this->getHelp());
+    }
+
+    /**
+     * Sets the aliases for the command.
+     *
+     * @param array $aliases An array of aliases for the command
+     *
+     * @return Command The current instance
+     *
+     * @api
+     */
+    public function setAliases($aliases)
+    {
+        foreach ($aliases as $alias) {
+            $this->validateName($alias);
+        }
+
+        $this->aliases = $aliases;
+
+        return $this;
+    }
+
+    /**
+     * Returns the aliases for the command.
+     *
+     * @return array An array of aliases for the command
+     *
+     * @api
+     */
+    public function getAliases()
+    {
+        return $this->aliases;
+    }
+
+    /**
+     * Returns the synopsis for the command.
+     *
+     * @return string The synopsis
+     */
+    public function getSynopsis()
+    {
+        if (null === $this->synopsis) {
+            $this->synopsis = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis()));
+        }
+
+        return $this->synopsis;
+    }
+
+    /**
+     * Gets a helper instance by name.
+     *
+     * @param string $name The helper name
+     *
+     * @return mixed The helper value
+     *
+     * @throws \InvalidArgumentException if the helper is not defined
+     *
+     * @api
+     */
+    public function getHelper($name)
+    {
+        return $this->helperSet->get($name);
+    }
+
+    /**
+     * Returns a text representation of the command.
+     *
+     * @return string A string representing the command
+     */
+    public function asText()
+    {
+        $messages = array(
+            '<comment>Usage:</comment>',
+            ' '.$this->getSynopsis(),
+            '',
+        );
+
+        if ($this->getAliases()) {
+            $messages[] = '<comment>Aliases:</comment> <info>'.implode(', ', $this->getAliases()).'</info>';
+        }
+
+        $messages[] = $this->getNativeDefinition()->asText();
+
+        if ($help = $this->getProcessedHelp()) {
+            $messages[] = '<comment>Help:</comment>';
+            $messages[] = ' '.str_replace("\n", "\n ", $help)."\n";
+        }
+
+        return implode("\n", $messages);
+    }
+
+    /**
+     * Returns an XML representation of the command.
+     *
+     * @param Boolean $asDom Whether to return a DOM or an XML string
+     *
+     * @return string|DOMDocument An XML string representing the command
+     */
+    public function asXml($asDom = false)
+    {
+        $dom = new \DOMDocument('1.0', 'UTF-8');
+        $dom->formatOutput = true;
+        $dom->appendChild($commandXML = $dom->createElement('command'));
+        $commandXML->setAttribute('id', $this->name);
+        $commandXML->setAttribute('name', $this->name);
+
+        $commandXML->appendChild($usageXML = $dom->createElement('usage'));
+        $usageXML->appendChild($dom->createTextNode(sprintf($this->getSynopsis(), '')));
+
+        $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
+        $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $this->getDescription())));
+
+        $commandXML->appendChild($helpXML = $dom->createElement('help'));
+        $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $this->getProcessedHelp())));
+
+        $commandXML->appendChild($aliasesXML = $dom->createElement('aliases'));
+        foreach ($this->getAliases() as $alias) {
+            $aliasesXML->appendChild($aliasXML = $dom->createElement('alias'));
+            $aliasXML->appendChild($dom->createTextNode($alias));
+        }
+
+        $definition = $this->getNativeDefinition()->asXml(true);
+        $commandXML->appendChild($dom->importNode($definition->getElementsByTagName('arguments')->item(0), true));
+        $commandXML->appendChild($dom->importNode($definition->getElementsByTagName('options')->item(0), true));
+
+        return $asDom ? $dom : $dom->saveXml();
+    }
+
+    private function validateName($name)
+    {
+        if (!preg_match('/^[^\:]+(\:[^\:]+)*$/', $name)) {
+            throw new \InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
+        }
+    }
+}

+ 84 - 0
vendor/Symfony/Component/Console/Command/HelpCommand.php

@@ -0,0 +1,84 @@
+<?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\Command;
+
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Output\Output;
+use Symfony\Component\Console\Command\Command;
+
+/**
+ * HelpCommand displays the help for a given command.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class HelpCommand extends Command
+{
+    private $command;
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function configure()
+    {
+        $this->ignoreValidationErrors();
+
+        $this
+            ->setName('help')
+            ->setDefinition(array(
+                new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
+                new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
+            ))
+            ->setDescription('Displays help for a command')
+            ->setHelp(<<<EOF
+The <info>%command.name%</info> command displays help for a given command:
+
+  <info>php %command.full_name% list</info>
+
+You can also output the help as XML by using the <comment>--xml</comment> option:
+
+  <info>php %command.full_name% --xml list</info>
+EOF
+            )
+        ;
+    }
+
+    /**
+     * Sets the command
+     *
+     * @param Command $command The command to set
+     */
+    public function setCommand(Command $command)
+    {
+        $this->command = $command;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function execute(InputInterface $input, OutputInterface $output)
+    {
+        if (null === $this->command) {
+            $this->command = $this->getApplication()->get($input->getArgument('command_name'));
+        }
+
+        if ($input->getOption('xml')) {
+            $output->writeln($this->command->asXml(), OutputInterface::OUTPUT_RAW);
+        } else {
+            $output->writeln($this->command->asText());
+        }
+
+        $this->command = null;
+    }
+}

+ 87 - 0
vendor/Symfony/Component/Console/Command/ListCommand.php

@@ -0,0 +1,87 @@
+<?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\Command;
+
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Output\Output;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputDefinition;
+
+/**
+ * ListCommand displays the list of all available commands for the application.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ListCommand extends Command
+{
+    /**
+     * {@inheritdoc}
+     */
+    protected function configure()
+    {
+        $this
+            ->setName('list')
+            ->setDefinition($this->createDefinition())
+            ->setDescription('Lists commands')
+            ->setHelp(<<<EOF
+The <info>%command.name%</info> command lists all commands:
+
+  <info>php %command.full_name%</info>
+
+You can also display the commands for a specific namespace:
+
+  <info>php %command.full_name% test</info>
+
+You can also output the information as XML by using the <comment>--xml</comment> option:
+
+  <info>php %command.full_name% --xml</info>
+
+It's also possible to get raw list of commands (useful for embedding command runner):
+
+  <info>php %command.full_name% --raw</info>
+EOF
+            )
+        ;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function getNativeDefinition()
+    {
+        return $this->createDefinition();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function execute(InputInterface $input, OutputInterface $output)
+    {
+        if ($input->getOption('xml')) {
+            $output->writeln($this->getApplication()->asXml($input->getArgument('namespace')), OutputInterface::OUTPUT_RAW);
+        } else {
+            $output->writeln($this->getApplication()->asText($input->getArgument('namespace'), $input->getOption('raw')));
+        }
+    }
+
+    private function createDefinition()
+    {
+        return new InputDefinition(array(
+            new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
+            new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
+            new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
+        ));
+    }
+}

+ 192 - 0
vendor/Symfony/Component/Console/Formatter/OutputFormatter.php

@@ -0,0 +1,192 @@
+<?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\Formatter;
+
+/**
+ * Formatter class for console output.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * @api
+ */
+class OutputFormatter implements OutputFormatterInterface
+{
+    /**
+     * The pattern to phrase the format.
+     */
+    const FORMAT_PATTERN = '#<([a-z][a-z0-9_=;-]+)>(.*?)</\\1?>#is';
+
+    private $decorated;
+    private $styles = array();
+
+    /**
+     * Initializes console output formatter.
+     *
+     * @param   Boolean $decorated  Whether this formatter should actually decorate strings
+     * @param   array   $styles     Array of "name => FormatterStyle" instances
+     *
+     * @api
+     */
+    public function __construct($decorated = null, array $styles = array())
+    {
+        $this->decorated = (Boolean) $decorated;
+
+        $this->setStyle('error',    new OutputFormatterStyle('white', 'red'));
+        $this->setStyle('info',     new OutputFormatterStyle('green'));
+        $this->setStyle('comment',  new OutputFormatterStyle('yellow'));
+        $this->setStyle('question', new OutputFormatterStyle('black', 'cyan'));
+
+        foreach ($styles as $name => $style) {
+            $this->setStyle($name, $style);
+        }
+    }
+
+    /**
+     * Sets the decorated flag.
+     *
+     * @param Boolean $decorated Whether to decorate the messages or not
+     *
+     * @api
+     */
+    public function setDecorated($decorated)
+    {
+        $this->decorated = (Boolean) $decorated;
+    }
+
+    /**
+     * Gets the decorated flag.
+     *
+     * @return Boolean true if the output will decorate messages, false otherwise
+     *
+     * @api
+     */
+    public function isDecorated()
+    {
+        return $this->decorated;
+    }
+
+    /**
+     * Sets a new style.
+     *
+     * @param string                        $name  The style name
+     * @param OutputFormatterStyleInterface $style The style instance
+     *
+     * @api
+     */
+    public function setStyle($name, OutputFormatterStyleInterface $style)
+    {
+        $this->styles[strtolower($name)] = $style;
+    }
+
+    /**
+     * Checks if output formatter has style with specified name.
+     *
+     * @param   string  $name
+     *
+     * @return  Boolean
+     *
+     * @api
+     */
+    public function hasStyle($name)
+    {
+        return isset($this->styles[strtolower($name)]);
+    }
+
+    /**
+     * Gets style options from style with specified name.
+     *
+     * @param   string  $name
+     *
+     * @return  OutputFormatterStyleInterface
+     *
+     * @throws  \InvalidArgumentException When style isn't defined
+     *
+     * @api
+     */
+    public function getStyle($name)
+    {
+        if (!$this->hasStyle($name)) {
+            throw new \InvalidArgumentException('Undefined style: '.$name);
+        }
+
+        return $this->styles[strtolower($name)];
+    }
+
+    /**
+     * Formats a message according to the given styles.
+     *
+     * @param  string $message The message to style
+     *
+     * @return string The styled message
+     *
+     * @api
+     */
+    public function format($message)
+    {
+        return preg_replace_callback(self::FORMAT_PATTERN, array($this, 'replaceStyle'), $message);
+    }
+
+    /**
+     * Replaces style of the output.
+     *
+     * @param array $match
+     *
+     * @return string The replaced style
+     */
+    private function replaceStyle($match)
+    {
+        if (!$this->isDecorated()) {
+            return $match[2];
+        }
+
+        if (isset($this->styles[strtolower($match[1])])) {
+            $style = $this->styles[strtolower($match[1])];
+        } else {
+            $style = $this->createStyleFromString($match[1]);
+
+            if (false === $style) {
+                return $match[0];
+            }
+        }
+
+        return $style->apply($this->format($match[2]));
+    }
+
+    /**
+     * Tries to create new style instance from string.
+     *
+     * @param   string  $string
+     *
+     * @return  Symfony\Component\Console\Format\FormatterStyle|Boolean false if string is not format string
+     */
+    private function createStyleFromString($string)
+    {
+        if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) {
+            return false;
+        }
+
+        $style = new OutputFormatterStyle();
+        foreach ($matches as $match) {
+            array_shift($match);
+
+            if ('fg' == $match[0]) {
+                $style->setForeground($match[1]);
+            } elseif ('bg' == $match[0]) {
+                $style->setBackground($match[1]);
+            } else {
+                $style->setOption($match[1]);
+            }
+        }
+
+        return $style;
+    }
+}

+ 83 - 0
vendor/Symfony/Component/Console/Formatter/OutputFormatterInterface.php

@@ -0,0 +1,83 @@
+<?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\Formatter;
+
+/**
+ * Formatter interface for console output.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * @api
+ */
+interface OutputFormatterInterface
+{
+    /**
+     * Sets the decorated flag.
+     *
+     * @param Boolean $decorated Whether to decorate the messages or not
+     *
+     * @api
+     */
+    function setDecorated($decorated);
+
+    /**
+     * Gets the decorated flag.
+     *
+     * @return Boolean true if the output will decorate messages, false otherwise
+     *
+     * @api
+     */
+    function isDecorated();
+
+    /**
+     * Sets a new style.
+     *
+     * @param string                        $name  The style name
+     * @param OutputFormatterStyleInterface $style The style instance
+     *
+     * @api
+     */
+    function setStyle($name, OutputFormatterStyleInterface $style);
+
+    /**
+     * Checks if output formatter has style with specified name.
+     *
+     * @param   string  $name
+     *
+     * @return  Boolean
+     *
+     * @api
+     */
+    function hasStyle($name);
+
+    /**
+     * Gets style options from style with specified name.
+     *
+     * @param   string  $name
+     *
+     * @return  OutputFormatterStyleInterface
+     *
+     * @api
+     */
+    function getStyle($name);
+
+    /**
+     * Formats a message according to the given styles.
+     *
+     * @param  string $message The message to style
+     *
+     * @return string The styled message
+     *
+     * @api
+     */
+    function format($message);
+}

+ 218 - 0
vendor/Symfony/Component/Console/Formatter/OutputFormatterStyle.php

@@ -0,0 +1,218 @@
+<?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\Formatter;
+
+/**
+ * Formatter style class for defining styles.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * @api
+ */
+class OutputFormatterStyle implements OutputFormatterStyleInterface
+{
+    static private $availableForegroundColors = array(
+        'black'     => 30,
+        'red'       => 31,
+        'green'     => 32,
+        'yellow'    => 33,
+        'blue'      => 34,
+        'magenta'   => 35,
+        'cyan'      => 36,
+        'white'     => 37
+    );
+    static private $availableBackgroundColors = array(
+        'black'     => 40,
+        'red'       => 41,
+        'green'     => 42,
+        'yellow'    => 43,
+        'blue'      => 44,
+        'magenta'   => 45,
+        'cyan'      => 46,
+        'white'     => 47
+    );
+    static private $availableOptions = array(
+        'bold'          => 1,
+        'underscore'    => 4,
+        'blink'         => 5,
+        'reverse'       => 7,
+        'conceal'       => 8
+    );
+
+    private $foreground;
+    private $background;
+    private $options = array();
+
+    /**
+     * Initializes output formatter style.
+     *
+     * @param   string  $foreground     style foreground color name
+     * @param   string  $background     style background color name
+     * @param   array   $options        style options
+     *
+     * @api
+     */
+    public function __construct($foreground = null, $background = null, array $options = array())
+    {
+        if (null !== $foreground) {
+            $this->setForeground($foreground);
+        }
+        if (null !== $background) {
+            $this->setBackground($background);
+        }
+        if (count($options)) {
+            $this->setOptions($options);
+        }
+    }
+
+    /**
+     * Sets style foreground color.
+     *
+     * @param   string  $color  color name
+     *
+     * @throws \InvalidArgumentException When the color name isn't defined
+     *
+     * @api
+     */
+    public function setForeground($color = null)
+    {
+        if (null === $color) {
+            $this->foreground = null;
+
+            return;
+        }
+
+        if (!isset(static::$availableForegroundColors[$color])) {
+            throw new \InvalidArgumentException(sprintf(
+                'Invalid foreground color specified: "%s". Expected one of (%s)',
+                $color,
+                implode(', ', array_keys(static::$availableForegroundColors))
+            ));
+        }
+
+        $this->foreground = static::$availableForegroundColors[$color];
+    }
+
+    /**
+     * Sets style background color.
+     *
+     * @param   string  $color  color name
+     *
+     * @throws \InvalidArgumentException When the color name isn't defined
+     *
+     * @api
+     */
+    public function setBackground($color = null)
+    {
+        if (null === $color) {
+            $this->background = null;
+
+            return;
+        }
+
+        if (!isset(static::$availableBackgroundColors[$color])) {
+            throw new \InvalidArgumentException(sprintf(
+                'Invalid background color specified: "%s". Expected one of (%s)',
+                $color,
+                implode(', ', array_keys(static::$availableBackgroundColors))
+            ));
+        }
+
+        $this->background = static::$availableBackgroundColors[$color];
+    }
+
+    /**
+     * Sets some specific style option.
+     *
+     * @param   string  $option     option name
+     *
+     * @throws \InvalidArgumentException When the option name isn't defined
+     *
+     * @api
+     */
+    public function setOption($option)
+    {
+        if (!isset(static::$availableOptions[$option])) {
+            throw new \InvalidArgumentException(sprintf(
+                'Invalid option specified: "%s". Expected one of (%s)',
+                $option,
+                implode(', ', array_keys(static::$availableOptions))
+            ));
+        }
+
+        if (false === array_search(static::$availableOptions[$option], $this->options)) {
+            $this->options[] = static::$availableOptions[$option];
+        }
+    }
+
+    /**
+     * Unsets some specific style option.
+     *
+     * @param   string  $option     option name
+     *
+     * @throws \InvalidArgumentException When the option name isn't defined
+     *
+     */
+    public function unsetOption($option)
+    {
+        if (!isset(static::$availableOptions[$option])) {
+            throw new \InvalidArgumentException(sprintf(
+                'Invalid option specified: "%s". Expected one of (%s)',
+                $option,
+                implode(', ', array_keys(static::$availableOptions))
+            ));
+        }
+
+        $pos = array_search(static::$availableOptions[$option], $this->options);
+        if (false !== $pos) {
+            unset($this->options[$pos]);
+        }
+    }
+
+    /**
+     * Sets multiple style options at once.
+     *
+     * @param   array   $options
+     */
+    public function setOptions(array $options)
+    {
+        $this->options = array();
+
+        foreach ($options as $option) {
+            $this->setOption($option);
+        }
+    }
+
+    /**
+     * Applies the style to a given text.
+     *
+     * @param string $text The text to style
+     *
+     * @return string
+     */
+    public function apply($text)
+    {
+        $codes = array();
+
+        if (null !== $this->foreground) {
+            $codes[] = $this->foreground;
+        }
+        if (null !== $this->background) {
+            $codes[] = $this->background;
+        }
+        if (count($this->options)) {
+            $codes = array_merge($codes, $this->options);
+        }
+
+        return sprintf("\033[%sm%s\033[0m", implode(';', $codes), $text);
+    }
+}

+ 72 - 0
vendor/Symfony/Component/Console/Formatter/OutputFormatterStyleInterface.php

@@ -0,0 +1,72 @@
+<?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\Formatter;
+
+/**
+ * Formatter style interface for defining styles.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * @api
+ */
+interface OutputFormatterStyleInterface
+{
+    /**
+     * Sets style foreground color.
+     *
+     * @param   string  $color  color name
+     *
+     * @api
+     */
+    function setForeground($color = null);
+
+    /**
+     * Sets style background color.
+     *
+     * @param   string  $color  color name
+     *
+     * @api
+     */
+    function setBackground($color = null);
+
+    /**
+     * Sets some specific style option.
+     *
+     * @param   string  $option     option name
+     *
+     * @api
+     */
+    function setOption($option);
+
+    /**
+     * Unsets some specific style option.
+     *
+     * @param   string  $option     option name
+     */
+    function unsetOption($option);
+
+    /**
+     * Sets multiple style options at once.
+     *
+     * @param   array   $options
+     */
+    function setOptions(array $options);
+
+    /**
+     * Applies the style to a given text.
+     *
+     * @param string $text The text to style
+     *
+     * @return string
+     */
+    function apply($text);
+}

+ 139 - 0
vendor/Symfony/Component/Console/Helper/DialogHelper.php

@@ -0,0 +1,139 @@
+<?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;
+
+/**
+ * The Dialog class provides helpers to interact with the user.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class DialogHelper extends Helper
+{
+    private $inputStream;
+
+    /**
+     * 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
+     *
+     * @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)
+    {
+        $output->write($question);
+
+        $ret = fgets($this->inputStream ?: STDIN, 4096);
+        if (false === $ret) {
+            throw new \RuntimeException('Aborted');
+        }
+        $ret = trim($ret);
+
+        return strlen($ret) > 0 ? $ret : $default;
+    }
+
+    /**
+     * Asks a confirmation to the user.
+     *
+     * The question will be asked until the user answers by nothing, yes, or no.
+     *
+     * @param OutputInterface $output   An Output instance
+     * @param string|array    $question The question to ask
+     * @param Boolean         $default  The default answer if the user enters nothing
+     *
+     * @return Boolean true if the user has confirmed, false otherwise
+     */
+    public function askConfirmation(OutputInterface $output, $question, $default = true)
+    {
+        $answer = 'z';
+        while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) {
+            $answer = $this->ask($output, $question);
+        }
+
+        if (false === $default) {
+            return $answer && 'y' == strtolower($answer[0]);
+        }
+
+        return !$answer || 'y' == strtolower($answer[0]);
+    }
+
+    /**
+     * Asks 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 callback        $validator A PHP callback
+     * @param integer         $attempts  Max number of times to ask before giving up (false by default, which means infinite)
+     * @param string          $default  The default answer if none is given by the user
+     *
+     * @return mixed
+     *
+     * @throws \Exception When any of the validators return an error
+     */
+    public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null)
+    {
+        $error = null;
+        while (false === $attempts || $attempts--) {
+            if (null !== $error) {
+                $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error'));
+            }
+
+            $value = $this->ask($output, $question, $default);
+
+            try {
+                return call_user_func($validator, $value);
+            } catch (\Exception $error) {
+            }
+        }
+
+        throw $error;
+    }
+
+    /**
+     * Sets the input stream to read from when interacting with the user.
+     *
+     * This is mainly useful for testing purpose.
+     *
+     * @param resource $stream The input stream
+     */
+    public function setInputStream($stream)
+    {
+        $this->inputStream = $stream;
+    }
+
+    /**
+     * Returns the helper's input stream
+     *
+     * @return string
+     */
+    public function getInputStream()
+    {
+        return $this->inputStream;
+    }
+
+    /**
+     * Returns the helper's canonical name.
+     */
+    public function getName()
+    {
+        return 'dialog';
+    }
+}

+ 97 - 0
vendor/Symfony/Component/Console/Helper/FormatterHelper.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;
+
+/**
+ * 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
+     */
+    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 Boolean      $large    Whether to return a large block
+     *
+     * @return string The formatter message
+     */
+    public function formatBlock($messages, $style, $large = false)
+    {
+        $messages = (array) $messages;
+
+        $len = 0;
+        $lines = array();
+        foreach ($messages as $message) {
+            $lines[] = sprintf($large ? '  %s  ' : ' %s ', $message);
+            $len = max($this->strlen($message) + ($large ? 4 : 2), $len);
+        }
+
+        $messages = $large ? array(str_repeat(' ', $len)) : array();
+        foreach ($lines as $line) {
+            $messages[] = $line.str_repeat(' ', $len - $this->strlen($line));
+        }
+        if ($large) {
+            $messages[] = str_repeat(' ', $len);
+        }
+
+        foreach ($messages as &$message) {
+            $message = sprintf('<%s>%s</%s>', $style, $message, $style);
+        }
+
+        return implode("\n", $messages);
+    }
+
+    /**
+     * Returns the length of a string, using mb_strlen if it is available.
+     *
+     * @param string $string The string to check its length
+     *
+     * @return integer The length of the string
+     */
+    private function strlen($string)
+    {
+        if (!function_exists('mb_strlen')) {
+            return strlen($string);
+        }
+
+        if (false === $encoding = mb_detect_encoding($string)) {
+            return strlen($string);
+        }
+
+        return mb_strlen($string, $encoding);
+    }
+
+    /**
+     * Returns the helper's canonical name.
+     *
+     * @return string The canonical name of the helper
+     */
+    public function getName()
+    {
+        return 'formatter';
+    }
+}

+ 42 - 0
vendor/Symfony/Component/Console/Helper/Helper.php

@@ -0,0 +1,42 @@
+<?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;
+
+/**
+ * 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;
+    }
+}

+ 49 - 0
vendor/Symfony/Component/Console/Helper/HelperInterface.php

@@ -0,0 +1,49 @@
+<?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>
+ *
+ * @api
+ */
+interface HelperInterface
+{
+    /**
+     * Sets the helper set associated with this helper.
+     *
+     * @param HelperSet $helperSet A HelperSet instance
+     *
+     * @api
+     */
+    function setHelperSet(HelperSet $helperSet = null);
+
+    /**
+     * Gets the helper set associated with this helper.
+     *
+     * @return HelperSet A HelperSet instance
+     *
+     * @api
+     */
+    function getHelperSet();
+
+    /**
+     * Returns the canonical name of this helper.
+     *
+     * @return string The canonical name
+     *
+     * @api
+     */
+    function getName();
+}

+ 104 - 0
vendor/Symfony/Component/Console/Helper/HelperSet.php

@@ -0,0 +1,104 @@
+<?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;
+
+/**
+ * HelperSet represents a set of helpers to be used with a command.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class HelperSet
+{
+    private $helpers;
+    private $command;
+
+    /**
+     * Constructor.
+     *
+     * @param Helper[] $helpers An array of helper.
+     */
+    public function __construct(array $helpers = array())
+    {
+        $this->helpers = array();
+        foreach ($helpers as $alias => $helper) {
+            $this->set($helper, is_int($alias) ? null : $alias);
+        }
+    }
+
+    /**
+     * Sets a helper.
+     *
+     * @param HelperInterface $helper The helper instance
+     * @param string          $alias  An alias
+     */
+    public function set(HelperInterface $helper, $alias = null)
+    {
+        $this->helpers[$helper->getName()] = $helper;
+        if (null !== $alias) {
+            $this->helpers[$alias] = $helper;
+        }
+
+        $helper->setHelperSet($this);
+    }
+
+    /**
+     * Returns true if the helper if defined.
+     *
+     * @param string  $name The helper name
+     *
+     * @return Boolean true if the helper is defined, false otherwise
+     */
+    public function has($name)
+    {
+        return isset($this->helpers[$name]);
+    }
+
+    /**
+     * Gets a helper value.
+     *
+     * @param string $name The helper name
+     *
+     * @return HelperInterface The helper instance
+     *
+     * @throws \InvalidArgumentException if the helper is not defined
+     */
+    public function get($name)
+    {
+        if (!$this->has($name)) {
+            throw new \InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
+        }
+
+        return $this->helpers[$name];
+    }
+
+    /**
+     * Sets the command associated with this helper set.
+     *
+     * @param Command $command A Command instance
+     */
+    public function setCommand(Command $command = null)
+    {
+        $this->command = $command;
+    }
+
+    /**
+     * Gets the command associated with this helper set.
+     *
+     * @return Command A Command instance
+     */
+    public function getCommand()
+    {
+        return $this->command;
+    }
+}

+ 311 - 0
vendor/Symfony/Component/Console/Input/ArgvInput.php

@@ -0,0 +1,311 @@
+<?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\Input;
+
+/**
+ * ArgvInput represents an input coming from the CLI arguments.
+ *
+ * Usage:
+ *
+ *     $input = new ArgvInput();
+ *
+ * By default, the `$_SERVER['argv']` array is used for the input values.
+ *
+ * This can be overridden by explicitly passing the input values in the constructor:
+ *
+ *     $input = new ArgvInput($_SERVER['argv']);
+ *
+ * If you pass it yourself, don't forget that the first element of the array
+ * is the name of the running application.
+ *
+ * When passing an argument to the constructor, be sure that it respects
+ * the same rules as the argv one. It's almost always better to use the
+ * `StringInput` when you want to provide your own input.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @see    http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html
+ * @see    http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02
+ *
+ * @api
+ */
+class ArgvInput extends Input
+{
+    private $tokens;
+    private $parsed;
+
+    /**
+     * Constructor.
+     *
+     * @param array           $argv An array of parameters from the CLI (in the argv format)
+     * @param InputDefinition $definition A InputDefinition instance
+     *
+     * @api
+     */
+    public function __construct(array $argv = null, InputDefinition $definition = null)
+    {
+        if (null === $argv) {
+            $argv = $_SERVER['argv'];
+        }
+
+        // strip the application name
+        array_shift($argv);
+
+        $this->tokens = $argv;
+
+        parent::__construct($definition);
+    }
+
+    protected function setTokens(array $tokens)
+    {
+        $this->tokens = $tokens;
+    }
+
+    /**
+     * Processes command line arguments.
+     */
+    protected function parse()
+    {
+        $parseOptions = true;
+        $this->parsed = $this->tokens;
+        while (null !== $token = array_shift($this->parsed)) {
+            if ($parseOptions && '--' == $token) {
+                $parseOptions = false;
+            } elseif ($parseOptions && 0 === strpos($token, '--')) {
+                $this->parseLongOption($token);
+            } elseif ($parseOptions && '-' === $token[0]) {
+                $this->parseShortOption($token);
+            } else {
+                $this->parseArgument($token);
+            }
+        }
+    }
+
+    /**
+     * Parses a short option.
+     *
+     * @param string $token The current token.
+     */
+    private function parseShortOption($token)
+    {
+        $name = substr($token, 1);
+
+        if (strlen($name) > 1) {
+            if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) {
+                // an option with a value (with no space)
+                $this->addShortOption($name[0], substr($name, 1));
+            } else {
+                $this->parseShortOptionSet($name);
+            }
+        } else {
+            $this->addShortOption($name, null);
+        }
+    }
+
+    /**
+     * Parses a short option set.
+     *
+     * @param string $name The current token
+     *
+     * @throws \RuntimeException When option given doesn't exist
+     */
+    private function parseShortOptionSet($name)
+    {
+        $len = strlen($name);
+        for ($i = 0; $i < $len; $i++) {
+            if (!$this->definition->hasShortcut($name[$i])) {
+                throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i]));
+            }
+
+            $option = $this->definition->getOptionForShortcut($name[$i]);
+            if ($option->acceptValue()) {
+                $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));
+
+                break;
+            } else {
+                $this->addLongOption($option->getName(), true);
+            }
+        }
+    }
+
+    /**
+     * Parses a long option.
+     *
+     * @param string $token The current token
+     */
+    private function parseLongOption($token)
+    {
+        $name = substr($token, 2);
+
+        if (false !== $pos = strpos($name, '=')) {
+            $this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1));
+        } else {
+            $this->addLongOption($name, null);
+        }
+    }
+
+    /**
+     * Parses an argument.
+     *
+     * @param string $token The current token
+     *
+     * @throws \RuntimeException When too many arguments are given
+     */
+    private function parseArgument($token)
+    {
+        $c = count($this->arguments);
+
+        // if input is expecting another argument, add it
+        if ($this->definition->hasArgument($c)) {
+            $arg = $this->definition->getArgument($c);
+            $this->arguments[$arg->getName()] = $arg->isArray()? array($token) : $token;
+
+        // if last argument isArray(), append token to last argument
+        } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
+            $arg = $this->definition->getArgument($c - 1);
+            $this->arguments[$arg->getName()][] = $token;
+
+        // unexpected argument
+        } else {
+            throw new \RuntimeException('Too many arguments.');
+        }
+    }
+
+    /**
+     * Adds a short option value.
+     *
+     * @param string $shortcut The short option key
+     * @param mixed  $value    The value for the option
+     *
+     * @throws \RuntimeException When option given doesn't exist
+     */
+    private function addShortOption($shortcut, $value)
+    {
+        if (!$this->definition->hasShortcut($shortcut)) {
+            throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
+        }
+
+        $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
+    }
+
+    /**
+     * Adds a long option value.
+     *
+     * @param string $name  The long option key
+     * @param mixed  $value The value for the option
+     *
+     * @throws \RuntimeException When option given doesn't exist
+     */
+    private function addLongOption($name, $value)
+    {
+        if (!$this->definition->hasOption($name)) {
+            throw new \RuntimeException(sprintf('The "--%s" option does not exist.', $name));
+        }
+
+        $option = $this->definition->getOption($name);
+
+        if (null === $value && $option->acceptValue()) {
+            // if option accepts an optional or mandatory argument
+            // let's see if there is one provided
+            $next = array_shift($this->parsed);
+            if ('-' !== $next[0]) {
+                $value = $next;
+            } else {
+                array_unshift($this->parsed, $next);
+            }
+        }
+
+        if (null === $value) {
+            if ($option->isValueRequired()) {
+                throw new \RuntimeException(sprintf('The "--%s" option requires a value.', $name));
+            }
+
+            $value = $option->isValueOptional() ? $option->getDefault() : true;
+        }
+
+        if ($option->isArray()) {
+            $this->options[$name][] = $value;
+        } else {
+            $this->options[$name] = $value;
+        }
+    }
+
+    /**
+     * Returns the first argument from the raw parameters (not parsed).
+     *
+     * @return string The value of the first argument or null otherwise
+     */
+    public function getFirstArgument()
+    {
+        foreach ($this->tokens as $token) {
+            if ($token && '-' === $token[0]) {
+                continue;
+            }
+
+            return $token;
+        }
+    }
+
+    /**
+     * Returns true if the raw parameters (not parsed) contain a value.
+     *
+     * This method is to be used to introspect the input parameters
+     * before they have been validated. It must be used carefully.
+     *
+     * @param string|array $values The value(s) to look for in the raw parameters (can be an array)
+     *
+     * @return Boolean true if the value is contained in the raw parameters
+     */
+    public function hasParameterOption($values)
+    {
+        $values = (array) $values;
+
+        foreach ($this->tokens as $v) {
+            if (in_array($v, $values)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns the value of a raw option (not parsed).
+     *
+     * This method is to be used to introspect the input parameters
+     * before they have been validated. It must be used carefully.
+     *
+     * @param string|array $values The value(s) to look for in the raw parameters (can be an array)
+     * @param mixed $default The default value to return if no result is found
+     *
+     * @return mixed The option value
+     */
+    public function getParameterOption($values, $default = false)
+    {
+        $values = (array) $values;
+
+        $tokens = $this->tokens;
+        while ($token = array_shift($tokens)) {
+            foreach ($values as $value) {
+                if (0 === strpos($token, $value)) {
+                    if (false !== $pos = strpos($token, '=')) {
+                        return substr($token, $pos + 1);
+                    }
+
+                    return array_shift($tokens);
+                }
+            }
+        }
+
+        return $default;
+    }
+}

+ 190 - 0
vendor/Symfony/Component/Console/Input/ArrayInput.php

@@ -0,0 +1,190 @@
+<?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\Input;
+
+/**
+ * ArrayInput represents an input provided as an array.
+ *
+ * Usage:
+ *
+ *     $input = new ArrayInput(array('name' => 'foo', '--bar' => 'foobar'));
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class ArrayInput extends Input
+{
+    private $parameters;
+
+    /**
+     * Constructor.
+     *
+     * @param array           $parameters An array of parameters
+     * @param InputDefinition $definition A InputDefinition instance
+     *
+     * @api
+     */
+    public function __construct(array $parameters, InputDefinition $definition = null)
+    {
+        $this->parameters = $parameters;
+
+        parent::__construct($definition);
+    }
+
+    /**
+     * Returns the first argument from the raw parameters (not parsed).
+     *
+     * @return string The value of the first argument or null otherwise
+     */
+    public function getFirstArgument()
+    {
+        foreach ($this->parameters as $key => $value) {
+            if ($key && '-' === $key[0]) {
+                continue;
+            }
+
+            return $value;
+        }
+    }
+
+    /**
+     * Returns true if the raw parameters (not parsed) contain a value.
+     *
+     * This method is to be used to introspect the input parameters
+     * before they have been validated. It must be used carefully.
+     *
+     * @param string|array $values The values to look for in the raw parameters (can be an array)
+     *
+     * @return Boolean true if the value is contained in the raw parameters
+     */
+    public function hasParameterOption($values)
+    {
+        $values = (array) $values;
+
+        foreach ($this->parameters as $k => $v) {
+            if (!is_int($k)) {
+                $v = $k;
+            }
+
+            if (in_array($v, $values)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns the value of a raw option (not parsed).
+     *
+     * This method is to be used to introspect the input parameters
+     * before they have been validated. It must be used carefully.
+     *
+     * @param string|array $values The value(s) to look for in the raw parameters (can be an array)
+     * @param mixed $default The default value to return if no result is found
+     *
+     * @return mixed The option value
+     */
+    public function getParameterOption($values, $default = false)
+    {
+        $values = (array) $values;
+
+        foreach ($this->parameters as $k => $v) {
+            if (is_int($k) && in_array($v, $values)) {
+                return true;
+            } elseif (in_array($k, $values)) {
+                return $v;
+            }
+        }
+
+        return $default;
+    }
+
+    /**
+     * Processes command line arguments.
+     */
+    protected function parse()
+    {
+        foreach ($this->parameters as $key => $value) {
+            if (0 === strpos($key, '--')) {
+                $this->addLongOption(substr($key, 2), $value);
+            } elseif ('-' === $key[0]) {
+                $this->addShortOption(substr($key, 1), $value);
+            } else {
+                $this->addArgument($key, $value);
+            }
+        }
+    }
+
+    /**
+     * Adds a short option value.
+     *
+     * @param string $shortcut The short option key
+     * @param mixed  $value    The value for the option
+     *
+     * @throws \InvalidArgumentException When option given doesn't exist
+     */
+    private function addShortOption($shortcut, $value)
+    {
+        if (!$this->definition->hasShortcut($shortcut)) {
+            throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
+        }
+
+        $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
+    }
+
+    /**
+     * Adds a long option value.
+     *
+     * @param string $name  The long option key
+     * @param mixed  $value The value for the option
+     *
+     * @throws \InvalidArgumentException When option given doesn't exist
+     * @throws \InvalidArgumentException When a required value is missing
+     */
+    private function addLongOption($name, $value)
+    {
+        if (!$this->definition->hasOption($name)) {
+            throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
+        }
+
+        $option = $this->definition->getOption($name);
+
+        if (null === $value) {
+            if ($option->isValueRequired()) {
+                throw new \InvalidArgumentException(sprintf('The "--%s" option requires a value.', $name));
+            }
+
+            $value = $option->isValueOptional() ? $option->getDefault() : true;
+        }
+
+        $this->options[$name] = $value;
+    }
+
+    /**
+     * Adds an argument value.
+     *
+     * @param string $name  The argument name
+     * @param mixed  $value The value for the argument
+     *
+     * @throws \InvalidArgumentException When argument given doesn't exist
+     */
+    private function addArgument($name, $value)
+    {
+        if (!$this->definition->hasArgument($name)) {
+            throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
+        }
+
+        $this->arguments[$name] = $value;
+    }
+}

+ 211 - 0
vendor/Symfony/Component/Console/Input/Input.php

@@ -0,0 +1,211 @@
+<?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\Input;
+
+/**
+ * Input is the base class for all concrete Input classes.
+ *
+ * Three concrete classes are provided by default:
+ *
+ *  * `ArgvInput`: The input comes from the CLI arguments (argv)
+ *  * `StringInput`: The input is provided as a string
+ *  * `ArrayInput`: The input is provided as an array
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+abstract class Input implements InputInterface
+{
+    protected $definition;
+    protected $options;
+    protected $arguments;
+    protected $interactive = true;
+
+    /**
+     * Constructor.
+     *
+     * @param InputDefinition $definition A InputDefinition instance
+     */
+    public function __construct(InputDefinition $definition = null)
+    {
+        if (null === $definition) {
+            $this->definition = new InputDefinition();
+        } else {
+            $this->bind($definition);
+            $this->validate();
+        }
+    }
+
+    /**
+     * Binds the current Input instance with the given arguments and options.
+     *
+     * @param InputDefinition $definition A InputDefinition instance
+     */
+    public function bind(InputDefinition $definition)
+    {
+        $this->arguments = array();
+        $this->options = array();
+        $this->definition = $definition;
+
+        $this->parse();
+    }
+
+    /**
+     * Processes command line arguments.
+     */
+    abstract protected function parse();
+
+    /**
+     * Validates the input.
+     *
+     * @throws \RuntimeException When not enough arguments are given
+     */
+    public function validate()
+    {
+        if (count($this->arguments) < $this->definition->getArgumentRequiredCount()) {
+            throw new \RuntimeException('Not enough arguments.');
+        }
+    }
+
+    /**
+     * Checks if the input is interactive.
+     *
+     * @return Boolean Returns true if the input is interactive
+     */
+    public function isInteractive()
+    {
+        return $this->interactive;
+    }
+
+    /**
+     * Sets the input interactivity.
+     *
+     * @param Boolean $interactive If the input should be interactive
+     */
+    public function setInteractive($interactive)
+    {
+        $this->interactive = (Boolean) $interactive;
+    }
+
+    /**
+     * Returns the argument values.
+     *
+     * @return array An array of argument values
+     */
+    public function getArguments()
+    {
+        return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
+    }
+
+    /**
+     * Returns the argument value for a given argument name.
+     *
+     * @param string $name The argument name
+     *
+     * @return mixed The argument value
+     *
+     * @throws \InvalidArgumentException When argument given doesn't exist
+     */
+    public function getArgument($name)
+    {
+        if (!$this->definition->hasArgument($name)) {
+            throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
+        }
+
+        return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault();
+    }
+
+    /**
+     * Sets an argument value by name.
+     *
+     * @param string $name  The argument name
+     * @param string $value The argument value
+     *
+     * @throws \InvalidArgumentException When argument given doesn't exist
+     */
+    public function setArgument($name, $value)
+    {
+        if (!$this->definition->hasArgument($name)) {
+            throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
+        }
+
+        $this->arguments[$name] = $value;
+    }
+
+    /**
+     * Returns true if an InputArgument object exists by name or position.
+     *
+     * @param string|integer $name The InputArgument name or position
+     *
+     * @return Boolean true if the InputArgument object exists, false otherwise
+     */
+    public function hasArgument($name)
+    {
+        return $this->definition->hasArgument($name);
+    }
+
+    /**
+     * Returns the options values.
+     *
+     * @return array An array of option values
+     */
+    public function getOptions()
+    {
+        return array_merge($this->definition->getOptionDefaults(), $this->options);
+    }
+
+    /**
+     * Returns the option value for a given option name.
+     *
+     * @param string $name The option name
+     *
+     * @return mixed The option value
+     *
+     * @throws \InvalidArgumentException When option given doesn't exist
+     */
+    public function getOption($name)
+    {
+        if (!$this->definition->hasOption($name)) {
+            throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
+        }
+
+        return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
+    }
+
+    /**
+     * Sets an option value by name.
+     *
+     * @param string $name  The option name
+     * @param string $value The option value
+     *
+     * @throws \InvalidArgumentException When option given doesn't exist
+     */
+    public function setOption($name, $value)
+    {
+        if (!$this->definition->hasOption($name)) {
+            throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
+        }
+
+        $this->options[$name] = $value;
+    }
+
+    /**
+     * Returns true if an InputOption object exists by name.
+     *
+     * @param string $name The InputOption name
+     *
+     * @return Boolean true if the InputOption object exists, false otherwise
+     */
+    public function hasOption($name)
+    {
+        return $this->definition->hasOption($name);
+    }
+}

+ 132 - 0
vendor/Symfony/Component/Console/Input/InputArgument.php

@@ -0,0 +1,132 @@
+<?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\Input;
+
+/**
+ * Represents a command line argument.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class InputArgument
+{
+    const REQUIRED = 1;
+    const OPTIONAL = 2;
+    const IS_ARRAY = 4;
+
+    private $name;
+    private $mode;
+    private $default;
+    private $description;
+
+    /**
+     * Constructor.
+     *
+     * @param string  $name        The argument name
+     * @param integer $mode        The argument mode: self::REQUIRED or self::OPTIONAL
+     * @param string  $description A description text
+     * @param mixed   $default     The default value (for self::OPTIONAL mode only)
+     *
+     * @throws \InvalidArgumentException When argument mode is not valid
+     *
+     * @api
+     */
+    public function __construct($name, $mode = null, $description = '', $default = null)
+    {
+        if (null === $mode) {
+            $mode = self::OPTIONAL;
+        } elseif (!is_int($mode) || $mode > 7 || $mode < 1) {
+            throw new \InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode));
+        }
+
+        $this->name        = $name;
+        $this->mode        = $mode;
+        $this->description = $description;
+
+        $this->setDefault($default);
+    }
+
+    /**
+     * Returns the argument name.
+     *
+     * @return string The argument name
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * Returns true if the argument is required.
+     *
+     * @return Boolean true if parameter mode is self::REQUIRED, false otherwise
+     */
+    public function isRequired()
+    {
+        return self::REQUIRED === (self::REQUIRED & $this->mode);
+    }
+
+    /**
+     * Returns true if the argument can take multiple values.
+     *
+     * @return Boolean true if mode is self::IS_ARRAY, false otherwise
+     */
+    public function isArray()
+    {
+        return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
+    }
+
+    /**
+     * Sets the default value.
+     *
+     * @param mixed $default The default value
+     *
+     * @throws \LogicException When incorrect default value is given
+     */
+    public function setDefault($default = null)
+    {
+        if (self::REQUIRED === $this->mode && null !== $default) {
+            throw new \LogicException('Cannot set a default value except for Parameter::OPTIONAL mode.');
+        }
+
+        if ($this->isArray()) {
+            if (null === $default) {
+                $default = array();
+            } elseif (!is_array($default)) {
+                throw new \LogicException('A default value for an array argument must be an array.');
+            }
+        }
+
+        $this->default = $default;
+    }
+
+    /**
+     * Returns the default value.
+     *
+     * @return mixed The default value
+     */
+    public function getDefault()
+    {
+        return $this->default;
+    }
+
+    /**
+     * Returns the description text.
+     *
+     * @return string The description text
+     */
+    public function getDescription()
+    {
+        return $this->description;
+    }
+}

+ 533 - 0
vendor/Symfony/Component/Console/Input/InputDefinition.php

@@ -0,0 +1,533 @@
+<?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\Input;
+
+/**
+ * A InputDefinition represents a set of valid command line arguments and options.
+ *
+ * Usage:
+ *
+ *     $definition = new InputDefinition(array(
+ *       new InputArgument('name', InputArgument::REQUIRED),
+ *       new InputOption('foo', 'f', InputOption::VALUE_REQUIRED),
+ *     ));
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class InputDefinition
+{
+    private $arguments;
+    private $requiredCount;
+    private $hasAnArrayArgument = false;
+    private $hasOptional;
+    private $options;
+    private $shortcuts;
+
+    /**
+     * Constructor.
+     *
+     * @param array $definition An array of InputArgument and InputOption instance
+     *
+     * @api
+     */
+    public function __construct(array $definition = array())
+    {
+        $this->setDefinition($definition);
+    }
+
+    /**
+     * Sets the definition of the input.
+     *
+     * @param array $definition The definition array
+     *
+     * @api
+     */
+    public function setDefinition(array $definition)
+    {
+        $arguments = array();
+        $options = array();
+        foreach ($definition as $item) {
+            if ($item instanceof InputOption) {
+                $options[] = $item;
+            } else {
+                $arguments[] = $item;
+            }
+        }
+
+        $this->setArguments($arguments);
+        $this->setOptions($options);
+    }
+
+    /**
+     * Sets the InputArgument objects.
+     *
+     * @param array $arguments An array of InputArgument objects
+     *
+     * @api
+     */
+    public function setArguments($arguments = array())
+    {
+        $this->arguments          = array();
+        $this->requiredCount      = 0;
+        $this->hasOptional        = false;
+        $this->hasAnArrayArgument = false;
+        $this->addArguments($arguments);
+    }
+
+    /**
+     * Adds an array of InputArgument objects.
+     *
+     * @param InputArgument[] $arguments An array of InputArgument objects
+     *
+     * @api
+     */
+    public function addArguments($arguments = array())
+    {
+        if (null !== $arguments) {
+            foreach ($arguments as $argument) {
+                $this->addArgument($argument);
+            }
+        }
+    }
+
+    /**
+     * Adds an InputArgument object.
+     *
+     * @param InputArgument $argument An InputArgument object
+     *
+     * @throws \LogicException When incorrect argument is given
+     *
+     * @api
+     */
+    public function addArgument(InputArgument $argument)
+    {
+        if (isset($this->arguments[$argument->getName()])) {
+            throw new \LogicException(sprintf('An argument with name "%s" already exist.', $argument->getName()));
+        }
+
+        if ($this->hasAnArrayArgument) {
+            throw new \LogicException('Cannot add an argument after an array argument.');
+        }
+
+        if ($argument->isRequired() && $this->hasOptional) {
+            throw new \LogicException('Cannot add a required argument after an optional one.');
+        }
+
+        if ($argument->isArray()) {
+            $this->hasAnArrayArgument = true;
+        }
+
+        if ($argument->isRequired()) {
+            ++$this->requiredCount;
+        } else {
+            $this->hasOptional = true;
+        }
+
+        $this->arguments[$argument->getName()] = $argument;
+    }
+
+    /**
+     * Returns an InputArgument by name or by position.
+     *
+     * @param string|integer $name The InputArgument name or position
+     *
+     * @return InputArgument An InputArgument object
+     *
+     * @throws \InvalidArgumentException When argument given doesn't exist
+     *
+     * @api
+     */
+    public function getArgument($name)
+    {
+        $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
+
+        if (!$this->hasArgument($name)) {
+            throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
+        }
+
+        return $arguments[$name];
+    }
+
+    /**
+     * Returns true if an InputArgument object exists by name or position.
+     *
+     * @param string|integer $name The InputArgument name or position
+     *
+     * @return Boolean true if the InputArgument object exists, false otherwise
+     *
+     * @api
+     */
+    public function hasArgument($name)
+    {
+        $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
+
+        return isset($arguments[$name]);
+    }
+
+    /**
+     * Gets the array of InputArgument objects.
+     *
+     * @return array An array of InputArgument objects
+     *
+     * @api
+     */
+    public function getArguments()
+    {
+        return $this->arguments;
+    }
+
+    /**
+     * Returns the number of InputArguments.
+     *
+     * @return integer The number of InputArguments
+     */
+    public function getArgumentCount()
+    {
+        return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments);
+    }
+
+    /**
+     * Returns the number of required InputArguments.
+     *
+     * @return integer The number of required InputArguments
+     */
+    public function getArgumentRequiredCount()
+    {
+        return $this->requiredCount;
+    }
+
+    /**
+     * Gets the default values.
+     *
+     * @return array An array of default values
+     */
+    public function getArgumentDefaults()
+    {
+        $values = array();
+        foreach ($this->arguments as $argument) {
+            $values[$argument->getName()] = $argument->getDefault();
+        }
+
+        return $values;
+    }
+
+    /**
+     * Sets the InputOption objects.
+     *
+     * @param array $options An array of InputOption objects
+     *
+     * @api
+     */
+    public function setOptions($options = array())
+    {
+        $this->options = array();
+        $this->shortcuts = array();
+        $this->addOptions($options);
+    }
+
+    /**
+     * Adds an array of InputOption objects.
+     *
+     * @param InputOption[] $options An array of InputOption objects
+     *
+     * @api
+     */
+    public function addOptions($options = array())
+    {
+        foreach ($options as $option) {
+            $this->addOption($option);
+        }
+    }
+
+    /**
+     * Adds an InputOption object.
+     *
+     * @param InputOption $option An InputOption object
+     *
+     * @throws \LogicException When option given already exist
+     *
+     * @api
+     */
+    public function addOption(InputOption $option)
+    {
+        if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
+            throw new \LogicException(sprintf('An option named "%s" already exist.', $option->getName()));
+        } elseif (isset($this->shortcuts[$option->getShortcut()]) && !$option->equals($this->options[$this->shortcuts[$option->getShortcut()]])) {
+            throw new \LogicException(sprintf('An option with shortcut "%s" already exist.', $option->getShortcut()));
+        }
+
+        $this->options[$option->getName()] = $option;
+        if ($option->getShortcut()) {
+            $this->shortcuts[$option->getShortcut()] = $option->getName();
+        }
+    }
+
+    /**
+     * Returns an InputOption by name.
+     *
+     * @param string $name The InputOption name
+     *
+     * @return InputOption A InputOption object
+     *
+     * @api
+     */
+    public function getOption($name)
+    {
+        if (!$this->hasOption($name)) {
+            throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
+        }
+
+        return $this->options[$name];
+    }
+
+    /**
+     * Returns true if an InputOption object exists by name.
+     *
+     * @param string $name The InputOption name
+     *
+     * @return Boolean true if the InputOption object exists, false otherwise
+     *
+     * @api
+     */
+    public function hasOption($name)
+    {
+        return isset($this->options[$name]);
+    }
+
+    /**
+     * Gets the array of InputOption objects.
+     *
+     * @return array An array of InputOption objects
+     *
+     * @api
+     */
+    public function getOptions()
+    {
+        return $this->options;
+    }
+
+    /**
+     * Returns true if an InputOption object exists by shortcut.
+     *
+     * @param string $name The InputOption shortcut
+     *
+     * @return Boolean true if the InputOption object exists, false otherwise
+     */
+    public function hasShortcut($name)
+    {
+        return isset($this->shortcuts[$name]);
+    }
+
+    /**
+     * Gets an InputOption by shortcut.
+     *
+     * @param string $shortcut the Shortcut name
+     *
+     * @return InputOption An InputOption object
+     */
+    public function getOptionForShortcut($shortcut)
+    {
+        return $this->getOption($this->shortcutToName($shortcut));
+    }
+
+    /**
+     * Gets an array of default values.
+     *
+     * @return array An array of all default values
+     */
+    public function getOptionDefaults()
+    {
+        $values = array();
+        foreach ($this->options as $option) {
+            $values[$option->getName()] = $option->getDefault();
+        }
+
+        return $values;
+    }
+
+    /**
+     * Returns the InputOption name given a shortcut.
+     *
+     * @param string $shortcut The shortcut
+     *
+     * @return string The InputOption name
+     *
+     * @throws \InvalidArgumentException When option given does not exist
+     */
+    private function shortcutToName($shortcut)
+    {
+        if (!isset($this->shortcuts[$shortcut])) {
+            throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
+        }
+
+        return $this->shortcuts[$shortcut];
+    }
+
+    /**
+     * Gets the synopsis.
+     *
+     * @return string The synopsis
+     */
+    public function getSynopsis()
+    {
+        $elements = array();
+        foreach ($this->getOptions() as $option) {
+            $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
+            $elements[] = sprintf('['.($option->isValueRequired() ? '%s--%s="..."' : ($option->isValueOptional() ? '%s--%s[="..."]' : '%s--%s')).']', $shortcut, $option->getName());
+        }
+
+        foreach ($this->getArguments() as $argument) {
+            $elements[] = sprintf($argument->isRequired() ? '%s' : '[%s]', $argument->getName().($argument->isArray() ? '1' : ''));
+
+            if ($argument->isArray()) {
+                $elements[] = sprintf('... [%sN]', $argument->getName());
+            }
+        }
+
+        return implode(' ', $elements);
+    }
+
+    /**
+     * Returns a textual representation of the InputDefinition.
+     *
+     * @return string A string representing the InputDefinition
+     */
+    public function asText()
+    {
+        // find the largest option or argument name
+        $max = 0;
+        foreach ($this->getOptions() as $option) {
+            $nameLength = strlen($option->getName()) + 2;
+            if ($option->getShortcut()) {
+                $nameLength += strlen($option->getShortcut()) + 3;
+            }
+
+            $max = max($max, $nameLength);
+        }
+        foreach ($this->getArguments() as $argument) {
+            $max = max($max, strlen($argument->getName()));
+        }
+        ++$max;
+
+        $text = array();
+
+        if ($this->getArguments()) {
+            $text[] = '<comment>Arguments:</comment>';
+            foreach ($this->getArguments() as $argument) {
+                if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
+                    $default = sprintf('<comment> (default: %s)</comment>', $this->formatDefaultValue($argument->getDefault()));
+                } else {
+                    $default = '';
+                }
+
+                $description = str_replace("\n", "\n".str_pad('', $max + 2, ' '), $argument->getDescription());
+
+                $text[] = sprintf(" <info>%-${max}s</info> %s%s", $argument->getName(), $description, $default);
+            }
+
+            $text[] = '';
+        }
+
+        if ($this->getOptions()) {
+            $text[] = '<comment>Options:</comment>';
+
+            foreach ($this->getOptions() as $option) {
+                if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
+                    $default = sprintf('<comment> (default: %s)</comment>', $this->formatDefaultValue($option->getDefault()));
+                } else {
+                    $default = '';
+                }
+
+                $multiple = $option->isArray() ? '<comment> (multiple values allowed)</comment>' : '';
+                $description = str_replace("\n", "\n".str_pad('', $max + 2, ' '), $option->getDescription());
+
+                $optionMax = $max - strlen($option->getName()) - 2;
+                $text[] = sprintf(" <info>%s</info> %-${optionMax}s%s%s%s",
+                    '--'.$option->getName(),
+                    $option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '',
+                    $description,
+                    $default,
+                    $multiple
+                );
+            }
+
+            $text[] = '';
+        }
+
+        return implode("\n", $text);
+    }
+
+    /**
+     * Returns an XML representation of the InputDefinition.
+     *
+     * @param Boolean $asDom Whether to return a DOM or an XML string
+     *
+     * @return string|DOMDocument An XML string representing the InputDefinition
+     */
+    public function asXml($asDom = false)
+    {
+        $dom = new \DOMDocument('1.0', 'UTF-8');
+        $dom->formatOutput = true;
+        $dom->appendChild($definitionXML = $dom->createElement('definition'));
+
+        $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
+        foreach ($this->getArguments() as $argument) {
+            $argumentsXML->appendChild($argumentXML = $dom->createElement('argument'));
+            $argumentXML->setAttribute('name', $argument->getName());
+            $argumentXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
+            $argumentXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
+            $argumentXML->appendChild($descriptionXML = $dom->createElement('description'));
+            $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
+
+            $argumentXML->appendChild($defaultsXML = $dom->createElement('defaults'));
+            $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : (is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array()));
+            foreach ($defaults as $default) {
+                $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
+                $defaultXML->appendChild($dom->createTextNode($default));
+            }
+        }
+
+        $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
+        foreach ($this->getOptions() as $option) {
+            $optionsXML->appendChild($optionXML = $dom->createElement('option'));
+            $optionXML->setAttribute('name', '--'.$option->getName());
+            $optionXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
+            $optionXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
+            $optionXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
+            $optionXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
+            $optionXML->appendChild($descriptionXML = $dom->createElement('description'));
+            $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
+
+            if ($option->acceptValue()) {
+                $optionXML->appendChild($defaultsXML = $dom->createElement('defaults'));
+                $defaults = is_array($option->getDefault()) ? $option->getDefault() : (is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array()));
+                foreach ($defaults as $default) {
+                    $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
+                    $defaultXML->appendChild($dom->createTextNode($default));
+                }
+            }
+        }
+
+        return $asDom ? $dom : $dom->saveXml();
+    }
+
+    private function formatDefaultValue($default)
+    {
+        if (is_array($default) && $default === array_values($default)) {
+            return sprintf("array('%s')", implode("', '", $default));
+        }
+
+        return str_replace("\n", '', var_export($default, true));
+    }
+}

+ 152 - 0
vendor/Symfony/Component/Console/Input/InputInterface.php

@@ -0,0 +1,152 @@
+<?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\Input;
+
+/**
+ * InputInterface is the interface implemented by all input classes.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface InputInterface
+{
+    /**
+     * Returns the first argument from the raw parameters (not parsed).
+     *
+     * @return string The value of the first argument or null otherwise
+     */
+    function getFirstArgument();
+
+    /**
+     * Returns true if the raw parameters (not parsed) contain a value.
+     *
+     * This method is to be used to introspect the input parameters
+     * before they have been validated. It must be used carefully.
+     *
+     * @param string|array $values The values to look for in the raw parameters (can be an array)
+     *
+     * @return Boolean true if the value is contained in the raw parameters
+     */
+    function hasParameterOption($values);
+
+    /**
+     * Returns the value of a raw option (not parsed).
+     *
+     * This method is to be used to introspect the input parameters
+     * before they have been validated. It must be used carefully.
+     *
+     * @param string|array $values The value(s) to look for in the raw parameters (can be an array)
+     * @param mixed $default The default value to return if no result is found
+     *
+     * @return mixed The option value
+     */
+    function getParameterOption($values, $default = false);
+
+    /**
+     * Binds the current Input instance with the given arguments and options.
+     *
+     * @param InputDefinition $definition A InputDefinition instance
+     */
+    function bind(InputDefinition $definition);
+
+    /**
+     * Validates if arguments given are correct.
+     *
+     * Throws an exception when not enough arguments are given.
+     *
+     * @throws \RuntimeException
+     */
+    function validate();
+
+    /**
+     * Returns all the given arguments merged with the default values.
+     *
+     * @return array
+     */
+    function getArguments();
+
+    /**
+     * Gets argument by name.
+     *
+     * @param string $name The name of the argument
+     *
+     * @return mixed
+     */
+    function getArgument($name);
+
+    /**
+     * Sets an argument value by name.
+     *
+     * @param string $name  The argument name
+     * @param string $value The argument value
+     *
+     * @throws \InvalidArgumentException When argument given doesn't exist
+     */
+    function setArgument($name, $value);
+
+    /**
+     * Returns true if an InputArgument object exists by name or position.
+     *
+     * @param string|integer $name The InputArgument name or position
+     *
+     * @return Boolean true if the InputArgument object exists, false otherwise
+     */
+    function hasArgument($name);
+
+    /**
+     * Returns all the given options merged with the default values.
+     *
+     * @return array
+     */
+    function getOptions();
+
+    /**
+     * Gets an option by name.
+     *
+     * @param string $name The name of the option
+     *
+     * @return mixed
+     */
+    function getOption($name);
+
+    /**
+     * Sets an option value by name.
+     *
+     * @param string $name  The option name
+     * @param string $value The option value
+     *
+     * @throws \InvalidArgumentException When option given doesn't exist
+     */
+    function setOption($name, $value);
+
+    /**
+     * Returns true if an InputOption object exists by name.
+     *
+     * @param string $name The InputOption name
+     *
+     * @return Boolean true if the InputOption object exists, false otherwise
+     */
+    function hasOption($name);
+
+    /**
+     * Is this input means interactive?
+     *
+     * @return Boolean
+     */
+    function isInteractive();
+
+    /**
+     * Sets the input interactivity.
+     *
+     * @param Boolean $interactive If the input should be interactive
+     */
+    function setInteractive($interactive);
+}

+ 201 - 0
vendor/Symfony/Component/Console/Input/InputOption.php

@@ -0,0 +1,201 @@
+<?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\Input;
+
+/**
+ * Represents a command line option.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class InputOption
+{
+    const VALUE_NONE     = 1;
+    const VALUE_REQUIRED = 2;
+    const VALUE_OPTIONAL = 4;
+    const VALUE_IS_ARRAY = 8;
+
+    private $name;
+    private $shortcut;
+    private $mode;
+    private $default;
+    private $description;
+
+    /**
+     * Constructor.
+     *
+     * @param string  $name        The option name
+     * @param string  $shortcut    The shortcut (can be null)
+     * @param integer $mode        The option mode: One of the VALUE_* constants
+     * @param string  $description A description text
+     * @param mixed   $default     The default value (must be null for self::VALUE_REQUIRED or self::VALUE_NONE)
+     *
+     * @throws \InvalidArgumentException If option mode is invalid or incompatible
+     *
+     * @api
+     */
+    public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null)
+    {
+        if (0 === strpos($name, '--')) {
+            $name = substr($name, 2);
+        }
+
+        if (empty($shortcut)) {
+            $shortcut = null;
+        }
+
+        if (null !== $shortcut) {
+            if ('-' === $shortcut[0]) {
+                $shortcut = substr($shortcut, 1);
+            }
+        }
+
+        if (null === $mode) {
+            $mode = self::VALUE_NONE;
+        } elseif (!is_int($mode) || $mode > 15 || $mode < 1) {
+            throw new \InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
+        }
+
+        $this->name        = $name;
+        $this->shortcut    = $shortcut;
+        $this->mode        = $mode;
+        $this->description = $description;
+
+        if ($this->isArray() && !$this->acceptValue()) {
+            throw new \InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.');
+        }
+
+        $this->setDefault($default);
+    }
+
+    /**
+     * Returns the option shortcut.
+     *
+     * @return string The shortcut
+     */
+    public function getShortcut()
+    {
+        return $this->shortcut;
+    }
+
+    /**
+     * Returns the option name.
+     *
+     * @return string The name
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * Returns true if the option accepts a value.
+     *
+     * @return Boolean true if value mode is not self::VALUE_NONE, false otherwise
+     */
+    public function acceptValue()
+    {
+        return $this->isValueRequired() || $this->isValueOptional();
+    }
+
+    /**
+     * Returns true if the option requires a value.
+     *
+     * @return Boolean true if value mode is self::VALUE_REQUIRED, false otherwise
+     */
+    public function isValueRequired()
+    {
+        return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode);
+    }
+
+    /**
+     * Returns true if the option takes an optional value.
+     *
+     * @return Boolean true if value mode is self::VALUE_OPTIONAL, false otherwise
+     */
+    public function isValueOptional()
+    {
+        return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode);
+    }
+
+    /**
+     * Returns true if the option can take multiple values.
+     *
+     * @return Boolean true if mode is self::VALUE_IS_ARRAY, false otherwise
+     */
+    public function isArray()
+    {
+        return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
+    }
+
+    /**
+     * Sets the default value.
+     *
+     * @param mixed $default The default value
+     *
+     * @throws \LogicException When incorrect default value is given
+     */
+    public function setDefault($default = null)
+    {
+        if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
+            throw new \LogicException('Cannot set a default value when using Option::VALUE_NONE mode.');
+        }
+
+        if ($this->isArray()) {
+            if (null === $default) {
+                $default = array();
+            } elseif (!is_array($default)) {
+                throw new \LogicException('A default value for an array option must be an array.');
+            }
+        }
+
+        $this->default = $this->acceptValue() ? $default : false;
+    }
+
+    /**
+     * Returns the default value.
+     *
+     * @return mixed The default value
+     */
+    public function getDefault()
+    {
+        return $this->default;
+    }
+
+    /**
+     * Returns the description text.
+     *
+     * @return string The description text
+     */
+    public function getDescription()
+    {
+        return $this->description;
+    }
+
+    /**
+     * Checks whether the given option equals this one
+     *
+     * @param InputOption $option option to compare
+     * @return Boolean
+     */
+    public function equals(InputOption $option)
+    {
+        return $option->getName() === $this->getName()
+            && $option->getShortcut() === $this->getShortcut()
+            && $option->getDefault() === $this->getDefault()
+            && $option->isArray() === $this->isArray()
+            && $option->isValueRequired() === $this->isValueRequired()
+            && $option->isValueOptional() === $this->isValueOptional()
+        ;
+    }
+}

+ 79 - 0
vendor/Symfony/Component/Console/Input/StringInput.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\Input;
+
+/**
+ * StringInput represents an input provided as a string.
+ *
+ * Usage:
+ *
+ *     $input = new StringInput('foo --bar="foobar"');
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class StringInput extends ArgvInput
+{
+    const REGEX_STRING = '([^ ]+?)(?: |(?<!\\\\)"|(?<!\\\\)\'|$)';
+    const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
+
+    /**
+     * Constructor.
+     *
+     * @param string     $input An array of parameters from the CLI (in the argv format)
+     * @param InputDefinition $definition A InputDefinition instance
+     *
+     * @api
+     */
+    public function __construct($input, InputDefinition $definition = null)
+    {
+        parent::__construct(array(), $definition);
+
+        $this->setTokens($this->tokenize($input));
+    }
+
+    /**
+     * Tokenizes a string.
+     *
+     * @param string $input The input to tokenize
+     *
+     * @throws \InvalidArgumentException When unable to parse input (should never happen)
+     */
+    private function tokenize($input)
+    {
+        $input = preg_replace('/(\r\n|\r|\n|\t)/', ' ', $input);
+
+        $tokens = array();
+        $length = strlen($input);
+        $cursor = 0;
+        while ($cursor < $length) {
+            if (preg_match('/\s+/A', $input, $match, null, $cursor)) {
+            } elseif (preg_match('/([^="\' ]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) {
+                $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2)));
+            } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) {
+                $tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2));
+            } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) {
+                $tokens[] = stripcslashes($match[1]);
+            } else {
+                // should never happen
+                // @codeCoverageIgnoreStart
+                throw new \InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10)));
+                // @codeCoverageIgnoreEnd
+            }
+
+            $cursor += strlen($match[0]);
+        }
+
+        return $tokens;
+    }
+}

+ 19 - 0
vendor/Symfony/Component/Console/LICENSE

@@ -0,0 +1,19 @@
+Copyright (c) 2004-2012 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 83 - 0
vendor/Symfony/Component/Console/Output/ConsoleOutput.php

@@ -0,0 +1,83 @@
+<?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\Output;
+
+use Symfony\Component\Console\Formatter\OutputFormatter;
+use Symfony\Component\Console\Formatter\OutputFormatterInterface;
+use Symfony\Component\Console\Output\ConsoleOutputInterface;
+
+/**
+ * ConsoleOutput is the default class for all CLI output. It uses STDOUT.
+ *
+ * This class is a convenient wrapper around `StreamOutput`.
+ *
+ *     $output = new ConsoleOutput();
+ *
+ * This is equivalent to:
+ *
+ *     $output = new StreamOutput(fopen('php://stdout', 'w'));
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
+{
+    private $stderr;
+
+    /**
+     * Constructor.
+     *
+     * @param integer         $verbosity The verbosity level (self::VERBOSITY_QUIET, self::VERBOSITY_NORMAL,
+     *                                   self::VERBOSITY_VERBOSE)
+     * @param Boolean         $decorated Whether to decorate messages or not (null for auto-guessing)
+     * @param OutputFormatter $formatter Output formatter instance
+     *
+     * @api
+     */
+    public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
+    {
+        parent::__construct(fopen('php://stdout', 'w'), $verbosity, $decorated, $formatter);
+        $this->stderr = new StreamOutput(fopen('php://stderr', 'w'), $verbosity, $decorated, $formatter);
+    }
+
+    public function setDecorated($decorated)
+    {
+        parent::setDecorated($decorated);
+        $this->stderr->setDecorated($decorated);
+    }
+
+    public function setFormatter(OutputFormatterInterface $formatter)
+    {
+        parent::setFormatter($formatter);
+        $this->stderr->setFormatter($formatter);
+    }
+
+    public function setVerbosity($level)
+    {
+        parent::setVerbosity($level);
+        $this->stderr->setVerbosity($level);
+    }
+
+    /**
+     * @return OutputInterface
+     */
+    public function getErrorOutput()
+    {
+        return $this->stderr;
+    }
+
+    public function setErrorOutput(OutputInterface $error)
+    {
+        $this->stderr = $error;
+    }
+}

+ 30 - 0
vendor/Symfony/Component/Console/Output/ConsoleOutputInterface.php

@@ -0,0 +1,30 @@
+<?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\Output;
+
+use Symfony\Component\Console\Output\OutputInterface;
+
+/**
+ * ConsoleOutputInterface is the interface implemented by ConsoleOutput class.
+ * This adds information about stderr output stream.
+ *
+ * @author Dariusz Gรณrecki <darek.krk@gmail.com>
+ */
+interface ConsoleOutputInterface extends OutputInterface
+{
+    /**
+     * @return OutputInterface
+     */
+    public function getErrorOutput();
+
+    public function setErrorOutput(OutputInterface $error);
+}

+ 34 - 0
vendor/Symfony/Component/Console/Output/NullOutput.php

@@ -0,0 +1,34 @@
+<?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\Output;
+
+/**
+ * NullOutput suppresses all output.
+ *
+ *     $output = new NullOutput();
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class NullOutput extends Output
+{
+    /**
+     * Writes a message to the output.
+     *
+     * @param string $message A message to write to the output
+     * @param Boolean $newline Whether to add a newline or not
+     */
+    public function doWrite($message, $newline)
+    {
+    }
+}

+ 180 - 0
vendor/Symfony/Component/Console/Output/Output.php

@@ -0,0 +1,180 @@
+<?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\Output;
+
+use Symfony\Component\Console\Formatter\OutputFormatterInterface;
+use Symfony\Component\Console\Formatter\OutputFormatter;
+
+/**
+ * Base class for output classes.
+ *
+ * There are three levels of verbosity:
+ *
+ *  * normal: no option passed (normal output - information)
+ *  * verbose: -v (more output - debug)
+ *  * quiet: -q (no output)
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+abstract class Output implements OutputInterface
+{
+    private $verbosity;
+    private $formatter;
+
+    /**
+     * Constructor.
+     *
+     * @param integer                  $verbosity The verbosity level (self::VERBOSITY_QUIET, self::VERBOSITY_NORMAL, self::VERBOSITY_VERBOSE)
+     * @param Boolean                  $decorated Whether to decorate messages or not (null for auto-guessing)
+     * @param OutputFormatterInterface $formatter Output formatter instance
+     *
+     * @api
+     */
+    public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
+    {
+        $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity;
+        $this->formatter = null === $formatter ? new OutputFormatter() : $formatter;
+        $this->formatter->setDecorated((Boolean) $decorated);
+    }
+
+    /**
+     * Sets output formatter.
+     *
+     * @param OutputFormatterInterface $formatter
+     *
+     * @api
+     */
+    public function setFormatter(OutputFormatterInterface $formatter)
+    {
+        $this->formatter = $formatter;
+    }
+
+    /**
+     * Returns current output formatter instance.
+     *
+     * @return  OutputFormatterInterface
+     *
+     * @api
+     */
+    public function getFormatter()
+    {
+        return $this->formatter;
+    }
+
+    /**
+     * Sets the decorated flag.
+     *
+     * @param Boolean $decorated Whether to decorate the messages or not
+     *
+     * @api
+     */
+    public function setDecorated($decorated)
+    {
+        $this->formatter->setDecorated((Boolean) $decorated);
+    }
+
+    /**
+     * Gets the decorated flag.
+     *
+     * @return Boolean true if the output will decorate messages, false otherwise
+     *
+     * @api
+     */
+    public function isDecorated()
+    {
+        return $this->formatter->isDecorated();
+    }
+
+    /**
+     * Sets the verbosity of the output.
+     *
+     * @param integer $level The level of verbosity
+     *
+     * @api
+     */
+    public function setVerbosity($level)
+    {
+        $this->verbosity = (int) $level;
+    }
+
+    /**
+     * Gets the current verbosity of the output.
+     *
+     * @return integer The current level of verbosity
+     *
+     * @api
+     */
+    public function getVerbosity()
+    {
+        return $this->verbosity;
+    }
+
+    /**
+     * Writes a message to the output and adds a newline at the end.
+     *
+     * @param string|array $messages The message as an array of lines of a single string
+     * @param integer      $type     The type of output
+     *
+     * @api
+     */
+    public function writeln($messages, $type = 0)
+    {
+        $this->write($messages, true, $type);
+    }
+
+    /**
+     * Writes a message to the output.
+     *
+     * @param string|array $messages The message as an array of lines of a single string
+     * @param Boolean      $newline  Whether to add a newline or not
+     * @param integer      $type     The type of output
+     *
+     * @throws \InvalidArgumentException When unknown output type is given
+     *
+     * @api
+     */
+    public function write($messages, $newline = false, $type = 0)
+    {
+        if (self::VERBOSITY_QUIET === $this->verbosity) {
+            return;
+        }
+
+        $messages = (array) $messages;
+
+        foreach ($messages as $message) {
+            switch ($type) {
+                case OutputInterface::OUTPUT_NORMAL:
+                    $message = $this->formatter->format($message);
+                    break;
+                case OutputInterface::OUTPUT_RAW:
+                    break;
+                case OutputInterface::OUTPUT_PLAIN:
+                    $message = strip_tags($this->formatter->format($message));
+                    break;
+                default:
+                    throw new \InvalidArgumentException(sprintf('Unknown output type given (%s)', $type));
+            }
+
+            $this->doWrite($message, $newline);
+        }
+    }
+
+    /**
+     * Writes a message to the output.
+     *
+     * @param string  $message A message to write to the output
+     * @param Boolean $newline Whether to add a newline or not
+     */
+    abstract public function doWrite($message, $newline);
+}

+ 109 - 0
vendor/Symfony/Component/Console/Output/OutputInterface.php

@@ -0,0 +1,109 @@
+<?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\Output;
+
+use Symfony\Component\Console\Formatter\OutputFormatterInterface;
+
+/**
+ * OutputInterface is the interface implemented by all Output classes.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+interface OutputInterface
+{
+    const VERBOSITY_QUIET   = 0;
+    const VERBOSITY_NORMAL  = 1;
+    const VERBOSITY_VERBOSE = 2;
+
+    const OUTPUT_NORMAL = 0;
+    const OUTPUT_RAW = 1;
+    const OUTPUT_PLAIN = 2;
+
+    /**
+     * Writes a message to the output.
+     *
+     * @param string|array $messages The message as an array of lines of a single string
+     * @param Boolean      $newline  Whether to add a newline or not
+     * @param integer      $type     The type of output
+     *
+     * @throws \InvalidArgumentException When unknown output type is given
+     *
+     * @api
+     */
+    function write($messages, $newline = false, $type = 0);
+
+    /**
+     * Writes a message to the output and adds a newline at the end.
+     *
+     * @param string|array $messages The message as an array of lines of a single string
+     * @param integer      $type     The type of output
+     *
+     * @api
+     */
+    function writeln($messages, $type = 0);
+
+    /**
+     * Sets the verbosity of the output.
+     *
+     * @param integer $level The level of verbosity
+     *
+     * @api
+     */
+    function setVerbosity($level);
+
+    /**
+     * Gets the current verbosity of the output.
+     *
+     * @return integer The current level of verbosity
+     *
+     * @api
+     */
+    function getVerbosity();
+
+    /**
+     * Sets the decorated flag.
+     *
+     * @param Boolean $decorated Whether to decorate the messages or not
+     *
+     * @api
+     */
+    function setDecorated($decorated);
+
+    /**
+     * Gets the decorated flag.
+     *
+     * @return Boolean true if the output will decorate messages, false otherwise
+     *
+     * @api
+     */
+    function isDecorated();
+
+    /**
+     * Sets output formatter.
+     *
+     * @param OutputFormatterInterface $formatter
+     *
+     * @api
+     */
+    function setFormatter(OutputFormatterInterface $formatter);
+
+    /**
+     * Returns current output formatter instance.
+     *
+     * @return  OutputFormatterInterface
+     *
+     * @api
+     */
+    function getFormatter();
+}

+ 113 - 0
vendor/Symfony/Component/Console/Output/StreamOutput.php

@@ -0,0 +1,113 @@
+<?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\Output;
+
+use Symfony\Component\Console\Formatter\OutputFormatterInterface;
+
+/**
+ * StreamOutput writes the output to a given stream.
+ *
+ * Usage:
+ *
+ * $output = new StreamOutput(fopen('php://stdout', 'w'));
+ *
+ * As `StreamOutput` can use any stream, you can also use a file:
+ *
+ * $output = new StreamOutput(fopen('/path/to/output.log', 'a', false));
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class StreamOutput extends Output
+{
+    private $stream;
+
+    /**
+     * Constructor.
+     *
+     * @param mixed           $stream    A stream resource
+     * @param integer         $verbosity The verbosity level (self::VERBOSITY_QUIET, self::VERBOSITY_NORMAL,
+     *                                   self::VERBOSITY_VERBOSE)
+     * @param Boolean         $decorated Whether to decorate messages or not (null for auto-guessing)
+     * @param OutputFormatter $formatter Output formatter instance
+     *
+     * @throws \InvalidArgumentException When first argument is not a real stream
+     *
+     * @api
+     */
+    public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
+    {
+        if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) {
+            throw new \InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
+        }
+
+        $this->stream = $stream;
+
+        if (null === $decorated) {
+            $decorated = $this->hasColorSupport($decorated);
+        }
+
+        parent::__construct($verbosity, $decorated, $formatter);
+    }
+
+    /**
+     * Gets the stream attached to this StreamOutput instance.
+     *
+     * @return resource A stream resource
+     */
+    public function getStream()
+    {
+        return $this->stream;
+    }
+
+    /**
+     * Writes a message to the output.
+     *
+     * @param string  $message A message to write to the output
+     * @param Boolean $newline Whether to add a newline or not
+     *
+     * @throws \RuntimeException When unable to write output (should never happen)
+     */
+    public function doWrite($message, $newline)
+    {
+        if (false === @fwrite($this->stream, $message.($newline ? PHP_EOL : ''))) {
+            // @codeCoverageIgnoreStart
+            // should never happen
+            throw new \RuntimeException('Unable to write output.');
+            // @codeCoverageIgnoreEnd
+        }
+
+        fflush($this->stream);
+    }
+
+    /**
+     * Returns true if the stream supports colorization.
+     *
+     * Colorization is disabled if not supported by the stream:
+     *
+     *  -  windows without ansicon
+     *  -  non tty consoles
+     *
+     * @return Boolean true if the stream supports colorization, false otherwise
+     */
+    protected function hasColorSupport()
+    {
+        // @codeCoverageIgnoreStart
+        if (DIRECTORY_SEPARATOR == '\\') {
+            return false !== getenv('ANSICON');
+        }
+
+        return function_exists('posix_isatty') && @posix_isatty($this->stream);
+        // @codeCoverageIgnoreEnd
+    }
+}

+ 48 - 0
vendor/Symfony/Component/Console/README.md

@@ -0,0 +1,48 @@
+Console Component
+=================
+
+Console eases the creation of beautiful and testable command line interfaces.
+
+The Application object manages the CLI application:
+
+    use Symfony\Component\Console\Application;
+
+    $console = new Application();
+    $console->run();
+
+The ``run()`` method parses the arguments and options passed on the command
+line and executes the right command.
+
+Registering a new command can easily be done via the ``register()`` method,
+which returns a ``Command`` instance:
+
+    use Symfony\Component\Console\Input\InputInterface;
+    use Symfony\Component\Console\Input\InputArgument;
+    use Symfony\Component\Console\Input\InputOption;
+    use Symfony\Component\Console\Output\OutputInterface;
+
+    $console
+        ->register('ls')
+        ->setDefinition(array(
+            new InputArgument('dir', InputArgument::REQUIRED, 'Directory name'),
+        ))
+        ->setDescription('Displays the files in the given directory')
+        ->setCode(function (InputInterface $input, OutputInterface $output) {
+            $dir = $input->getArgument('dir');
+
+            $output->writeln(sprintf('Dir listing for <info>%s</info>', $dir));
+        })
+    ;
+
+You can also register new commands via classes.
+
+The component provides a lot of features like output coloring, input and
+output abstractions (so that you can easily unit-test your commands),
+validation, automatic help messages, ...
+
+Resources
+---------
+
+Unit tests:
+
+https://github.com/symfony/symfony/tree/master/tests/Symfony/Tests/Component/Console

+ 206 - 0
vendor/Symfony/Component/Console/Shell.php

@@ -0,0 +1,206 @@
+<?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;
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Input\StringInput;
+use Symfony\Component\Console\Output\ConsoleOutput;
+use Symfony\Component\Process\ProcessBuilder;
+use Symfony\Component\Process\PhpExecutableFinder;
+
+/**
+ * A Shell wraps an Application to add shell capabilities to it.
+ *
+ * Support for history and completion only works with a PHP compiled
+ * with readline support (either --with-readline or --with-libedit)
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Martin Hasoลˆ <martin.hason@gmail.com>
+ */
+class Shell
+{
+    private $application;
+    private $history;
+    private $output;
+    private $hasReadline;
+    private $prompt;
+    private $processIsolation;
+
+    /**
+     * Constructor.
+     *
+     * If there is no readline support for the current PHP executable
+     * a \RuntimeException exception is thrown.
+     *
+     * @param Application $application An application instance
+     */
+    public function __construct(Application $application)
+    {
+        $this->hasReadline = function_exists('readline');
+        $this->application = $application;
+        $this->history = getenv('HOME').'/.history_'.$application->getName();
+        $this->output = new ConsoleOutput();
+        $this->prompt = $application->getName().' > ';
+        $this->processIsolation = false;
+    }
+
+    /**
+     * Runs the shell.
+     */
+    public function run()
+    {
+        $this->application->setAutoExit(false);
+        $this->application->setCatchExceptions(true);
+
+        if ($this->hasReadline) {
+            readline_read_history($this->history);
+            readline_completion_function(array($this, 'autocompleter'));
+        }
+
+        $this->output->writeln($this->getHeader());
+        $php = null;
+        if ($this->processIsolation) {
+            $finder = new PhpExecutableFinder();
+            $php = $finder->find();
+            $this->output->writeln(<<<EOF
+<info>Running with process isolation, you should consider this:</info>
+  * each command is executed as separate process,
+  * commands don't support interactivity, all params must be passed explicitly,
+  * commands output is not colorized.
+
+EOF
+            );
+        }
+
+        while (true) {
+            $command = $this->readline();
+
+            if (false === $command) {
+                $this->output->writeln("\n");
+
+                break;
+            }
+
+            if ($this->hasReadline) {
+                readline_add_history($command);
+                readline_write_history($this->history);
+            }
+
+            if ($this->processIsolation) {
+                $pb = new ProcessBuilder();
+
+                $process = $pb
+                    ->add($php)
+                    ->add($_SERVER['argv'][0])
+                    ->add($command)
+                    ->inheritEnvironmentVariables(true)
+                    ->getProcess()
+                ;
+
+                $output = $this->output;
+                $process->run(function($type, $data) use ($output) {
+                    $output->writeln($data);
+                });
+
+                $ret = $process->getExitCode();
+            } else {
+                $ret = $this->application->run(new StringInput($command), $this->output);
+            }
+
+            if (0 !== $ret) {
+                $this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
+            }
+        }
+    }
+
+    /**
+     * Returns the shell header.
+     *
+     * @return string The header string
+     */
+    protected function getHeader()
+    {
+        return <<<EOF
+
+Welcome to the <info>{$this->application->getName()}</info> shell (<comment>{$this->application->getVersion()}</comment>).
+
+At the prompt, type <comment>help</comment> for some help,
+or <comment>list</comment> to get a list of available commands.
+
+To exit the shell, type <comment>^D</comment>.
+
+EOF;
+    }
+
+    /**
+     * Tries to return autocompletion for the current entered text.
+     *
+     * @param string $text The last segment of the entered text
+     * @return Boolean|array A list of guessed strings or true
+     */
+    private function autocompleter($text)
+    {
+        $info = readline_info();
+        $text = substr($info['line_buffer'], 0, $info['end']);
+
+        if ($info['point'] !== $info['end']) {
+            return true;
+        }
+
+        // task name?
+        if (false === strpos($text, ' ') || !$text) {
+            return array_keys($this->application->all());
+        }
+
+        // options and arguments?
+        try {
+            $command = $this->application->find(substr($text, 0, strpos($text, ' ')));
+        } catch (\Exception $e) {
+            return true;
+        }
+
+        $list = array('--help');
+        foreach ($command->getDefinition()->getOptions() as $option) {
+            $list[] = '--'.$option->getName();
+        }
+
+        return $list;
+    }
+
+    /**
+     * Reads a single line from standard input.
+     *
+     * @return string The single line from standard input
+     */
+    private function readline()
+    {
+        if ($this->hasReadline) {
+            $line = readline($this->prompt);
+        } else {
+            $this->output->write($this->prompt);
+            $line = fgets(STDIN, 1024);
+            $line = (!$line && strlen($line) == 0) ? false : rtrim($line);
+        }
+
+        return $line;
+    }
+
+    public function getProcessIsolation()
+    {
+        return $this->processIsolation;
+    }
+
+    public function setProcessIsolation($processIsolation)
+    {
+        $this->processIsolation = (Boolean) $processIsolation;
+    }
+}

+ 102 - 0
vendor/Symfony/Component/Console/Tester/ApplicationTester.php

@@ -0,0 +1,102 @@
+<?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\Tester;
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Input\ArrayInput;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Output\StreamOutput;
+
+/**
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ApplicationTester
+{
+    private $application;
+    private $input;
+    private $output;
+
+    /**
+     * Constructor.
+     *
+     * @param Application $application An Application instance to test.
+     */
+    public function __construct(Application $application)
+    {
+        $this->application = $application;
+    }
+
+    /**
+     * Executes the application.
+     *
+     * Available options:
+     *
+     *  * interactive: Sets the input interactive flag
+     *  * decorated:   Sets the output decorated flag
+     *  * verbosity:   Sets the output verbosity flag
+     *
+     * @param array $input   An array of arguments and options
+     * @param array $options An array of options
+     *
+     * @return integer The command exit code
+     */
+    public function run(array $input, $options = array())
+    {
+        $this->input = new ArrayInput($input);
+        if (isset($options['interactive'])) {
+            $this->input->setInteractive($options['interactive']);
+        }
+
+        $this->output = new StreamOutput(fopen('php://memory', 'w', false));
+        if (isset($options['decorated'])) {
+            $this->output->setDecorated($options['decorated']);
+        }
+        if (isset($options['verbosity'])) {
+            $this->output->setVerbosity($options['verbosity']);
+        }
+
+        return $this->application->run($this->input, $this->output);
+    }
+
+    /**
+     * Gets the display returned by the last execution of the application.
+     *
+     * @return string The display
+     */
+    public function getDisplay()
+    {
+        rewind($this->output->getStream());
+
+        return stream_get_contents($this->output->getStream());
+    }
+
+    /**
+     * Gets the input instance used by the last execution of the application.
+     *
+     * @return InputInterface The current input instance
+     */
+    public function getInput()
+    {
+        return $this->input;
+    }
+
+    /**
+     * Gets the output instance used by the last execution of the application.
+     *
+     * @return OutputInterface The current output instance
+     */
+    public function getOutput()
+    {
+        return $this->output;
+    }
+}

+ 100 - 0
vendor/Symfony/Component/Console/Tester/CommandTester.php

@@ -0,0 +1,100 @@
+<?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\Tester;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\ArrayInput;
+use Symfony\Component\Console\Output\StreamOutput;
+
+/**
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class CommandTester
+{
+    private $command;
+    private $input;
+    private $output;
+
+    /**
+     * Constructor.
+     *
+     * @param Command $command A Command instance to test.
+     */
+    public function __construct(Command $command)
+    {
+        $this->command = $command;
+    }
+
+    /**
+     * Executes the command.
+     *
+     * Available options:
+     *
+     *  * interactive: Sets the input interactive flag
+     *  * decorated:   Sets the output decorated flag
+     *  * verbosity:   Sets the output verbosity flag
+     *
+     * @param array $input   An array of arguments and options
+     * @param array $options An array of options
+     *
+     * @return integer The command exit code
+     */
+    public function execute(array $input, array $options = array())
+    {
+        $this->input = new ArrayInput($input);
+        if (isset($options['interactive'])) {
+            $this->input->setInteractive($options['interactive']);
+        }
+
+        $this->output = new StreamOutput(fopen('php://memory', 'w', false));
+        if (isset($options['decorated'])) {
+            $this->output->setDecorated($options['decorated']);
+        }
+        if (isset($options['verbosity'])) {
+            $this->output->setVerbosity($options['verbosity']);
+        }
+
+        return $this->command->run($this->input, $this->output);
+    }
+
+    /**
+     * Gets the display returned by the last execution of the command.
+     *
+     * @return string The display
+     */
+    public function getDisplay()
+    {
+        rewind($this->output->getStream());
+
+        return stream_get_contents($this->output->getStream());
+    }
+
+    /**
+     * Gets the input instance used by the last execution of the command.
+     *
+     * @return InputInterface The current input instance
+     */
+    public function getInput()
+    {
+        return $this->input;
+    }
+
+    /**
+     * Gets the output instance used by the last execution of the command.
+     *
+     * @return OutputInterface The current output instance
+     */
+    public function getOutput()
+    {
+        return $this->output;
+    }
+}

+ 30 - 0
vendor/Symfony/Component/Console/composer.json

@@ -0,0 +1,30 @@
+{
+    "name": "symfony/console",
+    "type": "library",
+    "description": "Symfony Console Component",
+    "keywords": [],
+    "homepage": "http://symfony.com",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Fabien Potencier",
+            "email": "fabien@symfony.com"
+        },
+        {
+            "name": "Symfony Community",
+            "homepage": "http://symfony.com/contributors"
+        }
+    ],
+    "require": {
+        "php": ">=5.3.2"
+    },
+    "autoload": {
+        "psr-0": { "Symfony\\Component\\Console": "" }
+    },
+    "target-dir": "Symfony/Component/Console",
+    "extra": {
+        "branch-alias": {
+            "dev-master": "2.1-dev"
+        }
+    }
+}