Update Composer, update everything

This commit is contained in:
Oliver Davies 2018-11-23 12:29:20 +00:00
parent ea3e94409f
commit dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions

1
vendor/stack/builder/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
vendor

20
vendor/stack/builder/.travis.yml vendored Normal file
View file

@ -0,0 +1,20 @@
language: php
php:
- 5.3.3
- 5.3
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
before_script:
- composer install --no-interaction --prefer-source
script: phpunit --coverage-text
matrix:
allow_failures:
- php: hhvm
fast_finish: true

26
vendor/stack/builder/CHANGELOG.md vendored Normal file
View file

@ -0,0 +1,26 @@
CHANGELOG
=========
* 1.0.5 (2017-11-18)
* Add compability with Symfony 4.
* 1.0.4 (2016-06-02)
* Add compability with Symfony 3.
* 1.0.3 (2014-11-23)
* Only call Terminable middlewares once.
* 1.0.2 (2014-05-18)
* Validate missing arguments (@bajbnet).
* 1.0.1 (2013-10-25)
* Lower PHP requirement to 5.3.
* 1.0.0 (2013-08-02)
* Initial release.

19
vendor/stack/builder/LICENSE vendored Normal file
View file

@ -0,0 +1,19 @@
Copyright (c) 2013 Igor Wiedler
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.

69
vendor/stack/builder/README.md vendored Normal file
View file

