This repository was archived by the owner on Jan 29, 2020. It is now read-only.
This repository was archived by the owner on Jan 29, 2020. It is now read-only.
New PathMiddlewareDecorator #183
Open
Description
- I was not able to find an open or closed issue matching what I'm seeing.
- This is not a question.
I was taking a look to the PathMiddlewareDecorator for a project I'm working on, but it kinda didn't suited my needs.
- I needed it to match a routes flexibly using regular expressions if necessary.
- I needed it to match optionally by request route
- I needed to decide if the middleware being decorated was going to execute if the routed matched or didn't match.
So I ended up building my own decorator. How keen are you guys of accepting a PR with it? Here's a very naive implementation:
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface as NextHandler;
/**
* Decorates a middleware to be executed on a router pattern match/un-match
*
* You can optionally pass a method to the arguments.
*
* @author Matías Navarro Carter <[email protected]>
*/
final class PathMiddlewareDecorator implements MiddlewareInterface
{
public const IF_MATCHES = 1;
public const IF_NOT_MATCHES = 0;
/**
* @var MiddlewareInterface
*/
private $middleware;
/**
* @var int
*/
private $executionRule;
/**
* @var string|string[]
*/
private $path;
/**
* @var string|null
*/
private $method;
/**
* PathMiddlewareDecorator constructor.
*
* @param MiddlewareInterface $middleware The middleware to execute.
* @param string|string[] $path A path pattern or an array of patterns.
* @param string|null $method A method to match.
* @param int $executionRule The rule of execution.
*/
public function __construct(
MiddlewareInterface $middleware,
$path,
string $method = null,
int $executionRule = self::IF_MATCHES
) {
$this->middleware = $middleware;
$this->path = $path;
$this->method = $method;
$this->executionRule = $executionRule;
}
/**
* @param Request $request
* @param NextHandler $handler
*
* @return Response
*/
public function process(Request $request, NextHandler $handler): Response
{
$match = $this->matches($request);
if (self::IF_MATCHES === $this->executionRule && true === $match) {
return $this->middleware->process($request, $handler);
}
if (self::IF_NOT_MATCHES === $this->executionRule && false === $match) {
return $this->middleware->process($request, $handler);
}
return $handler->handle($request);
}
/**
* @param Request $request
*
* @return bool
*/
private function matches(Request $request): bool
{
if ($this->method && $request->getMethod() !== $this->method) {
return false;
}
return $this->matchesRegex($request->getUri()->getPath(), $this->path);
}
/**
* @param string $requestPath
* @param $pathOrPaths
*
* @return bool
*/
private function matchesRegex(string $requestPath, $pathOrPaths): bool
{
if (is_array($pathOrPaths)) {
foreach ($pathOrPaths as $string) {
$result = $this->matchesRegex($requestPath, $string);
if (true === $result) {
return true;
}
}
}
if (\is_string($pathOrPaths)) {
return 0 !== preg_match('/'.str_replace('/', '\/', $pathOrPaths).'/', $requestPath);
}
return false;
}
}
Of course it should be named differently to the one you guys already have. Maybe ConfigurablePathMiddlewareDecorator
?
Metadata
Metadata
Assignees
Labels
No labels