Compare commits

..

24 Commits

Author SHA1 Message Date
Simon 7ba29457ff Pass unit tests 2023-08-09 04:55:26 +02:00
Simon 30db793e85 Optimized parameter handling 2023-08-09 00:18:30 +02:00
sessingo d3b1577095 RouteResource: simplified the findUrl method (issue: #666) 2023-05-06 21:07:58 +02:00
Simon Sessingø 00d1c534de Merge pull request #667 from skipperbent/fix-resource-parameters
Resource-type not respecting parameters when using getUrl (issue: #666)
2023-05-06 17:33:53 +02:00
Simon Sessingø 37f826f24c Merge pull request #664 from SunflowerFuchs/v5-development
Fixed Route::setUrl() behavior
2023-05-06 17:32:57 +02:00
sessingo f3c6015a59 Fixed Resource-type not respecting parameters when using getUrl (issue: #666) 2023-05-06 17:29:33 +02:00
Pascal Pirschel b2851e41f1 Fixed Route::setUrl() behavior
When there are no parameters in the url, correctly empty the routes parameter array
2023-05-05 13:48:26 +02:00
sessingo e105f266e3 Fixed typo 2023-04-24 20:05:33 +02:00
sessingo a49d7c13b6 Reverted exception handling to old behavior (issue: #660) 2023-04-24 20:03:15 +02:00
sessingo 4778a8f29e InputItem: php8.1 deprecated warning-Added returnTypeWillChange to offsetGet 2023-04-21 11:28:19 +02:00
Simon Sessingø 2b4ae2b211 Merge pull request #654 from skipperbent/v5-exception-handling
PHP8: better exception handling
2023-04-08 19:56:55 +02:00
sessingo fa05d64a76 PHP8: better exception handling
Looks like PHP8 handles exceptions differently with Throwables used in cases where php-error occoured.
To fix this Throwable are now used to catch exception in routeRequest and any instance of Throwable will be converted to Exception.
2023-04-08 19:49:51 +02:00
Simon Sessingø 5ac747374b Merge pull request #652 from skipperbent/fix-tostring
[BUGFIX] String return type
2023-04-07 15:38:41 +02:00
sessingo d6642a7f7b Changed behavior of router to always exspect returned output to be string. 2023-04-07 15:30:24 +02:00
Simon Sessingø ebf9224407 Merge pull request #649 from skipperbent/feature-csrfverifier
[!!!] CsrfVerifier changes
2023-04-07 14:36:13 +02:00
Simon Sessingø c635771fcd Merge pull request #650 from skipperbent/v5-fix-exception
[BUGFIX] Exception handling improvements
2023-04-07 14:35:56 +02:00
sessingo 791d69b24d Updated documentation 2023-04-07 13:08:40 +02:00
sessingo aa654a3ac6 [BUGFIX] Fixed exception-handler rewrite not always triggered 2023-04-07 13:05:27 +02:00
sessingo 6c6d81d3c9 [!!!] CsrfVerifier changes
- [!!!] Made $except and $include array not nullable.
- Added more customizable BaseCsrfVerifier. Can now be used as ticket for no hotlinking etc.
2023-04-06 13:09:26 +02:00
sessingo 8c79b74e14 Bugfixes 2023-04-02 03:22:38 +02:00
Simon Sessingø 77da37e00e Merge pull request #644 from skipperbent/v5-property-types
[!!!] Added type definitions to property types
2023-04-02 03:14:50 +02:00
sessingo 5946397c15 [!!!] Added type definitions to property types
- Request: optimized getIp method and reversed the order so proxy is always checked first.
2023-04-02 03:10:27 +02:00
Simon Sessingø dc3b1fe74e Merge pull request #641 from skipperbent/fix-session
[BUGFIX] Fixed SESSION not shutdown correctly when using redirect.
2023-03-30 16:21:04 +02:00
sessingo c622ef97b0 [BUGFIX] Fixed SESSION not shutdown correctly when using redirect.
- Disabled multiple route rendering by default.
2023-03-30 16:15:06 +02:00
31 changed files with 290 additions and 195 deletions
+16 -4
View File
@@ -85,7 +85,7 @@ You can donate any amount of your choice by [clicking here](https://www.paypal.c
- [Registering new event](#registering-new-event)
- [Custom EventHandlers](#custom-eventhandlers)
- [Advanced](#advanced)
- [Disable multiple route rendering](#disable-multiple-route-rendering)
- [Multiple route rendering](#multiple-route-rendering)
- [Restrict access to IP](#restrict-access-to-ip)
- [Setting custom base path](#setting-custom-base-path)
- [Url rewriting](#url-rewriting)
@@ -1036,6 +1036,17 @@ class CustomExceptionHandler implements IExceptionHandler
return;
}
/* Other error */
if($error instanceof MyCustomException) {
$request->setRewriteRoute(
// Add new route based on current url (minus query-string) and add custom parameters.
(new RouteUrl(url(null, null, []), 'PageController@error'))->setParameters(['exception' => $error])
);
return;
}
throw $error;
@@ -1492,11 +1503,12 @@ class DatabaseDebugHandler implements IEventHandler
# Advanced
## Disable multiple route rendering
## Multiple route rendering
By default the router will try to execute all routes that matches a given url. To stop the router from executing any further routes any method can return a value.
If you need multiple routes to be executed on the same url, you can enable this feature by setting `SimpleRouter::enableMultiRouteRendering(true)`
in your `routes.php` file.
This behavior can be easily disabled by setting `SimpleRouter::enableMultiRouteRendering(false)` in your `routes.php` file. This is the same behavior as version 3 and below.
This is most commonly used in advanced cases, for example in CMS systems where multiple routes needs to be rendered.
## Restrict access to IP
+11 -11
View File
@@ -9,37 +9,37 @@ class InputFile implements IInputItem
/**
* @var string
*/
public $index;
public string $index;
/**
* @var string
*/
public $name;
public string $name;
/**
* @var string|null
*/
public $filename;
public ?string $filename = null;
/**
* @var int|null
*/
public $size;
public ?int $size = null;
/**
* @var int|null
* @var string|null
*/
public $type;
public ?string $type = null;
/**
* @var int
*/
public $errors;
public int $errors = 0;
/**
* @var string|null
*/
public $tmpName;
public ?string $tmpName = null;
public function __construct(string $index)
{
@@ -74,7 +74,7 @@ class InputFile implements IInputItem
'error' => null,
];
return (new static($values['index']))
return (new self($values['index']))
->setSize((int)$values['size'])
->setError((int)$values['error'])
->setType($values['type'])
@@ -104,9 +104,9 @@ class InputFile implements IInputItem
}
/**
* @return string
* @return int
*/
public function getSize(): string
public function getSize(): ?int
{
return $this->size;
}
+7 -7
View File
@@ -10,40 +10,40 @@ class InputHandler
/**
* @var array
*/
protected $get = [];
protected array $get = [];
/**
* @var array
*/
protected $post = [];
protected array $post = [];
/**
* @var array
*/
protected $file = [];
protected array $file = [];
/**
* @var Request
*/
protected $request;
protected Request $request;
/**
* Original post variables
* @var array
*/
protected $originalPost = [];
protected array $originalPost = [];
/**
* Original get/params variables
* @var array
*/
protected $originalParams = [];
protected array $originalParams = [];
/**
* Get original file variables
* @var array
*/
protected $originalFile = [];
protected array $originalFile = [];
/**
* Input constructor.
+11 -2
View File
@@ -8,10 +8,18 @@ use IteratorAggregate;
class InputItem implements ArrayAccess, IInputItem, IteratorAggregate
{
public $index;
public $name;
public string $index;
public string $name;
/**
* @var mixed|null
*/
public $value;
/**
* @param string $index
* @param mixed $value
*/
public function __construct(string $index, $value = null)
{
$this->index = $index;
@@ -81,6 +89,7 @@ class InputItem implements ArrayAccess, IInputItem, IteratorAggregate
return isset($this->value[$offset]);
}
#[\ReturnTypeWillChange]
public function offsetGet($offset): ?self
{
if ($this->offsetExists($offset) === true) {
+25 -20
View File
@@ -17,18 +17,18 @@ class BaseCsrfVerifier implements IMiddleware
* For example: /admin/*
* @var array|null
*/
protected $except;
protected array $except = [];
/**
* Urls to include. Can be used to include urls from a certain path.
* @var array|null
*/
protected $include;
protected array $include = [];
/**
* @var ITokenProvider
*/
protected $tokenProvider;
protected ITokenProvider $tokenProvider;
/**
* BaseCsrfVerifier constructor.
@@ -38,6 +38,23 @@ class BaseCsrfVerifier implements IMiddleware
$this->tokenProvider = new CookieTokenProvider();
}
protected function isIncluded(Request $request): bool
{
if (count($this->include) > 0) {
foreach ($this->include as $includeUrl) {
$includeUrl = rtrim($includeUrl, '/');
if ($includeUrl[strlen($includeUrl) - 1] === '*') {
$includeUrl = rtrim($includeUrl, '*');
return $request->getUrl()->contains($includeUrl);
}
return ($includeUrl === rtrim($request->getUrl()->getRelativeUrl(false), '/'));
}
}
return false;
}
/**
* Check if the url matches the urls in the except property
* @param Request $request
@@ -45,11 +62,11 @@ class BaseCsrfVerifier implements IMiddleware
*/
protected function skip(Request $request): bool
{
if ($this->except === null || count($this->except) === 0) {
if (count($this->except) === 0) {
return false;
}
foreach($this->except as $url) {
foreach ($this->except as $url) {
$url = rtrim($url, '/');
if ($url[strlen($url) - 1] === '*') {
$url = rtrim($url, '*');
@@ -60,20 +77,9 @@ class BaseCsrfVerifier implements IMiddleware
if ($skip === true) {
if(is_array($this->include) === true && count($this->include) > 0) {
foreach($this->include as $includeUrl) {
$includeUrl = rtrim($includeUrl, '/');
if ($includeUrl[strlen($includeUrl) - 1] === '*') {
$includeUrl = rtrim($includeUrl, '*');
$skip = !$request->getUrl()->contains($includeUrl);
break;
}
$skip = !$this->isIncluded($request);
$skip = !($includeUrl === rtrim($request->getUrl()->getRelativeUrl(false), '/'));
}
}
if($skip === false) {
if ($skip === false) {
continue;
}
@@ -92,12 +98,11 @@ class BaseCsrfVerifier implements IMiddleware
*/
public function handle(Request $request): void
{
if ($this->skip($request) === false && $request->isPostBack() === true) {
if ($this->skip($request) === false && ($request->isPostBack() === true || $this->isIncluded($request) === true)) {
$token = $request->getInputHandler()->value(
static::POST_KEY,
$request->getHeader(static::HEADER_KEY),
Request::$requestTypesPost
);
if ($this->tokenProvider->validate((string)$token) === false) {
@@ -7,8 +7,8 @@ use Pecee\SimpleRouter\Exceptions\HttpException;
abstract class IpRestrictAccess implements IMiddleware
{
protected $ipBlacklist = [];
protected $ipWhitelist = [];
protected array $ipBlacklist = [];
protected array $ipWhitelist = [];
protected function validate(string $ip): bool
{
+19 -17
View File
@@ -29,7 +29,7 @@ class Request
* All request-types
* @var string[]
*/
public static $requestTypes = [
public static array $requestTypes = [
self::REQUEST_TYPE_GET,
self::REQUEST_TYPE_POST,
self::REQUEST_TYPE_PUT,
@@ -43,7 +43,7 @@ class Request
* Post request-types.
* @var string[]
*/
public static $requestTypesPost = [
public static array $requestTypesPost = [
self::REQUEST_TYPE_POST,
self::REQUEST_TYPE_PUT,
self::REQUEST_TYPE_PATCH,
@@ -55,65 +55,65 @@ class Request
*
* @var array
*/
private $data = [];
private array $data = [];
/**
* Server headers
* @var array
*/
protected $headers = [];
protected array $headers = [];
/**
* Request ContentType
* @var string
*/
protected $contentType;
protected string $contentType;
/**
* Request host
* @var string
* @var string|null
*/
protected $host;
protected ?string $host;
/**
* Current request url
* @var Url
*/
protected $url;
protected Url $url;
/**
* Request method
* @var string
*/
protected $method;
protected string $method;
/**
* Input handler
* @var InputHandler
*/
protected $inputHandler;
protected InputHandler $inputHandler;
/**
* Defines if request has pending rewrite
* @var bool
*/
protected $hasPendingRewrite = false;
protected bool $hasPendingRewrite = false;
/**
* @var ILoadableRoute|null
*/
protected $rewriteRoute;
protected ?ILoadableRoute $rewriteRoute = null;
/**
* Rewrite url
* @var string|null
*/
protected $rewriteUrl;
protected ?string $rewriteUrl = null;
/**
* @var array
*/
protected $loadedRoutes = [];
protected array $loadedRoutes = [];
/**
* Request constructor.
@@ -224,15 +224,17 @@ class Request
*/
public function getIp(bool $safeMode = false): ?string
{
$headers = ['remote-addr'];
$headers = [];
if($safeMode === false) {
$headers = array_merge($headers, [
$headers = [
'http-cf-connecting-ip',
'http-client-ip',
'http-x-forwarded-for',
]);
];
}
$headers[] = 'remote-addr';
return $this->getFirstHeader($headers);
}
+1 -2
View File
@@ -7,7 +7,7 @@ use Pecee\Exceptions\InvalidArgumentException;
class Response
{
protected $request;
protected Request $request;
public function __construct(Request $request)
{
@@ -65,7 +65,6 @@ class Response
public function cache(string $eTag, int $lastModifiedTime = 2592000): self
{
$this->headers([
'Cache-Control: public',
sprintf('Last-Modified: %s GMT', gmdate('D, d M Y H:i:s', $lastModifiedTime)),
@@ -12,12 +12,12 @@ class CookieTokenProvider implements ITokenProvider
/**
* @var string
*/
protected $token;
protected ?string $token = null;
/**
* @var int
*/
protected $cookieTimeoutMinutes = 120;
protected int $cookieTimeoutMinutes = 120;
/**
* CookieTokenProvider constructor.
+10 -10
View File
@@ -10,53 +10,53 @@ class Url implements JsonSerializable
/**
* @var string|null
*/
private $originalUrl;
private ?string $originalUrl = null;
/**
* @var string|null
*/
private $scheme;
private ?string $scheme = null;
/**
* @var string|null
*/
private $host;
private ?string $host = null;
/**
* @var int|null
*/
private $port;
private ?int $port = null;
/**
* @var string|null
*/
private $username;
private ?string $username = null;
/**
* @var string|null
*/
private $password;
private ?string $password = null;
/**
* @var string|null
*/
private $path;
private ?string $path = null;
/**
* Original path with no sanitization to ending slash
* @var string|null
*/
private $originalPath;
private ?string $originalPath = null;
/**
* @var array
*/
private $params = [];
private array $params = [];
/**
* @var string|null
*/
private $fragment;
private ?string $fragment = null;
/**
* Url constructor.
@@ -27,11 +27,11 @@ class ClassLoader implements IClassLoader
* @param object $class
* @param string $method
* @param array $parameters
* @return object
* @return string
*/
public function loadClassMethod($class, string $method, array $parameters)
public function loadClassMethod($class, string $method, array $parameters): string
{
return call_user_func_array([$class, $method], array_values($parameters));
return (string)call_user_func_array([$class, $method], array_values($parameters));
}
/**
@@ -39,11 +39,11 @@ class ClassLoader implements IClassLoader
*
* @param Callable $closure
* @param array $parameters
* @return mixed
* @return string
*/
public function loadClosure(Callable $closure, array $parameters)
public function loadClosure(callable $closure, array $parameters): string
{
return call_user_func_array($closure, array_values($parameters));
return (string)call_user_func_array($closure, array_values($parameters));
}
}
@@ -17,7 +17,7 @@ interface IClassLoader
* @param object $class
* @param string $method
* @param array $parameters
* @return object
* @return mixed
*/
public function loadClassMethod($class, string $method, array $parameters);
@@ -12,17 +12,17 @@ class EventArgument implements IEventArgument
* Event name
* @var string
*/
protected $eventName;
protected string $eventName;
/**
* @var Router
*/
protected $router;
protected Router $router;
/**
* @var array
*/
protected $arguments = [];
protected array $arguments = [];
public function __construct(string $eventName, Router $router, array $arguments = [])
{
@@ -9,12 +9,12 @@ class ClassNotFoundHttpException extends NotFoundHttpException
/**
* @var string
*/
protected $class;
protected string $class;
/**
* @var string|null
*/
protected $method;
protected ?string $method = null;
public function __construct(string $class, ?string $method = null, string $message = "", int $code = 0, Throwable $previous = null)
{
@@ -20,7 +20,7 @@ class CallbackExceptionHandler implements IExceptionHandler
/**
* @var Closure
*/
protected $callback;
protected Closure $callback;
public function __construct(Closure $callback)
{
@@ -13,7 +13,7 @@ class DebugEventHandler implements IEventHandler
* Debug callback
* @var Closure
*/
protected $callback;
protected Closure $callback;
public function __construct()
{
@@ -97,7 +97,7 @@ class EventHandler implements IEventHandler
* All available events
* @var array
*/
public static $events = [
public static array $events = [
self::EVENT_ALL,
self::EVENT_INIT,
self::EVENT_LOAD,
@@ -120,7 +120,7 @@ class EventHandler implements IEventHandler
* List of all registered events
* @var array
*/
private $registeredEvents = [];
private array $registeredEvents = [];
/**
* Register new event
@@ -12,17 +12,17 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
/**
* @var string
*/
protected $url;
protected string $url;
/**
* @var string
*/
protected $name;
protected ?string $name = null;
/**
* @var string|null
*/
protected $regex;
protected ?string $regex = null;
/**
* Loads and renders middlewares-classes
@@ -82,15 +82,18 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
{
$this->url = ($url === '/') ? '/' : '/' . trim($url, '/') . '/';
$parameters = [];
if (strpos($this->url, $this->paramModifiers[0]) !== false) {
$regex = sprintf(static::PARAMETERS_REGEX_FORMAT, $this->paramModifiers[0], $this->paramOptionalSymbol, $this->paramModifiers[1]);
if ((bool)preg_match_all('/' . $regex . '/u', $this->url, $matches) !== false) {
$this->parameters = array_fill_keys($matches[1], null);
$parameters = array_fill_keys($matches[1], null);
}
}
$this->parameters = $parameters;
return $this;
}
@@ -195,7 +198,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
*/
public function hasName(string $name): bool
{
return strtolower((string)$this->name) === strtolower((string)$name);
return strtolower((string)$this->name) === strtolower($name);
}
/**
+15 -15
View File
@@ -18,37 +18,37 @@ abstract class Route implements IRoute
*
* @var bool
*/
protected $filterEmptyParams = true;
protected bool $filterEmptyParams = true;
/**
* If true the last parameter of the route will include ending trail/slash.
* @var bool
*/
protected $slashParameterEnabled = false;
protected bool $slashParameterEnabled = false;
/**
* Default regular expression used for parsing parameters.
* @var string|null
*/
protected $defaultParameterRegex;
protected $paramModifiers = '{}';
protected $paramOptionalSymbol = '?';
protected $urlRegex = '/^%s\/?$/u';
protected $group;
protected $parent;
protected ?string $defaultParameterRegex = null;
protected string $paramModifiers = '{}';
protected string $paramOptionalSymbol = '?';
protected string $urlRegex = '/^%s\/?$/u';
protected ?IGroupRoute $group = null;
protected ?IRoute $parent = null;
/**
* @var string|callable|null
*/
protected $callback;
protected $defaultNamespace;
protected ?string $defaultNamespace = null;
/* Default options */
protected $namespace;
protected $requestMethods = [];
protected $where = [];
protected $parameters = [];
protected $originalParameters = [];
protected $middlewares = [];
protected ?string $namespace = null;
protected array $requestMethods = [];
protected array $where = [];
protected array $parameters = [];
protected array $originalParameters = [];
protected array $middlewares = [];
/**
* Render route
@@ -6,10 +6,10 @@ use Pecee\Http\Request;
class RouteController extends LoadableRoute implements IControllerRoute
{
protected $defaultMethod = 'index';
protected $controller;
protected $method;
protected $names = [];
protected string $defaultMethod = 'index';
protected string $controller;
protected ?string $method = null;
protected array $names = [];
public function __construct($url, $controller)
{
+7 -7
View File
@@ -7,12 +7,12 @@ use Pecee\SimpleRouter\Handlers\IExceptionHandler;
class RouteGroup extends Route implements IGroupRoute
{
protected $urlRegex = '/^%s\/?/u';
protected $prefix;
protected $name;
protected $domains = [];
protected $exceptionHandlers = [];
protected $mergeExceptionHandlers = true;
protected string $urlRegex = '/^%s\/?/u';
protected ?string $prefix = null;
protected ?string $name = null;
protected array $domains = [];
protected array $exceptionHandlers = [];
protected bool $mergeExceptionHandlers = true;
/**
* Method called to check if a domain matches
@@ -22,7 +22,7 @@ class RouteGroup extends Route implements IGroupRoute
*/
public function matchDomain(Request $request): bool
{
if ($this->domains === null || count($this->domains) === 0) {
if (count($this->domains) === 0) {
return true;
}
+32 -25
View File
@@ -6,28 +6,28 @@ use Pecee\Http\Request;
class RouteResource extends LoadableRoute implements IControllerRoute
{
protected $urls = [
'index' => '',
'create' => 'create',
'store' => '',
'show' => '',
'edit' => 'edit',
'update' => '',
protected array $urls = [
'index' => '',
'create' => 'create',
'store' => '',
'show' => '',
'edit' => 'edit',
'update' => '',
'destroy' => '',
];
protected $methodNames = [
'index' => 'index',
'create' => 'create',
'store' => 'store',
'show' => 'show',
'edit' => 'edit',
'update' => 'update',
protected array $methodNames = [
'index' => 'index',
'create' => 'create',
'store' => 'store',
'show' => 'show',
'edit' => 'edit',
'update' => 'update',
'destroy' => 'destroy',
];
protected $names = [];
protected $controller;
protected array $names = [];
protected string $controller;
public function __construct($url, $controller)
{
@@ -69,11 +69,18 @@ class RouteResource extends LoadableRoute implements IControllerRoute
public function findUrl(?string $method = null, $parameters = null, ?string $name = null): string
{
$url = array_search($name, $this->names, true);
if ($url !== false) {
return rtrim($this->url . $this->urls[$url], '/') . '/';
$parametersUrl = '';
if ($parameters !== null && count($parameters) > 0) {
$parametersUrl = join('/', $parameters) . '/';
}
return $this->url;
if ($url !== false) {
return rtrim($this->url . $parametersUrl . $this->urls[$url], '/') . '/';
}
return $this->url . $parametersUrl;
}
protected function call($method): bool
@@ -172,12 +179,12 @@ class RouteResource extends LoadableRoute implements IControllerRoute
$this->name = $name;
$this->names = [
'index' => $this->name . '.index',
'create' => $this->name . '.create',
'store' => $this->name . '.store',
'show' => $this->name . '.show',
'edit' => $this->name . '.edit',
'update' => $this->name . '.update',
'index' => $this->name . '.index',
'create' => $this->name . '.create',
'store' => $this->name . '.store',
'show' => $this->name . '.show',
'edit' => $this->name . '.edit',
'update' => $this->name . '.update',
'destroy' => $this->name . '.destroy',
];
+36 -36
View File
@@ -28,56 +28,56 @@ class Router
* Current request
* @var Request
*/
protected $request;
protected Request $request;
/**
* Defines if a route is currently being processed.
* @var bool
*/
protected $isProcessingRoute;
protected bool $isProcessingRoute;
/**
* Defines all data from current processing route.
* @var ILoadableRoute
*/
protected $currentProcessingRoute;
protected ILoadableRoute $currentProcessingRoute;
/**
* All added routes
* @var array
*/
protected $routes = [];
protected array $routes = [];
/**
* List of processed routes
* @var array|ILoadableRoute[]
*/
protected $processedRoutes = [];
protected array $processedRoutes = [];
/**
* Stack of routes used to keep track of sub-routes added
* when a route is being processed.
* @var array
*/
protected $routeStack = [];
protected array $routeStack = [];
/**
* List of added bootmanagers
* @var array
*/
protected $bootManagers = [];
protected array $bootManagers = [];
/**
* Csrf verifier class
* @var BaseCsrfVerifier|null
*/
protected $csrfVerifier;
protected ?BaseCsrfVerifier $csrfVerifier;
/**
* Get exception handlers
* @var array
*/
protected $exceptionHandlers = [];
protected array $exceptionHandlers = [];
/**
* List of loaded exception that has been loaded.
@@ -85,44 +85,44 @@ class Router
*
* @var array
*/
protected $loadedExceptionHandlers = [];
protected array $loadedExceptionHandlers = [];
/**
* Enable or disabled debugging
* @var bool
*/
protected $debugEnabled = false;
protected bool $debugEnabled = false;
/**
* The start time used when debugging is enabled
* @var float
*/
protected $debugStartTime;
protected float $debugStartTime;
/**
* List containing all debug messages
* @var array
*/
protected $debugList = [];
protected array $debugList = [];
/**
* Contains any registered event-handler.
* @var array
*/
protected $eventHandlers = [];
protected array $eventHandlers = [];
/**
* Class loader instance
* @var IClassLoader
*/
protected $classLoader;
protected IClassLoader $classLoader;
/**
* When enabled the router will render all routes that matches.
* When disabled the router will stop execution when first route is found.
* @var bool
*/
protected $renderMultipleRoutes = true;
protected bool $renderMultipleRoutes = false;
/**
* Router constructor.
@@ -166,7 +166,7 @@ class Router
public function addRoute(IRoute $route): IRoute
{
$this->fireEvents(EventHandler::EVENT_ADD_ROUTE, [
'route' => $route,
'route' => $route,
'isSubRoute' => $this->isProcessingRoute,
]);
@@ -307,7 +307,7 @@ class Router
$this->debug('Rendering bootmanager "%s"', $className);
$this->fireEvents(EventHandler::EVENT_RENDER_BOOTMANAGER, [
'bootmanagers' => $this->bootManagers,
'bootmanager' => $manager,
'bootmanager' => $manager,
]);
/* Render bootmanager */
@@ -345,8 +345,8 @@ class Router
try {
/* Verify csrf token for request */
$this->csrfVerifier->handle($this->request);
} catch(\Exception $e) {
$this->handleException($e);
} catch (Exception $e) {
return $this->handleException($e);
}
}
@@ -381,7 +381,7 @@ class Router
foreach ($this->processedRoutes as $key => $route) {
$this->debug('Matching route "%s"', get_class($route));
/* Add current processing route to constants */
$this->currentProcessingRoute = $route;
@@ -405,7 +405,7 @@ class Router
}
$this->fireEvents(EventHandler::EVENT_RENDER_MIDDLEWARES, [
'route' => $route,
'route' => $route,
'middlewares' => $route->getMiddlewares(),
]);
@@ -427,7 +427,7 @@ class Router
$routeOutput = $route->renderRoute($this->request, $this);
if ($this->renderMultipleRoutes === true) {
if ($routeOutput !== null) {
if ($routeOutput !== '') {
return $routeOutput;
}
@@ -444,12 +444,12 @@ class Router
}
} catch (Exception $e) {
$this->handleException($e);
return $this->handleException($e);
}
if ($methodNotAllowed === true) {
$message = sprintf('Route "%s" or method "%s" not allowed.', $this->request->getUrl()->getPath(), $this->request->getMethod());
$this->handleException(new NotFoundHttpException($message, 403));
return $this->handleException(new NotFoundHttpException($message, 403));
}
if (count($this->request->getLoadedRoutes()) === 0) {
@@ -500,7 +500,7 @@ class Router
$this->request->setHasPendingRewrite(false);
$this->fireEvents(EventHandler::EVENT_REWRITE, [
'rewriteUrl' => $this->request->getRewriteUrl(),
'rewriteUrl' => $this->request->getRewriteUrl(),
'rewriteRoute' => $this->request->getRewriteRoute(),
]);
@@ -521,7 +521,7 @@ class Router
$this->debug('Starting exception handling for "%s"', get_class($e));
$this->fireEvents(EventHandler::EVENT_LOAD_EXCEPTIONS, [
'exception' => $e,
'exception' => $e,
'exceptionHandlers' => $this->exceptionHandlers,
]);
@@ -533,8 +533,8 @@ class Router
}
$this->fireEvents(EventHandler::EVENT_RENDER_EXCEPTION, [
'exception' => $e,
'exceptionHandler' => $handler,
'exception' => $e,
'exceptionHandler' => $handler,
'exceptionHandlers' => $this->exceptionHandlers,
]);
@@ -556,7 +556,7 @@ class Router
$this->debug('Exception handler contains rewrite, reloading routes');
$this->fireEvents(EventHandler::EVENT_REWRITE, [
'rewriteUrl' => $this->request->getRewriteUrl(),
'rewriteUrl' => $this->request->getRewriteUrl(),
'rewriteRoute' => $this->request->getRewriteRoute(),
]);
@@ -667,9 +667,9 @@ class Router
$this->debug('Finding url', func_get_args());
$this->fireEvents(EventHandler::EVENT_GET_URL, [
'name' => $name,
'name' => $name,
'parameters' => $parameters,
'getParams' => $getParams,
'getParams' => $getParams,
]);
if ($name === '' && $parameters === '') {
@@ -913,8 +913,8 @@ class Router
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
$this->debugList[] = [
'message' => vsprintf($message, $args),
'time' => number_format(microtime(true) - $this->debugStartTime, 10),
'trace' => end($trace),
'time' => number_format(microtime(true) - $this->debugStartTime, 10),
'trace' => end($trace),
];
}
@@ -940,7 +940,7 @@ class Router
{
return $this->debugList;
}
/**
* Get the current processing route details.
*
+5 -5
View File
@@ -37,19 +37,19 @@ class SimpleRouter
* Default namespace added to all routes
* @var string|null
*/
protected static $defaultNamespace;
protected static ?string $defaultNamespace = null;
/**
* The response object
* @var Response
* @var Response|null
*/
protected static $response;
protected static ?Response $response = null;
/**
* Router instance
* @var Router
*/
protected static $router;
protected static ?Router $router = null;
/**
* Start routing
@@ -493,7 +493,7 @@ class SimpleRouter
* Prepends the default namespace to all new routes added.
*
* @param ILoadableRoute|IRoute $route
* @return IRoute
* @return IRoute|ILoadableRoute
*/
public static function addDefaultNamespace(IRoute $route): IRoute
{
@@ -2,12 +2,12 @@
class DummyCsrfVerifier extends \Pecee\Http\Middleware\BaseCsrfVerifier {
protected $except = [
protected array $except = [
'/exclude-page',
'/exclude-all/*',
];
protected $include = [
protected array $include = [
'/exclude-all/include-page',
];
@@ -2,12 +2,12 @@
class IpRestrictMiddleware extends \Pecee\Http\Middleware\IpRestrictAccess {
protected $ipBlacklist = [
protected array $ipBlacklist = [
'5.5.5.5',
'8.8.*',
];
protected $ipWhitelist = [
protected array $ipWhitelist = [
'8.8.2.2',
];
@@ -0,0 +1,11 @@
<?php
use Pecee\Http\Request;
class DummyLoadableRoute extends Pecee\SimpleRouter\Route\LoadableRoute {
public function matchRoute(string $url, Request $request): bool
{
return false;
}
}
@@ -0,0 +1,27 @@
<?php
require_once 'Dummy/Route/DummyLoadableRoute.php';
class LoadableRouteTest extends \PHPUnit\Framework\TestCase
{
public function testSetUrlUpdatesParameters()
{
$route = new DummyLoadableRoute();
$this->assertEmpty($route->getParameters());
$route->setUrl('/');
$this->assertEmpty($route->getParameters());
$expected = ['param' => null, 'optionalParam' => null];
$route->setUrl('/{param}/{optionalParam?}');
$this->assertEquals($expected, $route->getParameters());
$expected = ['otherParam' => null];
$route->setUrl('/{otherParam}');
$this->assertEquals($expected, $route->getParameters());
$expected = [];
$route->setUrl('/');
$this->assertEquals($expected, $route->getParameters());
}
}
@@ -63,7 +63,22 @@ class RouterResourceTest extends \PHPUnit\Framework\TestCase
$response = TestRouter::debugOutput('/resource/38', 'get');
$this->assertEquals('show 38', $response);
}
public function testResourceUrls()
{
TestRouter::resource('/resource', 'ResourceController')->name('resource');
TestRouter::debugNoReset('/resource');
$this->assertEquals('/resource/3/create/', TestRouter::router()->getUrl('resource.create', ['id' => 3]));
$this->assertEquals('/resource/5/edit/', TestRouter::router()->getUrl('resource.edit', ['id' => 5]));
$this->assertEquals('/resource/6/', TestRouter::router()->getUrl('resource.update', ['id' => 6]));
$this->assertEquals('/resource/9/', TestRouter::router()->getUrl('resource.destroy', ['id' => 9]));
$this->assertEquals('/resource/12/', TestRouter::router()->getUrl('resource.delete', ['id' => 12]));
$this->assertEquals('/resource/', TestRouter::router()->getUrl('resource'));
TestRouter::router()->reset();
}
}
+1 -1
View File
@@ -184,7 +184,7 @@ class RouterUrlTest extends \PHPUnit\Framework\TestCase
// Should match /?jackdaniels=true&cola=yeah
$this->assertEquals('/?jackdaniels=true&cola=yeah', TestRouter::getUrl('home', null, ['jackdaniels' => 'true', 'cola' => 'yeah']));
TestRouter::router()->reset();
TestRouter::reset();
}
+5
View File
@@ -8,6 +8,11 @@ class TestRouter extends \Pecee\SimpleRouter\SimpleRouter
static::request()->setHost('testhost.com');
}
public static function reset(): void
{
static::$router = null;
}
public static function debugNoReset(string $testUrl, string $testMethod = 'get'): void
{
$request = static::request();