Development

- Added event-arguments data.
- Added event-arguments to the event list in documentation.
- Fixed missing exceptions thrown in phpDocs.
- Added unit-tests for new event functionality.
This commit is contained in:
Simon Sessingø
2018-03-29 18:51:28 +02:00
parent a9c03f9271
commit f5a023117a
11 changed files with 162 additions and 70 deletions
+25 -18
View File
@@ -1238,23 +1238,25 @@ It will also cover the basics of event-handlers; how to use the handlers provide
This section contains all available events that can be registered using the `EventHandler`. This section contains all available events that can be registered using the `EventHandler`.
| Name | Description | All event callbacks will retrieve a `EventArgument` object as parameter. This object contains easy access to event-name, router- and request instance and any special event-arguments related to the given event. You can see what special event arguments each event returns in the list below.
| ------------- |------------- |
| `EventHandler::EVENT_ALL` | Fires when a event is triggered. | | Name | Special arguments | Description |
| `EventHandler::EVENT_INIT` | Fires when router is initializing and before routes are loaded. | | ------------- |----------- | ---- |
| `EventHandler::EVENT_LOAD` | Fires when all routes has been loaded and rendered, just before the output is returned. | | `EVENT_ALL` | - | Fires when a event is triggered. |
| `EventHandler::EVENT_REWRITE` | Fires when a url-rewrite is and just before the routes are re-initialized. | | `EVENT_INIT` | - | Fires when router is initializing and before routes are loaded. |
| `EventHandler::EVENT_BOOT` | Fires when the router is booting. This happens just before boot-managers are rendered and before any routes has been loaded. | | `EVENT_LOAD` | `loadedRoutes` | Fires when all routes has been loaded and rendered, just before the output is returned. |
| `EventHandler::EVENT_RENDER_BOOTMANAGER` | Fires before a boot-manager is rendered. | | `EVENT_REWRITE` | `rewriteUrl`<br>`rewriteRoute` | Fires when a url-rewrite is and just before the routes are re-initialized. |
| `EventHandler::EVENT_LOAD_ROUTES` | Fires when the router is about to load all routes. | | `EVENT_BOOT` | `bootmanagers` | Fires when the router is booting. This happens just before boot-managers are rendered and before any routes has been loaded. |
| `EventHandler::EVENT_FIND_ROUTE` | Fires whenever the `findRoute` method is called within the `Router`. This usually happens when the router tries to find routes that contains a certain url, usually after the `EventHandler::EVENT_GET_URL` event. | | `EVENT_RENDER_BOOTMANAGER` | `bootmanagers`<br>`bootmanager` | Fires before a boot-manager is rendered. |
| `EventHandler::EVENT_GET_URL` | Fires whenever the `Router::getUrl` method or `url`-helper function is called and the router tries to find the route. | | `EVENT_LOAD_ROUTES` | `routes` | Fires when the router is about to load all routes. |
| `EventHandler::EVENT_MATCH_ROUTE` | Fires when a route is matched and valid (correct request-type etc). and before the route is rendered. | | `EVENT_FIND_ROUTE` | `name` | Fires whenever the `findRoute` method is called within the `Router`. This usually happens when the router tries to find routes that contains a certain url, usually after the `EventHandler::EVENT_GET_URL` event. |
| `EventHandler::EVENT_RENDER_ROUTE` | Fires before a route is rendered. | | `EVENT_GET_URL` | `name`<br>`parameters`<br>`getParams` | Fires whenever the `Router::getUrl` method or `url`-helper function is called and the router tries to find the route. |
| `EventHandler::EVENT_LOAD_EXCEPTIONS` | Fires when the router is loading exception-handlers. | | `EVENT_MATCH_ROUTE` | `route` | Fires when a route is matched and valid (correct request-type etc). and before the route is rendered. |
| `EventHandler::EVENT_RENDER_EXCEPTION` | Fires before the router is rendering a exception-handler. | | `EVENT_RENDER_ROUTE` | `route` | Fires before a route is rendered. |
| `EventHandler::EVENT_RENDER_MIDDLEWARE` | Fires before a middleware is rendered. | | `EVENT_LOAD_EXCEPTIONS` | `exception`<br>`exceptionHandlers` | Fires when the router is loading exception-handlers. |
| `EventHandler::EVENT_RENDER_CSRF` | Fires before the CSRF-verifier is rendered. | | `EVENT_RENDER_EXCEPTION` | `exception`<br>`exceptionHandler`<br>`exceptionHandlers` | Fires before the router is rendering a exception-handler. |
| `EVENT_RENDER_MIDDLEWARES` | `route`<br>`middlewares` | Fires before middlewares for a route is rendered. |
| `EVENT_RENDER_CSRF` | `csrfVerifier` | Fires before the CSRF-verifier is rendered. |
## Registering new event ## Registering new event
@@ -1272,9 +1274,14 @@ use Pecee\SimpleRouter\Event\EventArgument;
// --- your routes goes here --- // --- your routes goes here ---
$eventHandler = new EventHandler(); $eventHandler = new EventHandler();
// Add event that fires when a route is rendered
$eventHandler->register(EventHandler::EVENT_RENDER_ROUTE, function(EventArgument $argument) { $eventHandler->register(EventHandler::EVENT_RENDER_ROUTE, function(EventArgument $argument) {
// Fires when route is rendered ... // Get the route by using the special argument for this event.
$route = $argument->route;
// DO STUFF...
}); });
@@ -70,6 +70,34 @@ class EventArgument implements IEventArgument
return $this->getRouter()->getRequest(); return $this->getRouter()->getRequest();
} }
/**
* @param string $name
* @return mixed
*/
public function __get($name)
{
return $this->arguments[$name] ?? null;
}
/**
* @param string $name
* @return bool
*/
public function __isset($name)
{
return array_key_exists($name, $this->arguments);
}
/**
* @param string $name
* @param mixed $value
* @throws \InvalidArgumentException
*/
public function __set($name, $value)
{
throw new \InvalidArgumentException('Not supported');
}
/** /**
* Get arguments * Get arguments
* *
@@ -41,9 +41,9 @@ class DebugEventHandler implements IEventHandler
* *
* @param Router $router Router instance * @param Router $router Router instance
* @param string $name Event name * @param string $name Event name
* @param array ...$eventArgs Event arguments * @param array $eventArgs Event arguments
*/ */
public function fireEvents(Router $router, string $name, ...$eventArgs): void public function fireEvents(Router $router, string $name, array $eventArgs = []): void
{ {
$callback = $this->callback; $callback = $this->callback;
$callback(new EventArgument($router, $eventArgs)); $callback(new EventArgument($router, $eventArgs));
@@ -80,7 +80,7 @@ class EventHandler implements IEventHandler
/** /**
* Fires before a middleware is rendered. * Fires before a middleware is rendered.
*/ */
public const EVENT_RENDER_MIDDLEWARE = 'onRenderMiddleware'; public const EVENT_RENDER_MIDDLEWARES = 'onRenderMiddlewares';
/** /**
* Fires before the CSRF-verifier is rendered. * Fires before the CSRF-verifier is rendered.
@@ -105,7 +105,7 @@ class EventHandler implements IEventHandler
self::EVENT_RENDER_ROUTE, self::EVENT_RENDER_ROUTE,
self::EVENT_LOAD_EXCEPTIONS, self::EVENT_LOAD_EXCEPTIONS,
self::EVENT_RENDER_EXCEPTION, self::EVENT_RENDER_EXCEPTION,
self::EVENT_RENDER_MIDDLEWARE, self::EVENT_RENDER_MIDDLEWARES,
self::EVENT_RENDER_CSRF, self::EVENT_RENDER_CSRF,
]; ];
@@ -163,9 +163,9 @@ class EventHandler implements IEventHandler
* *
* @param Router $router Router instance * @param Router $router Router instance
* @param string $name Event name * @param string $name Event name
* @param array ...$eventArgs Event arguments * @param array $eventArgs Event arguments
*/ */
public function fireEvents(Router $router, string $name, ...$eventArgs): void public function fireEvents(Router $router, string $name, array $eventArgs = []): void
{ {
$events = $this->getEvents(static::EVENT_ALL, $name); $events = $this->getEvents(static::EVENT_ALL, $name);
@@ -19,8 +19,8 @@ interface IEventHandler {
* *
* @param Router $router Router instance * @param Router $router Router instance
* @param string $name Event name * @param string $name Event name
* @param array ...$eventArgs Event arguments * @param array $eventArgs Event arguments
*/ */
public function fireEvents(Router $router, string $name, ...$eventArgs) : void; public function fireEvents(Router $router, string $name, array $eventArgs = []) : void;
} }
@@ -42,9 +42,11 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
throw new HttpException($middleware . ' must be inherit the IMiddleware interface'); throw new HttpException($middleware . ' must be inherit the IMiddleware interface');
} }
$router->debug('Loading middleware "%s"', \get_class($middleware)); $className = \get_class($middleware);
$router->debug('Loading middleware "%s"', $className);
$middleware->handle($request); $middleware->handle($request);
$router->debug('Finished loading middleware'); $router->debug('Finished loading middleware "%s"', $className);
} }
$router->debug('Finished loading middlewares'); $router->debug('Finished loading middlewares');
+1 -1
View File
@@ -82,7 +82,7 @@ abstract class Route implements IRoute
*/ */
public function renderRoute(Request $request, Router $router): ?string public function renderRoute(Request $request, Router $router): ?string
{ {
$router->debug('Starting rendering route'); $router->debug('Starting rendering route "%s"', \get_class($this));
$callback = $this->getCallback(); $callback = $this->getCallback();
+61 -19
View File
@@ -258,23 +258,31 @@ class Router
{ {
$this->debug('Loading routes'); $this->debug('Loading routes');
$this->fireEvents(EventHandler::EVENT_BOOT); $this->fireEvents(EventHandler::EVENT_BOOT, [
'bootmanagers' => $this->bootManagers,
]);
/* Initialize boot-managers */ /* Initialize boot-managers */
/* @var $manager IRouterBootManager */ /* @var $manager IRouterBootManager */
foreach ($this->bootManagers as $manager) { foreach ($this->bootManagers as $manager) {
$this->debug('Rendering bootmanager %s', \get_class($manager)); $className = \get_class($manager);
$this->fireEvents(EventHandler::EVENT_RENDER_BOOTMANAGER, $manager); $this->debug('Rendering bootmanager "%s"', $className);
$this->fireEvents(EventHandler::EVENT_RENDER_BOOTMANAGER, [
'bootmanagers' => $this->bootManagers,
'bootmanager' => $manager,
]);
/* Render bootmanager */ /* Render bootmanager */
$manager->boot($this, $this->request); $manager->boot($this, $this->request);
$this->debug('Finished rendering bootmanager'); $this->debug('Finished rendering bootmanager "%s"', $className);
} }
$this->fireEvents(EventHandler::EVENT_LOAD_ROUTES); $this->fireEvents(EventHandler::EVENT_LOAD_ROUTES, [
'routes' => $this->routes,
]);
/* Loop through each route-request */ /* Loop through each route-request */
$this->processRoutes($this->routes); $this->processRoutes($this->routes);
@@ -301,7 +309,9 @@ class Router
if ($this->csrfVerifier !== null) { if ($this->csrfVerifier !== null) {
$this->fireEvents(EventHandler::EVENT_RENDER_CSRF); $this->fireEvents(EventHandler::EVENT_RENDER_CSRF, [
'csrfVerifier' => $this->csrfVerifier,
]);
/* Verify csrf token for request */ /* Verify csrf token for request */
$this->csrfVerifier->handle($this->request); $this->csrfVerifier->handle($this->request);
@@ -309,7 +319,9 @@ class Router
$output = $this->routeRequest(); $output = $this->routeRequest();
$this->fireEvents(EventHandler::EVENT_LOAD); $this->fireEvents(EventHandler::EVENT_LOAD, [
'loadedRoutes' => $this->getRequest()->getLoadedRoutes(),
]);
$this->debug('Routing complete'); $this->debug('Routing complete');
@@ -340,7 +352,9 @@ class Router
/* If the route matches */ /* If the route matches */
if ($route->matchRoute($url, $this->request) === true) { if ($route->matchRoute($url, $this->request) === true) {
$this->fireEvents(EventHandler::EVENT_MATCH_ROUTE); $this->fireEvents(EventHandler::EVENT_MATCH_ROUTE, [
'route' => $route,
]);
/* Check if request method matches */ /* Check if request method matches */
if (\count($route->getRequestMethods()) !== 0 && \in_array($this->request->getMethod(), $route->getRequestMethods(), true) === false) { if (\count($route->getRequestMethods()) !== 0 && \in_array($this->request->getMethod(), $route->getRequestMethods(), true) === false) {
@@ -349,7 +363,10 @@ class Router
continue; continue;
} }
$this->fireEvents(EventHandler::EVENT_RENDER_MIDDLEWARE); $this->fireEvents(EventHandler::EVENT_RENDER_MIDDLEWARES, [
'route' => $route,
'middlewares' => $route->getMiddlewares(),
]);
$route->loadMiddleware($this->request, $this); $route->loadMiddleware($this->request, $this);
@@ -361,6 +378,11 @@ class Router
$methodNotAllowed = false; $methodNotAllowed = false;
$this->request->addLoadedRoute($route); $this->request->addLoadedRoute($route);
$this->fireEvents(EventHandler::EVENT_RENDER_ROUTE, [
'route' => $route,
]);
$output = $route->renderRoute($this->request, $this); $output = $route->renderRoute($this->request, $this);
if ($output !== null) { if ($output !== null) {
return $output; return $output;
@@ -427,7 +449,10 @@ class Router
unset($this->processedRoutes[$key]); unset($this->processedRoutes[$key]);
$this->request->setHasPendingRewrite(false); $this->request->setHasPendingRewrite(false);
$this->fireEvents(EventHandler::EVENT_REWRITE); $this->fireEvents(EventHandler::EVENT_REWRITE, [
'rewriteUrl' => $this->request->getRewriteUrl(),
'rewriteRoute' => $this->request->getRewriteRoute(),
]);
return $this->routeRequest(); return $this->routeRequest();
} }
@@ -445,7 +470,10 @@ class Router
{ {
$this->debug('Starting exception handling for "%s"', \get_class($e)); $this->debug('Starting exception handling for "%s"', \get_class($e));
$this->fireEvents(EventHandler::EVENT_LOAD_EXCEPTIONS); $this->fireEvents(EventHandler::EVENT_LOAD_EXCEPTIONS, [
'exception' => $e,
'exceptionHandlers' => $this->exceptionHandlers,
]);
/* @var $handler IExceptionHandler */ /* @var $handler IExceptionHandler */
foreach ($this->exceptionHandlers as $key => $handler) { foreach ($this->exceptionHandlers as $key => $handler) {
@@ -454,7 +482,11 @@ class Router
$handler = new $handler(); $handler = new $handler();
} }
$this->fireEvents(EventHandler::EVENT_RENDER_EXCEPTION); $this->fireEvents(EventHandler::EVENT_RENDER_EXCEPTION, [
'exception' => $e,
'exceptionHandler' => $handler,
'exceptionHandlers' => $this->exceptionHandlers,
]);
$this->debug('Processing exception-handler "%s"', \get_class($handler)); $this->debug('Processing exception-handler "%s"', \get_class($handler));
@@ -473,7 +505,10 @@ class Router
$this->debug('Exception handler contains rewrite, reloading routes'); $this->debug('Exception handler contains rewrite, reloading routes');
$this->fireEvents(EventHandler::EVENT_REWRITE); $this->fireEvents(EventHandler::EVENT_REWRITE, [
'rewriteUrl' => $this->request->getRewriteUrl(),
'rewriteRoute' => $this->request->getRewriteRoute(),
]);
return $this->routeRequest(); return $this->routeRequest();
} }
@@ -498,7 +533,10 @@ class Router
public function findRoute(string $name): ?ILoadableRoute public function findRoute(string $name): ?ILoadableRoute
{ {
$this->debug('Finding route by name "%s"', $name); $this->debug('Finding route by name "%s"', $name);
$this->fireEvents(EventHandler::EVENT_FIND_ROUTE);
$this->fireEvents(EventHandler::EVENT_FIND_ROUTE, [
'name' => $name,
]);
/* @var $route ILoadableRoute */ /* @var $route ILoadableRoute */
foreach ($this->processedRoutes as $route) { foreach ($this->processedRoutes as $route) {
@@ -576,7 +614,11 @@ class Router
{ {
$this->debug('Finding url', \func_get_args()); $this->debug('Finding url', \func_get_args());
$this->fireEvents(EventHandler::EVENT_GET_URL); $this->fireEvents(EventHandler::EVENT_GET_URL, [
'name' => $name,
'parameters' => $parameters,
'getParams' => $getParams,
]);
if ($getParams !== null && \is_array($getParams) === false) { if ($getParams !== null && \is_array($getParams) === false) {
throw new InvalidArgumentException('Invalid type for getParams. Must be array or null'); throw new InvalidArgumentException('Invalid type for getParams. Must be array or null');
@@ -772,12 +814,12 @@ class Router
} }
/** /**
* Fire event * Fire event in event-handler.
* *
* @param string $name * @param string $name
* @param array ...$args * @param array $arguments
*/ */
protected function fireEvents($name, ...$args): void protected function fireEvents($name, array $arguments = []): void
{ {
if (\count($this->eventHandlers) === 0) { if (\count($this->eventHandlers) === 0) {
return; return;
@@ -785,7 +827,7 @@ class Router
/* @var IEventHandler $eventHandler */ /* @var IEventHandler $eventHandler */
foreach ($this->eventHandlers as $eventHandler) { foreach ($this->eventHandlers as $eventHandler) {
$eventHandler->fireEvents($this, $name, $args); $eventHandler->fireEvents($this, $name, $arguments);
} }
} }
+2
View File
@@ -51,6 +51,8 @@ class SimpleRouter
/** /**
* Start routing * Start routing
* *
* @throws \Pecee\SimpleRouter\Exceptions\NotFoundHttpException
* @throws \Pecee\Http\Middleware\Exceptions\TokenMismatchException
* @throws HttpException * @throws HttpException
* @throws \Exception * @throws \Exception
*/ */
+21 -15
View File
@@ -4,6 +4,7 @@ require_once 'Dummy/DummyMiddleware.php';
require_once 'Dummy/DummyController.php'; require_once 'Dummy/DummyController.php';
require_once 'Dummy/Handler/ExceptionHandler.php'; require_once 'Dummy/Handler/ExceptionHandler.php';
require_once 'Dummy/Security/SilentTokenProvider.php'; require_once 'Dummy/Security/SilentTokenProvider.php';
require_once 'Dummy/Managers/TestBootManager.php';
use \Pecee\SimpleRouter\Handlers\EventHandler; use \Pecee\SimpleRouter\Handlers\EventHandler;
use \Pecee\SimpleRouter\Event\EventArgument; use \Pecee\SimpleRouter\Event\EventArgument;
@@ -11,12 +12,12 @@ use \Pecee\SimpleRouter\Event\EventArgument;
class EventHandlerTest extends \PHPUnit\Framework\TestCase class EventHandlerTest extends \PHPUnit\Framework\TestCase
{ {
public function testMissingEvents() { public function testAllEventTriggered()
{
$events = EventHandler::$events; $events = EventHandler::$events;
// Remove the all event // Remove the all event
unset($events[\array_search(EventHandler::EVENT_ALL, $events, true)], $events[\array_search(EventHandler::EVENT_REWRITE, $events, true)]); unset($events[\array_search(EventHandler::EVENT_ALL, $events, true)]);
$eventHandler = new EventHandler(); $eventHandler = new EventHandler();
$eventHandler->register(EventHandler::EVENT_ALL, function (EventArgument $arg) use (&$events) { $eventHandler->register(EventHandler::EVENT_ALL, function (EventArgument $arg) use (&$events) {
@@ -26,6 +27,7 @@ class EventHandlerTest extends \PHPUnit\Framework\TestCase
TestRouter::addEventHandler($eventHandler); TestRouter::addEventHandler($eventHandler);
// Add rewrite
TestRouter::error(function (\Pecee\Http\Request $request, \Exception $error) { TestRouter::error(function (\Pecee\Http\Request $request, \Exception $error) {
// Trigger rewrite // Trigger rewrite
@@ -35,28 +37,36 @@ class EventHandlerTest extends \PHPUnit\Framework\TestCase
TestRouter::get('/', 'DummyController@method1')->name('home'); TestRouter::get('/', 'DummyController@method1')->name('home');
// Trigger findRoute
TestRouter::router()->findRoute('home'); TestRouter::router()->findRoute('home');
// Trigger getUrl
TestRouter::router()->getUrl('home'); TestRouter::router()->getUrl('home');
// Add csrf-verifier
$csrfVerifier = new \Pecee\Http\Middleware\BaseCsrfVerifier(); $csrfVerifier = new \Pecee\Http\Middleware\BaseCsrfVerifier();
$csrfVerifier->setTokenProvider(new SilentTokenProvider()); $csrfVerifier->setTokenProvider(new SilentTokenProvider());
TestRouter::csrfVerifier($csrfVerifier); TestRouter::csrfVerifier($csrfVerifier);
TestRouter::debug('/not-existing'); // Add boot-manager
TestRouter::addBootManager(new TestBootManager([
'/test',
], '/'));
// Start router
TestRouter::debug('/non-existing');
$this->assertEquals($events, []); $this->assertEquals($events, []);
TestRouter::router()->reset();
} }
public function testAllEvent() { public function testAllEvent()
{
$status = 0; $status = false;
$eventHandler = new EventHandler(); $eventHandler = new EventHandler();
$eventHandler->register(EventHandler::EVENT_ALL, function (EventArgument $arg) use (&$status) { $eventHandler->register(EventHandler::EVENT_ALL, function (EventArgument $arg) use (&$status) {
$status++; $status = true;
}); });
TestRouter::addEventHandler($eventHandler); TestRouter::addEventHandler($eventHandler);
@@ -65,11 +75,7 @@ class EventHandlerTest extends \PHPUnit\Framework\TestCase
TestRouter::debug('/'); TestRouter::debug('/');
// All event should fire for each other event // All event should fire for each other event
$this->assertEquals(\count(EventHandler::$events), $status); $this->assertEquals(true, $status);
}
public function testEvents() {
$this->assertEquals(true, true);
} }
} }
+10 -5
View File
@@ -7,23 +7,28 @@ require_once 'Dummy/Handler/ExceptionHandler.php';
class InputHandlerTest extends \PHPUnit\Framework\TestCase class InputHandlerTest extends \PHPUnit\Framework\TestCase
{ {
public function testGet() { public function testGet()
{
$this->assertEquals(true, true); $this->assertEquals(true, true);
} }
public function testPost() { public function testPost()
{
$this->assertEquals(true, true); $this->assertEquals(true, true);
} }
public function testFile() { public function testFile()
{
$this->assertEquals(true, true); $this->assertEquals(true, true);
} }
public function testFiles() { public function testFiles()
{
$this->assertEquals(true, true); $this->assertEquals(true, true);
} }
public function testAll() { public function testAll()
{
$this->assertEquals(true, true); $this->assertEquals(true, true);
} }