@ -0,0 +1,69 @@
# Stack/Builder
Builder for stack middlewares based on HttpKernelInterface.
Stack/Builder is a small library that helps you construct a nested
HttpKernelInterface decorator tree. It models it as a stack of middlewares.
## Example
If you want to decorate a [silex](https://github.com/fabpot/Silex) app with
session and cache middlewares, you'll have to do something like this:
```php
use Symfony\Component\HttpKernel\HttpCache\Store;
$app = new Silex\Application();
$app->get('/', function () {
return 'Hello World!';
});
$app = new Stack\Session(
new Symfony\Component\HttpKernel\HttpCache\HttpCache(
$app,
new Store(__DIR__.'/cache')
)
);
```
This can get quite annoying indeed. Stack/Builder simplifies that:
```php
$stack = (new Stack\Builder())
->push('Stack\Session')
->push('Symfony\Component\HttpKernel\HttpCache\HttpCache', new Store(__DIR__.'/cache'));
$app = $stack->resolve($app);
```
As you can see, by arranging the layers as a stack, they become a lot easier
to work with.
In the front controller, you need to serve the request:
```php
use Symfony\Component\HttpFoundation\Request;
$request = Request::createFromGlobals();
$response = $app->handle($request)->send();
$app->terminate($request, $response);
```
Stack/Builder also supports pushing a `callable` on to the stack, for situations
where instantiating middlewares might be more complicated. The `callable` should
accept a `HttpKernelInterface` as the first argument and should also return a
`HttpKernelInterface`. The example above could be rewritten as:
```php
$stack = (new Stack\Builder())
->push('Stack\Session')
->push(function ($app) {
$cache = new HttpCache($app, new Store(__DIR__.'/cache'));
return $cache;
})
;
```
## Inspiration
* [Rack::Builder](http://rack.rubyforge.org/doc/Rack/Builder.html)
* [HttpKernel middlewares](https://igor.io/2013/02/02/http-kernel-middlewares.html)

26
vendor/stack/builder/composer.json vendored Normal file
View file

@ -0,0 +1,26 @@
{
"name": "stack/builder",
"description": "Builder for stack middlewares based on HttpKernelInterface.",
"keywords": ["stack"],
"license": "MIT",
"authors": [
{
"name": "Igor Wiedler",
"email": "igor@wiedler.ch"
}
],
"require": {
"php": ">=5.3.0",
"symfony/http-foundation": "~2.1|~3.0|~4.0",
"symfony/http-kernel": "~2.1|~3.0|~4.0"
},
"require-dev": {
"silex/silex": "~1.0"
},
"autoload": {
"psr-0": { "Stack": "src" }
},
"extra": {
"branch-alias": { "dev-master": "1.0-dev" }
}
}

576
vendor/stack/builder/composer.lock generated vendored Normal file
View file

@ -0,0 +1,576 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "01b70e8acfcec52232420838dc8ba788",
"packages": [
{
"name": "psr/log",
"version": "1.0.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Log\\": "Psr/Log/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
"homepage": "https://github.com/php-fig/log",
"keywords": [
"log",
"psr",
"psr-3"
],
"time": "2016-10-10T12:19:37+00:00"
},
{
"name": "symfony/debug",
"version": "v3.3.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
"reference": "74557880e2846b5c84029faa96b834da37e29810"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/debug/zipball/74557880e2846b5c84029faa96b834da37e29810",
"reference": "74557880e2846b5c84029faa96b834da37e29810",
"shasum": ""
},
"require": {
"php": "^5.5.9|>=7.0.8",
"psr/log": "~1.0"
},
"conflict": {
"symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
},
"require-dev": {
"symfony/http-kernel": "~2.8|~3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.3-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Debug\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com",
"time": "2017-11-10T16:38:39+00:00"
},
{
"name": "symfony/event-dispatcher",
"version": "v3.0.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "54da3ff63dec3c9c0e32ec3f95a7d94ef64baa00"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/54da3ff63dec3c9c0e32ec3f95a7d94ef64baa00",
"reference": "54da3ff63dec3c9c0e32ec3f95a7d94ef64baa00",
"shasum": ""
},
"require": {
"php": ">=5.5.9"
},
"require-dev": {
"psr/log": "~1.0",
"symfony/config": "~2.8|~3.0",
"symfony/dependency-injection": "~2.8|~3.0",
"symfony/expression-language": "~2.8|~3.0",
"symfony/stopwatch": "~2.8|~3.0"
},
"suggest": {
"symfony/dependency-injection": "",
"symfony/http-kernel": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\EventDispatcher\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
"time": "2016-07-19T10:44:15+00:00"
},
{
"name": "symfony/http-foundation",
"version": "v3.0.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
"reference": "49ba00f8ede742169cb6b70abe33243f4d673f82"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/49ba00f8ede742169cb6b70abe33243f4d673f82",
"reference": "49ba00f8ede742169cb6b70abe33243f4d673f82",
"shasum": ""
},
"require": {
"php": ">=5.5.9",
"symfony/polyfill-mbstring": "~1.1"
},
"require-dev": {
"symfony/expression-language": "~2.8|~3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\HttpFoundation\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony HttpFoundation Component",
"homepage": "https://symfony.com",
"time": "2016-07-17T13:54:30+00:00"
},
{
"name": "symfony/http-kernel",
"version": "v3.0.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
"reference": "d97ba4425e36e79c794e7d14ff36f00f081b37b3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/d97ba4425e36e79c794e7d14ff36f00f081b37b3",
"reference": "d97ba4425e36e79c794e7d14ff36f00f081b37b3",
"shasum": ""
},
"require": {
"php": ">=5.5.9",
"psr/log": "~1.0",
"symfony/debug": "~2.8|~3.0",
"symfony/event-dispatcher": "~2.8|~3.0",
"symfony/http-foundation": "~2.8.8|~3.0.8|~3.1.2|~3.2"
},
"conflict": {
"symfony/config": "<2.8"
},
"require-dev": {
"symfony/browser-kit": "~2.8|~3.0",
"symfony/class-loader": "~2.8|~3.0",
"symfony/config": "~2.8|~3.0",
"symfony/console": "~2.8|~3.0",
"symfony/css-selector": "~2.8|~3.0",
"symfony/dependency-injection": "~2.8|~3.0",
"symfony/dom-crawler": "~2.8|~3.0",
"symfony/expression-language": "~2.8|~3.0",
"symfony/finder": "~2.8|~3.0",
"symfony/process": "~2.8|~3.0",
"symfony/routing": "~2.8|~3.0",
"symfony/stopwatch": "~2.8|~3.0",
"symfony/templating": "~2.8|~3.0",
"symfony/translation": "~2.8|~3.0",
"symfony/var-dumper": "~2.8|~3.0"
},
"suggest": {
"symfony/browser-kit": "",
"symfony/class-loader": "",
"symfony/config": "",
"symfony/console": "",
"symfony/dependency-injection": "",
"symfony/finder": "",
"symfony/var-dumper": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\HttpKernel\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony HttpKernel Component",
"homepage": "https://symfony.com",
"time": "2016-07-30T09:10:37+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.6.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296",
"reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.6-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"time": "2017-10-11T12:05:26+00:00"
}
],
"packages-dev": [
{
"name": "pimple/pimple",
"version": "v1.1.1",
"source": {
"type": "git",
"url": "https://github.com/silexphp/Pimple.git",
"reference": "2019c145fe393923f3441b23f29bbdfaa5c58c4d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/silexphp/Pimple/zipball/2019c145fe393923f3441b23f29bbdfaa5c58c4d",
"reference": "2019c145fe393923f3441b23f29bbdfaa5c58c4d",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1.x-dev"
}
},
"autoload": {
"psr-0": {
"Pimple": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
}
],
"description": "Pimple is a simple Dependency Injection Container for PHP 5.3",
"homepage": "http://pimple.sensiolabs.org",
"keywords": [
"container",
"dependency injection"
],
"time": "2013-11-22T08:30:29+00:00"
},
{
"name": "silex/silex",
"version": "v1.3.6",
"source": {
"type": "git",
"url": "https://github.com/silexphp/Silex.git",
"reference": "ff8aa6bc2e066e14b07e0c63e9bd9dd1458af136"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/silexphp/Silex/zipball/ff8aa6bc2e066e14b07e0c63e9bd9dd1458af136",
"reference": "ff8aa6bc2e066e14b07e0c63e9bd9dd1458af136",
"shasum": ""
},
"require": {
"php": ">=5.3.9",
"pimple/pimple": "~1.0",
"symfony/event-dispatcher": "~2.3|3.0.*",
"symfony/http-foundation": "~2.3|3.0.*",
"symfony/http-kernel": "~2.3|3.0.*",
"symfony/routing": "~2.3|3.0.*"
},
"require-dev": {
"doctrine/dbal": "~2.2",
"monolog/monolog": "^1.4.1",
"swiftmailer/swiftmailer": "~5",
"symfony/browser-kit": "~2.3|3.0.*",
"symfony/config": "~2.3|3.0.*",
"symfony/css-selector": "~2.3|3.0.*",
"symfony/debug": "~2.3|3.0.*",
"symfony/dom-crawler": "~2.3|3.0.*",
"symfony/finder": "~2.3|3.0.*",
"symfony/form": "~2.3|3.0.*",
"symfony/intl": "~2.3|3.0.*",
"symfony/monolog-bridge": "~2.3|3.0.*",
"symfony/options-resolver": "~2.3|3.0.*",
"symfony/phpunit-bridge": "~2.7",
"symfony/process": "~2.3|3.0.*",
"symfony/security": "~2.3|3.0.*",
"symfony/serializer": "~2.3|3.0.*",
"symfony/translation": "~2.3|3.0.*",
"symfony/twig-bridge": "~2.3|3.0.*",
"symfony/validator": "~2.3|3.0.*",
"twig/twig": "~1.28|~2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.3.x-dev"
}
},
"autoload": {
"psr-4": {
"Silex\\": "src/Silex"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Igor Wiedler",
"email": "igor@wiedler.ch"
}
],
"description": "The PHP micro-framework based on the Symfony Components",
"homepage": "http://silex.sensiolabs.org",
"keywords": [
"microframework"
],
"time": "2017-04-30T16:26:54+00:00"
},
{
"name": "symfony/routing",
"version": "v3.0.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/routing.git",
"reference": "9038984bd9c05ab07280121e9e10f61a7231457b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/routing/zipball/9038984bd9c05ab07280121e9e10f61a7231457b",
"reference": "9038984bd9c05ab07280121e9e10f61a7231457b",
"shasum": ""
},
"require": {
"php": ">=5.5.9"
},
"conflict": {
"symfony/config": "<2.8"
},
"require-dev": {
"doctrine/annotations": "~1.0",
"doctrine/common": "~2.2",
"psr/log": "~1.0",
"symfony/config": "~2.8|~3.0",
"symfony/expression-language": "~2.8|~3.0",
"symfony/http-foundation": "~2.8|~3.0",
"symfony/yaml": "~2.8|~3.0"
},
"suggest": {
"doctrine/annotations": "For using the annotation loader",
"symfony/config": "For using the all-in-one router or any loader",
"symfony/dependency-injection": "For loading routes from a service",
"symfony/expression-language": "For using expression matching",
"symfony/http-foundation": "For using a Symfony Request object",
"symfony/yaml": "For using the YAML loader"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Routing\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Routing Component",
"homepage": "https://symfony.com",
"keywords": [
"router",
"routing",
"uri",
"url"
],
"time": "2016-06-29T05:40:00+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=5.3.0"
},
"platform-dev": []
}

30
vendor/stack/builder/phpunit.xml.dist vendored Normal file
View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php"
>
<testsuites>
<testsuite name="unit">
<directory>./tests/unit/</directory>
</testsuite>
</testsuites>
<testsuites>
<testsuite name="integration">
<directory>./tests/integration/</directory>
</testsuite>
</testsuites>
<testsuites>
<testsuite name="functional">
<directory>./tests/functional/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./src/</directory>
</whitelist>
</filter>
</phpunit>

View file

@ -0,0 +1,63 @@
<?php
namespace Stack;
use Symfony\Component\HttpKernel\HttpKernelInterface;
class Builder
{
private $specs;
public function __construct()
{
$this->specs = new \SplStack();
}
public function unshift(/*$kernelClass, $args...*/)
{
if (func_num_args() === 0) {
throw new \InvalidArgumentException("Missing argument(s) when calling unshift");
}
$spec = func_get_args();
$this->specs->unshift($spec);
return $this;
}
public function push(/*$kernelClass, $args...*/)
{
if (func_num_args() === 0) {
throw new \InvalidArgumentException("Missing argument(s) when calling push");
}
$spec = func_get_args();
$this->specs->push($spec);
return $this;
}
public function resolve(HttpKernelInterface $app)
{
$middlewares = array($app);
foreach ($this->specs as $spec) {
$args = $spec;
$firstArg = array_shift($args);
if (is_callable($firstArg)) {
$app = $firstArg($app);
} else {
$kernelClass = $firstArg;
array_unshift($args, $app);
$reflection = new \ReflectionClass($kernelClass);
$app = $reflection->newInstanceArgs($args);
}
array_unshift($middlewares, $app);
}
return new StackedHttpKernel($app, $middlewares);
}
}

View file

@ -0,0 +1,37 @@
<?php
namespace Stack;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\TerminableInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class StackedHttpKernel implements HttpKernelInterface, TerminableInterface
{
private $app;
private $middlewares = array();
public function __construct(HttpKernelInterface $app, array $middlewares)
{
$this->app = $app;
$this->middlewares = $middlewares;
}
public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
{
return $this->app->handle($request, $type, $catch);
}
public function terminate(Request $request, Response $response)
{
$prevKernel = null;
foreach ($this->middlewares as $kernel) {
// if prev kernel was terminable we can assume this middleware has already been called
if (!$prevKernel instanceof TerminableInterface && $kernel instanceof TerminableInterface) {
$kernel->terminate($request, $response);
}
$prevKernel = $kernel;
}
}
}

View file

@ -0,0 +1,60 @@
<?php
namespace functional;
use Silex\Application;
use Stack\Builder;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
class SilexApplicationTest extends \PHPUnit_Framework_TestCase
{
public function testWithAppendMiddlewares()
{
$app = new Application();
$app->get('/foo', function () {
return 'bar';
});
$finished = false;
$app->finish(function () use (&$finished) {
$finished = true;
});
$stack = new Builder();
$stack
->push('functional\Append', '.A')
->push('functional\Append', '.B');
$app = $stack->resolve($app);
$request = Request::create('/foo');
$response = $app->handle($request);
$app->terminate($request, $response);
$this->assertSame('bar.B.A', $response->getContent());
$this->assertTrue($finished);
}
}
class Append implements HttpKernelInterface
{
private $app;
private $appendix;
public function __construct(HttpKernelInterface $app, $appendix)
{
$this->app = $app;
$this->appendix = $appendix;
}
public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
{
$response = clone $this->app->handle($request, $type, $catch);
$response->setContent($response->getContent().$this->appendix);
return $response;
}
}

View file

@ -0,0 +1,215 @@
<?php
namespace Stack;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\TerminableInterface;
/** @covers Stack\Builder */
class BuilderTest extends \PHPUnit_Framework_TestCase
{
/** @test */
public function withoutMiddlewaresItShouldReturnOriginalResponse()
{
$app = $this->getHttpKernelMock(new Response('ok'));
$stack = new Builder();
$resolved = $stack->resolve($app);
$request = Request::create('/');
$response = $resolved->handle($request);
$this->assertInstanceOf('Stack\StackedHttpKernel', $resolved);
$this->assertSame('ok', $response->getContent());
}
/** @test */
public function resolvedKernelShouldDelegateTerminateCalls()
{
$app = $this->getTerminableMock();
$stack = new Builder();
$resolved = $stack->resolve($app);
$request = Request::create('/');
$response = new Response('ok');
$resolved->handle($request);
$resolved->terminate($request, $response);
}
/** @test */
public function pushShouldReturnSelf()
{
$stack = new Builder();
$this->assertSame($stack, $stack->push('Stack\AppendA'));
}
/** @test */
public function pushShouldThrowOnInvalidInput()
{
$this->setExpectedException('InvalidArgumentException', 'Missing argument(s) when calling push');
$stack = new Builder();
$stack->push();
}
/** @test */
public function unshiftShouldReturnSelf()
{
$stack = new Builder();
$this->assertSame($stack, $stack->unshift('Stack\AppendA'));
}
/** @test */
public function unshiftShouldThrowOnInvalidInput()
{
$this->setExpectedException('InvalidArgumentException', 'Missing argument(s) when calling unshift');
$stack = new Builder();
$stack->unshift();
}
/** @test */
public function appendMiddlewareShouldAppendToBody()
{
$app = $this->getHttpKernelMock(new Response('ok'));
$stack = new Builder();
$stack->push('Stack\AppendA');
$resolved = $stack->resolve($app);
$request = Request::create('/');
$response = $resolved->handle($request);
$this->assertSame('ok.A', $response->getContent());
}
/** @test */
public function unshiftMiddlewareShouldPutMiddlewareBeforePushed()
{
$app = $this->getHttpKernelMock(new Response('ok'));
$stack = new Builder();
$stack->push('Stack\Append', '2.');
$stack->unshift('Stack\Append', '1.');
$resolved = $stack->resolve($app);
$request = Request::create('/');
$response = $resolved->handle($request);
$this->assertSame('ok2.1.', $response->getContent());
}
/** @test */
public function stackedMiddlewaresShouldWrapInReverseOrder()
{
$app = $this->getHttpKernelMock(new Response('ok'));
$stack = new Builder();
$stack->push('Stack\AppendA');
$stack->push('Stack\AppendB');
$resolved = $stack->resolve($app);
$request = Request::create('/');
$response = $resolved->handle($request);
$this->assertSame('ok.B.A', $response->getContent());
}
/** @test */
public function resolveShouldPassPushArgumentsToMiddlewareConstructor()
{
$app = $this->getHttpKernelMock(new Response('ok'));
$stack = new Builder();
$stack->push('Stack\Append', '.foo');
$stack->push('Stack\Append', '.bar');
$resolved = $stack->resolve($app);
$request = Request::create('/');
$response = $resolved->handle($request);
$this->assertSame('ok.bar.foo', $response->getContent());
}
/** @test */
public function resolveShouldCallSpecFactories()
{
$app = $this->getHttpKernelMock(new Response('ok'));
$stack = new Builder();
$stack->push(function ($app) { return new Append($app, '.foo'); });
$stack->push(function ($app) { return new Append($app, '.bar'); });
$resolved = $stack->resolve($app);
$request = Request::create('/');
$response = $resolved->handle($request);
$this->assertSame('ok.bar.foo', $response->getContent());
}
private function getHttpKernelMock(Response $response)
{
$app = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$app->expects($this->any())
->method('handle')
->with($this->isInstanceOf('Symfony\Component\HttpFoundation\Request'))
->will($this->returnValue($response));
return $app;
}
private function getTerminableMock()
{
$app = $this->getMock('Stack\TerminableHttpKernel');
$app->expects($this->once())
->method('terminate')
->with(
$this->isInstanceOf('Symfony\Component\HttpFoundation\Request'),
$this->isInstanceOf('Symfony\Component\HttpFoundation\Response')
);
return $app;
}
}
abstract class TerminableHttpKernel implements HttpKernelInterface, TerminableInterface
{
}
class Append implements HttpKernelInterface
{
private $app;
private $appendix;
public function __construct(HttpKernelInterface $app, $appendix)
{
$this->app = $app;
$this->appendix = $appendix;
}
public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
{
$response = clone $this->app->handle($request, $type, $catch);
$response->setContent($response->getContent().$this->appendix);
return $response;
}
}
class AppendA extends Append
{
public function __construct(HttpKernelInterface $app)
{
parent::__construct($app, '.A');
}
}
class AppendB extends Append
{
public function __construct(HttpKernelInterface $app)
{
parent::__construct($app, '.B');
}
}

View file

@ -0,0 +1,155 @@
<?php
namespace Stack;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\TerminableInterface;
class StackedHttpKernelTest extends \PHPUnit_Framework_TestCase
{
/** @test */
public function handleShouldDelegateToApp()
{
$app = $this->getHttpKernelMock(new Response('ok'));
$kernel = new StackedHttpKernel($app, array($app));
$request = Request::create('/');
$response = $kernel->handle($request);
$this->assertSame('ok', $response->getContent());
}
/** @test */
public function handleShouldStillDelegateToAppWithMiddlewares()
{
$app = $this->getHttpKernelMock(new Response('ok'));
$bar = $this->getHttpKernelMock(new Response('bar'));
$foo = $this->getHttpKernelMock(new Response('foo'));
$kernel = new StackedHttpKernel($app, array($foo, $bar, $app));
$request = Request::create('/');
$response = $kernel->handle($request);
$this->assertSame('ok', $response->getContent());
}
/** @test */
public function terminateShouldDelegateToMiddlewares()
{
$first = new TerminableKernelSpy();
$second = new TerminableKernelSpy($first);
$third = new KernelSpy($second);
$fourth = new TerminableKernelSpy($third);
$fifth = new TerminableKernelSpy($fourth);
$kernel = new StackedHttpKernel($fifth, $middlewares = array($fifth, $fourth, $third, $second, $first));
$request = Request::create('/');
$response = $kernel->handle($request);
$kernel->terminate($request, $response);
$this->assertTerminablesCalledOnce($middlewares);
}
private function assertTerminablesCalledOnce(array $middlewares)
{
foreach ($middlewares as $kernel) {
if ($kernel instanceof TerminableInterface) {
$this->assertEquals(1, $kernel->terminateCallCount(), "Terminate was called {$kernel->terminateCallCount()} times");
}
}
}
private function getHttpKernelMock(Response $response)
{
$app = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$app->expects($this->any())
->method('handle')
->with($this->isInstanceOf('Symfony\Component\HttpFoundation\Request'))
->will($this->returnValue($response));
return $app;
}
private function getTerminableMock(Response $response = null)
{
$app = $this->getMock('Stack\TerminableHttpKernel');
if ($response) {
$app->expects($this->any())
->method('handle')
->with($this->isInstanceOf('Symfony\Component\HttpFoundation\Request'))
->will($this->returnValue($response));
}
$app->expects($this->once())
->method('terminate')
->with(
$this->isInstanceOf('Symfony\Component\HttpFoundation\Request'),
$this->isInstanceOf('Symfony\Component\HttpFoundation\Response')
);
return $app;
}
private function getDelegatingTerminableMock(TerminableInterface $next)
{
$app = $this->getMock('Stack\TerminableHttpKernel');
$app->expects($this->once())
->method('terminate')
->with(
$this->isInstanceOf('Symfony\Component\HttpFoundation\Request'),
$this->isInstanceOf('Symfony\Component\HttpFoundation\Response')
)
->will($this->returnCallback(function ($request, $response) use ($next) {
$next->terminate($request, $response);
}));
return $app;
}
}
class KernelSpy implements HttpKernelInterface
{
private $handleCallCount = 0;
public function __construct(HttpKernelInterface $kernel = null)
{
$this->kernel = $kernel;
}
public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
{
$this->handleCallCount++;
if ($this->kernel) {
return $this->kernel->handle($request, $type, $catch);
}
return new Response('OK');
}
public function handleCallCount()
{
return $this->handleCallCount;
}
}
class TerminableKernelSpy extends KernelSpy implements TerminableInterface
{
private $terminateCallCount = 0;
public function terminate(Request $request, Response $response)
{
$this->terminateCallCount++;
if ($this->kernel && $this->kernel instanceof TerminableInterface) {
return $this->kernel->terminate($request, $response);
}
}
public function terminateCallCount()
{
return $this->terminateCallCount;
}
}