Compare commits

...

11 Commits

Author SHA1 Message Date
Simon Sessingø 032a2ae7e0 Merge pull request #583 from skipperbent/v4-development
Version 4.3.7.2
2021-07-18 01:45:36 +02:00
Simon Sessingø c2e2d3bb5d Merge pull request #582 from skipperbent/v4-group-prefix-bug
Fixed issue causing group prefix to trigger on paths without "/" (issue #573 - thanks @Venloress)
2021-07-18 01:44:57 +02:00
Simon Sessingø 5dd0690009 Fixed issue causing group prefix to trigger on paths without "/" (issue #573 - thanks @Venloress). 2021-07-18 01:41:26 +02:00
Simon Sessingø ee61eda1e8 Merge pull request #580 from skipperbent/v4-development
Updated documentation
2021-07-17 22:00:22 +02:00
Simon Sessingø 471bbe137f Updated documentation 2021-07-17 21:59:23 +02:00
Simon Sessingø b17ba06a8c Merge pull request #578 from skipperbent/v4-development
Version 4.3.7.0
2021-07-17 21:56:47 +02:00
Simon Sessingø 69494265a5 Merge pull request #577 from skipperbent/v4-prevent-merge-attribute
Added group attribute to stop router from merging exception-handlers (issue: #573)
2021-07-17 21:54:07 +02:00
Simon Sessingø 0d8915b206 Fixed return type. 2021-07-17 21:52:00 +02:00
Simon Sessingø b54a25804a Added group attribute to stop router from merging exception-handlers (issue: #573)
- Added new mergeExceptionHandlers attribute to stop router from merging exception-handlers.
- RouteGroup: Added setMergeExceptionHandlers and getMergeExceptionHandlers methods.
- IRouteGroup: Added setMergeExceptionHandlers and getMergeExceptionHandlers method.
- Updated documentation to reflect changes.
- Added unit-tests.
2021-07-17 21:46:05 +02:00
Simon Sessingø 4b8dbdc9e5 Merge pull request #575 from skipperbent/v4-development
Updated documentation
2021-07-16 22:31:06 +02:00
Simon Sessingø 7fe66ac938 Updated documentation
- Changed Router references to SimpleRouter.
- Updated ErrorHandler example.
- Minor tweaks
2021-07-16 22:28:54 +02:00
5 changed files with 152 additions and 26 deletions
+61 -11
View File
@@ -62,6 +62,7 @@ You can donate any amount of your choice by [clicking here](https://www.paypal.c
- [ExceptionHandlers](#exceptionhandlers)
- [Handling 404, 403 and other errors](#handling-404-403-and-other-errors)
- [Using custom exception handlers](#using-custom-exception-handlers)
- [Prevent merge of parent exception-handlers](#prevent-merge-of-parent-exception-handlers)
- [Urls](#urls)
- [Get the current url](#get-the-current-url)
- [Get by name (single route)](#get-by-name-single-route)
@@ -791,7 +792,7 @@ If you want to store the token elsewhere, please refer to the "Creating custom T
When you've created your CSRF-verifier you need to tell simple-php-router that it should use it. You can do this by adding the following line in your `routes.php` file:
```php
Router::csrfVerifier(new \Demo\Middlewares\CsrfVerifier());
SimpleRouter::csrfVerifier(new \Demo\Middlewares\CsrfVerifier());
```
## Getting CSRF-token
@@ -807,7 +808,7 @@ csrf_token();
You can also get the token directly:
```php
return Router::router()->getCsrfVerifier()->getTokenProvider()->getToken();
return SimpleRouter::router()->getCsrfVerifier()->getTokenProvider()->getToken();
```
The default name/key for the input-field is `csrf_token` and is defined in the `POST_KEY` constant in the `BaseCsrfVerifier` class.
@@ -893,10 +894,10 @@ class SessionTokenProvider implements ITokenProvider
Next you need to set your custom `ITokenProvider` implementation on your `BaseCsrfVerifier` class in your routes file:
```php
$verifier = new \dscuz\Middleware\CsrfVerifier();
$verifier = new \Demo\Middlewares\CsrfVerifier();
$verifier->setTokenProvider(new SessionTokenProvider());
Router::csrfVerifier($verifier);
SimpleRouter::csrfVerifier($verifier);
```
---
@@ -938,7 +939,7 @@ ExceptionHandler are classes that handles all exceptions. ExceptionsHandlers mus
## Handling 404, 403 and other errors
If you simply want to catch a 404 (page not found) etc. you can use the `Router::error($callback)` static helper method.
If you simply want to catch a 404 (page not found) etc. you can use the `SimpleRouter::error($callback)` static helper method.
This will add a callback method which is fired whenever an error occurs on all routes.
@@ -946,17 +947,31 @@ The basic example below simply redirect the page to `/not-found` if an `NotFound
The code should be placed in the file that contains your routes.
```php
Router::get('/not-found', 'PageController@notFound');
SimpleRouter::get('/not-found', 'PageController@notFound');
SimpleRouter::get('/forbidden', 'PageController@notFound');
Router::error(function(Request $request, \Exception $exception) {
SimpleRouter::error(function(Request $request, \Exception $exception) {
if($exception instanceof NotFoundHttpException && $exception->getCode() === 404) {
response()->redirect('/not-found');
switch($exception->getCode()) {
// Page not found
case 404:
response()->redirect('/not-found');
// Forbidden
case 403:
response()->redirect('/forbidden');
}
});
```
The example above will redirect all errors with http-code `404` (page not found) to `/not-found` and `403` (forbidden) to `/forbidden`.
If you do not want a redirect, but want the error-page rendered on the current-url, you can tell the router to execute a rewrite callback like so:
```php
$request->setRewriteCallback('ErrorController@notFound');
```
## Using custom exception handlers
This is a basic example of an ExceptionHandler implementation (please see "[Easily overwrite route about to be loaded](#easily-overwrite-route-about-to-be-loaded)" for examples on how to change callback).
@@ -1000,6 +1015,41 @@ class CustomExceptionHandler implements IExceptionHandler
}
```
You can add your custom exception-handler class to your group by using the `exceptionHandler` settings-attribute.
`exceptionHandler` can be either class-name or array of class-names.
```php
SimpleRouter::group(['exceptionHandler' => \Demo\Handlers\CustomExceptionHandler::class], function() {
// Your routes here
});
```
### Prevent merge of parent exception-handlers
By default the router will merge exception-handlers to any handlers provided by parent groups, and will be executed in the order of newest to oldest.
If you want your groups exception handler to be executed independently, you can add the `mergeExceptionHandlers` attribute and set it to `false`.
```php
SimpleRouter::group(['prefix' => '/', 'exceptionHandler' => \Demo\Handlers\FirstExceptionHandler::class, 'mergeExceptionHandlers' => false], function() {
SimpleRouter::group(['prefix' => '/admin', 'exceptionHandler' => \Demo\Handlers\SecondExceptionHandler::class], function() {
// Both SecondExceptionHandler and FirstExceptionHandler will trigger (in that order).
});
SimpleRouter::group(['prefix' => '/user', 'exceptionHandler' => \Demo\Handlers\SecondExceptionHandler::class, 'mergeExceptionHandlers' => false], function() {
// Only SecondExceptionHandler will trigger.
});
});
```
---
# Urls
@@ -1297,7 +1347,7 @@ All event callbacks will retrieve a `EventArgument` object as parameter. This ob
| `EVENT_RENDER_BOOTMANAGER` | `bootmanagers`<br>`bootmanager` | Fires before a boot-manager is rendered. |
| `EVENT_LOAD_ROUTES` | `routes` | Fires when the router is about to load all routes. |
| `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. |
| `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. |
| `EVENT_GET_URL` | `name`<br>`parameters`<br>`getParams` | Fires whenever the `SimpleRouter::getUrl` method or `url`-helper function is called and the router tries to find the route. |
| `EVENT_MATCH_ROUTE` | `route` | Fires when a route is matched and valid (correct request-type etc). and before the route is rendered. |
| `EVENT_RENDER_ROUTE` | `route` | Fires before a route is rendered. |
| `EVENT_LOAD_EXCEPTIONS` | `exception`<br>`exceptionHandlers` | Fires when the router is loading exception-handlers. |
@@ -1480,7 +1530,7 @@ $eventHandler->register(EventHandler::EVENT_ADD_ROUTE, function(EventArgument $e
});
TestRouter::addEventHandler($eventHandler);
SimpleRouter::addEventHandler($eventHandler);
```
In the example shown above, we create a new `EVENT_ADD_ROUTE` event that triggers, when a new route is added.
@@ -31,6 +31,21 @@ interface IGroupRoute extends IRoute
*/
public function setExceptionHandlers(array $handlers): self;
/**
* Returns true if group should overwrite existing exception-handlers.
*
* @return bool
*/
public function getMergeExceptionHandlers(): bool;
/**
* When enabled group will overwrite any existing exception-handlers.
*
* @param bool $merge
* @return static
*/
public function setMergeExceptionHandlers(bool $merge): self;
/**
* Get exception-handlers for group
*
+30 -1
View File
@@ -12,6 +12,7 @@ class RouteGroup extends Route implements IGroupRoute
protected $name;
protected $domains = [];
protected $exceptionHandlers = [];
protected $mergeExceptionHandlers = true;
/**
* Method called to check if a domain matches
@@ -36,6 +37,7 @@ class RouteGroup extends Route implements IGroupRoute
if ($parameters !== null && count($parameters) !== 0) {
$this->parameters = $parameters;
return true;
}
}
@@ -76,7 +78,7 @@ class RouteGroup extends Route implements IGroupRoute
}
/* Skip if prefix doesn't match */
if ($this->prefix !== null && stripos($url, $parsedPrefix) === false) {
if ($this->prefix !== null && stripos($url, rtrim($parsedPrefix, '/') . '/') === false) {
return false;
}
@@ -174,6 +176,29 @@ class RouteGroup extends Route implements IGroupRoute
return $this->prefix;
}
/**
* When enabled group will overwrite any existing exception-handlers.
*
* @param bool $merge
* @return static
*/
public function setMergeExceptionHandlers(bool $merge): IGroupRoute
{
$this->mergeExceptionHandlers = $merge;
return $this;
}
/**
* Returns true if group should overwrite existing exception-handlers.
*
* @return bool
*/
public function getMergeExceptionHandlers(): bool
{
return $this->mergeExceptionHandlers;
}
/**
* Merge with information from another route.
*
@@ -187,6 +212,10 @@ class RouteGroup extends Route implements IGroupRoute
$this->setPrefix($settings['prefix'] . $this->prefix);
}
if (isset($settings['mergeExceptionHandlers']) === true) {
$this->setMergeExceptionHandlers($settings['mergeExceptionHandlers']);
}
if ($merge === false && isset($settings['exceptionHandler']) === true) {
$this->setExceptionHandlers((array)$settings['exceptionHandler']);
}
+16 -11
View File
@@ -160,7 +160,7 @@ class Router
public function addRoute(IRoute $route): IRoute
{
$this->fireEvents(EventHandler::EVENT_ADD_ROUTE, [
'route' => $route,
'route' => $route,
'isSubRoute' => $this->isProcessingRoute,
]);
@@ -203,7 +203,7 @@ class Router
/**
* Process added routes.
*
* @param array $routes
* @param array|IRoute[] $routes
* @param IGroupRoute|null $group
* @throws NotFoundHttpException
*/
@@ -211,9 +211,6 @@ class Router
{
$this->debug('Processing routes');
// Loop through each route-request
$exceptionHandlers = [];
// Stop processing routes if no valid route is found.
if ($this->request->getRewriteRoute() === null && $this->request->getUrl()->getOriginalUrl() === '') {
$this->debug('Halted route-processing as no valid route was found');
@@ -223,7 +220,7 @@ class Router
$url = $this->request->getRewriteUrl() ?? $this->request->getUrl()->getPath();
/* @var $route IRoute */
// Loop through each route-request
foreach ($routes as $route) {
$this->debug('Processing route "%s"', get_class($route));
@@ -240,13 +237,22 @@ class Router
/* Add exception handlers */
if (count($route->getExceptionHandlers()) !== 0) {
/** @noinspection AdditionOperationOnArraysInspection */
$exceptionHandlers += $route->getExceptionHandlers();
if ($route->getMergeExceptionHandlers() === true) {
foreach ($route->getExceptionHandlers() as $handler) {
$this->exceptionHandlers[] = $handler;
}
} else {
$this->exceptionHandlers = $route->getExceptionHandlers();
}
}
/* Only render partial group if it matches */
if ($route instanceof IPartialGroupRoute === true) {
$this->renderAndProcess($route);
continue;
}
}
@@ -264,8 +270,6 @@ class Router
$this->processedRoutes[] = $route;
}
}
$this->exceptionHandlers = array_merge($exceptionHandlers, $this->exceptionHandlers);
}
/**
@@ -679,7 +683,7 @@ class Router
->setParams($getParams);
}
if($name !== null) {
if ($name !== null) {
/* We try to find a match on the given name */
$route = $this->findRoute($name);
@@ -942,6 +946,7 @@ class Router
public function addExceptionHandler(IExceptionHandler $handler): self
{
$this->exceptionHandlers[] = $handler;
return $this;
}
+30 -3
View File
@@ -33,9 +33,9 @@ class RouterRewriteTest extends \PHPUnit\Framework\TestCase
global $stack;
$stack = [];
TestRouter::group(['exceptionHandler' => [ExceptionHandlerFirst::class, ExceptionHandlerSecond::class]], function () use ($stack) {
TestRouter::group(['exceptionHandler' => [ExceptionHandlerFirst::class, ExceptionHandlerSecond::class]], function () {
TestRouter::group(['exceptionHandler' => ExceptionHandlerThird::class], function () use ($stack) {
TestRouter::group(['prefix' => '/test', 'exceptionHandler' => ExceptionHandlerThird::class], function () {
TestRouter::get('/my-path', 'DummyController@method1');
@@ -43,7 +43,7 @@ class RouterRewriteTest extends \PHPUnit\Framework\TestCase
});
try {
TestRouter::debug('/my-non-existing-path', 'get');
TestRouter::debug('/test/non-existing', 'get');
} catch (\ResponseException $e) {
}
@@ -58,6 +58,33 @@ class RouterRewriteTest extends \PHPUnit\Framework\TestCase
}
public function testStopMergeExceptionHandlers()
{
global $stack;
$stack = [];
TestRouter::group(['prefix' => '/', 'exceptionHandler' => ExceptionHandlerFirst::class], function () {
TestRouter::group(['prefix' => '/admin', 'exceptionHandler' => ExceptionHandlerSecond::class, 'mergeExceptionHandlers' => false], function () {
TestRouter::get('/my-path', 'DummyController@method1');
});
});
try {
TestRouter::debug('/admin/my-path-test', 'get');
} catch (\Pecee\SimpleRouter\Exceptions\NotFoundHttpException $e) {
}
$expectedStack = [
ExceptionHandlerSecond::class,
];
$this->assertEquals($expectedStack, $stack);
}
public function testRewriteExceptionMessage()
{
$this->expectException(\Pecee\SimpleRouter\Exceptions\NotFoundHttpException::class);