diff --git a/composer.json b/composer.json
index 49bc768b2b2319682f275375e67bc70517791506..7fbc7b2658f64b25a328d4d0d520a21b55dee67a 100644
--- a/composer.json
+++ b/composer.json
@@ -15,6 +15,7 @@
     "symfony/routing": "2.6.*",
     "symfony/serializer": "2.6.*",
     "symfony/validator": "2.6.*",
+    "symfony/process": "2.6.*",
     "symfony/yaml": "2.6.*",
     "twig/twig": "1.16.*",
     "doctrine/common": "dev-master#a45d110f71c323e29f41eb0696fa230e3fa1b1b5",
diff --git a/composer.lock b/composer.lock
index eb1c2c45b70719d800ae685eb55bb3ff5d605751..635968be5694617be6a2c0b0504d89e75565133d 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "hash": "f42dce2268b1a6fcf8ffc8720c45f28f",
+    "hash": "57cb0f99786ec791d5e89578b7ed4602",
     "packages": [
         {
             "name": "doctrine/annotations",
@@ -2041,6 +2041,53 @@
             "homepage": "http://symfony.com",
             "time": "2014-12-03 16:40:43"
         },
+        {
+            "name": "symfony/process",
+            "version": "v2.6.1",
+            "target-dir": "Symfony/Component/Process",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/Process.git",
+                "reference": "bf0c9bd625f13b0b0bbe39919225cf145dfb935a"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/Process/zipball/bf0c9bd625f13b0b0bbe39919225cf145dfb935a",
+                "reference": "bf0c9bd625f13b0b0bbe39919225cf145dfb935a",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.6-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Symfony\\Component\\Process\\": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Symfony Community",
+                    "homepage": "http://symfony.com/contributors"
+                },
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                }
+            ],
+            "description": "Symfony Process Component",
+            "homepage": "http://symfony.com",
+            "time": "2014-12-02 20:19:20"
+        },
         {
             "name": "symfony/routing",
             "version": "v2.6.1",
diff --git a/core/vendor/composer/autoload_namespaces.php b/core/vendor/composer/autoload_namespaces.php
index 18472d710f2bb9643b8d327c4ec70612bd404224..54e2998cc44cc37844dae599815aa74afaea8ded 100644
--- a/core/vendor/composer/autoload_namespaces.php
+++ b/core/vendor/composer/autoload_namespaces.php
@@ -16,6 +16,7 @@
     'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
     'Symfony\\Component\\Serializer\\' => array($vendorDir . '/symfony/serializer'),
     'Symfony\\Component\\Routing\\' => array($vendorDir . '/symfony/routing'),
+    'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
     'Symfony\\Component\\HttpKernel\\' => array($vendorDir . '/symfony/http-kernel'),
     'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'),
     'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'),
diff --git a/core/vendor/composer/installed.json b/core/vendor/composer/installed.json
index 7128da006bf18c0602c1b64c434772d017295eff..85cb45e9e28e6cec983796bb098cb423b9686033 100644
--- a/core/vendor/composer/installed.json
+++ b/core/vendor/composer/installed.json
@@ -2603,5 +2603,54 @@
         ],
         "description": "Symfony Yaml Component",
         "homepage": "http://symfony.com"
