Skip to content
This repository has been archived by the owner on Jul 31, 2022. It is now read-only.

Commit

Permalink
Merge pull request #13 from tbreuss/develop
Browse files Browse the repository at this point in the history
Cleaner & better middleware implementation
  • Loading branch information
tbreuss authored Sep 8, 2018
2 parents b18c375 + 0341d86 commit a153043
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 74 deletions.
21 changes: 5 additions & 16 deletions src/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Tebe\HttpFactory\HttpFactory;
use Tebe\Pvc\Exception\SystemException;
use Tebe\Pvc\Middleware\MiddlewareDispatcher;
use Tebe\Pvc\Middleware\RouterMiddleware;
use Tebe\Pvc\Middleware\MiddlewarePipe;
use Tebe\Pvc\Middleware\RequestHandler;

class Application
{
Expand Down Expand Up @@ -175,20 +174,10 @@ public function run(): void
$view = new View($viewsPath);
$this->setView($view);

$middlewares = array_merge(
$this->middlewares,
[new RouterMiddleware($this->getView(), $this->getConfig()->get('controllersPath'))]
);

$middlewareDispatcher = new MiddlewareDispatcher(
$middlewares,
function () {
return (new HttpFactory)->createResponse(200);
}
);

$pipe = MiddlewarePipe::create($this->middlewares);
$request = $this->getRequest();
$response = $middlewareDispatcher->handle($request);
$requestHandler = new RequestHandler($view, $this->getConfig()->get('controllersPath'));
$response = $pipe->process($request, $requestHandler);

$this->emit($response);
}
Expand Down
51 changes: 0 additions & 51 deletions src/Middleware/MiddlewareDispatcher.php

This file was deleted.

60 changes: 60 additions & 0 deletions src/Middleware/MiddlewarePipe.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

namespace Tebe\Pvc\Middleware;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

class MiddlewarePipe implements MiddlewareInterface
{
/**
* @var ServerMiddlewareInterface[]
*/
private $middlewares = [];

private function __construct()
{
}

/**
* @param MiddlewareInterface[] $middlewares FIFO array of middlewares
* @return self
*/
public static function create(array $middlewares = []): self
{
$pipe = new self();
foreach ($middlewares as $middleware) {
$pipe = $pipe->add($middleware);
}
return $pipe;
}

/**
* @param ServerRequestInterface $request
* @param RequestHandlerInterface $requestHandler
* @return ResponseInterface
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $requestHandler): ResponseInterface
{
if (empty($this->middlewares)) {
return $requestHandler->handle($request);
}
$stack = MiddlewareStack::create($requestHandler, array_reverse($this->middlewares));
return $stack->handle($request);
}

/**
* Creates a new pipe with the given middleware connected.
*
* @param MiddlewareInterface $middleware
* @return self
*/
public function add(MiddlewareInterface $middleware): self
{
$pipe = clone $this;
array_push($pipe->middlewares, $middleware);
return $pipe;
}
}
87 changes: 87 additions & 0 deletions src/Middleware/MiddlewareStack.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

namespace Tebe\Pvc\Middleware;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

class MiddlewareStack implements RequestHandlerInterface
{
/**
* @var RequestHandlerInterface
*/
private $requestHandler;

/**
* @var MiddlewareInterface[]
*/
private $middlewares = [];

/**
* @param RequestHandlerInterface $requestHandler
*/
private function __construct(RequestHandlerInterface $requestHandler)
{
$this->requestHandler = $requestHandler;
}

/**
* @param RequestHandlerInterface $requestHandler
* @param MiddlewareInterface[] $middlewares LIFO array of middlewares
* @return self
*/
public static function create(RequestHandlerInterface $requestHandler, array $middlewares = []): self
{
$stack = new self($requestHandler);
foreach ($middlewares as $middleware) {
$stack = $stack->push($middleware);
}
return $stack;
}

/**
* @param ServerRequestInterface $request
* @return ResponseInterface
*/
public function handle(ServerRequestInterface $request): ResponseInterface
{
$next = $this->peek();
if (null === $next) {
return $this->requestHandler->handle($request);
}
return $next->process($request, $this->pop());
}

/**
* Creates a new stack with the given middleware pushed.
*
* @param MiddlewareInterface $middleware
* @return self
*/
public function push(MiddlewareInterface $middleware): self
{
$stack = clone $this;
array_unshift($stack->middlewares, $middleware);
return $stack;
}

/**
* @return MiddlewareInterface|null
*/
private function peek()
{
return reset($this->middlewares) ?: null;
}

/**
* @return self
*/
private function pop(): self
{
$stack = clone $this;
array_shift($stack->middlewares);
return $stack;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Tebe\HttpFactory\HttpFactory;
use Tebe\Pvc\Controller;
use Tebe\Pvc\ErrorController;
use Tebe\Pvc\Exception\HttpException;
use Tebe\Pvc\Exception\SystemException;
use Tebe\Pvc\View;

class RouterMiddleware implements MiddlewareInterface
class RequestHandler implements RequestHandlerInterface
{
/**
* @var View
Expand All @@ -35,6 +35,7 @@ class RouterMiddleware implements MiddlewareInterface
* RouterMiddleware constructor.
* @param View $view
* @param string $controllersPath
* @throws SystemException
*/
public function __construct(View $view, string $controllersPath)
{
Expand All @@ -43,14 +44,12 @@ public function __construct(View $view, string $controllersPath)
}

/**
* @param ServerRequestInterface $request
* @param RequestHandlerInterface $handler
* @return ResponseInterface
* Handle the request and return a response.
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
public function handle(ServerRequestInterface $request): ResponseInterface
{
$this->request = $request;
$response = $handler->handle($request);
$response = (new HttpFactory())->createResponse();
$pathInfo = $this->getPathInfo();

try {
Expand Down Expand Up @@ -129,6 +128,7 @@ private function executeAction(Controller $controller): string
* @param Controller $controller
* @param string $methodName
* @return array
* @throws \ReflectionException
*/
private function getHttpGetVars(Controller $controller, string $methodName): array
{
Expand Down

0 comments on commit a153043

Please sign in to comment.