From 53108e68cf03e573ed2ab75f5f684082c629d09f Mon Sep 17 00:00:00 2001
From: Damien <damien.burel@maarch.org>
Date: Tue, 24 Jul 2018 16:16:37 +0200
Subject: [PATCH] FIX #8177 Vendor again

---
 composer.json                                 |    5 +-
 .../resource/controllers/ResController.php    |    1 +
 .../controllers/VersionUpdateController.php   |    2 +-
 vendor/composer/autoload_files.php            |    3 +
 vendor/composer/autoload_namespaces.php       |    1 -
 vendor/composer/autoload_psr4.php             |    7 +
 vendor/composer/autoload_static.php           |   45 +-
 vendor/composer/installed.json                |  499 ++++++-
 vendor/guzzlehttp/guzzle/CHANGELOG.md         | 1287 +++++++++++++++++
 vendor/guzzlehttp/guzzle/LICENSE              |   19 +
 vendor/guzzlehttp/guzzle/README.md            |   91 ++
 vendor/guzzlehttp/guzzle/UPGRADING.md         | 1203 +++++++++++++++
 vendor/guzzlehttp/guzzle/composer.json        |   44 +
 vendor/guzzlehttp/guzzle/src/Client.php       |  422 ++++++
 .../guzzlehttp/guzzle/src/ClientInterface.php |   84 ++
 .../guzzle/src/Cookie/CookieJar.php           |  314 ++++
 .../guzzle/src/Cookie/CookieJarInterface.php  |   84 ++
 .../guzzle/src/Cookie/FileCookieJar.php       |   90 ++
 .../guzzle/src/Cookie/SessionCookieJar.php    |   71 +
 .../guzzle/src/Cookie/SetCookie.php           |  403 ++++++
 .../src/Exception/BadResponseException.php    |   27 +
 .../guzzle/src/Exception/ClientException.php  |    7 +
 .../guzzle/src/Exception/ConnectException.php |   37 +
 .../guzzle/src/Exception/GuzzleException.php  |   13 +
 .../guzzle/src/Exception/RequestException.php |  217 +++
 .../guzzle/src/Exception/SeekException.php    |   27 +
 .../guzzle/src/Exception/ServerException.php  |    7 +
 .../Exception/TooManyRedirectsException.php   |    4 +
 .../src/Exception/TransferException.php       |    4 +
 .../guzzle/src/Handler/CurlFactory.php        |  565 ++++++++
 .../src/Handler/CurlFactoryInterface.php      |   27 +
 .../guzzle/src/Handler/CurlHandler.php        |   45 +
 .../guzzle/src/Handler/CurlMultiHandler.php   |  199 +++
 .../guzzle/src/Handler/EasyHandle.php         |   92 ++
 .../guzzle/src/Handler/MockHandler.php        |  189 +++
 .../guzzlehttp/guzzle/src/Handler/Proxy.php   |   55 +
 .../guzzle/src/Handler/StreamHandler.php      |  532 +++++++
 vendor/guzzlehttp/guzzle/src/HandlerStack.php |  273 ++++
 .../guzzle/src/MessageFormatter.php           |  180 +++
 vendor/guzzlehttp/guzzle/src/Middleware.php   |  255 ++++
 vendor/guzzlehttp/guzzle/src/Pool.php         |  123 ++
 .../guzzle/src/PrepareBodyMiddleware.php      |  106 ++
 .../guzzle/src/RedirectMiddleware.php         |  237 +++
 .../guzzlehttp/guzzle/src/RequestOptions.php  |  255 ++++
 .../guzzlehttp/guzzle/src/RetryMiddleware.php |  112 ++
 .../guzzlehttp/guzzle/src/TransferStats.php   |  126 ++
 vendor/guzzlehttp/guzzle/src/UriTemplate.php  |  237 +++
 vendor/guzzlehttp/guzzle/src/functions.php    |  333 +++++
 .../guzzle/src/functions_include.php          |    6 +
 vendor/guzzlehttp/promises/CHANGELOG.md       |   65 +
 vendor/guzzlehttp/promises/LICENSE            |   19 +
 vendor/guzzlehttp/promises/Makefile           |   13 +
 vendor/guzzlehttp/promises/README.md          |  504 +++++++
 vendor/guzzlehttp/promises/composer.json      |   34 +
 .../promises/src/AggregateException.php       |   16 +
 .../promises/src/CancellationException.php    |    9 +
 vendor/guzzlehttp/promises/src/Coroutine.php  |  151 ++
 .../guzzlehttp/promises/src/EachPromise.php   |  229 +++
 .../promises/src/FulfilledPromise.php         |   82 ++
 vendor/guzzlehttp/promises/src/Promise.php    |  280 ++++
 .../promises/src/PromiseInterface.php         |   93 ++
 .../promises/src/PromisorInterface.php        |   15 +
 .../promises/src/RejectedPromise.php          |   87 ++
 .../promises/src/RejectionException.php       |   47 +
 vendor/guzzlehttp/promises/src/TaskQueue.php  |   66 +
 .../promises/src/TaskQueueInterface.php       |   25 +
 vendor/guzzlehttp/promises/src/functions.php  |  457 ++++++
 .../promises/src/functions_include.php        |    6 +
 vendor/guzzlehttp/psr7/CHANGELOG.md           |  110 ++
 vendor/guzzlehttp/psr7/LICENSE                |   19 +
 vendor/guzzlehttp/psr7/README.md              |  739 ++++++++++
 vendor/guzzlehttp/psr7/composer.json          |   39 +
 vendor/guzzlehttp/psr7/src/AppendStream.php   |  233 +++
 vendor/guzzlehttp/psr7/src/BufferStream.php   |  137 ++
 vendor/guzzlehttp/psr7/src/CachingStream.php  |  138 ++
 vendor/guzzlehttp/psr7/src/DroppingStream.php |   42 +
 vendor/guzzlehttp/psr7/src/FnStream.php       |  149 ++
 vendor/guzzlehttp/psr7/src/InflateStream.php  |   52 +
 vendor/guzzlehttp/psr7/src/LazyOpenStream.php |   39 +
 vendor/guzzlehttp/psr7/src/LimitStream.php    |  155 ++
 vendor/guzzlehttp/psr7/src/MessageTrait.php   |  183 +++
 .../guzzlehttp/psr7/src/MultipartStream.php   |  153 ++
 vendor/guzzlehttp/psr7/src/NoSeekStream.php   |   22 +
 vendor/guzzlehttp/psr7/src/PumpStream.php     |  165 +++
 vendor/guzzlehttp/psr7/src/Request.php        |  142 ++
 vendor/guzzlehttp/psr7/src/Response.php       |  132 ++
 vendor/guzzlehttp/psr7/src/ServerRequest.php  |  358 +++++
 vendor/guzzlehttp/psr7/src/Stream.php         |  257 ++++
 .../psr7/src/StreamDecoratorTrait.php         |  149 ++
 vendor/guzzlehttp/psr7/src/StreamWrapper.php  |  121 ++
 vendor/guzzlehttp/psr7/src/UploadedFile.php   |  316 ++++
 vendor/guzzlehttp/psr7/src/Uri.php            |  702 +++++++++
 vendor/guzzlehttp/psr7/src/UriNormalizer.php  |  216 +++
 vendor/guzzlehttp/psr7/src/UriResolver.php    |  219 +++
 vendor/guzzlehttp/psr7/src/functions.php      |  828 +++++++++++
 .../guzzlehttp/psr7/src/functions_include.php |    6 +
 vendor/m4tthumphrey/php-gitlab-api/.gitignore |    2 -
 .../m4tthumphrey/php-gitlab-api/.travis.yml   |   17 -
 vendor/m4tthumphrey/php-gitlab-api/LICENSE    |    2 +-
 vendor/m4tthumphrey/php-gitlab-api/README.md  |   96 --
 .../m4tthumphrey/php-gitlab-api/composer.json |   85 +-
 .../lib/Gitlab/Api/AbstractApi.php            |  140 +-
 .../lib/Gitlab/Api/DeployKeys.php             |   20 +-
 .../lib/Gitlab/Api/Deployments.php            |   25 +
 .../lib/Gitlab/Api/Environments.php           |   48 +
 .../php-gitlab-api/lib/Gitlab/Api/Groups.php  |  142 +-
 .../lib/Gitlab/Api/IssueBoards.php            |   88 ++
 .../php-gitlab-api/lib/Gitlab/Api/Issues.php  |  143 +-
 .../php-gitlab-api/lib/Gitlab/Api/Jobs.php    |  178 +++
 .../lib/Gitlab/Api/MergeRequests.php          |  213 +--
 .../lib/Gitlab/Api/Milestones.php             |   28 +-
 .../lib/Gitlab/Api/ProjectNamespaces.php      |   30 +-
 .../lib/Gitlab/Api/Projects.php               |  465 +++---
 .../lib/Gitlab/Api/Repositories.php           |  257 ++--
 .../lib/Gitlab/Api/RepositoryFiles.php        |  135 ++
 .../lib/Gitlab/Api/Snippets.php               |   11 +
 .../php-gitlab-api/lib/Gitlab/Api/Users.php   |  133 +-
 .../php-gitlab-api/lib/Gitlab/Api/Version.php |    9 +
 .../php-gitlab-api/lib/Gitlab/Client.php      |  391 +++--
 .../lib/Gitlab/Exception/ErrorException.php   |    3 +-
 .../Gitlab/Exception/ExceptionInterface.php   |   12 +
 .../Exception/InvalidArgumentException.php    |    3 +-
 .../Exception/MissingArgumentException.php    |    2 +-
 .../lib/Gitlab/Exception/RuntimeException.php |    3 +-
 .../Exception/ValidationFailedException.php   |    3 +-
 .../lib/Gitlab/HttpClient/Builder.php         |  118 ++
 .../lib/Gitlab/HttpClient/HttpClient.php      |  231 ---
 .../Gitlab/HttpClient/HttpClientInterface.php |   98 --
 .../HttpClient/Listener/AuthListener.php      |   95 --
 .../HttpClient/Listener/ErrorListener.php     |   97 --
 .../Listener/PaginationListener.php           |   38 -
 .../Gitlab/HttpClient/Message/FormRequest.php |    8 -
 .../HttpClient/Message/QueryStringBuilder.php |   76 +
 .../lib/Gitlab/HttpClient/Message/Request.php |    8 -
 .../Gitlab/HttpClient/Message/Response.php    |   48 -
 .../HttpClient/Message/ResponseMediator.php   |   73 +
 .../Gitlab/HttpClient/Plugin/ApiVersion.php   |   29 +
 .../HttpClient/Plugin/Authentication.php      |   86 ++
 .../Plugin/GitlabExceptionThrower.php         |   86 ++
 .../lib/Gitlab/HttpClient/Plugin/History.php  |   44 +
 .../lib/Gitlab/Model/Branch.php               |   26 +-
 .../php-gitlab-api/lib/Gitlab/Model/Group.php |   17 +-
 .../php-gitlab-api/lib/Gitlab/Model/Hook.php  |    6 +-
 .../php-gitlab-api/lib/Gitlab/Model/Issue.php |   16 +-
 .../php-gitlab-api/lib/Gitlab/Model/Job.php   |   83 ++
 .../lib/Gitlab/Model/MergeRequest.php         |   18 +-
 .../lib/Gitlab/Model/Milestone.php            |    8 +-
 .../lib/Gitlab/Model/Pipeline.php             |   49 +
 .../lib/Gitlab/Model/Project.php              |  313 ++--
 .../lib/Gitlab/Model/ProjectHook.php          |   12 +-
 .../lib/Gitlab/Model/Session.php              |    6 +-
 .../lib/Gitlab/Model/Snippet.php              |   10 +-
 .../php-gitlab-api/lib/Gitlab/Model/User.php  |   20 +-
 .../php-gitlab-api/lib/Gitlab/ResultPager.php |   27 +-
 .../php-gitlab-api/phpunit.xml.dist           |   25 -
 .../test/Gitlab/Tests/Api/AbstractApiTest.php |  177 ---
 .../test/Gitlab/Tests/Api/ApiTestCase.php     |   23 -
 .../test/Gitlab/Tests/Api/DeployKeysTest.php  |   51 -
 .../test/Gitlab/Tests/Api/GroupsTest.php      |  264 ----
 .../test/Gitlab/Tests/Api/IssuesTest.php      |  279 ----
 .../test/Gitlab/Tests/Api/KeysTest.php        |   26 -
 .../Gitlab/Tests/Api/MergeRequestsTest.php    |  368 -----
 .../test/Gitlab/Tests/Api/MilestonesTest.php  |  100 --
 .../Tests/Api/ProjectNamespacesTest.php       |   70 -
 .../test/Gitlab/Tests/Api/ProjectsTest.php    | 1098 --------------
 .../Gitlab/Tests/Api/RepositoriesTest.php     |  708 ---------
 .../test/Gitlab/Tests/Api/SnippetsTest.php    |  114 --
 .../test/Gitlab/Tests/Api/SystemHooksTest.php |   80 -
 .../test/Gitlab/Tests/Api/TagsTest.php        |   87 --
 .../test/Gitlab/Tests/Api/TestCase.php        |   38 -
 .../test/Gitlab/Tests/Api/UsersTest.php       |  459 ------
 .../php-gitlab-api/test/bootstrap.php         |   18 -
 vendor/php-http/client-common/CHANGELOG.md    |  137 ++
 vendor/php-http/client-common/LICENSE         |   19 +
 vendor/php-http/client-common/README.md       |   55 +
 vendor/php-http/client-common/composer.json   |   43 +
 .../client-common/src/BatchClient.php         |   73 +
 .../client-common/src/BatchResult.php         |  181 +++
 .../src/EmulatedHttpAsyncClient.php           |   27 +
 .../client-common/src/EmulatedHttpClient.php  |   27 +
 .../src/Exception/BatchException.php          |   39 +
 .../CircularRedirectionException.php          |   14 +
 .../src/Exception/ClientErrorException.php    |   14 +
 .../Exception/HttpClientNotFoundException.php |   14 +
 .../src/Exception/LoopException.php           |   14 +
 .../MultipleRedirectionException.php          |   14 +
 .../src/Exception/ServerErrorException.php    |   14 +
 .../client-common/src/FlexibleHttpClient.php  |   39 +
 .../src/HttpAsyncClientDecorator.php          |   29 +
 .../src/HttpAsyncClientEmulator.php           |   36 +
 .../client-common/src/HttpClientDecorator.php |   29 +
 .../client-common/src/HttpClientEmulator.php  |   32 +
 .../client-common/src/HttpClientPool.php      |   59 +
 .../HttpClientPool/LeastUsedClientPool.php    |   45 +
 .../src/HttpClientPool/RandomClientPool.php   |   31 +
 .../HttpClientPool/RoundRobinClientPool.php   |   41 +
 .../client-common/src/HttpClientPoolItem.php  |  178 +++
 .../client-common/src/HttpClientRouter.php    |   74 +
 .../client-common/src/HttpMethodsClient.php   |  205 +++
 vendor/php-http/client-common/src/Plugin.php  |   32 +
 .../src/Plugin/AddHostPlugin.php              |   77 +
 .../src/Plugin/AddPathPlugin.php              |   48 +
 .../src/Plugin/AuthenticationPlugin.php       |   38 +
 .../src/Plugin/BaseUriPlugin.php              |   54 +
 .../src/Plugin/ContentLengthPlugin.php        |   36 +
 .../src/Plugin/ContentTypePlugin.php          |  123 ++
 .../client-common/src/Plugin/CookiePlugin.php |  180 +++
 .../src/Plugin/DecoderPlugin.php              |  140 ++
 .../client-common/src/Plugin/ErrorPlugin.php  |   55 +
 .../src/Plugin/HeaderAppendPlugin.php         |   45 +
 .../src/Plugin/HeaderDefaultsPlugin.php       |   43 +
 .../src/Plugin/HeaderRemovePlugin.php         |   41 +
 .../src/Plugin/HeaderSetPlugin.php            |   41 +
 .../src/Plugin/HistoryPlugin.php              |   49 +
 .../client-common/src/Plugin/Journal.php      |   31 +
 .../src/Plugin/QueryDefaultsPlugin.php        |   54 +
 .../src/Plugin/RedirectPlugin.php             |  270 ++++
 .../src/Plugin/RequestMatcherPlugin.php       |   47 +
 .../client-common/src/Plugin/RetryPlugin.php  |  122 ++
 .../client-common/src/PluginClient.php        |  179 +++
 .../client-common/src/PluginClientFactory.php |   62 +
 vendor/php-http/guzzle6-adapter/CHANGELOG.md  |   66 +
 vendor/php-http/guzzle6-adapter/LICENSE       |   20 +
 vendor/php-http/guzzle6-adapter/README.md     |   59 +
 vendor/php-http/guzzle6-adapter/composer.json |   49 +
 vendor/php-http/guzzle6-adapter/puli.json     |   16 +
 .../php-http/guzzle6-adapter/src/Client.php   |   84 ++
 .../php-http/guzzle6-adapter/src/Promise.php  |  140 ++
 .../multipart-stream-builder/CHANGELOG.md     |   60 +
 .../php-http/multipart-stream-builder/LICENSE |   19 +
 .../multipart-stream-builder/README.md        |   37 +
 .../multipart-stream-builder/appveyor.yml     |   39 +
 .../multipart-stream-builder/composer.json    |   43 +
 .../src/ApacheMimetypeHelper.php              |  142 ++
 .../src/CustomMimetypeHelper.php              |   51 +
 .../src/MimetypeHelper.php                    |   27 +
 .../src/MultipartStreamBuilder.php            |  278 ++++
 237 files changed, 24071 insertions(+), 5708 deletions(-)
 create mode 100644 vendor/guzzlehttp/guzzle/CHANGELOG.md
 create mode 100644 vendor/guzzlehttp/guzzle/LICENSE
 create mode 100644 vendor/guzzlehttp/guzzle/README.md
 create mode 100644 vendor/guzzlehttp/guzzle/UPGRADING.md
 create mode 100644 vendor/guzzlehttp/guzzle/composer.json
 create mode 100644 vendor/guzzlehttp/guzzle/src/Client.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/ClientInterface.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Exception/ClientException.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Exception/RequestException.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Exception/SeekException.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Exception/ServerException.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Exception/TransferException.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Handler/Proxy.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/HandlerStack.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/MessageFormatter.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Middleware.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/Pool.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/RequestOptions.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/RetryMiddleware.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/TransferStats.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/UriTemplate.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/functions.php
 create mode 100644 vendor/guzzlehttp/guzzle/src/functions_include.php
 create mode 100644 vendor/guzzlehttp/promises/CHANGELOG.md
 create mode 100644 vendor/guzzlehttp/promises/LICENSE
 create mode 100644 vendor/guzzlehttp/promises/Makefile
 create mode 100644 vendor/guzzlehttp/promises/README.md
 create mode 100644 vendor/guzzlehttp/promises/composer.json
 create mode 100644 vendor/guzzlehttp/promises/src/AggregateException.php
 create mode 100644 vendor/guzzlehttp/promises/src/CancellationException.php
 create mode 100644 vendor/guzzlehttp/promises/src/Coroutine.php
 create mode 100644 vendor/guzzlehttp/promises/src/EachPromise.php
 create mode 100644 vendor/guzzlehttp/promises/src/FulfilledPromise.php
 create mode 100644 vendor/guzzlehttp/promises/src/Promise.php
 create mode 100644 vendor/guzzlehttp/promises/src/PromiseInterface.php
 create mode 100644 vendor/guzzlehttp/promises/src/PromisorInterface.php
 create mode 100644 vendor/guzzlehttp/promises/src/RejectedPromise.php
 create mode 100644 vendor/guzzlehttp/promises/src/RejectionException.php
 create mode 100644 vendor/guzzlehttp/promises/src/TaskQueue.php
 create mode 100644 vendor/guzzlehttp/promises/src/TaskQueueInterface.php
 create mode 100644 vendor/guzzlehttp/promises/src/functions.php
 create mode 100644 vendor/guzzlehttp/promises/src/functions_include.php
 create mode 100644 vendor/guzzlehttp/psr7/CHANGELOG.md
 create mode 100644 vendor/guzzlehttp/psr7/LICENSE
 create mode 100644 vendor/guzzlehttp/psr7/README.md
 create mode 100644 vendor/guzzlehttp/psr7/composer.json
 create mode 100644 vendor/guzzlehttp/psr7/src/AppendStream.php
 create mode 100644 vendor/guzzlehttp/psr7/src/BufferStream.php
 create mode 100644 vendor/guzzlehttp/psr7/src/CachingStream.php
 create mode 100644 vendor/guzzlehttp/psr7/src/DroppingStream.php
 create mode 100644 vendor/guzzlehttp/psr7/src/FnStream.php
 create mode 100644 vendor/guzzlehttp/psr7/src/InflateStream.php
 create mode 100644 vendor/guzzlehttp/psr7/src/LazyOpenStream.php
 create mode 100644 vendor/guzzlehttp/psr7/src/LimitStream.php
 create mode 100644 vendor/guzzlehttp/psr7/src/MessageTrait.php
 create mode 100644 vendor/guzzlehttp/psr7/src/MultipartStream.php
 create mode 100644 vendor/guzzlehttp/psr7/src/NoSeekStream.php
 create mode 100644 vendor/guzzlehttp/psr7/src/PumpStream.php
 create mode 100644 vendor/guzzlehttp/psr7/src/Request.php
 create mode 100644 vendor/guzzlehttp/psr7/src/Response.php
 create mode 100644 vendor/guzzlehttp/psr7/src/ServerRequest.php
 create mode 100644 vendor/guzzlehttp/psr7/src/Stream.php
 create mode 100644 vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php
 create mode 100644 vendor/guzzlehttp/psr7/src/StreamWrapper.php
 create mode 100644 vendor/guzzlehttp/psr7/src/UploadedFile.php
 create mode 100644 vendor/guzzlehttp/psr7/src/Uri.php
 create mode 100644 vendor/guzzlehttp/psr7/src/UriNormalizer.php
 create mode 100644 vendor/guzzlehttp/psr7/src/UriResolver.php
 create mode 100644 vendor/guzzlehttp/psr7/src/functions.php
 create mode 100644 vendor/guzzlehttp/psr7/src/functions_include.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/.gitignore
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/.travis.yml
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/README.md
 create mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Deployments.php
 create mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Environments.php
 create mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/IssueBoards.php
 create mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Jobs.php
 create mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/RepositoryFiles.php
 create mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Version.php
 create mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/ExceptionInterface.php
 create mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Builder.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/HttpClient.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/HttpClientInterface.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Listener/AuthListener.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Listener/ErrorListener.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Listener/PaginationListener.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/FormRequest.php
 create mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/QueryStringBuilder.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/Request.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/Response.php
 create mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/ResponseMediator.php
 create mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Plugin/ApiVersion.php
 create mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Plugin/Authentication.php
 create mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Plugin/GitlabExceptionThrower.php
 create mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Plugin/History.php
 create mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Job.php
 create mode 100644 vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Pipeline.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/phpunit.xml.dist
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/AbstractApiTest.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/ApiTestCase.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/DeployKeysTest.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/GroupsTest.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/IssuesTest.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/KeysTest.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/MergeRequestsTest.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/MilestonesTest.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/ProjectNamespacesTest.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/ProjectsTest.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/RepositoriesTest.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/SnippetsTest.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/SystemHooksTest.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/TagsTest.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/TestCase.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/UsersTest.php
 delete mode 100644 vendor/m4tthumphrey/php-gitlab-api/test/bootstrap.php
 create mode 100644 vendor/php-http/client-common/CHANGELOG.md
 create mode 100644 vendor/php-http/client-common/LICENSE
 create mode 100644 vendor/php-http/client-common/README.md
 create mode 100644 vendor/php-http/client-common/composer.json
 create mode 100644 vendor/php-http/client-common/src/BatchClient.php
 create mode 100644 vendor/php-http/client-common/src/BatchResult.php
 create mode 100644 vendor/php-http/client-common/src/EmulatedHttpAsyncClient.php
 create mode 100644 vendor/php-http/client-common/src/EmulatedHttpClient.php
 create mode 100644 vendor/php-http/client-common/src/Exception/BatchException.php
 create mode 100644 vendor/php-http/client-common/src/Exception/CircularRedirectionException.php
 create mode 100644 vendor/php-http/client-common/src/Exception/ClientErrorException.php
 create mode 100644 vendor/php-http/client-common/src/Exception/HttpClientNotFoundException.php
 create mode 100644 vendor/php-http/client-common/src/Exception/LoopException.php
 create mode 100644 vendor/php-http/client-common/src/Exception/MultipleRedirectionException.php
 create mode 100644 vendor/php-http/client-common/src/Exception/ServerErrorException.php
 create mode 100644 vendor/php-http/client-common/src/FlexibleHttpClient.php
 create mode 100644 vendor/php-http/client-common/src/HttpAsyncClientDecorator.php
 create mode 100644 vendor/php-http/client-common/src/HttpAsyncClientEmulator.php
 create mode 100644 vendor/php-http/client-common/src/HttpClientDecorator.php
 create mode 100644 vendor/php-http/client-common/src/HttpClientEmulator.php
 create mode 100644 vendor/php-http/client-common/src/HttpClientPool.php
 create mode 100644 vendor/php-http/client-common/src/HttpClientPool/LeastUsedClientPool.php
 create mode 100644 vendor/php-http/client-common/src/HttpClientPool/RandomClientPool.php
 create mode 100644 vendor/php-http/client-common/src/HttpClientPool/RoundRobinClientPool.php
 create mode 100644 vendor/php-http/client-common/src/HttpClientPoolItem.php
 create mode 100644 vendor/php-http/client-common/src/HttpClientRouter.php
 create mode 100644 vendor/php-http/client-common/src/HttpMethodsClient.php
 create mode 100644 vendor/php-http/client-common/src/Plugin.php
 create mode 100644 vendor/php-http/client-common/src/Plugin/AddHostPlugin.php
 create mode 100644 vendor/php-http/client-common/src/Plugin/AddPathPlugin.php
 create mode 100644 vendor/php-http/client-common/src/Plugin/AuthenticationPlugin.php
 create mode 100644 vendor/php-http/client-common/src/Plugin/BaseUriPlugin.php
 create mode 100644 vendor/php-http/client-common/src/Plugin/ContentLengthPlugin.php
 create mode 100644 vendor/php-http/client-common/src/Plugin/ContentTypePlugin.php
 create mode 100644 vendor/php-http/client-common/src/Plugin/CookiePlugin.php
 create mode 100644 vendor/php-http/client-common/src/Plugin/DecoderPlugin.php
 create mode 100644 vendor/php-http/client-common/src/Plugin/ErrorPlugin.php
 create mode 100644 vendor/php-http/client-common/src/Plugin/HeaderAppendPlugin.php
 create mode 100644 vendor/php-http/client-common/src/Plugin/HeaderDefaultsPlugin.php
 create mode 100644 vendor/php-http/client-common/src/Plugin/HeaderRemovePlugin.php
 create mode 100644 vendor/php-http/client-common/src/Plugin/HeaderSetPlugin.php
 create mode 100644 vendor/php-http/client-common/src/Plugin/HistoryPlugin.php
 create mode 100644 vendor/php-http/client-common/src/Plugin/Journal.php
 create mode 100644 vendor/php-http/client-common/src/Plugin/QueryDefaultsPlugin.php
 create mode 100644 vendor/php-http/client-common/src/Plugin/RedirectPlugin.php
 create mode 100644 vendor/php-http/client-common/src/Plugin/RequestMatcherPlugin.php
 create mode 100644 vendor/php-http/client-common/src/Plugin/RetryPlugin.php
 create mode 100644 vendor/php-http/client-common/src/PluginClient.php
 create mode 100644 vendor/php-http/client-common/src/PluginClientFactory.php
 create mode 100644 vendor/php-http/guzzle6-adapter/CHANGELOG.md
 create mode 100644 vendor/php-http/guzzle6-adapter/LICENSE
 create mode 100644 vendor/php-http/guzzle6-adapter/README.md
 create mode 100644 vendor/php-http/guzzle6-adapter/composer.json
 create mode 100644 vendor/php-http/guzzle6-adapter/puli.json
 create mode 100644 vendor/php-http/guzzle6-adapter/src/Client.php
 create mode 100644 vendor/php-http/guzzle6-adapter/src/Promise.php
 create mode 100644 vendor/php-http/multipart-stream-builder/CHANGELOG.md
 create mode 100644 vendor/php-http/multipart-stream-builder/LICENSE
 create mode 100644 vendor/php-http/multipart-stream-builder/README.md
 create mode 100644 vendor/php-http/multipart-stream-builder/appveyor.yml
 create mode 100644 vendor/php-http/multipart-stream-builder/composer.json
 create mode 100644 vendor/php-http/multipart-stream-builder/src/ApacheMimetypeHelper.php
 create mode 100644 vendor/php-http/multipart-stream-builder/src/CustomMimetypeHelper.php
 create mode 100644 vendor/php-http/multipart-stream-builder/src/MimetypeHelper.php
 create mode 100644 vendor/php-http/multipart-stream-builder/src/MultipartStreamBuilder.php

diff --git a/composer.json b/composer.json
index 9f08a564f89..88a5674a9c8 100755
--- a/composer.json
+++ b/composer.json
@@ -34,9 +34,10 @@
         "slim/slim": "^3.8",
         "respect/validation": "^1.1",
         "php-http/curl-client": "^1.7",
-        "m4tthumphrey/php-gitlab-api": "8",
+        "m4tthumphrey/php-gitlab-api": "^9.10",
         "jumbojett/openid-connect-php": "^0.3.0",
         "zf1/zend-search-lucene": "~1.12",
-        "setasign/fpdi-tcpdf": "2.0.0"
+        "setasign/fpdi-tcpdf": "2.0.0",
+        "php-http/guzzle6-adapter": "^1.1"
     }
 }
diff --git a/src/app/resource/controllers/ResController.php b/src/app/resource/controllers/ResController.php
index 67ba464ceab..e9f32e34fef 100755
--- a/src/app/resource/controllers/ResController.php
+++ b/src/app/resource/controllers/ResController.php
@@ -265,6 +265,7 @@ class ResController
                 try {
                     $pdf = new TcpdfFpdi('P', 'pt');
                     $nbPages = $pdf->setSourceFile($pathToDocument);
+                    $pdf->setPrintHeader(false);
                     for ($i = 1; $i <= $nbPages; $i++) {
                         $page = $pdf->importPage($i);
                         $size = $pdf->getTemplateSize($page);
diff --git a/src/app/versionUpdate/controllers/VersionUpdateController.php b/src/app/versionUpdate/controllers/VersionUpdateController.php
index 5fbe2a8e191..801e9d59123 100644
--- a/src/app/versionUpdate/controllers/VersionUpdateController.php
+++ b/src/app/versionUpdate/controllers/VersionUpdateController.php
@@ -28,7 +28,7 @@ class VersionUpdateController
             return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']);
         }
 
-        $client = new Client('https://labs.maarch.org/api/v4/');
+        $client = Client::create('https://labs.maarch.org/api/v4/');
         try {
             $tags = $client->api('tags')->all('12');
         } catch (\Exception $e) {
diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php
index a5479ea55c6..9b45ff26b0f 100644
--- a/vendor/composer/autoload_files.php
+++ b/vendor/composer/autoload_files.php
@@ -6,8 +6,11 @@ $vendorDir = dirname(dirname(__FILE__));
 $baseDir = dirname($vendorDir);
 
 return array(
+    'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
     '253c157292f75eb38082b5acb06f3f01' => $vendorDir . '/nikic/fast-route/src/functions.php',
     'ddc0a4d7e61c0286f0f8593b1903e894' => $vendorDir . '/clue/stream-filter/src/functions.php',
     '8cff32064859f4559445b89279f3199c' => $vendorDir . '/php-http/message/src/filters.php',
+    'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
+    '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
     '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
 );
diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php
index daae60bfc1e..3225edbdd0e 100644
--- a/vendor/composer/autoload_namespaces.php
+++ b/vendor/composer/autoload_namespaces.php
@@ -11,5 +11,4 @@ return array(
     'Zend_Search' => array($vendorDir . '/zf1/zend-search/library'),
     'Zend_Exception' => array($vendorDir . '/zf1/zend-exception/library'),
     'Pimple' => array($vendorDir . '/pimple/pimple/src'),
-    'Gitlab\\' => array($vendorDir . '/m4tthumphrey/php-gitlab-api/lib'),
 );
diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php
index d8a0b24e916..2abc338813c 100644
--- a/vendor/composer/autoload_psr4.php
+++ b/vendor/composer/autoload_psr4.php
@@ -33,12 +33,19 @@ return array(
     'Interop\\Http\\Factory\\' => array($vendorDir . '/http-interop/http-factory/src'),
     'Interop\\Container\\' => array($vendorDir . '/container-interop/container-interop/src/Interop/Container'),
     'Http\\Promise\\' => array($vendorDir . '/php-http/promise/src'),
+    'Http\\Message\\MultipartStream\\' => array($vendorDir . '/php-http/multipart-stream-builder/src'),
     'Http\\Message\\' => array($vendorDir . '/php-http/message-factory/src', $vendorDir . '/php-http/message/src'),
     'Http\\Discovery\\' => array($vendorDir . '/php-http/discovery/src'),
     'Http\\Client\\Curl\\' => array($vendorDir . '/php-http/curl-client/src'),
+    'Http\\Client\\Common\\' => array($vendorDir . '/php-http/client-common/src'),
     'Http\\Client\\' => array($vendorDir . '/php-http/httplug/src'),
+    'Http\\Adapter\\Guzzle6\\' => array($vendorDir . '/php-http/guzzle6-adapter/src'),
     'History\\' => array($baseDir . '/src/app/history'),
+    'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
+    'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
+    'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
     'Group\\' => array($baseDir . '/src/app/group'),
+    'Gitlab\\' => array($vendorDir . '/m4tthumphrey/php-gitlab-api/lib/Gitlab'),
     'Folder\\' => array($baseDir . '/src/app/folder'),
     'FastRoute\\' => array($vendorDir . '/nikic/fast-route/src'),
     'Entity\\' => array($baseDir . '/src/app/entity'),
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
index 5c2c107f54e..8bcb68eaa5f 100644
--- a/vendor/composer/autoload_static.php
+++ b/vendor/composer/autoload_static.php
@@ -7,9 +7,12 @@ namespace Composer\Autoload;
 class ComposerStaticInit3cf41326f2ce1ccc88c4676c4e39ea47
 {
     public static $files = array (
+        'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
         '253c157292f75eb38082b5acb06f3f01' => __DIR__ . '/..' . '/nikic/fast-route/src/functions.php',
         'ddc0a4d7e61c0286f0f8593b1903e894' => __DIR__ . '/..' . '/clue/stream-filter/src/functions.php',
         '8cff32064859f4559445b89279f3199c' => __DIR__ . '/..' . '/php-http/message/src/filters.php',
+        'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
+        '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
         '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
     );
 
@@ -76,15 +79,22 @@ class ComposerStaticInit3cf41326f2ce1ccc88c4676c4e39ea47
         'H' => 
         array (
             'Http\\Promise\\' => 13,
+            'Http\\Message\\MultipartStream\\' => 29,
             'Http\\Message\\' => 13,
             'Http\\Discovery\\' => 15,
             'Http\\Client\\Curl\\' => 17,
+            'Http\\Client\\Common\\' => 19,
             'Http\\Client\\' => 12,
+            'Http\\Adapter\\Guzzle6\\' => 21,
             'History\\' => 8,
         ),
         'G' => 
         array (
+            'GuzzleHttp\\Psr7\\' => 16,
+            'GuzzleHttp\\Promise\\' => 19,
+            'GuzzleHttp\\' => 11,
             'Group\\' => 6,
+            'Gitlab\\' => 7,
         ),
         'F' => 
         array (
@@ -228,6 +238,10 @@ class ComposerStaticInit3cf41326f2ce1ccc88c4676c4e39ea47
         array (
             0 => __DIR__ . '/..' . '/php-http/promise/src',
         ),
+        'Http\\Message\\MultipartStream\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/php-http/multipart-stream-builder/src',
+        ),
         'Http\\Message\\' => 
         array (
             0 => __DIR__ . '/..' . '/php-http/message-factory/src',
@@ -241,18 +255,42 @@ class ComposerStaticInit3cf41326f2ce1ccc88c4676c4e39ea47
         array (
             0 => __DIR__ . '/..' . '/php-http/curl-client/src',
         ),
+        'Http\\Client\\Common\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/php-http/client-common/src',
+        ),
         'Http\\Client\\' => 
         array (
             0 => __DIR__ . '/..' . '/php-http/httplug/src',
         ),
+        'Http\\Adapter\\Guzzle6\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/php-http/guzzle6-adapter/src',
+        ),
         'History\\' => 
         array (
             0 => __DIR__ . '/../..' . '/src/app/history',
         ),
+        'GuzzleHttp\\Psr7\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src',
+        ),
+        'GuzzleHttp\\Promise\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/guzzlehttp/promises/src',
+        ),
+        'GuzzleHttp\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',
+        ),
         'Group\\' => 
         array (
             0 => __DIR__ . '/../..' . '/src/app/group',
         ),
+        'Gitlab\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/m4tthumphrey/php-gitlab-api/lib/Gitlab',
+        ),
         'Folder\\' => 
         array (
             0 => __DIR__ . '/../..' . '/src/app/folder',
@@ -334,13 +372,6 @@ class ComposerStaticInit3cf41326f2ce1ccc88c4676c4e39ea47
                 0 => __DIR__ . '/..' . '/pimple/pimple/src',
             ),
         ),
-        'G' => 
-        array (
-            'Gitlab\\' => 
-            array (
-                0 => __DIR__ . '/..' . '/m4tthumphrey/php-gitlab-api/lib',
-            ),
-        ),
     );
 
     public static $classMap = array (
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index 950519a81b0..b110d3d9201 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -174,64 +174,6 @@
         "notification-url": "https://packagist.org/downloads/",
         "description": "Bare-bones OpenID Connect client"
     },
-    {
-        "name": "m4tthumphrey/php-gitlab-api",
-        "version": "8.0.0",
-        "version_normalized": "8.0.0.0",
-        "source": {
-            "type": "git",
-            "url": "https://github.com/m4tthumphrey/php-gitlab-api.git",
-            "reference": "51242d88b68d30a0f17662e481e96561bcf846d0"
-        },
-        "dist": {
-            "type": "zip",
-            "url": "https://api.github.com/repos/m4tthumphrey/php-gitlab-api/zipball/51242d88b68d30a0f17662e481e96561bcf846d0",
-            "reference": "51242d88b68d30a0f17662e481e96561bcf846d0",
-            "shasum": ""
-        },
-        "require": {
-            "ext-curl": "*",
-            "ext-xml": "*",
-            "kriswallsmith/buzz": ">=0.7",
-            "php": ">=5.3.2"
-        },
-        "require-dev": {
-            "phpunit/phpunit": "~4.5"
-        },
-        "time": "2017-06-06T07:40:46+00:00",
-        "type": "library",
-        "installation-source": "dist",
-        "autoload": {
-            "psr-0": {
-                "Gitlab\\": "lib/"
-            }
-        },
-        "notification-url": "https://packagist.org/downloads/",
-        "license": [
-            "MIT"
-        ],
-        "authors": [
-            {
-                "name": "Thibault Duplessis",
-                "email": "thibault.duplessis@gmail.com",
-                "homepage": "http://ornicar.github.com"
-            },
-            {
-                "name": "KnpLabs Team",
-                "homepage": "http://knplabs.com"
-            },
-            {
-                "name": "Matt Humphrey",
-                "homepage": "http://m4tt.io"
-            }
-        ],
-        "description": "GitLab API client",
-        "homepage": "https://github.com/m4tthumphrey/php-gitlab-api",
-        "keywords": [
-            "api",
-            "gitlab"
-        ]
-    },
     {
         "name": "php-http/message-factory",
         "version": "v1.0.2",
@@ -1637,5 +1579,446 @@
             "fpdi",
             "pdf"
         ]
+    },
+    {
+        "name": "php-http/multipart-stream-builder",
+        "version": "1.0.0",
+        "version_normalized": "1.0.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/php-http/multipart-stream-builder.git",
+            "reference": "1fa3c623fc813a43b39494b2a1612174e36e0fb0"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/php-http/multipart-stream-builder/zipball/1fa3c623fc813a43b39494b2a1612174e36e0fb0",
+            "reference": "1fa3c623fc813a43b39494b2a1612174e36e0fb0",
+            "shasum": ""
+        },
+        "require": {
+            "php": "^5.5 || ^7.0",
+            "php-http/discovery": "^1.0",
+            "php-http/message-factory": "^1.0.2",
+            "psr/http-message": "^1.0"
+        },
+        "require-dev": {
+            "php-http/message": "^1.5",
+            "phpunit/phpunit": "^4.8 || ^5.4",
+            "zendframework/zend-diactoros": "^1.3.5"
+        },
+        "time": "2017-05-21T17:45:25+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "0.3-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Http\\Message\\MultipartStream\\": "src/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Tobias Nyholm",
+                "email": "tobias.nyholm@gmail.com"
+            }
+        ],
+        "description": "A builder class that help you create a multipart stream",
+        "homepage": "http://php-http.org",
+        "keywords": [
+            "factory",
+            "http",
+            "message",
+            "multipart stream",
+            "stream"
+        ]
+    },
+    {
+        "name": "php-http/client-common",
+        "version": "1.7.0",
+        "version_normalized": "1.7.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/php-http/client-common.git",
+            "reference": "9accb4a082eb06403747c0ffd444112eda41a0fd"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/php-http/client-common/zipball/9accb4a082eb06403747c0ffd444112eda41a0fd",
+            "reference": "9accb4a082eb06403747c0ffd444112eda41a0fd",
+            "shasum": ""
+        },
+        "require": {
+            "php": "^5.4 || ^7.0",
+            "php-http/httplug": "^1.1",
+            "php-http/message": "^1.6",
+            "php-http/message-factory": "^1.0",
+            "symfony/options-resolver": "^2.6 || ^3.0 || ^4.0"
+        },
+        "require-dev": {
+            "guzzlehttp/psr7": "^1.4",
+            "phpspec/phpspec": "^2.5 || ^3.4 || ^4.2"
+        },
+        "suggest": {
+            "php-http/cache-plugin": "PSR-6 Cache plugin",
+            "php-http/logger-plugin": "PSR-3 Logger plugin",
+            "php-http/stopwatch-plugin": "Symfony Stopwatch plugin"
+        },
+        "time": "2017-11-30T11:06:59+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.7-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Http\\Client\\Common\\": "src/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Márk Sági-Kazár",
+                "email": "mark.sagikazar@gmail.com"
+            }
+        ],
+        "description": "Common HTTP Client implementations and tools for HTTPlug",
+        "homepage": "http://httplug.io",
+        "keywords": [
+            "client",
+            "common",
+            "http",
+            "httplug"
+        ]
+    },
+    {
+        "name": "m4tthumphrey/php-gitlab-api",
+        "version": "9.10.0",
+        "version_normalized": "9.10.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/m4tthumphrey/php-gitlab-api.git",
+            "reference": "c946569ae75eff6317a5691ab590b6eb071bdb26"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/m4tthumphrey/php-gitlab-api/zipball/c946569ae75eff6317a5691ab590b6eb071bdb26",
+            "reference": "c946569ae75eff6317a5691ab590b6eb071bdb26",
+            "shasum": ""
+        },
+        "require": {
+            "ext-xml": "*",
+            "php": "^5.6 || ^7.0",
+            "php-http/client-common": "^1.6",
+            "php-http/client-implementation": "^1.0",
+            "php-http/discovery": "^1.2",
+            "php-http/httplug": "^1.1",
+            "php-http/multipart-stream-builder": "^1.0",
+            "symfony/options-resolver": "^2.6 || ^3.0 || ^4.0"
+        },
+        "require-dev": {
+            "guzzlehttp/psr7": "^1.2",
+            "php-http/guzzle6-adapter": "^1.0",
+            "php-http/mock-client": "^1.0",
+            "phpunit/phpunit": "^5.0"
+        },
+        "time": "2018-06-15T13:59:39+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "9.8.x-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Gitlab\\": "lib/Gitlab/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Thibault Duplessis",
+                "email": "thibault.duplessis@gmail.com",
+                "homepage": "http://ornicar.github.com"
+            },
+            {
+                "name": "KnpLabs Team",
+                "homepage": "http://knplabs.com"
+            },
+            {
+                "name": "Matt Humphrey",
+                "homepage": "http://m4tt.io"
+            }
+        ],
+        "description": "GitLab API client",
+        "homepage": "https://github.com/m4tthumphrey/php-gitlab-api",
+        "keywords": [
+            "api",
+            "gitlab"
+        ]
+    },
+    {
+        "name": "guzzlehttp/promises",
+        "version": "v1.3.1",
+        "version_normalized": "1.3.1.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/guzzle/promises.git",
+            "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
+            "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.5.0"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^4.0"
+        },
+        "time": "2016-12-20T10:07:11+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.4-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "GuzzleHttp\\Promise\\": "src/"
+            },
+            "files": [
+                "src/functions_include.php"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Michael Dowling",
+                "email": "mtdowling@gmail.com",
+                "homepage": "https://github.com/mtdowling"
+            }
+        ],
+        "description": "Guzzle promises library",
+        "keywords": [
+            "promise"
+        ]
+    },
+    {
+        "name": "guzzlehttp/psr7",
+        "version": "1.4.2",
+        "version_normalized": "1.4.2.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/guzzle/psr7.git",
+            "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
+            "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.4.0",
+            "psr/http-message": "~1.0"
+        },
+        "provide": {
+            "psr/http-message-implementation": "1.0"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "~4.0"
+        },
+        "time": "2017-03-20T17:10:46+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.4-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "GuzzleHttp\\Psr7\\": "src/"
+            },
+            "files": [
+                "src/functions_include.php"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Michael Dowling",
+                "email": "mtdowling@gmail.com",
+                "homepage": "https://github.com/mtdowling"
+            },
+            {
+                "name": "Tobias Schultze",
+                "homepage": "https://github.com/Tobion"
+            }
+        ],
+        "description": "PSR-7 message implementation that also provides common utility methods",
+        "keywords": [
+            "http",
+            "message",
+            "request",
+            "response",
+            "stream",
+            "uri",
+            "url"
+        ]
+    },
+    {
+        "name": "guzzlehttp/guzzle",
+        "version": "6.3.3",
+        "version_normalized": "6.3.3.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/guzzle/guzzle.git",
+            "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba",
+            "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba",
+            "shasum": ""
+        },
+        "require": {
+            "guzzlehttp/promises": "^1.0",
+            "guzzlehttp/psr7": "^1.4",
+            "php": ">=5.5"
+        },
+        "require-dev": {
+            "ext-curl": "*",
+            "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
+            "psr/log": "^1.0"
+        },
+        "suggest": {
+            "psr/log": "Required for using the Log middleware"
+        },
+        "time": "2018-04-22T15:46:56+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "6.3-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "files": [
+                "src/functions_include.php"
+            ],
+            "psr-4": {
+                "GuzzleHttp\\": "src/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Michael Dowling",
+                "email": "mtdowling@gmail.com",
+                "homepage": "https://github.com/mtdowling"
+            }
+        ],
+        "description": "Guzzle is a PHP HTTP client library",
+        "homepage": "http://guzzlephp.org/",
+        "keywords": [
+            "client",
+            "curl",
+            "framework",
+            "http",
+            "http client",
+            "rest",
+            "web service"
+        ]
+    },
+    {
+        "name": "php-http/guzzle6-adapter",
+        "version": "v1.1.1",
+        "version_normalized": "1.1.1.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/php-http/guzzle6-adapter.git",
+            "reference": "a56941f9dc6110409cfcddc91546ee97039277ab"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/php-http/guzzle6-adapter/zipball/a56941f9dc6110409cfcddc91546ee97039277ab",
+            "reference": "a56941f9dc6110409cfcddc91546ee97039277ab",
+            "shasum": ""
+        },
+        "require": {
+            "guzzlehttp/guzzle": "^6.0",
+            "php": ">=5.5.0",
+            "php-http/httplug": "^1.0"
+        },
+        "provide": {
+            "php-http/async-client-implementation": "1.0",
+            "php-http/client-implementation": "1.0"
+        },
+        "require-dev": {
+            "ext-curl": "*",
+            "php-http/adapter-integration-tests": "^0.4"
+        },
+        "time": "2016-05-10T06:13:32+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.2-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Http\\Adapter\\Guzzle6\\": "src/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Márk Sági-Kazár",
+                "email": "mark.sagikazar@gmail.com"
+            },
+            {
+                "name": "David de Boer",
+                "email": "david@ddeboer.nl"
+            }
+        ],
+        "description": "Guzzle 6 HTTP Adapter",
+        "homepage": "http://httplug.io",
+        "keywords": [
+            "Guzzle",
+            "http"
+        ]
     }
 ]
diff --git a/vendor/guzzlehttp/guzzle/CHANGELOG.md b/vendor/guzzlehttp/guzzle/CHANGELOG.md
new file mode 100644
index 00000000000..17badd75606
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/CHANGELOG.md
@@ -0,0 +1,1287 @@
+# Change Log
+
+## 6.3.3 - 2018-04-22
+
+* Fix: Default headers when decode_content is specified
+
+
+## 6.3.2 - 2018-03-26
+
+* Fix: Release process
+
+
+## 6.3.1 - 2018-03-26
+
+* Bug fix: Parsing 0 epoch expiry times in cookies [#2014](https://github.com/guzzle/guzzle/pull/2014)
+* Improvement: Better ConnectException detection [#2012](https://github.com/guzzle/guzzle/pull/2012)
+* Bug fix: Malformed domain that contains a "/" [#1999](https://github.com/guzzle/guzzle/pull/1999)
+* Bug fix: Undefined offset when a cookie has no first key-value pair [#1998](https://github.com/guzzle/guzzle/pull/1998)
+* Improvement: Support PHPUnit 6 [#1953](https://github.com/guzzle/guzzle/pull/1953)
+* Bug fix: Support empty headers [#1915](https://github.com/guzzle/guzzle/pull/1915)
+* Bug fix: Ignore case during header modifications [#1916](https://github.com/guzzle/guzzle/pull/1916)
+
++ Minor code cleanups, documentation fixes and clarifications.
+
+
+## 6.3.0 - 2017-06-22
+
+* Feature: force IP resolution (ipv4 or ipv6) [#1608](https://github.com/guzzle/guzzle/pull/1608), [#1659](https://github.com/guzzle/guzzle/pull/1659)
+* Improvement: Don't include summary in exception message when body is empty [#1621](https://github.com/guzzle/guzzle/pull/1621)
+* Improvement: Handle `on_headers` option in MockHandler [#1580](https://github.com/guzzle/guzzle/pull/1580)
+* Improvement: Added SUSE Linux CA path [#1609](https://github.com/guzzle/guzzle/issues/1609)
+* Improvement: Use class reference for getting the name of the class instead of using hardcoded strings [#1641](https://github.com/guzzle/guzzle/pull/1641)
+* Feature: Added `read_timeout` option [#1611](https://github.com/guzzle/guzzle/pull/1611)
+* Bug fix: PHP 7.x fixes [#1685](https://github.com/guzzle/guzzle/pull/1685), [#1686](https://github.com/guzzle/guzzle/pull/1686), [#1811](https://github.com/guzzle/guzzle/pull/1811)
+* Deprecation: BadResponseException instantiation without a response [#1642](https://github.com/guzzle/guzzle/pull/1642)
+* Feature: Added NTLM auth [#1569](https://github.com/guzzle/guzzle/pull/1569)
+* Feature: Track redirect HTTP status codes [#1711](https://github.com/guzzle/guzzle/pull/1711)
+* Improvement: Check handler type during construction [#1745](https://github.com/guzzle/guzzle/pull/1745)
+* Improvement: Always include the Content-Length if there's a body [#1721](https://github.com/guzzle/guzzle/pull/1721)
+* Feature: Added convenience method to access a cookie by name [#1318](https://github.com/guzzle/guzzle/pull/1318)
+* Bug fix: Fill `CURLOPT_CAPATH` and `CURLOPT_CAINFO` properly [#1684](https://github.com/guzzle/guzzle/pull/1684)
+* Improvement:  	Use `\GuzzleHttp\Promise\rejection_for` function instead of object init [#1827](https://github.com/guzzle/guzzle/pull/1827)
+
+
++ Minor code cleanups, documentation fixes and clarifications.
+
+## 6.2.3 - 2017-02-28
+
+* Fix deprecations with guzzle/psr7 version 1.4
+
+## 6.2.2 - 2016-10-08
+
+* Allow to pass nullable Response to delay callable
+* Only add scheme when host is present
+* Fix drain case where content-length is the literal string zero
+* Obfuscate in-URL credentials in exceptions
+
+## 6.2.1 - 2016-07-18
+
+* Address HTTP_PROXY security vulnerability, CVE-2016-5385:
+  https://httpoxy.org/
+* Fixing timeout bug with StreamHandler:
+  https://github.com/guzzle/guzzle/pull/1488
+* Only read up to `Content-Length` in PHP StreamHandler to avoid timeouts when
+  a server does not honor `Connection: close`.
+* Ignore URI fragment when sending requests.
+
+## 6.2.0 - 2016-03-21
+
+* Feature: added `GuzzleHttp\json_encode` and `GuzzleHttp\json_decode`.
+  https://github.com/guzzle/guzzle/pull/1389
+* Bug fix: Fix sleep calculation when waiting for delayed requests.
+  https://github.com/guzzle/guzzle/pull/1324
+* Feature: More flexible history containers.
+  https://github.com/guzzle/guzzle/pull/1373
+* Bug fix: defer sink stream opening in StreamHandler.
+  https://github.com/guzzle/guzzle/pull/1377
+* Bug fix: do not attempt to escape cookie values.
+  https://github.com/guzzle/guzzle/pull/1406
+* Feature: report original content encoding and length on decoded responses.
+  https://github.com/guzzle/guzzle/pull/1409
+* Bug fix: rewind seekable request bodies before dispatching to cURL.
+  https://github.com/guzzle/guzzle/pull/1422
+* Bug fix: provide an empty string to `http_build_query` for HHVM workaround.
+  https://github.com/guzzle/guzzle/pull/1367
+
+## 6.1.1 - 2015-11-22
+
+* Bug fix: Proxy::wrapSync() now correctly proxies to the appropriate handler
+  https://github.com/guzzle/guzzle/commit/911bcbc8b434adce64e223a6d1d14e9a8f63e4e4
+* Feature: HandlerStack is now more generic.
+  https://github.com/guzzle/guzzle/commit/f2102941331cda544745eedd97fc8fd46e1ee33e
+* Bug fix: setting verify to false in the StreamHandler now disables peer
+  verification. https://github.com/guzzle/guzzle/issues/1256
+* Feature: Middleware now uses an exception factory, including more error
+  context. https://github.com/guzzle/guzzle/pull/1282
+* Feature: better support for disabled functions.
+  https://github.com/guzzle/guzzle/pull/1287
+* Bug fix: fixed regression where MockHandler was not using `sink`.
+  https://github.com/guzzle/guzzle/pull/1292
+
+## 6.1.0 - 2015-09-08
+
+* Feature: Added the `on_stats` request option to provide access to transfer
+  statistics for requests. https://github.com/guzzle/guzzle/pull/1202
+* Feature: Added the ability to persist session cookies in CookieJars.
+  https://github.com/guzzle/guzzle/pull/1195
+* Feature: Some compatibility updates for Google APP Engine
+  https://github.com/guzzle/guzzle/pull/1216
+* Feature: Added support for NO_PROXY to prevent the use of a proxy based on
+  a simple set of rules. https://github.com/guzzle/guzzle/pull/1197
+* Feature: Cookies can now contain square brackets.
+  https://github.com/guzzle/guzzle/pull/1237
+* Bug fix: Now correctly parsing `=` inside of quotes in Cookies.
+  https://github.com/guzzle/guzzle/pull/1232
+* Bug fix: Cusotm cURL options now correctly override curl options of the
+  same name. https://github.com/guzzle/guzzle/pull/1221
+* Bug fix: Content-Type header is now added when using an explicitly provided
+  multipart body. https://github.com/guzzle/guzzle/pull/1218
+* Bug fix: Now ignoring Set-Cookie headers that have no name.
+* Bug fix: Reason phrase is no longer cast to an int in some cases in the
+  cURL handler. https://github.com/guzzle/guzzle/pull/1187
+* Bug fix: Remove the Authorization header when redirecting if the Host
+  header changes. https://github.com/guzzle/guzzle/pull/1207
+* Bug fix: Cookie path matching fixes
+  https://github.com/guzzle/guzzle/issues/1129
+* Bug fix: Fixing the cURL `body_as_string` setting
+  https://github.com/guzzle/guzzle/pull/1201
+* Bug fix: quotes are no longer stripped when parsing cookies.
+  https://github.com/guzzle/guzzle/issues/1172
+* Bug fix: `form_params` and `query` now always uses the `&` separator.
+  https://github.com/guzzle/guzzle/pull/1163
+* Bug fix: Adding a Content-Length to PHP stream wrapper requests if not set.
+  https://github.com/guzzle/guzzle/pull/1189
+
+## 6.0.2 - 2015-07-04
+
+* Fixed a memory leak in the curl handlers in which references to callbacks
+  were not being removed by `curl_reset`.
+* Cookies are now extracted properly before redirects.
+* Cookies now allow more character ranges.
+* Decoded Content-Encoding responses are now modified to correctly reflect
+  their state if the encoding was automatically removed by a handler. This
+  means that the `Content-Encoding` header may be removed an the
+  `Content-Length` modified to reflect the message size after removing the
+  encoding.
+* Added a more explicit error message when trying to use `form_params` and
+  `multipart` in the same request.
+* Several fixes for HHVM support.
+* Functions are now conditionally required using an additional level of
+  indirection to help with global Composer installations.
+
+## 6.0.1 - 2015-05-27
+
+* Fixed a bug with serializing the `query` request option where the `&`
+  separator was missing.
+* Added a better error message for when `body` is provided as an array. Please
+  use `form_params` or `multipart` instead.
+* Various doc fixes.
+
+## 6.0.0 - 2015-05-26
+
+* See the UPGRADING.md document for more information.
+* Added `multipart` and `form_params` request options.
+* Added `synchronous` request option.
+* Added the `on_headers` request option.
+* Fixed `expect` handling.
+* No longer adding default middlewares in the client ctor. These need to be
+  present on the provided handler in order to work.
+* Requests are no longer initiated when sending async requests with the
+  CurlMultiHandler. This prevents unexpected recursion from requests completing
+  while ticking the cURL loop.
+* Removed the semantics of setting `default` to `true`. This is no longer
+  required now that the cURL loop is not ticked for async requests.
+* Added request and response logging middleware.
+* No longer allowing self signed certificates when using the StreamHandler.
+* Ensuring that `sink` is valid if saving to a file.
+* Request exceptions now include a "handler context" which provides handler
+  specific contextual information.
+* Added `GuzzleHttp\RequestOptions` to allow request options to be applied
+  using constants.
+* `$maxHandles` has been removed from CurlMultiHandler.
+* `MultipartPostBody` is now part of the `guzzlehttp/psr7` package.
+
+## 5.3.0 - 2015-05-19
+
+* Mock now supports `save_to`
+* Marked `AbstractRequestEvent::getTransaction()` as public.
+* Fixed a bug in which multiple headers using different casing would overwrite
+  previous headers in the associative array.
+* Added `Utils::getDefaultHandler()`
+* Marked `GuzzleHttp\Client::getDefaultUserAgent` as deprecated.
+* URL scheme is now always lowercased.
+
+## 6.0.0-beta.1
+
+* Requires PHP >= 5.5
+* Updated to use PSR-7
+  * Requires immutable messages, which basically means an event based system
+    owned by a request instance is no longer possible.
+  * Utilizing the [Guzzle PSR-7 package](https://github.com/guzzle/psr7).
+  * Removed the dependency on `guzzlehttp/streams`. These stream abstractions
+    are available in the `guzzlehttp/psr7` package under the `GuzzleHttp\Psr7`
+    namespace.
+* Added middleware and handler system
+  * Replaced the Guzzle event and subscriber system with a middleware system.
+  * No longer depends on RingPHP, but rather places the HTTP handlers directly
+    in Guzzle, operating on PSR-7 messages.
+  * Retry logic is now encapsulated in `GuzzleHttp\Middleware::retry`, which
+    means the `guzzlehttp/retry-subscriber` is now obsolete.
+  * Mocking responses is now handled using `GuzzleHttp\Handler\MockHandler`.
+* Asynchronous responses
+  * No longer supports the `future` request option to send an async request.
+    Instead, use one of the `*Async` methods of a client (e.g., `requestAsync`,
+    `getAsync`, etc.).
+  * Utilizing `GuzzleHttp\Promise` instead of React's promise library to avoid
+    recursion required by chaining and forwarding react promises. See
+    https://github.com/guzzle/promises
+  * Added `requestAsync` and `sendAsync` to send request asynchronously.
+  * Added magic methods for `getAsync()`, `postAsync()`, etc. to send requests
+    asynchronously.
+* Request options
+  * POST and form updates
+    * Added the `form_fields` and `form_files` request options.
+    * Removed the `GuzzleHttp\Post` namespace.
+    * The `body` request option no longer accepts an array for POST requests.
+  * The `exceptions` request option has been deprecated in favor of the
+    `http_errors` request options.
+  * The `save_to` request option has been deprecated in favor of `sink` request
+    option.
+* Clients no longer accept an array of URI template string and variables for
+  URI variables. You will need to expand URI templates before passing them
+  into a client constructor or request method.
+* Client methods `get()`, `post()`, `put()`, `patch()`, `options()`, etc. are
+  now magic methods that will send synchronous requests.
+* Replaced `Utils.php` with plain functions in `functions.php`.
+* Removed `GuzzleHttp\Collection`.
+* Removed `GuzzleHttp\BatchResults`. Batched pool results are now returned as
+  an array.
+* Removed `GuzzleHttp\Query`. Query string handling is now handled using an
+  associative array passed into the `query` request option. The query string
+  is serialized using PHP's `http_build_query`. If you need more control, you
+  can pass the query string in as a string.
+* `GuzzleHttp\QueryParser` has been replaced with the
+  `GuzzleHttp\Psr7\parse_query`.
+
+## 5.2.0 - 2015-01-27
+
+* Added `AppliesHeadersInterface` to make applying headers to a request based
+  on the body more generic and not specific to `PostBodyInterface`.
+* Reduced the number of stack frames needed to send requests.
+* Nested futures are now resolved in the client rather than the RequestFsm
+* Finishing state transitions is now handled in the RequestFsm rather than the
+  RingBridge.
+* Added a guard in the Pool class to not use recursion for request retries.
+
+## 5.1.0 - 2014-12-19
+
+* Pool class no longer uses recursion when a request is intercepted.
+* The size of a Pool can now be dynamically adjusted using a callback.
+  See https://github.com/guzzle/guzzle/pull/943.
+* Setting a request option to `null` when creating a request with a client will
+  ensure that the option is not set. This allows you to overwrite default
+  request options on a per-request basis.
+  See https://github.com/guzzle/guzzle/pull/937.
+* Added the ability to limit which protocols are allowed for redirects by
+  specifying a `protocols` array in the `allow_redirects` request option.
+* Nested futures due to retries are now resolved when waiting for synchronous
+  responses. See https://github.com/guzzle/guzzle/pull/947.
+* `"0"` is now an allowed URI path. See
+  https://github.com/guzzle/guzzle/pull/935.
+* `Query` no longer typehints on the `$query` argument in the constructor,
+  allowing for strings and arrays.
+* Exceptions thrown in the `end` event are now correctly wrapped with Guzzle
+  specific exceptions if necessary.
+
+## 5.0.3 - 2014-11-03
+
+This change updates query strings so that they are treated as un-encoded values
+by default where the value represents an un-encoded value to send over the
+wire. A Query object then encodes the value before sending over the wire. This
+means that even value query string values (e.g., ":") are url encoded. This
+makes the Query class match PHP's http_build_query function. However, if you
+want to send requests over the wire using valid query string characters that do
+not need to be encoded, then you can provide a string to Url::setQuery() and
+pass true as the second argument to specify that the query string is a raw
+string that should not be parsed or encoded (unless a call to getQuery() is
+subsequently made, forcing the query-string to be converted into a Query
+object).
+
+## 5.0.2 - 2014-10-30
+
+* Added a trailing `\r\n` to multipart/form-data payloads. See
+  https://github.com/guzzle/guzzle/pull/871
+* Added a `GuzzleHttp\Pool::send()` convenience method to match the docs.
+* Status codes are now returned as integers. See
+  https://github.com/guzzle/guzzle/issues/881
+* No longer overwriting an existing `application/x-www-form-urlencoded` header
+  when sending POST requests, allowing for customized headers. See
+  https://github.com/guzzle/guzzle/issues/877
+* Improved path URL serialization.
+
+  * No longer double percent-encoding characters in the path or query string if
+    they are already encoded.
+  * Now properly encoding the supplied path to a URL object, instead of only
+    encoding ' ' and '?'.
+  * Note: This has been changed in 5.0.3 to now encode query string values by
+    default unless the `rawString` argument is provided when setting the query
+    string on a URL: Now allowing many more characters to be present in the
+    query string without being percent encoded. See http://tools.ietf.org/html/rfc3986#appendix-A
+
+## 5.0.1 - 2014-10-16
+
+Bugfix release.
+
+* Fixed an issue where connection errors still returned response object in
+  error and end events event though the response is unusable. This has been
+  corrected so that a response is not returned in the `getResponse` method of
+  these events if the response did not complete. https://github.com/guzzle/guzzle/issues/867
+* Fixed an issue where transfer statistics were not being populated in the
+  RingBridge. https://github.com/guzzle/guzzle/issues/866
+
+## 5.0.0 - 2014-10-12
+
+Adding support for non-blocking responses and some minor API cleanup.
+
+### New Features
+
+* Added support for non-blocking responses based on `guzzlehttp/guzzle-ring`.
+* Added a public API for creating a default HTTP adapter.
+* Updated the redirect plugin to be non-blocking so that redirects are sent
+  concurrently. Other plugins like this can now be updated to be non-blocking.
+* Added a "progress" event so that you can get upload and download progress
+  events.
+* Added `GuzzleHttp\Pool` which implements FutureInterface and transfers
+  requests concurrently using a capped pool size as efficiently as possible.
+* Added `hasListeners()` to EmitterInterface.
+* Removed `GuzzleHttp\ClientInterface::sendAll` and marked
+  `GuzzleHttp\Client::sendAll` as deprecated (it's still there, just not the
+  recommended way).
+
+### Breaking changes
+
+The breaking changes in this release are relatively minor. The biggest thing to
+look out for is that request and response objects no longer implement fluent
+interfaces.
+
+* Removed the fluent interfaces (i.e., `return $this`) from requests,
+  responses, `GuzzleHttp\Collection`, `GuzzleHttp\Url`,
+  `GuzzleHttp\Query`, `GuzzleHttp\Post\PostBody`, and
+  `GuzzleHttp\Cookie\SetCookie`. This blog post provides a good outline of
+  why I did this: http://ocramius.github.io/blog/fluent-interfaces-are-evil/.
+  This also makes the Guzzle message interfaces compatible with the current
+  PSR-7 message proposal.
+* Removed "functions.php", so that Guzzle is truly PSR-4 compliant. Except
+  for the HTTP request functions from function.php, these functions are now
+  implemented in `GuzzleHttp\Utils` using camelCase. `GuzzleHttp\json_decode`
+  moved to `GuzzleHttp\Utils::jsonDecode`. `GuzzleHttp\get_path` moved to
+  `GuzzleHttp\Utils::getPath`. `GuzzleHttp\set_path` moved to
+  `GuzzleHttp\Utils::setPath`. `GuzzleHttp\batch` should now be
+  `GuzzleHttp\Pool::batch`, which returns an `objectStorage`. Using functions.php
+  caused problems for many users: they aren't PSR-4 compliant, require an
+  explicit include, and needed an if-guard to ensure that the functions are not
+  declared multiple times.
+* Rewrote adapter layer.
+    * Removing all classes from `GuzzleHttp\Adapter`, these are now
+      implemented as callables that are stored in `GuzzleHttp\Ring\Client`.
+    * Removed the concept of "parallel adapters". Sending requests serially or
+      concurrently is now handled using a single adapter.
+    * Moved `GuzzleHttp\Adapter\Transaction` to `GuzzleHttp\Transaction`. The
+      Transaction object now exposes the request, response, and client as public
+      properties. The getters and setters have been removed.
+* Removed the "headers" event. This event was only useful for changing the
+  body a response once the headers of the response were known. You can implement
+  a similar behavior in a number of ways. One example might be to use a
+  FnStream that has access to the transaction being sent. For example, when the
+  first byte is written, you could check if the response headers match your
+  expectations, and if so, change the actual stream body that is being
+  written to.
+* Removed the `asArray` parameter from
+  `GuzzleHttp\Message\MessageInterface::getHeader`. If you want to get a header
+  value as an array, then use the newly added `getHeaderAsArray()` method of
+  `MessageInterface`. This change makes the Guzzle interfaces compatible with
+  the PSR-7 interfaces.
+* `GuzzleHttp\Message\MessageFactory` no longer allows subclasses to add
+  custom request options using double-dispatch (this was an implementation
+  detail). Instead, you should now provide an associative array to the
+  constructor which is a mapping of the request option name mapping to a
+  function that applies the option value to a request.
+* Removed the concept of "throwImmediately" from exceptions and error events.
+  This control mechanism was used to stop a transfer of concurrent requests
+  from completing. This can now be handled by throwing the exception or by
+  cancelling a pool of requests or each outstanding future request individually.
+* Updated to "GuzzleHttp\Streams" 3.0.
+    * `GuzzleHttp\Stream\StreamInterface::getContents()` no longer accepts a
+      `maxLen` parameter. This update makes the Guzzle streams project
+      compatible with the current PSR-7 proposal.
+    * `GuzzleHttp\Stream\Stream::__construct`,
+      `GuzzleHttp\Stream\Stream::factory`, and
+      `GuzzleHttp\Stream\Utils::create` no longer accept a size in the second
+      argument. They now accept an associative array of options, including the
+      "size" key and "metadata" key which can be used to provide custom metadata.
+
+## 4.2.2 - 2014-09-08
+
+* Fixed a memory leak in the CurlAdapter when reusing cURL handles.
+* No longer using `request_fulluri` in stream adapter proxies.
+* Relative redirects are now based on the last response, not the first response.
+
+## 4.2.1 - 2014-08-19
+
+* Ensuring that the StreamAdapter does not always add a Content-Type header
+* Adding automated github releases with a phar and zip
+
+## 4.2.0 - 2014-08-17
+
+* Now merging in default options using a case-insensitive comparison.
+  Closes https://github.com/guzzle/guzzle/issues/767
+* Added the ability to automatically decode `Content-Encoding` response bodies
+  using the `decode_content` request option. This is set to `true` by default
+  to decode the response body if it comes over the wire with a
+  `Content-Encoding`. Set this value to `false` to disable decoding the
+  response content, and pass a string to provide a request `Accept-Encoding`
+  header and turn on automatic response decoding. This feature now allows you
+  to pass an `Accept-Encoding` header in the headers of a request but still
+  disable automatic response decoding.
+  Closes https://github.com/guzzle/guzzle/issues/764
+* Added the ability to throw an exception immediately when transferring
+  requests in parallel. Closes https://github.com/guzzle/guzzle/issues/760
+* Updating guzzlehttp/streams dependency to ~2.1
+* No longer utilizing the now deprecated namespaced methods from the stream
+  package.
+
+## 4.1.8 - 2014-08-14
+
+* Fixed an issue in the CurlFactory that caused setting the `stream=false`
+  request option to throw an exception.
+  See: https://github.com/guzzle/guzzle/issues/769
+* TransactionIterator now calls rewind on the inner iterator.
+  See: https://github.com/guzzle/guzzle/pull/765
+* You can now set the `Content-Type` header to `multipart/form-data`
+  when creating POST requests to force multipart bodies.
+  See https://github.com/guzzle/guzzle/issues/768
+
+## 4.1.7 - 2014-08-07
+
+* Fixed an error in the HistoryPlugin that caused the same request and response
+  to be logged multiple times when an HTTP protocol error occurs.
+* Ensuring that cURL does not add a default Content-Type when no Content-Type
+  has been supplied by the user. This prevents the adapter layer from modifying
+  the request that is sent over the wire after any listeners may have already
+  put the request in a desired state (e.g., signed the request).
+* Throwing an exception when you attempt to send requests that have the
+  "stream" set to true in parallel using the MultiAdapter.
+* Only calling curl_multi_select when there are active cURL handles. This was
+  previously changed and caused performance problems on some systems due to PHP
+  always selecting until the maximum select timeout.
+* Fixed a bug where multipart/form-data POST fields were not correctly
+  aggregated (e.g., values with "&").
+
+## 4.1.6 - 2014-08-03
+
+* Added helper methods to make it easier to represent messages as strings,
+  including getting the start line and getting headers as a string.
+
+## 4.1.5 - 2014-08-02
+
+* Automatically retrying cURL "Connection died, retrying a fresh connect"
+  errors when possible.
+* cURL implementation cleanup
+* Allowing multiple event subscriber listeners to be registered per event by
+  passing an array of arrays of listener configuration.
+
+## 4.1.4 - 2014-07-22
+
+* Fixed a bug that caused multi-part POST requests with more than one field to
+  serialize incorrectly.
+* Paths can now be set to "0"
+* `ResponseInterface::xml` now accepts a `libxml_options` option and added a
+  missing default argument that was required when parsing XML response bodies.
+* A `save_to` stream is now created lazily, which means that files are not
+  created on disk unless a request succeeds.
+
+## 4.1.3 - 2014-07-15
+
+* Various fixes to multipart/form-data POST uploads
+* Wrapping function.php in an if-statement to ensure Guzzle can be used
+  globally and in a Composer install
+* Fixed an issue with generating and merging in events to an event array
+* POST headers are only applied before sending a request to allow you to change
+  the query aggregator used before uploading
+* Added much more robust query string parsing
+* Fixed various parsing and normalization issues with URLs
+* Fixing an issue where multi-valued headers were not being utilized correctly
+  in the StreamAdapter
+
+## 4.1.2 - 2014-06-18
+
+* Added support for sending payloads with GET requests
+
+## 4.1.1 - 2014-06-08
+
+* Fixed an issue related to using custom message factory options in subclasses
+* Fixed an issue with nested form fields in a multi-part POST
+* Fixed an issue with using the `json` request option for POST requests
+* Added `ToArrayInterface` to `GuzzleHttp\Cookie\CookieJar`
+
+## 4.1.0 - 2014-05-27
+
+* Added a `json` request option to easily serialize JSON payloads.
+* Added a `GuzzleHttp\json_decode()` wrapper to safely parse JSON.
+* Added `setPort()` and `getPort()` to `GuzzleHttp\Message\RequestInterface`.
+* Added the ability to provide an emitter to a client in the client constructor.
+* Added the ability to persist a cookie session using $_SESSION.
+* Added a trait that can be used to add event listeners to an iterator.
+* Removed request method constants from RequestInterface.
+* Fixed warning when invalid request start-lines are received.
+* Updated MessageFactory to work with custom request option methods.
+* Updated cacert bundle to latest build.
+
+4.0.2 (2014-04-16)
+------------------
+
+* Proxy requests using the StreamAdapter now properly use request_fulluri (#632)
+* Added the ability to set scalars as POST fields (#628)
+
+## 4.0.1 - 2014-04-04
+
+* The HTTP status code of a response is now set as the exception code of
+  RequestException objects.
+* 303 redirects will now correctly switch from POST to GET requests.
+* The default parallel adapter of a client now correctly uses the MultiAdapter.
+* HasDataTrait now initializes the internal data array as an empty array so
+  that the toArray() method always returns an array.
+
+## 4.0.0 - 2014-03-29
+
+* For more information on the 4.0 transition, see:
+  http://mtdowling.com/blog/2014/03/15/guzzle-4-rc/
+* For information on changes and upgrading, see:
+  https://github.com/guzzle/guzzle/blob/master/UPGRADING.md#3x-to-40
+* Added `GuzzleHttp\batch()` as a convenience function for sending requests in
+  parallel without needing to write asynchronous code.
+* Restructured how events are added to `GuzzleHttp\ClientInterface::sendAll()`.
+  You can now pass a callable or an array of associative arrays where each
+  associative array contains the "fn", "priority", and "once" keys.
+
+## 4.0.0.rc-2 - 2014-03-25
+
+* Removed `getConfig()` and `setConfig()` from clients to avoid confusion
+  around whether things like base_url, message_factory, etc. should be able to
+  be retrieved or modified.
+* Added `getDefaultOption()` and `setDefaultOption()` to ClientInterface
+* functions.php functions were renamed using snake_case to match PHP idioms
+* Added support for `HTTP_PROXY`, `HTTPS_PROXY`, and
+  `GUZZLE_CURL_SELECT_TIMEOUT` environment variables
+* Added the ability to specify custom `sendAll()` event priorities
+* Added the ability to specify custom stream context options to the stream
+  adapter.
+* Added a functions.php function for `get_path()` and `set_path()`
+* CurlAdapter and MultiAdapter now use a callable to generate curl resources
+* MockAdapter now properly reads a body and emits a `headers` event
+* Updated Url class to check if a scheme and host are set before adding ":"
+  and "//". This allows empty Url (e.g., "") to be serialized as "".
+* Parsing invalid XML no longer emits warnings
+* Curl classes now properly throw AdapterExceptions
+* Various performance optimizations
+* Streams are created with the faster `Stream\create()` function
+* Marked deprecation_proxy() as internal
+* Test server is now a collection of static methods on a class
+
+## 4.0.0-rc.1 - 2014-03-15
+
+* See https://github.com/guzzle/guzzle/blob/master/UPGRADING.md#3x-to-40
+
+## 3.8.1 - 2014-01-28
+
+* Bug: Always using GET requests when redirecting from a 303 response
+* Bug: CURLOPT_SSL_VERIFYHOST is now correctly set to false when setting `$certificateAuthority` to false in
+  `Guzzle\Http\ClientInterface::setSslVerification()`
+* Bug: RedirectPlugin now uses strict RFC 3986 compliance when combining a base URL with a relative URL
+* Bug: The body of a request can now be set to `"0"`
+* Sending PHP stream requests no longer forces `HTTP/1.0`
+* Adding more information to ExceptionCollection exceptions so that users have more context, including a stack trace of
+  each sub-exception
+* Updated the `$ref` attribute in service descriptions to merge over any existing parameters of a schema (rather than
+  clobbering everything).
+* Merging URLs will now use the query string object from the relative URL (thus allowing custom query aggregators)
+* Query strings are now parsed in a way that they do no convert empty keys with no value to have a dangling `=`.
+  For example `foo&bar=baz` is now correctly parsed and recognized as `foo&bar=baz` rather than `foo=&bar=baz`.
+* Now properly escaping the regular expression delimiter when matching Cookie domains.
+* Network access is now disabled when loading XML documents
+
+## 3.8.0 - 2013-12-05
+
+* Added the ability to define a POST name for a file
+* JSON response parsing now properly walks additionalProperties
+* cURL error code 18 is now retried automatically in the BackoffPlugin
+* Fixed a cURL error when URLs contain fragments
+* Fixed an issue in the BackoffPlugin retry event where it was trying to access all exceptions as if they were
+  CurlExceptions
+* CURLOPT_PROGRESS function fix for PHP 5.5 (69fcc1e)
+* Added the ability for Guzzle to work with older versions of cURL that do not support `CURLOPT_TIMEOUT_MS`
+* Fixed a bug that was encountered when parsing empty header parameters
+* UriTemplate now has a `setRegex()` method to match the docs
+* The `debug` request parameter now checks if it is truthy rather than if it exists
+* Setting the `debug` request parameter to true shows verbose cURL output instead of using the LogPlugin
+* Added the ability to combine URLs using strict RFC 3986 compliance
+* Command objects can now return the validation errors encountered by the command
+* Various fixes to cache revalidation (#437 and 29797e5)
+* Various fixes to the AsyncPlugin
+* Cleaned up build scripts
+
+## 3.7.4 - 2013-10-02
+
+* Bug fix: 0 is now an allowed value in a description parameter that has a default value (#430)
+* Bug fix: SchemaFormatter now returns an integer when formatting to a Unix timestamp
+  (see https://github.com/aws/aws-sdk-php/issues/147)
+* Bug fix: Cleaned up and fixed URL dot segment removal to properly resolve internal dots
+* Minimum PHP version is now properly specified as 5.3.3 (up from 5.3.2) (#420)
+* Updated the bundled cacert.pem (#419)
+* OauthPlugin now supports adding authentication to headers or query string (#425)
+
+## 3.7.3 - 2013-09-08
+
+* Added the ability to get the exception associated with a request/command when using `MultiTransferException` and
+  `CommandTransferException`.
+* Setting `additionalParameters` of a response to false is now honored when parsing responses with a service description
+* Schemas are only injected into response models when explicitly configured.
+* No longer guessing Content-Type based on the path of a request. Content-Type is now only guessed based on the path of
+  an EntityBody.
+* Bug fix: ChunkedIterator can now properly chunk a \Traversable as well as an \Iterator.
+* Bug fix: FilterIterator now relies on `\Iterator` instead of `\Traversable`.
+* Bug fix: Gracefully handling malformed responses in RequestMediator::writeResponseBody()
+* Bug fix: Replaced call to canCache with canCacheRequest in the CallbackCanCacheStrategy of the CachePlugin
+* Bug fix: Visiting XML attributes first before visiting XML children when serializing requests
+* Bug fix: Properly parsing headers that contain commas contained in quotes
+* Bug fix: mimetype guessing based on a filename is now case-insensitive
+
+## 3.7.2 - 2013-08-02
+
+* Bug fix: Properly URL encoding paths when using the PHP-only version of the UriTemplate expander
+  See https://github.com/guzzle/guzzle/issues/371
+* Bug fix: Cookie domains are now matched correctly according to RFC 6265
+  See https://github.com/guzzle/guzzle/issues/377
+* Bug fix: GET parameters are now used when calculating an OAuth signature
+* Bug fix: Fixed an issue with cache revalidation where the If-None-Match header was being double quoted
+* `Guzzle\Common\AbstractHasDispatcher::dispatch()` now returns the event that was dispatched
+* `Guzzle\Http\QueryString::factory()` now guesses the most appropriate query aggregator to used based on the input.
+  See https://github.com/guzzle/guzzle/issues/379
+* Added a way to add custom domain objects to service description parsing using the `operation.parse_class` event. See
+  https://github.com/guzzle/guzzle/pull/380
+* cURL multi cleanup and optimizations
+
+## 3.7.1 - 2013-07-05
+
+* Bug fix: Setting default options on a client now works
+* Bug fix: Setting options on HEAD requests now works. See #352
+* Bug fix: Moving stream factory before send event to before building the stream. See #353
+* Bug fix: Cookies no longer match on IP addresses per RFC 6265
+* Bug fix: Correctly parsing header parameters that are in `<>` and quotes
+* Added `cert` and `ssl_key` as request options
+* `Host` header can now diverge from the host part of a URL if the header is set manually
+* `Guzzle\Service\Command\LocationVisitor\Request\XmlVisitor` was rewritten to change from using SimpleXML to XMLWriter
+* OAuth parameters are only added via the plugin if they aren't already set
+* Exceptions are now thrown when a URL cannot be parsed
+* Returning `false` if `Guzzle\Http\EntityBody::getContentMd5()` fails
+* Not setting a `Content-MD5` on a command if calculating the Content-MD5 fails via the CommandContentMd5Plugin
+
+## 3.7.0 - 2013-06-10
+
+* See UPGRADING.md for more information on how to upgrade.
+* Requests now support the ability to specify an array of $options when creating a request to more easily modify a
+  request. You can pass a 'request.options' configuration setting to a client to apply default request options to
+  every request created by a client (e.g. default query string variables, headers, curl options, etc.).
+* Added a static facade class that allows you to use Guzzle with static methods and mount the class to `\Guzzle`.
+  See `Guzzle\Http\StaticClient::mount`.
+* Added `command.request_options` to `Guzzle\Service\Command\AbstractCommand` to pass request options to requests
+      created by a command (e.g. custom headers, query string variables, timeout settings, etc.).
+* Stream size in `Guzzle\Stream\PhpStreamRequestFactory` will now be set if Content-Length is returned in the
+  headers of a response
+* Added `Guzzle\Common\Collection::setPath($path, $value)` to set a value into an array using a nested key
+  (e.g. `$collection->setPath('foo/baz/bar', 'test'); echo $collection['foo']['bar']['bar'];`)
+* ServiceBuilders now support storing and retrieving arbitrary data
+* CachePlugin can now purge all resources for a given URI
+* CachePlugin can automatically purge matching cached items when a non-idempotent request is sent to a resource
+* CachePlugin now uses the Vary header to determine if a resource is a cache hit
+* `Guzzle\Http\Message\Response` now implements `\Serializable`
+* Added `Guzzle\Cache\CacheAdapterFactory::fromCache()` to more easily create cache adapters
+* `Guzzle\Service\ClientInterface::execute()` now accepts an array, single command, or Traversable
+* Fixed a bug in `Guzzle\Http\Message\Header\Link::addLink()`
+* Better handling of calculating the size of a stream in `Guzzle\Stream\Stream` using fstat() and caching the size
+* `Guzzle\Common\Exception\ExceptionCollection` now creates a more readable exception message
+* Fixing BC break: Added back the MonologLogAdapter implementation rather than extending from PsrLog so that older
+  Symfony users can still use the old version of Monolog.
+* Fixing BC break: Added the implementation back in for `Guzzle\Http\Message\AbstractMessage::getTokenizedHeader()`.
+  Now triggering an E_USER_DEPRECATED warning when used. Use `$message->getHeader()->parseParams()`.
+* Several performance improvements to `Guzzle\Common\Collection`
+* Added an `$options` argument to the end of the following methods of `Guzzle\Http\ClientInterface`:
+  createRequest, head, delete, put, patch, post, options, prepareRequest
+* Added an `$options` argument to the end of `Guzzle\Http\Message\Request\RequestFactoryInterface::createRequest()`
+* Added an `applyOptions()` method to `Guzzle\Http\Message\Request\RequestFactoryInterface`
+* Changed `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $body = null)` to
+  `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $options = array())`. You can still pass in a
+  resource, string, or EntityBody into the $options parameter to specify the download location of the response.
+* Changed `Guzzle\Common\Collection::__construct($data)` to no longer accepts a null value for `$data` but a
+  default `array()`
+* Added `Guzzle\Stream\StreamInterface::isRepeatable`
+* Removed `Guzzle\Http\ClientInterface::setDefaultHeaders(). Use
+  $client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`. or
+  $client->getConfig()->setPath('request.options/headers', array('header_name' => 'value'))`.
+* Removed `Guzzle\Http\ClientInterface::getDefaultHeaders(). Use $client->getConfig()->getPath('request.options/headers')`.
+* Removed `Guzzle\Http\ClientInterface::expandTemplate()`
+* Removed `Guzzle\Http\ClientInterface::setRequestFactory()`
+* Removed `Guzzle\Http\ClientInterface::getCurlMulti()`
+* Removed `Guzzle\Http\Message\RequestInterface::canCache`
+* Removed `Guzzle\Http\Message\RequestInterface::setIsRedirect`
+* Removed `Guzzle\Http\Message\RequestInterface::isRedirect`
+* Made `Guzzle\Http\Client::expandTemplate` and `getUriTemplate` protected methods.
+* You can now enable E_USER_DEPRECATED warnings to see if you are using a deprecated method by setting
+  `Guzzle\Common\Version::$emitWarnings` to true.
+* Marked `Guzzle\Http\Message\Request::isResponseBodyRepeatable()` as deprecated. Use
+      `$request->getResponseBody()->isRepeatable()` instead.
+* Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use
+  `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead.
+* Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use
+  `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead.
+* Marked `Guzzle\Http\Message\Request::setIsRedirect()` as deprecated. Use the HistoryPlugin instead.
+* Marked `Guzzle\Http\Message\Request::isRedirect()` as deprecated. Use the HistoryPlugin instead.
+* Marked `Guzzle\Cache\CacheAdapterFactory::factory()` as deprecated
+* Marked 'command.headers', 'command.response_body' and 'command.on_complete' as deprecated for AbstractCommand.
+  These will work through Guzzle 4.0
+* Marked 'request.params' for `Guzzle\Http\Client` as deprecated. Use [request.options][params].
+* Marked `Guzzle\Service\Client::enableMagicMethods()` as deprecated. Magic methods can no longer be disabled on a Guzzle\Service\Client.
+* Marked `Guzzle\Service\Client::getDefaultHeaders()` as deprecated. Use $client->getConfig()->getPath('request.options/headers')`.
+* Marked `Guzzle\Service\Client::setDefaultHeaders()` as deprecated. Use $client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`.
+* Marked `Guzzle\Parser\Url\UrlParser` as deprecated. Just use PHP's `parse_url()` and percent encode your UTF-8.
+* Marked `Guzzle\Common\Collection::inject()` as deprecated.
+* Marked `Guzzle\Plugin\CurlAuth\CurlAuthPlugin` as deprecated. Use `$client->getConfig()->setPath('request.options/auth', array('user', 'pass', 'Basic|Digest');`
+* CacheKeyProviderInterface and DefaultCacheKeyProvider are no longer used. All of this logic is handled in a
+  CacheStorageInterface. These two objects and interface will be removed in a future version.
+* Always setting X-cache headers on cached responses
+* Default cache TTLs are now handled by the CacheStorageInterface of a CachePlugin
+* `CacheStorageInterface::cache($key, Response $response, $ttl = null)` has changed to `cache(RequestInterface
+  $request, Response $response);`
+* `CacheStorageInterface::fetch($key)` has changed to `fetch(RequestInterface $request);`
+* `CacheStorageInterface::delete($key)` has changed to `delete(RequestInterface $request);`
+* Added `CacheStorageInterface::purge($url)`
+* `DefaultRevalidation::__construct(CacheKeyProviderInterface $cacheKey, CacheStorageInterface $cache, CachePlugin
+  $plugin)` has changed to `DefaultRevalidation::__construct(CacheStorageInterface $cache,
+  CanCacheStrategyInterface $canCache = null)`
+* Added `RevalidationInterface::shouldRevalidate(RequestInterface $request, Response $response)`
+
+## 3.6.0 - 2013-05-29
+
+* ServiceDescription now implements ToArrayInterface
+* Added command.hidden_params to blacklist certain headers from being treated as additionalParameters
+* Guzzle can now correctly parse incomplete URLs
+* Mixed casing of headers are now forced to be a single consistent casing across all values for that header.
+* Messages internally use a HeaderCollection object to delegate handling case-insensitive header resolution
+* Removed the whole changedHeader() function system of messages because all header changes now go through addHeader().
+* Specific header implementations can be created for complex headers. When a message creates a header, it uses a
+  HeaderFactory which can map specific headers to specific header classes. There is now a Link header and
+  CacheControl header implementation.
+* Removed from interface: Guzzle\Http\ClientInterface::setUriTemplate
+* Removed from interface: Guzzle\Http\ClientInterface::setCurlMulti()
+* Removed Guzzle\Http\Message\Request::receivedRequestHeader() and implemented this functionality in
+  Guzzle\Http\Curl\RequestMediator
+* Removed the optional $asString parameter from MessageInterface::getHeader(). Just cast the header to a string.
+* Removed the optional $tryChunkedTransfer option from Guzzle\Http\Message\EntityEnclosingRequestInterface
+* Removed the $asObjects argument from Guzzle\Http\Message\MessageInterface::getHeaders()
+* Removed Guzzle\Parser\ParserRegister::get(). Use getParser()
+* Removed Guzzle\Parser\ParserRegister::set(). Use registerParser().
+* All response header helper functions return a string rather than mixing Header objects and strings inconsistently
+* Removed cURL blacklist support. This is no longer necessary now that Expect, Accept, etc. are managed by Guzzle
+  directly via interfaces
+* Removed the injecting of a request object onto a response object. The methods to get and set a request still exist
+  but are a no-op until removed.
+* Most classes that used to require a `Guzzle\Service\Command\CommandInterface` typehint now request a
+  `Guzzle\Service\Command\ArrayCommandInterface`.
+* Added `Guzzle\Http\Message\RequestInterface::startResponse()` to the RequestInterface to handle injecting a response
+  on a request while the request is still being transferred
+* The ability to case-insensitively search for header values
+* Guzzle\Http\Message\Header::hasExactHeader
+* Guzzle\Http\Message\Header::raw. Use getAll()
+* Deprecated cache control specific methods on Guzzle\Http\Message\AbstractMessage. Use the CacheControl header object
+  instead.
+* `Guzzle\Service\Command\CommandInterface` now extends from ToArrayInterface and ArrayAccess
+* Added the ability to cast Model objects to a string to view debug information.
+
+## 3.5.0 - 2013-05-13
+
+* Bug: Fixed a regression so that request responses are parsed only once per oncomplete event rather than multiple times
+* Bug: Better cleanup of one-time events across the board (when an event is meant to fire once, it will now remove
+  itself from the EventDispatcher)
+* Bug: `Guzzle\Log\MessageFormatter` now properly writes "total_time" and "connect_time" values
+* Bug: Cloning an EntityEnclosingRequest now clones the EntityBody too
+* Bug: Fixed an undefined index error when parsing nested JSON responses with a sentAs parameter that reference a
+  non-existent key
+* Bug: All __call() method arguments are now required (helps with mocking frameworks)
+* Deprecating Response::getRequest() and now using a shallow clone of a request object to remove a circular reference
+  to help with refcount based garbage collection of resources created by sending a request
+* Deprecating ZF1 cache and log adapters. These will be removed in the next major version.
+* Deprecating `Response::getPreviousResponse()` (method signature still exists, but it's deprecated). Use the
+  HistoryPlugin for a history.
+* Added a `responseBody` alias for the `response_body` location
+* Refactored internals to no longer rely on Response::getRequest()
+* HistoryPlugin can now be cast to a string
+* HistoryPlugin now logs transactions rather than requests and responses to more accurately keep track of the requests
+  and responses that are sent over the wire
+* Added `getEffectiveUrl()` and `getRedirectCount()` to Response objects
+
+## 3.4.3 - 2013-04-30
+
+* Bug fix: Fixing bug introduced in 3.4.2 where redirect responses are duplicated on the final redirected response
+* Added a check to re-extract the temp cacert bundle from the phar before sending each request
+
+## 3.4.2 - 2013-04-29
+
+* Bug fix: Stream objects now work correctly with "a" and "a+" modes
+* Bug fix: Removing `Transfer-Encoding: chunked` header when a Content-Length is present
+* Bug fix: AsyncPlugin no longer forces HEAD requests
+* Bug fix: DateTime timezones are now properly handled when using the service description schema formatter
+* Bug fix: CachePlugin now properly handles stale-if-error directives when a request to the origin server fails
+* Setting a response on a request will write to the custom request body from the response body if one is specified
+* LogPlugin now writes to php://output when STDERR is undefined
+* Added the ability to set multiple POST files for the same key in a single call
+* application/x-www-form-urlencoded POSTs now use the utf-8 charset by default
+* Added the ability to queue CurlExceptions to the MockPlugin
+* Cleaned up how manual responses are queued on requests (removed "queued_response" and now using request.before_send)
+* Configuration loading now allows remote files
+
+## 3.4.1 - 2013-04-16
+
+* Large refactoring to how CurlMulti handles work. There is now a proxy that sits in front of a pool of CurlMulti
+  handles. This greatly simplifies the implementation, fixes a couple bugs, and provides a small performance boost.
+* Exceptions are now properly grouped when sending requests in parallel
+* Redirects are now properly aggregated when a multi transaction fails
+* Redirects now set the response on the original object even in the event of a failure
+* Bug fix: Model names are now properly set even when using $refs
+* Added support for PHP 5.5's CurlFile to prevent warnings with the deprecated @ syntax
+* Added support for oauth_callback in OAuth signatures
+* Added support for oauth_verifier in OAuth signatures
+* Added support to attempt to retrieve a command first literally, then ucfirst, the with inflection
+
+## 3.4.0 - 2013-04-11
+
+* Bug fix: URLs are now resolved correctly based on http://tools.ietf.org/html/rfc3986#section-5.2. #289
+* Bug fix: Absolute URLs with a path in a service description will now properly override the base URL. #289
+* Bug fix: Parsing a query string with a single PHP array value will now result in an array. #263
+* Bug fix: Better normalization of the User-Agent header to prevent duplicate headers. #264.
+* Bug fix: Added `number` type to service descriptions.
+* Bug fix: empty parameters are removed from an OAuth signature
+* Bug fix: Revalidating a cache entry prefers the Last-Modified over the Date header
+* Bug fix: Fixed "array to string" error when validating a union of types in a service description
+* Bug fix: Removed code that attempted to determine the size of a stream when data is written to the stream
+* Bug fix: Not including an `oauth_token` if the value is null in the OauthPlugin.
+* Bug fix: Now correctly aggregating successful requests and failed requests in CurlMulti when a redirect occurs.
+* The new default CURLOPT_TIMEOUT setting has been increased to 150 seconds so that Guzzle works on poor connections.
+* Added a feature to EntityEnclosingRequest::setBody() that will automatically set the Content-Type of the request if
+  the Content-Type can be determined based on the entity body or the path of the request.
+* Added the ability to overwrite configuration settings in a client when grabbing a throwaway client from a builder.
+* Added support for a PSR-3 LogAdapter.
+* Added a `command.after_prepare` event
+* Added `oauth_callback` parameter to the OauthPlugin
+* Added the ability to create a custom stream class when using a stream factory
+* Added a CachingEntityBody decorator
+* Added support for `additionalParameters` in service descriptions to define how custom parameters are serialized.
+* The bundled SSL certificate is now provided in the phar file and extracted when running Guzzle from a phar.
+* You can now send any EntityEnclosingRequest with POST fields or POST files and cURL will handle creating bodies
+* POST requests using a custom entity body are now treated exactly like PUT requests but with a custom cURL method. This
+  means that the redirect behavior of POST requests with custom bodies will not be the same as POST requests that use
+  POST fields or files (the latter is only used when emulating a form POST in the browser).
+* Lots of cleanup to CurlHandle::factory and RequestFactory::createRequest
+
+## 3.3.1 - 2013-03-10
+
+* Added the ability to create PHP streaming responses from HTTP requests
+* Bug fix: Running any filters when parsing response headers with service descriptions
+* Bug fix: OauthPlugin fixes to allow for multi-dimensional array signing, and sorting parameters before signing
+* Bug fix: Removed the adding of default empty arrays and false Booleans to responses in order to be consistent across
+  response location visitors.
+* Bug fix: Removed the possibility of creating configuration files with circular dependencies
+* RequestFactory::create() now uses the key of a POST file when setting the POST file name
+* Added xmlAllowEmpty to serialize an XML body even if no XML specific parameters are set
+
+## 3.3.0 - 2013-03-03
+
+* A large number of performance optimizations have been made
+* Bug fix: Added 'wb' as a valid write mode for streams
+* Bug fix: `Guzzle\Http\Message\Response::json()` now allows scalar values to be returned
+* Bug fix: Fixed bug in `Guzzle\Http\Message\Response` where wrapping quotes were stripped from `getEtag()`
+* BC: Removed `Guzzle\Http\Utils` class
+* BC: Setting a service description on a client will no longer modify the client's command factories.
+* BC: Emitting IO events from a RequestMediator is now a parameter that must be set in a request's curl options using
+  the 'emit_io' key. This was previously set under a request's parameters using 'curl.emit_io'
+* BC: `Guzzle\Stream\Stream::getWrapper()` and `Guzzle\Stream\Stream::getSteamType()` are no longer converted to
+  lowercase
+* Operation parameter objects are now lazy loaded internally
+* Added ErrorResponsePlugin that can throw errors for responses defined in service description operations' errorResponses
+* Added support for instantiating responseType=class responseClass classes. Classes must implement
+  `Guzzle\Service\Command\ResponseClassInterface`
+* Added support for additionalProperties for top-level parameters in responseType=model responseClasses. These
+  additional properties also support locations and can be used to parse JSON responses where the outermost part of the
+  JSON is an array
+* Added support for nested renaming of JSON models (rename sentAs to name)
+* CachePlugin
+    * Added support for stale-if-error so that the CachePlugin can now serve stale content from the cache on error
+    * Debug headers can now added to cached response in the CachePlugin
+
+## 3.2.0 - 2013-02-14
+
+* CurlMulti is no longer reused globally. A new multi object is created per-client. This helps to isolate clients.
+* URLs with no path no longer contain a "/" by default
+* Guzzle\Http\QueryString does no longer manages the leading "?". This is now handled in Guzzle\Http\Url.
+* BadResponseException no longer includes the full request and response message
+* Adding setData() to Guzzle\Service\Description\ServiceDescriptionInterface
+* Adding getResponseBody() to Guzzle\Http\Message\RequestInterface
+* Various updates to classes to use ServiceDescriptionInterface type hints rather than ServiceDescription
+* Header values can now be normalized into distinct values when multiple headers are combined with a comma separated list
+* xmlEncoding can now be customized for the XML declaration of a XML service description operation
+* Guzzle\Http\QueryString now uses Guzzle\Http\QueryAggregator\QueryAggregatorInterface objects to add custom value
+  aggregation and no longer uses callbacks
+* The URL encoding implementation of Guzzle\Http\QueryString can now be customized
+* Bug fix: Filters were not always invoked for array service description parameters
+* Bug fix: Redirects now use a target response body rather than a temporary response body
+* Bug fix: The default exponential backoff BackoffPlugin was not giving when the request threshold was exceeded
+* Bug fix: Guzzle now takes the first found value when grabbing Cache-Control directives
+
+## 3.1.2 - 2013-01-27
+
+* Refactored how operation responses are parsed. Visitors now include a before() method responsible for parsing the
+  response body. For example, the XmlVisitor now parses the XML response into an array in the before() method.
+* Fixed an issue where cURL would not automatically decompress responses when the Accept-Encoding header was sent
+* CURLOPT_SSL_VERIFYHOST is never set to 1 because it is deprecated (see 5e0ff2ef20f839e19d1eeb298f90ba3598784444)
+* Fixed a bug where redirect responses were not chained correctly using getPreviousResponse()
+* Setting default headers on a client after setting the user-agent will not erase the user-agent setting
+
+## 3.1.1 - 2013-01-20
+
+* Adding wildcard support to Guzzle\Common\Collection::getPath()
+* Adding alias support to ServiceBuilder configs
+* Adding Guzzle\Service\Resource\CompositeResourceIteratorFactory and cleaning up factory interface
+
+## 3.1.0 - 2013-01-12
+
+* BC: CurlException now extends from RequestException rather than BadResponseException
+* BC: Renamed Guzzle\Plugin\Cache\CanCacheStrategyInterface::canCache() to canCacheRequest() and added CanCacheResponse()
+* Added getData to ServiceDescriptionInterface
+* Added context array to RequestInterface::setState()
+* Bug: Removing hard dependency on the BackoffPlugin from Guzzle\Http
+* Bug: Adding required content-type when JSON request visitor adds JSON to a command
+* Bug: Fixing the serialization of a service description with custom data
+* Made it easier to deal with exceptions thrown when transferring commands or requests in parallel by providing
+  an array of successful and failed responses
+* Moved getPath from Guzzle\Service\Resource\Model to Guzzle\Common\Collection
+* Added Guzzle\Http\IoEmittingEntityBody
+* Moved command filtration from validators to location visitors
+* Added `extends` attributes to service description parameters
+* Added getModels to ServiceDescriptionInterface
+
+## 3.0.7 - 2012-12-19
+
+* Fixing phar detection when forcing a cacert to system if null or true
+* Allowing filename to be passed to `Guzzle\Http\Message\Request::setResponseBody()`
+* Cleaning up `Guzzle\Common\Collection::inject` method
+* Adding a response_body location to service descriptions
+
+## 3.0.6 - 2012-12-09
+
+* CurlMulti performance improvements
+* Adding setErrorResponses() to Operation
+* composer.json tweaks
+
+## 3.0.5 - 2012-11-18
+
+* Bug: Fixing an infinite recursion bug caused from revalidating with the CachePlugin
+* Bug: Response body can now be a string containing "0"
+* Bug: Using Guzzle inside of a phar uses system by default but now allows for a custom cacert
+* Bug: QueryString::fromString now properly parses query string parameters that contain equal signs
+* Added support for XML attributes in service description responses
+* DefaultRequestSerializer now supports array URI parameter values for URI template expansion
+* Added better mimetype guessing to requests and post files
+
+## 3.0.4 - 2012-11-11
+
+* Bug: Fixed a bug when adding multiple cookies to a request to use the correct glue value
+* Bug: Cookies can now be added that have a name, domain, or value set to "0"
+* Bug: Using the system cacert bundle when using the Phar
+* Added json and xml methods to Response to make it easier to parse JSON and XML response data into data structures
+* Enhanced cookie jar de-duplication
+* Added the ability to enable strict cookie jars that throw exceptions when invalid cookies are added
+* Added setStream to StreamInterface to actually make it possible to implement custom rewind behavior for entity bodies
+* Added the ability to create any sort of hash for a stream rather than just an MD5 hash
+
+## 3.0.3 - 2012-11-04
+
+* Implementing redirects in PHP rather than cURL
+* Added PECL URI template extension and using as default parser if available
+* Bug: Fixed Content-Length parsing of Response factory
+* Adding rewind() method to entity bodies and streams. Allows for custom rewinding of non-repeatable streams.
+* Adding ToArrayInterface throughout library
+* Fixing OauthPlugin to create unique nonce values per request
+
+## 3.0.2 - 2012-10-25
+
+* Magic methods are enabled by default on clients
+* Magic methods return the result of a command
+* Service clients no longer require a base_url option in the factory
+* Bug: Fixed an issue with URI templates where null template variables were being expanded
+
+## 3.0.1 - 2012-10-22
+
+* Models can now be used like regular collection objects by calling filter, map, etc.
+* Models no longer require a Parameter structure or initial data in the constructor
+* Added a custom AppendIterator to get around a PHP bug with the `\AppendIterator`
+
+## 3.0.0 - 2012-10-15
+
+* Rewrote service description format to be based on Swagger
+    * Now based on JSON schema
+    * Added nested input structures and nested response models
+    * Support for JSON and XML input and output models
+    * Renamed `commands` to `operations`
+    * Removed dot class notation
+    * Removed custom types
+* Broke the project into smaller top-level namespaces to be more component friendly
+* Removed support for XML configs and descriptions. Use arrays or JSON files.
+* Removed the Validation component and Inspector
+* Moved all cookie code to Guzzle\Plugin\Cookie
+* Magic methods on a Guzzle\Service\Client now return the command un-executed.
+* Calling getResult() or getResponse() on a command will lazily execute the command if needed.
+* Now shipping with cURL's CA certs and using it by default
+* Added previousResponse() method to response objects
+* No longer sending Accept and Accept-Encoding headers on every request
+* Only sending an Expect header by default when a payload is greater than 1MB
+* Added/moved client options:
+    * curl.blacklist to curl.option.blacklist
+    * Added ssl.certificate_authority
+* Added a Guzzle\Iterator component
+* Moved plugins from Guzzle\Http\Plugin to Guzzle\Plugin
+* Added a more robust backoff retry strategy (replaced the ExponentialBackoffPlugin)
+* Added a more robust caching plugin
+* Added setBody to response objects
+* Updating LogPlugin to use a more flexible MessageFormatter
+* Added a completely revamped build process
+* Cleaning up Collection class and removing default values from the get method
+* Fixed ZF2 cache adapters
+
+## 2.8.8 - 2012-10-15
+
+* Bug: Fixed a cookie issue that caused dot prefixed domains to not match where popular browsers did
+
+## 2.8.7 - 2012-09-30
+
+* Bug: Fixed config file aliases for JSON includes
+* Bug: Fixed cookie bug on a request object by using CookieParser to parse cookies on requests
+* Bug: Removing the path to a file when sending a Content-Disposition header on a POST upload
+* Bug: Hardening request and response parsing to account for missing parts
+* Bug: Fixed PEAR packaging
+* Bug: Fixed Request::getInfo
+* Bug: Fixed cases where CURLM_CALL_MULTI_PERFORM return codes were causing curl transactions to fail
+* Adding the ability for the namespace Iterator factory to look in multiple directories
+* Added more getters/setters/removers from service descriptions
+* Added the ability to remove POST fields from OAuth signatures
+* OAuth plugin now supports 2-legged OAuth
+
+## 2.8.6 - 2012-09-05
+
+* Added the ability to modify and build service descriptions
+* Added the use of visitors to apply parameters to locations in service descriptions using the dynamic command
+* Added a `json` parameter location
+* Now allowing dot notation for classes in the CacheAdapterFactory
+* Using the union of two arrays rather than an array_merge when extending service builder services and service params
+* Ensuring that a service is a string before doing strpos() checks on it when substituting services for references
+  in service builder config files.
+* Services defined in two different config files that include one another will by default replace the previously
+  defined service, but you can now create services that extend themselves and merge their settings over the previous
+* The JsonLoader now supports aliasing filenames with different filenames. This allows you to alias something like
+  '_default' with a default JSON configuration file.
+
+## 2.8.5 - 2012-08-29
+
+* Bug: Suppressed empty arrays from URI templates
+* Bug: Added the missing $options argument from ServiceDescription::factory to enable caching
+* Added support for HTTP responses that do not contain a reason phrase in the start-line
+* AbstractCommand commands are now invokable
+* Added a way to get the data used when signing an Oauth request before a request is sent
+
+## 2.8.4 - 2012-08-15
+
+* Bug: Custom delay time calculations are no longer ignored in the ExponentialBackoffPlugin
+* Added the ability to transfer entity bodies as a string rather than streamed. This gets around curl error 65. Set `body_as_string` in a request's curl options to enable.
+* Added a StreamInterface, EntityBodyInterface, and added ftell() to Guzzle\Common\Stream
+* Added an AbstractEntityBodyDecorator and a ReadLimitEntityBody decorator to transfer only a subset of a decorated stream
+* Stream and EntityBody objects will now return the file position to the previous position after a read required operation (e.g. getContentMd5())
+* Added additional response status codes
+* Removed SSL information from the default User-Agent header
+* DELETE requests can now send an entity body
+* Added an EventDispatcher to the ExponentialBackoffPlugin and added an ExponentialBackoffLogger to log backoff retries
+* Added the ability of the MockPlugin to consume mocked request bodies
+* LogPlugin now exposes request and response objects in the extras array
+
+## 2.8.3 - 2012-07-30
+
+* Bug: Fixed a case where empty POST requests were sent as GET requests
+* Bug: Fixed a bug in ExponentialBackoffPlugin that caused fatal errors when retrying an EntityEnclosingRequest that does not have a body
+* Bug: Setting the response body of a request to null after completing a request, not when setting the state of a request to new
+* Added multiple inheritance to service description commands
+* Added an ApiCommandInterface and added `getParamNames()` and `hasParam()`
+* Removed the default 2mb size cutoff from the Md5ValidatorPlugin so that it now defaults to validating everything
+* Changed CurlMulti::perform to pass a smaller timeout to CurlMulti::executeHandles
+
+## 2.8.2 - 2012-07-24
+
+* Bug: Query string values set to 0 are no longer dropped from the query string
+* Bug: A Collection object is no longer created each time a call is made to `Guzzle\Service\Command\AbstractCommand::getRequestHeaders()`
+* Bug: `+` is now treated as an encoded space when parsing query strings
+* QueryString and Collection performance improvements
+* Allowing dot notation for class paths in filters attribute of a service descriptions
+
+## 2.8.1 - 2012-07-16
+
+* Loosening Event Dispatcher dependency
+* POST redirects can now be customized using CURLOPT_POSTREDIR
+
+## 2.8.0 - 2012-07-15
+
+* BC: Guzzle\Http\Query
+    * Query strings with empty variables will always show an equal sign unless the variable is set to QueryString::BLANK (e.g. ?acl= vs ?acl)
+    * Changed isEncodingValues() and isEncodingFields() to isUrlEncoding()
+    * Changed setEncodeValues(bool) and setEncodeFields(bool) to useUrlEncoding(bool)
+    * Changed the aggregation functions of QueryString to be static methods
+    * Can now use fromString() with querystrings that have a leading ?
+* cURL configuration values can be specified in service descriptions using `curl.` prefixed parameters
+* Content-Length is set to 0 before emitting the request.before_send event when sending an empty request body
+* Cookies are no longer URL decoded by default
+* Bug: URI template variables set to null are no longer expanded
+
+## 2.7.2 - 2012-07-02
+
+* BC: Moving things to get ready for subtree splits. Moving Inflection into Common. Moving Guzzle\Http\Parser to Guzzle\Parser.
+* BC: Removing Guzzle\Common\Batch\Batch::count() and replacing it with isEmpty()
+* CachePlugin now allows for a custom request parameter function to check if a request can be cached
+* Bug fix: CachePlugin now only caches GET and HEAD requests by default
+* Bug fix: Using header glue when transferring headers over the wire
+* Allowing deeply nested arrays for composite variables in URI templates
+* Batch divisors can now return iterators or arrays
+
+## 2.7.1 - 2012-06-26
+
+* Minor patch to update version number in UA string
+* Updating build process
+
+## 2.7.0 - 2012-06-25
+
+* BC: Inflection classes moved to Guzzle\Inflection. No longer static methods. Can now inject custom inflectors into classes.
+* BC: Removed magic setX methods from commands
+* BC: Magic methods mapped to service description commands are now inflected in the command factory rather than the client __call() method
+* Verbose cURL options are no longer enabled by default. Set curl.debug to true on a client to enable.
+* Bug: Now allowing colons in a response start-line (e.g. HTTP/1.1 503 Service Unavailable: Back-end server is at capacity)
+* Guzzle\Service\Resource\ResourceIteratorApplyBatched now internally uses the Guzzle\Common\Batch namespace
+* Added Guzzle\Service\Plugin namespace and a PluginCollectionPlugin
+* Added the ability to set POST fields and files in a service description
+* Guzzle\Http\EntityBody::factory() now accepts objects with a __toString() method
+* Adding a command.before_prepare event to clients
+* Added BatchClosureTransfer and BatchClosureDivisor
+* BatchTransferException now includes references to the batch divisor and transfer strategies
+* Fixed some tests so that they pass more reliably
+* Added Guzzle\Common\Log\ArrayLogAdapter
+
+## 2.6.6 - 2012-06-10
+
+* BC: Removing Guzzle\Http\Plugin\BatchQueuePlugin
+* BC: Removing Guzzle\Service\Command\CommandSet
+* Adding generic batching system (replaces the batch queue plugin and command set)
+* Updating ZF cache and log adapters and now using ZF's composer repository
+* Bug: Setting the name of each ApiParam when creating through an ApiCommand
+* Adding result_type, result_doc, deprecated, and doc_url to service descriptions
+* Bug: Changed the default cookie header casing back to 'Cookie'
+
+## 2.6.5 - 2012-06-03
+
+* BC: Renaming Guzzle\Http\Message\RequestInterface::getResourceUri() to getResource()
+* BC: Removing unused AUTH_BASIC and AUTH_DIGEST constants from
+* BC: Guzzle\Http\Cookie is now used to manage Set-Cookie data, not Cookie data
+* BC: Renaming methods in the CookieJarInterface
+* Moving almost all cookie logic out of the CookiePlugin and into the Cookie or CookieJar implementations
+* Making the default glue for HTTP headers ';' instead of ','
+* Adding a removeValue to Guzzle\Http\Message\Header
+* Adding getCookies() to request interface.
+* Making it easier to add event subscribers to HasDispatcherInterface classes. Can now directly call addSubscriber()
+
+## 2.6.4 - 2012-05-30
+
+* BC: Cleaning up how POST files are stored in EntityEnclosingRequest objects. Adding PostFile class.
+* BC: Moving ApiCommand specific functionality from the Inspector and on to the ApiCommand
+* Bug: Fixing magic method command calls on clients
+* Bug: Email constraint only validates strings
+* Bug: Aggregate POST fields when POST files are present in curl handle
+* Bug: Fixing default User-Agent header
+* Bug: Only appending or prepending parameters in commands if they are specified
+* Bug: Not requiring response reason phrases or status codes to match a predefined list of codes
+* Allowing the use of dot notation for class namespaces when using instance_of constraint
+* Added any_match validation constraint
+* Added an AsyncPlugin
+* Passing request object to the calculateWait method of the ExponentialBackoffPlugin
+* Allowing the result of a command object to be changed
+* Parsing location and type sub values when instantiating a service description rather than over and over at runtime
+
+## 2.6.3 - 2012-05-23
+
+* [BC] Guzzle\Common\FromConfigInterface no longer requires any config options.
+* [BC] Refactoring how POST files are stored on an EntityEnclosingRequest. They are now separate from POST fields.
+* You can now use an array of data when creating PUT request bodies in the request factory.
+* Removing the requirement that HTTPS requests needed a Cache-Control: public directive to be cacheable.
+* [Http] Adding support for Content-Type in multipart POST uploads per upload
+* [Http] Added support for uploading multiple files using the same name (foo[0], foo[1])
+* Adding more POST data operations for easier manipulation of POST data.
+* You can now set empty POST fields.
+* The body of a request is only shown on EntityEnclosingRequest objects that do not use POST files.
+* Split the Guzzle\Service\Inspector::validateConfig method into two methods. One to initialize when a command is created, and one to validate.
+* CS updates
+
+## 2.6.2 - 2012-05-19
+
+* [Http] Better handling of nested scope requests in CurlMulti.  Requests are now always prepares in the send() method rather than the addRequest() method.
+
+## 2.6.1 - 2012-05-19
+
+* [BC] Removing 'path' support in service descriptions.  Use 'uri'.
+* [BC] Guzzle\Service\Inspector::parseDocBlock is now protected. Adding getApiParamsForClass() with cache.
+* [BC] Removing Guzzle\Common\NullObject.  Use https://github.com/mtdowling/NullObject if you need it.
+* [BC] Removing Guzzle\Common\XmlElement.
+* All commands, both dynamic and concrete, have ApiCommand objects.
+* Adding a fix for CurlMulti so that if all of the connections encounter some sort of curl error, then the loop exits.
+* Adding checks to EntityEnclosingRequest so that empty POST files and fields are ignored.
+* Making the method signature of Guzzle\Service\Builder\ServiceBuilder::factory more flexible.
+
+## 2.6.0 - 2012-05-15
+
+* [BC] Moving Guzzle\Service\Builder to Guzzle\Service\Builder\ServiceBuilder
+* [BC] Executing a Command returns the result of the command rather than the command
+* [BC] Moving all HTTP parsing logic to Guzzle\Http\Parsers. Allows for faster C implementations if needed.
+* [BC] Changing the Guzzle\Http\Message\Response::setProtocol() method to accept a protocol and version in separate args.
+* [BC] Moving ResourceIterator* to Guzzle\Service\Resource
+* [BC] Completely refactored ResourceIterators to iterate over a cloned command object
+* [BC] Moved Guzzle\Http\UriTemplate to Guzzle\Http\Parser\UriTemplate\UriTemplate
+* [BC] Guzzle\Guzzle is now deprecated
+* Moving Guzzle\Common\Guzzle::inject to Guzzle\Common\Collection::inject
+* Adding Guzzle\Version class to give version information about Guzzle
+* Adding Guzzle\Http\Utils class to provide getDefaultUserAgent() and getHttpDate()
+* Adding Guzzle\Curl\CurlVersion to manage caching curl_version() data
+* ServiceDescription and ServiceBuilder are now cacheable using similar configs
+* Changing the format of XML and JSON service builder configs.  Backwards compatible.
+* Cleaned up Cookie parsing
+* Trimming the default Guzzle User-Agent header
+* Adding a setOnComplete() method to Commands that is called when a command completes
+* Keeping track of requests that were mocked in the MockPlugin
+* Fixed a caching bug in the CacheAdapterFactory
+* Inspector objects can be injected into a Command object
+* Refactoring a lot of code and tests to be case insensitive when dealing with headers
+* Adding Guzzle\Http\Message\HeaderComparison for easy comparison of HTTP headers using a DSL
+* Adding the ability to set global option overrides to service builder configs
+* Adding the ability to include other service builder config files from within XML and JSON files
+* Moving the parseQuery method out of Url and on to QueryString::fromString() as a static factory method.
+
+## 2.5.0 - 2012-05-08
+
+* Major performance improvements
+* [BC] Simplifying Guzzle\Common\Collection.  Please check to see if you are using features that are now deprecated.
+* [BC] Using a custom validation system that allows a flyweight implementation for much faster validation. No longer using Symfony2 Validation component.
+* [BC] No longer supporting "{{ }}" for injecting into command or UriTemplates.  Use "{}"
+* Added the ability to passed parameters to all requests created by a client
+* Added callback functionality to the ExponentialBackoffPlugin
+* Using microtime in ExponentialBackoffPlugin to allow more granular backoff strategies.
+* Rewinding request stream bodies when retrying requests
+* Exception is thrown when JSON response body cannot be decoded
+* Added configurable magic method calls to clients and commands.  This is off by default.
+* Fixed a defect that added a hash to every parsed URL part
+* Fixed duplicate none generation for OauthPlugin.
+* Emitting an event each time a client is generated by a ServiceBuilder
+* Using an ApiParams object instead of a Collection for parameters of an ApiCommand
+* cache.* request parameters should be renamed to params.cache.*
+* Added the ability to set arbitrary curl options on requests (disable_wire, progress, etc.). See CurlHandle.
+* Added the ability to disable type validation of service descriptions
+* ServiceDescriptions and ServiceBuilders are now Serializable
diff --git a/vendor/guzzlehttp/guzzle/LICENSE b/vendor/guzzlehttp/guzzle/LICENSE
new file mode 100644
index 00000000000..50a177b0320
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2011-2018 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
+
+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/vendor/guzzlehttp/guzzle/README.md b/vendor/guzzlehttp/guzzle/README.md
new file mode 100644
index 00000000000..bcd18b8e718
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/README.md
@@ -0,0 +1,91 @@
+Guzzle, PHP HTTP client
+=======================
+
+[![Latest Version](https://img.shields.io/github/release/guzzle/guzzle.svg?style=flat-square)](https://github.com/guzzle/guzzle/releases)
+[![Build Status](https://img.shields.io/travis/guzzle/guzzle.svg?style=flat-square)](https://travis-ci.org/guzzle/guzzle)
+[![Total Downloads](https://img.shields.io/packagist/dt/guzzlehttp/guzzle.svg?style=flat-square)](https://packagist.org/packages/guzzlehttp/guzzle)
+
+Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and
+trivial to integrate with web services.
+
+- Simple interface for building query strings, POST requests, streaming large
+  uploads, streaming large downloads, using HTTP cookies, uploading JSON data,
+  etc...
+- Can send both synchronous and asynchronous requests using the same interface.
+- Uses PSR-7 interfaces for requests, responses, and streams. This allows you
+  to utilize other PSR-7 compatible libraries with Guzzle.
+- Abstracts away the underlying HTTP transport, allowing you to write
+  environment and transport agnostic code; i.e., no hard dependency on cURL,
+  PHP streams, sockets, or non-blocking event loops.
+- Middleware system allows you to augment and compose client behavior.
+
+```php
+$client = new \GuzzleHttp\Client();
+$res = $client->request('GET', 'https://api.github.com/repos/guzzle/guzzle');
+echo $res->getStatusCode();
+// 200
+echo $res->getHeaderLine('content-type');
+// 'application/json; charset=utf8'
+echo $res->getBody();
+// '{"id": 1420053, "name": "guzzle", ...}'
+
+// Send an asynchronous request.
+$request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org');
+$promise = $client->sendAsync($request)->then(function ($response) {
+    echo 'I completed! ' . $response->getBody();
+});
+$promise->wait();
+```
+
+## Help and docs
+
+- [Documentation](http://guzzlephp.org/)
+- [Stack Overflow](http://stackoverflow.com/questions/tagged/guzzle)
+- [Gitter](https://gitter.im/guzzle/guzzle)
+
+
+## Installing Guzzle
+
+The recommended way to install Guzzle is through
+[Composer](http://getcomposer.org).
+
+```bash
+# Install Composer
+curl -sS https://getcomposer.org/installer | php
+```
+
+Next, run the Composer command to install the latest stable version of Guzzle:
+
+```bash
+php composer.phar require guzzlehttp/guzzle
+```
+
+After installing, you need to require Composer's autoloader:
+
+```php
+require 'vendor/autoload.php';
+```
+
+You can then later update Guzzle using composer:
+
+ ```bash
+composer.phar update
+ ```
+
+
+## Version Guidance
+
+| Version | Status     | Packagist           | Namespace    | Repo                | Docs                | PSR-7 | PHP Version |
+|---------|------------|---------------------|--------------|---------------------|---------------------|-------|-------------|
+| 3.x     | EOL        | `guzzle/guzzle`     | `Guzzle`     | [v3][guzzle-3-repo] | [v3][guzzle-3-docs] | No    | >= 5.3.3    |
+| 4.x     | EOL        | `guzzlehttp/guzzle` | `GuzzleHttp` | [v4][guzzle-4-repo] | N/A                 | No    | >= 5.4      |
+| 5.x     | Maintained | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No    | >= 5.4      |
+| 6.x     | Latest     | `guzzlehttp/guzzle` | `GuzzleHttp` | [v6][guzzle-6-repo] | [v6][guzzle-6-docs] | Yes   | >= 5.5      |
+
+[guzzle-3-repo]: https://github.com/guzzle/guzzle3
+[guzzle-4-repo]: https://github.com/guzzle/guzzle/tree/4.x
+[guzzle-5-repo]: https://github.com/guzzle/guzzle/tree/5.3
+[guzzle-6-repo]: https://github.com/guzzle/guzzle
+[guzzle-3-docs]: http://guzzle3.readthedocs.org/en/latest/
+[guzzle-5-docs]: http://guzzle.readthedocs.org/en/5.3/
+[guzzle-6-docs]: http://guzzle.readthedocs.org/en/latest/
diff --git a/vendor/guzzlehttp/guzzle/UPGRADING.md b/vendor/guzzlehttp/guzzle/UPGRADING.md
new file mode 100644
index 00000000000..91d1dcc9931
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/UPGRADING.md
@@ -0,0 +1,1203 @@
+Guzzle Upgrade Guide
+====================
+
+5.0 to 6.0
+----------
+
+Guzzle now uses [PSR-7](http://www.php-fig.org/psr/psr-7/) for HTTP messages.
+Due to the fact that these messages are immutable, this prompted a refactoring
+of Guzzle to use a middleware based system rather than an event system. Any
+HTTP message interaction (e.g., `GuzzleHttp\Message\Request`) need to be
+updated to work with the new immutable PSR-7 request and response objects. Any
+event listeners or subscribers need to be updated to become middleware
+functions that wrap handlers (or are injected into a
+`GuzzleHttp\HandlerStack`).
+
+- Removed `GuzzleHttp\BatchResults`
+- Removed `GuzzleHttp\Collection`
+- Removed `GuzzleHttp\HasDataTrait`
+- Removed `GuzzleHttp\ToArrayInterface`
+- The `guzzlehttp/streams` dependency has been removed. Stream functionality
+  is now present in the `GuzzleHttp\Psr7` namespace provided by the
+  `guzzlehttp/psr7` package.
+- Guzzle no longer uses ReactPHP promises and now uses the
+  `guzzlehttp/promises` library. We use a custom promise library for three
+  significant reasons:
+  1. React promises (at the time of writing this) are recursive. Promise
+     chaining and promise resolution will eventually blow the stack. Guzzle
+     promises are not recursive as they use a sort of trampolining technique.
+     Note: there has been movement in the React project to modify promises to
+     no longer utilize recursion.
+  2. Guzzle needs to have the ability to synchronously block on a promise to
+     wait for a result. Guzzle promises allows this functionality (and does
+     not require the use of recursion).
+  3. Because we need to be able to wait on a result, doing so using React
+     promises requires wrapping react promises with RingPHP futures. This
+     overhead is no longer needed, reducing stack sizes, reducing complexity,
+     and improving performance.
+- `GuzzleHttp\Mimetypes` has been moved to a function in
+  `GuzzleHttp\Psr7\mimetype_from_extension` and
+  `GuzzleHttp\Psr7\mimetype_from_filename`.
+- `GuzzleHttp\Query` and `GuzzleHttp\QueryParser` have been removed. Query
+  strings must now be passed into request objects as strings, or provided to
+  the `query` request option when creating requests with clients. The `query`
+  option uses PHP's `http_build_query` to convert an array to a string. If you
+  need a different serialization technique, you will need to pass the query
+  string in as a string. There are a couple helper functions that will make
+  working with query strings easier: `GuzzleHttp\Psr7\parse_query` and
+  `GuzzleHttp\Psr7\build_query`.
+- Guzzle no longer has a dependency on RingPHP. Due to the use of a middleware
+  system based on PSR-7, using RingPHP and it's middleware system as well adds
+  more complexity than the benefits it provides. All HTTP handlers that were
+  present in RingPHP have been modified to work directly with PSR-7 messages
+  and placed in the `GuzzleHttp\Handler` namespace. This significantly reduces
+  complexity in Guzzle, removes a dependency, and improves performance. RingPHP
+  will be maintained for Guzzle 5 support, but will no longer be a part of
+  Guzzle 6.
+- As Guzzle now uses a middleware based systems the event system and RingPHP
+  integration has been removed. Note: while the event system has been removed,
+  it is possible to add your own type of event system that is powered by the
+  middleware system.
+  - Removed the `Event` namespace.
+  - Removed the `Subscriber` namespace.
+  - Removed `Transaction` class
+  - Removed `RequestFsm`
+  - Removed `RingBridge`
+  - `GuzzleHttp\Subscriber\Cookie` is now provided by
+    `GuzzleHttp\Middleware::cookies`
+  - `GuzzleHttp\Subscriber\HttpError` is now provided by
+    `GuzzleHttp\Middleware::httpError`
+  - `GuzzleHttp\Subscriber\History` is now provided by
+    `GuzzleHttp\Middleware::history`
+  - `GuzzleHttp\Subscriber\Mock` is now provided by
+    `GuzzleHttp\Handler\MockHandler`
+  - `GuzzleHttp\Subscriber\Prepare` is now provided by
+    `GuzzleHttp\PrepareBodyMiddleware`
+  - `GuzzleHttp\Subscriber\Redirect` is now provided by
+    `GuzzleHttp\RedirectMiddleware`
+- Guzzle now uses `Psr\Http\Message\UriInterface` (implements in
+  `GuzzleHttp\Psr7\Uri`) for URI support. `GuzzleHttp\Url` is now gone.
+- Static functions in `GuzzleHttp\Utils` have been moved to namespaced
+  functions under the `GuzzleHttp` namespace. This requires either a Composer
+  based autoloader or you to include functions.php.
+- `GuzzleHttp\ClientInterface::getDefaultOption` has been renamed to
+  `GuzzleHttp\ClientInterface::getConfig`.
+- `GuzzleHttp\ClientInterface::setDefaultOption` has been removed.
+- The `json` and `xml` methods of response objects has been removed. With the
+  migration to strictly adhering to PSR-7 as the interface for Guzzle messages,
+  adding methods to message interfaces would actually require Guzzle messages
+  to extend from PSR-7 messages rather then work with them directly.
+
+## Migrating to middleware
+
+The change to PSR-7 unfortunately required significant refactoring to Guzzle
+due to the fact that PSR-7 messages are immutable. Guzzle 5 relied on an event
+system from plugins. The event system relied on mutability of HTTP messages and
+side effects in order to work. With immutable messages, you have to change your
+workflow to become more about either returning a value (e.g., functional
+middlewares) or setting a value on an object. Guzzle v6 has chosen the
+functional middleware approach.
+
+Instead of using the event system to listen for things like the `before` event,
+you now create a stack based middleware function that intercepts a request on
+the way in and the promise of the response on the way out. This is a much
+simpler and more predictable approach than the event system and works nicely
+with PSR-7 middleware. Due to the use of promises, the middleware system is
+also asynchronous.
+
+v5:
+
+```php
+use GuzzleHttp\Event\BeforeEvent;
+$client = new GuzzleHttp\Client();
+// Get the emitter and listen to the before event.
+$client->getEmitter()->on('before', function (BeforeEvent $e) {
+    // Guzzle v5 events relied on mutation
+    $e->getRequest()->setHeader('X-Foo', 'Bar');
+});
+```
+
+v6:
+
+In v6, you can modify the request before it is sent using the `mapRequest`
+middleware. The idiomatic way in v6 to modify the request/response lifecycle is
+to setup a handler middleware stack up front and inject the handler into a
+client.
+
+```php
+use GuzzleHttp\Middleware;
+// Create a handler stack that has all of the default middlewares attached
+$handler = GuzzleHttp\HandlerStack::create();
+// Push the handler onto the handler stack
+$handler->push(Middleware::mapRequest(function (RequestInterface $request) {
+    // Notice that we have to return a request object
+    return $request->withHeader('X-Foo', 'Bar');
+}));
+// Inject the handler into the client
+$client = new GuzzleHttp\Client(['handler' => $handler]);
+```
+
+## POST Requests
+
+This version added the [`form_params`](http://guzzle.readthedocs.org/en/latest/request-options.html#form_params)
+and `multipart` request options. `form_params` is an associative array of
+strings or array of strings and is used to serialize an
+`application/x-www-form-urlencoded` POST request. The
+[`multipart`](http://guzzle.readthedocs.org/en/latest/request-options.html#multipart)
+option is now used to send a multipart/form-data POST request.
+
+`GuzzleHttp\Post\PostFile` has been removed. Use the `multipart` option to add
+POST files to a multipart/form-data request.
+
+The `body` option no longer accepts an array to send POST requests. Please use
+`multipart` or `form_params` instead.
+
+The `base_url` option has been renamed to `base_uri`.
+
+4.x to 5.0
+----------
+
+## Rewritten Adapter Layer
+
+Guzzle now uses [RingPHP](http://ringphp.readthedocs.org/en/latest) to send
+HTTP requests. The `adapter` option in a `GuzzleHttp\Client` constructor
+is still supported, but it has now been renamed to `handler`. Instead of
+passing a `GuzzleHttp\Adapter\AdapterInterface`, you must now pass a PHP
+`callable` that follows the RingPHP specification.
+
+## Removed Fluent Interfaces
+
+[Fluent interfaces were removed](http://ocramius.github.io/blog/fluent-interfaces-are-evil)
+from the following classes:
+
+- `GuzzleHttp\Collection`
+- `GuzzleHttp\Url`
+- `GuzzleHttp\Query`
+- `GuzzleHttp\Post\PostBody`
+- `GuzzleHttp\Cookie\SetCookie`
+
+## Removed functions.php
+
+Removed "functions.php", so that Guzzle is truly PSR-4 compliant. The following
+functions can be used as replacements.
+
+- `GuzzleHttp\json_decode` -> `GuzzleHttp\Utils::jsonDecode`
+- `GuzzleHttp\get_path` -> `GuzzleHttp\Utils::getPath`
+- `GuzzleHttp\Utils::setPath` -> `GuzzleHttp\set_path`
+- `GuzzleHttp\Pool::batch` -> `GuzzleHttp\batch`. This function is, however,
+  deprecated in favor of using `GuzzleHttp\Pool::batch()`.
+
+The "procedural" global client has been removed with no replacement (e.g.,
+`GuzzleHttp\get()`, `GuzzleHttp\post()`, etc.). Use a `GuzzleHttp\Client`
+object as a replacement.
+
+## `throwImmediately` has been removed
+
+The concept of "throwImmediately" has been removed from exceptions and error
+events. This control mechanism was used to stop a transfer of concurrent
+requests from completing. This can now be handled by throwing the exception or
+by cancelling a pool of requests or each outstanding future request
+individually.
+
+## headers event has been removed
+
+Removed the "headers" event. This event was only useful for changing the
+body a response once the headers of the response were known. You can implement
+a similar behavior in a number of ways. One example might be to use a
+FnStream that has access to the transaction being sent. For example, when the
+first byte is written, you could check if the response headers match your
+expectations, and if so, change the actual stream body that is being
+written to.
+
+## Updates to HTTP Messages
+
+Removed the `asArray` parameter from
+`GuzzleHttp\Message\MessageInterface::getHeader`. If you want to get a header
+value as an array, then use the newly added `getHeaderAsArray()` method of
+`MessageInterface`. This change makes the Guzzle interfaces compatible with
+the PSR-7 interfaces.
+
+3.x to 4.0
+----------
+
+## Overarching changes:
+
+- Now requires PHP 5.4 or greater.
+- No longer requires cURL to send requests.
+- Guzzle no longer wraps every exception it throws. Only exceptions that are
+  recoverable are now wrapped by Guzzle.
+- Various namespaces have been removed or renamed.
+- No longer requiring the Symfony EventDispatcher. A custom event dispatcher
+  based on the Symfony EventDispatcher is
+  now utilized in `GuzzleHttp\Event\EmitterInterface` (resulting in significant
+  speed and functionality improvements).
+
+Changes per Guzzle 3.x namespace are described below.
+
+## Batch
+
+The `Guzzle\Batch` namespace has been removed. This is best left to
+third-parties to implement on top of Guzzle's core HTTP library.
+
+## Cache
+
+The `Guzzle\Cache` namespace has been removed. (Todo: No suitable replacement
+has been implemented yet, but hoping to utilize a PSR cache interface).
+
+## Common
+
+- Removed all of the wrapped exceptions. It's better to use the standard PHP
+  library for unrecoverable exceptions.
+- `FromConfigInterface` has been removed.
+- `Guzzle\Common\Version` has been removed. The VERSION constant can be found
+  at `GuzzleHttp\ClientInterface::VERSION`.
+
+### Collection
+
+- `getAll` has been removed. Use `toArray` to convert a collection to an array.
+- `inject` has been removed.
+- `keySearch` has been removed.
+- `getPath` no longer supports wildcard expressions. Use something better like
+  JMESPath for this.
+- `setPath` now supports appending to an existing array via the `[]` notation.
+
+### Events
+
+Guzzle no longer requires Symfony's EventDispatcher component. Guzzle now uses
+`GuzzleHttp\Event\Emitter`.
+
+- `Symfony\Component\EventDispatcher\EventDispatcherInterface` is replaced by
+  `GuzzleHttp\Event\EmitterInterface`.
+- `Symfony\Component\EventDispatcher\EventDispatcher` is replaced by
+  `GuzzleHttp\Event\Emitter`.
+- `Symfony\Component\EventDispatcher\Event` is replaced by
+  `GuzzleHttp\Event\Event`, and Guzzle now has an EventInterface in
+  `GuzzleHttp\Event\EventInterface`.
+- `AbstractHasDispatcher` has moved to a trait, `HasEmitterTrait`, and
+  `HasDispatcherInterface` has moved to `HasEmitterInterface`. Retrieving the
+  event emitter of a request, client, etc. now uses the `getEmitter` method
+  rather than the `getDispatcher` method.
+
+#### Emitter
+
+- Use the `once()` method to add a listener that automatically removes itself
+  the first time it is invoked.
+- Use the `listeners()` method to retrieve a list of event listeners rather than
+  the `getListeners()` method.
+- Use `emit()` instead of `dispatch()` to emit an event from an emitter.
+- Use `attach()` instead of `addSubscriber()` and `detach()` instead of
+  `removeSubscriber()`.
+
+```php
+$mock = new Mock();
+// 3.x
+$request->getEventDispatcher()->addSubscriber($mock);
+$request->getEventDispatcher()->removeSubscriber($mock);
+// 4.x
+$request->getEmitter()->attach($mock);
+$request->getEmitter()->detach($mock);
+```
+
+Use the `on()` method to add a listener rather than the `addListener()` method.
+
+```php
+// 3.x
+$request->getEventDispatcher()->addListener('foo', function (Event $event) { /* ... */ } );
+// 4.x
+$request->getEmitter()->on('foo', function (Event $event, $name) { /* ... */ } );
+```
+
+## Http
+
+### General changes
+
+- The cacert.pem certificate has been moved to `src/cacert.pem`.
+- Added the concept of adapters that are used to transfer requests over the
+  wire.
+- Simplified the event system.
+- Sending requests in parallel is still possible, but batching is no longer a
+  concept of the HTTP layer. Instead, you must use the `complete` and `error`
+  events to asynchronously manage parallel request transfers.
+- `Guzzle\Http\Url` has moved to `GuzzleHttp\Url`.
+- `Guzzle\Http\QueryString` has moved to `GuzzleHttp\Query`.
+- QueryAggregators have been rewritten so that they are simply callable
+  functions.
+- `GuzzleHttp\StaticClient` has been removed. Use the functions provided in
+  `functions.php` for an easy to use static client instance.
+- Exceptions in `GuzzleHttp\Exception` have been updated to all extend from
+  `GuzzleHttp\Exception\TransferException`.
+
+### Client
+
+Calling methods like `get()`, `post()`, `head()`, etc. no longer create and
+return a request, but rather creates a request, sends the request, and returns
+the response.
+
+```php
+// 3.0
+$request = $client->get('/');
+$response = $request->send();
+
+// 4.0
+$response = $client->get('/');
+
+// or, to mirror the previous behavior
+$request = $client->createRequest('GET', '/');
+$response = $client->send($request);
+```
+
+`GuzzleHttp\ClientInterface` has changed.
+
+- The `send` method no longer accepts more than one request. Use `sendAll` to
+  send multiple requests in parallel.
+- `setUserAgent()` has been removed. Use a default request option instead. You
+  could, for example, do something like:
+  `$client->setConfig('defaults/headers/User-Agent', 'Foo/Bar ' . $client::getDefaultUserAgent())`.
+- `setSslVerification()` has been removed. Use default request options instead,
+  like `$client->setConfig('defaults/verify', true)`.
+
+`GuzzleHttp\Client` has changed.
+
+- The constructor now accepts only an associative array. You can include a
+  `base_url` string or array to use a URI template as the base URL of a client.
+  You can also specify a `defaults` key that is an associative array of default
+  request options. You can pass an `adapter` to use a custom adapter,
+  `batch_adapter` to use a custom adapter for sending requests in parallel, or
+  a `message_factory` to change the factory used to create HTTP requests and
+  responses.
+- The client no longer emits a `client.create_request` event.
+- Creating requests with a client no longer automatically utilize a URI
+  template. You must pass an array into a creational method (e.g.,
+  `createRequest`, `get`, `put`, etc.) in order to expand a URI template.
+
+### Messages
+
+Messages no longer have references to their counterparts (i.e., a request no
+longer has a reference to it's response, and a response no loger has a
+reference to its request). This association is now managed through a
+`GuzzleHttp\Adapter\TransactionInterface` object. You can get references to
+these transaction objects using request events that are emitted over the
+lifecycle of a request.
+
+#### Requests with a body
+
+- `GuzzleHttp\Message\EntityEnclosingRequest` and
+  `GuzzleHttp\Message\EntityEnclosingRequestInterface` have been removed. The
+  separation between requests that contain a body and requests that do not
+  contain a body has been removed, and now `GuzzleHttp\Message\RequestInterface`
+  handles both use cases.
+- Any method that previously accepts a `GuzzleHttp\Response` object now accept a
+  `GuzzleHttp\Message\ResponseInterface`.
+- `GuzzleHttp\Message\RequestFactoryInterface` has been renamed to
+  `GuzzleHttp\Message\MessageFactoryInterface`. This interface is used to create
+  both requests and responses and is implemented in
+  `GuzzleHttp\Message\MessageFactory`.
+- POST field and file methods have been removed from the request object. You
+  must now use the methods made available to `GuzzleHttp\Post\PostBodyInterface`
+  to control the format of a POST body. Requests that are created using a
+  standard `GuzzleHttp\Message\MessageFactoryInterface` will automatically use
+  a `GuzzleHttp\Post\PostBody` body if the body was passed as an array or if
+  the method is POST and no body is provided.
+
+```php
+$request = $client->createRequest('POST', '/');
+$request->getBody()->setField('foo', 'bar');
+$request->getBody()->addFile(new PostFile('file_key', fopen('/path/to/content', 'r')));
+```
+
+#### Headers
+
+- `GuzzleHttp\Message\Header` has been removed. Header values are now simply
+  represented by an array of values or as a string. Header values are returned
+  as a string by default when retrieving a header value from a message. You can
+  pass an optional argument of `true` to retrieve a header value as an array
+  of strings instead of a single concatenated string.
+- `GuzzleHttp\PostFile` and `GuzzleHttp\PostFileInterface` have been moved to
+  `GuzzleHttp\Post`. This interface has been simplified and now allows the
+  addition of arbitrary headers.
+- Custom headers like `GuzzleHttp\Message\Header\Link` have been removed. Most
+  of the custom headers are now handled separately in specific
+  subscribers/plugins, and `GuzzleHttp\Message\HeaderValues::parseParams()` has
+  been updated to properly handle headers that contain parameters (like the
+  `Link` header).
+
+#### Responses
+
+- `GuzzleHttp\Message\Response::getInfo()` and
+  `GuzzleHttp\Message\Response::setInfo()` have been removed. Use the event
+  system to retrieve this type of information.
+- `GuzzleHttp\Message\Response::getRawHeaders()` has been removed.
+- `GuzzleHttp\Message\Response::getMessage()` has been removed.
+- `GuzzleHttp\Message\Response::calculateAge()` and other cache specific
+  methods have moved to the CacheSubscriber.
+- Header specific helper functions like `getContentMd5()` have been removed.
+  Just use `getHeader('Content-MD5')` instead.
+- `GuzzleHttp\Message\Response::setRequest()` and
+  `GuzzleHttp\Message\Response::getRequest()` have been removed. Use the event
+  system to work with request and response objects as a transaction.
+- `GuzzleHttp\Message\Response::getRedirectCount()` has been removed. Use the
+  Redirect subscriber instead.
+- `GuzzleHttp\Message\Response::isSuccessful()` and other related methods have
+  been removed. Use `getStatusCode()` instead.
+
+#### Streaming responses
+
+Streaming requests can now be created by a client directly, returning a
+`GuzzleHttp\Message\ResponseInterface` object that contains a body stream
+referencing an open PHP HTTP stream.
+
+```php
+// 3.0
+use Guzzle\Stream\PhpStreamRequestFactory;
+$request = $client->get('/');
+$factory = new PhpStreamRequestFactory();
+$stream = $factory->fromRequest($request);
+$data = $stream->read(1024);
+
+// 4.0
+$response = $client->get('/', ['stream' => true]);
+// Read some data off of the stream in the response body
+$data = $response->getBody()->read(1024);
+```
+
+#### Redirects
+
+The `configureRedirects()` method has been removed in favor of a
+`allow_redirects` request option.
+
+```php
+// Standard redirects with a default of a max of 5 redirects
+$request = $client->createRequest('GET', '/', ['allow_redirects' => true]);
+
+// Strict redirects with a custom number of redirects
+$request = $client->createRequest('GET', '/', [
+    'allow_redirects' => ['max' => 5, 'strict' => true]
+]);
+```
+
+#### EntityBody
+
+EntityBody interfaces and classes have been removed or moved to
+`GuzzleHttp\Stream`. All classes and interfaces that once required
+`GuzzleHttp\EntityBodyInterface` now require
+`GuzzleHttp\Stream\StreamInterface`. Creating a new body for a request no
+longer uses `GuzzleHttp\EntityBody::factory` but now uses
+`GuzzleHttp\Stream\Stream::factory` or even better:
+`GuzzleHttp\Stream\create()`.
+
+- `Guzzle\Http\EntityBodyInterface` is now `GuzzleHttp\Stream\StreamInterface`
+- `Guzzle\Http\EntityBody` is now `GuzzleHttp\Stream\Stream`
+- `Guzzle\Http\CachingEntityBody` is now `GuzzleHttp\Stream\CachingStream`
+- `Guzzle\Http\ReadLimitEntityBody` is now `GuzzleHttp\Stream\LimitStream`
+- `Guzzle\Http\IoEmittyinEntityBody` has been removed.
+
+#### Request lifecycle events
+
+Requests previously submitted a large number of requests. The number of events
+emitted over the lifecycle of a request has been significantly reduced to make
+it easier to understand how to extend the behavior of a request. All events
+emitted during the lifecycle of a request now emit a custom
+`GuzzleHttp\Event\EventInterface` object that contains context providing
+methods and a way in which to modify the transaction at that specific point in
+time (e.g., intercept the request and set a response on the transaction).
+
+- `request.before_send` has been renamed to `before` and now emits a
+  `GuzzleHttp\Event\BeforeEvent`
+- `request.complete` has been renamed to `complete` and now emits a
+  `GuzzleHttp\Event\CompleteEvent`.
+- `request.sent` has been removed. Use `complete`.
+- `request.success` has been removed. Use `complete`.
+- `error` is now an event that emits a `GuzzleHttp\Event\ErrorEvent`.
+- `request.exception` has been removed. Use `error`.
+- `request.receive.status_line` has been removed.
+- `curl.callback.progress` has been removed. Use a custom `StreamInterface` to
+  maintain a status update.
+- `curl.callback.write` has been removed. Use a custom `StreamInterface` to
+  intercept writes.
+- `curl.callback.read` has been removed. Use a custom `StreamInterface` to
+  intercept reads.
+
+`headers` is a new event that is emitted after the response headers of a
+request have been received before the body of the response is downloaded. This
+event emits a `GuzzleHttp\Event\HeadersEvent`.
+
+You can intercept a request and inject a response using the `intercept()` event
+of a `GuzzleHttp\Event\BeforeEvent`, `GuzzleHttp\Event\CompleteEvent`, and
+`GuzzleHttp\Event\ErrorEvent` event.
+
+See: http://docs.guzzlephp.org/en/latest/events.html
+
+## Inflection
+
+The `Guzzle\Inflection` namespace has been removed. This is not a core concern
+of Guzzle.
+
+## Iterator
+
+The `Guzzle\Iterator` namespace has been removed.
+
+- `Guzzle\Iterator\AppendIterator`, `Guzzle\Iterator\ChunkedIterator`, and
+  `Guzzle\Iterator\MethodProxyIterator` are nice, but not a core requirement of
+  Guzzle itself.
+- `Guzzle\Iterator\FilterIterator` is no longer needed because an equivalent
+  class is shipped with PHP 5.4.
+- `Guzzle\Iterator\MapIterator` is not really needed when using PHP 5.5 because
+  it's easier to just wrap an iterator in a generator that maps values.
+
+For a replacement of these iterators, see https://github.com/nikic/iter
+
+## Log
+
+The LogPlugin has moved to https://github.com/guzzle/log-subscriber. The
+`Guzzle\Log` namespace has been removed. Guzzle now relies on
+`Psr\Log\LoggerInterface` for all logging. The MessageFormatter class has been
+moved to `GuzzleHttp\Subscriber\Log\Formatter`.
+
+## Parser
+
+The `Guzzle\Parser` namespace has been removed. This was previously used to
+make it possible to plug in custom parsers for cookies, messages, URI
+templates, and URLs; however, this level of complexity is not needed in Guzzle
+so it has been removed.
+
+- Cookie: Cookie parsing logic has been moved to
+  `GuzzleHttp\Cookie\SetCookie::fromString`.
+- Message: Message parsing logic for both requests and responses has been moved
+  to `GuzzleHttp\Message\MessageFactory::fromMessage`. Message parsing is only
+  used in debugging or deserializing messages, so it doesn't make sense for
+  Guzzle as a library to add this level of complexity to parsing messages.
+- UriTemplate: URI template parsing has been moved to
+  `GuzzleHttp\UriTemplate`. The Guzzle library will automatically use the PECL
+  URI template library if it is installed.
+- Url: URL parsing is now performed in `GuzzleHttp\Url::fromString` (previously
+  it was `Guzzle\Http\Url::factory()`). If custom URL parsing is necessary,
+  then developers are free to subclass `GuzzleHttp\Url`.
+
+## Plugin
+
+The `Guzzle\Plugin` namespace has been renamed to `GuzzleHttp\Subscriber`.
+Several plugins are shipping with the core Guzzle library under this namespace.
+
+- `GuzzleHttp\Subscriber\Cookie`: Replaces the old CookiePlugin. Cookie jar
+  code has moved to `GuzzleHttp\Cookie`.
+- `GuzzleHttp\Subscriber\History`: Replaces the old HistoryPlugin.
+- `GuzzleHttp\Subscriber\HttpError`: Throws errors when a bad HTTP response is
+  received.
+- `GuzzleHttp\Subscriber\Mock`: Replaces the old MockPlugin.
+- `GuzzleHttp\Subscriber\Prepare`: Prepares the body of a request just before
+  sending. This subscriber is attached to all requests by default.
+- `GuzzleHttp\Subscriber\Redirect`: Replaces the RedirectPlugin.
+
+The following plugins have been removed (third-parties are free to re-implement
+these if needed):
+
+- `GuzzleHttp\Plugin\Async` has been removed.
+- `GuzzleHttp\Plugin\CurlAuth` has been removed.
+- `GuzzleHttp\Plugin\ErrorResponse\ErrorResponsePlugin` has been removed. This
+  functionality should instead be implemented with event listeners that occur
+  after normal response parsing occurs in the guzzle/command package.
+
+The following plugins are not part of the core Guzzle package, but are provided
+in separate repositories:
+
+- `Guzzle\Http\Plugin\BackoffPlugin` has been rewritten to be much simpler
+  to build custom retry policies using simple functions rather than various
+  chained classes. See: https://github.com/guzzle/retry-subscriber
+- `Guzzle\Http\Plugin\Cache\CachePlugin` has moved to
+  https://github.com/guzzle/cache-subscriber
+- `Guzzle\Http\Plugin\Log\LogPlugin` has moved to
+  https://github.com/guzzle/log-subscriber
+- `Guzzle\Http\Plugin\Md5\Md5Plugin` has moved to
+  https://github.com/guzzle/message-integrity-subscriber
+- `Guzzle\Http\Plugin\Mock\MockPlugin` has moved to
+  `GuzzleHttp\Subscriber\MockSubscriber`.
+- `Guzzle\Http\Plugin\Oauth\OauthPlugin` has moved to
+  https://github.com/guzzle/oauth-subscriber
+
+## Service
+
+The service description layer of Guzzle has moved into two separate packages:
+
+- http://github.com/guzzle/command Provides a high level abstraction over web
+  services by representing web service operations using commands.
+- http://github.com/guzzle/guzzle-services Provides an implementation of
+  guzzle/command that provides request serialization and response parsing using
+  Guzzle service descriptions.
+
+## Stream
+
+Stream have moved to a separate package available at
+https://github.com/guzzle/streams.
+
+`Guzzle\Stream\StreamInterface` has been given a large update to cleanly take
+on the responsibilities of `Guzzle\Http\EntityBody` and
+`Guzzle\Http\EntityBodyInterface` now that they have been removed. The number
+of methods implemented by the `StreamInterface` has been drastically reduced to
+allow developers to more easily extend and decorate stream behavior.
+
+## Removed methods from StreamInterface
+
+- `getStream` and `setStream` have been removed to better encapsulate streams.
+- `getMetadata` and `setMetadata` have been removed in favor of
+  `GuzzleHttp\Stream\MetadataStreamInterface`.
+- `getWrapper`, `getWrapperData`, `getStreamType`, and `getUri` have all been
+  removed. This data is accessible when
+  using streams that implement `GuzzleHttp\Stream\MetadataStreamInterface`.
+- `rewind` has been removed. Use `seek(0)` for a similar behavior.
+
+## Renamed methods
+
+- `detachStream` has been renamed to `detach`.
+- `feof` has been renamed to `eof`.
+- `ftell` has been renamed to `tell`.
+- `readLine` has moved from an instance method to a static class method of
+  `GuzzleHttp\Stream\Stream`.
+
+## Metadata streams
+
+`GuzzleHttp\Stream\MetadataStreamInterface` has been added to denote streams
+that contain additional metadata accessible via `getMetadata()`.
+`GuzzleHttp\Stream\StreamInterface::getMetadata` and
+`GuzzleHttp\Stream\StreamInterface::setMetadata` have been removed.
+
+## StreamRequestFactory
+
+The entire concept of the StreamRequestFactory has been removed. The way this
+was used in Guzzle 3 broke the actual interface of sending streaming requests
+(instead of getting back a Response, you got a StreamInterface). Streaming
+PHP requests are now implemented through the `GuzzleHttp\Adapter\StreamAdapter`.
+
+3.6 to 3.7
+----------
+
+### Deprecations
+
+- You can now enable E_USER_DEPRECATED warnings to see if you are using any deprecated methods.:
+
+```php
+\Guzzle\Common\Version::$emitWarnings = true;
+```
+
+The following APIs and options have been marked as deprecated:
+
+- Marked `Guzzle\Http\Message\Request::isResponseBodyRepeatable()` as deprecated. Use `$request->getResponseBody()->isRepeatable()` instead.
+- Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead.
+- Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead.
+- Marked `Guzzle\Http\Message\Request::setIsRedirect()` as deprecated. Use the HistoryPlugin instead.
+- Marked `Guzzle\Http\Message\Request::isRedirect()` as deprecated. Use the HistoryPlugin instead.
+- Marked `Guzzle\Cache\CacheAdapterFactory::factory()` as deprecated
+- Marked `Guzzle\Service\Client::enableMagicMethods()` as deprecated. Magic methods can no longer be disabled on a Guzzle\Service\Client.
+- Marked `Guzzle\Parser\Url\UrlParser` as deprecated. Just use PHP's `parse_url()` and percent encode your UTF-8.
+- Marked `Guzzle\Common\Collection::inject()` as deprecated.
+- Marked `Guzzle\Plugin\CurlAuth\CurlAuthPlugin` as deprecated. Use
+  `$client->getConfig()->setPath('request.options/auth', array('user', 'pass', 'Basic|Digest|NTLM|Any'));` or
+  `$client->setDefaultOption('auth', array('user', 'pass', 'Basic|Digest|NTLM|Any'));`
+
+3.7 introduces `request.options` as a parameter for a client configuration and as an optional argument to all creational
+request methods. When paired with a client's configuration settings, these options allow you to specify default settings
+for various aspects of a request. Because these options make other previous configuration options redundant, several
+configuration options and methods of a client and AbstractCommand have been deprecated.
+
+- Marked `Guzzle\Service\Client::getDefaultHeaders()` as deprecated. Use `$client->getDefaultOption('headers')`.
+- Marked `Guzzle\Service\Client::setDefaultHeaders()` as deprecated. Use `$client->setDefaultOption('headers/{header_name}', 'value')`.
+- Marked 'request.params' for `Guzzle\Http\Client` as deprecated. Use `$client->setDefaultOption('params/{param_name}', 'value')`
+- Marked 'command.headers', 'command.response_body' and 'command.on_complete' as deprecated for AbstractCommand. These will work through Guzzle 4.0
+
+        $command = $client->getCommand('foo', array(
+            'command.headers' => array('Test' => '123'),
+            'command.response_body' => '/path/to/file'
+        ));
+
+        // Should be changed to:
+
+        $command = $client->getCommand('foo', array(
+            'command.request_options' => array(
+                'headers' => array('Test' => '123'),
+                'save_as' => '/path/to/file'
+            )
+        ));
+
+### Interface changes
+
+Additions and changes (you will need to update any implementations or subclasses you may have created):
+
+- Added an `$options` argument to the end of the following methods of `Guzzle\Http\ClientInterface`:
+  createRequest, head, delete, put, patch, post, options, prepareRequest
+- Added an `$options` argument to the end of `Guzzle\Http\Message\Request\RequestFactoryInterface::createRequest()`
+- Added an `applyOptions()` method to `Guzzle\Http\Message\Request\RequestFactoryInterface`
+- Changed `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $body = null)` to
+  `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $options = array())`. You can still pass in a
+  resource, string, or EntityBody into the $options parameter to specify the download location of the response.
+- Changed `Guzzle\Common\Collection::__construct($data)` to no longer accepts a null value for `$data` but a
+  default `array()`
+- Added `Guzzle\Stream\StreamInterface::isRepeatable`
+- Made `Guzzle\Http\Client::expandTemplate` and `getUriTemplate` protected methods.
+
+The following methods were removed from interfaces. All of these methods are still available in the concrete classes
+that implement them, but you should update your code to use alternative methods:
+
+- Removed `Guzzle\Http\ClientInterface::setDefaultHeaders(). Use
+  `$client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`. or
+  `$client->getConfig()->setPath('request.options/headers', array('header_name' => 'value'))` or
+  `$client->setDefaultOption('headers/{header_name}', 'value')`. or
+  `$client->setDefaultOption('headers', array('header_name' => 'value'))`.
+- Removed `Guzzle\Http\ClientInterface::getDefaultHeaders(). Use `$client->getConfig()->getPath('request.options/headers')`.
+- Removed `Guzzle\Http\ClientInterface::expandTemplate()`. This is an implementation detail.
+- Removed `Guzzle\Http\ClientInterface::setRequestFactory()`. This is an implementation detail.
+- Removed `Guzzle\Http\ClientInterface::getCurlMulti()`. This is a very specific implementation detail.
+- Removed `Guzzle\Http\Message\RequestInterface::canCache`. Use the CachePlugin.
+- Removed `Guzzle\Http\Message\RequestInterface::setIsRedirect`. Use the HistoryPlugin.
+- Removed `Guzzle\Http\Message\RequestInterface::isRedirect`. Use the HistoryPlugin.
+
+### Cache plugin breaking changes
+
+- CacheKeyProviderInterface and DefaultCacheKeyProvider are no longer used. All of this logic is handled in a
+  CacheStorageInterface. These two objects and interface will be removed in a future version.
+- Always setting X-cache headers on cached responses
+- Default cache TTLs are now handled by the CacheStorageInterface of a CachePlugin
+- `CacheStorageInterface::cache($key, Response $response, $ttl = null)` has changed to `cache(RequestInterface
+  $request, Response $response);`
+- `CacheStorageInterface::fetch($key)` has changed to `fetch(RequestInterface $request);`
+- `CacheStorageInterface::delete($key)` has changed to `delete(RequestInterface $request);`
+- Added `CacheStorageInterface::purge($url)`
+- `DefaultRevalidation::__construct(CacheKeyProviderInterface $cacheKey, CacheStorageInterface $cache, CachePlugin
+  $plugin)` has changed to `DefaultRevalidation::__construct(CacheStorageInterface $cache,
+  CanCacheStrategyInterface $canCache = null)`
+- Added `RevalidationInterface::shouldRevalidate(RequestInterface $request, Response $response)`
+
+3.5 to 3.6
+----------
+
+* Mixed casing of headers are now forced to be a single consistent casing across all values for that header.
+* Messages internally use a HeaderCollection object to delegate handling case-insensitive header resolution
+* Removed the whole changedHeader() function system of messages because all header changes now go through addHeader().
+  For example, setHeader() first removes the header using unset on a HeaderCollection and then calls addHeader().
+  Keeping the Host header and URL host in sync is now handled by overriding the addHeader method in Request.
+* Specific header implementations can be created for complex headers. When a message creates a header, it uses a
+  HeaderFactory which can map specific headers to specific header classes. There is now a Link header and
+  CacheControl header implementation.
+* Moved getLinks() from Response to just be used on a Link header object.
+
+If you previously relied on Guzzle\Http\Message\Header::raw(), then you will need to update your code to use the
+HeaderInterface (e.g. toArray(), getAll(), etc.).
+
+### Interface changes
+
+* Removed from interface: Guzzle\Http\ClientInterface::setUriTemplate
+* Removed from interface: Guzzle\Http\ClientInterface::setCurlMulti()
+* Removed Guzzle\Http\Message\Request::receivedRequestHeader() and implemented this functionality in
+  Guzzle\Http\Curl\RequestMediator
+* Removed the optional $asString parameter from MessageInterface::getHeader(). Just cast the header to a string.
+* Removed the optional $tryChunkedTransfer option from Guzzle\Http\Message\EntityEnclosingRequestInterface
+* Removed the $asObjects argument from Guzzle\Http\Message\MessageInterface::getHeaders()
+
+### Removed deprecated functions
+
+* Removed Guzzle\Parser\ParserRegister::get(). Use getParser()
+* Removed Guzzle\Parser\ParserRegister::set(). Use registerParser().
+
+### Deprecations
+
+* The ability to case-insensitively search for header values
+* Guzzle\Http\Message\Header::hasExactHeader
+* Guzzle\Http\Message\Header::raw. Use getAll()
+* Deprecated cache control specific methods on Guzzle\Http\Message\AbstractMessage. Use the CacheControl header object
+  instead.
+
+### Other changes
+
+* All response header helper functions return a string rather than mixing Header objects and strings inconsistently
+* Removed cURL blacklist support. This is no longer necessary now that Expect, Accept, etc. are managed by Guzzle
+  directly via interfaces
+* Removed the injecting of a request object onto a response object. The methods to get and set a request still exist
+  but are a no-op until removed.
+* Most classes that used to require a `Guzzle\Service\Command\CommandInterface` typehint now request a
+  `Guzzle\Service\Command\ArrayCommandInterface`.
+* Added `Guzzle\Http\Message\RequestInterface::startResponse()` to the RequestInterface to handle injecting a response
+  on a request while the request is still being transferred
+* `Guzzle\Service\Command\CommandInterface` now extends from ToArrayInterface and ArrayAccess
+
+3.3 to 3.4
+----------
+
+Base URLs of a client now follow the rules of http://tools.ietf.org/html/rfc3986#section-5.2.2 when merging URLs.
+
+3.2 to 3.3
+----------
+
+### Response::getEtag() quote stripping removed
+
+`Guzzle\Http\Message\Response::getEtag()` no longer strips quotes around the ETag response header
+
+### Removed `Guzzle\Http\Utils`
+
+The `Guzzle\Http\Utils` class was removed. This class was only used for testing.
+
+### Stream wrapper and type
+
+`Guzzle\Stream\Stream::getWrapper()` and `Guzzle\Stream\Stream::getStreamType()` are no longer converted to lowercase.
+
+### curl.emit_io became emit_io
+
+Emitting IO events from a RequestMediator is now a parameter that must be set in a request's curl options using the
+'emit_io' key. This was previously set under a request's parameters using 'curl.emit_io'
+
+3.1 to 3.2
+----------
+
+### CurlMulti is no longer reused globally
+
+Before 3.2, the same CurlMulti object was reused globally for each client. This can cause issue where plugins added
+to a single client can pollute requests dispatched from other clients.
+
+If you still wish to reuse the same CurlMulti object with each client, then you can add a listener to the
+ServiceBuilder's `service_builder.create_client` event to inject a custom CurlMulti object into each client as it is
+created.
+
+```php
+$multi = new Guzzle\Http\Curl\CurlMulti();
+$builder = Guzzle\Service\Builder\ServiceBuilder::factory('/path/to/config.json');
+$builder->addListener('service_builder.create_client', function ($event) use ($multi) {
+    $event['client']->setCurlMulti($multi);
+}
+});
+```
+
+### No default path
+
+URLs no longer have a default path value of '/' if no path was specified.
+
+Before:
+
+```php
+$request = $client->get('http://www.foo.com');
+echo $request->getUrl();
+// >> http://www.foo.com/
+```
+
+After:
+
+```php
+$request = $client->get('http://www.foo.com');
+echo $request->getUrl();
+// >> http://www.foo.com
+```
+
+### Less verbose BadResponseException
+
+The exception message for `Guzzle\Http\Exception\BadResponseException` no longer contains the full HTTP request and
+response information. You can, however, get access to the request and response object by calling `getRequest()` or
+`getResponse()` on the exception object.
+
+### Query parameter aggregation
+
+Multi-valued query parameters are no longer aggregated using a callback function. `Guzzle\Http\Query` now has a
+setAggregator() method that accepts a `Guzzle\Http\QueryAggregator\QueryAggregatorInterface` object. This object is
+responsible for handling the aggregation of multi-valued query string variables into a flattened hash.
+
+2.8 to 3.x
+----------
+
+### Guzzle\Service\Inspector
+
+Change `\Guzzle\Service\Inspector::fromConfig` to `\Guzzle\Common\Collection::fromConfig`
+
+**Before**
+
+```php
+use Guzzle\Service\Inspector;
+
+class YourClient extends \Guzzle\Service\Client
+{
+    public static function factory($config = array())
+    {
+        $default = array();
+        $required = array('base_url', 'username', 'api_key');
+        $config = Inspector::fromConfig($config, $default, $required);
+
+        $client = new self(
+            $config->get('base_url'),
+            $config->get('username'),
+            $config->get('api_key')
+        );
+        $client->setConfig($config);
+
+        $client->setDescription(ServiceDescription::factory(__DIR__ . DIRECTORY_SEPARATOR . 'client.json'));
+
+        return $client;
+    }
+```
+
+**After**
+
+```php
+use Guzzle\Common\Collection;
+
+class YourClient extends \Guzzle\Service\Client
+{
+    public static function factory($config = array())
+    {
+        $default = array();
+        $required = array('base_url', 'username', 'api_key');
+        $config = Collection::fromConfig($config, $default, $required);
+
+        $client = new self(
+            $config->get('base_url'),
+            $config->get('username'),
+            $config->get('api_key')
+        );
+        $client->setConfig($config);
+
+        $client->setDescription(ServiceDescription::factory(__DIR__ . DIRECTORY_SEPARATOR . 'client.json'));
+
+        return $client;
+    }
+```
+
+### Convert XML Service Descriptions to JSON
+
+**Before**
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<client>
+    <commands>
+        <!-- Groups -->
+        <command name="list_groups" method="GET" uri="groups.json">
+            <doc>Get a list of groups</doc>
+        </command>
+        <command name="search_groups" method="GET" uri='search.json?query="{{query}} type:group"'>
+            <doc>Uses a search query to get a list of groups</doc>
+            <param name="query" type="string" required="true" />
+        </command>
+        <command name="create_group" method="POST" uri="groups.json">
+            <doc>Create a group</doc>
+            <param name="data" type="array" location="body" filters="json_encode" doc="Group JSON"/>
+            <param name="Content-Type" location="header" static="application/json"/>
+        </command>
+        <command name="delete_group" method="DELETE" uri="groups/{{id}}.json">
+            <doc>Delete a group by ID</doc>
+            <param name="id" type="integer" required="true"/>
+        </command>
+        <command name="get_group" method="GET" uri="groups/{{id}}.json">
+            <param name="id" type="integer" required="true"/>
+        </command>
+        <command name="update_group" method="PUT" uri="groups/{{id}}.json">
+            <doc>Update a group</doc>
+            <param name="id" type="integer" required="true"/>
+            <param name="data" type="array" location="body" filters="json_encode" doc="Group JSON"/>
+            <param name="Content-Type" location="header" static="application/json"/>
+        </command>
+    </commands>
+</client>
+```
+
+**After**
+
+```json
+{
+    "name":       "Zendesk REST API v2",
+    "apiVersion": "2012-12-31",
+    "description":"Provides access to Zendesk views, groups, tickets, ticket fields, and users",
+    "operations": {
+        "list_groups":  {
+            "httpMethod":"GET",
+            "uri":       "groups.json",
+            "summary":   "Get a list of groups"
+        },
+        "search_groups":{
+            "httpMethod":"GET",
+            "uri":       "search.json?query=\"{query} type:group\"",
+            "summary":   "Uses a search query to get a list of groups",
+            "parameters":{
+                "query":{
+                    "location":   "uri",
+                    "description":"Zendesk Search Query",
+                    "type":       "string",
+                    "required":   true
+                }
+            }
+        },
+        "create_group": {
+            "httpMethod":"POST",
+            "uri":       "groups.json",
+            "summary":   "Create a group",
+            "parameters":{
+                "data":        {
+                    "type":       "array",
+                    "location":   "body",
+                    "description":"Group JSON",
+                    "filters":    "json_encode",
+                    "required":   true
+                },
+                "Content-Type":{
+                    "type":    "string",
+                    "location":"header",
+                    "static":  "application/json"
+                }
+            }
+        },
+        "delete_group": {
+            "httpMethod":"DELETE",
+            "uri":       "groups/{id}.json",
+            "summary":   "Delete a group",
+            "parameters":{
+                "id":{
+                    "location":   "uri",
+                    "description":"Group to delete by ID",
+                    "type":       "integer",
+                    "required":   true
+                }
+            }
+        },
+        "get_group":    {
+            "httpMethod":"GET",
+            "uri":       "groups/{id}.json",
+            "summary":   "Get a ticket",
+            "parameters":{
+                "id":{
+                    "location":   "uri",
+                    "description":"Group to get by ID",
+                    "type":       "integer",
+                    "required":   true
+                }
+            }
+        },
+        "update_group": {
+            "httpMethod":"PUT",
+            "uri":       "groups/{id}.json",
+            "summary":   "Update a group",
+            "parameters":{
+                "id":          {
+                    "location":   "uri",
+                    "description":"Group to update by ID",
+                    "type":       "integer",
+                    "required":   true
+                },
+                "data":        {
+                    "type":       "array",
+                    "location":   "body",
+                    "description":"Group JSON",
+                    "filters":    "json_encode",
+                    "required":   true
+                },
+                "Content-Type":{
+                    "type":    "string",
+                    "location":"header",
+                    "static":  "application/json"
+                }
+            }
+        }
+}
+```
+
+### Guzzle\Service\Description\ServiceDescription
+
+Commands are now called Operations
+
+**Before**
+
+```php
+use Guzzle\Service\Description\ServiceDescription;
+
+$sd = new ServiceDescription();
+$sd->getCommands();     // @returns ApiCommandInterface[]
+$sd->hasCommand($name);
+$sd->getCommand($name); // @returns ApiCommandInterface|null
+$sd->addCommand($command); // @param ApiCommandInterface $command
+```
+
+**After**
+
+```php
+use Guzzle\Service\Description\ServiceDescription;
+
+$sd = new ServiceDescription();
+$sd->getOperations();           // @returns OperationInterface[]
+$sd->hasOperation($name);
+$sd->getOperation($name);       // @returns OperationInterface|null
+$sd->addOperation($operation);  // @param OperationInterface $operation
+```
+
+### Guzzle\Common\Inflection\Inflector
+
+Namespace is now `Guzzle\Inflection\Inflector`
+
+### Guzzle\Http\Plugin
+
+Namespace is now `Guzzle\Plugin`. Many other changes occur within this namespace and are detailed in their own sections below.
+
+### Guzzle\Http\Plugin\LogPlugin and Guzzle\Common\Log
+
+Now `Guzzle\Plugin\Log\LogPlugin` and `Guzzle\Log` respectively.
+
+**Before**
+
+```php
+use Guzzle\Common\Log\ClosureLogAdapter;
+use Guzzle\Http\Plugin\LogPlugin;
+
+/** @var \Guzzle\Http\Client */
+$client;
+
+// $verbosity is an integer indicating desired message verbosity level
+$client->addSubscriber(new LogPlugin(new ClosureLogAdapter(function($m) { echo $m; }, $verbosity = LogPlugin::LOG_VERBOSE);
+```
+
+**After**
+
+```php
+use Guzzle\Log\ClosureLogAdapter;
+use Guzzle\Log\MessageFormatter;
+use Guzzle\Plugin\Log\LogPlugin;
+
+/** @var \Guzzle\Http\Client */
+$client;
+
+// $format is a string indicating desired message format -- @see MessageFormatter
+$client->addSubscriber(new LogPlugin(new ClosureLogAdapter(function($m) { echo $m; }, $format = MessageFormatter::DEBUG_FORMAT);
+```
+
+### Guzzle\Http\Plugin\CurlAuthPlugin
+
+Now `Guzzle\Plugin\CurlAuth\CurlAuthPlugin`.
+
+### Guzzle\Http\Plugin\ExponentialBackoffPlugin
+
+Now `Guzzle\Plugin\Backoff\BackoffPlugin`, and other changes.
+
+**Before**
+
+```php
+use Guzzle\Http\Plugin\ExponentialBackoffPlugin;
+
+$backoffPlugin = new ExponentialBackoffPlugin($maxRetries, array_merge(
+        ExponentialBackoffPlugin::getDefaultFailureCodes(), array(429)
+    ));
+
+$client->addSubscriber($backoffPlugin);
+```
+
+**After**
+
+```php
+use Guzzle\Plugin\Backoff\BackoffPlugin;
+use Guzzle\Plugin\Backoff\HttpBackoffStrategy;
+
+// Use convenient factory method instead -- see implementation for ideas of what
+// you can do with chaining backoff strategies
+$backoffPlugin = BackoffPlugin::getExponentialBackoff($maxRetries, array_merge(
+        HttpBackoffStrategy::getDefaultFailureCodes(), array(429)
+    ));
+$client->addSubscriber($backoffPlugin);
+```
+
+### Known Issues
+
+#### [BUG] Accept-Encoding header behavior changed unintentionally.
+
+(See #217) (Fixed in 09daeb8c666fb44499a0646d655a8ae36456575e)
+
+In version 2.8 setting the `Accept-Encoding` header would set the CURLOPT_ENCODING option, which permitted cURL to
+properly handle gzip/deflate compressed responses from the server. In versions affected by this bug this does not happen.
+See issue #217 for a workaround, or use a version containing the fix.
diff --git a/vendor/guzzlehttp/guzzle/composer.json b/vendor/guzzlehttp/guzzle/composer.json
new file mode 100644
index 00000000000..1f328e308cd
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/composer.json
@@ -0,0 +1,44 @@
+{
+    "name": "guzzlehttp/guzzle",
+    "type": "library",
+    "description": "Guzzle is a PHP HTTP client library",
+    "keywords": ["framework", "http", "rest", "web service", "curl", "client", "HTTP client"],
+    "homepage": "http://guzzlephp.org/",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Michael Dowling",
+            "email": "mtdowling@gmail.com",
+            "homepage": "https://github.com/mtdowling"
+        }
+    ],
+    "require": {
+        "php": ">=5.5",
+        "guzzlehttp/psr7": "^1.4",
+        "guzzlehttp/promises": "^1.0"
+    },
+    "require-dev": {
+        "ext-curl": "*",
+        "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
+        "psr/log": "^1.0"
+    },
+    "autoload": {
+        "files": ["src/functions_include.php"],
+        "psr-4": {
+            "GuzzleHttp\\": "src/"
+        }
+    },
+    "autoload-dev": {
+        "psr-4": {
+            "GuzzleHttp\\Tests\\": "tests/"
+        }
+    },
+    "suggest": {
+        "psr/log": "Required for using the Log middleware"
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "6.3-dev"
+        }
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/Client.php b/vendor/guzzlehttp/guzzle/src/Client.php
new file mode 100644
index 00000000000..80417918d05
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Client.php
@@ -0,0 +1,422 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Cookie\CookieJar;
+use GuzzleHttp\Promise;
+use GuzzleHttp\Psr7;
+use Psr\Http\Message\UriInterface;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * @method ResponseInterface get(string|UriInterface $uri, array $options = [])
+ * @method ResponseInterface head(string|UriInterface $uri, array $options = [])
+ * @method ResponseInterface put(string|UriInterface $uri, array $options = [])
+ * @method ResponseInterface post(string|UriInterface $uri, array $options = [])
+ * @method ResponseInterface patch(string|UriInterface $uri, array $options = [])
+ * @method ResponseInterface delete(string|UriInterface $uri, array $options = [])
+ * @method Promise\PromiseInterface getAsync(string|UriInterface $uri, array $options = [])
+ * @method Promise\PromiseInterface headAsync(string|UriInterface $uri, array $options = [])
+ * @method Promise\PromiseInterface putAsync(string|UriInterface $uri, array $options = [])
+ * @method Promise\PromiseInterface postAsync(string|UriInterface $uri, array $options = [])
+ * @method Promise\PromiseInterface patchAsync(string|UriInterface $uri, array $options = [])
+ * @method Promise\PromiseInterface deleteAsync(string|UriInterface $uri, array $options = [])
+ */
+class Client implements ClientInterface
+{
+    /** @var array Default request options */
+    private $config;
+
+    /**
+     * Clients accept an array of constructor parameters.
+     *
+     * Here's an example of creating a client using a base_uri and an array of
+     * default request options to apply to each request:
+     *
+     *     $client = new Client([
+     *         'base_uri'        => 'http://www.foo.com/1.0/',
+     *         'timeout'         => 0,
+     *         'allow_redirects' => false,
+     *         'proxy'           => '192.168.16.1:10'
+     *     ]);
+     *
+     * Client configuration settings include the following options:
+     *
+     * - handler: (callable) Function that transfers HTTP requests over the
+     *   wire. The function is called with a Psr7\Http\Message\RequestInterface
+     *   and array of transfer options, and must return a
+     *   GuzzleHttp\Promise\PromiseInterface that is fulfilled with a
+     *   Psr7\Http\Message\ResponseInterface on success. "handler" is a
+     *   constructor only option that cannot be overridden in per/request
+     *   options. If no handler is provided, a default handler will be created
+     *   that enables all of the request options below by attaching all of the
+     *   default middleware to the handler.
+     * - base_uri: (string|UriInterface) Base URI of the client that is merged
+     *   into relative URIs. Can be a string or instance of UriInterface.
+     * - **: any request option
+     *
+     * @param array $config Client configuration settings.
+     *
+     * @see \GuzzleHttp\RequestOptions for a list of available request options.
+     */
+    public function __construct(array $config = [])
+    {
+        if (!isset($config['handler'])) {
+            $config['handler'] = HandlerStack::create();
+        } elseif (!is_callable($config['handler'])) {
+            throw new \InvalidArgumentException('handler must be a callable');
+        }
+
+        // Convert the base_uri to a UriInterface
+        if (isset($config['base_uri'])) {
+            $config['base_uri'] = Psr7\uri_for($config['base_uri']);
+        }
+
+        $this->configureDefaults($config);
+    }
+
+    public function __call($method, $args)
+    {
+        if (count($args) < 1) {
+            throw new \InvalidArgumentException('Magic request methods require a URI and optional options array');
+        }
+
+        $uri = $args[0];
+        $opts = isset($args[1]) ? $args[1] : [];
+
+        return substr($method, -5) === 'Async'
+            ? $this->requestAsync(substr($method, 0, -5), $uri, $opts)
+            : $this->request($method, $uri, $opts);
+    }
+
+    public function sendAsync(RequestInterface $request, array $options = [])
+    {
+        // Merge the base URI into the request URI if needed.
+        $options = $this->prepareDefaults($options);
+
+        return $this->transfer(
+            $request->withUri($this->buildUri($request->getUri(), $options), $request->hasHeader('Host')),
+            $options
+        );
+    }
+
+    public function send(RequestInterface $request, array $options = [])
+    {
+        $options[RequestOptions::SYNCHRONOUS] = true;
+        return $this->sendAsync($request, $options)->wait();
+    }
+
+    public function requestAsync($method, $uri = '', array $options = [])
+    {
+        $options = $this->prepareDefaults($options);
+        // Remove request modifying parameter because it can be done up-front.
+        $headers = isset($options['headers']) ? $options['headers'] : [];
+        $body = isset($options['body']) ? $options['body'] : null;
+        $version = isset($options['version']) ? $options['version'] : '1.1';
+        // Merge the URI into the base URI.
+        $uri = $this->buildUri($uri, $options);
+        if (is_array($body)) {
+            $this->invalidBody();
+        }
+        $request = new Psr7\Request($method, $uri, $headers, $body, $version);
+        // Remove the option so that they are not doubly-applied.
+        unset($options['headers'], $options['body'], $options['version']);
+
+        return $this->transfer($request, $options);
+    }
+
+    public function request($method, $uri = '', array $options = [])
+    {
+        $options[RequestOptions::SYNCHRONOUS] = true;
+        return $this->requestAsync($method, $uri, $options)->wait();
+    }
+
+    public function getConfig($option = null)
+    {
+        return $option === null
+            ? $this->config
+            : (isset($this->config[$option]) ? $this->config[$option] : null);
+    }
+
+    private function buildUri($uri, array $config)
+    {
+        // for BC we accept null which would otherwise fail in uri_for
+        $uri = Psr7\uri_for($uri === null ? '' : $uri);
+
+        if (isset($config['base_uri'])) {
+            $uri = Psr7\UriResolver::resolve(Psr7\uri_for($config['base_uri']), $uri);
+        }
+
+        return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri;
+    }
+
+    /**
+     * Configures the default options for a client.
+     *
+     * @param array $config
+     */
+    private function configureDefaults(array $config)
+    {
+        $defaults = [
+            'allow_redirects' => RedirectMiddleware::$defaultSettings,
+            'http_errors'     => true,
+            'decode_content'  => true,
+            'verify'          => true,
+            'cookies'         => false
+        ];
+
+        // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set.
+
+        // We can only trust the HTTP_PROXY environment variable in a CLI
+        // process due to the fact that PHP has no reliable mechanism to
+        // get environment variables that start with "HTTP_".
+        if (php_sapi_name() == 'cli' && getenv('HTTP_PROXY')) {
+            $defaults['proxy']['http'] = getenv('HTTP_PROXY');
+        }
+
+        if ($proxy = getenv('HTTPS_PROXY')) {
+            $defaults['proxy']['https'] = $proxy;
+        }
+
+        if ($noProxy = getenv('NO_PROXY')) {
+            $cleanedNoProxy = str_replace(' ', '', $noProxy);
+            $defaults['proxy']['no'] = explode(',', $cleanedNoProxy);
+        }
+
+        $this->config = $config + $defaults;
+
+        if (!empty($config['cookies']) && $config['cookies'] === true) {
+            $this->config['cookies'] = new CookieJar();
+        }
+
+        // Add the default user-agent header.
+        if (!isset($this->config['headers'])) {
+            $this->config['headers'] = ['User-Agent' => default_user_agent()];
+        } else {
+            // Add the User-Agent header if one was not already set.
+            foreach (array_keys($this->config['headers']) as $name) {
+                if (strtolower($name) === 'user-agent') {
+                    return;
+                }
+            }
+            $this->config['headers']['User-Agent'] = default_user_agent();
+        }
+    }
+
+    /**
+     * Merges default options into the array.
+     *
+     * @param array $options Options to modify by reference
+     *
+     * @return array
+     */
+    private function prepareDefaults($options)
+    {
+        $defaults = $this->config;
+
+        if (!empty($defaults['headers'])) {
+            // Default headers are only added if they are not present.
+            $defaults['_conditional'] = $defaults['headers'];
+            unset($defaults['headers']);
+        }
+
+        // Special handling for headers is required as they are added as
+        // conditional headers and as headers passed to a request ctor.
+        if (array_key_exists('headers', $options)) {
+            // Allows default headers to be unset.
+            if ($options['headers'] === null) {
+                $defaults['_conditional'] = null;
+                unset($options['headers']);
+            } elseif (!is_array($options['headers'])) {
+                throw new \InvalidArgumentException('headers must be an array');
+            }
+        }
+
+        // Shallow merge defaults underneath options.
+        $result = $options + $defaults;
+
+        // Remove null values.
+        foreach ($result as $k => $v) {
+            if ($v === null) {
+                unset($result[$k]);
+            }
+        }
+
+        return $result;
+    }
+
+    /**
+     * Transfers the given request and applies request options.
+     *
+     * The URI of the request is not modified and the request options are used
+     * as-is without merging in default options.
+     *
+     * @param RequestInterface $request
+     * @param array            $options
+     *
+     * @return Promise\PromiseInterface
+     */
+    private function transfer(RequestInterface $request, array $options)
+    {
+        // save_to -> sink
+        if (isset($options['save_to'])) {
+            $options['sink'] = $options['save_to'];
+            unset($options['save_to']);
+        }
+
+        // exceptions -> http_errors
+        if (isset($options['exceptions'])) {
+            $options['http_errors'] = $options['exceptions'];
+            unset($options['exceptions']);
+        }
+
+        $request = $this->applyOptions($request, $options);
+        $handler = $options['handler'];
+
+        try {
+            return Promise\promise_for($handler($request, $options));
+        } catch (\Exception $e) {
+            return Promise\rejection_for($e);
+        }
+    }
+
+    /**
+     * Applies the array of request options to a request.
+     *
+     * @param RequestInterface $request
+     * @param array            $options
+     *
+     * @return RequestInterface
+     */
+    private function applyOptions(RequestInterface $request, array &$options)
+    {
+        $modify = [
+            'set_headers' => [],
+        ];
+
+        if (isset($options['headers'])) {
+            $modify['set_headers'] = $options['headers'];
+            unset($options['headers']);
+        }
+
+        if (isset($options['form_params'])) {
+            if (isset($options['multipart'])) {
+                throw new \InvalidArgumentException('You cannot use '
+                    . 'form_params and multipart at the same time. Use the '
+                    . 'form_params option if you want to send application/'
+                    . 'x-www-form-urlencoded requests, and the multipart '
+                    . 'option to send multipart/form-data requests.');
+            }
+            $options['body'] = http_build_query($options['form_params'], '', '&');
+            unset($options['form_params']);
+            // Ensure that we don't have the header in different case and set the new value.
+            $options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
+            $options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded';
+        }
+
+        if (isset($options['multipart'])) {
+            $options['body'] = new Psr7\MultipartStream($options['multipart']);
+            unset($options['multipart']);
+        }
+
+        if (isset($options['json'])) {
+            $options['body'] = \GuzzleHttp\json_encode($options['json']);
+            unset($options['json']);
+            // Ensure that we don't have the header in different case and set the new value.
+            $options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
+            $options['_conditional']['Content-Type'] = 'application/json';
+        }
+
+        if (!empty($options['decode_content'])
+            && $options['decode_content'] !== true
+        ) {
+            // Ensure that we don't have the header in different case and set the new value.
+            $options['_conditional'] = Psr7\_caseless_remove(['Accept-Encoding'], $options['_conditional']);
+            $modify['set_headers']['Accept-Encoding'] = $options['decode_content'];
+        }
+
+        if (isset($options['body'])) {
+            if (is_array($options['body'])) {
+                $this->invalidBody();
+            }
+            $modify['body'] = Psr7\stream_for($options['body']);
+            unset($options['body']);
+        }
+
+        if (!empty($options['auth']) && is_array($options['auth'])) {
+            $value = $options['auth'];
+            $type = isset($value[2]) ? strtolower($value[2]) : 'basic';
+            switch ($type) {
+                case 'basic':
+                    // Ensure that we don't have the header in different case and set the new value.
+                    $modify['set_headers'] = Psr7\_caseless_remove(['Authorization'], $modify['set_headers']);
+                    $modify['set_headers']['Authorization'] = 'Basic '
+                        . base64_encode("$value[0]:$value[1]");
+                    break;
+                case 'digest':
+                    // @todo: Do not rely on curl
+                    $options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_DIGEST;
+                    $options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
+                    break;
+                case 'ntlm':
+                    $options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_NTLM;
+                    $options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
+                    break;
+            }
+        }
+
+        if (isset($options['query'])) {
+            $value = $options['query'];
+            if (is_array($value)) {
+                $value = http_build_query($value, null, '&', PHP_QUERY_RFC3986);
+            }
+            if (!is_string($value)) {
+                throw new \InvalidArgumentException('query must be a string or array');
+            }
+            $modify['query'] = $value;
+            unset($options['query']);
+        }
+
+        // Ensure that sink is not an invalid value.
+        if (isset($options['sink'])) {
+            // TODO: Add more sink validation?
+            if (is_bool($options['sink'])) {
+                throw new \InvalidArgumentException('sink must not be a boolean');
+            }
+        }
+
+        $request = Psr7\modify_request($request, $modify);
+        if ($request->getBody() instanceof Psr7\MultipartStream) {
+            // Use a multipart/form-data POST if a Content-Type is not set.
+            // Ensure that we don't have the header in different case and set the new value.
+            $options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
+            $options['_conditional']['Content-Type'] = 'multipart/form-data; boundary='
+                . $request->getBody()->getBoundary();
+        }
+
+        // Merge in conditional headers if they are not present.
+        if (isset($options['_conditional'])) {
+            // Build up the changes so it's in a single clone of the message.
+            $modify = [];
+            foreach ($options['_conditional'] as $k => $v) {
+                if (!$request->hasHeader($k)) {
+                    $modify['set_headers'][$k] = $v;
+                }
+            }
+            $request = Psr7\modify_request($request, $modify);
+            // Don't pass this internal value along to middleware/handlers.
+            unset($options['_conditional']);
+        }
+
+        return $request;
+    }
+
+    private function invalidBody()
+    {
+        throw new \InvalidArgumentException('Passing in the "body" request '
+            . 'option as an array to send a POST request has been deprecated. '
+            . 'Please use the "form_params" request option to send a '
+            . 'application/x-www-form-urlencoded request, or the "multipart" '
+            . 'request option to send a multipart/form-data request.');
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/ClientInterface.php b/vendor/guzzlehttp/guzzle/src/ClientInterface.php
new file mode 100644
index 00000000000..2dbcffa492d
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/ClientInterface.php
@@ -0,0 +1,84 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Promise\PromiseInterface;
+use GuzzleHttp\Exception\GuzzleException;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\UriInterface;
+
+/**
+ * Client interface for sending HTTP requests.
+ */
+interface ClientInterface
+{
+    const VERSION = '6.3.3';
+
+    /**
+     * Send an HTTP request.
+     *
+     * @param RequestInterface $request Request to send
+     * @param array            $options Request options to apply to the given
+     *                                  request and to the transfer.
+     *
+     * @return ResponseInterface
+     * @throws GuzzleException
+     */
+    public function send(RequestInterface $request, array $options = []);
+
+    /**
+     * Asynchronously send an HTTP request.
+     *
+     * @param RequestInterface $request Request to send
+     * @param array            $options Request options to apply to the given
+     *                                  request and to the transfer.
+     *
+     * @return PromiseInterface
+     */
+    public function sendAsync(RequestInterface $request, array $options = []);
+
+    /**
+     * Create and send an HTTP request.
+     *
+     * Use an absolute path to override the base path of the client, or a
+     * relative path to append to the base path of the client. The URL can
+     * contain the query string as well.
+     *
+     * @param string              $method  HTTP method.
+     * @param string|UriInterface $uri     URI object or string.
+     * @param array               $options Request options to apply.
+     *
+     * @return ResponseInterface
+     * @throws GuzzleException
+     */
+    public function request($method, $uri, array $options = []);
+
+    /**
+     * Create and send an asynchronous HTTP request.
+     *
+     * Use an absolute path to override the base path of the client, or a
+     * relative path to append to the base path of the client. The URL can
+     * contain the query string as well. Use an array to provide a URL
+     * template and additional variables to use in the URL template expansion.
+     *
+     * @param string              $method  HTTP method
+     * @param string|UriInterface $uri     URI object or string.
+     * @param array               $options Request options to apply.
+     *
+     * @return PromiseInterface
+     */
+    public function requestAsync($method, $uri, array $options = []);
+
+    /**
+     * Get a client configuration option.
+     *
+     * These options include default request options of the client, a "handler"
+     * (if utilized by the concrete client), and a "base_uri" if utilized by
+     * the concrete client.
+     *
+     * @param string|null $option The config option to retrieve.
+     *
+     * @return mixed
+     */
+    public function getConfig($option = null);
+}
diff --git a/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php b/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php
new file mode 100644
index 00000000000..78f2b79fecb
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php
@@ -0,0 +1,314 @@
+<?php
+namespace GuzzleHttp\Cookie;
+
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Cookie jar that stores cookies as an array
+ */
+class CookieJar implements CookieJarInterface
+{
+    /** @var SetCookie[] Loaded cookie data */
+    private $cookies = [];
+
+    /** @var bool */
+    private $strictMode;
+
+    /**
+     * @param bool $strictMode   Set to true to throw exceptions when invalid
+     *                           cookies are added to the cookie jar.
+     * @param array $cookieArray Array of SetCookie objects or a hash of
+     *                           arrays that can be used with the SetCookie
+     *                           constructor
+     */
+    public function __construct($strictMode = false, $cookieArray = [])
+    {
+        $this->strictMode = $strictMode;
+
+        foreach ($cookieArray as $cookie) {
+            if (!($cookie instanceof SetCookie)) {
+                $cookie = new SetCookie($cookie);
+            }
+            $this->setCookie($cookie);
+        }
+    }
+
+    /**
+     * Create a new Cookie jar from an associative array and domain.
+     *
+     * @param array  $cookies Cookies to create the jar from
+     * @param string $domain  Domain to set the cookies to
+     *
+     * @return self
+     */
+    public static function fromArray(array $cookies, $domain)
+    {
+        $cookieJar = new self();
+        foreach ($cookies as $name => $value) {
+            $cookieJar->setCookie(new SetCookie([
+                'Domain'  => $domain,
+                'Name'    => $name,
+                'Value'   => $value,
+                'Discard' => true
+            ]));
+        }
+
+        return $cookieJar;
+    }
+
+    /**
+     * @deprecated
+     */
+    public static function getCookieValue($value)
+    {
+        return $value;
+    }
+
+    /**
+     * Evaluate if this cookie should be persisted to storage
+     * that survives between requests.
+     *
+     * @param SetCookie $cookie Being evaluated.
+     * @param bool $allowSessionCookies If we should persist session cookies
+     * @return bool
+     */
+    public static function shouldPersist(
+        SetCookie $cookie,
+        $allowSessionCookies = false
+    ) {
+        if ($cookie->getExpires() || $allowSessionCookies) {
+            if (!$cookie->getDiscard()) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Finds and returns the cookie based on the name
+     *
+     * @param string $name cookie name to search for
+     * @return SetCookie|null cookie that was found or null if not found
+     */
+    public function getCookieByName($name)
+    {
+        // don't allow a null name
+        if ($name === null) {
+            return null;
+        }
+        foreach ($this->cookies as $cookie) {
+            if ($cookie->getName() !== null && strcasecmp($cookie->getName(), $name) === 0) {
+                return $cookie;
+            }
+        }
+    }
+
+    public function toArray()
+    {
+        return array_map(function (SetCookie $cookie) {
+            return $cookie->toArray();
+        }, $this->getIterator()->getArrayCopy());
+    }
+
+    public function clear($domain = null, $path = null, $name = null)
+    {
+        if (!$domain) {
+            $this->cookies = [];
+            return;
+        } elseif (!$path) {
+            $this->cookies = array_filter(
+                $this->cookies,
+                function (SetCookie $cookie) use ($path, $domain) {
+                    return !$cookie->matchesDomain($domain);
+                }
+            );
+        } elseif (!$name) {
+            $this->cookies = array_filter(
+                $this->cookies,
+                function (SetCookie $cookie) use ($path, $domain) {
+                    return !($cookie->matchesPath($path) &&
+                        $cookie->matchesDomain($domain));
+                }
+            );
+        } else {
+            $this->cookies = array_filter(
+                $this->cookies,
+                function (SetCookie $cookie) use ($path, $domain, $name) {
+                    return !($cookie->getName() == $name &&
+                        $cookie->matchesPath($path) &&
+                        $cookie->matchesDomain($domain));
+                }
+            );
+        }
+    }
+
+    public function clearSessionCookies()
+    {
+        $this->cookies = array_filter(
+            $this->cookies,
+            function (SetCookie $cookie) {
+                return !$cookie->getDiscard() && $cookie->getExpires();
+            }
+        );
+    }
+
+    public function setCookie(SetCookie $cookie)
+    {
+        // If the name string is empty (but not 0), ignore the set-cookie
+        // string entirely.
+        $name = $cookie->getName();
+        if (!$name && $name !== '0') {
+            return false;
+        }
+
+        // Only allow cookies with set and valid domain, name, value
+        $result = $cookie->validate();
+        if ($result !== true) {
+            if ($this->strictMode) {
+                throw new \RuntimeException('Invalid cookie: ' . $result);
+            } else {
+                $this->removeCookieIfEmpty($cookie);
+                return false;
+            }
+        }
+
+        // Resolve conflicts with previously set cookies
+        foreach ($this->cookies as $i => $c) {
+
+            // Two cookies are identical, when their path, and domain are
+            // identical.
+            if ($c->getPath() != $cookie->getPath() ||
+                $c->getDomain() != $cookie->getDomain() ||
+                $c->getName() != $cookie->getName()
+            ) {
+                continue;
+            }
+
+            // The previously set cookie is a discard cookie and this one is
+            // not so allow the new cookie to be set
+            if (!$cookie->getDiscard() && $c->getDiscard()) {
+                unset($this->cookies[$i]);
+                continue;
+            }
+
+            // If the new cookie's expiration is further into the future, then
+            // replace the old cookie
+            if ($cookie->getExpires() > $c->getExpires()) {
+                unset($this->cookies[$i]);
+                continue;
+            }
+
+            // If the value has changed, we better change it
+            if ($cookie->getValue() !== $c->getValue()) {
+                unset($this->cookies[$i]);
+                continue;
+            }
+
+            // The cookie exists, so no need to continue
+            return false;
+        }
+
+        $this->cookies[] = $cookie;
+
+        return true;
+    }
+
+    public function count()
+    {
+        return count($this->cookies);
+    }
+
+    public function getIterator()
+    {
+        return new \ArrayIterator(array_values($this->cookies));
+    }
+
+    public function extractCookies(
+        RequestInterface $request,
+        ResponseInterface $response
+    ) {
+        if ($cookieHeader = $response->getHeader('Set-Cookie')) {
+            foreach ($cookieHeader as $cookie) {
+                $sc = SetCookie::fromString($cookie);
+                if (!$sc->getDomain()) {
+                    $sc->setDomain($request->getUri()->getHost());
+                }
+                if (0 !== strpos($sc->getPath(), '/')) {
+                    $sc->setPath($this->getCookiePathFromRequest($request));
+                }
+                $this->setCookie($sc);
+            }
+        }
+    }
+
+    /**
+     * Computes cookie path following RFC 6265 section 5.1.4
+     *
+     * @link https://tools.ietf.org/html/rfc6265#section-5.1.4
+     *
+     * @param RequestInterface $request
+     * @return string
+     */
+    private function getCookiePathFromRequest(RequestInterface $request)
+    {
+        $uriPath = $request->getUri()->getPath();
+        if (''  === $uriPath) {
+            return '/';
+        }
+        if (0 !== strpos($uriPath, '/')) {
+            return '/';
+        }
+        if ('/' === $uriPath) {
+            return '/';
+        }
+        if (0 === $lastSlashPos = strrpos($uriPath, '/')) {
+            return '/';
+        }
+
+        return substr($uriPath, 0, $lastSlashPos);
+    }
+
+    public function withCookieHeader(RequestInterface $request)
+    {
+        $values = [];
+        $uri = $request->getUri();
+        $scheme = $uri->getScheme();
+        $host = $uri->getHost();
+        $path = $uri->getPath() ?: '/';
+
+        foreach ($this->cookies as $cookie) {
+            if ($cookie->matchesPath($path) &&
+                $cookie->matchesDomain($host) &&
+                !$cookie->isExpired() &&
+                (!$cookie->getSecure() || $scheme === 'https')
+            ) {
+                $values[] = $cookie->getName() . '='
+                    . $cookie->getValue();
+            }
+        }
+
+        return $values
+            ? $request->withHeader('Cookie', implode('; ', $values))
+            : $request;
+    }
+
+    /**
+     * If a cookie already exists and the server asks to set it again with a
+     * null value, the cookie must be deleted.
+     *
+     * @param SetCookie $cookie
+     */
+    private function removeCookieIfEmpty(SetCookie $cookie)
+    {
+        $cookieValue = $cookie->getValue();
+        if ($cookieValue === null || $cookieValue === '') {
+            $this->clear(
+                $cookie->getDomain(),
+                $cookie->getPath(),
+                $cookie->getName()
+            );
+        }
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php b/vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php
new file mode 100644
index 00000000000..2cf298a867b
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php
@@ -0,0 +1,84 @@
+<?php
+namespace GuzzleHttp\Cookie;
+
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Stores HTTP cookies.
+ *
+ * It extracts cookies from HTTP requests, and returns them in HTTP responses.
+ * CookieJarInterface instances automatically expire contained cookies when
+ * necessary. Subclasses are also responsible for storing and retrieving
+ * cookies from a file, database, etc.
+ *
+ * @link http://docs.python.org/2/library/cookielib.html Inspiration
+ */
+interface CookieJarInterface extends \Countable, \IteratorAggregate
+{
+    /**
+     * Create a request with added cookie headers.
+     *
+     * If no matching cookies are found in the cookie jar, then no Cookie
+     * header is added to the request and the same request is returned.
+     *
+     * @param RequestInterface $request Request object to modify.
+     *
+     * @return RequestInterface returns the modified request.
+     */
+    public function withCookieHeader(RequestInterface $request);
+
+    /**
+     * Extract cookies from an HTTP response and store them in the CookieJar.
+     *
+     * @param RequestInterface  $request  Request that was sent
+     * @param ResponseInterface $response Response that was received
+     */
+    public function extractCookies(
+        RequestInterface $request,
+        ResponseInterface $response
+    );
+
+    /**
+     * Sets a cookie in the cookie jar.
+     *
+     * @param SetCookie $cookie Cookie to set.
+     *
+     * @return bool Returns true on success or false on failure
+     */
+    public function setCookie(SetCookie $cookie);
+
+    /**
+     * Remove cookies currently held in the cookie jar.
+     *
+     * Invoking this method without arguments will empty the whole cookie jar.
+     * If given a $domain argument only cookies belonging to that domain will
+     * be removed. If given a $domain and $path argument, cookies belonging to
+     * the specified path within that domain are removed. If given all three
+     * arguments, then the cookie with the specified name, path and domain is
+     * removed.
+     *
+     * @param string $domain Clears cookies matching a domain
+     * @param string $path   Clears cookies matching a domain and path
+     * @param string $name   Clears cookies matching a domain, path, and name
+     *
+     * @return CookieJarInterface
+     */
+    public function clear($domain = null, $path = null, $name = null);
+
+    /**
+     * Discard all sessions cookies.
+     *
+     * Removes cookies that don't have an expire field or a have a discard
+     * field set to true. To be called when the user agent shuts down according
+     * to RFC 2965.
+     */
+    public function clearSessionCookies();
+
+    /**
+     * Converts the cookie jar to an array.
+     *
+     * @return array
+     */
+    public function toArray();
+}
diff --git a/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php b/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php
new file mode 100644
index 00000000000..9887c1d54b2
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php
@@ -0,0 +1,90 @@
+<?php
+namespace GuzzleHttp\Cookie;
+
+/**
+ * Persists non-session cookies using a JSON formatted file
+ */
+class FileCookieJar extends CookieJar
+{
+    /** @var string filename */
+    private $filename;
+
+    /** @var bool Control whether to persist session cookies or not. */
+    private $storeSessionCookies;
+
+    /**
+     * Create a new FileCookieJar object
+     *
+     * @param string $cookieFile        File to store the cookie data
+     * @param bool $storeSessionCookies Set to true to store session cookies
+     *                                  in the cookie jar.
+     *
+     * @throws \RuntimeException if the file cannot be found or created
+     */
+    public function __construct($cookieFile, $storeSessionCookies = false)
+    {
+        $this->filename = $cookieFile;
+        $this->storeSessionCookies = $storeSessionCookies;
+
+        if (file_exists($cookieFile)) {
+            $this->load($cookieFile);
+        }
+    }
+
+    /**
+     * Saves the file when shutting down
+     */
+    public function __destruct()
+    {
+        $this->save($this->filename);
+    }
+
+    /**
+     * Saves the cookies to a file.
+     *
+     * @param string $filename File to save
+     * @throws \RuntimeException if the file cannot be found or created
+     */
+    public function save($filename)
+    {
+        $json = [];
+        foreach ($this as $cookie) {
+            /** @var SetCookie $cookie */
+            if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
+                $json[] = $cookie->toArray();
+            }
+        }
+
+        $jsonStr = \GuzzleHttp\json_encode($json);
+        if (false === file_put_contents($filename, $jsonStr)) {
+            throw new \RuntimeException("Unable to save file {$filename}");
+        }
+    }
+
+    /**
+     * Load cookies from a JSON formatted file.
+     *
+     * Old cookies are kept unless overwritten by newly loaded ones.
+     *
+     * @param string $filename Cookie file to load.
+     * @throws \RuntimeException if the file cannot be loaded.
+     */
+    public function load($filename)
+    {
+        $json = file_get_contents($filename);
+        if (false === $json) {
+            throw new \RuntimeException("Unable to load file {$filename}");
+        } elseif ($json === '') {
+            return;
+        }
+
+        $data = \GuzzleHttp\json_decode($json, true);
+        if (is_array($data)) {
+            foreach (json_decode($json, true) as $cookie) {
+                $this->setCookie(new SetCookie($cookie));
+            }
+        } elseif (strlen($data)) {
+            throw new \RuntimeException("Invalid cookie file: {$filename}");
+        }
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php b/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php
new file mode 100644
index 00000000000..4497bcf03e2
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php
@@ -0,0 +1,71 @@
+<?php
+namespace GuzzleHttp\Cookie;
+
+/**
+ * Persists cookies in the client session
+ */
+class SessionCookieJar extends CookieJar
+{
+    /** @var string session key */
+    private $sessionKey;
+    
+    /** @var bool Control whether to persist session cookies or not. */
+    private $storeSessionCookies;
+
+    /**
+     * Create a new SessionCookieJar object
+     *
+     * @param string $sessionKey        Session key name to store the cookie
+     *                                  data in session
+     * @param bool $storeSessionCookies Set to true to store session cookies
+     *                                  in the cookie jar.
+     */
+    public function __construct($sessionKey, $storeSessionCookies = false)
+    {
+        $this->sessionKey = $sessionKey;
+        $this->storeSessionCookies = $storeSessionCookies;
+        $this->load();
+    }
+
+    /**
+     * Saves cookies to session when shutting down
+     */
+    public function __destruct()
+    {
+        $this->save();
+    }
+
+    /**
+     * Save cookies to the client session
+     */
+    public function save()
+    {
+        $json = [];
+        foreach ($this as $cookie) {
+            /** @var SetCookie $cookie */
+            if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
+                $json[] = $cookie->toArray();
+            }
+        }
+
+        $_SESSION[$this->sessionKey] = json_encode($json);
+    }
+
+    /**
+     * Load the contents of the client session into the data array
+     */
+    protected function load()
+    {
+        if (!isset($_SESSION[$this->sessionKey])) {
+            return;
+        }
+        $data = json_decode($_SESSION[$this->sessionKey], true);
+        if (is_array($data)) {
+            foreach ($data as $cookie) {
+                $this->setCookie(new SetCookie($cookie));
+            }
+        } elseif (strlen($data)) {
+            throw new \RuntimeException("Invalid cookie data");
+        }
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php b/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php
new file mode 100644
index 00000000000..f6993943e74
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php
@@ -0,0 +1,403 @@
+<?php
+namespace GuzzleHttp\Cookie;
+
+/**
+ * Set-Cookie object
+ */
+class SetCookie
+{
+    /** @var array */
+    private static $defaults = [
+        'Name'     => null,
+        'Value'    => null,
+        'Domain'   => null,
+        'Path'     => '/',
+        'Max-Age'  => null,
+        'Expires'  => null,
+        'Secure'   => false,
+        'Discard'  => false,
+        'HttpOnly' => false
+    ];
+
+    /** @var array Cookie data */
+    private $data;
+
+    /**
+     * Create a new SetCookie object from a string
+     *
+     * @param string $cookie Set-Cookie header string
+     *
+     * @return self
+     */
+    public static function fromString($cookie)
+    {
+        // Create the default return array
+        $data = self::$defaults;
+        // Explode the cookie string using a series of semicolons
+        $pieces = array_filter(array_map('trim', explode(';', $cookie)));
+        // The name of the cookie (first kvp) must exist and include an equal sign.
+        if (empty($pieces[0]) || !strpos($pieces[0], '=')) {
+            return new self($data);
+        }
+
+        // Add the cookie pieces into the parsed data array
+        foreach ($pieces as $part) {
+            $cookieParts = explode('=', $part, 2);
+            $key = trim($cookieParts[0]);
+            $value = isset($cookieParts[1])
+                ? trim($cookieParts[1], " \n\r\t\0\x0B")
+                : true;
+
+            // Only check for non-cookies when cookies have been found
+            if (empty($data['Name'])) {
+                $data['Name'] = $key;
+                $data['Value'] = $value;
+            } else {
+                foreach (array_keys(self::$defaults) as $search) {
+                    if (!strcasecmp($search, $key)) {
+                        $data[$search] = $value;
+                        continue 2;
+                    }
+                }
+                $data[$key] = $value;
+            }
+        }
+
+        return new self($data);
+    }
+
+    /**
+     * @param array $data Array of cookie data provided by a Cookie parser
+     */
+    public function __construct(array $data = [])
+    {
+        $this->data = array_replace(self::$defaults, $data);
+        // Extract the Expires value and turn it into a UNIX timestamp if needed
+        if (!$this->getExpires() && $this->getMaxAge()) {
+            // Calculate the Expires date
+            $this->setExpires(time() + $this->getMaxAge());
+        } elseif ($this->getExpires() && !is_numeric($this->getExpires())) {
+            $this->setExpires($this->getExpires());
+        }
+    }
+
+    public function __toString()
+    {
+        $str = $this->data['Name'] . '=' . $this->data['Value'] . '; ';
+        foreach ($this->data as $k => $v) {
+            if ($k !== 'Name' && $k !== 'Value' && $v !== null && $v !== false) {
+                if ($k === 'Expires') {
+                    $str .= 'Expires=' . gmdate('D, d M Y H:i:s \G\M\T', $v) . '; ';
+                } else {
+                    $str .= ($v === true ? $k : "{$k}={$v}") . '; ';
+                }
+            }
+        }
+
+        return rtrim($str, '; ');
+    }
+
+    public function toArray()
+    {
+        return $this->data;
+    }
+
+    /**
+     * Get the cookie name
+     *
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->data['Name'];
+    }
+
+    /**
+     * Set the cookie name
+     *
+     * @param string $name Cookie name
+     */
+    public function setName($name)
+    {
+        $this->data['Name'] = $name;
+    }
+
+    /**
+     * Get the cookie value
+     *
+     * @return string
+     */
+    public function getValue()
+    {
+        return $this->data['Value'];
+    }
+
+    /**
+     * Set the cookie value
+     *
+     * @param string $value Cookie value
+     */
+    public function setValue($value)
+    {
+        $this->data['Value'] = $value;
+    }
+
+    /**
+     * Get the domain
+     *
+     * @return string|null
+     */
+    public function getDomain()
+    {
+        return $this->data['Domain'];
+    }
+
+    /**
+     * Set the domain of the cookie
+     *
+     * @param string $domain
+     */
+    public function setDomain($domain)
+    {
+        $this->data['Domain'] = $domain;
+    }
+
+    /**
+     * Get the path
+     *
+     * @return string
+     */
+    public function getPath()
+    {
+        return $this->data['Path'];
+    }
+
+    /**
+     * Set the path of the cookie
+     *
+     * @param string $path Path of the cookie
+     */
+    public function setPath($path)
+    {
+        $this->data['Path'] = $path;
+    }
+
+    /**
+     * Maximum lifetime of the cookie in seconds
+     *
+     * @return int|null
+     */
+    public function getMaxAge()
+    {
+        return $this->data['Max-Age'];
+    }
+
+    /**
+     * Set the max-age of the cookie
+     *
+     * @param int $maxAge Max age of the cookie in seconds
+     */
+    public function setMaxAge($maxAge)
+    {
+        $this->data['Max-Age'] = $maxAge;
+    }
+
+    /**
+     * The UNIX timestamp when the cookie Expires
+     *
+     * @return mixed
+     */
+    public function getExpires()
+    {
+        return $this->data['Expires'];
+    }
+
+    /**
+     * Set the unix timestamp for which the cookie will expire
+     *
+     * @param int $timestamp Unix timestamp
+     */
+    public function setExpires($timestamp)
+    {
+        $this->data['Expires'] = is_numeric($timestamp)
+            ? (int) $timestamp
+            : strtotime($timestamp);
+    }
+
+    /**
+     * Get whether or not this is a secure cookie
+     *
+     * @return null|bool
+     */
+    public function getSecure()
+    {
+        return $this->data['Secure'];
+    }
+
+    /**
+     * Set whether or not the cookie is secure
+     *
+     * @param bool $secure Set to true or false if secure
+     */
+    public function setSecure($secure)
+    {
+        $this->data['Secure'] = $secure;
+    }
+
+    /**
+     * Get whether or not this is a session cookie
+     *
+     * @return null|bool
+     */
+    public function getDiscard()
+    {
+        return $this->data['Discard'];
+    }
+
+    /**
+     * Set whether or not this is a session cookie
+     *
+     * @param bool $discard Set to true or false if this is a session cookie
+     */
+    public function setDiscard($discard)
+    {
+        $this->data['Discard'] = $discard;
+    }
+
+    /**
+     * Get whether or not this is an HTTP only cookie
+     *
+     * @return bool
+     */
+    public function getHttpOnly()
+    {
+        return $this->data['HttpOnly'];
+    }
+
+    /**
+     * Set whether or not this is an HTTP only cookie
+     *
+     * @param bool $httpOnly Set to true or false if this is HTTP only
+     */
+    public function setHttpOnly($httpOnly)
+    {
+        $this->data['HttpOnly'] = $httpOnly;
+    }
+
+    /**
+     * Check if the cookie matches a path value.
+     *
+     * A request-path path-matches a given cookie-path if at least one of
+     * the following conditions holds:
+     *
+     * - The cookie-path and the request-path are identical.
+     * - The cookie-path is a prefix of the request-path, and the last
+     *   character of the cookie-path is %x2F ("/").
+     * - The cookie-path is a prefix of the request-path, and the first
+     *   character of the request-path that is not included in the cookie-
+     *   path is a %x2F ("/") character.
+     *
+     * @param string $requestPath Path to check against
+     *
+     * @return bool
+     */
+    public function matchesPath($requestPath)
+    {
+        $cookiePath = $this->getPath();
+
+        // Match on exact matches or when path is the default empty "/"
+        if ($cookiePath === '/' || $cookiePath == $requestPath) {
+            return true;
+        }
+
+        // Ensure that the cookie-path is a prefix of the request path.
+        if (0 !== strpos($requestPath, $cookiePath)) {
+            return false;
+        }
+
+        // Match if the last character of the cookie-path is "/"
+        if (substr($cookiePath, -1, 1) === '/') {
+            return true;
+        }
+
+        // Match if the first character not included in cookie path is "/"
+        return substr($requestPath, strlen($cookiePath), 1) === '/';
+    }
+
+    /**
+     * Check if the cookie matches a domain value
+     *
+     * @param string $domain Domain to check against
+     *
+     * @return bool
+     */
+    public function matchesDomain($domain)
+    {
+        // Remove the leading '.' as per spec in RFC 6265.
+        // http://tools.ietf.org/html/rfc6265#section-5.2.3
+        $cookieDomain = ltrim($this->getDomain(), '.');
+
+        // Domain not set or exact match.
+        if (!$cookieDomain || !strcasecmp($domain, $cookieDomain)) {
+            return true;
+        }
+
+        // Matching the subdomain according to RFC 6265.
+        // http://tools.ietf.org/html/rfc6265#section-5.1.3
+        if (filter_var($domain, FILTER_VALIDATE_IP)) {
+            return false;
+        }
+
+        return (bool) preg_match('/\.' . preg_quote($cookieDomain, '/') . '$/', $domain);
+    }
+
+    /**
+     * Check if the cookie is expired
+     *
+     * @return bool
+     */
+    public function isExpired()
+    {
+        return $this->getExpires() !== null && time() > $this->getExpires();
+    }
+
+    /**
+     * Check if the cookie is valid according to RFC 6265
+     *
+     * @return bool|string Returns true if valid or an error message if invalid
+     */
+    public function validate()
+    {
+        // Names must not be empty, but can be 0
+        $name = $this->getName();
+        if (empty($name) && !is_numeric($name)) {
+            return 'The cookie name must not be empty';
+        }
+
+        // Check if any of the invalid characters are present in the cookie name
+        if (preg_match(
+            '/[\x00-\x20\x22\x28-\x29\x2c\x2f\x3a-\x40\x5c\x7b\x7d\x7f]/',
+            $name
+        )) {
+            return 'Cookie name must not contain invalid characters: ASCII '
+                . 'Control characters (0-31;127), space, tab and the '
+                . 'following characters: ()<>@,;:\"/?={}';
+        }
+
+        // Value must not be empty, but can be 0
+        $value = $this->getValue();
+        if (empty($value) && !is_numeric($value)) {
+            return 'The cookie value must not be empty';
+        }
+
+        // Domains must not be empty, but can be 0
+        // A "0" is not a valid internet domain, but may be used as server name
+        // in a private network.
+        $domain = $this->getDomain();
+        if (empty($domain) && !is_numeric($domain)) {
+            return 'The cookie domain must not be empty';
+        }
+
+        return true;
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php b/vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php
new file mode 100644
index 00000000000..427d896fb2f
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php
@@ -0,0 +1,27 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Exception when an HTTP error occurs (4xx or 5xx error)
+ */
+class BadResponseException extends RequestException
+{
+    public function __construct(
+        $message,
+        RequestInterface $request,
+        ResponseInterface $response = null,
+        \Exception $previous = null,
+        array $handlerContext = []
+    ) {
+        if (null === $response) {
+            @trigger_error(
+                'Instantiating the ' . __CLASS__ . ' class without a Response is deprecated since version 6.3 and will be removed in 7.0.',
+                E_USER_DEPRECATED
+            );
+        }
+        parent::__construct($message, $request, $response, $previous, $handlerContext);
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/Exception/ClientException.php b/vendor/guzzlehttp/guzzle/src/Exception/ClientException.php
new file mode 100644
index 00000000000..f95c09f2b1a
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Exception/ClientException.php
@@ -0,0 +1,7 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+/**
+ * Exception when a client error is encountered (4xx codes)
+ */
+class ClientException extends BadResponseException {}
diff --git a/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php b/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php
new file mode 100644
index 00000000000..d33b0cc19d6
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php
@@ -0,0 +1,37 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Exception thrown when a connection cannot be established.
+ *
+ * Note that no response is present for a ConnectException
+ */
+class ConnectException extends RequestException
+{
+    public function __construct(
+        $message,
+        RequestInterface $request,
+        \Exception $previous = null,
+        array $handlerContext = []
+    ) {
+        parent::__construct($message, $request, null, $previous, $handlerContext);
+    }
+
+    /**
+     * @return null
+     */
+    public function getResponse()
+    {
+        return null;
+    }
+
+    /**
+     * @return bool
+     */
+    public function hasResponse()
+    {
+        return false;
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php b/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php
new file mode 100644
index 00000000000..510778f6eb2
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php
@@ -0,0 +1,13 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+/**
+ * @method string getMessage()
+ * @method \Throwable|null getPrevious()
+ * @method mixed getCode()
+ * @method string getFile()
+ * @method int getLine()
+ * @method array getTrace()
+ * @method string getTraceAsString()
+ */
+interface GuzzleException {}
diff --git a/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php b/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php
new file mode 100644
index 00000000000..39de327e7b6
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php
@@ -0,0 +1,217 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use GuzzleHttp\Promise\PromiseInterface;
+use Psr\Http\Message\UriInterface;
+
+/**
+ * HTTP Request exception
+ */
+class RequestException extends TransferException
+{
+    /** @var RequestInterface */
+    private $request;
+
+    /** @var ResponseInterface */
+    private $response;
+
+    /** @var array */
+    private $handlerContext;
+
+    public function __construct(
+        $message,
+        RequestInterface $request,
+        ResponseInterface $response = null,
+        \Exception $previous = null,
+        array $handlerContext = []
+    ) {
+        // Set the code of the exception if the response is set and not future.
+        $code = $response && !($response instanceof PromiseInterface)
+            ? $response->getStatusCode()
+            : 0;
+        parent::__construct($message, $code, $previous);
+        $this->request = $request;
+        $this->response = $response;
+        $this->handlerContext = $handlerContext;
+    }
+
+    /**
+     * Wrap non-RequestExceptions with a RequestException
+     *
+     * @param RequestInterface $request
+     * @param \Exception       $e
+     *
+     * @return RequestException
+     */
+    public static function wrapException(RequestInterface $request, \Exception $e)
+    {
+        return $e instanceof RequestException
+            ? $e
+            : new RequestException($e->getMessage(), $request, null, $e);
+    }
+
+    /**
+     * Factory method to create a new exception with a normalized error message
+     *
+     * @param RequestInterface  $request  Request
+     * @param ResponseInterface $response Response received
+     * @param \Exception        $previous Previous exception
+     * @param array             $ctx      Optional handler context.
+     *
+     * @return self
+     */
+    public static function create(
+        RequestInterface $request,
+        ResponseInterface $response = null,
+        \Exception $previous = null,
+        array $ctx = []
+    ) {
+        if (!$response) {
+            return new self(
+                'Error completing request',
+                $request,
+                null,
+                $previous,
+                $ctx
+            );
+        }
+
+        $level = (int) floor($response->getStatusCode() / 100);
+        if ($level === 4) {
+            $label = 'Client error';
+            $className = ClientException::class;
+        } elseif ($level === 5) {
+            $label = 'Server error';
+            $className = ServerException::class;
+        } else {
+            $label = 'Unsuccessful request';
+            $className = __CLASS__;
+        }
+
+        $uri = $request->getUri();
+        $uri = static::obfuscateUri($uri);
+
+        // Client Error: `GET /` resulted in a `404 Not Found` response:
+        // <html> ... (truncated)
+        $message = sprintf(
+            '%s: `%s %s` resulted in a `%s %s` response',
+            $label,
+            $request->getMethod(),
+            $uri,
+            $response->getStatusCode(),
+            $response->getReasonPhrase()
+        );
+
+        $summary = static::getResponseBodySummary($response);
+
+        if ($summary !== null) {
+            $message .= ":\n{$summary}\n";
+        }
+
+        return new $className($message, $request, $response, $previous, $ctx);
+    }
+
+    /**
+     * Get a short summary of the response
+     *
+     * Will return `null` if the response is not printable.
+     *
+     * @param ResponseInterface $response
+     *
+     * @return string|null
+     */
+    public static function getResponseBodySummary(ResponseInterface $response)
+    {
+        $body = $response->getBody();
+
+        if (!$body->isSeekable()) {
+            return null;
+        }
+
+        $size = $body->getSize();
+
+        if ($size === 0) {
+            return null;
+        }
+
+        $summary = $body->read(120);
+        $body->rewind();
+
+        if ($size > 120) {
+            $summary .= ' (truncated...)';
+        }
+
+        // Matches any printable character, including unicode characters:
+        // letters, marks, numbers, punctuation, spacing, and separators.
+        if (preg_match('/[^\pL\pM\pN\pP\pS\pZ\n\r\t]/', $summary)) {
+            return null;
+        }
+
+        return $summary;
+    }
+
+    /**
+     * Obfuscates URI if there is an username and a password present
+     *
+     * @param UriInterface $uri
+     *
+     * @return UriInterface
+     */
+    private static function obfuscateUri($uri)
+    {
+        $userInfo = $uri->getUserInfo();
+
+        if (false !== ($pos = strpos($userInfo, ':'))) {
+            return $uri->withUserInfo(substr($userInfo, 0, $pos), '***');
+        }
+
+        return $uri;
+    }
+
+    /**
+     * Get the request that caused the exception
+     *
+     * @return RequestInterface
+     */
+    public function getRequest()
+    {
+        return $this->request;
+    }
+
+    /**
+     * Get the associated response
+     *
+     * @return ResponseInterface|null
+     */
+    public function getResponse()
+    {
+        return $this->response;
+    }
+
+    /**
+     * Check if a response was received
+     *
+     * @return bool
+     */
+    public function hasResponse()
+    {
+        return $this->response !== null;
+    }
+
+    /**
+     * Get contextual information about the error from the underlying handler.
+     *
+     * The contents of this array will vary depending on which handler you are
+     * using. It may also be just an empty array. Relying on this data will
+     * couple you to a specific handler, but can give more debug information
+     * when needed.
+     *
+     * @return array
+     */
+    public function getHandlerContext()
+    {
+        return $this->handlerContext;
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/Exception/SeekException.php b/vendor/guzzlehttp/guzzle/src/Exception/SeekException.php
new file mode 100644
index 00000000000..a77c28926cf
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Exception/SeekException.php
@@ -0,0 +1,27 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Exception thrown when a seek fails on a stream.
+ */
+class SeekException extends \RuntimeException implements GuzzleException
+{
+    private $stream;
+
+    public function __construct(StreamInterface $stream, $pos = 0, $msg = '')
+    {
+        $this->stream = $stream;
+        $msg = $msg ?: 'Could not seek the stream to position ' . $pos;
+        parent::__construct($msg);
+    }
+
+    /**
+     * @return StreamInterface
+     */
+    public function getStream()
+    {
+        return $this->stream;
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/Exception/ServerException.php b/vendor/guzzlehttp/guzzle/src/Exception/ServerException.php
new file mode 100644
index 00000000000..7cdd340866b
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Exception/ServerException.php
@@ -0,0 +1,7 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+/**
+ * Exception when a server error is encountered (5xx codes)
+ */
+class ServerException extends BadResponseException {}
diff --git a/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php b/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php
new file mode 100644
index 00000000000..b60a9678d65
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php
@@ -0,0 +1,4 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+class TooManyRedirectsException extends RequestException {}
diff --git a/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php b/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php
new file mode 100644
index 00000000000..b92071ca206
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php
@@ -0,0 +1,4 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+class TransferException extends \RuntimeException implements GuzzleException {}
diff --git a/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php b/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php
new file mode 100644
index 00000000000..e0923714306
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php
@@ -0,0 +1,565 @@
+<?php
+namespace GuzzleHttp\Handler;
+
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\Exception\ConnectException;
+use GuzzleHttp\Promise\FulfilledPromise;
+use GuzzleHttp\Psr7;
+use GuzzleHttp\Psr7\LazyOpenStream;
+use GuzzleHttp\TransferStats;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Creates curl resources from a request
+ */
+class CurlFactory implements CurlFactoryInterface
+{
+    /** @var array */
+    private $handles = [];
+
+    /** @var int Total number of idle handles to keep in cache */
+    private $maxHandles;
+
+    /**
+     * @param int $maxHandles Maximum number of idle handles.
+     */
+    public function __construct($maxHandles)
+    {
+        $this->maxHandles = $maxHandles;
+    }
+
+    public function create(RequestInterface $request, array $options)
+    {
+        if (isset($options['curl']['body_as_string'])) {
+            $options['_body_as_string'] = $options['curl']['body_as_string'];
+            unset($options['curl']['body_as_string']);
+        }
+
+        $easy = new EasyHandle;
+        $easy->request = $request;
+        $easy->options = $options;
+        $conf = $this->getDefaultConf($easy);
+        $this->applyMethod($easy, $conf);
+        $this->applyHandlerOptions($easy, $conf);
+        $this->applyHeaders($easy, $conf);
+        unset($conf['_headers']);
+
+        // Add handler options from the request configuration options
+        if (isset($options['curl'])) {
+            $conf = array_replace($conf, $options['curl']);
+        }
+
+        $conf[CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy);
+        $easy->handle = $this->handles
+            ? array_pop($this->handles)
+            : curl_init();
+        curl_setopt_array($easy->handle, $conf);
+
+        return $easy;
+    }
+
+    public function release(EasyHandle $easy)
+    {
+        $resource = $easy->handle;
+        unset($easy->handle);
+
+        if (count($this->handles) >= $this->maxHandles) {
+            curl_close($resource);
+        } else {
+            // Remove all callback functions as they can hold onto references
+            // and are not cleaned up by curl_reset. Using curl_setopt_array
+            // does not work for some reason, so removing each one
+            // individually.
+            curl_setopt($resource, CURLOPT_HEADERFUNCTION, null);
+            curl_setopt($resource, CURLOPT_READFUNCTION, null);
+            curl_setopt($resource, CURLOPT_WRITEFUNCTION, null);
+            curl_setopt($resource, CURLOPT_PROGRESSFUNCTION, null);
+            curl_reset($resource);
+            $this->handles[] = $resource;
+        }
+    }
+
+    /**
+     * Completes a cURL transaction, either returning a response promise or a
+     * rejected promise.
+     *
+     * @param callable             $handler
+     * @param EasyHandle           $easy
+     * @param CurlFactoryInterface $factory Dictates how the handle is released
+     *
+     * @return \GuzzleHttp\Promise\PromiseInterface
+     */
+    public static function finish(
+        callable $handler,
+        EasyHandle $easy,
+        CurlFactoryInterface $factory
+    ) {
+        if (isset($easy->options['on_stats'])) {
+            self::invokeStats($easy);
+        }
+
+        if (!$easy->response || $easy->errno) {
+            return self::finishError($handler, $easy, $factory);
+        }
+
+        // Return the response if it is present and there is no error.
+        $factory->release($easy);
+
+        // Rewind the body of the response if possible.
+        $body = $easy->response->getBody();
+        if ($body->isSeekable()) {
+            $body->rewind();
+        }
+
+        return new FulfilledPromise($easy->response);
+    }
+
+    private static function invokeStats(EasyHandle $easy)
+    {
+        $curlStats = curl_getinfo($easy->handle);
+        $stats = new TransferStats(
+            $easy->request,
+            $easy->response,
+            $curlStats['total_time'],
+            $easy->errno,
+            $curlStats
+        );
+        call_user_func($easy->options['on_stats'], $stats);
+    }
+
+    private static function finishError(
+        callable $handler,
+        EasyHandle $easy,
+        CurlFactoryInterface $factory
+    ) {
+        // Get error information and release the handle to the factory.
+        $ctx = [
+            'errno' => $easy->errno,
+            'error' => curl_error($easy->handle),
+        ] + curl_getinfo($easy->handle);
+        $factory->release($easy);
+
+        // Retry when nothing is present or when curl failed to rewind.
+        if (empty($easy->options['_err_message'])
+            && (!$easy->errno || $easy->errno == 65)
+        ) {
+            return self::retryFailedRewind($handler, $easy, $ctx);
+        }
+
+        return self::createRejection($easy, $ctx);
+    }
+
+    private static function createRejection(EasyHandle $easy, array $ctx)
+    {
+        static $connectionErrors = [
+            CURLE_OPERATION_TIMEOUTED  => true,
+            CURLE_COULDNT_RESOLVE_HOST => true,
+            CURLE_COULDNT_CONNECT      => true,
+            CURLE_SSL_CONNECT_ERROR    => true,
+            CURLE_GOT_NOTHING          => true,
+        ];
+
+        // If an exception was encountered during the onHeaders event, then
+        // return a rejected promise that wraps that exception.
+        if ($easy->onHeadersException) {
+            return \GuzzleHttp\Promise\rejection_for(
+                new RequestException(
+                    'An error was encountered during the on_headers event',
+                    $easy->request,
+                    $easy->response,
+                    $easy->onHeadersException,
+                    $ctx
+                )
+            );
+        }
+
+        $message = sprintf(
+            'cURL error %s: %s (%s)',
+            $ctx['errno'],
+            $ctx['error'],
+            'see http://curl.haxx.se/libcurl/c/libcurl-errors.html'
+        );
+
+        // Create a connection exception if it was a specific error code.
+        $error = isset($connectionErrors[$easy->errno])
+            ? new ConnectException($message, $easy->request, null, $ctx)
+            : new RequestException($message, $easy->request, $easy->response, null, $ctx);
+
+        return \GuzzleHttp\Promise\rejection_for($error);
+    }
+
+    private function getDefaultConf(EasyHandle $easy)
+    {
+        $conf = [
+            '_headers'             => $easy->request->getHeaders(),
+            CURLOPT_CUSTOMREQUEST  => $easy->request->getMethod(),
+            CURLOPT_URL            => (string) $easy->request->getUri()->withFragment(''),
+            CURLOPT_RETURNTRANSFER => false,
+            CURLOPT_HEADER         => false,
+            CURLOPT_CONNECTTIMEOUT => 150,
+        ];
+
+        if (defined('CURLOPT_PROTOCOLS')) {
+            $conf[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
+        }
+
+        $version = $easy->request->getProtocolVersion();
+        if ($version == 1.1) {
+            $conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
+        } elseif ($version == 2.0) {
+            $conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0;
+        } else {
+            $conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0;
+        }
+
+        return $conf;
+    }
+
+    private function applyMethod(EasyHandle $easy, array &$conf)
+    {
+        $body = $easy->request->getBody();
+        $size = $body->getSize();
+
+        if ($size === null || $size > 0) {
+            $this->applyBody($easy->request, $easy->options, $conf);
+            return;
+        }
+
+        $method = $easy->request->getMethod();
+        if ($method === 'PUT' || $method === 'POST') {
+            // See http://tools.ietf.org/html/rfc7230#section-3.3.2
+            if (!$easy->request->hasHeader('Content-Length')) {
+                $conf[CURLOPT_HTTPHEADER][] = 'Content-Length: 0';
+            }
+        } elseif ($method === 'HEAD') {
+            $conf[CURLOPT_NOBODY] = true;
+            unset(
+                $conf[CURLOPT_WRITEFUNCTION],
+                $conf[CURLOPT_READFUNCTION],
+                $conf[CURLOPT_FILE],
+                $conf[CURLOPT_INFILE]
+            );
+        }
+    }
+
+    private function applyBody(RequestInterface $request, array $options, array &$conf)
+    {
+        $size = $request->hasHeader('Content-Length')
+            ? (int) $request->getHeaderLine('Content-Length')
+            : null;
+
+        // Send the body as a string if the size is less than 1MB OR if the
+        // [curl][body_as_string] request value is set.
+        if (($size !== null && $size < 1000000) ||
+            !empty($options['_body_as_string'])
+        ) {
+            $conf[CURLOPT_POSTFIELDS] = (string) $request->getBody();
+            // Don't duplicate the Content-Length header
+            $this->removeHeader('Content-Length', $conf);
+            $this->removeHeader('Transfer-Encoding', $conf);
+        } else {
+            $conf[CURLOPT_UPLOAD] = true;
+            if ($size !== null) {
+                $conf[CURLOPT_INFILESIZE] = $size;
+                $this->removeHeader('Content-Length', $conf);
+            }
+            $body = $request->getBody();
+            if ($body->isSeekable()) {
+                $body->rewind();
+            }
+            $conf[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body) {
+                return $body->read($length);
+            };
+        }
+
+        // If the Expect header is not present, prevent curl from adding it
+        if (!$request->hasHeader('Expect')) {
+            $conf[CURLOPT_HTTPHEADER][] = 'Expect:';
+        }
+
+        // cURL sometimes adds a content-type by default. Prevent this.
+        if (!$request->hasHeader('Content-Type')) {
+            $conf[CURLOPT_HTTPHEADER][] = 'Content-Type:';
+        }
+    }
+
+    private function applyHeaders(EasyHandle $easy, array &$conf)
+    {
+        foreach ($conf['_headers'] as $name => $values) {
+            foreach ($values as $value) {
+                $value = (string) $value;
+                if ($value === '') {
+                    // cURL requires a special format for empty headers.
+                    // See https://github.com/guzzle/guzzle/issues/1882 for more details.
+                    $conf[CURLOPT_HTTPHEADER][] = "$name;";
+                } else {
+                    $conf[CURLOPT_HTTPHEADER][] = "$name: $value";
+                }
+            }
+        }
+
+        // Remove the Accept header if one was not set
+        if (!$easy->request->hasHeader('Accept')) {
+            $conf[CURLOPT_HTTPHEADER][] = 'Accept:';
+        }
+    }
+
+    /**
+     * Remove a header from the options array.
+     *
+     * @param string $name    Case-insensitive header to remove
+     * @param array  $options Array of options to modify
+     */
+    private function removeHeader($name, array &$options)
+    {
+        foreach (array_keys($options['_headers']) as $key) {
+            if (!strcasecmp($key, $name)) {
+                unset($options['_headers'][$key]);
+                return;
+            }
+        }
+    }
+
+    private function applyHandlerOptions(EasyHandle $easy, array &$conf)
+    {
+        $options = $easy->options;
+        if (isset($options['verify'])) {
+            if ($options['verify'] === false) {
+                unset($conf[CURLOPT_CAINFO]);
+                $conf[CURLOPT_SSL_VERIFYHOST] = 0;
+                $conf[CURLOPT_SSL_VERIFYPEER] = false;
+            } else {
+                $conf[CURLOPT_SSL_VERIFYHOST] = 2;
+                $conf[CURLOPT_SSL_VERIFYPEER] = true;
+                if (is_string($options['verify'])) {
+                    // Throw an error if the file/folder/link path is not valid or doesn't exist.
+                    if (!file_exists($options['verify'])) {
+                        throw new \InvalidArgumentException(
+                            "SSL CA bundle not found: {$options['verify']}"
+                        );
+                    }
+                    // If it's a directory or a link to a directory use CURLOPT_CAPATH.
+                    // If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO.
+                    if (is_dir($options['verify']) ||
+                        (is_link($options['verify']) && is_dir(readlink($options['verify'])))) {
+                        $conf[CURLOPT_CAPATH] = $options['verify'];
+                    } else {
+                        $conf[CURLOPT_CAINFO] = $options['verify'];
+                    }
+                }
+            }
+        }
+
+        if (!empty($options['decode_content'])) {
+            $accept = $easy->request->getHeaderLine('Accept-Encoding');
+            if ($accept) {
+                $conf[CURLOPT_ENCODING] = $accept;
+            } else {
+                $conf[CURLOPT_ENCODING] = '';
+                // Don't let curl send the header over the wire
+                $conf[CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
+            }
+        }
+
+        if (isset($options['sink'])) {
+            $sink = $options['sink'];
+            if (!is_string($sink)) {
+                $sink = \GuzzleHttp\Psr7\stream_for($sink);
+            } elseif (!is_dir(dirname($sink))) {
+                // Ensure that the directory exists before failing in curl.
+                throw new \RuntimeException(sprintf(
+                    'Directory %s does not exist for sink value of %s',
+                    dirname($sink),
+                    $sink
+                ));
+            } else {
+                $sink = new LazyOpenStream($sink, 'w+');
+            }
+            $easy->sink = $sink;
+            $conf[CURLOPT_WRITEFUNCTION] = function ($ch, $write) use ($sink) {
+                return $sink->write($write);
+            };
+        } else {
+            // Use a default temp stream if no sink was set.
+            $conf[CURLOPT_FILE] = fopen('php://temp', 'w+');
+            $easy->sink = Psr7\stream_for($conf[CURLOPT_FILE]);
+        }
+        $timeoutRequiresNoSignal = false;
+        if (isset($options['timeout'])) {
+            $timeoutRequiresNoSignal |= $options['timeout'] < 1;
+            $conf[CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000;
+        }
+
+        // CURL default value is CURL_IPRESOLVE_WHATEVER
+        if (isset($options['force_ip_resolve'])) {
+            if ('v4' === $options['force_ip_resolve']) {
+                $conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4;
+            } elseif ('v6' === $options['force_ip_resolve']) {
+                $conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V6;
+            }
+        }
+
+        if (isset($options['connect_timeout'])) {
+            $timeoutRequiresNoSignal |= $options['connect_timeout'] < 1;
+            $conf[CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000;
+        }
+
+        if ($timeoutRequiresNoSignal && strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
+            $conf[CURLOPT_NOSIGNAL] = true;
+        }
+
+        if (isset($options['proxy'])) {
+            if (!is_array($options['proxy'])) {
+                $conf[CURLOPT_PROXY] = $options['proxy'];
+            } else {
+                $scheme = $easy->request->getUri()->getScheme();
+                if (isset($options['proxy'][$scheme])) {
+                    $host = $easy->request->getUri()->getHost();
+                    if (!isset($options['proxy']['no']) ||
+                        !\GuzzleHttp\is_host_in_noproxy($host, $options['proxy']['no'])
+                    ) {
+                        $conf[CURLOPT_PROXY] = $options['proxy'][$scheme];
+                    }
+                }
+            }
+        }
+
+        if (isset($options['cert'])) {
+            $cert = $options['cert'];
+            if (is_array($cert)) {
+                $conf[CURLOPT_SSLCERTPASSWD] = $cert[1];
+                $cert = $cert[0];
+            }
+            if (!file_exists($cert)) {
+                throw new \InvalidArgumentException(
+                    "SSL certificate not found: {$cert}"
+                );
+            }
+            $conf[CURLOPT_SSLCERT] = $cert;
+        }
+
+        if (isset($options['ssl_key'])) {
+            $sslKey = $options['ssl_key'];
+            if (is_array($sslKey)) {
+                $conf[CURLOPT_SSLKEYPASSWD] = $sslKey[1];
+                $sslKey = $sslKey[0];
+            }
+            if (!file_exists($sslKey)) {
+                throw new \InvalidArgumentException(
+                    "SSL private key not found: {$sslKey}"
+                );
+            }
+            $conf[CURLOPT_SSLKEY] = $sslKey;
+        }
+
+        if (isset($options['progress'])) {
+            $progress = $options['progress'];
+            if (!is_callable($progress)) {
+                throw new \InvalidArgumentException(
+                    'progress client option must be callable'
+                );
+            }
+            $conf[CURLOPT_NOPROGRESS] = false;
+            $conf[CURLOPT_PROGRESSFUNCTION] = function () use ($progress) {
+                $args = func_get_args();
+                // PHP 5.5 pushed the handle onto the start of the args
+                if (is_resource($args[0])) {
+                    array_shift($args);
+                }
+                call_user_func_array($progress, $args);
+            };
+        }
+
+        if (!empty($options['debug'])) {
+            $conf[CURLOPT_STDERR] = \GuzzleHttp\debug_resource($options['debug']);
+            $conf[CURLOPT_VERBOSE] = true;
+        }
+    }
+
+    /**
+     * This function ensures that a response was set on a transaction. If one
+     * was not set, then the request is retried if possible. This error
+     * typically means you are sending a payload, curl encountered a
+     * "Connection died, retrying a fresh connect" error, tried to rewind the
+     * stream, and then encountered a "necessary data rewind wasn't possible"
+     * error, causing the request to be sent through curl_multi_info_read()
+     * without an error status.
+     */
+    private static function retryFailedRewind(
+        callable $handler,
+        EasyHandle $easy,
+        array $ctx
+    ) {
+        try {
+            // Only rewind if the body has been read from.
+            $body = $easy->request->getBody();
+            if ($body->tell() > 0) {
+                $body->rewind();
+            }
+        } catch (\RuntimeException $e) {
+            $ctx['error'] = 'The connection unexpectedly failed without '
+                . 'providing an error. The request would have been retried, '
+                . 'but attempting to rewind the request body failed. '
+                . 'Exception: ' . $e;
+            return self::createRejection($easy, $ctx);
+        }
+
+        // Retry no more than 3 times before giving up.
+        if (!isset($easy->options['_curl_retries'])) {
+            $easy->options['_curl_retries'] = 1;
+        } elseif ($easy->options['_curl_retries'] == 2) {
+            $ctx['error'] = 'The cURL request was retried 3 times '
+                . 'and did not succeed. The most likely reason for the failure '
+                . 'is that cURL was unable to rewind the body of the request '
+                . 'and subsequent retries resulted in the same error. Turn on '
+                . 'the debug option to see what went wrong. See '
+                . 'https://bugs.php.net/bug.php?id=47204 for more information.';
+            return self::createRejection($easy, $ctx);
+        } else {
+            $easy->options['_curl_retries']++;
+        }
+
+        return $handler($easy->request, $easy->options);
+    }
+
+    private function createHeaderFn(EasyHandle $easy)
+    {
+        if (isset($easy->options['on_headers'])) {
+            $onHeaders = $easy->options['on_headers'];
+
+            if (!is_callable($onHeaders)) {
+                throw new \InvalidArgumentException('on_headers must be callable');
+            }
+        } else {
+            $onHeaders = null;
+        }
+
+        return function ($ch, $h) use (
+            $onHeaders,
+            $easy,
+            &$startingResponse
+        ) {
+            $value = trim($h);
+            if ($value === '') {
+                $startingResponse = true;
+                $easy->createResponse();
+                if ($onHeaders !== null) {
+                    try {
+                        $onHeaders($easy->response);
+                    } catch (\Exception $e) {
+                        // Associate the exception with the handle and trigger
+                        // a curl header write error by returning 0.
+                        $easy->onHeadersException = $e;
+                        return -1;
+                    }
+                }
+            } elseif ($startingResponse) {
+                $startingResponse = false;
+                $easy->headers = [$value];
+            } else {
+                $easy->headers[] = $value;
+            }
+            return strlen($h);
+        };
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php b/vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php
new file mode 100644
index 00000000000..b0fc236850b
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php
@@ -0,0 +1,27 @@
+<?php
+namespace GuzzleHttp\Handler;
+
+use Psr\Http\Message\RequestInterface;
+
+interface CurlFactoryInterface
+{
+    /**
+     * Creates a cURL handle resource.
+     *
+     * @param RequestInterface $request Request
+     * @param array            $options Transfer options
+     *
+     * @return EasyHandle
+     * @throws \RuntimeException when an option cannot be applied
+     */
+    public function create(RequestInterface $request, array $options);
+
+    /**
+     * Release an easy handle, allowing it to be reused or closed.
+     *
+     * This function must call unset on the easy handle's "handle" property.
+     *
+     * @param EasyHandle $easy
+     */
+    public function release(EasyHandle $easy);
+}
diff --git a/vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php b/vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php
new file mode 100644
index 00000000000..43577da66e2
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php
@@ -0,0 +1,45 @@
+<?php
+namespace GuzzleHttp\Handler;
+
+use GuzzleHttp\Psr7;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * HTTP handler that uses cURL easy handles as a transport layer.
+ *
+ * When using the CurlHandler, custom curl options can be specified as an
+ * associative array of curl option constants mapping to values in the
+ * **curl** key of the "client" key of the request.
+ */
+class CurlHandler
+{
+    /** @var CurlFactoryInterface */
+    private $factory;
+
+    /**
+     * Accepts an associative array of options:
+     *
+     * - factory: Optional curl factory used to create cURL handles.
+     *
+     * @param array $options Array of options to use with the handler
+     */
+    public function __construct(array $options = [])
+    {
+        $this->factory = isset($options['handle_factory'])
+            ? $options['handle_factory']
+            : new CurlFactory(3);
+    }
+
+    public function __invoke(RequestInterface $request, array $options)
+    {
+        if (isset($options['delay'])) {
+            usleep($options['delay'] * 1000);
+        }
+
+        $easy = $this->factory->create($request, $options);
+        curl_exec($easy->handle);
+        $easy->errno = curl_errno($easy->handle);
+
+        return CurlFactory::finish($this, $easy, $this->factory);
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php b/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php
new file mode 100644
index 00000000000..2754d8e4378
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php
@@ -0,0 +1,199 @@
+<?php
+namespace GuzzleHttp\Handler;
+
+use GuzzleHttp\Promise as P;
+use GuzzleHttp\Promise\Promise;
+use GuzzleHttp\Psr7;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Returns an asynchronous response using curl_multi_* functions.
+ *
+ * When using the CurlMultiHandler, custom curl options can be specified as an
+ * associative array of curl option constants mapping to values in the
+ * **curl** key of the provided request options.
+ *
+ * @property resource $_mh Internal use only. Lazy loaded multi-handle.
+ */
+class CurlMultiHandler
+{
+    /** @var CurlFactoryInterface */
+    private $factory;
+    private $selectTimeout;
+    private $active;
+    private $handles = [];
+    private $delays = [];
+
+    /**
+     * This handler accepts the following options:
+     *
+     * - handle_factory: An optional factory  used to create curl handles
+     * - select_timeout: Optional timeout (in seconds) to block before timing
+     *   out while selecting curl handles. Defaults to 1 second.
+     *
+     * @param array $options
+     */
+    public function __construct(array $options = [])
+    {
+        $this->factory = isset($options['handle_factory'])
+            ? $options['handle_factory'] : new CurlFactory(50);
+        $this->selectTimeout = isset($options['select_timeout'])
+            ? $options['select_timeout'] : 1;
+    }
+
+    public function __get($name)
+    {
+        if ($name === '_mh') {
+            return $this->_mh = curl_multi_init();
+        }
+
+        throw new \BadMethodCallException();
+    }
+
+    public function __destruct()
+    {
+        if (isset($this->_mh)) {
+            curl_multi_close($this->_mh);
+            unset($this->_mh);
+        }
+    }
+
+    public function __invoke(RequestInterface $request, array $options)
+    {
+        $easy = $this->factory->create($request, $options);
+        $id = (int) $easy->handle;
+
+        $promise = new Promise(
+            [$this, 'execute'],
+            function () use ($id) {
+                return $this->cancel($id);
+            }
+        );
+
+        $this->addRequest(['easy' => $easy, 'deferred' => $promise]);
+
+        return $promise;
+    }
+
+    /**
+     * Ticks the curl event loop.
+     */
+    public function tick()
+    {
+        // Add any delayed handles if needed.
+        if ($this->delays) {
+            $currentTime = microtime(true);
+            foreach ($this->delays as $id => $delay) {
+                if ($currentTime >= $delay) {
+                    unset($this->delays[$id]);
+                    curl_multi_add_handle(
+                        $this->_mh,
+                        $this->handles[$id]['easy']->handle
+                    );
+                }
+            }
+        }
+
+        // Step through the task queue which may add additional requests.
+        P\queue()->run();
+
+        if ($this->active &&
+            curl_multi_select($this->_mh, $this->selectTimeout) === -1
+        ) {
+            // Perform a usleep if a select returns -1.
+            // See: https://bugs.php.net/bug.php?id=61141
+            usleep(250);
+        }
+
+        while (curl_multi_exec($this->_mh, $this->active) === CURLM_CALL_MULTI_PERFORM);
+
+        $this->processMessages();
+    }
+
+    /**
+     * Runs until all outstanding connections have completed.
+     */
+    public function execute()
+    {
+        $queue = P\queue();
+
+        while ($this->handles || !$queue->isEmpty()) {
+            // If there are no transfers, then sleep for the next delay
+            if (!$this->active && $this->delays) {
+                usleep($this->timeToNext());
+            }
+            $this->tick();
+        }
+    }
+
+    private function addRequest(array $entry)
+    {
+        $easy = $entry['easy'];
+        $id = (int) $easy->handle;
+        $this->handles[$id] = $entry;
+        if (empty($easy->options['delay'])) {
+            curl_multi_add_handle($this->_mh, $easy->handle);
+        } else {
+            $this->delays[$id] = microtime(true) + ($easy->options['delay'] / 1000);
+        }
+    }
+
+    /**
+     * Cancels a handle from sending and removes references to it.
+     *
+     * @param int $id Handle ID to cancel and remove.
+     *
+     * @return bool True on success, false on failure.
+     */
+    private function cancel($id)
+    {
+        // Cannot cancel if it has been processed.
+        if (!isset($this->handles[$id])) {
+            return false;
+        }
+
+        $handle = $this->handles[$id]['easy']->handle;
+        unset($this->delays[$id], $this->handles[$id]);
+        curl_multi_remove_handle($this->_mh, $handle);
+        curl_close($handle);
+
+        return true;
+    }
+
+    private function processMessages()
+    {
+        while ($done = curl_multi_info_read($this->_mh)) {
+            $id = (int) $done['handle'];
+            curl_multi_remove_handle($this->_mh, $done['handle']);
+
+            if (!isset($this->handles[$id])) {
+                // Probably was cancelled.
+                continue;
+            }
+
+            $entry = $this->handles[$id];
+            unset($this->handles[$id], $this->delays[$id]);
+            $entry['easy']->errno = $done['result'];
+            $entry['deferred']->resolve(
+                CurlFactory::finish(
+                    $this,
+                    $entry['easy'],
+                    $this->factory
+                )
+            );
+        }
+    }
+
+    private function timeToNext()
+    {
+        $currentTime = microtime(true);
+        $nextTime = PHP_INT_MAX;
+        foreach ($this->delays as $time) {
+            if ($time < $nextTime) {
+                $nextTime = $time;
+            }
+        }
+
+        return max(0, $nextTime - $currentTime) * 1000000;
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php b/vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php
new file mode 100644
index 00000000000..7754e9111b7
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php
@@ -0,0 +1,92 @@
+<?php
+namespace GuzzleHttp\Handler;
+
+use GuzzleHttp\Psr7\Response;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Represents a cURL easy handle and the data it populates.
+ *
+ * @internal
+ */
+final class EasyHandle
+{
+    /** @var resource cURL resource */
+    public $handle;
+
+    /** @var StreamInterface Where data is being written */
+    public $sink;
+
+    /** @var array Received HTTP headers so far */
+    public $headers = [];
+
+    /** @var ResponseInterface Received response (if any) */
+    public $response;
+
+    /** @var RequestInterface Request being sent */
+    public $request;
+
+    /** @var array Request options */
+    public $options = [];
+
+    /** @var int cURL error number (if any) */
+    public $errno = 0;
+
+    /** @var \Exception Exception during on_headers (if any) */
+    public $onHeadersException;
+
+    /**
+     * Attach a response to the easy handle based on the received headers.
+     *
+     * @throws \RuntimeException if no headers have been received.
+     */
+    public function createResponse()
+    {
+        if (empty($this->headers)) {
+            throw new \RuntimeException('No headers have been received');
+        }
+
+        // HTTP-version SP status-code SP reason-phrase
+        $startLine = explode(' ', array_shift($this->headers), 3);
+        $headers = \GuzzleHttp\headers_from_lines($this->headers);
+        $normalizedKeys = \GuzzleHttp\normalize_header_keys($headers);
+
+        if (!empty($this->options['decode_content'])
+            && isset($normalizedKeys['content-encoding'])
+        ) {
+            $headers['x-encoded-content-encoding']
+                = $headers[$normalizedKeys['content-encoding']];
+            unset($headers[$normalizedKeys['content-encoding']]);
+            if (isset($normalizedKeys['content-length'])) {
+                $headers['x-encoded-content-length']
+                    = $headers[$normalizedKeys['content-length']];
+
+                $bodyLength = (int) $this->sink->getSize();
+                if ($bodyLength) {
+                    $headers[$normalizedKeys['content-length']] = $bodyLength;
+                } else {
+                    unset($headers[$normalizedKeys['content-length']]);
+                }
+            }
+        }
+
+        // Attach a response to the easy handle with the parsed headers.
+        $this->response = new Response(
+            $startLine[1],
+            $headers,
+            $this->sink,
+            substr($startLine[0], 5),
+            isset($startLine[2]) ? (string) $startLine[2] : null
+        );
+    }
+
+    public function __get($name)
+    {
+        $msg = $name === 'handle'
+            ? 'The EasyHandle has been released'
+            : 'Invalid property: ' . $name;
+        throw new \BadMethodCallException($msg);
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php b/vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php
new file mode 100644
index 00000000000..d892061c7a0
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php
@@ -0,0 +1,189 @@
+<?php
+namespace GuzzleHttp\Handler;
+
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\HandlerStack;
+use GuzzleHttp\Promise\PromiseInterface;
+use GuzzleHttp\Promise\RejectedPromise;
+use GuzzleHttp\TransferStats;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Handler that returns responses or throw exceptions from a queue.
+ */
+class MockHandler implements \Countable
+{
+    private $queue = [];
+    private $lastRequest;
+    private $lastOptions;
+    private $onFulfilled;
+    private $onRejected;
+
+    /**
+     * Creates a new MockHandler that uses the default handler stack list of
+     * middlewares.
+     *
+     * @param array $queue Array of responses, callables, or exceptions.
+     * @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
+     * @param callable $onRejected  Callback to invoke when the return value is rejected.
+     *
+     * @return HandlerStack
+     */
+    public static function createWithMiddleware(
+        array $queue = null,
+        callable $onFulfilled = null,
+        callable $onRejected = null
+    ) {
+        return HandlerStack::create(new self($queue, $onFulfilled, $onRejected));
+    }
+
+    /**
+     * The passed in value must be an array of
+     * {@see Psr7\Http\Message\ResponseInterface} objects, Exceptions,
+     * callables, or Promises.
+     *
+     * @param array $queue
+     * @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
+     * @param callable $onRejected  Callback to invoke when the return value is rejected.
+     */
+    public function __construct(
+        array $queue = null,
+        callable $onFulfilled = null,
+        callable $onRejected = null
+    ) {
+        $this->onFulfilled = $onFulfilled;
+        $this->onRejected = $onRejected;
+
+        if ($queue) {
+            call_user_func_array([$this, 'append'], $queue);
+        }
+    }
+
+    public function __invoke(RequestInterface $request, array $options)
+    {
+        if (!$this->queue) {
+            throw new \OutOfBoundsException('Mock queue is empty');
+        }
+
+        if (isset($options['delay'])) {
+            usleep($options['delay'] * 1000);
+        }
+
+        $this->lastRequest = $request;
+        $this->lastOptions = $options;
+        $response = array_shift($this->queue);
+
+        if (isset($options['on_headers'])) {
+            if (!is_callable($options['on_headers'])) {
+                throw new \InvalidArgumentException('on_headers must be callable');
+            }
+            try {
+                $options['on_headers']($response);
+            } catch (\Exception $e) {
+                $msg = 'An error was encountered during the on_headers event';
+                $response = new RequestException($msg, $request, $response, $e);
+            }
+        }
+
+        if (is_callable($response)) {
+            $response = call_user_func($response, $request, $options);
+        }
+
+        $response = $response instanceof \Exception
+            ? \GuzzleHttp\Promise\rejection_for($response)
+            : \GuzzleHttp\Promise\promise_for($response);
+
+        return $response->then(
+            function ($value) use ($request, $options) {
+                $this->invokeStats($request, $options, $value);
+                if ($this->onFulfilled) {
+                    call_user_func($this->onFulfilled, $value);
+                }
+                if (isset($options['sink'])) {
+                    $contents = (string) $value->getBody();
+                    $sink = $options['sink'];
+
+                    if (is_resource($sink)) {
+                        fwrite($sink, $contents);
+                    } elseif (is_string($sink)) {
+                        file_put_contents($sink, $contents);
+                    } elseif ($sink instanceof \Psr\Http\Message\StreamInterface) {
+                        $sink->write($contents);
+                    }
+                }
+
+                return $value;
+            },
+            function ($reason) use ($request, $options) {
+                $this->invokeStats($request, $options, null, $reason);
+                if ($this->onRejected) {
+                    call_user_func($this->onRejected, $reason);
+                }
+                return \GuzzleHttp\Promise\rejection_for($reason);
+            }
+        );
+    }
+
+    /**
+     * Adds one or more variadic requests, exceptions, callables, or promises
+     * to the queue.
+     */
+    public function append()
+    {
+        foreach (func_get_args() as $value) {
+            if ($value instanceof ResponseInterface
+                || $value instanceof \Exception
+                || $value instanceof PromiseInterface
+                || is_callable($value)
+            ) {
+                $this->queue[] = $value;
+            } else {
+                throw new \InvalidArgumentException('Expected a response or '
+                    . 'exception. Found ' . \GuzzleHttp\describe_type($value));
+            }
+        }
+    }
+
+    /**
+     * Get the last received request.
+     *
+     * @return RequestInterface
+     */
+    public function getLastRequest()
+    {
+        return $this->lastRequest;
+    }
+
+    /**
+     * Get the last received request options.
+     *
+     * @return array
+     */
+    public function getLastOptions()
+    {
+        return $this->lastOptions;
+    }
+
+    /**
+     * Returns the number of remaining items in the queue.
+     *
+     * @return int
+     */
+    public function count()
+    {
+        return count($this->queue);
+    }
+
+    private function invokeStats(
+        RequestInterface $request,
+        array $options,
+        ResponseInterface $response = null,
+        $reason = null
+    ) {
+        if (isset($options['on_stats'])) {
+            $stats = new TransferStats($request, $response, 0, $reason);
+            call_user_func($options['on_stats'], $stats);
+        }
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php b/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php
new file mode 100644
index 00000000000..f8b00be0b99
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php
@@ -0,0 +1,55 @@
+<?php
+namespace GuzzleHttp\Handler;
+
+use GuzzleHttp\RequestOptions;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Provides basic proxies for handlers.
+ */
+class Proxy
+{
+    /**
+     * Sends synchronous requests to a specific handler while sending all other
+     * requests to another handler.
+     *
+     * @param callable $default Handler used for normal responses
+     * @param callable $sync    Handler used for synchronous responses.
+     *
+     * @return callable Returns the composed handler.
+     */
+    public static function wrapSync(
+        callable $default,
+        callable $sync
+    ) {
+        return function (RequestInterface $request, array $options) use ($default, $sync) {
+            return empty($options[RequestOptions::SYNCHRONOUS])
+                ? $default($request, $options)
+                : $sync($request, $options);
+        };
+    }
+
+    /**
+     * Sends streaming requests to a streaming compatible handler while sending
+     * all other requests to a default handler.
+     *
+     * This, for example, could be useful for taking advantage of the
+     * performance benefits of curl while still supporting true streaming
+     * through the StreamHandler.
+     *
+     * @param callable $default   Handler used for non-streaming responses
+     * @param callable $streaming Handler used for streaming responses
+     *
+     * @return callable Returns the composed handler.
+     */
+    public static function wrapStreaming(
+        callable $default,
+        callable $streaming
+    ) {
+        return function (RequestInterface $request, array $options) use ($default, $streaming) {
+            return empty($options['stream'])
+                ? $default($request, $options)
+                : $streaming($request, $options);
+        };
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php b/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php
new file mode 100644
index 00000000000..b686545ea7f
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php
@@ -0,0 +1,532 @@
+<?php
+namespace GuzzleHttp\Handler;
+
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\Exception\ConnectException;
+use GuzzleHttp\Promise\FulfilledPromise;
+use GuzzleHttp\Promise\PromiseInterface;
+use GuzzleHttp\Psr7;
+use GuzzleHttp\TransferStats;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * HTTP handler that uses PHP's HTTP stream wrapper.
+ */
+class StreamHandler
+{
+    private $lastHeaders = [];
+
+    /**
+     * Sends an HTTP request.
+     *
+     * @param RequestInterface $request Request to send.
+     * @param array            $options Request transfer options.
+     *
+     * @return PromiseInterface
+     */
+    public function __invoke(RequestInterface $request, array $options)
+    {
+        // Sleep if there is a delay specified.
+        if (isset($options['delay'])) {
+            usleep($options['delay'] * 1000);
+        }
+
+        $startTime = isset($options['on_stats']) ? microtime(true) : null;
+
+        try {
+            // Does not support the expect header.
+            $request = $request->withoutHeader('Expect');
+
+            // Append a content-length header if body size is zero to match
+            // cURL's behavior.
+            if (0 === $request->getBody()->getSize()) {
+                $request = $request->withHeader('Content-Length', 0);
+            }
+
+            return $this->createResponse(
+                $request,
+                $options,
+                $this->createStream($request, $options),
+                $startTime
+            );
+        } catch (\InvalidArgumentException $e) {
+            throw $e;
+        } catch (\Exception $e) {
+            // Determine if the error was a networking error.
+            $message = $e->getMessage();
+            // This list can probably get more comprehensive.
+            if (strpos($message, 'getaddrinfo') // DNS lookup failed
+                || strpos($message, 'Connection refused')
+                || strpos($message, "couldn't connect to host") // error on HHVM
+                || strpos($message, "connection attempt failed")
+            ) {
+                $e = new ConnectException($e->getMessage(), $request, $e);
+            }
+            $e = RequestException::wrapException($request, $e);
+            $this->invokeStats($options, $request, $startTime, null, $e);
+
+            return \GuzzleHttp\Promise\rejection_for($e);
+        }
+    }
+
+    private function invokeStats(
+        array $options,
+        RequestInterface $request,
+        $startTime,
+        ResponseInterface $response = null,
+        $error = null
+    ) {
+        if (isset($options['on_stats'])) {
+            $stats = new TransferStats(
+                $request,
+                $response,
+                microtime(true) - $startTime,
+                $error,
+                []
+            );
+            call_user_func($options['on_stats'], $stats);
+        }
+    }
+
+    private function createResponse(
+        RequestInterface $request,
+        array $options,
+        $stream,
+        $startTime
+    ) {
+        $hdrs = $this->lastHeaders;
+        $this->lastHeaders = [];
+        $parts = explode(' ', array_shift($hdrs), 3);
+        $ver = explode('/', $parts[0])[1];
+        $status = $parts[1];
+        $reason = isset($parts[2]) ? $parts[2] : null;
+        $headers = \GuzzleHttp\headers_from_lines($hdrs);
+        list($stream, $headers) = $this->checkDecode($options, $headers, $stream);
+        $stream = Psr7\stream_for($stream);
+        $sink = $stream;
+
+        if (strcasecmp('HEAD', $request->getMethod())) {
+            $sink = $this->createSink($stream, $options);
+        }
+
+        $response = new Psr7\Response($status, $headers, $sink, $ver, $reason);
+
+        if (isset($options['on_headers'])) {
+            try {
+                $options['on_headers']($response);
+            } catch (\Exception $e) {
+                $msg = 'An error was encountered during the on_headers event';
+                $ex = new RequestException($msg, $request, $response, $e);
+                return \GuzzleHttp\Promise\rejection_for($ex);
+            }
+        }
+
+        // Do not drain when the request is a HEAD request because they have
+        // no body.
+        if ($sink !== $stream) {
+            $this->drain(
+                $stream,
+                $sink,
+                $response->getHeaderLine('Content-Length')
+            );
+        }
+
+        $this->invokeStats($options, $request, $startTime, $response, null);
+
+        return new FulfilledPromise($response);
+    }
+
+    private function createSink(StreamInterface $stream, array $options)
+    {
+        if (!empty($options['stream'])) {
+            return $stream;
+        }
+
+        $sink = isset($options['sink'])
+            ? $options['sink']
+            : fopen('php://temp', 'r+');
+
+        return is_string($sink)
+            ? new Psr7\LazyOpenStream($sink, 'w+')
+            : Psr7\stream_for($sink);
+    }
+
+    private function checkDecode(array $options, array $headers, $stream)
+    {
+        // Automatically decode responses when instructed.
+        if (!empty($options['decode_content'])) {
+            $normalizedKeys = \GuzzleHttp\normalize_header_keys($headers);
+            if (isset($normalizedKeys['content-encoding'])) {
+                $encoding = $headers[$normalizedKeys['content-encoding']];
+                if ($encoding[0] === 'gzip' || $encoding[0] === 'deflate') {
+                    $stream = new Psr7\InflateStream(
+                        Psr7\stream_for($stream)
+                    );
+                    $headers['x-encoded-content-encoding']
+                        = $headers[$normalizedKeys['content-encoding']];
+                    // Remove content-encoding header
+                    unset($headers[$normalizedKeys['content-encoding']]);
+                    // Fix content-length header
+                    if (isset($normalizedKeys['content-length'])) {
+                        $headers['x-encoded-content-length']
+                            = $headers[$normalizedKeys['content-length']];
+
+                        $length = (int) $stream->getSize();
+                        if ($length === 0) {
+                            unset($headers[$normalizedKeys['content-length']]);
+                        } else {
+                            $headers[$normalizedKeys['content-length']] = [$length];
+                        }
+                    }
+                }
+            }
+        }
+
+        return [$stream, $headers];
+    }
+
+    /**
+     * Drains the source stream into the "sink" client option.
+     *
+     * @param StreamInterface $source
+     * @param StreamInterface $sink
+     * @param string          $contentLength Header specifying the amount of
+     *                                       data to read.
+     *
+     * @return StreamInterface
+     * @throws \RuntimeException when the sink option is invalid.
+     */
+    private function drain(
+        StreamInterface $source,
+        StreamInterface $sink,
+        $contentLength
+    ) {
+        // If a content-length header is provided, then stop reading once
+        // that number of bytes has been read. This can prevent infinitely
+        // reading from a stream when dealing with servers that do not honor
+        // Connection: Close headers.
+        Psr7\copy_to_stream(
+            $source,
+            $sink,
+            (strlen($contentLength) > 0 && (int) $contentLength > 0) ? (int) $contentLength : -1
+        );
+
+        $sink->seek(0);
+        $source->close();
+
+        return $sink;
+    }
+
+    /**
+     * Create a resource and check to ensure it was created successfully
+     *
+     * @param callable $callback Callable that returns stream resource
+     *
+     * @return resource
+     * @throws \RuntimeException on error
+     */
+    private function createResource(callable $callback)
+    {
+        $errors = null;
+        set_error_handler(function ($_, $msg, $file, $line) use (&$errors) {
+            $errors[] = [
+                'message' => $msg,
+                'file'    => $file,
+                'line'    => $line
+            ];
+            return true;
+        });
+
+        $resource = $callback();
+        restore_error_handler();
+
+        if (!$resource) {
+            $message = 'Error creating resource: ';
+            foreach ($errors as $err) {
+                foreach ($err as $key => $value) {
+                    $message .= "[$key] $value" . PHP_EOL;
+                }
+            }
+            throw new \RuntimeException(trim($message));
+        }
+
+        return $resource;
+    }
+
+    private function createStream(RequestInterface $request, array $options)
+    {
+        static $methods;
+        if (!$methods) {
+            $methods = array_flip(get_class_methods(__CLASS__));
+        }
+
+        // HTTP/1.1 streams using the PHP stream wrapper require a
+        // Connection: close header
+        if ($request->getProtocolVersion() == '1.1'
+            && !$request->hasHeader('Connection')
+        ) {
+            $request = $request->withHeader('Connection', 'close');
+        }
+
+        // Ensure SSL is verified by default
+        if (!isset($options['verify'])) {
+            $options['verify'] = true;
+        }
+
+        $params = [];
+        $context = $this->getDefaultContext($request);
+
+        if (isset($options['on_headers']) && !is_callable($options['on_headers'])) {
+            throw new \InvalidArgumentException('on_headers must be callable');
+        }
+
+        if (!empty($options)) {
+            foreach ($options as $key => $value) {
+                $method = "add_{$key}";
+                if (isset($methods[$method])) {
+                    $this->{$method}($request, $context, $value, $params);
+                }
+            }
+        }
+
+        if (isset($options['stream_context'])) {
+            if (!is_array($options['stream_context'])) {
+                throw new \InvalidArgumentException('stream_context must be an array');
+            }
+            $context = array_replace_recursive(
+                $context,
+                $options['stream_context']
+            );
+        }
+
+        // Microsoft NTLM authentication only supported with curl handler
+        if (isset($options['auth'])
+            && is_array($options['auth'])
+            && isset($options['auth'][2])
+            && 'ntlm' == $options['auth'][2]
+        ) {
+            throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler');
+        }
+
+        $uri = $this->resolveHost($request, $options);
+
+        $context = $this->createResource(
+            function () use ($context, $params) {
+                return stream_context_create($context, $params);
+            }
+        );
+
+        return $this->createResource(
+            function () use ($uri, &$http_response_header, $context, $options) {
+                $resource = fopen((string) $uri, 'r', null, $context);
+                $this->lastHeaders = $http_response_header;
+
+                if (isset($options['read_timeout'])) {
+                    $readTimeout = $options['read_timeout'];
+                    $sec = (int) $readTimeout;
+                    $usec = ($readTimeout - $sec) * 100000;
+                    stream_set_timeout($resource, $sec, $usec);
+                }
+
+                return $resource;
+            }
+        );
+    }
+
+    private function resolveHost(RequestInterface $request, array $options)
+    {
+        $uri = $request->getUri();
+
+        if (isset($options['force_ip_resolve']) && !filter_var($uri->getHost(), FILTER_VALIDATE_IP)) {
+            if ('v4' === $options['force_ip_resolve']) {
+                $records = dns_get_record($uri->getHost(), DNS_A);
+                if (!isset($records[0]['ip'])) {
+                    throw new ConnectException(sprintf("Could not resolve IPv4 address for host '%s'", $uri->getHost()), $request);
+                }
+                $uri = $uri->withHost($records[0]['ip']);
+            } elseif ('v6' === $options['force_ip_resolve']) {
+                $records = dns_get_record($uri->getHost(), DNS_AAAA);
+                if (!isset($records[0]['ipv6'])) {
+                    throw new ConnectException(sprintf("Could not resolve IPv6 address for host '%s'", $uri->getHost()), $request);
+                }
+                $uri = $uri->withHost('[' . $records[0]['ipv6'] . ']');
+            }
+        }
+
+        return $uri;
+    }
+
+    private function getDefaultContext(RequestInterface $request)
+    {
+        $headers = '';
+        foreach ($request->getHeaders() as $name => $value) {
+            foreach ($value as $val) {
+                $headers .= "$name: $val\r\n";
+            }
+        }
+
+        $context = [
+            'http' => [
+                'method'           => $request->getMethod(),
+                'header'           => $headers,
+                'protocol_version' => $request->getProtocolVersion(),
+                'ignore_errors'    => true,
+                'follow_location'  => 0,
+            ],
+        ];
+
+        $body = (string) $request->getBody();
+
+        if (!empty($body)) {
+            $context['http']['content'] = $body;
+            // Prevent the HTTP handler from adding a Content-Type header.
+            if (!$request->hasHeader('Content-Type')) {
+                $context['http']['header'] .= "Content-Type:\r\n";
+            }
+        }
+
+        $context['http']['header'] = rtrim($context['http']['header']);
+
+        return $context;
+    }
+
+    private function add_proxy(RequestInterface $request, &$options, $value, &$params)
+    {
+        if (!is_array($value)) {
+            $options['http']['proxy'] = $value;
+        } else {
+            $scheme = $request->getUri()->getScheme();
+            if (isset($value[$scheme])) {
+                if (!isset($value['no'])
+                    || !\GuzzleHttp\is_host_in_noproxy(
+                        $request->getUri()->getHost(),
+                        $value['no']
+                    )
+                ) {
+                    $options['http']['proxy'] = $value[$scheme];
+                }
+            }
+        }
+    }
+
+    private function add_timeout(RequestInterface $request, &$options, $value, &$params)
+    {
+        if ($value > 0) {
+            $options['http']['timeout'] = $value;
+        }
+    }
+
+    private function add_verify(RequestInterface $request, &$options, $value, &$params)
+    {
+        if ($value === true) {
+            // PHP 5.6 or greater will find the system cert by default. When
+            // < 5.6, use the Guzzle bundled cacert.
+            if (PHP_VERSION_ID < 50600) {
+                $options['ssl']['cafile'] = \GuzzleHttp\default_ca_bundle();
+            }
+        } elseif (is_string($value)) {
+            $options['ssl']['cafile'] = $value;
+            if (!file_exists($value)) {
+                throw new \RuntimeException("SSL CA bundle not found: $value");
+            }
+        } elseif ($value === false) {
+            $options['ssl']['verify_peer'] = false;
+            $options['ssl']['verify_peer_name'] = false;
+            return;
+        } else {
+            throw new \InvalidArgumentException('Invalid verify request option');
+        }
+
+        $options['ssl']['verify_peer'] = true;
+        $options['ssl']['verify_peer_name'] = true;
+        $options['ssl']['allow_self_signed'] = false;
+    }
+
+    private function add_cert(RequestInterface $request, &$options, $value, &$params)
+    {
+        if (is_array($value)) {
+            $options['ssl']['passphrase'] = $value[1];
+            $value = $value[0];
+        }
+
+        if (!file_exists($value)) {
+            throw new \RuntimeException("SSL certificate not found: {$value}");
+        }
+
+        $options['ssl']['local_cert'] = $value;
+    }
+
+    private function add_progress(RequestInterface $request, &$options, $value, &$params)
+    {
+        $this->addNotification(
+            $params,
+            function ($code, $a, $b, $c, $transferred, $total) use ($value) {
+                if ($code == STREAM_NOTIFY_PROGRESS) {
+                    $value($total, $transferred, null, null);
+                }
+            }
+        );
+    }
+
+    private function add_debug(RequestInterface $request, &$options, $value, &$params)
+    {
+        if ($value === false) {
+            return;
+        }
+
+        static $map = [
+            STREAM_NOTIFY_CONNECT       => 'CONNECT',
+            STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED',
+            STREAM_NOTIFY_AUTH_RESULT   => 'AUTH_RESULT',
+            STREAM_NOTIFY_MIME_TYPE_IS  => 'MIME_TYPE_IS',
+            STREAM_NOTIFY_FILE_SIZE_IS  => 'FILE_SIZE_IS',
+            STREAM_NOTIFY_REDIRECTED    => 'REDIRECTED',
+            STREAM_NOTIFY_PROGRESS      => 'PROGRESS',
+            STREAM_NOTIFY_FAILURE       => 'FAILURE',
+            STREAM_NOTIFY_COMPLETED     => 'COMPLETED',
+            STREAM_NOTIFY_RESOLVE       => 'RESOLVE',
+        ];
+        static $args = ['severity', 'message', 'message_code',
+            'bytes_transferred', 'bytes_max'];
+
+        $value = \GuzzleHttp\debug_resource($value);
+        $ident = $request->getMethod() . ' ' . $request->getUri()->withFragment('');
+        $this->addNotification(
+            $params,
+            function () use ($ident, $value, $map, $args) {
+                $passed = func_get_args();
+                $code = array_shift($passed);
+                fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
+                foreach (array_filter($passed) as $i => $v) {
+                    fwrite($value, $args[$i] . ': "' . $v . '" ');
+                }
+                fwrite($value, "\n");
+            }
+        );
+    }
+
+    private function addNotification(array &$params, callable $notify)
+    {
+        // Wrap the existing function if needed.
+        if (!isset($params['notification'])) {
+            $params['notification'] = $notify;
+        } else {
+            $params['notification'] = $this->callArray([
+                $params['notification'],
+                $notify
+            ]);
+        }
+    }
+
+    private function callArray(array $functions)
+    {
+        return function () use ($functions) {
+            $args = func_get_args();
+            foreach ($functions as $fn) {
+                call_user_func_array($fn, $args);
+            }
+        };
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/HandlerStack.php b/vendor/guzzlehttp/guzzle/src/HandlerStack.php
new file mode 100644
index 00000000000..24c46fd9fea
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/HandlerStack.php
@@ -0,0 +1,273 @@
+<?php
+namespace GuzzleHttp;
+
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Creates a composed Guzzle handler function by stacking middlewares on top of
+ * an HTTP handler function.
+ */
+class HandlerStack
+{
+    /** @var callable */
+    private $handler;
+
+    /** @var array */
+    private $stack = [];
+
+    /** @var callable|null */
+    private $cached;
+
+    /**
+     * Creates a default handler stack that can be used by clients.
+     *
+     * The returned handler will wrap the provided handler or use the most
+     * appropriate default handler for your system. The returned HandlerStack has
+     * support for cookies, redirects, HTTP error exceptions, and preparing a body
+     * before sending.
+     *
+     * The returned handler stack can be passed to a client in the "handler"
+     * option.
+     *
+     * @param callable $handler HTTP handler function to use with the stack. If no
+     *                          handler is provided, the best handler for your
+     *                          system will be utilized.
+     *
+     * @return HandlerStack
+     */
+    public static function create(callable $handler = null)
+    {
+        $stack = new self($handler ?: choose_handler());
+        $stack->push(Middleware::httpErrors(), 'http_errors');
+        $stack->push(Middleware::redirect(), 'allow_redirects');
+        $stack->push(Middleware::cookies(), 'cookies');
+        $stack->push(Middleware::prepareBody(), 'prepare_body');
+
+        return $stack;
+    }
+
+    /**
+     * @param callable $handler Underlying HTTP handler.
+     */
+    public function __construct(callable $handler = null)
+    {
+        $this->handler = $handler;
+    }
+
+    /**
+     * Invokes the handler stack as a composed handler
+     *
+     * @param RequestInterface $request
+     * @param array            $options
+     */
+    public function __invoke(RequestInterface $request, array $options)
+    {
+        $handler = $this->resolve();
+
+        return $handler($request, $options);
+    }
+
+    /**
+     * Dumps a string representation of the stack.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        $depth = 0;
+        $stack = [];
+        if ($this->handler) {
+            $stack[] = "0) Handler: " . $this->debugCallable($this->handler);
+        }
+
+        $result = '';
+        foreach (array_reverse($this->stack) as $tuple) {
+            $depth++;
+            $str = "{$depth}) Name: '{$tuple[1]}', ";
+            $str .= "Function: " . $this->debugCallable($tuple[0]);
+            $result = "> {$str}\n{$result}";
+            $stack[] = $str;
+        }
+
+        foreach (array_keys($stack) as $k) {
+            $result .= "< {$stack[$k]}\n";
+        }
+
+        return $result;
+    }
+
+    /**
+     * Set the HTTP handler that actually returns a promise.
+     *
+     * @param callable $handler Accepts a request and array of options and
+     *                          returns a Promise.
+     */
+    public function setHandler(callable $handler)
+    {
+        $this->handler = $handler;
+        $this->cached = null;
+    }
+
+    /**
+     * Returns true if the builder has a handler.
+     *
+     * @return bool
+     */
+    public function hasHandler()
+    {
+        return (bool) $this->handler;
+    }
+
+    /**
+     * Unshift a middleware to the bottom of the stack.
+     *
+     * @param callable $middleware Middleware function
+     * @param string   $name       Name to register for this middleware.
+     */
+    public function unshift(callable $middleware, $name = null)
+    {
+        array_unshift($this->stack, [$middleware, $name]);
+        $this->cached = null;
+    }
+
+    /**
+     * Push a middleware to the top of the stack.
+     *
+     * @param callable $middleware Middleware function
+     * @param string   $name       Name to register for this middleware.
+     */
+    public function push(callable $middleware, $name = '')
+    {
+        $this->stack[] = [$middleware, $name];
+        $this->cached = null;
+    }
+
+    /**
+     * Add a middleware before another middleware by name.
+     *
+     * @param string   $findName   Middleware to find
+     * @param callable $middleware Middleware function
+     * @param string   $withName   Name to register for this middleware.
+     */
+    public function before($findName, callable $middleware, $withName = '')
+    {
+        $this->splice($findName, $withName, $middleware, true);
+    }
+
+    /**
+     * Add a middleware after another middleware by name.
+     *
+     * @param string   $findName   Middleware to find
+     * @param callable $middleware Middleware function
+     * @param string   $withName   Name to register for this middleware.
+     */
+    public function after($findName, callable $middleware, $withName = '')
+    {
+        $this->splice($findName, $withName, $middleware, false);
+    }
+
+    /**
+     * Remove a middleware by instance or name from the stack.
+     *
+     * @param callable|string $remove Middleware to remove by instance or name.
+     */
+    public function remove($remove)
+    {
+        $this->cached = null;
+        $idx = is_callable($remove) ? 0 : 1;
+        $this->stack = array_values(array_filter(
+            $this->stack,
+            function ($tuple) use ($idx, $remove) {
+                return $tuple[$idx] !== $remove;
+            }
+        ));
+    }
+
+    /**
+     * Compose the middleware and handler into a single callable function.
+     *
+     * @return callable
+     */
+    public function resolve()
+    {
+        if (!$this->cached) {
+            if (!($prev = $this->handler)) {
+                throw new \LogicException('No handler has been specified');
+            }
+
+            foreach (array_reverse($this->stack) as $fn) {
+                $prev = $fn[0]($prev);
+            }
+
+            $this->cached = $prev;
+        }
+
+        return $this->cached;
+    }
+
+    /**
+     * @param $name
+     * @return int
+     */
+    private function findByName($name)
+    {
+        foreach ($this->stack as $k => $v) {
+            if ($v[1] === $name) {
+                return $k;
+            }
+        }
+
+        throw new \InvalidArgumentException("Middleware not found: $name");
+    }
+
+    /**
+     * Splices a function into the middleware list at a specific position.
+     *
+     * @param          $findName
+     * @param          $withName
+     * @param callable $middleware
+     * @param          $before
+     */
+    private function splice($findName, $withName, callable $middleware, $before)
+    {
+        $this->cached = null;
+        $idx = $this->findByName($findName);
+        $tuple = [$middleware, $withName];
+
+        if ($before) {
+            if ($idx === 0) {
+                array_unshift($this->stack, $tuple);
+            } else {
+                $replacement = [$tuple, $this->stack[$idx]];
+                array_splice($this->stack, $idx, 1, $replacement);
+            }
+        } elseif ($idx === count($this->stack) - 1) {
+            $this->stack[] = $tuple;
+        } else {
+            $replacement = [$this->stack[$idx], $tuple];
+            array_splice($this->stack, $idx, 1, $replacement);
+        }
+    }
+
+    /**
+     * Provides a debug string for a given callable.
+     *
+     * @param array|callable $fn Function to write as a string.
+     *
+     * @return string
+     */
+    private function debugCallable($fn)
+    {
+        if (is_string($fn)) {
+            return "callable({$fn})";
+        }
+
+        if (is_array($fn)) {
+            return is_string($fn[0])
+                ? "callable({$fn[0]}::{$fn[1]})"
+                : "callable(['" . get_class($fn[0]) . "', '{$fn[1]}'])";
+        }
+
+        return 'callable(' . spl_object_hash($fn) . ')';
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/MessageFormatter.php b/vendor/guzzlehttp/guzzle/src/MessageFormatter.php
new file mode 100644
index 00000000000..663ac739163
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/MessageFormatter.php
@@ -0,0 +1,180 @@
+<?php
+namespace GuzzleHttp;
+
+use Psr\Http\Message\MessageInterface;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Formats log messages using variable substitutions for requests, responses,
+ * and other transactional data.
+ *
+ * The following variable substitutions are supported:
+ *
+ * - {request}:        Full HTTP request message
+ * - {response}:       Full HTTP response message
+ * - {ts}:             ISO 8601 date in GMT
+ * - {date_iso_8601}   ISO 8601 date in GMT
+ * - {date_common_log} Apache common log date using the configured timezone.
+ * - {host}:           Host of the request
+ * - {method}:         Method of the request
+ * - {uri}:            URI of the request
+ * - {version}:        Protocol version
+ * - {target}:         Request target of the request (path + query + fragment)
+ * - {hostname}:       Hostname of the machine that sent the request
+ * - {code}:           Status code of the response (if available)
+ * - {phrase}:         Reason phrase of the response  (if available)
+ * - {error}:          Any error messages (if available)
+ * - {req_header_*}:   Replace `*` with the lowercased name of a request header to add to the message
+ * - {res_header_*}:   Replace `*` with the lowercased name of a response header to add to the message
+ * - {req_headers}:    Request headers
+ * - {res_headers}:    Response headers
+ * - {req_body}:       Request body
+ * - {res_body}:       Response body
+ */
+class MessageFormatter
+{
+    /**
+     * Apache Common Log Format.
+     * @link http://httpd.apache.org/docs/2.4/logs.html#common
+     * @var string
+     */
+    const CLF = "{hostname} {req_header_User-Agent} - [{date_common_log}] \"{method} {target} HTTP/{version}\" {code} {res_header_Content-Length}";
+    const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}";
+    const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}';
+
+    /** @var string Template used to format log messages */
+    private $template;
+
+    /**
+     * @param string $template Log message template
+     */
+    public function __construct($template = self::CLF)
+    {
+        $this->template = $template ?: self::CLF;
+    }
+
+    /**
+     * Returns a formatted message string.
+     *
+     * @param RequestInterface  $request  Request that was sent
+     * @param ResponseInterface $response Response that was received
+     * @param \Exception        $error    Exception that was received
+     *
+     * @return string
+     */
+    public function format(
+        RequestInterface $request,
+        ResponseInterface $response = null,
+        \Exception $error = null
+    ) {
+        $cache = [];
+
+        return preg_replace_callback(
+            '/{\s*([A-Za-z_\-\.0-9]+)\s*}/',
+            function (array $matches) use ($request, $response, $error, &$cache) {
+                if (isset($cache[$matches[1]])) {
+                    return $cache[$matches[1]];
+                }
+
+                $result = '';
+                switch ($matches[1]) {
+                    case 'request':
+                        $result = Psr7\str($request);
+                        break;
+                    case 'response':
+                        $result = $response ? Psr7\str($response) : '';
+                        break;
+                    case 'req_headers':
+                        $result = trim($request->getMethod()
+                                . ' ' . $request->getRequestTarget())
+                            . ' HTTP/' . $request->getProtocolVersion() . "\r\n"
+                            . $this->headers($request);
+                        break;
+                    case 'res_headers':
+                        $result = $response ?
+                            sprintf(
+                                'HTTP/%s %d %s',
+                                $response->getProtocolVersion(),
+                                $response->getStatusCode(),
+                                $response->getReasonPhrase()
+                            ) . "\r\n" . $this->headers($response)
+                            : 'NULL';
+                        break;
+                    case 'req_body':
+                        $result = $request->getBody();
+                        break;
+                    case 'res_body':
+                        $result = $response ? $response->getBody() : 'NULL';
+                        break;
+                    case 'ts':
+                    case 'date_iso_8601':
+                        $result = gmdate('c');
+                        break;
+                    case 'date_common_log':
+                        $result = date('d/M/Y:H:i:s O');
+                        break;
+                    case 'method':
+                        $result = $request->getMethod();
+                        break;
+                    case 'version':
+                        $result = $request->getProtocolVersion();
+                        break;
+                    case 'uri':
+                    case 'url':
+                        $result = $request->getUri();
+                        break;
+                    case 'target':
+                        $result = $request->getRequestTarget();
+                        break;
+                    case 'req_version':
+                        $result = $request->getProtocolVersion();
+                        break;
+                    case 'res_version':
+                        $result = $response
+                            ? $response->getProtocolVersion()
+                            : 'NULL';
+                        break;
+                    case 'host':
+                        $result = $request->getHeaderLine('Host');
+                        break;
+                    case 'hostname':
+                        $result = gethostname();
+                        break;
+                    case 'code':
+                        $result = $response ? $response->getStatusCode() : 'NULL';
+                        break;
+                    case 'phrase':
+                        $result = $response ? $response->getReasonPhrase() : 'NULL';
+                        break;
+                    case 'error':
+                        $result = $error ? $error->getMessage() : 'NULL';
+                        break;
+                    default:
+                        // handle prefixed dynamic headers
+                        if (strpos($matches[1], 'req_header_') === 0) {
+                            $result = $request->getHeaderLine(substr($matches[1], 11));
+                        } elseif (strpos($matches[1], 'res_header_') === 0) {
+                            $result = $response
+                                ? $response->getHeaderLine(substr($matches[1], 11))
+                                : 'NULL';
+                        }
+                }
+
+                $cache[$matches[1]] = $result;
+                return $result;
+            },
+            $this->template
+        );
+    }
+
+    private function headers(MessageInterface $message)
+    {
+        $result = '';
+        foreach ($message->getHeaders() as $name => $values) {
+            $result .= $name . ': ' . implode(', ', $values) . "\r\n";
+        }
+
+        return trim($result);
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/Middleware.php b/vendor/guzzlehttp/guzzle/src/Middleware.php
new file mode 100644
index 00000000000..d4ad75c94f3
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Middleware.php
@@ -0,0 +1,255 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Cookie\CookieJarInterface;
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\Promise\RejectedPromise;
+use GuzzleHttp\Psr7;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Log\LoggerInterface;
+use Psr\Log\LogLevel;
+
+/**
+ * Functions used to create and wrap handlers with handler middleware.
+ */
+final class Middleware
+{
+    /**
+     * Middleware that adds cookies to requests.
+     *
+     * The options array must be set to a CookieJarInterface in order to use
+     * cookies. This is typically handled for you by a client.
+     *
+     * @return callable Returns a function that accepts the next handler.
+     */
+    public static function cookies()
+    {
+        return function (callable $handler) {
+            return function ($request, array $options) use ($handler) {
+                if (empty($options['cookies'])) {
+                    return $handler($request, $options);
+                } elseif (!($options['cookies'] instanceof CookieJarInterface)) {
+                    throw new \InvalidArgumentException('cookies must be an instance of GuzzleHttp\Cookie\CookieJarInterface');
+                }
+                $cookieJar = $options['cookies'];
+                $request = $cookieJar->withCookieHeader($request);
+                return $handler($request, $options)
+                    ->then(
+                        function ($response) use ($cookieJar, $request) {
+                            $cookieJar->extractCookies($request, $response);
+                            return $response;
+                        }
+                );
+            };
+        };
+    }
+
+    /**
+     * Middleware that throws exceptions for 4xx or 5xx responses when the
+     * "http_error" request option is set to true.
+     *
+     * @return callable Returns a function that accepts the next handler.
+     */
+    public static function httpErrors()
+    {
+        return function (callable $handler) {
+            return function ($request, array $options) use ($handler) {
+                if (empty($options['http_errors'])) {
+                    return $handler($request, $options);
+                }
+                return $handler($request, $options)->then(
+                    function (ResponseInterface $response) use ($request, $handler) {
+                        $code = $response->getStatusCode();
+                        if ($code < 400) {
+                            return $response;
+                        }
+                        throw RequestException::create($request, $response);
+                    }
+                );
+            };
+        };
+    }
+
+    /**
+     * Middleware that pushes history data to an ArrayAccess container.
+     *
+     * @param array|\ArrayAccess $container Container to hold the history (by reference).
+     *
+     * @return callable Returns a function that accepts the next handler.
+     * @throws \InvalidArgumentException if container is not an array or ArrayAccess.
+     */
+    public static function history(&$container)
+    {
+        if (!is_array($container) && !$container instanceof \ArrayAccess) {
+            throw new \InvalidArgumentException('history container must be an array or object implementing ArrayAccess');
+        }
+
+        return function (callable $handler) use (&$container) {
+            return function ($request, array $options) use ($handler, &$container) {
+                return $handler($request, $options)->then(
+                    function ($value) use ($request, &$container, $options) {
+                        $container[] = [
+                            'request'  => $request,
+                            'response' => $value,
+                            'error'    => null,
+                            'options'  => $options
+                        ];
+                        return $value;
+                    },
+                    function ($reason) use ($request, &$container, $options) {
+                        $container[] = [
+                            'request'  => $request,
+                            'response' => null,
+                            'error'    => $reason,
+                            'options'  => $options
+                        ];
+                        return \GuzzleHttp\Promise\rejection_for($reason);
+                    }
+                );
+            };
+        };
+    }
+
+    /**
+     * Middleware that invokes a callback before and after sending a request.
+     *
+     * The provided listener cannot modify or alter the response. It simply
+     * "taps" into the chain to be notified before returning the promise. The
+     * before listener accepts a request and options array, and the after
+     * listener accepts a request, options array, and response promise.
+     *
+     * @param callable $before Function to invoke before forwarding the request.
+     * @param callable $after  Function invoked after forwarding.
+     *
+     * @return callable Returns a function that accepts the next handler.
+     */
+    public static function tap(callable $before = null, callable $after = null)
+    {
+        return function (callable $handler) use ($before, $after) {
+            return function ($request, array $options) use ($handler, $before, $after) {
+                if ($before) {
+                    $before($request, $options);
+                }
+                $response = $handler($request, $options);
+                if ($after) {
+                    $after($request, $options, $response);
+                }
+                return $response;
+            };
+        };
+    }
+
+    /**
+     * Middleware that handles request redirects.
+     *
+     * @return callable Returns a function that accepts the next handler.
+     */
+    public static function redirect()
+    {
+        return function (callable $handler) {
+            return new RedirectMiddleware($handler);
+        };
+    }
+
+    /**
+     * Middleware that retries requests based on the boolean result of
+     * invoking the provided "decider" function.
+     *
+     * If no delay function is provided, a simple implementation of exponential
+     * backoff will be utilized.
+     *
+     * @param callable $decider Function that accepts the number of retries,
+     *                          a request, [response], and [exception] and
+     *                          returns true if the request is to be retried.
+     * @param callable $delay   Function that accepts the number of retries and
+     *                          returns the number of milliseconds to delay.
+     *
+     * @return callable Returns a function that accepts the next handler.
+     */
+    public static function retry(callable $decider, callable $delay = null)
+    {
+        return function (callable $handler) use ($decider, $delay) {
+            return new RetryMiddleware($decider, $handler, $delay);
+        };
+    }
+
+    /**
+     * Middleware that logs requests, responses, and errors using a message
+     * formatter.
+     *
+     * @param LoggerInterface  $logger Logs messages.
+     * @param MessageFormatter $formatter Formatter used to create message strings.
+     * @param string           $logLevel Level at which to log requests.
+     *
+     * @return callable Returns a function that accepts the next handler.
+     */
+    public static function log(LoggerInterface $logger, MessageFormatter $formatter, $logLevel = LogLevel::INFO)
+    {
+        return function (callable $handler) use ($logger, $formatter, $logLevel) {
+            return function ($request, array $options) use ($handler, $logger, $formatter, $logLevel) {
+                return $handler($request, $options)->then(
+                    function ($response) use ($logger, $request, $formatter, $logLevel) {
+                        $message = $formatter->format($request, $response);
+                        $logger->log($logLevel, $message);
+                        return $response;
+                    },
+                    function ($reason) use ($logger, $request, $formatter) {
+                        $response = $reason instanceof RequestException
+                            ? $reason->getResponse()
+                            : null;
+                        $message = $formatter->format($request, $response, $reason);
+                        $logger->notice($message);
+                        return \GuzzleHttp\Promise\rejection_for($reason);
+                    }
+                );
+            };
+        };
+    }
+
+    /**
+     * This middleware adds a default content-type if possible, a default
+     * content-length or transfer-encoding header, and the expect header.
+     *
+     * @return callable
+     */
+    public static function prepareBody()
+    {
+        return function (callable $handler) {
+            return new PrepareBodyMiddleware($handler);
+        };
+    }
+
+    /**
+     * Middleware that applies a map function to the request before passing to
+     * the next handler.
+     *
+     * @param callable $fn Function that accepts a RequestInterface and returns
+     *                     a RequestInterface.
+     * @return callable
+     */
+    public static function mapRequest(callable $fn)
+    {
+        return function (callable $handler) use ($fn) {
+            return function ($request, array $options) use ($handler, $fn) {
+                return $handler($fn($request), $options);
+            };
+        };
+    }
+
+    /**
+     * Middleware that applies a map function to the resolved promise's
+     * response.
+     *
+     * @param callable $fn Function that accepts a ResponseInterface and
+     *                     returns a ResponseInterface.
+     * @return callable
+     */
+    public static function mapResponse(callable $fn)
+    {
+        return function (callable $handler) use ($fn) {
+            return function ($request, array $options) use ($handler, $fn) {
+                return $handler($request, $options)->then($fn);
+            };
+        };
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/Pool.php b/vendor/guzzlehttp/guzzle/src/Pool.php
new file mode 100644
index 00000000000..8f1be33cd39
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/Pool.php
@@ -0,0 +1,123 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Promise\PromisorInterface;
+use Psr\Http\Message\RequestInterface;
+use GuzzleHttp\Promise\EachPromise;
+
+/**
+ * Sends and iterator of requests concurrently using a capped pool size.
+ *
+ * The pool will read from an iterator until it is cancelled or until the
+ * iterator is consumed. When a request is yielded, the request is sent after
+ * applying the "request_options" request options (if provided in the ctor).
+ *
+ * When a function is yielded by the iterator, the function is provided the
+ * "request_options" array that should be merged on top of any existing
+ * options, and the function MUST then return a wait-able promise.
+ */
+class Pool implements PromisorInterface
+{
+    /** @var EachPromise */
+    private $each;
+
+    /**
+     * @param ClientInterface $client   Client used to send the requests.
+     * @param array|\Iterator $requests Requests or functions that return
+     *                                  requests to send concurrently.
+     * @param array           $config   Associative array of options
+     *     - concurrency: (int) Maximum number of requests to send concurrently
+     *     - options: Array of request options to apply to each request.
+     *     - fulfilled: (callable) Function to invoke when a request completes.
+     *     - rejected: (callable) Function to invoke when a request is rejected.
+     */
+    public function __construct(
+        ClientInterface $client,
+        $requests,
+        array $config = []
+    ) {
+        // Backwards compatibility.
+        if (isset($config['pool_size'])) {
+            $config['concurrency'] = $config['pool_size'];
+        } elseif (!isset($config['concurrency'])) {
+            $config['concurrency'] = 25;
+        }
+
+        if (isset($config['options'])) {
+            $opts = $config['options'];
+            unset($config['options']);
+        } else {
+            $opts = [];
+        }
+
+        $iterable = \GuzzleHttp\Promise\iter_for($requests);
+        $requests = function () use ($iterable, $client, $opts) {
+            foreach ($iterable as $key => $rfn) {
+                if ($rfn instanceof RequestInterface) {
+                    yield $key => $client->sendAsync($rfn, $opts);
+                } elseif (is_callable($rfn)) {
+                    yield $key => $rfn($opts);
+                } else {
+                    throw new \InvalidArgumentException('Each value yielded by '
+                        . 'the iterator must be a Psr7\Http\Message\RequestInterface '
+                        . 'or a callable that returns a promise that fulfills '
+                        . 'with a Psr7\Message\Http\ResponseInterface object.');
+                }
+            }
+        };
+
+        $this->each = new EachPromise($requests(), $config);
+    }
+
+    public function promise()
+    {
+        return $this->each->promise();
+    }
+
+    /**
+     * Sends multiple requests concurrently and returns an array of responses
+     * and exceptions that uses the same ordering as the provided requests.
+     *
+     * IMPORTANT: This method keeps every request and response in memory, and
+     * as such, is NOT recommended when sending a large number or an
+     * indeterminate number of requests concurrently.
+     *
+     * @param ClientInterface $client   Client used to send the requests
+     * @param array|\Iterator $requests Requests to send concurrently.
+     * @param array           $options  Passes through the options available in
+     *                                  {@see GuzzleHttp\Pool::__construct}
+     *
+     * @return array Returns an array containing the response or an exception
+     *               in the same order that the requests were sent.
+     * @throws \InvalidArgumentException if the event format is incorrect.
+     */
+    public static function batch(
+        ClientInterface $client,
+        $requests,
+        array $options = []
+    ) {
+        $res = [];
+        self::cmpCallback($options, 'fulfilled', $res);
+        self::cmpCallback($options, 'rejected', $res);
+        $pool = new static($client, $requests, $options);
+        $pool->promise()->wait();
+        ksort($res);
+
+        return $res;
+    }
+
+    private static function cmpCallback(array &$options, $name, array &$results)
+    {
+        if (!isset($options[$name])) {
+            $options[$name] = function ($v, $k) use (&$results) {
+                $results[$k] = $v;
+            };
+        } else {
+            $currentFn = $options[$name];
+            $options[$name] = function ($v, $k) use (&$results, $currentFn) {
+                $currentFn($v, $k);
+                $results[$k] = $v;
+            };
+        }
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php b/vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php
new file mode 100644
index 00000000000..2eb95f9b2d3
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php
@@ -0,0 +1,106 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Promise\PromiseInterface;
+use GuzzleHttp\Psr7;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Prepares requests that contain a body, adding the Content-Length,
+ * Content-Type, and Expect headers.
+ */
+class PrepareBodyMiddleware
+{
+    /** @var callable  */
+    private $nextHandler;
+
+    /**
+     * @param callable $nextHandler Next handler to invoke.
+     */
+    public function __construct(callable $nextHandler)
+    {
+        $this->nextHandler = $nextHandler;
+    }
+
+    /**
+     * @param RequestInterface $request
+     * @param array            $options
+     *
+     * @return PromiseInterface
+     */
+    public function __invoke(RequestInterface $request, array $options)
+    {
+        $fn = $this->nextHandler;
+
+        // Don't do anything if the request has no body.
+        if ($request->getBody()->getSize() === 0) {
+            return $fn($request, $options);
+        }
+
+        $modify = [];
+
+        // Add a default content-type if possible.
+        if (!$request->hasHeader('Content-Type')) {
+            if ($uri = $request->getBody()->getMetadata('uri')) {
+                if ($type = Psr7\mimetype_from_filename($uri)) {
+                    $modify['set_headers']['Content-Type'] = $type;
+                }
+            }
+        }
+
+        // Add a default content-length or transfer-encoding header.
+        if (!$request->hasHeader('Content-Length')
+            && !$request->hasHeader('Transfer-Encoding')
+        ) {
+            $size = $request->getBody()->getSize();
+            if ($size !== null) {
+                $modify['set_headers']['Content-Length'] = $size;
+            } else {
+                $modify['set_headers']['Transfer-Encoding'] = 'chunked';
+            }
+        }
+
+        // Add the expect header if needed.
+        $this->addExpectHeader($request, $options, $modify);
+
+        return $fn(Psr7\modify_request($request, $modify), $options);
+    }
+
+    private function addExpectHeader(
+        RequestInterface $request,
+        array $options,
+        array &$modify
+    ) {
+        // Determine if the Expect header should be used
+        if ($request->hasHeader('Expect')) {
+            return;
+        }
+
+        $expect = isset($options['expect']) ? $options['expect'] : null;
+
+        // Return if disabled or if you're not using HTTP/1.1 or HTTP/2.0
+        if ($expect === false || $request->getProtocolVersion() < 1.1) {
+            return;
+        }
+
+        // The expect header is unconditionally enabled
+        if ($expect === true) {
+            $modify['set_headers']['Expect'] = '100-Continue';
+            return;
+        }
+
+        // By default, send the expect header when the payload is > 1mb
+        if ($expect === null) {
+            $expect = 1048576;
+        }
+
+        // Always add if the body cannot be rewound, the size cannot be
+        // determined, or the size is greater than the cutoff threshold
+        $body = $request->getBody();
+        $size = $body->getSize();
+
+        if ($size === null || $size >= (int) $expect || !$body->isSeekable()) {
+            $modify['set_headers']['Expect'] = '100-Continue';
+        }
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php b/vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php
new file mode 100644
index 00000000000..131b77179aa
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php
@@ -0,0 +1,237 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Exception\BadResponseException;
+use GuzzleHttp\Exception\TooManyRedirectsException;
+use GuzzleHttp\Promise\PromiseInterface;
+use GuzzleHttp\Psr7;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\UriInterface;
+
+/**
+ * Request redirect middleware.
+ *
+ * Apply this middleware like other middleware using
+ * {@see GuzzleHttp\Middleware::redirect()}.
+ */
+class RedirectMiddleware
+{
+    const HISTORY_HEADER = 'X-Guzzle-Redirect-History';
+
+    const STATUS_HISTORY_HEADER = 'X-Guzzle-Redirect-Status-History';
+
+    public static $defaultSettings = [
+        'max'             => 5,
+        'protocols'       => ['http', 'https'],
+        'strict'          => false,
+        'referer'         => false,
+        'track_redirects' => false,
+    ];
+
+    /** @var callable  */
+    private $nextHandler;
+
+    /**
+     * @param callable $nextHandler Next handler to invoke.
+     */
+    public function __construct(callable $nextHandler)
+    {
+        $this->nextHandler = $nextHandler;
+    }
+
+    /**
+     * @param RequestInterface $request
+     * @param array            $options
+     *
+     * @return PromiseInterface
+     */
+    public function __invoke(RequestInterface $request, array $options)
+    {
+        $fn = $this->nextHandler;
+
+        if (empty($options['allow_redirects'])) {
+            return $fn($request, $options);
+        }
+
+        if ($options['allow_redirects'] === true) {
+            $options['allow_redirects'] = self::$defaultSettings;
+        } elseif (!is_array($options['allow_redirects'])) {
+            throw new \InvalidArgumentException('allow_redirects must be true, false, or array');
+        } else {
+            // Merge the default settings with the provided settings
+            $options['allow_redirects'] += self::$defaultSettings;
+        }
+
+        if (empty($options['allow_redirects']['max'])) {
+            return $fn($request, $options);
+        }
+
+        return $fn($request, $options)
+            ->then(function (ResponseInterface $response) use ($request, $options) {
+                return $this->checkRedirect($request, $options, $response);
+            });
+    }
+
+    /**
+     * @param RequestInterface  $request
+     * @param array             $options
+     * @param ResponseInterface|PromiseInterface $response
+     *
+     * @return ResponseInterface|PromiseInterface
+     */
+    public function checkRedirect(
+        RequestInterface $request,
+        array $options,
+        ResponseInterface $response
+    ) {
+        if (substr($response->getStatusCode(), 0, 1) != '3'
+            || !$response->hasHeader('Location')
+        ) {
+            return $response;
+        }
+
+        $this->guardMax($request, $options);
+        $nextRequest = $this->modifyRequest($request, $options, $response);
+
+        if (isset($options['allow_redirects']['on_redirect'])) {
+            call_user_func(
+                $options['allow_redirects']['on_redirect'],
+                $request,
+                $response,
+                $nextRequest->getUri()
+            );
+        }
+
+        /** @var PromiseInterface|ResponseInterface $promise */
+        $promise = $this($nextRequest, $options);
+
+        // Add headers to be able to track history of redirects.
+        if (!empty($options['allow_redirects']['track_redirects'])) {
+            return $this->withTracking(
+                $promise,
+                (string) $nextRequest->getUri(),
+                $response->getStatusCode()
+            );
+        }
+
+        return $promise;
+    }
+
+    private function withTracking(PromiseInterface $promise, $uri, $statusCode)
+    {
+        return $promise->then(
+            function (ResponseInterface $response) use ($uri, $statusCode) {
+                // Note that we are pushing to the front of the list as this
+                // would be an earlier response than what is currently present
+                // in the history header.
+                $historyHeader = $response->getHeader(self::HISTORY_HEADER);
+                $statusHeader = $response->getHeader(self::STATUS_HISTORY_HEADER);
+                array_unshift($historyHeader, $uri);
+                array_unshift($statusHeader, $statusCode);
+                return $response->withHeader(self::HISTORY_HEADER, $historyHeader)
+                                ->withHeader(self::STATUS_HISTORY_HEADER, $statusHeader);
+            }
+        );
+    }
+
+    private function guardMax(RequestInterface $request, array &$options)
+    {
+        $current = isset($options['__redirect_count'])
+            ? $options['__redirect_count']
+            : 0;
+        $options['__redirect_count'] = $current + 1;
+        $max = $options['allow_redirects']['max'];
+
+        if ($options['__redirect_count'] > $max) {
+            throw new TooManyRedirectsException(
+                "Will not follow more than {$max} redirects",
+                $request
+            );
+        }
+    }
+
+    /**
+     * @param RequestInterface  $request
+     * @param array             $options
+     * @param ResponseInterface $response
+     *
+     * @return RequestInterface
+     */
+    public function modifyRequest(
+        RequestInterface $request,
+        array $options,
+        ResponseInterface $response
+    ) {
+        // Request modifications to apply.
+        $modify = [];
+        $protocols = $options['allow_redirects']['protocols'];
+
+        // Use a GET request if this is an entity enclosing request and we are
+        // not forcing RFC compliance, but rather emulating what all browsers
+        // would do.
+        $statusCode = $response->getStatusCode();
+        if ($statusCode == 303 ||
+            ($statusCode <= 302 && $request->getBody() && !$options['allow_redirects']['strict'])
+        ) {
+            $modify['method'] = 'GET';
+            $modify['body'] = '';
+        }
+
+        $modify['uri'] = $this->redirectUri($request, $response, $protocols);
+        Psr7\rewind_body($request);
+
+        // Add the Referer header if it is told to do so and only
+        // add the header if we are not redirecting from https to http.
+        if ($options['allow_redirects']['referer']
+            && $modify['uri']->getScheme() === $request->getUri()->getScheme()
+        ) {
+            $uri = $request->getUri()->withUserInfo('', '');
+            $modify['set_headers']['Referer'] = (string) $uri;
+        } else {
+            $modify['remove_headers'][] = 'Referer';
+        }
+
+        // Remove Authorization header if host is different.
+        if ($request->getUri()->getHost() !== $modify['uri']->getHost()) {
+            $modify['remove_headers'][] = 'Authorization';
+        }
+
+        return Psr7\modify_request($request, $modify);
+    }
+
+    /**
+     * Set the appropriate URL on the request based on the location header
+     *
+     * @param RequestInterface  $request
+     * @param ResponseInterface $response
+     * @param array             $protocols
+     *
+     * @return UriInterface
+     */
+    private function redirectUri(
+        RequestInterface $request,
+        ResponseInterface $response,
+        array $protocols
+    ) {
+        $location = Psr7\UriResolver::resolve(
+            $request->getUri(),
+            new Psr7\Uri($response->getHeaderLine('Location'))
+        );
+
+        // Ensure that the redirect URI is allowed based on the protocols.
+        if (!in_array($location->getScheme(), $protocols)) {
+            throw new BadResponseException(
+                sprintf(
+                    'Redirect URI, %s, does not use one of the allowed redirect protocols: %s',
+                    $location,
+                    implode(', ', $protocols)
+                ),
+                $request,
+                $response
+            );
+        }
+
+        return $location;
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/RequestOptions.php b/vendor/guzzlehttp/guzzle/src/RequestOptions.php
new file mode 100644
index 00000000000..c6aacfb1578
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/RequestOptions.php
@@ -0,0 +1,255 @@
+<?php
+namespace GuzzleHttp;
+
+/**
+ * This class contains a list of built-in Guzzle request options.
+ *
+ * More documentation for each option can be found at http://guzzlephp.org/.
+ *
+ * @link http://docs.guzzlephp.org/en/v6/request-options.html
+ */
+final class RequestOptions
+{
+    /**
+     * allow_redirects: (bool|array) Controls redirect behavior. Pass false
+     * to disable redirects, pass true to enable redirects, pass an
+     * associative to provide custom redirect settings. Defaults to "false".
+     * This option only works if your handler has the RedirectMiddleware. When
+     * passing an associative array, you can provide the following key value
+     * pairs:
+     *
+     * - max: (int, default=5) maximum number of allowed redirects.
+     * - strict: (bool, default=false) Set to true to use strict redirects
+     *   meaning redirect POST requests with POST requests vs. doing what most
+     *   browsers do which is redirect POST requests with GET requests
+     * - referer: (bool, default=true) Set to false to disable the Referer
+     *   header.
+     * - protocols: (array, default=['http', 'https']) Allowed redirect
+     *   protocols.
+     * - on_redirect: (callable) PHP callable that is invoked when a redirect
+     *   is encountered. The callable is invoked with the request, the redirect
+     *   response that was received, and the effective URI. Any return value
+     *   from the on_redirect function is ignored.
+     */
+    const ALLOW_REDIRECTS = 'allow_redirects';
+
+    /**
+     * auth: (array) Pass an array of HTTP authentication parameters to use
+     * with the request. The array must contain the username in index [0],
+     * the password in index [1], and you can optionally provide a built-in
+     * authentication type in index [2]. Pass null to disable authentication
+     * for a request.
+     */
+    const AUTH = 'auth';
+
+    /**
+     * body: (resource|string|null|int|float|StreamInterface|callable|\Iterator)
+     * Body to send in the request.
+     */
+    const BODY = 'body';
+
+    /**
+     * cert: (string|array) Set to a string to specify the path to a file
+     * containing a PEM formatted SSL client side certificate. If a password
+     * is required, then set cert to an array containing the path to the PEM
+     * file in the first array element followed by the certificate password
+     * in the second array element.
+     */
+    const CERT = 'cert';
+
+    /**
+     * cookies: (bool|GuzzleHttp\Cookie\CookieJarInterface, default=false)
+     * Specifies whether or not cookies are used in a request or what cookie
+     * jar to use or what cookies to send. This option only works if your
+     * handler has the `cookie` middleware. Valid values are `false` and
+     * an instance of {@see GuzzleHttp\Cookie\CookieJarInterface}.
+     */
+    const COOKIES = 'cookies';
+
+    /**
+     * connect_timeout: (float, default=0) Float describing the number of
+     * seconds to wait while trying to connect to a server. Use 0 to wait
+     * indefinitely (the default behavior).
+     */
+    const CONNECT_TIMEOUT = 'connect_timeout';
+
+    /**
+     * debug: (bool|resource) Set to true or set to a PHP stream returned by
+     * fopen()  enable debug output with the HTTP handler used to send a
+     * request.
+     */
+    const DEBUG = 'debug';
+
+    /**
+     * decode_content: (bool, default=true) Specify whether or not
+     * Content-Encoding responses (gzip, deflate, etc.) are automatically
+     * decoded.
+     */
+    const DECODE_CONTENT = 'decode_content';
+
+    /**
+     * delay: (int) The amount of time to delay before sending in milliseconds.
+     */
+    const DELAY = 'delay';
+
+    /**
+     * expect: (bool|integer) Controls the behavior of the
+     * "Expect: 100-Continue" header.
+     *
+     * Set to `true` to enable the "Expect: 100-Continue" header for all
+     * requests that sends a body. Set to `false` to disable the
+     * "Expect: 100-Continue" header for all requests. Set to a number so that
+     * the size of the payload must be greater than the number in order to send
+     * the Expect header. Setting to a number will send the Expect header for
+     * all requests in which the size of the payload cannot be determined or
+     * where the body is not rewindable.
+     *
+     * By default, Guzzle will add the "Expect: 100-Continue" header when the
+     * size of the body of a request is greater than 1 MB and a request is
+     * using HTTP/1.1.
+     */
+    const EXPECT = 'expect';
+
+    /**
+     * form_params: (array) Associative array of form field names to values
+     * where each value is a string or array of strings. Sets the Content-Type
+     * header to application/x-www-form-urlencoded when no Content-Type header
+     * is already present.
+     */
+    const FORM_PARAMS = 'form_params';
+
+    /**
+     * headers: (array) Associative array of HTTP headers. Each value MUST be
+     * a string or array of strings.
+     */
+    const HEADERS = 'headers';
+
+    /**
+     * http_errors: (bool, default=true) Set to false to disable exceptions
+     * when a non- successful HTTP response is received. By default,
+     * exceptions will be thrown for 4xx and 5xx responses. This option only
+     * works if your handler has the `httpErrors` middleware.
+     */
+    const HTTP_ERRORS = 'http_errors';
+
+    /**
+     * json: (mixed) Adds JSON data to a request. The provided value is JSON
+     * encoded and a Content-Type header of application/json will be added to
+     * the request if no Content-Type header is already present.
+     */
+    const JSON = 'json';
+
+    /**
+     * multipart: (array) Array of associative arrays, each containing a
+     * required "name" key mapping to the form field, name, a required
+     * "contents" key mapping to a StreamInterface|resource|string, an
+     * optional "headers" associative array of custom headers, and an
+     * optional "filename" key mapping to a string to send as the filename in
+     * the part. If no "filename" key is present, then no "filename" attribute
+     * will be added to the part.
+     */
+    const MULTIPART = 'multipart';
+
+    /**
+     * on_headers: (callable) A callable that is invoked when the HTTP headers
+     * of the response have been received but the body has not yet begun to
+     * download.
+     */
+    const ON_HEADERS = 'on_headers';
+
+    /**
+     * on_stats: (callable) allows you to get access to transfer statistics of
+     * a request and access the lower level transfer details of the handler
+     * associated with your client. ``on_stats`` is a callable that is invoked
+     * when a handler has finished sending a request. The callback is invoked
+     * with transfer statistics about the request, the response received, or
+     * the error encountered. Included in the data is the total amount of time
+     * taken to send the request.
+     */
+    const ON_STATS = 'on_stats';
+
+    /**
+     * progress: (callable) Defines a function to invoke when transfer
+     * progress is made. The function accepts the following positional
+     * arguments: the total number of bytes expected to be downloaded, the
+     * number of bytes downloaded so far, the number of bytes expected to be
+     * uploaded, the number of bytes uploaded so far.
+     */
+    const PROGRESS = 'progress';
+
+    /**
+     * proxy: (string|array) Pass a string to specify an HTTP proxy, or an
+     * array to specify different proxies for different protocols (where the
+     * key is the protocol and the value is a proxy string).
+     */
+    const PROXY = 'proxy';
+
+    /**
+     * query: (array|string) Associative array of query string values to add
+     * to the request. This option uses PHP's http_build_query() to create
+     * the string representation. Pass a string value if you need more
+     * control than what this method provides
+     */
+    const QUERY = 'query';
+
+    /**
+     * sink: (resource|string|StreamInterface) Where the data of the
+     * response is written to. Defaults to a PHP temp stream. Providing a
+     * string will write data to a file by the given name.
+     */
+    const SINK = 'sink';
+
+    /**
+     * synchronous: (bool) Set to true to inform HTTP handlers that you intend
+     * on waiting on the response. This can be useful for optimizations. Note
+     * that a promise is still returned if you are using one of the async
+     * client methods.
+     */
+    const SYNCHRONOUS = 'synchronous';
+
+    /**
+     * ssl_key: (array|string) Specify the path to a file containing a private
+     * SSL key in PEM format. If a password is required, then set to an array
+     * containing the path to the SSL key in the first array element followed
+     * by the password required for the certificate in the second element.
+     */
+    const SSL_KEY = 'ssl_key';
+
+    /**
+     * stream: Set to true to attempt to stream a response rather than
+     * download it all up-front.
+     */
+    const STREAM = 'stream';
+
+    /**
+     * verify: (bool|string, default=true) Describes the SSL certificate
+     * verification behavior of a request. Set to true to enable SSL
+     * certificate verification using the system CA bundle when available
+     * (the default). Set to false to disable certificate verification (this
+     * is insecure!). Set to a string to provide the path to a CA bundle on
+     * disk to enable verification using a custom certificate.
+     */
+    const VERIFY = 'verify';
+
+    /**
+     * timeout: (float, default=0) Float describing the timeout of the
+     * request in seconds. Use 0 to wait indefinitely (the default behavior).
+     */
+    const TIMEOUT = 'timeout';
+
+    /**
+     * read_timeout: (float, default=default_socket_timeout ini setting) Float describing
+     * the body read timeout, for stream requests.
+     */
+    const READ_TIMEOUT = 'read_timeout';
+
+    /**
+     * version: (float) Specifies the HTTP protocol version to attempt to use.
+     */
+    const VERSION = 'version';
+
+    /**
+     * force_ip_resolve: (bool) Force client to use only ipv4 or ipv6 protocol
+     */
+    const FORCE_IP_RESOLVE = 'force_ip_resolve';
+}
diff --git a/vendor/guzzlehttp/guzzle/src/RetryMiddleware.php b/vendor/guzzlehttp/guzzle/src/RetryMiddleware.php
new file mode 100644
index 00000000000..f27090fd197
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/RetryMiddleware.php
@@ -0,0 +1,112 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Promise\PromiseInterface;
+use GuzzleHttp\Promise\RejectedPromise;
+use GuzzleHttp\Psr7;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Middleware that retries requests based on the boolean result of
+ * invoking the provided "decider" function.
+ */
+class RetryMiddleware
+{
+    /** @var callable  */
+    private $nextHandler;
+
+    /** @var callable */
+    private $decider;
+
+    /**
+     * @param callable $decider     Function that accepts the number of retries,
+     *                              a request, [response], and [exception] and
+     *                              returns true if the request is to be
+     *                              retried.
+     * @param callable $nextHandler Next handler to invoke.
+     * @param callable $delay       Function that accepts the number of retries
+     *                              and [response] and returns the number of
+     *                              milliseconds to delay.
+     */
+    public function __construct(
+        callable $decider,
+        callable $nextHandler,
+        callable $delay = null
+    ) {
+        $this->decider = $decider;
+        $this->nextHandler = $nextHandler;
+        $this->delay = $delay ?: __CLASS__ . '::exponentialDelay';
+    }
+
+    /**
+     * Default exponential backoff delay function.
+     *
+     * @param $retries
+     *
+     * @return int
+     */
+    public static function exponentialDelay($retries)
+    {
+        return (int) pow(2, $retries - 1);
+    }
+
+    /**
+     * @param RequestInterface $request
+     * @param array            $options
+     *
+     * @return PromiseInterface
+     */
+    public function __invoke(RequestInterface $request, array $options)
+    {
+        if (!isset($options['retries'])) {
+            $options['retries'] = 0;
+        }
+
+        $fn = $this->nextHandler;
+        return $fn($request, $options)
+            ->then(
+                $this->onFulfilled($request, $options),
+                $this->onRejected($request, $options)
+            );
+    }
+
+    private function onFulfilled(RequestInterface $req, array $options)
+    {
+        return function ($value) use ($req, $options) {
+            if (!call_user_func(
+                $this->decider,
+                $options['retries'],
+                $req,
+                $value,
+                null
+            )) {
+                return $value;
+            }
+            return $this->doRetry($req, $options, $value);
+        };
+    }
+
+    private function onRejected(RequestInterface $req, array $options)
+    {
+        return function ($reason) use ($req, $options) {
+            if (!call_user_func(
+                $this->decider,
+                $options['retries'],
+                $req,
+                null,
+                $reason
+            )) {
+                return \GuzzleHttp\Promise\rejection_for($reason);
+            }
+            return $this->doRetry($req, $options);
+        };
+    }
+
+    private function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null)
+    {
+        $options['delay'] = call_user_func($this->delay, ++$options['retries'], $response);
+
+        return $this($request, $options);
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/TransferStats.php b/vendor/guzzlehttp/guzzle/src/TransferStats.php
new file mode 100644
index 00000000000..15f717e1ea6
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/TransferStats.php
@@ -0,0 +1,126 @@
+<?php
+namespace GuzzleHttp;
+
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\UriInterface;
+
+/**
+ * Represents data at the point after it was transferred either successfully
+ * or after a network error.
+ */
+final class TransferStats
+{
+    private $request;
+    private $response;
+    private $transferTime;
+    private $handlerStats;
+    private $handlerErrorData;
+
+    /**
+     * @param RequestInterface  $request          Request that was sent.
+     * @param ResponseInterface $response         Response received (if any)
+     * @param null              $transferTime     Total handler transfer time.
+     * @param mixed             $handlerErrorData Handler error data.
+     * @param array             $handlerStats     Handler specific stats.
+     */
+    public function __construct(
+        RequestInterface $request,
+        ResponseInterface $response = null,
+        $transferTime = null,
+        $handlerErrorData = null,
+        $handlerStats = []
+    ) {
+        $this->request = $request;
+        $this->response = $response;
+        $this->transferTime = $transferTime;
+        $this->handlerErrorData = $handlerErrorData;
+        $this->handlerStats = $handlerStats;
+    }
+
+    /**
+     * @return RequestInterface
+     */
+    public function getRequest()
+    {
+        return $this->request;
+    }
+
+    /**
+     * Returns the response that was received (if any).
+     *
+     * @return ResponseInterface|null
+     */
+    public function getResponse()
+    {
+        return $this->response;
+    }
+
+    /**
+     * Returns true if a response was received.
+     *
+     * @return bool
+     */
+    public function hasResponse()
+    {
+        return $this->response !== null;
+    }
+
+    /**
+     * Gets handler specific error data.
+     *
+     * This might be an exception, a integer representing an error code, or
+     * anything else. Relying on this value assumes that you know what handler
+     * you are using.
+     *
+     * @return mixed
+     */
+    public function getHandlerErrorData()
+    {
+        return $this->handlerErrorData;
+    }
+
+    /**
+     * Get the effective URI the request was sent to.
+     *
+     * @return UriInterface
+     */
+    public function getEffectiveUri()
+    {
+        return $this->request->getUri();
+    }
+
+    /**
+     * Get the estimated time the request was being transferred by the handler.
+     *
+     * @return float Time in seconds.
+     */
+    public function getTransferTime()
+    {
+        return $this->transferTime;
+    }
+
+    /**
+     * Gets an array of all of the handler specific transfer data.
+     *
+     * @return array
+     */
+    public function getHandlerStats()
+    {
+        return $this->handlerStats;
+    }
+
+    /**
+     * Get a specific handler statistic from the handler by name.
+     *
+     * @param string $stat Handler specific transfer stat to retrieve.
+     *
+     * @return mixed|null
+     */
+    public function getHandlerStat($stat)
+    {
+        return isset($this->handlerStats[$stat])
+            ? $this->handlerStats[$stat]
+            : null;
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/UriTemplate.php b/vendor/guzzlehttp/guzzle/src/UriTemplate.php
new file mode 100644
index 00000000000..96dcfd09cd7
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/UriTemplate.php
@@ -0,0 +1,237 @@
+<?php
+namespace GuzzleHttp;
+
+/**
+ * Expands URI templates. Userland implementation of PECL uri_template.
+ *
+ * @link http://tools.ietf.org/html/rfc6570
+ */
+class UriTemplate
+{
+    /** @var string URI template */
+    private $template;
+
+    /** @var array Variables to use in the template expansion */
+    private $variables;
+
+    /** @var array Hash for quick operator lookups */
+    private static $operatorHash = [
+        ''  => ['prefix' => '',  'joiner' => ',', 'query' => false],
+        '+' => ['prefix' => '',  'joiner' => ',', 'query' => false],
+        '#' => ['prefix' => '#', 'joiner' => ',', 'query' => false],
+        '.' => ['prefix' => '.', 'joiner' => '.', 'query' => false],
+        '/' => ['prefix' => '/', 'joiner' => '/', 'query' => false],
+        ';' => ['prefix' => ';', 'joiner' => ';', 'query' => true],
+        '?' => ['prefix' => '?', 'joiner' => '&', 'query' => true],
+        '&' => ['prefix' => '&', 'joiner' => '&', 'query' => true]
+    ];
+
+    /** @var array Delimiters */
+    private static $delims = [':', '/', '?', '#', '[', ']', '@', '!', '$',
+        '&', '\'', '(', ')', '*', '+', ',', ';', '='];
+
+    /** @var array Percent encoded delimiters */
+    private static $delimsPct = ['%3A', '%2F', '%3F', '%23', '%5B', '%5D',
+        '%40', '%21', '%24', '%26', '%27', '%28', '%29', '%2A', '%2B', '%2C',
+        '%3B', '%3D'];
+
+    public function expand($template, array $variables)
+    {
+        if (false === strpos($template, '{')) {
+            return $template;
+        }
+
+        $this->template = $template;
+        $this->variables = $variables;
+
+        return preg_replace_callback(
+            '/\{([^\}]+)\}/',
+            [$this, 'expandMatch'],
+            $this->template
+        );
+    }
+
+    /**
+     * Parse an expression into parts
+     *
+     * @param string $expression Expression to parse
+     *
+     * @return array Returns an associative array of parts
+     */
+    private function parseExpression($expression)
+    {
+        $result = [];
+
+        if (isset(self::$operatorHash[$expression[0]])) {
+            $result['operator'] = $expression[0];
+            $expression = substr($expression, 1);
+        } else {
+            $result['operator'] = '';
+        }
+
+        foreach (explode(',', $expression) as $value) {
+            $value = trim($value);
+            $varspec = [];
+            if ($colonPos = strpos($value, ':')) {
+                $varspec['value'] = substr($value, 0, $colonPos);
+                $varspec['modifier'] = ':';
+                $varspec['position'] = (int) substr($value, $colonPos + 1);
+            } elseif (substr($value, -1) === '*') {
+                $varspec['modifier'] = '*';
+                $varspec['value'] = substr($value, 0, -1);
+            } else {
+                $varspec['value'] = (string) $value;
+                $varspec['modifier'] = '';
+            }
+            $result['values'][] = $varspec;
+        }
+
+        return $result;
+    }
+
+    /**
+     * Process an expansion
+     *
+     * @param array $matches Matches met in the preg_replace_callback
+     *
+     * @return string Returns the replacement string
+     */
+    private function expandMatch(array $matches)
+    {
+        static $rfc1738to3986 = ['+' => '%20', '%7e' => '~'];
+
+        $replacements = [];
+        $parsed = self::parseExpression($matches[1]);
+        $prefix = self::$operatorHash[$parsed['operator']]['prefix'];
+        $joiner = self::$operatorHash[$parsed['operator']]['joiner'];
+        $useQuery = self::$operatorHash[$parsed['operator']]['query'];
+
+        foreach ($parsed['values'] as $value) {
+            if (!isset($this->variables[$value['value']])) {
+                continue;
+            }
+
+            $variable = $this->variables[$value['value']];
+            $actuallyUseQuery = $useQuery;
+            $expanded = '';
+
+            if (is_array($variable)) {
+                $isAssoc = $this->isAssoc($variable);
+                $kvp = [];
+                foreach ($variable as $key => $var) {
+                    if ($isAssoc) {
+                        $key = rawurlencode($key);
+                        $isNestedArray = is_array($var);
+                    } else {
+                        $isNestedArray = false;
+                    }
+
+                    if (!$isNestedArray) {
+                        $var = rawurlencode($var);
+                        if ($parsed['operator'] === '+' ||
+                            $parsed['operator'] === '#'
+                        ) {
+                            $var = $this->decodeReserved($var);
+                        }
+                    }
+
+                    if ($value['modifier'] === '*') {
+                        if ($isAssoc) {
+                            if ($isNestedArray) {
+                                // Nested arrays must allow for deeply nested
+                                // structures.
+                                $var = strtr(
+                                    http_build_query([$key => $var]),
+                                    $rfc1738to3986
+                                );
+                            } else {
+                                $var = $key . '=' . $var;
+                            }
+                        } elseif ($key > 0 && $actuallyUseQuery) {
+                            $var = $value['value'] . '=' . $var;
+                        }
+                    }
+
+                    $kvp[$key] = $var;
+                }
+
+                if (empty($variable)) {
+                    $actuallyUseQuery = false;
+                } elseif ($value['modifier'] === '*') {
+                    $expanded = implode($joiner, $kvp);
+                    if ($isAssoc) {
+                        // Don't prepend the value name when using the explode
+                        // modifier with an associative array.
+                        $actuallyUseQuery = false;
+                    }
+                } else {
+                    if ($isAssoc) {
+                        // When an associative array is encountered and the
+                        // explode modifier is not set, then the result must be
+                        // a comma separated list of keys followed by their
+                        // respective values.
+                        foreach ($kvp as $k => &$v) {
+                            $v = $k . ',' . $v;
+                        }
+                    }
+                    $expanded = implode(',', $kvp);
+                }
+            } else {
+                if ($value['modifier'] === ':') {
+                    $variable = substr($variable, 0, $value['position']);
+                }
+                $expanded = rawurlencode($variable);
+                if ($parsed['operator'] === '+' || $parsed['operator'] === '#') {
+                    $expanded = $this->decodeReserved($expanded);
+                }
+            }
+
+            if ($actuallyUseQuery) {
+                if (!$expanded && $joiner !== '&') {
+                    $expanded = $value['value'];
+                } else {
+                    $expanded = $value['value'] . '=' . $expanded;
+                }
+            }
+
+            $replacements[] = $expanded;
+        }
+
+        $ret = implode($joiner, $replacements);
+        if ($ret && $prefix) {
+            return $prefix . $ret;
+        }
+
+        return $ret;
+    }
+
+    /**
+     * Determines if an array is associative.
+     *
+     * This makes the assumption that input arrays are sequences or hashes.
+     * This assumption is a tradeoff for accuracy in favor of speed, but it
+     * should work in almost every case where input is supplied for a URI
+     * template.
+     *
+     * @param array $array Array to check
+     *
+     * @return bool
+     */
+    private function isAssoc(array $array)
+    {
+        return $array && array_keys($array)[0] !== 0;
+    }
+
+    /**
+     * Removes percent encoding on reserved characters (used with + and #
+     * modifiers).
+     *
+     * @param string $string String to fix
+     *
+     * @return string
+     */
+    private function decodeReserved($string)
+    {
+        return str_replace(self::$delimsPct, self::$delims, $string);
+    }
+}
diff --git a/vendor/guzzlehttp/guzzle/src/functions.php b/vendor/guzzlehttp/guzzle/src/functions.php
new file mode 100644
index 00000000000..a3ac450db94
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/functions.php
@@ -0,0 +1,333 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Handler\CurlHandler;
+use GuzzleHttp\Handler\CurlMultiHandler;
+use GuzzleHttp\Handler\Proxy;
+use GuzzleHttp\Handler\StreamHandler;
+
+/**
+ * Expands a URI template
+ *
+ * @param string $template  URI template
+ * @param array  $variables Template variables
+ *
+ * @return string
+ */
+function uri_template($template, array $variables)
+{
+    if (extension_loaded('uri_template')) {
+        // @codeCoverageIgnoreStart
+        return \uri_template($template, $variables);
+        // @codeCoverageIgnoreEnd
+    }
+
+    static $uriTemplate;
+    if (!$uriTemplate) {
+        $uriTemplate = new UriTemplate();
+    }
+
+    return $uriTemplate->expand($template, $variables);
+}
+
+/**
+ * Debug function used to describe the provided value type and class.
+ *
+ * @param mixed $input
+ *
+ * @return string Returns a string containing the type of the variable and
+ *                if a class is provided, the class name.
+ */
+function describe_type($input)
+{
+    switch (gettype($input)) {
+        case 'object':
+            return 'object(' . get_class($input) . ')';
+        case 'array':
+            return 'array(' . count($input) . ')';
+        default:
+            ob_start();
+            var_dump($input);
+            // normalize float vs double
+            return str_replace('double(', 'float(', rtrim(ob_get_clean()));
+    }
+}
+
+/**
+ * Parses an array of header lines into an associative array of headers.
+ *
+ * @param array $lines Header lines array of strings in the following
+ *                     format: "Name: Value"
+ * @return array
+ */
+function headers_from_lines($lines)
+{
+    $headers = [];
+
+    foreach ($lines as $line) {
+        $parts = explode(':', $line, 2);
+        $headers[trim($parts[0])][] = isset($parts[1])
+            ? trim($parts[1])
+            : null;
+    }
+
+    return $headers;
+}
+
+/**
+ * Returns a debug stream based on the provided variable.
+ *
+ * @param mixed $value Optional value
+ *
+ * @return resource
+ */
+function debug_resource($value = null)
+{
+    if (is_resource($value)) {
+        return $value;
+    } elseif (defined('STDOUT')) {
+        return STDOUT;
+    }
+
+    return fopen('php://output', 'w');
+}
+
+/**
+ * Chooses and creates a default handler to use based on the environment.
+ *
+ * The returned handler is not wrapped by any default middlewares.
+ *
+ * @throws \RuntimeException if no viable Handler is available.
+ * @return callable Returns the best handler for the given system.
+ */
+function choose_handler()
+{
+    $handler = null;
+    if (function_exists('curl_multi_exec') && function_exists('curl_exec')) {
+        $handler = Proxy::wrapSync(new CurlMultiHandler(), new CurlHandler());
+    } elseif (function_exists('curl_exec')) {
+        $handler = new CurlHandler();
+    } elseif (function_exists('curl_multi_exec')) {
+        $handler = new CurlMultiHandler();
+    }
+
+    if (ini_get('allow_url_fopen')) {
+        $handler = $handler
+            ? Proxy::wrapStreaming($handler, new StreamHandler())
+            : new StreamHandler();
+    } elseif (!$handler) {
+        throw new \RuntimeException('GuzzleHttp requires cURL, the '
+            . 'allow_url_fopen ini setting, or a custom HTTP handler.');
+    }
+
+    return $handler;
+}
+
+/**
+ * Get the default User-Agent string to use with Guzzle
+ *
+ * @return string
+ */
+function default_user_agent()
+{
+    static $defaultAgent = '';
+
+    if (!$defaultAgent) {
+        $defaultAgent = 'GuzzleHttp/' . Client::VERSION;
+        if (extension_loaded('curl') && function_exists('curl_version')) {
+            $defaultAgent .= ' curl/' . \curl_version()['version'];
+        }
+        $defaultAgent .= ' PHP/' . PHP_VERSION;
+    }
+
+    return $defaultAgent;
+}
+
+/**
+ * Returns the default cacert bundle for the current system.
+ *
+ * First, the openssl.cafile and curl.cainfo php.ini settings are checked.
+ * If those settings are not configured, then the common locations for
+ * bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X
+ * and Windows are checked. If any of these file locations are found on
+ * disk, they will be utilized.
+ *
+ * Note: the result of this function is cached for subsequent calls.
+ *
+ * @return string
+ * @throws \RuntimeException if no bundle can be found.
+ */
+function default_ca_bundle()
+{
+    static $cached = null;
+    static $cafiles = [
+        // Red Hat, CentOS, Fedora (provided by the ca-certificates package)
+        '/etc/pki/tls/certs/ca-bundle.crt',
+        // Ubuntu, Debian (provided by the ca-certificates package)
+        '/etc/ssl/certs/ca-certificates.crt',
+        // FreeBSD (provided by the ca_root_nss package)
+        '/usr/local/share/certs/ca-root-nss.crt',
+        // SLES 12 (provided by the ca-certificates package)
+        '/var/lib/ca-certificates/ca-bundle.pem',
+        // OS X provided by homebrew (using the default path)
+        '/usr/local/etc/openssl/cert.pem',
+        // Google app engine
+        '/etc/ca-certificates.crt',
+        // Windows?
+        'C:\\windows\\system32\\curl-ca-bundle.crt',
+        'C:\\windows\\curl-ca-bundle.crt',
+    ];
+
+    if ($cached) {
+        return $cached;
+    }
+
+    if ($ca = ini_get('openssl.cafile')) {
+        return $cached = $ca;
+    }
+
+    if ($ca = ini_get('curl.cainfo')) {
+        return $cached = $ca;
+    }
+
+    foreach ($cafiles as $filename) {
+        if (file_exists($filename)) {
+            return $cached = $filename;
+        }
+    }
+
+    throw new \RuntimeException(<<< EOT
+No system CA bundle could be found in any of the the common system locations.
+PHP versions earlier than 5.6 are not properly configured to use the system's
+CA bundle by default. In order to verify peer certificates, you will need to
+supply the path on disk to a certificate bundle to the 'verify' request
+option: http://docs.guzzlephp.org/en/latest/clients.html#verify. If you do not
+need a specific certificate bundle, then Mozilla provides a commonly used CA
+bundle which can be downloaded here (provided by the maintainer of cURL):
+https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt. Once
+you have a CA bundle available on disk, you can set the 'openssl.cafile' PHP
+ini setting to point to the path to the file, allowing you to omit the 'verify'
+request option. See http://curl.haxx.se/docs/sslcerts.html for more
+information.
+EOT
+    );
+}
+
+/**
+ * Creates an associative array of lowercase header names to the actual
+ * header casing.
+ *
+ * @param array $headers
+ *
+ * @return array
+ */
+function normalize_header_keys(array $headers)
+{
+    $result = [];
+    foreach (array_keys($headers) as $key) {
+        $result[strtolower($key)] = $key;
+    }
+
+    return $result;
+}
+
+/**
+ * Returns true if the provided host matches any of the no proxy areas.
+ *
+ * This method will strip a port from the host if it is present. Each pattern
+ * can be matched with an exact match (e.g., "foo.com" == "foo.com") or a
+ * partial match: (e.g., "foo.com" == "baz.foo.com" and ".foo.com" ==
+ * "baz.foo.com", but ".foo.com" != "foo.com").
+ *
+ * Areas are matched in the following cases:
+ * 1. "*" (without quotes) always matches any hosts.
+ * 2. An exact match.
+ * 3. The area starts with "." and the area is the last part of the host. e.g.
+ *    '.mit.edu' will match any host that ends with '.mit.edu'.
+ *
+ * @param string $host         Host to check against the patterns.
+ * @param array  $noProxyArray An array of host patterns.
+ *
+ * @return bool
+ */
+function is_host_in_noproxy($host, array $noProxyArray)
+{
+    if (strlen($host) === 0) {
+        throw new \InvalidArgumentException('Empty host provided');
+    }
+
+    // Strip port if present.
+    if (strpos($host, ':')) {
+        $host = explode($host, ':', 2)[0];
+    }
+
+    foreach ($noProxyArray as $area) {
+        // Always match on wildcards.
+        if ($area === '*') {
+            return true;
+        } elseif (empty($area)) {
+            // Don't match on empty values.
+            continue;
+        } elseif ($area === $host) {
+            // Exact matches.
+            return true;
+        } else {
+            // Special match if the area when prefixed with ".". Remove any
+            // existing leading "." and add a new leading ".".
+            $area = '.' . ltrim($area, '.');
+            if (substr($host, -(strlen($area))) === $area) {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+/**
+ * Wrapper for json_decode that throws when an error occurs.
+ *
+ * @param string $json    JSON data to parse
+ * @param bool $assoc     When true, returned objects will be converted
+ *                        into associative arrays.
+ * @param int    $depth   User specified recursion depth.
+ * @param int    $options Bitmask of JSON decode options.
+ *
+ * @return mixed
+ * @throws \InvalidArgumentException if the JSON cannot be decoded.
+ * @link http://www.php.net/manual/en/function.json-decode.php
+ */
+function json_decode($json, $assoc = false, $depth = 512, $options = 0)
+{
+    $data = \json_decode($json, $assoc, $depth, $options);
+    if (JSON_ERROR_NONE !== json_last_error()) {
+        throw new \InvalidArgumentException(
+            'json_decode error: ' . json_last_error_msg()
+        );
+    }
+
+    return $data;
+}
+
+/**
+ * Wrapper for JSON encoding that throws when an error occurs.
+ *
+ * @param mixed $value   The value being encoded
+ * @param int    $options JSON encode option bitmask
+ * @param int    $depth   Set the maximum depth. Must be greater than zero.
+ *
+ * @return string
+ * @throws \InvalidArgumentException if the JSON cannot be encoded.
+ * @link http://www.php.net/manual/en/function.json-encode.php
+ */
+function json_encode($value, $options = 0, $depth = 512)
+{
+    $json = \json_encode($value, $options, $depth);
+    if (JSON_ERROR_NONE !== json_last_error()) {
+        throw new \InvalidArgumentException(
+            'json_encode error: ' . json_last_error_msg()
+        );
+    }
+
+    return $json;
+}
diff --git a/vendor/guzzlehttp/guzzle/src/functions_include.php b/vendor/guzzlehttp/guzzle/src/functions_include.php
new file mode 100644
index 00000000000..a93393acc4e
--- /dev/null
+++ b/vendor/guzzlehttp/guzzle/src/functions_include.php
@@ -0,0 +1,6 @@
+<?php
+
+// Don't redefine the functions if included multiple times.
+if (!function_exists('GuzzleHttp\uri_template')) {
+    require __DIR__ . '/functions.php';
+}
diff --git a/vendor/guzzlehttp/promises/CHANGELOG.md b/vendor/guzzlehttp/promises/CHANGELOG.md
new file mode 100644
index 00000000000..551929f6bd5
--- /dev/null
+++ b/vendor/guzzlehttp/promises/CHANGELOG.md
@@ -0,0 +1,65 @@
+# CHANGELOG
+
+
+## 1.3.1 - 2016-12-20
+
+### Fixed
+
+- `wait()` foreign promise compatibility
+
+
+## 1.3.0 - 2016-11-18
+
+### Added
+
+- Adds support for custom task queues.
+
+### Fixed
+
+- Fixed coroutine promise memory leak.
+
+
+## 1.2.0 - 2016-05-18
+
+### Changed
+
+- Update to now catch `\Throwable` on PHP 7+
+
+
+## 1.1.0 - 2016-03-07
+
+### Changed
+
+- Update EachPromise to prevent recurring on a iterator when advancing, as this
+  could trigger fatal generator errors.
+- Update Promise to allow recursive waiting without unwrapping exceptions.
+
+
+## 1.0.3 - 2015-10-15
+
+### Changed
+
+- Update EachPromise to immediately resolve when the underlying promise iterator
+  is empty. Previously, such a promise would throw an exception when its `wait`
+  function was called.
+
+
+## 1.0.2 - 2015-05-15
+
+### Changed
+
+- Conditionally require functions.php.
+
+
+## 1.0.1 - 2015-06-24
+
+### Changed
+
+- Updating EachPromise to call next on the underlying promise iterator as late
+  as possible to ensure that generators that generate new requests based on
+  callbacks are not iterated until after callbacks are invoked.
+
+
+## 1.0.0 - 2015-05-12
+
+- Initial release
diff --git a/vendor/guzzlehttp/promises/LICENSE b/vendor/guzzlehttp/promises/LICENSE
new file mode 100644
index 00000000000..67f91a14c00
--- /dev/null
+++ b/vendor/guzzlehttp/promises/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2015-2016 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
+
+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/vendor/guzzlehttp/promises/Makefile b/vendor/guzzlehttp/promises/Makefile
new file mode 100644
index 00000000000..8d5b3ef95eb
--- /dev/null
+++ b/vendor/guzzlehttp/promises/Makefile
@@ -0,0 +1,13 @@
+all: clean test
+
+test:
+	vendor/bin/phpunit
+
+coverage:
+	vendor/bin/phpunit --coverage-html=artifacts/coverage
+
+view-coverage:
+	open artifacts/coverage/index.html
+
+clean:
+	rm -rf artifacts/*
diff --git a/vendor/guzzlehttp/promises/README.md b/vendor/guzzlehttp/promises/README.md
new file mode 100644
index 00000000000..7b607e28b13
--- /dev/null
+++ b/vendor/guzzlehttp/promises/README.md
@@ -0,0 +1,504 @@
+# Guzzle Promises
+
+[Promises/A+](https://promisesaplus.com/) implementation that handles promise
+chaining and resolution iteratively, allowing for "infinite" promise chaining
+while keeping the stack size constant. Read [this blog post](https://blog.domenic.me/youre-missing-the-point-of-promises/)
+for a general introduction to promises.
+
+- [Features](#features)
+- [Quick start](#quick-start)
+- [Synchronous wait](#synchronous-wait)
+- [Cancellation](#cancellation)
+- [API](#api)
+  - [Promise](#promise)
+  - [FulfilledPromise](#fulfilledpromise)
+  - [RejectedPromise](#rejectedpromise)
+- [Promise interop](#promise-interop)
+- [Implementation notes](#implementation-notes)
+
+
+# Features
+
+- [Promises/A+](https://promisesaplus.com/) implementation.
+- Promise resolution and chaining is handled iteratively, allowing for
+  "infinite" promise chaining.
+- Promises have a synchronous `wait` method.
+- Promises can be cancelled.
+- Works with any object that has a `then` function.
+- C# style async/await coroutine promises using
+  `GuzzleHttp\Promise\coroutine()`.
+
+
+# Quick start
+
+A *promise* represents the eventual result of an asynchronous operation. The
+primary way of interacting with a promise is through its `then` method, which
+registers callbacks to receive either a promise's eventual value or the reason
+why the promise cannot be fulfilled.
+
+
+## Callbacks
+
+Callbacks are registered with the `then` method by providing an optional 
+`$onFulfilled` followed by an optional `$onRejected` function.
+
+
+```php
+use GuzzleHttp\Promise\Promise;
+
+$promise = new Promise();
+$promise->then(
+    // $onFulfilled
+    function ($value) {
+        echo 'The promise was fulfilled.';
+    },
+    // $onRejected
+    function ($reason) {
+        echo 'The promise was rejected.';
+    }
+);
+```
+
+*Resolving* a promise means that you either fulfill a promise with a *value* or
+reject a promise with a *reason*. Resolving a promises triggers callbacks
+registered with the promises's `then` method. These callbacks are triggered
+only once and in the order in which they were added.
+
+
+## Resolving a promise
+
+Promises are fulfilled using the `resolve($value)` method. Resolving a promise
+with any value other than a `GuzzleHttp\Promise\RejectedPromise` will trigger
+all of the onFulfilled callbacks (resolving a promise with a rejected promise
+will reject the promise and trigger the `$onRejected` callbacks).
+
+```php
+use GuzzleHttp\Promise\Promise;
+
+$promise = new Promise();
+$promise
+    ->then(function ($value) {
+        // Return a value and don't break the chain
+        return "Hello, " . $value;
+    })
+    // This then is executed after the first then and receives the value
+    // returned from the first then.
+    ->then(function ($value) {
+        echo $value;
+    });
+
+// Resolving the promise triggers the $onFulfilled callbacks and outputs
+// "Hello, reader".
+$promise->resolve('reader.');
+```
+
+
+## Promise forwarding
+
+Promises can be chained one after the other. Each then in the chain is a new
+promise. The return value of a promise is what's forwarded to the next
+promise in the chain. Returning a promise in a `then` callback will cause the
+subsequent promises in the chain to only be fulfilled when the returned promise
+has been fulfilled. The next promise in the chain will be invoked with the
+resolved value of the promise.
+
+```php
+use GuzzleHttp\Promise\Promise;
+
+$promise = new Promise();
+$nextPromise = new Promise();
+
+$promise
+    ->then(function ($value) use ($nextPromise) {
+        echo $value;
+        return $nextPromise;
+    })
+    ->then(function ($value) {
+        echo $value;
+    });
+
+// Triggers the first callback and outputs "A"
+$promise->resolve('A');
+// Triggers the second callback and outputs "B"
+$nextPromise->resolve('B');
+```
+
+## Promise rejection
+
+When a promise is rejected, the `$onRejected` callbacks are invoked with the
+rejection reason.
+
+```php
+use GuzzleHttp\Promise\Promise;
+
+$promise = new Promise();
+$promise->then(null, function ($reason) {
+    echo $reason;
+});
+
+$promise->reject('Error!');
+// Outputs "Error!"
+```
+
+## Rejection forwarding
+
+If an exception is thrown in an `$onRejected` callback, subsequent
+`$onRejected` callbacks are invoked with the thrown exception as the reason.
+
+```php
+use GuzzleHttp\Promise\Promise;
+
+$promise = new Promise();
+$promise->then(null, function ($reason) {
+    throw new \Exception($reason);
+})->then(null, function ($reason) {
+    assert($reason->getMessage() === 'Error!');
+});
+
+$promise->reject('Error!');
+```
+
+You can also forward a rejection down the promise chain by returning a
+`GuzzleHttp\Promise\RejectedPromise` in either an `$onFulfilled` or
+`$onRejected` callback.
+
+```php
+use GuzzleHttp\Promise\Promise;
+use GuzzleHttp\Promise\RejectedPromise;
+
+$promise = new Promise();
+$promise->then(null, function ($reason) {
+    return new RejectedPromise($reason);
+})->then(null, function ($reason) {
+    assert($reason === 'Error!');
+});
+
+$promise->reject('Error!');
+```
+
+If an exception is not thrown in a `$onRejected` callback and the callback
+does not return a rejected promise, downstream `$onFulfilled` callbacks are
+invoked using the value returned from the `$onRejected` callback.
+
+```php
+use GuzzleHttp\Promise\Promise;
+use GuzzleHttp\Promise\RejectedPromise;
+
+$promise = new Promise();
+$promise
+    ->then(null, function ($reason) {
+        return "It's ok";
+    })
+    ->then(function ($value) {
+        assert($value === "It's ok");
+    });
+
+$promise->reject('Error!');
+```
+
+# Synchronous wait
+
+You can synchronously force promises to complete using a promise's `wait`
+method. When creating a promise, you can provide a wait function that is used
+to synchronously force a promise to complete. When a wait function is invoked
+it is expected to deliver a value to the promise or reject the promise. If the
+wait function does not deliver a value, then an exception is thrown. The wait
+function provided to a promise constructor is invoked when the `wait` function
+of the promise is called.
+
+```php
+$promise = new Promise(function () use (&$promise) {
+    $promise->resolve('foo');
+});
+
+// Calling wait will return the value of the promise.
+echo $promise->wait(); // outputs "foo"
+```
+
+If an exception is encountered while invoking the wait function of a promise,
+the promise is rejected with the exception and the exception is thrown.
+
+```php
+$promise = new Promise(function () use (&$promise) {
+    throw new \Exception('foo');
+});
+
+$promise->wait(); // throws the exception.
+```
+
+Calling `wait` on a promise that has been fulfilled will not trigger the wait
+function. It will simply return the previously resolved value.
+
+```php
+$promise = new Promise(function () { die('this is not called!'); });
+$promise->resolve('foo');
+echo $promise->wait(); // outputs "foo"
+```
+
+Calling `wait` on a promise that has been rejected will throw an exception. If
+the rejection reason is an instance of `\Exception` the reason is thrown.
+Otherwise, a `GuzzleHttp\Promise\RejectionException` is thrown and the reason
+can be obtained by calling the `getReason` method of the exception.
+
+```php
+$promise = new Promise();
+$promise->reject('foo');
+$promise->wait();
+```
+
+> PHP Fatal error:  Uncaught exception 'GuzzleHttp\Promise\RejectionException' with message 'The promise was rejected with value: foo'
+
+
+## Unwrapping a promise
+
+When synchronously waiting on a promise, you are joining the state of the
+promise into the current state of execution (i.e., return the value of the
+promise if it was fulfilled or throw an exception if it was rejected). This is
+called "unwrapping" the promise. Waiting on a promise will by default unwrap
+the promise state.
+
+You can force a promise to resolve and *not* unwrap the state of the promise
+by passing `false` to the first argument of the `wait` function:
+
+```php
+$promise = new Promise();
+$promise->reject('foo');
+// This will not throw an exception. It simply ensures the promise has
+// been resolved.
+$promise->wait(false);
+```
+
+When unwrapping a promise, the resolved value of the promise will be waited
+upon until the unwrapped value is not a promise. This means that if you resolve
+promise A with a promise B and unwrap promise A, the value returned by the
+wait function will be the value delivered to promise B.
+
+**Note**: when you do not unwrap the promise, no value is returned.
+
+
+# Cancellation
+
+You can cancel a promise that has not yet been fulfilled using the `cancel()`
+method of a promise. When creating a promise you can provide an optional
+cancel function that when invoked cancels the action of computing a resolution
+of the promise.
+
+
+# API
+
+
+## Promise
+
+When creating a promise object, you can provide an optional `$waitFn` and
+`$cancelFn`. `$waitFn` is a function that is invoked with no arguments and is
+expected to resolve the promise. `$cancelFn` is a function with no arguments
+that is expected to cancel the computation of a promise. It is invoked when the
+`cancel()` method of a promise is called.
+
+```php
+use GuzzleHttp\Promise\Promise;
+
+$promise = new Promise(
+    function () use (&$promise) {
+        $promise->resolve('waited');
+    },
+    function () {
+        // do something that will cancel the promise computation (e.g., close
+        // a socket, cancel a database query, etc...)
+    }
+);
+
+assert('waited' === $promise->wait());
+```
+
+A promise has the following methods:
+
+- `then(callable $onFulfilled, callable $onRejected) : PromiseInterface`
+  
+  Appends fulfillment and rejection handlers to the promise, and returns a new promise resolving to the return value of the called handler.
+
+- `otherwise(callable $onRejected) : PromiseInterface`
+  
+  Appends a rejection handler callback to the promise, and returns a new promise resolving to the return value of the callback if it is called, or to its original fulfillment value if the promise is instead fulfilled.
+
+- `wait($unwrap = true) : mixed`
+
+  Synchronously waits on the promise to complete.
+  
+  `$unwrap` controls whether or not the value of the promise is returned for a
+  fulfilled promise or if an exception is thrown if the promise is rejected.
+  This is set to `true` by default.
+
+- `cancel()`
+
+  Attempts to cancel the promise if possible. The promise being cancelled and
+  the parent most ancestor that has not yet been resolved will also be
+  cancelled. Any promises waiting on the cancelled promise to resolve will also
+  be cancelled.
+
+- `getState() : string`
+
+  Returns the state of the promise. One of `pending`, `fulfilled`, or
+  `rejected`.
+
+- `resolve($value)`
+
+  Fulfills the promise with the given `$value`.
+
+- `reject($reason)`
+
+  Rejects the promise with the given `$reason`.
+
+
+## FulfilledPromise
+
+A fulfilled promise can be created to represent a promise that has been
+fulfilled.
+
+```php
+use GuzzleHttp\Promise\FulfilledPromise;
+
+$promise = new FulfilledPromise('value');
+
+// Fulfilled callbacks are immediately invoked.
+$promise->then(function ($value) {
+    echo $value;
+});
+```
+
+
+## RejectedPromise
+
+A rejected promise can be created to represent a promise that has been
+rejected.
+
+```php
+use GuzzleHttp\Promise\RejectedPromise;
+
+$promise = new RejectedPromise('Error');
+
+// Rejected callbacks are immediately invoked.
+$promise->then(null, function ($reason) {
+    echo $reason;
+});
+```
+
+
+# Promise interop
+
+This library works with foreign promises that have a `then` method. This means
+you can use Guzzle promises with [React promises](https://github.com/reactphp/promise)
+for example. When a foreign promise is returned inside of a then method
+callback, promise resolution will occur recursively.
+
+```php
+// Create a React promise
+$deferred = new React\Promise\Deferred();
+$reactPromise = $deferred->promise();
+
+// Create a Guzzle promise that is fulfilled with a React promise.
+$guzzlePromise = new \GuzzleHttp\Promise\Promise();
+$guzzlePromise->then(function ($value) use ($reactPromise) {
+    // Do something something with the value...
+    // Return the React promise
+    return $reactPromise;
+});
+```
+
+Please note that wait and cancel chaining is no longer possible when forwarding
+a foreign promise. You will need to wrap a third-party promise with a Guzzle
+promise in order to utilize wait and cancel functions with foreign promises.
+
+
+## Event Loop Integration
+
+In order to keep the stack size constant, Guzzle promises are resolved
+asynchronously using a task queue. When waiting on promises synchronously, the
+task queue will be automatically run to ensure that the blocking promise and
+any forwarded promises are resolved. When using promises asynchronously in an
+event loop, you will need to run the task queue on each tick of the loop. If
+you do not run the task queue, then promises will not be resolved.
+
+You can run the task queue using the `run()` method of the global task queue
+instance.
+
+```php
+// Get the global task queue
+$queue = \GuzzleHttp\Promise\queue();
+$queue->run();
+```
+
+For example, you could use Guzzle promises with React using a periodic timer:
+
+```php
+$loop = React\EventLoop\Factory::create();
+$loop->addPeriodicTimer(0, [$queue, 'run']);
+```
+
+*TODO*: Perhaps adding a `futureTick()` on each tick would be faster?
+
+
+# Implementation notes
+
+
+## Promise resolution and chaining is handled iteratively
+
+By shuffling pending handlers from one owner to another, promises are
+resolved iteratively, allowing for "infinite" then chaining.
+
+```php
+<?php
+require 'vendor/autoload.php';
+
+use GuzzleHttp\Promise\Promise;
+
+$parent = new Promise();
+$p = $parent;
+
+for ($i = 0; $i < 1000; $i++) {
+    $p = $p->then(function ($v) {
+        // The stack size remains constant (a good thing)
+        echo xdebug_get_stack_depth() . ', ';
+        return $v + 1;
+    });
+}
+
+$parent->resolve(0);
+var_dump($p->wait()); // int(1000)
+
+```
+
+When a promise is fulfilled or rejected with a non-promise value, the promise
+then takes ownership of the handlers of each child promise and delivers values
+down the chain without using recursion.
+
+When a promise is resolved with another promise, the original promise transfers
+all of its pending handlers to the new promise. When the new promise is
+eventually resolved, all of the pending handlers are delivered the forwarded
+value.
+
+
+## A promise is the deferred.
+
+Some promise libraries implement promises using a deferred object to represent
+a computation and a promise object to represent the delivery of the result of
+the computation. This is a nice separation of computation and delivery because
+consumers of the promise cannot modify the value that will be eventually
+delivered.
+
+One side effect of being able to implement promise resolution and chaining
+iteratively is that you need to be able for one promise to reach into the state
+of another promise to shuffle around ownership of handlers. In order to achieve
+this without making the handlers of a promise publicly mutable, a promise is
+also the deferred value, allowing promises of the same parent class to reach
+into and modify the private properties of promises of the same type. While this
+does allow consumers of the value to modify the resolution or rejection of the
+deferred, it is a small price to pay for keeping the stack size constant.
+
+```php
+$promise = new Promise();
+$promise->then(function ($value) { echo $value; });
+// The promise is the deferred value, so you can deliver a value to it.
+$promise->resolve('foo');
+// prints "foo"
+```
diff --git a/vendor/guzzlehttp/promises/composer.json b/vendor/guzzlehttp/promises/composer.json
new file mode 100644
index 00000000000..ec41a61e6e8
--- /dev/null
+++ b/vendor/guzzlehttp/promises/composer.json
@@ -0,0 +1,34 @@
+{
+    "name": "guzzlehttp/promises",
+    "description": "Guzzle promises library",
+    "keywords": ["promise"],
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Michael Dowling",
+            "email": "mtdowling@gmail.com",
+            "homepage": "https://github.com/mtdowling"
+        }
+    ],
+    "require": {
+        "php": ">=5.5.0"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^4.0"
+    },
+    "autoload": {
+        "psr-4": {
+            "GuzzleHttp\\Promise\\": "src/"
+        },
+        "files": ["src/functions_include.php"]
+    },
+    "scripts": {
+        "test": "vendor/bin/phpunit",
+        "test-ci": "vendor/bin/phpunit --coverage-text"
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "1.4-dev"
+        }
+    }
+}
diff --git a/vendor/guzzlehttp/promises/src/AggregateException.php b/vendor/guzzlehttp/promises/src/AggregateException.php
new file mode 100644
index 00000000000..6a5690c3762
--- /dev/null
+++ b/vendor/guzzlehttp/promises/src/AggregateException.php
@@ -0,0 +1,16 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+/**
+ * Exception thrown when too many errors occur in the some() or any() methods.
+ */
+class AggregateException extends RejectionException
+{
+    public function __construct($msg, array $reasons)
+    {
+        parent::__construct(
+            $reasons,
+            sprintf('%s; %d rejected promises', $msg, count($reasons))
+        );
+    }
+}
diff --git a/vendor/guzzlehttp/promises/src/CancellationException.php b/vendor/guzzlehttp/promises/src/CancellationException.php
new file mode 100644
index 00000000000..cb360b8056a
--- /dev/null
+++ b/vendor/guzzlehttp/promises/src/CancellationException.php
@@ -0,0 +1,9 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+/**
+ * Exception that is set as the reason for a promise that has been cancelled.
+ */
+class CancellationException extends RejectionException
+{
+}
diff --git a/vendor/guzzlehttp/promises/src/Coroutine.php b/vendor/guzzlehttp/promises/src/Coroutine.php
new file mode 100644
index 00000000000..6aa09587022
--- /dev/null
+++ b/vendor/guzzlehttp/promises/src/Coroutine.php
@@ -0,0 +1,151 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+use Exception;
+use Generator;
+use Throwable;
+
+/**
+ * Creates a promise that is resolved using a generator that yields values or
+ * promises (somewhat similar to C#'s async keyword).
+ *
+ * When called, the coroutine function will start an instance of the generator
+ * and returns a promise that is fulfilled with its final yielded value.
+ *
+ * Control is returned back to the generator when the yielded promise settles.
+ * This can lead to less verbose code when doing lots of sequential async calls
+ * with minimal processing in between.
+ *
+ *     use GuzzleHttp\Promise;
+ *
+ *     function createPromise($value) {
+ *         return new Promise\FulfilledPromise($value);
+ *     }
+ *
+ *     $promise = Promise\coroutine(function () {
+ *         $value = (yield createPromise('a'));
+ *         try {
+ *             $value = (yield createPromise($value . 'b'));
+ *         } catch (\Exception $e) {
+ *             // The promise was rejected.
+ *         }
+ *         yield $value . 'c';
+ *     });
+ *
+ *     // Outputs "abc"
+ *     $promise->then(function ($v) { echo $v; });
+ *
+ * @param callable $generatorFn Generator function to wrap into a promise.
+ *
+ * @return Promise
+ * @link https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration
+ */
+final class Coroutine implements PromiseInterface
+{
+    /**
+     * @var PromiseInterface|null
+     */
+    private $currentPromise;
+
+    /**
+     * @var Generator
+     */
+    private $generator;
+
+    /**
+     * @var Promise
+     */
+    private $result;
+
+    public function __construct(callable $generatorFn)
+    {
+        $this->generator = $generatorFn();
+        $this->result = new Promise(function () {
+            while (isset($this->currentPromise)) {
+                $this->currentPromise->wait();
+            }
+        });
+        $this->nextCoroutine($this->generator->current());
+    }
+
+    public function then(
+        callable $onFulfilled = null,
+        callable $onRejected = null
+    ) {
+        return $this->result->then($onFulfilled, $onRejected);
+    }
+
+    public function otherwise(callable $onRejected)
+    {
+        return $this->result->otherwise($onRejected);
+    }
+
+    public function wait($unwrap = true)
+    {
+        return $this->result->wait($unwrap);
+    }
+
+    public function getState()
+    {
+        return $this->result->getState();
+    }
+
+    public function resolve($value)
+    {
+        $this->result->resolve($value);
+    }
+
+    public function reject($reason)
+    {
+        $this->result->reject($reason);
+    }
+
+    public function cancel()
+    {
+        $this->currentPromise->cancel();
+        $this->result->cancel();
+    }
+
+    private function nextCoroutine($yielded)
+    {
+        $this->currentPromise = promise_for($yielded)
+            ->then([$this, '_handleSuccess'], [$this, '_handleFailure']);
+    }
+
+    /**
+     * @internal
+     */
+    public function _handleSuccess($value)
+    {
+        unset($this->currentPromise);
+        try {
+            $next = $this->generator->send($value);
+            if ($this->generator->valid()) {
+                $this->nextCoroutine($next);
+            } else {
+                $this->result->resolve($value);
+            }
+        } catch (Exception $exception) {
+            $this->result->reject($exception);
+        } catch (Throwable $throwable) {
+            $this->result->reject($throwable);
+        }
+    }
+
+    /**
+     * @internal
+     */
+    public function _handleFailure($reason)
+    {
+        unset($this->currentPromise);
+        try {
+            $nextYield = $this->generator->throw(exception_for($reason));
+            // The throw was caught, so keep iterating on the coroutine
+            $this->nextCoroutine($nextYield);
+        } catch (Exception $exception) {
+            $this->result->reject($exception);
+        } catch (Throwable $throwable) {
+            $this->result->reject($throwable);
+        }
+    }
+}
diff --git a/vendor/guzzlehttp/promises/src/EachPromise.php b/vendor/guzzlehttp/promises/src/EachPromise.php
new file mode 100644
index 00000000000..d0ddf603fb3
--- /dev/null
+++ b/vendor/guzzlehttp/promises/src/EachPromise.php
@@ -0,0 +1,229 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+/**
+ * Represents a promise that iterates over many promises and invokes
+ * side-effect functions in the process.
+ */
+class EachPromise implements PromisorInterface
+{
+    private $pending = [];
+
+    /** @var \Iterator */
+    private $iterable;
+
+    /** @var callable|int */
+    private $concurrency;
+
+    /** @var callable */
+    private $onFulfilled;
+
+    /** @var callable */
+    private $onRejected;
+
+    /** @var Promise */
+    private $aggregate;
+
+    /** @var bool */
+    private $mutex;
+
+    /**
+     * Configuration hash can include the following key value pairs:
+     *
+     * - fulfilled: (callable) Invoked when a promise fulfills. The function
+     *   is invoked with three arguments: the fulfillment value, the index
+     *   position from the iterable list of the promise, and the aggregate
+     *   promise that manages all of the promises. The aggregate promise may
+     *   be resolved from within the callback to short-circuit the promise.
+     * - rejected: (callable) Invoked when a promise is rejected. The
+     *   function is invoked with three arguments: the rejection reason, the
+     *   index position from the iterable list of the promise, and the
+     *   aggregate promise that manages all of the promises. The aggregate
+     *   promise may be resolved from within the callback to short-circuit
+     *   the promise.
+     * - concurrency: (integer) Pass this configuration option to limit the
+     *   allowed number of outstanding concurrently executing promises,
+     *   creating a capped pool of promises. There is no limit by default.
+     *
+     * @param mixed    $iterable Promises or values to iterate.
+     * @param array    $config   Configuration options
+     */
+    public function __construct($iterable, array $config = [])
+    {
+        $this->iterable = iter_for($iterable);
+
+        if (isset($config['concurrency'])) {
+            $this->concurrency = $config['concurrency'];
+        }
+
+        if (isset($config['fulfilled'])) {
+            $this->onFulfilled = $config['fulfilled'];
+        }
+
+        if (isset($config['rejected'])) {
+            $this->onRejected = $config['rejected'];
+        }
+    }
+
+    public function promise()
+    {
+        if ($this->aggregate) {
+            return $this->aggregate;
+        }
+
+        try {
+            $this->createPromise();
+            $this->iterable->rewind();
+            $this->refillPending();
+        } catch (\Throwable $e) {
+            $this->aggregate->reject($e);
+        } catch (\Exception $e) {
+            $this->aggregate->reject($e);
+        }
+
+        return $this->aggregate;
+    }
+
+    private function createPromise()
+    {
+        $this->mutex = false;
+        $this->aggregate = new Promise(function () {
+            reset($this->pending);
+            if (empty($this->pending) && !$this->iterable->valid()) {
+                $this->aggregate->resolve(null);
+                return;
+            }
+
+            // Consume a potentially fluctuating list of promises while
+            // ensuring that indexes are maintained (precluding array_shift).
+            while ($promise = current($this->pending)) {
+                next($this->pending);
+                $promise->wait();
+                if ($this->aggregate->getState() !== PromiseInterface::PENDING) {
+                    return;
+                }
+            }
+        });
+
+        // Clear the references when the promise is resolved.
+        $clearFn = function () {
+            $this->iterable = $this->concurrency = $this->pending = null;
+            $this->onFulfilled = $this->onRejected = null;
+        };
+
+        $this->aggregate->then($clearFn, $clearFn);
+    }
+
+    private function refillPending()
+    {
+        if (!$this->concurrency) {
+            // Add all pending promises.
+            while ($this->addPending() && $this->advanceIterator());
+            return;
+        }
+
+        // Add only up to N pending promises.
+        $concurrency = is_callable($this->concurrency)
+            ? call_user_func($this->concurrency, count($this->pending))
+            : $this->concurrency;
+        $concurrency = max($concurrency - count($this->pending), 0);
+        // Concurrency may be set to 0 to disallow new promises.
+        if (!$concurrency) {
+            return;
+        }
+        // Add the first pending promise.
+        $this->addPending();
+        // Note this is special handling for concurrency=1 so that we do
+        // not advance the iterator after adding the first promise. This
+        // helps work around issues with generators that might not have the
+        // next value to yield until promise callbacks are called.
+        while (--$concurrency
+            && $this->advanceIterator()
+            && $this->addPending());
+    }
+
+    private function addPending()
+    {
+        if (!$this->iterable || !$this->iterable->valid()) {
+            return false;
+        }
+
+        $promise = promise_for($this->iterable->current());
+        $idx = $this->iterable->key();
+
+        $this->pending[$idx] = $promise->then(
+            function ($value) use ($idx) {
+                if ($this->onFulfilled) {
+                    call_user_func(
+                        $this->onFulfilled, $value, $idx, $this->aggregate
+                    );
+                }
+                $this->step($idx);
+            },
+            function ($reason) use ($idx) {
+                if ($this->onRejected) {
+                    call_user_func(
+                        $this->onRejected, $reason, $idx, $this->aggregate
+                    );
+                }
+                $this->step($idx);
+            }
+        );
+
+        return true;
+    }
+
+    private function advanceIterator()
+    {
+        // Place a lock on the iterator so that we ensure to not recurse,
+        // preventing fatal generator errors.
+        if ($this->mutex) {
+            return false;
+        }
+
+        $this->mutex = true;
+
+        try {
+            $this->iterable->next();
+            $this->mutex = false;
+            return true;
+        } catch (\Throwable $e) {
+            $this->aggregate->reject($e);
+            $this->mutex = false;
+            return false;
+        } catch (\Exception $e) {
+            $this->aggregate->reject($e);
+            $this->mutex = false;
+            return false;
+        }
+    }
+
+    private function step($idx)
+    {
+        // If the promise was already resolved, then ignore this step.
+        if ($this->aggregate->getState() !== PromiseInterface::PENDING) {
+            return;
+        }
+
+        unset($this->pending[$idx]);
+
+        // Only refill pending promises if we are not locked, preventing the
+        // EachPromise to recursively invoke the provided iterator, which
+        // cause a fatal error: "Cannot resume an already running generator"
+        if ($this->advanceIterator() && !$this->checkIfFinished()) {
+            // Add more pending promises if possible.
+            $this->refillPending();
+        }
+    }
+
+    private function checkIfFinished()
+    {
+        if (!$this->pending && !$this->iterable->valid()) {
+            // Resolve the promise if there's nothing left to do.
+            $this->aggregate->resolve(null);
+            return true;
+        }
+
+        return false;
+    }
+}
diff --git a/vendor/guzzlehttp/promises/src/FulfilledPromise.php b/vendor/guzzlehttp/promises/src/FulfilledPromise.php
new file mode 100644
index 00000000000..dbbeeb9f71b
--- /dev/null
+++ b/vendor/guzzlehttp/promises/src/FulfilledPromise.php
@@ -0,0 +1,82 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+/**
+ * A promise that has been fulfilled.
+ *
+ * Thenning off of this promise will invoke the onFulfilled callback
+ * immediately and ignore other callbacks.
+ */
+class FulfilledPromise implements PromiseInterface
+{
+    private $value;
+
+    public function __construct($value)
+    {
+        if (method_exists($value, 'then')) {
+            throw new \InvalidArgumentException(
+                'You cannot create a FulfilledPromise with a promise.');
+        }
+
+        $this->value = $value;
+    }
+
+    public function then(
+        callable $onFulfilled = null,
+        callable $onRejected = null
+    ) {
+        // Return itself if there is no onFulfilled function.
+        if (!$onFulfilled) {
+            return $this;
+        }
+
+        $queue = queue();
+        $p = new Promise([$queue, 'run']);
+        $value = $this->value;
+        $queue->add(static function () use ($p, $value, $onFulfilled) {
+            if ($p->getState() === self::PENDING) {
+                try {
+                    $p->resolve($onFulfilled($value));
+                } catch (\Throwable $e) {
+                    $p->reject($e);
+                } catch (\Exception $e) {
+                    $p->reject($e);
+                }
+            }
+        });
+
+        return $p;
+    }
+
+    public function otherwise(callable $onRejected)
+    {
+        return $this->then(null, $onRejected);
+    }
+
+    public function wait($unwrap = true, $defaultDelivery = null)
+    {
+        return $unwrap ? $this->value : null;
+    }
+
+    public function getState()
+    {
+        return self::FULFILLED;
+    }
+
+    public function resolve($value)
+    {
+        if ($value !== $this->value) {
+            throw new \LogicException("Cannot resolve a fulfilled promise");
+        }
+    }
+
+    public function reject($reason)
+    {
+        throw new \LogicException("Cannot reject a fulfilled promise");
+    }
+
+    public function cancel()
+    {
+        // pass
+    }
+}
diff --git a/vendor/guzzlehttp/promises/src/Promise.php b/vendor/guzzlehttp/promises/src/Promise.php
new file mode 100644
index 00000000000..844ada073c8
--- /dev/null
+++ b/vendor/guzzlehttp/promises/src/Promise.php
@@ -0,0 +1,280 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+/**
+ * Promises/A+ implementation that avoids recursion when possible.
+ *
+ * @link https://promisesaplus.com/
+ */
+class Promise implements PromiseInterface
+{
+    private $state = self::PENDING;
+    private $result;
+    private $cancelFn;
+    private $waitFn;
+    private $waitList;
+    private $handlers = [];
+
+    /**
+     * @param callable $waitFn   Fn that when invoked resolves the promise.
+     * @param callable $cancelFn Fn that when invoked cancels the promise.
+     */
+    public function __construct(
+        callable $waitFn = null,
+        callable $cancelFn = null
+    ) {
+        $this->waitFn = $waitFn;
+        $this->cancelFn = $cancelFn;
+    }
+
+    public function then(
+        callable $onFulfilled = null,
+        callable $onRejected = null
+    ) {
+        if ($this->state === self::PENDING) {
+            $p = new Promise(null, [$this, 'cancel']);
+            $this->handlers[] = [$p, $onFulfilled, $onRejected];
+            $p->waitList = $this->waitList;
+            $p->waitList[] = $this;
+            return $p;
+        }
+
+        // Return a fulfilled promise and immediately invoke any callbacks.
+        if ($this->state === self::FULFILLED) {
+            return $onFulfilled
+                ? promise_for($this->result)->then($onFulfilled)
+                : promise_for($this->result);
+        }
+
+        // It's either cancelled or rejected, so return a rejected promise
+        // and immediately invoke any callbacks.
+        $rejection = rejection_for($this->result);
+        return $onRejected ? $rejection->then(null, $onRejected) : $rejection;
+    }
+
+    public function otherwise(callable $onRejected)
+    {
+        return $this->then(null, $onRejected);
+    }
+
+    public function wait($unwrap = true)
+    {
+        $this->waitIfPending();
+
+        $inner = $this->result instanceof PromiseInterface
+            ? $this->result->wait($unwrap)
+            : $this->result;
+
+        if ($unwrap) {
+            if ($this->result instanceof PromiseInterface
+                || $this->state === self::FULFILLED
+            ) {
+                return $inner;
+            } else {
+                // It's rejected so "unwrap" and throw an exception.
+                throw exception_for($inner);
+            }
+        }
+    }
+
+    public function getState()
+    {
+        return $this->state;
+    }
+
+    public function cancel()
+    {
+        if ($this->state !== self::PENDING) {
+            return;
+        }
+
+        $this->waitFn = $this->waitList = null;
+
+        if ($this->cancelFn) {
+            $fn = $this->cancelFn;
+            $this->cancelFn = null;
+            try {
+                $fn();
+            } catch (\Throwable $e) {
+                $this->reject($e);
+            } catch (\Exception $e) {
+                $this->reject($e);
+            }
+        }
+
+        // Reject the promise only if it wasn't rejected in a then callback.
+        if ($this->state === self::PENDING) {
+            $this->reject(new CancellationException('Promise has been cancelled'));
+        }
+    }
+
+    public function resolve($value)
+    {
+        $this->settle(self::FULFILLED, $value);
+    }
+
+    public function reject($reason)
+    {
+        $this->settle(self::REJECTED, $reason);
+    }
+
+    private function settle($state, $value)
+    {
+        if ($this->state !== self::PENDING) {
+            // Ignore calls with the same resolution.
+            if ($state === $this->state && $value === $this->result) {
+                return;
+            }
+            throw $this->state === $state
+                ? new \LogicException("The promise is already {$state}.")
+                : new \LogicException("Cannot change a {$this->state} promise to {$state}");
+        }
+
+        if ($value === $this) {
+            throw new \LogicException('Cannot fulfill or reject a promise with itself');
+        }
+
+        // Clear out the state of the promise but stash the handlers.
+        $this->state = $state;
+        $this->result = $value;
+        $handlers = $this->handlers;
+        $this->handlers = null;
+        $this->waitList = $this->waitFn = null;
+        $this->cancelFn = null;
+
+        if (!$handlers) {
+            return;
+        }
+
+        // If the value was not a settled promise or a thenable, then resolve
+        // it in the task queue using the correct ID.
+        if (!method_exists($value, 'then')) {
+            $id = $state === self::FULFILLED ? 1 : 2;
+            // It's a success, so resolve the handlers in the queue.
+            queue()->add(static function () use ($id, $value, $handlers) {
+                foreach ($handlers as $handler) {
+                    self::callHandler($id, $value, $handler);
+                }
+            });
+        } elseif ($value instanceof Promise
+            && $value->getState() === self::PENDING
+        ) {
+            // We can just merge our handlers onto the next promise.
+            $value->handlers = array_merge($value->handlers, $handlers);
+        } else {
+            // Resolve the handlers when the forwarded promise is resolved.
+            $value->then(
+                static function ($value) use ($handlers) {
+                    foreach ($handlers as $handler) {
+                        self::callHandler(1, $value, $handler);
+                    }
+                },
+                static function ($reason) use ($handlers) {
+                    foreach ($handlers as $handler) {
+                        self::callHandler(2, $reason, $handler);
+                    }
+                }
+            );
+        }
+    }
+
+    /**
+     * Call a stack of handlers using a specific callback index and value.
+     *
+     * @param int   $index   1 (resolve) or 2 (reject).
+     * @param mixed $value   Value to pass to the callback.
+     * @param array $handler Array of handler data (promise and callbacks).
+     *
+     * @return array Returns the next group to resolve.
+     */
+    private static function callHandler($index, $value, array $handler)
+    {
+        /** @var PromiseInterface $promise */
+        $promise = $handler[0];
+
+        // The promise may have been cancelled or resolved before placing
+        // this thunk in the queue.
+        if ($promise->getState() !== self::PENDING) {
+            return;
+        }
+
+        try {
+            if (isset($handler[$index])) {
+                $promise->resolve($handler[$index]($value));
+            } elseif ($index === 1) {
+                // Forward resolution values as-is.
+                $promise->resolve($value);
+            } else {
+                // Forward rejections down the chain.
+                $promise->reject($value);
+            }
+        } catch (\Throwable $reason) {
+            $promise->reject($reason);
+        } catch (\Exception $reason) {
+            $promise->reject($reason);
+        }
+    }
+
+    private function waitIfPending()
+    {
+        if ($this->state !== self::PENDING) {
+            return;
+        } elseif ($this->waitFn) {
+            $this->invokeWaitFn();
+        } elseif ($this->waitList) {
+            $this->invokeWaitList();
+        } else {
+            // If there's not wait function, then reject the promise.
+            $this->reject('Cannot wait on a promise that has '
+                . 'no internal wait function. You must provide a wait '
+                . 'function when constructing the promise to be able to '
+                . 'wait on a promise.');
+        }
+
+        queue()->run();
+
+        if ($this->state === self::PENDING) {
+            $this->reject('Invoking the wait callback did not resolve the promise');
+        }
+    }
+
+    private function invokeWaitFn()
+    {
+        try {
+            $wfn = $this->waitFn;
+            $this->waitFn = null;
+            $wfn(true);
+        } catch (\Exception $reason) {
+            if ($this->state === self::PENDING) {
+                // The promise has not been resolved yet, so reject the promise
+                // with the exception.
+                $this->reject($reason);
+            } else {
+                // The promise was already resolved, so there's a problem in
+                // the application.
+                throw $reason;
+            }
+        }
+    }
+
+    private function invokeWaitList()
+    {
+        $waitList = $this->waitList;
+        $this->waitList = null;
+
+        foreach ($waitList as $result) {
+            while (true) {
+                $result->waitIfPending();
+
+                if ($result->result instanceof Promise) {
+                    $result = $result->result;
+                } else {
+                    if ($result->result instanceof PromiseInterface) {
+                        $result->result->wait(false);
+                    }
+                    break;
+                }
+            }
+        }
+    }
+}
diff --git a/vendor/guzzlehttp/promises/src/PromiseInterface.php b/vendor/guzzlehttp/promises/src/PromiseInterface.php
new file mode 100644
index 00000000000..8f5f4b99b26
--- /dev/null
+++ b/vendor/guzzlehttp/promises/src/PromiseInterface.php
@@ -0,0 +1,93 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+/**
+ * A promise represents the eventual result of an asynchronous operation.
+ *
+ * The primary way of interacting with a promise is through its then method,
+ * which registers callbacks to receive either a promise’s eventual value or
+ * the reason why the promise cannot be fulfilled.
+ *
+ * @link https://promisesaplus.com/
+ */
+interface PromiseInterface
+{
+    const PENDING = 'pending';
+    const FULFILLED = 'fulfilled';
+    const REJECTED = 'rejected';
+
+    /**
+     * Appends fulfillment and rejection handlers to the promise, and returns
+     * a new promise resolving to the return value of the called handler.
+     *
+     * @param callable $onFulfilled Invoked when the promise fulfills.
+     * @param callable $onRejected  Invoked when the promise is rejected.
+     *
+     * @return PromiseInterface
+     */
+    public function then(
+        callable $onFulfilled = null,
+        callable $onRejected = null
+    );
+
+    /**
+     * Appends a rejection handler callback to the promise, and returns a new
+     * promise resolving to the return value of the callback if it is called,
+     * or to its original fulfillment value if the promise is instead
+     * fulfilled.
+     *
+     * @param callable $onRejected Invoked when the promise is rejected.
+     *
+     * @return PromiseInterface
+     */
+    public function otherwise(callable $onRejected);
+
+    /**
+     * Get the state of the promise ("pending", "rejected", or "fulfilled").
+     *
+     * The three states can be checked against the constants defined on
+     * PromiseInterface: PENDING, FULFILLED, and REJECTED.
+     *
+     * @return string
+     */
+    public function getState();
+
+    /**
+     * Resolve the promise with the given value.
+     *
+     * @param mixed $value
+     * @throws \RuntimeException if the promise is already resolved.
+     */
+    public function resolve($value);
+
+    /**
+     * Reject the promise with the given reason.
+     *
+     * @param mixed $reason
+     * @throws \RuntimeException if the promise is already resolved.
+     */
+    public function reject($reason);
+
+    /**
+     * Cancels the promise if possible.
+     *
+     * @link https://github.com/promises-aplus/cancellation-spec/issues/7
+     */
+    public function cancel();
+
+    /**
+     * Waits until the promise completes if possible.
+     *
+     * Pass $unwrap as true to unwrap the result of the promise, either
+     * returning the resolved value or throwing the rejected exception.
+     *
+     * If the promise cannot be waited on, then the promise will be rejected.
+     *
+     * @param bool $unwrap
+     *
+     * @return mixed
+     * @throws \LogicException if the promise has no wait function or if the
+     *                         promise does not settle after waiting.
+     */
+    public function wait($unwrap = true);
+}
diff --git a/vendor/guzzlehttp/promises/src/PromisorInterface.php b/vendor/guzzlehttp/promises/src/PromisorInterface.php
new file mode 100644
index 00000000000..b07fe32bc13
--- /dev/null
+++ b/vendor/guzzlehttp/promises/src/PromisorInterface.php
@@ -0,0 +1,15 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+/**
+ * Interface used with classes that return a promise.
+ */
+interface PromisorInterface
+{
+    /**
+     * Returns a promise.
+     *
+     * @return PromiseInterface
+     */
+    public function promise();
+}
diff --git a/vendor/guzzlehttp/promises/src/RejectedPromise.php b/vendor/guzzlehttp/promises/src/RejectedPromise.php
new file mode 100644
index 00000000000..2bc6508e7b6
--- /dev/null
+++ b/vendor/guzzlehttp/promises/src/RejectedPromise.php
@@ -0,0 +1,87 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+/**
+ * A promise that has been rejected.
+ *
+ * Thenning off of this promise will invoke the onRejected callback
+ * immediately and ignore other callbacks.
+ */
+class RejectedPromise implements PromiseInterface
+{
+    private $reason;
+
+    public function __construct($reason)
+    {
+        if (method_exists($reason, 'then')) {
+            throw new \InvalidArgumentException(
+                'You cannot create a RejectedPromise with a promise.');
+        }
+
+        $this->reason = $reason;
+    }
+
+    public function then(
+        callable $onFulfilled = null,
+        callable $onRejected = null
+    ) {
+        // If there's no onRejected callback then just return self.
+        if (!$onRejected) {
+            return $this;
+        }
+
+        $queue = queue();
+        $reason = $this->reason;
+        $p = new Promise([$queue, 'run']);
+        $queue->add(static function () use ($p, $reason, $onRejected) {
+            if ($p->getState() === self::PENDING) {
+                try {
+                    // Return a resolved promise if onRejected does not throw.
+                    $p->resolve($onRejected($reason));
+                } catch (\Throwable $e) {
+                    // onRejected threw, so return a rejected promise.
+                    $p->reject($e);
+                } catch (\Exception $e) {
+                    // onRejected threw, so return a rejected promise.
+                    $p->reject($e);
+                }
+            }
+        });
+
+        return $p;
+    }
+
+    public function otherwise(callable $onRejected)
+    {
+        return $this->then(null, $onRejected);
+    }
+
+    public function wait($unwrap = true, $defaultDelivery = null)
+    {
+        if ($unwrap) {
+            throw exception_for($this->reason);
+        }
+    }
+
+    public function getState()
+    {
+        return self::REJECTED;
+    }
+
+    public function resolve($value)
+    {
+        throw new \LogicException("Cannot resolve a rejected promise");
+    }
+
+    public function reject($reason)
+    {
+        if ($reason !== $this->reason) {
+            throw new \LogicException("Cannot reject a rejected promise");
+        }
+    }
+
+    public function cancel()
+    {
+        // pass
+    }
+}
diff --git a/vendor/guzzlehttp/promises/src/RejectionException.php b/vendor/guzzlehttp/promises/src/RejectionException.php
new file mode 100644
index 00000000000..07c1136da16
--- /dev/null
+++ b/vendor/guzzlehttp/promises/src/RejectionException.php
@@ -0,0 +1,47 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+/**
+ * A special exception that is thrown when waiting on a rejected promise.
+ *
+ * The reason value is available via the getReason() method.
+ */
+class RejectionException extends \RuntimeException
+{
+    /** @var mixed Rejection reason. */
+    private $reason;
+
+    /**
+     * @param mixed $reason       Rejection reason.
+     * @param string $description Optional description
+     */
+    public function __construct($reason, $description = null)
+    {
+        $this->reason = $reason;
+
+        $message = 'The promise was rejected';
+
+        if ($description) {
+            $message .= ' with reason: ' . $description;
+        } elseif (is_string($reason)
+            || (is_object($reason) && method_exists($reason, '__toString'))
+        ) {
+            $message .= ' with reason: ' . $this->reason;
+        } elseif ($reason instanceof \JsonSerializable) {
+            $message .= ' with reason: '
+                . json_encode($this->reason, JSON_PRETTY_PRINT);
+        }
+
+        parent::__construct($message);
+    }
+
+    /**
+     * Returns the rejection reason.
+     *
+     * @return mixed
+     */
+    public function getReason()
+    {
+        return $this->reason;
+    }
+}
diff --git a/vendor/guzzlehttp/promises/src/TaskQueue.php b/vendor/guzzlehttp/promises/src/TaskQueue.php
new file mode 100644
index 00000000000..6e8a2a083cd
--- /dev/null
+++ b/vendor/guzzlehttp/promises/src/TaskQueue.php
@@ -0,0 +1,66 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+/**
+ * A task queue that executes tasks in a FIFO order.
+ *
+ * This task queue class is used to settle promises asynchronously and
+ * maintains a constant stack size. You can use the task queue asynchronously
+ * by calling the `run()` function of the global task queue in an event loop.
+ *
+ *     GuzzleHttp\Promise\queue()->run();
+ */
+class TaskQueue implements TaskQueueInterface
+{
+    private $enableShutdown = true;
+    private $queue = [];
+
+    public function __construct($withShutdown = true)
+    {
+        if ($withShutdown) {
+            register_shutdown_function(function () {
+                if ($this->enableShutdown) {
+                    // Only run the tasks if an E_ERROR didn't occur.
+                    $err = error_get_last();
+                    if (!$err || ($err['type'] ^ E_ERROR)) {
+                        $this->run();
+                    }
+                }
+            });
+        }
+    }
+
+    public function isEmpty()
+    {
+        return !$this->queue;
+    }
+
+    public function add(callable $task)
+    {
+        $this->queue[] = $task;
+    }
+
+    public function run()
+    {
+        /** @var callable $task */
+        while ($task = array_shift($this->queue)) {
+            $task();
+        }
+    }
+
+    /**
+     * The task queue will be run and exhausted by default when the process
+     * exits IFF the exit is not the result of a PHP E_ERROR error.
+     *
+     * You can disable running the automatic shutdown of the queue by calling
+     * this function. If you disable the task queue shutdown process, then you
+     * MUST either run the task queue (as a result of running your event loop
+     * or manually using the run() method) or wait on each outstanding promise.
+     *
+     * Note: This shutdown will occur before any destructors are triggered.
+     */
+    public function disableShutdown()
+    {
+        $this->enableShutdown = false;
+    }
+}
diff --git a/vendor/guzzlehttp/promises/src/TaskQueueInterface.php b/vendor/guzzlehttp/promises/src/TaskQueueInterface.php
new file mode 100644
index 00000000000..ac8306e1971
--- /dev/null
+++ b/vendor/guzzlehttp/promises/src/TaskQueueInterface.php
@@ -0,0 +1,25 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+interface TaskQueueInterface
+{
+    /**
+     * Returns true if the queue is empty.
+     *
+     * @return bool
+     */
+    public function isEmpty();
+
+    /**
+     * Adds a task to the queue that will be executed the next time run is
+     * called.
+     *
+     * @param callable $task
+     */
+    public function add(callable $task);
+
+    /**
+     * Execute all of the pending task in the queue.
+     */
+    public function run();
+}
diff --git a/vendor/guzzlehttp/promises/src/functions.php b/vendor/guzzlehttp/promises/src/functions.php
new file mode 100644
index 00000000000..4e27709af36
--- /dev/null
+++ b/vendor/guzzlehttp/promises/src/functions.php
@@ -0,0 +1,457 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+/**
+ * Get the global task queue used for promise resolution.
+ *
+ * This task queue MUST be run in an event loop in order for promises to be
+ * settled asynchronously. It will be automatically run when synchronously
+ * waiting on a promise.
+ *
+ * <code>
+ * while ($eventLoop->isRunning()) {
+ *     GuzzleHttp\Promise\queue()->run();
+ * }
+ * </code>
+ *
+ * @param TaskQueueInterface $assign Optionally specify a new queue instance.
+ *
+ * @return TaskQueueInterface
+ */
+function queue(TaskQueueInterface $assign = null)
+{
+    static $queue;
+
+    if ($assign) {
+        $queue = $assign;
+    } elseif (!$queue) {
+        $queue = new TaskQueue();
+    }
+
+    return $queue;
+}
+
+/**
+ * Adds a function to run in the task queue when it is next `run()` and returns
+ * a promise that is fulfilled or rejected with the result.
+ *
+ * @param callable $task Task function to run.
+ *
+ * @return PromiseInterface
+ */
+function task(callable $task)
+{
+    $queue = queue();
+    $promise = new Promise([$queue, 'run']);
+    $queue->add(function () use ($task, $promise) {
+        try {
+            $promise->resolve($task());
+        } catch (\Throwable $e) {
+            $promise->reject($e);
+        } catch (\Exception $e) {
+            $promise->reject($e);
+        }
+    });
+
+    return $promise;
+}
+
+/**
+ * Creates a promise for a value if the value is not a promise.
+ *
+ * @param mixed $value Promise or value.
+ *
+ * @return PromiseInterface
+ */
+function promise_for($value)
+{
+    if ($value instanceof PromiseInterface) {
+        return $value;
+    }
+
+    // Return a Guzzle promise that shadows the given promise.
+    if (method_exists($value, 'then')) {
+        $wfn = method_exists($value, 'wait') ? [$value, 'wait'] : null;
+        $cfn = method_exists($value, 'cancel') ? [$value, 'cancel'] : null;
+        $promise = new Promise($wfn, $cfn);
+        $value->then([$promise, 'resolve'], [$promise, 'reject']);
+        return $promise;
+    }
+
+    return new FulfilledPromise($value);
+}
+
+/**
+ * Creates a rejected promise for a reason if the reason is not a promise. If
+ * the provided reason is a promise, then it is returned as-is.
+ *
+ * @param mixed $reason Promise or reason.
+ *
+ * @return PromiseInterface
+ */
+function rejection_for($reason)
+{
+    if ($reason instanceof PromiseInterface) {
+        return $reason;
+    }
+
+    return new RejectedPromise($reason);
+}
+
+/**
+ * Create an exception for a rejected promise value.
+ *
+ * @param mixed $reason
+ *
+ * @return \Exception|\Throwable
+ */
+function exception_for($reason)
+{
+    return $reason instanceof \Exception || $reason instanceof \Throwable
+        ? $reason
+        : new RejectionException($reason);
+}
+
+/**
+ * Returns an iterator for the given value.
+ *
+ * @param mixed $value
+ *
+ * @return \Iterator
+ */
+function iter_for($value)
+{
+    if ($value instanceof \Iterator) {
+        return $value;
+    } elseif (is_array($value)) {
+        return new \ArrayIterator($value);
+    } else {
+        return new \ArrayIterator([$value]);
+    }
+}
+
+/**
+ * Synchronously waits on a promise to resolve and returns an inspection state
+ * array.
+ *
+ * Returns a state associative array containing a "state" key mapping to a
+ * valid promise state. If the state of the promise is "fulfilled", the array
+ * will contain a "value" key mapping to the fulfilled value of the promise. If
+ * the promise is rejected, the array will contain a "reason" key mapping to
+ * the rejection reason of the promise.
+ *
+ * @param PromiseInterface $promise Promise or value.
+ *
+ * @return array
+ */
+function inspect(PromiseInterface $promise)
+{
+    try {
+        return [
+            'state' => PromiseInterface::FULFILLED,
+            'value' => $promise->wait()
+        ];
+    } catch (RejectionException $e) {
+        return ['state' => PromiseInterface::REJECTED, 'reason' => $e->getReason()];
+    } catch (\Throwable $e) {
+        return ['state' => PromiseInterface::REJECTED, 'reason' => $e];
+    } catch (\Exception $e) {
+        return ['state' => PromiseInterface::REJECTED, 'reason' => $e];
+    }
+}
+
+/**
+ * Waits on all of the provided promises, but does not unwrap rejected promises
+ * as thrown exception.
+ *
+ * Returns an array of inspection state arrays.
+ *
+ * @param PromiseInterface[] $promises Traversable of promises to wait upon.
+ *
+ * @return array
+ * @see GuzzleHttp\Promise\inspect for the inspection state array format.
+ */
+function inspect_all($promises)
+{
+    $results = [];
+    foreach ($promises as $key => $promise) {
+        $results[$key] = inspect($promise);
+    }
+
+    return $results;
+}
+
+/**
+ * Waits on all of the provided promises and returns the fulfilled values.
+ *
+ * Returns an array that contains the value of each promise (in the same order
+ * the promises were provided). An exception is thrown if any of the promises
+ * are rejected.
+ *
+ * @param mixed $promises Iterable of PromiseInterface objects to wait on.
+ *
+ * @return array
+ * @throws \Exception on error
+ * @throws \Throwable on error in PHP >=7
+ */
+function unwrap($promises)
+{
+    $results = [];
+    foreach ($promises as $key => $promise) {
+        $results[$key] = $promise->wait();
+    }
+
+    return $results;
+}
+
+/**
+ * Given an array of promises, return a promise that is fulfilled when all the
+ * items in the array are fulfilled.
+ *
+ * The promise's fulfillment value is an array with fulfillment values at
+ * respective positions to the original array. If any promise in the array
+ * rejects, the returned promise is rejected with the rejection reason.
+ *
+ * @param mixed $promises Promises or values.
+ *
+ * @return PromiseInterface
+ */
+function all($promises)
+{
+    $results = [];
+    return each(
+        $promises,
+        function ($value, $idx) use (&$results) {
+            $results[$idx] = $value;
+        },
+        function ($reason, $idx, Promise $aggregate) {
+            $aggregate->reject($reason);
+        }
+    )->then(function () use (&$results) {
+        ksort($results);
+        return $results;
+    });
+}
+
+/**
+ * Initiate a competitive race between multiple promises or values (values will
+ * become immediately fulfilled promises).
+ *
+ * When count amount of promises have been fulfilled, the returned promise is
+ * fulfilled with an array that contains the fulfillment values of the winners
+ * in order of resolution.
+ *
+ * This prommise is rejected with a {@see GuzzleHttp\Promise\AggregateException}
+ * if the number of fulfilled promises is less than the desired $count.
+ *
+ * @param int   $count    Total number of promises.
+ * @param mixed $promises Promises or values.
+ *
+ * @return PromiseInterface
+ */
+function some($count, $promises)
+{
+    $results = [];
+    $rejections = [];
+
+    return each(
+        $promises,
+        function ($value, $idx, PromiseInterface $p) use (&$results, $count) {
+            if ($p->getState() !== PromiseInterface::PENDING) {
+                return;
+            }
+            $results[$idx] = $value;
+            if (count($results) >= $count) {
+                $p->resolve(null);
+            }
+        },
+        function ($reason) use (&$rejections) {
+            $rejections[] = $reason;
+        }
+    )->then(
+        function () use (&$results, &$rejections, $count) {
+            if (count($results) !== $count) {
+                throw new AggregateException(
+                    'Not enough promises to fulfill count',
+                    $rejections
+                );
+            }
+            ksort($results);
+            return array_values($results);
+        }
+    );
+}
+
+/**
+ * Like some(), with 1 as count. However, if the promise fulfills, the
+ * fulfillment value is not an array of 1 but the value directly.
+ *
+ * @param mixed $promises Promises or values.
+ *
+ * @return PromiseInterface
+ */
+function any($promises)
+{
+    return some(1, $promises)->then(function ($values) { return $values[0]; });
+}
+
+/**
+ * Returns a promise that is fulfilled when all of the provided promises have
+ * been fulfilled or rejected.
+ *
+ * The returned promise is fulfilled with an array of inspection state arrays.
+ *
+ * @param mixed $promises Promises or values.
+ *
+ * @return PromiseInterface
+ * @see GuzzleHttp\Promise\inspect for the inspection state array format.
+ */
+function settle($promises)
+{
+    $results = [];
+
+    return each(
+        $promises,
+        function ($value, $idx) use (&$results) {
+            $results[$idx] = ['state' => PromiseInterface::FULFILLED, 'value' => $value];
+        },
+        function ($reason, $idx) use (&$results) {
+            $results[$idx] = ['state' => PromiseInterface::REJECTED, 'reason' => $reason];
+        }
+    )->then(function () use (&$results) {
+        ksort($results);
+        return $results;
+    });
+}
+
+/**
+ * Given an iterator that yields promises or values, returns a promise that is
+ * fulfilled with a null value when the iterator has been consumed or the
+ * aggregate promise has been fulfilled or rejected.
+ *
+ * $onFulfilled is a function that accepts the fulfilled value, iterator
+ * index, and the aggregate promise. The callback can invoke any necessary side
+ * effects and choose to resolve or reject the aggregate promise if needed.
+ *
+ * $onRejected is a function that accepts the rejection reason, iterator
+ * index, and the aggregate promise. The callback can invoke any necessary side
+ * effects and choose to resolve or reject the aggregate promise if needed.
+ *
+ * @param mixed    $iterable    Iterator or array to iterate over.
+ * @param callable $onFulfilled
+ * @param callable $onRejected
+ *
+ * @return PromiseInterface
+ */
+function each(
+    $iterable,
+    callable $onFulfilled = null,
+    callable $onRejected = null
+) {
+    return (new EachPromise($iterable, [
+        'fulfilled' => $onFulfilled,
+        'rejected'  => $onRejected
+    ]))->promise();
+}
+
+/**
+ * Like each, but only allows a certain number of outstanding promises at any
+ * given time.
+ *
+ * $concurrency may be an integer or a function that accepts the number of
+ * pending promises and returns a numeric concurrency limit value to allow for
+ * dynamic a concurrency size.
+ *
+ * @param mixed        $iterable
+ * @param int|callable $concurrency
+ * @param callable     $onFulfilled
+ * @param callable     $onRejected
+ *
+ * @return PromiseInterface
+ */
+function each_limit(
+    $iterable,
+    $concurrency,
+    callable $onFulfilled = null,
+    callable $onRejected = null
+) {
+    return (new EachPromise($iterable, [
+        'fulfilled'   => $onFulfilled,
+        'rejected'    => $onRejected,
+        'concurrency' => $concurrency
+    ]))->promise();
+}
+
+/**
+ * Like each_limit, but ensures that no promise in the given $iterable argument
+ * is rejected. If any promise is rejected, then the aggregate promise is
+ * rejected with the encountered rejection.
+ *
+ * @param mixed        $iterable
+ * @param int|callable $concurrency
+ * @param callable     $onFulfilled
+ *
+ * @return PromiseInterface
+ */
+function each_limit_all(
+    $iterable,
+    $concurrency,
+    callable $onFulfilled = null
+) {
+    return each_limit(
+        $iterable,
+        $concurrency,
+        $onFulfilled,
+        function ($reason, $idx, PromiseInterface $aggregate) {
+            $aggregate->reject($reason);
+        }
+    );
+}
+
+/**
+ * Returns true if a promise is fulfilled.
+ *
+ * @param PromiseInterface $promise
+ *
+ * @return bool
+ */
+function is_fulfilled(PromiseInterface $promise)
+{
+    return $promise->getState() === PromiseInterface::FULFILLED;
+}
+
+/**
+ * Returns true if a promise is rejected.
+ *
+ * @param PromiseInterface $promise
+ *
+ * @return bool
+ */
+function is_rejected(PromiseInterface $promise)
+{
+    return $promise->getState() === PromiseInterface::REJECTED;
+}
+
+/**
+ * Returns true if a promise is fulfilled or rejected.
+ *
+ * @param PromiseInterface $promise
+ *
+ * @return bool
+ */
+function is_settled(PromiseInterface $promise)
+{
+    return $promise->getState() !== PromiseInterface::PENDING;
+}
+
+/**
+ * @see Coroutine
+ *
+ * @param callable $generatorFn
+ *
+ * @return PromiseInterface
+ */
+function coroutine(callable $generatorFn)
+{
+    return new Coroutine($generatorFn);
+}
diff --git a/vendor/guzzlehttp/promises/src/functions_include.php b/vendor/guzzlehttp/promises/src/functions_include.php
new file mode 100644
index 00000000000..34cd1710aa2
--- /dev/null
+++ b/vendor/guzzlehttp/promises/src/functions_include.php
@@ -0,0 +1,6 @@
+<?php
+
+// Don't redefine the functions if included multiple times.
+if (!function_exists('GuzzleHttp\Promise\promise_for')) {
+    require __DIR__ . '/functions.php';
+}
diff --git a/vendor/guzzlehttp/psr7/CHANGELOG.md b/vendor/guzzlehttp/psr7/CHANGELOG.md
new file mode 100644
index 00000000000..5c252b3a208
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/CHANGELOG.md
@@ -0,0 +1,110 @@
+# CHANGELOG
+
+## 1.4.2 - 2017-03-20
+
+* Reverted BC break to `Uri::resolve` and `Uri::removeDotSegments` by removing 
+  calls to `trigger_error` when deprecated methods are invoked.
+
+## 1.4.1 - 2017-02-27
+
+* Reverted BC break by reintroducing behavior to automagically fix a URI with a
+  relative path and an authority by adding a leading slash to the path. It's only
+  deprecated now.
+* Added triggering of silenced deprecation warnings.
+
+## 1.4.0 - 2017-02-21
+
+* Fix `Stream::read` when length parameter <= 0.
+* `copy_to_stream` reads bytes in chunks instead of `maxLen` into memory.
+* Fix `ServerRequest::getUriFromGlobals` when `Host` header contains port.
+* Ensure `ServerRequest::getUriFromGlobals` returns a URI in absolute form.
+* Allow `parse_response` to parse a response without delimiting space and reason.
+* Ensure each URI modification results in a valid URI according to PSR-7 discussions.
+  Invalid modifications will throw an exception instead of returning a wrong URI or
+  doing some magic.
+  - `(new Uri)->withPath('foo')->withHost('example.com')` will throw an exception
+    because the path of a URI with an authority must start with a slash "/" or be empty
+  - `(new Uri())->withScheme('http')` will return `'http://localhost'`
+* Fix compatibility of URIs with `file` scheme and empty host.
+* Added common URI utility methods based on RFC 3986 (see documentation in the readme):
+  - `Uri::isDefaultPort`
+  - `Uri::isAbsolute`
+  - `Uri::isNetworkPathReference`
+  - `Uri::isAbsolutePathReference`
+  - `Uri::isRelativePathReference`
+  - `Uri::isSameDocumentReference`
+  - `Uri::composeComponents`
+  - `UriNormalizer::normalize`
+  - `UriNormalizer::isEquivalent`
+  - `UriResolver::relativize`
+* Deprecated `Uri::resolve` in favor of `UriResolver::resolve`
+* Deprecated `Uri::removeDotSegments` in favor of `UriResolver::removeDotSegments`
+
+## 1.3.1 - 2016-06-25
+
+* Fix `Uri::__toString` for network path references, e.g. `//example.org`.
+* Fix missing lowercase normalization for host.
+* Fix handling of URI components in case they are `'0'` in a lot of places,
+  e.g. as a user info password.
+* Fix `Uri::withAddedHeader` to correctly merge headers with different case.
+* Fix trimming of header values in `Uri::withAddedHeader`. Header values may
+  be surrounded by whitespace which should be ignored according to RFC 7230
+  Section 3.2.4. This does not apply to header names.
+* Fix `Uri::withAddedHeader` with an array of header values.
+* Fix `Uri::resolve` when base path has no slash and handling of fragment.
+* Fix handling of encoding in `Uri::with(out)QueryValue` so one can pass the
+  key/value both in encoded as well as decoded form to those methods. This is
+  consistent with withPath, withQuery etc.
+* Fix `ServerRequest::withoutAttribute` when attribute value is null.
+
+## 1.3.0 - 2016-04-13
+
+* Added remaining interfaces needed for full PSR7 compatibility
+  (ServerRequestInterface, UploadedFileInterface, etc.).
+* Added support for stream_for from scalars.
+* Can now extend Uri.
+* Fixed a bug in validating request methods by making it more permissive.
+
+## 1.2.3 - 2016-02-18
+
+* Fixed support in `GuzzleHttp\Psr7\CachingStream` for seeking forward on remote
+  streams, which can sometimes return fewer bytes than requested with `fread`.
+* Fixed handling of gzipped responses with FNAME headers.
+
+## 1.2.2 - 2016-01-22
+
+* Added support for URIs without any authority.
+* Added support for HTTP 451 'Unavailable For Legal Reasons.'
+* Added support for using '0' as a filename.
+* Added support for including non-standard ports in Host headers.
+
+## 1.2.1 - 2015-11-02
+
+* Now supporting negative offsets when seeking to SEEK_END.
+
+## 1.2.0 - 2015-08-15
+
+* Body as `"0"` is now properly added to a response.
+* Now allowing forward seeking in CachingStream.
+* Now properly parsing HTTP requests that contain proxy targets in
+  `parse_request`.
+* functions.php is now conditionally required.
+* user-info is no longer dropped when resolving URIs.
+
+## 1.1.0 - 2015-06-24
+
+* URIs can now be relative.
+* `multipart/form-data` headers are now overridden case-insensitively.
+* URI paths no longer encode the following characters because they are allowed
+  in URIs: "(", ")", "*", "!", "'"
+* A port is no longer added to a URI when the scheme is missing and no port is
+  present.
+
+## 1.0.0 - 2015-05-19
+
+Initial release.
+
+Currently unsupported:
+
+- `Psr\Http\Message\ServerRequestInterface`
+- `Psr\Http\Message\UploadedFileInterface`
diff --git a/vendor/guzzlehttp/psr7/LICENSE b/vendor/guzzlehttp/psr7/LICENSE
new file mode 100644
index 00000000000..581d95f9202
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2015 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
+
+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/vendor/guzzlehttp/psr7/README.md b/vendor/guzzlehttp/psr7/README.md
new file mode 100644
index 00000000000..16499358ea1
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/README.md
@@ -0,0 +1,739 @@
+# PSR-7 Message Implementation
+
+This repository contains a full [PSR-7](http://www.php-fig.org/psr/psr-7/)
+message implementation, several stream decorators, and some helpful
+functionality like query string parsing.
+
+
+[![Build Status](https://travis-ci.org/guzzle/psr7.svg?branch=master)](https://travis-ci.org/guzzle/psr7)
+
+
+# Stream implementation
+
+This package comes with a number of stream implementations and stream
+decorators.
+
+
+## AppendStream
+
+`GuzzleHttp\Psr7\AppendStream`
+
+Reads from multiple streams, one after the other.
+
+```php
+use GuzzleHttp\Psr7;
+
+$a = Psr7\stream_for('abc, ');
+$b = Psr7\stream_for('123.');
+$composed = new Psr7\AppendStream([$a, $b]);
+
+$composed->addStream(Psr7\stream_for(' Above all listen to me'));
+
+echo $composed; // abc, 123. Above all listen to me.
+```
+
+
+## BufferStream
+
+`GuzzleHttp\Psr7\BufferStream`
+
+Provides a buffer stream that can be written to fill a buffer, and read
+from to remove bytes from the buffer.
+
+This stream returns a "hwm" metadata value that tells upstream consumers
+what the configured high water mark of the stream is, or the maximum
+preferred size of the buffer.
+
+```php
+use GuzzleHttp\Psr7;
+
+// When more than 1024 bytes are in the buffer, it will begin returning
+// false to writes. This is an indication that writers should slow down.
+$buffer = new Psr7\BufferStream(1024);
+```
+
+
+## CachingStream
+
+The CachingStream is used to allow seeking over previously read bytes on
+non-seekable streams. This can be useful when transferring a non-seekable
+entity body fails due to needing to rewind the stream (for example, resulting
+from a redirect). Data that is read from the remote stream will be buffered in
+a PHP temp stream so that previously read bytes are cached first in memory,
+then on disk.
+
+```php
+use GuzzleHttp\Psr7;
+
+$original = Psr7\stream_for(fopen('http://www.google.com', 'r'));
+$stream = new Psr7\CachingStream($original);
+
+$stream->read(1024);
+echo $stream->tell();
+// 1024
+
+$stream->seek(0);
+echo $stream->tell();
+// 0
+```
+
+
+## DroppingStream
+
+`GuzzleHttp\Psr7\DroppingStream`
+
+Stream decorator that begins dropping data once the size of the underlying
+stream becomes too full.
+
+```php
+use GuzzleHttp\Psr7;
+
+// Create an empty stream
+$stream = Psr7\stream_for();
+
+// Start dropping data when the stream has more than 10 bytes
+$dropping = new Psr7\DroppingStream($stream, 10);
+
+$dropping->write('01234567890123456789');
+echo $stream; // 0123456789
+```
+
+
+## FnStream
+
+`GuzzleHttp\Psr7\FnStream`
+
+Compose stream implementations based on a hash of functions.
+
+Allows for easy testing and extension of a provided stream without needing
+to create a concrete class for a simple extension point.
+
+```php
+
+use GuzzleHttp\Psr7;
+
+$stream = Psr7\stream_for('hi');
+$fnStream = Psr7\FnStream::decorate($stream, [
+    'rewind' => function () use ($stream) {
+        echo 'About to rewind - ';
+        $stream->rewind();
+        echo 'rewound!';
+    }
+]);
+
+$fnStream->rewind();
+// Outputs: About to rewind - rewound!
+```
+
+
+## InflateStream
+
+`GuzzleHttp\Psr7\InflateStream`
+
+Uses PHP's zlib.inflate filter to inflate deflate or gzipped content.
+
+This stream decorator skips the first 10 bytes of the given stream to remove
+the gzip header, converts the provided stream to a PHP stream resource,
+then appends the zlib.inflate filter. The stream is then converted back
+to a Guzzle stream resource to be used as a Guzzle stream.
+
+
+## LazyOpenStream
+
+`GuzzleHttp\Psr7\LazyOpenStream`
+
+Lazily reads or writes to a file that is opened only after an IO operation
+take place on the stream.
+
+```php
+use GuzzleHttp\Psr7;
+
+$stream = new Psr7\LazyOpenStream('/path/to/file', 'r');
+// The file has not yet been opened...
+
+echo $stream->read(10);
+// The file is opened and read from only when needed.
+```
+
+
+## LimitStream
+
+`GuzzleHttp\Psr7\LimitStream`
+
+LimitStream can be used to read a subset or slice of an existing stream object.
+This can be useful for breaking a large file into smaller pieces to be sent in
+chunks (e.g. Amazon S3's multipart upload API).
+
+```php
+use GuzzleHttp\Psr7;
+
+$original = Psr7\stream_for(fopen('/tmp/test.txt', 'r+'));
+echo $original->getSize();
+// >>> 1048576
+
+// Limit the size of the body to 1024 bytes and start reading from byte 2048
+$stream = new Psr7\LimitStream($original, 1024, 2048);
+echo $stream->getSize();
+// >>> 1024
+echo $stream->tell();
+// >>> 0
+```
+
+
+## MultipartStream
+
+`GuzzleHttp\Psr7\MultipartStream`
+
+Stream that when read returns bytes for a streaming multipart or
+multipart/form-data stream.
+
+
+## NoSeekStream
+
+`GuzzleHttp\Psr7\NoSeekStream`
+
+NoSeekStream wraps a stream and does not allow seeking.
+
+```php
+use GuzzleHttp\Psr7;
+
+$original = Psr7\stream_for('foo');
+$noSeek = new Psr7\NoSeekStream($original);
+
+echo $noSeek->read(3);
+// foo
+var_export($noSeek->isSeekable());
+// false
+$noSeek->seek(0);
+var_export($noSeek->read(3));
+// NULL
+```
+
+
+## PumpStream
+
+`GuzzleHttp\Psr7\PumpStream`
+
+Provides a read only stream that pumps data from a PHP callable.
+
+When invoking the provided callable, the PumpStream will pass the amount of
+data requested to read to the callable. The callable can choose to ignore
+this value and return fewer or more bytes than requested. Any extra data
+returned by the provided callable is buffered internally until drained using
+the read() function of the PumpStream. The provided callable MUST return
+false when there is no more data to read.
+
+
+## Implementing stream decorators
+
+Creating a stream decorator is very easy thanks to the
+`GuzzleHttp\Psr7\StreamDecoratorTrait`. This trait provides methods that
+implement `Psr\Http\Message\StreamInterface` by proxying to an underlying
+stream. Just `use` the `StreamDecoratorTrait` and implement your custom
+methods.
+
+For example, let's say we wanted to call a specific function each time the last
+byte is read from a stream. This could be implemented by overriding the
+`read()` method.
+
+```php
+use Psr\Http\Message\StreamInterface;
+use GuzzleHttp\Psr7\StreamDecoratorTrait;
+
+class EofCallbackStream implements StreamInterface
+{
+    use StreamDecoratorTrait;
+
+    private $callback;
+
+    public function __construct(StreamInterface $stream, callable $cb)
+    {
+        $this->stream = $stream;
+        $this->callback = $cb;
+    }
+
+    public function read($length)
+    {
+        $result = $this->stream->read($length);
+
+        // Invoke the callback when EOF is hit.
+        if ($this->eof()) {
+            call_user_func($this->callback);
+        }
+
+        return $result;
+    }
+}
+```
+
+This decorator could be added to any existing stream and used like so:
+
+```php
+use GuzzleHttp\Psr7;
+
+$original = Psr7\stream_for('foo');
+
+$eofStream = new EofCallbackStream($original, function () {
+    echo 'EOF!';
+});
+
+$eofStream->read(2);
+$eofStream->read(1);
+// echoes "EOF!"
+$eofStream->seek(0);
+$eofStream->read(3);
+// echoes "EOF!"
+```
+
+
+## PHP StreamWrapper
+
+You can use the `GuzzleHttp\Psr7\StreamWrapper` class if you need to use a
+PSR-7 stream as a PHP stream resource.
+
+Use the `GuzzleHttp\Psr7\StreamWrapper::getResource()` method to create a PHP
+stream from a PSR-7 stream.
+
+```php
+use GuzzleHttp\Psr7\StreamWrapper;
+
+$stream = GuzzleHttp\Psr7\stream_for('hello!');
+$resource = StreamWrapper::getResource($stream);
+echo fread($resource, 6); // outputs hello!
+```
+
+
+# Function API
+
+There are various functions available under the `GuzzleHttp\Psr7` namespace.
+
+
+## `function str`
+
+`function str(MessageInterface $message)`
+
+Returns the string representation of an HTTP message.
+
+```php
+$request = new GuzzleHttp\Psr7\Request('GET', 'http://example.com');
+echo GuzzleHttp\Psr7\str($request);
+```
+
+
+## `function uri_for`
+
+`function uri_for($uri)`
+
+This function accepts a string or `Psr\Http\Message\UriInterface` and returns a
+UriInterface for the given value. If the value is already a `UriInterface`, it
+is returned as-is.
+
+```php
+$uri = GuzzleHttp\Psr7\uri_for('http://example.com');
+assert($uri === GuzzleHttp\Psr7\uri_for($uri));
+```
+
+
+## `function stream_for`
+
+`function stream_for($resource = '', array $options = [])`
+
+Create a new stream based on the input type.
+
+Options is an associative array that can contain the following keys:
+
+* - metadata: Array of custom metadata.
+* - size: Size of the stream.
+
+This method accepts the following `$resource` types:
+
+- `Psr\Http\Message\StreamInterface`: Returns the value as-is.
+- `string`: Creates a stream object that uses the given string as the contents.
+- `resource`: Creates a stream object that wraps the given PHP stream resource.
+- `Iterator`: If the provided value implements `Iterator`, then a read-only
+  stream object will be created that wraps the given iterable. Each time the
+  stream is read from, data from the iterator will fill a buffer and will be
+  continuously called until the buffer is equal to the requested read size.
+  Subsequent read calls will first read from the buffer and then call `next`
+  on the underlying iterator until it is exhausted.
+- `object` with `__toString()`: If the object has the `__toString()` method,
+  the object will be cast to a string and then a stream will be returned that
+  uses the string value.
+- `NULL`: When `null` is passed, an empty stream object is returned.
+- `callable` When a callable is passed, a read-only stream object will be
+  created that invokes the given callable. The callable is invoked with the
+  number of suggested bytes to read. The callable can return any number of
+  bytes, but MUST return `false` when there is no more data to return. The
+  stream object that wraps the callable will invoke the callable until the
+  number of requested bytes are available. Any additional bytes will be
+  buffered and used in subsequent reads.
+
+```php
+$stream = GuzzleHttp\Psr7\stream_for('foo');
+$stream = GuzzleHttp\Psr7\stream_for(fopen('/path/to/file', 'r'));
+
+$generator function ($bytes) {
+    for ($i = 0; $i < $bytes; $i++) {
+        yield ' ';
+    }
+}
+
+$stream = GuzzleHttp\Psr7\stream_for($generator(100));
+```
+
+
+## `function parse_header`
+
+`function parse_header($header)`
+
+Parse an array of header values containing ";" separated data into an array of
+associative arrays representing the header key value pair data of the header.
+When a parameter does not contain a value, but just contains a key, this
+function will inject a key with a '' string value.
+
+
+## `function normalize_header`
+
+`function normalize_header($header)`
+
+Converts an array of header values that may contain comma separated headers
+into an array of headers with no comma separated values.
+
+
+## `function modify_request`
+
+`function modify_request(RequestInterface $request, array $changes)`
+
+Clone and modify a request with the given changes. This method is useful for
+reducing the number of clones needed to mutate a message.
+
+The changes can be one of:
+
+- method: (string) Changes the HTTP method.
+- set_headers: (array) Sets the given headers.
+- remove_headers: (array) Remove the given headers.
+- body: (mixed) Sets the given body.
+- uri: (UriInterface) Set the URI.
+- query: (string) Set the query string value of the URI.
+- version: (string) Set the protocol version.
+
+
+## `function rewind_body`
+
+`function rewind_body(MessageInterface $message)`
+
+Attempts to rewind a message body and throws an exception on failure. The body
+of the message will only be rewound if a call to `tell()` returns a value other
+than `0`.
+
+
+## `function try_fopen`
+
+`function try_fopen($filename, $mode)`
+
+Safely opens a PHP stream resource using a filename.
+
+When fopen fails, PHP normally raises a warning. This function adds an error
+handler that checks for errors and throws an exception instead.
+
+
+## `function copy_to_string`
+
+`function copy_to_string(StreamInterface $stream, $maxLen = -1)`
+
+Copy the contents of a stream into a string until the given number of bytes
+have been read.
+
+
+## `function copy_to_stream`
+
+`function copy_to_stream(StreamInterface $source, StreamInterface $dest, $maxLen = -1)`
+
+Copy the contents of a stream into another stream until the given number of
+bytes have been read.
+
+
+## `function hash`
+
+`function hash(StreamInterface $stream, $algo, $rawOutput = false)`
+
+Calculate a hash of a Stream. This method reads the entire stream to calculate
+a rolling hash (based on PHP's hash_init functions).
+
+
+## `function readline`
+
+`function readline(StreamInterface $stream, $maxLength = null)`
+
+Read a line from the stream up to the maximum allowed buffer length.
+
+
+## `function parse_request`
+
+`function parse_request($message)`
+
+Parses a request message string into a request object.
+
+
+## `function parse_response`
+
+`function parse_response($message)`
+
+Parses a response message string into a response object.
+
+
+## `function parse_query`
+
+`function parse_query($str, $urlEncoding = true)`
+
+Parse a query string into an associative array.
+
+If multiple values are found for the same key, the value of that key value pair
+will become an array. This function does not parse nested PHP style arrays into
+an associative array (e.g., `foo[a]=1&foo[b]=2` will be parsed into
+`['foo[a]' => '1', 'foo[b]' => '2']`).
+
+
+## `function build_query`
+
+`function build_query(array $params, $encoding = PHP_QUERY_RFC3986)`
+
+Build a query string from an array of key value pairs.
+
+This function can use the return value of parse_query() to build a query string.
+This function does not modify the provided keys when an array is encountered
+(like http_build_query would).
+
+
+## `function mimetype_from_filename`
+
+`function mimetype_from_filename($filename)`
+
+Determines the mimetype of a file by looking at its extension.
+
+
+## `function mimetype_from_extension`
+
+`function mimetype_from_extension($extension)`
+
+Maps a file extensions to a mimetype.
+
+
+# Additional URI Methods
+
+Aside from the standard `Psr\Http\Message\UriInterface` implementation in form of the `GuzzleHttp\Psr7\Uri` class,
+this library also provides additional functionality when working with URIs as static methods.
+
+## URI Types
+
+An instance of `Psr\Http\Message\UriInterface` can either be an absolute URI or a relative reference.
+An absolute URI has a scheme. A relative reference is used to express a URI relative to another URI,
+the base URI. Relative references can be divided into several forms according to
+[RFC 3986 Section 4.2](https://tools.ietf.org/html/rfc3986#section-4.2):
+
+- network-path references, e.g. `//example.com/path`
+- absolute-path references, e.g. `/path`
+- relative-path references, e.g. `subpath`
+
+The following methods can be used to identify the type of the URI.
+
+### `GuzzleHttp\Psr7\Uri::isAbsolute`
+
+`public static function isAbsolute(UriInterface $uri): bool`
+
+Whether the URI is absolute, i.e. it has a scheme.
+
+### `GuzzleHttp\Psr7\Uri::isNetworkPathReference`
+
+`public static function isNetworkPathReference(UriInterface $uri): bool`
+
+Whether the URI is a network-path reference. A relative reference that begins with two slash characters is
+termed an network-path reference.
+
+### `GuzzleHttp\Psr7\Uri::isAbsolutePathReference`
+
+`public static function isAbsolutePathReference(UriInterface $uri): bool`
+
+Whether the URI is a absolute-path reference. A relative reference that begins with a single slash character is
+termed an absolute-path reference.
+
+### `GuzzleHttp\Psr7\Uri::isRelativePathReference`
+
+`public static function isRelativePathReference(UriInterface $uri): bool`
+
+Whether the URI is a relative-path reference. A relative reference that does not begin with a slash character is
+termed a relative-path reference.
+
+### `GuzzleHttp\Psr7\Uri::isSameDocumentReference`
+
+`public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null): bool`
+
+Whether the URI is a same-document reference. A same-document reference refers to a URI that is, aside from its
+fragment component, identical to the base URI. When no base URI is given, only an empty URI reference
+(apart from its fragment) is considered a same-document reference.
+
+## URI Components
+
+Additional methods to work with URI components.
+
+### `GuzzleHttp\Psr7\Uri::isDefaultPort`
+
+`public static function isDefaultPort(UriInterface $uri): bool`
+
+Whether the URI has the default port of the current scheme. `Psr\Http\Message\UriInterface::getPort` may return null
+or the standard port. This method can be used independently of the implementation.
+
+### `GuzzleHttp\Psr7\Uri::composeComponents`
+
+`public static function composeComponents($scheme, $authority, $path, $query, $fragment): string`
+
+Composes a URI reference string from its various components according to
+[RFC 3986 Section 5.3](https://tools.ietf.org/html/rfc3986#section-5.3). Usually this method does not need to be called
+manually but instead is used indirectly via `Psr\Http\Message\UriInterface::__toString`.
+
+### `GuzzleHttp\Psr7\Uri::fromParts`
+
+`public static function fromParts(array $parts): UriInterface`
+
+Creates a URI from a hash of [`parse_url`](http://php.net/manual/en/function.parse-url.php) components.
+
+
+### `GuzzleHttp\Psr7\Uri::withQueryValue`
+
+`public static function withQueryValue(UriInterface $uri, $key, $value): UriInterface`
+
+Creates a new URI with a specific query string value. Any existing query string values that exactly match the
+provided key are removed and replaced with the given key value pair. A value of null will set the query string
+key without a value, e.g. "key" instead of "key=value".
+
+
+### `GuzzleHttp\Psr7\Uri::withoutQueryValue`
+
+`public static function withoutQueryValue(UriInterface $uri, $key): UriInterface`
+
+Creates a new URI with a specific query string value removed. Any existing query string values that exactly match the
+provided key are removed.
+
+## Reference Resolution
+
+`GuzzleHttp\Psr7\UriResolver` provides methods to resolve a URI reference in the context of a base URI according
+to [RFC 3986 Section 5](https://tools.ietf.org/html/rfc3986#section-5). This is for example also what web browsers
+do when resolving a link in a website based on the current request URI.
+
+### `GuzzleHttp\Psr7\UriResolver::resolve`
+
+`public static function resolve(UriInterface $base, UriInterface $rel): UriInterface`
+
+Converts the relative URI into a new URI that is resolved against the base URI.
+
+### `GuzzleHttp\Psr7\UriResolver::removeDotSegments`
+
+`public static function removeDotSegments(string $path): string`
+
+Removes dot segments from a path and returns the new path according to
+[RFC 3986 Section 5.2.4](https://tools.ietf.org/html/rfc3986#section-5.2.4).
+
+### `GuzzleHttp\Psr7\UriResolver::relativize`
+
+`public static function relativize(UriInterface $base, UriInterface $target): UriInterface`
+
+Returns the target URI as a relative reference from the base URI. This method is the counterpart to resolve():
+
+```php
+(string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target))
+```
+
+One use-case is to use the current request URI as base URI and then generate relative links in your documents
+to reduce the document size or offer self-contained downloadable document archives.
+
+```php
+$base = new Uri('http://example.com/a/b/');
+echo UriResolver::relativize($base, new Uri('http://example.com/a/b/c'));  // prints 'c'.
+echo UriResolver::relativize($base, new Uri('http://example.com/a/x/y'));  // prints '../x/y'.
+echo UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'.
+echo UriResolver::relativize($base, new Uri('http://example.org/a/b/'));   // prints '//example.org/a/b/'.
+```
+
+## Normalization and Comparison
+
+`GuzzleHttp\Psr7\UriNormalizer` provides methods to normalize and compare URIs according to
+[RFC 3986 Section 6](https://tools.ietf.org/html/rfc3986#section-6).
+
+### `GuzzleHttp\Psr7\UriNormalizer::normalize`
+
+`public static function normalize(UriInterface $uri, $flags = self::PRESERVING_NORMALIZATIONS): UriInterface`
+
+Returns a normalized URI. The scheme and host component are already normalized to lowercase per PSR-7 UriInterface.
+This methods adds additional normalizations that can be configured with the `$flags` parameter which is a bitmask
+of normalizations to apply. The following normalizations are available:
+
+- `UriNormalizer::PRESERVING_NORMALIZATIONS`
+
+    Default normalizations which only include the ones that preserve semantics.
+
+- `UriNormalizer::CAPITALIZE_PERCENT_ENCODING`
+
+    All letters within a percent-encoding triplet (e.g., "%3A") are case-insensitive, and should be capitalized.
+
+    Example: `http://example.org/a%c2%b1b` → `http://example.org/a%C2%B1b`
+
+- `UriNormalizer::DECODE_UNRESERVED_CHARACTERS`
+
+    Decodes percent-encoded octets of unreserved characters. For consistency, percent-encoded octets in the ranges of
+    ALPHA (%41–%5A and %61–%7A), DIGIT (%30–%39), hyphen (%2D), period (%2E), underscore (%5F), or tilde (%7E) should
+    not be created by URI producers and, when found in a URI, should be decoded to their corresponding unreserved
+    characters by URI normalizers.
+
+    Example: `http://example.org/%7Eusern%61me/` → `http://example.org/~username/`
+
+- `UriNormalizer::CONVERT_EMPTY_PATH`
+
+    Converts the empty path to "/" for http and https URIs.
+
+    Example: `http://example.org` → `http://example.org/`
+
+- `UriNormalizer::REMOVE_DEFAULT_HOST`
+
+    Removes the default host of the given URI scheme from the URI. Only the "file" scheme defines the default host
+    "localhost". All of `file:/myfile`, `file:///myfile`, and `file://localhost/myfile` are equivalent according to
+    RFC 3986.
+
+    Example: `file://localhost/myfile` → `file:///myfile`
+
+- `UriNormalizer::REMOVE_DEFAULT_PORT`
+
+    Removes the default port of the given URI scheme from the URI.
+
+    Example: `http://example.org:80/` → `http://example.org/`
+
+- `UriNormalizer::REMOVE_DOT_SEGMENTS`
+
+    Removes unnecessary dot-segments. Dot-segments in relative-path references are not removed as it would
+    change the semantics of the URI reference.
+
+    Example: `http://example.org/../a/b/../c/./d.html` → `http://example.org/a/c/d.html`
+
+- `UriNormalizer::REMOVE_DUPLICATE_SLASHES`
+
+    Paths which include two or more adjacent slashes are converted to one. Webservers usually ignore duplicate slashes
+    and treat those URIs equivalent. But in theory those URIs do not need to be equivalent. So this normalization
+    may change the semantics. Encoded slashes (%2F) are not removed.
+
+    Example: `http://example.org//foo///bar.html` → `http://example.org/foo/bar.html`
+
+- `UriNormalizer::SORT_QUERY_PARAMETERS`
+
+    Sort query parameters with their values in alphabetical order. However, the order of parameters in a URI may be
+    significant (this is not defined by the standard). So this normalization is not safe and may change the semantics
+    of the URI.
+
+    Example: `?lang=en&article=fred` → `?article=fred&lang=en`
+
+### `GuzzleHttp\Psr7\UriNormalizer::isEquivalent`
+
+`public static function isEquivalent(UriInterface $uri1, UriInterface $uri2, $normalizations = self::PRESERVING_NORMALIZATIONS): bool`
+
+Whether two URIs can be considered equivalent. Both URIs are normalized automatically before comparison with the given
+`$normalizations` bitmask. The method also accepts relative URI references and returns true when they are equivalent.
+This of course assumes they will be resolved against the same base URI. If this is not the case, determination of
+equivalence or difference of relative references does not mean anything.
diff --git a/vendor/guzzlehttp/psr7/composer.json b/vendor/guzzlehttp/psr7/composer.json
new file mode 100644
index 00000000000..b1c5a90ba71
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/composer.json
@@ -0,0 +1,39 @@
+{
+    "name": "guzzlehttp/psr7",
+    "type": "library",
+    "description": "PSR-7 message implementation that also provides common utility methods",
+    "keywords": ["request", "response", "message", "stream", "http", "uri", "url"],
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Michael Dowling",
+            "email": "mtdowling@gmail.com",
+            "homepage": "https://github.com/mtdowling"
+        },
+        {
+            "name": "Tobias Schultze",
+            "homepage": "https://github.com/Tobion"
+        }
+    ],
+    "require": {
+        "php": ">=5.4.0",
+        "psr/http-message": "~1.0"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "~4.0"
+    },
+    "provide": {
+        "psr/http-message-implementation": "1.0"
+    },
+    "autoload": {
+        "psr-4": {
+            "GuzzleHttp\\Psr7\\": "src/"
+        },
+        "files": ["src/functions_include.php"]
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "1.4-dev"
+        }
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/AppendStream.php b/vendor/guzzlehttp/psr7/src/AppendStream.php
new file mode 100644
index 00000000000..23039fd794b
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/AppendStream.php
@@ -0,0 +1,233 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Reads from multiple streams, one after the other.
+ *
+ * This is a read-only stream decorator.
+ */
+class AppendStream implements StreamInterface
+{
+    /** @var StreamInterface[] Streams being decorated */
+    private $streams = [];
+
+    private $seekable = true;
+    private $current = 0;
+    private $pos = 0;
+    private $detached = false;
+
+    /**
+     * @param StreamInterface[] $streams Streams to decorate. Each stream must
+     *                                   be readable.
+     */
+    public function __construct(array $streams = [])
+    {
+        foreach ($streams as $stream) {
+            $this->addStream($stream);
+        }
+    }
+
+    public function __toString()
+    {
+        try {
+            $this->rewind();
+            return $this->getContents();
+        } catch (\Exception $e) {
+            return '';
+        }
+    }
+
+    /**
+     * Add a stream to the AppendStream
+     *
+     * @param StreamInterface $stream Stream to append. Must be readable.
+     *
+     * @throws \InvalidArgumentException if the stream is not readable
+     */
+    public function addStream(StreamInterface $stream)
+    {
+        if (!$stream->isReadable()) {
+            throw new \InvalidArgumentException('Each stream must be readable');
+        }
+
+        // The stream is only seekable if all streams are seekable
+        if (!$stream->isSeekable()) {
+            $this->seekable = false;
+        }
+
+        $this->streams[] = $stream;
+    }
+
+    public function getContents()
+    {
+        return copy_to_string($this);
+    }
+
+    /**
+     * Closes each attached stream.
+     *
+     * {@inheritdoc}
+     */
+    public function close()
+    {
+        $this->pos = $this->current = 0;
+
+        foreach ($this->streams as $stream) {
+            $stream->close();
+        }
+
+        $this->streams = [];
+    }
+
+    /**
+     * Detaches each attached stream
+     *
+     * {@inheritdoc}
+     */
+    public function detach()
+    {
+        $this->close();
+        $this->detached = true;
+    }
+
+    public function tell()
+    {
+        return $this->pos;
+    }
+
+    /**
+     * Tries to calculate the size by adding the size of each stream.
+     *
+     * If any of the streams do not return a valid number, then the size of the
+     * append stream cannot be determined and null is returned.
+     *
+     * {@inheritdoc}
+     */
+    public function getSize()
+    {
+        $size = 0;
+
+        foreach ($this->streams as $stream) {
+            $s = $stream->getSize();
+            if ($s === null) {
+                return null;
+            }
+            $size += $s;
+        }
+
+        return $size;
+    }
+
+    public function eof()
+    {
+        return !$this->streams ||
+            ($this->current >= count($this->streams) - 1 &&
+             $this->streams[$this->current]->eof());
+    }
+
+    public function rewind()
+    {
+        $this->seek(0);
+    }
+
+    /**
+     * Attempts to seek to the given position. Only supports SEEK_SET.
+     *
+     * {@inheritdoc}
+     */
+    public function seek($offset, $whence = SEEK_SET)
+    {
+        if (!$this->seekable) {
+            throw new \RuntimeException('This AppendStream is not seekable');
+        } elseif ($whence !== SEEK_SET) {
+            throw new \RuntimeException('The AppendStream can only seek with SEEK_SET');
+        }
+
+        $this->pos = $this->current = 0;
+
+        // Rewind each stream
+        foreach ($this->streams as $i => $stream) {
+            try {
+                $stream->rewind();
+            } catch (\Exception $e) {
+                throw new \RuntimeException('Unable to seek stream '
+                    . $i . ' of the AppendStream', 0, $e);
+            }
+        }
+
+        // Seek to the actual position by reading from each stream
+        while ($this->pos < $offset && !$this->eof()) {
+            $result = $this->read(min(8096, $offset - $this->pos));
+            if ($result === '') {
+                break;
+            }
+        }
+    }
+
+    /**
+     * Reads from all of the appended streams until the length is met or EOF.
+     *
+     * {@inheritdoc}
+     */
+    public function read($length)
+    {
+        $buffer = '';
+        $total = count($this->streams) - 1;
+        $remaining = $length;
+        $progressToNext = false;
+
+        while ($remaining > 0) {
+
+            // Progress to the next stream if needed.
+            if ($progressToNext || $this->streams[$this->current]->eof()) {
+                $progressToNext = false;
+                if ($this->current === $total) {
+                    break;
+                }
+                $this->current++;
+            }
+
+            $result = $this->streams[$this->current]->read($remaining);
+
+            // Using a loose comparison here to match on '', false, and null
+            if ($result == null) {
+                $progressToNext = true;
+                continue;
+            }
+
+            $buffer .= $result;
+            $remaining = $length - strlen($buffer);
+        }
+
+        $this->pos += strlen($buffer);
+
+        return $buffer;
+    }
+
+    public function isReadable()
+    {
+        return true;
+    }
+
+    public function isWritable()
+    {
+        return false;
+    }
+
+    public function isSeekable()
+    {
+        return $this->seekable;
+    }
+
+    public function write($string)
+    {
+        throw new \RuntimeException('Cannot write to an AppendStream');
+    }
+
+    public function getMetadata($key = null)
+    {
+        return $key ? null : [];
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/BufferStream.php b/vendor/guzzlehttp/psr7/src/BufferStream.php
new file mode 100644
index 00000000000..af4d4c22777
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/BufferStream.php
@@ -0,0 +1,137 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Provides a buffer stream that can be written to to fill a buffer, and read
+ * from to remove bytes from the buffer.
+ *
+ * This stream returns a "hwm" metadata value that tells upstream consumers
+ * what the configured high water mark of the stream is, or the maximum
+ * preferred size of the buffer.
+ */
+class BufferStream implements StreamInterface
+{
+    private $hwm;
+    private $buffer = '';
+
+    /**
+     * @param int $hwm High water mark, representing the preferred maximum
+     *                 buffer size. If the size of the buffer exceeds the high
+     *                 water mark, then calls to write will continue to succeed
+     *                 but will return false to inform writers to slow down
+     *                 until the buffer has been drained by reading from it.
+     */
+    public function __construct($hwm = 16384)
+    {
+        $this->hwm = $hwm;
+    }
+
+    public function __toString()
+    {
+        return $this->getContents();
+    }
+
+    public function getContents()
+    {
+        $buffer = $this->buffer;
+        $this->buffer = '';
+
+        return $buffer;
+    }
+
+    public function close()
+    {
+        $this->buffer = '';
+    }
+
+    public function detach()
+    {
+        $this->close();
+    }
+
+    public function getSize()
+    {
+        return strlen($this->buffer);
+    }
+
+    public function isReadable()
+    {
+        return true;
+    }
+
+    public function isWritable()
+    {
+        return true;
+    }
+
+    public function isSeekable()
+    {
+        return false;
+    }
+
+    public function rewind()
+    {
+        $this->seek(0);
+    }
+
+    public function seek($offset, $whence = SEEK_SET)
+    {
+        throw new \RuntimeException('Cannot seek a BufferStream');
+    }
+
+    public function eof()
+    {
+        return strlen($this->buffer) === 0;
+    }
+
+    public function tell()
+    {
+        throw new \RuntimeException('Cannot determine the position of a BufferStream');
+    }
+
+    /**
+     * Reads data from the buffer.
+     */
+    public function read($length)
+    {
+        $currentLength = strlen($this->buffer);
+
+        if ($length >= $currentLength) {
+            // No need to slice the buffer because we don't have enough data.
+            $result = $this->buffer;
+            $this->buffer = '';
+        } else {
+            // Slice up the result to provide a subset of the buffer.
+            $result = substr($this->buffer, 0, $length);
+            $this->buffer = substr($this->buffer, $length);
+        }
+
+        return $result;
+    }
+
+    /**
+     * Writes data to the buffer.
+     */
+    public function write($string)
+    {
+        $this->buffer .= $string;
+
+        // TODO: What should happen here?
+        if (strlen($this->buffer) >= $this->hwm) {
+            return false;
+        }
+
+        return strlen($string);
+    }
+
+    public function getMetadata($key = null)
+    {
+        if ($key == 'hwm') {
+            return $this->hwm;
+        }
+
+        return $key ? null : [];
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/CachingStream.php b/vendor/guzzlehttp/psr7/src/CachingStream.php
new file mode 100644
index 00000000000..ed68f0861aa
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/CachingStream.php
@@ -0,0 +1,138 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Stream decorator that can cache previously read bytes from a sequentially
+ * read stream.
+ */
+class CachingStream implements StreamInterface
+{
+    use StreamDecoratorTrait;
+
+    /** @var StreamInterface Stream being wrapped */
+    private $remoteStream;
+
+    /** @var int Number of bytes to skip reading due to a write on the buffer */
+    private $skipReadBytes = 0;
+
+    /**
+     * We will treat the buffer object as the body of the stream
+     *
+     * @param StreamInterface $stream Stream to cache
+     * @param StreamInterface $target Optionally specify where data is cached
+     */
+    public function __construct(
+        StreamInterface $stream,
+        StreamInterface $target = null
+    ) {
+        $this->remoteStream = $stream;
+        $this->stream = $target ?: new Stream(fopen('php://temp', 'r+'));
+    }
+
+    public function getSize()
+    {
+        return max($this->stream->getSize(), $this->remoteStream->getSize());
+    }
+
+    public function rewind()
+    {
+        $this->seek(0);
+    }
+
+    public function seek($offset, $whence = SEEK_SET)
+    {
+        if ($whence == SEEK_SET) {
+            $byte = $offset;
+        } elseif ($whence == SEEK_CUR) {
+            $byte = $offset + $this->tell();
+        } elseif ($whence == SEEK_END) {
+            $size = $this->remoteStream->getSize();
+            if ($size === null) {
+                $size = $this->cacheEntireStream();
+            }
+            $byte = $size + $offset;
+        } else {
+            throw new \InvalidArgumentException('Invalid whence');
+        }
+
+        $diff = $byte - $this->stream->getSize();
+
+        if ($diff > 0) {
+            // Read the remoteStream until we have read in at least the amount
+            // of bytes requested, or we reach the end of the file.
+            while ($diff > 0 && !$this->remoteStream->eof()) {
+                $this->read($diff);
+                $diff = $byte - $this->stream->getSize();
+            }
+        } else {
+            // We can just do a normal seek since we've already seen this byte.
+            $this->stream->seek($byte);
+        }
+    }
+
+    public function read($length)
+    {
+        // Perform a regular read on any previously read data from the buffer
+        $data = $this->stream->read($length);
+        $remaining = $length - strlen($data);
+
+        // More data was requested so read from the remote stream
+        if ($remaining) {
+            // If data was written to the buffer in a position that would have
+            // been filled from the remote stream, then we must skip bytes on
+            // the remote stream to emulate overwriting bytes from that
+            // position. This mimics the behavior of other PHP stream wrappers.
+            $remoteData = $this->remoteStream->read(
+                $remaining + $this->skipReadBytes
+            );
+
+            if ($this->skipReadBytes) {
+                $len = strlen($remoteData);
+                $remoteData = substr($remoteData, $this->skipReadBytes);
+                $this->skipReadBytes = max(0, $this->skipReadBytes - $len);
+            }
+
+            $data .= $remoteData;
+            $this->stream->write($remoteData);
+        }
+
+        return $data;
+    }
+
+    public function write($string)
+    {
+        // When appending to the end of the currently read stream, you'll want
+        // to skip bytes from being read from the remote stream to emulate
+        // other stream wrappers. Basically replacing bytes of data of a fixed
+        // length.
+        $overflow = (strlen($string) + $this->tell()) - $this->remoteStream->tell();
+        if ($overflow > 0) {
+            $this->skipReadBytes += $overflow;
+        }
+
+        return $this->stream->write($string);
+    }
+
+    public function eof()
+    {
+        return $this->stream->eof() && $this->remoteStream->eof();
+    }
+
+    /**
+     * Close both the remote stream and buffer stream
+     */
+    public function close()
+    {
+        $this->remoteStream->close() && $this->stream->close();
+    }
+
+    private function cacheEntireStream()
+    {
+        $target = new FnStream(['write' => 'strlen']);
+        copy_to_stream($this, $target);
+
+        return $this->tell();
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/DroppingStream.php b/vendor/guzzlehttp/psr7/src/DroppingStream.php
new file mode 100644
index 00000000000..8935c80d729
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/DroppingStream.php
@@ -0,0 +1,42 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Stream decorator that begins dropping data once the size of the underlying
+ * stream becomes too full.
+ */
+class DroppingStream implements StreamInterface
+{
+    use StreamDecoratorTrait;
+
+    private $maxLength;
+
+    /**
+     * @param StreamInterface $stream    Underlying stream to decorate.
+     * @param int             $maxLength Maximum size before dropping data.
+     */
+    public function __construct(StreamInterface $stream, $maxLength)
+    {
+        $this->stream = $stream;
+        $this->maxLength = $maxLength;
+    }
+
+    public function write($string)
+    {
+        $diff = $this->maxLength - $this->stream->getSize();
+
+        // Begin returning 0 when the underlying stream is too large.
+        if ($diff <= 0) {
+            return 0;
+        }
+
+        // Write the stream or a subset of the stream if needed.
+        if (strlen($string) < $diff) {
+            return $this->stream->write($string);
+        }
+
+        return $this->stream->write(substr($string, 0, $diff));
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/FnStream.php b/vendor/guzzlehttp/psr7/src/FnStream.php
new file mode 100644
index 00000000000..cc9b4453f71
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/FnStream.php
@@ -0,0 +1,149 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Compose stream implementations based on a hash of functions.
+ *
+ * Allows for easy testing and extension of a provided stream without needing
+ * to create a concrete class for a simple extension point.
+ */
+class FnStream implements StreamInterface
+{
+    /** @var array */
+    private $methods;
+
+    /** @var array Methods that must be implemented in the given array */
+    private static $slots = ['__toString', 'close', 'detach', 'rewind',
+        'getSize', 'tell', 'eof', 'isSeekable', 'seek', 'isWritable', 'write',
+        'isReadable', 'read', 'getContents', 'getMetadata'];
+
+    /**
+     * @param array $methods Hash of method name to a callable.
+     */
+    public function __construct(array $methods)
+    {
+        $this->methods = $methods;
+
+        // Create the functions on the class
+        foreach ($methods as $name => $fn) {
+            $this->{'_fn_' . $name} = $fn;
+        }
+    }
+
+    /**
+     * Lazily determine which methods are not implemented.
+     * @throws \BadMethodCallException
+     */
+    public function __get($name)
+    {
+        throw new \BadMethodCallException(str_replace('_fn_', '', $name)
+            . '() is not implemented in the FnStream');
+    }
+
+    /**
+     * The close method is called on the underlying stream only if possible.
+     */
+    public function __destruct()
+    {
+        if (isset($this->_fn_close)) {
+            call_user_func($this->_fn_close);
+        }
+    }
+
+    /**
+     * Adds custom functionality to an underlying stream by intercepting
+     * specific method calls.
+     *
+     * @param StreamInterface $stream  Stream to decorate
+     * @param array           $methods Hash of method name to a closure
+     *
+     * @return FnStream
+     */
+    public static function decorate(StreamInterface $stream, array $methods)
+    {
+        // If any of the required methods were not provided, then simply
+        // proxy to the decorated stream.
+        foreach (array_diff(self::$slots, array_keys($methods)) as $diff) {
+            $methods[$diff] = [$stream, $diff];
+        }
+
+        return new self($methods);
+    }
+
+    public function __toString()
+    {
+        return call_user_func($this->_fn___toString);
+    }
+
+    public function close()
+    {
+        return call_user_func($this->_fn_close);
+    }
+
+    public function detach()
+    {
+        return call_user_func($this->_fn_detach);
+    }
+
+    public function getSize()
+    {
+        return call_user_func($this->_fn_getSize);
+    }
+
+    public function tell()
+    {
+        return call_user_func($this->_fn_tell);
+    }
+
+    public function eof()
+    {
+        return call_user_func($this->_fn_eof);
+    }
+
+    public function isSeekable()
+    {
+        return call_user_func($this->_fn_isSeekable);
+    }
+
+    public function rewind()
+    {
+        call_user_func($this->_fn_rewind);
+    }
+
+    public function seek($offset, $whence = SEEK_SET)
+    {
+        call_user_func($this->_fn_seek, $offset, $whence);
+    }
+
+    public function isWritable()
+    {
+        return call_user_func($this->_fn_isWritable);
+    }
+
+    public function write($string)
+    {
+        return call_user_func($this->_fn_write, $string);
+    }
+
+    public function isReadable()
+    {
+        return call_user_func($this->_fn_isReadable);
+    }
+
+    public function read($length)
+    {
+        return call_user_func($this->_fn_read, $length);
+    }
+
+    public function getContents()
+    {
+        return call_user_func($this->_fn_getContents);
+    }
+
+    public function getMetadata($key = null)
+    {
+        return call_user_func($this->_fn_getMetadata, $key);
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/InflateStream.php b/vendor/guzzlehttp/psr7/src/InflateStream.php
new file mode 100644
index 00000000000..0051d3fec5a
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/InflateStream.php
@@ -0,0 +1,52 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Uses PHP's zlib.inflate filter to inflate deflate or gzipped content.
+ *
+ * This stream decorator skips the first 10 bytes of the given stream to remove
+ * the gzip header, converts the provided stream to a PHP stream resource,
+ * then appends the zlib.inflate filter. The stream is then converted back
+ * to a Guzzle stream resource to be used as a Guzzle stream.
+ *
+ * @link http://tools.ietf.org/html/rfc1952
+ * @link http://php.net/manual/en/filters.compression.php
+ */
+class InflateStream implements StreamInterface
+{
+    use StreamDecoratorTrait;
+
+    public function __construct(StreamInterface $stream)
+    {
+        // read the first 10 bytes, ie. gzip header
+        $header = $stream->read(10);
+        $filenameHeaderLength = $this->getLengthOfPossibleFilenameHeader($stream, $header);
+        // Skip the header, that is 10 + length of filename + 1 (nil) bytes
+        $stream = new LimitStream($stream, -1, 10 + $filenameHeaderLength);
+        $resource = StreamWrapper::getResource($stream);
+        stream_filter_append($resource, 'zlib.inflate', STREAM_FILTER_READ);
+        $this->stream = new Stream($resource);
+    }
+
+    /**
+     * @param StreamInterface $stream
+     * @param $header
+     * @return int
+     */
+    private function getLengthOfPossibleFilenameHeader(StreamInterface $stream, $header)
+    {
+        $filename_header_length = 0;
+
+        if (substr(bin2hex($header), 6, 2) === '08') {
+            // we have a filename, read until nil
+            $filename_header_length = 1;
+            while ($stream->read(1) !== chr(0)) {
+                $filename_header_length++;
+            }
+        }
+
+        return $filename_header_length;
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/LazyOpenStream.php b/vendor/guzzlehttp/psr7/src/LazyOpenStream.php
new file mode 100644
index 00000000000..02cec3af493
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/LazyOpenStream.php
@@ -0,0 +1,39 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Lazily reads or writes to a file that is opened only after an IO operation
+ * take place on the stream.
+ */
+class LazyOpenStream implements StreamInterface
+{
+    use StreamDecoratorTrait;
+
+    /** @var string File to open */
+    private $filename;
+
+    /** @var string $mode */
+    private $mode;
+
+    /**
+     * @param string $filename File to lazily open
+     * @param string $mode     fopen mode to use when opening the stream
+     */
+    public function __construct($filename, $mode)
+    {
+        $this->filename = $filename;
+        $this->mode = $mode;
+    }
+
+    /**
+     * Creates the underlying stream lazily when required.
+     *
+     * @return StreamInterface
+     */
+    protected function createStream()
+    {
+        return stream_for(try_fopen($this->filename, $this->mode));
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/LimitStream.php b/vendor/guzzlehttp/psr7/src/LimitStream.php
new file mode 100644
index 00000000000..3c13d4f4115
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/LimitStream.php
@@ -0,0 +1,155 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+
+/**
+ * Decorator used to return only a subset of a stream
+ */
+class LimitStream implements StreamInterface
+{
+    use StreamDecoratorTrait;
+
+    /** @var int Offset to start reading from */
+    private $offset;
+
+    /** @var int Limit the number of bytes that can be read */
+    private $limit;
+
+    /**
+     * @param StreamInterface $stream Stream to wrap
+     * @param int             $limit  Total number of bytes to allow to be read
+     *                                from the stream. Pass -1 for no limit.
+     * @param int             $offset Position to seek to before reading (only
+     *                                works on seekable streams).
+     */
+    public function __construct(
+        StreamInterface $stream,
+        $limit = -1,
+        $offset = 0
+    ) {
+        $this->stream = $stream;
+        $this->setLimit($limit);
+        $this->setOffset($offset);
+    }
+
+    public function eof()
+    {
+        // Always return true if the underlying stream is EOF
+        if ($this->stream->eof()) {
+            return true;
+        }
+
+        // No limit and the underlying stream is not at EOF
+        if ($this->limit == -1) {
+            return false;
+        }
+
+        return $this->stream->tell() >= $this->offset + $this->limit;
+    }
+
+    /**
+     * Returns the size of the limited subset of data
+     * {@inheritdoc}
+     */
+    public function getSize()
+    {
+        if (null === ($length = $this->stream->getSize())) {
+            return null;
+        } elseif ($this->limit == -1) {
+            return $length - $this->offset;
+        } else {
+            return min($this->limit, $length - $this->offset);
+        }
+    }
+
+    /**
+     * Allow for a bounded seek on the read limited stream
+     * {@inheritdoc}
+     */
+    public function seek($offset, $whence = SEEK_SET)
+    {
+        if ($whence !== SEEK_SET || $offset < 0) {
+            throw new \RuntimeException(sprintf(
+                'Cannot seek to offset % with whence %s',
+                $offset,
+                $whence
+            ));
+        }
+
+        $offset += $this->offset;
+
+        if ($this->limit !== -1) {
+            if ($offset > $this->offset + $this->limit) {
+                $offset = $this->offset + $this->limit;
+            }
+        }
+
+        $this->stream->seek($offset);
+    }
+
+    /**
+     * Give a relative tell()
+     * {@inheritdoc}
+     */
+    public function tell()
+    {
+        return $this->stream->tell() - $this->offset;
+    }
+
+    /**
+     * Set the offset to start limiting from
+     *
+     * @param int $offset Offset to seek to and begin byte limiting from
+     *
+     * @throws \RuntimeException if the stream cannot be seeked.
+     */
+    public function setOffset($offset)
+    {
+        $current = $this->stream->tell();
+
+        if ($current !== $offset) {
+            // If the stream cannot seek to the offset position, then read to it
+            if ($this->stream->isSeekable()) {
+                $this->stream->seek($offset);
+            } elseif ($current > $offset) {
+                throw new \RuntimeException("Could not seek to stream offset $offset");
+            } else {
+                $this->stream->read($offset - $current);
+            }
+        }
+
+        $this->offset = $offset;
+    }
+
+    /**
+     * Set the limit of bytes that the decorator allows to be read from the
+     * stream.
+     *
+     * @param int $limit Number of bytes to allow to be read from the stream.
+     *                   Use -1 for no limit.
+     */
+    public function setLimit($limit)
+    {
+        $this->limit = $limit;
+    }
+
+    public function read($length)
+    {
+        if ($this->limit == -1) {
+            return $this->stream->read($length);
+        }
+
+        // Check if the current position is less than the total allowed
+        // bytes + original offset
+        $remaining = ($this->offset + $this->limit) - $this->stream->tell();
+        if ($remaining > 0) {
+            // Only return the amount of requested data, ensuring that the byte
+            // limit is not exceeded
+            return $this->stream->read(min($remaining, $length));
+        }
+
+        return '';
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/MessageTrait.php b/vendor/guzzlehttp/psr7/src/MessageTrait.php
new file mode 100644
index 00000000000..1e4da649ad5
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/MessageTrait.php
@@ -0,0 +1,183 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Trait implementing functionality common to requests and responses.
+ */
+trait MessageTrait
+{
+    /** @var array Map of all registered headers, as original name => array of values */
+    private $headers = [];
+
+    /** @var array Map of lowercase header name => original name at registration */
+    private $headerNames  = [];
+
+    /** @var string */
+    private $protocol = '1.1';
+
+    /** @var StreamInterface */
+    private $stream;
+
+    public function getProtocolVersion()
+    {
+        return $this->protocol;
+    }
+
+    public function withProtocolVersion($version)
+    {
+        if ($this->protocol === $version) {
+            return $this;
+        }
+
+        $new = clone $this;
+        $new->protocol = $version;
+        return $new;
+    }
+
+    public function getHeaders()
+    {
+        return $this->headers;
+    }
+
+    public function hasHeader($header)
+    {
+        return isset($this->headerNames[strtolower($header)]);
+    }
+
+    public function getHeader($header)
+    {
+        $header = strtolower($header);
+
+        if (!isset($this->headerNames[$header])) {
+            return [];
+        }
+
+        $header = $this->headerNames[$header];
+
+        return $this->headers[$header];
+    }
+
+    public function getHeaderLine($header)
+    {
+        return implode(', ', $this->getHeader($header));
+    }
+
+    public function withHeader($header, $value)
+    {
+        if (!is_array($value)) {
+            $value = [$value];
+        }
+
+        $value = $this->trimHeaderValues($value);
+        $normalized = strtolower($header);
+
+        $new = clone $this;
+        if (isset($new->headerNames[$normalized])) {
+            unset($new->headers[$new->headerNames[$normalized]]);
+        }
+        $new->headerNames[$normalized] = $header;
+        $new->headers[$header] = $value;
+
+        return $new;
+    }
+
+    public function withAddedHeader($header, $value)
+    {
+        if (!is_array($value)) {
+            $value = [$value];
+        }
+
+        $value = $this->trimHeaderValues($value);
+        $normalized = strtolower($header);
+
+        $new = clone $this;
+        if (isset($new->headerNames[$normalized])) {
+            $header = $this->headerNames[$normalized];
+            $new->headers[$header] = array_merge($this->headers[$header], $value);
+        } else {
+            $new->headerNames[$normalized] = $header;
+            $new->headers[$header] = $value;
+        }
+
+        return $new;
+    }
+
+    public function withoutHeader($header)
+    {
+        $normalized = strtolower($header);
+
+        if (!isset($this->headerNames[$normalized])) {
+            return $this;
+        }
+
+        $header = $this->headerNames[$normalized];
+
+        $new = clone $this;
+        unset($new->headers[$header], $new->headerNames[$normalized]);
+
+        return $new;
+    }
+
+    public function getBody()
+    {
+        if (!$this->stream) {
+            $this->stream = stream_for('');
+        }
+
+        return $this->stream;
+    }
+
+    public function withBody(StreamInterface $body)
+    {
+        if ($body === $this->stream) {
+            return $this;
+        }
+
+        $new = clone $this;
+        $new->stream = $body;
+        return $new;
+    }
+
+    private function setHeaders(array $headers)
+    {
+        $this->headerNames = $this->headers = [];
+        foreach ($headers as $header => $value) {
+            if (!is_array($value)) {
+                $value = [$value];
+            }
+
+            $value = $this->trimHeaderValues($value);
+            $normalized = strtolower($header);
+            if (isset($this->headerNames[$normalized])) {
+                $header = $this->headerNames[$normalized];
+                $this->headers[$header] = array_merge($this->headers[$header], $value);
+            } else {
+                $this->headerNames[$normalized] = $header;
+                $this->headers[$header] = $value;
+            }
+        }
+    }
+
+    /**
+     * Trims whitespace from the header values.
+     *
+     * Spaces and tabs ought to be excluded by parsers when extracting the field value from a header field.
+     *
+     * header-field = field-name ":" OWS field-value OWS
+     * OWS          = *( SP / HTAB )
+     *
+     * @param string[] $values Header values
+     *
+     * @return string[] Trimmed header values
+     *
+     * @see https://tools.ietf.org/html/rfc7230#section-3.2.4
+     */
+    private function trimHeaderValues(array $values)
+    {
+        return array_map(function ($value) {
+            return trim($value, " \t");
+        }, $values);
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/MultipartStream.php b/vendor/guzzlehttp/psr7/src/MultipartStream.php
new file mode 100644
index 00000000000..c0fd584f759
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/MultipartStream.php
@@ -0,0 +1,153 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Stream that when read returns bytes for a streaming multipart or
+ * multipart/form-data stream.
+ */
+class MultipartStream implements StreamInterface
+{
+    use StreamDecoratorTrait;
+
+    private $boundary;
+
+    /**
+     * @param array  $elements Array of associative arrays, each containing a
+     *                         required "name" key mapping to the form field,
+     *                         name, a required "contents" key mapping to a
+     *                         StreamInterface/resource/string, an optional
+     *                         "headers" associative array of custom headers,
+     *                         and an optional "filename" key mapping to a
+     *                         string to send as the filename in the part.
+     * @param string $boundary You can optionally provide a specific boundary
+     *
+     * @throws \InvalidArgumentException
+     */
+    public function __construct(array $elements = [], $boundary = null)
+    {
+        $this->boundary = $boundary ?: sha1(uniqid('', true));
+        $this->stream = $this->createStream($elements);
+    }
+
+    /**
+     * Get the boundary
+     *
+     * @return string
+     */
+    public function getBoundary()
+    {
+        return $this->boundary;
+    }
+
+    public function isWritable()
+    {
+        return false;
+    }
+
+    /**
+     * Get the headers needed before transferring the content of a POST file
+     */
+    private function getHeaders(array $headers)
+    {
+        $str = '';
+        foreach ($headers as $key => $value) {
+            $str .= "{$key}: {$value}\r\n";
+        }
+
+        return "--{$this->boundary}\r\n" . trim($str) . "\r\n\r\n";
+    }
+
+    /**
+     * Create the aggregate stream that will be used to upload the POST data
+     */
+    protected function createStream(array $elements)
+    {
+        $stream = new AppendStream();
+
+        foreach ($elements as $element) {
+            $this->addElement($stream, $element);
+        }
+
+        // Add the trailing boundary with CRLF
+        $stream->addStream(stream_for("--{$this->boundary}--\r\n"));
+
+        return $stream;
+    }
+
+    private function addElement(AppendStream $stream, array $element)
+    {
+        foreach (['contents', 'name'] as $key) {
+            if (!array_key_exists($key, $element)) {
+                throw new \InvalidArgumentException("A '{$key}' key is required");
+            }
+        }
+
+        $element['contents'] = stream_for($element['contents']);
+
+        if (empty($element['filename'])) {
+            $uri = $element['contents']->getMetadata('uri');
+            if (substr($uri, 0, 6) !== 'php://') {
+                $element['filename'] = $uri;
+            }
+        }
+
+        list($body, $headers) = $this->createElement(
+            $element['name'],
+            $element['contents'],
+            isset($element['filename']) ? $element['filename'] : null,
+            isset($element['headers']) ? $element['headers'] : []
+        );
+
+        $stream->addStream(stream_for($this->getHeaders($headers)));
+        $stream->addStream($body);
+        $stream->addStream(stream_for("\r\n"));
+    }
+
+    /**
+     * @return array
+     */
+    private function createElement($name, StreamInterface $stream, $filename, array $headers)
+    {
+        // Set a default content-disposition header if one was no provided
+        $disposition = $this->getHeader($headers, 'content-disposition');
+        if (!$disposition) {
+            $headers['Content-Disposition'] = ($filename === '0' || $filename)
+                ? sprintf('form-data; name="%s"; filename="%s"',
+                    $name,
+                    basename($filename))
+                : "form-data; name=\"{$name}\"";
+        }
+
+        // Set a default content-length header if one was no provided
+        $length = $this->getHeader($headers, 'content-length');
+        if (!$length) {
+            if ($length = $stream->getSize()) {
+                $headers['Content-Length'] = (string) $length;
+            }
+        }
+
+        // Set a default Content-Type if one was not supplied
+        $type = $this->getHeader($headers, 'content-type');
+        if (!$type && ($filename === '0' || $filename)) {
+            if ($type = mimetype_from_filename($filename)) {
+                $headers['Content-Type'] = $type;
+            }
+        }
+
+        return [$stream, $headers];
+    }
+
+    private function getHeader(array $headers, $key)
+    {
+        $lowercaseHeader = strtolower($key);
+        foreach ($headers as $k => $v) {
+            if (strtolower($k) === $lowercaseHeader) {
+                return $v;
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/NoSeekStream.php b/vendor/guzzlehttp/psr7/src/NoSeekStream.php
new file mode 100644
index 00000000000..233221805ec
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/NoSeekStream.php
@@ -0,0 +1,22 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Stream decorator that prevents a stream from being seeked
+ */
+class NoSeekStream implements StreamInterface
+{
+    use StreamDecoratorTrait;
+
+    public function seek($offset, $whence = SEEK_SET)
+    {
+        throw new \RuntimeException('Cannot seek a NoSeekStream');
+    }
+
+    public function isSeekable()
+    {
+        return false;
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/PumpStream.php b/vendor/guzzlehttp/psr7/src/PumpStream.php
new file mode 100644
index 00000000000..ffb5440da16
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/PumpStream.php
@@ -0,0 +1,165 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Provides a read only stream that pumps data from a PHP callable.
+ *
+ * When invoking the provided callable, the PumpStream will pass the amount of
+ * data requested to read to the callable. The callable can choose to ignore
+ * this value and return fewer or more bytes than requested. Any extra data
+ * returned by the provided callable is buffered internally until drained using
+ * the read() function of the PumpStream. The provided callable MUST return
+ * false when there is no more data to read.
+ */
+class PumpStream implements StreamInterface
+{
+    /** @var callable */
+    private $source;
+
+    /** @var int */
+    private $size;
+
+    /** @var int */
+    private $tellPos = 0;
+
+    /** @var array */
+    private $metadata;
+
+    /** @var BufferStream */
+    private $buffer;
+
+    /**
+     * @param callable $source Source of the stream data. The callable MAY
+     *                         accept an integer argument used to control the
+     *                         amount of data to return. The callable MUST
+     *                         return a string when called, or false on error
+     *                         or EOF.
+     * @param array $options   Stream options:
+     *                         - metadata: Hash of metadata to use with stream.
+     *                         - size: Size of the stream, if known.
+     */
+    public function __construct(callable $source, array $options = [])
+    {
+        $this->source = $source;
+        $this->size = isset($options['size']) ? $options['size'] : null;
+        $this->metadata = isset($options['metadata']) ? $options['metadata'] : [];
+        $this->buffer = new BufferStream();
+    }
+
+    public function __toString()
+    {
+        try {
+            return copy_to_string($this);
+        } catch (\Exception $e) {
+            return '';
+        }
+    }
+
+    public function close()
+    {
+        $this->detach();
+    }
+
+    public function detach()
+    {
+        $this->tellPos = false;
+        $this->source = null;
+    }
+
+    public function getSize()
+    {
+        return $this->size;
+    }
+
+    public function tell()
+    {
+        return $this->tellPos;
+    }
+
+    public function eof()
+    {
+        return !$this->source;
+    }
+
+    public function isSeekable()
+    {
+        return false;
+    }
+
+    public function rewind()
+    {
+        $this->seek(0);
+    }
+
+    public function seek($offset, $whence = SEEK_SET)
+    {
+        throw new \RuntimeException('Cannot seek a PumpStream');
+    }
+
+    public function isWritable()
+    {
+        return false;
+    }
+
+    public function write($string)
+    {
+        throw new \RuntimeException('Cannot write to a PumpStream');
+    }
+
+    public function isReadable()
+    {
+        return true;
+    }
+
+    public function read($length)
+    {
+        $data = $this->buffer->read($length);
+        $readLen = strlen($data);
+        $this->tellPos += $readLen;
+        $remaining = $length - $readLen;
+
+        if ($remaining) {
+            $this->pump($remaining);
+            $data .= $this->buffer->read($remaining);
+            $this->tellPos += strlen($data) - $readLen;
+        }
+
+        return $data;
+    }
+
+    public function getContents()
+    {
+        $result = '';
+        while (!$this->eof()) {
+            $result .= $this->read(1000000);
+        }
+
+        return $result;
+    }
+
+    public function getMetadata($key = null)
+    {
+        if (!$key) {
+            return $this->metadata;
+        }
+
+        return isset($this->metadata[$key]) ? $this->metadata[$key] : null;
+    }
+
+    private function pump($length)
+    {
+        if ($this->source) {
+            do {
+                $data = call_user_func($this->source, $length);
+                if ($data === false || $data === null) {
+                    $this->source = null;
+                    return;
+                }
+                $this->buffer->write($data);
+                $length -= strlen($data);
+            } while ($length > 0);
+        }
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/Request.php b/vendor/guzzlehttp/psr7/src/Request.php
new file mode 100644
index 00000000000..08285484da2
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/Request.php
@@ -0,0 +1,142 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use InvalidArgumentException;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\StreamInterface;
+use Psr\Http\Message\UriInterface;
+
+/**
+ * PSR-7 request implementation.
+ */
+class Request implements RequestInterface
+{
+    use MessageTrait;
+
+    /** @var string */
+    private $method;
+
+    /** @var null|string */
+    private $requestTarget;
+
+    /** @var UriInterface */
+    private $uri;
+
+    /**
+     * @param string                               $method  HTTP method
+     * @param string|UriInterface                  $uri     URI
+     * @param array                                $headers Request headers
+     * @param string|null|resource|StreamInterface $body    Request body
+     * @param string                               $version Protocol version
+     */
+    public function __construct(
+        $method,
+        $uri,
+        array $headers = [],
+        $body = null,
+        $version = '1.1'
+    ) {
+        if (!($uri instanceof UriInterface)) {
+            $uri = new Uri($uri);
+        }
+
+        $this->method = strtoupper($method);
+        $this->uri = $uri;
+        $this->setHeaders($headers);
+        $this->protocol = $version;
+
+        if (!$this->hasHeader('Host')) {
+            $this->updateHostFromUri();
+        }
+
+        if ($body !== '' && $body !== null) {
+            $this->stream = stream_for($body);
+        }
+    }
+
+    public function getRequestTarget()
+    {
+        if ($this->requestTarget !== null) {
+            return $this->requestTarget;
+        }
+
+        $target = $this->uri->getPath();
+        if ($target == '') {
+            $target = '/';
+        }
+        if ($this->uri->getQuery() != '') {
+            $target .= '?' . $this->uri->getQuery();
+        }
+
+        return $target;
+    }
+
+    public function withRequestTarget($requestTarget)
+    {
+        if (preg_match('#\s#', $requestTarget)) {
+            throw new InvalidArgumentException(
+                'Invalid request target provided; cannot contain whitespace'
+            );
+        }
+
+        $new = clone $this;
+        $new->requestTarget = $requestTarget;
+        return $new;
+    }
+
+    public function getMethod()
+    {
+        return $this->method;
+    }
+
+    public function withMethod($method)
+    {
+        $new = clone $this;
+        $new->method = strtoupper($method);
+        return $new;
+    }
+
+    public function getUri()
+    {
+        return $this->uri;
+    }
+
+    public function withUri(UriInterface $uri, $preserveHost = false)
+    {
+        if ($uri === $this->uri) {
+            return $this;
+        }
+
+        $new = clone $this;
+        $new->uri = $uri;
+
+        if (!$preserveHost) {
+            $new->updateHostFromUri();
+        }
+
+        return $new;
+    }
+
+    private function updateHostFromUri()
+    {
+        $host = $this->uri->getHost();
+
+        if ($host == '') {
+            return;
+        }
+
+        if (($port = $this->uri->getPort()) !== null) {
+            $host .= ':' . $port;
+        }
+
+        if (isset($this->headerNames['host'])) {
+            $header = $this->headerNames['host'];
+        } else {
+            $header = 'Host';
+            $this->headerNames['host'] = 'Host';
+        }
+        // Ensure Host is the first header.
+        // See: http://tools.ietf.org/html/rfc7230#section-5.4
+        $this->headers = [$header => [$host]] + $this->headers;
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/Response.php b/vendor/guzzlehttp/psr7/src/Response.php
new file mode 100644
index 00000000000..2830c6c9ee1
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/Response.php
@@ -0,0 +1,132 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * PSR-7 response implementation.
+ */
+class Response implements ResponseInterface
+{
+    use MessageTrait;
+
+    /** @var array Map of standard HTTP status code/reason phrases */
+    private static $phrases = [
+        100 => 'Continue',
+        101 => 'Switching Protocols',
+        102 => 'Processing',
+        200 => 'OK',
+        201 => 'Created',
+        202 => 'Accepted',
+        203 => 'Non-Authoritative Information',
+        204 => 'No Content',
+        205 => 'Reset Content',
+        206 => 'Partial Content',
+        207 => 'Multi-status',
+        208 => 'Already Reported',
+        300 => 'Multiple Choices',
+        301 => 'Moved Permanently',
+        302 => 'Found',
+        303 => 'See Other',
+        304 => 'Not Modified',
+        305 => 'Use Proxy',
+        306 => 'Switch Proxy',
+        307 => 'Temporary Redirect',
+        400 => 'Bad Request',
+        401 => 'Unauthorized',
+        402 => 'Payment Required',
+        403 => 'Forbidden',
+        404 => 'Not Found',
+        405 => 'Method Not Allowed',
+        406 => 'Not Acceptable',
+        407 => 'Proxy Authentication Required',
+        408 => 'Request Time-out',
+        409 => 'Conflict',
+        410 => 'Gone',
+        411 => 'Length Required',
+        412 => 'Precondition Failed',
+        413 => 'Request Entity Too Large',
+        414 => 'Request-URI Too Large',
+        415 => 'Unsupported Media Type',
+        416 => 'Requested range not satisfiable',
+        417 => 'Expectation Failed',
+        418 => 'I\'m a teapot',
+        422 => 'Unprocessable Entity',
+        423 => 'Locked',
+        424 => 'Failed Dependency',
+        425 => 'Unordered Collection',
+        426 => 'Upgrade Required',
+        428 => 'Precondition Required',
+        429 => 'Too Many Requests',
+        431 => 'Request Header Fields Too Large',
+        451 => 'Unavailable For Legal Reasons',
+        500 => 'Internal Server Error',
+        501 => 'Not Implemented',
+        502 => 'Bad Gateway',
+        503 => 'Service Unavailable',
+        504 => 'Gateway Time-out',
+        505 => 'HTTP Version not supported',
+        506 => 'Variant Also Negotiates',
+        507 => 'Insufficient Storage',
+        508 => 'Loop Detected',
+        511 => 'Network Authentication Required',
+    ];
+
+    /** @var string */
+    private $reasonPhrase = '';
+
+    /** @var int */
+    private $statusCode = 200;
+
+    /**
+     * @param int                                  $status  Status code
+     * @param array                                $headers Response headers
+     * @param string|null|resource|StreamInterface $body    Response body
+     * @param string                               $version Protocol version
+     * @param string|null                          $reason  Reason phrase (when empty a default will be used based on the status code)
+     */
+    public function __construct(
+        $status = 200,
+        array $headers = [],
+        $body = null,
+        $version = '1.1',
+        $reason = null
+    ) {
+        $this->statusCode = (int) $status;
+
+        if ($body !== '' && $body !== null) {
+            $this->stream = stream_for($body);
+        }
+
+        $this->setHeaders($headers);
+        if ($reason == '' && isset(self::$phrases[$this->statusCode])) {
+            $this->reasonPhrase = self::$phrases[$this->statusCode];
+        } else {
+            $this->reasonPhrase = (string) $reason;
+        }
+
+        $this->protocol = $version;
+    }
+
+    public function getStatusCode()
+    {
+        return $this->statusCode;
+    }
+
+    public function getReasonPhrase()
+    {
+        return $this->reasonPhrase;
+    }
+
+    public function withStatus($code, $reasonPhrase = '')
+    {
+        $new = clone $this;
+        $new->statusCode = (int) $code;
+        if ($reasonPhrase == '' && isset(self::$phrases[$new->statusCode])) {
+            $reasonPhrase = self::$phrases[$new->statusCode];
+        }
+        $new->reasonPhrase = $reasonPhrase;
+        return $new;
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/ServerRequest.php b/vendor/guzzlehttp/psr7/src/ServerRequest.php
new file mode 100644
index 00000000000..575aab8489a
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/ServerRequest.php
@@ -0,0 +1,358 @@
+<?php
+
+namespace GuzzleHttp\Psr7;
+
+use InvalidArgumentException;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Message\UriInterface;
+use Psr\Http\Message\StreamInterface;
+use Psr\Http\Message\UploadedFileInterface;
+
+/**
+ * Server-side HTTP request
+ *
+ * Extends the Request definition to add methods for accessing incoming data,
+ * specifically server parameters, cookies, matched path parameters, query
+ * string arguments, body parameters, and upload file information.
+ *
+ * "Attributes" are discovered via decomposing the request (and usually
+ * specifically the URI path), and typically will be injected by the application.
+ *
+ * Requests are considered immutable; all methods that might change state are
+ * implemented such that they retain the internal state of the current
+ * message and return a new instance that contains the changed state.
+ */
+class ServerRequest extends Request implements ServerRequestInterface
+{
+    /**
+     * @var array
+     */
+    private $attributes = [];
+
+    /**
+     * @var array
+     */
+    private $cookieParams = [];
+
+    /**
+     * @var null|array|object
+     */
+    private $parsedBody;
+
+    /**
+     * @var array
+     */
+    private $queryParams = [];
+
+    /**
+     * @var array
+     */
+    private $serverParams;
+
+    /**
+     * @var array
+     */
+    private $uploadedFiles = [];
+
+    /**
+     * @param string                               $method       HTTP method
+     * @param string|UriInterface                  $uri          URI
+     * @param array                                $headers      Request headers
+     * @param string|null|resource|StreamInterface $body         Request body
+     * @param string                               $version      Protocol version
+     * @param array                                $serverParams Typically the $_SERVER superglobal
+     */
+    public function __construct(
+        $method,
+        $uri,
+        array $headers = [],
+        $body = null,
+        $version = '1.1',
+        array $serverParams = []
+    ) {
+        $this->serverParams = $serverParams;
+
+        parent::__construct($method, $uri, $headers, $body, $version);
+    }
+
+    /**
+     * Return an UploadedFile instance array.
+     *
+     * @param array $files A array which respect $_FILES structure
+     * @throws InvalidArgumentException for unrecognized values
+     * @return array
+     */
+    public static function normalizeFiles(array $files)
+    {
+        $normalized = [];
+
+        foreach ($files as $key => $value) {
+            if ($value instanceof UploadedFileInterface) {
+                $normalized[$key] = $value;
+            } elseif (is_array($value) && isset($value['tmp_name'])) {
+                $normalized[$key] = self::createUploadedFileFromSpec($value);
+            } elseif (is_array($value)) {
+                $normalized[$key] = self::normalizeFiles($value);
+                continue;
+            } else {
+                throw new InvalidArgumentException('Invalid value in files specification');
+            }
+        }
+
+        return $normalized;
+    }
+
+    /**
+     * Create and return an UploadedFile instance from a $_FILES specification.
+     *
+     * If the specification represents an array of values, this method will
+     * delegate to normalizeNestedFileSpec() and return that return value.
+     *
+     * @param array $value $_FILES struct
+     * @return array|UploadedFileInterface
+     */
+    private static function createUploadedFileFromSpec(array $value)
+    {
+        if (is_array($value['tmp_name'])) {
+            return self::normalizeNestedFileSpec($value);
+        }
+
+        return new UploadedFile(
+            $value['tmp_name'],
+            (int) $value['size'],
+            (int) $value['error'],
+            $value['name'],
+            $value['type']
+        );
+    }
+
+    /**
+     * Normalize an array of file specifications.
+     *
+     * Loops through all nested files and returns a normalized array of
+     * UploadedFileInterface instances.
+     *
+     * @param array $files
+     * @return UploadedFileInterface[]
+     */
+    private static function normalizeNestedFileSpec(array $files = [])
+    {
+        $normalizedFiles = [];
+
+        foreach (array_keys($files['tmp_name']) as $key) {
+            $spec = [
+                'tmp_name' => $files['tmp_name'][$key],
+                'size'     => $files['size'][$key],
+                'error'    => $files['error'][$key],
+                'name'     => $files['name'][$key],
+                'type'     => $files['type'][$key],
+            ];
+            $normalizedFiles[$key] = self::createUploadedFileFromSpec($spec);
+        }
+
+        return $normalizedFiles;
+    }
+
+    /**
+     * Return a ServerRequest populated with superglobals:
+     * $_GET
+     * $_POST
+     * $_COOKIE
+     * $_FILES
+     * $_SERVER
+     *
+     * @return ServerRequestInterface
+     */
+    public static function fromGlobals()
+    {
+        $method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET';
+        $headers = function_exists('getallheaders') ? getallheaders() : [];
+        $uri = self::getUriFromGlobals();
+        $body = new LazyOpenStream('php://input', 'r+');
+        $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $_SERVER['SERVER_PROTOCOL']) : '1.1';
+
+        $serverRequest = new ServerRequest($method, $uri, $headers, $body, $protocol, $_SERVER);
+
+        return $serverRequest
+            ->withCookieParams($_COOKIE)
+            ->withQueryParams($_GET)
+            ->withParsedBody($_POST)
+            ->withUploadedFiles(self::normalizeFiles($_FILES));
+    }
+
+    /**
+     * Get a Uri populated with values from $_SERVER.
+     *
+     * @return UriInterface
+     */
+    public static function getUriFromGlobals() {
+        $uri = new Uri('');
+
+        $uri = $uri->withScheme(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http');
+
+        $hasPort = false;
+        if (isset($_SERVER['HTTP_HOST'])) {
+            $hostHeaderParts = explode(':', $_SERVER['HTTP_HOST']);
+            $uri = $uri->withHost($hostHeaderParts[0]);
+            if (isset($hostHeaderParts[1])) {
+                $hasPort = true;
+                $uri = $uri->withPort($hostHeaderParts[1]);
+            }
+        } elseif (isset($_SERVER['SERVER_NAME'])) {
+            $uri = $uri->withHost($_SERVER['SERVER_NAME']);
+        } elseif (isset($_SERVER['SERVER_ADDR'])) {
+            $uri = $uri->withHost($_SERVER['SERVER_ADDR']);
+        }
+
+        if (!$hasPort && isset($_SERVER['SERVER_PORT'])) {
+            $uri = $uri->withPort($_SERVER['SERVER_PORT']);
+        }
+
+        $hasQuery = false;
+        if (isset($_SERVER['REQUEST_URI'])) {
+            $requestUriParts = explode('?', $_SERVER['REQUEST_URI']);
+            $uri = $uri->withPath($requestUriParts[0]);
+            if (isset($requestUriParts[1])) {
+                $hasQuery = true;
+                $uri = $uri->withQuery($requestUriParts[1]);
+            }
+        }
+
+        if (!$hasQuery && isset($_SERVER['QUERY_STRING'])) {
+            $uri = $uri->withQuery($_SERVER['QUERY_STRING']);
+        }
+
+        return $uri;
+    }
+
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getServerParams()
+    {
+        return $this->serverParams;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getUploadedFiles()
+    {
+        return $this->uploadedFiles;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function withUploadedFiles(array $uploadedFiles)
+    {
+        $new = clone $this;
+        $new->uploadedFiles = $uploadedFiles;
+
+        return $new;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getCookieParams()
+    {
+        return $this->cookieParams;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function withCookieParams(array $cookies)
+    {
+        $new = clone $this;
+        $new->cookieParams = $cookies;
+
+        return $new;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getQueryParams()
+    {
+        return $this->queryParams;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function withQueryParams(array $query)
+    {
+        $new = clone $this;
+        $new->queryParams = $query;
+
+        return $new;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getParsedBody()
+    {
+        return $this->parsedBody;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function withParsedBody($data)
+    {
+        $new = clone $this;
+        $new->parsedBody = $data;
+
+        return $new;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getAttributes()
+    {
+        return $this->attributes;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getAttribute($attribute, $default = null)
+    {
+        if (false === array_key_exists($attribute, $this->attributes)) {
+            return $default;
+        }
+
+        return $this->attributes[$attribute];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function withAttribute($attribute, $value)
+    {
+        $new = clone $this;
+        $new->attributes[$attribute] = $value;
+
+        return $new;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function withoutAttribute($attribute)
+    {
+        if (false === array_key_exists($attribute, $this->attributes)) {
+            return $this;
+        }
+
+        $new = clone $this;
+        unset($new->attributes[$attribute]);
+
+        return $new;
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/Stream.php b/vendor/guzzlehttp/psr7/src/Stream.php
new file mode 100644
index 00000000000..e33662879ff
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/Stream.php
@@ -0,0 +1,257 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * PHP stream implementation.
+ *
+ * @var $stream
+ */
+class Stream implements StreamInterface
+{
+    private $stream;
+    private $size;
+    private $seekable;
+    private $readable;
+    private $writable;
+    private $uri;
+    private $customMetadata;
+
+    /** @var array Hash of readable and writable stream types */
+    private static $readWriteHash = [
+        'read' => [
+            'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true,
+            'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true,
+            'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true,
+            'x+t' => true, 'c+t' => true, 'a+' => true
+        ],
+        'write' => [
+            'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true,
+            'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true,
+            'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true,
+            'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true
+        ]
+    ];
+
+    /**
+     * This constructor accepts an associative array of options.
+     *
+     * - size: (int) If a read stream would otherwise have an indeterminate
+     *   size, but the size is known due to foreknowledge, then you can
+     *   provide that size, in bytes.
+     * - metadata: (array) Any additional metadata to return when the metadata
+     *   of the stream is accessed.
+     *
+     * @param resource $stream  Stream resource to wrap.
+     * @param array    $options Associative array of options.
+     *
+     * @throws \InvalidArgumentException if the stream is not a stream resource
+     */
+    public function __construct($stream, $options = [])
+    {
+        if (!is_resource($stream)) {
+            throw new \InvalidArgumentException('Stream must be a resource');
+        }
+
+        if (isset($options['size'])) {
+            $this->size = $options['size'];
+        }
+
+        $this->customMetadata = isset($options['metadata'])
+            ? $options['metadata']
+            : [];
+
+        $this->stream = $stream;
+        $meta = stream_get_meta_data($this->stream);
+        $this->seekable = $meta['seekable'];
+        $this->readable = isset(self::$readWriteHash['read'][$meta['mode']]);
+        $this->writable = isset(self::$readWriteHash['write'][$meta['mode']]);
+        $this->uri = $this->getMetadata('uri');
+    }
+
+    public function __get($name)
+    {
+        if ($name == 'stream') {
+            throw new \RuntimeException('The stream is detached');
+        }
+
+        throw new \BadMethodCallException('No value for ' . $name);
+    }
+
+    /**
+     * Closes the stream when the destructed
+     */
+    public function __destruct()
+    {
+        $this->close();
+    }
+
+    public function __toString()
+    {
+        try {
+            $this->seek(0);
+            return (string) stream_get_contents($this->stream);
+        } catch (\Exception $e) {
+            return '';
+        }
+    }
+
+    public function getContents()
+    {
+        $contents = stream_get_contents($this->stream);
+
+        if ($contents === false) {
+            throw new \RuntimeException('Unable to read stream contents');
+        }
+
+        return $contents;
+    }
+
+    public function close()
+    {
+        if (isset($this->stream)) {
+            if (is_resource($this->stream)) {
+                fclose($this->stream);
+            }
+            $this->detach();
+        }
+    }
+
+    public function detach()
+    {
+        if (!isset($this->stream)) {
+            return null;
+        }
+
+        $result = $this->stream;
+        unset($this->stream);
+        $this->size = $this->uri = null;
+        $this->readable = $this->writable = $this->seekable = false;
+
+        return $result;
+    }
+
+    public function getSize()
+    {
+        if ($this->size !== null) {
+            return $this->size;
+        }
+
+        if (!isset($this->stream)) {
+            return null;
+        }
+
+        // Clear the stat cache if the stream has a URI
+        if ($this->uri) {
+            clearstatcache(true, $this->uri);
+        }
+
+        $stats = fstat($this->stream);
+        if (isset($stats['size'])) {
+            $this->size = $stats['size'];
+            return $this->size;
+        }
+
+        return null;
+    }
+
+    public function isReadable()
+    {
+        return $this->readable;
+    }
+
+    public function isWritable()
+    {
+        return $this->writable;
+    }
+
+    public function isSeekable()
+    {
+        return $this->seekable;
+    }
+
+    public function eof()
+    {
+        return !$this->stream || feof($this->stream);
+    }
+
+    public function tell()
+    {
+        $result = ftell($this->stream);
+
+        if ($result === false) {
+            throw new \RuntimeException('Unable to determine stream position');
+        }
+
+        return $result;
+    }
+
+    public function rewind()
+    {
+        $this->seek(0);
+    }
+
+    public function seek($offset, $whence = SEEK_SET)
+    {
+        if (!$this->seekable) {
+            throw new \RuntimeException('Stream is not seekable');
+        } elseif (fseek($this->stream, $offset, $whence) === -1) {
+            throw new \RuntimeException('Unable to seek to stream position '
+                . $offset . ' with whence ' . var_export($whence, true));
+        }
+    }
+
+    public function read($length)
+    {
+        if (!$this->readable) {
+            throw new \RuntimeException('Cannot read from non-readable stream');
+        }
+        if ($length < 0) {
+            throw new \RuntimeException('Length parameter cannot be negative');
+        }
+
+        if (0 === $length) {
+            return '';
+        }
+
+        $string = fread($this->stream, $length);
+        if (false === $string) {
+            throw new \RuntimeException('Unable to read from stream');
+        }
+
+        return $string;
+    }
+
+    public function write($string)
+    {
+        if (!$this->writable) {
+            throw new \RuntimeException('Cannot write to a non-writable stream');
+        }
+
+        // We can't know the size after writing anything
+        $this->size = null;
+        $result = fwrite($this->stream, $string);
+
+        if ($result === false) {
+            throw new \RuntimeException('Unable to write to stream');
+        }
+
+        return $result;
+    }
+
+    public function getMetadata($key = null)
+    {
+        if (!isset($this->stream)) {
+            return $key ? null : [];
+        } elseif (!$key) {
+            return $this->customMetadata + stream_get_meta_data($this->stream);
+        } elseif (isset($this->customMetadata[$key])) {
+            return $this->customMetadata[$key];
+        }
+
+        $meta = stream_get_meta_data($this->stream);
+
+        return isset($meta[$key]) ? $meta[$key] : null;
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php b/vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php
new file mode 100644
index 00000000000..daec6f52ea7
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php
@@ -0,0 +1,149 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Stream decorator trait
+ * @property StreamInterface stream
+ */
+trait StreamDecoratorTrait
+{
+    /**
+     * @param StreamInterface $stream Stream to decorate
+     */
+    public function __construct(StreamInterface $stream)
+    {
+        $this->stream = $stream;
+    }
+
+    /**
+     * Magic method used to create a new stream if streams are not added in
+     * the constructor of a decorator (e.g., LazyOpenStream).
+     *
+     * @param string $name Name of the property (allows "stream" only).
+     *
+     * @return StreamInterface
+     */
+    public function __get($name)
+    {
+        if ($name == 'stream') {
+            $this->stream = $this->createStream();
+            return $this->stream;
+        }
+
+        throw new \UnexpectedValueException("$name not found on class");
+    }
+
+    public function __toString()
+    {
+        try {
+            if ($this->isSeekable()) {
+                $this->seek(0);
+            }
+            return $this->getContents();
+        } catch (\Exception $e) {
+            // Really, PHP? https://bugs.php.net/bug.php?id=53648
+            trigger_error('StreamDecorator::__toString exception: '
+                . (string) $e, E_USER_ERROR);
+            return '';
+        }
+    }
+
+    public function getContents()
+    {
+        return copy_to_string($this);
+    }
+
+    /**
+     * Allow decorators to implement custom methods
+     *
+     * @param string $method Missing method name
+     * @param array  $args   Method arguments
+     *
+     * @return mixed
+     */
+    public function __call($method, array $args)
+    {
+        $result = call_user_func_array([$this->stream, $method], $args);
+
+        // Always return the wrapped object if the result is a return $this
+        return $result === $this->stream ? $this : $result;
+    }
+
+    public function close()
+    {
+        $this->stream->close();
+    }
+
+    public function getMetadata($key = null)
+    {
+        return $this->stream->getMetadata($key);
+    }
+
+    public function detach()
+    {
+        return $this->stream->detach();
+    }
+
+    public function getSize()
+    {
+        return $this->stream->getSize();
+    }
+
+    public function eof()
+    {
+        return $this->stream->eof();
+    }
+
+    public function tell()
+    {
+        return $this->stream->tell();
+    }
+
+    public function isReadable()
+    {
+        return $this->stream->isReadable();
+    }
+
+    public function isWritable()
+    {
+        return $this->stream->isWritable();
+    }
+
+    public function isSeekable()
+    {
+        return $this->stream->isSeekable();
+    }
+
+    public function rewind()
+    {
+        $this->seek(0);
+    }
+
+    public function seek($offset, $whence = SEEK_SET)
+    {
+        $this->stream->seek($offset, $whence);
+    }
+
+    public function read($length)
+    {
+        return $this->stream->read($length);
+    }
+
+    public function write($string)
+    {
+        return $this->stream->write($string);
+    }
+
+    /**
+     * Implement in subclasses to dynamically create streams when requested.
+     *
+     * @return StreamInterface
+     * @throws \BadMethodCallException
+     */
+    protected function createStream()
+    {
+        throw new \BadMethodCallException('Not implemented');
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/StreamWrapper.php b/vendor/guzzlehttp/psr7/src/StreamWrapper.php
new file mode 100644
index 00000000000..cf7b2232e46
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/StreamWrapper.php
@@ -0,0 +1,121 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Converts Guzzle streams into PHP stream resources.
+ */
+class StreamWrapper
+{
+    /** @var resource */
+    public $context;
+
+    /** @var StreamInterface */
+    private $stream;
+
+    /** @var string r, r+, or w */
+    private $mode;
+
+    /**
+     * Returns a resource representing the stream.
+     *
+     * @param StreamInterface $stream The stream to get a resource for
+     *
+     * @return resource
+     * @throws \InvalidArgumentException if stream is not readable or writable
+     */
+    public static function getResource(StreamInterface $stream)
+    {
+        self::register();
+
+        if ($stream->isReadable()) {
+            $mode = $stream->isWritable() ? 'r+' : 'r';
+        } elseif ($stream->isWritable()) {
+            $mode = 'w';
+        } else {
+            throw new \InvalidArgumentException('The stream must be readable, '
+                . 'writable, or both.');
+        }
+
+        return fopen('guzzle://stream', $mode, null, stream_context_create([
+            'guzzle' => ['stream' => $stream]
+        ]));
+    }
+
+    /**
+     * Registers the stream wrapper if needed
+     */
+    public static function register()
+    {
+        if (!in_array('guzzle', stream_get_wrappers())) {
+            stream_wrapper_register('guzzle', __CLASS__);
+        }
+    }
+
+    public function stream_open($path, $mode, $options, &$opened_path)
+    {
+        $options = stream_context_get_options($this->context);
+
+        if (!isset($options['guzzle']['stream'])) {
+            return false;
+        }
+
+        $this->mode = $mode;
+        $this->stream = $options['guzzle']['stream'];
+
+        return true;
+    }
+
+    public function stream_read($count)
+    {
+        return $this->stream->read($count);
+    }
+
+    public function stream_write($data)
+    {
+        return (int) $this->stream->write($data);
+    }
+
+    public function stream_tell()
+    {
+        return $this->stream->tell();
+    }
+
+    public function stream_eof()
+    {
+        return $this->stream->eof();
+    }
+
+    public function stream_seek($offset, $whence)
+    {
+        $this->stream->seek($offset, $whence);
+
+        return true;
+    }
+
+    public function stream_stat()
+    {
+        static $modeMap = [
+            'r'  => 33060,
+            'r+' => 33206,
+            'w'  => 33188
+        ];
+
+        return [
+            'dev'     => 0,
+            'ino'     => 0,
+            'mode'    => $modeMap[$this->mode],
+            'nlink'   => 0,
+            'uid'     => 0,
+            'gid'     => 0,
+            'rdev'    => 0,
+            'size'    => $this->stream->getSize() ?: 0,
+            'atime'   => 0,
+            'mtime'   => 0,
+            'ctime'   => 0,
+            'blksize' => 0,
+            'blocks'  => 0
+        ];
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/UploadedFile.php b/vendor/guzzlehttp/psr7/src/UploadedFile.php
new file mode 100644
index 00000000000..e62bd5c8076
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/UploadedFile.php
@@ -0,0 +1,316 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use InvalidArgumentException;
+use Psr\Http\Message\StreamInterface;
+use Psr\Http\Message\UploadedFileInterface;
+use RuntimeException;
+
+class UploadedFile implements UploadedFileInterface
+{
+    /**
+     * @var int[]
+     */
+    private static $errors = [
+        UPLOAD_ERR_OK,
+        UPLOAD_ERR_INI_SIZE,
+        UPLOAD_ERR_FORM_SIZE,
+        UPLOAD_ERR_PARTIAL,
+        UPLOAD_ERR_NO_FILE,
+        UPLOAD_ERR_NO_TMP_DIR,
+        UPLOAD_ERR_CANT_WRITE,
+        UPLOAD_ERR_EXTENSION,
+    ];
+
+    /**
+     * @var string
+     */
+    private $clientFilename;
+
+    /**
+     * @var string
+     */
+    private $clientMediaType;
+
+    /**
+     * @var int
+     */
+    private $error;
+
+    /**
+     * @var null|string
+     */
+    private $file;
+
+    /**
+     * @var bool
+     */
+    private $moved = false;
+
+    /**
+     * @var int
+     */
+    private $size;
+
+    /**
+     * @var StreamInterface|null
+     */
+    private $stream;
+
+    /**
+     * @param StreamInterface|string|resource $streamOrFile
+     * @param int $size
+     * @param int $errorStatus
+     * @param string|null $clientFilename
+     * @param string|null $clientMediaType
+     */
+    public function __construct(
+        $streamOrFile,
+        $size,
+        $errorStatus,
+        $clientFilename = null,
+        $clientMediaType = null
+    ) {
+        $this->setError($errorStatus);
+        $this->setSize($size);
+        $this->setClientFilename($clientFilename);
+        $this->setClientMediaType($clientMediaType);
+
+        if ($this->isOk()) {
+            $this->setStreamOrFile($streamOrFile);
+        }
+    }
+
+    /**
+     * Depending on the value set file or stream variable
+     *
+     * @param mixed $streamOrFile
+     * @throws InvalidArgumentException
+     */
+    private function setStreamOrFile($streamOrFile)
+    {
+        if (is_string($streamOrFile)) {
+            $this->file = $streamOrFile;
+        } elseif (is_resource($streamOrFile)) {
+            $this->stream = new Stream($streamOrFile);
+        } elseif ($streamOrFile instanceof StreamInterface) {
+            $this->stream = $streamOrFile;
+        } else {
+            throw new InvalidArgumentException(
+                'Invalid stream or file provided for UploadedFile'
+            );
+        }
+    }
+
+    /**
+     * @param int $error
+     * @throws InvalidArgumentException
+     */
+    private function setError($error)
+    {
+        if (false === is_int($error)) {
+            throw new InvalidArgumentException(
+                'Upload file error status must be an integer'
+            );
+        }
+
+        if (false === in_array($error, UploadedFile::$errors)) {
+            throw new InvalidArgumentException(
+                'Invalid error status for UploadedFile'
+            );
+        }
+
+        $this->error = $error;
+    }
+
+    /**
+     * @param int $size
+     * @throws InvalidArgumentException
+     */
+    private function setSize($size)
+    {
+        if (false === is_int($size)) {
+            throw new InvalidArgumentException(
+                'Upload file size must be an integer'
+            );
+        }
+
+        $this->size = $size;
+    }
+
+    /**
+     * @param mixed $param
+     * @return boolean
+     */
+    private function isStringOrNull($param)
+    {
+        return in_array(gettype($param), ['string', 'NULL']);
+    }
+
+    /**
+     * @param mixed $param
+     * @return boolean
+     */
+    private function isStringNotEmpty($param)
+    {
+        return is_string($param) && false === empty($param);
+    }
+
+    /**
+     * @param string|null $clientFilename
+     * @throws InvalidArgumentException
+     */
+    private function setClientFilename($clientFilename)
+    {
+        if (false === $this->isStringOrNull($clientFilename)) {
+            throw new InvalidArgumentException(
+                'Upload file client filename must be a string or null'
+            );
+        }
+
+        $this->clientFilename = $clientFilename;
+    }
+
+    /**
+     * @param string|null $clientMediaType
+     * @throws InvalidArgumentException
+     */
+    private function setClientMediaType($clientMediaType)
+    {
+        if (false === $this->isStringOrNull($clientMediaType)) {
+            throw new InvalidArgumentException(
+                'Upload file client media type must be a string or null'
+            );
+        }
+
+        $this->clientMediaType = $clientMediaType;
+    }
+
+    /**
+     * Return true if there is no upload error
+     *
+     * @return boolean
+     */
+    private function isOk()
+    {
+        return $this->error === UPLOAD_ERR_OK;
+    }
+
+    /**
+     * @return boolean
+     */
+    public function isMoved()
+    {
+        return $this->moved;
+    }
+
+    /**
+     * @throws RuntimeException if is moved or not ok
+     */
+    private function validateActive()
+    {
+        if (false === $this->isOk()) {
+            throw new RuntimeException('Cannot retrieve stream due to upload error');
+        }
+
+        if ($this->isMoved()) {
+            throw new RuntimeException('Cannot retrieve stream after it has already been moved');
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     * @throws RuntimeException if the upload was not successful.
+     */
+    public function getStream()
+    {
+        $this->validateActive();
+
+        if ($this->stream instanceof StreamInterface) {
+            return $this->stream;
+        }
+
+        return new LazyOpenStream($this->file, 'r+');
+    }
+
+    /**
+     * {@inheritdoc}
+     *
+     * @see http://php.net/is_uploaded_file
+     * @see http://php.net/move_uploaded_file
+     * @param string $targetPath Path to which to move the uploaded file.
+     * @throws RuntimeException if the upload was not successful.
+     * @throws InvalidArgumentException if the $path specified is invalid.
+     * @throws RuntimeException on any error during the move operation, or on
+     *     the second or subsequent call to the method.
+     */
+    public function moveTo($targetPath)
+    {
+        $this->validateActive();
+
+        if (false === $this->isStringNotEmpty($targetPath)) {
+            throw new InvalidArgumentException(
+                'Invalid path provided for move operation; must be a non-empty string'
+            );
+        }
+
+        if ($this->file) {
+            $this->moved = php_sapi_name() == 'cli'
+                ? rename($this->file, $targetPath)
+                : move_uploaded_file($this->file, $targetPath);
+        } else {
+            copy_to_stream(
+                $this->getStream(),
+                new LazyOpenStream($targetPath, 'w')
+            );
+
+            $this->moved = true;
+        }
+
+        if (false === $this->moved) {
+            throw new RuntimeException(
+                sprintf('Uploaded file could not be moved to %s', $targetPath)
+            );
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     *
+     * @return int|null The file size in bytes or null if unknown.
+     */
+    public function getSize()
+    {
+        return $this->size;
+    }
+
+    /**
+     * {@inheritdoc}
+     *
+     * @see http://php.net/manual/en/features.file-upload.errors.php
+     * @return int One of PHP's UPLOAD_ERR_XXX constants.
+     */
+    public function getError()
+    {
+        return $this->error;
+    }
+
+    /**
+     * {@inheritdoc}
+     *
+     * @return string|null The filename sent by the client or null if none
+     *     was provided.
+     */
+    public function getClientFilename()
+    {
+        return $this->clientFilename;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getClientMediaType()
+    {
+        return $this->clientMediaType;
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/Uri.php b/vendor/guzzlehttp/psr7/src/Uri.php
new file mode 100644
index 00000000000..f46c1db9e07
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/Uri.php
@@ -0,0 +1,702 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\UriInterface;
+
+/**
+ * PSR-7 URI implementation.
+ *
+ * @author Michael Dowling
+ * @author Tobias Schultze
+ * @author Matthew Weier O'Phinney
+ */
+class Uri implements UriInterface
+{
+    /**
+     * Absolute http and https URIs require a host per RFC 7230 Section 2.7
+     * but in generic URIs the host can be empty. So for http(s) URIs
+     * we apply this default host when no host is given yet to form a
+     * valid URI.
+     */
+    const HTTP_DEFAULT_HOST = 'localhost';
+
+    private static $defaultPorts = [
+        'http'  => 80,
+        'https' => 443,
+        'ftp' => 21,
+        'gopher' => 70,
+        'nntp' => 119,
+        'news' => 119,
+        'telnet' => 23,
+        'tn3270' => 23,
+        'imap' => 143,
+        'pop' => 110,
+        'ldap' => 389,
+    ];
+
+    private static $charUnreserved = 'a-zA-Z0-9_\-\.~';
+    private static $charSubDelims = '!\$&\'\(\)\*\+,;=';
+    private static $replaceQuery = ['=' => '%3D', '&' => '%26'];
+
+    /** @var string Uri scheme. */
+    private $scheme = '';
+
+    /** @var string Uri user info. */
+    private $userInfo = '';
+
+    /** @var string Uri host. */
+    private $host = '';
+
+    /** @var int|null Uri port. */
+    private $port;
+
+    /** @var string Uri path. */
+    private $path = '';
+
+    /** @var string Uri query string. */
+    private $query = '';
+
+    /** @var string Uri fragment. */
+    private $fragment = '';
+
+    /**
+     * @param string $uri URI to parse
+     */
+    public function __construct($uri = '')
+    {
+        // weak type check to also accept null until we can add scalar type hints
+        if ($uri != '') {
+            $parts = parse_url($uri);
+            if ($parts === false) {
+                throw new \InvalidArgumentException("Unable to parse URI: $uri");
+            }
+            $this->applyParts($parts);
+        }
+    }
+
+    public function __toString()
+    {
+        return self::composeComponents(
+            $this->scheme,
+            $this->getAuthority(),
+            $this->path,
+            $this->query,
+            $this->fragment
+        );
+    }
+
+    /**
+     * Composes a URI reference string from its various components.
+     *
+     * Usually this method does not need to be called manually but instead is used indirectly via
+     * `Psr\Http\Message\UriInterface::__toString`.
+     *
+     * PSR-7 UriInterface treats an empty component the same as a missing component as
+     * getQuery(), getFragment() etc. always return a string. This explains the slight
+     * difference to RFC 3986 Section 5.3.
+     *
+     * Another adjustment is that the authority separator is added even when the authority is missing/empty
+     * for the "file" scheme. This is because PHP stream functions like `file_get_contents` only work with
+     * `file:///myfile` but not with `file:/myfile` although they are equivalent according to RFC 3986. But
+     * `file:///` is the more common syntax for the file scheme anyway (Chrome for example redirects to
+     * that format).
+     *
+     * @param string $scheme
+     * @param string $authority
+     * @param string $path
+     * @param string $query
+     * @param string $fragment
+     *
+     * @return string
+     *
+     * @link https://tools.ietf.org/html/rfc3986#section-5.3
+     */
+    public static function composeComponents($scheme, $authority, $path, $query, $fragment)
+    {
+        $uri = '';
+
+        // weak type checks to also accept null until we can add scalar type hints
+        if ($scheme != '') {
+            $uri .= $scheme . ':';
+        }
+
+        if ($authority != ''|| $scheme === 'file') {
+            $uri .= '//' . $authority;
+        }
+
+        $uri .= $path;
+
+        if ($query != '') {
+            $uri .= '?' . $query;
+        }
+
+        if ($fragment != '') {
+            $uri .= '#' . $fragment;
+        }
+
+        return $uri;
+    }
+
+    /**
+     * Whether the URI has the default port of the current scheme.
+     *
+     * `Psr\Http\Message\UriInterface::getPort` may return null or the standard port. This method can be used
+     * independently of the implementation.
+     *
+     * @param UriInterface $uri
+     *
+     * @return bool
+     */
+    public static function isDefaultPort(UriInterface $uri)
+    {
+        return $uri->getPort() === null
+            || (isset(self::$defaultPorts[$uri->getScheme()]) && $uri->getPort() === self::$defaultPorts[$uri->getScheme()]);
+    }
+
+    /**
+     * Whether the URI is absolute, i.e. it has a scheme.
+     *
+     * An instance of UriInterface can either be an absolute URI or a relative reference. This method returns true
+     * if it is the former. An absolute URI has a scheme. A relative reference is used to express a URI relative
+     * to another URI, the base URI. Relative references can be divided into several forms:
+     * - network-path references, e.g. '//example.com/path'
+     * - absolute-path references, e.g. '/path'
+     * - relative-path references, e.g. 'subpath'
+     *
+     * @param UriInterface $uri
+     *
+     * @return bool
+     * @see Uri::isNetworkPathReference
+     * @see Uri::isAbsolutePathReference
+     * @see Uri::isRelativePathReference
+     * @link https://tools.ietf.org/html/rfc3986#section-4
+     */
+    public static function isAbsolute(UriInterface $uri)
+    {
+        return $uri->getScheme() !== '';
+    }
+
+    /**
+     * Whether the URI is a network-path reference.
+     *
+     * A relative reference that begins with two slash characters is termed an network-path reference.
+     *
+     * @param UriInterface $uri
+     *
+     * @return bool
+     * @link https://tools.ietf.org/html/rfc3986#section-4.2
+     */
+    public static function isNetworkPathReference(UriInterface $uri)
+    {
+        return $uri->getScheme() === '' && $uri->getAuthority() !== '';
+    }
+
+    /**
+     * Whether the URI is a absolute-path reference.
+     *
+     * A relative reference that begins with a single slash character is termed an absolute-path reference.
+     *
+     * @param UriInterface $uri
+     *
+     * @return bool
+     * @link https://tools.ietf.org/html/rfc3986#section-4.2
+     */
+    public static function isAbsolutePathReference(UriInterface $uri)
+    {
+        return $uri->getScheme() === ''
+            && $uri->getAuthority() === ''
+            && isset($uri->getPath()[0])
+            && $uri->getPath()[0] === '/';
+    }
+
+    /**
+     * Whether the URI is a relative-path reference.
+     *
+     * A relative reference that does not begin with a slash character is termed a relative-path reference.
+     *
+     * @param UriInterface $uri
+     *
+     * @return bool
+     * @link https://tools.ietf.org/html/rfc3986#section-4.2
+     */
+    public static function isRelativePathReference(UriInterface $uri)
+    {
+        return $uri->getScheme() === ''
+            && $uri->getAuthority() === ''
+            && (!isset($uri->getPath()[0]) || $uri->getPath()[0] !== '/');
+    }
+
+    /**
+     * Whether the URI is a same-document reference.
+     *
+     * A same-document reference refers to a URI that is, aside from its fragment
+     * component, identical to the base URI. When no base URI is given, only an empty
+     * URI reference (apart from its fragment) is considered a same-document reference.
+     *
+     * @param UriInterface      $uri  The URI to check
+     * @param UriInterface|null $base An optional base URI to compare against
+     *
+     * @return bool
+     * @link https://tools.ietf.org/html/rfc3986#section-4.4
+     */
+    public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null)
+    {
+        if ($base !== null) {
+            $uri = UriResolver::resolve($base, $uri);
+
+            return ($uri->getScheme() === $base->getScheme())
+                && ($uri->getAuthority() === $base->getAuthority())
+                && ($uri->getPath() === $base->getPath())
+                && ($uri->getQuery() === $base->getQuery());
+        }
+
+        return $uri->getScheme() === '' && $uri->getAuthority() === '' && $uri->getPath() === '' && $uri->getQuery() === '';
+    }
+
+    /**
+     * Removes dot segments from a path and returns the new path.
+     *
+     * @param string $path
+     *
+     * @return string
+     *
+     * @deprecated since version 1.4. Use UriResolver::removeDotSegments instead.
+     * @see UriResolver::removeDotSegments
+     */
+    public static function removeDotSegments($path)
+    {
+        return UriResolver::removeDotSegments($path);
+    }
+
+    /**
+     * Converts the relative URI into a new URI that is resolved against the base URI.
+     *
+     * @param UriInterface        $base Base URI
+     * @param string|UriInterface $rel  Relative URI
+     *
+     * @return UriInterface
+     *
+     * @deprecated since version 1.4. Use UriResolver::resolve instead.
+     * @see UriResolver::resolve
+     */
+    public static function resolve(UriInterface $base, $rel)
+    {
+        if (!($rel instanceof UriInterface)) {
+            $rel = new self($rel);
+        }
+
+        return UriResolver::resolve($base, $rel);
+    }
+
+    /**
+     * Creates a new URI with a specific query string value removed.
+     *
+     * Any existing query string values that exactly match the provided key are
+     * removed.
+     *
+     * @param UriInterface $uri URI to use as a base.
+     * @param string       $key Query string key to remove.
+     *
+     * @return UriInterface
+     */
+    public static function withoutQueryValue(UriInterface $uri, $key)
+    {
+        $current = $uri->getQuery();
+        if ($current === '') {
+            return $uri;
+        }
+
+        $decodedKey = rawurldecode($key);
+        $result = array_filter(explode('&', $current), function ($part) use ($decodedKey) {
+            return rawurldecode(explode('=', $part)[0]) !== $decodedKey;
+        });
+
+        return $uri->withQuery(implode('&', $result));
+    }
+
+    /**
+     * Creates a new URI with a specific query string value.
+     *
+     * Any existing query string values that exactly match the provided key are
+     * removed and replaced with the given key value pair.
+     *
+     * A value of null will set the query string key without a value, e.g. "key"
+     * instead of "key=value".
+     *
+     * @param UriInterface $uri   URI to use as a base.
+     * @param string       $key   Key to set.
+     * @param string|null  $value Value to set
+     *
+     * @return UriInterface
+     */
+    public static function withQueryValue(UriInterface $uri, $key, $value)
+    {
+        $current = $uri->getQuery();
+
+        if ($current === '') {
+            $result = [];
+        } else {
+            $decodedKey = rawurldecode($key);
+            $result = array_filter(explode('&', $current), function ($part) use ($decodedKey) {
+                return rawurldecode(explode('=', $part)[0]) !== $decodedKey;
+            });
+        }
+
+        // Query string separators ("=", "&") within the key or value need to be encoded
+        // (while preventing double-encoding) before setting the query string. All other
+        // chars that need percent-encoding will be encoded by withQuery().
+        $key = strtr($key, self::$replaceQuery);
+
+        if ($value !== null) {
+            $result[] = $key . '=' . strtr($value, self::$replaceQuery);
+        } else {
+            $result[] = $key;
+        }
+
+        return $uri->withQuery(implode('&', $result));
+    }
+
+    /**
+     * Creates a URI from a hash of `parse_url` components.
+     *
+     * @param array $parts
+     *
+     * @return UriInterface
+     * @link http://php.net/manual/en/function.parse-url.php
+     *
+     * @throws \InvalidArgumentException If the components do not form a valid URI.
+     */
+    public static function fromParts(array $parts)
+    {
+        $uri = new self();
+        $uri->applyParts($parts);
+        $uri->validateState();
+
+        return $uri;
+    }
+
+    public function getScheme()
+    {
+        return $this->scheme;
+    }
+
+    public function getAuthority()
+    {
+        $authority = $this->host;
+        if ($this->userInfo !== '') {
+            $authority = $this->userInfo . '@' . $authority;
+        }
+
+        if ($this->port !== null) {
+            $authority .= ':' . $this->port;
+        }
+
+        return $authority;
+    }
+
+    public function getUserInfo()
+    {
+        return $this->userInfo;
+    }
+
+    public function getHost()
+    {
+        return $this->host;
+    }
+
+    public function getPort()
+    {
+        return $this->port;
+    }
+
+    public function getPath()
+    {
+        return $this->path;
+    }
+
+    public function getQuery()
+    {
+        return $this->query;
+    }
+
+    public function getFragment()
+    {
+        return $this->fragment;
+    }
+
+    public function withScheme($scheme)
+    {
+        $scheme = $this->filterScheme($scheme);
+
+        if ($this->scheme === $scheme) {
+            return $this;
+        }
+
+        $new = clone $this;
+        $new->scheme = $scheme;
+        $new->removeDefaultPort();
+        $new->validateState();
+
+        return $new;
+    }
+
+    public function withUserInfo($user, $password = null)
+    {
+        $info = $user;
+        if ($password != '') {
+            $info .= ':' . $password;
+        }
+
+        if ($this->userInfo === $info) {
+            return $this;
+        }
+
+        $new = clone $this;
+        $new->userInfo = $info;
+        $new->validateState();
+
+        return $new;
+    }
+
+    public function withHost($host)
+    {
+        $host = $this->filterHost($host);
+
+        if ($this->host === $host) {
+            return $this;
+        }
+
+        $new = clone $this;
+        $new->host = $host;
+        $new->validateState();
+
+        return $new;
+    }
+
+    public function withPort($port)
+    {
+        $port = $this->filterPort($port);
+
+        if ($this->port === $port) {
+            return $this;
+        }
+
+        $new = clone $this;
+        $new->port = $port;
+        $new->removeDefaultPort();
+        $new->validateState();
+
+        return $new;
+    }
+
+    public function withPath($path)
+    {
+        $path = $this->filterPath($path);
+
+        if ($this->path === $path) {
+            return $this;
+        }
+
+        $new = clone $this;
+        $new->path = $path;
+        $new->validateState();
+
+        return $new;
+    }
+
+    public function withQuery($query)
+    {
+        $query = $this->filterQueryAndFragment($query);
+
+        if ($this->query === $query) {
+            return $this;
+        }
+
+        $new = clone $this;
+        $new->query = $query;
+
+        return $new;
+    }
+
+    public function withFragment($fragment)
+    {
+        $fragment = $this->filterQueryAndFragment($fragment);
+
+        if ($this->fragment === $fragment) {
+            return $this;
+        }
+
+        $new = clone $this;
+        $new->fragment = $fragment;
+
+        return $new;
+    }
+
+    /**
+     * Apply parse_url parts to a URI.
+     *
+     * @param array $parts Array of parse_url parts to apply.
+     */
+    private function applyParts(array $parts)
+    {
+        $this->scheme = isset($parts['scheme'])
+            ? $this->filterScheme($parts['scheme'])
+            : '';
+        $this->userInfo = isset($parts['user']) ? $parts['user'] : '';
+        $this->host = isset($parts['host'])
+            ? $this->filterHost($parts['host'])
+            : '';
+        $this->port = isset($parts['port'])
+            ? $this->filterPort($parts['port'])
+            : null;
+        $this->path = isset($parts['path'])
+            ? $this->filterPath($parts['path'])
+            : '';
+        $this->query = isset($parts['query'])
+            ? $this->filterQueryAndFragment($parts['query'])
+            : '';
+        $this->fragment = isset($parts['fragment'])
+            ? $this->filterQueryAndFragment($parts['fragment'])
+            : '';
+        if (isset($parts['pass'])) {
+            $this->userInfo .= ':' . $parts['pass'];
+        }
+
+        $this->removeDefaultPort();
+    }
+
+    /**
+     * @param string $scheme
+     *
+     * @return string
+     *
+     * @throws \InvalidArgumentException If the scheme is invalid.
+     */
+    private function filterScheme($scheme)
+    {
+        if (!is_string($scheme)) {
+            throw new \InvalidArgumentException('Scheme must be a string');
+        }
+
+        return strtolower($scheme);
+    }
+
+    /**
+     * @param string $host
+     *
+     * @return string
+     *
+     * @throws \InvalidArgumentException If the host is invalid.
+     */
+    private function filterHost($host)
+    {
+        if (!is_string($host)) {
+            throw new \InvalidArgumentException('Host must be a string');
+        }
+
+        return strtolower($host);
+    }
+
+    /**
+     * @param int|null $port
+     *
+     * @return int|null
+     *
+     * @throws \InvalidArgumentException If the port is invalid.
+     */
+    private function filterPort($port)
+    {
+        if ($port === null) {
+            return null;
+        }
+
+        $port = (int) $port;
+        if (1 > $port || 0xffff < $port) {
+            throw new \InvalidArgumentException(
+                sprintf('Invalid port: %d. Must be between 1 and 65535', $port)
+            );
+        }
+
+        return $port;
+    }
+
+    private function removeDefaultPort()
+    {
+        if ($this->port !== null && self::isDefaultPort($this)) {
+            $this->port = null;
+        }
+    }
+
+    /**
+     * Filters the path of a URI
+     *
+     * @param string $path
+     *
+     * @return string
+     *
+     * @throws \InvalidArgumentException If the path is invalid.
+     */
+    private function filterPath($path)
+    {
+        if (!is_string($path)) {
+            throw new \InvalidArgumentException('Path must be a string');
+        }
+
+        return preg_replace_callback(
+            '/(?:[^' . self::$charUnreserved . self::$charSubDelims . '%:@\/]++|%(?![A-Fa-f0-9]{2}))/',
+            [$this, 'rawurlencodeMatchZero'],
+            $path
+        );
+    }
+
+    /**
+     * Filters the query string or fragment of a URI.
+     *
+     * @param string $str
+     *
+     * @return string
+     *
+     * @throws \InvalidArgumentException If the query or fragment is invalid.
+     */
+    private function filterQueryAndFragment($str)
+    {
+        if (!is_string($str)) {
+            throw new \InvalidArgumentException('Query and fragment must be a string');
+        }
+
+        return preg_replace_callback(
+            '/(?:[^' . self::$charUnreserved . self::$charSubDelims . '%:@\/\?]++|%(?![A-Fa-f0-9]{2}))/',
+            [$this, 'rawurlencodeMatchZero'],
+            $str
+        );
+    }
+
+    private function rawurlencodeMatchZero(array $match)
+    {
+        return rawurlencode($match[0]);
+    }
+
+    private function validateState()
+    {
+        if ($this->host === '' && ($this->scheme === 'http' || $this->scheme === 'https')) {
+            $this->host = self::HTTP_DEFAULT_HOST;
+        }
+
+        if ($this->getAuthority() === '') {
+            if (0 === strpos($this->path, '//')) {
+                throw new \InvalidArgumentException('The path of a URI without an authority must not start with two slashes "//"');
+            }
+            if ($this->scheme === '' && false !== strpos(explode('/', $this->path, 2)[0], ':')) {
+                throw new \InvalidArgumentException('A relative URI must not have a path beginning with a segment containing a colon');
+            }
+        } elseif (isset($this->path[0]) && $this->path[0] !== '/') {
+            @trigger_error(
+                'The path of a URI with an authority must start with a slash "/" or be empty. Automagically fixing the URI ' .
+                'by adding a leading slash to the path is deprecated since version 1.4 and will throw an exception instead.',
+                E_USER_DEPRECATED
+            );
+            $this->path = '/'. $this->path;
+            //throw new \InvalidArgumentException('The path of a URI with an authority must start with a slash "/" or be empty');
+        }
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/UriNormalizer.php b/vendor/guzzlehttp/psr7/src/UriNormalizer.php
new file mode 100644
index 00000000000..384c29e5086
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/UriNormalizer.php
@@ -0,0 +1,216 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\UriInterface;
+
+/**
+ * Provides methods to normalize and compare URIs.
+ *
+ * @author Tobias Schultze
+ *
+ * @link https://tools.ietf.org/html/rfc3986#section-6
+ */
+final class UriNormalizer
+{
+    /**
+     * Default normalizations which only include the ones that preserve semantics.
+     *
+     * self::CAPITALIZE_PERCENT_ENCODING | self::DECODE_UNRESERVED_CHARACTERS | self::CONVERT_EMPTY_PATH |
+     * self::REMOVE_DEFAULT_HOST | self::REMOVE_DEFAULT_PORT | self::REMOVE_DOT_SEGMENTS
+     */
+    const PRESERVING_NORMALIZATIONS = 63;
+
+    /**
+     * All letters within a percent-encoding triplet (e.g., "%3A") are case-insensitive, and should be capitalized.
+     *
+     * Example: http://example.org/a%c2%b1b → http://example.org/a%C2%B1b
+     */
+    const CAPITALIZE_PERCENT_ENCODING = 1;
+
+    /**
+     * Decodes percent-encoded octets of unreserved characters.
+     *
+     * For consistency, percent-encoded octets in the ranges of ALPHA (%41–%5A and %61–%7A), DIGIT (%30–%39),
+     * hyphen (%2D), period (%2E), underscore (%5F), or tilde (%7E) should not be created by URI producers and,
+     * when found in a URI, should be decoded to their corresponding unreserved characters by URI normalizers.
+     *
+     * Example: http://example.org/%7Eusern%61me/ → http://example.org/~username/
+     */
+    const DECODE_UNRESERVED_CHARACTERS = 2;
+
+    /**
+     * Converts the empty path to "/" for http and https URIs.
+     *
+     * Example: http://example.org → http://example.org/
+     */
+    const CONVERT_EMPTY_PATH = 4;
+
+    /**
+     * Removes the default host of the given URI scheme from the URI.
+     *
+     * Only the "file" scheme defines the default host "localhost".
+     * All of `file:/myfile`, `file:///myfile`, and `file://localhost/myfile`
+     * are equivalent according to RFC 3986. The first format is not accepted
+     * by PHPs stream functions and thus already normalized implicitly to the
+     * second format in the Uri class. See `GuzzleHttp\Psr7\Uri::composeComponents`.
+     *
+     * Example: file://localhost/myfile → file:///myfile
+     */
+    const REMOVE_DEFAULT_HOST = 8;
+
+    /**
+     * Removes the default port of the given URI scheme from the URI.
+     *
+     * Example: http://example.org:80/ → http://example.org/
+     */
+    const REMOVE_DEFAULT_PORT = 16;
+
+    /**
+     * Removes unnecessary dot-segments.
+     *
+     * Dot-segments in relative-path references are not removed as it would
+     * change the semantics of the URI reference.
+     *
+     * Example: http://example.org/../a/b/../c/./d.html → http://example.org/a/c/d.html
+     */
+    const REMOVE_DOT_SEGMENTS = 32;
+
+    /**
+     * Paths which include two or more adjacent slashes are converted to one.
+     *
+     * Webservers usually ignore duplicate slashes and treat those URIs equivalent.
+     * But in theory those URIs do not need to be equivalent. So this normalization
+     * may change the semantics. Encoded slashes (%2F) are not removed.
+     *
+     * Example: http://example.org//foo///bar.html → http://example.org/foo/bar.html
+     */
+    const REMOVE_DUPLICATE_SLASHES = 64;
+
+    /**
+     * Sort query parameters with their values in alphabetical order.
+     *
+     * However, the order of parameters in a URI may be significant (this is not defined by the standard).
+     * So this normalization is not safe and may change the semantics of the URI.
+     *
+     * Example: ?lang=en&article=fred → ?article=fred&lang=en
+     *
+     * Note: The sorting is neither locale nor Unicode aware (the URI query does not get decoded at all) as the
+     * purpose is to be able to compare URIs in a reproducible way, not to have the params sorted perfectly.
+     */
+    const SORT_QUERY_PARAMETERS = 128;
+
+    /**
+     * Returns a normalized URI.
+     *
+     * The scheme and host component are already normalized to lowercase per PSR-7 UriInterface.
+     * This methods adds additional normalizations that can be configured with the $flags parameter.
+     *
+     * PSR-7 UriInterface cannot distinguish between an empty component and a missing component as
+     * getQuery(), getFragment() etc. always return a string. This means the URIs "/?#" and "/" are
+     * treated equivalent which is not necessarily true according to RFC 3986. But that difference
+     * is highly uncommon in reality. So this potential normalization is implied in PSR-7 as well.
+     *
+     * @param UriInterface $uri   The URI to normalize
+     * @param int          $flags A bitmask of normalizations to apply, see constants
+     *
+     * @return UriInterface The normalized URI
+     * @link https://tools.ietf.org/html/rfc3986#section-6.2
+     */
+    public static function normalize(UriInterface $uri, $flags = self::PRESERVING_NORMALIZATIONS)
+    {
+        if ($flags & self::CAPITALIZE_PERCENT_ENCODING) {
+            $uri = self::capitalizePercentEncoding($uri);
+        }
+
+        if ($flags & self::DECODE_UNRESERVED_CHARACTERS) {
+            $uri = self::decodeUnreservedCharacters($uri);
+        }
+
+        if ($flags & self::CONVERT_EMPTY_PATH && $uri->getPath() === '' &&
+            ($uri->getScheme() === 'http' || $uri->getScheme() === 'https')
+        ) {
+            $uri = $uri->withPath('/');
+        }
+
+        if ($flags & self::REMOVE_DEFAULT_HOST && $uri->getScheme() === 'file' && $uri->getHost() === 'localhost') {
+            $uri = $uri->withHost('');
+        }
+
+        if ($flags & self::REMOVE_DEFAULT_PORT && $uri->getPort() !== null && Uri::isDefaultPort($uri)) {
+            $uri = $uri->withPort(null);
+        }
+
+        if ($flags & self::REMOVE_DOT_SEGMENTS && !Uri::isRelativePathReference($uri)) {
+            $uri = $uri->withPath(UriResolver::removeDotSegments($uri->getPath()));
+        }
+
+        if ($flags & self::REMOVE_DUPLICATE_SLASHES) {
+            $uri = $uri->withPath(preg_replace('#//++#', '/', $uri->getPath()));
+        }
+
+        if ($flags & self::SORT_QUERY_PARAMETERS && $uri->getQuery() !== '') {
+            $queryKeyValues = explode('&', $uri->getQuery());
+            sort($queryKeyValues);
+            $uri = $uri->withQuery(implode('&', $queryKeyValues));
+        }
+
+        return $uri;
+    }
+
+    /**
+     * Whether two URIs can be considered equivalent.
+     *
+     * Both URIs are normalized automatically before comparison with the given $normalizations bitmask. The method also
+     * accepts relative URI references and returns true when they are equivalent. This of course assumes they will be
+     * resolved against the same base URI. If this is not the case, determination of equivalence or difference of
+     * relative references does not mean anything.
+     *
+     * @param UriInterface $uri1           An URI to compare
+     * @param UriInterface $uri2           An URI to compare
+     * @param int          $normalizations A bitmask of normalizations to apply, see constants
+     *
+     * @return bool
+     * @link https://tools.ietf.org/html/rfc3986#section-6.1
+     */
+    public static function isEquivalent(UriInterface $uri1, UriInterface $uri2, $normalizations = self::PRESERVING_NORMALIZATIONS)
+    {
+        return (string) self::normalize($uri1, $normalizations) === (string) self::normalize($uri2, $normalizations);
+    }
+
+    private static function capitalizePercentEncoding(UriInterface $uri)
+    {
+        $regex = '/(?:%[A-Fa-f0-9]{2})++/';
+
+        $callback = function (array $match) {
+            return strtoupper($match[0]);
+        };
+
+        return
+            $uri->withPath(
+                preg_replace_callback($regex, $callback, $uri->getPath())
+            )->withQuery(
+                preg_replace_callback($regex, $callback, $uri->getQuery())
+            );
+    }
+
+    private static function decodeUnreservedCharacters(UriInterface $uri)
+    {
+        $regex = '/%(?:2D|2E|5F|7E|3[0-9]|[46][1-9A-F]|[57][0-9A])/i';
+
+        $callback = function (array $match) {
+            return rawurldecode($match[0]);
+        };
+
+        return
+            $uri->withPath(
+                preg_replace_callback($regex, $callback, $uri->getPath())
+            )->withQuery(
+                preg_replace_callback($regex, $callback, $uri->getQuery())
+            );
+    }
+
+    private function __construct()
+    {
+        // cannot be instantiated
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/UriResolver.php b/vendor/guzzlehttp/psr7/src/UriResolver.php
new file mode 100644
index 00000000000..c1cb8a275af
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/UriResolver.php
@@ -0,0 +1,219 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\UriInterface;
+
+/**
+ * Resolves a URI reference in the context of a base URI and the opposite way.
+ *
+ * @author Tobias Schultze
+ *
+ * @link https://tools.ietf.org/html/rfc3986#section-5
+ */
+final class UriResolver
+{
+    /**
+     * Removes dot segments from a path and returns the new path.
+     *
+     * @param string $path
+     *
+     * @return string
+     * @link http://tools.ietf.org/html/rfc3986#section-5.2.4
+     */
+    public static function removeDotSegments($path)
+    {
+        if ($path === '' || $path === '/') {
+            return $path;
+        }
+
+        $results = [];
+        $segments = explode('/', $path);
+        foreach ($segments as $segment) {
+            if ($segment === '..') {
+                array_pop($results);
+            } elseif ($segment !== '.') {
+                $results[] = $segment;
+            }
+        }
+
+        $newPath = implode('/', $results);
+
+        if ($path[0] === '/' && (!isset($newPath[0]) || $newPath[0] !== '/')) {
+            // Re-add the leading slash if necessary for cases like "/.."
+            $newPath = '/' . $newPath;
+        } elseif ($newPath !== '' && ($segment === '.' || $segment === '..')) {
+            // Add the trailing slash if necessary
+            // If newPath is not empty, then $segment must be set and is the last segment from the foreach
+            $newPath .= '/';
+        }
+
+        return $newPath;
+    }
+
+    /**
+     * Converts the relative URI into a new URI that is resolved against the base URI.
+     *
+     * @param UriInterface $base Base URI
+     * @param UriInterface $rel  Relative URI
+     *
+     * @return UriInterface
+     * @link http://tools.ietf.org/html/rfc3986#section-5.2
+     */
+    public static function resolve(UriInterface $base, UriInterface $rel)
+    {
+        if ((string) $rel === '') {
+            // we can simply return the same base URI instance for this same-document reference
+            return $base;
+        }
+
+        if ($rel->getScheme() != '') {
+            return $rel->withPath(self::removeDotSegments($rel->getPath()));
+        }
+
+        if ($rel->getAuthority() != '') {
+            $targetAuthority = $rel->getAuthority();
+            $targetPath = self::removeDotSegments($rel->getPath());
+            $targetQuery = $rel->getQuery();
+        } else {
+            $targetAuthority = $base->getAuthority();
+            if ($rel->getPath() === '') {
+                $targetPath = $base->getPath();
+                $targetQuery = $rel->getQuery() != '' ? $rel->getQuery() : $base->getQuery();
+            } else {
+                if ($rel->getPath()[0] === '/') {
+                    $targetPath = $rel->getPath();
+                } else {
+                    if ($targetAuthority != '' && $base->getPath() === '') {
+                        $targetPath = '/' . $rel->getPath();
+                    } else {
+                        $lastSlashPos = strrpos($base->getPath(), '/');
+                        if ($lastSlashPos === false) {
+                            $targetPath = $rel->getPath();
+                        } else {
+                            $targetPath = substr($base->getPath(), 0, $lastSlashPos + 1) . $rel->getPath();
+                        }
+                    }
+                }
+                $targetPath = self::removeDotSegments($targetPath);
+                $targetQuery = $rel->getQuery();
+            }
+        }
+
+        return new Uri(Uri::composeComponents(
+            $base->getScheme(),
+            $targetAuthority,
+            $targetPath,
+            $targetQuery,
+            $rel->getFragment()
+        ));
+    }
+
+    /**
+     * Returns the target URI as a relative reference from the base URI.
+     *
+     * This method is the counterpart to resolve():
+     *
+     *    (string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target))
+     *
+     * One use-case is to use the current request URI as base URI and then generate relative links in your documents
+     * to reduce the document size or offer self-contained downloadable document archives.
+     *
+     *    $base = new Uri('http://example.com/a/b/');
+     *    echo UriResolver::relativize($base, new Uri('http://example.com/a/b/c'));  // prints 'c'.
+     *    echo UriResolver::relativize($base, new Uri('http://example.com/a/x/y'));  // prints '../x/y'.
+     *    echo UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'.
+     *    echo UriResolver::relativize($base, new Uri('http://example.org/a/b/'));   // prints '//example.org/a/b/'.
+     *
+     * This method also accepts a target that is already relative and will try to relativize it further. Only a
+     * relative-path reference will be returned as-is.
+     *
+     *    echo UriResolver::relativize($base, new Uri('/a/b/c'));  // prints 'c' as well
+     *
+     * @param UriInterface $base   Base URI
+     * @param UriInterface $target Target URI
+     *
+     * @return UriInterface The relative URI reference
+     */
+    public static function relativize(UriInterface $base, UriInterface $target)
+    {
+        if ($target->getScheme() !== '' &&
+            ($base->getScheme() !== $target->getScheme() || $target->getAuthority() === '' && $base->getAuthority() !== '')
+        ) {
+            return $target;
+        }
+
+        if (Uri::isRelativePathReference($target)) {
+            // As the target is already highly relative we return it as-is. It would be possible to resolve
+            // the target with `$target = self::resolve($base, $target);` and then try make it more relative
+            // by removing a duplicate query. But let's not do that automatically.
+            return $target;
+        }
+
+        if ($target->getAuthority() !== '' && $base->getAuthority() !== $target->getAuthority()) {
+            return $target->withScheme('');
+        }
+
+        // We must remove the path before removing the authority because if the path starts with two slashes, the URI
+        // would turn invalid. And we also cannot set a relative path before removing the authority, as that is also
+        // invalid.
+        $emptyPathUri = $target->withScheme('')->withPath('')->withUserInfo('')->withPort(null)->withHost('');
+
+        if ($base->getPath() !== $target->getPath()) {
+            return $emptyPathUri->withPath(self::getRelativePath($base, $target));
+        }
+
+        if ($base->getQuery() === $target->getQuery()) {
+            // Only the target fragment is left. And it must be returned even if base and target fragment are the same.
+            return $emptyPathUri->withQuery('');
+        }
+
+        // If the base URI has a query but the target has none, we cannot return an empty path reference as it would
+        // inherit the base query component when resolving.
+        if ($target->getQuery() === '') {
+            $segments = explode('/', $target->getPath());
+            $lastSegment = end($segments);
+
+            return $emptyPathUri->withPath($lastSegment === '' ? './' : $lastSegment);
+        }
+
+        return $emptyPathUri;
+    }
+
+    private static function getRelativePath(UriInterface $base, UriInterface $target)
+    {
+        $sourceSegments = explode('/', $base->getPath());
+        $targetSegments = explode('/', $target->getPath());
+        array_pop($sourceSegments);
+        $targetLastSegment = array_pop($targetSegments);
+        foreach ($sourceSegments as $i => $segment) {
+            if (isset($targetSegments[$i]) && $segment === $targetSegments[$i]) {
+                unset($sourceSegments[$i], $targetSegments[$i]);
+            } else {
+                break;
+            }
+        }
+        $targetSegments[] = $targetLastSegment;
+        $relativePath = str_repeat('../', count($sourceSegments)) . implode('/', $targetSegments);
+
+        // A reference to am empty last segment or an empty first sub-segment must be prefixed with "./".
+        // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used
+        // as the first segment of a relative-path reference, as it would be mistaken for a scheme name.
+        if ('' === $relativePath || false !== strpos(explode('/', $relativePath, 2)[0], ':')) {
+            $relativePath = "./$relativePath";
+        } elseif ('/' === $relativePath[0]) {
+            if ($base->getAuthority() != '' && $base->getPath() === '') {
+                // In this case an extra slash is added by resolve() automatically. So we must not add one here.
+                $relativePath = ".$relativePath";
+            } else {
+                $relativePath = "./$relativePath";
+            }
+        }
+
+        return $relativePath;
+    }
+
+    private function __construct()
+    {
+        // cannot be instantiated
+    }
+}
diff --git a/vendor/guzzlehttp/psr7/src/functions.php b/vendor/guzzlehttp/psr7/src/functions.php
new file mode 100644
index 00000000000..e40348d6abd
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/functions.php
@@ -0,0 +1,828 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\MessageInterface;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Message\StreamInterface;
+use Psr\Http\Message\UriInterface;
+
+/**
+ * Returns the string representation of an HTTP message.
+ *
+ * @param MessageInterface $message Message to convert to a string.
+ *
+ * @return string
+ */
+function str(MessageInterface $message)
+{
+    if ($message instanceof RequestInterface) {
+        $msg = trim($message->getMethod() . ' '
+                . $message->getRequestTarget())
+            . ' HTTP/' . $message->getProtocolVersion();
+        if (!$message->hasHeader('host')) {
+            $msg .= "\r\nHost: " . $message->getUri()->getHost();
+        }
+    } elseif ($message instanceof ResponseInterface) {
+        $msg = 'HTTP/' . $message->getProtocolVersion() . ' '
+            . $message->getStatusCode() . ' '
+            . $message->getReasonPhrase();
+    } else {
+        throw new \InvalidArgumentException('Unknown message type');
+    }
+
+    foreach ($message->getHeaders() as $name => $values) {
+        $msg .= "\r\n{$name}: " . implode(', ', $values);
+    }
+
+    return "{$msg}\r\n\r\n" . $message->getBody();
+}
+
+/**
+ * Returns a UriInterface for the given value.
+ *
+ * This function accepts a string or {@see Psr\Http\Message\UriInterface} and
+ * returns a UriInterface for the given value. If the value is already a
+ * `UriInterface`, it is returned as-is.
+ *
+ * @param string|UriInterface $uri
+ *
+ * @return UriInterface
+ * @throws \InvalidArgumentException
+ */
+function uri_for($uri)
+{
+    if ($uri instanceof UriInterface) {
+        return $uri;
+    } elseif (is_string($uri)) {
+        return new Uri($uri);
+    }
+
+    throw new \InvalidArgumentException('URI must be a string or UriInterface');
+}
+
+/**
+ * Create a new stream based on the input type.
+ *
+ * Options is an associative array that can contain the following keys:
+ * - metadata: Array of custom metadata.
+ * - size: Size of the stream.
+ *
+ * @param resource|string|null|int|float|bool|StreamInterface|callable $resource Entity body data
+ * @param array                                                        $options  Additional options
+ *
+ * @return Stream
+ * @throws \InvalidArgumentException if the $resource arg is not valid.
+ */
+function stream_for($resource = '', array $options = [])
+{
+    if (is_scalar($resource)) {
+        $stream = fopen('php://temp', 'r+');
+        if ($resource !== '') {
+            fwrite($stream, $resource);
+            fseek($stream, 0);
+        }
+        return new Stream($stream, $options);
+    }
+
+    switch (gettype($resource)) {
+        case 'resource':
+            return new Stream($resource, $options);
+        case 'object':
+            if ($resource instanceof StreamInterface) {
+                return $resource;
+            } elseif ($resource instanceof \Iterator) {
+                return new PumpStream(function () use ($resource) {
+                    if (!$resource->valid()) {
+                        return false;
+                    }
+                    $result = $resource->current();
+                    $resource->next();
+                    return $result;
+                }, $options);
+            } elseif (method_exists($resource, '__toString')) {
+                return stream_for((string) $resource, $options);
+            }
+            break;
+        case 'NULL':
+            return new Stream(fopen('php://temp', 'r+'), $options);
+    }
+
+    if (is_callable($resource)) {
+        return new PumpStream($resource, $options);
+    }
+
+    throw new \InvalidArgumentException('Invalid resource type: ' . gettype($resource));
+}
+
+/**
+ * Parse an array of header values containing ";" separated data into an
+ * array of associative arrays representing the header key value pair
+ * data of the header. When a parameter does not contain a value, but just
+ * contains a key, this function will inject a key with a '' string value.
+ *
+ * @param string|array $header Header to parse into components.
+ *
+ * @return array Returns the parsed header values.
+ */
+function parse_header($header)
+{
+    static $trimmed = "\"'  \n\t\r";
+    $params = $matches = [];
+
+    foreach (normalize_header($header) as $val) {
+        $part = [];
+        foreach (preg_split('/;(?=([^"]*"[^"]*")*[^"]*$)/', $val) as $kvp) {
+            if (preg_match_all('/<[^>]+>|[^=]+/', $kvp, $matches)) {
+                $m = $matches[0];
+                if (isset($m[1])) {
+                    $part[trim($m[0], $trimmed)] = trim($m[1], $trimmed);
+                } else {
+                    $part[] = trim($m[0], $trimmed);
+                }
+            }
+        }
+        if ($part) {
+            $params[] = $part;
+        }
+    }
+
+    return $params;
+}
+
+/**
+ * Converts an array of header values that may contain comma separated
+ * headers into an array of headers with no comma separated values.
+ *
+ * @param string|array $header Header to normalize.
+ *
+ * @return array Returns the normalized header field values.
+ */
+function normalize_header($header)
+{
+    if (!is_array($header)) {
+        return array_map('trim', explode(',', $header));
+    }
+
+    $result = [];
+    foreach ($header as $value) {
+        foreach ((array) $value as $v) {
+            if (strpos($v, ',') === false) {
+                $result[] = $v;
+                continue;
+            }
+            foreach (preg_split('/,(?=([^"]*"[^"]*")*[^"]*$)/', $v) as $vv) {
+                $result[] = trim($vv);
+            }
+        }
+    }
+
+    return $result;
+}
+
+/**
+ * Clone and modify a request with the given changes.
+ *
+ * The changes can be one of:
+ * - method: (string) Changes the HTTP method.
+ * - set_headers: (array) Sets the given headers.
+ * - remove_headers: (array) Remove the given headers.
+ * - body: (mixed) Sets the given body.
+ * - uri: (UriInterface) Set the URI.
+ * - query: (string) Set the query string value of the URI.
+ * - version: (string) Set the protocol version.
+ *
+ * @param RequestInterface $request Request to clone and modify.
+ * @param array            $changes Changes to apply.
+ *
+ * @return RequestInterface
+ */
+function modify_request(RequestInterface $request, array $changes)
+{
+    if (!$changes) {
+        return $request;
+    }
+
+    $headers = $request->getHeaders();
+
+    if (!isset($changes['uri'])) {
+        $uri = $request->getUri();
+    } else {
+        // Remove the host header if one is on the URI
+        if ($host = $changes['uri']->getHost()) {
+            $changes['set_headers']['Host'] = $host;
+
+            if ($port = $changes['uri']->getPort()) {
+                $standardPorts = ['http' => 80, 'https' => 443];
+                $scheme = $changes['uri']->getScheme();
+                if (isset($standardPorts[$scheme]) && $port != $standardPorts[$scheme]) {
+                    $changes['set_headers']['Host'] .= ':'.$port;
+                }
+            }
+        }
+        $uri = $changes['uri'];
+    }
+
+    if (!empty($changes['remove_headers'])) {
+        $headers = _caseless_remove($changes['remove_headers'], $headers);
+    }
+
+    if (!empty($changes['set_headers'])) {
+        $headers = _caseless_remove(array_keys($changes['set_headers']), $headers);
+        $headers = $changes['set_headers'] + $headers;
+    }
+
+    if (isset($changes['query'])) {
+        $uri = $uri->withQuery($changes['query']);
+    }
+
+    if ($request instanceof ServerRequestInterface) {
+        return new ServerRequest(
+            isset($changes['method']) ? $changes['method'] : $request->getMethod(),
+            $uri,
+            $headers,
+            isset($changes['body']) ? $changes['body'] : $request->getBody(),
+            isset($changes['version'])
+                ? $changes['version']
+                : $request->getProtocolVersion(),
+            $request->getServerParams()
+        );
+    }
+
+    return new Request(
+        isset($changes['method']) ? $changes['method'] : $request->getMethod(),
+        $uri,
+        $headers,
+        isset($changes['body']) ? $changes['body'] : $request->getBody(),
+        isset($changes['version'])
+            ? $changes['version']
+            : $request->getProtocolVersion()
+    );
+}
+
+/**
+ * Attempts to rewind a message body and throws an exception on failure.
+ *
+ * The body of the message will only be rewound if a call to `tell()` returns a
+ * value other than `0`.
+ *
+ * @param MessageInterface $message Message to rewind
+ *
+ * @throws \RuntimeException
+ */
+function rewind_body(MessageInterface $message)
+{
+    $body = $message->getBody();
+
+    if ($body->tell()) {
+        $body->rewind();
+    }
+}
+
+/**
+ * Safely opens a PHP stream resource using a filename.
+ *
+ * When fopen fails, PHP normally raises a warning. This function adds an
+ * error handler that checks for errors and throws an exception instead.
+ *
+ * @param string $filename File to open
+ * @param string $mode     Mode used to open the file
+ *
+ * @return resource
+ * @throws \RuntimeException if the file cannot be opened
+ */
+function try_fopen($filename, $mode)
+{
+    $ex = null;
+    set_error_handler(function () use ($filename, $mode, &$ex) {
+        $ex = new \RuntimeException(sprintf(
+            'Unable to open %s using mode %s: %s',
+            $filename,
+            $mode,
+            func_get_args()[1]
+        ));
+    });
+
+    $handle = fopen($filename, $mode);
+    restore_error_handler();
+
+    if ($ex) {
+        /** @var $ex \RuntimeException */
+        throw $ex;
+    }
+
+    return $handle;
+}
+
+/**
+ * Copy the contents of a stream into a string until the given number of
+ * bytes have been read.
+ *
+ * @param StreamInterface $stream Stream to read
+ * @param int             $maxLen Maximum number of bytes to read. Pass -1
+ *                                to read the entire stream.
+ * @return string
+ * @throws \RuntimeException on error.
+ */
+function copy_to_string(StreamInterface $stream, $maxLen = -1)
+{
+    $buffer = '';
+
+    if ($maxLen === -1) {
+        while (!$stream->eof()) {
+            $buf = $stream->read(1048576);
+            // Using a loose equality here to match on '' and false.
+            if ($buf == null) {
+                break;
+            }
+            $buffer .= $buf;
+        }
+        return $buffer;
+    }
+
+    $len = 0;
+    while (!$stream->eof() && $len < $maxLen) {
+        $buf = $stream->read($maxLen - $len);
+        // Using a loose equality here to match on '' and false.
+        if ($buf == null) {
+            break;
+        }
+        $buffer .= $buf;
+        $len = strlen($buffer);
+    }
+
+    return $buffer;
+}
+
+/**
+ * Copy the contents of a stream into another stream until the given number
+ * of bytes have been read.
+ *
+ * @param StreamInterface $source Stream to read from
+ * @param StreamInterface $dest   Stream to write to
+ * @param int             $maxLen Maximum number of bytes to read. Pass -1
+ *                                to read the entire stream.
+ *
+ * @throws \RuntimeException on error.
+ */
+function copy_to_stream(
+    StreamInterface $source,
+    StreamInterface $dest,
+    $maxLen = -1
+) {
+    $bufferSize = 8192;
+
+    if ($maxLen === -1) {
+        while (!$source->eof()) {
+            if (!$dest->write($source->read($bufferSize))) {
+                break;
+            }
+        }
+    } else {
+        $remaining = $maxLen;
+        while ($remaining > 0 && !$source->eof()) {
+            $buf = $source->read(min($bufferSize, $remaining));
+            $len = strlen($buf);
+            if (!$len) {
+                break;
+            }
+            $remaining -= $len;
+            $dest->write($buf);
+        }
+    }
+}
+
+/**
+ * Calculate a hash of a Stream
+ *
+ * @param StreamInterface $stream    Stream to calculate the hash for
+ * @param string          $algo      Hash algorithm (e.g. md5, crc32, etc)
+ * @param bool            $rawOutput Whether or not to use raw output
+ *
+ * @return string Returns the hash of the stream
+ * @throws \RuntimeException on error.
+ */
+function hash(
+    StreamInterface $stream,
+    $algo,
+    $rawOutput = false
+) {
+    $pos = $stream->tell();
+
+    if ($pos > 0) {
+        $stream->rewind();
+    }
+
+    $ctx = hash_init($algo);
+    while (!$stream->eof()) {
+        hash_update($ctx, $stream->read(1048576));
+    }
+
+    $out = hash_final($ctx, (bool) $rawOutput);
+    $stream->seek($pos);
+
+    return $out;
+}
+
+/**
+ * Read a line from the stream up to the maximum allowed buffer length
+ *
+ * @param StreamInterface $stream    Stream to read from
+ * @param int             $maxLength Maximum buffer length
+ *
+ * @return string|bool
+ */
+function readline(StreamInterface $stream, $maxLength = null)
+{
+    $buffer = '';
+    $size = 0;
+
+    while (!$stream->eof()) {
+        // Using a loose equality here to match on '' and false.
+        if (null == ($byte = $stream->read(1))) {
+            return $buffer;
+        }
+        $buffer .= $byte;
+        // Break when a new line is found or the max length - 1 is reached
+        if ($byte === "\n" || ++$size === $maxLength - 1) {
+            break;
+        }
+    }
+
+    return $buffer;
+}
+
+/**
+ * Parses a request message string into a request object.
+ *
+ * @param string $message Request message string.
+ *
+ * @return Request
+ */
+function parse_request($message)
+{
+    $data = _parse_message($message);
+    $matches = [];
+    if (!preg_match('/^[\S]+\s+([a-zA-Z]+:\/\/|\/).*/', $data['start-line'], $matches)) {
+        throw new \InvalidArgumentException('Invalid request string');
+    }
+    $parts = explode(' ', $data['start-line'], 3);
+    $version = isset($parts[2]) ? explode('/', $parts[2])[1] : '1.1';
+
+    $request = new Request(
+        $parts[0],
+        $matches[1] === '/' ? _parse_request_uri($parts[1], $data['headers']) : $parts[1],
+        $data['headers'],
+        $data['body'],
+        $version
+    );
+
+    return $matches[1] === '/' ? $request : $request->withRequestTarget($parts[1]);
+}
+
+/**
+ * Parses a response message string into a response object.
+ *
+ * @param string $message Response message string.
+ *
+ * @return Response
+ */
+function parse_response($message)
+{
+    $data = _parse_message($message);
+    // According to https://tools.ietf.org/html/rfc7230#section-3.1.2 the space
+    // between status-code and reason-phrase is required. But browsers accept
+    // responses without space and reason as well.
+    if (!preg_match('/^HTTP\/.* [0-9]{3}( .*|$)/', $data['start-line'])) {
+        throw new \InvalidArgumentException('Invalid response string');
+    }
+    $parts = explode(' ', $data['start-line'], 3);
+
+    return new Response(
+        $parts[1],
+        $data['headers'],
+        $data['body'],
+        explode('/', $parts[0])[1],
+        isset($parts[2]) ? $parts[2] : null
+    );
+}
+
+/**
+ * Parse a query string into an associative array.
+ *
+ * If multiple values are found for the same key, the value of that key
+ * value pair will become an array. This function does not parse nested
+ * PHP style arrays into an associative array (e.g., foo[a]=1&foo[b]=2 will
+ * be parsed into ['foo[a]' => '1', 'foo[b]' => '2']).
+ *
+ * @param string      $str         Query string to parse
+ * @param bool|string $urlEncoding How the query string is encoded
+ *
+ * @return array
+ */
+function parse_query($str, $urlEncoding = true)
+{
+    $result = [];
+
+    if ($str === '') {
+        return $result;
+    }
+
+    if ($urlEncoding === true) {
+        $decoder = function ($value) {
+            return rawurldecode(str_replace('+', ' ', $value));
+        };
+    } elseif ($urlEncoding == PHP_QUERY_RFC3986) {
+        $decoder = 'rawurldecode';
+    } elseif ($urlEncoding == PHP_QUERY_RFC1738) {
+        $decoder = 'urldecode';
+    } else {
+        $decoder = function ($str) { return $str; };
+    }
+
+    foreach (explode('&', $str) as $kvp) {
+        $parts = explode('=', $kvp, 2);
+        $key = $decoder($parts[0]);
+        $value = isset($parts[1]) ? $decoder($parts[1]) : null;
+        if (!isset($result[$key])) {
+            $result[$key] = $value;
+        } else {
+            if (!is_array($result[$key])) {
+                $result[$key] = [$result[$key]];
+            }
+            $result[$key][] = $value;
+        }
+    }
+
+    return $result;
+}
+
+/**
+ * Build a query string from an array of key value pairs.
+ *
+ * This function can use the return value of parse_query() to build a query
+ * string. This function does not modify the provided keys when an array is
+ * encountered (like http_build_query would).
+ *
+ * @param array     $params   Query string parameters.
+ * @param int|false $encoding Set to false to not encode, PHP_QUERY_RFC3986
+ *                            to encode using RFC3986, or PHP_QUERY_RFC1738
+ *                            to encode using RFC1738.
+ * @return string
+ */
+function build_query(array $params, $encoding = PHP_QUERY_RFC3986)
+{
+    if (!$params) {
+        return '';
+    }
+
+    if ($encoding === false) {
+        $encoder = function ($str) { return $str; };
+    } elseif ($encoding === PHP_QUERY_RFC3986) {
+        $encoder = 'rawurlencode';
+    } elseif ($encoding === PHP_QUERY_RFC1738) {
+        $encoder = 'urlencode';
+    } else {
+        throw new \InvalidArgumentException('Invalid type');
+    }
+
+    $qs = '';
+    foreach ($params as $k => $v) {
+        $k = $encoder($k);
+        if (!is_array($v)) {
+            $qs .= $k;
+            if ($v !== null) {
+                $qs .= '=' . $encoder($v);
+            }
+            $qs .= '&';
+        } else {
+            foreach ($v as $vv) {
+                $qs .= $k;
+                if ($vv !== null) {
+                    $qs .= '=' . $encoder($vv);
+                }
+                $qs .= '&';
+            }
+        }
+    }
+
+    return $qs ? (string) substr($qs, 0, -1) : '';
+}
+
+/**
+ * Determines the mimetype of a file by looking at its extension.
+ *
+ * @param $filename
+ *
+ * @return null|string
+ */
+function mimetype_from_filename($filename)
+{
+    return mimetype_from_extension(pathinfo($filename, PATHINFO_EXTENSION));
+}
+
+/**
+ * Maps a file extensions to a mimetype.
+ *
+ * @param $extension string The file extension.
+ *
+ * @return string|null
+ * @link http://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x/conf/mime.types
+ */
+function mimetype_from_extension($extension)
+{
+    static $mimetypes = [
+        '7z' => 'application/x-7z-compressed',
+        'aac' => 'audio/x-aac',
+        'ai' => 'application/postscript',
+        'aif' => 'audio/x-aiff',
+        'asc' => 'text/plain',
+        'asf' => 'video/x-ms-asf',
+        'atom' => 'application/atom+xml',
+        'avi' => 'video/x-msvideo',
+        'bmp' => 'image/bmp',
+        'bz2' => 'application/x-bzip2',
+        'cer' => 'application/pkix-cert',
+        'crl' => 'application/pkix-crl',
+        'crt' => 'application/x-x509-ca-cert',
+        'css' => 'text/css',
+        'csv' => 'text/csv',
+        'cu' => 'application/cu-seeme',
+        'deb' => 'application/x-debian-package',
+        'doc' => 'application/msword',
+        'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+        'dvi' => 'application/x-dvi',
+        'eot' => 'application/vnd.ms-fontobject',
+        'eps' => 'application/postscript',
+        'epub' => 'application/epub+zip',
+        'etx' => 'text/x-setext',
+        'flac' => 'audio/flac',
+        'flv' => 'video/x-flv',
+        'gif' => 'image/gif',
+        'gz' => 'application/gzip',
+        'htm' => 'text/html',
+        'html' => 'text/html',
+        'ico' => 'image/x-icon',
+        'ics' => 'text/calendar',
+        'ini' => 'text/plain',
+        'iso' => 'application/x-iso9660-image',
+        'jar' => 'application/java-archive',
+        'jpe' => 'image/jpeg',
+        'jpeg' => 'image/jpeg',
+        'jpg' => 'image/jpeg',
+        'js' => 'text/javascript',
+        'json' => 'application/json',
+        'latex' => 'application/x-latex',
+        'log' => 'text/plain',
+        'm4a' => 'audio/mp4',
+        'm4v' => 'video/mp4',
+        'mid' => 'audio/midi',
+        'midi' => 'audio/midi',
+        'mov' => 'video/quicktime',
+        'mp3' => 'audio/mpeg',
+        'mp4' => 'video/mp4',
+        'mp4a' => 'audio/mp4',
+        'mp4v' => 'video/mp4',
+        'mpe' => 'video/mpeg',
+        'mpeg' => 'video/mpeg',
+        'mpg' => 'video/mpeg',
+        'mpg4' => 'video/mp4',
+        'oga' => 'audio/ogg',
+        'ogg' => 'audio/ogg',
+        'ogv' => 'video/ogg',
+        'ogx' => 'application/ogg',
+        'pbm' => 'image/x-portable-bitmap',
+        'pdf' => 'application/pdf',
+        'pgm' => 'image/x-portable-graymap',
+        'png' => 'image/png',
+        'pnm' => 'image/x-portable-anymap',
+        'ppm' => 'image/x-portable-pixmap',
+        'ppt' => 'application/vnd.ms-powerpoint',
+        'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+        'ps' => 'application/postscript',
+        'qt' => 'video/quicktime',
+        'rar' => 'application/x-rar-compressed',
+        'ras' => 'image/x-cmu-raster',
+        'rss' => 'application/rss+xml',
+        'rtf' => 'application/rtf',
+        'sgm' => 'text/sgml',
+        'sgml' => 'text/sgml',
+        'svg' => 'image/svg+xml',
+        'swf' => 'application/x-shockwave-flash',
+        'tar' => 'application/x-tar',
+        'tif' => 'image/tiff',
+        'tiff' => 'image/tiff',
+        'torrent' => 'application/x-bittorrent',
+        'ttf' => 'application/x-font-ttf',
+        'txt' => 'text/plain',
+        'wav' => 'audio/x-wav',
+        'webm' => 'video/webm',
+        'wma' => 'audio/x-ms-wma',
+        'wmv' => 'video/x-ms-wmv',
+        'woff' => 'application/x-font-woff',
+        'wsdl' => 'application/wsdl+xml',
+        'xbm' => 'image/x-xbitmap',
+        'xls' => 'application/vnd.ms-excel',
+        'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+        'xml' => 'application/xml',
+        'xpm' => 'image/x-xpixmap',
+        'xwd' => 'image/x-xwindowdump',
+        'yaml' => 'text/yaml',
+        'yml' => 'text/yaml',
+        'zip' => 'application/zip',
+    ];
+
+    $extension = strtolower($extension);
+
+    return isset($mimetypes[$extension])
+        ? $mimetypes[$extension]
+        : null;
+}
+
+/**
+ * Parses an HTTP message into an associative array.
+ *
+ * The array contains the "start-line" key containing the start line of
+ * the message, "headers" key containing an associative array of header
+ * array values, and a "body" key containing the body of the message.
+ *
+ * @param string $message HTTP request or response to parse.
+ *
+ * @return array
+ * @internal
+ */
+function _parse_message($message)
+{
+    if (!$message) {
+        throw new \InvalidArgumentException('Invalid message');
+    }
+
+    // Iterate over each line in the message, accounting for line endings
+    $lines = preg_split('/(\\r?\\n)/', $message, -1, PREG_SPLIT_DELIM_CAPTURE);
+    $result = ['start-line' => array_shift($lines), 'headers' => [], 'body' => ''];
+    array_shift($lines);
+
+    for ($i = 0, $totalLines = count($lines); $i < $totalLines; $i += 2) {
+        $line = $lines[$i];
+        // If two line breaks were encountered, then this is the end of body
+        if (empty($line)) {
+            if ($i < $totalLines - 1) {
+                $result['body'] = implode('', array_slice($lines, $i + 2));
+            }
+            break;
+        }
+        if (strpos($line, ':')) {
+            $parts = explode(':', $line, 2);
+            $key = trim($parts[0]);
+            $value = isset($parts[1]) ? trim($parts[1]) : '';
+            $result['headers'][$key][] = $value;
+        }
+    }
+
+    return $result;
+}
+
+/**
+ * Constructs a URI for an HTTP request message.
+ *
+ * @param string $path    Path from the start-line
+ * @param array  $headers Array of headers (each value an array).
+ *
+ * @return string
+ * @internal
+ */
+function _parse_request_uri($path, array $headers)
+{
+    $hostKey = array_filter(array_keys($headers), function ($k) {
+        return strtolower($k) === 'host';
+    });
+
+    // If no host is found, then a full URI cannot be constructed.
+    if (!$hostKey) {
+        return $path;
+    }
+
+    $host = $headers[reset($hostKey)][0];
+    $scheme = substr($host, -4) === ':443' ? 'https' : 'http';
+
+    return $scheme . '://' . $host . '/' . ltrim($path, '/');
+}
+
+/** @internal */
+function _caseless_remove($keys, array $data)
+{
+    $result = [];
+
+    foreach ($keys as &$key) {
+        $key = strtolower($key);
+    }
+
+    foreach ($data as $k => $v) {
+        if (!in_array(strtolower($k), $keys)) {
+            $result[$k] = $v;
+        }
+    }
+
+    return $result;
+}
diff --git a/vendor/guzzlehttp/psr7/src/functions_include.php b/vendor/guzzlehttp/psr7/src/functions_include.php
new file mode 100644
index 00000000000..96a4a83a01a
--- /dev/null
+++ b/vendor/guzzlehttp/psr7/src/functions_include.php
@@ -0,0 +1,6 @@
+<?php
+
+// Don't redefine the functions if included multiple times.
+if (!function_exists('GuzzleHttp\Psr7\str')) {
+    require __DIR__ . '/functions.php';
+}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/.gitignore b/vendor/m4tthumphrey/php-gitlab-api/.gitignore
deleted file mode 100644
index d1502b087b4..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-vendor/
-composer.lock
diff --git a/vendor/m4tthumphrey/php-gitlab-api/.travis.yml b/vendor/m4tthumphrey/php-gitlab-api/.travis.yml
deleted file mode 100644
index 97190200d26..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/.travis.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-language: php
-
-sudo: false
-
-php:
-  - 5.3
-  - 5.4
-  - 5.5
-  - 5.6
-  - 7.0
-
-before_script:
-  - travis_retry composer self-update
-  - travis_retry composer install --no-interaction --prefer-source
-
-script:
-  - vendor/bin/phpunit --verbose --coverage-text
diff --git a/vendor/m4tthumphrey/php-gitlab-api/LICENSE b/vendor/m4tthumphrey/php-gitlab-api/LICENSE
index 8791c72e0c8..a30bb7fa527 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/LICENSE
+++ b/vendor/m4tthumphrey/php-gitlab-api/LICENSE
@@ -1,6 +1,6 @@
 MIT License
 
-Copyright (c) 2017 Matt Humphrey
+Copyright (c) 2018 Matt Humphrey
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/vendor/m4tthumphrey/php-gitlab-api/README.md b/vendor/m4tthumphrey/php-gitlab-api/README.md
deleted file mode 100644
index b8cbdb352a5..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/README.md
+++ /dev/null
@@ -1,96 +0,0 @@
-A PHP wrapper to be used with [Gitlab's API](https://github.com/gitlabhq/gitlabhq/tree/master/doc/api).
-==============
-
-[![Build Status](https://travis-ci.org/m4tthumphrey/php-gitlab-api.svg?branch=master)](https://travis-ci.org/m4tthumphrey/php-gitlab-api)
-
-Based on [php-github-api](https://github.com/m4tthumphrey/php-github-api) and code from [KnpLabs](https://github.com/KnpLabs/php-github-api).
-
-Installation
-------------
-1. Install Composer
-
-    ```bash
-    $ curl -sS https://getcomposer.org/installer | php
-    $ sudo mv composer.phar /usr/local/bin/composer
-    ```
-
-2. Add the following to your require block in composer.json config.
-
-    > Note: be careful when using the `dev-master` tag as this may have unexpected results depending on your version of
-    Gitlab. See the Versioning section below for more information.
-
-    `php composer.phar require m4tthumphrey/php-gitlab-api:dev-master`
-
-3. Include Composer's autoloader:
-
-    ```php
-    require_once dirname(__DIR__).'/vendor/autoload.php';
-    ```
-
-Versioning
-----------
-
-From the 6.0 stable release of Gitlab, I shall now be matching the client version with the Gitlab version. For example
-when Gitlab 6.1 is released I will release version 6.1.0 of the API client. If I need to make future updates to the client
-before the next API version is released, I'll simply use a 3rd build version - `6.1.1`, `6.1.2` etc for example.
-
-It is recommended that you keep your composer file in sync with whatever version of Gitlab you are currently running:
-if you are using 6.0, you should require `6.0.*`; 6.1 should be `6.1.*`...
-
-General API Usage
------------------
-
-```php
-$client = new \Gitlab\Client('http://git.yourdomain.com/api/v3/');               // change here
-$client->authenticate('your_gitlab_token_here', \Gitlab\Client::AUTH_URL_TOKEN); // change here
-
-$project = $client->api('projects')->create('My Project', array(
-  'description' => 'This is a project',
-  'issues_enabled' => false
-));
-
-```
-
-Model Usage
------------
-
-You can also use the library in an object oriented manner:
-
-```php
-$client = new \Gitlab\Client('http://git.yourdomain.com/api/v3/');               // change here
-$client->authenticate('your_gitlab_token_here', \Gitlab\Client::AUTH_URL_TOKEN); // change here
-
-# Creating a new project
-$project = \Gitlab\Model\Project::create($client, 'My Project', array(
-  'description' => 'This is my project',
-  'issues_enabled' => false
-));
-
-$project->addHook('http://mydomain.com/hook/push/1');
-
-# Creating a new issue
-$project = new \Gitlab\Model\Project(1, $client);
-$issue = $project->createIssue('This does not work.', array(
-  'description' => 'This doesn\'t work properly. Please fix.',
-  'assignee_id' => 2
-));
-
-# Closing that issue
-$issue->close();
-```
-
-You get the idea! Take a look around ([API methods](https://github.com/m4tthumphrey/php-gitlab-api/tree/master/lib/Gitlab/Api),
-[models](https://github.com/m4tthumphrey/php-gitlab-api/tree/master/lib/Gitlab/Model)) and please feel free to report any bugs.
-
-Framework Integrations
-----------------------
-- **Symfony** - https://github.com/Zeichen32/GitLabApiBundle
-- **Laravel** - https://github.com/vinkla/gitlab
-
-If you have integrated GitLab into a popular PHP framework, let us know!
-
-Contributing
-------------
-
-There are many parts of Gitlab that I have not added to this as it was originally created for personal use, hence the
-lack of tests. Feel free to fork and add new functionality and tests, I'll gladly accept decent pull requests.
diff --git a/vendor/m4tthumphrey/php-gitlab-api/composer.json b/vendor/m4tthumphrey/php-gitlab-api/composer.json
index 3c29600a42e..1075af28e95 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/composer.json
+++ b/vendor/m4tthumphrey/php-gitlab-api/composer.json
@@ -1,35 +1,50 @@
-{
-	"name": "m4tthumphrey/php-gitlab-api",
-	"type": "library",
-	"description": "GitLab API client",
-	"homepage": "https://github.com/m4tthumphrey/php-gitlab-api",
-	"keywords": ["gitlab", "api"],
-	"license": "MIT",
-	"authors": [
-		{
-			"name": "Matt Humphrey",
-			"homepage": "http://m4tt.io"
-		},
-		{
-			"name": "KnpLabs Team",
-			"homepage": "http://knplabs.com"
-		},
-		{
-			"name": "Thibault Duplessis",
-			"email": "thibault.duplessis@gmail.com",
-			"homepage": "http://ornicar.github.com"
-		}
-	],
-	"require": {
-		"php":                ">=5.3.2",
-		"ext-curl":           "*",
-		"ext-xml":            "*",
-		"kriswallsmith/buzz": ">=0.7"
-	},
-	"require-dev": {
-		"phpunit/phpunit": "~4.5"
-	},
-	"autoload": {
-		"psr-0": { "Gitlab\\": "lib/" }
-	}
-}
+{
+	"name": "m4tthumphrey/php-gitlab-api",
+	"type": "library",
+	"description": "GitLab API client",
+	"homepage": "https://github.com/m4tthumphrey/php-gitlab-api",
+	"keywords": ["gitlab", "api"],
+	"license": "MIT",
+	"authors": [
+		{
+			"name": "Matt Humphrey",
+			"homepage": "http://m4tt.io"
+		},
+		{
+			"name": "KnpLabs Team",
+			"homepage": "http://knplabs.com"
+		},
+		{
+			"name": "Thibault Duplessis",
+			"email": "thibault.duplessis@gmail.com",
+			"homepage": "http://ornicar.github.com"
+		}
+	],
+	"require": {
+		"php": "^5.6 || ^7.0",
+		"ext-xml": "*",
+		"php-http/client-common": "^1.6",
+		"php-http/client-implementation": "^1.0",
+		"php-http/discovery": "^1.2",
+		"php-http/httplug": "^1.1",
+		"php-http/multipart-stream-builder": "^1.0",
+		"symfony/options-resolver": "^2.6 || ^3.0 || ^4.0"
+	},
+	"require-dev": {
+		"guzzlehttp/psr7": "^1.2",
+		"php-http/guzzle6-adapter": "^1.0",
+		"php-http/mock-client": "^1.0",
+		"phpunit/phpunit": "^5.0"
+	},
+	"autoload": {
+		"psr-4": { "Gitlab\\": "lib/Gitlab/" }
+	},
+	"autoload-dev": {
+		"psr-4": { "Gitlab\\Tests\\": "test/Gitlab/Tests/" }
+	},
+	"extra": {
+		"branch-alias": {
+			"dev-master": "9.8.x-dev"
+		}
+	}
+}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/AbstractApi.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/AbstractApi.php
index d6e3ab723c6..ef9120a20d0 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/AbstractApi.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/AbstractApi.php
@@ -1,6 +1,14 @@
 <?php namespace Gitlab\Api;
 
 use Gitlab\Client;
+use Gitlab\HttpClient\Message\QueryStringBuilder;
+use Gitlab\HttpClient\Message\ResponseMediator;
+use Gitlab\Tests\HttpClient\Message\QueryStringBuilderTest;
+use Http\Discovery\StreamFactoryDiscovery;
+use Http\Message\MultipartStream\MultipartStreamBuilder;
+use Http\Message\StreamFactory;
+use Psr\Http\Message\ResponseInterface;
+use Symfony\Component\OptionsResolver\OptionsResolver;
 
 /**
  * Abstract class for Api classes
@@ -11,11 +19,6 @@ use Gitlab\Client;
  */
 abstract class AbstractApi implements ApiInterface
 {
-    /**
-     * Default entries per page
-     */
-    const PER_PAGE = 20;
-
     /**
      * The client
      *
@@ -23,12 +26,19 @@ abstract class AbstractApi implements ApiInterface
      */
     protected $client;
 
+    /**
+     * @var StreamFactory
+     */
+    private $streamFactory;
+
     /**
      * @param Client $client
+     * @param StreamFactory|null $streamFactory
      */
-    public function __construct(Client $client)
+    public function __construct(Client $client, StreamFactory $streamFactory = null)
     {
         $this->client = $client;
+        $this->streamFactory = $streamFactory ?: StreamFactoryDiscovery::find();
     }
 
     /**
@@ -41,43 +51,69 @@ abstract class AbstractApi implements ApiInterface
     }
 
     /**
+     * Performs a GET query and returns the response as a PSR-7 response object.
+     *
      * @param string $path
      * @param array $parameters
      * @param array $requestHeaders
-     * @return mixed
+     * @return ResponseInterface
      */
-    protected function get($path, array $parameters = array(), $requestHeaders = array())
+    protected function getAsResponse($path, array $parameters = array(), $requestHeaders = array())
     {
-        $response = $this->client->getHttpClient()->get($path, $parameters, $requestHeaders);
+        $path = $this->preparePath($path, $parameters);
 
-        return $response->getContent();
+        return $this->client->getHttpClient()->get($path, $requestHeaders);
     }
 
     /**
      * @param string $path
      * @param array $parameters
      * @param array $requestHeaders
-     * @param array $files
      * @return mixed
      */
-    protected function post($path, array $parameters = array(), $requestHeaders = array(), array $files = array())
+    protected function get($path, array $parameters = array(), $requestHeaders = array())
     {
-        $response = $this->client->getHttpClient()->post($path, $parameters, $requestHeaders, $files);
-
-        return $response->getContent();
+        return ResponseMediator::getContent($this->getAsResponse($path, $parameters, $requestHeaders));
     }
 
     /**
      * @param string $path
      * @param array $parameters
      * @param array $requestHeaders
+     * @param array $files
      * @return mixed
      */
-    protected function patch($path, array $parameters = array(), $requestHeaders = array())
+    protected function post($path, array $parameters = array(), $requestHeaders = array(), array $files = array())
     {
-        $response = $this->client->getHttpClient()->patch($path, $parameters, $requestHeaders);
-
-        return $response->getContent();
+        $path = $this->preparePath($path);
+
+        $body = null;
+        if (empty($files) && !empty($parameters)) {
+            $body = $this->streamFactory->createStream(QueryStringBuilder::build($parameters));
+            $requestHeaders['Content-Type'] = 'application/x-www-form-urlencoded';
+        } elseif (!empty($files)) {
+            $builder = new MultipartStreamBuilder($this->streamFactory);
+
+            foreach ($parameters as $name => $value) {
+                $builder->addResource($name, $value);
+            }
+
+            foreach ($files as $name => $file) {
+                $builder->addResource($name, fopen($file, 'r'), [
+                    'headers' => [
+                        'Content-Type' => $this->guessContentType($file),
+                    ],
+                    'filename' => basename($file),
+                ]);
+            }
+
+            $body = $builder->build();
+            $requestHeaders['Content-Type'] = 'multipart/form-data; boundary='.$builder->getBoundary();
+        }
+
+        $response = $this->client->getHttpClient()->post($path, $requestHeaders, $body);
+
+        return ResponseMediator::getContent($response);
     }
 
     /**
@@ -88,9 +124,17 @@ abstract class AbstractApi implements ApiInterface
      */
     protected function put($path, array $parameters = array(), $requestHeaders = array())
     {
-        $response = $this->client->getHttpClient()->put($path, $parameters, $requestHeaders);
+        $path = $this->preparePath($path);
+
+        $body = null;
+        if (!empty($parameters)) {
+            $body = $this->streamFactory->createStream(http_build_query($parameters));
+            $requestHeaders['Content-Type'] = 'application/x-www-form-urlencoded';
+        }
 
-        return $response->getContent();
+        $response = $this->client->getHttpClient()->put($path, $requestHeaders, $body);
+
+        return ResponseMediator::getContent($response);
     }
 
     /**
@@ -101,9 +145,11 @@ abstract class AbstractApi implements ApiInterface
      */
     protected function delete($path, array $parameters = array(), $requestHeaders = array())
     {
-        $response = $this->client->getHttpClient()->delete($path, $parameters, $requestHeaders);
+        $path = $this->preparePath($path, $parameters);
+
+        $response = $this->client->getHttpClient()->delete($path, $requestHeaders);
 
-        return $response->getContent();
+        return ResponseMediator::getContent($response);
     }
 
     /**
@@ -126,4 +172,52 @@ abstract class AbstractApi implements ApiInterface
 
         return str_replace('.', '%2E', $path);
     }
+
+    /**
+     * Create a new OptionsResolver with page and per_page options.
+     *
+     * @return OptionsResolver
+     */
+    protected function createOptionsResolver()
+    {
+        $resolver = new OptionsResolver();
+        $resolver->setDefined('page')
+            ->setAllowedTypes('page', 'int')
+            ->setAllowedValues('page', function ($value) {
+                return $value > 0;
+            })
+        ;
+        $resolver->setDefined('per_page')
+            ->setAllowedTypes('per_page', 'int')
+            ->setAllowedValues('per_page', function ($value) {
+                return $value > 0 && $value <= 100;
+            })
+        ;
+
+        return $resolver;
+    }
+
+    private function preparePath($path, array $parameters = [])
+    {
+        if (count($parameters) > 0) {
+            $path .= '?'.QueryStringBuilder::build($parameters);
+        }
+
+        return $path;
+    }
+
+    /**
+     * @param $file
+     *
+     * @return string
+     */
+    private function guessContentType($file)
+    {
+        if (!class_exists(\finfo::class, false)) {
+            return 'application/octet-stream';
+        }
+        $finfo = new \finfo(FILEINFO_MIME_TYPE);
+
+        return $finfo->file($file);
+    }
 }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/DeployKeys.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/DeployKeys.php
index f7e2a39d5f5..32e0a82cbd0 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/DeployKeys.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/DeployKeys.php
@@ -2,23 +2,15 @@
 
 class DeployKeys extends AbstractApi
 {
-    const ORDER_BY = 'id';
-    const SORT = 'asc';
-
     /**
-     * @param int $page
-     * @param int $per_page
-     * @param string $order_by
-     * @param string $sort
+     * @param array $parameters
+     *
      * @return mixed
      */
-    public function all($page = 1, $per_page = self::PER_PAGE, $order_by = self::ORDER_BY, $sort = self::SORT)
+    public function all(array $parameters = [])
     {
-        return $this->get('deploy_keys', array(
-            'page' => $page,
-            'per_page' => $per_page,
-            'order_by' => $order_by,
-            'sort' => $sort
-        ));
+        $resolver = $this->createOptionsResolver();
+
+        return $this->get('deploy_keys', $resolver->resolve($parameters));
     }
 }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Deployments.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Deployments.php
new file mode 100644
index 00000000000..f085e20f2f9
--- /dev/null
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Deployments.php
@@ -0,0 +1,25 @@
+<?php namespace Gitlab\Api;
+
+class Deployments extends AbstractApi
+{
+    /**
+     * @param int $project_id
+     * @param array $parameters
+     * @return mixed
+     */
+    public function all($project_id, array $parameters = [])
+    {
+        $resolver = $this->createOptionsResolver();
+        return $this->get($this->getProjectPath($project_id, 'deployments'), $resolver->resolve($parameters));
+    }
+
+    /**
+     * @param int $project_id
+     * @param string $deployment_id
+     * @return mixed
+     */
+    public function show($project_id, $deployment_id)
+    {
+        return $this->get($this->getProjectPath($project_id, 'deployments/' . $deployment_id));
+    }
+}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Environments.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Environments.php
new file mode 100644
index 00000000000..48270a6334b
--- /dev/null
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Environments.php
@@ -0,0 +1,48 @@
+<?php namespace Gitlab\Api;
+
+use Symfony\Component\OptionsResolver\OptionsResolver;
+
+class Environments extends AbstractApi
+{
+    /**
+     * @param int $project_id
+     * @param array $parameters
+     * @return mixed
+     */
+    public function all($project_id, array $parameters = [])
+    {
+        $resolver = $this->createOptionsResolver();
+        return $this->get($this->getProjectPath($project_id, 'environments'), $resolver->resolve($parameters));
+    }
+
+    /**
+     * @param int $project_id
+     * @param array $parameters (
+     *
+     *     @var string $name         The name of the environment
+     *     @var string $external_url Place to link to for this environment
+     * )
+     * @return mixed
+     */
+    public function create($project_id, array $parameters = array())
+    {
+        $resolver = new OptionsResolver();
+        $resolver->setDefined('name')
+            ->setRequired('name')
+            ->setAllowedTypes('name', 'string');
+        $resolver->setDefined('external_url')
+            ->setAllowedTypes('external_url', 'string');
+
+        return $this->post($this->getProjectPath($project_id, 'environment'), $resolver->resolve($parameters));
+    }
+
+    /**
+     * @param int $project_id
+     * @param string $environment_id
+     * @return mixed
+     */
+    public function remove($project_id, $environment_id)
+    {
+        return $this->delete($this->getProjectPath($project_id, 'environments/' . $environment_id));
+    }
+}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Groups.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Groups.php
index 4ec574d64cd..03807e6c0c7 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Groups.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Groups.php
@@ -1,32 +1,56 @@
 <?php namespace Gitlab\Api;
 
+use Symfony\Component\OptionsResolver\Options;
+
 class Groups extends AbstractApi
 {
     /**
-     * @param int $page
-     * @param int $per_page
+     * @param array $parameters (
+     *
+     *     @var int[]  $skip_groups   Skip the group IDs passes.
+     *     @var bool   $all_available Show all the groups you have access to.
+     *     @var string $search        Return list of authorized groups matching the search criteria.
+     *     @var string $order_by      Order groups by name or path. Default is name.
+     *     @var string $sort          Order groups in asc or desc order. Default is asc.
+     *     @var bool   $statistics    Include group statistics (admins only).
+     *     @var bool   $owned         Limit by groups owned by the current user.
+     * )
      * @return mixed
      */
-    public function all($page = 1, $per_page = self::PER_PAGE)
+    public function all(array $parameters = [])
     {
-        return $this->get('groups', array(
-            'page' => $page,
-            'per_page' => $per_page
-        ));
-    }
+        $resolver = $this->createOptionsResolver();
+        $booleanNormalizer = function (Options $resolver, $value) {
+            return $value ? 'true' : 'false';
+        };
 
-    /**
-     * @param string $query
-     * @param int $page
-     * @param int $per_page
-     * @return mixed
-     */
-    public function search($query, $page = 1, $per_page = self::PER_PAGE)
-    {
-        return $this->get('groups?search='.$this->encodePath($query), array(
-            'page' => $page,
-            'per_page' => $per_page
-        ));
+        $resolver->setDefined('skip_groups')
+            ->setAllowedTypes('skip_groups', 'array')
+            ->setAllowedValues('skip_groups', function (array $value) {
+                return count($value) == count(array_filter($value, 'is_int'));
+            })
+        ;
+        $resolver->setDefined('all_available')
+            ->setAllowedTypes('all_available', 'bool')
+            ->setNormalizer('all_available', $booleanNormalizer)
+        ;
+        $resolver->setDefined('search');
+        $resolver->setDefined('order_by')
+            ->setAllowedValues('order_by', ['name', 'path'])
+        ;
+        $resolver->setDefined('sort')
+            ->setAllowedValues('sort', ['asc', 'desc'])
+        ;
+        $resolver->setDefined('statistics')
+            ->setAllowedTypes('statistics', 'bool')
+            ->setNormalizer('statistics', $booleanNormalizer)
+        ;
+        $resolver->setDefined('owned')
+            ->setAllowedTypes('owned', 'bool')
+            ->setNormalizer('owned', $booleanNormalizer)
+        ;
+
+        return $this->get('groups', $resolver->resolve($parameters));
     }
 
     /**
@@ -42,15 +66,16 @@ class Groups extends AbstractApi
      * @param string $name
      * @param string $path
      * @param string $description
+     * @param string $visibility
      * @return mixed
      */
-    public function create($name, $path, $description = null, $visibility_level = 0)
+    public function create($name, $path, $description = null, $visibility = 'private')
     {
         return $this->post('groups', array(
             'name' => $name,
             'path' => $path,
             'description' => $description,
-            'visibility_level' => $visibility_level
+            'visibility' => $visibility,
         ));
     }
 
@@ -84,17 +109,20 @@ class Groups extends AbstractApi
     }
 
     /**
-     * @param int $id
-     * @param int $page
-     * @param int $per_page
+     * @param int   $id
+     * @param array $parameters (
+     *
+     *     @var string $query A query string to search for members.
+     * )
+     *
      * @return mixed
      */
-    public function members($id, $page = 1, $per_page = self::PER_PAGE)
+    public function members($id, array $parameters = [])
     {
-        return $this->get('groups/'.$this->encodePath($id).'/members', array(
-            'page' => $page,
-            'per_page' => $per_page
-        ));
+        $resolver = $this->createOptionsResolver();
+        $resolver->setDefined('query');
+
+        return $this->get('groups/'.$this->encodePath($id).'/members', $resolver->resolve($parameters));
     }
 
     /**
@@ -136,15 +164,55 @@ class Groups extends AbstractApi
 
     /**
      * @param $id
-     * @param int $page
-     * @param int $per_page
+     * @param array $parameters (
+     *
+     *     @var bool   $archived   Limit by archived status.
+     *     @var string $visibility Limit by visibility public, internal, or private.
+     *     @var string $order_by   Return projects ordered by id, name, path, created_at, updated_at, or last_activity_at fields.
+     *                             Default is created_at.
+     *     @var string $sort       Return projects sorted in asc or desc order. Default is desc.
+     *     @var string $search     Return list of authorized projects matching the search criteria.
+     *     @var bool   $simple     Return only the ID, URL, name, and path of each project.
+     *     @var bool   $owned      Limit by projects owned by the current user.
+     *     @var bool   $starred    Limit by projects starred by the current user.
+     * )
+     *
      * @return mixed
      */
-    public function projects($id, $page = 1, $per_page = self::PER_PAGE)
+    public function projects($id, array $parameters = [])
     {
-        return $this->get('groups/'.$this->encodePath($id).'/projects', array(
-            'page' => $page,
-            'per_page' => $per_page
-        ));
+        $resolver = $this->createOptionsResolver();
+        $booleanNormalizer = function (Options $resolver, $value) {
+            return $value ? 'true' : 'false';
+        };
+
+        $resolver->setDefined('archived')
+            ->setAllowedTypes('archived', 'bool')
+            ->setNormalizer('archived', $booleanNormalizer)
+        ;
+        $resolver->setDefined('visibility')
+            ->setAllowedValues('visibility', ['public', 'internal', 'private'])
+        ;
+        $resolver->setDefined('order_by')
+            ->setAllowedValues('order_by', ['id', 'name', 'path', 'created_at', 'updated_at', 'last_activity_at'])
+        ;
+        $resolver->setDefined('sort')
+            ->setAllowedValues('sort', ['asc', 'desc'])
+        ;
+        $resolver->setDefined('search');
+        $resolver->setDefined('simple')
+            ->setAllowedTypes('simple', 'bool')
+            ->setNormalizer('simple', $booleanNormalizer)
+        ;
+        $resolver->setDefined('owned')
+            ->setAllowedTypes('owned', 'bool')
+            ->setNormalizer('owned', $booleanNormalizer)
+        ;
+        $resolver->setDefined('starred')
+            ->setAllowedTypes('starred', 'bool')
+            ->setNormalizer('starred', $booleanNormalizer)
+        ;
+
+        return $this->get('groups/'.$this->encodePath($id).'/projects', $resolver->resolve($parameters));
     }
 }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/IssueBoards.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/IssueBoards.php
new file mode 100644
index 00000000000..e5d460bc553
--- /dev/null
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/IssueBoards.php
@@ -0,0 +1,88 @@
+<?php namespace Gitlab\Api;
+
+class IssueBoards extends AbstractApi
+{
+    /**
+     * @param int $project_id
+     * @param array $parameters
+     *
+     * @return mixed
+     */
+    public function all($project_id = null, array $parameters = [])
+    {
+        $resolver = $this->createOptionsResolver();
+
+        $path = $project_id === null ? 'boards' : $this->getProjectPath($project_id, 'boards');
+
+        return $this->get($path, $resolver->resolve($parameters));
+    }
+
+    /**
+     * @param int $project_id
+     * @param int $board_id
+     * @return mixed
+     */
+    public function allLists($project_id, $board_id)
+    {
+        return $this->get($this->getProjectPath($project_id, 'boards/'.$this->encodePath($board_id).'/lists'));
+    }
+
+
+    /**
+     * @param int $project_id
+     * @param int $board_id
+     * @param int $list_id
+     * @return mixed
+     */
+    public function showList($project_id, $board_id, $list_id)
+    {
+        return $this->get($this->getProjectPath($project_id, 'boards/'.$this->encodePath($board_id).'/lists'.$this->encodePath($list_id)));
+    }
+
+    /**
+     * @param int $project_id
+     * @param int $board_id
+     * @param int $label_id
+     * @return mixed
+     */
+    public function createList($project_id, $board_id, $label_id)
+    {
+        $params = array(
+            'id' => $project_id,
+            'board_id' => $board_id,
+            'label_id' => $label_id
+        );
+
+        return $this->get($this->getProjectPath($project_id, 'boards/'.$this->encodePath($board_id).'/lists'), $params);
+    }
+
+    /**
+     * @param int $project_id
+     * @param int $board_id
+     * @param int $list_id
+     * @param int $position
+     * @return mixed
+     */
+    public function updateList($project_id, $board_id, $list_id, $position)
+    {
+        $params = array(
+            'id' => $project_id,
+            'board_id' => $board_id,
+            'list_id' => $list_id,
+            'position' => $position
+        );
+
+        return $this->put($this->getProjectPath($project_id, 'boards/'.$this->encodePath($board_id).'/lists/'.$this->encodePath($list_id)), $params);
+    }
+
+    /**
+     * @param int $project_id
+     * @param int $board_id
+     * @param int $list_id
+     * @return mixed
+     */
+    public function deleteList($project_id, $board_id, $list_id)
+    {
+        return $this->delete($this->getProjectPath($project_id, 'boards/'.$this->encodePath($board_id).'/lists/'.$this->encodePath($list_id)));
+    }
+}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Issues.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Issues.php
index 661ea7ac18a..9fa0f74da2b 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Issues.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Issues.php
@@ -4,32 +4,60 @@ class Issues extends AbstractApi
 {
     /**
      * @param int $project_id
-     * @param int $page
-     * @param int $per_page
-     * @param array $params
+     * @param array $parameters (
+     *
+     *     @var string $state     Return all issues or just those that are opened or closed.
+     *     @var string $labels    Comma-separated list of label names, issues must have all labels to be returned.
+     *                            No+Label lists all issues with no labels.
+     *     @var string $milestone The milestone title.
+     *     @var string scope      Return issues for the given scope: created-by-me, assigned-to-me or all. Defaults to created-by-me
+     *     @var int[]  $iids      Return only the issues having the given iid.
+     *     @var string $order_by  Return requests ordered by created_at or updated_at fields. Default is created_at.
+     *     @var string $sort      Return requests sorted in asc or desc order. Default is desc.
+     *     @var string $search    Search issues against their title and description.
+     * )
+     *
      * @return mixed
      */
-    public function all($project_id = null, $page = 1, $per_page = self::PER_PAGE, array $params = array())
+    public function all($project_id = null, array $parameters = [])
     {
-        $path = $project_id === null ? 'issues' : $this->getProjectPath($project_id, 'issues');
+        $resolver = $this->createOptionsResolver();
+
+        $resolver->setDefined('state')
+            ->setAllowedValues('state', ['opened', 'closed'])
+        ;
+        $resolver->setDefined('labels');
+        $resolver->setDefined('milestone');
+        $resolver->setDefined('iids')
+            ->setAllowedTypes('iids', 'array')
+            ->setAllowedValues('iids', function (array $value) {
+                return count($value) == count(array_filter($value, 'is_int'));
+            })
+        ;
+        $resolver->setDefined('scope')
+            ->setAllowedValues('scope', ['created-by-me', 'assigned-to-me', 'all'])
+        ;
+        $resolver->setDefined('order_by')
+            ->setAllowedValues('order_by', ['created_at', 'updated_at'])
+        ;
+        $resolver->setDefined('sort')
+            ->setAllowedValues('sort', ['asc', 'desc'])
+        ;
+        $resolver->setDefined('search');
 
-        $params = array_intersect_key($params, array('labels' => '', 'state' => '', 'sort' => '', 'order_by' => '', 'milestone' => ''));
-        $params = array_merge(array(
-            'page' => $page,
-            'per_page' => $per_page
-        ), $params);
+        $path = $project_id === null ? 'issues' : $this->getProjectPath($project_id, 'issues');
 
-        return $this->get($path, $params);
+        return $this->get($path, $resolver->resolve($parameters));
     }
 
     /**
      * @param int $project_id
-     * @param int $issue_id
+     * @param int $issue_iid
      * @return mixed
      */
-    public function show($project_id, $issue_id)
+    public function show($project_id, $issue_iid)
     {
-        return $this->get($this->getProjectPath($project_id, 'issues?iid='.$this->encodePath($issue_id)));
+        return $this->get($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_iid)));
     }
 
     /**
@@ -44,53 +72,53 @@ class Issues extends AbstractApi
 
     /**
      * @param int $project_id
-     * @param int $issue_id
+     * @param int $issue_iid
      * @param array $params
      * @return mixed
      */
-    public function update($project_id, $issue_id, array $params)
+    public function update($project_id, $issue_iid, array $params)
     {
-        return $this->put($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_id)), $params);
+        return $this->put($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_iid)), $params);
     }
 
     /**
      * @param int $project_id
-     * @param int $issue_id
+     * @param int $issue_iid
      * @return mixed
      */
-    public function remove($project_id, $issue_id)
+    public function remove($project_id, $issue_iid)
     {
-        return $this->delete($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_id)));
+        return $this->delete($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_iid)));
     }
 
     /**
      * @param int $project_id
-     * @param int $issue_id
+     * @param int $issue_iid
      * @return mixed
      */
-    public function showComments($project_id, $issue_id)
+    public function showComments($project_id, $issue_iid)
     {
-        return $this->get($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_id)).'/notes');
+        return $this->get($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_iid)).'/notes');
     }
 
     /**
      * @param int $project_id
-     * @param int $issue_id
+     * @param int $issue_iid
      * @param int $note_id
      * @return mixed
      */
-    public function showComment($project_id, $issue_id, $note_id)
+    public function showComment($project_id, $issue_iid, $note_id)
     {
-        return $this->get($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_id)).'/notes/'.$this->encodePath($note_id));
+        return $this->get($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_iid)).'/notes/'.$this->encodePath($note_id));
     }
 
     /**
      * @param int $project_id
-     * @param int $issue_id
+     * @param int $issue_iid
      * @param string|array $body
      * @return mixed
      */
-    public function addComment($project_id, $issue_id, $body)
+    public function addComment($project_id, $issue_iid, $body)
     {
         // backwards compatibility
         if (is_array($body)) {
@@ -99,70 +127,70 @@ class Issues extends AbstractApi
             $params = array('body' => $body);
         }
 
-        return $this->post($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_id).'/notes'), $params);
+        return $this->post($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_iid).'/notes'), $params);
     }
 
     /**
      * @param int $project_id
-     * @param int $issue_id
+     * @param int $issue_iid
      * @param int $note_id
      * @param string $body
      * @return mixed
      */
-    public function updateComment($project_id, $issue_id, $note_id, $body)
+    public function updateComment($project_id, $issue_iid, $note_id, $body)
     {
-        return $this->put($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_id).'/notes/'.$this->encodePath($note_id)), array(
+        return $this->put($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_iid).'/notes/'.$this->encodePath($note_id)), array(
             'body' => $body
         ));
     }
 
     /**
      * @param int $project_id
-     * @param int $issue_id
+     * @param int $issue_iid
      * @param int $note_id
      * @return mixed
      */
-    public function removeComment($project_id, $issue_id, $note_id)
+    public function removeComment($project_id, $issue_iid, $note_id)
     {
-        return $this->delete($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_id).'/notes/'.$this->encodePath($note_id)));
+        return $this->delete($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_iid).'/notes/'.$this->encodePath($note_id)));
     }
 
     /**
      * @param int $project_id
-     * @param int $issue_id
+     * @param int $issue_iid
      * @param string $duration
      */
-    public function setTimeEstimate($project_id, $issue_id, $duration)
+    public function setTimeEstimate($project_id, $issue_iid, $duration)
     {
-        return $this->post($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_id).'/time_estimate'), array('duration' => $duration));
+        return $this->post($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_iid).'/time_estimate'), array('duration' => $duration));
     }
 
     /**
      * @param int $project_id
-     * @param int $issue_id
+     * @param int $issue_iid
      */
-    public function resetTimeEstimate($project_id, $issue_id)
+    public function resetTimeEstimate($project_id, $issue_iid)
     {
-        return $this->post($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_id).'/reset_time_estimate'));
+        return $this->post($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_iid).'/reset_time_estimate'));
     }
 
     /**
      * @param int $project_id
-     * @param int $issue_id
+     * @param int $issue_iid
      * @param string $duration
      */
-    public function addSpentTime($project_id, $issue_id, $duration)
+    public function addSpentTime($project_id, $issue_iid, $duration)
     {
-        return $this->post($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_id).'/add_spent_time'), array('duration' => $duration));
+        return $this->post($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_iid).'/add_spent_time'), array('duration' => $duration));
     }
 
     /**
      * @param int $project_id
-     * @param int $issue_id
+     * @param int $issue_iid
      */
-    public function resetSpentTime($project_id, $issue_id)
+    public function resetSpentTime($project_id, $issue_iid)
     {
-        return $this->post($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_id).'/reset_spent_time'));
+        return $this->post($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_iid).'/reset_spent_time'));
     }
 
     /**
@@ -174,4 +202,25 @@ class Issues extends AbstractApi
     {
         return $this->get($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_iid) .'/time_stats'));
     }
+
+    /**
+     * @param int $project_id
+     * @param int $issue_iid
+     *
+     * @return mixed
+     */
+    public function awardEmoji($project_id, $issue_iid)
+    {
+        return $this->get($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_iid).'/award_emoji'));
+    }
+
+    /**
+    * @param int $project_id
+    * @param int $issue_iid
+    * @return mixed
+    */
+    public function closedByMergeRequests($project_id, $issue_iid)
+    {
+        return $this->get($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_iid)).'/closed_by');
+    }
 }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Jobs.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Jobs.php
new file mode 100644
index 00000000000..68c6509a540
--- /dev/null
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Jobs.php
@@ -0,0 +1,178 @@
+<?php namespace Gitlab\Api;
+
+use Psr\Http\Message\StreamInterface;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+
+class Jobs extends AbstractApi
+{
+    const SCOPE_CREATED = 'created';
+    const SCOPE_PENDING = 'pending';
+    const SCOPE_RUNNING = 'running';
+    const SCOPE_FAILED = 'failed';
+    const SCOPE_SUCCESS = 'success';
+    const SCOPE_CANCELED = 'canceled';
+    const SCOPE_SKIPPED = 'skipped';
+    const SCOPE_MANUAL = 'manual';
+
+    /**
+     * @param int|string $project_id
+     * @param array $parameters (
+     *
+     *     @var string|string[] $scope The scope of jobs to show, one or array of: created, pending, running, failed,
+     *                                 success, canceled, skipped, manual; showing all jobs if none provided.
+     * )
+     *
+     * @return mixed
+     */
+    public function all($project_id, array $parameters = [])
+    {
+        $resolver = $this->createOptionsResolver();
+
+        return $this->get("projects/".$this->encodePath($project_id)."/jobs", $resolver->resolve($parameters));
+    }
+
+    /**
+     * @param int|string $project_id
+     * @param int $pipeline_id
+     * @param array $parameters (
+     *
+     *     @var string|string[] $scope The scope of jobs to show, one or array of: created, pending, running, failed,
+     *                                 success, canceled, skipped, manual; showing all jobs if none provided.
+     * )
+     *
+     * @return mixed
+     */
+    public function pipelineJobs($project_id, $pipeline_id, array $parameters = [])
+    {
+        $resolver = $this->createOptionsResolver();
+
+        return $this->get(
+            $this->getProjectPath($project_id, 'pipelines/').$this->encodePath($pipeline_id)."/jobs",
+            $resolver->resolve($parameters)
+        );
+    }
+
+    /**
+     * @param int|string $project_id
+     * @param int $job_id
+     * @return mixed
+     */
+    public function show($project_id, $job_id)
+    {
+        return $this->get("projects/".$this->encodePath($project_id)."/jobs/".$this->encodePath($job_id));
+    }
+
+    /**
+     * @param int|string $project_id
+     * @param int $job_id
+     * @return StreamInterface
+     */
+    public function artifacts($project_id, $job_id)
+    {
+        return $this->getAsResponse("projects/".$this->encodePath($project_id)."/jobs/".$this->encodePath($job_id)."/artifacts")->getBody();
+    }
+
+    /**
+     * @param int|string $project_id
+     * @param string $ref_name
+     * @param string $job_name
+     * @return StreamInterface
+     */
+    public function artifactsByRefName($project_id, $ref_name, $job_name)
+    {
+        return $this->getAsResponse("projects/".$this->encodePath($project_id)."/jobs/artifacts/".$this->encodePath($ref_name)."/download", array(
+            'job' => $this->encodePath($job_name)
+        ))->getBody();
+    }
+
+    /**
+     * @param int|string $project_id
+     * @param int $job_id
+     * @return string
+     */
+    public function trace($project_id, $job_id)
+    {
+        return $this->get("projects/".$this->encodePath($project_id)."/jobs/".$this->encodePath($job_id)."/trace");
+    }
+
+    /**
+     * @param int|string $project_id
+     * @param int $job_id
+     * @return mixed
+     */
+    public function cancel($project_id, $job_id)
+    {
+        return $this->post("projects/".$this->encodePath($project_id)."/jobs/".$this->encodePath($job_id)."/cancel");
+    }
+
+    /**
+     * @param int|string $project_id
+     * @param int $job_id
+     * @return mixed
+     */
+    public function retry($project_id, $job_id)
+    {
+        return $this->post("projects/".$this->encodePath($project_id)."/jobs/".$this->encodePath($job_id)."/retry");
+    }
+
+    /**
+     * @param int|string $project_id
+     * @param int $job_id
+     * @return mixed
+     */
+    public function erase($project_id, $job_id)
+    {
+        return $this->post("projects/".$this->encodePath($project_id)."/jobs/".$this->encodePath($job_id)."/erase");
+    }
+
+    /**
+     * @param int|string $project_id
+     * @param int $job_id
+     * @return mixed
+     */
+    public function keepArtifacts($project_id, $job_id)
+    {
+        return $this->post("projects/".$this->encodePath($project_id)."/jobs/".$this->encodePath($job_id)."/artifacts/keep");
+    }
+
+    /**
+     * @param int|string $project_id
+     * @param int $job_id
+     * @return mixed
+     */
+    public function play($project_id, $job_id)
+    {
+        return $this->post("projects/".$this->encodePath($project_id)."/jobs/".$this->encodePath($job_id)."/play");
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function createOptionsResolver()
+    {
+        $allowedScopeValues = [
+            self::SCOPE_CANCELED,
+            self::SCOPE_CREATED,
+            self::SCOPE_FAILED,
+            self::SCOPE_MANUAL,
+            self::SCOPE_PENDING,
+            self::SCOPE_RUNNING,
+            self::SCOPE_SKIPPED,
+            self::SCOPE_SUCCESS,
+        ];
+
+        $resolver = parent::createOptionsResolver();
+        $resolver->setDefined('scope')
+            ->setAllowedTypes('scope', ['string', 'array'])
+            ->setAllowedValues('scope', $allowedScopeValues)
+            ->addAllowedValues('scope', function ($value) use ($allowedScopeValues) {
+                return is_array($value) && empty(array_diff($value, $allowedScopeValues));
+            })
+            ->setNormalizer('scope', function (OptionsResolver $resolver, $value) {
+                return (array) $value;
+            })
+        ;
+
+        return $resolver;
+    }
+}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/MergeRequests.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/MergeRequests.php
index 2d6dc618495..d7b4ebb2e5f 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/MergeRequests.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/MergeRequests.php
@@ -1,5 +1,9 @@
 <?php namespace Gitlab\Api;
 
+use Symfony\Component\OptionsResolver\Options;
+use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
+use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException;
+
 class MergeRequests extends AbstractApi
 {
     const STATE_ALL = 'all';
@@ -7,80 +11,66 @@ class MergeRequests extends AbstractApi
     const STATE_OPENED = 'opened';
     const STATE_CLOSED = 'closed';
 
-    const ORDER_BY = 'created_at';
-    const SORT = 'asc';
-
-    /**
-     * @param int $project_id
-     * @param string $state
-     * @param int $page
-     * @param int $per_page
-     * @param string $order_by
-     * @param string $sort
-     * @param string $object
-     * @return mixed
-     */
-    public function getList($project_id, $state = self::STATE_ALL, $page = 1, $per_page = self::PER_PAGE, $order_by = self::ORDER_BY, $sort = self::SORT, $object = 'merge_requests')
-    {
-        return $this->get($this->getProjectPath($project_id, $object), array(
-            'page' => $page,
-            'per_page' => $per_page,
-            'state' => $state,
-            'order_by' => $order_by,
-            'sort' => $sort
-        ));
-    }
-
-    /**
-     * @param int $project_id
-     * @param int $page
-     * @param int $per_page
-     * @param string $order_by
-     * @param string $sort
-     * @return mixed
-     */
-    public function all($project_id, $page = 1, $per_page = self::PER_PAGE, $order_by = self::ORDER_BY, $sort = self::SORT)
-    {
-        return $this->getList($project_id, self::STATE_ALL, $page, $per_page, $order_by, $sort);
-    }
-
     /**
-     * @param int $project_id
-     * @param int $page
-     * @param int $per_page
-     * @param string $order_by
-     * @param string $sort
+     * @param int   $project_id
+     * @param array $parameters {
+     *
+     *     @var int[]              $iids           Return the request having the given iid.
+     *     @var string             $state          Return all merge requests or just those that are opened, closed, or
+     *                                             merged.
+     *     @var string             $order_by       Return requests ordered by created_at or updated_at fields. Default
+     *                                             is created_at.
+     *     @var string             $sort           Return requests sorted in asc or desc order. Default is desc.
+     *     @var string             $milestone      Return merge requests for a specific milestone.
+     *     @var string             $view           If simple, returns the iid, URL, title, description, and basic state
+     *                                             of merge request.
+     *     @var string             $labels         Return merge requests matching a comma separated list of labels.
+     *     @var \DateTimeInterface $created_after  Return merge requests created after the given time (inclusive).
+     *     @var \DateTimeInterface $created_before Return merge requests created before the given time (inclusive).
+     * }
+     *
+     * @throws UndefinedOptionsException If an option name is undefined.
+     * @throws InvalidOptionsException   If an option doesn't fulfill the specified validation rules.
+     *
      * @return mixed
      */
-    public function merged($project_id, $page = 1, $per_page = self::PER_PAGE, $order_by = self::ORDER_BY, $sort = self::SORT)
+    public function all($project_id, array $parameters = [])
     {
-        return $this->getList($project_id, self::STATE_MERGED, $page, $per_page, $order_by, $sort);
-    }
-
-    /**
-     * @param int $project_id
-     * @param int $page
-     * @param int $per_page
-     * @param string $order_by
-     * @param string $sort
-     * @return mixed
-     */
-    public function opened($project_id, $page = 1, $per_page = self::PER_PAGE, $order_by = self::ORDER_BY, $sort = self::SORT)
-    {
-        return $this->getList($project_id, self::STATE_OPENED, $page, $per_page, $order_by, $sort);
-    }
-
-    /**
-     * @param int $project_id
-     * @param int $page
-     * @param int $per_page
-     * @param string $order_by
-     * @param string $sort
-     * @return mixed
-     */
-    public function closed($project_id, $page = 1, $per_page = self::PER_PAGE, $order_by = self::ORDER_BY, $sort = self::SORT)
-    {
-        return $this->getList($project_id, self::STATE_CLOSED, $page, $per_page, $order_by, $sort);
+        $resolver = $this->createOptionsResolver();
+        $datetimeNormalizer = function (Options $resolver, \DateTimeInterface $value) {
+            return $value->format('c');
+        };
+        $resolver->setDefined('iids')
+            ->setAllowedTypes('iids', 'array')
+            ->setAllowedValues('iids', function (array $value) {
+                return count($value) == count(array_filter($value, 'is_int'));
+            })
+        ;
+        $resolver->setDefined('state')
+            ->setAllowedValues('state', ['all', 'opened', 'merged', 'closed'])
+        ;
+        $resolver->setDefined('order_by')
+            ->setAllowedValues('order_by', ['created_at', 'updated_at'])
+        ;
+        $resolver->setDefined('sort')
+            ->setAllowedValues('sort', ['asc', 'desc'])
+        ;
+        $resolver->setDefined('milestone');
+        $resolver->setDefined('view')
+            ->setAllowedValues('view', ['simple'])
+        ;
+        $resolver->setDefined('labels');
+        $resolver->setDefined('created_after')
+            ->setAllowedTypes('created_after', \DateTimeInterface::class)
+            ->setNormalizer('created_after', $datetimeNormalizer)
+        ;
+        $resolver->setDefined('created_before')
+            ->setAllowedTypes('created_before', \DateTimeInterface::class)
+            ->setNormalizer('created_before', $datetimeNormalizer)
+        ;
+        $resolver->setDefined('search');
+        
+        return $this->get($this->getProjectPath($project_id, 'merge_requests'), $resolver->resolve($parameters));
     }
 
     /**
@@ -90,7 +80,7 @@ class MergeRequests extends AbstractApi
      */
     public function show($project_id, $mr_id)
     {
-        return $this->get($this->getProjectPath($project_id, 'merge_request/'.$this->encodePath($mr_id)));
+        return $this->get($this->getProjectPath($project_id, 'merge_requests/'.$this->encodePath($mr_id)));
     }
 
     /**
@@ -123,7 +113,7 @@ class MergeRequests extends AbstractApi
      */
     public function update($project_id, $mr_id, array $params)
     {
-        return $this->put($this->getProjectPath($project_id, 'merge_request/'.$this->encodePath($mr_id)), $params);
+        return $this->put($this->getProjectPath($project_id, 'merge_requests/'.$this->encodePath($mr_id)), $params);
     }
 
     /**
@@ -140,17 +130,18 @@ class MergeRequests extends AbstractApi
             $params = array('merge_commit_message' => $message);
         }
 
-        return $this->put($this->getProjectPath($project_id, 'merge_request/'.$this->encodePath($mr_id).'/merge'), $params);
+        return $this->put($this->getProjectPath($project_id, 'merge_requests/'.$this->encodePath($mr_id).'/merge'), $params);
     }
 
     /**
-     * @param int $project_id
-     * @param int $mr_id
+     * @param int   $project_id
+     * @param int   $mr_id
+     *
      * @return mixed
      */
-    public function showNotes($project_id, $mr_id, $page = 1, $per_page = self::PER_PAGE, $order_by = self::ORDER_BY, $sort = 'desc')
+    public function showNotes($project_id, $mr_id)
     {
-        return $this->getList($project_id, null, $page, $per_page, $order_by, $sort, 'merge_requests/'.$this->encodePath($mr_id).'/notes');
+        return $this->get($this->getProjectPath($project_id, 'merge_requests/'.$this->encodePath($mr_id).'/notes'));
     }
 
     /**
@@ -173,7 +164,9 @@ class MergeRequests extends AbstractApi
      */
     public function showComments($project_id, $mr_id)
     {
-        return $this->get($this->getProjectPath($project_id, 'merge_request/'.$this->encodePath($mr_id).'/comments'));
+        @trigger_error(sprintf('The %s() method is deprecated since version 9.1 and will be removed in 10.0. Use the showNotes() method instead.', __METHOD__), E_USER_DEPRECATED);
+
+        return $this->showNotes($project_id, $mr_id);
     }
 
     /**
@@ -184,9 +177,9 @@ class MergeRequests extends AbstractApi
      */
     public function addComment($project_id, $mr_id, $note)
     {
-        return $this->post($this->getProjectPath($project_id, 'merge_request/'.$this->encodePath($mr_id).'/comments'), array(
-            'note' => $note
-        ));
+        @trigger_error(sprintf('The %s() method is deprecated since version 9.1 and will be removed in 10.0. Use the addNote() method instead.', __METHOD__), E_USER_DEPRECATED);
+
+        return $this->addNote($project_id, $mr_id, $note);
     }
 
     /**
@@ -196,17 +189,17 @@ class MergeRequests extends AbstractApi
      */
     public function changes($project_id, $mr_id)
     {
-        return $this->get($this->getProjectPath($project_id, 'merge_request/'.$this->encodePath($mr_id).'/changes'));
+        return $this->get($this->getProjectPath($project_id, 'merge_requests/'.$this->encodePath($mr_id).'/changes'));
     }
 
     /**
-     * @param $project_id
-     * @param $mr_iid
+     * @param int $project_id
+     * @param int $mr_id
      * @return mixed
      */
-    public function getByIid($project_id, $mr_iid)
+    public function commits($project_id, $mr_id)
     {
-        return $this->get($this->getProjectPath($project_id, 'merge_requests'), array('iid' => $mr_iid));
+        return $this->get($this->getProjectPath($project_id, 'merge_requests/'.$this->encodePath($mr_id).'/commits'));
     }
 
     /**
@@ -214,8 +207,52 @@ class MergeRequests extends AbstractApi
      * @param int $mr_id
      * @return mixed
      */
-    public function commits($project_id, $mr_id)
+    public function closesIssues($project_id, $mr_id)
+    {
+        return $this->get($this->getProjectPath($project_id, 'merge_requests/'.$this->encodePath($mr_id).'/closes_issues'));
+    }
+
+    /**
+     * @param int $project_id
+     * @param int $mr_id
+     *
+     * @return mixed
+     */
+    public function approvals($project_id, $merge_request_iid)
+    {
+        return $this->get($this->getProjectPath($project_id, 'merge_requests/'.$this->encodePath($merge_request_iid).'/approvals'));
+    }
+
+    /**
+     * @param int $project_id
+     * @param int $mr_id
+     *
+     * @return mixed
+     */
+    public function approve($project_id, $merge_request_iid)
+    {
+        return $this->post($this->getProjectPath($project_id, 'merge_requests/'.$this->encodePath($merge_request_iid).'/approve'));
+    }
+
+    /**
+     * @param int $project_id
+     * @param int $mr_id
+     *
+     * @return mixed
+     */
+    public function unapprove($project_id, $merge_request_iid)
+    {
+        return $this->post($this->getProjectPath($project_id, 'merge_requests/'.$this->encodePath($merge_request_iid).'/unapprove'));
+    }
+
+    /**
+     * @param int $project_id
+     * @param int $merge_request_iid
+     *
+     * @return mixed
+     */
+    public function awardEmoji($project_id, $merge_request_iid)
     {
-        return $this->get($this->getProjectPath($project_id, 'merge_request/'.$this->encodePath($mr_id).'/commits'));
+        return $this->get($this->getProjectPath($project_id, 'merge_requests/'.$this->encodePath($merge_request_iid).'/award_emoji'));
     }
 }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Milestones.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Milestones.php
index 3b15281834e..0f9b2d25ed5 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Milestones.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Milestones.php
@@ -4,16 +4,30 @@ class Milestones extends AbstractApi
 {
     /**
      * @param int $project_id
-     * @param int $page
-     * @param int $per_page
+     * @param array $parameters (
+     *
+     *     @var int[]  $iids   Return only the milestones having the given iids.
+     *     @var string $state  Return only active or closed milestones.
+     *     @var string $search Return only milestones with a title or description matching the provided string.
+     * )
+     *
      * @return mixed
      */
-    public function all($project_id, $page = 1, $per_page = self::PER_PAGE)
+    public function all($project_id, array $parameters = [])
     {
-        return $this->get($this->getProjectPath($project_id, 'milestones'), array(
-            'page' => $page,
-            'per_page' => $per_page
-        ));
+        $resolver = $this->createOptionsResolver();
+        $resolver->setDefined('iids')
+            ->setAllowedTypes('iids', 'array')
+            ->setAllowedValues('iids', function (array $value) {
+                return count($value) == count(array_filter($value, 'is_int'));
+            })
+        ;
+        $resolver->setDefined('state')
+            ->setAllowedValues('state', ['active', 'closed'])
+        ;
+        $resolver->setDefined('search');
+
+        return $this->get($this->getProjectPath($project_id, 'milestones'), $resolver->resolve($parameters));
     }
 
     /**
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/ProjectNamespaces.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/ProjectNamespaces.php
index 480fa79c880..815d4e083ad 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/ProjectNamespaces.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/ProjectNamespaces.php
@@ -3,30 +3,18 @@
 class ProjectNamespaces extends AbstractApi
 {
     /**
-     * @param int $page
-     * @param int $per_page
+     * @param array $parameters (
+     *
+     *     @var string $search Returns a list of namespaces the user is authorized to see based on the search criteria.
+     * )
+     *
      * @return mixed
      */
-    public function all($page = 1, $per_page = self::PER_PAGE)
+    public function all(array $parameters = [])
     {
-        return $this->get('namespaces', array(
-            'page' => $page,
-            'per_page' => $per_page
-        ));
-    }
+        $resolver = $this->createOptionsResolver();
+        $resolver->setDefined('search');
 
-    /**
-     * @param string $terms
-     * @param int $page
-     * @param int $per_page
-     * @return mixed
-     */
-    public function search($terms, $page = 1, $per_page = self::PER_PAGE)
-    {
-        return $this->get('namespaces', array(
-            'search' => $terms,
-            'page' => $page,
-            'per_page' => $per_page
-        ));
+        return $this->get('namespaces', $resolver->resolve($parameters));
     }
 }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Projects.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Projects.php
index 65781babcb4..f5f67df160a 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Projects.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Projects.php
@@ -1,87 +1,112 @@
 <?php namespace Gitlab\Api;
 
+use Symfony\Component\OptionsResolver\Options;
+use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
+use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+
 class Projects extends AbstractApi
 {
-    const ORDER_BY = 'created_at';
-    const SORT = 'asc';
-
-    /**
-     * @param int $page
-     * @param int $per_page
-     * @param string $order_by
-     * @param string $sort
-     * @return mixed
-     */
-    public function all($page = 1, $per_page = self::PER_PAGE, $order_by = self::ORDER_BY, $sort = self::SORT)
-    {
-        return $this->get('projects/all', array(
-            'page' => $page,
-            'per_page' => $per_page,
-            'order_by' => $order_by,
-            'sort' => $sort
-        ));
-    }
-
-    /**
-     * @param int $page
-     * @param int $per_page
-     * @param string $order_by
-     * @param string $sort
-     * @return mixed
-     */
-    public function accessible($page = 1, $per_page = self::PER_PAGE, $order_by = self::ORDER_BY, $sort = self::SORT)
-    {
-        return $this->get('projects', array(
-            'page' => $page,
-            'per_page' => $per_page,
-            'order_by' => $order_by,
-            'sort' => $sort
-        ));
-    }
-
-    /**
-     * Get projects owned by the current user
-     * @param int $page
-     * @param int $per_page
-     * @param string $order_by
-     * @param string $sort
-     * @return mixed
-     */
-    public function owned($page = 1, $per_page = self::PER_PAGE, $order_by = self::ORDER_BY, $sort = self::SORT)
-    {
-        return $this->get('projects?owned=1', array(
-            'page' => $page,
-            'per_page' => $per_page,
-            'order_by' => $order_by,
-            'sort' => $sort
-        ));
-    }
-
-    /**
-     * @param string $query
-     * @param int $page
-     * @param int $per_page
-     * @param string $order_by
-     * @param string $sort
-     * @return mixed
-     */
-    public function search($query, $page = 1, $per_page = self::PER_PAGE, $order_by = self::ORDER_BY, $sort = self::SORT)
-    {
-        return $this->get('projects/search/'.$this->encodePath($query), array(
-            'page' => $page,
-            'per_page' => $per_page,
-            'order_by' => $order_by,
-            'sort' => $sort
-        ));
-    }
-
     /**
-     * @param int $project_id
-     * @return mixed
-     */
-    public function show($project_id)
-    {
-        return $this->get('projects/'.$this->encodePath($project_id));
+     * @param array $parameters {
+     *
+     *     @var bool   $archived                    Limit by archived status.
+     *     @var string $visibility                  Limit by visibility public, internal, or private.
+     *     @var string $order_by                    Return projects ordered by id, name, path, created_at, updated_at,
+     *                                              or last_activity_at fields. Default is created_at.
+     *     @var string $sort                        Return projects sorted in asc or desc order. Default is desc.
+     *     @var string $search                      Return list of projects matching the search criteria.
+     *     @var bool   $simple                      Return only the ID, URL, name, and path of each project.
+     *     @var bool   $owned                       Limit by projects owned by the current user.
+     *     @var bool   $membership                  Limit by projects that the current user is a member of.
+     *     @var bool   $starred                     Limit by projects starred by the current user.
+     *     @var bool   $statistics                  Include project statistics.
+     *     @var bool   $with_issues_enabled         Limit by enabled issues feature.
+     *     @var bool   $with_merge_requests_enabled Limit by enabled merge requests feature.
+     * }
+     *
+     * @throws UndefinedOptionsException If an option name is undefined
+     * @throws InvalidOptionsException   If an option doesn't fulfill the
+     *                                   specified validation rules
+     *
+     * @return mixed
+     */
+    public function all(array $parameters = [])
+    {
+        $resolver = $this->createOptionsResolver();
+        $booleanNormalizer = function (Options $resolver, $value) {
+            return $value ? 'true' : 'false';
+        };
+        $resolver->setDefined('archived')
+            ->setAllowedTypes('archived', 'bool')
+            ->setNormalizer('archived', $booleanNormalizer)
+        ;
+        $resolver->setDefined('visibility')
+            ->setAllowedValues('visibility', ['public', 'internal', 'private'])
+        ;
+        $resolver->setDefined('order_by')
+            ->setAllowedValues('order_by', ['id', 'name', 'path', 'created_at', 'updated_at', 'last_activity_at'])
+        ;
+        $resolver->setDefined('sort')
+            ->setAllowedValues('sort', ['asc', 'desc'])
+        ;
+        $resolver->setDefined('search');
+        $resolver->setDefined('simple')
+            ->setAllowedTypes('simple', 'bool')
+            ->setNormalizer('simple', $booleanNormalizer)
+        ;
+        $resolver->setDefined('owned')
+            ->setAllowedTypes('owned', 'bool')
+            ->setNormalizer('owned', $booleanNormalizer)
+        ;
+        $resolver->setDefined('membership')
+            ->setAllowedTypes('membership', 'bool')
+            ->setNormalizer('membership', $booleanNormalizer)
+        ;
+        $resolver->setDefined('starred')
+            ->setAllowedTypes('starred', 'bool')
+            ->setNormalizer('starred', $booleanNormalizer)
+        ;
+        $resolver->setDefined('statistics')
+            ->setAllowedTypes('statistics', 'bool')
+            ->setNormalizer('statistics', $booleanNormalizer)
+        ;
+        $resolver->setDefined('with_issues_enabled')
+            ->setAllowedTypes('with_issues_enabled', 'bool')
+            ->setNormalizer('with_issues_enabled', $booleanNormalizer)
+        ;
+        $resolver->setDefined('with_merge_requests_enabled')
+            ->setAllowedTypes('with_merge_requests_enabled', 'bool')
+            ->setNormalizer('with_merge_requests_enabled', $booleanNormalizer)
+        ;
+
+        return $this->get('projects', $resolver->resolve($parameters));
+    }
+
+    /**
+     * @param int $project_id
+     * @param array $parameters {
+     *
+     *     @var bool   $statistics                    Include project statistics.
+     *     @var bool   $with_custom_attributes        Include project custom attributes.
+     * }
+     * @return mixed
+     */
+    public function show($project_id, array $parameters = [])
+    {
+        $resolver = $this->createOptionsResolver();
+        $booleanNormalizer = function (Options $resolver, $value) {
+            return $value ? true : false;
+        };
+        $resolver->setDefined('statistics')
+            ->setAllowedTypes('statistics', 'bool')
+            ->setNormalizer('statistics', $booleanNormalizer)
+        ;
+        $resolver->setDefined('with_custom_attributes')
+            ->setAllowedTypes('with_custom_attributes', 'bool')
+            ->setNormalizer('with_custom_attributes', $booleanNormalizer)
+        ;
+        return $this->get('projects/'.$this->encodePath($project_id), $resolver->resolve($parameters));
     }
 
     /**
@@ -132,7 +157,8 @@ class Projects extends AbstractApi
      * @param int $project_id
      * @return mixed
      */
-    public function archive($project_id){
+    public function archive($project_id)
+    {
         return $this->post("projects/".$this->encodePath($project_id)."/archive");
     }
 
@@ -140,49 +166,54 @@ class Projects extends AbstractApi
      * @param int $project_id
      * @return mixed
      */
-    public function unarchive($project_id){
+    public function unarchive($project_id)
+    {
         return $this->post("projects/".$this->encodePath($project_id)."/unarchive");
     }
 
     /**
-     * @param int $project_id
-     * @param array $scope
+     * @param int   $project_id
+     * @param array $parameters (
+     *
+     *     @var string $scope       The scope of pipelines, one of: running, pending, finished, branches, tags.
+     *     @var string $status      The status of pipelines, one of: running, pending, success, failed, canceled, skipped.
+     *     @var string $ref         The ref of pipelines.
+     *     @var bool   $yaml_errors Returns pipelines with invalid configurations.
+     *     @var string $name        The name of the user who triggered pipelines.
+     *     @var string $username    The username of the user who triggered pipelines.
+     *     @var string $order_by    Order pipelines by id, status, ref, or user_id (default: id).
+     *     @var string $order       Sort pipelines in asc or desc order (default: desc).
+     * )
      * @return mixed
      */
-    public function builds($project_id, $scope = null)
+    public function pipelines($project_id, array $parameters = [])
     {
-        return $this->get($this->getProjectPath($project_id, 'builds'), array(
-            'scope' => $scope
-        ));
-    }
+        $resolver = $this->createOptionsResolver();
+        $booleanNormalizer = function (Options $resolver, $value) {
+            return $value ? 'true' : 'false';
+        };
 
-    /**
-     * @param int $project_id
-     * @param int $build_id
-     * @return mixed
-     */
-    public function build($project_id, $build_id)
-    {
-        return $this->get($this->getProjectPath($project_id, 'builds/'.$this->encodePath($build_id)));
-    }
+        $resolver->setDefined('scope')
+            ->setAllowedValues('scope', ['running', 'pending', 'finished', 'branches', 'tags'])
+        ;
+        $resolver->setDefined('status')
+            ->setAllowedValues('status', ['running', 'pending', 'success', 'failed', 'canceled', 'skipped'])
+        ;
+        $resolver->setDefined('ref');
+        $resolver->setDefined('yaml_errors')
+            ->setAllowedTypes('yaml_errors', 'bool')
+            ->setNormalizer('yaml_errors', $booleanNormalizer)
+        ;
+        $resolver->setDefined('name');
+        $resolver->setDefined('username');
+        $resolver->setDefined('order_by')
+            ->setAllowedValues('order_by', ['id', 'status', 'ref', 'user_id'])
+        ;
+        $resolver->setDefined('sort')
+            ->setAllowedValues('sort', ['asc', 'desc'])
+        ;
 
-    /**
-     * @param int $project_id
-     * @param int $build_id
-     * @return mixed
-     */
-    public function trace($project_id, $build_id)
-    {
-        return $this->get($this->getProjectPath($project_id, 'builds/'.$this->encodePath($build_id).'/trace'));
-    }
-
-    /**
-     * @param int $project_id
-     * @return mixed
-     */
-    public function pipelines($project_id)
-    {
-        return $this->get($this->getProjectPath($project_id, 'pipelines'));
+        return $this->get($this->getProjectPath($project_id, 'pipelines'), $resolver->resolve($parameters));
     }
 
     /**
@@ -202,7 +233,7 @@ class Projects extends AbstractApi
      */
     public function createPipeline($project_id, $commit_ref)
     {
-        return $this->post($this->getProjectPath($project_id, 'pipelines'), array(
+        return $this->post($this->getProjectPath($project_id, 'pipeline'), array(
             'ref' => $commit_ref));
     }
 
@@ -228,14 +259,33 @@ class Projects extends AbstractApi
 
     /**
      * @param int $project_id
-     * @param string $username_query
+     * @param array $parameters (
+     *
+     *     @var string $query           The query you want to search members for.
+     * )
+     *
+     * @throws MissingOptionsException  If a required option is not provided
+     *
      * @return mixed
      */
-    public function members($project_id, $username_query = null)
+    public function members($project_id, $parameters = [])
     {
-        return $this->get($this->getProjectPath($project_id, 'members'), array(
-            'query' => $username_query
-        ));
+        if (!is_array($parameters)) {
+            @trigger_error("Deprecated: String parameter of the members() function is deprecated.", E_USER_NOTICE);
+            $username_query = $parameters;
+            $parameters = array();
+            if (!empty($username_query)) {
+                $parameters['query'] = $username_query;
+            }
+        }
+
+        $resolver = $this->createOptionsResolver();
+
+        $resolver->setDefined('query')
+            ->setAllowedTypes('query', 'string')
+        ;
+
+        return $this->get($this->getProjectPath($project_id, 'members'), $resolver->resolve($parameters));
     }
 
     /**
@@ -287,25 +337,15 @@ class Projects extends AbstractApi
 
     /**
      * @param int $project_id
+     * @param array $parameters
+     *
      * @return mixed
      */
-    public function deployKeys($project_id)
+    public function hooks($project_id, array $parameters = [])
     {
-        return $this->get($this->getProjectPath($project_id, 'deploy_keys'));
-    }
+        $resolver = $this->createOptionsResolver();
 
-    /**
-     * @param int $project_id
-     * @param int $page
-     * @param int $per_page
-     * @return mixed
-     */
-    public function hooks($project_id, $page = 1, $per_page = self::PER_PAGE)
-    {
-        return $this->get($this->getProjectPath($project_id, 'hooks'), array(
-            'page' => $page,
-            'per_page' => $per_page
-        ));
+        return $this->get($this->getProjectPath($project_id, 'hooks'), $resolver->resolve($parameters));
     }
 
     /**
@@ -360,9 +400,9 @@ class Projects extends AbstractApi
      * @param int $project_id
      * @return mixed
      */
-    public function keys($project_id)
+    public function deployKeys($project_id)
     {
-        return $this->get($this->getProjectPath($project_id, 'keys'));
+        return $this->get($this->getProjectPath($project_id, 'deploy_keys'));
     }
 
     /**
@@ -370,22 +410,24 @@ class Projects extends AbstractApi
      * @param int $key_id
      * @return mixed
      */
-    public function key($project_id, $key_id)
+    public function deployKey($project_id, $key_id)
     {
-        return $this->get($this->getProjectPath($project_id, 'keys/'.$this->encodePath($key_id)));
+        return $this->get($this->getProjectPath($project_id, 'deploy_keys/'.$this->encodePath($key_id)));
     }
 
     /**
      * @param int $project_id
      * @param string $title
      * @param string $key
+     * @param bool $canPush
      * @return mixed
      */
-    public function addKey($project_id, $title, $key)
+    public function addDeployKey($project_id, $title, $key, $canPush = false)
     {
-        return $this->post($this->getProjectPath($project_id, 'keys'), array(
+        return $this->post($this->getProjectPath($project_id, 'deploy_keys'), array(
             'title' => $title,
-            'key' => $key
+            'key' => $key,
+            'can_push' => $canPush
         ));
     }
 
@@ -394,9 +436,9 @@ class Projects extends AbstractApi
      * @param int $key_id
      * @return mixed
      */
-    public function removeKey($project_id, $key_id)
+    public function deleteDeployKey($project_id, $key_id)
     {
-        return $this->delete($this->getProjectPath($project_id, 'keys/'.$this->encodePath($key_id)));
+        return $this->delete($this->getProjectPath($project_id, 'deploy_keys/'.$this->encodePath($key_id)));
     }
 
     /**
@@ -404,33 +446,49 @@ class Projects extends AbstractApi
      * @param int $key_id
      * @return mixed
      */
-    public function enableKey($project_id, $key_id)
+    public function enableDeployKey($project_id, $key_id)
     {
-        return $this->post($this->getProjectPath($project_id, 'keys/'.$this->encodePath($key_id).'/enable'));
+        return $this->post($this->getProjectPath($project_id, 'deploy_keys/'.$this->encodePath($key_id).'/enable'));
     }
 
     /**
      * @param int $project_id
-     * @param int $key_id
+     * @param array $parameters (
+     *
+     *     @var string             $action      Include only events of a particular action type.
+     *     @var string             $target_type Include only events of a particular target type.
+     *     @var \DateTimeInterface $before      Include only events created before a particular date.
+     *     @var \DateTimeInterface $after       Include only events created after a particular date.
+     *     @var string             $sort        Sort events in asc or desc order by created_at. Default is desc.
+     * )
+     *
      * @return mixed
      */
-    public function disableKey($project_id, $key_id)
+    public function events($project_id, array $parameters = [])
     {
-        return $this->delete($this->getProjectPath($project_id, 'keys/'.$this->encodePath($key_id).'/disable'));
-    }
+        $resolver = $this->createOptionsResolver();
+        $datetimeNormalizer = function (Options $resolver, \DateTimeInterface $value) {
+            return $value->format('Y-m-d');
+        };
 
-    /**
-     * @param int $project_id
-     * @param int $page
-     * @param int $per_page
-     * @return mixed
-     */
-    public function events($project_id, $page = 1, $per_page = self::PER_PAGE)
-    {
-        return $this->get($this->getProjectPath($project_id, 'events'), array(
-            'page' => $page,
-            'per_page' => $per_page
-        ));
+        $resolver->setDefined('action')
+            ->setAllowedValues('action', ['created', 'updated', 'closed', 'reopened', 'pushed', 'commented', 'merged', 'joined', 'left', 'destroyed', 'expired'])
+        ;
+        $resolver->setDefined('target_type')
+            ->setAllowedValues('target_type', ['issue', 'milestone', 'merge_request', 'note', 'project', 'snippet', 'user'])
+        ;
+        $resolver->setDefined('before')
+            ->setAllowedTypes('before', \DateTimeInterface::class)
+            ->setNormalizer('before', $datetimeNormalizer);
+        $resolver->setDefined('after')
+            ->setAllowedTypes('after', \DateTimeInterface::class)
+            ->setNormalizer('after', $datetimeNormalizer)
+        ;
+        $resolver->setDefined('sort')
+            ->setAllowedValues('sort', ['asc', 'desc'])
+        ;
+
+        return $this->get($this->getProjectPath($project_id, 'events'), $resolver->resolve($parameters));
     }
 
     /**
@@ -475,12 +533,32 @@ class Projects extends AbstractApi
     }
 
     /**
+     * Get languages used in a project with percentage value.
+     *
      * @param int $project_id
      * @return mixed
      */
-    public function fork($project_id)
+    public function languages($project_id)
     {
-        return $this->post('projects/fork/'.$this->encodePath($project_id));
+        return $this->get($this->getProjectPath($project_id, 'languages'));
+    }
+
+    /**
+     * @param int $project_id
+     * @param array $params (
+     *
+     *     @var string $namespace      The ID or path of the namespace that the project will be forked to
+     * )
+     * @return mixed
+     */
+    public function fork($project_id, array $parameters = [])
+    {
+        $resolver = new OptionsResolver();
+        $resolver->setDefined('namespace');
+
+        $resolved = $resolver->resolve($parameters);
+
+        return $this->post($this->getProjectPath($project_id, 'fork'), $resolved);
     }
 
     /**
@@ -525,11 +603,15 @@ class Projects extends AbstractApi
 
     /**
      * @param int $project_id
+     * @param array $parameters
+     *
      * @return mixed
      */
-    public function variables($project_id)
+    public function variables($project_id, array $parameters = [])
     {
-        return $this->get($this->getProjectPath($project_id, 'variables'));
+        $resolver = $this->createOptionsResolver();
+
+        return $this->get($this->getProjectPath($project_id, 'variables'), $resolver->resolve($parameters));
     }
 
     /**
@@ -546,27 +628,51 @@ class Projects extends AbstractApi
      * @param int $project_id
      * @param string $key
      * @param string $value
+     * @param bool $protected
+     * @param string $environment_scope
      * @return mixed
      */
-    public function addVariable($project_id, $key, $value)
+    public function addVariable($project_id, $key, $value, $protected = null, $environment_scope = null)
     {
-        return $this->post($this->getProjectPath($project_id, 'variables'), array(
+        $payload = array(
             'key'   => $key,
-            'value' => $value
-        ));
+            'value' => $value,
+        );
+
+        if ($protected) {
+            $payload['protected'] = $protected;
+        }
+
+        if ($environment_scope) {
+            $payload['environment_scope'] = $environment_scope;
+        }
+
+        return $this->post($this->getProjectPath($project_id, 'variables'), $payload);
     }
 
     /**
      * @param int $project_id
      * @param string $key
      * @param string $value
+     * @param bool $protected
+     * @param string $environment_scope
      * @return mixed
      */
-    public function updateVariable($project_id, $key, $value)
+    public function updateVariable($project_id, $key, $value, $protected = null, $environment_scope = null)
     {
-        return $this->put($this->getProjectPath($project_id, 'variables/'.$this->encodePath($key)), array(
+        $payload = array(
             'value' => $value,
-        ));
+        );
+
+        if ($protected) {
+            $payload['protected'] = $protected;
+        }
+
+        if ($environment_scope) {
+            $payload['environment_scope'] = $environment_scope;
+        }
+
+        return $this->put($this->getProjectPath($project_id, 'variables/'.$this->encodePath($key)), $payload);
     }
 
     /**
@@ -591,16 +697,15 @@ class Projects extends AbstractApi
 
     /**
      * @param int $project_id
-     * @param int $page
-     * @param int $per_page
+     * @param array $parameters
+     *
      * @return mixed
      */
-    public function deployments($project_id, $page = 1, $per_page = self::PER_PAGE)
+    public function deployments($project_id, array $parameters = [])
     {
-        return $this->get($this->getProjectPath($project_id, 'deployments'), array(
-            'page' => $page,
-            'per_page' => $per_page
-        ));
+        $resolver = $this->createOptionsResolver();
+
+        return $this->get($this->getProjectPath($project_id, 'deployments'), $resolver->resolve($parameters));
     }
 
     /**
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Repositories.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Repositories.php
index bb6e842e858..14313b66e7e 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Repositories.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Repositories.php
@@ -1,14 +1,19 @@
 <?php namespace Gitlab\Api;
 
+use Symfony\Component\OptionsResolver\Options;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+
 class Repositories extends AbstractApi
 {
     /**
      * @param int $project_id
+     * @param array $parameters
      * @return mixed
      */
-    public function branches($project_id)
+    public function branches($project_id, array $parameters = [])
     {
-        return $this->get($this->getProjectPath($project_id, 'repository/branches'));
+        $resolver = $this->createOptionsResolver();
+        return $this->get($this->getProjectPath($project_id, 'repository/branches'), $resolver->resolve($parameters));
     }
 
     /**
@@ -18,31 +23,31 @@ class Repositories extends AbstractApi
      */
     public function branch($project_id, $branch_id)
     {
-        return $this->get($this->getProjectPath($project_id, 'repository/branches/'.$this->encodeBranch($branch_id)));
+        return $this->get($this->getProjectPath($project_id, 'repository/branches/'.$this->encodePath($branch_id)));
     }
 
     /**
      * @param int $project_id
-     * @param string $branch_name
+     * @param string $branch
      * @param string $ref
      * @return mixed
      */
-    public function createBranch($project_id, $branch_name, $ref)
+    public function createBranch($project_id, $branch, $ref)
     {
         return $this->post($this->getProjectPath($project_id, 'repository/branches'), array(
-            'branch_name' => $branch_name,
+            'branch' => $branch,
             'ref' => $ref
         ));
     }
 
     /**
      * @param int $project_id
-     * @param string $branch_name
+     * @param string $branch
      * @return mixed
      */
-    public function deleteBranch($project_id, $branch_name)
+    public function deleteBranch($project_id, $branch)
     {
-        return $this->delete($this->getProjectPath($project_id, 'repository/branches/'.$this->encodeBranch($branch_name)));
+        return $this->delete($this->getProjectPath($project_id, 'repository/branches/'.$this->encodePath($branch)));
     }
 
     /**
@@ -54,7 +59,7 @@ class Repositories extends AbstractApi
      */
     public function protectBranch($project_id, $branch_name, $devPush = false, $devMerge = false)
     {
-        return $this->put($this->getProjectPath($project_id, 'repository/branches/'.$this->encodeBranch($branch_name).'/protect'), array(
+        return $this->put($this->getProjectPath($project_id, 'repository/branches/'.$this->encodePath($branch_name).'/protect'), array(
             'developers_can_push' => $devPush,
             'developers_can_merge' => $devMerge
         ));
@@ -67,16 +72,19 @@ class Repositories extends AbstractApi
      */
     public function unprotectBranch($project_id, $branch_name)
     {
-        return $this->put($this->getProjectPath($project_id, 'repository/branches/'.$this->encodeBranch($branch_name).'/unprotect'));
+        return $this->put($this->getProjectPath($project_id, 'repository/branches/'.$this->encodePath($branch_name).'/unprotect'));
     }
 
     /**
      * @param int $project_id
+     * @param array $parameters
      * @return mixed
      */
-    public function tags($project_id)
+    public function tags($project_id, array $parameters = [])
     {
-        return $this->get($this->getProjectPath($project_id, 'repository/tags'));
+        $resolver = $this->createOptionsResolver();
+
+        return $this->get($this->getProjectPath($project_id, 'repository/tags'), $resolver->resolve($parameters));
     }
 
     /**
@@ -102,12 +110,13 @@ class Repositories extends AbstractApi
      *
      * @return mixed
      */
-    public function createRelease( $project_id, $tag_name, $description ) {
-        return $this->post( $this->getProjectPath( $project_id, 'repository/tags/' . $this->encodeBranch( $tag_name ) . '/release' ), array(
+    public function createRelease($project_id, $tag_name, $description)
+    {
+        return $this->post($this->getProjectPath($project_id, 'repository/tags/' . $this->encodePath($tag_name) . '/release'), array(
             'id'          => $project_id,
             'tag_name'    => $tag_name,
             'description' => $description
-        ) );
+        ));
     }
 
     /**
@@ -117,71 +126,134 @@ class Repositories extends AbstractApi
      *
      * @return mixed
      */
-    public function updateRelease( $project_id, $tag_name, $description ) {
-        return $this->put( $this->getProjectPath( $project_id, 'repository/tags/' . $this->encodeBranch( $tag_name ) . '/release' ), array(
+    public function updateRelease($project_id, $tag_name, $description)
+    {
+        return $this->put($this->getProjectPath($project_id, 'repository/tags/' . $this->encodePath($tag_name) . '/release'), array(
             'id'          => $project_id,
             'tag_name'    => $tag_name,
             'description' => $description
-        ) );
+        ));
     }
 
     /**
      * @param int $project_id
-     * @param string $sha
-     * @param string $scope
-     * @param int $page
-     * @param int $per_page
+     * @param array $parameters (
+     *
+     *     @var string             $ref_name The name of a repository branch or tag or if not given the default branch.
+     *     @var \DateTimeInterface $since    Only commits after or on this date will be returned.
+     *     @var \DateTimeInterface $until    Only commits before or on this date will be returned.
+     * )
      *
      * @return mixed
      */
-    public function commitBuilds($project_id, $sha, $scope = null, $page = 0, $per_page = self::PER_PAGE)
+    public function commits($project_id, array $parameters = [])
     {
-        return $this->get($this->getProjectPath($project_id, 'repository/commits/'.$this->encodePath($sha).'/builds'), array(
-            'page' => $page,
-            'per_page' => $per_page,
-            'scope' => $scope
-        ));
+        $resolver = $this->createOptionsResolver();
+        $datetimeNormalizer = function (Options $options, \DateTimeInterface $value) {
+            return $value->format('c');
+        };
+
+        $resolver->setDefined('ref_name');
+        $resolver->setDefined('since')
+            ->setAllowedTypes('since', \DateTimeInterface::class)
+            ->setNormalizer('since', $datetimeNormalizer)
+        ;
+        $resolver->setDefined('until')
+            ->setAllowedTypes('until', \DateTimeInterface::class)
+            ->setNormalizer('until', $datetimeNormalizer)
+        ;
+
+        return $this->get($this->getProjectPath($project_id, 'repository/commits'), $resolver->resolve($parameters));
     }
 
     /**
      * @param int $project_id
-     * @param int $page
-     * @param int $per_page
-     * @param null $ref_name
+     * @param $sha
      * @return mixed
      */
-    public function commits($project_id, $page = 0, $per_page = self::PER_PAGE, $ref_name = null)
+    public function commit($project_id, $sha)
     {
-        return $this->get($this->getProjectPath($project_id, 'repository/commits'), array(
-            'page' => $page,
-            'per_page' => $per_page,
-            'ref_name' => $ref_name
-        ));
+        return $this->get($this->getProjectPath($project_id, 'repository/commits/'.$this->encodePath($sha)));
     }
 
     /**
      * @param int $project_id
-     * @param $sha
+     * @param array $parameters (
+     *
+     *     @var string $branch         Name of the branch to commit into. To create a new branch, also provide start_branch.
+     *     @var string $commit_message Commit message.
+     *     @var string $start_branch   Name of the branch to start the new commit from.
+     *     @var array $actions (
+     *
+     *         @var string $action        he action to perform, create, delete, move, update.
+     *         @var string $file_path     Full path to the file.
+     *         @var string $previous_path Original full path to the file being moved.
+     *         @var string $content       File content, required for all except delete. Optional for move.
+     *         @var string $encoding      text or base64. text is default.
+     *     )
+     *     @var string $author_email   Specify the commit author's email address.
+     *     @var string $author_name    Specify the commit author's name.
+     * )
+     *
      * @return mixed
      */
-    public function commit($project_id, $sha)
+    public function createCommit($project_id, array $parameters = [])
     {
-        return $this->get($this->getProjectPath($project_id, 'repository/commits/'.$this->encodePath($sha)));
+        $resolver = new OptionsResolver();
+        $resolver->setDefined('branch')
+            ->setRequired('branch')
+        ;
+        $resolver->setDefined('commit_message')
+            ->setRequired('commit_message')
+        ;
+        $resolver->setDefined('start_branch');
+        $resolver->setDefined('actions')
+            ->setRequired('actions')
+            ->setAllowedTypes('actions', 'array')
+            ->setAllowedValues('actions', function (array $actions) {
+                return !empty($actions);
+            })
+            ->setNormalizer('actions', function (Options $resolver, array $actions) {
+                $actionsOptionsResolver = new OptionsResolver();
+                $actionsOptionsResolver->setDefined('action')
+                    ->setRequired('action')
+                    ->setAllowedValues('action', ['create', 'delete', 'move', 'update'])
+                ;
+                $actionsOptionsResolver->setDefined('file_path')
+                    ->setRequired('file_path')
+                ;
+                $actionsOptionsResolver->setDefined('previous_path');
+                $actionsOptionsResolver->setDefined('content');
+                $actionsOptionsResolver->setDefined('encoding')
+                    ->setAllowedValues('encoding', ['test', 'base64'])
+                ;
+
+                return array_map(function ($action) use ($actionsOptionsResolver) {
+                    return $actionsOptionsResolver->resolve($action);
+                }, $actions);
+            })
+        ;
+        $resolver->setDefined('author_email');
+        $resolver->setDefined('author_name');
+
+        return $this->post($this->getProjectPath($project_id, 'repository/commits'), $resolver->resolve($parameters));
     }
 
     /**
-     * @param int $project_id
+     * @param int    $project_id
      * @param string $sha
-     * @param int $page
-     * @param int $per_page
+     * @param array  $parameters
+     *
      * @return mixed
      */
-    public function commitComments($project_id, $sha, $page = 0, $per_page = self::PER_PAGE)
+    public function commitComments($project_id, $sha, array $parameters = [])
     {
-        return $this->get($this->getProjectPath($project_id, 'repository/commits/'.$this->encodePath($sha).'/comments'), array(
-            'page' => $page,
-            'per_page' => $per_page
-        ));
+        $resolver = $this->createOptionsResolver();
+
+        return $this->get(
+            $this->getProjectPath($project_id, 'repository/commits/'.$this->encodePath($sha).'/comments'),
+            $resolver->resolve($parameters)
+        );
     }
 
     /**
@@ -198,6 +270,31 @@ class Repositories extends AbstractApi
         return $this->post($this->getProjectPath($project_id, 'repository/commits/'.$this->encodePath($sha).'/comments'), $params);
     }
 
+    /**
+     * @param int $project_id
+     * @param string $sha
+     * @param array $params
+     * @return mixed
+     */
+    public function getCommitBuildStatus($project_id, $sha, array $params = array())
+    {
+        return $this->get($this->getProjectPath($project_id, 'repository/commits/'.$this->encodePath($sha).'/statuses'), $params);
+    }
+
+    /**
+     * @param int $project_id
+     * @param string $sha
+     * @param string $state
+     * @param array $params
+     * @return mixed
+     */
+    public function postCommitBuildStatus($project_id, $sha, $state, array $params = array())
+    {
+        $params['state'] = $state;
+
+        return $this->post($this->getProjectPath($project_id, 'statuses/'.$this->encodePath($sha)), $params);
+    }
+
     /**
      * @param int $project_id
      * @param string $fromShaOrMaster
@@ -208,7 +305,7 @@ class Repositories extends AbstractApi
     {
         return $this->get($this->getProjectPath(
             $project_id,
-            'repository/compare?from='.$this->encodeBranch($fromShaOrMaster).'&to='.$this->encodeBranch($toShaOrMaster)
+            'repository/compare?from='.$this->encodePath($fromShaOrMaster).'&to='.$this->encodePath($toShaOrMaster)
         ));
     }
 
@@ -240,9 +337,9 @@ class Repositories extends AbstractApi
      */
     public function blob($project_id, $sha, $filepath)
     {
-        return $this->get($this->getProjectPath($project_id, 'repository/commits/'.$this->encodePath($sha).'/blob'), array(
-            'filepath' => $filepath
-        ));
+        @trigger_error(sprintf('The %s() method is deprecated since version 9.2 and will be removed in 10.0. Use the %s::getRawFile() method instead.', __METHOD__, RepositoryFiles::class), E_USER_DEPRECATED);
+
+        return $this->client->repositoryFiles()->getRawFile($project_id, $filepath, $sha);
     }
 
     /**
@@ -253,78 +350,83 @@ class Repositories extends AbstractApi
      */
     public function getFile($project_id, $file_path, $ref)
     {
-        return $this->get($this->getProjectPath($project_id, 'repository/files'), array(
-            'file_path' => $file_path,
-            'ref' => $ref
-        ));
+        @trigger_error(sprintf('The %s() method is deprecated since version 9.2 and will be removed in 10.0. Use the %s::getFile() method instead.', __METHOD__, RepositoryFiles::class), E_USER_DEPRECATED);
+
+        return $this->client->repositoryFiles()->getFile($project_id, $file_path, $ref);
     }
 
     /**
      * @param int $project_id
      * @param string $file_path
      * @param string $content
-     * @param string $branch_name
+     * @param string $branch
      * @param string $commit_message
      * @param string $encoding
      * @param string $author_email
      * @param string $author_name
      * @return mixed
      */
-    public function createFile($project_id, $file_path, $content, $branch_name, $commit_message, $encoding = null, $author_email = null, $author_name = null)
+    public function createFile($project_id, $file_path, $content, $branch, $commit_message, $encoding = null, $author_email = null, $author_name = null)
     {
-        return $this->post($this->getProjectPath($project_id, 'repository/files'), array(
+        @trigger_error(sprintf('The %s() method is deprecated since version 9.2 and will be removed in 10.0. Use the %s::createFile() method instead.', __METHOD__, RepositoryFiles::class), E_USER_DEPRECATED);
+
+        return $this->client->repositoryFiles()->createFile($project_id, [
             'file_path' => $file_path,
-            'branch_name' => $branch_name,
+            'branch' => $branch,
             'content' => $content,
             'commit_message' => $commit_message,
             'encoding' => $encoding,
             'author_email' => $author_email,
             'author_name' => $author_name,
-        ));
+        ]);
     }
 
     /**
      * @param int $project_id
      * @param string $file_path
      * @param string $content
-     * @param string $branch_name
+     * @param string $branch
      * @param string $commit_message
      * @param string $encoding
      * @param string $author_email
      * @param string $author_name
      * @return mixed
      */
-    public function updateFile($project_id, $file_path, $content, $branch_name, $commit_message, $encoding = null, $author_email = null, $author_name = null)
+    public function updateFile($project_id, $file_path, $content, $branch, $commit_message, $encoding = null, $author_email = null, $author_name = null)
     {
-        return $this->put($this->getProjectPath($project_id, 'repository/files'), array(
+        @trigger_error(sprintf('The %s() method is deprecated since version 9.2 and will be removed in 10.0. Use the %s::updateFile() method instead.', __METHOD__, RepositoryFiles::class), E_USER_DEPRECATED);
+
+        return $this->client->repositoryFiles()->updateFile($project_id, [
             'file_path' => $file_path,
-            'branch_name' => $branch_name,
+            'branch' => $branch,
             'content' => $content,
             'commit_message' => $commit_message,
             'encoding' => $encoding,
             'author_email' => $author_email,
             'author_name' => $author_name,
-        ));
+        ]);
     }
 
     /**
      * @param int $project_id
      * @param string $file_path
-     * @param string $branch_name
+     * @param string $branch
      * @param string $commit_message
      * @param string $author_email
      * @param string $author_name
      * @return mixed
      */
-    public function deleteFile($project_id, $file_path, $branch_name, $commit_message, $author_email = null, $author_name = null)
+    public function deleteFile($project_id, $file_path, $branch, $commit_message, $author_email = null, $author_name = null)
     {
-        return $this->delete($this->getProjectPath($project_id, 'repository/files'), array(
+        @trigger_error(sprintf('The %s() method is deprecated since version 9.2 and will be removed in 10.0. Use the %s::deleteFile() method instead.', __METHOD__, RepositoryFiles::class), E_USER_DEPRECATED);
+
+        return $this->client->repositoryFiles()->deleteFile($project_id, [
             'file_path' => $file_path,
-            'branch_name' => $branch_name,
+            'branch' => $branch,
             'commit_message' => $commit_message,
             'author_email' => $author_email,
             'author_name' => $author_name,
-        ));
+        ]);
     }
 
     /**
@@ -346,15 +448,4 @@ class Repositories extends AbstractApi
     {
         return $this->get($this->getProjectPath($project_id, 'repository/archive.'.$format), $params);
     }
-
-    /**
-     * @param string $path
-     * @return string
-     */
-    protected function encodeBranch($path)
-    {
-        $path = $this->encodePath($path);
-
-        return str_replace('%2F', '/', $path);
-    }
 }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/RepositoryFiles.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/RepositoryFiles.php
new file mode 100644
index 00000000000..bc20c00f0d8
--- /dev/null
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/RepositoryFiles.php
@@ -0,0 +1,135 @@
+<?php
+
+namespace Gitlab\Api;
+
+use Symfony\Component\OptionsResolver\OptionsResolver;
+
+class RepositoryFiles extends AbstractApi
+{
+    /**
+     * @param int $project_id
+     * @param string $file_path
+     * @param string $ref
+     * @return mixed
+     */
+    public function getFile($project_id, $file_path, $ref)
+    {
+        return $this->get($this->getProjectPath($project_id, 'repository/files/'.$this->encodePath($file_path)), array(
+            'ref' => $ref
+        ));
+    }
+
+    /**
+     * @param int $project_id
+     * @param string $file_path
+     * @param string $ref
+     * @return mixed
+     */
+    public function getRawFile($project_id, $file_path, $ref)
+    {
+        return $this->get($this->getProjectPath($project_id, 'repository/files/'.$this->encodePath($file_path).'/raw'), array(
+            'ref' => $ref,
+        ));
+    }
+
+    /**
+     * @param int   $project_id
+     * @param array $parameters (
+     *
+     *     @var string $file_path      Url encoded full path to new file. Ex. lib%2Fclass%2Erb.
+     *     @var string $branch         Name of the branch.
+     *     @var string $start_branch   Name of the branch to start the new commit from.
+     *     @var string $encoding       Change encoding to 'base64'. Default is text.
+     *     @var string $author_email   Specify the commit author's email address.
+     *     @var string $author_name    Specify the commit author's name.
+     *     @var string $content        File content.
+     *     @var string $commit_message Commit message.
+     * )
+     *
+     * @return mixed
+     */
+    public function createFile($project_id, array $parameters = [])
+    {
+        $resolver = new OptionsResolver();
+        $resolver->setRequired('file_path');
+        $resolver->setRequired('branch');
+        $resolver->setDefined('start_branch');
+        $resolver->setDefined('encoding')
+            ->setAllowedValues('encoding', ['text', 'base64'])
+        ;
+        $resolver->setDefined('author_email');
+        $resolver->setDefined('author_name');
+        $resolver->setRequired('content');
+        $resolver->setRequired('commit_message');
+
+        $resolved = $resolver->resolve($parameters);
+
+        return $this->post($this->getProjectPath($project_id, 'repository/files/'.$this->encodePath($resolved['file_path'])), $resolved);
+    }
+
+    /**
+     * @param int   $project_id
+     * @param array $parameters (
+     *
+     *     @var string $file_path      Url encoded full path to new file. Ex. lib%2Fclass%2Erb.
+     *     @var string $branch         Name of the branch.
+     *     @var string $start_branch   Name of the branch to start the new commit from.
+     *     @var string $encoding       Change encoding to 'base64'. Default is text.
+     *     @var string $author_email   Specify the commit author's email address.
+     *     @var string $author_name    Specify the commit author's name.
+     *     @var string $content        File content.
+     *     @var string $commit_message Commit message.
+     *     @var string $last_commit_id Last known file commit id.
+     * )
+     *
+     * @return mixed
+     */
+    public function updateFile($project_id, array $parameters = [])
+    {
+        $resolver = new OptionsResolver();
+        $resolver->setRequired('file_path');
+        $resolver->setRequired('branch');
+        $resolver->setDefined('start_branch');
+        $resolver->setDefined('encoding')
+            ->setAllowedValues('encoding', ['text', 'base64'])
+        ;
+        $resolver->setDefined('author_email');
+        $resolver->setDefined('author_name');
+        $resolver->setRequired('content');
+        $resolver->setRequired('commit_message');
+        $resolver->setDefined('last_commit_id');
+
+        $resolved = $resolver->resolve($parameters);
+
+        return $this->put($this->getProjectPath($project_id, 'repository/files/'.$this->encodePath($resolved['file_path'])), $resolved);
+    }
+
+    /**
+     * @param int   $project_id
+     * @param array $parameters (
+     *
+     *     @var string $file_path      Url encoded full path to new file. Ex. lib%2Fclass%2Erb.
+     *     @var string $branch         Name of the branch.
+     *     @var string $start_branch   Name of the branch to start the new commit from.
+     *     @var string $author_email   Specify the commit author's email address.
+     *     @var string $author_name    Specify the commit author's name.
+     *     @var string $commit_message Commit message.
+     * )
+     *
+     * @return mixed
+     */
+    public function deleteFile($project_id, array $parameters = [])
+    {
+        $resolver = new OptionsResolver();
+        $resolver->setRequired('file_path');
+        $resolver->setRequired('branch');
+        $resolver->setDefined('start_branch');
+        $resolver->setDefined('author_email');
+        $resolver->setDefined('author_name');
+        $resolver->setRequired('commit_message');
+
+        $resolved = $resolver->resolve($parameters);
+
+        return $this->delete($this->getProjectPath($project_id, 'repository/files/'.$this->encodePath($resolved['file_path'])), $resolved);
+    }
+}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Snippets.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Snippets.php
index 00921128c89..e17c0cba754 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Snippets.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Snippets.php
@@ -67,4 +67,15 @@ class Snippets extends AbstractApi
     {
         return $this->delete($this->getProjectPath($project_id, 'snippets/'.$this->encodePath($snippet_id)));
     }
+
+    /**
+     * @param int $project_id
+     * @param int $snippet_id
+     *
+     * @return mixed
+     */
+    public function awardEmoji($project_id, $snippet_id)
+    {
+        return $this->get($this->getProjectPath($project_id, 'snippets/'.$this->encodePath($snippet_id).'/award_emoji'));
+    }
 }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Users.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Users.php
index a3e31ff5cfc..d4f49b1e086 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Users.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Users.php
@@ -1,57 +1,75 @@
 <?php namespace Gitlab\Api;
 
+use Symfony\Component\OptionsResolver\Options;
+
 class Users extends AbstractApi
 {
     /**
-     * @param null|true $active
-     * @param int $page
-     * @param int $per_page
+     * @param array $parameters (
+     *
+     * @var string             $search         Search for user by email or username.
+     * @var string             $username       Lookup for user by username.
+     * @var bool               $external       Search for external users only.
+     * @var string             $extern_uid     Lookup for users by external uid.
+     * @var string             $provider       Lookup for users by provider.
+     * @var \DateTimeInterface $created_before Return users created before the given time (inclusive).
+     * @var \DateTimeInterface $created_after  Return users created after the given time (inclusive).
+     * @var bool               $active         Return only active users. It does not support filtering inactive users.
+     * @var bool               $blocked        Return only blocked users. It does not support filtering non-blocked users.
+     * )
+     *
      * @return mixed
      */
-    public function all($active = null, $page = 1, $per_page = self::PER_PAGE)
+    public function all(array $parameters = [])
     {
-        return $this->get('users', array(
-            'active' => $active,
-            'page' => $page,
-            'per_page' => $per_page
-        ));
-    }
+        $resolver = $this->createOptionsResolver();
+        $datetimeNormalizer = function (Options $resolver, \DateTimeInterface $value) {
+            return $value->format('c');
+        };
 
-    /**
-     * @param string $username
-     * @return mixed
-     */
-    public function lookup($username)
-    {
-        return $this->get('users', array(
-            'username' => $username
-        ));
+        $resolver->setDefined('search');
+        $resolver->setDefined('username');
+        $resolver->setDefined('external')
+            ->setAllowedTypes('external', 'bool')
+        ;
+        $resolver->setDefined('extern_uid');
+        $resolver->setDefined('provider');
+        $resolver->setDefined('created_before')
+            ->setAllowedTypes('created_before', \DateTimeInterface::class)
+            ->setNormalizer('created_before', $datetimeNormalizer)
+        ;
+        $resolver->setDefined('created_after')
+            ->setAllowedTypes('created_after', \DateTimeInterface::class)
+            ->setNormalizer('created_after', $datetimeNormalizer)
+        ;
+        $resolver->setDefined('active')
+            ->setAllowedTypes('active', 'bool')
+            ->setAllowedValues('active', true)
+        ;
+        $resolver->setDefined('blocked')
+            ->setAllowedTypes('blocked', 'bool')
+            ->setAllowedValues('blocked', true)
+        ;
+
+
+        return $this->get('users', $resolver->resolve($parameters));
     }
 
     /**
-     * @param string $query
-     * @param null|true $active
-     * @param int $page
-     * @param int $per_page
+     * @param int $id
      * @return mixed
      */
-    public function search($query, $active = null, $page = 1, $per_page = self::PER_PAGE)
+    public function show($id)
     {
-        return $this->get('users', array(
-            'search' => $query,
-            'active' => $active,
-            'page' => $page,
-            'per_page' => $per_page
-        ));
+        return $this->get('users/'.$this->encodePath($id));
     }
 
     /**
-     * @param int $id
      * @return mixed
      */
-    public function show($id)
+    public function user()
     {
-        return $this->get('users/'.$this->encodePath($id));
+        return $this->get('user');
     }
 
     /**
@@ -93,7 +111,7 @@ class Users extends AbstractApi
      */
     public function block($id)
     {
-        return $this->put('users/'.$this->encodePath($id).'/block');
+        return $this->post('users/'.$this->encodePath($id).'/block');
     }
 
     /**
@@ -102,7 +120,7 @@ class Users extends AbstractApi
      */
     public function unblock($id)
     {
-        return $this->put('users/'.$this->encodePath($id).'/unblock');
+        return $this->post('users/'.$this->encodePath($id).'/unblock');
     }
 
     /**
@@ -235,4 +253,49 @@ class Users extends AbstractApi
     {
         return $this->get('user/emails/'.$this->encodePath($id));
     }
+
+    /**
+     * @param int $user_id
+     * @return mixed
+     */
+    public function userImpersonationTokens($user_id)
+    {
+        return $this->get('users/'.$this->encodePath($user_id).'/impersonation_tokens');
+    }
+
+    /**
+     * @param int $user_id
+     * @param int $impersonation_token_id
+     * @return mixed
+     */
+    public function userImpersonationToken($user_id, $impersonation_token_id)
+    {
+        return $this->get('users/'.$this->encodePath($user_id).'/impersonation_tokens/'.$this->encodePath($impersonation_token_id));
+    }
+
+    /**
+     * @param int $user_id
+     * @param string $name
+     * @param array $scopes
+     * @param null $expires_at
+     * @return mixed
+     */
+    public function createImpersonationToken($user_id, $name, array $scopes, $expires_at = null)
+    {
+        return $this->post('users/'.$this->encodePath($user_id).'/impersonation_tokens', array(
+            'name' => $name,
+            'scopes' => $scopes,
+            'expires_at' => $expires_at
+        ));
+    }
+
+    /**
+     * @param int $user_id
+     * @param int $impersonation_token_id
+     * @return mixed
+     */
+    public function removeImpersonationToken($user_id, $impersonation_token_id)
+    {
+        return $this->delete('users/'.$this->encodePath($user_id).'/impersonation_tokens/'.$this->encodePath($impersonation_token_id));
+    }
 }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Version.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Version.php
new file mode 100644
index 00000000000..59a58104b28
--- /dev/null
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Api/Version.php
@@ -0,0 +1,9 @@
+<?php namespace Gitlab\Api;
+
+class Version extends AbstractApi
+{
+    public function show()
+    {
+        return $this->get('version');
+    }
+}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Client.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Client.php
index 5f0fd395091..376e461f4cb 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Client.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Client.php
@@ -1,14 +1,18 @@
 <?php namespace Gitlab;
 
-use Buzz\Client\Curl;
-use Buzz\Client\ClientInterface;
-
 use Gitlab\Api\AbstractApi;
 use Gitlab\Exception\InvalidArgumentException;
-use Gitlab\HttpClient\HttpClient;
-use Gitlab\HttpClient\HttpClientInterface;
-use Gitlab\HttpClient\Listener\AuthListener;
-use Gitlab\HttpClient\Listener\PaginationListener;
+use Gitlab\HttpClient\Builder;
+use Gitlab\HttpClient\Plugin\ApiVersion;
+use Gitlab\HttpClient\Plugin\History;
+use Gitlab\HttpClient\Plugin\Authentication;
+use Gitlab\HttpClient\Plugin\GitlabExceptionThrower;
+use Http\Client\Common\HttpMethodsClient;
+use Http\Client\Common\Plugin\AddHostPlugin;
+use Http\Client\Common\Plugin\HeaderDefaultsPlugin;
+use Http\Client\Common\Plugin\HistoryPlugin;
+use Http\Client\HttpClient;
+use Http\Discovery\UriFactoryDiscovery;
 
 /**
  * Simple API wrapper for Gitlab
@@ -17,6 +21,7 @@ use Gitlab\HttpClient\Listener\PaginationListener;
  *
  * @property-read \Gitlab\Api\Groups $groups
  * @property-read \Gitlab\Api\Issues $issues
+ * @property-read \Gitlab\Api\Jobs $jobs
  * @property-read \Gitlab\Api\MergeRequests $merge_requests
  * @property-read \Gitlab\Api\MergeRequests $mr
  * @property-read \Gitlab\Api\Milestones $milestones
@@ -32,6 +37,7 @@ use Gitlab\HttpClient\Listener\PaginationListener;
  * @property-read \Gitlab\Api\Users $users
  * @property-read \Gitlab\Api\Keys $keys
  * @property-read \Gitlab\Api\Tags $tags
+ * @property-read \Gitlab\Api\Version $version
  */
 class Client
 {
@@ -54,48 +60,206 @@ class Client
     const AUTH_OAUTH_TOKEN = 'oauth_token';
 
     /**
-     * @var array
+     * @var History
      */
-    private $options = array(
-        'user_agent'  => 'php-gitlab-api (http://github.com/m4tthumphrey/php-gitlab-api)',
-        'timeout'     => 60
-    );
+    private $responseHistory;
 
-    private $baseUrl;
+    /**
+     * @var Builder
+     */
+    private $httpClientBuilder;
 
     /**
-     * The Buzz instance used to communicate with Gitlab
+     * Instantiate a new Gitlab client
      *
-     * @var HttpClient
+     * @param Builder $httpClientBuilder
      */
-    private $httpClient;
+    public function __construct(Builder $httpClientBuilder = null)
+    {
+        $this->responseHistory = new History();
+        $this->httpClientBuilder = $httpClientBuilder ?: new Builder();
+
+        $this->httpClientBuilder->addPlugin(new GitlabExceptionThrower());
+        $this->httpClientBuilder->addPlugin(new HistoryPlugin($this->responseHistory));
+        $this->httpClientBuilder->addPlugin(new ApiVersion());
+        $this->httpClientBuilder->addPlugin(new HeaderDefaultsPlugin([
+            'User-Agent' => 'php-gitlab-api (http://github.com/m4tthumphrey/php-gitlab-api)',
+        ]));
+
+        $this->setUrl('https://gitlab.com');
+    }
 
     /**
-     * Instantiate a new Gitlab client
+     * Create a Gitlab\Client using an url.
+     *
+     * @param string $url
      *
-     * @param string               $baseUrl
-     * @param null|ClientInterface $httpClient Buzz client
-     * @param array                $options
+     * @return Client
      */
-    public function __construct($baseUrl, ClientInterface $httpClient = null, array $options = array())
+    public static function create($url)
     {
-        foreach ($options as $name => $value) {
-            $this->setOption($name, $value);
-        }
+        $client = new self();
+        $client->setUrl($url);
+
+        return $client;
+    }
+
+    /**
+     * Create a Gitlab\Client using an HttpClient.
+     *
+     * @param HttpClient $httpClient
+     *
+     * @return Client
+     */
+    public static function createWithHttpClient(HttpClient $httpClient)
+    {
+        $builder = new Builder($httpClient);
+
+        return new self($builder);
+    }
+
+    /**
+     * @return Api\DeployKeys
+     */
+    public function deployKeys()
+    {
+        return new Api\DeployKeys($this);
+    }
+
+    /**
+     * @return Api\Environments
+     */
+    public function environments()
+    {
+        return new Api\Environments($this);
+    }
+    
+    /**
+     * @return Api\Groups
+     */
+    public function groups()
+    {
+        return new Api\Groups($this);
+    }
+
+    /**
+     * @return Api\Issues
+     */
+    public function issues()
+    {
+        return new Api\Issues($this);
+    }
+
+    /**
+     * @return Api\IssueBoards
+     */
+    public function issueBoards()
+    {
+        return new Api\IssueBoards($this);
+    }
+
+    /**
+     * @return Api\Jobs
+     */
+    public function jobs()
+    {
+        return new Api\Jobs($this);
+    }
+
+    /**
+     * @return Api\MergeRequests
+     */
+    public function mergeRequests()
+    {
+        return new Api\MergeRequests($this);
+    }
+
+    /**
+     * @return Api\Milestones
+     */
+    public function milestones()
+    {
+        return new Api\Milestones($this);
+    }
+
+    /**
+     * @return Api\ProjectNamespaces
+     */
+    public function namespaces()
+    {
+        return new Api\ProjectNamespaces($this);
+    }
+
+    /**
+     * @return Api\Projects
+     */
+    public function projects()
+    {
+        return new Api\Projects($this);
+    }
+
+    /**
+     * @return Api\Repositories
+     */
+    public function repositories()
+    {
+        return new Api\Repositories($this);
+    }
+
+    /**
+     * @return Api\RepositoryFiles
+     */
+    public function repositoryFiles()
+    {
+        return new Api\RepositoryFiles($this);
+    }
+
+    /**
+     * @return Api\Snippets
+     */
+    public function snippets()
+    {
+        return new Api\Snippets($this);
+    }
 
-        $httpClient = $httpClient ?: new Curl();
-        $httpClient->setTimeout($this->options['timeout']);
-        $httpClient->setVerifyPeer(false);
+    /**
+     * @return Api\SystemHooks
+     */
+    public function systemHooks()
+    {
+        return new Api\SystemHooks($this);
+    }
 
-        $this->baseUrl     = $baseUrl;
-        $this->httpClient  = new HttpClient($this->baseUrl, $this->options, $httpClient);
+    /**
+     * @return Api\Users
+     */
+    public function users()
+    {
+        return new Api\Users($this);
+    }
 
-        /**
-         * a Pagination listener on Response
-         */
-        $this->httpClient->addListener(
-            new PaginationListener()
-        );
+    /**
+     * @return Api\Keys
+     */
+    public function keys()
+    {
+        return new Api\Keys($this);
+    }
+
+    /**
+     * @return Api\Tags
+     */
+    public function tags()
+    {
+        return new Api\Tags($this);
+    }
+
+    /**
+     * @return Api\Version
+     */
+    public function version()
+    {
+        return new Api\Version($this);
     }
 
     /**
@@ -109,68 +273,67 @@ class Client
         switch ($name) {
 
             case 'deploy_keys':
-                $api = new Api\DeployKeys($this);
-                break;
+                return $this->deployKeys();
 
+            case 'environments':
+                return $this->environments();
+                
             case 'groups':
-                $api = new Api\Groups($this);
-                break;
+                return $this->groups();
 
             case 'issues':
-                $api = new Api\Issues($this);
-                break;
+                return $this->issues();
+
+            case 'board':
+            case 'issue_boards':
+                return $this->issueBoards();
+            case 'jobs':
+                return $this->jobs();
 
             case 'mr':
             case 'merge_requests':
-                $api = new Api\MergeRequests($this);
-                break;
+                return $this->mergeRequests();
 
             case 'milestones':
             case 'ms':
-                $api = new Api\Milestones($this);
-                break;
+                return $this->milestones();
 
             case 'namespaces':
             case 'ns':
-                $api = new Api\ProjectNamespaces($this);
-                break;
+                return $this->namespaces();
 
             case 'projects':
-                $api = new Api\Projects($this);
-                break;
+                return $this->projects();
 
             case 'repo':
             case 'repositories':
-                $api = new Api\Repositories($this);
-                break;
+                return $this->repositories();
 
+            case 'repositoryFiles':
+                return $this->repositoryFiles();
+                
             case 'snippets':
-                $api = new Api\Snippets($this);
-                break;
+                return $this->snippets();
 
             case 'hooks':
             case 'system_hooks':
-                $api = new Api\SystemHooks($this);
-                break;
+                return $this->systemHooks();
 
             case 'users':
-                $api = new Api\Users($this);
-                break;
+                return $this->users();
 
             case 'keys':
-                $api = new Api\Keys($this);
-                break;
+                return $this->keys();
 
             case 'tags':
-                $api = new Api\Tags($this);
-                break;
+                return $this->tags();
+
+            case 'version':
+                return $this->version();
 
             default:
                 throw new InvalidArgumentException('Invalid endpoint: "'.$name.'"');
-
         }
-
-        return $api;
     }
 
     /**
@@ -183,117 +346,47 @@ class Client
      */
     public function authenticate($token, $authMethod = self::AUTH_URL_TOKEN, $sudo = null)
     {
-        $this->httpClient->addListener(
-            new AuthListener(
-                $authMethod,
-                $token,
-                $sudo
-            )
-        );
-
-        return $this;
-    }
-
-    /**
-     * @return HttpClient
-     */
-    public function getHttpClient()
-    {
-        return $this->httpClient;
-    }
-
-    /**
-     * @param HttpClientInterface $httpClient
-     * @return $this
-     */
-    public function setHttpClient(HttpClientInterface $httpClient)
-    {
-        $this->httpClient = $httpClient;
+        $this->httpClientBuilder->removePlugin(Authentication::class);
+        $this->httpClientBuilder->addPlugin(new Authentication($authMethod, $token, $sudo));
 
         return $this;
     }
 
     /**
      * @param string $url
-     * @return $this
-     */
-    public function setBaseUrl($url)
-    {
-        $this->baseUrl = $url;
-
-        return $this;
-    }
-
-    /**
-     * @return string
-     */
-    public function getBaseUrl()
-    {
-        return $this->baseUrl;
-    }
-
-    /**
-     * Clears used headers
      *
      * @return $this
      */
-    public function clearHeaders()
-    {
-        $this->httpClient->clearHeaders();
-
-        return $this;
-    }
-
-    /**
-     * @param array $headers
-     * @return $this
-     */
-    public function setHeaders(array $headers)
+    public function setUrl($url)
     {
-        $this->httpClient->setHeaders($headers);
+        $this->httpClientBuilder->removePlugin(AddHostPlugin::class);
+        $this->httpClientBuilder->addPlugin(new AddHostPlugin(UriFactoryDiscovery::find()->createUri($url)));
 
         return $this;
     }
 
     /**
-     * @param string $name
-     *
-     * @return mixed
-     *
-     * @throws InvalidArgumentException
+     * @param string $api
+     * @return AbstractApi
      */
-    public function getOption($name)
+    public function __get($api)
     {
-        if (!array_key_exists($name, $this->options)) {
-            throw new InvalidArgumentException(sprintf('Undefined option called: "%s"', $name));
-        }
-
-        return $this->options[$name];
+        return $this->api($api);
     }
 
     /**
-     * @param string $name
-     * @param mixed $value
-     * @throws InvalidArgumentException
-     * @return $this
+     * @return HttpMethodsClient
      */
-    public function setOption($name, $value)
+    public function getHttpClient()
     {
-        if (!array_key_exists($name, $this->options)) {
-            throw new InvalidArgumentException(sprintf('Undefined option called: "%s"', $name));
-        }
-
-        $this->options[$name] = $value;
-
-        return $this;
+        return $this->httpClientBuilder->getHttpClient();
     }
 
     /**
-     * @param string $api
-     * @return AbstractApi
+     * @return History
      */
-    public function __get($api)
+    public function getResponseHistory()
     {
-        return $this->api($api);
+        return $this->responseHistory;
     }
 }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/ErrorException.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/ErrorException.php
index 322a7082da8..4bca15dc291 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/ErrorException.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/ErrorException.php
@@ -5,7 +5,6 @@
  *
  * @author Joseph Bielawski <stloyd@gmail.com>
  */
-class ErrorException extends \ErrorException
+class ErrorException extends \ErrorException implements ExceptionInterface
 {
-
 }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/ExceptionInterface.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/ExceptionInterface.php
new file mode 100644
index 00000000000..81403dcf89c
--- /dev/null
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/ExceptionInterface.php
@@ -0,0 +1,12 @@
+<?php namespace Gitlab\Exception;
+
+use Http\Client\Exception;
+
+/**
+ * ExceptionInterface
+ *
+ * @author Graham Campbell <graham@alt-three.com>
+ */
+interface ExceptionInterface extends Exception
+{
+}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/InvalidArgumentException.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/InvalidArgumentException.php
index 892a6dc4bd9..f430ab9e5e2 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/InvalidArgumentException.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/InvalidArgumentException.php
@@ -5,7 +5,6 @@
  *
  * @author Joseph Bielawski <stloyd@gmail.com>
  */
-class InvalidArgumentException extends \InvalidArgumentException
+class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
 {
-
 }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/MissingArgumentException.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/MissingArgumentException.php
index f157b49d1e5..93a5451e5ec 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/MissingArgumentException.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/MissingArgumentException.php
@@ -5,7 +5,7 @@
  *
  * @author Joseph Bielawski <stloyd@gmail.com>
  */
-class MissingArgumentException extends ErrorException
+class MissingArgumentException extends ErrorException implements ExceptionInterface
 {
     public function __construct($required, $code = 0, $previous = null)
     {
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/RuntimeException.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/RuntimeException.php
index 9d938e2cc39..0a12b500cc2 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/RuntimeException.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/RuntimeException.php
@@ -5,7 +5,6 @@
  *
  * @author Joseph Bielawski <stloyd@gmail.com>
  */
-class RuntimeException extends \RuntimeException
+class RuntimeException extends \RuntimeException implements ExceptionInterface
 {
-
 }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/ValidationFailedException.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/ValidationFailedException.php
index 9ce6635fe58..066b9f855cd 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/ValidationFailedException.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Exception/ValidationFailedException.php
@@ -5,7 +5,6 @@
  *
  * @author Joseph Bielawski <stloyd@gmail.com>
  */
-class ValidationFailedException extends ErrorException
+class ValidationFailedException extends ErrorException implements ExceptionInterface
 {
-
 }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Builder.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Builder.php
new file mode 100644
index 00000000000..8c6f586eba1
--- /dev/null
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Builder.php
@@ -0,0 +1,118 @@
+<?php
+
+namespace Gitlab\HttpClient;
+
+use Http\Client\Common\HttpMethodsClient;
+use Http\Client\Common\Plugin;
+use Http\Client\Common\PluginClient;
+use Http\Client\Common\PluginClientFactory;
+use Http\Client\HttpClient;
+use Http\Discovery\HttpClientDiscovery;
+use Http\Discovery\MessageFactoryDiscovery;
+use Http\Discovery\StreamFactoryDiscovery;
+use Http\Message\MessageFactory;
+use Http\Message\RequestFactory;
+use Http\Message\StreamFactory;
+
+/**
+ * A builder that builds the API client.
+ * This will allow you to fluently add and remove plugins.
+ *
+ * @author Tobias Nyholm <tobias.nyholm@gmail.com>
+ */
+class Builder
+{
+    /**
+     * The object that sends HTTP messages.
+     *
+     * @var HttpClient
+     */
+    private $httpClient;
+
+    /**
+     * A HTTP client with all our plugins.
+     *
+     * @var HttpMethodsClient
+     */
+    private $pluginClient;
+
+    /**
+     * @var MessageFactory
+     */
+    private $requestFactory;
+
+    /**
+     * @var StreamFactory
+     */
+    private $streamFactory;
+
+    /**
+     * True if we should create a new Plugin client at next request.
+     *
+     * @var bool
+     */
+    private $httpClientModified = true;
+
+    /**
+     * @var Plugin[]
+     */
+    private $plugins = [];
+
+    /**
+     * @param HttpClient     $httpClient
+     * @param RequestFactory $requestFactory
+     * @param StreamFactory  $streamFactory
+     */
+    public function __construct(
+        HttpClient $httpClient = null,
+        RequestFactory $requestFactory = null,
+        StreamFactory $streamFactory = null
+    ) {
+        $this->httpClient = $httpClient ?: HttpClientDiscovery::find();
+        $this->requestFactory = $requestFactory ?: MessageFactoryDiscovery::find();
+        $this->streamFactory = $streamFactory ?: StreamFactoryDiscovery::find();
+    }
+
+    /**
+     * @return HttpMethodsClient
+     */
+    public function getHttpClient()
+    {
+        if ($this->httpClientModified) {
+            $this->httpClientModified = false;
+
+            $this->pluginClient = new HttpMethodsClient(
+                (new PluginClientFactory())->createClient($this->httpClient, $this->plugins),
+                $this->requestFactory
+            );
+        }
+
+        return $this->pluginClient;
+    }
+
+    /**
+     * Add a new plugin to the end of the plugin chain.
+     *
+     * @param Plugin $plugin
+     */
+    public function addPlugin(Plugin $plugin)
+    {
+        $this->plugins[] = $plugin;
+        $this->httpClientModified = true;
+    }
+
+    /**
+     * Remove a plugin by its fully qualified class name (FQCN).
+     *
+     * @param string $fqcn
+     */
+    public function removePlugin($fqcn)
+    {
+        foreach ($this->plugins as $idx => $plugin) {
+            if ($plugin instanceof $fqcn) {
+                unset($this->plugins[$idx]);
+                $this->httpClientModified = true;
+            }
+        }
+    }
+}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/HttpClient.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/HttpClient.php
deleted file mode 100644
index 7a84bfb436a..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/HttpClient.php
+++ /dev/null
@@ -1,231 +0,0 @@
-<?php namespace Gitlab\HttpClient;
-
-use Buzz\Client\ClientInterface;
-use Buzz\Listener\ListenerInterface;
-use Buzz\Message\Form\FormUpload;
-
-use Gitlab\Exception\ErrorException;
-use Gitlab\Exception\RuntimeException;
-use Gitlab\HttpClient\Listener\ErrorListener;
-use Gitlab\HttpClient\Message\Request;
-use Gitlab\HttpClient\Message\Response;
-use Gitlab\HttpClient\Message\FormRequest;
-
-/**
- * Performs requests on Gitlab API. API documentation should be self-explanatory.
- *
- * @author Joseph Bielawski <stloyd@gmail.com>
- * @author Matt Humphrey <matt@m4tt.co>
- */
-class HttpClient implements HttpClientInterface
-{
-    /**
-     * @var array
-     */
-    protected $options = array(
-        'user_agent'  => 'php-gitlab-api (http://github.com/m4tthumphrey/php-gitlab-api)',
-        'timeout'     => 10,
-    );
-
-    /**
-     * @var string
-     */
-    protected $baseUrl;
-
-    /**
-     * @var ListenerInterface[]
-     */
-    protected $listeners = array();
-    /**
-     * @var array
-     */
-    protected $headers = array();
-
-    /**
-     * @var Response
-     */
-    private $lastResponse;
-
-    /**
-     * @var Request
-     */
-    private $lastRequest;
-
-    /**
-     * @param string $baseUrl
-     * @param array $options
-     * @param ClientInterface $client
-     */
-    public function __construct($baseUrl, array $options, ClientInterface $client)
-    {
-        $this->baseUrl = $baseUrl;
-        $this->options = array_merge($this->options, $options);
-        $this->client  = $client;
-
-        $this->addListener(new ErrorListener($this->options));
-
-        $this->clearHeaders();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public function setOption($name, $value)
-    {
-        $this->options[$name] = $value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public function setHeaders(array $headers)
-    {
-        $this->headers = array_merge($this->headers, $headers);
-    }
-
-    /**
-     * Clears used headers
-     */
-    public function clearHeaders()
-    {
-        $this->headers = array();
-    }
-
-    /**
-     * @param ListenerInterface $listener
-     */
-    public function addListener(ListenerInterface $listener)
-    {
-        $this->listeners[get_class($listener)] = $listener;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public function get($path, array $parameters = array(), array $headers = array())
-    {
-        if (0 < count($parameters)) {
-            $path .= (false === strpos($path, '?') ? '?' : '&').http_build_query($parameters, '', '&');
-        }
-
-        return $this->request($path, array(), 'GET', $headers);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public function post($path, array $parameters = array(), array $headers = array(), array $files = array())
-    {
-        return $this->request($path, $parameters, 'POST', $headers, $files);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public function patch($path, array $parameters = array(), array $headers = array())
-    {
-        return $this->request($path, $parameters, 'PATCH', $headers);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public function delete($path, array $parameters = array(), array $headers = array())
-    {
-        return $this->request($path, $parameters, 'DELETE', $headers);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public function put($path, array $parameters = array(), array $headers = array())
-    {
-        return $this->request($path, $parameters, 'PUT', $headers);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public function request($path, array $parameters = array(), $httpMethod = 'GET', array $headers = array(), array $files = array())
-    {
-        $path = trim($this->baseUrl.$path, '/');
-
-        $request = $this->createRequest($httpMethod, $path, $parameters, $headers, $files);
-
-        $hasListeners = 0 < count($this->listeners);
-        if ($hasListeners) {
-            foreach ($this->listeners as $listener) {
-                $listener->preSend($request);
-            }
-        }
-
-        $response = new Response();
-
-        try {
-            $this->client->send($request, $response);
-        } catch (\LogicException $e) {
-            throw new ErrorException($e->getMessage());
-        } catch (\RuntimeException $e) {
-            throw new RuntimeException($e->getMessage());
-        }
-
-        $this->lastRequest  = $request;
-        $this->lastResponse = $response;
-
-        if ($hasListeners) {
-            foreach ($this->listeners as $listener) {
-                $listener->postSend($request, $response);
-            }
-        }
-
-        return $response;
-    }
-
-    /**
-     * @return Request
-     */
-    public function getLastRequest()
-    {
-        return $this->lastRequest;
-    }
-
-    /**
-     * @return Response
-     */
-    public function getLastResponse()
-    {
-        return $this->lastResponse;
-    }
-
-    /**
-     * @param string $httpMethod
-     * @param string $url
-     * @param array $parameters
-     * @param array $headers
-     * @param array $files
-     *
-     * @return FormRequest|Request
-     */
-    private function createRequest($httpMethod, $url, array $parameters, array $headers, array $files)
-    {
-        if (empty($files)) {
-            $request = new Request($httpMethod);
-            $request->setContent(http_build_query($parameters));
-        } else {
-            $request = new FormRequest($httpMethod);
-            foreach ($parameters as $name => $value) {
-                $request->setField($name, $value);
-            }
-
-            foreach ($files as $name => $file) {
-                $upload = new FormUpload($file);
-                $request->setField($name, $upload);
-            }
-        }
-        $request->setHeaders($this->headers);
-        $request->fromUrl($url);
-        $request->addHeaders($headers);
-
-        return $request;
-    }
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/HttpClientInterface.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/HttpClientInterface.php
deleted file mode 100644
index 674987becc9..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/HttpClientInterface.php
+++ /dev/null
@@ -1,98 +0,0 @@
-<?php namespace Gitlab\HttpClient;
-
-use Gitlab\Exception\InvalidArgumentException;
-
-/**
- * Performs requests on Gitlab API. API documentation should be self-explanatory.
- *
- * @author Joseph Bielawski <stloyd@gmail.com>
- * @author Matt Humphrey <matt@m4tt.co>
- */
-interface HttpClientInterface
-{
-    /**
-     * Send a GET request
-     *
-     * @param string $path       Request path
-     * @param array  $parameters GET Parameters
-     * @param array  $headers    Reconfigure the request headers for this call only
-     *
-     * @return array Data
-     */
-    public function get($path, array $parameters = array(), array $headers = array());
-
-    /**
-     * Send a POST request
-     *
-     * @param string $path Request path
-     * @param array $parameters POST Parameters
-     * @param array $headers Reconfigure the request headers for this call only
-     * @param array $files Files paths of files to upload
-     *
-     * @return array Data
-     */
-    public function post($path, array $parameters = array(), array $headers = array(), array $files = array());
-
-    /**
-     * Send a PATCH request
-     *
-     * @param string $path       Request path
-     * @param array  $parameters PATCH Parameters
-     * @param array  $headers    Reconfigure the request headers for this call only
-     *
-     * @return array Data
-     */
-    public function patch($path, array $parameters = array(), array $headers = array());
-
-    /**
-     * Send a PUT request
-     *
-     * @param string $path       Request path
-     * @param array  $parameters PUT Parameters
-     * @param array  $headers    Reconfigure the request headers for this call only
-     *
-     * @return array Data
-     */
-    public function put($path, array $parameters = array(), array $headers = array());
-
-    /**
-     * Send a DELETE request
-     *
-     * @param string $path       Request path
-     * @param array  $parameters DELETE Parameters
-     * @param array  $headers    Reconfigure the request headers for this call only
-     *
-     * @return array Data
-     */
-    public function delete($path, array $parameters = array(), array $headers = array());
-
-    /**
-     * Send a request to the server, receive a response,
-     * decode the response and returns an associative array
-     *
-     * @param string $path       Request API path
-     * @param array  $parameters Parameters
-     * @param string $httpMethod HTTP method to use
-     * @param array  $headers    Request headers
-     *
-     * @return array Data
-     */
-    public function request($path, array $parameters = array(), $httpMethod = 'GET', array $headers = array());
-
-    /**
-     * Change an option value.
-     *
-     * @param string $name  The option name
-     * @param mixed  $value The value
-     *
-     * @throws InvalidArgumentException
-     */
-    public function setOption($name, $value);
-
-    /**
-     * Set HTTP headers
-     *
-     * @param array $headers
-     */
-    public function setHeaders(array $headers);
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Listener/AuthListener.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Listener/AuthListener.php
deleted file mode 100644
index 27164112280..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Listener/AuthListener.php
+++ /dev/null
@@ -1,95 +0,0 @@
-<?php namespace Gitlab\HttpClient\Listener;
-
-use Gitlab\Client;
-use Gitlab\Exception\InvalidArgumentException;
-
-use Buzz\Listener\ListenerInterface;
-use Buzz\Message\MessageInterface;
-use Buzz\Message\RequestInterface;
-use Buzz\Util\Url;
-
-/**
- * @author Joseph Bielawski <stloyd@gmail.com>
- * @author Matt Humphrey <matt@m4tt.co>
- */
-class AuthListener implements ListenerInterface
-{
-    /**
-     * @var string
-     */
-    private $method;
-
-    /**
-     * @var string
-     */
-    private $token;
-
-    /**
-     * @var string|null
-     */
-    private $sudo;
-
-    /**
-     * @param string      $method
-     * @param string      $token
-     * @param string|null $sudo
-     */
-    public function __construct($method, $token, $sudo = null)
-    {
-        $this->method  = $method;
-        $this->token = $token;
-        $this->sudo = $sudo;
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @throws InvalidArgumentException
-     */
-    public function preSend(RequestInterface $request)
-    {
-        // Skip by default
-        if (null === $this->method) {
-            return;
-        }
-
-        switch ($this->method) {
-            case Client::AUTH_HTTP_TOKEN:
-                $request->addHeader('PRIVATE-TOKEN: '.$this->token);
-                if (!is_null($this->sudo)) {
-                    $request->addHeader('SUDO: '.$this->sudo);
-                }
-                break;
-
-            case Client::AUTH_URL_TOKEN:
-                $url  = $request->getUrl();
-
-                $query = array(
-                    'private_token' => $this->token
-                );
-
-                if (!is_null($this->sudo)) {
-                    $query['sudo'] = $this->sudo;
-                }
-
-                $url .= (false === strpos($url, '?') ? '?' : '&').utf8_encode(http_build_query($query, '', '&'));
-
-                $request->fromUrl(new Url($url));
-                break;
-
-            case Client::AUTH_OAUTH_TOKEN:
-                $request->addHeader('Authorization: Bearer '.$this->token);
-                if (!is_null($this->sudo)) {
-                    $request->addHeader('SUDO: '.$this->sudo);
-                }
-                break;
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public function postSend(RequestInterface $request, MessageInterface $response)
-    {
-    }
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Listener/ErrorListener.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Listener/ErrorListener.php
deleted file mode 100644
index cb2acc68b21..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Listener/ErrorListener.php
+++ /dev/null
@@ -1,97 +0,0 @@
-<?php namespace Gitlab\HttpClient\Listener;
-
-use Buzz\Listener\ListenerInterface;
-use Buzz\Message\MessageInterface;
-use Buzz\Message\RequestInterface;
-use Gitlab\Exception\ErrorException;
-use Gitlab\Exception\RuntimeException;
-
-/**
- * @author Joseph Bielawski <stloyd@gmail.com>
- * @author Matt Humphrey <git@m4tt.co>
- */
-class ErrorListener implements ListenerInterface
-{
-    /**
-     * @var array
-     */
-    private $options;
-
-    /**
-     * @param array $options
-     */
-    public function __construct(array $options)
-    {
-        $this->options = $options;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public function preSend(RequestInterface $request)
-    {
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public function postSend(RequestInterface $request, MessageInterface $response)
-    {
-        /** @var $response \Gitlab\HttpClient\Message\Response */
-        if ($response->isClientError() || $response->isServerError()) {
-            $content = $response->getContent();
-            if (is_array($content) && isset($content['message'])) {
-                if (400 == $response->getStatusCode()) {
-                    $message = $this->parseMessage($content['message']);
-
-                    throw new ErrorException($message, 400);
-                }
-            }
-
-            $errorMessage = null;
-            if (isset($content['error'])) {
-                $errorMessage = $content['error'];
-                if (is_array($content['error'])) {
-                    $errorMessage = implode("\n", $content['error']);
-                }
-            } elseif (isset($content['message'])) {
-                $errorMessage = $this->parseMessage($content['message']);
-            } else {
-                $errorMessage = $content;
-            }
-
-            throw new RuntimeException($errorMessage, $response->getStatusCode());
-        }
-    }
-
-    /**
-     * @param mixed $message
-     * @return string
-     */
-    protected function parseMessage($message)
-    {
-        $string = $message;
-
-        if (is_array($message)) {
-            $format = '"%s" %s';
-            $errors = array();
-
-            foreach ($message as $field => $messages) {
-                if (is_array($messages)) {
-                    $messages = array_unique($messages);
-                    foreach ($messages as $error) {
-                        $errors[] = sprintf($format, $field, $error);
-                    }
-                } elseif (is_integer($field)) {
-                    $errors[] = $messages;
-                } else {
-                    $errors[] = sprintf($format, $field, $messages);
-                }
-            }
-
-            $string = implode(', ', $errors);
-        }
-
-        return $string;
-    }
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Listener/PaginationListener.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Listener/PaginationListener.php
deleted file mode 100644
index 80ba39ea965..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Listener/PaginationListener.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php namespace Gitlab\HttpClient\Listener;
-
-use Buzz\Listener\ListenerInterface;
-use Buzz\Message\MessageInterface;
-use Buzz\Message\RequestInterface;
-
-class PaginationListener implements ListenerInterface
-{
-    /**
-     * {@inheritDoc}
-     */
-    public function preSend(RequestInterface $request)
-    {
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public function postSend(RequestInterface $request, MessageInterface $response)
-    {
-        $header = $response->getHeader('Link');
-
-        if (empty($header)) {
-            return null;
-        }
-
-        $pagination = array();
-        foreach (explode(',', $header) as $link) {
-            preg_match('/<(.*)>; rel="(.*)"/i', trim($link, ','), $match);
-
-            if (3 === count($match)) {
-                $pagination[$match[2]] = $match[1];
-            }
-        }
-
-        $response->setPagination($pagination);
-    }
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/FormRequest.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/FormRequest.php
deleted file mode 100644
index ecd05e17d8e..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/FormRequest.php
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php namespace Gitlab\HttpClient\Message;
-
-use Buzz\Message\Form\FormRequest as BaseFormRequest;
-
-class FormRequest extends BaseFormRequest
-{
-
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/QueryStringBuilder.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/QueryStringBuilder.php
new file mode 100644
index 00000000000..03e16a32610
--- /dev/null
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/QueryStringBuilder.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace Gitlab\HttpClient\Message;
+
+final class QueryStringBuilder
+{
+    /**
+     * Encode a query as a query string according to RFC 3986. Indexed arrays are encoded using
+     * empty squared brackets ([]) unlike http_build_query.
+     *
+     * @param mixed $query
+     *
+     * @return string
+     */
+    public static function build($query)
+    {
+        if (!is_array($query)) {
+            return static::rawurlencode($query);
+        }
+        return implode('&', array_map(function ($value, $key) {
+            return static::encode($value, $key);
+        }, $query, array_keys($query)));
+    }
+
+    /**
+     * Encode a value
+     * @param mixed $query
+     * @param string $prefix
+     *
+     * @return string
+     */
+    private static function encode($query, $prefix)
+    {
+        if (!is_array($query)) {
+            return static::rawurlencode($prefix).'='.static::rawurlencode($query);
+        }
+
+        $isIndexedArray = static::isIndexedArray($query);
+        return implode('&', array_map(function ($value, $key) use ($prefix, $isIndexedArray) {
+            $prefix = $isIndexedArray ? $prefix.'[]' : $prefix.'['.$key.']';
+            return static::encode($value, $prefix);
+        }, $query, array_keys($query)));
+    }
+
+    /**
+     * Tell if the given array is an indexed one (i.e. contains only sequential integer keys starting from 0).
+     *
+     * @param array $query
+     *
+     * @return bool
+     */
+    public static function isIndexedArray(array $query)
+    {
+        if (empty($query) || !isset($query[0])) {
+            return false;
+        }
+
+        return array_keys($query) === range(0, count($query) - 1);
+    }
+
+    /**
+     * Encode a value like rawurlencode, but return "0" when false is given.
+     *
+     * @param mixed $value
+     *
+     * @return string
+     */
+    private static function rawurlencode($value)
+    {
+        if ($value === false) {
+            return '0';
+        }
+
+        return rawurlencode($value);
+    }
+}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/Request.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/Request.php
deleted file mode 100644
index 41a950f35f3..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/Request.php
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php namespace Gitlab\HttpClient\Message;
-
-use Buzz\Message\Request as BaseRequest;
-
-class Request extends BaseRequest
-{
-
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/Response.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/Response.php
deleted file mode 100644
index e5746e0b8c2..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/Response.php
+++ /dev/null
@@ -1,48 +0,0 @@
-<?php namespace Gitlab\HttpClient\Message;
-
-use Buzz\Message\Response as BaseResponse;
-
-class Response extends BaseResponse
-{
-    /**
-     * @var array pagination
-     * See PaginationListener
-     */
-    protected $pagination = array();
-
-    /**
-     * @return mixed
-     */
-    public function getPagination()
-    {
-        return $this->pagination;
-    }
-
-    /**
-     * @param array $pagination
-     */
-    public function setPagination(array $pagination)
-    {
-        $this->pagination = $pagination;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public function getContent()
-    {
-        $response = parent::getContent();
-
-        if ($this->getHeader('Content-Type') === 'application/json') {
-            $content  = json_decode($response, true);
-    
-            if (JSON_ERROR_NONE !== json_last_error()) {
-                return $response;
-            }
-    
-            return $content;
-        }
-
-        return $response;
-    }
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/ResponseMediator.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/ResponseMediator.php
new file mode 100644
index 00000000000..16bd781f07f
--- /dev/null
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/ResponseMediator.php
@@ -0,0 +1,73 @@
+<?php
+
+namespace Gitlab\HttpClient\Message;
+
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Utilities to parse response headers and content.
+ */
+class ResponseMediator
+{
+    /**
+     * Return the response body as a string or json array if content type is application/json.
+     *.
+     * @param ResponseInterface $response
+     *
+     * @return array|string
+     */
+    public static function getContent(ResponseInterface $response)
+    {
+        $body = $response->getBody()->__toString();
+        if (strpos($response->getHeaderLine('Content-Type'), 'application/json') === 0) {
+            $content = json_decode($body, true);
+            if (JSON_ERROR_NONE === json_last_error()) {
+                return $content;
+            }
+        }
+
+        return $body;
+    }
+
+    /**
+     * Extract pagination URIs from Link header.
+     *
+     * @param ResponseInterface $response
+     *
+     * @return array|null
+     */
+    public static function getPagination(ResponseInterface $response)
+    {
+        if (!$response->hasHeader('Link')) {
+            return null;
+        }
+
+        $header = self::getHeader($response, 'Link');
+        $pagination = array();
+        foreach (explode(',', $header) as $link) {
+            preg_match('/<(.*)>; rel="(.*)"/i', trim($link, ','), $match);
+
+            if (3 === count($match)) {
+                $pagination[$match[2]] = $match[1];
+            }
+        }
+
+        return $pagination;
+    }
+
+
+    /**
+     * Get the value for a single header.
+     *
+     * @param ResponseInterface $response
+     * @param string $name
+     *
+     * @return string|null
+     */
+    private static function getHeader(ResponseInterface $response, $name)
+    {
+        $headers = $response->getHeader($name);
+
+        return array_shift($headers);
+    }
+}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Plugin/ApiVersion.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Plugin/ApiVersion.php
new file mode 100644
index 00000000000..46b20e40228
--- /dev/null
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Plugin/ApiVersion.php
@@ -0,0 +1,29 @@
+<?php
+
+
+namespace Gitlab\HttpClient\Plugin;
+
+use Http\Client\Common\Plugin;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Prefix requests path with /api/v4/ if required.
+ *
+ * @author Fabien Bourigault <bourigaultfabien@gmail.com>
+ */
+class ApiVersion implements Plugin
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function handleRequest(RequestInterface $request, callable $next, callable $first)
+    {
+        $uri = $request->getUri();
+
+        if (substr($uri->getPath(), 0, 8) !== '/api/v4/') {
+            $request = $request->withUri($uri->withPath('/api/v4/'.$uri->getPath()));
+        }
+
+        return $next($request);
+    }
+}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Plugin/Authentication.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Plugin/Authentication.php
new file mode 100644
index 00000000000..aac0acc4a2e
--- /dev/null
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Plugin/Authentication.php
@@ -0,0 +1,86 @@
+<?php
+
+namespace Gitlab\HttpClient\Plugin;
+
+use Gitlab\Client;
+use Http\Client\Common\Plugin;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Add authentication to the request.
+ *
+ * @author Tobias Nyholm <tobias.nyholm@gmail.com>
+ * @author Fabien Bourigault <bourigaultfabien@gmail.com>
+ */
+class Authentication implements Plugin
+{
+    /**
+     * @var string
+     */
+    private $method;
+
+    /**
+     * @var string
+     */
+    private $token;
+
+    /**
+     * @var string|null
+     */
+    private $sudo;
+
+    /**
+     * @param string      $method
+     * @param string      $token
+     * @param string|null $sudo
+     */
+    public function __construct($method, $token, $sudo = null)
+    {
+        $this->method  = $method;
+        $this->token = $token;
+        $this->sudo = $sudo;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function handleRequest(RequestInterface $request, callable $next, callable $first)
+    {
+        switch ($this->method) {
+            case Client::AUTH_HTTP_TOKEN:
+                $request = $request->withHeader('PRIVATE-TOKEN', $this->token);
+                if (!is_null($this->sudo)) {
+                    $request = $request->withHeader('SUDO', $this->sudo);
+                }
+                break;
+
+            case Client::AUTH_URL_TOKEN:
+                $uri = $request->getUri();
+                $query = $uri->getQuery();
+
+                $parameters = [
+                    'private_token' => $this->token,
+                ];
+
+                if (!is_null($this->sudo)) {
+                    $parameters['sudo'] = $this->sudo;
+                }
+
+                $query .= empty($query) ? '' : '&';
+                $query .= utf8_encode(http_build_query($parameters, '', '&'));
+
+                $uri = $uri->withQuery($query);
+                $request = $request->withUri($uri);
+                break;
+
+            case Client::AUTH_OAUTH_TOKEN:
+                $request = $request->withHeader('Authorization', 'Bearer '.$this->token);
+                if (!is_null($this->sudo)) {
+                    $request = $request->withHeader('SUDO', $this->sudo);
+                }
+                break;
+        }
+
+        return $next($request);
+    }
+}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Plugin/GitlabExceptionThrower.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Plugin/GitlabExceptionThrower.php
new file mode 100644
index 00000000000..bb61e31219f
--- /dev/null
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Plugin/GitlabExceptionThrower.php
@@ -0,0 +1,86 @@
+<?php
+
+namespace Gitlab\HttpClient\Plugin;
+
+use Gitlab\Exception\ErrorException;
+use Gitlab\Exception\RuntimeException;
+use Gitlab\HttpClient\Message\ResponseMediator;
+use Http\Client\Common\Plugin;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * A plugin to remember the last response.
+ *
+ * @author Tobias Nyholm <tobias.nyholm@gmail.com>
+ * @author Fabien Bourigault <bourigaultfabien@gmail.com>
+ */
+class GitlabExceptionThrower implements Plugin
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function handleRequest(RequestInterface $request, callable $next, callable $first)
+    {
+        return $next($request)->then(function (ResponseInterface $response) {
+            if ($response->getStatusCode() >= 400 && $response->getStatusCode() < 600) {
+                $content = ResponseMediator::getContent($response);
+                if (is_array($content) && isset($content['message'])) {
+                    if (400 == $response->getStatusCode()) {
+                        $message = $this->parseMessage($content['message']);
+
+                        throw new ErrorException($message, 400);
+                    }
+                }
+
+                $errorMessage = null;
+                if (isset($content['error'])) {
+                    $errorMessage = $content['error'];
+                    if (is_array($content['error'])) {
+                        $errorMessage = implode("\n", $content['error']);
+                    }
+                } elseif (isset($content['message'])) {
+                    $errorMessage = $this->parseMessage($content['message']);
+                } else {
+                    $errorMessage = $content;
+                }
+
+                throw new RuntimeException($errorMessage, $response->getStatusCode());
+            }
+
+            return $response;
+        });
+    }
+
+    /**
+     * @param mixed $message
+     *
+     * @return string
+     */
+    private function parseMessage($message)
+    {
+        $string = $message;
+
+        if (is_array($message)) {
+            $format = '"%s" %s';
+            $errors = array();
+
+            foreach ($message as $field => $messages) {
+                if (is_array($messages)) {
+                    $messages = array_unique($messages);
+                    foreach ($messages as $error) {
+                        $errors[] = sprintf($format, $field, $error);
+                    }
+                } elseif (is_integer($field)) {
+                    $errors[] = $messages;
+                } else {
+                    $errors[] = sprintf($format, $field, $messages);
+                }
+            }
+
+            $string = implode(', ', $errors);
+        }
+
+        return $string;
+    }
+}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Plugin/History.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Plugin/History.php
new file mode 100644
index 00000000000..8412356fdae
--- /dev/null
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Plugin/History.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace Gitlab\HttpClient\Plugin;
+
+use Http\Client\Common\Plugin\Journal;
+use Http\Client\Exception;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * A plugin to remember the last response.
+ *
+ * @author Tobias Nyholm <tobias.nyholm@gmail.com>
+ */
+class History implements Journal
+{
+    /**
+     * @var ResponseInterface
+     */
+    private $lastResponse;
+
+    /**
+     * @return ResponseInterface|null
+     */
+    public function getLastResponse()
+    {
+        return $this->lastResponse;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function addSuccess(RequestInterface $request, ResponseInterface $response)
+    {
+        $this->lastResponse = $response;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function addFailure(RequestInterface $request, Exception $exception)
+    {
+    }
+}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Branch.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Branch.php
index 23afebcfea9..8c7ef36b415 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Branch.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Branch.php
@@ -1,7 +1,7 @@
 <?php namespace Gitlab\Model;
 
+use Gitlab\Api\Projects;
 use Gitlab\Client;
-use Gitlab\Api\AbstractApi as Api;
 
 /**
  * Class Branch
@@ -57,7 +57,7 @@ class Branch extends AbstractModel
      */
     public function show()
     {
-        $data = $this->api('repositories')->branch($this->project->id, $this->name);
+        $data = $this->client->repositories()->branch($this->project->id, $this->name);
 
         return static::fromArray($this->getClient(), $this->project, $data);
     }
@@ -69,7 +69,7 @@ class Branch extends AbstractModel
      */
     public function protect($devPush = false, $devMerge = false)
     {
-        $data = $this->api('repositories')->protectBranch($this->project->id, $this->name, $devPush, $devMerge);
+        $data = $this->client->repositories()->protectBranch($this->project->id, $this->name, $devPush, $devMerge);
 
         return static::fromArray($this->getClient(), $this->project, $data);
     }
@@ -79,7 +79,7 @@ class Branch extends AbstractModel
      */
     public function unprotect()
     {
-        $data = $this->api('repositories')->unprotectBranch($this->project->id, $this->name);
+        $data = $this->client->repositories()->unprotectBranch($this->project->id, $this->name);
 
         return static::fromArray($this->getClient(), $this->project, $data);
     }
@@ -89,19 +89,21 @@ class Branch extends AbstractModel
      */
     public function delete()
     {
-        $this->api('repositories')->deleteBranch($this->project->id, $this->name);
+        $this->client->repositories()->deleteBranch($this->project->id, $this->name);
 
         return true;
     }
 
     /**
-     * @param int $page
-     * @param int $per_page
+     * @param array $parameters
+     *
+     * @see Projects::commits for available parameters.
+     *
      * @return Commit[]
      */
-    public function commits($page = 1, $per_page = Api::PER_PAGE)
+    public function commits(array $parameters = [])
     {
-        return $this->project->commits($page, $per_page, $this->name);
+        return $this->project->commits($parameters);
     }
 
     /**
@@ -112,7 +114,7 @@ class Branch extends AbstractModel
      */
     public function createFile($file_path, $content, $commit_message)
     {
-        $data = $this->api('repositories')->createFile($this->project->id, $file_path, $content, $this->name, $commit_message);
+        $data = $this->client->repositories()->createFile($this->project->id, $file_path, $content, $this->name, $commit_message);
 
         return File::fromArray($this->getClient(), $this->project, $data);
     }
@@ -125,7 +127,7 @@ class Branch extends AbstractModel
      */
     public function updateFile($file_path, $content, $commit_message)
     {
-        $data = $this->api('repositories')->updateFile($this->project->id, $file_path, $content, $this->name, $commit_message);
+        $data = $this->client->repositories()->updateFile($this->project->id, $file_path, $content, $this->name, $commit_message);
 
         return File::fromArray($this->getClient(), $this->project, $data);
     }
@@ -137,7 +139,7 @@ class Branch extends AbstractModel
      */
     public function deleteFile($file_path, $commit_message)
     {
-        $this->api('repositories')->deleteFile($this->project->id, $file_path, $this->name, $commit_message);
+        $this->client->repositories()->deleteFile($this->project->id, $file_path, $this->name, $commit_message);
 
         return true;
     }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Group.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Group.php
index 38891d6c195..48923f18240 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Group.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Group.php
@@ -52,7 +52,7 @@ class Group extends AbstractModel
      */
     public static function create(Client $client, $name, $path)
     {
-        $data = $client->api('groups')->create($name, $path);
+        $data = $client->groups()->create($name, $path);
 
         return static::fromArray($client, $data);
     }
@@ -72,7 +72,7 @@ class Group extends AbstractModel
      */
     public function show()
     {
-        $data = $this->api('groups')->show($this->id);
+        $data = $this->client->groups()->show($this->id);
 
         return Group::fromArray($this->getClient(), $data);
     }
@@ -83,7 +83,7 @@ class Group extends AbstractModel
      */
     public function transfer($project_id)
     {
-        $data = $this->api('groups')->transfer($this->id, $project_id);
+        $data = $this->client->groups()->transfer($this->id, $project_id);
 
         return Group::fromArray($this->getClient(), $data);
     }
@@ -93,7 +93,7 @@ class Group extends AbstractModel
      */
     public function members()
     {
-        $data = $this->api('groups')->members($this->id);
+        $data = $this->client->groups()->members($this->id);
 
         $members = array();
         foreach ($data as $member) {
@@ -110,7 +110,7 @@ class Group extends AbstractModel
      */
     public function addMember($user_id, $access_level)
     {
-        $data = $this->api('groups')->addMember($this->id, $user_id, $access_level);
+        $data = $this->client->groups()->addMember($this->id, $user_id, $access_level);
 
         return User::fromArray($this->getClient(), $data);
     }
@@ -121,7 +121,7 @@ class Group extends AbstractModel
      */
     public function removeMember($user_id)
     {
-        $this->api('groups')->removeMember($this->id, $user_id);
+        $this->client->groups()->removeMember($this->id, $user_id);
 
         return true;
     }
@@ -131,9 +131,8 @@ class Group extends AbstractModel
      */
     public function projects()
     {
+        $data = $this->client->groups()->projects($this->id);
 
-        $data = $this->api('groups')->projects($this->id);
-
-        return Group::fromArray($this->getClient(),$data);
+        return Group::fromArray($this->getClient(), $data);
     }
 }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Hook.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Hook.php
index 15bda399228..d276982e206 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Hook.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Hook.php
@@ -39,7 +39,7 @@ class Hook extends AbstractModel
      */
     public static function create(Client $client, $url)
     {
-        $data = $client->api('system_hooks')->create($url);
+        $data = $client->systemHooks()->create($url);
 
         return static::fromArray($client, $data);
     }
@@ -59,7 +59,7 @@ class Hook extends AbstractModel
      */
     public function test()
     {
-        $this->api('system_hooks')->test($this->id);
+        $this->client->systemHooks()->test($this->id);
 
         return true;
     }
@@ -69,7 +69,7 @@ class Hook extends AbstractModel
      */
     public function delete()
     {
-        $this->api('system_hooks')->remove($this->id);
+        $this->client->systemHooks()->remove($this->id);
 
         return true;
     }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Issue.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Issue.php
index 86c7e2adda5..9ee7c45742c 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Issue.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Issue.php
@@ -50,7 +50,7 @@ class Issue extends AbstractModel implements Noteable
      */
     public static function fromArray(Client $client, Project $project, array $data)
     {
-        $issue = new static($project, $data['id'], $client);
+        $issue = new static($project, $data['iid'], $client);
 
         if (isset($data['author'])) {
             $data['author'] = User::fromArray($client, $data['author']);
@@ -65,14 +65,14 @@ class Issue extends AbstractModel implements Noteable
 
     /**
      * @param Project $project
-     * @param int $id
+     * @param int $iid
      * @param Client $client
      */
-    public function __construct(Project $project, $id = null, Client $client = null)
+    public function __construct(Project $project, $iid = null, Client $client = null)
     {
         $this->setClient($client);
         $this->setData('project', $project);
-        $this->setData('id', $id);
+        $this->setData('iid', $iid);
     }
 
     /**
@@ -80,7 +80,7 @@ class Issue extends AbstractModel implements Noteable
      */
     public function show()
     {
-        $data = $this->api('issues')->show($this->project->id, $this->id);
+        $data = $this->client->issues()->show($this->project->id, $this->iid);
 
         return static::fromArray($this->getClient(), $this->project, $data);
     }
@@ -91,7 +91,7 @@ class Issue extends AbstractModel implements Noteable
      */
     public function update(array $params)
     {
-        $data = $this->api('issues')->update($this->project->id, $this->id, $params);
+        $data = $this->client->issues()->update($this->project->id, $this->iid, $params);
 
         return static::fromArray($this->getClient(), $this->project, $data);
     }
@@ -135,7 +135,7 @@ class Issue extends AbstractModel implements Noteable
      */
     public function addComment($comment)
     {
-        $data = $this->api('issues')->addComment($this->project->id, $this->id, array(
+        $data = $this->client->issues()->addComment($this->project->id, $this->iid, array(
             'body' => $comment
         ));
 
@@ -148,7 +148,7 @@ class Issue extends AbstractModel implements Noteable
     public function showComments()
     {
         $notes = array();
-        $data = $this->api('issues')->showComments($this->project->id, $this->id);
+        $data = $this->client->issues()->showComments($this->project->id, $this->iid);
 
         foreach ($data as $note) {
             $notes[] = Note::fromArray($this->getClient(), $this, $note);
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Job.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Job.php
new file mode 100644
index 00000000000..586e3a31185
--- /dev/null
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Job.php
@@ -0,0 +1,83 @@
+<?php namespace Gitlab\Model;
+
+use Gitlab\Client;
+
+/**
+ * Class Commit
+ *
+ * @property-read Commit $commit
+ * @property-read int $id
+ * @property-read string $coverage
+ * @property-read string $created_at
+ * @property-read string $artifacts_file
+ * @property-read string $finished_at
+ * @property-read string $name
+ * @property-read Pipeline $pipeline
+ * @property-read string $ref
+ * @property-read string $runner
+ * @property-read string $stage
+ * @property-read string $started_at
+ * @property-read string $status
+ * @property-read string|bool $tag
+ * @property-read User $user
+ */
+class Job extends AbstractModel
+{
+    /**
+     * @var array
+     */
+    protected static $properties = array(
+        'id',
+        'commit',
+        'coverage',
+        'created_at',
+        'artifacts_file',
+        'finished_at',
+        'name',
+        'pipeline',
+        'ref',
+        'runner',
+        'stage',
+        'started_at',
+        'status',
+        'tag',
+        'user'
+    );
+
+    /**
+     * @param Client  $client
+     * @param Project $project
+     * @param array   $data
+     * @return Job
+     */
+    public static function fromArray(Client $client, Project $project, array $data)
+    {
+        $job = new static($project, $data['id'], $client);
+
+        if (isset($data['user'])) {
+            $data['user'] = User::fromArray($client, $data['user']);
+        }
+
+        if (isset($data['commit'])) {
+            $data['commit'] = Commit::fromArray($client, $project, $data['commit']);
+        }
+
+        if (isset($data['pipeline'])) {
+            $data['pipeline'] = Pipeline::fromArray($client, $project, $data['pipeline']);
+        }
+
+        return $job->hydrate($data);
+    }
+
+    /**
+     * @param Project $project
+     * @param int $id
+     * @param Client  $client
+     */
+    public function __construct(Project $project, $id = null, Client $client = null)
+    {
+        $this->setClient($client);
+        $this->setData('project', $project);
+        $this->setData('id', $id);
+    }
+}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/MergeRequest.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/MergeRequest.php
index 686b47a7d29..03251f3b01d 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/MergeRequest.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/MergeRequest.php
@@ -90,14 +90,14 @@ class MergeRequest extends AbstractModel implements Noteable
 
     /**
      * @param Project $project
-     * @param int $id
+     * @param int $iid
      * @param Client $client
      */
-    public function __construct(Project $project, $id = null, Client $client = null)
+    public function __construct(Project $project, $iid = null, Client $client = null)
     {
         $this->setClient($client);
         $this->setData('project', $project);
-        $this->setData('id', $id);
+        $this->setData('iid', $iid);
     }
 
     /**
@@ -105,7 +105,7 @@ class MergeRequest extends AbstractModel implements Noteable
      */
     public function show()
     {
-        $data = $this->api('mr')->show($this->project->id, $this->id);
+        $data = $this->client->mergeRequests()->show($this->project->id, $this->iid);
 
         return static::fromArray($this->getClient(), $this->project, $data);
     }
@@ -116,7 +116,7 @@ class MergeRequest extends AbstractModel implements Noteable
      */
     public function update(array $params)
     {
-        $data = $this->api('mr')->update($this->project->id, $this->id, $params);
+        $data = $this->client->mergeRequests()->update($this->project->id, $this->iid, $params);
 
         return static::fromArray($this->getClient(), $this->project, $data);
     }
@@ -160,7 +160,7 @@ class MergeRequest extends AbstractModel implements Noteable
      */
     public function merge($message = null)
     {
-        $data = $this->api('mr')->merge($this->project->id, $this->id, array(
+        $data = $this->client->mergeRequests()->merge($this->project->id, $this->iid, array(
             'merge_commit_message' => $message
         ));
 
@@ -183,7 +183,7 @@ class MergeRequest extends AbstractModel implements Noteable
      */
     public function addComment($comment)
     {
-        $data = $this->api('mr')->addComment($this->project->id, $this->id, $comment);
+        $data = $this->client->mergeRequests()->addComment($this->project->id, $this->iid, $comment);
 
         return Note::fromArray($this->getClient(), $this, $data);
     }
@@ -194,7 +194,7 @@ class MergeRequest extends AbstractModel implements Noteable
     public function showComments()
     {
         $notes = array();
-        $data = $this->api('mr')->showComments($this->project->id, $this->id);
+        $data = $this->client->mergeRequests()->showComments($this->project->id, $this->iid);
 
         foreach ($data as $note) {
             $notes[] = Note::fromArray($this->getClient(), $this, $note);
@@ -220,7 +220,7 @@ class MergeRequest extends AbstractModel implements Noteable
      */
     public function changes()
     {
-        $data = $this->api('mr')->changes($this->project->id, $this->id);
+        $data = $this->client->mergeRequests()->changes($this->project->id, $this->iid);
 
         return static::fromArray($this->getClient(), $this->project, $data);
     }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Milestone.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Milestone.php
index c59afca38bf..8b07d38af8a 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Milestone.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Milestone.php
@@ -11,6 +11,7 @@ use Gitlab\Client;
  * @property-read string $title
  * @property-read string $description
  * @property-read string $due_date
+ * @property-read string $start_date
  * @property-read string $state
  * @property-read bool $closed
  * @property-read string $updated_at
@@ -30,6 +31,7 @@ class Milestone extends AbstractModel
         'title',
         'description',
         'due_date',
+        'start_date',
         'state',
         'closed',
         'updated_at',
@@ -66,7 +68,7 @@ class Milestone extends AbstractModel
      */
     public function show()
     {
-        $data = $this->api('milestones')->show($this->project->id, $this->id);
+        $data = $this->client->milestones()->show($this->project->id, $this->id);
 
         return static::fromArray($this->getClient(), $this->project, $data);
     }
@@ -77,7 +79,7 @@ class Milestone extends AbstractModel
      */
     public function update(array $params)
     {
-        $data = $this->api('milestones')->update($this->project->id, $this->id, $params);
+        $data = $this->client->milestones()->update($this->project->id, $this->id, $params);
 
         return static::fromArray($this->getClient(), $this->project, $data);
     }
@@ -103,7 +105,7 @@ class Milestone extends AbstractModel
      */
     public function issues()
     {
-        $data = $this->api('milestones')->issues($this->project->id, $this->id);
+        $data = $this->client->milestones()->issues($this->project->id, $this->id);
 
         $issues = array();
         foreach ($data as $issue) {
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Pipeline.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Pipeline.php
new file mode 100644
index 00000000000..efeccbc9879
--- /dev/null
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Pipeline.php
@@ -0,0 +1,49 @@
+<?php namespace Gitlab\Model;
+
+use Gitlab\Client;
+
+/**
+ * Class Commit
+ *
+ * @property-read int $id
+ * @property-read string $ref
+ * @property-read string $sha
+ * @property-read string $status
+ */
+class Pipeline extends AbstractModel
+{
+    /**
+     * @var array
+     */
+    protected static $properties = array(
+        'id',
+        'ref',
+        'sha',
+        'status'
+    );
+
+    /**
+     * @param Client  $client
+     * @param Project $project
+     * @param array   $data
+     * @return Pipeline
+     */
+    public static function fromArray(Client $client, Project $project, array $data)
+    {
+        $pipeline = new static($project, $data['id'], $client);
+
+        return $pipeline->hydrate($data);
+    }
+
+    /**
+     * @param Project $project
+     * @param int $id
+     * @param Client  $client
+     */
+    public function __construct(Project $project, $id = null, Client $client = null)
+    {
+        $this->setClient($client);
+        $this->setData('project', $project);
+        $this->setData('id', $id);
+    }
+}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Project.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Project.php
index 44fa9a7eed1..399014b7c63 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Project.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Project.php
@@ -1,8 +1,8 @@
 <?php namespace Gitlab\Model;
 
-use Gitlab\Api\MergeRequests;
+use Gitlab\Api\Projects;
+use Gitlab\Api\Repositories;
 use Gitlab\Client;
-use Gitlab\Api\AbstractApi as Api;
 
 /**
  * Class Project
@@ -29,6 +29,7 @@ use Gitlab\Api\AbstractApi as Api;
  * @property-read int $greatest_access_level
  * @property-read string $last_activity_at
  * @property-read string $tag_list
+ * @property-read string $avatar_url
  * @property-read User $owner
  * @property-read ProjectNamespace $namespace
  */
@@ -61,7 +62,8 @@ class Project extends AbstractModel
         'greatest_access_level',
         'last_activity_at',
         'snippets_enabled',
-        'tag_list'
+        'tag_list',
+        'avatar_url'
     );
 
     /**
@@ -93,7 +95,7 @@ class Project extends AbstractModel
      */
     public static function create(Client $client, $name, array $params = array())
     {
-        $data = $client->api('projects')->create($name, $params);
+        $data = $client->projects()->create($name, $params);
 
         return static::fromArray($client, $data);
     }
@@ -107,7 +109,7 @@ class Project extends AbstractModel
      */
     public static function createForUser($user_id, Client $client, $name, array $params = array())
     {
-        $data = $client->api('projects')->createForUser($user_id, $name, $params);
+        $data = $client->projects()->createForUser($user_id, $name, $params);
 
         return static::fromArray($client, $data);
     }
@@ -126,7 +128,7 @@ class Project extends AbstractModel
      */
     public function show()
     {
-        $data = $this->api('projects')->show($this->id);
+        $data = $this->client->projects()->show($this->id);
 
         return static::fromArray($this->getClient(), $data);
     }
@@ -137,7 +139,7 @@ class Project extends AbstractModel
      */
     public function update(array $params)
     {
-        $data = $this->api('projects')->update($this->id, $params);
+        $data = $this->client->projects()->update($this->id, $params);
 
         return static::fromArray($this->getClient(), $data);
     }
@@ -147,7 +149,7 @@ class Project extends AbstractModel
      */
     public function archive()
     {
-        $data = $this->api("projects")->archive($this->id);
+        $data = $this->client->projects()->archive($this->id);
 
         return static::fromArray($this->getClient(), $data);
     }
@@ -157,7 +159,7 @@ class Project extends AbstractModel
      */
     public function unarchive()
     {
-        $data = $this->api("projects")->unarchive($this->id);
+        $data = $this->client->projects()->unarchive($this->id);
 
         return static::fromArray($this->getClient(), $data);
     }
@@ -167,7 +169,7 @@ class Project extends AbstractModel
      */
     public function remove()
     {
-        $this->api('projects')->remove($this->id);
+        $this->client->projects()->remove($this->id);
 
         return true;
     }
@@ -178,7 +180,7 @@ class Project extends AbstractModel
      */
     public function members($username_query = null)
     {
-        $data = $this->api('projects')->members($this->id, $username_query);
+        $data = $this->client->projects()->members($this->id, $username_query);
 
         $members = array();
         foreach ($data as $member) {
@@ -194,7 +196,7 @@ class Project extends AbstractModel
      */
     public function member($user_id)
     {
-        $data = $this->api('projects')->member($this->id, $user_id);
+        $data = $this->client->projects()->member($this->id, $user_id);
 
         return User::fromArray($this->getClient(), $data);
     }
@@ -206,7 +208,7 @@ class Project extends AbstractModel
      */
     public function addMember($user_id, $access_level)
     {
-        $data = $this->api('projects')->addMember($this->id, $user_id, $access_level);
+        $data = $this->client->projects()->addMember($this->id, $user_id, $access_level);
 
         return User::fromArray($this->getClient(), $data);
     }
@@ -218,7 +220,7 @@ class Project extends AbstractModel
      */
     public function saveMember($user_id, $access_level)
     {
-        $data = $this->api('projects')->saveMember($this->id, $user_id, $access_level);
+        $data = $this->client->projects()->saveMember($this->id, $user_id, $access_level);
 
         return User::fromArray($this->getClient(), $data);
     }
@@ -229,19 +231,21 @@ class Project extends AbstractModel
      */
     public function removeMember($user_id)
     {
-        $this->api('projects')->removeMember($this->id, $user_id);
+        $this->client->projects()->removeMember($this->id, $user_id);
 
         return true;
     }
 
     /**
-     * @param int $page
-     * @param int $per_page
+     * @param array $parameters
+     *
+     * @see Projects::hooks() for available parameters.
+     *
      * @return ProjectHook[]
      */
-    public function hooks($page = 1, $per_page = Api::PER_PAGE)
+    public function hooks(array $parameters = [])
     {
-        $data = $this->api('projects')->hooks($this->id, $page, $per_page);
+        $data = $this->client->projects()->hooks($this->id, $parameters);
 
         $hooks = array();
         foreach ($data as $hook) {
@@ -269,7 +273,7 @@ class Project extends AbstractModel
      */
     public function addHook($url, array $events = array())
     {
-        $data = $this->api('projects')->addHook($this->id, $url, $events);
+        $data = $this->client->projects()->addHook($this->id, $url, $events);
 
         return ProjectHook::fromArray($this->getClient(), $this, $data);
     }
@@ -300,9 +304,9 @@ class Project extends AbstractModel
     /**
      * @return Key[]
      */
-    public function keys()
+    public function deployKeys()
     {
-        $data = $this->api('projects')->keys($this->id);
+        $data = $this->client->projects()->deployKeys($this->id);
 
         $keys = array();
         foreach ($data as $key) {
@@ -316,9 +320,9 @@ class Project extends AbstractModel
      * @param int $key_id
      * @return Key
      */
-    public function key($key_id)
+    public function deployKey($key_id)
     {
-        $data = $this->api('projects')->key($this->id, $key_id);
+        $data = $this->client->projects()->deployKey($this->id, $key_id);
 
         return Key::fromArray($this->getClient(), $data);
     }
@@ -326,11 +330,12 @@ class Project extends AbstractModel
     /**
      * @param string $title
      * @param string $key
+     * @param bool $canPush
      * @return Key
      */
-    public function addKey($title, $key)
+    public function addDeployKey($title, $key, $canPush = false)
     {
-        $data = $this->api('projects')->addKey($this->id, $title, $key);
+        $data = $this->client->projects()->addDeployKey($this->id, $title, $key, $canPush);
 
         return Key::fromArray($this->getClient(), $data);
     }
@@ -339,9 +344,9 @@ class Project extends AbstractModel
      * @param string $key_id
      * @return bool
      */
-    public function removeKey($key_id)
+    public function deleteDeployKey($key_id)
     {
-        $this->api('projects')->removeKey($this->id, $key_id);
+        $this->client->projects()->deleteDeployKey($this->id, $key_id);
 
         return true;
     }
@@ -350,20 +355,9 @@ class Project extends AbstractModel
      * @param string $key_id
      * @return bool
      */
-    public function enableKey($key_id)
+    public function enableDeployKey($key_id)
     {
-        $this->api('projects')->enableKey($this->id, $key_id);
-
-        return true;
-    }
-
-    /**
-     * @param string $key_id
-     * @return bool
-     */
-    public function disableKey($key_id)
-    {
-        $this->api('projects')->disableKey($this->id, $key_id);
+        $this->client->projects()->enableDeployKey($this->id, $key_id);
 
         return true;
     }
@@ -375,7 +369,7 @@ class Project extends AbstractModel
      */
     public function createBranch($name, $ref)
     {
-        $data = $this->api('repositories')->createBranch($this->id, $name, $ref);
+        $data = $this->client->repositories()->createBranch($this->id, $name, $ref);
 
         return Branch::fromArray($this->getClient(), $this, $data);
     }
@@ -386,7 +380,7 @@ class Project extends AbstractModel
      */
     public function deleteBranch($name)
     {
-        $this->api('repositories')->deleteBranch($this->id, $name);
+        $this->client->repositories()->deleteBranch($this->id, $name);
 
         return true;
     }
@@ -396,7 +390,7 @@ class Project extends AbstractModel
      */
     public function branches()
     {
-        $data = $this->api('repo')->branches($this->id);
+        $data = $this->client->repositories()->branches($this->id);
 
         $branches = array();
         foreach ($data as $branch) {
@@ -449,7 +443,7 @@ class Project extends AbstractModel
      */
     public function tags()
     {
-        $data = $this->api('repo')->tags($this->id);
+        $data = $this->client->repositories()->tags($this->id);
 
         $tags = array();
         foreach ($data as $tag) {
@@ -460,14 +454,15 @@ class Project extends AbstractModel
     }
 
     /**
-     * @param int $page
-     * @param int $per_page
-     * @param string $ref_name
+     * @param array $parameters
+     *
+     * @see Repositories::commits() for available parameters.
+     *
      * @return Commit[]
      */
-    public function commits($page = 0, $per_page = Api::PER_PAGE, $ref_name = null)
+    public function commits(array $parameters = [])
     {
-        $data = $this->api('repo')->commits($this->id, $page, $per_page, $ref_name);
+        $data = $this->client->repositories()->commits($this->id, $parameters);
 
         $commits = array();
         foreach ($data as $commit) {
@@ -483,20 +478,22 @@ class Project extends AbstractModel
      */
     public function commit($sha)
     {
-        $data = $this->api('repo')->commit($this->id, $sha);
+        $data = $this->client->repositories()->commit($this->id, $sha);
 
         return Commit::fromArray($this->getClient(), $this, $data);
     }
 
     /**
      * @param string $ref
-     * @param int $page
-     * @param int $per_page
+     * @param array $parameters
+     *
+     * @see Repositories::commitComments() for available parameters.
+     *
      * @return Commit[]
      */
-    public function commitComments($ref, $page = 0, $per_page = Api::PER_PAGE)
+    public function commitComments($ref, array $parameters = [])
     {
-        $data = $this->api('repo')->commitComments($this->id, $ref, $page, $per_page);
+        $data = $this->client->repositories()->commitComments($this->id, $ref, $parameters);
 
         $comments = array();
         foreach ($data as $comment) {
@@ -514,7 +511,7 @@ class Project extends AbstractModel
      */
     public function createCommitComment($ref, $note, array $params = array())
     {
-        $data = $this->api('repo')->createCommitComment($this->id, $ref, $note, $params);
+        $data = $this->client->repositories()->createCommitComment($this->id, $ref, $note, $params);
 
         return CommitNote::fromArray($this->getClient(), $data);
     }
@@ -525,7 +522,7 @@ class Project extends AbstractModel
      */
     public function diff($sha)
     {
-        return $this->api('repo')->diff($this->id, $sha);
+        return $this->client->repositories()->diff($this->id, $sha);
     }
 
     /**
@@ -535,7 +532,7 @@ class Project extends AbstractModel
      */
     public function compare($from, $to)
     {
-        $data = $this->api('repo')->compare($this->id, $from, $to);
+        $data = $this->client->repositories()->compare($this->id, $from, $to);
 
         return Comparison::fromArray($this->getClient(), $this, $data);
     }
@@ -546,7 +543,7 @@ class Project extends AbstractModel
      */
     public function tree(array $params = array())
     {
-        $data = $this->api('repo')->tree($this->id, $params);
+        $data = $this->client->repositories()->tree($this->id, $params);
 
         $tree = array();
         foreach ($data as $node) {
@@ -563,7 +560,7 @@ class Project extends AbstractModel
      */
     public function blob($sha, $filepath)
     {
-        return $this->api('repo')->blob($this->id, $sha, $filepath);
+        return $this->client->repositories()->blob($this->id, $sha, $filepath);
     }
 
     /**
@@ -574,7 +571,7 @@ class Project extends AbstractModel
      */
     public function getFile($sha, $filepath)
     {
-        return $this->api('repo')->getFile($this->id, $filepath, $sha);
+        return $this->client->repositories()->getFile($this->id, $filepath, $sha);
     }
 
     /**
@@ -588,7 +585,22 @@ class Project extends AbstractModel
      */
     public function createFile($file_path, $content, $branch_name, $commit_message, $author_email = null, $author_name = null)
     {
-        $data = $this->api('repo')->createFile($this->id, $file_path, $content, $branch_name, $commit_message, null, $author_email, $author_name);
+        $parameters = [
+            'file_path' => $file_path,
+            'branch' => $branch_name,
+            'content' => $content,
+            'commit_message' => $commit_message,
+        ];
+
+        if ($author_email !== null) {
+            $parameters['author_email'] = $author_email;
+        }
+
+        if ($author_name !== null) {
+            $parameters['author_name'] = $author_name;
+        }
+
+        $data = $this->client->repositoryFiles()->createFile($this->id, $parameters);
 
         return File::fromArray($this->getClient(), $this, $data);
     }
@@ -604,7 +616,22 @@ class Project extends AbstractModel
      */
     public function updateFile($file_path, $content, $branch_name, $commit_message, $author_email = null, $author_name = null)
     {
-        $data = $this->api('repo')->updateFile($this->id, $file_path, $content, $branch_name, $commit_message, null, $author_email, $author_name);
+        $parameters = [
+            'file_path' => $file_path,
+            'branch' => $branch_name,
+            'content' => $content,
+            'commit_message' => $commit_message,
+        ];
+
+        if ($author_email !== null) {
+            $parameters['author_email'] = $author_email;
+        }
+
+        if ($author_name !== null) {
+            $parameters['author_name'] = $author_name;
+        }
+
+        $data = $this->client->repositoryFiles()->updateFile($this->id, $parameters);
 
         return File::fromArray($this->getClient(), $this, $data);
     }
@@ -619,19 +646,35 @@ class Project extends AbstractModel
      */
     public function deleteFile($file_path, $branch_name, $commit_message, $author_email = null, $author_name = null)
     {
-        $this->api('repo')->deleteFile($this->id, $file_path, $branch_name, $commit_message, $author_email, $author_name);
+        $parameters = [
+            'file_path' => $file_path,
+            'branch' => $branch_name,
+            'commit_message' => $commit_message,
+        ];
+
+        if ($author_email !== null) {
+            $parameters['author_email'] = $author_email;
+        }
+
+        if ($author_name !== null) {
+            $parameters['author_name'] = $author_name;
+        }
+
+        $this->client->repositoryFiles()->deleteFile($this->id, $parameters);
 
         return true;
     }
 
     /**
-     * @param int $page
-     * @param int $per_page
+     * @param array $parameters
+     *
+     * @see Projects::events() for available parameters.
+     *
      * @return Event[]
      */
-    public function events($page = 1, $per_page = Api::PER_PAGE)
+    public function events(array $parameters = [])
     {
-        $data = $this->api('projects')->events($this->id, $page, $per_page);
+        $data = $this->client->projects()->events($this->id, $parameters);
 
         $events = array();
         foreach ($data as $event) {
@@ -642,14 +685,15 @@ class Project extends AbstractModel
     }
 
     /**
-     * @param int    $page
-     * @param int    $per_page
-     * @param string $state
+     * @param array $parameters
+     *
+     * @see MergeRequests::all() for available parameters.
+     *
      * @return MergeRequest[]
      */
-    public function mergeRequests($page = 1, $per_page = Api::PER_PAGE, $state = MergeRequests::STATE_ALL)
+    public function mergeRequests(array $parameters = [])
     {
-        $data = $this->api('mr')->$state($this->id, $page, $per_page);
+        $data = $this->client->mergeRequests()->all($this->id, $parameters);
 
         $mrs = array();
         foreach ($data as $mr) {
@@ -680,7 +724,7 @@ class Project extends AbstractModel
      */
     public function createMergeRequest($source, $target, $title, $assignee = null, $description = null)
     {
-        $data = $this->api('mr')->create($this->id, $source, $target, $title, $assignee, null, $description);
+        $data = $this->client->mergeRequests()->create($this->id, $source, $target, $title, $assignee, $this->id, $description);
 
         return MergeRequest::fromArray($this->getClient(), $this, $data);
     }
@@ -731,13 +775,15 @@ class Project extends AbstractModel
     }
 
     /**
-     * @param int $page
-     * @param int $per_page
+     * @param array $parameters
+     *
+     * @see Issues::all() for available parameters.
+     *
      * @return Issue[]
      */
-    public function issues($page = 1, $per_page = Api::PER_PAGE)
+    public function issues(array $parameters = [])
     {
-        $data = $this->api('issues')->all($this->id, $page, $per_page);
+        $data = $this->client->issues()->all($this->id, $parameters);
 
         $issues = array();
         foreach ($data as $issue) {
@@ -755,65 +801,67 @@ class Project extends AbstractModel
     public function createIssue($title, array $params = array())
     {
         $params['title'] = $title;
-        $data = $this->api('issues')->create($this->id, $params);
+        $data = $this->client->issues()->create($this->id, $params);
 
         return Issue::fromArray($this->getClient(), $this, $data);
     }
 
     /**
-     * @param int $id
+     * @param int $iid
      * @return Issue
      */
-    public function issue($id)
+    public function issue($iid)
     {
-        $issue = new Issue($this, $id, $this->getClient());
+        $issue = new Issue($this, $iid, $this->getClient());
 
         return $issue->show();
     }
 
     /**
-     * @param int $id
+     * @param int $iid
      * @param array $params
      * @return Issue
      */
-    public function updateIssue($id, array $params)
+    public function updateIssue($iid, array $params)
     {
-        $issue = new Issue($this, $id, $this->getClient());
+        $issue = new Issue($this, $iid, $this->getClient());
 
         return $issue->update($params);
     }
 
     /**
-     * @param int $id
+     * @param int $iid
      * @param string $comment
      * @return Issue
      */
-    public function closeIssue($id, $comment = null)
+    public function closeIssue($iid, $comment = null)
     {
-        $issue = new Issue($this, $id, $this->getClient());
+        $issue = new Issue($this, $iid, $this->getClient());
 
         return $issue->close($comment);
     }
 
     /**
-     * @param int $id
+     * @param int $iid
      * @return Issue
      */
-    public function openIssue($id)
+    public function openIssue($iid)
     {
-        $issue = new Issue($this, $id, $this->getClient());
+        $issue = new Issue($this, $iid, $this->getClient());
 
         return $issue->open();
     }
 
     /**
-     * @param int $page
-     * @param int $per_page
+     * @param array $parameters
+     *
+     * @see Milestones::all() for available parameters.
+     *
      * @return Milestone[]
      */
-    public function milestones($page = 1, $per_page = Api::PER_PAGE)
+    public function milestones(array $parameters = [])
     {
-        $data = $this->api('milestones')->all($this->id, $page, $per_page);
+        $data = $this->client->milestones()->all($this->id, $parameters);
 
         $milestones = array();
         foreach ($data as $milestone) {
@@ -831,7 +879,7 @@ class Project extends AbstractModel
     public function createMilestone($title, array $params = array())
     {
         $params['title'] = $title;
-        $data = $this->api('milestones')->create($this->id, $params);
+        $data = $this->client->milestones()->create($this->id, $params);
 
         return Milestone::fromArray($this->getClient(), $this, $data);
     }
@@ -875,7 +923,7 @@ class Project extends AbstractModel
      */
     public function snippets()
     {
-        $data = $this->api('snippets')->all($this->id);
+        $data = $this->client->snippets()->all($this->id);
 
         $snippets = array();
         foreach ($data as $snippet) {
@@ -889,12 +937,11 @@ class Project extends AbstractModel
      * @param string $title
      * @param string $filename
      * @param string $code
-     * @param string $lifetime
      * @return Snippet
      */
-    public function createSnippet($title, $filename, $code, $lifetime = null)
+    public function createSnippet($title, $filename, $code)
     {
-        $data = $this->api('snippets')->create($this->id, $title, $filename, $code, $lifetime);
+        $data = $this->client->snippets()->create($this->id, $title, $filename, $code);
 
         return Snippet::fromArray($this->getClient(), $this, $data);
     }
@@ -912,7 +959,7 @@ class Project extends AbstractModel
 
     /**
      * @param int $id
-     * @return Snippet
+     * @return string
      */
     public function snippetContent($id)
     {
@@ -961,7 +1008,7 @@ class Project extends AbstractModel
      */
     public function forkTo($id)
     {
-        $data = $this->api('projects')->createForkRelation($id, $this->id);
+        $data = $this->client->projects()->createForkRelation($id, $this->id);
 
         return Project::fromArray($this->getClient(), $data);
     }
@@ -981,7 +1028,7 @@ class Project extends AbstractModel
      */
     public function createForkRelation($id)
     {
-        $data = $this->api('projects')->createForkRelation($this->id, $id);
+        $data = $this->client->projects()->createForkRelation($this->id, $id);
 
         return Project::fromArray($this->getClient(), $data);
     }
@@ -991,7 +1038,7 @@ class Project extends AbstractModel
      */
     public function removeForkRelation()
     {
-        $this->api('projects')->removeForkRelation($this->id);
+        $this->client->projects()->removeForkRelation($this->id);
 
         return true;
     }
@@ -1003,7 +1050,7 @@ class Project extends AbstractModel
      */
     public function setService($service_name, array $params = array())
     {
-        $this->api('projects')->setService($this->id, $service_name, $params);
+        $this->client->projects()->setService($this->id, $service_name, $params);
 
         return true;
     }
@@ -1014,7 +1061,7 @@ class Project extends AbstractModel
      */
     public function removeService($service_name)
     {
-        $this->api('projects')->removeService($this->id, $service_name);
+        $this->client->projects()->removeService($this->id, $service_name);
 
         return true;
     }
@@ -1024,7 +1071,7 @@ class Project extends AbstractModel
      */
     public function labels()
     {
-        $data = $this->api('projects')->labels($this->id);
+        $data = $this->client->projects()->labels($this->id);
 
         $labels = array();
         foreach ($data as $label) {
@@ -1041,7 +1088,7 @@ class Project extends AbstractModel
      */
     public function addLabel($name, $color)
     {
-        $data = $this->api('projects')->addLabel($this->id, array(
+        $data = $this->client->projects()->addLabel($this->id, array(
             'name' => $name,
             'color' => $color
         ));
@@ -1062,7 +1109,7 @@ class Project extends AbstractModel
 
         $params['name'] = $name;
 
-        $data = $this->api('projects')->updateLabel($this->id, $params);
+        $data = $this->client->projects()->updateLabel($this->id, $params);
 
         return Label::fromArray($this->getClient(), $this, $data);
     }
@@ -1073,7 +1120,7 @@ class Project extends AbstractModel
      */
     public function removeLabel($name)
     {
-        $this->api('projects')->removeLabel($this->id, $name);
+        $this->client->projects()->removeLabel($this->id, $name);
 
         return true;
     }
@@ -1083,7 +1130,7 @@ class Project extends AbstractModel
      */
     public function contributors()
     {
-        $data = $this->api('repo')->contributors($this->id);
+        $data = $this->client->repositories()->contributors($this->id);
 
         $contributors = array();
         foreach ($data as $contributor) {
@@ -1092,4 +1139,48 @@ class Project extends AbstractModel
 
         return $contributors;
     }
+
+    /**
+     * @param array $scopes
+     * @return Job[]
+     */
+    public function jobs(array $scopes = [])
+    {
+        $data = $this->client->jobs()->all($this->id, $scopes);
+
+        $jobs = array();
+        foreach ($data as $job) {
+            $jobs[] = Job::fromArray($this->getClient(), $this, $job);
+        }
+
+        return $jobs;
+    }
+
+    /**
+     * @param int $pipeline_id
+     * @param array $scopes
+     * @return Job[]
+     */
+    public function pipelineJobs($pipeline_id, array $scopes = [])
+    {
+        $data = $this->client->jobs()->pipelineJobs($this->id, $pipeline_id, $scopes);
+
+        $jobs = array();
+        foreach ($data as $job) {
+            $jobs[] = Job::fromArray($this->getClient(), $this, $job);
+        }
+
+        return $jobs;
+    }
+
+    /**
+     * @param int $job_id
+     * @return Job
+     */
+    public function job($job_id)
+    {
+        $data = $this->client->jobs()->show($this->id, $job_id);
+
+        return Job::fromArray($this->getClient(), $this, $data);
+    }
 }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/ProjectHook.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/ProjectHook.php
index 3da0a7c02ba..1789ca68bbc 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/ProjectHook.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/ProjectHook.php
@@ -11,8 +11,9 @@ use Gitlab\Client;
  * @property-read bool $push_events
  * @property-read bool $issues_events
  * @property-read bool $merge_requests_events
- * @property-read bool $build_events
+ * @property-read bool $job_events
  * @property-read bool $tag_push_events
+ * @property-read bool $pipeline_events
  * @property-read string $created_at
  * @property-read Project $project
  */
@@ -29,8 +30,9 @@ class ProjectHook extends AbstractModel
         'push_events',
         'issues_events',
         'merge_requests_events',
-        'build_events',
+        'job_events',
         'tag_push_events',
+        'pipeline_events',
         'created_at'
     );
 
@@ -64,7 +66,7 @@ class ProjectHook extends AbstractModel
      */
     public function show()
     {
-        $data = $this->api('projects')->hook($this->project->id, $this->id);
+        $data = $this->client->projects()->hook($this->project->id, $this->id);
 
         return static::fromArray($this->getClient(), $this->project, $data);
     }
@@ -74,7 +76,7 @@ class ProjectHook extends AbstractModel
      */
     public function delete()
     {
-        $this->api('projects')->removeHook($this->project->id, $this->id);
+        $this->client->projects()->removeHook($this->project->id, $this->id);
 
         return true;
     }
@@ -93,7 +95,7 @@ class ProjectHook extends AbstractModel
      */
     public function update(array $params)
     {
-        $data = $this->api('projects')->updateHook($this->project->id, $this->id, $params);
+        $data = $this->client->projects()->updateHook($this->project->id, $this->id, $params);
 
         return static::fromArray($this->getClient(), $this->project, $data);
     }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Session.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Session.php
index f9b8177beff..7cf4cfe79c4 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Session.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Session.php
@@ -51,7 +51,7 @@ class Session extends AbstractModel
      */
     public function me()
     {
-        $data = $this->api('users')->show();
+        $data = $this->client->users()->user();
 
         return User::fromArray($this->getClient(), $data);
     }
@@ -59,11 +59,11 @@ class Session extends AbstractModel
     /**
      * @param string $email
      * @param string $password
-     * @return $this
+     * @return Session
      */
     public function login($email, $password)
     {
-        $data = $this->api('users')->session($email, $password);
+        $data = $this->client->users()->session($email, $password);
 
         return $this->hydrate($data);
     }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Snippet.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Snippet.php
index 5d20e0dbf72..1f021bcb4f8 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Snippet.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/Snippet.php
@@ -8,7 +8,6 @@ use Gitlab\Client;
  * @property-read int $id
  * @property-read string $title
  * @property-read string $file_name
- * @property-read string $expires_at
  * @property-read string $updated_at
  * @property-read string $created_at
  * @property-read Project $project
@@ -24,7 +23,6 @@ class Snippet extends AbstractModel
         'title',
         'file_name',
         'author',
-        'expires_at',
         'updated_at',
         'created_at',
         'project'
@@ -64,7 +62,7 @@ class Snippet extends AbstractModel
      */
     public function show()
     {
-        $data = $this->api('snippets')->show($this->project->id, $this->id);
+        $data = $this->client->snippets()->show($this->project->id, $this->id);
 
         return static::fromArray($this->getClient(), $this->project, $data);
     }
@@ -75,7 +73,7 @@ class Snippet extends AbstractModel
      */
     public function update(array $params)
     {
-        $data = $this->api('snippets')->update($this->project->id, $this->id, $params);
+        $data = $this->client->snippets()->update($this->project->id, $this->id, $params);
 
         return static::fromArray($this->getClient(), $this->project, $data);
     }
@@ -85,7 +83,7 @@ class Snippet extends AbstractModel
      */
     public function content()
     {
-        return $this->api('snippets')->content($this->project->id, $this->id);
+        return $this->client->snippets()->content($this->project->id, $this->id);
     }
 
     /**
@@ -93,7 +91,7 @@ class Snippet extends AbstractModel
      */
     public function remove()
     {
-        $this->api('snippets')->remove($this->project->id, $this->id);
+        $this->client->snippets()->remove($this->project->id, $this->id);
 
         return true;
     }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/User.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/User.php
index 5ffffc16e26..ef654756df4 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/User.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/Model/User.php
@@ -86,7 +86,7 @@ class User extends AbstractModel
      */
     public static function create(Client $client, $email, $password, array $params = array())
     {
-        $data = $client->api('users')->create($email, $password, $params);
+        $data = $client->users()->create($email, $password, $params);
 
         return static::fromArray($client, $data);
     }
@@ -106,7 +106,7 @@ class User extends AbstractModel
      */
     public function show()
     {
-        $data = $this->api('users')->show($this->id);
+        $data = $this->client->users()->show($this->id);
 
         return static::fromArray($this->getClient(), $data);
     }
@@ -117,7 +117,7 @@ class User extends AbstractModel
      */
     public function update(array $params)
     {
-        $data = $this->api('users')->update($this->id, $params);
+        $data = $this->client->users()->update($this->id, $params);
 
         return static::fromArray($this->getClient(), $data);
     }
@@ -127,7 +127,7 @@ class User extends AbstractModel
      */
     public function remove()
     {
-        $this->api('users')->remove($this->id);
+        $this->client->users()->remove($this->id);
 
         return true;
     }
@@ -137,7 +137,7 @@ class User extends AbstractModel
      */
     public function block()
     {
-        $this->api('users')->block($this->id);
+        $this->client->users()->block($this->id);
 
         return true;
     }
@@ -147,7 +147,7 @@ class User extends AbstractModel
      */
     public function unblock()
     {
-        $this->api('users')->unblock($this->id);
+        $this->client->users()->unblock($this->id);
 
         return true;
     }
@@ -157,7 +157,7 @@ class User extends AbstractModel
      */
     public function keys()
     {
-        $data = $this->api('users')->keys();
+        $data = $this->client->users()->keys();
 
         $keys = array();
         foreach ($data as $key) {
@@ -174,7 +174,7 @@ class User extends AbstractModel
      */
     public function createKey($title, $key)
     {
-        $data = $this->api('users')->createKey($title, $key);
+        $data = $this->client->users()->createKey($title, $key);
 
         return Key::fromArray($this->getClient(), $data);
     }
@@ -186,7 +186,7 @@ class User extends AbstractModel
      */
     public function createKeyForUser($user_id, $title, $key)
     {
-        $data = $this->api('users')->createKeyForUser($user_id, $title, $key);
+        $data = $this->client->users()->createKeyForUser($user_id, $title, $key);
 
         return Key::fromArray($this->getClient(), $data);
     }
@@ -197,7 +197,7 @@ class User extends AbstractModel
      */
     public function removeKey($id)
     {
-        $this->api('users')->removeKey($id);
+        $this->client->users()->removeKey($id);
 
         return true;
     }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/ResultPager.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/ResultPager.php
index 3cfb44d1373..b436305b135 100644
--- a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/ResultPager.php
+++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/ResultPager.php
@@ -1,6 +1,7 @@
 <?php namespace Gitlab;
 
 use Gitlab\Api\ApiInterface;
+use Gitlab\HttpClient\Message\ResponseMediator;
 
 /**
  * Pager class for supporting pagination in Gitlab classes
@@ -33,9 +34,7 @@ class ResultPager implements ResultPagerInterface
      */
     public function fetch(ApiInterface $api, $method, array $parameters = array())
     {
-        $result = call_user_func_array(array($api, $method), $parameters);
-
-        return $result;
+        return call_user_func_array(array($api, $method), $parameters);
     }
 
     /**
@@ -44,7 +43,6 @@ class ResultPager implements ResultPagerInterface
     public function fetchAll(ApiInterface $api, $method, array $parameters = array())
     {
         $result = call_user_func_array(array($api, $method), $parameters);
-
         while ($this->hasNext()) {
             $result = array_merge($result, $this->fetchNext());
         }
@@ -105,7 +103,17 @@ class ResultPager implements ResultPagerInterface
      */
     protected function has($key)
     {
-        return !empty($this->client->getHttpClient()->getLastResponse()->getPagination()) && isset($this->client->getHttpClient()->getLastResponse()->getPagination()[$key]);
+        $lastResponse = $this->client->getResponseHistory()->getLastResponse();
+        if ($lastResponse == null) {
+            return false;
+        }
+
+        $pagination = ResponseMediator::getPagination($lastResponse);
+        if ($pagination == null) {
+            return false;
+        }
+
+        return isset($pagination[$key]);
     }
 
     /**
@@ -113,9 +121,12 @@ class ResultPager implements ResultPagerInterface
      */
     protected function get($key)
     {
-        if ($this->has($key)) {
-            $result = $this->client->getHttpClient()->get(strtr($this->client->getHttpClient()->getLastResponse()->getPagination()[$key], array($this->client->getBaseUrl() => '')))->getContent();
-            return $result;
+        if (!$this->has($key)) {
+            return [];
         }
+
+        $pagination = ResponseMediator::getPagination($this->client->getResponseHistory()->getLastResponse());
+
+        return ResponseMediator::getContent($this->client->getHttpClient()->get($pagination[$key]));
     }
 }
diff --git a/vendor/m4tthumphrey/php-gitlab-api/phpunit.xml.dist b/vendor/m4tthumphrey/php-gitlab-api/phpunit.xml.dist
deleted file mode 100644
index e01386f15e1..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/phpunit.xml.dist
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<phpunit backupGlobals="false"
-				 backupStaticAttributes="false"
-				 colors="true"
-				 convertErrorsToExceptions="true"
-				 convertNoticesToExceptions="true"
-				 convertWarningsToExceptions="true"
-				 processIsolation="false"
-				 stopOnFailure="false"
-				 syntaxCheck="false"
-				 bootstrap="test/bootstrap.php"
-	>
-	<testsuites>
-		<testsuite name="php-gitlab-api Test Suite">
-			<directory>./test/Gitlab/</directory>
-		</testsuite>
-	</testsuites>
-
-	<filter>
-		<whitelist>
-			<directory suffix=".php">./lib/Gitlab/</directory>
-		</whitelist>
-	</filter>
-</phpunit>
\ No newline at end of file
diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/AbstractApiTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/AbstractApiTest.php
deleted file mode 100644
index aa1eeaea288..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/AbstractApiTest.php
+++ /dev/null
@@ -1,177 +0,0 @@
-<?php namespace Gitlab\Tests\Api;
-
-use Gitlab\Api\AbstractApi;
-use Gitlab\Client;
-use Gitlab\HttpClient\Message\Response;
-
-class AbstractApiTest extends TestCase
-{
-    /**
-     * @test
-     */
-    public function shouldPassGETRequestToClient()
-    {
-        $response = $this->getResponse('value');
-
-        $httpClient = $this->getHttpMock();
-        $httpClient
-            ->expects($this->any())
-            ->method('get')
-            ->with('/path', array('param1' => 'param1value'), array('header1' => 'header1value'))
-            ->will($this->returnValue($response));
-
-        $client = $this->getClientMock();
-        $client->setHttpClient($httpClient);
-
-        $api = $this->getAbstractApiObject($client);
-        $this->assertEquals('value', $api->get('/path', array('param1' => 'param1value'), array('header1' => 'header1value')));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldPassPOSTRequestToClient()
-    {
-        $response = $this->getResponse('value');
-
-        $httpClient = $this->getHttpMock();
-        $httpClient
-            ->expects($this->any())
-            ->method('post')
-            ->with('/path', array('param1' => 'param1value'), array('header1' => 'header1value'))
-            ->will($this->returnValue($response));
-
-        $client = $this->getClientMock();
-        $client->setHttpClient($httpClient);
-
-        $api = $this->getAbstractApiObject($client);
-        $this->assertEquals('value', $api->post('/path', array('param1' => 'param1value'), array('header1' => 'header1value')));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldPassPUTRequestToClient()
-    {
-        $response = $this->getResponse('value');
-
-        $httpClient = $this->getHttpMock();
-        $httpClient
-            ->expects($this->any())
-            ->method('put')
-            ->with('/path', array('param1' => 'param1value'), array('header1' => 'header1value'))
-            ->will($this->returnValue($response));
-
-        $client = $this->getClientMock();
-        $client->setHttpClient($httpClient);
-
-        $api = $this->getAbstractApiObject($client);
-        $this->assertEquals('value', $api->put('/path', array('param1' => 'param1value'), array('header1' => 'header1value')));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldPassDELETERequestToClient()
-    {
-        $response = $this->getResponse('value');
-
-        $httpClient = $this->getHttpMock();
-        $httpClient
-            ->expects($this->any())
-            ->method('delete')
-            ->with('/path', array('param1' => 'param1value'), array('header1' => 'header1value'))
-            ->will($this->returnValue($response));
-
-        $client = $this->getClientMock();
-        $client->setHttpClient($httpClient);
-
-        $api = $this->getAbstractApiObject($client);
-        $this->assertEquals('value', $api->delete('/path', array('param1' => 'param1value'), array('header1' => 'header1value')));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldPassPATCHRequestToClient()
-    {
-        $response = $this->getResponse('value');
-
-        $httpClient = $this->getHttpMock();
-        $httpClient
-            ->expects($this->any())
-            ->method('patch')
-            ->with('/path', array('param1' => 'param1value'), array('header1' => 'header1value'))
-            ->will($this->returnValue($response));
-
-        $client = $this->getClientMock();
-        $client->setHttpClient($httpClient);
-
-        $api = $this->getAbstractApiObject($client);
-        $this->assertEquals('value', $api->patch('/path', array('param1' => 'param1value'), array('header1' => 'header1value')));
-    }
-
-    /**
-     * @param mixed $value
-     * @return Response
-     */
-    protected function getResponse($value)
-    {
-        $response = new Response();
-        $response->setContent($value);
-
-        return $response;
-    }
-
-    /**
-     * @param Client $client
-     * @return AbstractApiTestInstance
-     */
-    protected function getAbstractApiObject(Client $client)
-    {
-        return new AbstractApiTestInstance($client);
-    }
-}
-
-class AbstractApiTestInstance extends AbstractApi
-{
-    /**
-     * {@inheritDoc}
-     */
-    public function get($path, array $parameters = array(), $requestHeaders = array())
-    {
-        return parent::get($path, $parameters, $requestHeaders);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public function post($path, array $parameters = array(), $requestHeaders = array(), array $files = array())
-    {
-        return parent::post($path, $parameters, $requestHeaders, $files);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public function patch($path, array $parameters = array(), $requestHeaders = array())
-    {
-        return parent::patch($path, $parameters, $requestHeaders);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public function put($path, array $parameters = array(), $requestHeaders = array())
-    {
-        return parent::put($path, $parameters, $requestHeaders);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public function delete($path, array $parameters = array(), $requestHeaders = array())
-    {
-        return parent::delete($path, $parameters, $requestHeaders);
-    }
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/ApiTestCase.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/ApiTestCase.php
deleted file mode 100644
index a695d97cb80..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/ApiTestCase.php
+++ /dev/null
@@ -1,23 +0,0 @@
-<?php namespace Gitlab\Tests\Api;
-
-abstract class ApiTestCase extends TestCase
-{
-    abstract protected function getApiClass();
-
-    /**
-     * @param array $methods
-     * @return \PHPUnit_Framework_MockObject_MockObject|mixed
-     */
-    protected function getApiMock($methods = array())
-    {
-        $client = $this->getClientMock();
-
-        $methods = array_merge(array('get', 'post', 'postRaw', 'patch', 'delete', 'put', 'head'), $methods);
-
-        return $this->getMockBuilder($this->getApiClass())
-            ->setMethods($methods)
-            ->setConstructorArgs(array($client))
-            ->getMock()
-        ;
-    }
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/DeployKeysTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/DeployKeysTest.php
deleted file mode 100644
index a17dd312c3d..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/DeployKeysTest.php
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php namespace Gitlab\Tests\Api;
-
-class DeployKeysTest extends ApiTestCase
-{
-    /**
-     * @test
-     */
-    public function shouldGetAllDeployKeys()
-    {
-        $expectedArray = $this->getMultipleDeployKeysData();
-
-        $api = $this->getMultipleDeployKeysRequestMock('deploy_keys', $expectedArray);
-
-        $this->assertEquals($expectedArray, $api->all());
-    }
-
-    protected function getMultipleDeployKeysRequestMock($path, $expectedArray = array(), $page = 1, $per_page = 20, $order_by = 'id', $sort = 'asc')
-    {
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with($path, array('page' => $page, 'per_page' => $per_page, 'order_by' => $order_by, 'sort' => $sort))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        return $api;
-    }
-
-    protected function getMultipleDeployKeysData()
-    {
-        return array(
-            array(
-                'id' => 1,
-                'title' => 'Public key',
-                'key' => 'ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=',
-                'created_at' => '2013-10-02T10:12:29Z'
-            ),
-            array(
-                'id' => 3,
-                'title' => 'Another Public key',
-                'key' => 'ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=',
-                'created_at' => '2013-10-02T11:12:29Z'
-            )
-        );
-    }
-
-    protected function getApiClass()
-    {
-        return 'Gitlab\Api\DeployKeys';
-    }
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/GroupsTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/GroupsTest.php
deleted file mode 100644
index 20fd1fd58f3..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/GroupsTest.php
+++ /dev/null
@@ -1,264 +0,0 @@
-<?php namespace Gitlab\Tests\Api;
-
-use Gitlab\Api\AbstractApi;
-
-class GroupsTest extends ApiTestCase
-{
-    /**
-     * @test
-     */
-    public function shouldGetAllGroups()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'name' => 'A group'),
-            array('id' => 2, 'name' => 'Another group'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('groups', array('page' => 1, 'per_page' => 10))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->all(1, 10));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldNotNeedPaginationWhenGettingGroups()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'name' => 'A group'),
-            array('id' => 2, 'name' => 'Another group'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('groups', array('page' => 1, 'per_page' => AbstractApi::PER_PAGE))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->all());
-    }
-
-    /**
-     * @test
-     */
-    public function shouldSearchGroups()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'name' => 'A group'),
-            array('id' => 2, 'name' => 'Another group'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('groups?search=some%20group', array('page' => 1, 'per_page' => AbstractApi::PER_PAGE))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->search('some group'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldSearchGroupsWithPagination()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'name' => 'A group'),
-            array('id' => 2, 'name' => 'Another group'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('groups?search=group', array('page' => 2, 'per_page' => 5))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->search('group', 2, 5));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldShowGroup()
-    {
-        $expectedArray = array('id' => 1, 'name' => 'A group');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('groups/1')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->show(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateGroup()
-    {
-        $expectedArray = array('id' => 1, 'name' => 'A new group');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('groups', array('name' => 'A new group', 'path' => 'a-new-group', 'description' => null, 'visibility_level' => 0))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->create('A new group', 'a-new-group'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateGroupWithDescriptionAndVisLevel()
-    {
-        $expectedArray = array('id' => 1, 'name' => 'A new group', 'visibility_level' => 2);
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('groups', array('name' => 'A new group', 'path' => 'a-new-group', 'description' => 'Description', 'visibility_level' => 2))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->create('A new group', 'a-new-group', 'Description', 2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldUpdateGroup()
-    {
-        $expectedArray = array('id' => 3, 'name' => 'Group name', 'path' => 'group-path');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('put')
-            ->with('groups/3', array('name' => 'Group name', 'path' => 'group-path'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->update(3, array('name' => 'Group name', 'path' => 'group-path')));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldTransferProjectToGroup()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('groups/1/projects/2')
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->transfer(1, 2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetMembers()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'name' => 'Matt'),
-            array('id' => 2, 'name' => 'Bob')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('groups/1/members')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->members(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldAddMember()
-    {
-        $expectedArray = array('id' => 1, 'name' => 'Matt');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('groups/1/members', array('user_id' => 2, 'access_level' => 3))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->addMember(1, 2, 3));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldSaveMember()
-    {
-        $expectedArray = array('id' => 1, 'name' => 'Matt');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('put')
-            ->with('groups/1/members/2', array('access_level' => 4))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->saveMember(1, 2, 4));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldRemoveMember()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('delete')
-            ->with('groups/1/members/2')
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->removeMember(1, 2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldRemoveGroup()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('delete')
-            ->with('groups/1')
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->remove(1));
-    }
-
-    protected function getApiClass()
-    {
-        return 'Gitlab\Api\Groups';
-    }
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/IssuesTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/IssuesTest.php
deleted file mode 100644
index 8c656f003a2..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/IssuesTest.php
+++ /dev/null
@@ -1,279 +0,0 @@
-<?php namespace Gitlab\Tests\Api;
-
-use Gitlab\Api\AbstractApi;
-
-class IssuesTest extends ApiTestCase
-{
-    /**
-     * @test
-     */
-    public function shouldGetAllIssues()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'title' => 'An issue'),
-            array('id' => 2, 'title' => 'Another issue'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('issues', array('page' => 1, 'per_page' => AbstractApi::PER_PAGE))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->all());
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetProjectIssuesWithPagination()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'title' => 'An issue'),
-            array('id' => 2, 'title' => 'Another issue'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/issues', array('page' => 2, 'per_page' => 5))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->all(1, 2, 5));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetProjectIssuesWithParams()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'title' => 'An issue'),
-            array('id' => 2, 'title' => 'Another issue'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/issues', array('page' => 2, 'per_page' => 5, 'order_by' => 'created_at', 'sort' => 'desc', 'labels' => 'foo,bar', 'state' => 'open'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->all(1, 2, 5, array('order_by' => 'created_at', 'sort' => 'desc', 'labels' => 'foo,bar', 'state' => 'open')));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldShowIssue()
-    {
-        $expectedArray = array('id' => 2, 'title' => 'Another issue');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/issues?iid=2')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->show(1, 2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateIssue()
-    {
-        $expectedArray = array('id' => 3, 'title' => 'A new issue');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/issues', array('title' => 'A new issue', 'labels' => 'foo,bar'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->create(1, array('title' => 'A new issue', 'labels' => 'foo,bar')));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldUpdateIssue()
-    {
-        $expectedArray = array('id' => 2, 'title' => 'A renamed issue');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('put')
-            ->with('projects/1/issues/2', array('title' => 'A renamed issue', 'labels' => 'foo'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->update(1, 2, array('title' => 'A renamed issue', 'labels' => 'foo')));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetIssueComments()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'body' => 'A comment'),
-            array('id' => 2, 'body' => 'Another comment')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/issues/2/notes')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->showComments(1, 2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetIssueComment()
-    {
-        $expectedArray = array('id' => 3, 'body' => 'A new comment');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/issues/2/notes/3')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->showComment(1, 2, 3));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateComment()
-    {
-        $expectedArray = array('id' => 3, 'body' => 'A new comment');
-
-        $api = $this->getApiMock();
-        $api->expects($this->exactly(2))
-            ->method('post')
-            ->with('projects/1/issues/2/notes', array('body' => 'A new comment'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->addComment(1, 2, array('body' => 'A new comment')));
-        $this->assertEquals($expectedArray, $api->addComment(1, 2, 'A new comment'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldUpdateComment()
-    {
-        $expectedArray = array('id' => 3, 'body' => 'An edited comment');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('put')
-            ->with('projects/1/issues/2/notes/3', array('body' => 'An edited comment'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->updateComment(1, 2, 3, 'An edited comment'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldSetTimeEstimate()
-    {
-        $expectedArray = array('time_estimate' => 14400, 'total_time_spent' => 0, 'human_time_estimate' => '4h', 'human_total_time_spent' => null);
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/issues/2/time_estimate', array('duration' => '4h'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->setTimeEstimate(1, 2, '4h'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldResetTimeEstimate()
-    {
-        $expectedArray = array('time_estimate' => 0, 'total_time_spent' => 0, 'human_time_estimate' => null, 'human_total_time_spent' => null);
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/issues/2/reset_time_estimate')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->resetTimeEstimate(1, 2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldAddSpentTime()
-    {
-        $expectedArray = array('time_estimate' => 0, 'total_time_spent' => 14400, 'human_time_estimate' => null, 'human_total_time_spent' => '4h');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/issues/2/add_spent_time', array('duration' => '4h'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->addSpentTime(1, 2, '4h'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldResetSpentTime()
-    {
-        $expectedArray = array('time_estimate' => 0, 'total_time_spent' => 0, 'human_time_estimate' => null, 'human_total_time_spent' => null);
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/issues/2/reset_spent_time')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->resetSpentTime(1, 2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetIssueTimeStats()
-    {
-        $expectedArray = array('time_estimate' => 14400, 'total_time_spent' => 5400, 'human_time_estimate' => '4h', 'human_total_time_spent' => '1h 30m');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/issues/2/time_stats')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->getTimeStats(1, 2));
-    }
-
-    protected function getApiClass()
-    {
-        return 'Gitlab\Api\Issues';
-    }
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/KeysTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/KeysTest.php
deleted file mode 100644
index 2f9e94b7a58..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/KeysTest.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php namespace Gitlab\Tests\Api;
-
-use Gitlab\Api\AbstractApi;
-
-class KeysTest extends ApiTestCase
-{
-    /**
-     * @test
-     */
-    public function shouldShowKey()
-    {
-        $expectedArray = array('id' => 1, 'title' => 'A key', 'key' => 'ssh-rsa key', 'created_at' => '2016-01-01T01:00:00.000Z');
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('keys/1')
-            ->will($this->returnValue($expectedArray));
-
-        $this->assertEquals($expectedArray, $api->show(1));
-    }
-
-    protected function getApiClass()
-    {
-        return 'Gitlab\Api\Keys';
-    }
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/MergeRequestsTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/MergeRequestsTest.php
deleted file mode 100644
index bd6e6eb2b70..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/MergeRequestsTest.php
+++ /dev/null
@@ -1,368 +0,0 @@
-<?php namespace Gitlab\Tests\Api;
-
-use Gitlab\Api\AbstractApi;
-use Gitlab\Api\MergeRequests;
-
-class MergeRequestsTest extends ApiTestCase
-{
-    /**
-     * @test
-     */
-    public function shouldGetMergeRequestListWithDefaultParams()
-    {
-        $expectedArray = $this->getMultipleMergeRequestsData();
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/merge_requests', array('page' => 1, 'per_page' => AbstractApi::PER_PAGE, 'state' => MergeRequests::STATE_ALL, 'order_by' => MergeRequests::ORDER_BY, 'sort' => MergeRequests::SORT))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->getList(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetAll()
-    {
-        $expectedArray = $this->getMultipleMergeRequestsData();
-
-        $api = $this->getApiMock(array('getList'));
-        $api->expects($this->once())
-            ->method('getList')
-            ->with(1, MergeRequests::STATE_ALL, 1, AbstractApi::PER_PAGE, MergeRequests::ORDER_BY, MergeRequests::SORT)
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->all(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetAllWithParams()
-    {
-        $expectedArray = $this->getMultipleMergeRequestsData();
-
-        $api = $this->getApiMock(array('getList'));
-        $api->expects($this->once())
-            ->method('getList')
-            ->with(1, MergeRequests::STATE_ALL, 2, 5,  'title', 'desc')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->all(1, 2, 5, 'title', 'desc'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetMerged()
-    {
-        $expectedArray = $this->getMultipleMergeRequestsData();
-
-        $api = $this->getApiMock(array('getList'));
-        $api->expects($this->once())
-            ->method('getList')
-            ->with(1, MergeRequests::STATE_MERGED, 1, AbstractApi::PER_PAGE, MergeRequests::ORDER_BY, MergeRequests::SORT)
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->merged(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetMergedWithParams()
-    {
-        $expectedArray = $this->getMultipleMergeRequestsData();
-
-        $api = $this->getApiMock(array('getList'));
-        $api->expects($this->once())
-            ->method('getList')
-            ->with(1, MergeRequests::STATE_MERGED, 3, 15, 'updated_at', 'asc')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->merged(1, 3, 15, 'updated_at', 'asc'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetOpened()
-    {
-        $expectedArray = $this->getMultipleMergeRequestsData();
-
-        $api = $this->getApiMock(array('getList'));
-        $api->expects($this->once())
-            ->method('getList')
-            ->with(1, MergeRequests::STATE_OPENED, 1, AbstractApi::PER_PAGE, MergeRequests::ORDER_BY, MergeRequests::SORT)
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->opened(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetOpenedWithParams()
-    {
-        $expectedArray = $this->getMultipleMergeRequestsData();
-
-        $api = $this->getApiMock(array('getList'));
-        $api->expects($this->once())
-            ->method('getList')
-            ->with(1, MergeRequests::STATE_OPENED, 2, 4, 'title', 'desc')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->opened(1, 2, 4, 'title', 'desc'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetClosed()
-    {
-        $expectedArray = $this->getMultipleMergeRequestsData();
-
-        $api = $this->getApiMock(array('getList'));
-        $api->expects($this->once())
-            ->method('getList')
-            ->with(1, MergeRequests::STATE_CLOSED, 1, AbstractApi::PER_PAGE, MergeRequests::ORDER_BY, MergeRequests::SORT)
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->closed(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetClosedWithParams()
-    {
-        $expectedArray = $this->getMultipleMergeRequestsData();
-
-        $api = $this->getApiMock(array('getList'));
-        $api->expects($this->once())
-            ->method('getList')
-            ->with(1, MergeRequests::STATE_CLOSED, 2, 4, 'title', 'desc')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->closed(1, 2, 4, 'title', 'desc'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldShowMergeRequest()
-    {
-        $expectedArray = array('id' => 2, 'name' => 'A merge request');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/merge_request/2')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->show(1, 2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateMergeRequestWithoutOptionalParams()
-    {
-        $expectedArray = array('id' => 3, 'title' => 'Merge Request');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/merge_requests', array(
-                'title' => 'Merge Request',
-                'target_branch' => 'master',
-                'source_branch' => 'develop',
-                'description' => null,
-                'assignee_id' => null,
-                'target_project_id' => null
-            ))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->create(1, 'develop', 'master', 'Merge Request'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateMergeRequestWithOptionalParams()
-    {
-        $expectedArray = array('id' => 3, 'title' => 'Merge Request');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/merge_requests', array(
-                'title' => 'Merge Request',
-                'target_branch' => 'master',
-                'source_branch' => 'develop',
-                'description' => 'Some changes',
-                'assignee_id' => 6,
-                'target_project_id' => 20
-            ))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->create(1, 'develop', 'master', 'Merge Request', 6, 20, 'Some changes'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldUpdateMergeRequest()
-    {
-        $expectedArray = array('id' => 2, 'title' => 'Updated title');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('put')
-            ->with('projects/1/merge_request/2', array('title' => 'Updated title', 'description' => 'No so many changes now', 'state_event' => 'close'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->update(1, 2, array(
-            'title' => 'Updated title',
-            'description' => 'No so many changes now',
-            'state_event' => 'close'
-        )));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldMergeMergeRequest()
-    {
-        $expectedArray = array('id' => 2, 'title' => 'Updated title');
-
-        $api = $this->getApiMock();
-        $api->expects($this->exactly(2))
-            ->method('put')
-            ->with('projects/1/merge_request/2/merge', array('merge_commit_message' => 'Accepted'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->merge(1, 2, 'Accepted'));
-        $this->assertEquals($expectedArray, $api->merge(1, 2, array('merge_commit_message' => 'Accepted')));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetMergeRequestNotes()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'body' => 'A comment'),
-            array('id' => 2, 'body' => 'Another comment')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/merge_requests/2/notes')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->showNotes(1, 2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetMergeRequestComments()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'note' => 'A comment'),
-            array('id' => 2, 'note' => 'Another comment')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/merge_request/2/comments')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->showComments(1, 2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldAddMergeRequestComment()
-    {
-        $expectedArray = array('id' => 2, 'title' => 'A comment');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/merge_request/2/comments', array('note' => 'A comment'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->addComment(1, 2, 'A comment'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetMergeRequestChanges()
-    {
-        $expectedArray = array('id' => 1, 'title' => 'A merge request');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/merge_request/2/changes')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->changes(1, 2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetMergeRequestByIid()
-    {
-        $expectedArray = array('id' => 1, 'title' => 'A merge request');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/merge_requests', array('iid' => 2))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->getByIid(1, 2));
-    }
-
-    protected function getMultipleMergeRequestsData()
-    {
-        return array(
-            array('id' => 1, 'title' => 'A merge request'),
-            array('id' => 2, 'title' => 'Another merge request')
-        );
-    }
-
-    protected function getApiClass()
-    {
-        return 'Gitlab\Api\MergeRequests';
-    }
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/MilestonesTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/MilestonesTest.php
deleted file mode 100644
index e22c2370ff9..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/MilestonesTest.php
+++ /dev/null
@@ -1,100 +0,0 @@
-<?php namespace Gitlab\Tests\Api;
-
-class MilestonesTest extends ApiTestCase
-{
-    /**
-     * @test
-     */
-    public function shouldGetAllMilestones()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'title' => 'A milestone'),
-            array('id' => 2, 'title' => 'Another milestone'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/milestones')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->all(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldShowMilestone()
-    {
-        $expectedArray = array('id' => 1, 'name' => 'A milestone');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/milestones/2')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->show(1, 2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateMilestone()
-    {
-        $expectedArray = array('id' => 3, 'title' => 'A new milestone');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/milestones', array('description' => 'Some text', 'title' => 'A new milestone'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->create(1, array('description' => 'Some text', 'title' => 'A new milestone')));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldUpdateMilestone()
-    {
-        $expectedArray = array('id' => 3, 'title' => 'Updated milestone');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('put')
-            ->with('projects/1/milestones/3', array('title' => 'Updated milestone', 'due_date' => '2015-04-01', 'state_event' => 'close'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->update(1, 3, array('title' => 'Updated milestone', 'due_date' => '2015-04-01', 'state_event' => 'close')));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetMilestonesIssues()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'title' => 'An issue'),
-            array('id' => 2, 'title' => 'Another issue'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/milestones/3/issues')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->issues(1, 3));
-    }
-
-    protected function getApiClass()
-    {
-        return 'Gitlab\Api\Milestones';
-    }
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/ProjectNamespacesTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/ProjectNamespacesTest.php
deleted file mode 100644
index 1feb5ff1f41..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/ProjectNamespacesTest.php
+++ /dev/null
@@ -1,70 +0,0 @@
-<?php namespace Gitlab\Tests\Api;
-
-use Gitlab\Api\AbstractApi;
-
-class ProjectNamespacesTest extends ApiTestCase
-{
-    /**
-     * @test
-     */
-    public function shouldGetAllNamespaces()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'name' => 'bespokes'),
-            array('id' => 2, 'name' => 'internal')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('namespaces', array('page' => 1, 'per_page' => 10))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->all(1, 10));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldNotNeedPaginationWhenGettingNamespaces()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'name' => 'bespokes'),
-            array('id' => 2, 'name' => 'internal')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('namespaces', array('page' => 1, 'per_page' => AbstractApi::PER_PAGE))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->all());
-    }
-    /**
-     * @test
-     */
-    public function shouldSearchNamespaces()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'name' => 'bespokes'),
-            array('id' => 2, 'name' => 'internal')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('namespaces', array('search' => 'term', 'page' => 1, 'per_page' => 10))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->search('term', 1, 10));
-    }
-
-    protected function getApiClass()
-    {
-        return 'Gitlab\Api\ProjectNamespaces';
-    }
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/ProjectsTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/ProjectsTest.php
deleted file mode 100644
index 47bb26432f1..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/ProjectsTest.php
+++ /dev/null
@@ -1,1098 +0,0 @@
-<?php namespace Gitlab\Tests\Api;
-
-use Gitlab\Api\AbstractApi;
-use Gitlab\Api\Projects;
-
-class ProjectsTest extends ApiTestCase
-{
-    /**
-     * @test
-     */
-    public function shouldGetAllProjects()
-    {
-        $expectedArray = $this->getMultipleProjectsData();
-
-        $api = $this->getMultipleProjectsRequestMock('projects/all', $expectedArray);
-
-        $this->assertEquals($expectedArray, $api->all());
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetAllProjectsSortedByName()
-    {
-        $expectedArray = $this->getMultipleProjectsData();
-
-        $api = $this->getMultipleProjectsRequestMock('projects/all', $expectedArray, 1, 5, 'name', 'asc');
-
-        $this->assertEquals($expectedArray, $api->all(1, 5, 'name'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldNotNeedPaginationWhenGettingProjects()
-    {
-        $expectedArray = $this->getMultipleProjectsData();
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/all', array('page' => 1, 'per_page' => AbstractApi::PER_PAGE, 'order_by' => Projects::ORDER_BY, 'sort' => Projects::SORT))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->all());
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetAccessibleProjects()
-    {
-        $expectedArray = $this->getMultipleProjectsData();
-
-        $api = $this->getMultipleProjectsRequestMock('projects', $expectedArray, 2, 7);
-
-        $this->assertEquals($expectedArray, $api->accessible(2, 7));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetOwnedProjects()
-    {
-        $expectedArray = $this->getMultipleProjectsData();
-
-        $api = $this->getMultipleProjectsRequestMock('projects?owned=1', $expectedArray, 3, 50);
-
-        $this->assertEquals($expectedArray, $api->owned(3, 50));
-    }
-
-
-    /**
-     * @test
-     */
-    public function shouldSearchProjects()
-    {
-        $expectedArray = $this->getMultipleProjectsData();
-
-        $api = $this->getMultipleProjectsRequestMock('projects/search/a%20project', $expectedArray);
-        $this->assertEquals($expectedArray, $api->search('a project'));
-
-        $api = $this->getMultipleProjectsRequestMock('projects/search/a%2Eproject', $expectedArray);
-        $this->assertEquals($expectedArray, $api->search('a.project'));
-
-        $api = $this->getMultipleProjectsRequestMock('projects/search/a%2Fproject', $expectedArray);
-        $this->assertEquals($expectedArray, $api->search('a/project'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldShowProject()
-    {
-        $expectedArray = array('id' => 1, 'name' => 'Project Name');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->show(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateProject()
-    {
-        $expectedArray = array('id' => 1, 'name' => 'Project Name');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects', array('name' => 'Project Name', 'issues_enabled' => true))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->create('Project Name', array(
-            'issues_enabled' => true
-        )));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldUpdateProject()
-    {
-        $expectedArray = array('id' => 1, 'name' => 'Updated Name');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('put')
-            ->with('projects/1', array('name' => 'Updated Name', 'issues_enabled' => true))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->update(1, array(
-            'name' => 'Updated Name',
-            'issues_enabled' => true
-        )));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldArchiveProject()
-    {
-        $expectedArray = array('id' => 1, 'archived' => true);
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/archive')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->archive(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldUnarchiveProject()
-    {
-        $expectedArray = array('id' => 1, 'archived' => false);
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/unarchive')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->unarchive(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateProjectForUser()
-    {
-        $expectedArray = array('id' => 1, 'name' => 'Project Name');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/user/1', array('name' => 'Project Name', 'issues_enabled' => true))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->createForUser(1, 'Project Name', array(
-            'issues_enabled' => true
-        )));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldRemoveProject()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('delete')
-            ->with('projects/1')
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->remove(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetBuilds()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'status' => 'success'),
-            array('id' => 2, 'status' => 'failed')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/builds')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->builds(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetBuildsWithScope()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'status' => 'success'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/builds', array('scope' => 'success'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->builds(1, 'success'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetBuildsWithMultipleScopes()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'status' => 'success'),
-            array('id' => 1, 'status' => 'failed'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/builds', array('scope' => array('success', 'failed')))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->builds(1, array('success', 'failed')));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetBuild()
-    {
-        $expectedArray = array('id' => 2);
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/builds/2')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->build(1, 2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetTrace()
-    {
-        $expectedString = 'runner trace of a specific build';
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/builds/2/trace')
-            ->will($this->returnValue($expectedString))
-        ;
-
-        $this->assertEquals($expectedString, $api->trace(1, 2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetPipelines()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'status' => 'success','ref' => 'new-pipeline'),
-            array('id' => 2, 'status' => 'failed', 'ref' => 'new-pipeline'),
-            array('id' => 3, 'status' => 'pending', 'ref'=> 'test-pipeline')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/pipelines')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->pipelines(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetPipeline()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'status' => 'success','ref' => 'new-pipeline'),
-            array('id' => 2, 'status' => 'failed', 'ref' => 'new-pipeline'),
-            array('id' => 3, 'status' => 'pending', 'ref'=> 'test-pipeline')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/pipelines/3')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->pipeline(1, 3));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreatePipeline()
-    {
-        $expectedArray = array(
-            array('id' => 4, 'status' => 'created', 'ref'=> 'test-pipeline')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/pipelines', array('ref' => 'test-pipeline'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->createPipeline(1, 'test-pipeline'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldRetryPipeline()
-    {
-        $expectedArray = array(
-            array('id' => 5, 'status' => 'pending', 'ref'=> 'test-pipeline')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/pipelines/4/retry')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->retryPipeline(1, 4));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCancelPipeline()
-    {
-        $expectedArray = array(
-            array('id' => 6, 'status' => 'cancelled', 'ref'=> 'test-pipeline')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/pipelines/6/cancel')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->cancelPipeline(1, 6));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetMembers()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'name' => 'Matt'),
-            array('id' => 2, 'name' => 'Bob')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/members')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->members(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetMembersWithQuery()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'name' => 'Matt')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/members', array('query' => 'at'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->members(1, 'at'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetMember()
-    {
-        $expectedArray = array('id' => 2, 'name' => 'Matt');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/members/2')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->member(1, 2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldAddMember()
-    {
-        $expectedArray = array('id' => 1, 'name' => 'Matt');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/members', array('user_id' => 2, 'access_level' => 3))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->addMember(1, 2, 3));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldSaveMember()
-    {
-        $expectedArray = array('id' => 1, 'name' => 'Matt');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('put')
-            ->with('projects/1/members/2', array('access_level' => 4))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->saveMember(1, 2, 4));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldRemoveMember()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('delete')
-            ->with('projects/1/members/2')
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->removeMember(1, 2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetHooks()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'name' => 'Test hook'),
-            array('id' => 2, 'name' => 'Another hook'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/hooks')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->hooks(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetHook()
-    {
-        $expectedArray = array('id' => 2, 'name' => 'Another hook');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/hooks/2')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->hook(1, 2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldAddHook()
-    {
-        $expectedArray = array('id' => 3, 'name' => 'A new hook', 'url' => 'http://www.example.com');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/hooks', array('url' => 'http://www.example.com', 'push_events' => true, 'issues_events' => true, 'merge_requests_events' => true))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->addHook(1, 'http://www.example.com', array('push_events' => true, 'issues_events' => true, 'merge_requests_events' => true)));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldAddHookWithOnlyUrl()
-    {
-        $expectedArray = array('id' => 3, 'name' => 'A new hook', 'url' => 'http://www.example.com');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/hooks', array('url' => 'http://www.example.com', 'push_events' => true))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->addHook(1, 'http://www.example.com'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldAddHookWithoutPushEvents()
-    {
-        $expectedArray = array('id' => 3, 'name' => 'A new hook', 'url' => 'http://www.example.com');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/hooks', array('url' => 'http://www.example.com', 'push_events' => false))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->addHook(1, 'http://www.example.com', array('push_events' => false)));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldUpdateHook()
-    {
-        $expectedArray = array('id' => 3, 'name' => 'A new hook', 'url' => 'http://www.example.com');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('put')
-            ->with('projects/1/hooks/3', array('url' => 'http://www.example-test.com', 'push_events' => false))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->updateHook(1, 3, array('url' => 'http://www.example-test.com', 'push_events' => false)));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldRemoveHook()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('delete')
-            ->with('projects/1/hooks/2')
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->removeHook(1, 2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetKeys()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'title' => 'test-key'),
-            array('id' => 2, 'title' => 'another-key')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/keys')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->keys(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetKey()
-    {
-        $expectedArray = array('id' => 2, 'title' => 'another-key');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/keys/2')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->key(1, 2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldAddKey()
-    {
-        $expectedArray = array('id' => 3, 'title' => 'new-key');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/keys', array('title' => 'new-key', 'key' => '...'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->addKey(1, 'new-key', '...'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldRemoveKey()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('delete')
-            ->with('projects/1/keys/3')
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->removeKey(1, 3));
-    }
-
-    /**
-     * @test
-     */
-    public function shoudEnableKey()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/keys/3/enable')
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->enableKey(1, 3));
-    }
-
-    /**
-     * @test
-     */
-    public function shoudDisableKey()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('delete')
-            ->with('projects/1/keys/3/disable')
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->disableKey(1, 3));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetEvents()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'title' => 'An event'),
-            array('id' => 2, 'title' => 'Another event')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/events', array(
-                'page' => 1,
-                'per_page' => AbstractApi::PER_PAGE
-            ))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->events(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetEventsWithPagination()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'title' => 'An event'),
-            array('id' => 2, 'title' => 'Another event')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/events', array(
-                'page' => 2,
-                'per_page' => 15
-            ))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->events(1, 2, 15));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetLabels()
-    {
-        $expectedArray = array(
-            array('name' => 'bug', 'color' => '#000000'),
-            array('name' => 'feature', 'color' => '#ff0000')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/labels')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->labels(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldAddLabel()
-    {
-        $expectedArray = array('name' => 'bug', 'color' => '#000000');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/labels', array('name' => 'wont-fix', 'color' => '#ffffff'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->addLabel(1, array('name' => 'wont-fix', 'color' => '#ffffff')));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldUpdateLabel()
-    {
-        $expectedArray = array('name' => 'bug', 'color' => '#00ffff');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('put')
-            ->with('projects/1/labels', array('name' => 'bug', 'new_name' => 'big-bug', 'color' => '#00ffff'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->updateLabel(1, array('name' => 'bug', 'new_name' => 'big-bug', 'color' => '#00ffff')));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldRemoveLabel()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('delete')
-            ->with('projects/1/labels', array('name' => 'bug'))
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->removeLabel(1, 'bug'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateForkRelation()
-    {
-        $expectedArray = array('project_id' => 1, 'forked_id' => 2);
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/fork/2')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->createForkRelation(1, 2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldRemoveForkRelation()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('delete')
-            ->with('projects/2/fork')
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->removeForkRelation(2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldSetService()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('put')
-            ->with('projects/1/services/hipchat', array('param' => 'value'))
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->setService(1, 'hipchat', array('param' => 'value')));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldRemoveService()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('delete')
-            ->with('projects/1/services/hipchat')
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->removeService(1, 'hipchat'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetVariables()
-    {
-        $expectedArray = array(
-            array('key' => 'ftp_username', 'value' => 'ftp'),
-            array('key' => 'ftp_password', 'value' => 'somepassword')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/variables')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->variables(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetVariable()
-    {
-        $expectedArray = array('key' => 'ftp_username', 'value' => 'ftp');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/variables/ftp_username')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->variable(1, 'ftp_username'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldAddVariable()
-    {
-        $expectedKey   = 'ftp_port';
-        $expectedValue = '21';
-
-        $expectedArray = array(
-            'key'   => $expectedKey,
-            'value' => $expectedValue,
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/variables', $expectedArray)
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->addVariable(1, $expectedKey, $expectedValue));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldUpdateVariable()
-    {
-        $expectedKey   = 'ftp_port';
-        $expectedValue = '22';
-
-        $expectedArray = array(
-            'key'   => 'ftp_port',
-            'value' => '22',
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('put')
-            ->with('projects/1/variables/'.$expectedKey, array('value' => $expectedValue))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->updateVariable(1, $expectedKey, $expectedValue));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldRemoveVariable()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('delete')
-            ->with('projects/1/variables/ftp_password')
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->removeVariable(1, 'ftp_password'));
-    }
-
-    protected function getMultipleProjectsRequestMock($path, $expectedArray = array(), $page = 1, $per_page = 20, $order_by = 'created_at', $sort = 'asc')
-    {
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with($path, array('page' => $page, 'per_page' => $per_page, 'order_by' => $order_by, 'sort' => $sort))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        return $api;
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetDeployments()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'sha' => '0000001'),
-            array('id' => 2, 'sha' => '0000002'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/deployments', array(
-                'page' => 1,
-                'per_page' => AbstractApi::PER_PAGE
-            ))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->deployments(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetDeploymentsWithPagination()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'sha' => '0000001'),
-            array('id' => 2, 'sha' => '0000002'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/deployments', array(
-                'page' => 2,
-                'per_page' => 15
-            ))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->deployments(1, 2, 15));
-    }
-
-    protected function getMultipleProjectsData()
-    {
-        return array(
-            array('id' => 1, 'name' => 'A project'),
-            array('id' => 2, 'name' => 'Another project')
-        );
-    }
-
-    protected function getApiClass()
-    {
-        return 'Gitlab\Api\Projects';
-    }
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/RepositoriesTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/RepositoriesTest.php
deleted file mode 100644
index a6bffd100c2..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/RepositoriesTest.php
+++ /dev/null
@@ -1,708 +0,0 @@
-<?php namespace Gitlab\Tests\Api;
-
-use Gitlab\Api\AbstractApi;
-
-class RepositoriesTest extends ApiTestCase
-{
-    /**
-     * @test
-     */
-    public function shouldGetBranches()
-    {
-        $expectedArray = array(
-            array('name' => 'master'),
-            array('name' => 'develop')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/repository/branches')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->branches(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetBranch()
-    {
-        $expectedArray = array('name' => 'master');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/repository/branches/master')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->branch(1, 'master'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateBranch()
-    {
-        $expectedArray = array('name' => 'feature');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/repository/branches', array('branch_name' => 'feature', 'ref' => 'master'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->createBranch(1, 'feature', 'master'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldDeleteBranch()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('delete')
-            ->with('projects/1/repository/branches/master')
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->deleteBranch(1, 'master'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldProtectBranch()
-    {
-        $expectedArray = array('name' => 'master');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('put')
-            ->with('projects/1/repository/branches/master/protect', array('developers_can_push' => false, 'developers_can_merge' => false))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->protectBranch(1, 'master'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldProtectBranchWithPermissions()
-    {
-        $expectedArray = array('name' => 'master');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('put')
-            ->with('projects/1/repository/branches/master/protect', array('developers_can_push' => true, 'developers_can_merge' => true))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->protectBranch(1, 'master', true, true));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldUnprotectBranch()
-    {
-        $expectedArray = array('name' => 'master');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('put')
-            ->with('projects/1/repository/branches/master/unprotect')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->unprotectBranch(1, 'master'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetTags()
-    {
-        $expectedArray = array(
-            array('name' => '1.0'),
-            array('name' => '1.1')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/repository/tags')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->tags(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateTag()
-    {
-        $expectedArray = array('name' => '1.0');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/repository/tags', array(
-                'tag_name' => '1.0',
-                'ref' => 'abcd1234',
-                'message' => '1.0 release'
-            ))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->createTag(1, '1.0', 'abcd1234', '1.0 release'));
-    }
-
-	/**
-	 * @test
-	 */
-	public function shouldCreateRelease() {
-		$project_id  = 1;
-		$tagName     = 'sometag';
-		$description = '1.0 release';
-
-		$expectedArray = array( 'name' => $tagName );
-
-		$api = $this->getApiMock();
-		$api->expects( $this->once())
-		    ->method('post')
-		    ->with( 'projects/' . $project_id . '/repository/tags/' . $tagName . '/release', array(
-			    'id' => $project_id,
-			    'tag_name' => $tagName,
-			    'description' => $description
-		    ))
-		    ->will($this->returnValue($expectedArray))
-		;
-
-		$this->assertEquals( $expectedArray, $api->createRelease( $project_id, $tagName, $description ) );
-	}
-
-	/**
-	 * @test
-	 */
-	public function shouldUpdateRelease() {
-		$project_id  = 1;
-		$tagName     = 'sometag';
-		$description = '1.0 release';
-
-		$expectedArray = array( 'description' => $tagName );
-
-		$api = $this->getApiMock();
-		$api->expects( $this->once())
-		    ->method('put')
-		    ->with( 'projects/' . $project_id . '/repository/tags/' . $tagName . '/release', array(
-			    'id' => $project_id,
-			    'tag_name' => $tagName,
-			    'description' => $description
-		    ))
-		    ->will($this->returnValue($expectedArray))
-		;
-
-		$this->assertEquals( $expectedArray, $api->updateRelease( $project_id, $tagName, $description ) );
-	}
-
-    /**
-     * @test
-     */
-    public function shouldGetCommits()
-    {
-        $expectedArray = array(
-            array('id' => 'abcd1234', 'title' => 'A commit'),
-            array('id' => 'efgh5678', 'title' => 'Another commit')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/repository/commits', array('page' => 0, 'per_page' => AbstractApi::PER_PAGE, 'ref_name' => null))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->commits(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetCommitBuilds()
-    {
-        $expectedArray = array(
-            array('id' => 'abcd1234', 'status' => 'failed'),
-            array('id' => 'efgh5678', 'status' => 'success')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/repository/commits/abcd12345/builds', array('page' => 0, 'per_page' => AbstractApi::PER_PAGE, 'scope' => null))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->commitBuilds(1, 'abcd12345'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetCommitBuildsWithScope()
-    {
-        $expectedArray = array(
-            array('id' => 'abcd1234', 'status' => 'success'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/repository/commits/abcd12345/builds', array('page' => 0, 'per_page' => AbstractApi::PER_PAGE, 'scope' => 'success'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->commitBuilds(1, 'abcd12345', 'success'));
-    }
-
-
-    /**
-     * @test
-     */
-    public function shouldGetCommitsWithParams()
-    {
-        $expectedArray = array(
-            array('id' => 'abcd1234', 'title' => 'A commit'),
-            array('id' => 'efgh5678', 'title' => 'Another commit')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/repository/commits', array('page' => 2, 'per_page' => 25, 'ref_name' => 'master'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->commits(1, 2, 25, 'master'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetCommit()
-    {
-        $expectedArray = array('id' => 'abcd1234', 'title' => 'A commit');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/repository/commits/abcd1234')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->commit(1, 'abcd1234'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetCommitComments()
-    {
-        $expectedArray = array(
-            array('note' => 'A commit message'),
-            array('note' => 'Another commit message')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/repository/commits/abcd1234/comments')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->commitComments(1, 'abcd1234'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateCommitComment()
-    {
-        $expectedArray = array('id' => 2, 'title' => 'A new comment');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/repository/commits/abcd1234/comments', array('note' => 'A new comment'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->createCommitComment(1, 'abcd1234', 'A new comment'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateCommitCommentWithParams()
-    {
-        $expectedArray = array('id' => 2, 'title' => 'A new comment');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/repository/commits/abcd1234/comments', array(
-                'note' => 'A new comment',
-                'path' => '/some/file.txt',
-                'line' => 123, 'line_type' => 'old'
-            ))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->createCommitComment(1, 'abcd1234', 'A new comment', array(
-            'path' => '/some/file.txt',
-            'line' => 123,
-            'line_type' => 'old'
-        )));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCompare()
-    {
-        $expectedArray = array('commit' => 'object');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/repository/compare?from=master&to=feature')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->compare(1, 'master', 'feature'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetDiff()
-    {
-        $expectedArray = array(
-            array('diff' => '--- ...'),
-            array('diff' => '+++ ...')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/repository/commits/abcd1234/diff')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->diff(1, 'abcd1234'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetTree()
-    {
-        $expectedArray = array(
-            array('name' => 'file1.txt'),
-            array('name' => 'file2.csv')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/repository/tree')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->tree(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetTreeWithParams()
-    {
-        $expectedArray = array(
-            array('name' => 'dir/file1.txt'),
-            array('name' => 'dir/file2.csv')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/repository/tree', array('path' => 'dir/', 'ref_name' => 'master'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->tree(1, array('path' => 'dir/', 'ref_name' => 'master')));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetBlob()
-    {
-        $expectedString = 'something in a file';
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/repository/commits/abcd1234/blob', array('filepath' => 'dir/file1.txt'))
-            ->will($this->returnValue($expectedString))
-        ;
-
-        $this->assertEquals($expectedString, $api->blob(1, 'abcd1234', 'dir/file1.txt'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetFile()
-    {
-        $expectedArray = array('file_name' => 'file1.txt', 'file_path' => 'dir/file1.txt');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/repository/files', array('file_path' => 'dir/file1.txt', 'ref' => 'abcd1234'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->getFile(1, 'dir/file1.txt', 'abcd1234'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateFile()
-    {
-        $expectedArray = array('file_name' => 'file1.txt', 'file_path' => 'dir/file1.txt');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/repository/files', array(
-                'file_path' => 'dir/file1.txt',
-                'branch_name' => 'master',
-                'encoding' => null,
-                'content' => 'some contents',
-                'commit_message' => 'Added new file',
-                'author_email' => null,
-                'author_name' => null,
-            ))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->createFile(1, 'dir/file1.txt', 'some contents', 'master', 'Added new file'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateFileWithEncoding()
-    {
-        $expectedArray = array('file_name' => 'file1.txt', 'file_path' => 'dir/file1.txt');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/repository/files', array(
-                'file_path' => 'dir/file1.txt',
-                'branch_name' => 'master',
-                'encoding' => 'text',
-                'content' => 'some contents',
-                'commit_message' => 'Added new file',
-                'author_email' => null,
-                'author_name' => null,
-            ))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->createFile(1, 'dir/file1.txt', 'some contents', 'master', 'Added new file', 'text'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateFileWithAuthor()
-    {
-        $expectedArray = array('file_name' => 'file1.txt', 'file_path' => 'dir/file1.txt');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/repository/files', array(
-                'file_path' => 'dir/file1.txt',
-                'branch_name' => 'master',
-                'encoding' => null,
-                'content' => 'some contents',
-                'commit_message' => 'Added new file',
-                'author_email' => 'gitlab@example.com',
-                'author_name' => 'GitLab User',
-            ))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->createFile(1, 'dir/file1.txt', 'some contents', 'master', 'Added new file', null, 'gitlab@example.com', 'GitLab User'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldUpdateFile()
-    {
-        $expectedArray = array('file_name' => 'file1.txt', 'file_path' => 'dir/file1.txt');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('put')
-            ->with('projects/1/repository/files', array(
-                'file_path' => 'dir/file1.txt',
-                'branch_name' => 'master',
-                'encoding' => null,
-                'content' => 'some new contents',
-                'commit_message' => 'Updated new file',
-                'author_email' => null,
-                'author_name' => null,
-            ))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->updateFile(1, 'dir/file1.txt', 'some new contents', 'master', 'Updated new file'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldUpdateFileWithEncoding()
-    {
-        $expectedArray = array('file_name' => 'file1.txt', 'file_path' => 'dir/file1.txt');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('put')
-            ->with('projects/1/repository/files', array(
-                'file_path' => 'dir/file1.txt',
-                'branch_name' => 'master',
-                'encoding' => 'base64',
-                'content' => 'some new contents',
-                'commit_message' => 'Updated file',
-                'author_email' => null,
-                'author_name' => null,
-            ))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->updateFile(1, 'dir/file1.txt', 'some new contents', 'master', 'Updated file', 'base64'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldUpdateFileWithAuthor()
-    {
-        $expectedArray = array('file_name' => 'file1.txt', 'file_path' => 'dir/file1.txt');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('put')
-            ->with('projects/1/repository/files', array(
-                'file_path' => 'dir/file1.txt',
-                'branch_name' => 'master',
-                'encoding' => null,
-                'content' => 'some new contents',
-                'commit_message' => 'Updated file',
-                'author_email' => 'gitlab@example.com',
-                'author_name' => 'GitLab User',
-            ))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->updateFile(1, 'dir/file1.txt', 'some new contents', 'master', 'Updated file', null, 'gitlab@example.com', 'GitLab User'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldDeleteFile()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('delete')
-            ->with('projects/1/repository/files', array(
-                'file_path' => 'dir/file1.txt',
-                'branch_name' => 'master',
-                'commit_message' => 'Deleted file',
-                'author_email' => null,
-                'author_name' => null,
-            ))
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->deleteFile(1, 'dir/file1.txt', 'master', 'Deleted file'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldDeleteFileWithAuthor()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('delete')
-            ->with('projects/1/repository/files', array(
-                'file_path' => 'dir/file1.txt',
-                'branch_name' => 'master',
-                'commit_message' => 'Deleted file',
-                'author_email' => 'gitlab@example.com',
-                'author_name' => 'GitLab User',
-            ))
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->deleteFile(1, 'dir/file1.txt', 'master', 'Deleted file', 'gitlab@example.com', 'GitLab User'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetContributors()
-    {
-        $expectedArray = array(
-            array('name' => 'Matt'),
-            array('name' => 'Bob')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/repository/contributors')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->contributors(1));
-    }
-
-    protected function getApiClass()
-    {
-        return 'Gitlab\Api\Repositories';
-    }
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/SnippetsTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/SnippetsTest.php
deleted file mode 100644
index 694aac5959d..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/SnippetsTest.php
+++ /dev/null
@@ -1,114 +0,0 @@
-<?php namespace Gitlab\Tests\Api;
-
-class SnippetsTest extends ApiTestCase
-{
-    /**
-     * @test
-     */
-    public function shouldGetAllSnippets()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'title' => 'A snippet'),
-            array('id' => 2, 'title' => 'Another snippet'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/snippets')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->all(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldShowSnippet()
-    {
-        $expectedArray = array('id' => 2, 'title' => 'Another snippet');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/snippets/2')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->show(1, 2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateSnippet()
-    {
-        $expectedArray = array('id' => 3, 'title' => 'A new snippet');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/snippets', array('title' => 'A new snippet', 'code' => 'A file', 'file_name' => 'file.txt'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->create(1, 'A new snippet', 'file.txt', 'A file'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldUpdateSnippet()
-    {
-        $expectedArray = array('id' => 3, 'title' => 'Updated snippet');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('put')
-            ->with('projects/1/snippets/3', array('title' => 'Updated snippet', 'code' => 'New content', 'file_name' => 'new_file.txt'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->update(1, 3, array('file_name' => 'new_file.txt', 'code' => 'New content', 'title' => 'Updated snippet')));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldShowContent()
-    {
-        $expectedString = 'New content';
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/snippets/3/raw')
-            ->will($this->returnValue($expectedString))
-        ;
-
-        $this->assertEquals($expectedString, $api->content(1, 3));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldRemoveSnippet()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('delete')
-            ->with('projects/1/snippets/3')
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->remove(1, 3));
-    }
-
-    protected function getApiClass()
-    {
-        return 'Gitlab\Api\Snippets';
-    }
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/SystemHooksTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/SystemHooksTest.php
deleted file mode 100644
index 3bf16bce6bc..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/SystemHooksTest.php
+++ /dev/null
@@ -1,80 +0,0 @@
-<?php namespace Gitlab\Tests\Api;
-
-class SystemHooksTest extends ApiTestCase
-{
-    /**
-     * @test
-     */
-    public function shouldGetAllHooks()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'url' => 'http://www.example.com'),
-            array('id' => 2, 'url' => 'http://www.example.org'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('hooks')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->all());
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateHook()
-    {
-        $expectedArray = array('id' => 3, 'url' => 'http://www.example.net');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('hooks', array('url' => 'http://www.example.net'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->create('http://www.example.net'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldTestHook()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('hooks/3')
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->test(3));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldRemoveHook()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('delete')
-            ->with('hooks/3')
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->remove(3));
-    }
-
-    protected function getApiClass()
-    {
-        return 'Gitlab\Api\SystemHooks';
-    }
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/TagsTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/TagsTest.php
deleted file mode 100644
index b6aaafa6fca..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/TagsTest.php
+++ /dev/null
@@ -1,87 +0,0 @@
-<?php namespace Gitlab\Tests\Api;
-
-use Gitlab\Api\AbstractApi;
-
-class TagsTest extends ApiTestCase
-{
-    /**
-     * @test
-     */
-    public function shouldGetAllTags()
-    {
-        $expectedArray = array(
-            array('name' => 'v1.0.0'),
-            array('name' => 'v1.1.0'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/repository/tags')
-            ->will($this->returnValue($expectedArray));
-        $this->assertEquals($expectedArray, $api->all(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldShowTag()
-    {
-        $expectedArray = array(
-            array('name' => 'v1.0.0'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('projects/1/repository/tags/v1.0.0')
-            ->will($this->returnValue($expectedArray));
-        $this->assertEquals($expectedArray, $api->show(1, 'v1.0.0'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateTag()
-    {
-        $expectedArray = array(
-            array('name' => 'v1.1.0'),
-        );
-
-        $params = array(
-            'id'       => 1,
-            'tag_name' => 'v1.1.0',
-            'ref'      => 'ref/heads/master'
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('projects/1/repository/tags', $params)
-            ->will($this->returnValue($expectedArray));
-
-        $this->assertEquals($expectedArray, $api->create(1, $params));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldRemoveTag()
-    {
-        $expectedArray = array(
-            array('name' => 'v1.1.0'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('delete')
-            ->with('projects/1/repository/tags/v1.1.0')
-            ->will($this->returnValue($expectedArray));
-        $this->assertEquals($expectedArray, $api->remove(1, 'v1.1.0'));
-    }
-
-    protected function getApiClass()
-    {
-        return 'Gitlab\Api\Tags';
-    }
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/TestCase.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/TestCase.php
deleted file mode 100644
index cba51e5e26a..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/TestCase.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php namespace Gitlab\Tests\Api;
-
-use Buzz\Client\Curl;
-
-use Gitlab\Client;
-use Gitlab\HttpClient\HttpClientInterface;
-
-abstract class TestCase extends \PHPUnit_Framework_TestCase
-{
-    /**
-     * @return Client
-     */
-    protected function getClientMock()
-    {
-        return new Client($this->getHttpMock());
-    }
-
-    /**
-     * @return \PHPUnit_Framework_MockObject_MockObject|HttpClientInterface
-     */
-    protected function getHttpMock()
-    {
-        return $this->getMock('Gitlab\HttpClient\HttpClient', array(), array(null, array(), $this->getHttpClientMock()));
-    }
-
-    /**
-     * @return \PHPUnit_Framework_MockObject_MockObject|Curl
-     */
-    protected function getHttpClientMock()
-    {
-        $httpClient = $this->getMock('Buzz\Client\Curl', array('send'));
-        $httpClient
-            ->expects($this->any())
-            ->method('send');
-
-        return $httpClient;
-    }
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/UsersTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/UsersTest.php
deleted file mode 100644
index a1441da0089..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/UsersTest.php
+++ /dev/null
@@ -1,459 +0,0 @@
-<?php namespace Gitlab\Tests\Api;
-
-use Gitlab\Api\AbstractApi;
-
-class UsersTest extends ApiTestCase
-{
-    /**
-     * @test
-     */
-    public function shouldGetAllUsers()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'name' => 'Matt'),
-            array('id' => 2, 'name' => 'John'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('users', array('active' => null, 'page' => 1, 'per_page' => 10))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->all(null, 1, 10));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetActiveUsers()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'name' => 'Matt'),
-            array('id' => 2, 'name' => 'John'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('users', array('active' => true, 'page' => 1, 'per_page' => AbstractApi::PER_PAGE))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->all(true));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldNotNeedPaginationWhenGettingUsers()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'name' => 'Matt'),
-            array('id' => 2, 'name' => 'John'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('users', array('active' => null, 'page' => 1, 'per_page' => AbstractApi::PER_PAGE))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->all());
-    }
-
-    /**
-     * @test
-     */
-    public function shouldSearchUsers()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'name' => 'Matt')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('users', array('search' => 'ma', 'active' => null, 'page' => 1, 'per_page' => AbstractApi::PER_PAGE))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->search('ma'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldSearchActiveUsers()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'name' => 'Matt')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('users', array('search' => 'ma', 'active' => true, 'page' => 1, 'per_page' => AbstractApi::PER_PAGE))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->search('ma', true));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldSearchActiveUsersWithPagination()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'name' => 'Matt')
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('users', array('search' => 'ma', 'active' => true, 'page' => 2, 'per_page' => 5))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->search('ma', true, 2, 5));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldShowUser()
-    {
-        $expectedArray = array('id' => 1, 'name' => 'Matt');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('users/1')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->show(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateUser()
-    {
-        $expectedArray = array('id' => 3, 'name' => 'Billy');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('users', array('email' => 'billy@example.com', 'password' => 'password'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->create('billy@example.com', 'password'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateUserWithAdditionalInfo()
-    {
-        $expectedArray = array('id' => 3, 'name' => 'Billy');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('users', array('email' => 'billy@example.com', 'password' => 'password', 'name' => 'Billy', 'bio' => 'A person'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->create('billy@example.com', 'password', array('name' => 'Billy', 'bio' => 'A person')));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldUpdateUser()
-    {
-        $expectedArray = array('id' => 3, 'name' => 'Billy Bob');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('put')
-            ->with('users/3', array('name' => 'Billy Bob'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->update(3, array('name' => 'Billy Bob')));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldRemoveUser()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('delete')
-            ->with('users/1')
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->remove(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldBlockUser()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('put')
-            ->with('users/1/block')
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->block(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldUnblockUser()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('put')
-            ->with('users/1/unblock')
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->unblock(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldShowCurrentUser()
-    {
-        $expectedArray = array('id' => 1, 'name' => 'Matt');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('user')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->me());
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetCurrentUserKeys()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'title' => 'A key'),
-            array('id' => 2, 'name' => 'Another key'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('user/keys')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->keys(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetCurrentUserKey()
-    {
-        $expectedArray = array('id' => 1, 'title' => 'A key');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('user/keys/1')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->key(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateKeyForCurrentUser()
-    {
-        $expectedArray = array('id' => 3, 'title' => 'A new key');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('user/keys', array('title' => 'A new key', 'key' => '...'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->createKey('A new key', '...'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldDeleteKeyForCurrentUser()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('delete')
-            ->with('user/keys/3')
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->removeKey(3));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetUserKeys()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'title' => 'A key'),
-            array('id' => 2, 'name' => 'Another key'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('users/1/keys')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->userKeys(1));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetUserKey()
-    {
-        $expectedArray = array('id' => 2, 'title' => 'Another key');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('users/1/keys/2')
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->userKey(1, 2));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldCreateKeyForUser()
-    {
-        $expectedArray = array('id' => 3, 'title' => 'A new key');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('post')
-            ->with('users/1/keys', array('title' => 'A new key', 'key' => '...'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->createKeyForUser(1, 'A new key', '...'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldDeleteKeyForUser()
-    {
-        $expectedBool = true;
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('delete')
-            ->with('users/1/keys/3')
-            ->will($this->returnValue($expectedBool))
-        ;
-
-        $this->assertEquals($expectedBool, $api->removeUserKey(1, 3));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldAttemptLogin()
-    {
-        $expectedArray = array('id' => 1, 'name' => 'Matt');
-
-        $api = $this->getApiMock();
-        $api->expects($this->exactly(2))
-            ->method('post')
-            ->with('session', array('login' => 'matt', 'password' => 'password', 'email' => 'matt'))
-            ->will($this->returnValue($expectedArray))
-        ;
-
-        $this->assertEquals($expectedArray, $api->session('matt', 'password'));
-        $this->assertEquals($expectedArray, $api->login('matt', 'password'));
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetUserEmails()
-    {
-        $expectedArray = array(
-            array('id' => 1, 'email' => 'foo@bar.baz'),
-            array('id' => 2, 'email' => 'foo@bar.qux'),
-        );
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('user/emails')
-            ->will($this->returnValue($expectedArray));
-
-        $this->assertEquals($expectedArray, $api->emails());
-    }
-
-    /**
-     * @test
-     */
-    public function shouldGetSpecificUserEmail()
-    {
-        $expectedArray = array('id' => 1, 'email' => 'foo@bar.baz');
-
-        $api = $this->getApiMock();
-        $api->expects($this->once())
-            ->method('get')
-            ->with('user/emails/1')
-            ->will($this->returnValue($expectedArray));
-
-        $this->assertEquals($expectedArray, $api->email(1));
-    }
-
-    protected function getApiClass()
-    {
-        return 'Gitlab\Api\Users';
-    }
-}
diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/bootstrap.php b/vendor/m4tthumphrey/php-gitlab-api/test/bootstrap.php
deleted file mode 100644
index 83bc8b088a4..00000000000
--- a/vendor/m4tthumphrey/php-gitlab-api/test/bootstrap.php
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php
-
-function includeIfExists($file)
-{
-    if (file_exists($file)) {
-        return include $file;
-    }
-}
-
-if ((!$loader = includeIfExists(__DIR__.'/../vendor/autoload.php')) && (!$loader = includeIfExists(__DIR__.'/../../../.composer/autoload.php'))) {
-    die('You must set up the project dependencies, run the following commands:'.PHP_EOL.
-        'curl -s http://getcomposer.org/installer | php'.PHP_EOL.
-        'php composer.phar install'.PHP_EOL);
-}
-
-$loader->add('Gitlab\Tests', __DIR__);
-
-return $loader;
\ No newline at end of file
diff --git a/vendor/php-http/client-common/CHANGELOG.md b/vendor/php-http/client-common/CHANGELOG.md
new file mode 100644
index 00000000000..3031720c6d5
--- /dev/null
+++ b/vendor/php-http/client-common/CHANGELOG.md
@@ -0,0 +1,137 @@
+# Change Log
+
+## 1.7.0 - 2017-11-30
+
+### Added 
+
+- Symfony 4 support
+
+### Changed
+
+- Strict comparison in DecoderPlugin
+
+## 1.6.0 - 2017-10-16
+
+### Added
+
+- Add HttpClientPool client to leverage load balancing and fallback mechanism [see the documentation](http://docs.php-http.org/en/latest/components/client-common.html) for more details.
+- `PluginClientFactory` to create `PluginClient` instances.
+- Added new option 'delay' for `RetryPlugin`.
+- Added new option 'decider' for `RetryPlugin`.
+- Supports more cookie date formats in the Cookie Plugin
+
+### Changed
+
+- The `RetryPlugin` does now wait between retries. To disable/change this feature you must write something like: 
+ 
+```php
+$plugin = new RetryPlugin(['delay' => function(RequestInterface $request, Exception $e, $retries) { 
+  return 0; 
+}); 
+```
+
+### Deprecated
+
+- The `debug_plugins` option for `PluginClient` is deprecated and will be removed in 2.0. Use the decorator design pattern instead like in [ProfilePlugin](https://github.com/php-http/HttplugBundle/blob/de33f9c14252f22093a5ec7d84f17535ab31a384/Collector/ProfilePlugin.php).
+
+## 1.5.0 - 2017-03-30
+
+### Added
+
+- `QueryDefaultsPlugin` to add default query parameters.
+
+## 1.4.2 - 2017-03-18
+
+### Deprecated
+
+- `DecoderPlugin` does not longer claim to support `compress` content encoding
+
+### Fixed
+
+- `CookiePlugin` allows main domain cookies to be sent/stored for subdomains
+- `DecoderPlugin` uses the right `FilteredStream` to handle `deflate` content encoding
+
+
+## 1.4.1 - 2017-02-20
+
+### Fixed
+
+- Cast return value of `StreamInterface::getSize` to string in `ContentLengthPlugin`
+
+
+## 1.4.0 - 2016-11-04
+
+### Added
+
+- Add Path plugin
+- Base URI plugin that combines Add Host and Add Path plugins
+
+
+## 1.3.0 - 2016-10-16
+
+### Changed
+
+- Fix Emulated Trait to use Http based promise which respect the HttpAsyncClient interface
+- Require Httplug 1.1 where we use HTTP specific promises.
+- RedirectPlugin: use the full URL instead of the URI to properly keep track of redirects
+- Add AddPathPlugin for API URLs with base path
+- Add BaseUriPlugin that combines AddHostPlugin and AddPathPlugin
+
+
+## 1.2.1 - 2016-07-26
+
+### Changed
+
+- AddHostPlugin also sets the port if specified
+
+
+## 1.2.0 - 2016-07-14
+
+### Added
+
+- Suggest separate plugins in composer.json
+- Introduced `debug_plugins` option for `PluginClient`
+
+
+## 1.1.0 - 2016-05-04
+
+### Added
+
+- Add a flexible http client providing both contract, and only emulating what's necessary
+- HTTP Client Router: route requests to underlying clients
+- Plugin client and core plugins moved here from `php-http/plugins`
+
+### Deprecated
+
+- Extending client classes, they will be made final in version 2.0
+
+
+## 1.0.0 - 2016-01-27
+
+### Changed
+
+- Remove useless interface in BatchException
+
+
+## 0.2.0 - 2016-01-12
+
+### Changed
+
+- Updated package files
+- Updated HTTPlug to RC1
+
+
+## 0.1.1 - 2015-12-26
+
+### Added
+
+- Emulated clients
+
+
+## 0.1.0 - 2015-12-25
+
+### Added
+
+- Batch client from utils
+- Methods client from utils
+- Emulators and decorators from client-tools
diff --git a/vendor/php-http/client-common/LICENSE b/vendor/php-http/client-common/LICENSE
new file mode 100644
index 00000000000..4558d6f0630
--- /dev/null
+++ b/vendor/php-http/client-common/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2015-2016 PHP HTTP Team <team@php-http.org>
+
+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/vendor/php-http/client-common/README.md b/vendor/php-http/client-common/README.md
new file mode 100644
index 00000000000..017bfcec93b
--- /dev/null
+++ b/vendor/php-http/client-common/README.md
@@ -0,0 +1,55 @@
+# HTTP Client Common
+
+[![Latest Version](https://img.shields.io/github/release/php-http/client-common.svg?style=flat-square)](https://github.com/php-http/client-common/releases)
+[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)
+[![Build Status](https://img.shields.io/travis/php-http/client-common.svg?style=flat-square)](https://travis-ci.org/php-http/client-common)
+[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/php-http/client-common.svg?style=flat-square)](https://scrutinizer-ci.com/g/php-http/client-common)
+[![Quality Score](https://img.shields.io/scrutinizer/g/php-http/client-common.svg?style=flat-square)](https://scrutinizer-ci.com/g/php-http/client-common)
+[![Total Downloads](https://img.shields.io/packagist/dt/php-http/client-common.svg?style=flat-square)](https://packagist.org/packages/php-http/client-common)
+
+**Common HTTP Client implementations and tools for HTTPlug.**
+
+
+## Install
+
+Via Composer
+
+``` bash
+$ composer require php-http/client-common
+```
+
+
+## Usage
+
+This package provides common tools for HTTP Clients:
+
+- BatchClient to handle sending requests in parallel
+- A convenience client with HTTP method names as class methods
+- Emulator, decorator layers for sync/async clients
+
+
+## Documentation
+
+Please see the [official documentation](http://docs.php-http.org/en/latest/components/client-common.html).
+
+
+## Testing
+
+``` bash
+$ composer test
+```
+
+
+## Contributing
+
+Please see our [contributing guide](http://docs.php-http.org/en/latest/development/contributing.html).
+
+
+## Security
+
+If you discover any security related issues, please contact us at [security@php-http.org](mailto:security@php-http.org).
+
+
+## License
+
+The MIT License (MIT). Please see [License File](LICENSE) for more information.
diff --git a/vendor/php-http/client-common/composer.json b/vendor/php-http/client-common/composer.json
new file mode 100644
index 00000000000..fc5fc5fb4ea
--- /dev/null
+++ b/vendor/php-http/client-common/composer.json
@@ -0,0 +1,43 @@
+{
+    "name": "php-http/client-common",
+    "description": "Common HTTP Client implementations and tools for HTTPlug",
+    "license": "MIT",
+    "keywords": ["http", "client", "httplug", "common"],
+    "homepage": "http://httplug.io",
+    "authors": [
+        {
+            "name": "Márk Sági-Kazár",
+            "email": "mark.sagikazar@gmail.com"
+        }
+    ],
+    "require": {
+        "php": "^5.4 || ^7.0",
+        "php-http/httplug": "^1.1",
+        "php-http/message-factory": "^1.0",
+        "php-http/message": "^1.6",
+        "symfony/options-resolver": "^2.6 || ^3.0 || ^4.0"
+    },
+    "require-dev": {
+        "phpspec/phpspec": "^2.5 || ^3.4 || ^4.2",
+        "guzzlehttp/psr7": "^1.4"
+    },
+    "suggest": {
+        "php-http/logger-plugin": "PSR-3 Logger plugin",
+        "php-http/cache-plugin": "PSR-6 Cache plugin",
+        "php-http/stopwatch-plugin": "Symfony Stopwatch plugin"
+    },
+    "autoload": {
+        "psr-4": {
+            "Http\\Client\\Common\\": "src/"
+        }
+    },
+    "scripts": {
+        "test": "vendor/bin/phpspec run",
+        "test-ci": "vendor/bin/phpspec run -c phpspec.ci.yml"
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "1.7-dev"
+        }
+    }
+}
diff --git a/vendor/php-http/client-common/src/BatchClient.php b/vendor/php-http/client-common/src/BatchClient.php
new file mode 100644
index 00000000000..2036355b604
--- /dev/null
+++ b/vendor/php-http/client-common/src/BatchClient.php
@@ -0,0 +1,73 @@
+<?php
+
+namespace Http\Client\Common;
+
+use Http\Client\Exception;
+use Http\Client\HttpClient;
+use Http\Client\Common\Exception\BatchException;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * BatchClient allow to sends multiple request and retrieve a Batch Result.
+ *
+ * This implementation simply loops over the requests and uses sendRequest with each of them.
+ *
+ * @author Joel Wurtz <jwurtz@jolicode.com>
+ */
+class BatchClient implements HttpClient
+{
+    /**
+     * @var HttpClient
+     */
+    private $client;
+
+    /**
+     * @param HttpClient $client
+     */
+    public function __construct(HttpClient $client)
+    {
+        $this->client = $client;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function sendRequest(RequestInterface $request)
+    {
+        return $this->client->sendRequest($request);
+    }
+
+    /**
+     * Send several requests.
+     *
+     * You may not assume that the requests are executed in a particular order. If the order matters
+     * for your application, use sendRequest sequentially.
+     *
+     * @param RequestInterface[] The requests to send
+     *
+     * @return BatchResult Containing one result per request
+     *
+     * @throws BatchException If one or more requests fails. The exception gives access to the
+     *                        BatchResult with a map of request to result for success, request to
+     *                        exception for failures
+     */
+    public function sendRequests(array $requests)
+    {
+        $batchResult = new BatchResult();
+
+        foreach ($requests as $request) {
+            try {
+                $response = $this->sendRequest($request);
+                $batchResult = $batchResult->addResponse($request, $response);
+            } catch (Exception $e) {
+                $batchResult = $batchResult->addException($request, $e);
+            }
+        }
+
+        if ($batchResult->hasExceptions()) {
+            throw new BatchException($batchResult);
+        }
+
+        return $batchResult;
+    }
+}
diff --git a/vendor/php-http/client-common/src/BatchResult.php b/vendor/php-http/client-common/src/BatchResult.php
new file mode 100644
index 00000000000..710611d6d00
--- /dev/null
+++ b/vendor/php-http/client-common/src/BatchResult.php
@@ -0,0 +1,181 @@
+<?php
+
+namespace Http\Client\Common;
+
+use Http\Client\Exception;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Responses and exceptions returned from parallel request execution.
+ *
+ * @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
+ */
+final class BatchResult
+{
+    /**
+     * @var \SplObjectStorage
+     */
+    private $responses;
+
+    /**
+     * @var \SplObjectStorage
+     */
+    private $exceptions;
+
+    public function __construct()
+    {
+        $this->responses = new \SplObjectStorage();
+        $this->exceptions = new \SplObjectStorage();
+    }
+
+    /**
+     * Checks if there are any successful responses at all.
+     *
+     * @return bool
+     */
+    public function hasResponses()
+    {
+        return $this->responses->count() > 0;
+    }
+
+    /**
+     * Returns all successful responses.
+     *
+     * @return ResponseInterface[]
+     */
+    public function getResponses()
+    {
+        $responses = [];
+
+        foreach ($this->responses as $request) {
+            $responses[] = $this->responses[$request];
+        }
+
+        return $responses;
+    }
+
+    /**
+     * Checks if there is a successful response for a request.
+     *
+     * @param RequestInterface $request
+     *
+     * @return bool
+     */
+    public function isSuccessful(RequestInterface $request)
+    {
+        return $this->responses->contains($request);
+    }
+
+    /**
+     * Returns the response for a successful request.
+     *
+     * @param RequestInterface $request
+     *
+     * @return ResponseInterface
+     *
+     * @throws \UnexpectedValueException If request was not part of the batch or failed
+     */
+    public function getResponseFor(RequestInterface $request)
+    {
+        try {
+            return $this->responses[$request];
+        } catch (\UnexpectedValueException $e) {
+            throw new \UnexpectedValueException('Request not found', $e->getCode(), $e);
+        }
+    }
+
+    /**
+     * Adds a response in an immutable way.
+     *
+     * @param RequestInterface  $request
+     * @param ResponseInterface $response
+     *
+     * @return BatchResult the new BatchResult with this request-response pair added to it
+     */
+    public function addResponse(RequestInterface $request, ResponseInterface $response)
+    {
+        $new = clone $this;
+        $new->responses->attach($request, $response);
+
+        return $new;
+    }
+
+    /**
+     * Checks if there are any unsuccessful requests at all.
+     *
+     * @return bool
+     */
+    public function hasExceptions()
+    {
+        return $this->exceptions->count() > 0;
+    }
+
+    /**
+     * Returns all exceptions for the unsuccessful requests.
+     *
+     * @return Exception[]
+     */
+    public function getExceptions()
+    {
+        $exceptions = [];
+
+        foreach ($this->exceptions as $request) {
+            $exceptions[] = $this->exceptions[$request];
+        }
+
+        return $exceptions;
+    }
+
+    /**
+     * Checks if there is an exception for a request, meaning the request failed.
+     *
+     * @param RequestInterface $request
+     *
+     * @return bool
+     */
+    public function isFailed(RequestInterface $request)
+    {
+        return $this->exceptions->contains($request);
+    }
+
+    /**
+     * Returns the exception for a failed request.
+     *
+     * @param RequestInterface $request
+     *
+     * @return Exception
+     *
+     * @throws \UnexpectedValueException If request was not part of the batch or was successful
+     */
+    public function getExceptionFor(RequestInterface $request)
+    {
+        try {
+            return $this->exceptions[$request];
+        } catch (\UnexpectedValueException $e) {
+            throw new \UnexpectedValueException('Request not found', $e->getCode(), $e);
+        }
+    }
+
+    /**
+     * Adds an exception in an immutable way.
+     *
+     * @param RequestInterface $request
+     * @param Exception        $exception
+     *
+     * @return BatchResult the new BatchResult with this request-exception pair added to it
+     */
+    public function addException(RequestInterface $request, Exception $exception)
+    {
+        $new = clone $this;
+        $new->exceptions->attach($request, $exception);
+
+        return $new;
+    }
+
+    public function __clone()
+    {
+        $this->responses = clone $this->responses;
+        $this->exceptions = clone $this->exceptions;
+    }
+}
diff --git a/vendor/php-http/client-common/src/EmulatedHttpAsyncClient.php b/vendor/php-http/client-common/src/EmulatedHttpAsyncClient.php
new file mode 100644
index 00000000000..1b163167e6d
--- /dev/null
+++ b/vendor/php-http/client-common/src/EmulatedHttpAsyncClient.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Http\Client\Common;
+
+use Http\Client\HttpAsyncClient;
+use Http\Client\HttpClient;
+
+/**
+ * Emulates an async HTTP client.
+ *
+ * This should be replaced by an anonymous class in PHP 7.
+ *
+ * @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
+ */
+class EmulatedHttpAsyncClient implements HttpClient, HttpAsyncClient
+{
+    use HttpAsyncClientEmulator;
+    use HttpClientDecorator;
+
+    /**
+     * @param HttpClient $httpClient
+     */
+    public function __construct(HttpClient $httpClient)
+    {
+        $this->httpClient = $httpClient;
+    }
+}
diff --git a/vendor/php-http/client-common/src/EmulatedHttpClient.php b/vendor/php-http/client-common/src/EmulatedHttpClient.php
new file mode 100644
index 00000000000..01046c83e4c
--- /dev/null
+++ b/vendor/php-http/client-common/src/EmulatedHttpClient.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Http\Client\Common;
+
+use Http\Client\HttpAsyncClient;
+use Http\Client\HttpClient;
+
+/**
+ * Emulates an HTTP client.
+ *
+ * This should be replaced by an anonymous class in PHP 7.
+ *
+ * @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
+ */
+class EmulatedHttpClient implements HttpClient, HttpAsyncClient
+{
+    use HttpAsyncClientDecorator;
+    use HttpClientEmulator;
+
+    /**
+     * @param HttpAsyncClient $httpAsyncClient
+     */
+    public function __construct(HttpAsyncClient $httpAsyncClient)
+    {
+        $this->httpAsyncClient = $httpAsyncClient;
+    }
+}
diff --git a/vendor/php-http/client-common/src/Exception/BatchException.php b/vendor/php-http/client-common/src/Exception/BatchException.php
new file mode 100644
index 00000000000..66a92719e4a
--- /dev/null
+++ b/vendor/php-http/client-common/src/Exception/BatchException.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace Http\Client\Common\Exception;
+
+use Http\Client\Exception\TransferException;
+use Http\Client\Common\BatchResult;
+
+/**
+ * This exception is thrown when HttpClient::sendRequests led to at least one failure.
+ *
+ * It gives access to a BatchResult with the request-exception and request-response pairs.
+ *
+ * @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
+ */
+final class BatchException extends TransferException
+{
+    /**
+     * @var BatchResult
+     */
+    private $result;
+
+    /**
+     * @param BatchResult $result
+     */
+    public function __construct(BatchResult $result)
+    {
+        $this->result = $result;
+    }
+
+    /**
+     * Returns the BatchResult that contains all responses and exceptions.
+     *
+     * @return BatchResult
+     */
+    public function getResult()
+    {
+        return $this->result;
+    }
+}
diff --git a/vendor/php-http/client-common/src/Exception/CircularRedirectionException.php b/vendor/php-http/client-common/src/Exception/CircularRedirectionException.php
new file mode 100644
index 00000000000..73ec521e173
--- /dev/null
+++ b/vendor/php-http/client-common/src/Exception/CircularRedirectionException.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Http\Client\Common\Exception;
+
+use Http\Client\Exception\HttpException;
+
+/**
+ * Thrown when circular redirection is detected.
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+class CircularRedirectionException extends HttpException
+{
+}
diff --git a/vendor/php-http/client-common/src/Exception/ClientErrorException.php b/vendor/php-http/client-common/src/Exception/ClientErrorException.php
new file mode 100644
index 00000000000..b1f6cc855eb
--- /dev/null
+++ b/vendor/php-http/client-common/src/Exception/ClientErrorException.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Http\Client\Common\Exception;
+
+use Http\Client\Exception\HttpException;
+
+/**
+ * Thrown when there is a client error (4xx).
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+class ClientErrorException extends HttpException
+{
+}
diff --git a/vendor/php-http/client-common/src/Exception/HttpClientNotFoundException.php b/vendor/php-http/client-common/src/Exception/HttpClientNotFoundException.php
new file mode 100644
index 00000000000..5d33f983836
--- /dev/null
+++ b/vendor/php-http/client-common/src/Exception/HttpClientNotFoundException.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Http\Client\Common\Exception;
+
+use Http\Client\Exception\TransferException;
+
+/**
+ * Thrown when a http client cannot be chosen in a pool.
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+class HttpClientNotFoundException extends TransferException
+{
+}
diff --git a/vendor/php-http/client-common/src/Exception/LoopException.php b/vendor/php-http/client-common/src/Exception/LoopException.php
new file mode 100644
index 00000000000..e834124df60
--- /dev/null
+++ b/vendor/php-http/client-common/src/Exception/LoopException.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Http\Client\Common\Exception;
+
+use Http\Client\Exception\RequestException;
+
+/**
+ * Thrown when the Plugin Client detects an endless loop.
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+class LoopException extends RequestException
+{
+}
diff --git a/vendor/php-http/client-common/src/Exception/MultipleRedirectionException.php b/vendor/php-http/client-common/src/Exception/MultipleRedirectionException.php
new file mode 100644
index 00000000000..ae514cd738c
--- /dev/null
+++ b/vendor/php-http/client-common/src/Exception/MultipleRedirectionException.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Http\Client\Common\Exception;
+
+use Http\Client\Exception\HttpException;
+
+/**
+ * Redirect location cannot be chosen.
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+class MultipleRedirectionException extends HttpException
+{
+}
diff --git a/vendor/php-http/client-common/src/Exception/ServerErrorException.php b/vendor/php-http/client-common/src/Exception/ServerErrorException.php
new file mode 100644
index 00000000000..665d72418b0
--- /dev/null
+++ b/vendor/php-http/client-common/src/Exception/ServerErrorException.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Http\Client\Common\Exception;
+
+use Http\Client\Exception\HttpException;
+
+/**
+ * Thrown when there is a server error (5xx).
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+class ServerErrorException extends HttpException
+{
+}
diff --git a/vendor/php-http/client-common/src/FlexibleHttpClient.php b/vendor/php-http/client-common/src/FlexibleHttpClient.php
new file mode 100644
index 00000000000..58f88132d26
--- /dev/null
+++ b/vendor/php-http/client-common/src/FlexibleHttpClient.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace Http\Client\Common;
+
+use Http\Client\HttpAsyncClient;
+use Http\Client\HttpClient;
+
+/**
+ * A flexible http client, which implements both interface and will emulate
+ * one contract, the other, or none at all depending on the injected client contract.
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+final class FlexibleHttpClient implements HttpClient, HttpAsyncClient
+{
+    use HttpClientDecorator;
+    use HttpAsyncClientDecorator;
+
+    /**
+     * @param HttpClient|HttpAsyncClient $client
+     */
+    public function __construct($client)
+    {
+        if (!($client instanceof HttpClient) && !($client instanceof HttpAsyncClient)) {
+            throw new \LogicException('Client must be an instance of Http\\Client\\HttpClient or Http\\Client\\HttpAsyncClient');
+        }
+
+        $this->httpClient = $client;
+        $this->httpAsyncClient = $client;
+
+        if (!($this->httpClient instanceof HttpClient)) {
+            $this->httpClient = new EmulatedHttpClient($this->httpClient);
+        }
+
+        if (!($this->httpAsyncClient instanceof HttpAsyncClient)) {
+            $this->httpAsyncClient = new EmulatedHttpAsyncClient($this->httpAsyncClient);
+        }
+    }
+}
diff --git a/vendor/php-http/client-common/src/HttpAsyncClientDecorator.php b/vendor/php-http/client-common/src/HttpAsyncClientDecorator.php
new file mode 100644
index 00000000000..6eb576cdb15
--- /dev/null
+++ b/vendor/php-http/client-common/src/HttpAsyncClientDecorator.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace Http\Client\Common;
+
+use Http\Client\HttpAsyncClient;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Decorates an HTTP Async Client.
+ *
+ * @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
+ */
+trait HttpAsyncClientDecorator
+{
+    /**
+     * @var HttpAsyncClient
+     */
+    protected $httpAsyncClient;
+
+    /**
+     * {@inheritdoc}
+     *
+     * @see HttpAsyncClient::sendAsyncRequest
+     */
+    public function sendAsyncRequest(RequestInterface $request)
+    {
+        return $this->httpAsyncClient->sendAsyncRequest($request);
+    }
+}
diff --git a/vendor/php-http/client-common/src/HttpAsyncClientEmulator.php b/vendor/php-http/client-common/src/HttpAsyncClientEmulator.php
new file mode 100644
index 00000000000..c0ba354f87c
--- /dev/null
+++ b/vendor/php-http/client-common/src/HttpAsyncClientEmulator.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace Http\Client\Common;
+
+use Http\Client\Exception;
+use Http\Client\Promise;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Emulates an HTTP Async Client in an HTTP Client.
+ *
+ * @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
+ */
+trait HttpAsyncClientEmulator
+{
+    /**
+     * {@inheritdoc}
+     *
+     * @see HttpClient::sendRequest
+     */
+    abstract public function sendRequest(RequestInterface $request);
+
+    /**
+     * {@inheritdoc}
+     *
+     * @see HttpAsyncClient::sendAsyncRequest
+     */
+    public function sendAsyncRequest(RequestInterface $request)
+    {
+        try {
+            return new Promise\HttpFulfilledPromise($this->sendRequest($request));
+        } catch (Exception $e) {
+            return new Promise\HttpRejectedPromise($e);
+        }
+    }
+}
diff --git a/vendor/php-http/client-common/src/HttpClientDecorator.php b/vendor/php-http/client-common/src/HttpClientDecorator.php
new file mode 100644
index 00000000000..a33d5efd79e
--- /dev/null
+++ b/vendor/php-http/client-common/src/HttpClientDecorator.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace Http\Client\Common;
+
+use Http\Client\HttpClient;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Decorates an HTTP Client.
+ *
+ * @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
+ */
+trait HttpClientDecorator
+{
+    /**
+     * @var HttpClient
+     */
+    protected $httpClient;
+
+    /**
+     * {@inheritdoc}
+     *
+     * @see HttpClient::sendRequest
+     */
+    public function sendRequest(RequestInterface $request)
+    {
+        return $this->httpClient->sendRequest($request);
+    }
+}
diff --git a/vendor/php-http/client-common/src/HttpClientEmulator.php b/vendor/php-http/client-common/src/HttpClientEmulator.php
new file mode 100644
index 00000000000..dbec1aba330
--- /dev/null
+++ b/vendor/php-http/client-common/src/HttpClientEmulator.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Http\Client\Common;
+
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Emulates an HTTP Client in an HTTP Async Client.
+ *
+ * @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
+ */
+trait HttpClientEmulator
+{
+    /**
+     * {@inheritdoc}
+     *
+     * @see HttpClient::sendRequest
+     */
+    public function sendRequest(RequestInterface $request)
+    {
+        $promise = $this->sendAsyncRequest($request);
+
+        return $promise->wait();
+    }
+
+    /**
+     * {@inheritdoc}
+     *
+     * @see HttpAsyncClient::sendAsyncRequest
+     */
+    abstract public function sendAsyncRequest(RequestInterface $request);
+}
diff --git a/vendor/php-http/client-common/src/HttpClientPool.php b/vendor/php-http/client-common/src/HttpClientPool.php
new file mode 100644
index 00000000000..7ac292ca138
--- /dev/null
+++ b/vendor/php-http/client-common/src/HttpClientPool.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace Http\Client\Common;
+
+use Http\Client\Common\Exception\HttpClientNotFoundException;
+use Http\Client\HttpAsyncClient;
+use Http\Client\HttpClient;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * A http client pool allows to send requests on a pool of different http client using a specific strategy (least used,
+ * round robin, ...).
+ */
+abstract class HttpClientPool implements HttpAsyncClient, HttpClient
+{
+    /**
+     * @var HttpClientPoolItem[]
+     */
+    protected $clientPool = [];
+
+    /**
+     * Add a client to the pool.
+     *
+     * @param HttpClient|HttpAsyncClient|HttpClientPoolItem $client
+     */
+    public function addHttpClient($client)
+    {
+        if (!$client instanceof HttpClientPoolItem) {
+            $client = new HttpClientPoolItem($client);
+        }
+
+        $this->clientPool[] = $client;
+    }
+
+    /**
+     * Return an http client given a specific strategy.
+     *
+     * @throws HttpClientNotFoundException When no http client has been found into the pool
+     *
+     * @return HttpClientPoolItem Return a http client that can do both sync or async
+     */
+    abstract protected function chooseHttpClient();
+
+    /**
+     * {@inheritdoc}
+     */
+    public function sendAsyncRequest(RequestInterface $request)
+    {
+        return $this->chooseHttpClient()->sendAsyncRequest($request);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function sendRequest(RequestInterface $request)
+    {
+        return $this->chooseHttpClient()->sendRequest($request);
+    }
+}
diff --git a/vendor/php-http/client-common/src/HttpClientPool/LeastUsedClientPool.php b/vendor/php-http/client-common/src/HttpClientPool/LeastUsedClientPool.php
new file mode 100644
index 00000000000..6299cceb60f
--- /dev/null
+++ b/vendor/php-http/client-common/src/HttpClientPool/LeastUsedClientPool.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace Http\Client\Common\HttpClientPool;
+
+use Http\Client\Common\Exception\HttpClientNotFoundException;
+use Http\Client\Common\HttpClientPool;
+use Http\Client\Common\HttpClientPoolItem;
+
+/**
+ * LeastUsedClientPool will choose the client with the less current request in the pool.
+ *
+ * This strategy is only useful when doing async request
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+final class LeastUsedClientPool extends HttpClientPool
+{
+    /**
+     * {@inheritdoc}
+     */
+    protected function chooseHttpClient()
+    {
+        $clientPool = array_filter($this->clientPool, function (HttpClientPoolItem $clientPoolItem) {
+            return !$clientPoolItem->isDisabled();
+        });
+
+        if (0 === count($clientPool)) {
+            throw new HttpClientNotFoundException('Cannot choose a http client as there is no one present in the pool');
+        }
+
+        usort($clientPool, function (HttpClientPoolItem $clientA, HttpClientPoolItem $clientB) {
+            if ($clientA->getSendingRequestCount() === $clientB->getSendingRequestCount()) {
+                return 0;
+            }
+
+            if ($clientA->getSendingRequestCount() < $clientB->getSendingRequestCount()) {
+                return -1;
+            }
+
+            return 1;
+        });
+
+        return reset($clientPool);
+    }
+}
diff --git a/vendor/php-http/client-common/src/HttpClientPool/RandomClientPool.php b/vendor/php-http/client-common/src/HttpClientPool/RandomClientPool.php
new file mode 100644
index 00000000000..3255f865df3
--- /dev/null
+++ b/vendor/php-http/client-common/src/HttpClientPool/RandomClientPool.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Http\Client\Common\HttpClientPool;
+
+use Http\Client\Common\Exception\HttpClientNotFoundException;
+use Http\Client\Common\HttpClientPool;
+use Http\Client\Common\HttpClientPoolItem;
+
+/**
+ * RoundRobinClientPool will choose the next client in the pool.
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+final class RandomClientPool extends HttpClientPool
+{
+    /**
+     * {@inheritdoc}
+     */
+    protected function chooseHttpClient()
+    {
+        $clientPool = array_filter($this->clientPool, function (HttpClientPoolItem $clientPoolItem) {
+            return !$clientPoolItem->isDisabled();
+        });
+
+        if (0 === count($clientPool)) {
+            throw new HttpClientNotFoundException('Cannot choose a http client as there is no one present in the pool');
+        }
+
+        return $clientPool[array_rand($clientPool)];
+    }
+}
diff --git a/vendor/php-http/client-common/src/HttpClientPool/RoundRobinClientPool.php b/vendor/php-http/client-common/src/HttpClientPool/RoundRobinClientPool.php
new file mode 100644
index 00000000000..8d8e40a013b
--- /dev/null
+++ b/vendor/php-http/client-common/src/HttpClientPool/RoundRobinClientPool.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace Http\Client\Common\HttpClientPool;
+
+use Http\Client\Common\Exception\HttpClientNotFoundException;
+use Http\Client\Common\HttpClientPool;
+
+/**
+ * RoundRobinClientPool will choose the next client in the pool.
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+final class RoundRobinClientPool extends HttpClientPool
+{
+    /**
+     * {@inheritdoc}
+     */
+    protected function chooseHttpClient()
+    {
+        $last = current($this->clientPool);
+
+        do {
+            $client = next($this->clientPool);
+
+            if (false === $client) {
+                $client = reset($this->clientPool);
+
+                if (false === $client) {
+                    throw new HttpClientNotFoundException('Cannot choose a http client as there is no one present in the pool');
+                }
+            }
+
+            // Case when there is only one and the last one has been disabled
+            if ($last === $client && $client->isDisabled()) {
+                throw new HttpClientNotFoundException('Cannot choose a http client as there is no one enabled in the pool');
+            }
+        } while ($client->isDisabled());
+
+        return $client;
+    }
+}
diff --git a/vendor/php-http/client-common/src/HttpClientPoolItem.php b/vendor/php-http/client-common/src/HttpClientPoolItem.php
new file mode 100644
index 00000000000..09cd6ddf1c9
--- /dev/null
+++ b/vendor/php-http/client-common/src/HttpClientPoolItem.php
@@ -0,0 +1,178 @@
+<?php
+
+namespace Http\Client\Common;
+
+use Http\Client\HttpAsyncClient;
+use Http\Client\HttpClient;
+use Psr\Http\Message\RequestInterface;
+use Http\Client\Exception;
+
+/**
+ * A HttpClientPoolItem represent a HttpClient inside a Pool.
+ *
+ * It is disabled when a request failed and can be reenable after a certain number of seconds
+ * It also keep tracks of the current number of request the client is currently sending (only usable for async method)
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+class HttpClientPoolItem implements HttpClient, HttpAsyncClient
+{
+    /**
+     * @var int Number of request this client is currently sending
+     */
+    private $sendingRequestCount = 0;
+
+    /**
+     * @var \DateTime|null Time when this client has been disabled or null if enable
+     */
+    private $disabledAt;
+
+    /**
+     * @var int|null Number of seconds after this client is reenable, by default null: never reenable this client
+     */
+    private $reenableAfter;
+
+    /**
+     * @var FlexibleHttpClient A http client responding to async and sync request
+     */
+    private $client;
+
+    /**
+     * @param HttpClient|HttpAsyncClient $client
+     * @param null|int                   $reenableAfter Number of seconds after this client is reenable
+     */
+    public function __construct($client, $reenableAfter = null)
+    {
+        $this->client = new FlexibleHttpClient($client);
+        $this->reenableAfter = $reenableAfter;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function sendRequest(RequestInterface $request)
+    {
+        if ($this->isDisabled()) {
+            throw new Exception\RequestException('Cannot send the request as this client has been disabled', $request);
+        }
+
+        try {
+            $this->incrementRequestCount();
+            $response = $this->client->sendRequest($request);
+            $this->decrementRequestCount();
+        } catch (Exception $e) {
+            $this->disable();
+            $this->decrementRequestCount();
+
+            throw $e;
+        }
+
+        return $response;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function sendAsyncRequest(RequestInterface $request)
+    {
+        if ($this->isDisabled()) {
+            throw new Exception\RequestException('Cannot send the request as this client has been disabled', $request);
+        }
+
+        $this->incrementRequestCount();
+
+        return $this->client->sendAsyncRequest($request)->then(function ($response) {
+            $this->decrementRequestCount();
+
+            return $response;
+        }, function ($exception) {
+            $this->disable();
+            $this->decrementRequestCount();
+
+            throw $exception;
+        });
+    }
+
+    /**
+     * Whether this client is disabled or not.
+     *
+     * Will also reactivate this client if possible
+     *
+     * @internal
+     *
+     * @return bool
+     */
+    public function isDisabled()
+    {
+        $disabledAt = $this->getDisabledAt();
+
+        if (null !== $this->reenableAfter && null !== $disabledAt) {
+            // Reenable after a certain time
+            $now = new \DateTime();
+
+            if (($now->getTimestamp() - $disabledAt->getTimestamp()) >= $this->reenableAfter) {
+                $this->enable();
+
+                return false;
+            }
+
+            return true;
+        }
+
+        return null !== $disabledAt;
+    }
+
+    /**
+     * Get current number of request that is send by the underlying http client.
+     *
+     * @internal
+     *
+     * @return int
+     */
+    public function getSendingRequestCount()
+    {
+        return $this->sendingRequestCount;
+    }
+
+    /**
+     * Return when this client has been disabled or null if it's enabled.
+     *
+     * @return \DateTime|null
+     */
+    private function getDisabledAt()
+    {
+        return $this->disabledAt;
+    }
+
+    /**
+     * Increment the request count.
+     */
+    private function incrementRequestCount()
+    {
+        ++$this->sendingRequestCount;
+    }
+
+    /**
+     * Decrement the request count.
+     */
+    private function decrementRequestCount()
+    {
+        --$this->sendingRequestCount;
+    }
+
+    /**
+     * Enable the current client.
+     */
+    private function enable()
+    {
+        $this->disabledAt = null;
+    }
+
+    /**
+     * Disable the current client.
+     */
+    private function disable()
+    {
+        $this->disabledAt = new \DateTime('now');
+    }
+}
diff --git a/vendor/php-http/client-common/src/HttpClientRouter.php b/vendor/php-http/client-common/src/HttpClientRouter.php
new file mode 100644
index 00000000000..9f721336a17
--- /dev/null
+++ b/vendor/php-http/client-common/src/HttpClientRouter.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace Http\Client\Common;
+
+use Http\Client\Exception\RequestException;
+use Http\Client\HttpAsyncClient;
+use Http\Client\HttpClient;
+use Http\Message\RequestMatcher;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Route a request to a specific client in the stack based using a RequestMatcher.
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+final class HttpClientRouter implements HttpClient, HttpAsyncClient
+{
+    /**
+     * @var array
+     */
+    private $clients = [];
+
+    /**
+     * {@inheritdoc}
+     */
+    public function sendRequest(RequestInterface $request)
+    {
+        $client = $this->chooseHttpClient($request);
+
+        return $client->sendRequest($request);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function sendAsyncRequest(RequestInterface $request)
+    {
+        $client = $this->chooseHttpClient($request);
+
+        return $client->sendAsyncRequest($request);
+    }
+
+    /**
+     * Add a client to the router.
+     *
+     * @param HttpClient|HttpAsyncClient $client
+     * @param RequestMatcher             $requestMatcher
+     */
+    public function addClient($client, RequestMatcher $requestMatcher)
+    {
+        $this->clients[] = [
+            'matcher' => $requestMatcher,
+            'client' => new FlexibleHttpClient($client),
+        ];
+    }
+
+    /**
+     * Choose an HTTP client given a specific request.
+     *
+     * @param RequestInterface $request
+     *
+     * @return HttpClient|HttpAsyncClient
+     */
+    protected function chooseHttpClient(RequestInterface $request)
+    {
+        foreach ($this->clients as $client) {
+            if ($client['matcher']->matches($request)) {
+                return $client['client'];
+            }
+        }
+
+        throw new RequestException('No client found for the specified request', $request);
+    }
+}
diff --git a/vendor/php-http/client-common/src/HttpMethodsClient.php b/vendor/php-http/client-common/src/HttpMethodsClient.php
new file mode 100644
index 00000000000..58804fc243f
--- /dev/null
+++ b/vendor/php-http/client-common/src/HttpMethodsClient.php
@@ -0,0 +1,205 @@
+<?php
+
+namespace Http\Client\Common;
+
+use Http\Client\Exception;
+use Http\Client\HttpClient;
+use Http\Message\RequestFactory;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\StreamInterface;
+use Psr\Http\Message\UriInterface;
+
+/**
+ * Convenience HTTP client that integrates the MessageFactory in order to send
+ * requests in the following form:.
+ *
+ * $client
+ *     ->get('/foo')
+ *     ->post('/bar')
+ * ;
+ *
+ * The client also exposes the sendRequest methods of the wrapped HttpClient.
+ *
+ * @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
+ * @author David Buchmann <mail@davidbu.ch>
+ */
+class HttpMethodsClient implements HttpClient
+{
+    /**
+     * @var HttpClient
+     */
+    private $httpClient;
+
+    /**
+     * @var RequestFactory
+     */
+    private $requestFactory;
+
+    /**
+     * @param HttpClient     $httpClient     The client to send requests with
+     * @param RequestFactory $requestFactory The message factory to create requests
+     */
+    public function __construct(HttpClient $httpClient, RequestFactory $requestFactory)
+    {
+        $this->httpClient = $httpClient;
+        $this->requestFactory = $requestFactory;
+    }
+
+    /**
+     * Sends a GET request.
+     *
+     * @param string|UriInterface $uri
+     * @param array               $headers
+     *
+     * @throws Exception
+     *
+     * @return ResponseInterface
+     */
+    public function get($uri, array $headers = [])
+    {
+        return $this->send('GET', $uri, $headers, null);
+    }
+
+    /**
+     * Sends an HEAD request.
+     *
+     * @param string|UriInterface $uri
+     * @param array               $headers
+     *
+     * @throws Exception
+     *
+     * @return ResponseInterface
+     */
+    public function head($uri, array $headers = [])
+    {
+        return $this->send('HEAD', $uri, $headers, null);
+    }
+
+    /**
+     * Sends a TRACE request.
+     *
+     * @param string|UriInterface $uri
+     * @param array               $headers
+     *
+     * @throws Exception
+     *
+     * @return ResponseInterface
+     */
+    public function trace($uri, array $headers = [])
+    {
+        return $this->send('TRACE', $uri, $headers, null);
+    }
+
+    /**
+     * Sends a POST request.
+     *
+     * @param string|UriInterface         $uri
+     * @param array                       $headers
+     * @param string|StreamInterface|null $body
+     *
+     * @throws Exception
+     *
+     * @return ResponseInterface
+     */
+    public function post($uri, array $headers = [], $body = null)
+    {
+        return $this->send('POST', $uri, $headers, $body);
+    }
+
+    /**
+     * Sends a PUT request.
+     *
+     * @param string|UriInterface         $uri
+     * @param array                       $headers
+     * @param string|StreamInterface|null $body
+     *
+     * @throws Exception
+     *
+     * @return ResponseInterface
+     */
+    public function put($uri, array $headers = [], $body = null)
+    {
+        return $this->send('PUT', $uri, $headers, $body);
+    }
+
+    /**
+     * Sends a PATCH request.
+     *
+     * @param string|UriInterface         $uri
+     * @param array                       $headers
+     * @param string|StreamInterface|null $body
+     *
+     * @throws Exception
+     *
+     * @return ResponseInterface
+     */
+    public function patch($uri, array $headers = [], $body = null)
+    {
+        return $this->send('PATCH', $uri, $headers, $body);
+    }
+
+    /**
+     * Sends a DELETE request.
+     *
+     * @param string|UriInterface         $uri
+     * @param array                       $headers
+     * @param string|StreamInterface|null $body
+     *
+     * @throws Exception
+     *
+     * @return ResponseInterface
+     */
+    public function delete($uri, array $headers = [], $body = null)
+    {
+        return $this->send('DELETE', $uri, $headers, $body);
+    }
+
+    /**
+     * Sends an OPTIONS request.
+     *
+     * @param string|UriInterface         $uri
+     * @param array                       $headers
+     * @param string|StreamInterface|null $body
+     *
+     * @throws Exception
+     *
+     * @return ResponseInterface
+     */
+    public function options($uri, array $headers = [], $body = null)
+    {
+        return $this->send('OPTIONS', $uri, $headers, $body);
+    }
+
+    /**
+     * Sends a request with any HTTP method.
+     *
+     * @param string                      $method  HTTP method to use
+     * @param string|UriInterface         $uri
+     * @param array                       $headers
+     * @param string|StreamInterface|null $body
+     *
+     * @throws Exception
+     *
+     * @return ResponseInterface
+     */
+    public function send($method, $uri, array $headers = [], $body = null)
+    {
+        return $this->sendRequest($this->requestFactory->createRequest(
+            $method,
+            $uri,
+            $headers,
+            $body
+        ));
+    }
+
+    /**
+     * Forward to the underlying HttpClient.
+     *
+     * {@inheritdoc}
+     */
+    public function sendRequest(RequestInterface $request)
+    {
+        return $this->httpClient->sendRequest($request);
+    }
+}
diff --git a/vendor/php-http/client-common/src/Plugin.php b/vendor/php-http/client-common/src/Plugin.php
new file mode 100644
index 00000000000..89a2a622d46
--- /dev/null
+++ b/vendor/php-http/client-common/src/Plugin.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Http\Client\Common;
+
+use Http\Promise\Promise;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * A plugin is a middleware to transform the request and/or the response.
+ *
+ * The plugin can:
+ *  - break the chain and return a response
+ *  - dispatch the request to the next middleware
+ *  - restart the request
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+interface Plugin
+{
+    /**
+     * Handle the request and return the response coming from the next callable.
+     *
+     * @see http://docs.php-http.org/en/latest/plugins/build-your-own.html
+     *
+     * @param RequestInterface $request
+     * @param callable         $next    Next middleware in the chain, the request is passed as the first argument
+     * @param callable         $first   First middleware in the chain, used to to restart a request
+     *
+     * @return Promise Resolves a PSR-7 Response or fails with an Http\Client\Exception (The same as HttpAsyncClient).
+     */
+    public function handleRequest(RequestInterface $request, callable $next, callable $first);
+}
diff --git a/vendor/php-http/client-common/src/Plugin/AddHostPlugin.php b/vendor/php-http/client-common/src/Plugin/AddHostPlugin.php
new file mode 100644
index 00000000000..29ab8ae8409
--- /dev/null
+++ b/vendor/php-http/client-common/src/Plugin/AddHostPlugin.php
@@ -0,0 +1,77 @@
+<?php
+
+namespace Http\Client\Common\Plugin;
+
+use Http\Client\Common\Plugin;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\UriInterface;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+
+/**
+ * Add schema, host and port to a request. Can be set to overwrite the schema and host if desired.
+ *
+ * @author Tobias Nyholm <tobias.nyholm@gmail.com>
+ */
+final class AddHostPlugin implements Plugin
+{
+    /**
+     * @var UriInterface
+     */
+    private $host;
+
+    /**
+     * @var bool
+     */
+    private $replace;
+
+    /**
+     * @param UriInterface $host
+     * @param array        $config {
+     *
+     *     @var bool $replace True will replace all hosts, false will only add host when none is specified.
+     * }
+     */
+    public function __construct(UriInterface $host, array $config = [])
+    {
+        if ('' === $host->getHost()) {
+            throw new \LogicException('Host can not be empty');
+        }
+
+        $this->host = $host;
+
+        $resolver = new OptionsResolver();
+        $this->configureOptions($resolver);
+        $options = $resolver->resolve($config);
+
+        $this->replace = $options['replace'];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function handleRequest(RequestInterface $request, callable $next, callable $first)
+    {
+        if ($this->replace || '' === $request->getUri()->getHost()) {
+            $uri = $request->getUri()
+                ->withHost($this->host->getHost())
+                ->withScheme($this->host->getScheme())
+                ->withPort($this->host->getPort())
+            ;
+
+            $request = $request->withUri($uri);
+        }
+
+        return $next($request);
+    }
+
+    /**
+     * @param OptionsResolver $resolver
+     */
+    private function configureOptions(OptionsResolver $resolver)
+    {
+        $resolver->setDefaults([
+            'replace' => false,
+        ]);
+        $resolver->setAllowedTypes('replace', 'bool');
+    }
+}
diff --git a/vendor/php-http/client-common/src/Plugin/AddPathPlugin.php b/vendor/php-http/client-common/src/Plugin/AddPathPlugin.php
new file mode 100644
index 00000000000..e24d61a4e42
--- /dev/null
+++ b/vendor/php-http/client-common/src/Plugin/AddPathPlugin.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace Http\Client\Common\Plugin;
+
+use Http\Client\Common\Plugin;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\UriInterface;
+
+/**
+ * Prepend a base path to the request URI. Useful for base API URLs like http://domain.com/api.
+ *
+ * @author Sullivan Senechal <soullivaneuh@gmail.com>
+ */
+final class AddPathPlugin implements Plugin
+{
+    /**
+     * @var UriInterface
+     */
+    private $uri;
+
+    /**
+     * @param UriInterface $uri
+     */
+    public function __construct(UriInterface $uri)
+    {
+        if ('' === $uri->getPath()) {
+            throw new \LogicException('URI path cannot be empty');
+        }
+
+        if ('/' === substr($uri->getPath(), -1)) {
+            throw new \LogicException('URI path cannot end with a slash.');
+        }
+
+        $this->uri = $uri;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function handleRequest(RequestInterface $request, callable $next, callable $first)
+    {
+        $request = $request->withUri($request->getUri()
+            ->withPath($this->uri->getPath().$request->getUri()->getPath())
+        );
+
+        return $next($request);
+    }
+}
diff --git a/vendor/php-http/client-common/src/Plugin/AuthenticationPlugin.php b/vendor/php-http/client-common/src/Plugin/AuthenticationPlugin.php
new file mode 100644
index 00000000000..194712fcde0
--- /dev/null
+++ b/vendor/php-http/client-common/src/Plugin/AuthenticationPlugin.php
@@ -0,0 +1,38 @@
+<?php
+
+namespace Http\Client\Common\Plugin;
+
+use Http\Client\Common\Plugin;
+use Http\Message\Authentication;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Send an authenticated request.
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+final class AuthenticationPlugin implements Plugin
+{
+    /**
+     * @var Authentication An authentication system
+     */
+    private $authentication;
+
+    /**
+     * @param Authentication $authentication
+     */
+    public function __construct(Authentication $authentication)
+    {
+        $this->authentication = $authentication;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function handleRequest(RequestInterface $request, callable $next, callable $first)
+    {
+        $request = $this->authentication->authenticate($request);
+
+        return $next($request);
+    }
+}
diff --git a/vendor/php-http/client-common/src/Plugin/BaseUriPlugin.php b/vendor/php-http/client-common/src/Plugin/BaseUriPlugin.php
new file mode 100644
index 00000000000..2c2a7752cf4
--- /dev/null
+++ b/vendor/php-http/client-common/src/Plugin/BaseUriPlugin.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace Http\Client\Common\Plugin;
+
+use Http\Client\Common\Plugin;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\UriInterface;
+
+/**
+ * Combines the AddHostPlugin and AddPathPlugin.
+ *
+ * @author Sullivan Senechal <soullivaneuh@gmail.com>
+ */
+final class BaseUriPlugin implements Plugin
+{
+    /**
+     * @var AddHostPlugin
+     */
+    private $addHostPlugin;
+
+    /**
+     * @var AddPathPlugin|null
+     */
+    private $addPathPlugin = null;
+
+    /**
+     * @param UriInterface $uri        Has to contain a host name and cans have a path.
+     * @param array        $hostConfig Config for AddHostPlugin. @see AddHostPlugin::configureOptions
+     */
+    public function __construct(UriInterface $uri, array $hostConfig = [])
+    {
+        $this->addHostPlugin = new AddHostPlugin($uri, $hostConfig);
+
+        if (rtrim($uri->getPath(), '/')) {
+            $this->addPathPlugin = new AddPathPlugin($uri);
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function handleRequest(RequestInterface $request, callable $next, callable $first)
+    {
+        $addHostNext = function (RequestInterface $request) use ($next, $first) {
+            return $this->addHostPlugin->handleRequest($request, $next, $first);
+        };
+
+        if ($this->addPathPlugin) {
+            return $this->addPathPlugin->handleRequest($request, $addHostNext, $first);
+        }
+
+        return $addHostNext($request);
+    }
+}
diff --git a/vendor/php-http/client-common/src/Plugin/ContentLengthPlugin.php b/vendor/php-http/client-common/src/Plugin/ContentLengthPlugin.php
new file mode 100644
index 00000000000..0f7aafaeda3
--- /dev/null
+++ b/vendor/php-http/client-common/src/Plugin/ContentLengthPlugin.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace Http\Client\Common\Plugin;
+
+use Http\Client\Common\Plugin;
+use Http\Message\Encoding\ChunkStream;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Allow to set the correct content length header on the request or to transfer it as a chunk if not possible.
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+final class ContentLengthPlugin implements Plugin
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function handleRequest(RequestInterface $request, callable $next, callable $first)
+    {
+        if (!$request->hasHeader('Content-Length')) {
+            $stream = $request->getBody();
+
+            // Cannot determine the size so we use a chunk stream
+            if (null === $stream->getSize()) {
+                $stream = new ChunkStream($stream);
+                $request = $request->withBody($stream);
+                $request = $request->withAddedHeader('Transfer-Encoding', 'chunked');
+            } else {
+                $request = $request->withHeader('Content-Length', (string) $stream->getSize());
+            }
+        }
+
+        return $next($request);
+    }
+}
diff --git a/vendor/php-http/client-common/src/Plugin/ContentTypePlugin.php b/vendor/php-http/client-common/src/Plugin/ContentTypePlugin.php
new file mode 100644
index 00000000000..8ef1d62b34b
--- /dev/null
+++ b/vendor/php-http/client-common/src/Plugin/ContentTypePlugin.php
@@ -0,0 +1,123 @@
+<?php
+
+namespace Http\Client\Common\Plugin;
+
+use Http\Client\Common\Plugin;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\StreamInterface;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+
+/**
+ * Allow to set the correct content type header on the request automatically only if it is not set.
+ *
+ * @author Karim Pinchon <karim.pinchon@gmail.com>
+ */
+final class ContentTypePlugin implements Plugin
+{
+    /**
+     * Allow to disable the content type detection when stream is too large (as it can consume a lot of resource).
+     *
+     * @var bool
+     *
+     * true     skip the content type detection
+     * false    detect the content type (default value)
+     */
+    protected $skipDetection;
+
+    /**
+     * Determine the size stream limit for which the detection as to be skipped (default to 16Mb).
+     *
+     * @var int
+     */
+    protected $sizeLimit;
+
+    /**
+     * @param array $config {
+     *
+     *     @var bool $skip_detection True skip detection if stream size is bigger than $size_limit.
+     *     @var int $size_limit size stream limit for which the detection as to be skipped.
+     * }
+     */
+    public function __construct(array $config = [])
+    {
+        $resolver = new OptionsResolver();
+        $resolver->setDefaults([
+            'skip_detection' => false,
+            'size_limit' => 16000000,
+        ]);
+        $resolver->setAllowedTypes('skip_detection', 'bool');
+        $resolver->setAllowedTypes('size_limit', 'int');
+
+        $options = $resolver->resolve($config);
+
+        $this->skipDetection = $options['skip_detection'];
+        $this->sizeLimit = $options['size_limit'];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function handleRequest(RequestInterface $request, callable $next, callable $first)
+    {
+        if (!$request->hasHeader('Content-Type')) {
+            $stream = $request->getBody();
+            $streamSize = $stream->getSize();
+
+            if (!$stream->isSeekable()) {
+                return $next($request);
+            }
+
+            if (0 === $streamSize) {
+                return $next($request);
+            }
+
+            if ($this->skipDetection && (null === $streamSize || $streamSize >= $this->sizeLimit)) {
+                return $next($request);
+            }
+
+            if ($this->isJson($stream)) {
+                $request = $request->withHeader('Content-Type', 'application/json');
+
+                return $next($request);
+            }
+
+            if ($this->isXml($stream)) {
+                $request = $request->withHeader('Content-Type', 'application/xml');
+
+                return $next($request);
+            }
+        }
+
+        return $next($request);
+    }
+
+    /**
+     * @param $stream StreamInterface
+     *
+     * @return bool
+     */
+    private function isJson($stream)
+    {
+        $stream->rewind();
+
+        json_decode($stream->getContents());
+
+        return JSON_ERROR_NONE === json_last_error();
+    }
+
+    /**
+     * @param $stream StreamInterface
+     *
+     * @return \SimpleXMLElement|false
+     */
+    private function isXml($stream)
+    {
+        $stream->rewind();
+
+        $previousValue = libxml_use_internal_errors(true);
+        $isXml = simplexml_load_string($stream->getContents());
+        libxml_use_internal_errors($previousValue);
+
+        return $isXml;
+    }
+}
diff --git a/vendor/php-http/client-common/src/Plugin/CookiePlugin.php b/vendor/php-http/client-common/src/Plugin/CookiePlugin.php
new file mode 100644
index 00000000000..59ee90da19d
--- /dev/null
+++ b/vendor/php-http/client-common/src/Plugin/CookiePlugin.php
@@ -0,0 +1,180 @@
+<?php
+
+namespace Http\Client\Common\Plugin;
+
+use Http\Client\Common\Plugin;
+use Http\Client\Exception\TransferException;
+use Http\Message\Cookie;
+use Http\Message\CookieJar;
+use Http\Message\CookieUtil;
+use Http\Message\Exception\UnexpectedValueException;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Handle request cookies.
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+final class CookiePlugin implements Plugin
+{
+    /**
+     * Cookie storage.
+     *
+     * @var CookieJar
+     */
+    private $cookieJar;
+
+    /**
+     * @param CookieJar $cookieJar
+     */
+    public function __construct(CookieJar $cookieJar)
+    {
+        $this->cookieJar = $cookieJar;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function handleRequest(RequestInterface $request, callable $next, callable $first)
+    {
+        foreach ($this->cookieJar->getCookies() as $cookie) {
+            if ($cookie->isExpired()) {
+                continue;
+            }
+
+            if (!$cookie->matchDomain($request->getUri()->getHost())) {
+                continue;
+            }
+
+            if (!$cookie->matchPath($request->getUri()->getPath())) {
+                continue;
+            }
+
+            if ($cookie->isSecure() && ('https' !== $request->getUri()->getScheme())) {
+                continue;
+            }
+
+            $request = $request->withAddedHeader('Cookie', sprintf('%s=%s', $cookie->getName(), $cookie->getValue()));
+        }
+
+        return $next($request)->then(function (ResponseInterface $response) use ($request) {
+            if ($response->hasHeader('Set-Cookie')) {
+                $setCookies = $response->getHeader('Set-Cookie');
+
+                foreach ($setCookies as $setCookie) {
+                    $cookie = $this->createCookie($request, $setCookie);
+
+                    // Cookie invalid do not use it
+                    if (null === $cookie) {
+                        continue;
+                    }
+
+                    // Restrict setting cookie from another domain
+                    if (!preg_match("/\.{$cookie->getDomain()}$/", '.'.$request->getUri()->getHost())) {
+                        continue;
+                    }
+
+                    $this->cookieJar->addCookie($cookie);
+                }
+            }
+
+            return $response;
+        });
+    }
+
+    /**
+     * Creates a cookie from a string.
+     *
+     * @param RequestInterface $request
+     * @param $setCookie
+     *
+     * @return Cookie|null
+     *
+     * @throws TransferException
+     */
+    private function createCookie(RequestInterface $request, $setCookie)
+    {
+        $parts = array_map('trim', explode(';', $setCookie));
+
+        if (empty($parts) || !strpos($parts[0], '=')) {
+            return;
+        }
+
+        list($name, $cookieValue) = $this->createValueKey(array_shift($parts));
+
+        $maxAge = null;
+        $expires = null;
+        $domain = $request->getUri()->getHost();
+        $path = $request->getUri()->getPath();
+        $secure = false;
+        $httpOnly = false;
+
+        // Add the cookie pieces into the parsed data array
+        foreach ($parts as $part) {
+            list($key, $value) = $this->createValueKey($part);
+
+            switch (strtolower($key)) {
+                case 'expires':
+                    try {
+                        $expires = CookieUtil::parseDate($value);
+                    } catch (UnexpectedValueException $e) {
+                        throw new TransferException(
+                            sprintf(
+                                'Cookie header `%s` expires value `%s` could not be converted to date',
+                                $name,
+                                $value
+                            ),
+                            null,
+                            $e
+                        );
+                    }
+
+                    break;
+
+                case 'max-age':
+                    $maxAge = (int) $value;
+
+                    break;
+
+                case 'domain':
+                    $domain = $value;
+
+                    break;
+
+                case 'path':
+                    $path = $value;
+
+                    break;
+
+                case 'secure':
+                    $secure = true;
+
+                    break;
+
+                case 'httponly':
+                    $httpOnly = true;
+
+                    break;
+            }
+        }
+
+        return new Cookie($name, $cookieValue, $maxAge, $domain, $path, $secure, $httpOnly, $expires);
+    }
+
+    /**
+     * Separates key/value pair from cookie.
+     *
+     * @param $part
+     *
+     * @return array
+     */
+    private function createValueKey($part)
+    {
+        $parts = explode('=', $part, 2);
+        $key = trim($parts[0]);
+        $value = isset($parts[1]) ? trim($parts[1]) : true;
+
+        return [$key, $value];
+    }
+}
diff --git a/vendor/php-http/client-common/src/Plugin/DecoderPlugin.php b/vendor/php-http/client-common/src/Plugin/DecoderPlugin.php
new file mode 100644
index 00000000000..b661b613ac7
--- /dev/null
+++ b/vendor/php-http/client-common/src/Plugin/DecoderPlugin.php
@@ -0,0 +1,140 @@
+<?php
+
+namespace Http\Client\Common\Plugin;
+
+use Http\Client\Common\Plugin;
+use Http\Message\Encoding;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\StreamInterface;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+
+/**
+ * Allow to decode response body with a chunk, deflate, compress or gzip encoding.
+ *
+ * If zlib is not installed, only chunked encoding can be handled.
+ *
+ * If Content-Encoding is not disabled, the plugin will add an Accept-Encoding header for the encoding methods it supports.
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+final class DecoderPlugin implements Plugin
+{
+    /**
+     * @var bool Whether this plugin decode stream with value in the Content-Encoding header (default to true).
+     *
+     * If set to false only the Transfer-Encoding header will be used
+     */
+    private $useContentEncoding;
+
+    /**
+     * @param array $config {
+     *
+     *    @var bool $use_content_encoding Whether this plugin should look at the Content-Encoding header first or only at the Transfer-Encoding (defaults to true).
+     * }
+     */
+    public function __construct(array $config = [])
+    {
+        $resolver = new OptionsResolver();
+        $resolver->setDefaults([
+            'use_content_encoding' => true,
+        ]);
+        $resolver->setAllowedTypes('use_content_encoding', 'bool');
+        $options = $resolver->resolve($config);
+
+        $this->useContentEncoding = $options['use_content_encoding'];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function handleRequest(RequestInterface $request, callable $next, callable $first)
+    {
+        $encodings = extension_loaded('zlib') ? ['gzip', 'deflate'] : ['identity'];
+
+        if ($this->useContentEncoding) {
+            $request = $request->withHeader('Accept-Encoding', $encodings);
+        }
+        $encodings[] = 'chunked';
+        $request = $request->withHeader('TE', $encodings);
+
+        return $next($request)->then(function (ResponseInterface $response) {
+            return $this->decodeResponse($response);
+        });
+    }
+
+    /**
+     * Decode a response body given its Transfer-Encoding or Content-Encoding value.
+     *
+     * @param ResponseInterface $response Response to decode
+     *
+     * @return ResponseInterface New response decoded
+     */
+    private function decodeResponse(ResponseInterface $response)
+    {
+        $response = $this->decodeOnEncodingHeader('Transfer-Encoding', $response);
+
+        if ($this->useContentEncoding) {
+            $response = $this->decodeOnEncodingHeader('Content-Encoding', $response);
+        }
+
+        return $response;
+    }
+
+    /**
+     * Decode a response on a specific header (content encoding or transfer encoding mainly).
+     *
+     * @param string            $headerName Name of the header
+     * @param ResponseInterface $response   Response
+     *
+     * @return ResponseInterface A new instance of the response decoded
+     */
+    private function decodeOnEncodingHeader($headerName, ResponseInterface $response)
+    {
+        if ($response->hasHeader($headerName)) {
+            $encodings = $response->getHeader($headerName);
+            $newEncodings = [];
+
+            while ($encoding = array_pop($encodings)) {
+                $stream = $this->decorateStream($encoding, $response->getBody());
+
+                if (false === $stream) {
+                    array_unshift($newEncodings, $encoding);
+
+                    continue;
+                }
+
+                $response = $response->withBody($stream);
+            }
+
+            $response = $response->withHeader($headerName, $newEncodings);
+        }
+
+        return $response;
+    }
+
+    /**
+     * Decorate a stream given an encoding.
+     *
+     * @param string          $encoding
+     * @param StreamInterface $stream
+     *
+     * @return StreamInterface|false A new stream interface or false if encoding is not supported
+     */
+    private function decorateStream($encoding, StreamInterface $stream)
+    {
+        if ('chunked' === strtolower($encoding)) {
+            return new Encoding\DechunkStream($stream);
+        }
+
+        if ('deflate' === strtolower($encoding)) {
+            return new Encoding\DecompressStream($stream);
+        }
+
+        if ('gzip' === strtolower($encoding)) {
+            return new Encoding\GzipDecodeStream($stream);
+        }
+
+        return false;
+    }
+}
diff --git a/vendor/php-http/client-common/src/Plugin/ErrorPlugin.php b/vendor/php-http/client-common/src/Plugin/ErrorPlugin.php
new file mode 100644
index 00000000000..f09d3b161a8
--- /dev/null
+++ b/vendor/php-http/client-common/src/Plugin/ErrorPlugin.php
@@ -0,0 +1,55 @@
+<?php
+
+namespace Http\Client\Common\Plugin;
+
+use Http\Client\Common\Exception\ClientErrorException;
+use Http\Client\Common\Exception\ServerErrorException;
+use Http\Client\Common\Plugin;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Throw exception when the response of a request is not acceptable.
+ *
+ * Status codes 400-499 lead to a ClientErrorException, status 500-599 to a ServerErrorException.
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+final class ErrorPlugin implements Plugin
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function handleRequest(RequestInterface $request, callable $next, callable $first)
+    {
+        $promise = $next($request);
+
+        return $promise->then(function (ResponseInterface $response) use ($request) {
+            return $this->transformResponseToException($request, $response);
+        });
+    }
+
+    /**
+     * Transform response to an error if possible.
+     *
+     * @param RequestInterface  $request  Request of the call
+     * @param ResponseInterface $response Response of the call
+     *
+     * @throws ClientErrorException If response status code is a 4xx
+     * @throws ServerErrorException If response status code is a 5xx
+     *
+     * @return ResponseInterface If status code is not in 4xx or 5xx return response
+     */
+    protected function transformResponseToException(RequestInterface $request, ResponseInterface $response)
+    {
+        if ($response->getStatusCode() >= 400 && $response->getStatusCode() < 500) {
+            throw new ClientErrorException($response->getReasonPhrase(), $request, $response);
+        }
+
+        if ($response->getStatusCode() >= 500 && $response->getStatusCode() < 600) {
+            throw new ServerErrorException($response->getReasonPhrase(), $request, $response);
+        }
+
+        return $response;
+    }
+}
diff --git a/vendor/php-http/client-common/src/Plugin/HeaderAppendPlugin.php b/vendor/php-http/client-common/src/Plugin/HeaderAppendPlugin.php
new file mode 100644
index 00000000000..26fd8134585
--- /dev/null
+++ b/vendor/php-http/client-common/src/Plugin/HeaderAppendPlugin.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace Http\Client\Common\Plugin;
+
+use Http\Client\Common\Plugin;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Append headers to the request.
+ *
+ * If the header already exists the value will be appended to the current value.
+ *
+ * This only makes sense for headers that can have multiple values like 'Forwarded'
+ *
+ * @see https://en.wikipedia.org/wiki/List_of_HTTP_header_fields
+ *
+ * @author Soufiane Ghzal <sghzal@gmail.com>
+ */
+final class HeaderAppendPlugin implements Plugin
+{
+    /**
+     * @var array
+     */
+    private $headers = [];
+
+    /**
+     * @param array $headers Hashmap of header name to header value
+     */
+    public function __construct(array $headers)
+    {
+        $this->headers = $headers;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function handleRequest(RequestInterface $request, callable $next, callable $first)
+    {
+        foreach ($this->headers as $header => $headerValue) {
+            $request = $request->withAddedHeader($header, $headerValue);
+        }
+
+        return $next($request);
+    }
+}
diff --git a/vendor/php-http/client-common/src/Plugin/HeaderDefaultsPlugin.php b/vendor/php-http/client-common/src/Plugin/HeaderDefaultsPlugin.php
new file mode 100644
index 00000000000..6dfc1115a06
--- /dev/null
+++ b/vendor/php-http/client-common/src/Plugin/HeaderDefaultsPlugin.php
@@ -0,0 +1,43 @@
+<?php
+
+namespace Http\Client\Common\Plugin;
+
+use Http\Client\Common\Plugin;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Set header to default value if it does not exist.
+ *
+ * If a given header already exists the value wont be replaced and the request wont be changed.
+ *
+ * @author Soufiane Ghzal <sghzal@gmail.com>
+ */
+final class HeaderDefaultsPlugin implements Plugin
+{
+    /**
+     * @var array
+     */
+    private $headers = [];
+
+    /**
+     * @param array $headers Hashmap of header name to header value
+     */
+    public function __construct(array $headers)
+    {
+        $this->headers = $headers;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function handleRequest(RequestInterface $request, callable $next, callable $first)
+    {
+        foreach ($this->headers as $header => $headerValue) {
+            if (!$request->hasHeader($header)) {
+                $request = $request->withHeader($header, $headerValue);
+            }
+        }
+
+        return $next($request);
+    }
+}
diff --git a/vendor/php-http/client-common/src/Plugin/HeaderRemovePlugin.php b/vendor/php-http/client-common/src/Plugin/HeaderRemovePlugin.php
new file mode 100644
index 00000000000..fc9c19d1aad
--- /dev/null
+++ b/vendor/php-http/client-common/src/Plugin/HeaderRemovePlugin.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace Http\Client\Common\Plugin;
+
+use Http\Client\Common\Plugin;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Removes headers from the request.
+ *
+ * @author Soufiane Ghzal <sghzal@gmail.com>
+ */
+final class HeaderRemovePlugin implements Plugin
+{
+    /**
+     * @var array
+     */
+    private $headers = [];
+
+    /**
+     * @param array $headers List of header names to remove from the request
+     */
+    public function __construct(array $headers)
+    {
+        $this->headers = $headers;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function handleRequest(RequestInterface $request, callable $next, callable $first)
+    {
+        foreach ($this->headers as $header) {
+            if ($request->hasHeader($header)) {
+                $request = $request->withoutHeader($header);
+            }
+        }
+
+        return $next($request);
+    }
+}
diff --git a/vendor/php-http/client-common/src/Plugin/HeaderSetPlugin.php b/vendor/php-http/client-common/src/Plugin/HeaderSetPlugin.php
new file mode 100644
index 00000000000..75f11d40aaa
--- /dev/null
+++ b/vendor/php-http/client-common/src/Plugin/HeaderSetPlugin.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace Http\Client\Common\Plugin;
+
+use Http\Client\Common\Plugin;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Set headers on the request.
+ *
+ * If the header does not exist it wil be set, if the header already exists it will be replaced.
+ *
+ * @author Soufiane Ghzal <sghzal@gmail.com>
+ */
+final class HeaderSetPlugin implements Plugin
+{
+    /**
+     * @var array
+     */
+    private $headers = [];
+
+    /**
+     * @param array $headers Hashmap of header name to header value
+     */
+    public function __construct(array $headers)
+    {
+        $this->headers = $headers;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function handleRequest(RequestInterface $request, callable $next, callable $first)
+    {
+        foreach ($this->headers as $header => $headerValue) {
+            $request = $request->withHeader($header, $headerValue);
+        }
+
+        return $next($request);
+    }
+}
diff --git a/vendor/php-http/client-common/src/Plugin/HistoryPlugin.php b/vendor/php-http/client-common/src/Plugin/HistoryPlugin.php
new file mode 100644
index 00000000000..5abddbd8412
--- /dev/null
+++ b/vendor/php-http/client-common/src/Plugin/HistoryPlugin.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace Http\Client\Common\Plugin;
+
+use Http\Client\Common\Plugin;
+use Http\Client\Exception;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Record HTTP calls.
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+final class HistoryPlugin implements Plugin
+{
+    /**
+     * Journal use to store request / responses / exception.
+     *
+     * @var Journal
+     */
+    private $journal;
+
+    /**
+     * @param Journal $journal
+     */
+    public function __construct(Journal $journal)
+    {
+        $this->journal = $journal;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function handleRequest(RequestInterface $request, callable $next, callable $first)
+    {
+        $journal = $this->journal;
+
+        return $next($request)->then(function (ResponseInterface $response) use ($request, $journal) {
+            $journal->addSuccess($request, $response);
+
+            return $response;
+        }, function (Exception $exception) use ($request, $journal) {
+            $journal->addFailure($request, $exception);
+
+            throw $exception;
+        });
+    }
+}
diff --git a/vendor/php-http/client-common/src/Plugin/Journal.php b/vendor/php-http/client-common/src/Plugin/Journal.php
new file mode 100644
index 00000000000..15f309569fb
--- /dev/null
+++ b/vendor/php-http/client-common/src/Plugin/Journal.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Http\Client\Common\Plugin;
+
+use Http\Client\Exception;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Records history of HTTP calls.
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+interface Journal
+{
+    /**
+     * Record a successful call.
+     *
+     * @param RequestInterface  $request  Request use to make the call
+     * @param ResponseInterface $response Response returned by the call
+     */
+    public function addSuccess(RequestInterface $request, ResponseInterface $response);
+
+    /**
+     * Record a failed call.
+     *
+     * @param RequestInterface $request   Request use to make the call
+     * @param Exception        $exception Exception returned by the call
+     */
+    public function addFailure(RequestInterface $request, Exception $exception);
+}
diff --git a/vendor/php-http/client-common/src/Plugin/QueryDefaultsPlugin.php b/vendor/php-http/client-common/src/Plugin/QueryDefaultsPlugin.php
new file mode 100644
index 00000000000..6c1e32cd307
--- /dev/null
+++ b/vendor/php-http/client-common/src/Plugin/QueryDefaultsPlugin.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace Http\Client\Common\Plugin;
+
+use Http\Client\Common\Plugin;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Set query to default value if it does not exist.
+ *
+ * If a given query parameter already exists the value wont be replaced and the request wont be changed.
+ *
+ * @author Tobias Nyholm <tobias.nyholm@gmail.com>
+ */
+final class QueryDefaultsPlugin implements Plugin
+{
+    /**
+     * @var array
+     */
+    private $queryParams = [];
+
+    /**
+     * @param array $queryParams Hashmap of query name to query value. Names and values must not be url encoded as
+     *                           this plugin will encode them
+     */
+    public function __construct(array $queryParams)
+    {
+        $this->queryParams = $queryParams;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function handleRequest(RequestInterface $request, callable $next, callable $first)
+    {
+        foreach ($this->queryParams as $name => $value) {
+            $uri = $request->getUri();
+            $array = [];
+            parse_str($uri->getQuery(), $array);
+
+            // If query value is not found
+            if (!isset($array[$name])) {
+                $array[$name] = $value;
+
+                // Create a new request with the new URI with the added query param
+                $request = $request->withUri(
+                    $uri->withQuery(http_build_query($array))
+                );
+            }
+        }
+
+        return $next($request);
+    }
+}
diff --git a/vendor/php-http/client-common/src/Plugin/RedirectPlugin.php b/vendor/php-http/client-common/src/Plugin/RedirectPlugin.php
new file mode 100644
index 00000000000..d2f442edb8f
--- /dev/null
+++ b/vendor/php-http/client-common/src/Plugin/RedirectPlugin.php
@@ -0,0 +1,270 @@
+<?php
+
+namespace Http\Client\Common\Plugin;
+
+use Http\Client\Common\Exception\CircularRedirectionException;
+use Http\Client\Common\Exception\MultipleRedirectionException;
+use Http\Client\Common\Plugin;
+use Http\Client\Exception\HttpException;
+use Psr\Http\Message\MessageInterface;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\UriInterface;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+
+/**
+ * Follow redirections.
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+class RedirectPlugin implements Plugin
+{
+    /**
+     * Rule on how to redirect, change method for the new request.
+     *
+     * @var array
+     */
+    protected $redirectCodes = [
+        300 => [
+            'switch' => [
+                'unless' => ['GET', 'HEAD'],
+                'to' => 'GET',
+            ],
+            'multiple' => true,
+            'permanent' => false,
+        ],
+        301 => [
+            'switch' => [
+                'unless' => ['GET', 'HEAD'],
+                'to' => 'GET',
+            ],
+            'multiple' => false,
+            'permanent' => true,
+        ],
+        302 => [
+            'switch' => [
+                'unless' => ['GET', 'HEAD'],
+                'to' => 'GET',
+            ],
+            'multiple' => false,
+            'permanent' => false,
+        ],
+        303 => [
+            'switch' => [
+                'unless' => ['GET', 'HEAD'],
+                'to' => 'GET',
+            ],
+            'multiple' => false,
+            'permanent' => false,
+        ],
+        307 => [
+            'switch' => false,
+            'multiple' => false,
+            'permanent' => false,
+        ],
+        308 => [
+            'switch' => false,
+            'multiple' => false,
+            'permanent' => true,
+        ],
+    ];
+
+    /**
+     * Determine how header should be preserved from old request.
+     *
+     * @var bool|array
+     *
+     * true     will keep all previous headers (default value)
+     * false    will ditch all previous headers
+     * string[] will keep only headers with the specified names
+     */
+    protected $preserveHeader;
+
+    /**
+     * Store all previous redirect from 301 / 308 status code.
+     *
+     * @var array
+     */
+    protected $redirectStorage = [];
+
+    /**
+     * Whether the location header must be directly used for a multiple redirection status code (300).
+     *
+     * @var bool
+     */
+    protected $useDefaultForMultiple;
+
+    /**
+     * @var array
+     */
+    protected $circularDetection = [];
+
+    /**
+     * @param array $config {
+     *
+     *     @var bool|string[] $preserve_header True keeps all headers, false remove all of them, an array is interpreted as a list of header names to keep
+     *     @var bool $use_default_for_multiple Whether the location header must be directly used for a multiple redirection status code (300).
+     * }
+     */
+    public function __construct(array $config = [])
+    {
+        $resolver = new OptionsResolver();
+        $resolver->setDefaults([
+            'preserve_header' => true,
+            'use_default_for_multiple' => true,
+        ]);
+        $resolver->setAllowedTypes('preserve_header', ['bool', 'array']);
+        $resolver->setAllowedTypes('use_default_for_multiple', 'bool');
+        $resolver->setNormalizer('preserve_header', function (OptionsResolver $resolver, $value) {
+            if (is_bool($value) && false === $value) {
+                return [];
+            }
+
+            return $value;
+        });
+        $options = $resolver->resolve($config);
+
+        $this->preserveHeader = $options['preserve_header'];
+        $this->useDefaultForMultiple = $options['use_default_for_multiple'];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function handleRequest(RequestInterface $request, callable $next, callable $first)
+    {
+        // Check in storage
+        if (array_key_exists((string) $request->getUri(), $this->redirectStorage)) {
+            $uri = $this->redirectStorage[(string) $request->getUri()]['uri'];
+            $statusCode = $this->redirectStorage[(string) $request->getUri()]['status'];
+            $redirectRequest = $this->buildRedirectRequest($request, $uri, $statusCode);
+
+            return $first($redirectRequest);
+        }
+
+        return $next($request)->then(function (ResponseInterface $response) use ($request, $first) {
+            $statusCode = $response->getStatusCode();
+
+            if (!array_key_exists($statusCode, $this->redirectCodes)) {
+                return $response;
+            }
+
+            $uri = $this->createUri($response, $request);
+            $redirectRequest = $this->buildRedirectRequest($request, $uri, $statusCode);
+            $chainIdentifier = spl_object_hash((object) $first);
+
+            if (!array_key_exists($chainIdentifier, $this->circularDetection)) {
+                $this->circularDetection[$chainIdentifier] = [];
+            }
+
+            $this->circularDetection[$chainIdentifier][] = (string) $request->getUri();
+
+            if (in_array((string) $redirectRequest->getUri(), $this->circularDetection[$chainIdentifier])) {
+                throw new CircularRedirectionException('Circular redirection detected', $request, $response);
+            }
+
+            if ($this->redirectCodes[$statusCode]['permanent']) {
+                $this->redirectStorage[(string) $request->getUri()] = [
+                    'uri' => $uri,
+                    'status' => $statusCode,
+                ];
+            }
+
+            // Call redirect request in synchrone
+            $redirectPromise = $first($redirectRequest);
+
+            return $redirectPromise->wait();
+        });
+    }
+
+    /**
+     * Builds the redirect request.
+     *
+     * @param RequestInterface $request    Original request
+     * @param UriInterface     $uri        New uri
+     * @param int              $statusCode Status code from the redirect response
+     *
+     * @return MessageInterface|RequestInterface
+     */
+    protected function buildRedirectRequest(RequestInterface $request, UriInterface $uri, $statusCode)
+    {
+        $request = $request->withUri($uri);
+
+        if (false !== $this->redirectCodes[$statusCode]['switch'] && !in_array($request->getMethod(), $this->redirectCodes[$statusCode]['switch']['unless'])) {
+            $request = $request->withMethod($this->redirectCodes[$statusCode]['switch']['to']);
+        }
+
+        if (is_array($this->preserveHeader)) {
+            $headers = array_keys($request->getHeaders());
+
+            foreach ($headers as $name) {
+                if (!in_array($name, $this->preserveHeader)) {
+                    $request = $request->withoutHeader($name);
+                }
+            }
+        }
+
+        return $request;
+    }
+
+    /**
+     * Creates a new Uri from the old request and the location header.
+     *
+     * @param ResponseInterface $response The redirect response
+     * @param RequestInterface  $request  The original request
+     *
+     * @throws HttpException                If location header is not usable (missing or incorrect)
+     * @throws MultipleRedirectionException If a 300 status code is received and default location cannot be resolved (doesn't use the location header or not present)
+     *
+     * @return UriInterface
+     */
+    private function createUri(ResponseInterface $response, RequestInterface $request)
+    {
+        if ($this->redirectCodes[$response->getStatusCode()]['multiple'] && (!$this->useDefaultForMultiple || !$response->hasHeader('Location'))) {
+            throw new MultipleRedirectionException('Cannot choose a redirection', $request, $response);
+        }
+
+        if (!$response->hasHeader('Location')) {
+            throw new HttpException('Redirect status code, but no location header present in the response', $request, $response);
+        }
+
+        $location = $response->getHeaderLine('Location');
+        $parsedLocation = parse_url($location);
+
+        if (false === $parsedLocation) {
+            throw new HttpException(sprintf('Location %s could not be parsed', $location), $request, $response);
+        }
+
+        $uri = $request->getUri();
+
+        if (array_key_exists('scheme', $parsedLocation)) {
+            $uri = $uri->withScheme($parsedLocation['scheme']);
+        }
+
+        if (array_key_exists('host', $parsedLocation)) {
+            $uri = $uri->withHost($parsedLocation['host']);
+        }
+
+        if (array_key_exists('port', $parsedLocation)) {
+            $uri = $uri->withPort($parsedLocation['port']);
+        }
+
+        if (array_key_exists('path', $parsedLocation)) {
+            $uri = $uri->withPath($parsedLocation['path']);
+        }
+
+        if (array_key_exists('query', $parsedLocation)) {
+            $uri = $uri->withQuery($parsedLocation['query']);
+        } else {
+            $uri = $uri->withQuery('');
+        }
+
+        if (array_key_exists('fragment', $parsedLocation)) {
+            $uri = $uri->withFragment($parsedLocation['fragment']);
+        } else {
+            $uri = $uri->withFragment('');
+        }
+
+        return $uri;
+    }
+}
diff --git a/vendor/php-http/client-common/src/Plugin/RequestMatcherPlugin.php b/vendor/php-http/client-common/src/Plugin/RequestMatcherPlugin.php
new file mode 100644
index 00000000000..5f72b02d8ac
--- /dev/null
+++ b/vendor/php-http/client-common/src/Plugin/RequestMatcherPlugin.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace Http\Client\Common\Plugin;
+
+use Http\Client\Common\Plugin;
+use Http\Message\RequestMatcher;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Apply a delegated plugin based on a request match.
+ *
+ * @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
+ */
+final class RequestMatcherPlugin implements Plugin
+{
+    /**
+     * @var RequestMatcher
+     */
+    private $requestMatcher;
+
+    /**
+     * @var Plugin
+     */
+    private $delegatedPlugin;
+
+    /**
+     * @param RequestMatcher $requestMatcher
+     * @param Plugin         $delegatedPlugin
+     */
+    public function __construct(RequestMatcher $requestMatcher, Plugin $delegatedPlugin)
+    {
+        $this->requestMatcher = $requestMatcher;
+        $this->delegatedPlugin = $delegatedPlugin;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function handleRequest(RequestInterface $request, callable $next, callable $first)
+    {
+        if ($this->requestMatcher->matches($request)) {
+            return $this->delegatedPlugin->handleRequest($request, $next, $first);
+        }
+
+        return $next($request);
+    }
+}
diff --git a/vendor/php-http/client-common/src/Plugin/RetryPlugin.php b/vendor/php-http/client-common/src/Plugin/RetryPlugin.php
new file mode 100644
index 00000000000..8446246e673
--- /dev/null
+++ b/vendor/php-http/client-common/src/Plugin/RetryPlugin.php
@@ -0,0 +1,122 @@
+<?php
+
+namespace Http\Client\Common\Plugin;
+
+use Http\Client\Common\Plugin;
+use Http\Client\Exception;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+
+/**
+ * Retry the request if an exception is thrown.
+ *
+ * By default will retry only one time.
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+final class RetryPlugin implements Plugin
+{
+    /**
+     * Number of retry before sending an exception.
+     *
+     * @var int
+     */
+    private $retry;
+
+    /**
+     * @var callable
+     */
+    private $delay;
+
+    /**
+     * @var callable
+     */
+    private $decider;
+
+    /**
+     * Store the retry counter for each request.
+     *
+     * @var array
+     */
+    private $retryStorage = [];
+
+    /**
+     * @param array $config {
+     *
+     *     @var int $retries Number of retries to attempt if an exception occurs before letting the exception bubble up.
+     *     @var callable $decider A callback that gets a request and an exception to decide after a failure whether the request should be retried.
+     *     @var callable $delay A callback that gets a request, an exception and the number of retries and returns how many microseconds we should wait before trying again.
+     * }
+     */
+    public function __construct(array $config = [])
+    {
+        $resolver = new OptionsResolver();
+        $resolver->setDefaults([
+            'retries' => 1,
+            'decider' => function (RequestInterface $request, Exception $e) {
+                return true;
+            },
+            'delay' => __CLASS__.'::defaultDelay',
+        ]);
+        $resolver->setAllowedTypes('retries', 'int');
+        $resolver->setAllowedTypes('decider', 'callable');
+        $resolver->setAllowedTypes('delay', 'callable');
+        $options = $resolver->resolve($config);
+
+        $this->retry = $options['retries'];
+        $this->decider = $options['decider'];
+        $this->delay = $options['delay'];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function handleRequest(RequestInterface $request, callable $next, callable $first)
+    {
+        $chainIdentifier = spl_object_hash((object) $first);
+
+        return $next($request)->then(function (ResponseInterface $response) use ($request, $chainIdentifier) {
+            if (array_key_exists($chainIdentifier, $this->retryStorage)) {
+                unset($this->retryStorage[$chainIdentifier]);
+            }
+
+            return $response;
+        }, function (Exception $exception) use ($request, $next, $first, $chainIdentifier) {
+            if (!array_key_exists($chainIdentifier, $this->retryStorage)) {
+                $this->retryStorage[$chainIdentifier] = 0;
+            }
+
+            if ($this->retryStorage[$chainIdentifier] >= $this->retry) {
+                unset($this->retryStorage[$chainIdentifier]);
+
+                throw $exception;
+            }
+
+            if (!call_user_func($this->decider, $request, $exception)) {
+                throw $exception;
+            }
+
+            $time = call_user_func($this->delay, $request, $exception, $this->retryStorage[$chainIdentifier]);
+            usleep($time);
+
+            // Retry in synchrone
+            ++$this->retryStorage[$chainIdentifier];
+            $promise = $this->handleRequest($request, $next, $first);
+
+            return $promise->wait();
+        });
+    }
+
+    /**
+     * @param RequestInterface $request
+     * @param Exception        $e
+     * @param int              $retries The number of retries we made before. First time this get called it will be 0.
+     *
+     * @return int
+     */
+    public static function defaultDelay(RequestInterface $request, Exception $e, $retries)
+    {
+        return pow(2, $retries) * 500000;
+    }
+}
diff --git a/vendor/php-http/client-common/src/PluginClient.php b/vendor/php-http/client-common/src/PluginClient.php
new file mode 100644
index 00000000000..93aea8f2fda
--- /dev/null
+++ b/vendor/php-http/client-common/src/PluginClient.php
@@ -0,0 +1,179 @@
+<?php
+
+namespace Http\Client\Common;
+
+use Http\Client\Common\Exception\LoopException;
+use Http\Client\Exception as HttplugException;
+use Http\Client\HttpAsyncClient;
+use Http\Client\HttpClient;
+use Http\Client\Promise\HttpFulfilledPromise;
+use Http\Client\Promise\HttpRejectedPromise;
+use Psr\Http\Message\RequestInterface;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+
+/**
+ * The client managing plugins and providing a decorator around HTTP Clients.
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+final class PluginClient implements HttpClient, HttpAsyncClient
+{
+    /**
+     * An HTTP async client.
+     *
+     * @var HttpAsyncClient
+     */
+    private $client;
+
+    /**
+     * The plugin chain.
+     *
+     * @var Plugin[]
+     */
+    private $plugins;
+
+    /**
+     * A list of options.
+     *
+     * @var array
+     */
+    private $options;
+
+    /**
+     * @param HttpClient|HttpAsyncClient $client
+     * @param Plugin[]                   $plugins
+     * @param array                      $options {
+     *
+     *     @var int      $max_restarts
+     *     @var Plugin[] $debug_plugins an array of plugins that are injected between each normal plugin
+     * }
+     *
+     * @throws \RuntimeException if client is not an instance of HttpClient or HttpAsyncClient
+     */
+    public function __construct($client, array $plugins = [], array $options = [])
+    {
+        if ($client instanceof HttpAsyncClient) {
+            $this->client = $client;
+        } elseif ($client instanceof HttpClient) {
+            $this->client = new EmulatedHttpAsyncClient($client);
+        } else {
+            throw new \RuntimeException('Client must be an instance of Http\\Client\\HttpClient or Http\\Client\\HttpAsyncClient');
+        }
+
+        $this->plugins = $plugins;
+        $this->options = $this->configure($options);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function sendRequest(RequestInterface $request)
+    {
+        // If we don't have an http client, use the async call
+        if (!($this->client instanceof HttpClient)) {
+            return $this->sendAsyncRequest($request)->wait();
+        }
+
+        // Else we want to use the synchronous call of the underlying client, and not the async one in the case
+        // we have both an async and sync call
+        $pluginChain = $this->createPluginChain($this->plugins, function (RequestInterface $request) {
+            try {
+                return new HttpFulfilledPromise($this->client->sendRequest($request));
+            } catch (HttplugException $exception) {
+                return new HttpRejectedPromise($exception);
+            }
+        });
+
+        return $pluginChain($request)->wait();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function sendAsyncRequest(RequestInterface $request)
+    {
+        $pluginChain = $this->createPluginChain($this->plugins, function (RequestInterface $request) {
+            return $this->client->sendAsyncRequest($request);
+        });
+
+        return $pluginChain($request);
+    }
+
+    /**
+     * Configure the plugin client.
+     *
+     * @param array $options
+     *
+     * @return array
+     */
+    private function configure(array $options = [])
+    {
+        if (isset($options['debug_plugins'])) {
+            @trigger_error('The "debug_plugins" option is deprecated since 1.5 and will be removed in 2.0.', E_USER_DEPRECATED);
+        }
+
+        $resolver = new OptionsResolver();
+        $resolver->setDefaults([
+            'max_restarts' => 10,
+            'debug_plugins' => [],
+        ]);
+
+        $resolver
+            ->setAllowedTypes('debug_plugins', 'array')
+            ->setAllowedValues('debug_plugins', function (array $plugins) {
+                foreach ($plugins as $plugin) {
+                    // Make sure each object passed with the `debug_plugins` is an instance of Plugin.
+                    if (!$plugin instanceof Plugin) {
+                        return false;
+                    }
+                }
+
+                return true;
+            });
+
+        return $resolver->resolve($options);
+    }
+
+    /**
+     * Create the plugin chain.
+     *
+     * @param Plugin[] $pluginList     A list of plugins
+     * @param callable $clientCallable Callable making the HTTP call
+     *
+     * @return callable
+     */
+    private function createPluginChain($pluginList, callable $clientCallable)
+    {
+        $firstCallable = $lastCallable = $clientCallable;
+
+        /*
+         * Inject debug plugins between each plugin.
+         */
+        $pluginListWithDebug = $this->options['debug_plugins'];
+        foreach ($pluginList as $plugin) {
+            $pluginListWithDebug[] = $plugin;
+            $pluginListWithDebug = array_merge($pluginListWithDebug, $this->options['debug_plugins']);
+        }
+
+        while ($plugin = array_pop($pluginListWithDebug)) {
+            $lastCallable = function (RequestInterface $request) use ($plugin, $lastCallable, &$firstCallable) {
+                return $plugin->handleRequest($request, $lastCallable, $firstCallable);
+            };
+
+            $firstCallable = $lastCallable;
+        }
+
+        $firstCalls = 0;
+        $firstCallable = function (RequestInterface $request) use ($lastCallable, &$firstCalls) {
+            if ($firstCalls > $this->options['max_restarts']) {
+                throw new LoopException('Too many restarts in plugin client', $request);
+            }
+
+            ++$firstCalls;
+
+            return $lastCallable($request);
+        };
+
+        return $firstCallable;
+    }
+}
diff --git a/vendor/php-http/client-common/src/PluginClientFactory.php b/vendor/php-http/client-common/src/PluginClientFactory.php
new file mode 100644
index 00000000000..bd4c08f9a62
--- /dev/null
+++ b/vendor/php-http/client-common/src/PluginClientFactory.php
@@ -0,0 +1,62 @@
+<?php
+
+namespace Http\Client\Common;
+
+use Http\Client\HttpAsyncClient;
+use Http\Client\HttpClient;
+
+/**
+ * Factory to create PluginClient instances. Using this factory instead of calling PluginClient constructor will enable
+ * the Symfony profiling without any configuration.
+ *
+ * @author Fabien Bourigault <bourigaultfabien@gmail.com>
+ */
+final class PluginClientFactory
+{
+    /**
+     * @var callable
+     */
+    private static $factory;
+
+    /**
+     * Set the factory to use.
+     * The callable to provide must have the same arguments and return type as PluginClientFactory::createClient.
+     * This is used by the HTTPlugBundle to provide a better Symfony integration.
+     * Unlike the createClient method, this one is static to allow zero configuration profiling by hooking into early
+     * application execution.
+     *
+     * @internal
+     *
+     * @param callable $factory
+     */
+    public static function setFactory(callable $factory)
+    {
+        static::$factory = $factory;
+    }
+
+    /**
+     * @param HttpClient|HttpAsyncClient $client
+     * @param Plugin[]                   $plugins
+     * @param array                      $options {
+     *
+     *     @var string $client_name to give client a name which may be used when displaying client information  like in
+     *         the HTTPlugBundle profiler.
+     * }
+     *
+     * @see PluginClient constructor for PluginClient specific $options.
+     *
+     * @return PluginClient
+     */
+    public function createClient($client, array $plugins = [], array $options = [])
+    {
+        if (static::$factory) {
+            $factory = static::$factory;
+
+            return $factory($client, $plugins, $options);
+        }
+
+        unset($options['client_name']);
+
+        return new PluginClient($client, $plugins, $options);
+    }
+}
diff --git a/vendor/php-http/guzzle6-adapter/CHANGELOG.md b/vendor/php-http/guzzle6-adapter/CHANGELOG.md
new file mode 100644
index 00000000000..0fdb5069f33
--- /dev/null
+++ b/vendor/php-http/guzzle6-adapter/CHANGELOG.md
@@ -0,0 +1,66 @@
+# Change Log
+
+
+## 1.1.1 - 2016-05-10
+
+### Fixed
+
+- Adapter can again be instantiated without a guzzle client.
+
+## 1.1.0 - 2016-05-09
+
+### Added
+
+- Factory method Client::createWithConfig to create an adapter with custom
+  configuration for the underlying guzzle client.
+
+
+## 1.0.0 - 2016-01-26
+
+
+## 0.4.1 - 2016-01-13
+
+### Changed
+
+- Updated integration tests
+
+### Removed
+
+- Client common dependency
+
+
+## 0.4.0 - 2016-01-12
+
+### Changed
+
+- Updated package files
+- Updated HTTPlug to RC1
+
+
+## 0.2.1 - 2015-12-17
+
+### Added
+
+- Puli configuration and bindings
+
+### Changed
+
+- Guzzle setup conforms to HTTPlug requirement now: Minimal functionality in client
+
+
+## 0.2.0 - 2015-12-15
+
+### Added
+
+- Async client capabalities
+
+### Changed
+
+- HTTPlug instead of HTTP Adapter
+
+
+## 0.1.0 - 2015-06-12
+
+### Added
+
+- Initial release
diff --git a/vendor/php-http/guzzle6-adapter/LICENSE b/vendor/php-http/guzzle6-adapter/LICENSE
new file mode 100644
index 00000000000..48741e41658
--- /dev/null
+++ b/vendor/php-http/guzzle6-adapter/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2014-2015 Eric GELOEN <geloen.eric@gmail.com>
+Copyright (c) 2015-2016 PHP HTTP Team <team@php-http.org>
+
+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/vendor/php-http/guzzle6-adapter/README.md b/vendor/php-http/guzzle6-adapter/README.md
new file mode 100644
index 00000000000..623eb2f8d31
--- /dev/null
+++ b/vendor/php-http/guzzle6-adapter/README.md
@@ -0,0 +1,59 @@
+# Guzzle 6 HTTP Adapter
+
+[![Latest Version](https://img.shields.io/github/release/php-http/guzzle6-adapter.svg?style=flat-square)](https://github.com/php-http/guzzle6-adapter/releases)
+[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)
+[![Build Status](https://img.shields.io/travis/php-http/guzzle6-adapter.svg?style=flat-square)](https://travis-ci.org/php-http/guzzle6-adapter)
+[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/php-http/guzzle6-adapter.svg?style=flat-square)](https://scrutinizer-ci.com/g/php-http/guzzle6-adapter)
+[![Quality Score](https://img.shields.io/scrutinizer/g/php-http/guzzle6-adapter.svg?style=flat-square)](https://scrutinizer-ci.com/g/php-http/guzzle6-adapter)
+[![Total Downloads](https://img.shields.io/packagist/dt/php-http/guzzle6-adapter.svg?style=flat-square)](https://packagist.org/packages/php-http/guzzle6-adapter)
+
+**Guzzle 6 HTTP Adapter.**
+
+
+## Install
+
+Via Composer
+
+``` bash
+$ composer require php-http/guzzle6-adapter
+```
+
+
+## Documentation
+
+Please see the [official documentation](http://docs.php-http.org/en/latest/clients/guzzle6-adapter.html).
+
+
+## Testing
+
+First launch the http server:
+
+```bash
+$ ./vendor/bin/http_test_server > /dev/null 2>&1 &
+```
+
+Then the test suite:
+
+``` bash
+$ composer test
+```
+
+
+## Contributing
+
+Please see our [contributing guide](http://docs.php-http.org/en/latest/development/contributing.html).
+
+
+## Security
+
+If you discover any security related issues, please contact us at [security@php-http.org](mailto:security@php-http.org).
+
+
+## Credits
+
+Thanks to [David de Boer](https://github.com/ddeboer) for implementing this adapter.
+
+
+## License
+
+The MIT License (MIT). Please see [License File](LICENSE) for more information.
diff --git a/vendor/php-http/guzzle6-adapter/composer.json b/vendor/php-http/guzzle6-adapter/composer.json
new file mode 100644
index 00000000000..2f01d1a465d
--- /dev/null
+++ b/vendor/php-http/guzzle6-adapter/composer.json
@@ -0,0 +1,49 @@
+{
+    "name": "php-http/guzzle6-adapter",
+    "description": "Guzzle 6 HTTP Adapter",
+    "license": "MIT",
+    "keywords": ["guzzle", "http"],
+    "homepage": "http://httplug.io",
+    "authors": [
+        {
+            "name": "David de Boer",
+            "email": "david@ddeboer.nl"
+        },
+        {
+            "name": "Márk Sági-Kazár",
+            "email": "mark.sagikazar@gmail.com"
+        }
+    ],
+    "require": {
+        "php": ">=5.5.0",
+        "php-http/httplug": "^1.0",
+        "guzzlehttp/guzzle": "^6.0"
+    },
+    "require-dev": {
+        "ext-curl": "*",
+        "php-http/adapter-integration-tests": "^0.4"
+    },
+    "provide": {
+        "php-http/client-implementation": "1.0",
+        "php-http/async-client-implementation": "1.0"
+    },
+    "autoload": {
+        "psr-4": {
+            "Http\\Adapter\\Guzzle6\\": "src/"
+        }
+    },
+    "autoload-dev": {
+        "psr-4": {
+            "Http\\Adapter\\Guzzle6\\Tests\\": "tests/"
+        }
+    },
+    "scripts": {
+        "test": "vendor/bin/phpunit",
+        "test-ci": "vendor/bin/phpunit --coverage-text --coverage-clover=build/coverage.xml"
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "1.2-dev"
+        }
+    }
+}
diff --git a/vendor/php-http/guzzle6-adapter/puli.json b/vendor/php-http/guzzle6-adapter/puli.json
new file mode 100644
index 00000000000..bd296146404
--- /dev/null
+++ b/vendor/php-http/guzzle6-adapter/puli.json
@@ -0,0 +1,16 @@
+{
+    "version": "1.0",
+    "name": "php-http/guzzle6-adapter",
+    "bindings": {
+        "04b5a002-71a8-473d-a8df-75671551b84a": {
+            "_class": "Puli\\Discovery\\Binding\\ClassBinding",
+            "class": "Http\\Adapter\\Guzzle6\\Client",
+            "type": "Http\\Client\\HttpClient"
+        },
+        "9c856476-7f6b-43df-a740-15420a5f839c": {
+            "_class": "Puli\\Discovery\\Binding\\ClassBinding",
+            "class": "Http\\Adapter\\Guzzle6\\Client",
+            "type": "Http\\Client\\HttpAsyncClient"
+        }
+    }
+}
diff --git a/vendor/php-http/guzzle6-adapter/src/Client.php b/vendor/php-http/guzzle6-adapter/src/Client.php
new file mode 100644
index 00000000000..ded7494bddf
--- /dev/null
+++ b/vendor/php-http/guzzle6-adapter/src/Client.php
@@ -0,0 +1,84 @@
+<?php
+
+namespace Http\Adapter\Guzzle6;
+
+use GuzzleHttp\Client as GuzzleClient;
+use GuzzleHttp\ClientInterface;
+use GuzzleHttp\HandlerStack;
+use GuzzleHttp\Middleware;
+use Http\Client\HttpAsyncClient;
+use Http\Client\HttpClient;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * HTTP Adapter for Guzzle 6.
+ *
+ * @author David de Boer <david@ddeboer.nl>
+ */
+class Client implements HttpClient, HttpAsyncClient
+{
+    /**
+     * @var ClientInterface
+     */
+    private $client;
+
+    /**
+     * @param ClientInterface|null $client
+     */
+    public function __construct(ClientInterface $client = null)
+    {
+        if (!$client) {
+            $client = static::buildClient();
+        }
+
+        $this->client = $client;
+    }
+
+    /**
+     * Factory method to create the guzzle 6 adapter with custom configuration for guzzle.
+     *
+     * @param array $config Configuration to create guzzle with.
+     *
+     * @return Client
+     */
+    public static function createWithConfig(array $config)
+    {
+        return new self(static::buildClient($config));
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function sendRequest(RequestInterface $request)
+    {
+        $promise = $this->sendAsyncRequest($request);
+
+        return $promise->wait();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function sendAsyncRequest(RequestInterface $request)
+    {
+        $promise = $this->client->sendAsync($request);
+
+        return new Promise($promise, $request);
+    }
+
+    /**
+     * Build the guzzle client instance.
+     *
+     * @param array $config Additional configuration
+     *
+     * @return GuzzleClient
+     */
+    private static function buildClient(array $config = [])
+    {
+        $handlerStack = new HandlerStack(\GuzzleHttp\choose_handler());
+        $handlerStack->push(Middleware::prepareBody(), 'prepare_body');
+        $config = array_merge(['handler' => $handlerStack], $config);
+
+        return new GuzzleClient($config);
+    }
+}
diff --git a/vendor/php-http/guzzle6-adapter/src/Promise.php b/vendor/php-http/guzzle6-adapter/src/Promise.php
new file mode 100644
index 00000000000..4d5eb8df207
--- /dev/null
+++ b/vendor/php-http/guzzle6-adapter/src/Promise.php
@@ -0,0 +1,140 @@
+<?php
+
+namespace Http\Adapter\Guzzle6;
+
+use GuzzleHttp\Exception as GuzzleExceptions;
+use GuzzleHttp\Promise\PromiseInterface;
+use Http\Client\Exception as HttplugException;
+use Http\Promise\Promise as HttpPromise;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Wrapper around Guzzle promises.
+ *
+ * @author Joel Wurtz <joel.wurtz@gmail.com>
+ */
+class Promise implements HttpPromise
+{
+    /**
+     * @var PromiseInterface
+     */
+    private $promise;
+
+    /**
+     * @var string State of the promise
+     */
+    private $state;
+
+    /**
+     * @var ResponseInterface
+     */
+    private $response;
+
+    /**
+     * @var HttplugException
+     */
+    private $exception;
+
+    /**
+     * @var RequestInterface
+     */
+    private $request;
+
+    /**
+     * @param PromiseInterface $promise
+     * @param RequestInterface $request
+     */
+    public function __construct(PromiseInterface $promise, RequestInterface $request)
+    {
+        $this->request = $request;
+        $this->state = self::PENDING;
+        $this->promise = $promise->then(function ($response) {
+            $this->response = $response;
+            $this->state = self::FULFILLED;
+
+            return $response;
+        }, function ($reason) use ($request) {
+            $this->state = self::REJECTED;
+
+            if ($reason instanceof HttplugException) {
+                $this->exception = $reason;
+            } elseif ($reason instanceof GuzzleExceptions\GuzzleException) {
+                $this->exception = $this->handleException($reason, $request);
+            } elseif ($reason instanceof \Exception) {
+                $this->exception = new \RuntimeException('Invalid exception returned from Guzzle6', 0, $reason);
+            } else {
+                $this->exception = new \UnexpectedValueException('Reason returned from Guzzle6 must be an Exception', 0, $reason);
+            }
+
+            throw $this->exception;
+        });
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function then(callable $onFulfilled = null, callable $onRejected = null)
+    {
+        return new static($this->promise->then($onFulfilled, $onRejected), $this->request);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getState()
+    {
+        return $this->state;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function wait($unwrap = true)
+    {
+        $this->promise->wait(false);
+
+        if ($unwrap) {
+            if ($this->getState() == self::REJECTED) {
+                throw $this->exception;
+            }
+
+            return $this->response;
+        }
+    }
+
+    /**
+     * Converts a Guzzle exception into an Httplug exception.
+     *
+     * @param GuzzleExceptions\GuzzleException $exception
+     * @param RequestInterface                 $request
+     *
+     * @return HttplugException
+     */
+    private function handleException(GuzzleExceptions\GuzzleException $exception, RequestInterface $request)
+    {
+        if ($exception instanceof GuzzleExceptions\SeekException) {
+            return new HttplugException\RequestException($exception->getMessage(), $request, $exception);
+        }
+
+        if ($exception instanceof GuzzleExceptions\ConnectException) {
+            return new HttplugException\NetworkException($exception->getMessage(), $exception->getRequest(), $exception);
+        }
+
+        if ($exception instanceof GuzzleExceptions\RequestException) {
+            // Make sure we have a response for the HttpException
+            if ($exception->hasResponse()) {
+                return new HttplugException\HttpException(
+                    $exception->getMessage(),
+                    $exception->getRequest(),
+                    $exception->getResponse(),
+                    $exception
+                );
+            }
+
+            return new HttplugException\RequestException($exception->getMessage(), $exception->getRequest(), $exception);
+        }
+
+        return new HttplugException\TransferException($exception->getMessage(), 0, $exception);
+    }
+}
diff --git a/vendor/php-http/multipart-stream-builder/CHANGELOG.md b/vendor/php-http/multipart-stream-builder/CHANGELOG.md
new file mode 100644
index 00000000000..1f0ee3d7f32
--- /dev/null
+++ b/vendor/php-http/multipart-stream-builder/CHANGELOG.md
@@ -0,0 +1,60 @@
+# Change Log
+
+## 1.0.0 - 2017-05-21
+
+No changes from 0.2.0.
+
+## 0.2.0 - 2017-02-20
+
+You may do a BC update to version 0.2.0 if you are sure that you are not adding
+multiple resources with the same name to the Builder. 
+
+### Fixed
+
+- Make sure one can add resources with same name without overwrite. 
+
+## 0.1.6 - 2017-02-16
+
+### Fixed
+
+- Performance improvements by avoid using `uniqid()`. 
+
+## 0.1.5 - 2017-02-14
+
+### Fixed
+
+- Support for non-readable streams. This fix was needed because flaws in Guzzle, Zend and Slims implementations of PSR-7. 
+
+## 0.1.4 - 2016-12-31
+
+### Added
+
+- Added support for resetting the builder
+
+## 0.1.3 - 2016-12-22
+
+### Added
+
+- Added `CustomMimetypeHelper` to allow you to configure custom mimetypes. 
+
+### Changed
+
+- Using regular expression instead of `basename($filename)` because basename is depending on locale.
+
+## 0.1.2 - 2016-08-31
+
+### Added
+
+- Support for Outlook msg files. 
+
+## 0.1.1 - 2016-08-10
+
+### Added
+
+- Support for Apple passbook. 
+
+## 0.1.0 - 2016-07-19
+
+### Added
+
+- Initial release
diff --git a/vendor/php-http/multipart-stream-builder/LICENSE b/vendor/php-http/multipart-stream-builder/LICENSE
new file mode 100644
index 00000000000..8e2c4a0b85c
--- /dev/null
+++ b/vendor/php-http/multipart-stream-builder/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2015 PHP HTTP Team <team@php-http.org>
+
+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/vendor/php-http/multipart-stream-builder/README.md b/vendor/php-http/multipart-stream-builder/README.md
new file mode 100644
index 00000000000..10ad0588b4b
--- /dev/null
+++ b/vendor/php-http/multipart-stream-builder/README.md
@@ -0,0 +1,37 @@
+# PSR-7 Multipart Stream Builder
+
+[![Latest Version](https://img.shields.io/github/release/php-http/multipart-stream-builder.svg?style=flat-square)](https://github.com/php-http/multipart-stream-builder/releases)
+[![Build Status](https://img.shields.io/travis/php-http/multipart-stream-builder.svg?style=flat-square)](https://travis-ci.org/php-http/multipart-stream-builder)
+[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/php-http/multipart-stream-builder.svg?style=flat-square)](https://scrutinizer-ci.com/g/php-http/multipart-stream-builder)
+[![Quality Score](https://img.shields.io/scrutinizer/g/php-http/multipart-stream-builder.svg?style=flat-square)](https://scrutinizer-ci.com/g/php-http/multipart-stream-builder)
+[![Total Downloads](https://img.shields.io/packagist/dt/php-http/multipart-stream-builder.svg?style=flat-square)](https://packagist.org/packages/php-http/multipart-stream-builder)
+
+**A builder for Multipart PSR-7 Streams. The builder create streams independenly form any PSR-7 implementation.**
+
+
+## Install
+
+Via Composer
+
+``` bash
+$ composer require php-http/multipart-stream-builder
+```
+
+## Documentation
+
+Please see the [official documentation](http://php-http.readthedocs.org/en/latest/components/multipart-stream-builder.html).
+
+
+## Contributing
+
+Please see [CONTRIBUTING](CONTRIBUTING.md) and [CONDUCT](CONDUCT.md) for details.
+
+
+## Security
+
+If you discover any security related issues, please contact us at [security@php-http.org](mailto:security@php-http.org).
+
+
+## License
+
+The MIT License (MIT). Please see [License File](LICENSE) for more information.
diff --git a/vendor/php-http/multipart-stream-builder/appveyor.yml b/vendor/php-http/multipart-stream-builder/appveyor.yml
new file mode 100644
index 00000000000..8d7af73f722
--- /dev/null
+++ b/vendor/php-http/multipart-stream-builder/appveyor.yml
@@ -0,0 +1,39 @@
+build: false
+platform:
+  - x86
+  - x64
+
+clone_folder: c:\projects\php-http\multipart-stream-builder
+
+cache:
+  - c:\tools\php -> appveyor.yml
+
+init:
+  - SET PATH=c:\php;%PATH%
+  - SET COMPOSER_NO_INTERACTION=1
+  - SET PHP=1
+
+
+install:
+  - IF EXIST c:\php (SET PHP=0) ELSE (mkdir c:\php)
+  - cd c:\php
+  - IF %PHP%==1 appveyor DownloadFile http://windows.php.net/downloads/releases/archives/php-7.0.0-nts-Win32-VC14-x86.zip
+  - IF %PHP%==1 7z x php-7.0.0-nts-Win32-VC14-x86.zip -y >nul
+  - IF %PHP%==1 del /Q *.zip
+  - IF %PHP%==1 echo @php %%~dp0composer.phar %%* > composer.bat
+  - IF %PHP%==1 copy /Y php.ini-development php.ini
+  - IF %PHP%==1 echo max_execution_time=1200 >> php.ini
+  - IF %PHP%==1 echo date.timezone="UTC" >> php.ini
+  - IF %PHP%==1 echo extension_dir=ext >> php.ini
+  - IF %PHP%==1 echo extension=php_openssl.dll >> php.ini
+  - IF %PHP%==1 echo extension=php_mbstring.dll >> php.ini
+  - IF %PHP%==1 echo extension=php_fileinfo.dll >> php.ini
+  - appveyor DownloadFile https://getcomposer.org/composer.phar
+  - cd c:\projects\php-http\multipart-stream-builder
+  - mkdir %APPDATA%\Composer
+  - composer update --prefer-dist --no-progress --ansi
+
+test_script:
+  - cd c:\projects\php-http\multipart-stream-builder
+  - vendor\bin\phpunit.bat --verbose
+
diff --git a/vendor/php-http/multipart-stream-builder/composer.json b/vendor/php-http/multipart-stream-builder/composer.json
new file mode 100644
index 00000000000..1ada3605c54
--- /dev/null
+++ b/vendor/php-http/multipart-stream-builder/composer.json
@@ -0,0 +1,43 @@
+{
+    "name": "php-http/multipart-stream-builder",
+    "description": "A builder class that help you create a multipart stream",
+    "license": "MIT",
+    "keywords": ["http", "factory", "message", "stream", "multipart stream"],
+    "homepage": "http://php-http.org",
+    "authors": [
+        {
+            "name": "Tobias Nyholm",
+            "email": "tobias.nyholm@gmail.com"
+        }
+    ],
+    "require": {
+        "php": "^5.5 || ^7.0",
+        "psr/http-message": "^1.0",
+        "php-http/message-factory": "^1.0.2",
+        "php-http/discovery": "^1.0"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^4.8 || ^5.4",
+        "php-http/message": "^1.5",
+        "zendframework/zend-diactoros": "^1.3.5"
+    },
+    "autoload": {
+        "psr-4": {
+            "Http\\Message\\MultipartStream\\": "src/"
+        }
+    },
+    "autoload-dev": {
+        "psr-4": {
+            "tests\\Http\\Message\\MultipartStream\\": "tests/"
+        }
+    },
+    "scripts": {
+        "test": "vendor/bin/phpunit",
+        "test-ci": "vendor/bin/phpunit --coverage-text --coverage-clover=build/coverage.xml"
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "0.3-dev"
+        }
+    }
+}
diff --git a/vendor/php-http/multipart-stream-builder/src/ApacheMimetypeHelper.php b/vendor/php-http/multipart-stream-builder/src/ApacheMimetypeHelper.php
new file mode 100644
index 00000000000..6e4ca660246
--- /dev/null
+++ b/vendor/php-http/multipart-stream-builder/src/ApacheMimetypeHelper.php
@@ -0,0 +1,142 @@
+<?php
+
+namespace Http\Message\MultipartStream;
+
+/**
+ * This class helps to find the proper mime types. The source of this file is taken
+ * from Guzzle.
+ *
+ * @author Michael Dowling and contributors to guzzlehttp/psr7
+ * @author Tobias Nyholm <tobias.nyholm@gmail.com>
+ */
+class ApacheMimetypeHelper implements MimetypeHelper
+{
+    /**
+     * {@inheritdoc}
+     *
+     * @see http://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x/conf/mime.types
+     */
+    public function getMimetypeFromFilename($filename)
+    {
+        return $this->getMimetypeFromExtension(pathinfo($filename, PATHINFO_EXTENSION));
+    }
+
+    /**
+     * {@inheritdoc}
+     *
+     * @see http://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x/conf/mime.types
+     */
+    public function getMimetypeFromExtension($extension)
+    {
+        static $mimetypes = [
+            '7z' => 'application/x-7z-compressed',
+            'aac' => 'audio/x-aac',
+            'ai' => 'application/postscript',
+            'aif' => 'audio/x-aiff',
+            'asc' => 'text/plain',
+            'asf' => 'video/x-ms-asf',
+            'atom' => 'application/atom+xml',
+            'avi' => 'video/x-msvideo',
+            'bmp' => 'image/bmp',
+            'bz2' => 'application/x-bzip2',
+            'cer' => 'application/pkix-cert',
+            'crl' => 'application/pkix-crl',
+            'crt' => 'application/x-x509-ca-cert',
+            'css' => 'text/css',
+            'csv' => 'text/csv',
+            'cu' => 'application/cu-seeme',
+            'deb' => 'application/x-debian-package',
+            'doc' => 'application/msword',
+            'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+            'dvi' => 'application/x-dvi',
+            'eot' => 'application/vnd.ms-fontobject',
+            'eps' => 'application/postscript',
+            'epub' => 'application/epub+zip',
+            'etx' => 'text/x-setext',
+            'flac' => 'audio/flac',
+            'flv' => 'video/x-flv',
+            'gif' => 'image/gif',
+            'gz' => 'application/gzip',
+            'htm' => 'text/html',
+            'html' => 'text/html',
+            'ico' => 'image/x-icon',
+            'ics' => 'text/calendar',
+            'ini' => 'text/plain',
+            'iso' => 'application/x-iso9660-image',
+            'jar' => 'application/java-archive',
+            'jpe' => 'image/jpeg',
+            'jpeg' => 'image/jpeg',
+            'jpg' => 'image/jpeg',
+            'js' => 'text/javascript',
+            'json' => 'application/json',
+            'latex' => 'application/x-latex',
+            'log' => 'text/plain',
+            'm4a' => 'audio/mp4',
+            'm4v' => 'video/mp4',
+            'mid' => 'audio/midi',
+            'midi' => 'audio/midi',
+            'mov' => 'video/quicktime',
+            'mp3' => 'audio/mpeg',
+            'mp4' => 'video/mp4',
+            'mp4a' => 'audio/mp4',
+            'mp4v' => 'video/mp4',
+            'mpe' => 'video/mpeg',
+            'mpeg' => 'video/mpeg',
+            'mpg' => 'video/mpeg',
+            'mpg4' => 'video/mp4',
+            'oga' => 'audio/ogg',
+            'ogg' => 'audio/ogg',
+            'ogv' => 'video/ogg',
+            'ogx' => 'application/ogg',
+            'pbm' => 'image/x-portable-bitmap',
+            'pdf' => 'application/pdf',
+            'pgm' => 'image/x-portable-graymap',
+            'png' => 'image/png',
+            'pnm' => 'image/x-portable-anymap',
+            'ppm' => 'image/x-portable-pixmap',
+            'ppt' => 'application/vnd.ms-powerpoint',
+            'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+            'ps' => 'application/postscript',
+            'qt' => 'video/quicktime',
+            'rar' => 'application/x-rar-compressed',
+            'ras' => 'image/x-cmu-raster',
+            'rss' => 'application/rss+xml',
+            'rtf' => 'application/rtf',
+            'sgm' => 'text/sgml',
+            'sgml' => 'text/sgml',
+            'svg' => 'image/svg+xml',
+            'swf' => 'application/x-shockwave-flash',
+            'tar' => 'application/x-tar',
+            'tif' => 'image/tiff',
+            'tiff' => 'image/tiff',
+            'torrent' => 'application/x-bittorrent',
+            'ttf' => 'application/x-font-ttf',
+            'txt' => 'text/plain',
+            'wav' => 'audio/x-wav',
+            'webm' => 'video/webm',
+            'wma' => 'audio/x-ms-wma',
+            'wmv' => 'video/x-ms-wmv',
+            'woff' => 'application/x-font-woff',
+            'wsdl' => 'application/wsdl+xml',
+            'xbm' => 'image/x-xbitmap',
+            'xls' => 'application/vnd.ms-excel',
+            'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+            'xml' => 'application/xml',
+            'xpm' => 'image/x-xpixmap',
+            'xwd' => 'image/x-xwindowdump',
+            'yaml' => 'text/yaml',
+            'yml' => 'text/yaml',
+            'zip' => 'application/zip',
+
+            // Non-Apache standard
+            'pkpass' => 'application/vnd.apple.pkpass',
+            'msg' => 'application/vnd.ms-outlook',
+        ];
+
+        $extension = strtolower($extension);
+
+        return isset($mimetypes[$extension])
+            ? $mimetypes[$extension]
+            : null;
+    }
+}
diff --git a/vendor/php-http/multipart-stream-builder/src/CustomMimetypeHelper.php b/vendor/php-http/multipart-stream-builder/src/CustomMimetypeHelper.php
new file mode 100644
index 00000000000..9f3f0d9211e
--- /dev/null
+++ b/vendor/php-http/multipart-stream-builder/src/CustomMimetypeHelper.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace Http\Message\MultipartStream;
+
+/**
+ * Let you add your own mimetypes. The mimetype lookup will fallback on the ApacheMimeTypeHelper.
+ *
+ * @author Tobias Nyholm <tobias.nyholm@gmail.com>
+ */
+class CustomMimetypeHelper extends ApacheMimetypeHelper
+{
+    /**
+     * @var array
+     */
+    private $mimetypes = [];
+
+    /**
+     * @param array $mimetypes should be of type extension => mimetype
+     */
+    public function __construct(array $mimetypes = [])
+    {
+        $this->mimetypes = $mimetypes;
+    }
+
+    /**
+     * @param string $extension
+     * @param string $mimetype
+     *
+     * @return $this
+     */
+    public function addMimetype($extension, $mimetype)
+    {
+        $this->mimetypes[$extension] = $mimetype;
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     *
+     * Check if we have any defined mimetypes and of not fallback to ApacheMimetypeHelper
+     */
+    public function getMimetypeFromExtension($extension)
+    {
+        $extension = strtolower($extension);
+
+        return isset($this->mimetypes[$extension])
+            ? $this->mimetypes[$extension]
+            : parent::getMimetypeFromExtension($extension);
+    }
+}
diff --git a/vendor/php-http/multipart-stream-builder/src/MimetypeHelper.php b/vendor/php-http/multipart-stream-builder/src/MimetypeHelper.php
new file mode 100644
index 00000000000..fa7cf180037
--- /dev/null
+++ b/vendor/php-http/multipart-stream-builder/src/MimetypeHelper.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Http\Message\MultipartStream;
+
+/**
+ * @author Tobias Nyholm <tobias.nyholm@gmail.com>
+ */
+interface MimetypeHelper
+{
+    /**
+     * Determines the mimetype of a file by looking at its extension.
+     *
+     * @param string $filename
+     *
+     * @return null|string
+     */
+    public function getMimetypeFromFilename($filename);
+
+    /**
+     * Maps a file extensions to a mimetype.
+     *
+     * @param string $extension The file extension
+     *
+     * @return string|null
+     */
+    public function getMimetypeFromExtension($extension);
+}
diff --git a/vendor/php-http/multipart-stream-builder/src/MultipartStreamBuilder.php b/vendor/php-http/multipart-stream-builder/src/MultipartStreamBuilder.php
new file mode 100644
index 00000000000..3421d734874
--- /dev/null
+++ b/vendor/php-http/multipart-stream-builder/src/MultipartStreamBuilder.php
@@ -0,0 +1,278 @@
+<?php
+
+namespace Http\Message\MultipartStream;
+
+use Http\Discovery\StreamFactoryDiscovery;
+use Http\Message\StreamFactory;
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Build your own Multipart stream. A Multipart stream is a collection of streams separated with a $bounary. This
+ * class helps you to create a Multipart stream with stream implementations from any PSR7 library.
+ *
+ * @author Michael Dowling and contributors to guzzlehttp/psr7
+ * @author Tobias Nyholm <tobias.nyholm@gmail.com>
+ */
+class MultipartStreamBuilder
+{
+    /**
+     * @var StreamFactory
+     */
+    private $streamFactory;
+
+    /**
+     * @var MimetypeHelper
+     */
+    private $mimetypeHelper;
+
+    /**
+     * @var string
+     */
+    private $boundary;
+
+    /**
+     * @var array Element where each Element is an array with keys ['contents', 'headers', 'filename']
+     */
+    private $data = [];
+
+    /**
+     * @param StreamFactory|null $streamFactory
+     */
+    public function __construct(StreamFactory $streamFactory = null)
+    {
+        $this->streamFactory = $streamFactory ?: StreamFactoryDiscovery::find();
+    }
+
+    /**
+     * Add a resource to the Multipart Stream.
+     *
+     * @param string                          $name     the formpost name
+     * @param string|resource|StreamInterface $resource
+     * @param array                           $options  {
+     *
+     *     @var array $headers additional headers ['header-name' => 'header-value']
+     *     @var string $filename
+     * }
+     *
+     * @return MultipartStreamBuilder
+     */
+    public function addResource($name, $resource, array $options = [])
+    {
+        $stream = $this->streamFactory->createStream($resource);
+
+        // validate options['headers'] exists
+        if (!isset($options['headers'])) {
+            $options['headers'] = [];
+        }
+
+        // Try to add filename if it is missing
+        if (empty($options['filename'])) {
+            $options['filename'] = null;
+            $uri = $stream->getMetadata('uri');
+            if (substr($uri, 0, 6) !== 'php://') {
+                $options['filename'] = $uri;
+            }
+        }
+
+        $this->prepareHeaders($name, $stream, $options['filename'], $options['headers']);
+        $this->data[] = ['contents' => $stream, 'headers' => $options['headers'], 'filename' => $options['filename']];
+
+        return $this;
+    }
+
+    /**
+     * Build the stream.
+     *
+     * @return StreamInterface
+     */
+    public function build()
+    {
+        $streams = '';
+        foreach ($this->data as $data) {
+            // Add start and headers
+            $streams .= "--{$this->getBoundary()}\r\n".
+                $this->getHeaders($data['headers'])."\r\n";
+
+            // Convert the stream to string
+            /* @var $contentStream StreamInterface */
+            $contentStream = $data['contents'];
+            if ($contentStream->isSeekable()) {
+                $streams .= $contentStream->__toString();
+            } else {
+                $streams .= $contentStream->getContents();
+            }
+
+            $streams .= "\r\n";
+        }
+
+        // Append end
+        $streams .= "--{$this->getBoundary()}--\r\n";
+
+        return $this->streamFactory->createStream($streams);
+    }
+
+    /**
+     * Add extra headers if they are missing.
+     *
+     * @param string          $name
+     * @param StreamInterface $stream
+     * @param string          $filename
+     * @param array           &$headers
+     */
+    private function prepareHeaders($name, StreamInterface $stream, $filename, array &$headers)
+    {
+        $hasFilename = $filename === '0' || $filename;
+
+        // Set a default content-disposition header if one was not provided
+        if (!$this->hasHeader($headers, 'content-disposition')) {
+            $headers['Content-Disposition'] = sprintf('form-data; name="%s"', $name);
+            if ($hasFilename) {
+                $headers['Content-Disposition'] .= sprintf('; filename="%s"', $this->basename($filename));
+            }
+        }
+
+        // Set a default content-length header if one was not provided
+        if (!$this->hasHeader($headers, 'content-length')) {
+            if ($length = $stream->getSize()) {
+                $headers['Content-Length'] = (string) $length;
+            }
+        }
+
+        // Set a default Content-Type if one was not provided
+        if (!$this->hasHeader($headers, 'content-type') && $hasFilename) {
+            if ($type = $this->getMimetypeHelper()->getMimetypeFromFilename($filename)) {
+                $headers['Content-Type'] = $type;
+            }
+        }
+    }
+
+    /**
+     * Get the headers formatted for the HTTP message.
+     *
+     * @param array $headers
+     *
+     * @return string
+     */
+    private function getHeaders(array $headers)
+    {
+        $str = '';
+        foreach ($headers as $key => $value) {
+            $str .= sprintf("%s: %s\r\n", $key, $value);
+        }
+
+        return $str;
+    }
+
+    /**
+     * Check if header exist.
+     *
+     * @param array  $headers
+     * @param string $key     case insensitive
+     *
+     * @return bool
+     */
+    private function hasHeader(array $headers, $key)
+    {
+        $lowercaseHeader = strtolower($key);
+        foreach ($headers as $k => $v) {
+            if (strtolower($k) === $lowercaseHeader) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Get the boundary that separates the streams.
+     *
+     * @return string
+     */
+    public function getBoundary()
+    {
+        if ($this->boundary === null) {
+            $this->boundary = uniqid('', true);
+        }
+
+        return $this->boundary;
+    }
+
+    /**
+     * @param string $boundary
+     *
+     * @return MultipartStreamBuilder
+     */
+    public function setBoundary($boundary)
+    {
+        $this->boundary = $boundary;
+
+        return $this;
+    }
+
+    /**
+     * @return MimetypeHelper
+     */
+    private function getMimetypeHelper()
+    {
+        if ($this->mimetypeHelper === null) {
+            $this->mimetypeHelper = new ApacheMimetypeHelper();
+        }
+
+        return $this->mimetypeHelper;
+    }
+
+    /**
+     * If you have custom file extension you may overwrite the default MimetypeHelper with your own.
+     *
+     * @param MimetypeHelper $mimetypeHelper
+     *
+     * @return MultipartStreamBuilder
+     */
+    public function setMimetypeHelper(MimetypeHelper $mimetypeHelper)
+    {
+        $this->mimetypeHelper = $mimetypeHelper;
+
+        return $this;
+    }
+
+    /**
+     * Reset and clear all stored data. This allows you to use builder for a subsequent request.
+     *
+     * @return MultipartStreamBuilder
+     */
+    public function reset()
+    {
+        $this->data = [];
+        $this->boundary = null;
+
+        return $this;
+    }
+
+    /**
+     * Gets the filename from a given path.
+     *
+     * PHP's basename() does not properly support streams or filenames beginning with a non-US-ASCII character.
+     *
+     * @author Drupal 8.2
+     *
+     * @param string $path
+     *
+     * @return string
+     */
+    private function basename($path)
+    {
+        $separators = '/';
+        if (DIRECTORY_SEPARATOR != '/') {
+            // For Windows OS add special separator.
+            $separators .= DIRECTORY_SEPARATOR;
+        }
+
+        // Remove right-most slashes when $path points to directory.
+        $path = rtrim($path, $separators);
+
+        // Returns the trailing part of the $path starting after one of the directory separators.
+        $filename = preg_match('@[^'.preg_quote($separators, '@').']+$@', $path, $matches) ? $matches[0] : '';
+
+        return $filename;
+    }
+}
-- 
GitLab