Skip to content
This repository was archived by the owner on Jan 29, 2020. It is now read-only.

Commit 47ac19a

Browse files
committed
Created a MiddlewareListener
1 parent fe65cba commit 47ac19a

File tree

7 files changed

+239
-66
lines changed

7 files changed

+239
-66
lines changed

src/Application.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
* - RouteListener
2828
* - Router
2929
* - DispatchListener
30+
* - MiddlewareListener
3031
* - ViewManager
3132
*
3233
* The most common workflow is:
@@ -53,7 +54,7 @@ class Application implements
5354
const ERROR_EXCEPTION = 'error-exception';
5455
const ERROR_ROUTER_NO_MATCH = 'error-router-no-match';
5556
const ERROR_MIDDLEWARE_CANNOT_DISPATCH = 'error-middleware-cannot-dispatch';
56-
57+
5758
/**
5859
* @var array
5960
*/
@@ -66,6 +67,7 @@ class Application implements
6667
*/
6768
protected $defaultListeners = [
6869
'RouteListener',
70+
'MiddlewareListener',
6971
'DispatchListener',
7072
'HttpMethodListener',
7173
'ViewManager',

src/DispatchListener.php

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414
use Zend\EventManager\EventManagerInterface;
1515
use Zend\Mvc\Exception\InvalidControllerException;
1616
use Zend\Stdlib\ArrayUtils;
17-
use Zend\Psr7Bridge\Psr7ServerRequest as Psr7Request;
18-
use Zend\Psr7Bridge\Psr7Response;
1917

2018
/**
2119
* Default dispatch listener
@@ -63,29 +61,10 @@ public function attach(EventManagerInterface $events)
6361
*/
6462
public function onDispatch(MvcEvent $e)
6563
{
66-
$routeMatch = $e->getRouteMatch();
67-
$request = $e->getRequest();
68-
$application = $e->getApplication();
69-
$response = $application->getResponse();
70-
$serviceManager = $application->getServiceManager();
71-
72-
// middleware?
73-
$middleware = $routeMatch->getParam('middleware', false);
74-
if (false !== $middleware) {
75-
if (is_string($middleware) && $serviceManager->has($middleware)) {
76-
$middleware = $serviceManager->get($middleware);
77-
}
78-
if (!is_callable($middleware)) {
79-
$middleware = is_string($middleware) ? $middleware : get_class($middleware);
80-
$return = $this->marshalControllerNotFoundEvent($application::ERROR_MIDDLEWARE_CANNOT_DISPATCH, $middleware, $e, $application);
81-
return $this->complete($return, $e);
82-
}
83-
$return = $middleware(Psr7Request::fromZend($request), Psr7Response::fromZend($response));
84-
return $this->complete(Psr7Response::toZend($return), $e);
85-
}
86-
64+
$routeMatch = $e->getRouteMatch();
65+
$application = $e->getApplication();
66+
$serviceManager = $application->getServiceManager();
8767
$controllerName = $routeMatch->getParam('controller', 'not-found');
88-
$events = $application->getEventManager();
8968
$controllerLoader = $serviceManager->get('ControllerManager');
9069

9170
if (!$controllerLoader->has($controllerName)) {
@@ -107,14 +86,17 @@ public function onDispatch(MvcEvent $e)
10786
$controller->setEvent($e);
10887
}
10988

89+
$request = $e->getRequest();
90+
$response = $application->getResponse();
91+
11092
try {
11193
$return = $controller->dispatch($request, $response);
11294
} catch (\Exception $ex) {
11395
$e->setError($application::ERROR_EXCEPTION)
11496
->setController($controllerName)
11597
->setControllerClass(get_class($controller))
11698
->setParam('exception', $ex);
117-
$results = $events->trigger(MvcEvent::EVENT_DISPATCH_ERROR, $e);
99+
$results = $application->getEventManager()->trigger(MvcEvent::EVENT_DISPATCH_ERROR, $e);
118100
$return = $results->last();
119101
if (! $return) {
120102
$return = $e->getResult();

src/MiddlewareListener.php

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<?php
2+
/**
3+
* Zend Framework (http://framework.zend.com/)
4+
*
5+
* @link http://github.com/zendframework/zf2 for the canonical source repository
6+
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7+
* @license http://framework.zend.com/license/new-bsd New BSD License
8+
*/
9+
10+
namespace Zend\Mvc;
11+
12+
use ArrayObject;
13+
use Zend\EventManager\AbstractListenerAggregate;
14+
use Zend\EventManager\EventManagerInterface;
15+
use Zend\Mvc\Exception\InvalidControllerException;
16+
use Zend\Stdlib\ArrayUtils;
17+
use Zend\Psr7Bridge\Psr7ServerRequest as Psr7Request;
18+
use Zend\Psr7Bridge\Psr7Response;
19+
20+
class MiddlewareListener extends AbstractListenerAggregate
21+
{
22+
/**
23+
* Attach listeners to an event manager
24+
*
25+
* @param EventManagerInterface $events
26+
* @return void
27+
*/
28+
public function attach(EventManagerInterface $events)
29+
{
30+
$this->listeners[] = $events->attach(MvcEvent::EVENT_DISPATCH, [$this, 'onDispatch'], 1000);
31+
}
32+
33+
/**
34+
* Listen to the "dispatch" event
35+
*
36+
* @param MvcEvent $e
37+
* @return mixed
38+
*/
39+
public function onDispatch(MvcEvent $e)
40+
{
41+
$routeMatch = $e->getRouteMatch();
42+
$middleware = $routeMatch->getParam('middleware', false);
43+
if (false === $middleware) {
44+
return;
45+
}
46+
47+
$request = $e->getRequest();
48+
$application = $e->getApplication();
49+
$response = $application->getResponse();
50+
$serviceManager = $application->getServiceManager();
51+
$middlewareName = is_string($middleware) ? $middleware : get_class($middleware);
52+
53+
if (is_string($middleware) && $serviceManager->has($middleware)) {
54+
$middleware = $serviceManager->get($middleware);
55+
}
56+
if (!is_callable($middleware)) {
57+
$return = $this->marshalMiddlewareNotCallable($application::ERROR_MIDDLEWARE_CANNOT_DISPATCH, $middlewareName, $e, $application);
58+
$e->setResult($return);
59+
return $return;
60+
}
61+
try {
62+
$return = $middleware(Psr7Request::fromZend($request), Psr7Response::fromZend($response));
63+
} catch (\Exception $ex) {
64+
$e->setError($application::ERROR_EXCEPTION)
65+
->setController($middlewareName)
66+
->setControllerClass(get_class($middleware))
67+
->setParam('exception', $ex);
68+
$results = $events->trigger(MvcEvent::EVENT_DISPATCH_ERROR, $e);
69+
$return = $results->last();
70+
if (! $return) {
71+
$return = $e->getResult();
72+
}
73+
}
74+
75+
if (! $return instanceof \Psr\Http\Message\ResponseInterface) {
76+
$e->setResult($return);
77+
return $return;
78+
}
79+
$response = Psr7Response::toZend($return);
80+
$e->setResult($response);
81+
return $response;
82+
}
83+
84+
/**
85+
* Marshal a middleware not callable exception event
86+
*
87+
* @param string $type
88+
* @param string $middlewareName
89+
* @param MvcEvent $event
90+
* @param Application $application
91+
* @param \Exception $exception
92+
* @return mixed
93+
*/
94+
protected function marshalMiddlewareNotCallable(
95+
$type,
96+
$middlewareName,
97+
MvcEvent $event,
98+
Application $application,
99+
\Exception $exception = null
100+
) {
101+
$event->setError($type)
102+
->setController($middlewareName)
103+
->setControllerClass('Middleware not callable: ' . $middlewareName);
104+
if ($exception !== null) {
105+
$event->setParam('exception', $exception);
106+
}
107+
108+
$events = $application->getEventManager();
109+
$results = $events->trigger(MvcEvent::EVENT_DISPATCH_ERROR, $event);
110+
$return = $results->last();
111+
if (! $return) {
112+
$return = $event->getResult();
113+
}
114+
return $return;
115+
}
116+
}

src/Service/ServiceListenerFactory.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class ServiceListenerFactory implements FactoryInterface
3636
protected $defaultServiceConfig = [
3737
'invokables' => [
3838
'DispatchListener' => 'Zend\Mvc\DispatchListener',
39+
'MiddlewareListener' => 'Zend\Mvc\MiddlewareListener',
3940
'RouteListener' => 'Zend\Mvc\RouteListener',
4041
'SendResponseListener' => 'Zend\Mvc\SendResponseListener',
4142
'ViewJsonRenderer' => 'Zend\View\Renderer\JsonRenderer',

test/ApplicationTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ public function bootstrapRegistersListenersProvider()
166166
return [
167167
['RouteListener', MvcEvent::EVENT_ROUTE, 'onRoute'],
168168
['DispatchListener', MvcEvent::EVENT_DISPATCH, 'onDispatch'],
169+
['MiddlewareListener', MvcEvent::EVENT_DISPATCH, 'onDispatch'],
169170
['SendResponseListener', MvcEvent::EVENT_FINISH, 'sendResponse'],
170171
['ViewManager', MvcEvent::EVENT_BOOTSTRAP, 'onBootstrap'],
171172
['HttpMethodListener', MvcEvent::EVENT_ROUTE, 'onRoute'],

test/DispatchListenerTest.php

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -122,44 +122,4 @@ public function testUnlocatableControllerLoaderComposedOfAbstractFactory()
122122
$this->assertArrayHasKey('error', $log);
123123
$this->assertSame('error-controller-not-found', $log['error']);
124124
}
125-
126-
public function testMiddlewareDispatch()
127-
{
128-
$request = $this->serviceManager->get('Request');
129-
$request->setUri('http://example.local/path');
130-
131-
$router = $this->serviceManager->get('HttpRouter');
132-
$route = Router\Http\Literal::factory([
133-
'route' => '/path',
134-
'defaults' => [
135-
'middleware' => function($request, $response) {
136-
$this->assertInstanceOf('Psr\Http\Message\ServerRequestInterface', $request);
137-
$this->assertInstanceOf('Psr\Http\Message\ResponseInterface', $response);
138-
$response->getBody()->write('Test!');
139-
return $response;
140-
}
141-
],
142-
]);
143-
$router->addRoute('path', $route);
144-
$this->application->bootstrap();
145-
146-
$controllerLoader = $this->serviceManager->get('ControllerLoader');
147-
$controllerLoader->addAbstractFactory('ZendTest\Mvc\Controller\TestAsset\ControllerLoaderAbstractFactory');
148-
149-
$log = [];
150-
$this->application->getEventManager()->attach(MvcEvent::EVENT_DISPATCH_ERROR, function ($e) use (&$log) {
151-
$log['error'] = $e->getError();
152-
});
153-
154-
$this->application->run();
155-
156-
$event = $this->application->getMvcEvent();
157-
$dispatchListener = $this->serviceManager->get('DispatchListener');
158-
$return = $dispatchListener->onDispatch($event);
159-
160-
$this->assertEmpty($log);
161-
$this->assertInstanceOf('Zend\Http\Response', $return);
162-
$this->assertSame(200, $return->getStatusCode());
163-
$this->assertEquals('Test!', $return->getBody());
164-
}
165125
}

test/MiddlewareListenerTest.php

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
<?php
2+
/**
3+
* Zend Framework (http://framework.zend.com/)
4+
*
5+
* @link http://github.com/zendframework/zf2 for the canonical source repository
6+
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7+
* @license http://framework.zend.com/license/new-bsd New BSD License
8+
*/
9+
10+
namespace ZendTest\Mvc;
11+
12+
use PHPUnit_Framework_TestCase as TestCase;
13+
use Zend\Mvc\Application;
14+
use Zend\Mvc\MvcEvent;
15+
use Zend\Mvc\Router;
16+
use Zend\Mvc\Service\ServiceManagerConfig;
17+
use Zend\Mvc\Service\ServiceListenerFactory;
18+
use Zend\ServiceManager\ServiceManager;
19+
use Zend\Stdlib\ArrayUtils;
20+
21+
class MiddlewareListenerTest extends TestCase
22+
{
23+
/**
24+
* @var ServiceManager
25+
*/
26+
protected $serviceManager;
27+
28+
/**
29+
* @var Application
30+
*/
31+
protected $application;
32+
33+
public function setUp()
34+
{
35+
$serviceConfig = ArrayUtils::merge(
36+
$this->readAttribute(new ServiceListenerFactory, 'defaultServiceConfig'),
37+
[
38+
'allow_override' => true,
39+
'invokables' => [
40+
'Request' => 'Zend\Http\PhpEnvironment\Request',
41+
'Response' => 'Zend\Http\PhpEnvironment\Response',
42+
'ViewManager' => 'ZendTest\Mvc\TestAsset\MockViewManager',
43+
'SendResponseListener' => 'ZendTest\Mvc\TestAsset\MockSendResponseListener',
44+
'BootstrapListener' => 'ZendTest\Mvc\TestAsset\StubBootstrapListener',
45+
],
46+
'aliases' => [
47+
'Router' => 'HttpRouter',
48+
],
49+
'services' => [
50+
'Config' => [],
51+
'ApplicationConfig' => [
52+
'modules' => [],
53+
'module_listener_options' => [
54+
'config_cache_enabled' => false,
55+
'cache_dir' => 'data/cache',
56+
'module_paths' => [],
57+
],
58+
],
59+
],
60+
]
61+
);
62+
$this->serviceManager = new ServiceManager(new ServiceManagerConfig($serviceConfig));
63+
$this->application = $this->serviceManager->get('Application');
64+
}
65+
66+
public function setupPathMiddleware()
67+
{
68+
$request = $this->serviceManager->get('Request');
69+
$request->setUri('http://example.local/path');
70+
71+
$router = $this->serviceManager->get('HttpRouter');
72+
$route = Router\Http\Literal::factory([
73+
'route' => '/path',
74+
'defaults' => [
75+
'middleware' => function($request, $response) {
76+
$this->assertInstanceOf('Psr\Http\Message\ServerRequestInterface', $request);
77+
$this->assertInstanceOf('Psr\Http\Message\ResponseInterface', $response);
78+
$response->getBody()->write('Test!');
79+
return $response;
80+
}
81+
],
82+
]);
83+
$router->addRoute('path', $route);
84+
$this->application->bootstrap();
85+
}
86+
87+
88+
public function testMiddlewareDispatch()
89+
{
90+
$this->setupPathMiddleware();
91+
92+
$controllerLoader = $this->serviceManager->get('ControllerLoader');
93+
$controllerLoader->addAbstractFactory('ZendTest\Mvc\Controller\TestAsset\ControllerLoaderAbstractFactory');
94+
95+
$log = [];
96+
$this->application->getEventManager()->attach(MvcEvent::EVENT_DISPATCH_ERROR, function ($e) use (&$log) {
97+
$log['error'] = $e->getError();
98+
});
99+
100+
$this->application->run();
101+
102+
$event = $this->application->getMvcEvent();
103+
$dispatchListener = $this->serviceManager->get('DispatchListener');
104+
$return = $dispatchListener->onDispatch($event);
105+
106+
$this->assertEmpty($log);
107+
$this->assertInstanceOf('Zend\Http\Response', $return);
108+
$this->assertSame(200, $return->getStatusCode());
109+
$this->assertEquals('Test!', $return->getBody());
110+
}
111+
}

0 commit comments

Comments
 (0)