+    },
+    {
+        "name": "symfony/process",
+        "version": "v2.6.1",
+        "version_normalized": "2.6.1.0",
+        "target-dir": "Symfony/Component/Process",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/symfony/Process.git",
+            "reference": "bf0c9bd625f13b0b0bbe39919225cf145dfb935a"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/symfony/Process/zipball/bf0c9bd625f13b0b0bbe39919225cf145dfb935a",
+            "reference": "bf0c9bd625f13b0b0bbe39919225cf145dfb935a",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.3"
+        },
+        "time": "2014-12-02 20:19:20",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "2.6-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-0": {
+                "Symfony\\Component\\Process\\": ""
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Symfony Community",
+                "homepage": "http://symfony.com/contributors"
+            },
+            {
+                "name": "Fabien Potencier",
+                "email": "fabien@symfony.com"
+            }
+        ],
+        "description": "Symfony Process Component",
+        "homepage": "http://symfony.com"
     }
 ]
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/CHANGELOG.md b/core/vendor/symfony/process/Symfony/Component/Process/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..2f3c1beb74b7e819608c4f34c36b8122c329eb1f
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/CHANGELOG.md
@@ -0,0 +1,40 @@
+CHANGELOG
+=========
+
+2.5.0
+-----
+
+ * added support for PTY mode
+ * added the convenience method "mustRun"
+ * deprecation: Process::setStdin() is deprecated in favor of Process::setInput()
+ * deprecation: Process::getStdin() is deprecated in favor of Process::getInput()
+ * deprecation: Process::setInput() and ProcessBuilder::setInput() do not accept non-scalar types
+
+2.4.0
+-----
+
+ * added the ability to define an idle timeout
+
+2.3.0
+-----
+
+ * added ProcessUtils::escapeArgument() to fix the bug in escapeshellarg() function on Windows
+ * added Process::signal()
+ * added Process::getPid()
+ * added support for a TTY mode
+
+2.2.0
+-----
+
+ * added ProcessBuilder::setArguments() to reset the arguments on a builder
+ * added a way to retrieve the standard and error output incrementally
+ * added Process:restart()
+
+2.1.0
+-----
+
+ * added support for non-blocking processes (start(), wait(), isRunning(), stop())
+ * enhanced Windows compatibility
+ * added Process::getExitCodeText() that returns a string representation for
+   the exit code returned by the process
+ * added ProcessBuilder
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Exception/ExceptionInterface.php b/core/vendor/symfony/process/Symfony/Component/Process/Exception/ExceptionInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..75c1c9e5d800500d07f2790f21eb45a26439f3cd
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Exception/ExceptionInterface.php
@@ -0,0 +1,21 @@
+<?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\Process\Exception;
+
+/**
+ * Marker Interface for the Process Component.
+ *
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+interface ExceptionInterface
+{
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Exception/InvalidArgumentException.php b/core/vendor/symfony/process/Symfony/Component/Process/Exception/InvalidArgumentException.php
new file mode 100644
index 0000000000000000000000000000000000000000..926ee2118b03703381fabcd80e01bda817c7fa67
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Exception/InvalidArgumentException.php
@@ -0,0 +1,21 @@
+<?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\Process\Exception;
+
+/**
+ * InvalidArgumentException for the Process Component.
+ *
+ * @author Romain Neutron <imprec@gmail.com>
+ */
+class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
+{
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Exception/LogicException.php b/core/vendor/symfony/process/Symfony/Component/Process/Exception/LogicException.php
new file mode 100644
index 0000000000000000000000000000000000000000..be3d490dde8cdea7e594b6e18bc4825a1e2eee13
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Exception/LogicException.php
@@ -0,0 +1,21 @@
+<?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\Process\Exception;
+
+/**
+ * LogicException for the Process Component.
+ *
+ * @author Romain Neutron <imprec@gmail.com>
+ */
+class LogicException extends \LogicException implements ExceptionInterface
+{
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Exception/ProcessFailedException.php b/core/vendor/symfony/process/Symfony/Component/Process/Exception/ProcessFailedException.php
new file mode 100644
index 0000000000000000000000000000000000000000..7523a5e9cd4ea2c16390e0904968777941f3df02
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Exception/ProcessFailedException.php
@@ -0,0 +1,53 @@
+<?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\Process\Exception;
+
+use Symfony\Component\Process\Process;
+
+/**
+ * Exception for failed processes.
+ *
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+class ProcessFailedException extends RuntimeException
+{
+    private $process;
+
+    public function __construct(Process $process)
+    {
+        if ($process->isSuccessful()) {
+            throw new InvalidArgumentException('Expected a failed process, but the given process was successful.');
+        }
+
+        $error = sprintf('The command "%s" failed.'."\nExit Code: %s(%s)",
+            $process->getCommandLine(),
+            $process->getExitCode(),
+            $process->getExitCodeText()
+        );
+
+        if (!$process->isOutputDisabled()) {
+            $error .= sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s",
+                $process->getOutput(),
+                $process->getErrorOutput()
+            );
+        }
+
+        parent::__construct($error);
+
+        $this->process = $process;
+    }
+
+    public function getProcess()
+    {
+        return $this->process;
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Exception/ProcessTimedOutException.php b/core/vendor/symfony/process/Symfony/Component/Process/Exception/ProcessTimedOutException.php
new file mode 100644
index 0000000000000000000000000000000000000000..d45114696f640d9a05a4eea92ce1fa1b203d2a4a
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Exception/ProcessTimedOutException.php
@@ -0,0 +1,69 @@
+<?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\Process\Exception;
+
+use Symfony\Component\Process\Process;
+
+/**
+ * Exception that is thrown when a process times out.
+ *
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+class ProcessTimedOutException extends RuntimeException
+{
+    const TYPE_GENERAL = 1;
+    const TYPE_IDLE = 2;
+
+    private $process;
+    private $timeoutType;
+
+    public function __construct(Process $process, $timeoutType)
+    {
+        $this->process = $process;
+        $this->timeoutType = $timeoutType;
+
+        parent::__construct(sprintf(
+            'The process "%s" exceeded the timeout of %s seconds.',
+            $process->getCommandLine(),
+            $this->getExceededTimeout()
+        ));
+    }
+
+    public function getProcess()
+    {
+        return $this->process;
+    }
+
+    public function isGeneralTimeout()
+    {
+        return $this->timeoutType === self::TYPE_GENERAL;
+    }
+
+    public function isIdleTimeout()
+    {
+        return $this->timeoutType === self::TYPE_IDLE;
+    }
+
+    public function getExceededTimeout()
+    {
+        switch ($this->timeoutType) {
+            case self::TYPE_GENERAL:
+                return $this->process->getTimeout();
+
+            case self::TYPE_IDLE:
+                return $this->process->getIdleTimeout();
+
+            default:
+                throw new \LogicException(sprintf('Unknown timeout type "%d".', $this->timeoutType));
+        }
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Exception/RuntimeException.php b/core/vendor/symfony/process/Symfony/Component/Process/Exception/RuntimeException.php
new file mode 100644
index 0000000000000000000000000000000000000000..adead2536b10362f3e2c499612ce0ffeea3f6a49
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Exception/RuntimeException.php
@@ -0,0 +1,21 @@
+<?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\Process\Exception;
+
+/**
+ * RuntimeException for the Process Component.
+ *
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+class RuntimeException extends \RuntimeException implements ExceptionInterface
+{
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/ExecutableFinder.php b/core/vendor/symfony/process/Symfony/Component/Process/ExecutableFinder.php
new file mode 100644
index 0000000000000000000000000000000000000000..6ae74dca174b9bdb75c7edb54c69d8644f6c32a5
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/ExecutableFinder.php
@@ -0,0 +1,89 @@
+<?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\Process;
+
+/**
+ * Generic executable finder.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+class ExecutableFinder
+{
+    private $suffixes = array('.exe', '.bat', '.cmd', '.com');
+
+    /**
+     * Replaces default suffixes of executable.
+     *
+     * @param array $suffixes
+     */
+    public function setSuffixes(array $suffixes)
+    {
+        $this->suffixes = $suffixes;
+    }
+
+    /**
+     * Adds new possible suffix to check for executable.
+     *
+     * @param string $suffix
+     */
+    public function addSuffix($suffix)
+    {
+        $this->suffixes[] = $suffix;
+    }
+
+    /**
+     * Finds an executable by name.
+     *
+     * @param string $name      The executable name (without the extension)
+     * @param string $default   The default to return if no executable is found
+     * @param array  $extraDirs Additional dirs to check into
+     *
+     * @return string The executable path or default value
+     */
+    public function find($name, $default = null, array $extraDirs = array())
+    {
+        if (ini_get('open_basedir')) {
+            $searchPath = explode(PATH_SEPARATOR, ini_get('open_basedir'));
+            $dirs = array();
+            foreach ($searchPath as $path) {
+                if (is_dir($path)) {
+                    $dirs[] = $path;
+                } else {
+                    if (basename($path) == $name && is_executable($path)) {
+                        return $path;
+                    }
+                }
+            }
+        } else {
+            $dirs = array_merge(
+                explode(PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')),
+                $extraDirs
+            );
+        }
+
+        $suffixes = array('');
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $pathExt = getenv('PATHEXT');
+            $suffixes = $pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes;
+        }
+        foreach ($suffixes as $suffix) {
+            foreach ($dirs as $dir) {
+                if (is_file($file = $dir.DIRECTORY_SEPARATOR.$name.$suffix) && (defined('PHP_WINDOWS_VERSION_BUILD') || is_executable($file))) {
+                    return $file;
+                }
+            }
+        }
+
+        return $default;
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/LICENSE b/core/vendor/symfony/process/Symfony/Component/Process/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..0b3292cf9023507c2f1f93ddfee7dd8e15838048
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2004-2014 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.
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/PhpExecutableFinder.php b/core/vendor/symfony/process/Symfony/Component/Process/PhpExecutableFinder.php
new file mode 100644
index 0000000000000000000000000000000000000000..7854487a26b23ebaa1baf96e6660a4f7c4136d33
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/PhpExecutableFinder.php
@@ -0,0 +1,86 @@
+<?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\Process;
+
+/**
+ * An executable finder specifically designed for the PHP executable.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+class PhpExecutableFinder
+{
+    private $executableFinder;
+
+    public function __construct()
+    {
+        $this->executableFinder = new ExecutableFinder();
+    }
+
+    /**
+     * Finds The PHP executable.
+     *
+     * @param bool $includeArgs Whether or not include command arguments
+     *
+     * @return string|false The PHP executable path or false if it cannot be found
+     */
+    public function find($includeArgs = true)
+    {
+        // HHVM support
+        if (defined('HHVM_VERSION')) {
+            return (false !== ($hhvm = getenv('PHP_BINARY')) ? $hhvm : PHP_BINARY).($includeArgs ? ' '.implode(' ', $this->findArguments()) : '');
+        }
+
+        // PHP_BINARY return the current sapi executable
+        if (defined('PHP_BINARY') && PHP_BINARY && in_array(PHP_SAPI, array('cli', 'cli-server')) && is_file(PHP_BINARY)) {
+            return PHP_BINARY;
+        }
+
+        if ($php = getenv('PHP_PATH')) {
+            if (!is_executable($php)) {
+                return false;
+            }
+
+            return $php;
+        }
+
+        if ($php = getenv('PHP_PEAR_PHP_BIN')) {
+            if (is_executable($php)) {
+                return $php;
+            }
+        }
+
+        $dirs = array(PHP_BINDIR);
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $dirs[] = 'C:\xampp\php\\';
+        }
+
+        return $this->executableFinder->find('php', false, $dirs);
+    }
+
+    /**
+     * Finds the PHP executable arguments.
+     *
+     * @return array The PHP executable arguments
+     */
+    public function findArguments()
+    {
+        $arguments = array();
+
+        // HHVM support
+        if (defined('HHVM_VERSION')) {
+            $arguments[] = '--php';
+        }
+
+        return $arguments;
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/PhpProcess.php b/core/vendor/symfony/process/Symfony/Component/Process/PhpProcess.php
new file mode 100644
index 0000000000000000000000000000000000000000..bc25154a8ed2decab6ace8d3bcf02f8eafaa7cc9
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/PhpProcess.php
@@ -0,0 +1,73 @@
+<?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\Process;
+
+use Symfony\Component\Process\Exception\RuntimeException;
+
+/**
+ * PhpProcess runs a PHP script in an independent process.
+ *
+ * $p = new PhpProcess('<?php echo "foo"; ?>');
+ * $p->run();
+ * print $p->getOutput()."\n";
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class PhpProcess extends Process
+{
+    private $executableFinder;
+
+    /**
+     * Constructor.
+     *
+     * @param string $script  The PHP script to run (as a string)
+     * @param string $cwd     The working directory
+     * @param array  $env     The environment variables
+     * @param int    $timeout The timeout in seconds
+     * @param array  $options An array of options for proc_open
+     *
+     * @api
+     */
+    public function __construct($script, $cwd = null, array $env = array(), $timeout = 60, array $options = array())
+    {
+        parent::__construct(null, $cwd, $env, $script, $timeout, $options);
+
+        $this->executableFinder = new PhpExecutableFinder();
+    }
+
+    /**
+     * Sets the path to the PHP binary to use.
+     *
+     * @api
+     */
+    public function setPhpBinary($php)
+    {
+        $this->setCommandLine($php);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function start($callback = null)
+    {
+        if (null === $this->getCommandLine()) {
+            if (false === $php = $this->executableFinder->find()) {
+                throw new RuntimeException('Unable to find the PHP executable.');
+            }
+            $this->setCommandLine($php);
+        }
+
+        parent::start($callback);
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Pipes/AbstractPipes.php b/core/vendor/symfony/process/Symfony/Component/Process/Pipes/AbstractPipes.php
new file mode 100644
index 0000000000000000000000000000000000000000..d8b57d07a778ad71fa35c0e2bbbc9b3e39cf9691
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Pipes/AbstractPipes.php
@@ -0,0 +1,74 @@
+<?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\Process\Pipes;
+
+/**
+ * @author Romain Neutron <imprec@gmail.com>
+ *
+ * @internal
+ */
+abstract class AbstractPipes implements PipesInterface
+{
+    /** @var array */
+    public $pipes = array();
+
+    /** @var string */
+    protected $inputBuffer = '';
+    /** @var resource|null */
+    protected $input;
+
+    /** @var bool */
+    private $blocked = true;
+
+    /**
+     * {@inheritdoc}
+     */
+    public function close()
+    {
+        foreach ($this->pipes as $pipe) {
+            fclose($pipe);
+        }
+        $this->pipes = array();
+    }
+
+    /**
+     * Returns true if a system call has been interrupted.
+     *
+     * @return bool
+     */
+    protected function hasSystemCallBeenInterrupted()
+    {
+        $lastError = error_get_last();
+
+        // stream_select returns false when the `select` system call is interrupted by an incoming signal
+        return isset($lastError['message']) && false !== stripos($lastError['message'], 'interrupted system call');
+    }
+
+    /**
+     * Unblocks streams
+     */
+    protected function unblock()
+    {
+        if (!$this->blocked) {
+            return;
+        }
+
+        foreach ($this->pipes as $pipe) {
+            stream_set_blocking($pipe, 0);
+        }
+        if (null !== $this->input) {
+            stream_set_blocking($this->input, 0);
+        }
+
+        $this->blocked = false;
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Pipes/PipesInterface.php b/core/vendor/symfony/process/Symfony/Component/Process/Pipes/PipesInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..09d3f61d6ec940b37262cac97f2888d8117639b1
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Pipes/PipesInterface.php
@@ -0,0 +1,60 @@
+<?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\Process\Pipes;
+
+/**
+ * PipesInterface manages descriptors and pipes for the use of proc_open.
+ *
+ * @author Romain Neutron <imprec@gmail.com>
+ *
+ * @internal
+ */
+interface PipesInterface
+{
+    const CHUNK_SIZE = 16384;
+
+    /**
+     * Returns an array of descriptors for the use of proc_open.
+     *
+     * @return array
+     */
+    public function getDescriptors();
+
+    /**
+     * Returns an array of filenames indexed by their related stream in case these pipes use temporary files.
+     *
+     * @return string[]
+     */
+    public function getFiles();
+
+    /**
+     * Reads data in file handles and pipes.
+     *
+     * @param bool $blocking Whether to use blocking calls or not.
+     * @param bool $close    Whether to close pipes if they've reached EOF.
+     *
+     * @return string[] An array of read data indexed by their fd.
+     */
+    public function readAndWrite($blocking, $close = false);
+
+    /**
+     * Returns if the current state has open file handles or pipes.
+     *
+     * @return bool
+     */
+    public function areOpen();
+
+    /**
+     * Closes file handles and pipes.
+     */
+    public function close();
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Pipes/UnixPipes.php b/core/vendor/symfony/process/Symfony/Component/Process/Pipes/UnixPipes.php
new file mode 100644
index 0000000000000000000000000000000000000000..69f31467a03cc3b09ff06a02c630e7c1ef84f90d
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Pipes/UnixPipes.php
@@ -0,0 +1,214 @@
+<?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\Process\Pipes;
+
+use Symfony\Component\Process\Process;
+
+/**
+ * UnixPipes implementation uses unix pipes as handles.
+ *
+ * @author Romain Neutron <imprec@gmail.com>
+ *
+ * @internal
+ */
+class UnixPipes extends AbstractPipes
+{
+    /** @var bool */
+    private $ttyMode;
+    /** @var bool */
+    private $ptyMode;
+    /** @var bool */
+    private $disableOutput;
+
+    public function __construct($ttyMode, $ptyMode, $input, $disableOutput)
+    {
+        $this->ttyMode = (bool) $ttyMode;
+        $this->ptyMode = (bool) $ptyMode;
+        $this->disableOutput = (bool) $disableOutput;
+
+        if (is_resource($input)) {
+            $this->input = $input;
+        } else {
+            $this->inputBuffer = (string) $input;
+        }
+    }
+
+    public function __destruct()
+    {
+        $this->close();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getDescriptors()
+    {
+        if ($this->disableOutput) {
+            $nullstream = fopen('/dev/null', 'c');
+
+            return array(
+                array('pipe', 'r'),
+                $nullstream,
+                $nullstream,
+            );
+        }
+
+        if ($this->ttyMode) {
+            return array(
+                array('file', '/dev/tty', 'r'),
+                array('file', '/dev/tty', 'w'),
+                array('file', '/dev/tty', 'w'),
+            );
+        }
+
+        if ($this->ptyMode && Process::isPtySupported()) {
+            return array(
+                array('pty'),
+                array('pty'),
+                array('pty'),
+            );
+        }
+
+        return array(
+            array('pipe', 'r'),
+            array('pipe', 'w'), // stdout
+            array('pipe', 'w'), // stderr
+        );
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getFiles()
+    {
+        return array();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function readAndWrite($blocking, $close = false)
+    {
+        // only stdin is left open, job has been done !
+        // we can now close it
+        if (1 === count($this->pipes) && array(0) === array_keys($this->pipes)) {
+            fclose($this->pipes[0]);
+            unset($this->pipes[0]);
+        }
+
+        if (empty($this->pipes)) {
+            return array();
+        }
+
+        $this->unblock();
+
+        $read = array();
+
+        if (null !== $this->input) {
+            // if input is a resource, let's add it to stream_select argument to
+            // fill a buffer
+            $r = array_merge($this->pipes, array('input' => $this->input));
+        } else {
+            $r = $this->pipes;
+        }
+        // discard read on stdin
+        unset ($r[0]);
+
+        $w = isset($this->pipes[0]) ? array($this->pipes[0]) : null;
+        $e = null;
+
+        // let's have a look if something changed in streams
+        if (false === $n = @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
+            // if a system call has been interrupted, forget about it, let's try again
+            // otherwise, an error occurred, let's reset pipes
+            if (!$this->hasSystemCallBeenInterrupted()) {
+                $this->pipes = array();
+            }
+
+            return $read;
+        }
+
+        // nothing has changed
+        if (0 === $n) {
+            return $read;
+        }
+
+        foreach ($r as $pipe) {
+            // prior PHP 5.4 the array passed to stream_select is modified and
+            // lose key association, we have to find back the key
+            $type = (false !== $found = array_search($pipe, $this->pipes)) ? $found : 'input';
+            $data = '';
+            while ('' !== $dataread = (string) fread($pipe, self::CHUNK_SIZE)) {
+                $data .= $dataread;
+            }
+
+            if ('' !== $data) {
+                if ($type === 'input') {
+                    $this->inputBuffer .= $data;
+                } else {
+                    $read[$type] = $data;
+                }
+            }
+
+            if (false === $data || (true === $close && feof($pipe) && '' === $data)) {
+                if ($type === 'input') {
+                    // no more data to read on input resource
+                    // use an empty buffer in the next reads
+                    $this->input = null;
+                } else {
+                    fclose($this->pipes[$type]);
+                    unset($this->pipes[$type]);
+                }
+            }
+        }
+
+        if (null !== $w && 0 < count($w)) {
+            while ($len = strlen($this->inputBuffer)) {
+                $written = fwrite($w[0], $this->inputBuffer, 2 << 18); // write 512k
+                if ($written > 0) {
+                    $this->inputBuffer = (string) substr($this->inputBuffer, $written);
+                } else {
+                    break;
+                }
+            }
+        }
+
+        // no input to read on resource, buffer is empty and stdin still open
+        if ('' === $this->inputBuffer && null === $this->input && isset($this->pipes[0])) {
+            fclose($this->pipes[0]);
+            unset($this->pipes[0]);
+        }
+
+        return $read;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function areOpen()
+    {
+        return (bool) $this->pipes;
+    }
+
+    /**
+     * Creates a new UnixPipes instance
+     *
+     * @param Process         $process
+     * @param string|resource $input
+     *
+     * @return UnixPipes
+     */
+    public static function create(Process $process, $input)
+    {
+        return new static($process->isTty(), $process->isPty(), $input, $process->isOutputDisabled());
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Pipes/WindowsPipes.php b/core/vendor/symfony/process/Symfony/Component/Process/Pipes/WindowsPipes.php
new file mode 100644
index 0000000000000000000000000000000000000000..ecdf50eee2a721f2a9a5fcd33af3441444577d7f
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Pipes/WindowsPipes.php
@@ -0,0 +1,254 @@
+<?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\Process\Pipes;
+
+use Symfony\Component\Process\Process;
+use Symfony\Component\Process\Exception\RuntimeException;
+
+/**
+ * WindowsPipes implementation uses temporary files as handles.
+ *
+ * @see https://bugs.php.net/bug.php?id=51800
+ * @see https://bugs.php.net/bug.php?id=65650
+ *
+ * @author Romain Neutron <imprec@gmail.com>
+ *
+ * @internal
+ */
+class WindowsPipes extends AbstractPipes
+{
+    /** @var array */
+    private $files = array();
+    /** @var array */
+    private $fileHandles = array();
+    /** @var array */
+    private $readBytes = array(
+        Process::STDOUT => 0,
+        Process::STDERR => 0,
+    );
+    /** @var bool */
+    private $disableOutput;
+
+    public function __construct($disableOutput, $input)
+    {
+        $this->disableOutput = (bool) $disableOutput;
+
+        if (!$this->disableOutput) {
+            // Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big.
+            // Workaround for this problem is to use temporary files instead of pipes on Windows platform.
+            //
+            // @see https://bugs.php.net/bug.php?id=51800
+            $this->files = array(
+                Process::STDOUT => tempnam(sys_get_temp_dir(), 'sf_proc_stdout'),
+                Process::STDERR => tempnam(sys_get_temp_dir(), 'sf_proc_stderr'),
+            );
+            foreach ($this->files as $offset => $file) {
+                $this->fileHandles[$offset] = fopen($this->files[$offset], 'rb');
+                if (false === $this->fileHandles[$offset]) {
+                    throw new RuntimeException('A temporary file could not be opened to write the process output to, verify that your TEMP environment variable is writable');
+                }
+            }
+        }
+
+        if (is_resource($input)) {
+            $this->input = $input;
+        } else {
+            $this->inputBuffer = $input;
+        }
+    }
+
+    public function __destruct()
+    {
+        $this->close();
+        $this->removeFiles();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getDescriptors()
+    {
+        if ($this->disableOutput) {
+            $nullstream = fopen('NUL', 'c');
+
+            return array(
+                array('pipe', 'r'),
+                $nullstream,
+                $nullstream,
+            );
+        }
+
+        // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/bug.php?id=51800)
+        // We're not using file handles as it can produce corrupted output https://bugs.php.net/bug.php?id=65650
+        // So we redirect output within the commandline and pass the nul device to the process
+        return array(
+            array('pipe', 'r'),
+            array('file', 'NUL', 'w'),
+            array('file', 'NUL', 'w'),
+        );
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getFiles()
+    {
+        return $this->files;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function readAndWrite($blocking, $close = false)
+    {
+        $this->write($blocking, $close);
+
+        $read = array();
+        $fh = $this->fileHandles;
+        foreach ($fh as $type => $fileHandle) {
+            if (0 !== fseek($fileHandle, $this->readBytes[$type])) {
+                continue;
+            }
+            $data = '';
+            $dataread = null;
+            while (!feof($fileHandle)) {
+                if (false !== $dataread = fread($fileHandle, self::CHUNK_SIZE)) {
+                    $data .= $dataread;
+                }
+            }
+            if (0 < $length = strlen($data)) {
+                $this->readBytes[$type] += $length;
+                $read[$type] = $data;
+            }
+
+            if (false === $dataread || (true === $close && feof($fileHandle) && '' === $data)) {
+                fclose($this->fileHandles[$type]);
+                unset($this->fileHandles[$type]);
+            }
+        }
+
+        return $read;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function areOpen()
+    {
+        return (bool) $this->pipes && (bool) $this->fileHandles;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function close()
+    {
+        parent::close();
+        foreach ($this->fileHandles as $handle) {
+            fclose($handle);
+        }
+        $this->fileHandles = array();
+    }
+
+    /**
+     * Creates a new WindowsPipes instance.
+     *
+     * @param Process $process The process
+     * @param $input
+     *
+     * @return WindowsPipes
+     */
+    public static function create(Process $process, $input)
+    {
+        return new static($process->isOutputDisabled(), $input);
+    }
+
+    /**
+     * Removes temporary files
+     */
+    private function removeFiles()
+    {
+        foreach ($this->files as $filename) {
+            if (file_exists($filename)) {
+                @unlink($filename);
+            }
+        }
+        $this->files = array();
+    }
+
+    /**
+     * Writes input to stdin
+     *
+     * @param bool $blocking
+     * @param bool $close
+     */
+    private function write($blocking, $close)
+    {
+        if (empty($this->pipes)) {
+            return;
+        }
+
+        $this->unblock();
+
+        $r = null !== $this->input ? array('input' => $this->input) : null;
+        $w = isset($this->pipes[0]) ? array($this->pipes[0]) : null;
+        $e = null;
+
+        // let's have a look if something changed in streams
+        if (false === $n = @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
+            // if a system call has been interrupted, forget about it, let's try again
+            // otherwise, an error occurred, let's reset pipes
+            if (!$this->hasSystemCallBeenInterrupted()) {
+                $this->pipes = array();
+            }
+
+            return;
+        }
+
+        // nothing has changed
+        if (0 === $n) {
+            return;
+        }
+
+        if (null !== $w && 0 < count($r)) {
+            $data = '';
+            while ($dataread = fread($r['input'], self::CHUNK_SIZE)) {
+                $data .= $dataread;
+            }
+
+            $this->inputBuffer .= $data;
+
+            if (false === $data || (true === $close && feof($r['input']) && '' === $data)) {
+                // no more data to read on input resource
+                // use an empty buffer in the next reads
+                unset($this->input);
+            }
+        }
+
+        if (null !== $w && 0 < count($w)) {
+            while ($len = strlen($this->inputBuffer)) {
+                $written = fwrite($w[0], $this->inputBuffer, 2 << 18);
+                if ($written > 0) {
+                    $this->inputBuffer = (string) substr($this->inputBuffer, $written);
+                } else {
+                    break;
+                }
+            }
+        }
+
+        // no input to read on resource, buffer is empty and stdin still open
+        if ('' === $this->inputBuffer && null === $this->input && isset($this->pipes[0])) {
+            fclose($this->pipes[0]);
+            unset($this->pipes[0]);
+        }
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Process.php b/core/vendor/symfony/process/Symfony/Component/Process/Process.php
new file mode 100644
index 0000000000000000000000000000000000000000..b91bc5dea78479da407da52d15bf0c0d36a01782
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Process.php
@@ -0,0 +1,1508 @@
+<?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\Process;
+
+use Symfony\Component\Process\Exception\InvalidArgumentException;
+use Symfony\Component\Process\Exception\LogicException;
+use Symfony\Component\Process\Exception\ProcessFailedException;
+use Symfony\Component\Process\Exception\ProcessTimedOutException;
+use Symfony\Component\Process\Exception\RuntimeException;
+use Symfony\Component\Process\Pipes\PipesInterface;
+use Symfony\Component\Process\Pipes\UnixPipes;
+use Symfony\Component\Process\Pipes\WindowsPipes;
+
+/**
+ * Process is a thin wrapper around proc_* functions to easily
+ * start independent PHP processes.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Romain Neutron <imprec@gmail.com>
+ *
+ * @api
+ */
+class Process
+{
+    const ERR = 'err';
+    const OUT = 'out';
+
+    const STATUS_READY = 'ready';
+    const STATUS_STARTED = 'started';
+    const STATUS_TERMINATED = 'terminated';
+
+    const STDIN = 0;
+    const STDOUT = 1;
+    const STDERR = 2;
+
+    // Timeout Precision in seconds.
+    const TIMEOUT_PRECISION = 0.2;
+
+    private $callback;
+    private $commandline;
+    private $cwd;
+    private $env;
+    private $input;
+    private $starttime;
+    private $lastOutputTime;
+    private $timeout;
+    private $idleTimeout;
+    private $options;
+    private $exitcode;
+    private $fallbackExitcode;
+    private $processInformation;
+    private $outputDisabled = false;
+    private $stdout;
+    private $stderr;
+    private $enhanceWindowsCompatibility = true;
+    private $enhanceSigchildCompatibility;
+    private $process;
+    private $status = self::STATUS_READY;
+    private $incrementalOutputOffset = 0;
+    private $incrementalErrorOutputOffset = 0;
+    private $tty;
+    private $pty;
+
+    private $useFileHandles = false;
+    /** @var PipesInterface */
+    private $processPipes;
+
+    private $latestSignal;
+
+    private static $sigchild;
+
+    /**
+     * Exit codes translation table.
+     *
+     * User-defined errors must use exit codes in the 64-113 range.
+     *
+     * @var array
+     */
+    public static $exitCodes = array(
+        0 => 'OK',
+        1 => 'General error',
+        2 => 'Misuse of shell builtins',
+
+        126 => 'Invoked command cannot execute',
+        127 => 'Command not found',
+        128 => 'Invalid exit argument',
+
+        // signals
+        129 => 'Hangup',
+        130 => 'Interrupt',
+        131 => 'Quit and dump core',
+        132 => 'Illegal instruction',
+        133 => 'Trace/breakpoint trap',
+        134 => 'Process aborted',
+        135 => 'Bus error: "access to undefined portion of memory object"',
+        136 => 'Floating point exception: "erroneous arithmetic operation"',
+        137 => 'Kill (terminate immediately)',
+        138 => 'User-defined 1',
+        139 => 'Segmentation violation',
+        140 => 'User-defined 2',
+        141 => 'Write to pipe with no one reading',
+        142 => 'Signal raised by alarm',
+        143 => 'Termination (request to terminate)',
+        // 144 - not defined
+        145 => 'Child process terminated, stopped (or continued*)',
+        146 => 'Continue if stopped',
+        147 => 'Stop executing temporarily',
+        148 => 'Terminal stop signal',
+        149 => 'Background process attempting to read from tty ("in")',
+        150 => 'Background process attempting to write to tty ("out")',
+        151 => 'Urgent data available on socket',
+        152 => 'CPU time limit exceeded',
+        153 => 'File size limit exceeded',
+        154 => 'Signal raised by timer counting virtual time: "virtual timer expired"',
+        155 => 'Profiling timer expired',
+        // 156 - not defined
+        157 => 'Pollable event',
+        // 158 - not defined
+        159 => 'Bad syscall',
+    );
+
+    /**
+     * Constructor.
+     *
+     * @param string         $commandline The command line to run
+     * @param string|null    $cwd         The working directory or null to use the working dir of the current PHP process
+     * @param array|null     $env         The environment variables or null to inherit
+     * @param string|null    $input       The input
+     * @param int|float|null $timeout     The timeout in seconds or null to disable
+     * @param array          $options     An array of options for proc_open
+     *
+     * @throws RuntimeException When proc_open is not installed
+     *
+     * @api
+     */
+    public function __construct($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = array())
+    {
+        if (!function_exists('proc_open')) {
+            throw new RuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.');
+        }
+
+        $this->commandline = $commandline;
+        $this->cwd = $cwd;
+
+        // on Windows, if the cwd changed via chdir(), proc_open defaults to the dir where PHP was started
+        // on Gnu/Linux, PHP builds with --enable-maintainer-zts are also affected
+        // @see : https://bugs.php.net/bug.php?id=51800
+        // @see : https://bugs.php.net/bug.php?id=50524
+        if (null === $this->cwd && (defined('ZEND_THREAD_SAFE') || defined('PHP_WINDOWS_VERSION_BUILD'))) {
+            $this->cwd = getcwd();
+        }
+        if (null !== $env) {
+            $this->setEnv($env);
+        }
+
+        $this->input = $input;
+        $this->setTimeout($timeout);
+        $this->useFileHandles = defined('PHP_WINDOWS_VERSION_BUILD');
+        $this->pty = false;
+        $this->enhanceWindowsCompatibility = true;
+        $this->enhanceSigchildCompatibility = !defined('PHP_WINDOWS_VERSION_BUILD') && $this->isSigchildEnabled();
+        $this->options = array_replace(array('suppress_errors' => true, 'binary_pipes' => true), $options);
+    }
+
+    public function __destruct()
+    {
+        // stop() will check if we have a process running.
+        $this->stop();
+    }
+
+    public function __clone()
+    {
+        $this->resetProcessData();
+    }
+
+    /**
+     * Runs the process.
+     *
+     * The callback receives the type of output (out or err) and
+     * some bytes from the output in real-time. It allows to have feedback
+     * from the independent process during execution.
+     *
+     * The STDOUT and STDERR are also available after the process is finished
+     * via the getOutput() and getErrorOutput() methods.
+     *
+     * @param callable|null $callback A PHP callback to run whenever there is some
+     *                                output available on STDOUT or STDERR
+     *
+     * @return int The exit status code
+     *
+     * @throws RuntimeException When process can't be launched
+     * @throws RuntimeException When process stopped after receiving signal
+     * @throws LogicException   In case a callback is provided and output has been disabled
+     *
+     * @api
+     */
+    public function run($callback = null)
+    {
+        $this->start($callback);
+
+        return $this->wait();
+    }
+
+    /**
+     * Runs the process.
+     *
+     * This is identical to run() except that an exception is thrown if the process
+     * exits with a non-zero exit code.
+     *
+     * @param callable|null $callback
+     *
+     * @return self
+     *
+     * @throws RuntimeException       if PHP was compiled with --enable-sigchild and the enhanced sigchild compatibility mode is not enabled
+     * @throws ProcessFailedException if the process didn't terminate successfully
+     */
+    public function mustRun($callback = null)
+    {
+        if ($this->isSigchildEnabled() && !$this->enhanceSigchildCompatibility) {
+            throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
+        }
+
+        if (0 !== $this->run($callback)) {
+            throw new ProcessFailedException($this);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Starts the process and returns after writing the input to STDIN.
+     *
+     * This method blocks until all STDIN data is sent to the process then it
+     * returns while the process runs in the background.
+     *
+     * The termination of the process can be awaited with wait().
+     *
+     * The callback receives the type of output (out or err) and some bytes from
+     * the output in real-time while writing the standard input to the process.
+     * It allows to have feedback from the independent process during execution.
+     * If there is no callback passed, the wait() method can be called
+     * with true as a second parameter then the callback will get all data occurred
+     * in (and since) the start call.
+     *
+     * @param callable|null $callback A PHP callback to run whenever there is some
+     *                                output available on STDOUT or STDERR
+     *
+     * @return Process The process itself
+     *
+     * @throws RuntimeException When process can't be launched
+     * @throws RuntimeException When process is already running
+     * @throws LogicException   In case a callback is provided and output has been disabled
+     */
+    public function start($callback = null)
+    {
+        if ($this->isRunning()) {
+            throw new RuntimeException('Process is already running');
+        }
+        if ($this->outputDisabled && null !== $callback) {
+            throw new LogicException('Output has been disabled, enable it to allow the use of a callback.');
+        }
+
+        $this->resetProcessData();
+        $this->starttime = $this->lastOutputTime = microtime(true);
+        $this->callback = $this->buildCallback($callback);
+        $descriptors = $this->getDescriptors();
+
+        $commandline = $this->commandline;
+
+        if (defined('PHP_WINDOWS_VERSION_BUILD') && $this->enhanceWindowsCompatibility) {
+            $commandline = 'cmd /V:ON /E:ON /C "('.$commandline.')';
+            foreach ($this->processPipes->getFiles() as $offset => $filename) {
+                $commandline .= ' '.$offset.'>'.ProcessUtils::escapeArgument($filename);
+            }
+            $commandline .= '"';
+
+            if (!isset($this->options['bypass_shell'])) {
+                $this->options['bypass_shell'] = true;
+            }
+        }
+
+        $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $this->env, $this->options);
+
+        if (!is_resource($this->process)) {
+            throw new RuntimeException('Unable to launch a new process.');
+        }
+        $this->status = self::STATUS_STARTED;
+
+        if ($this->tty) {
+            return;
+        }
+
+        $this->updateStatus(false);
+        $this->checkTimeout();
+    }
+
+    /**
+     * Restarts the process.
+     *
+     * Be warned that the process is cloned before being started.
+     *
+     * @param callable|null $callback A PHP callback to run whenever there is some
+     *                                output available on STDOUT or STDERR
+     *
+     * @return Process The new process
+     *
+     * @throws RuntimeException When process can't be launched
+     * @throws RuntimeException When process is already running
+     *
+     * @see start()
+     */
+    public function restart($callback = null)
+    {
+        if ($this->isRunning()) {
+            throw new RuntimeException('Process is already running');
+        }
+
+        $process = clone $this;
+        $process->start($callback);
+
+        return $process;
+    }
+
+    /**
+     * Waits for the process to terminate.
+     *
+     * The callback receives the type of output (out or err) and some bytes
+     * from the output in real-time while writing the standard input to the process.
+     * It allows to have feedback from the independent process during execution.
+     *
+     * @param callable|null $callback A valid PHP callback
+     *
+     * @return int The exitcode of the process
+     *
+     * @throws RuntimeException When process timed out
+     * @throws RuntimeException When process stopped after receiving signal
+     * @throws LogicException   When process is not yet started
+     */
+    public function wait($callback = null)
+    {
+        $this->requireProcessIsStarted(__FUNCTION__);
+
+        $this->updateStatus(false);
+        if (null !== $callback) {
+            $this->callback = $this->buildCallback($callback);
+        }
+
+        do {
+            $this->checkTimeout();
+            $running = defined('PHP_WINDOWS_VERSION_BUILD') ? $this->isRunning() : $this->processPipes->areOpen();
+            $close = !defined('PHP_WINDOWS_VERSION_BUILD') || !$running;
+            $this->readPipes(true, $close);
+        } while ($running);
+
+        while ($this->isRunning()) {
+            usleep(1000);
+        }
+
+        if ($this->processInformation['signaled'] && $this->processInformation['termsig'] !== $this->latestSignal) {
+            throw new RuntimeException(sprintf('The process has been signaled with signal "%s".', $this->processInformation['termsig']));
+        }
+
+        return $this->exitcode;
+    }
+
+    /**
+     * Returns the Pid (process identifier), if applicable.
+     *
+     * @return int|null The process id if running, null otherwise
+     *
+     * @throws RuntimeException In case --enable-sigchild is activated
+     */
+    public function getPid()
+    {
+        if ($this->isSigchildEnabled()) {
+            throw new RuntimeException('This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved.');
+        }
+
+        $this->updateStatus(false);
+
+        return $this->isRunning() ? $this->processInformation['pid'] : null;
+    }
+
+    /**
+     * Sends a POSIX signal to the process.
+     *
+     * @param int $signal A valid POSIX signal (see http://www.php.net/manual/en/pcntl.constants.php)
+     *
+     * @return Process
+     *
+     * @throws LogicException   In case the process is not running
+     * @throws RuntimeException In case --enable-sigchild is activated
+     * @throws RuntimeException In case of failure
+     */
+    public function signal($signal)
+    {
+        $this->doSignal($signal, true);
+
+        return $this;
+    }
+
+    /**
+     * Disables fetching output and error output from the underlying process.
+     *
+     * @return Process
+     *
+     * @throws RuntimeException In case the process is already running
+     * @throws LogicException   if an idle timeout is set
+     */
+    public function disableOutput()
+    {
+        if ($this->isRunning()) {
+            throw new RuntimeException('Disabling output while the process is running is not possible.');
+        }
+        if (null !== $this->idleTimeout) {
+            throw new LogicException('Output can not be disabled while an idle timeout is set.');
+        }
+
+        $this->outputDisabled = true;
+
+        return $this;
+    }
+
+    /**
+     * Enables fetching output and error output from the underlying process.
+     *
+     * @return Process
+     *
+     * @throws RuntimeException In case the process is already running
+     */
+    public function enableOutput()
+    {
+        if ($this->isRunning()) {
+            throw new RuntimeException('Enabling output while the process is running is not possible.');
+        }
+
+        $this->outputDisabled = false;
+
+        return $this;
+    }
+
+    /**
+     * Returns true in case the output is disabled, false otherwise.
+     *
+     * @return bool
+     */
+    public function isOutputDisabled()
+    {
+        return $this->outputDisabled;
+    }
+
+    /**
+     * Returns the current output of the process (STDOUT).
+     *
+     * @return string The process output
+     *
+     * @throws LogicException in case the output has been disabled
+     * @throws LogicException In case the process is not started
+     *
+     * @api
+     */
+    public function getOutput()
+    {
+        if ($this->outputDisabled) {
+            throw new LogicException('Output has been disabled.');
+        }
+
+        $this->requireProcessIsStarted(__FUNCTION__);
+
+        $this->readPipes(false, defined('PHP_WINDOWS_VERSION_BUILD') ? !$this->processInformation['running'] : true);
+
+        return $this->stdout;
+    }
+
+    /**
+     * Returns the output incrementally.
+     *
+     * In comparison with the getOutput method which always return the whole
+     * output, this one returns the new output since the last call.
+     *
+     * @throws LogicException in case the output has been disabled
+     * @throws LogicException In case the process is not started
+     *
+     * @return string The process output since the last call
+     */
+    public function getIncrementalOutput()
+    {
+        $this->requireProcessIsStarted(__FUNCTION__);
+
+        $data = $this->getOutput();
+
+        $latest = substr($data, $this->incrementalOutputOffset);
+        $this->incrementalOutputOffset = strlen($data);
+
+        return $latest;
+    }
+
+    /**
+     * Clears the process output.
+     *
+     * @return Process
+     */
+    public function clearOutput()
+    {
+        $this->stdout = '';
+        $this->incrementalOutputOffset = 0;
+
+        return $this;
+    }
+
+    /**
+     * Returns the current error output of the process (STDERR).
+     *
+     * @return string The process error output
+     *
+     * @throws LogicException in case the output has been disabled
+     * @throws LogicException In case the process is not started
+     *
+     * @api
+     */
+    public function getErrorOutput()
+    {
+        if ($this->outputDisabled) {
+            throw new LogicException('Output has been disabled.');
+        }
+
+        $this->requireProcessIsStarted(__FUNCTION__);
+
+        $this->readPipes(false, defined('PHP_WINDOWS_VERSION_BUILD') ? !$this->processInformation['running'] : true);
+
+        return $this->stderr;
+    }
+
+    /**
+     * Returns the errorOutput incrementally.
+     *
+     * In comparison with the getErrorOutput method which always return the
+     * whole error output, this one returns the new error output since the last
+     * call.
+     *
+     * @throws LogicException in case the output has been disabled
+     * @throws LogicException In case the process is not started
+     *
+     * @return string The process error output since the last call
+     */
+    public function getIncrementalErrorOutput()
+    {
+        $this->requireProcessIsStarted(__FUNCTION__);
+
+        $data = $this->getErrorOutput();
+
+        $latest = substr($data, $this->incrementalErrorOutputOffset);
+        $this->incrementalErrorOutputOffset = strlen($data);
+
+        return $latest;
+    }
+
+    /**
+     * Clears the process output.
+     *
+     * @return Process
+     */
+    public function clearErrorOutput()
+    {
+        $this->stderr = '';
+        $this->incrementalErrorOutputOffset = 0;
+
+        return $this;
+    }
+
+    /**
+     * Returns the exit code returned by the process.
+     *
+     * @return null|int The exit status code, null if the Process is not terminated
+     *
+     * @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled
+     *
+     * @api
+     */
+    public function getExitCode()
+    {
+        if ($this->isSigchildEnabled() && !$this->enhanceSigchildCompatibility) {
+            throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
+        }
+
+        $this->updateStatus(false);
+
+        return $this->exitcode;
+    }
+
+    /**
+     * Returns a string representation for the exit code returned by the process.
+     *
+     * This method relies on the Unix exit code status standardization
+     * and might not be relevant for other operating systems.
+     *
+     * @return null|string A string representation for the exit status code, null if the Process is not terminated.
+     *
+     * @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled
+     *
+     * @see http://tldp.org/LDP/abs/html/exitcodes.html
+     * @see http://en.wikipedia.org/wiki/Unix_signal
+     */
+    public function getExitCodeText()
+    {
+        if (null === $exitcode = $this->getExitCode()) {
+            return;
+        }
+
+        return isset(self::$exitCodes[$exitcode]) ? self::$exitCodes[$exitcode] : 'Unknown error';
+    }
+
+    /**
+     * Checks if the process ended successfully.
+     *
+     * @return bool true if the process ended successfully, false otherwise
+     *
+     * @api
+     */
+    public function isSuccessful()
+    {
+        return 0 === $this->getExitCode();
+    }
+
+    /**
+     * Returns true if the child process has been terminated by an uncaught signal.
+     *
+     * It always returns false on Windows.
+     *
+     * @return bool
+     *
+     * @throws RuntimeException In case --enable-sigchild is activated
+     * @throws LogicException   In case the process is not terminated
+     *
+     * @api
+     */
+    public function hasBeenSignaled()
+    {
+        $this->requireProcessIsTerminated(__FUNCTION__);
+
+        if ($this->isSigchildEnabled()) {
+            throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
+        }
+
+        $this->updateStatus(false);
+
+        return $this->processInformation['signaled'];
+    }
+
+    /**
+     * Returns the number of the signal that caused the child process to terminate its execution.
+     *
+     * It is only meaningful if hasBeenSignaled() returns true.
+     *
+     * @return int
+     *
+     * @throws RuntimeException In case --enable-sigchild is activated
+     * @throws LogicException   In case the process is not terminated
+     *
+     * @api
+     */
+    public function getTermSignal()
+    {
+        $this->requireProcessIsTerminated(__FUNCTION__);
+
+        if ($this->isSigchildEnabled()) {
+            throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
+        }
+
+        $this->updateStatus(false);
+
+        return $this->processInformation['termsig'];
+    }
+
+    /**
+     * Returns true if the child process has been stopped by a signal.
+     *
+     * It always returns false on Windows.
+     *
+     * @return bool
+     *
+     * @throws LogicException In case the process is not terminated
+     *
+     * @api
+     */
+    public function hasBeenStopped()
+    {
+        $this->requireProcessIsTerminated(__FUNCTION__);
+
+        $this->updateStatus(false);
+
+        return $this->processInformation['stopped'];
+    }
+
+    /**
+     * Returns the number of the signal that caused the child process to stop its execution.
+     *
+     * It is only meaningful if hasBeenStopped() returns true.
+     *
+     * @return int
+     *
+     * @throws LogicException In case the process is not terminated
+     *
+     * @api
+     */
+    public function getStopSignal()
+    {
+        $this->requireProcessIsTerminated(__FUNCTION__);
+
+        $this->updateStatus(false);
+
+        return $this->processInformation['stopsig'];
+    }
+
+    /**
+     * Checks if the process is currently running.
+     *
+     * @return bool true if the process is currently running, false otherwise
+     */
+    public function isRunning()
+    {
+        if (self::STATUS_STARTED !== $this->status) {
+            return false;
+        }
+
+        $this->updateStatus(false);
+
+        return $this->processInformation['running'];
+    }
+
+    /**
+     * Checks if the process has been started with no regard to the current state.
+     *
+     * @return bool true if status is ready, false otherwise
+     */
+    public function isStarted()
+    {
+        return $this->status != self::STATUS_READY;
+    }
+
+    /**
+     * Checks if the process is terminated.
+     *
+     * @return bool true if process is terminated, false otherwise
+     */
+    public function isTerminated()
+    {
+        $this->updateStatus(false);
+
+        return $this->status == self::STATUS_TERMINATED;
+    }
+
+    /**
+     * Gets the process status.
+     *
+     * The status is one of: ready, started, terminated.
+     *
+     * @return string The current process status
+     */
+    public function getStatus()
+    {
+        $this->updateStatus(false);
+
+        return $this->status;
+    }
+
+    /**
+     * Stops the process.
+     *
+     * @param int|float $timeout The timeout in seconds
+     * @param int       $signal  A POSIX signal to send in case the process has not stop at timeout, default is SIGKILL
+     *
+     * @return int The exit-code of the process
+     *
+     * @throws RuntimeException if the process got signaled
+     */
+    public function stop($timeout = 10, $signal = null)
+    {
+        $timeoutMicro = microtime(true) + $timeout;
+        if ($this->isRunning()) {
+            if (defined('PHP_WINDOWS_VERSION_BUILD') && !$this->isSigchildEnabled()) {
+                exec(sprintf("taskkill /F /T /PID %d 2>&1", $this->getPid()), $output, $exitCode);
+                if ($exitCode > 0) {
+                    throw new RuntimeException('Unable to kill the process');
+                }
+            }
+            // given `SIGTERM` may not be defined and that `proc_terminate` uses the constant value and not the constant itself, we use the same here
+            $this->doSignal(15, false);
+            do {
+                usleep(1000);
+            } while ($this->isRunning() && microtime(true) < $timeoutMicro);
+
+            if ($this->isRunning() && !$this->isSigchildEnabled()) {
+                if (null !== $signal || defined('SIGKILL')) {
+                    // avoid exception here :
+                    // process is supposed to be running, but it might have stop
+                    // just after this line.
+                    // in any case, let's silently discard the error, we can not do anything
+                    $this->doSignal($signal ?: SIGKILL, false);
+                }
+            }
+        }
+
+        $this->updateStatus(false);
+        if ($this->processInformation['running']) {
+            $this->close();
+        }
+
+        return $this->exitcode;
+    }
+
+    /**
+     * Adds a line to the STDOUT stream.
+     *
+     * @param string $line The line to append
+     */
+    public function addOutput($line)
+    {
+        $this->lastOutputTime = microtime(true);
+        $this->stdout .= $line;
+    }
+
+    /**
+     * Adds a line to the STDERR stream.
+     *
+     * @param string $line The line to append
+     */
+    public function addErrorOutput($line)
+    {
+        $this->lastOutputTime = microtime(true);
+        $this->stderr .= $line;
+    }
+
+    /**
+     * Gets the command line to be executed.
+     *
+     * @return string The command to execute
+     */
+    public function getCommandLine()
+    {
+        return $this->commandline;
+    }
+
+    /**
+     * Sets the command line to be executed.
+     *
+     * @param string $commandline The command to execute
+     *
+     * @return self The current Process instance
+     */
+    public function setCommandLine($commandline)
+    {
+        $this->commandline = $commandline;
+
+        return $this;
+    }
+
+    /**
+     * Gets the process timeout (max. runtime).
+     *
+     * @return float|null The timeout in seconds or null if it's disabled
+     */
+    public function getTimeout()
+    {
+        return $this->timeout;
+    }
+
+    /**
+     * Gets the process idle timeout (max. time since last output).
+     *
+     * @return float|null The timeout in seconds or null if it's disabled
+     */
+    public function getIdleTimeout()
+    {
+        return $this->idleTimeout;
+    }
+
+    /**
+     * Sets the process timeout (max. runtime).
+     *
+     * To disable the timeout, set this value to null.
+     *
+     * @param int|float|null $timeout The timeout in seconds
+     *
+     * @return self The current Process instance
+     *
+     * @throws InvalidArgumentException if the timeout is negative
+     */
+    public function setTimeout($timeout)
+    {
+        $this->timeout = $this->validateTimeout($timeout);
+
+        return $this;
+    }
+
+    /**
+     * Sets the process idle timeout (max. time since last output).
+     *
+     * To disable the timeout, set this value to null.
+     *
+     * @param int|float|null     $timeout The timeout in seconds
+     *
+     * @return self The current Process instance.
+     *
+     * @throws LogicException           if the output is disabled
+     * @throws InvalidArgumentException if the timeout is negative
+     */
+    public function setIdleTimeout($timeout)
+    {
+        if (null !== $timeout && $this->outputDisabled) {
+            throw new LogicException('Idle timeout can not be set while the output is disabled.');
+        }
+
+        $this->idleTimeout = $this->validateTimeout($timeout);
+
+        return $this;
+    }
+
+    /**
+     * Enables or disables the TTY mode.
+     *
+     * @param bool $tty True to enabled and false to disable
+     *
+     * @return self The current Process instance
+     *
+     * @throws RuntimeException In case the TTY mode is not supported
+     */
+    public function setTty($tty)
+    {
+        if (defined('PHP_WINDOWS_VERSION_BUILD') && $tty) {
+            throw new RuntimeException('TTY mode is not supported on Windows platform.');
+        }
+
+        $this->tty = (bool) $tty;
+
+        return $this;
+    }
+
+    /**
+     * Checks if the TTY mode is enabled.
+     *
+     * @return bool true if the TTY mode is enabled, false otherwise
+     */
+    public function isTty()
+    {
+        return $this->tty;
+    }
+
+    /**
+     * Sets PTY mode.
+     *
+     * @param bool    $bool
+     *
+     * @return self
+     */
+    public function setPty($bool)
+    {
+        $this->pty = (bool) $bool;
+
+        return $this;
+    }
+
+    /**
+     * Returns PTY state.
+     *
+     * @return bool
+     */
+    public function isPty()
+    {
+        return $this->pty;
+    }
+
+    /**
+     * Gets the working directory.
+     *
+     * @return string|null The current working directory or null on failure
+     */
+    public function getWorkingDirectory()
+    {
+        if (null === $this->cwd) {
+            // getcwd() will return false if any one of the parent directories does not have
+            // the readable or search mode set, even if the current directory does
+            return getcwd() ?: null;
+        }
+
+        return $this->cwd;
+    }
+
+    /**
+     * Sets the current working directory.
+     *
+     * @param string $cwd The new working directory
+     *
+     * @return self The current Process instance
+     */
+    public function setWorkingDirectory($cwd)
+    {
+        $this->cwd = $cwd;
+
+        return $this;
+    }
+
+    /**
+     * Gets the environment variables.
+     *
+     * @return array The current environment variables
+     */
+    public function getEnv()
+    {
+        return $this->env;
+    }
+
+    /**
+     * Sets the environment variables.
+     *
+     * An environment variable value should be a string.
+     * If it is an array, the variable is ignored.
+     *
+     * That happens in PHP when 'argv' is registered into
+     * the $_ENV array for instance.
+     *
+     * @param array $env The new environment variables
+     *
+     * @return self The current Process instance
+     */
+    public function setEnv(array $env)
+    {
+        // Process can not handle env values that are arrays
+        $env = array_filter($env, function ($value) {
+            return !is_array($value);
+        });
+
+        $this->env = array();
+        foreach ($env as $key => $value) {
+            $this->env[(binary) $key] = (binary) $value;
+        }
+
+        return $this;
+    }
+
+    /**
+     * Gets the contents of STDIN.
+     *
+     * @return string|null The current contents
+     *
+     * @deprecated Deprecated since version 2.5, to be removed in 3.0.
+     *             This method is deprecated in favor of getInput.
+     */
+    public function getStdin()
+    {
+        return $this->getInput();
+    }
+
+    /**
+     * Gets the Process input.
+     *
+     * @return null|string The Process input
+     */
+    public function getInput()
+    {
+        return $this->input;
+    }
+
+    /**
+     * Sets the contents of STDIN.
+     *
+     * @param string|null $stdin The new contents
+     *
+     * @return self The current Process instance
+     *
+     * @deprecated Deprecated since version 2.5, to be removed in 3.0.
+     *             This method is deprecated in favor of setInput.
+     *
+     * @throws LogicException           In case the process is running
+     * @throws InvalidArgumentException In case the argument is invalid
+     */
+    public function setStdin($stdin)
+    {
+        return $this->setInput($stdin);
+    }
+
+    /**
+     * Sets the input.
+     *
+     * This content will be passed to the underlying process standard input.
+     *
+     * @param string|null $input The content
+     *
+     * @return self The current Process instance
+     *
+     * @throws LogicException In case the process is running
+     */
+    public function setInput($input)
+    {
+        if ($this->isRunning()) {
+            throw new LogicException('Input can not be set while the process is running.');
+        }
+
+        $this->input = ProcessUtils::validateInput(sprintf('%s::%s', __CLASS__, __FUNCTION__), $input);
+
+        return $this;
+    }
+
+    /**
+     * Gets the options for proc_open.
+     *
+     * @return array The current options
+     */
+    public function getOptions()
+    {
+        return $this->options;
+    }
+
+    /**
+     * Sets the options for proc_open.
+     *
+     * @param array $options The new options
+     *
+     * @return self The current Process instance
+     */
+    public function setOptions(array $options)
+    {
+        $this->options = $options;
+
+        return $this;
+    }
+
+    /**
+     * Gets whether or not Windows compatibility is enabled.
+     *
+     * This is true by default.
+     *
+     * @return bool
+     */
+    public function getEnhanceWindowsCompatibility()
+    {
+        return $this->enhanceWindowsCompatibility;
+    }
+
+    /**
+     * Sets whether or not Windows compatibility is enabled.
+     *
+     * @param bool $enhance
+     *
+     * @return self The current Process instance
+     */
+    public function setEnhanceWindowsCompatibility($enhance)
+    {
+        $this->enhanceWindowsCompatibility = (bool) $enhance;
+
+        return $this;
+    }
+
+    /**
+     * Returns whether sigchild compatibility mode is activated or not.
+     *
+     * @return bool
+     */
+    public function getEnhanceSigchildCompatibility()
+    {
+        return $this->enhanceSigchildCompatibility;
+    }
+
+    /**
+     * Activates sigchild compatibility mode.
+     *
+     * Sigchild compatibility mode is required to get the exit code and
+     * determine the success of a process when PHP has been compiled with
+     * the --enable-sigchild option
+     *
+     * @param bool $enhance
+     *
+     * @return self The current Process instance
+     */
+    public function setEnhanceSigchildCompatibility($enhance)
+    {
+        $this->enhanceSigchildCompatibility = (bool) $enhance;
+
+        return $this;
+    }
+
+    /**
+     * Performs a check between the timeout definition and the time the process started.
+     *
+     * In case you run a background process (with the start method), you should
+     * trigger this method regularly to ensure the process timeout
+     *
+     * @throws ProcessTimedOutException In case the timeout was reached
+     */
+    public function checkTimeout()
+    {
+        if ($this->status !== self::STATUS_STARTED) {
+            return;
+        }
+
+        if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) {
+            $this->stop(0);
+
+            throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL);
+        }
+
+        if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) {
+            $this->stop(0);
+
+            throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE);
+        }
+    }
+
+    /**
+     * Returns whether PTY is supported on the current operating system.
+     *
+     * @return bool
+     */
+    public static function isPtySupported()
+    {
+        static $result;
+
+        if (null !== $result) {
+            return $result;
+        }
+
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            return $result = false;
+        }
+
+        $proc = @proc_open('echo 1', array(array('pty'), array('pty'), array('pty')), $pipes);
+        if (is_resource($proc)) {
+            proc_close($proc);
+
+            return $result = true;
+        }
+
+        return $result = false;
+    }
+
+    /**
+     * Creates the descriptors needed by the proc_open.
+     *
+     * @return array
+     */
+    private function getDescriptors()
+    {
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->processPipes = WindowsPipes::create($this, $this->input);
+        } else {
+            $this->processPipes = UnixPipes::create($this, $this->input);
+        }
+        $descriptors = $this->processPipes->getDescriptors($this->outputDisabled);
+
+        if (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
+            // last exit code is output on the fourth pipe and caught to work around --enable-sigchild
+            $descriptors = array_merge($descriptors, array(array('pipe', 'w')));
+
+            $this->commandline = '('.$this->commandline.') 3>/dev/null; code=$?; echo $code >&3; exit $code';
+        }
+
+        return $descriptors;
+    }
+
+    /**
+     * Builds up the callback used by wait().
+     *
+     * The callbacks adds all occurred output to the specific buffer and calls
+     * the user callback (if present) with the received output.
+     *
+     * @param callable|null $callback The user defined PHP callback
+     *
+     * @return callable A PHP callable
+     */
+    protected function buildCallback($callback)
+    {
+        $that = $this;
+        $out = self::OUT;
+        $err = self::ERR;
+        $callback = function ($type, $data) use ($that, $callback, $out, $err) {
+            if ($out == $type) {
+                $that->addOutput($data);
+            } else {
+                $that->addErrorOutput($data);
+            }
+
+            if (null !== $callback) {
+                call_user_func($callback, $type, $data);
+            }
+        };
+
+        return $callback;
+    }
+
+    /**
+     * Updates the status of the process, reads pipes.
+     *
+     * @param bool $blocking Whether to use a blocking read call.
+     */
+    protected function updateStatus($blocking)
+    {
+        if (self::STATUS_STARTED !== $this->status) {
+            return;
+        }
+
+        $this->processInformation = proc_get_status($this->process);
+        $this->captureExitCode();
+
+        $this->readPipes($blocking, defined('PHP_WINDOWS_VERSION_BUILD') ? !$this->processInformation['running'] : true);
+
+        if (!$this->processInformation['running']) {
+            $this->close();
+        }
+    }
+
+    /**
+     * Returns whether PHP has been compiled with the '--enable-sigchild' option or not.
+     *
+     * @return bool
+     */
+    protected function isSigchildEnabled()
+    {
+        if (null !== self::$sigchild) {
+            return self::$sigchild;
+        }
+
+        if (!function_exists('phpinfo')) {
+            return self::$sigchild = false;
+        }
+
+        ob_start();
+        phpinfo(INFO_GENERAL);
+
+        return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');
+    }
+
+    /**
+     * Validates and returns the filtered timeout.
+     *
+     * @param int|float|null     $timeout
+     *
+     * @return float|null
+     *
+     * @throws InvalidArgumentException if the given timeout is a negative number
+     */
+    private function validateTimeout($timeout)
+    {
+        $timeout = (float) $timeout;
+
+        if (0.0 === $timeout) {
+            $timeout = null;
+        } elseif ($timeout < 0) {
+            throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
+        }
+
+        return $timeout;
+    }
+
+    /**
+     * Reads pipes, executes callback.
+     *
+     * @param bool $blocking Whether to use blocking calls or not.
+     * @param bool $close    Whether to close file handles or not.
+     */
+    private function readPipes($blocking, $close)
+    {
+        $result = $this->processPipes->readAndWrite($blocking, $close);
+
+        foreach ($result as $type => $data) {
+            if (3 == $type) {
+                $this->fallbackExitcode = (int) $data;
+            } else {
+                call_user_func($this->callback, $type === self::STDOUT ? self::OUT : self::ERR, $data);
+            }
+        }
+    }
+
+    /**
+     * Captures the exitcode if mentioned in the process information.
+     */
+    private function captureExitCode()
+    {
+        if (isset($this->processInformation['exitcode']) && -1 != $this->processInformation['exitcode']) {
+            $this->exitcode = $this->processInformation['exitcode'];
+        }
+    }
+
+    /**
+     * Closes process resource, closes file handles, sets the exitcode.
+     *
+     * @return int The exitcode
+     */
+    private function close()
+    {
+        $this->processPipes->close();
+        if (is_resource($this->process)) {
+            $exitcode = proc_close($this->process);
+        } else {
+            $exitcode = -1;
+        }
+
+        $this->exitcode = -1 !== $exitcode ? $exitcode : (null !== $this->exitcode ? $this->exitcode : -1);
+        $this->status = self::STATUS_TERMINATED;
+
+        if (-1 === $this->exitcode && null !== $this->fallbackExitcode) {
+            $this->exitcode = $this->fallbackExitcode;
+        } elseif (-1 === $this->exitcode && $this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) {
+            // if process has been signaled, no exitcode but a valid termsig, apply Unix convention
+            $this->exitcode = 128 + $this->processInformation['termsig'];
+        }
+
+        return $this->exitcode;
+    }
+
+    /**
+     * Resets data related to the latest run of the process.
+     */
+    private function resetProcessData()
+    {
+        $this->starttime = null;
+        $this->callback = null;
+        $this->exitcode = null;
+        $this->fallbackExitcode = null;
+        $this->processInformation = null;
+        $this->stdout = null;
+        $this->stderr = null;
+        $this->process = null;
+        $this->latestSignal = null;
+        $this->status = self::STATUS_READY;
+        $this->incrementalOutputOffset = 0;
+        $this->incrementalErrorOutputOffset = 0;
+    }
+
+    /**
+     * Sends a POSIX signal to the process.
+     *
+     * @param int  $signal         A valid POSIX signal (see http://www.php.net/manual/en/pcntl.constants.php)
+     * @param bool $throwException Whether to throw exception in case signal failed
+     *
+     * @return bool True if the signal was sent successfully, false otherwise
+     *
+     * @throws LogicException   In case the process is not running
+     * @throws RuntimeException In case --enable-sigchild is activated
+     * @throws RuntimeException In case of failure
+     */
+    private function doSignal($signal, $throwException)
+    {
+        if (!$this->isRunning()) {
+            if ($throwException) {
+                throw new LogicException('Can not send signal on a non running process.');
+            }
+
+            return false;
+        }
+
+        if ($this->isSigchildEnabled()) {
+            if ($throwException) {
+                throw new RuntimeException('This PHP has been compiled with --enable-sigchild. The process can not be signaled.');
+            }
+
+            return false;
+        }
+
+        if (true !== @proc_terminate($this->process, $signal)) {
+            if ($throwException) {
+                throw new RuntimeException(sprintf('Error while sending signal `%s`.', $signal));
+            }
+
+            return false;
+        }
+
+        $this->latestSignal = $signal;
+
+        return true;
+    }
+
+    /**
+     * Ensures the process is running or terminated, throws a LogicException if the process has a not started.
+     *
+     * @param string $functionName The function name that was called.
+     *
+     * @throws LogicException If the process has not run.
+     */
+    private function requireProcessIsStarted($functionName)
+    {
+        if (!$this->isStarted()) {
+            throw new LogicException(sprintf('Process must be started before calling %s.', $functionName));
+        }
+    }
+
+    /**
+     * Ensures the process is terminated, throws a LogicException if the process has a status different than `terminated`.
+     *
+     * @param string $functionName The function name that was called.
+     *
+     * @throws LogicException If the process is not yet terminated.
+     */
+    private function requireProcessIsTerminated($functionName)
+    {
+        if (!$this->isTerminated()) {
+            throw new LogicException(sprintf('Process must be terminated before calling %s.', $functionName));
+        }
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/ProcessBuilder.php b/core/vendor/symfony/process/Symfony/Component/Process/ProcessBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..71633cd7fac3c5acf0d3d08a575a6456e33c2cf7
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/ProcessBuilder.php
@@ -0,0 +1,287 @@
+<?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\Process;
+
+use Symfony\Component\Process\Exception\InvalidArgumentException;
+use Symfony\Component\Process\Exception\LogicException;
+
+/**
+ * Process builder.
+ *
+ * @author Kris Wallsmith <kris@symfony.com>
+ */
+class ProcessBuilder
+{
+    private $arguments;
+    private $cwd;
+    private $env = array();
+    private $input;
+    private $timeout = 60;
+    private $options = array();
+    private $inheritEnv = true;
+    private $prefix = array();
+    private $outputDisabled = false;
+
+    /**
+     * Constructor
+     *
+     * @param string[] $arguments An array of arguments
+     */
+    public function __construct(array $arguments = array())
+    {
+        $this->arguments = $arguments;
+    }
+
+    /**
+     * Creates a process builder instance.
+     *
+     * @param string[] $arguments An array of arguments
+     *
+     * @return ProcessBuilder
+     */
+    public static function create(array $arguments = array())
+    {
+        return new static($arguments);
+    }
+
+    /**
+     * Adds an unescaped argument to the command string.
+     *
+     * @param string $argument A command argument
+     *
+     * @return ProcessBuilder
+     */
+    public function add($argument)
+    {
+        $this->arguments[] = $argument;
+
+        return $this;
+    }
+
+    /**
+     * Adds an unescaped prefix to the command string.
+     *
+     * The prefix is preserved when resetting arguments.
+     *
+     * @param string|array $prefix A command prefix or an array of command prefixes
+     *
+     * @return ProcessBuilder
+     */
+    public function setPrefix($prefix)
+    {
+        $this->prefix = is_array($prefix) ? $prefix : array($prefix);
+
+        return $this;
+    }
+
+    /**
+     * Sets the arguments of the process.
+     *
+     * Arguments must not be escaped.
+     * Previous arguments are removed.
+     *
+     * @param string[] $arguments
+     *
+     * @return ProcessBuilder
+     */
+    public function setArguments(array $arguments)
+    {
+        $this->arguments = $arguments;
+
+        return $this;
+    }
+
+    /**
+     * Sets the working directory.
+     *
+     * @param null|string $cwd The working directory
+     *
+     * @return ProcessBuilder
+     */
+    public function setWorkingDirectory($cwd)
+    {
+        $this->cwd = $cwd;
+
+        return $this;
+    }
+
+    /**
+     * Sets whether environment variables will be inherited or not.
+     *
+     * @param bool $inheritEnv
+     *
+     * @return ProcessBuilder
+     */
+    public function inheritEnvironmentVariables($inheritEnv = true)
+    {
+        $this->inheritEnv = $inheritEnv;
+
+        return $this;
+    }
+
+    /**
+     * Sets an environment variable
+     *
+     * Setting a variable overrides its previous value. Use `null` to unset a
+     * defined environment variable.
+     *
+     * @param string      $name  The variable name
+     * @param null|string $value The variable value
+     *
+     * @return ProcessBuilder
+     */
+    public function setEnv($name, $value)
+    {
+        $this->env[$name] = $value;
+
+        return $this;
+    }
+
+    /**
+     * Adds a set of environment variables.
+     *
+     * Already existing environment variables with the same name will be
+     * overridden by the new values passed to this method. Pass `null` to unset
+     * a variable.
+     *
+     * @param array $variables The variables
+     *
+     * @return ProcessBuilder
+     */
+    public function addEnvironmentVariables(array $variables)
+    {
+        $this->env = array_replace($this->env, $variables);
+
+        return $this;
+    }
+
+    /**
+     * Sets the input of the process.
+     *
+     * Deprecation: As of Symfony 2.5, this method only accepts string values.
+     *
+     * @param string|null $input The input as a string
+     *
+     * @return ProcessBuilder
+     *
+     * @throws InvalidArgumentException In case the argument is invalid
+     */
+    public function setInput($input)
+    {
+        $this->input = ProcessUtils::validateInput(sprintf('%s::%s', __CLASS__, __FUNCTION__), $input);
+
+        return $this;
+    }
+
+    /**
+     * Sets the process timeout.
+     *
+     * To disable the timeout, set this value to null.
+     *
+     * @param float|null
+     *
+     * @return ProcessBuilder
+     *
+     * @throws InvalidArgumentException
+     */
+    public function setTimeout($timeout)
+    {
+        if (null === $timeout) {
+            $this->timeout = null;
+
+            return $this;
+        }
+
+        $timeout = (float) $timeout;
+
+        if ($timeout < 0) {
+            throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
+        }
+
+        $this->timeout = $timeout;
+
+        return $this;
+    }
+
+    /**
+     * Adds a proc_open option.
+     *
+     * @param string $name  The option name
+     * @param string $value The option value
+     *
+     * @return ProcessBuilder
+     */
+    public function setOption($name, $value)
+    {
+        $this->options[$name] = $value;
+
+        return $this;
+    }
+
+    /**
+     * Disables fetching output and error output from the underlying process.
+     *
+     * @return ProcessBuilder
+     */
+    public function disableOutput()
+    {
+        $this->outputDisabled = true;
+
+        return $this;
+    }
+
+    /**
+     * Enables fetching output and error output from the underlying process.
+     *
+     * @return ProcessBuilder
+     */
+    public function enableOutput()
+    {
+        $this->outputDisabled = false;
+
+        return $this;
+    }
+
+    /**
+     * Creates a Process instance and returns it.
+     *
+     * @return Process
+     *
+     * @throws LogicException In case no arguments have been provided
+     */
+    public function getProcess()
+    {
+        if (0 === count($this->prefix) && 0 === count($this->arguments)) {
+            throw new LogicException('You must add() command arguments before calling getProcess().');
+        }
+
+        $options = $this->options;
+
+        $arguments = array_merge($this->prefix, $this->arguments);
+        $script = implode(' ', array_map(array(__NAMESPACE__.'\\ProcessUtils', 'escapeArgument'), $arguments));
+
+        if ($this->inheritEnv) {
+            // include $_ENV for BC purposes
+            $env = array_replace($_ENV, $_SERVER, $this->env);
+        } else {
+            $env = $this->env;
+        }
+
+        $process = new Process($script, $this->cwd, $env, $this->input, $this->timeout, $options);
+
+        if ($this->outputDisabled) {
+            $process->disableOutput();
+        }
+
+        return $process;
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/ProcessUtils.php b/core/vendor/symfony/process/Symfony/Component/Process/ProcessUtils.php
new file mode 100644
index 0000000000000000000000000000000000000000..2ec321cc12c6b30b7b9fbcda5e899abb9cf4771f
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/ProcessUtils.php
@@ -0,0 +1,111 @@
+<?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\Process;
+
+use Symfony\Component\Process\Exception\InvalidArgumentException;
+
+/**
+ * ProcessUtils is a bunch of utility methods.
+ *
+ * This class contains static methods only and is not meant to be instantiated.
+ *
+ * @author Martin Hasoň <martin.hason@gmail.com>
+ */
+class ProcessUtils
+{
+    /**
+     * This class should not be instantiated
+     */
+    private function __construct()
+    {
+    }
+
+    /**
+     * Escapes a string to be used as a shell argument.
+     *
+     * @param string $argument The argument that will be escaped
+     *
+     * @return string The escaped argument
+     */
+    public static function escapeArgument($argument)
+    {
+        //Fix for PHP bug #43784 escapeshellarg removes % from given string
+        //Fix for PHP bug #49446 escapeshellarg doesn't work on Windows
+        //@see https://bugs.php.net/bug.php?id=43784
+        //@see https://bugs.php.net/bug.php?id=49446
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            if ('' === $argument) {
+                return escapeshellarg($argument);
+            }
+
+            $escapedArgument = '';
+            $quote =  false;
+            foreach (preg_split('/(")/i', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
+                if ('"' === $part) {
+                    $escapedArgument .= '\\"';
+                } elseif (self::isSurroundedBy($part, '%')) {
+                    // Avoid environment variable expansion
+                    $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
+                } else {
+                    // escape trailing backslash
+                    if ('\\' === substr($part, -1)) {
+                        $part .= '\\';
+                    }
+                    $quote = true;
+                    $escapedArgument .= $part;
+                }
+            }
+            if ($quote) {
+                $escapedArgument = '"'.$escapedArgument.'"';
+            }
+
+            return $escapedArgument;
+        }
+
+        return escapeshellarg($argument);
+    }
+
+    /**
+     * Validates and normalizes a Process input
+     *
+     * @param string $caller The name of method call that validates the input
+     * @param mixed  $input  The input to validate
+     *
+     * @return string The validated input
+     *
+     * @throws InvalidArgumentException In case the input is not valid
+     */
+    public static function validateInput($caller, $input)
+    {
+        if (null !== $input) {
+            if (is_resource($input)) {
+                return $input;
+            }
+            if (is_scalar($input)) {
+                return (string) $input;
+            }
+            // deprecated as of Symfony 2.5, to be removed in 3.0
+            if (is_object($input) && method_exists($input, '__toString')) {
+                return (string) $input;
+            }
+
+            throw new InvalidArgumentException(sprintf('%s only accepts strings or stream resources.', $caller));
+        }
+
+        return $input;
+    }
+
+    private static function isSurroundedBy($arg, $char)
+    {
+        return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1];
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/README.md b/core/vendor/symfony/process/Symfony/Component/Process/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..29d1cf9330441ee37ceb6300e7e9c5082ff90e2f
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/README.md
@@ -0,0 +1,51 @@
+Process Component
+=================
+
+Process executes commands in sub-processes.
+
+In this example, we run a simple directory listing and get the result back:
+
+```php
+use Symfony\Component\Process\Process;
+
+$process = new Process('ls -lsa');
+$process->setTimeout(3600);
+$process->run();
+if (!$process->isSuccessful()) {
+    throw new RuntimeException($process->getErrorOutput());
+}
+
+print $process->getOutput();
+```
+
+You can think that this is easy to achieve with plain PHP but it's not especially
+if you want to take care of the subtle differences between the different platforms.
+
+And if you want to be able to get some feedback in real-time, just pass an
+anonymous function to the ``run()`` method and you will get the output buffer
+as it becomes available:
+
+```php
+use Symfony\Component\Process\Process;
+
+$process = new Process('ls -lsa');
+$process->run(function ($type, $buffer) {
+    if (Process::ERR === $type) {
+        echo 'ERR > '.$buffer;
+    } else {
+        echo 'OUT > '.$buffer;
+    }
+});
+```
+
+That's great if you want to execute a long running command (like rsync-ing files to a
+remote server) and give feedback to the user in real-time.
+
+Resources
+---------
+
+You can run the unit tests with the following command:
+
+    $ cd path/to/Symfony/Component/Process/
+    $ composer.phar install
+    $ phpunit
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Tests/AbstractProcessTest.php b/core/vendor/symfony/process/Symfony/Component/Process/Tests/AbstractProcessTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..d48698a7cf3a6d770a8699a5633d19971de2e251
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Tests/AbstractProcessTest.php
@@ -0,0 +1,1125 @@
+<?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\Process\Tests;
+
+use Symfony\Component\Process\Exception\ProcessTimedOutException;
+use Symfony\Component\Process\Exception\LogicException;
+use Symfony\Component\Process\Pipes\PipesInterface;
+use Symfony\Component\Process\Process;
+use Symfony\Component\Process\Exception\RuntimeException;
+
+/**
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ */
+abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
+{
+    public function testThatProcessDoesNotThrowWarningDuringRun()
+    {
+        @trigger_error('Test Error', E_USER_NOTICE);
+        $process = $this->getProcess("php -r 'sleep(3)'");
+        $process->run();
+        $actualError = error_get_last();
+        $this->assertEquals('Test Error', $actualError['message']);
+        $this->assertEquals(E_USER_NOTICE, $actualError['type']);
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException
+     */
+    public function testNegativeTimeoutFromConstructor()
+    {
+        $this->getProcess('', null, null, null, -1);
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException
+     */
+    public function testNegativeTimeoutFromSetter()
+    {
+        $p = $this->getProcess('');
+        $p->setTimeout(-1);
+    }
+
+    public function testFloatAndNullTimeout()
+    {
+        $p = $this->getProcess('');
+
+        $p->setTimeout(10);
+        $this->assertSame(10.0, $p->getTimeout());
+
+        $p->setTimeout(null);
+        $this->assertNull($p->getTimeout());
+
+        $p->setTimeout(0.0);
+        $this->assertNull($p->getTimeout());
+    }
+
+    public function testStopWithTimeoutIsActuallyWorking()
+    {
+        $this->verifyPosixIsEnabled();
+
+        // exec is mandatory here since we send a signal to the process
+        // see https://github.com/symfony/symfony/issues/5030 about prepending
+        // command with exec
+        $p = $this->getProcess('exec php '.__DIR__.'/NonStopableProcess.php 3');
+        $p->start();
+        usleep(100000);
+        $start = microtime(true);
+        $p->stop(1.1, SIGKILL);
+        while ($p->isRunning()) {
+            usleep(1000);
+        }
+        $duration = microtime(true) - $start;
+
+        $this->assertLessThan(4, $duration);
+    }
+
+    public function testAllOutputIsActuallyReadOnTermination()
+    {
+        // this code will result in a maximum of 2 reads of 8192 bytes by calling
+        // start() and isRunning().  by the time getOutput() is called the process
+        // has terminated so the internal pipes array is already empty. normally
+        // the call to start() will not read any data as the process will not have
+        // generated output, but this is non-deterministic so we must count it as
+        // a possibility.  therefore we need 2 * PipesInterface::CHUNK_SIZE plus
+        // another byte which will never be read.
+        $expectedOutputSize = PipesInterface::CHUNK_SIZE * 2 + 2;
+
+        $code = sprintf('echo str_repeat(\'*\', %d);', $expectedOutputSize);
+        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg($code)));
+
+        $p->start();
+        // Let's wait enough time for process to finish...
+        // Here we don't call Process::run or Process::wait to avoid any read of pipes
+        usleep(500000);
+
+        if ($p->isRunning()) {
+            $this->markTestSkipped('Process execution did not complete in the required time frame');
+        }
+
+        $o = $p->getOutput();
+
+        $this->assertEquals($expectedOutputSize, strlen($o));
+    }
+
+    public function testCallbacksAreExecutedWithStart()
+    {
+        $data = '';
+
+        $process = $this->getProcess('echo foo && php -r "sleep(1);" && echo foo');
+        $process->start(function ($type, $buffer) use (&$data) {
+            $data .= $buffer;
+        });
+
+        while ($process->isRunning()) {
+            usleep(10000);
+        }
+
+        $this->assertEquals(2, preg_match_all('/foo/', $data, $matches));
+    }
+
+    /**
+     * tests results from sub processes
+     *
+     * @dataProvider responsesCodeProvider
+     */
+    public function testProcessResponses($expected, $getter, $code)
+    {
+        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg($code)));
+        $p->run();
+
+        $this->assertSame($expected, $p->$getter());
+    }
+
+    /**
+     * tests results from sub processes
+     *
+     * @dataProvider pipesCodeProvider
+     */
+    public function testProcessPipes($code, $size)
+    {
+        $expected = str_repeat(str_repeat('*', 1024), $size).'!';
+        $expectedLength = (1024 * $size) + 1;
+
+        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg($code)));
+        $p->setInput($expected);
+        $p->run();
+
+        $this->assertEquals($expectedLength, strlen($p->getOutput()));
+        $this->assertEquals($expectedLength, strlen($p->getErrorOutput()));
+    }
+
+    /**
+     * @dataProvider pipesCodeProvider
+     */
+    public function testSetStreamAsInput($code, $size)
+    {
+        $expected = str_repeat(str_repeat('*', 1024), $size).'!';
+        $expectedLength = (1024 * $size) + 1;
+
+        $stream = fopen('php://temporary', 'w+');
+        fwrite($stream, $expected);
+        rewind($stream);
+
+        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg($code)));
+        $p->setInput($stream);
+        $p->run();
+
+        fclose($stream);
+
+        $this->assertEquals($expectedLength, strlen($p->getOutput()));
+        $this->assertEquals($expectedLength, strlen($p->getErrorOutput()));
+    }
+
+    public function testSetInputWhileRunningThrowsAnException()
+    {
+        $process = $this->getProcess('php -r "usleep(500000);"');
+        $process->start();
+        try {
+            $process->setInput('foobar');
+            $process->stop();
+            $this->fail('A LogicException should have been raised.');
+        } catch (LogicException $e) {
+            $this->assertEquals('Input can not be set while the process is running.', $e->getMessage());
+        }
+        $process->stop();
+    }
+
+    /**
+     * @dataProvider provideInvalidInputValues
+     * @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException
+     * @expectedExceptionMessage Symfony\Component\Process\Process::setInput only accepts strings or stream resources.
+     */
+    public function testInvalidInput($value)
+    {
+        $process = $this->getProcess('php -v');
+        $process->setInput($value);
+    }
+
+    public function provideInvalidInputValues()
+    {
+        return array(
+            array(array()),
+            array(new NonStringifiable()),
+        );
+    }
+
+    /**
+     * @dataProvider provideInputValues
+     */
+    public function testValidInput($expected, $value)
+    {
+        $process = $this->getProcess('php -v');
+        $process->setInput($value);
+        $this->assertSame($expected, $process->getInput());
+    }
+
+    public function provideInputValues()
+    {
+        return array(
+            array(null, null),
+            array('24.5', 24.5),
+            array('input data', 'input data'),
+            // to maintain BC, supposed to be removed in 3.0
+            array('stringifiable', new Stringifiable()),
+        );
+    }
+
+    public function chainedCommandsOutputProvider()
+    {
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            return array(
+                array("2 \r\n2\r\n", '&&', '2'),
+            );
+        }
+
+        return array(
+            array("1\n1\n", ';', '1'),
+            array("2\n2\n", '&&', '2'),
+        );
+    }
+
+    /**
+     *
+     * @dataProvider chainedCommandsOutputProvider
+     */
+    public function testChainedCommandsOutput($expected, $operator, $input)
+    {
+        $process = $this->getProcess(sprintf('echo %s %s echo %s', $input, $operator, $input));
+        $process->run();
+        $this->assertEquals($expected, $process->getOutput());
+    }
+
+    public function testCallbackIsExecutedForOutput()
+    {
+        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('echo \'foo\';')));
+
+        $called = false;
+        $p->run(function ($type, $buffer) use (&$called) {
+            $called = $buffer === 'foo';
+        });
+
+        $this->assertTrue($called, 'The callback should be executed with the output');
+    }
+
+    public function testGetErrorOutput()
+    {
+        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }')));
+
+        $p->run();
+        $this->assertEquals(3, preg_match_all('/ERROR/', $p->getErrorOutput(), $matches));
+    }
+
+    public function testGetIncrementalErrorOutput()
+    {
+        // use a lock file to toggle between writing ("W") and reading ("R") the
+        // error stream
+        $lock = tempnam(sys_get_temp_dir(), get_class($this).'Lock');
+        file_put_contents($lock, 'W');
+
+        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { if (\'W\' === file_get_contents('.var_export($lock, true).')) { file_put_contents(\'php://stderr\', \'ERROR\'); $n++; file_put_contents('.var_export($lock, true).', \'R\'); } usleep(100); }')));
+
+        $p->start();
+        while ($p->isRunning()) {
+            if ('R' === file_get_contents($lock)) {
+                $this->assertLessThanOrEqual(1, preg_match_all('/ERROR/', $p->getIncrementalErrorOutput(), $matches));
+                file_put_contents($lock, 'W');
+            }
+            usleep(100);
+        }
+
+        unlink($lock);
+    }
+
+    public function testFlushErrorOutput()
+    {
+        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }')));
+
+        $p->run();
+        $p->clearErrorOutput();
+        $this->assertEmpty($p->getErrorOutput());
+    }
+
+    public function testGetOutput()
+    {
+        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { echo \' foo \'; $n++; }')));
+
+        $p->run();
+        $this->assertEquals(3, preg_match_all('/foo/', $p->getOutput(), $matches));
+    }
+
+    public function testGetIncrementalOutput()
+    {
+        // use a lock file to toggle between writing ("W") and reading ("R") the
+        // output stream
+        $lock = tempnam(sys_get_temp_dir(), get_class($this).'Lock');
+        file_put_contents($lock, 'W');
+
+        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { if (\'W\' === file_get_contents('.var_export($lock, true).')) { echo \' foo \'; $n++; file_put_contents('.var_export($lock, true).', \'R\'); } usleep(100); }')));
+
+        $p->start();
+        while ($p->isRunning()) {
+            if ('R' === file_get_contents($lock)) {
+                $this->assertLessThanOrEqual(1, preg_match_all('/foo/', $p->getIncrementalOutput(), $matches));
+                file_put_contents($lock, 'W');
+            }
+            usleep(100);
+        }
+
+        unlink($lock);
+    }
+
+    public function testFlushOutput()
+    {
+        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n=0;while ($n<3) {echo \' foo \';$n++;}')));
+
+        $p->run();
+        $p->clearOutput();
+        $this->assertEmpty($p->getOutput());
+    }
+
+    public function testZeroAsOutput()
+    {
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            // see http://stackoverflow.com/questions/7105433/windows-batch-echo-without-new-line
+            $p = $this->getProcess('echo | set /p dummyName=0');
+        } else {
+            $p = $this->getProcess('printf 0');
+        }
+
+        $p->run();
+        $this->assertSame('0', $p->getOutput());
+    }
+
+    public function testExitCodeCommandFailed()
+    {
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->markTestSkipped('Windows does not support POSIX exit code');
+        }
+
+        // such command run in bash return an exitcode 127
+        $process = $this->getProcess('nonexistingcommandIhopeneversomeonewouldnameacommandlikethis');
+        $process->run();
+
+        $this->assertGreaterThan(0, $process->getExitCode());
+    }
+
+    public function testTTYCommand()
+    {
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->markTestSkipped('Windows does have /dev/tty support');
+        }
+
+        $process = $this->getProcess('echo "foo" >> /dev/null && php -r "usleep(100000);"');
+        $process->setTty(true);
+        $process->start();
+        $this->assertTrue($process->isRunning());
+        $process->wait();
+
+        $this->assertSame(Process::STATUS_TERMINATED, $process->getStatus());
+    }
+
+    public function testTTYCommandExitCode()
+    {
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->markTestSkipped('Windows does have /dev/tty support');
+        }
+
+        $process = $this->getProcess('echo "foo" >> /dev/null');
+        $process->setTty(true);
+        $process->run();
+
+        $this->assertTrue($process->isSuccessful());
+    }
+
+    public function testTTYInWindowsEnvironment()
+    {
+        if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->markTestSkipped('This test is for Windows platform only');
+        }
+
+        $process = $this->getProcess('echo "foo" >> /dev/null');
+        $process->setTty(false);
+        $this->setExpectedException('Symfony\Component\Process\Exception\RuntimeException', 'TTY mode is not supported on Windows platform.');
+        $process->setTty(true);
+    }
+
+    public function testExitCodeTextIsNullWhenExitCodeIsNull()
+    {
+        $process = $this->getProcess('');
+        $this->assertNull($process->getExitCodeText());
+    }
+
+    public function testPTYCommand()
+    {
+        if (!Process::isPtySupported()) {
+            $this->markTestSkipped('PTY is not supported on this operating system.');
+        }
+
+        $process = $this->getProcess('echo "foo"');
+        $process->setPty(true);
+        $process->run();
+
+        $this->assertSame(Process::STATUS_TERMINATED, $process->getStatus());
+        $this->assertEquals("foo\r\n", $process->getOutput());
+    }
+
+    public function testMustRun()
+    {
+        $process = $this->getProcess('echo foo');
+
+        $this->assertSame($process, $process->mustRun());
+        $this->assertEquals("foo".PHP_EOL, $process->getOutput());
+    }
+
+    public function testSuccessfulMustRunHasCorrectExitCode()
+    {
+        $process = $this->getProcess('echo foo')->mustRun();
+        $this->assertEquals(0, $process->getExitCode());
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\ProcessFailedException
+     */
+    public function testMustRunThrowsException()
+    {
+        $process = $this->getProcess('exit 1');
+        $process->mustRun();
+    }
+
+    public function testExitCodeText()
+    {
+        $process = $this->getProcess('');
+        $r = new \ReflectionObject($process);
+        $p = $r->getProperty('exitcode');
+        $p->setAccessible(true);
+
+        $p->setValue($process, 2);
+        $this->assertEquals('Misuse of shell builtins', $process->getExitCodeText());
+    }
+
+    public function testStartIsNonBlocking()
+    {
+        $process = $this->getProcess('php -r "usleep(500000);"');
+        $start = microtime(true);
+        $process->start();
+        $end = microtime(true);
+        $this->assertLessThan(0.2, $end-$start);
+        $process->wait();
+    }
+
+    public function testUpdateStatus()
+    {
+        $process = $this->getProcess('php -h');
+        $process->run();
+        $this->assertTrue(strlen($process->getOutput()) > 0);
+    }
+
+    public function testGetExitCodeIsNullOnStart()
+    {
+        $process = $this->getProcess('php -r "usleep(200000);"');
+        $this->assertNull($process->getExitCode());
+        $process->start();
+        $this->assertNull($process->getExitCode());
+        $process->wait();
+        $this->assertEquals(0, $process->getExitCode());
+    }
+
+    public function testGetExitCodeIsNullOnWhenStartingAgain()
+    {
+        $process = $this->getProcess('php -r "usleep(200000);"');
+        $process->run();
+        $this->assertEquals(0, $process->getExitCode());
+        $process->start();
+        $this->assertNull($process->getExitCode());
+        $process->wait();
+        $this->assertEquals(0, $process->getExitCode());
+    }
+
+    public function testGetExitCode()
+    {
+        $process = $this->getProcess('php -m');
+        $process->run();
+        $this->assertSame(0, $process->getExitCode());
+    }
+
+    public function testStatus()
+    {
+        $process = $this->getProcess('php -r "usleep(500000);"');
+        $this->assertFalse($process->isRunning());
+        $this->assertFalse($process->isStarted());
+        $this->assertFalse($process->isTerminated());
+        $this->assertSame(Process::STATUS_READY, $process->getStatus());
+        $process->start();
+        $this->assertTrue($process->isRunning());
+        $this->assertTrue($process->isStarted());
+        $this->assertFalse($process->isTerminated());
+        $this->assertSame(Process::STATUS_STARTED, $process->getStatus());
+        $process->wait();
+        $this->assertFalse($process->isRunning());
+        $this->assertTrue($process->isStarted());
+        $this->assertTrue($process->isTerminated());
+        $this->assertSame(Process::STATUS_TERMINATED, $process->getStatus());
+    }
+
+    public function testStop()
+    {
+        $process = $this->getProcess('php -r "sleep(4);"');
+        $process->start();
+        $this->assertTrue($process->isRunning());
+        $process->stop();
+        $this->assertFalse($process->isRunning());
+    }
+
+    public function testIsSuccessful()
+    {
+        $process = $this->getProcess('php -m');
+        $process->run();
+        $this->assertTrue($process->isSuccessful());
+    }
+
+    public function testIsSuccessfulOnlyAfterTerminated()
+    {
+        $process = $this->getProcess('php -r "sleep(1);"');
+        $process->start();
+        while ($process->isRunning()) {
+            $this->assertFalse($process->isSuccessful());
+            usleep(300000);
+        }
+
+        $this->assertTrue($process->isSuccessful());
+    }
+
+    public function testIsNotSuccessful()
+    {
+        $process = $this->getProcess('php -r "usleep(500000);throw new \Exception(\'BOUM\');"');
+        $process->start();
+        $this->assertTrue($process->isRunning());
+        $process->wait();
+        $this->assertFalse($process->isSuccessful());
+    }
+
+    public function testProcessIsNotSignaled()
+    {
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->markTestSkipped('Windows does not support POSIX signals');
+        }
+
+        $process = $this->getProcess('php -m');
+        $process->run();
+        $this->assertFalse($process->hasBeenSignaled());
+    }
+
+    public function testProcessWithoutTermSignalIsNotSignaled()
+    {
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->markTestSkipped('Windows does not support POSIX signals');
+        }
+
+        $process = $this->getProcess('php -m');
+        $process->run();
+        $this->assertFalse($process->hasBeenSignaled());
+    }
+
+    public function testProcessWithoutTermSignal()
+    {
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->markTestSkipped('Windows does not support POSIX signals');
+        }
+
+        $process = $this->getProcess('php -m');
+        $process->run();
+        $this->assertEquals(0, $process->getTermSignal());
+    }
+
+    public function testProcessIsSignaledIfStopped()
+    {
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->markTestSkipped('Windows does not support POSIX signals');
+        }
+
+        $process = $this->getProcess('php -r "sleep(4);"');
+        $process->start();
+        $process->stop();
+        $this->assertTrue($process->hasBeenSignaled());
+    }
+
+    public function testProcessWithTermSignal()
+    {
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->markTestSkipped('Windows does not support POSIX signals');
+        }
+
+        // SIGTERM is only defined if pcntl extension is present
+        $termSignal = defined('SIGTERM') ? SIGTERM : 15;
+
+        $process = $this->getProcess('php -r "sleep(4);"');
+        $process->start();
+        $process->stop();
+
+        $this->assertEquals($termSignal, $process->getTermSignal());
+    }
+
+    public function testProcessThrowsExceptionWhenExternallySignaled()
+    {
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->markTestSkipped('Windows does not support POSIX signals');
+        }
+
+        if (!function_exists('posix_kill')) {
+            $this->markTestSkipped('posix_kill is required for this test');
+        }
+
+        $termSignal = defined('SIGKILL') ? SIGKILL : 9;
+
+        $process = $this->getProcess('exec php -r "while (true) {}"');
+        $process->start();
+        posix_kill($process->getPid(), $termSignal);
+
+        $this->setExpectedException('Symfony\Component\Process\Exception\RuntimeException', 'The process has been signaled with signal "9".');
+        $process->wait();
+    }
+
+    public function testRestart()
+    {
+        $process1 = $this->getProcess('php -r "echo getmypid();"');
+        $process1->run();
+        $process2 = $process1->restart();
+
+        $process2->wait(); // wait for output
+
+        // Ensure that both processed finished and the output is numeric
+        $this->assertFalse($process1->isRunning());
+        $this->assertFalse($process2->isRunning());
+        $this->assertTrue(is_numeric($process1->getOutput()));
+        $this->assertTrue(is_numeric($process2->getOutput()));
+
+        // Ensure that restart returned a new process by check that the output is different
+        $this->assertNotEquals($process1->getOutput(), $process2->getOutput());
+    }
+
+    public function testPhpDeadlock()
+    {
+        $this->markTestSkipped('Can cause PHP to hang');
+
+        // Sleep doesn't work as it will allow the process to handle signals and close
+        // file handles from the other end.
+        $process = $this->getProcess('php -r "while (true) {}"');
+        $process->start();
+
+        // PHP will deadlock when it tries to cleanup $process
+    }
+
+    public function testRunProcessWithTimeout()
+    {
+        $timeout = 0.5;
+        $process = $this->getProcess('php -r "usleep(600000);"');
+        $process->setTimeout($timeout);
+        $start = microtime(true);
+        try {
+            $process->run();
+            $this->fail('A RuntimeException should have been raised');
+        } catch (RuntimeException $e) {
+        }
+        $duration = microtime(true) - $start;
+
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            // Windows is a bit slower as it read file handles, then allow twice the precision
+            $maxDuration = $timeout + 2 * Process::TIMEOUT_PRECISION;
+        } else {
+            $maxDuration = $timeout + Process::TIMEOUT_PRECISION;
+        }
+
+        $this->assertLessThan($maxDuration, $duration);
+    }
+
+    public function testCheckTimeoutOnNonStartedProcess()
+    {
+        $process = $this->getProcess('php -r "sleep(3);"');
+        $process->checkTimeout();
+    }
+
+    public function testCheckTimeoutOnTerminatedProcess()
+    {
+        $process = $this->getProcess('php -v');
+        $process->run();
+        $process->checkTimeout();
+    }
+
+    public function testCheckTimeoutOnStartedProcess()
+    {
+        $timeout = 0.5;
+        $precision = 100000;
+        $process = $this->getProcess('php -r "sleep(3);"');
+        $process->setTimeout($timeout);
+        $start = microtime(true);
+
+        $process->start();
+
+        try {
+            while ($process->isRunning()) {
+                $process->checkTimeout();
+                usleep($precision);
+            }
+            $this->fail('A RuntimeException should have been raised');
+        } catch (RuntimeException $e) {
+        }
+        $duration = microtime(true) - $start;
+
+        $this->assertLessThan($timeout + $precision, $duration);
+        $this->assertFalse($process->isSuccessful());
+    }
+
+    /**
+     * @group idle-timeout
+     */
+    public function testIdleTimeout()
+    {
+        $process = $this->getProcess('php -r "sleep(3);"');
+        $process->setTimeout(10);
+        $process->setIdleTimeout(0.5);
+
+        try {
+            $process->run();
+
+            $this->fail('A timeout exception was expected.');
+        } catch (ProcessTimedOutException $ex) {
+            $this->assertTrue($ex->isIdleTimeout());
+            $this->assertFalse($ex->isGeneralTimeout());
+            $this->assertEquals(0.5, $ex->getExceededTimeout());
+        }
+    }
+
+    /**
+     * @group idle-timeout
+     */
+    public function testIdleTimeoutNotExceededWhenOutputIsSent()
+    {
+        $process = $this->getProcess('php -r "echo \'foo\'; sleep(1); echo \'foo\'; sleep(1); echo \'foo\'; sleep(1); "');
+        $process->setTimeout(2);
+        $process->setIdleTimeout(1.5);
+
+        try {
+            $process->run();
+            $this->fail('A timeout exception was expected.');
+        } catch (ProcessTimedOutException $ex) {
+            $this->assertTrue($ex->isGeneralTimeout());
+            $this->assertFalse($ex->isIdleTimeout());
+            $this->assertEquals(2, $ex->getExceededTimeout());
+        }
+    }
+
+    public function testStartAfterATimeout()
+    {
+        $process = $this->getProcess('php -r "$n = 1000; while ($n--) {echo \'\'; usleep(1000); }"');
+        $process->setTimeout(0.1);
+
+        try {
+            $process->run();
+            $this->fail('An exception should have been raised.');
+        } catch (\Exception $e) {
+        }
+        $process->start();
+        usleep(1000);
+        $process->stop();
+    }
+
+    public function testGetPid()
+    {
+        $process = $this->getProcess('php -r "usleep(500000);"');
+        $process->start();
+        $this->assertGreaterThan(0, $process->getPid());
+        $process->wait();
+    }
+
+    public function testGetPidIsNullBeforeStart()
+    {
+        $process = $this->getProcess('php -r "sleep(1);"');
+        $this->assertNull($process->getPid());
+    }
+
+    public function testGetPidIsNullAfterRun()
+    {
+        $process = $this->getProcess('php -m');
+        $process->run();
+        $this->assertNull($process->getPid());
+    }
+
+    public function testSignal()
+    {
+        $this->verifyPosixIsEnabled();
+
+        $process = $this->getProcess('exec php -f '.__DIR__.'/SignalListener.php');
+        $process->start();
+        usleep(500000);
+        $process->signal(SIGUSR1);
+
+        while ($process->isRunning() && false === strpos($process->getOutput(), 'Caught SIGUSR1')) {
+            usleep(10000);
+        }
+
+        $this->assertEquals('Caught SIGUSR1', $process->getOutput());
+    }
+
+    public function testExitCodeIsAvailableAfterSignal()
+    {
+        $this->verifyPosixIsEnabled();
+
+        $process = $this->getProcess('sleep 4');
+        $process->start();
+        $process->signal(SIGKILL);
+
+        while ($process->isRunning()) {
+            usleep(10000);
+        }
+
+        $this->assertFalse($process->isRunning());
+        $this->assertTrue($process->hasBeenSignaled());
+        $this->assertFalse($process->isSuccessful());
+        $this->assertEquals(137, $process->getExitCode());
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\LogicException
+     */
+    public function testSignalProcessNotRunning()
+    {
+        $this->verifyPosixIsEnabled();
+        $process = $this->getProcess('php -m');
+        $process->signal(SIGHUP);
+    }
+
+    /**
+     * @dataProvider provideMethodsThatNeedARunningProcess
+     */
+    public function testMethodsThatNeedARunningProcess($method)
+    {
+        $process = $this->getProcess('php -m');
+        $this->setExpectedException('Symfony\Component\Process\Exception\LogicException', sprintf('Process must be started before calling %s.', $method));
+        call_user_func(array($process, $method));
+    }
+
+    public function provideMethodsThatNeedARunningProcess()
+    {
+        return array(
+            array('getOutput'),
+            array('getIncrementalOutput'),
+            array('getErrorOutput'),
+            array('getIncrementalErrorOutput'),
+            array('wait'),
+        );
+    }
+
+    /**
+     * @dataProvider provideMethodsThatNeedATerminatedProcess
+     */
+    public function testMethodsThatNeedATerminatedProcess($method)
+    {
+        $process = $this->getProcess('php -r "sleep(1);"');
+        $process->start();
+        try {
+            call_user_func(array($process, $method));
+            $process->stop(0);
+            $this->fail('A LogicException must have been thrown');
+        } catch (\Exception $e) {
+            $this->assertInstanceOf('Symfony\Component\Process\Exception\LogicException', $e);
+            $this->assertEquals(sprintf('Process must be terminated before calling %s.', $method), $e->getMessage());
+        }
+        $process->stop(0);
+    }
+
+    public function provideMethodsThatNeedATerminatedProcess()
+    {
+        return array(
+            array('hasBeenSignaled'),
+            array('getTermSignal'),
+            array('hasBeenStopped'),
+            array('getStopSignal'),
+        );
+    }
+
+    private function verifyPosixIsEnabled()
+    {
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->markTestSkipped('POSIX signals do not work on Windows');
+        }
+        if (!defined('SIGUSR1')) {
+            $this->markTestSkipped('The pcntl extension is not enabled');
+        }
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     */
+    public function testSignalWithWrongIntSignal()
+    {
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->markTestSkipped('POSIX signals do not work on Windows');
+        }
+
+        $process = $this->getProcess('php -r "sleep(3);"');
+        $process->start();
+        $process->signal(-4);
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     */
+    public function testSignalWithWrongNonIntSignal()
+    {
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->markTestSkipped('POSIX signals do not work on Windows');
+        }
+
+        $process = $this->getProcess('php -r "sleep(3);"');
+        $process->start();
+        $process->signal('Céphalopodes');
+    }
+
+    public function testDisableOutputDisablesTheOutput()
+    {
+        $p = $this->getProcess('php -r "usleep(500000);"');
+        $this->assertFalse($p->isOutputDisabled());
+        $p->disableOutput();
+        $this->assertTrue($p->isOutputDisabled());
+        $p->enableOutput();
+        $this->assertFalse($p->isOutputDisabled());
+    }
+
+    public function testDisableOutputWhileRunningThrowsException()
+    {
+        $p = $this->getProcess('php -r "usleep(500000);"');
+        $p->start();
+        $this->setExpectedException('Symfony\Component\Process\Exception\RuntimeException', 'Disabling output while the process is running is not possible.');
+        $p->disableOutput();
+    }
+
+    public function testEnableOutputWhileRunningThrowsException()
+    {
+        $p = $this->getProcess('php -r "usleep(500000);"');
+        $p->disableOutput();
+        $p->start();
+        $this->setExpectedException('Symfony\Component\Process\Exception\RuntimeException', 'Enabling output while the process is running is not possible.');
+        $p->enableOutput();
+    }
+
+    public function testEnableOrDisableOutputAfterRunDoesNotThrowException()
+    {
+        $p = $this->getProcess('php -r "usleep(500000);"');
+        $p->disableOutput();
+        $p->start();
+        $p->wait();
+        $p->enableOutput();
+        $p->disableOutput();
+    }
+
+    public function testDisableOutputWhileIdleTimeoutIsSet()
+    {
+        $process = $this->getProcess('sleep 3');
+        $process->setIdleTimeout(1);
+        $this->setExpectedException('Symfony\Component\Process\Exception\LogicException', 'Output can not be disabled while an idle timeout is set.');
+        $process->disableOutput();
+    }
+
+    public function testSetIdleTimeoutWhileOutputIsDisabled()
+    {
+        $process = $this->getProcess('sleep 3');
+        $process->disableOutput();
+        $this->setExpectedException('Symfony\Component\Process\Exception\LogicException', 'Idle timeout can not be set while the output is disabled.');
+        $process->setIdleTimeout(1);
+    }
+
+    public function testSetNullIdleTimeoutWhileOutputIsDisabled()
+    {
+        $process = $this->getProcess('sleep 3');
+        $process->disableOutput();
+        $process->setIdleTimeout(null);
+    }
+
+    /**
+     * @dataProvider provideStartMethods
+     */
+    public function testStartWithACallbackAndDisabledOutput($startMethod, $exception, $exceptionMessage)
+    {
+        $p = $this->getProcess('php -r "usleep(500000);"');
+        $p->disableOutput();
+        $this->setExpectedException($exception, $exceptionMessage);
+        call_user_func(array($p, $startMethod), function () {});
+    }
+
+    public function provideStartMethods()
+    {
+        return array(
+            array('start', 'Symfony\Component\Process\Exception\LogicException', 'Output has been disabled, enable it to allow the use of a callback.'),
+            array('run', 'Symfony\Component\Process\Exception\LogicException', 'Output has been disabled, enable it to allow the use of a callback.'),
+            array('mustRun', 'Symfony\Component\Process\Exception\LogicException', 'Output has been disabled, enable it to allow the use of a callback.'),
+        );
+    }
+
+    /**
+     * @dataProvider provideOutputFetchingMethods
+     */
+    public function testGetOutputWhileDisabled($fetchMethod)
+    {
+        $p = $this->getProcess('php -r "usleep(500000);"');
+        $p->disableOutput();
+        $p->start();
+        $this->setExpectedException('Symfony\Component\Process\Exception\LogicException', 'Output has been disabled.');
+        call_user_func(array($p, $fetchMethod));
+    }
+
+    public function provideOutputFetchingMethods()
+    {
+        return array(
+            array('getOutput'),
+            array('getIncrementalOutput'),
+            array('getErrorOutput'),
+            array('getIncrementalErrorOutput'),
+        );
+    }
+
+    public function responsesCodeProvider()
+    {
+        return array(
+            //expected output / getter / code to execute
+            //array(1,'getExitCode','exit(1);'),
+            //array(true,'isSuccessful','exit();'),
+            array('output', 'getOutput', 'echo \'output\';'),
+        );
+    }
+
+    public function pipesCodeProvider()
+    {
+        $variations = array(
+            'fwrite(STDOUT, $in = file_get_contents(\'php://stdin\')); fwrite(STDERR, $in);',
+            'include \''.__DIR__.'/PipeStdinInStdoutStdErrStreamSelect.php\';',
+        );
+
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            // Avoid XL buffers on Windows because of https://bugs.php.net/bug.php?id=65650
+            $sizes = array(1, 2, 4, 8);
+        } else {
+            $sizes = array(1, 16, 64, 1024, 4096);
+        }
+
+        $codes = array();
+        foreach ($sizes as $size) {
+            foreach ($variations as $code) {
+                $codes[] = array($code, $size);
+            }
+        }
+
+        return $codes;
+    }
+
+    /**
+     * provides default method names for simple getter/setter
+     */
+    public function methodProvider()
+    {
+        $defaults = array(
+            array('CommandLine'),
+            array('Timeout'),
+            array('WorkingDirectory'),
+            array('Env'),
+            array('Stdin'),
+            array('Input'),
+            array('Options'),
+        );
+
+        return $defaults;
+    }
+
+    /**
+     * @param string      $commandline
+     * @param null|string $cwd
+     * @param null|array  $env
+     * @param null|string $input
+     * @param int         $timeout
+     * @param array       $options
+     *
+     * @return Process
+     */
+    abstract protected function getProcess($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = array());
+}
+
+class Stringifiable
+{
+    public function __toString()
+    {
+        return 'stringifiable';
+    }
+}
+
+class NonStringifiable
+{
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Tests/ExecutableFinderTest.php b/core/vendor/symfony/process/Symfony/Component/Process/Tests/ExecutableFinderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..5fbe1e0aa70fe1c4cc6366550146d8f2a96df625
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Tests/ExecutableFinderTest.php
@@ -0,0 +1,147 @@
+<?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\Process\Tests;
+
+use Symfony\Component\Process\ExecutableFinder;
+
+/**
+ * @author Chris Smith <chris@cs278.org>
+ */
+class ExecutableFinderTest extends \PHPUnit_Framework_TestCase
+{
+    private $path;
+
+    public function tearDown()
+    {
+        if ($this->path) {
+            // Restore path if it was changed.
+            putenv('PATH='.$this->path);
+        }
+    }
+
+    private function setPath($path)
+    {
+        $this->path = getenv('PATH');
+        putenv('PATH='.$path);
+    }
+
+    public function testFind()
+    {
+        if (!defined('PHP_BINARY')) {
+            $this->markTestSkipped('Requires the PHP_BINARY constant');
+        }
+
+        if (ini_get('open_basedir')) {
+            $this->markTestSkipped('Cannot test when open_basedir is set');
+        }
+
+        $this->setPath(dirname(PHP_BINARY));
+
+        $finder = new ExecutableFinder();
+        $result = $finder->find($this->getPhpBinaryName());
+
+        $this->assertSamePath(PHP_BINARY, $result);
+    }
+
+    public function testFindWithDefault()
+    {
+        if (ini_get('open_basedir')) {
+            $this->markTestSkipped('Cannot test when open_basedir is set');
+        }
+
+        $expected = 'defaultValue';
+
+        $this->setPath('');
+
+        $finder = new ExecutableFinder();
+        $result = $finder->find('foo', $expected);
+
+        $this->assertEquals($expected, $result);
+    }
+
+    public function testFindWithExtraDirs()
+    {
+        if (!defined('PHP_BINARY')) {
+            $this->markTestSkipped('Requires the PHP_BINARY constant');
+        }
+
+        if (ini_get('open_basedir')) {
+            $this->markTestSkipped('Cannot test when open_basedir is set');
+        }
+
+        $this->setPath('');
+
+        $extraDirs = array(dirname(PHP_BINARY));
+
+        $finder = new ExecutableFinder();
+        $result = $finder->find($this->getPhpBinaryName(), null, $extraDirs);
+
+        $this->assertSamePath(PHP_BINARY, $result);
+    }
+
+    public function testFindWithOpenBaseDir()
+    {
+        if (!defined('PHP_BINARY')) {
+            $this->markTestSkipped('Requires the PHP_BINARY constant');
+        }
+
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->markTestSkipped('Cannot run test on windows');
+        }
+
+        if (ini_get('open_basedir')) {
+            $this->markTestSkipped('Cannot test when open_basedir is set');
+        }
+
+        ini_set('open_basedir', dirname(PHP_BINARY).PATH_SEPARATOR.'/');
+
+        $finder = new ExecutableFinder();
+        $result = $finder->find($this->getPhpBinaryName());
+
+        $this->assertSamePath(PHP_BINARY, $result);
+    }
+
+    public function testFindProcessInOpenBasedir()
+    {
+        if (ini_get('open_basedir')) {
+            $this->markTestSkipped('Cannot test when open_basedir is set');
+        }
+
+        if (!defined('PHP_BINARY')) {
+            $this->markTestSkipped('Requires the PHP_BINARY constant');
+        }
+
+        $execPath = __DIR__.'/SignalListener.php';
+
+        $this->setPath('');
+        ini_set('open_basedir', PHP_BINARY.PATH_SEPARATOR.'/');
+
+        $finder = new ExecutableFinder();
+        $result = $finder->find($this->getPhpBinaryName(), false);
+
+        $this->assertSamePath(PHP_BINARY, $result);
+    }
+
+    private function assertSamePath($expected, $tested)
+    {
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->assertEquals(strtolower($expected), strtolower($tested));
+        } else {
+            $this->assertEquals($expected, $tested);
+        }
+    }
+
+    private function getPhpBinaryName()
+    {
+        return basename(PHP_BINARY, defined('PHP_WINDOWS_VERSION_BUILD') ? '.exe' : '');
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Tests/NonStopableProcess.php b/core/vendor/symfony/process/Symfony/Component/Process/Tests/NonStopableProcess.php
new file mode 100644
index 0000000000000000000000000000000000000000..2183e48c6436d1a770c2497dadb3c9a9a30958bd
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Tests/NonStopableProcess.php
@@ -0,0 +1,37 @@
+<?php
+
+/**
+ * Runs a PHP script that can be stopped only with a SIGKILL (9) signal for 3 seconds
+ *
+ * @args duration Run this script with a custom duration
+ *
+ * @example `php NonStopableProcess.php 42` will run the script for 42 seconds
+ */
+
+function handleSignal($signal)
+{
+    switch ($signal) {
+        case SIGTERM:
+            $name = 'SIGTERM';
+            break;
+        case SIGINT:
+            $name = 'SIGINT';
+            break;
+        default:
+            $name = $signal.' (unknown)';
+            break;
+    }
+
+    echo "received signal $name\n";
+}
+
+declare (ticks = 1);
+pcntl_signal(SIGTERM, 'handleSignal');
+pcntl_signal(SIGINT, 'handleSignal');
+
+$duration = isset($argv[1]) ? (int) $argv[1] : 3;
+$start = microtime(true);
+
+while ($duration > (microtime(true) - $start)) {
+    usleep(1000);
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Tests/PhpExecutableFinderTest.php b/core/vendor/symfony/process/Symfony/Component/Process/Tests/PhpExecutableFinderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e16f3f8bed14361076c23b39bb99e5504409af78
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Tests/PhpExecutableFinderTest.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\Process\Tests;
+
+use Symfony\Component\Process\PhpExecutableFinder;
+
+/**
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ */
+class PhpExecutableFinderTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * tests find() with the env var PHP_PATH
+     */
+    public function testFindWithPhpPath()
+    {
+        if (defined('PHP_BINARY')) {
+            $this->markTestSkipped('The PHP binary is easily available as of PHP 5.4');
+        }
+
+        $f = new PhpExecutableFinder();
+
+        $current = $f->find();
+
+        //not executable PHP_PATH
+        putenv('PHP_PATH=/not/executable/php');
+        $this->assertFalse($f->find(), '::find() returns false for not executable PHP');
+        $this->assertFalse($f->find(false), '::find() returns false for not executable PHP');
+
+        //executable PHP_PATH
+        putenv('PHP_PATH='.$current);
+        $this->assertEquals($f->find(), $current, '::find() returns the executable PHP');
+        $this->assertEquals($f->find(false), $current, '::find() returns the executable PHP');
+    }
+
+    /**
+     * tests find() with the env var PHP_PATH
+     */
+    public function testFindWithHHVM()
+    {
+        if (!defined('HHVM_VERSION')) {
+            $this->markTestSkipped('Should be executed in HHVM context.');
+        }
+
+        $f = new PhpExecutableFinder();
+
+        $current = $f->find();
+
+        $this->assertEquals($f->find(), $current.' --php', '::find() returns the executable PHP');
+        $this->assertEquals($f->find(false), $current, '::find() returns the executable PHP');
+    }
+
+    /**
+     * tests find() with the env var PHP_PATH
+     */
+    public function testFindArguments()
+    {
+        $f = new PhpExecutableFinder();
+
+        if (defined('HHVM_VERSION')) {
+            $this->assertEquals($f->findArguments(), array('--php'), '::findArguments() returns HHVM arguments');
+        } else {
+            $this->assertEquals($f->findArguments(), array(), '::findArguments() returns no arguments');
+        }
+    }
+
+    /**
+     * tests find() with default executable
+     */
+    public function testFindWithSuffix()
+    {
+        if (defined('PHP_BINARY')) {
+            $this->markTestSkipped('The PHP binary is easily available as of PHP 5.4');
+        }
+
+        putenv('PHP_PATH=');
+        putenv('PHP_PEAR_PHP_BIN=');
+        $f = new PhpExecutableFinder();
+
+        $current = $f->find();
+
+        //TODO maybe php executable is custom or even Windows
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->assertTrue(is_executable($current));
+            $this->assertTrue((bool) preg_match('/'.addSlashes(DIRECTORY_SEPARATOR).'php\.(exe|bat|cmd|com)$/i', $current), '::find() returns the executable PHP with suffixes');
+        }
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Tests/PhpProcessTest.php b/core/vendor/symfony/process/Symfony/Component/Process/Tests/PhpProcessTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..df66ad624be314fd7be72b1835567b741b3f2e2a
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Tests/PhpProcessTest.php
@@ -0,0 +1,29 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Process\Tests;
+
+use Symfony\Component\Process\PhpProcess;
+
+class PhpProcessTest extends \PHPUnit_Framework_TestCase
+{
+    public function testNonBlockingWorks()
+    {
+        $expected = 'hello world!';
+        $process = new PhpProcess(<<<PHP
+<?php echo '$expected';
+PHP
+        );
+        $process->start();
+        $process->wait();
+        $this->assertEquals($expected, $process->getOutput());
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Tests/PipeStdinInStdoutStdErrStreamSelect.php b/core/vendor/symfony/process/Symfony/Component/Process/Tests/PipeStdinInStdoutStdErrStreamSelect.php
new file mode 100644
index 0000000000000000000000000000000000000000..89d1f6a1acafb28a42cdf137580d4a4b8347c8ed
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Tests/PipeStdinInStdoutStdErrStreamSelect.php
@@ -0,0 +1,63 @@
+<?php
+
+define('ERR_SELECT_FAILED', 1);
+define('ERR_TIMEOUT', 2);
+define('ERR_READ_FAILED', 3);
+define('ERR_WRITE_FAILED', 4);
+
+$read = array(STDIN);
+$write = array(STDOUT, STDERR);
+
+stream_set_blocking(STDIN, 0);
+stream_set_blocking(STDOUT, 0);
+stream_set_blocking(STDERR, 0);
+
+$out = $err = '';
+while ($read || $write) {
+    $r = $read;
+    $w = $write;
+    $e = null;
+    $n = stream_select($r, $w, $e, 5);
+
+    if (false === $n) {
+        die(ERR_SELECT_FAILED);
+    } elseif ($n < 1) {
+        die(ERR_TIMEOUT);
+    }
+
+    if (in_array(STDOUT, $w) && strlen($out) > 0) {
+        $written = fwrite(STDOUT, (binary) $out, 32768);
+        if (false === $written) {
+            die(ERR_WRITE_FAILED);
+        }
+        $out = (binary) substr($out, $written);
+    }
+    if (null === $read && strlen($out) < 1) {
+        $write = array_diff($write, array(STDOUT));
+    }
+
+    if (in_array(STDERR, $w) && strlen($err) > 0) {
+        $written = fwrite(STDERR, (binary) $err, 32768);
+        if (false === $written) {
+            die(ERR_WRITE_FAILED);
+        }
+        $err = (binary) substr($err, $written);
+    }
+    if (null === $read && strlen($err) < 1) {
+        $write = array_diff($write, array(STDERR));
+    }
+
+    if ($r) {
+        $str = fread(STDIN, 32768);
+        if (false !== $str) {
+            $out .= $str;
+            $err .= $str;
+        }
+        if (false === $str || feof(STDIN)) {
+            $read = null;
+            if (!feof(STDIN)) {
+                die(ERR_READ_FAILED);
+            }
+        }
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Tests/ProcessBuilderTest.php b/core/vendor/symfony/process/Symfony/Component/Process/Tests/ProcessBuilderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e864f6623456b5f85a1ce79c3bfa42b31a33efa3
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Tests/ProcessBuilderTest.php
@@ -0,0 +1,225 @@
+<?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\Process\Tests;
+
+use Symfony\Component\Process\ProcessBuilder;
+
+class ProcessBuilderTest extends \PHPUnit_Framework_TestCase
+{
+    public function testInheritEnvironmentVars()
+    {
+        $_ENV['MY_VAR_1'] = 'foo';
+
+        $proc = ProcessBuilder::create()
+            ->add('foo')
+            ->getProcess();
+
+        unset($_ENV['MY_VAR_1']);
+
+        $env = $proc->getEnv();
+        $this->assertArrayHasKey('MY_VAR_1', $env);
+        $this->assertEquals('foo', $env['MY_VAR_1']);
+    }
+
+    public function testAddEnvironmentVariables()
+    {
+        $pb = new ProcessBuilder();
+        $env = array(
+            'foo' => 'bar',
+            'foo2' => 'bar2',
+        );
+        $proc = $pb
+            ->add('command')
+            ->setEnv('foo', 'bar2')
+            ->addEnvironmentVariables($env)
+            ->inheritEnvironmentVariables(false)
+            ->getProcess()
+        ;
+
+        $this->assertSame($env, $proc->getEnv());
+    }
+
+    public function testProcessShouldInheritAndOverrideEnvironmentVars()
+    {
+        $_ENV['MY_VAR_1'] = 'foo';
+
+        $proc = ProcessBuilder::create()
+            ->setEnv('MY_VAR_1', 'bar')
+            ->add('foo')
+            ->getProcess();
+
+        unset($_ENV['MY_VAR_1']);
+
+        $env = $proc->getEnv();
+        $this->assertArrayHasKey('MY_VAR_1', $env);
+        $this->assertEquals('bar', $env['MY_VAR_1']);
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException
+     */
+    public function testNegativeTimeoutFromSetter()
+    {
+        $pb = new ProcessBuilder();
+        $pb->setTimeout(-1);
+    }
+
+    public function testNullTimeout()
+    {
+        $pb = new ProcessBuilder();
+        $pb->setTimeout(10);
+        $pb->setTimeout(null);
+
+        $r = new \ReflectionObject($pb);
+        $p = $r->getProperty('timeout');
+        $p->setAccessible(true);
+
+        $this->assertNull($p->getValue($pb));
+    }
+
+    public function testShouldSetArguments()
+    {
+        $pb = new ProcessBuilder(array('initial'));
+        $pb->setArguments(array('second'));
+
+        $proc = $pb->getProcess();
+
+        $this->assertContains("second", $proc->getCommandLine());
+    }
+
+    public function testPrefixIsPrependedToAllGeneratedProcess()
+    {
+        $pb = new ProcessBuilder();
+        $pb->setPrefix('/usr/bin/php');
+
+        $proc = $pb->setArguments(array('-v'))->getProcess();
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->assertEquals('"/usr/bin/php" "-v"', $proc->getCommandLine());
+        } else {
+            $this->assertEquals("'/usr/bin/php' '-v'", $proc->getCommandLine());
+        }
+
+        $proc = $pb->setArguments(array('-i'))->getProcess();
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->assertEquals('"/usr/bin/php" "-i"', $proc->getCommandLine());
+        } else {
+            $this->assertEquals("'/usr/bin/php' '-i'", $proc->getCommandLine());
+        }
+    }
+
+    public function testArrayPrefixesArePrependedToAllGeneratedProcess()
+    {
+        $pb = new ProcessBuilder();
+        $pb->setPrefix(array('/usr/bin/php', 'composer.phar'));
+
+        $proc = $pb->setArguments(array('-v'))->getProcess();
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->assertEquals('"/usr/bin/php" "composer.phar" "-v"', $proc->getCommandLine());
+        } else {
+            $this->assertEquals("'/usr/bin/php' 'composer.phar' '-v'", $proc->getCommandLine());
+        }
+
+        $proc = $pb->setArguments(array('-i'))->getProcess();
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->assertEquals('"/usr/bin/php" "composer.phar" "-i"', $proc->getCommandLine());
+        } else {
+            $this->assertEquals("'/usr/bin/php' 'composer.phar' '-i'", $proc->getCommandLine());
+        }
+    }
+
+    public function testShouldEscapeArguments()
+    {
+        $pb = new ProcessBuilder(array('%path%', 'foo " bar', '%baz%baz'));
+        $proc = $pb->getProcess();
+
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->assertSame('^%"path"^% "foo \\" bar" "%baz%baz"', $proc->getCommandLine());
+        } else {
+            $this->assertSame("'%path%' 'foo \" bar' '%baz%baz'", $proc->getCommandLine());
+        }
+    }
+
+    public function testShouldEscapeArgumentsAndPrefix()
+    {
+        $pb = new ProcessBuilder(array('arg'));
+        $pb->setPrefix('%prefix%');
+        $proc = $pb->getProcess();
+
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->assertSame('^%"prefix"^% "arg"', $proc->getCommandLine());
+        } else {
+            $this->assertSame("'%prefix%' 'arg'", $proc->getCommandLine());
+        }
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\LogicException
+     */
+    public function testShouldThrowALogicExceptionIfNoPrefixAndNoArgument()
+    {
+        ProcessBuilder::create()->getProcess();
+    }
+
+    public function testShouldNotThrowALogicExceptionIfNoArgument()
+    {
+        $process = ProcessBuilder::create()
+            ->setPrefix('/usr/bin/php')
+            ->getProcess();
+
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->assertEquals('"/usr/bin/php"', $process->getCommandLine());
+        } else {
+            $this->assertEquals("'/usr/bin/php'", $process->getCommandLine());
+        }
+    }
+
+    public function testShouldNotThrowALogicExceptionIfNoPrefix()
+    {
+        $process = ProcessBuilder::create(array('/usr/bin/php'))
+            ->getProcess();
+
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->assertEquals('"/usr/bin/php"', $process->getCommandLine());
+        } else {
+            $this->assertEquals("'/usr/bin/php'", $process->getCommandLine());
+        }
+    }
+
+    public function testShouldReturnProcessWithDisabledOutput()
+    {
+        $process = ProcessBuilder::create(array('/usr/bin/php'))
+            ->disableOutput()
+            ->getProcess();
+
+        $this->assertTrue($process->isOutputDisabled());
+    }
+
+    public function testShouldReturnProcessWithEnabledOutput()
+    {
+        $process = ProcessBuilder::create(array('/usr/bin/php'))
+            ->disableOutput()
+            ->enableOutput()
+            ->getProcess();
+
+        $this->assertFalse($process->isOutputDisabled());
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException
+     * @expectedExceptionMessage Symfony\Component\Process\ProcessBuilder::setInput only accepts strings or stream resources.
+     */
+    public function testInvalidInput()
+    {
+        $builder = ProcessBuilder::create();
+        $builder->setInput(array());
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Tests/ProcessFailedExceptionTest.php b/core/vendor/symfony/process/Symfony/Component/Process/Tests/ProcessFailedExceptionTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..c48648f51735f8b0221d3b707180dda6a3c5b198
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Tests/ProcessFailedExceptionTest.php
@@ -0,0 +1,136 @@
+<?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\Process\Tests;
+
+use Symfony\Component\Process\Exception\ProcessFailedException;
+
+/**
+ * @author Sebastian Marek <proofek@gmail.com>
+ */
+class ProcessFailedExceptionTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * tests ProcessFailedException throws exception if the process was successful
+     */
+    public function testProcessFailedExceptionThrowsException()
+    {
+        $process = $this->getMock(
+            'Symfony\Component\Process\Process',
+            array('isSuccessful'),
+            array('php')
+        );
+        $process->expects($this->once())
+            ->method('isSuccessful')
+            ->will($this->returnValue(true));
+
+        $this->setExpectedException(
+            '\InvalidArgumentException',
+            'Expected a failed process, but the given process was successful.'
+        );
+
+        new ProcessFailedException($process);
+    }
+
+    /**
+     * tests ProcessFailedException uses information from process output
+     * to generate exception message
+     */
+    public function testProcessFailedExceptionPopulatesInformationFromProcessOutput()
+    {
+        $cmd = 'php';
+        $exitCode = 1;
+        $exitText = 'General error';
+        $output = "Command output";
+        $errorOutput = "FATAL: Unexpected error";
+
+        $process = $this->getMock(
+            'Symfony\Component\Process\Process',
+            array('isSuccessful', 'getOutput', 'getErrorOutput', 'getExitCode', 'getExitCodeText', 'isOutputDisabled'),
+            array($cmd)
+        );
+        $process->expects($this->once())
+            ->method('isSuccessful')
+            ->will($this->returnValue(false));
+
+        $process->expects($this->once())
+            ->method('getOutput')
+            ->will($this->returnValue($output));
+
+        $process->expects($this->once())
+            ->method('getErrorOutput')
+            ->will($this->returnValue($errorOutput));
+
+        $process->expects($this->once())
+            ->method('getExitCode')
+            ->will($this->returnValue($exitCode));
+
+        $process->expects($this->once())
+            ->method('getExitCodeText')
+            ->will($this->returnValue($exitText));
+
+        $process->expects($this->once())
+            ->method('isOutputDisabled')
+            ->will($this->returnValue(false));
+
+        $exception = new ProcessFailedException($process);
+
+        $this->assertEquals(
+            "The command \"$cmd\" failed.\nExit Code: $exitCode($exitText)\n\nOutput:\n================\n{$output}\n\nError Output:\n================\n{$errorOutput}",
+            $exception->getMessage()
+        );
+    }
+
+    /**
+     * Tests that ProcessFailedException does not extract information from
+     * process output if it was previously disabled
+     */
+    public function testDisabledOutputInFailedExceptionDoesNotPopulateOutput()
+    {
+        $cmd = 'php';
+        $exitCode = 1;
+        $exitText = 'General error';
+
+        $process = $this->getMock(
+            'Symfony\Component\Process\Process',
+            array('isSuccessful', 'isOutputDisabled', 'getExitCode', 'getExitCodeText', 'getOutput', 'getErrorOutput'),
+            array($cmd)
+        );
+        $process->expects($this->once())
+            ->method('isSuccessful')
+            ->will($this->returnValue(false));
+
+        $process->expects($this->never())
+            ->method('getOutput');
+
+        $process->expects($this->never())
+            ->method('getErrorOutput');
+
+        $process->expects($this->once())
+            ->method('getExitCode')
+            ->will($this->returnValue($exitCode));
+
+        $process->expects($this->once())
+            ->method('getExitCodeText')
+            ->will($this->returnValue($exitText));
+
+        $process->expects($this->once())
+            ->method('isOutputDisabled')
+            ->will($this->returnValue(true));
+
+        $exception = new ProcessFailedException($process);
+
+        $this->assertEquals(
+            "The command \"$cmd\" failed.\nExit Code: $exitCode($exitText)",
+            $exception->getMessage()
+        );
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Tests/ProcessInSigchildEnvironment.php b/core/vendor/symfony/process/Symfony/Component/Process/Tests/ProcessInSigchildEnvironment.php
new file mode 100644
index 0000000000000000000000000000000000000000..3977bcdcf1e8465e81eae0f8a2d312f970476d75
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Tests/ProcessInSigchildEnvironment.php
@@ -0,0 +1,22 @@
+<?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\Process\Tests;
+
+use Symfony\Component\Process\Process;
+
+class ProcessInSigchildEnvironment extends Process
+{
+    protected function isSigchildEnabled()
+    {
+        return true;
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Tests/ProcessUtilsTest.php b/core/vendor/symfony/process/Symfony/Component/Process/Tests/ProcessUtilsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..8ba94c114d266ee43c054384f30c7a38196cc6e7
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Tests/ProcessUtilsTest.php
@@ -0,0 +1,48 @@
+<?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\Process\Tests;
+
+use Symfony\Component\Process\ProcessUtils;
+
+class ProcessUtilsTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @dataProvider dataArguments
+     */
+    public function testEscapeArgument($result, $argument)
+    {
+        $this->assertSame($result, ProcessUtils::escapeArgument($argument));
+    }
+
+    public function dataArguments()
+    {
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            return array(
+                array('"\"php\" \"-v\""', '"php" "-v"'),
+                array('"foo bar"', 'foo bar'),
+                array('^%"path"^%', '%path%'),
+                array('"<|>\\" \\"\'f"', '<|>" "\'f'),
+                array('""', ''),
+                array('"with\trailingbs\\\\"', 'with\trailingbs\\'),
+            );
+        }
+
+        return array(
+            array("'\"php\" \"-v\"'", '"php" "-v"'),
+            array("'foo bar'", 'foo bar'),
+            array("'%path%'", '%path%'),
+            array("'<|>\" \"'\\''f'", '<|>" "\'f'),
+            array("''", ''),
+            array("'with\\trailingbs\\'", 'with\trailingbs\\'),
+        );
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Tests/SigchildDisabledProcessTest.php b/core/vendor/symfony/process/Symfony/Component/Process/Tests/SigchildDisabledProcessTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..fdae5ec25e41dbb2315c5f6e94a8bb46df502bc5
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Tests/SigchildDisabledProcessTest.php
@@ -0,0 +1,263 @@
+<?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\Process\Tests;
+
+class SigchildDisabledProcessTest extends AbstractProcessTest
+{
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
+     */
+    public function testGetExitCode()
+    {
+        parent::testGetExitCode();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
+     */
+    public function testGetExitCodeIsNullOnStart()
+    {
+        parent::testGetExitCodeIsNullOnStart();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
+     */
+    public function testGetExitCodeIsNullOnWhenStartingAgain()
+    {
+        parent::testGetExitCodeIsNullOnWhenStartingAgain();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
+     */
+    public function testExitCodeCommandFailed()
+    {
+        parent::testExitCodeCommandFailed();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
+     */
+    public function testMustRun()
+    {
+        parent::testMustRun();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
+     */
+    public function testSuccessfulMustRunHasCorrectExitCode()
+    {
+        parent::testSuccessfulMustRunHasCorrectExitCode();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     */
+    public function testMustRunThrowsException()
+    {
+        parent::testMustRunThrowsException();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     */
+    public function testProcessIsSignaledIfStopped()
+    {
+        parent::testProcessIsSignaledIfStopped();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.
+     */
+    public function testProcessWithTermSignal()
+    {
+        parent::testProcessWithTermSignal();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.
+     */
+    public function testProcessIsNotSignaled()
+    {
+        parent::testProcessIsNotSignaled();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.
+     */
+    public function testProcessWithoutTermSignal()
+    {
+        parent::testProcessWithoutTermSignal();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
+     */
+    public function testCheckTimeoutOnStartedProcess()
+    {
+        parent::testCheckTimeoutOnStartedProcess();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved.
+     */
+    public function testGetPid()
+    {
+        parent::testGetPid();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved.
+     */
+    public function testGetPidIsNullBeforeStart()
+    {
+        parent::testGetPidIsNullBeforeStart();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved.
+     */
+    public function testGetPidIsNullAfterRun()
+    {
+        parent::testGetPidIsNullAfterRun();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
+     */
+    public function testExitCodeText()
+    {
+        $process = $this->getProcess('qdfsmfkqsdfmqmsd');
+        $process->run();
+
+        $process->getExitCodeText();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
+     */
+    public function testExitCodeTextIsNullWhenExitCodeIsNull()
+    {
+        parent::testExitCodeTextIsNullWhenExitCodeIsNull();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
+     */
+    public function testIsSuccessful()
+    {
+        parent::testIsSuccessful();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
+     */
+    public function testIsSuccessfulOnlyAfterTerminated()
+    {
+        parent::testIsSuccessfulOnlyAfterTerminated();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
+     */
+    public function testIsNotSuccessful()
+    {
+        parent::testIsNotSuccessful();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
+     */
+    public function testTTYCommandExitCode()
+    {
+        parent::testTTYCommandExitCode();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process can not be signaled.
+     */
+    public function testSignal()
+    {
+        parent::testSignal();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.
+     */
+    public function testProcessWithoutTermSignalIsNotSignaled()
+    {
+        parent::testProcessWithoutTermSignalIsNotSignaled();
+    }
+
+    public function testStopWithTimeoutIsActuallyWorking()
+    {
+        $this->markTestSkipped('Stopping with signal is not supported in sigchild environment');
+    }
+
+    public function testProcessThrowsExceptionWhenExternallySignaled()
+    {
+        $this->markTestSkipped('Retrieving Pid is not supported in sigchild environment');
+    }
+
+    public function testExitCodeIsAvailableAfterSignal()
+    {
+        $this->markTestSkipped('Signal is not supported in sigchild environment');
+    }
+
+    public function testRunProcessWithTimeout()
+    {
+        $this->markTestSkipped('Signal (required for timeout) is not supported in sigchild environment');
+    }
+
+    public function provideStartMethods()
+    {
+        return array(
+            array('start', 'Symfony\Component\Process\Exception\LogicException', 'Output has been disabled, enable it to allow the use of a callback.'),
+            array('run', 'Symfony\Component\Process\Exception\LogicException', 'Output has been disabled, enable it to allow the use of a callback.'),
+            array('mustRun', 'Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.'),
+        );
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function getProcess($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = array())
+    {
+        $process = new ProcessInSigchildEnvironment($commandline, $cwd, $env, $input, $timeout, $options);
+        $process->setEnhanceSigchildCompatibility(false);
+
+        return $process;
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Tests/SigchildEnabledProcessTest.php b/core/vendor/symfony/process/Symfony/Component/Process/Tests/SigchildEnabledProcessTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..3fea3ba1cd337d91409b1932277510dc11b1b0a4
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Tests/SigchildEnabledProcessTest.php
@@ -0,0 +1,148 @@
+<?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\Process\Tests;
+
+class SigchildEnabledProcessTest extends AbstractProcessTest
+{
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.
+     */
+    public function testProcessIsSignaledIfStopped()
+    {
+        parent::testProcessIsSignaledIfStopped();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.
+     */
+    public function testProcessWithTermSignal()
+    {
+        parent::testProcessWithTermSignal();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.
+     */
+    public function testProcessIsNotSignaled()
+    {
+        parent::testProcessIsNotSignaled();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.
+     */
+    public function testProcessWithoutTermSignal()
+    {
+        parent::testProcessWithoutTermSignal();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved.
+     */
+    public function testGetPid()
+    {
+        parent::testGetPid();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved.
+     */
+    public function testGetPidIsNullBeforeStart()
+    {
+        parent::testGetPidIsNullBeforeStart();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved.
+     */
+    public function testGetPidIsNullAfterRun()
+    {
+        parent::testGetPidIsNullAfterRun();
+    }
+
+    public function testExitCodeText()
+    {
+        $process = $this->getProcess('qdfsmfkqsdfmqmsd');
+        $process->run();
+
+        $this->assertInternalType('string', $process->getExitCodeText());
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process can not be signaled.
+     */
+    public function testSignal()
+    {
+        parent::testSignal();
+    }
+
+    /**
+     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
+     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.
+     */
+    public function testProcessWithoutTermSignalIsNotSignaled()
+    {
+        parent::testProcessWithoutTermSignalIsNotSignaled();
+    }
+
+    public function testProcessThrowsExceptionWhenExternallySignaled()
+    {
+        $this->markTestSkipped('Retrieving Pid is not supported in sigchild environment');
+    }
+
+    public function testExitCodeIsAvailableAfterSignal()
+    {
+        $this->markTestSkipped('Signal is not supported in sigchild environment');
+    }
+
+    public function testStartAfterATimeout()
+    {
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->markTestSkipped('Restarting a timed-out process on Windows is not supported in sigchild environment');
+        }
+        parent::testStartAfterATimeout();
+    }
+
+    public function testStopWithTimeoutIsActuallyWorking()
+    {
+        $this->markTestSkipped('Stopping with signal is not supported in sigchild environment');
+    }
+
+    public function testRunProcessWithTimeout()
+    {
+        $this->markTestSkipped('Signal (required for timeout) is not supported in sigchild environment');
+    }
+
+    public function testCheckTimeoutOnStartedProcess()
+    {
+        $this->markTestSkipped('Signal (required for timeout) is not supported in sigchild environment');
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function getProcess($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = array())
+    {
+        $process = new ProcessInSigchildEnvironment($commandline, $cwd, $env, $input, $timeout, $options);
+        $process->setEnhanceSigchildCompatibility(true);
+
+        return $process;
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Tests/SignalListener.php b/core/vendor/symfony/process/Symfony/Component/Process/Tests/SignalListener.php
new file mode 100644
index 0000000000000000000000000000000000000000..32910e17068746718773733b8f6df9a2ab177736
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Tests/SignalListener.php
@@ -0,0 +1,16 @@
+<?php
+
+// required for signal handling
+declare (ticks = 1);
+
+pcntl_signal(SIGUSR1, function () {echo "Caught SIGUSR1"; exit;});
+
+$n = 0;
+
+// ticks require activity to work - sleep(4); does not work
+while ($n < 400) {
+    usleep(10000);
+    $n++;
+}
+
+return;
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/Tests/SimpleProcessTest.php b/core/vendor/symfony/process/Symfony/Component/Process/Tests/SimpleProcessTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..cd206ea4c390c75d88f224c33d9cf3c97dc43162
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/Tests/SimpleProcessTest.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\Process\Tests;
+
+use Symfony\Component\Process\Process;
+
+class SimpleProcessTest extends AbstractProcessTest
+{
+    private $enabledSigchild = false;
+
+    public function setUp()
+    {
+        ob_start();
+        phpinfo(INFO_GENERAL);
+
+        $this->enabledSigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');
+    }
+
+    public function testGetExitCode()
+    {
+        $this->skipIfPHPSigchild(); // This test use exitcode that is not available in this case
+        parent::testGetExitCode();
+    }
+
+    public function testExitCodeCommandFailed()
+    {
+        $this->skipIfPHPSigchild(); // This test use exitcode that is not available in this case
+        parent::testExitCodeCommandFailed();
+    }
+
+    public function testProcessIsSignaledIfStopped()
+    {
+        $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved');
+        parent::testProcessIsSignaledIfStopped();
+    }
+
+    public function testProcessWithTermSignal()
+    {
+        $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved');
+        parent::testProcessWithTermSignal();
+    }
+
+    public function testProcessIsNotSignaled()
+    {
+        $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved');
+        parent::testProcessIsNotSignaled();
+    }
+
+    public function testProcessWithoutTermSignal()
+    {
+        $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved');
+        parent::testProcessWithoutTermSignal();
+    }
+
+    public function testExitCodeText()
+    {
+        $this->skipIfPHPSigchild(); // This test use exitcode that is not available in this case
+        parent::testExitCodeText();
+    }
+
+    public function testIsSuccessful()
+    {
+        $this->skipIfPHPSigchild(); // This test use PID that is not available in this case
+        parent::testIsSuccessful();
+    }
+
+    public function testIsNotSuccessful()
+    {
+        $this->skipIfPHPSigchild(); // This test use PID that is not available in this case
+        parent::testIsNotSuccessful();
+    }
+
+    public function testGetPid()
+    {
+        $this->skipIfPHPSigchild(); // This test use PID that is not available in this case
+        parent::testGetPid();
+    }
+
+    public function testGetPidIsNullBeforeStart()
+    {
+        $this->skipIfPHPSigchild(); // This test use PID that is not available in this case
+        parent::testGetPidIsNullBeforeStart();
+    }
+
+    public function testGetPidIsNullAfterRun()
+    {
+        $this->skipIfPHPSigchild(); // This test use PID that is not available in this case
+        parent::testGetPidIsNullAfterRun();
+    }
+
+    public function testSignal()
+    {
+        $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. The process can not be signaled.');
+        parent::testSignal();
+    }
+
+    public function testProcessWithoutTermSignalIsNotSignaled()
+    {
+        $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved');
+        parent::testProcessWithoutTermSignalIsNotSignaled();
+    }
+
+    public function testProcessThrowsExceptionWhenExternallySignaled()
+    {
+        $this->skipIfPHPSigchild(); // This test use PID that is not available in this case
+        parent::testProcessThrowsExceptionWhenExternallySignaled();
+    }
+
+    public function testExitCodeIsAvailableAfterSignal()
+    {
+        $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. The process can not be signaled.');
+        parent::testExitCodeIsAvailableAfterSignal();
+    }
+
+    public function testSignalProcessNotRunning()
+    {
+        $this->setExpectedException('Symfony\Component\Process\Exception\LogicException', 'Can not send signal on a non running process.');
+        parent::testSignalProcessNotRunning();
+    }
+
+    public function testSignalWithWrongIntSignal()
+    {
+        if ($this->enabledSigchild) {
+            $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. The process can not be signaled.');
+        } else {
+            $this->setExpectedException('Symfony\Component\Process\Exception\RuntimeException', 'Error while sending signal `-4`.');
+        }
+        parent::testSignalWithWrongIntSignal();
+    }
+
+    public function testSignalWithWrongNonIntSignal()
+    {
+        if ($this->enabledSigchild) {
+            $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. The process can not be signaled.');
+        } else {
+            $this->setExpectedException('Symfony\Component\Process\Exception\RuntimeException', 'Error while sending signal `Céphalopodes`.');
+        }
+        parent::testSignalWithWrongNonIntSignal();
+    }
+
+    public function testStopTerminatesProcessCleanly()
+    {
+        try {
+            $process = $this->getProcess('php -r "echo \'foo\'; sleep(1); echo \'bar\';"');
+            $process->run(function () use ($process) {
+                $process->stop();
+            });
+        } catch (RuntimeException $e) {
+            $this->fail('A call to stop() is not expected to cause wait() to throw a RuntimeException');
+        }
+    }
+
+    public function testKillSignalTerminatesProcessCleanly()
+    {
+        $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. The process can not be signaled.');
+
+        try {
+            $process = $this->getProcess('php -r "echo \'foo\'; sleep(1); echo \'bar\';"');
+            $process->run(function () use ($process) {
+                if ($process->isRunning()) {
+                    $process->signal(defined('SIGKILL') ? SIGKILL : 9);
+                }
+            });
+        } catch (RuntimeException $e) {
+            $this->fail('A call to signal() is not expected to cause wait() to throw a RuntimeException');
+        }
+    }
+
+    public function testTermSignalTerminatesProcessCleanly()
+    {
+        $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. The process can not be signaled.');
+
+        try {
+            $process = $this->getProcess('php -r "echo \'foo\'; sleep(1); echo \'bar\';"');
+            $process->run(function () use ($process) {
+                if ($process->isRunning()) {
+                    $process->signal(defined('SIGTERM') ? SIGTERM : 15);
+                }
+            });
+        } catch (RuntimeException $e) {
+            $this->fail('A call to signal() is not expected to cause wait() to throw a RuntimeException');
+        }
+    }
+
+    public function testStopWithTimeoutIsActuallyWorking()
+    {
+        $this->skipIfPHPSigchild();
+
+        parent::testStopWithTimeoutIsActuallyWorking();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function getProcess($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = array())
+    {
+        return new Process($commandline, $cwd, $env, $input, $timeout, $options);
+    }
+
+    private function skipIfPHPSigchild()
+    {
+        if ($this->enabledSigchild) {
+            $this->markTestSkipped('Your PHP has been compiled with --enable-sigchild, this test can not be executed');
+        }
+    }
+
+    private function expectExceptionIfPHPSigchild($classname, $message)
+    {
+        if ($this->enabledSigchild) {
+            $this->setExpectedException($classname, $message);
+        }
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/composer.json b/core/vendor/symfony/process/Symfony/Component/Process/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..39fa97cb59b052c2f2fb49656f4df8ddf68f034f
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/composer.json
@@ -0,0 +1,31 @@
+{
+    "name": "symfony/process",
+    "type": "library",
+    "description": "Symfony Process 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.3"
+    },
+    "autoload": {
+        "psr-0": { "Symfony\\Component\\Process\\": "" }
+    },
+    "target-dir": "Symfony/Component/Process",
+    "minimum-stability": "dev",
+    "extra": {
+        "branch-alias": {
+            "dev-master": "2.6-dev"
+        }
+    }
+}
diff --git a/core/vendor/symfony/process/Symfony/Component/Process/phpunit.xml.dist b/core/vendor/symfony/process/Symfony/Component/Process/phpunit.xml.dist
new file mode 100644
index 0000000000000000000000000000000000000000..fcb230a06259fb48e93898f972d1a52722d61dd3
--- /dev/null
+++ b/core/vendor/symfony/process/Symfony/Component/Process/phpunit.xml.dist
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
+         backupGlobals="false"
+         colors="true"
+         bootstrap="vendor/autoload.php"
+>
+    <testsuites>
+        <testsuite name="Symfony Process Component Test Suite">
+            <directory>./Tests/</directory>
+        </testsuite>
+    </testsuites>
+
+    <filter>
+        <whitelist>
+            <directory>./</directory>
+            <exclude>
+                <directory>./Tests</directory>
+            </exclude>
+        </whitelist>
+    </filter>
+</phpunit>