Skip to content

Commit

Permalink
Update MiddlewareListener to use PSR middleware interfaces, drop interop
Browse files Browse the repository at this point in the history
Signed-off-by: Aleksei Khudiakov <aleksey@xerkus.pro>
  • Loading branch information
Xerkus committed Jun 4, 2020
1 parent 341a570 commit 6a5f0fd
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 145 deletions.
67 changes: 37 additions & 30 deletions src/MiddlewareListener.php
Expand Up @@ -8,28 +8,33 @@

namespace Laminas\Mvc\Middleware;

use Exception;
use Interop\Http\ServerMiddleware\MiddlewareInterface;
use Laminas\EventManager\AbstractListenerAggregate;
use Laminas\EventManager\EventManagerInterface;
use Laminas\Http\Response;
use Laminas\Mvc\Application;
use Laminas\Mvc\Exception\InvalidMiddlewareException;
use Laminas\Mvc\MvcEvent;
use Laminas\Psr7Bridge\Psr7Response;
use Laminas\Stratigility\Middleware\RequestHandlerMiddleware;
use Laminas\Stratigility\MiddlewarePipe;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Throwable;

use function gettype;
use function is_object;
use function is_string;

class MiddlewareListener extends AbstractListenerAggregate
{
/**
* Attach listeners to an event manager
*
* @return void
*/
public function attach(EventManagerInterface $events, $priority = 1)
public function attach(EventManagerInterface $events, $priority = 1) : void
{
$this->listeners[] = $events->attach(MvcEvent::EVENT_DISPATCH, [$this, 'onDispatch'], 1);
}
Expand All @@ -56,12 +61,9 @@ public function onDispatch(MvcEvent $event)
$response = $application->getResponse();
$serviceManager = $application->getServiceManager();

$psr7ResponsePrototype = Psr7Response::fromLaminas($response);

try {
$pipe = $this->createPipeFromSpec(
$serviceManager,
$psr7ResponsePrototype,
is_array($middleware) ? $middleware : [$middleware]
);
} catch (InvalidMiddlewareException $invalidMiddlewareException) {
Expand All @@ -80,20 +82,13 @@ public function onDispatch(MvcEvent $event)
try {
$return = (new MiddlewareController(
$pipe,
$psr7ResponsePrototype,
$application->getServiceManager()->get('EventManager'),
$event
))->dispatch($request, $response);
} catch (Throwable $ex) {
$caughtException = $ex;
} catch (Exception $ex) { // @TODO clean up once PHP 7 requirement is enforced
$caughtException = $ex;
}

if ($caughtException !== null) {
} catch (Throwable $exception) {
$event->setName(MvcEvent::EVENT_DISPATCH_ERROR);
$event->setError(Application::ERROR_EXCEPTION);
$event->setParam('exception', $caughtException);
$event->setParam('exception', $exception);

$events = $application->getEventManager();
$results = $events->triggerEvent($event);
Expand All @@ -117,34 +112,46 @@ public function onDispatch(MvcEvent $event)
/**
* Create a middleware pipe from the array spec given.
*
* @param mixed[] $middlewaresToBePiped
* List of string ids for middlewares in container, instances of MiddlewareInterface
* or callable middlewares
* @return MiddlewarePipe
* @param mixed[] $middlewarePipeSpec
* List of string ids for middleware in container, instances of MiddlewareInterface
* or RequestHandlerInterface
* @throws InvalidMiddlewareException
*/
private function createPipeFromSpec(
ContainerInterface $serviceLocator,
ResponseInterface $responsePrototype,
array $middlewaresToBePiped
) {
array $middlewarePipeSpec
): RequestHandlerInterface {
// Pipe has implicit empty pipeline handler
$pipe = new MiddlewarePipe();
$pipe->setResponsePrototype($responsePrototype);
foreach ($middlewaresToBePiped as $middlewareToBePiped) {
foreach ($middlewarePipeSpec as $middlewareToBePiped) {
if (null === $middlewareToBePiped) {
throw InvalidMiddlewareException::fromNull();
}

$middlewareName = is_string($middlewareToBePiped) ? $middlewareToBePiped : get_class($middlewareToBePiped);
$middlewareName = is_object($middlewareToBePiped)
? get_class($middlewareToBePiped)
: gettype($middlewareToBePiped);

if (is_string($middlewareToBePiped) && $serviceLocator->has($middlewareToBePiped)) {
if (is_string($middlewareToBePiped)) {
$middlewareName = $middlewareToBePiped;
if (! $serviceLocator->has($middlewareToBePiped)) {
// throw separately for stacktrace line hint
throw InvalidMiddlewareException::fromMiddlewareName($middlewareName);
}
$middlewareToBePiped = $serviceLocator->get($middlewareToBePiped);
}
if (! $middlewareToBePiped instanceof MiddlewareInterface && ! is_callable($middlewareToBePiped)) {
throw InvalidMiddlewareException::fromMiddlewareName($middlewareName);

if ($middlewareToBePiped instanceof MiddlewareInterface) {
$pipe->pipe($middlewareToBePiped);
continue;
}
if ($middlewareToBePiped instanceof RequestHandlerInterface) {
$middlewareToBePiped = new RequestHandlerMiddleware($middlewareToBePiped);
$pipe->pipe($middlewareToBePiped);
break; // request handler will always stop pipe processing. Rest of the pipe can be ignored
}

$pipe->pipe($middlewareToBePiped);
throw InvalidMiddlewareException::fromMiddlewareName($middlewareName);
}
return $pipe;
}
Expand All @@ -161,7 +168,7 @@ protected function marshalInvalidMiddleware(
$middlewareName,
MvcEvent $event,
Application $application,
Exception $exception = null
Throwable $exception = null
) {
$event->setName(MvcEvent::EVENT_DISPATCH_ERROR);
$event->setError($type);
Expand Down

0 comments on commit 6a5f0fd

Please sign in to comment.