Skip to content

Commit 9f07a5d

Browse files
authored
Merge pull request #93 from sunrise-php/release/v2.13.0
v2.13.0
2 parents c3db73a + 097831a commit 9f07a5d

File tree

6 files changed

+235
-2
lines changed

6 files changed

+235
-2
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## v2.13.0
2+
3+
* Supports for events using the `symfony/event-dispatcher`.

README.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
## Installation
1313

1414
```bash
15-
composer require 'sunrise/http-router:^2.11'
15+
composer require 'sunrise/http-router:^2.13'
1616
```
1717

1818
## Support for OpenAPI (Swagger) Specification (optional)
@@ -570,6 +570,32 @@ use Sunrise\Http\Router\Command\RouteListCommand;
570570
new RouteListCommand($router);
571571
```
572572

573+
### Events
574+
575+
> Available from version 2.13
576+
577+
```bash
578+
composer require symfony/event-dispatcher
579+
```
580+
581+
```php
582+
use Sunrise\Http\Router\Event\RouteEvent;
583+
use Symfony\Component\EventDispatcher\EventDispatcher;
584+
585+
$eventDispatcher = new EventDispatcher();
586+
587+
$eventDispatcher->addListener(RouteEvent::NAME, function (RouteEvent $event) {
588+
// gets the matched route:
589+
$event->getRoute();
590+
// gets the current request:
591+
$event->getRequest();
592+
// overrides the current request:
593+
$event->setRequest(ServerRequestInterface $request);
594+
});
595+
596+
$router->setEventDispatcher($eventDispatcher);
597+
```
598+
573599
---
574600

575601
## Test run

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@
4040
"sunrise/coding-standard": "1.0.0",
4141
"sunrise/http-factory": "1.1.0",
4242
"doctrine/annotations": "^1.6",
43-
"symfony/console": "^4.4"
43+
"symfony/console": "^4.4",
44+
"symfony/event-dispatcher": "^4.4"
4445
},
4546
"autoload": {
4647
"files": [

src/Event/RouteEvent.php

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php declare(strict_types=1);
2+
3+
/**
4+
* It's free open-source software released under the MIT License.
5+
*
6+
* @author Anatoly Fenric <[email protected]>
7+
* @copyright Copyright (c) 2018, Anatoly Fenric
8+
* @license https://github.com/sunrise-php/http-router/blob/master/LICENSE
9+
* @link https://github.com/sunrise-php/http-router
10+
*/
11+
12+
namespace Sunrise\Http\Router\Event;
13+
14+
/**
15+
* Import classes
16+
*/
17+
use Psr\Http\Message\ServerRequestInterface;
18+
use Sunrise\Http\Router\RouteInterface;
19+
use Symfony\Contracts\EventDispatcher\Event;
20+
21+
/**
22+
* RouteEvent
23+
*
24+
* @since 2.13.0
25+
*/
26+
final class RouteEvent extends Event
27+
{
28+
29+
/**
30+
* @var string
31+
*/
32+
public const NAME = 'router.route';
33+
34+
/**
35+
* @var RouteInterface
36+
*/
37+
private $route;
38+
39+
/**
40+
* @var ServerRequestInterface
41+
*/
42+
private $request;
43+
44+
/**
45+
* Constructor of the class
46+
*
47+
* @param RouteInterface $route
48+
* @param ServerRequestInterface $request
49+
*/
50+
public function __construct(RouteInterface $route, ServerRequestInterface $request)
51+
{
52+
$this->route = $route;
53+
$this->request = $request;
54+
}
55+
56+
/**
57+
* @return RouteInterface
58+
*/
59+
public function getRoute() : RouteInterface
60+
{
61+
return $this->route;
62+
}
63+
64+
/**
65+
* @return ServerRequestInterface
66+
*/
67+
public function getRequest() : ServerRequestInterface
68+
{
69+
return $this->request;
70+
}
71+
72+
/**
73+
* @param ServerRequestInterface $request
74+
*
75+
* @return void
76+
*/
77+
public function setRequest(ServerRequestInterface $request) : void
78+
{
79+
$this->request = $request;
80+
}
81+
}

src/Router.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@
1919
use Psr\Http\Message\ServerRequestInterface;
2020
use Psr\Http\Server\MiddlewareInterface;
2121
use Psr\Http\Server\RequestHandlerInterface;
22+
use Sunrise\Http\Router\Event\RouteEvent;
2223
use Sunrise\Http\Router\Exception\InvalidArgumentException;
2324
use Sunrise\Http\Router\Exception\MethodNotAllowedException;
2425
use Sunrise\Http\Router\Exception\PageNotFoundException;
2526
use Sunrise\Http\Router\Exception\RouteNotFoundException;
2627
use Sunrise\Http\Router\Loader\LoaderInterface;
2728
use Sunrise\Http\Router\RequestHandler\CallableRequestHandler;
2829
use Sunrise\Http\Router\RequestHandler\QueueableRequestHandler;
30+
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
2931

3032
/**
3133
* Import functions
@@ -90,6 +92,15 @@ class Router implements MiddlewareInterface, RequestHandlerInterface, RequestMet
9092
*/
9193
private $matchedRoute = null;
9294

95+
/**
96+
* The router's event dispatcher
97+
*
98+
* @var EventDispatcherInterface|null
99+
*
100+
* @since 2.13.0
101+
*/
102+
private $eventDispatcher = null;
103+
93104
/**
94105
* Gets the router host table
95106
*
@@ -132,6 +143,18 @@ public function getMatchedRoute() : ?RouteInterface
132143
return $this->matchedRoute;
133144
}
134145

146+
/**
147+
* Gets the router's event dispatcher
148+
*
149+
* @return EventDispatcherInterface|null
150+
*
151+
* @since 2.13.0
152+
*/
153+
public function getEventDispatcher() : ?EventDispatcherInterface
154+
{
155+
return $this->eventDispatcher;
156+
}
157+
135158
/**
136159
* Adds the given patterns to the router
137160
*
@@ -246,6 +269,20 @@ public function addMiddleware(MiddlewareInterface ...$middlewares) : void
246269
}
247270
}
248271

272+
/**
273+
* Sets the given event dispatcher to the router
274+
*
275+
* @param EventDispatcherInterface|null $eventDispatcher
276+
*
277+
* @return void
278+
*
279+
* @since 2.13.0
280+
*/
281+
public function setEventDispatcher(?EventDispatcherInterface $eventDispatcher) : void
282+
{
283+
$this->eventDispatcher = $eventDispatcher;
284+
}
285+
249286
/**
250287
* Gets allowed methods
251288
*
@@ -374,6 +411,13 @@ public function run(ServerRequestInterface $request) : ResponseInterface
374411
$routing = new CallableRequestHandler(function (ServerRequestInterface $request) : ResponseInterface {
375412
$route = $this->match($request);
376413
$this->matchedRoute = $route;
414+
415+
if (isset($this->eventDispatcher)) {
416+
$event = new RouteEvent($route, $request);
417+
$this->eventDispatcher->dispatch($event, RouteEvent::NAME);
418+
$request = $event->getRequest();
419+
}
420+
377421
return $route->handle($request);
378422
});
379423

@@ -396,6 +440,12 @@ public function handle(ServerRequestInterface $request) : ResponseInterface
396440
$route = $this->match($request);
397441
$this->matchedRoute = $route;
398442

443+
if (isset($this->eventDispatcher)) {
444+
$event = new RouteEvent($route, $request);
445+
$this->eventDispatcher->dispatch($event, RouteEvent::NAME);
446+
$request = $event->getRequest();
447+
}
448+
399449
$middlewares = $this->getMiddlewares();
400450
if (empty($middlewares)) {
401451
return $route->handle($request);

tests/RouterTest.php

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PHPUnit\Framework\TestCase;
99
use Psr\Http\Server\MiddlewareInterface;
1010
use Psr\Http\Server\RequestHandlerInterface;
11+
use Sunrise\Http\Router\Event\RouteEvent;
1112
use Sunrise\Http\Router\Exception\InvalidArgumentException;
1213
use Sunrise\Http\Router\Exception\MethodNotAllowedException;
1314
use Sunrise\Http\Router\Exception\PageNotFoundException;
@@ -19,6 +20,7 @@
1920
use Sunrise\Http\Router\Router;
2021
use Sunrise\Http\Message\ResponseFactory;
2122
use Sunrise\Http\ServerRequest\ServerRequestFactory;
23+
use Symfony\Component\EventDispatcher\EventDispatcher;
2224

2325
/**
2426
* Import functions
@@ -819,4 +821,74 @@ public function testMatchWithHosts() : void
819821
$router->match((new ServerRequestFactory)
820822
->createServerRequest('GET', 'http://localhost/ping'));
821823
}
824+
825+
/**
826+
* @return void
827+
*/
828+
public function testEventDispatcher() : void
829+
{
830+
$router = new Router();
831+
$this->assertNull($router->getEventDispatcher());
832+
833+
$eventDispatcher = new EventDispatcher();
834+
$router->setEventDispatcher($eventDispatcher);
835+
$this->assertSame($eventDispatcher, $router->getEventDispatcher());
836+
837+
$router->setEventDispatcher(null);
838+
$this->assertNull($router->getEventDispatcher());
839+
}
840+
841+
/**
842+
* @return void
843+
*/
844+
public function testRouteEvent() : void
845+
{
846+
$routes = [
847+
new Fixtures\Route(),
848+
new Fixtures\Route(),
849+
new Fixtures\Route(),
850+
];
851+
852+
$request = (new ServerRequestFactory)
853+
->createServerRequest(
854+
$routes[1]->getMethods()[1],
855+
$routes[1]->getPath()
856+
);
857+
858+
$eventDispatcher = new EventDispatcher();
859+
$eventDispatcher->addListener(RouteEvent::NAME, function (RouteEvent $event) use ($routes, $request) {
860+
$this->assertSame($routes[1]->getName(), $event->getRoute()->getName());
861+
$this->assertSame($request, $event->getRequest());
862+
});
863+
864+
$router = new Router();
865+
$router->addRoute(...$routes);
866+
$router->setEventDispatcher($eventDispatcher);
867+
$router->run($request);
868+
}
869+
870+
/**
871+
* @return void
872+
*/
873+
public function testRouteEventOverrideRequest() : void
874+
{
875+
$route = new Fixtures\Route();
876+
877+
$request = (new ServerRequestFactory)
878+
->createServerRequest(
879+
$route->getMethods()[0],
880+
$route->getPath()
881+
);
882+
883+
$eventDispatcher = new EventDispatcher();
884+
$eventDispatcher->addListener(RouteEvent::NAME, function (RouteEvent $event) use ($request) {
885+
$event->setRequest($request->withAttribute('foo', 'bar'));
886+
$this->assertNotSame($request, $event->getRequest());
887+
});
888+
889+
$router = new Router();
890+
$router->addRoute($route);
891+
$router->setEventDispatcher($eventDispatcher);
892+
$router->handle($request);
893+
}
822894
}

0 commit comments

Comments
 (0)