default services conflit ?

This commit is contained in:
armansansd
2022-04-27 11:30:43 +02:00
parent 28190a5749
commit 8bb1064a3b
8132 changed files with 900138 additions and 426 deletions

View File

@@ -0,0 +1,93 @@
<?php
require __DIR__ . '/../vendor/autoload.php';
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
use Symfony\Component\HttpKernel\Controller\ControllerResolver;
use Symfony\Component\HttpKernel\EventListener\RouterListener;
use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\TerminateEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
class Application implements HttpKernelInterface
{
private $kernel;
private $dispatcher;
public function __construct()
{
$routes = new RouteCollection();
$routes->add('hello', new Route('/foo', [
'_controller' => function (Request $request) {
return new Response('bar');
}]
));
$matcher = new UrlMatcher($routes, new RequestContext());
$this->dispatcher = new EventDispatcher();
$this->dispatcher->addSubscriber(new RouterListener($matcher, new RequestStack()));
$controllerResolver = new ControllerResolver();
$argumentResolver = new ArgumentResolver();
$this->kernel = new HttpKernel($this->dispatcher, $controllerResolver, new RequestStack(), $argumentResolver);
}
public function handle(Request $request, int $type = HttpKernelInterface::MASTER_REQUEST, bool $catch = true)
{
return $this->kernel->handle($request);
}
public function terminate(Request $request, Response $response)
{
$this->kernel->terminate($request, $response);
}
public function finish(callable $callback)
{
$dispatcher = $this->dispatcher;
$app = $this;
$request = Request::createFromGlobals();
$response = $app->handle($request);
$app->terminate($request, $response);
$event = new TerminateEvent($app, $request, $response);
$dispatcher->addSubscriber(new KernelTerminatedSubscriber($callback));
$dispatcher->dispatch($event, KernelEvents::TERMINATE);
}
}
class KernelTerminatedSubscriber implements EventSubscriberInterface
{
protected $callback;
public function __construct(callable $callback)
{
$this->callback = $callback;
}
public static function getSubscribedEvents()
{
return [
KernelEvents::TERMINATE => 'onKernelTerminated'
];
}
public function onKernelTerminated(TerminateEvent $event)
{
call_user_func($this->callback);
}
}

View File

@@ -0,0 +1,55 @@
<?php
namespace functional;
use Application;
use PHPUnit\Framework\TestCase;
use Stack\Builder;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
class ApplicationTest extends TestCase
{
public function testWithAppendMiddlewares()
{
$request = Request::create('/foo');
$app = new Application();
$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);
$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,219 @@
<?php
namespace Stack;
use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
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 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->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('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->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('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->createMock(HttpKernelInterface::class);
$app->expects($this->any())
->method('handle')
->with($this->isInstanceOf('Symfony\Component\HttpFoundation\Request'))
->will($this->returnValue($response));
return $app;
}
private function getTerminableMock()
{
$app = $this->createMock(TerminableHttpKernel::class);
$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,156 @@
<?php
namespace Stack;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\TerminableInterface;
class StackedHttpKernelTest extends 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->createMock(HttpKernelInterface::class);
$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;
}
}