mirror of
https://github.com/skipperbent/simple-php-router.git
synced 2026-06-17 00:37:52 +00:00
Development
- Better php7 support. - Added easier way to debug router. - Improvements and bugfixes. - Updated documentation.
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\Exceptions;
|
||||
|
||||
class InvalidArgumentException extends \InvalidArgumentException {
|
||||
class InvalidArgumentException extends \InvalidArgumentException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -7,15 +7,15 @@ interface IInputItem
|
||||
|
||||
public function getIndex(): string;
|
||||
|
||||
public function setIndex($index): self;
|
||||
public function setIndex(string $index): self;
|
||||
|
||||
public function getName(): string;
|
||||
|
||||
public function setName($name): self;
|
||||
public function setName(string $name): self;
|
||||
|
||||
public function getValue(): string;
|
||||
|
||||
public function setValue($value): self;
|
||||
public function setValue(string $value): self;
|
||||
|
||||
public function __toString();
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ class InputFile implements IInputItem
|
||||
public $errors;
|
||||
public $tmpName;
|
||||
|
||||
public function __construct($index)
|
||||
public function __construct(string $index)
|
||||
{
|
||||
$this->index = $index;
|
||||
|
||||
@@ -48,7 +48,7 @@ class InputFile implements IInputItem
|
||||
];
|
||||
|
||||
return (new static($values['index']))
|
||||
->setSize($values['size'])
|
||||
->setSize((int)$values['size'])
|
||||
->setError($values['error'])
|
||||
->setType($values['type'])
|
||||
->setTmpName($values['tmp_name'])
|
||||
@@ -69,7 +69,7 @@ class InputFile implements IInputItem
|
||||
* @param string $index
|
||||
* @return static
|
||||
*/
|
||||
public function setIndex($index): IInputItem
|
||||
public function setIndex(string $index): IInputItem
|
||||
{
|
||||
$this->index = $index;
|
||||
|
||||
@@ -89,7 +89,7 @@ class InputFile implements IInputItem
|
||||
* @param int $size
|
||||
* @return static
|
||||
*/
|
||||
public function setSize($size): IInputItem
|
||||
public function setSize(int $size): IInputItem
|
||||
{
|
||||
$this->size = $size;
|
||||
|
||||
@@ -118,7 +118,7 @@ class InputFile implements IInputItem
|
||||
* @param string $type
|
||||
* @return static
|
||||
*/
|
||||
public function setType($type): IInputItem
|
||||
public function setType(string $type): IInputItem
|
||||
{
|
||||
$this->type = $type;
|
||||
|
||||
@@ -152,7 +152,7 @@ class InputFile implements IInputItem
|
||||
* @param string $name
|
||||
* @return static
|
||||
*/
|
||||
public function setName($name): IInputItem
|
||||
public function setName(string $name): IInputItem
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
@@ -270,7 +270,7 @@ class InputFile implements IInputItem
|
||||
* @param string $value
|
||||
* @return static
|
||||
*/
|
||||
public function setValue($value): IInputItem
|
||||
public function setValue(string $value): IInputItem
|
||||
{
|
||||
$this->filename = $value;
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ class InputHandler
|
||||
* Parse input values
|
||||
*
|
||||
*/
|
||||
public function parseInputs() : void
|
||||
public function parseInputs(): void
|
||||
{
|
||||
/* Parse get requests */
|
||||
if (\count($_GET) !== 0) {
|
||||
@@ -69,7 +69,7 @@ class InputHandler
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function parseFiles() : array
|
||||
public function parseFiles(): array
|
||||
{
|
||||
$list = [];
|
||||
|
||||
@@ -80,7 +80,7 @@ class InputHandler
|
||||
$values['index'] = $key;
|
||||
try {
|
||||
$list[$key] = InputFile::createFromArray($values + $value);
|
||||
} catch(InvalidArgumentException $e ){
|
||||
} catch (InvalidArgumentException $e) {
|
||||
|
||||
}
|
||||
continue;
|
||||
@@ -101,7 +101,7 @@ class InputHandler
|
||||
return $list;
|
||||
}
|
||||
|
||||
protected function rearrangeFiles(array $values, &$index, $original) : array
|
||||
protected function rearrangeFiles(array $values, &$index, $original): array
|
||||
{
|
||||
|
||||
$originalIndex = $index[0];
|
||||
@@ -132,7 +132,7 @@ class InputHandler
|
||||
$output[$key] = $file;
|
||||
continue;
|
||||
|
||||
} catch(InvalidArgumentException $e) {
|
||||
} catch (InvalidArgumentException $e) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -152,7 +152,7 @@ class InputHandler
|
||||
return $output;
|
||||
}
|
||||
|
||||
protected function handleGetPost(array $array) : array
|
||||
protected function handleGetPost(array $array): array
|
||||
{
|
||||
$list = [];
|
||||
|
||||
@@ -179,7 +179,7 @@ class InputHandler
|
||||
* @param string|null $defaultValue
|
||||
* @return InputItem|string
|
||||
*/
|
||||
public function findPost($index, $defaultValue = null)
|
||||
public function findPost(string $index, ?string $defaultValue = null)
|
||||
{
|
||||
return $this->post[$index] ?? $defaultValue;
|
||||
}
|
||||
@@ -191,7 +191,7 @@ class InputHandler
|
||||
* @param string|null $defaultValue
|
||||
* @return InputFile|string
|
||||
*/
|
||||
public function findFile($index, $defaultValue = null)
|
||||
public function findFile(string $index, ?string $defaultValue = null)
|
||||
{
|
||||
return $this->file[$index] ?? $defaultValue;
|
||||
}
|
||||
@@ -203,7 +203,7 @@ class InputHandler
|
||||
* @param string|null $defaultValue
|
||||
* @return InputItem|string
|
||||
*/
|
||||
public function findGet($index, $defaultValue = null)
|
||||
public function findGet(string $index, ?string $defaultValue = null)
|
||||
{
|
||||
return $this->get[$index] ?? $defaultValue;
|
||||
}
|
||||
@@ -216,7 +216,7 @@ class InputHandler
|
||||
* @param array|string|null $methods
|
||||
* @return IInputItem|string
|
||||
*/
|
||||
public function getObject($index, $defaultValue = null, $methods = null)
|
||||
public function getObject(string $index, ?string $defaultValue = null, $methods = null)
|
||||
{
|
||||
if ($methods !== null && \is_string($methods) === true) {
|
||||
$methods = [$methods];
|
||||
@@ -247,7 +247,7 @@ class InputHandler
|
||||
* @param array|string|null $methods
|
||||
* @return InputItem|string
|
||||
*/
|
||||
public function get($index, $defaultValue = null, $methods = null)
|
||||
public function get(string $index, ?string $defaultValue = null, $methods = null)
|
||||
{
|
||||
$input = $this->getObject($index, $defaultValue, $methods);
|
||||
|
||||
@@ -264,7 +264,7 @@ class InputHandler
|
||||
* @param string $index
|
||||
* @return bool
|
||||
*/
|
||||
public function exists($index) : bool
|
||||
public function exists(string $index): bool
|
||||
{
|
||||
return ($this->getObject($index) !== null);
|
||||
}
|
||||
@@ -274,7 +274,7 @@ class InputHandler
|
||||
* @param array|null $filter Only take items in filter
|
||||
* @return array
|
||||
*/
|
||||
public function all(array $filter = null) : array
|
||||
public function all(array $filter = null): array
|
||||
{
|
||||
$output = $_GET + $_POST;
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ class InputItem implements IInputItem
|
||||
public $name;
|
||||
public $value;
|
||||
|
||||
public function __construct($index, $value = null)
|
||||
public function __construct(string $index, ?string $value = null)
|
||||
{
|
||||
$this->index = $index;
|
||||
$this->value = $value;
|
||||
@@ -25,7 +25,7 @@ class InputItem implements IInputItem
|
||||
return $this->index;
|
||||
}
|
||||
|
||||
public function setIndex($index): IInputItem
|
||||
public function setIndex(string $index): IInputItem
|
||||
{
|
||||
$this->index = $index;
|
||||
|
||||
@@ -43,9 +43,9 @@ class InputItem implements IInputItem
|
||||
/**
|
||||
* Set input name
|
||||
* @param string $name
|
||||
* @return static $this
|
||||
* @return static
|
||||
*/
|
||||
public function setName($name): IInputItem
|
||||
public function setName(string $name): IInputItem
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
@@ -63,9 +63,9 @@ class InputItem implements IInputItem
|
||||
/**
|
||||
* Set input value
|
||||
* @param string $value
|
||||
* @return static $this
|
||||
* @return static
|
||||
*/
|
||||
public function setValue($value): IInputItem
|
||||
public function setValue(string $value): IInputItem
|
||||
{
|
||||
$this->value = $value;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\Http\Middleware\Exceptions;
|
||||
|
||||
class TokenMismatchException extends \Exception
|
||||
|
||||
+23
-24
@@ -10,7 +10,7 @@ use Pecee\SimpleRouter\SimpleRouter;
|
||||
class Request
|
||||
{
|
||||
private $data = [];
|
||||
protected $headers;
|
||||
protected $headers = [];
|
||||
protected $host;
|
||||
protected $url;
|
||||
protected $method;
|
||||
@@ -35,7 +35,11 @@ class Request
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->parseHeaders();
|
||||
foreach ($_SERVER as $key => $value) {
|
||||
$this->headers[strtolower($key)] = $value;
|
||||
$this->headers[strtolower(str_replace('_', '-', $key))] = $value;
|
||||
}
|
||||
|
||||
$this->setHost($this->getHeader('http-host'));
|
||||
|
||||
// Check if special IIS header exist, otherwise use default.
|
||||
@@ -45,17 +49,6 @@ class Request
|
||||
$this->method = strtolower($this->inputHandler->get('_method', $this->getHeader('request-method')));
|
||||
}
|
||||
|
||||
protected function parseHeaders(): void
|
||||
{
|
||||
$this->headers = [];
|
||||
|
||||
foreach ($_SERVER as $key => $value) {
|
||||
$this->headers[strtolower($key)] = $value;
|
||||
$this->headers[strtolower(str_replace('_', '-', $key))] = $value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function isSecure(): bool
|
||||
{
|
||||
return $this->getHeader('http-x-forwarded-proto') === 'https' || $this->getHeader('https') !== null || $this->getHeader('server-port') === 443;
|
||||
@@ -221,9 +214,9 @@ class Request
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $host
|
||||
* @param string|null $host
|
||||
*/
|
||||
public function setHost($host): void
|
||||
public function setHost(?string $host): void
|
||||
{
|
||||
$this->host = $host;
|
||||
}
|
||||
@@ -231,7 +224,7 @@ class Request
|
||||
/**
|
||||
* @param string $method
|
||||
*/
|
||||
public function setMethod($method): void
|
||||
public function setMethod(string $method): void
|
||||
{
|
||||
$this->method = $method;
|
||||
}
|
||||
@@ -341,26 +334,32 @@ class Request
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the request contains a rewrite
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasRewrite(): bool
|
||||
{
|
||||
return $this->hasRewrite;
|
||||
}
|
||||
|
||||
public function setHasRewrite($value): self
|
||||
/**
|
||||
* Defines if the current request contains a rewrite.
|
||||
*
|
||||
* @param bool $boolean
|
||||
* @return Request
|
||||
*/
|
||||
public function setHasRewrite(bool $boolean): self
|
||||
{
|
||||
$this->hasRewrite = $value;
|
||||
$this->hasRewrite = $boolean;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isRewrite($url): bool
|
||||
{
|
||||
return ($this->rewriteUrl === $url);
|
||||
}
|
||||
|
||||
public function __isset($name)
|
||||
{
|
||||
return array_key_exists($name, $this->data);
|
||||
return array_key_exists($name, $this->data) === true;
|
||||
}
|
||||
|
||||
public function __set($name, $value = null)
|
||||
|
||||
@@ -19,7 +19,7 @@ class Response
|
||||
* @param int $code
|
||||
* @return static
|
||||
*/
|
||||
public function httpCode($code): self
|
||||
public function httpCode(int $code): self
|
||||
{
|
||||
http_response_code($code);
|
||||
|
||||
@@ -32,7 +32,7 @@ class Response
|
||||
* @param string $url
|
||||
* @param int $httpCode
|
||||
*/
|
||||
public function redirect($url, $httpCode = null): void
|
||||
public function redirect(string $url, ?int $httpCode = null): void
|
||||
{
|
||||
if ($httpCode !== null) {
|
||||
$this->httpCode($httpCode);
|
||||
@@ -52,7 +52,7 @@ class Response
|
||||
* @param string $name
|
||||
* @return static
|
||||
*/
|
||||
public function auth($name = ''): self
|
||||
public function auth(string $name = ''): self
|
||||
{
|
||||
$this->headers([
|
||||
'WWW-Authenticate: Basic realm="' . $name . '"',
|
||||
@@ -62,19 +62,19 @@ class Response
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function cache($eTag, $lastModified = 2592000): self
|
||||
public function cache(string $eTag, int $lastModifiedTime = 2592000): self
|
||||
{
|
||||
|
||||
$this->headers([
|
||||
'Cache-Control: public',
|
||||
'Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastModified) . ' GMT',
|
||||
'Etag: ' . $eTag,
|
||||
sprintf('Last-Modified: %s GMT', gmdate('D, d M Y H:i:s', $lastModifiedTime)),
|
||||
sprintf('Etag: %s', $eTag),
|
||||
]);
|
||||
|
||||
$httpModified = $this->request->getHeader('http-if-modified-since');
|
||||
$httpIfNoneMatch = $this->request->getHeader('http-if-none-match');
|
||||
|
||||
if (($httpIfNoneMatch !== null && $httpIfNoneMatch === $eTag) || ($httpModified !== null && strtotime($httpModified) === $lastModified)) {
|
||||
if (($httpIfNoneMatch !== null && $httpIfNoneMatch === $eTag) || ($httpModified !== null && strtotime($httpModified) === $lastModifiedTime)) {
|
||||
|
||||
$this->header('HTTP/1.1 304 Not Modified');
|
||||
exit(0);
|
||||
@@ -90,7 +90,7 @@ class Response
|
||||
* @param int $dept JSON debt.
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function json($value, $options = null, $dept = 512): void
|
||||
public function json($value, ?int $options = null, int $dept = 512): void
|
||||
{
|
||||
if (($value instanceof \JsonSerializable) === false && \is_array($value) === false) {
|
||||
throw new InvalidArgumentException('Invalid type for parameter "value". Must be of type array or object implementing the \JsonSerializable interface.');
|
||||
@@ -106,7 +106,7 @@ class Response
|
||||
* @param string $value
|
||||
* @return static
|
||||
*/
|
||||
public function header($value): self
|
||||
public function header(string $value): self
|
||||
{
|
||||
header($value);
|
||||
|
||||
|
||||
@@ -45,9 +45,9 @@ class CookieTokenProvider implements ITokenProvider
|
||||
* @param string $token
|
||||
* @return bool
|
||||
*/
|
||||
public function validate($token): bool
|
||||
public function validate(string $token): bool
|
||||
{
|
||||
if ($token !== null && $this->getToken() !== null) {
|
||||
if ($this->getToken() !== null) {
|
||||
return hash_equals($token, $this->getToken());
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ class CookieTokenProvider implements ITokenProvider
|
||||
*
|
||||
* @param string $token
|
||||
*/
|
||||
public function setToken($token): void
|
||||
public function setToken(string $token): void
|
||||
{
|
||||
$this->token = $token;
|
||||
setcookie(static::CSRF_KEY, $token, time() + 60 * $this->cookieTimeoutMinutes, '/');
|
||||
@@ -71,7 +71,7 @@ class CookieTokenProvider implements ITokenProvider
|
||||
* @param string|null $defaultValue
|
||||
* @return string|null
|
||||
*/
|
||||
public function getToken($defaultValue = null): ?string
|
||||
public function getToken(?string $defaultValue = null): ?string
|
||||
{
|
||||
$this->token = ($this->hasToken() === true) ? $_COOKIE[static::CSRF_KEY] : null;
|
||||
|
||||
@@ -108,9 +108,9 @@ class CookieTokenProvider implements ITokenProvider
|
||||
|
||||
/**
|
||||
* Set cookie timeout in minutes
|
||||
* @param $minutes
|
||||
* @param int $minutes
|
||||
*/
|
||||
public function setCookieTimeoutMinutes($minutes): void
|
||||
public function setCookieTimeoutMinutes(int $minutes): void
|
||||
{
|
||||
$this->cookieTimeoutMinutes = $minutes;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\Http\Security\Exceptions;
|
||||
|
||||
class SecurityException extends \Exception {
|
||||
class SecurityException extends \Exception
|
||||
{
|
||||
|
||||
}
|
||||
@@ -16,7 +16,7 @@ interface ITokenProvider
|
||||
* @param string $token
|
||||
* @return bool
|
||||
*/
|
||||
public function validate($token): bool;
|
||||
public function validate(string $token): bool;
|
||||
|
||||
/**
|
||||
* Get token token
|
||||
@@ -24,6 +24,6 @@ interface ITokenProvider
|
||||
* @param string|null $defaultValue
|
||||
* @return string|null
|
||||
*/
|
||||
public function getToken($defaultValue = null);
|
||||
public function getToken(?string $defaultValue = null): ?string;
|
||||
|
||||
}
|
||||
+30
-9
@@ -23,15 +23,16 @@ class Url
|
||||
* @param string $url
|
||||
* @throws MalformedUrlException
|
||||
*/
|
||||
public function __construct($url)
|
||||
public function __construct(?string $url)
|
||||
{
|
||||
$this->originalUrl = $url;
|
||||
$this->data = $this->parseUrl($url) + $this->data;
|
||||
if ($url !== null) {
|
||||
$this->data = $this->parseUrl($url) + $this->data;
|
||||
|
||||
if (isset($this->data['path']) === true && $this->data['path'] !== '/') {
|
||||
$this->data['path'] = rtrim($this->data['path'], '/') . '/';
|
||||
if (isset($this->data['path']) === true && $this->data['path'] !== '/') {
|
||||
$this->data['path'] = rtrim($this->data['path'], '/') . '/';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,7 +104,7 @@ class Url
|
||||
*/
|
||||
public function getPath(): ?string
|
||||
{
|
||||
return $this->data['path'];
|
||||
return $this->data['path'] ?? '/';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,7 +140,7 @@ class Url
|
||||
* @throws MalformedUrlException
|
||||
* @return array
|
||||
*/
|
||||
public function parseUrl($url, $component = -1): array
|
||||
public function parseUrl(string $url, int $component = -1): array
|
||||
{
|
||||
$encodedUrl = preg_replace_callback(
|
||||
'/[^:\/@?&=#]+/u',
|
||||
@@ -158,9 +159,29 @@ class Url
|
||||
return array_map('urldecode', $parts);
|
||||
}
|
||||
|
||||
public function contains($value): bool
|
||||
/**
|
||||
* Get position of value.
|
||||
* Returns -1 on failure.
|
||||
*
|
||||
* @param string $value
|
||||
* @return int
|
||||
*/
|
||||
public function indexOf(string $value): int
|
||||
{
|
||||
return (stripos($this->getOriginalUrl(), $value) === false);
|
||||
$index = stripos($this->getOriginalUrl(), $value);
|
||||
|
||||
return ($index === false) ? -1 : $index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if url contains value.
|
||||
*
|
||||
* @param string $value
|
||||
* @return bool
|
||||
*/
|
||||
public function contains(string $value): bool
|
||||
{
|
||||
return (stripos($this->getOriginalUrl(), $value) !== false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\SimpleRouter\Exceptions;
|
||||
|
||||
class HttpException extends \Exception
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\SimpleRouter\Exceptions;
|
||||
|
||||
class NotFoundHttpException extends HttpException
|
||||
|
||||
@@ -17,6 +17,6 @@ interface IControllerRoute extends IRoute
|
||||
* @param string $controller
|
||||
* @return static
|
||||
*/
|
||||
public function setController($controller): self;
|
||||
public function setController(string $controller): self;
|
||||
|
||||
}
|
||||
@@ -19,15 +19,15 @@ interface IGroupRoute extends IRoute
|
||||
* Add exception handler
|
||||
*
|
||||
* @param IExceptionHandler|string $handler
|
||||
* @return static $this;
|
||||
* @return static
|
||||
*/
|
||||
public function addExceptionHandler($handler);
|
||||
public function addExceptionHandler($handler): self;
|
||||
|
||||
/**
|
||||
* Set exception-handlers for group
|
||||
*
|
||||
* @param array $handlers
|
||||
* @return static $this
|
||||
* @return static
|
||||
*/
|
||||
public function setExceptionHandlers(array $handlers);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Pecee\SimpleRouter\Route;
|
||||
|
||||
use Pecee\Http\Request;
|
||||
use Pecee\SimpleRouter\Router;
|
||||
|
||||
interface ILoadableRoute extends IRoute
|
||||
{
|
||||
@@ -18,22 +19,32 @@ interface ILoadableRoute extends IRoute
|
||||
public function findUrl($method = null, $parameters = null, $name = null): string;
|
||||
|
||||
/**
|
||||
* Loads and renders middlewares-classes
|
||||
* Loads and renders middleware-classes
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Router $router
|
||||
*/
|
||||
public function loadMiddleware(Request $request);
|
||||
public function loadMiddleware(Request $request, Router $router): void;
|
||||
|
||||
public function getUrl();
|
||||
/**
|
||||
* Get url
|
||||
* @return string
|
||||
*/
|
||||
public function getUrl(): string;
|
||||
|
||||
public function setUrl($url);
|
||||
/**
|
||||
* Set url
|
||||
* @param string $url
|
||||
* @return static
|
||||
*/
|
||||
public function setUrl(string $url): self;
|
||||
|
||||
/**
|
||||
* Returns the provided name for the router.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getName(): string;
|
||||
public function getName(): ?string;
|
||||
|
||||
/**
|
||||
* Check if route has given name.
|
||||
@@ -41,7 +52,7 @@ interface ILoadableRoute extends IRoute
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function hasName($name): bool;
|
||||
public function hasName(string $name): bool;
|
||||
|
||||
/**
|
||||
* Sets the router name, which makes it easier to obtain the url or router at a later point.
|
||||
@@ -49,14 +60,14 @@ interface ILoadableRoute extends IRoute
|
||||
* @param string $name
|
||||
* @return static
|
||||
*/
|
||||
public function setName($name): self;
|
||||
public function setName(string $name): self;
|
||||
|
||||
/**
|
||||
* Get regular expression match used for matching route (if defined).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMatch(): string;
|
||||
public function getMatch(): ?string;
|
||||
|
||||
/**
|
||||
* Add regular expression match for the entire route.
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Pecee\SimpleRouter\Route;
|
||||
|
||||
use Pecee\Http\Request;
|
||||
use Pecee\SimpleRouter\Router;
|
||||
|
||||
interface IRoute
|
||||
{
|
||||
@@ -20,10 +21,11 @@ interface IRoute
|
||||
* Returns class to be rendered.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Router $router
|
||||
* @throws \Pecee\SimpleRouter\Exceptions\NotFoundHttpException
|
||||
* @return string
|
||||
*/
|
||||
public function renderRoute(Request $request): ?string;
|
||||
public function renderRoute(Request $request, Router $router): ?string;
|
||||
|
||||
/**
|
||||
* Returns callback name/identifier for the current route based on the callback.
|
||||
@@ -103,15 +105,20 @@ interface IRoute
|
||||
* @param string $method
|
||||
* @return static
|
||||
*/
|
||||
public function setMethod($method): self;
|
||||
public function setMethod(string $method): self;
|
||||
|
||||
public function getClass();
|
||||
/**
|
||||
* Get class
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getClass(): ?string;
|
||||
|
||||
/**
|
||||
* @param string $namespace
|
||||
* @return static
|
||||
*/
|
||||
public function setNamespace($namespace);
|
||||
public function setNamespace(string $namespace): self;
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
@@ -122,9 +129,13 @@ interface IRoute
|
||||
* @param string $namespace
|
||||
* @return static
|
||||
*/
|
||||
public function setDefaultNamespace($namespace);
|
||||
public function setDefaultNamespace($namespace): IRoute;
|
||||
|
||||
public function getDefaultNamespace();
|
||||
/**
|
||||
* Get default namespace
|
||||
* @return string|null
|
||||
*/
|
||||
public function getDefaultNamespace(): ?string;
|
||||
|
||||
/**
|
||||
* Get parameter names.
|
||||
@@ -139,7 +150,7 @@ interface IRoute
|
||||
* @param array $options
|
||||
* @return static
|
||||
*/
|
||||
public function setWhere(array $options);
|
||||
public function setWhere(array $options): self;
|
||||
|
||||
/**
|
||||
* Get parameters
|
||||
@@ -152,18 +163,18 @@ interface IRoute
|
||||
* Get parameters
|
||||
*
|
||||
* @param array $parameters
|
||||
* @return static $this
|
||||
* @return static
|
||||
*/
|
||||
public function setParameters(array $parameters);
|
||||
public function setParameters(array $parameters): self;
|
||||
|
||||
/**
|
||||
* Merge with information from another route.
|
||||
*
|
||||
* @param array $settings
|
||||
* @param bool $merge
|
||||
* @return static $this
|
||||
* @return static
|
||||
*/
|
||||
public function setSettings(array $settings, $merge = false);
|
||||
public function setSettings(array $settings, bool $merge = false): self;
|
||||
|
||||
/**
|
||||
* Export route settings to array so they can be merged with another route.
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Pecee\SimpleRouter\Route;
|
||||
use Pecee\Http\Middleware\IMiddleware;
|
||||
use Pecee\Http\Request;
|
||||
use Pecee\SimpleRouter\Exceptions\HttpException;
|
||||
use Pecee\SimpleRouter\Router;
|
||||
|
||||
abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
{
|
||||
@@ -24,10 +25,13 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
* Loads and renders middlewares-classes
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Router $router
|
||||
* @throws HttpException
|
||||
*/
|
||||
public function loadMiddleware(Request $request) : void
|
||||
public function loadMiddleware(Request $request, Router $router): void
|
||||
{
|
||||
$router->debug('Loading middlewares');
|
||||
|
||||
foreach ($this->getMiddlewares() as $middleware) {
|
||||
|
||||
if (\is_object($middleware) === false) {
|
||||
@@ -38,11 +42,15 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
throw new HttpException($middleware . ' must be inherit the IMiddleware interface');
|
||||
}
|
||||
|
||||
$router->debug('Loading middleware "%s"', \get_class($middleware));
|
||||
$middleware->handle($request);
|
||||
$router->debug('Finished loading middleware');
|
||||
}
|
||||
|
||||
$router->debug('Finished loading middlewares');
|
||||
}
|
||||
|
||||
public function matchRegex(Request $request, $url) : ?bool
|
||||
public function matchRegex(Request $request, $url): ?bool
|
||||
{
|
||||
/* Match on custom defined regular expression */
|
||||
|
||||
@@ -59,7 +67,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
* @param string $url
|
||||
* @return static
|
||||
*/
|
||||
public function setUrl($url) : self
|
||||
public function setUrl(string $url): ILoadableRoute
|
||||
{
|
||||
$this->url = ($url === '/') ? '/' : '/' . trim($url, '/') . '/';
|
||||
|
||||
@@ -75,7 +83,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUrl() : string
|
||||
public function getUrl(): string
|
||||
{
|
||||
return $this->url;
|
||||
}
|
||||
@@ -89,7 +97,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
* @param string|null $name
|
||||
* @return string
|
||||
*/
|
||||
public function findUrl($method = null, $parameters = null, $name = null) : string
|
||||
public function findUrl($method = null, $parameters = null, $name = null): string
|
||||
{
|
||||
$url = $this->getUrl();
|
||||
|
||||
@@ -144,7 +152,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName() : string
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
@@ -155,7 +163,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function hasName($name) : bool
|
||||
public function hasName(string $name): bool
|
||||
{
|
||||
return strtolower($this->name) === strtolower($name);
|
||||
}
|
||||
@@ -166,7 +174,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
* @param string $regex
|
||||
* @return static
|
||||
*/
|
||||
public function setMatch($regex) : ILoadableRoute
|
||||
public function setMatch($regex): ILoadableRoute
|
||||
{
|
||||
$this->regex = $regex;
|
||||
|
||||
@@ -178,7 +186,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMatch() : string
|
||||
public function getMatch(): string
|
||||
{
|
||||
return $this->regex;
|
||||
}
|
||||
@@ -191,7 +199,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
* @param string|array $name
|
||||
* @return static
|
||||
*/
|
||||
public function name($name) : ILoadableRoute
|
||||
public function name($name): ILoadableRoute
|
||||
{
|
||||
return $this->setName($name);
|
||||
}
|
||||
@@ -202,7 +210,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
* @param string $name
|
||||
* @return static
|
||||
*/
|
||||
public function setName($name) : ILoadableRoute
|
||||
public function setName(string $name): ILoadableRoute
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
@@ -216,7 +224,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
* @param bool $merge
|
||||
* @return static
|
||||
*/
|
||||
public function setSettings(array $values, $merge = false): IRoute
|
||||
public function setSettings(array $values, bool $merge = false): IRoute
|
||||
{
|
||||
if (isset($values['as']) === true) {
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Pecee\SimpleRouter\Route;
|
||||
use Pecee\Http\Middleware\IMiddleware;
|
||||
use Pecee\Http\Request;
|
||||
use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
|
||||
use Pecee\SimpleRouter\Router;
|
||||
|
||||
abstract class Route implements IRoute
|
||||
{
|
||||
@@ -59,10 +60,10 @@ abstract class Route implements IRoute
|
||||
/**
|
||||
* Load class by name
|
||||
* @param string $name
|
||||
* @return mixed
|
||||
* @return object
|
||||
* @throws NotFoundHttpException
|
||||
*/
|
||||
protected function loadClass($name)
|
||||
protected function loadClass($name): object
|
||||
{
|
||||
if (class_exists($name) === false) {
|
||||
throw new NotFoundHttpException(sprintf('Class "%s" does not exist', $name), 404);
|
||||
@@ -75,21 +76,25 @@ abstract class Route implements IRoute
|
||||
* Render route
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Router $router
|
||||
* @return string|null
|
||||
* @throws NotFoundHttpException
|
||||
*/
|
||||
public function renderRoute(Request $request): ?string
|
||||
public function renderRoute(Request $request, Router $router): ?string
|
||||
{
|
||||
$router->debug('Starting rendering route');
|
||||
|
||||
$callback = $this->getCallback();
|
||||
|
||||
if ($callback === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$router->debug('Parsing parameters');
|
||||
$parameters = $this->getParameters();
|
||||
$router->debug('Finished parsing parameters');
|
||||
|
||||
/* Filter parameters with null-value */
|
||||
|
||||
if ($this->filterEmptyParams === true) {
|
||||
$parameters = array_filter($parameters, function ($var) {
|
||||
return ($var !== null);
|
||||
@@ -98,7 +103,10 @@ abstract class Route implements IRoute
|
||||
|
||||
/* Render callback function */
|
||||
if (\is_callable($callback) === true) {
|
||||
$router->debug('Executing callback');
|
||||
|
||||
/* When the callback is a function */
|
||||
|
||||
return \call_user_func_array($callback, $parameters);
|
||||
}
|
||||
|
||||
@@ -109,6 +117,7 @@ abstract class Route implements IRoute
|
||||
|
||||
$className = ($namespace !== null && $controller[0][0] !== '\\') ? $namespace . '\\' . $controller[0] : $controller[0];
|
||||
|
||||
$router->debug('Loading class %s', $className);
|
||||
$class = $this->loadClass($className);
|
||||
$method = $controller[1];
|
||||
|
||||
@@ -116,6 +125,8 @@ abstract class Route implements IRoute
|
||||
throw new NotFoundHttpException(sprintf('Method "%s" does not exist in class "%s"', $method, $className), 404);
|
||||
}
|
||||
|
||||
$router->debug('Executing callback');
|
||||
|
||||
return \call_user_func_array([$class, $method], $parameters);
|
||||
}
|
||||
|
||||
@@ -300,7 +311,7 @@ abstract class Route implements IRoute
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getClass()
|
||||
public function getClass(): ?string
|
||||
{
|
||||
if (\is_string($this->callback) === true && strpos($this->callback, '@') !== false) {
|
||||
$tmp = explode('@', $this->callback);
|
||||
@@ -311,14 +322,14 @@ abstract class Route implements IRoute
|
||||
return null;
|
||||
}
|
||||
|
||||
public function setMethod($method): IRoute
|
||||
public function setMethod(string $method): IRoute
|
||||
{
|
||||
$this->callback = sprintf('%s@%s', $this->getClass(), $method);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setClass($class)
|
||||
public function setClass(string $class): IRoute
|
||||
{
|
||||
$this->callback = sprintf('%s@%s', $class, $this->getMethod());
|
||||
|
||||
@@ -327,9 +338,9 @@ abstract class Route implements IRoute
|
||||
|
||||
/**
|
||||
* @param string $namespace
|
||||
* @return static $this
|
||||
* @return static
|
||||
*/
|
||||
public function setNamespace($namespace)
|
||||
public function setNamespace(string $namespace): IRoute
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
|
||||
@@ -338,16 +349,16 @@ abstract class Route implements IRoute
|
||||
|
||||
/**
|
||||
* @param string $namespace
|
||||
* @return static $this
|
||||
* @return static
|
||||
*/
|
||||
public function setDefaultNamespace($namespace)
|
||||
public function setDefaultNamespace($namespace): IRoute
|
||||
{
|
||||
$this->defaultNamespace = $namespace;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDefaultNamespace()
|
||||
public function getDefaultNamespace(): ?string
|
||||
{
|
||||
return $this->defaultNamespace;
|
||||
}
|
||||
@@ -397,9 +408,9 @@ abstract class Route implements IRoute
|
||||
*
|
||||
* @param array $values
|
||||
* @param bool $merge
|
||||
* @return static $this
|
||||
* @return static
|
||||
*/
|
||||
public function setSettings(array $values, $merge = false)
|
||||
public function setSettings(array $values, bool $merge = false): IRoute
|
||||
{
|
||||
if ($this->namespace === null && isset($values['namespace']) === true) {
|
||||
$this->setNamespace($values['namespace']);
|
||||
@@ -445,7 +456,7 @@ abstract class Route implements IRoute
|
||||
* @param array $options
|
||||
* @return static
|
||||
*/
|
||||
public function setWhere(array $options)
|
||||
public function setWhere(array $options): IRoute
|
||||
{
|
||||
$this->where = $options;
|
||||
|
||||
@@ -486,9 +497,9 @@ abstract class Route implements IRoute
|
||||
* Get parameters
|
||||
*
|
||||
* @param array $parameters
|
||||
* @return static $this
|
||||
* @return static
|
||||
*/
|
||||
public function setParameters(array $parameters)
|
||||
public function setParameters(array $parameters): IRoute
|
||||
{
|
||||
/*
|
||||
* If this is the first time setting parameters we store them so we
|
||||
@@ -556,7 +567,7 @@ abstract class Route implements IRoute
|
||||
* This is used when no custom parameter regex is found.
|
||||
*
|
||||
* @param string $regex
|
||||
* @return static $this
|
||||
* @return static
|
||||
*/
|
||||
public function setDefaultParameterRegex($regex)
|
||||
{
|
||||
|
||||
@@ -24,7 +24,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function hasName($name): bool
|
||||
public function hasName(string $name): bool
|
||||
{
|
||||
if ($this->name === null) {
|
||||
return false;
|
||||
@@ -134,7 +134,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
|
||||
* @param string $controller
|
||||
* @return static
|
||||
*/
|
||||
public function setController($controller): IControllerRoute
|
||||
public function setController(string $controller): IControllerRoute
|
||||
{
|
||||
$this->controller = $controller;
|
||||
|
||||
@@ -157,7 +157,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
|
||||
* @param string $method
|
||||
* @return static
|
||||
*/
|
||||
public function setMethod($method): IRoute
|
||||
public function setMethod(string $method): IRoute
|
||||
{
|
||||
$this->method = $method;
|
||||
|
||||
@@ -171,7 +171,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
|
||||
* @param bool $merge
|
||||
* @return static
|
||||
*/
|
||||
public function setSettings(array $values, $merge = false): IRoute
|
||||
public function setSettings(array $values, bool $merge = false): IRoute
|
||||
{
|
||||
if (isset($values['names']) === true) {
|
||||
$this->names = $values['names'];
|
||||
|
||||
@@ -147,7 +147,7 @@ class RouteGroup extends Route implements IGroupRoute
|
||||
* @param bool $merge
|
||||
* @return static
|
||||
*/
|
||||
public function setSettings(array $values, $merge = false): IRoute
|
||||
public function setSettings(array $values, bool $merge = false): IRoute
|
||||
{
|
||||
|
||||
if (isset($values['prefix']) === true) {
|
||||
|
||||
@@ -42,7 +42,7 @@ class RouteResource extends LoadableRoute implements IControllerRoute
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function hasName($name): bool
|
||||
public function hasName(string $name): bool
|
||||
{
|
||||
if ($this->name === null) {
|
||||
return false;
|
||||
@@ -154,14 +154,14 @@ class RouteResource extends LoadableRoute implements IControllerRoute
|
||||
* @param string $controller
|
||||
* @return static
|
||||
*/
|
||||
public function setController($controller): IControllerRoute
|
||||
public function setController(string $controller): IControllerRoute
|
||||
{
|
||||
$this->controller = $controller;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setName($name): ILoadableRoute
|
||||
public function setName(string $name): ILoadableRoute
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
@@ -208,7 +208,7 @@ class RouteResource extends LoadableRoute implements IControllerRoute
|
||||
* @param bool $merge
|
||||
* @return static
|
||||
*/
|
||||
public function setSettings(array $values, $merge = false): IRoute
|
||||
public function setSettings(array $values, bool $merge = false): IRoute
|
||||
{
|
||||
if (isset($values['names']) === true) {
|
||||
$this->names = $values['names'];
|
||||
|
||||
@@ -66,6 +66,32 @@ class Router
|
||||
*/
|
||||
protected $exceptionHandlers;
|
||||
|
||||
/**
|
||||
* List of loaded exception that has been loaded.
|
||||
* Used to ensure that exception-handlers aren't loaded twice when rewriting route.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $loadedExceptionHandlers;
|
||||
|
||||
/**
|
||||
* Enable or disabled debugging
|
||||
* @var bool
|
||||
*/
|
||||
protected $debugEnabled = false;
|
||||
|
||||
/**
|
||||
* The start time used when debugging is enabled
|
||||
* @var float
|
||||
*/
|
||||
protected $debugStartTime;
|
||||
|
||||
/**
|
||||
* List containing all debug messages
|
||||
* @var array
|
||||
*/
|
||||
protected $debugList = [];
|
||||
|
||||
/**
|
||||
* Router constructor.
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
@@ -78,7 +104,7 @@ class Router
|
||||
/**
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
public function reset() : void
|
||||
public function reset(): void
|
||||
{
|
||||
$this->processingRoute = false;
|
||||
$this->request = new Request();
|
||||
@@ -87,6 +113,7 @@ class Router
|
||||
$this->routeStack = [];
|
||||
$this->processedRoutes = [];
|
||||
$this->exceptionHandlers = [];
|
||||
$this->loadedExceptionHandlers = [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,7 +121,7 @@ class Router
|
||||
* @param IRoute $route
|
||||
* @return IRoute
|
||||
*/
|
||||
public function addRoute(IRoute $route) : IRoute
|
||||
public function addRoute(IRoute $route): IRoute
|
||||
{
|
||||
/*
|
||||
* If a route is currently being processed, that means that the route being added are rendered from the parent
|
||||
@@ -102,10 +129,12 @@ class Router
|
||||
*/
|
||||
if ($this->processingRoute === true) {
|
||||
$this->routeStack[] = $route;
|
||||
|
||||
return $route;
|
||||
}
|
||||
|
||||
$this->routes[] = $route;
|
||||
|
||||
return $route;
|
||||
}
|
||||
|
||||
@@ -115,10 +144,11 @@ class Router
|
||||
* @param IRoute $route
|
||||
* @throws NotFoundHttpException
|
||||
*/
|
||||
protected function renderAndProcess(IRoute $route) : void {
|
||||
protected function renderAndProcess(IRoute $route): void
|
||||
{
|
||||
|
||||
$this->processingRoute = true;
|
||||
$route->renderRoute($this->request);
|
||||
$route->renderRoute($this->request, $this);
|
||||
$this->processingRoute = false;
|
||||
|
||||
if (\count($this->routeStack) !== 0) {
|
||||
@@ -139,13 +169,17 @@ class Router
|
||||
* @param IGroupRoute|null $group
|
||||
* @throws NotFoundHttpException
|
||||
*/
|
||||
protected function processRoutes(array $routes, IGroupRoute $group = null) : void
|
||||
protected function processRoutes(array $routes, ?IGroupRoute $group = null): void
|
||||
{
|
||||
$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() === null) {
|
||||
if ($this->request->getRewriteRoute() === null && $this->request->getUrl() === null) {
|
||||
$this->debug('Halted route-processing as no valid route was found');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -154,6 +188,8 @@ class Router
|
||||
/* @var $route IRoute */
|
||||
foreach ($routes as $route) {
|
||||
|
||||
$this->debug('Processing route "%s"', \get_class($route));
|
||||
|
||||
if ($group !== null) {
|
||||
/* Add the parent group */
|
||||
$route->setGroup($group);
|
||||
@@ -199,16 +235,22 @@ class Router
|
||||
* @throws NotFoundHttpException
|
||||
* @return void
|
||||
*/
|
||||
public function loadRoutes() : void
|
||||
public function loadRoutes(): void
|
||||
{
|
||||
$this->debug('Loading routes');
|
||||
|
||||
/* Initialize boot-managers */
|
||||
/* @var $manager IRouterBootManager */
|
||||
foreach ($this->bootManagers as $manager) {
|
||||
$this->debug('Rendering bootmanager %s', \get_class($manager));
|
||||
$manager->boot($this->request);
|
||||
$this->debug('Finished rendering bootmanager');
|
||||
}
|
||||
|
||||
/* Loop through each route-request */
|
||||
$this->processRoutes($this->routes);
|
||||
|
||||
$this->debug('Finished loading routes');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -219,9 +261,11 @@ class Router
|
||||
* @throws HttpException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function routeRequest($rewrite = false) : ?string
|
||||
public function routeRequest(bool $rewrite = false): ?string
|
||||
{
|
||||
$routeNotAllowed = false;
|
||||
$this->debug('Started routing request (rewrite: %s)', $rewrite === true ? 'yes' : 'no');
|
||||
|
||||
$methodNotAllowed = false;
|
||||
|
||||
try {
|
||||
|
||||
@@ -233,8 +277,6 @@ class Router
|
||||
/* Verify csrf token for request */
|
||||
$this->csrfVerifier->handle($this->request);
|
||||
}
|
||||
} else {
|
||||
$this->request->setHasRewrite(false);
|
||||
}
|
||||
|
||||
$url = $this->request->getRewriteUrl() ?? $this->request->getUrl()->getPath();
|
||||
@@ -242,38 +284,39 @@ class Router
|
||||
/* @var $route ILoadableRoute */
|
||||
foreach ($this->processedRoutes as $key => $route) {
|
||||
|
||||
$this->debug('Matching route "%s"', \get_class($route));
|
||||
|
||||
/* If the route matches */
|
||||
if ($route->matchRoute($url, $this->request) === true) {
|
||||
|
||||
/* Check if request method matches */
|
||||
if (\count($route->getRequestMethods()) !== 0 && \in_array($this->request->getMethod(), $route->getRequestMethods(), true) === false) {
|
||||
$routeNotAllowed = true;
|
||||
$this->debug('Method "%s" not allowed', $this->request->getMethod());
|
||||
$methodNotAllowed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
$route->loadMiddleware($this->request);
|
||||
$route->loadMiddleware($this->request, $this);
|
||||
|
||||
if ($this->hasRewrite($url) === true) {
|
||||
unset($this->processedRoutes[$key]);
|
||||
|
||||
return $this->routeRequest(true);
|
||||
$output = $this->handleRouteRewrite($key, $url);
|
||||
if ($output !== null) {
|
||||
return $output;
|
||||
}
|
||||
|
||||
/* Render route */
|
||||
$routeNotAllowed = false;
|
||||
$methodNotAllowed = false;
|
||||
|
||||
$this->request->addLoadedRoute($route);
|
||||
|
||||
$output = $route->renderRoute($this->request);
|
||||
$output = $route->renderRoute($this->request, $this);
|
||||
|
||||
if ($output !== null) {
|
||||
return $output;
|
||||
}
|
||||
|
||||
if ($this->hasRewrite($url) === true) {
|
||||
unset($this->processedRoutes[$key]);
|
||||
|
||||
return $this->routeRequest(true);
|
||||
$output = $this->handleRouteRewrite($key, $url);
|
||||
if ($output !== null) {
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,7 +325,7 @@ class Router
|
||||
$this->handleException($e);
|
||||
}
|
||||
|
||||
if ($routeNotAllowed === true) {
|
||||
if ($methodNotAllowed === true) {
|
||||
$message = sprintf('Route "%s" or method "%s" not allowed.', $this->request->getUrl()->getPath(), $this->request->getMethod());
|
||||
$this->handleException(new HttpException($message, 403));
|
||||
}
|
||||
@@ -297,35 +340,45 @@ class Router
|
||||
$message = sprintf('Route not found: "%s"', $this->request->getUrl()->getPath());
|
||||
}
|
||||
|
||||
$this->handleException(new NotFoundHttpException($message, 404));
|
||||
$this->debug($message);
|
||||
|
||||
return $this->handleException(new NotFoundHttpException($message, 404));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function hasRewrite($url) : bool
|
||||
/**
|
||||
* Handle route-rewrite
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $url
|
||||
* @return string|null
|
||||
* @throws HttpException
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function handleRouteRewrite($key, string $url): ?string
|
||||
{
|
||||
|
||||
/* If the request has changed */
|
||||
if ($this->request->hasRewrite() === true) {
|
||||
|
||||
if ($this->request->getRewriteRoute() !== null) {
|
||||
/* Render rewrite-route */
|
||||
$this->processedRoutes[] = $this->request->getRewriteRoute();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->request->isRewrite($url) === false) {
|
||||
|
||||
/* Render rewrite-url */
|
||||
$this->processedRoutes = array_values($this->processedRoutes);
|
||||
|
||||
return true;
|
||||
}
|
||||
if ($this->request->hasRewrite() === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return false;
|
||||
$route = $this->request->getRewriteRoute();
|
||||
|
||||
if ($route !== null) {
|
||||
/* Add rewrite route */
|
||||
$this->processedRoutes[] = $route;
|
||||
}
|
||||
|
||||
if ($this->request->getRewriteUrl() !== $url) {
|
||||
unset($this->processedRoutes[$key]);
|
||||
$this->request->setHasRewrite(false);
|
||||
|
||||
return $this->routeRequest(true);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -334,8 +387,10 @@ class Router
|
||||
* @throws \Exception
|
||||
* @return string|null
|
||||
*/
|
||||
protected function handleException(\Exception $e) : ?string
|
||||
protected function handleException(\Exception $e): ?string
|
||||
{
|
||||
$this->debug('Starting exception handling for "%s"', \get_class($e));
|
||||
|
||||
/* @var $handler IExceptionHandler */
|
||||
foreach ($this->exceptionHandlers as $key => $handler) {
|
||||
|
||||
@@ -343,17 +398,22 @@ class Router
|
||||
$handler = new $handler();
|
||||
}
|
||||
|
||||
$this->debug('Processing exception-handler "%s"', \get_class($handler));
|
||||
|
||||
if (($handler instanceof IExceptionHandler) === false) {
|
||||
throw new HttpException('Exception handler must implement the IExceptionHandler interface.', 500);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
$this->debug('Start rendering exception handler');
|
||||
$handler->handleError($this->request, $e);
|
||||
$this->debug('Finished rendering exception-handler');
|
||||
|
||||
if ($this->request->hasRewrite() === true) {
|
||||
unset($this->exceptionHandlers[$key]);
|
||||
$this->exceptionHandlers = array_values($this->exceptionHandlers);
|
||||
if (isset($this->loadedExceptionHandlers[$key]) === false && $this->request->hasRewrite() === true) {
|
||||
$this->loadedExceptionHandlers[$key] = $handler;
|
||||
|
||||
$this->debug('Exception handler contains rewrite, reloading routes');
|
||||
|
||||
return $this->routeRequest(true);
|
||||
}
|
||||
@@ -361,12 +421,15 @@ class Router
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
|
||||
$this->debug('Finished processing');
|
||||
}
|
||||
|
||||
$this->debug('Finished exception handling - exception not handled, throwing');
|
||||
throw $e;
|
||||
}
|
||||
|
||||
public function arrayToParams(array $getParams = [], $includeEmpty = true) : string
|
||||
public function arrayToParams(array $getParams = [], bool $includeEmpty = true): string
|
||||
{
|
||||
if (\count($getParams) !== 0) {
|
||||
|
||||
@@ -388,18 +451,25 @@ class Router
|
||||
* @param string $name
|
||||
* @return ILoadableRoute|null
|
||||
*/
|
||||
public function findRoute($name) : ?ILoadableRoute
|
||||
public function findRoute(string $name): ?ILoadableRoute
|
||||
{
|
||||
|
||||
$this->debug('Finding route by name "%s"', $name);
|
||||
|
||||
/* @var $route ILoadableRoute */
|
||||
foreach ($this->processedRoutes as $route) {
|
||||
|
||||
/* Check if the name matches with a name on the route. Should match either router alias or controller alias. */
|
||||
if ($route->hasName($name) === true) {
|
||||
$this->debug('Found route "%s" by name "%s"', $route->getUrl(), $name);
|
||||
|
||||
return $route;
|
||||
}
|
||||
|
||||
/* Direct match to controller */
|
||||
if ($route instanceof IControllerRoute && strtolower($route->getController()) === strtolower($name)) {
|
||||
$this->debug('Found route "%s" by controller "%s"', $route->getUrl(), $name);
|
||||
|
||||
return $route;
|
||||
}
|
||||
|
||||
@@ -408,6 +478,8 @@ class Router
|
||||
[$controller, $method] = array_map('strtolower', explode('@', $name));
|
||||
|
||||
if ($controller === strtolower($route->getClass()) && $method === strtolower($route->getMethod())) {
|
||||
$this->debug('Found route "%s" by controller "%s" and method "%s"', $route->getUrl(), $controller, $method);
|
||||
|
||||
return $route;
|
||||
}
|
||||
}
|
||||
@@ -417,16 +489,22 @@ class Router
|
||||
|
||||
/* Check if the entire callback is matching */
|
||||
if (strpos($route->getCallback(), $name) === 0 || strtolower($route->getCallback()) === strtolower($name)) {
|
||||
$this->debug('Found route "%s" by callback "%s"', $route->getUrl(), $name);
|
||||
|
||||
return $route;
|
||||
}
|
||||
|
||||
/* Check if the class part of the callback matches (class@method) */
|
||||
if (strtolower($name) === strtolower($route->getClass())) {
|
||||
$this->debug('Found route "%s" by class "%s"', $route->getUrl(), $name);
|
||||
|
||||
return $route;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->debug('Route not found');
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -448,8 +526,10 @@ class Router
|
||||
* @throws InvalidArgumentException
|
||||
* @return string
|
||||
*/
|
||||
public function getUrl($name = null, $parameters = null, $getParams = null) : string
|
||||
public function getUrl(?string $name = null, $parameters = null, $getParams = null): string
|
||||
{
|
||||
$this->debug('Finding url', \func_get_args());
|
||||
|
||||
if ($getParams !== null && \is_array($getParams) === false) {
|
||||
throw new InvalidArgumentException('Invalid type for getParams. Must be array or null');
|
||||
}
|
||||
@@ -513,28 +593,28 @@ class Router
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bootmanagers
|
||||
* Get BootManagers
|
||||
* @return array
|
||||
*/
|
||||
public function getBootManagers() : array
|
||||
public function getBootManagers(): array
|
||||
{
|
||||
return $this->bootManagers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set bootmanagers
|
||||
* Set BootManagers
|
||||
* @param array $bootManagers
|
||||
*/
|
||||
public function setBootManagers(array $bootManagers) : void
|
||||
public function setBootManagers(array $bootManagers): void
|
||||
{
|
||||
$this->bootManagers = $bootManagers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add bootmanager
|
||||
* Add BootManager
|
||||
* @param IRouterBootManager $bootManager
|
||||
*/
|
||||
public function addBootManager(IRouterBootManager $bootManager) : void
|
||||
public function addBootManager(IRouterBootManager $bootManager): void
|
||||
{
|
||||
$this->bootManagers[] = $bootManager;
|
||||
}
|
||||
@@ -544,7 +624,7 @@ class Router
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getProcessedRoutes() : array
|
||||
public function getProcessedRoutes(): array
|
||||
{
|
||||
return $this->processedRoutes;
|
||||
}
|
||||
@@ -552,7 +632,7 @@ class Router
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getRoutes() : array
|
||||
public function getRoutes(): array
|
||||
{
|
||||
return $this->routes;
|
||||
}
|
||||
@@ -563,7 +643,7 @@ class Router
|
||||
* @param array $routes
|
||||
* @return static
|
||||
*/
|
||||
public function setRoutes(array $routes) : self
|
||||
public function setRoutes(array $routes): self
|
||||
{
|
||||
$this->routes = $routes;
|
||||
|
||||
@@ -575,7 +655,7 @@ class Router
|
||||
*
|
||||
* @return Request
|
||||
*/
|
||||
public function getRequest() : Request
|
||||
public function getRequest(): Request
|
||||
{
|
||||
return $this->request;
|
||||
}
|
||||
@@ -584,7 +664,7 @@ class Router
|
||||
* Get csrf verifier class
|
||||
* @return BaseCsrfVerifier
|
||||
*/
|
||||
public function getCsrfVerifier() : BaseCsrfVerifier
|
||||
public function getCsrfVerifier(): ?BaseCsrfVerifier
|
||||
{
|
||||
return $this->csrfVerifier;
|
||||
}
|
||||
@@ -602,4 +682,47 @@ class Router
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new debug message
|
||||
* @param string $message
|
||||
* @param array $args
|
||||
*/
|
||||
public function debug(string $message, ...$args): void
|
||||
{
|
||||
if ($this->debugEnabled === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
$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),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disables debugging
|
||||
*
|
||||
* @param bool $boolean
|
||||
*/
|
||||
public function setDebugEnabled(bool $boolean): void
|
||||
{
|
||||
if ($boolean === true) {
|
||||
$this->debugStartTime = microtime(true);
|
||||
}
|
||||
|
||||
$this->debugEnabled = $boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list containing all debug messages.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDebugLog(): array
|
||||
{
|
||||
return $this->debugList;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -46,6 +46,8 @@ class SimpleRouter
|
||||
protected static $router;
|
||||
|
||||
/**
|
||||
* Start routing
|
||||
*
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
* @throws HttpException
|
||||
* @throws \Exception
|
||||
@@ -56,21 +58,55 @@ class SimpleRouter
|
||||
}
|
||||
|
||||
/**
|
||||
* Get debug info array
|
||||
* Start the routing an return array with debugging-information
|
||||
*
|
||||
* @return array
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
public static function debugInfo(): array
|
||||
public static function startDebug(): array
|
||||
{
|
||||
$routerOutput = null;
|
||||
|
||||
try {
|
||||
ob_start();
|
||||
static::router()->setDebugEnabled(true);
|
||||
static::start();
|
||||
$routerOutput = ob_get_contents();
|
||||
ob_end_clean();
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
|
||||
// Try to parse library version
|
||||
$composerFile = \dirname(__DIR__, 3) . '/composer.lock';
|
||||
$version = false;
|
||||
|
||||
if (is_file($composerFile) === true) {
|
||||
$composerInfo = json_decode(file_get_contents($composerFile), true);
|
||||
|
||||
if (isset($composerInfo['packages']) === true && \is_array($composerInfo['packages']) === true) {
|
||||
foreach ($composerInfo['packages'] as $package) {
|
||||
if (isset($package['name']) === true && strtolower($package['name']) === 'pecee/simple-router') {
|
||||
$version = $package['version'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'url' => static::request()->getUrl(),
|
||||
'method' => static::request()->getMethod(),
|
||||
'host' => static::request()->getHost(),
|
||||
'loaded_routes' => static::request()->getLoadedRoutes(),
|
||||
'all_routes' => static::router()->getRoutes(),
|
||||
'boot_managers' => static::router()->getBootManagers(),
|
||||
'csrf_verifier' => static::router()->getCsrfVerifier(),
|
||||
'url' => static::request()->getUrl(),
|
||||
'method' => static::request()->getMethod(),
|
||||
'host' => static::request()->getHost(),
|
||||
'loaded_routes' => static::request()->getLoadedRoutes(),
|
||||
'all_routes' => static::router()->getRoutes(),
|
||||
'boot_managers' => static::router()->getBootManagers(),
|
||||
'csrf_verifier' => static::router()->getCsrfVerifier(),
|
||||
'log' => static::router()->getDebugLog(),
|
||||
'router_output' => $routerOutput,
|
||||
'library_version' => $version,
|
||||
'php_version' => PHP_VERSION,
|
||||
'server_params' => static::request()->getHeaders(),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user