From 165d41b2140ea206181d603d6b3524d45b6f346b Mon Sep 17 00:00:00 2001 From: Lucas Silva Date: Tue, 30 Jul 2024 15:50:34 -0300 Subject: [PATCH 1/6] refactor: changes for php8.2 --- composer.json | 2 +- helpers.php | 25 ++-- src/Pecee/Controllers/IResourceController.php | 14 +-- src/Pecee/Http/Input/IInputItem.php | 4 +- src/Pecee/Http/Input/InputFile.php | 23 ++-- src/Pecee/Http/Input/InputHandler.php | 63 +++++----- src/Pecee/Http/Input/InputItem.php | 15 +-- .../Http/Middleware/BaseCsrfVerifier.php | 6 +- .../Http/Middleware/IpRestrictAccess.php | 2 +- src/Pecee/Http/Request.php | 38 +++--- src/Pecee/Http/Response.php | 9 +- .../Http/Security/CookieTokenProvider.php | 4 +- src/Pecee/Http/Url.php | 23 ++-- .../SimpleRouter/ClassLoader/ClassLoader.php | 4 +- .../SimpleRouter/ClassLoader/IClassLoader.php | 6 +- .../SimpleRouter/Event/EventArgument.php | 2 +- .../Handlers/CallbackExceptionHandler.php | 2 +- .../SimpleRouter/Handlers/EventHandler.php | 18 +-- src/Pecee/SimpleRouter/Route/IGroupRoute.php | 14 +-- .../SimpleRouter/Route/ILoadableRoute.php | 4 +- src/Pecee/SimpleRouter/Route/IRoute.php | 22 ++-- .../SimpleRouter/Route/LoadableRoute.php | 20 ++-- src/Pecee/SimpleRouter/Route/Route.php | 57 +++++---- .../SimpleRouter/Route/RouteController.php | 30 +++-- src/Pecee/SimpleRouter/Route/RouteGroup.php | 17 +-- .../SimpleRouter/Route/RouteResource.php | 13 +- src/Pecee/SimpleRouter/Route/RouteUrl.php | 7 +- src/Pecee/SimpleRouter/Router.php | 88 ++++++-------- src/Pecee/SimpleRouter/SimpleRouter.php | 111 +++++++++--------- tests/Pecee/SimpleRouter/CsrfVerifierTest.php | 11 +- .../Dummy/ClassLoader/CustomClassLoader.php | 13 +- .../Dummy/CsrfVerifier/DummyCsrfVerifier.php | 10 +- .../SimpleRouter/Dummy/ResourceController.php | 8 +- tests/Pecee/SimpleRouter/InputHandlerTest.php | 33 +++--- tests/TestRouter.php | 45 ++++--- tests/debug.php | 2 + 36 files changed, 382 insertions(+), 383 deletions(-) diff --git a/composer.json b/composer.json index 3208bfa6..c48fb587 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ } ], "require": { - "php": ">=7.4", + "php": "^8.2", "ext-json": "*" }, "require-dev": { diff --git a/helpers.php b/helpers.php index 81d836fc..b3115c3f 100644 --- a/helpers.php +++ b/helpers.php @@ -1,5 +1,7 @@ getInputHandler()->value($index, $defaultValue, ...$methods); @@ -80,9 +82,6 @@ function redirect(string $url, ?int $code = null): void function csrf_token(): ?string { $baseVerifier = Router::router()->getCsrfVerifier(); - if ($baseVerifier !== null) { - return $baseVerifier->getTokenProvider()->getToken(); - } + return $baseVerifier?->getTokenProvider()->getToken(); - return null; } \ No newline at end of file diff --git a/src/Pecee/Controllers/IResourceController.php b/src/Pecee/Controllers/IResourceController.php index 8c062fe2..7f1e97a3 100644 --- a/src/Pecee/Controllers/IResourceController.php +++ b/src/Pecee/Controllers/IResourceController.php @@ -8,41 +8,41 @@ interface IResourceController /** * @return mixed */ - public function index(); + public function index(): mixed; /** * @param mixed $id * @return mixed */ - public function show($id); + public function show(mixed $id): mixed; /** * @return mixed */ - public function store(); + public function store(): mixed; /** * @return mixed */ - public function create(); + public function create(): mixed; /** * View * @param mixed $id * @return mixed */ - public function edit($id); + public function edit(mixed $id): mixed; /** * @param mixed $id * @return mixed */ - public function update($id); + public function update(mixed $id): mixed; /** * @param mixed $id * @return mixed */ - public function destroy($id); + public function destroy(mixed $id): mixed; } \ No newline at end of file diff --git a/src/Pecee/Http/Input/IInputItem.php b/src/Pecee/Http/Input/IInputItem.php index 430b5573..a999ada1 100644 --- a/src/Pecee/Http/Input/IInputItem.php +++ b/src/Pecee/Http/Input/IInputItem.php @@ -16,12 +16,12 @@ public function setName(string $name): self; /** * @return mixed */ - public function getValue(); + public function getValue(): mixed; /** * @param mixed $value */ - public function setValue($value): self; + public function setValue(mixed $value): self; public function __toString(): string; diff --git a/src/Pecee/Http/Input/InputFile.php b/src/Pecee/Http/Input/InputFile.php index 24a38f79..d982eac7 100644 --- a/src/Pecee/Http/Input/InputFile.php +++ b/src/Pecee/Http/Input/InputFile.php @@ -52,7 +52,7 @@ public function __construct(string $index) } /** - * Create from array + * Create from an array * * @param array $values * @throws InvalidArgumentException @@ -65,7 +65,6 @@ public static function createFromArray(array $values): self } /* Easy way of ensuring that all indexes-are set and not filling the screen with isset() */ - $values += [ 'tmp_name' => null, 'type' => null, @@ -104,7 +103,7 @@ public function setIndex(string $index): IInputItem } /** - * @return int + * @return int|null */ public function getSize(): ?int { @@ -116,7 +115,7 @@ public function getSize(): ?int * @param int $size * @return static */ - public function setSize(int $size): IInputItem + public function setSize(int $size): self { $this->size = $size; @@ -145,7 +144,7 @@ public function getType(): string * @param string $type * @return static */ - public function setType(string $type): IInputItem + public function setType(string $type): self { $this->type = $type; @@ -165,7 +164,7 @@ public function getExtension(): string /** * Get human friendly name * - * @return string + * @return string|null */ public function getName(): ?string { @@ -174,7 +173,7 @@ public function getName(): ?string /** * Set human friendly name. - * Useful for adding validation etc. + * Useful for adding validation, etc. * * @param string $name * @return static @@ -192,7 +191,7 @@ public function setName(string $name): IInputItem * @param string $name * @return static */ - public function setFilename(string $name): IInputItem + public function setFilename(string $name): self { $this->filename = $name; @@ -202,7 +201,7 @@ public function setFilename(string $name): IInputItem /** * Get filename * - * @return string mixed + * @return string|null mixed */ public function getFilename(): ?string { @@ -256,7 +255,7 @@ public function getError(): ?int * @param int|null $error * @return static */ - public function setError(?int $error): IInputItem + public function setError(?int $error): self { $this->errors = (int)$error; @@ -276,7 +275,7 @@ public function getTmpName(): string * @param string $name * @return static */ - public function setTmpName(string $name): IInputItem + public function setTmpName(string $name): self { $this->tmpName = $name; @@ -297,7 +296,7 @@ public function getValue(): string * @param mixed $value * @return static */ - public function setValue($value): IInputItem + public function setValue(mixed $value): IInputItem { $this->filename = $value; diff --git a/src/Pecee/Http/Input/InputHandler.php b/src/Pecee/Http/Input/InputHandler.php index 79bd6728..3b35e1b3 100644 --- a/src/Pecee/Http/Input/InputHandler.php +++ b/src/Pecee/Http/Input/InputHandler.php @@ -28,7 +28,7 @@ class InputHandler protected Request $request; /** - * Original post variables + * Original post-variables * @var array */ protected array $originalPost = []; @@ -75,8 +75,8 @@ public function parseInputs(): void $contents = file_get_contents('php://input'); - // Append any PHP-input json - if (strpos(trim($contents), '{') === 0) { + // Append any PHP input JSON + if (str_starts_with(trim($contents), '{')) { $post = json_decode($contents, true); if ($post !== false) { @@ -102,7 +102,7 @@ public function parseInputs(): void /** * @param array $files Array with files to parse - * @param string|null $parentKey Key from parent (used when parsing nested array). + * @param string|null $parentKey Key from parent (used when parsing a nested array). * @return array */ public function parseFiles(array $files, ?string $parentKey = null): array @@ -123,7 +123,7 @@ public function parseFiles(array $files, ?string $parentKey = null): array try { $list[$key] = InputFile::createFromArray($values + $value); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { } continue; @@ -144,7 +144,7 @@ public function parseFiles(array $files, ?string $parentKey = null): array } /** - * Rearrange multi-dimensional file object created by PHP. + * Rearrange multidimensional file object created by PHP. * * @param array $values * @param array $index @@ -154,16 +154,16 @@ public function parseFiles(array $files, ?string $parentKey = null): array protected function rearrangeFile(array $values, array &$index, ?array $original): array { $originalIndex = $index[0]; + array_shift($index); $output = []; foreach ($values as $key => $value) { - if (is_array($original['name'][$key]) === false) { + if (is_array($original['name'][$key] ?? null) === false) { try { - $file = InputFile::createFromArray([ 'index' => ($key === '' && $originalIndex !== '') ? $originalIndex : $key, 'name' => $original['name'][$key], @@ -173,7 +173,7 @@ protected function rearrangeFile(array $values, array &$index, ?array $original) 'size' => $original['size'][$key], ]); - if (isset($output[$key]) === true) { + if (isset($output[$key])) { $output[$key][] = $file; continue; } @@ -181,9 +181,7 @@ protected function rearrangeFile(array $values, array &$index, ?array $original) $output[$key] = $file; continue; - } catch (InvalidArgumentException $e) { - - } + } catch (InvalidArgumentException) {} } $index[] = $key; @@ -202,7 +200,7 @@ protected function rearrangeFile(array $values, array &$index, ?array $original) } /** - * Parse input item from array + * Parse input item from an array * * @param array $array * @return array @@ -225,20 +223,21 @@ protected function parseInputItem(array $array): array } /** - * Find input object + * Find an input object * * @param string $index - * @param array ...$methods - * @return IInputItem|array|null + * @param mixed ...$methods + * @return array|InputFile|InputItem|string|null */ - public function find(string $index, ...$methods) + public function find(string $index, mixed ...$methods): InputFile|InputItem|array|string|null { $element = null; if (count($methods) > 0) { - $methods = is_array(...$methods) ? array_values(...$methods) : $methods; + $methods = array_values($methods); } + if (count($methods) === 0 || in_array(Request::REQUEST_TYPE_GET, $methods, true) === true) { $element = $this->get($index); } @@ -274,11 +273,11 @@ protected function getValueFromArray(array $array): array * Get input element value matching index * * @param string $index - * @param string|mixed|null $defaultValue + * @param mixed|null $defaultValue * @param array ...$methods - * @return string|array + * @return IInputItem|InputFile|InputItem|array|string|null */ - public function value(string $index, $defaultValue = null, ...$methods) + public function value(string $index, mixed $defaultValue = null, ...$methods): IInputItem|InputFile|InputItem|array|string|null { $input = $this->find($index, ...$methods); @@ -297,16 +296,16 @@ public function value(string $index, $defaultValue = null, ...$methods) } /** - * Check if a input-item exist. - * If an array is as $index parameter the method returns true if all elements exist. + * Check if an input-item exists. + * If an array is as $index parameter, the method returns true if all elements exist. * - * @param string|array $index + * @param array|string $index * @param array ...$methods * @return bool */ - public function exists($index, ...$methods): bool + public function exists(array|string $index, ...$methods): bool { - // Check array + // Check an array if (is_array($index) === true) { foreach ($index as $key) { if ($this->value($key, null, ...$methods) === null) { @@ -327,7 +326,7 @@ public function exists($index, ...$methods): bool * @param mixed|null $defaultValue * @return InputItem|array|string|null */ - public function post(string $index, $defaultValue = null) + public function post(string $index, mixed $defaultValue = null): InputItem|array|string|null { return $this->post[$index] ?? $defaultValue; } @@ -339,7 +338,7 @@ public function post(string $index, $defaultValue = null) * @param mixed|null $defaultValue * @return InputFile|array|string|null */ - public function file(string $index, $defaultValue = null) + public function file(string $index, mixed $defaultValue = null): InputFile|array|string|null { return $this->file[$index] ?? $defaultValue; } @@ -351,13 +350,13 @@ public function file(string $index, $defaultValue = null) * @param mixed|null $defaultValue * @return InputItem|array|string|null */ - public function get(string $index, $defaultValue = null) + public function get(string $index, mixed $defaultValue = null): InputItem|array|string|null { return $this->get[$index] ?? $defaultValue; } /** - * Get all get/post items + * Get all get- / post-items * @param array $filter Only take items in filter * @return array */ @@ -409,7 +408,7 @@ public function addFile(string $key, InputFile $item): void } /** - * Get original post variables + * Get original post-variables * @return array */ public function getOriginalPost(): array @@ -418,7 +417,7 @@ public function getOriginalPost(): array } /** - * Set original post variables + * Set original post-variables * @param array $post * @return static $this */ diff --git a/src/Pecee/Http/Input/InputItem.php b/src/Pecee/Http/Input/InputItem.php index 4d574a83..4a095e70 100644 --- a/src/Pecee/Http/Input/InputItem.php +++ b/src/Pecee/Http/Input/InputItem.php @@ -5,6 +5,7 @@ use ArrayAccess; use ArrayIterator; use IteratorAggregate; +use ReturnTypeWillChange; class InputItem implements ArrayAccess, IInputItem, IteratorAggregate { @@ -14,13 +15,13 @@ class InputItem implements ArrayAccess, IInputItem, IteratorAggregate /** * @var mixed|null */ - public $value; + public mixed $value; /** * @param string $index - * @param mixed $value + * @param mixed|null $value */ - public function __construct(string $index, $value = null) + public function __construct(string $index, mixed $value = null) { $this->index = $index; $this->value = $value; @@ -45,7 +46,7 @@ public function setIndex(string $index): IInputItem } /** - * @return string + * @return string|null */ public function getName(): ?string { @@ -67,7 +68,7 @@ public function setName(string $name): IInputItem /** * @return mixed */ - public function getValue() + public function getValue(): mixed { return $this->value; } @@ -77,7 +78,7 @@ public function getValue() * @param mixed $value * @return static */ - public function setValue($value): IInputItem + public function setValue(mixed $value): IInputItem { $this->value = $value; @@ -89,7 +90,7 @@ public function offsetExists($offset): bool return isset($this->value[$offset]); } - #[\ReturnTypeWillChange] + #[ReturnTypeWillChange] public function offsetGet($offset): ?self { if ($this->offsetExists($offset) === true) { diff --git a/src/Pecee/Http/Middleware/BaseCsrfVerifier.php b/src/Pecee/Http/Middleware/BaseCsrfVerifier.php index f9ce3fea..7ae43d8d 100644 --- a/src/Pecee/Http/Middleware/BaseCsrfVerifier.php +++ b/src/Pecee/Http/Middleware/BaseCsrfVerifier.php @@ -17,13 +17,13 @@ class BaseCsrfVerifier implements IMiddleware * For example: /admin/* * @var array|null */ - protected array $except = []; + protected ?array $except = []; /** * Urls to include. Can be used to include urls from a certain path. * @var array|null */ - protected array $include = []; + protected ?array $include = []; /** * @var ITokenProvider @@ -98,7 +98,7 @@ protected function skip(Request $request): bool */ public function handle(Request $request): void { - if ($this->skip($request) === false && ($request->isPostBack() === true || $request->isPostBack() === true && $this->isIncluded($request) === true)) { + if (!$this->skip($request) && ($request->isPostBack() || $request->isPostBack() && $this->isIncluded($request))) { $token = $request->getInputHandler()->value( static::POST_KEY, diff --git a/src/Pecee/Http/Middleware/IpRestrictAccess.php b/src/Pecee/Http/Middleware/IpRestrictAccess.php index 475880cd..8ff4265a 100644 --- a/src/Pecee/Http/Middleware/IpRestrictAccess.php +++ b/src/Pecee/Http/Middleware/IpRestrictAccess.php @@ -20,7 +20,7 @@ protected function validate(string $ip): bool foreach ($this->ipBlacklist as $blackIp) { // Blocks range (8.8.*) - if ($blackIp[strlen($blackIp) - 1] === '*' && strpos($ip, trim($blackIp, '*')) === 0) { + if ($blackIp[strlen($blackIp) - 1] === '*' && str_starts_with($ip, trim($blackIp, '*'))) { return false; } diff --git a/src/Pecee/Http/Request.php b/src/Pecee/Http/Request.php index e9f97422..fe3c34bc 100644 --- a/src/Pecee/Http/Request.php +++ b/src/Pecee/Http/Request.php @@ -2,10 +2,12 @@ namespace Pecee\Http; +use Closure; use Pecee\Http\Exceptions\MalformedUrlException; use Pecee\Http\Input\InputHandler; use Pecee\Http\Middleware\BaseCsrfVerifier; use Pecee\SimpleRouter\Route\ILoadableRoute; +use Pecee\SimpleRouter\Route\IRoute; use Pecee\SimpleRouter\Route\RouteUrl; use Pecee\SimpleRouter\SimpleRouter; @@ -99,10 +101,8 @@ class Request */ protected bool $hasPendingRewrite = false; - /** - * @var ILoadableRoute|null - */ - protected ?ILoadableRoute $rewriteRoute = null; + + protected null|ILoadableRoute|IRoute $rewriteRoute = null; /** * Rewrite url @@ -128,7 +128,7 @@ public function __construct() $this->setHost($this->getHeader('http-host')); - // Check if special IIS header exist, otherwise use default. + // Check if special IIS header exists, otherwise use default. $url = $this->getHeader('unencoded-url'); if ($url !== null) { $this->setUrl(new Url($url)); @@ -218,7 +218,7 @@ public function getHeaders(): array /** * Get id address * If $safe is false, this function will detect Proxys. But the user can edit this header to whatever he wants! - * https://stackoverflow.com/questions/3003145/how-to-get-the-client-ip-address-in-php#comment-25086804 + * Https://stackoverflow.com/questions/3003145/how-to-get-the-client-ip-address-in-php#comment-25086804 * @param bool $safeMode When enabled, only safe non-spoofable headers will be returned. Note this can cause issues when using proxy. * @return string|null */ @@ -271,22 +271,22 @@ public function getUserAgent(): ?string * Get header value by name * * @param string $name Name of the header. - * @param string|mixed|null $defaultValue Value to be returned if header is not found. + * @param mixed|null $defaultValue Value to be returned if header is not found. * @param bool $tryParse When enabled the method will try to find the header from both from client (http) and server-side variants, if the header is not found. * * @return string|null */ - public function getHeader(string $name, $defaultValue = null, bool $tryParse = true): ?string + public function getHeader(string $name, mixed $defaultValue = null, bool $tryParse = true): ?string { $name = strtolower($name); $header = $this->headers[$name] ?? null; if ($tryParse === true && $header === null) { - if (strpos($name, 'http-') === 0) { + if (str_starts_with($name, 'http-')) { // Trying to find client header variant which was not found, searching for header variant without http- prefix. $header = $this->headers[str_replace('http-', '', $name)] ?? null; } else { - // Trying to find server variant which was not found, searching for client variant with http- prefix. + // Trying to find server variant which was not found, searching for client variant with http-prefix. $header = $this->headers['http-' . $name] ?? null; } } @@ -301,7 +301,7 @@ public function getHeader(string $name, $defaultValue = null, bool $tryParse = t * @param mixed|null $defaultValue * @return mixed|null */ - public function getFirstHeader(array $headers, $defaultValue = null) + public function getFirstHeader(array $headers, mixed $defaultValue = null): mixed { foreach ($headers as $header) { $header = $this->getHeader($header); @@ -406,7 +406,7 @@ public function setUrl(Url $url): void public function setHost(?string $host): void { // Strip any potential ports from hostname - if (strpos((string)$host, ':') !== false) { + if (str_contains((string)$host, ':')) { $host = strstr($host, strrchr($host, ':'), true); } @@ -438,9 +438,9 @@ public function setRewriteRoute(ILoadableRoute $route): self /** * Get rewrite route * - * @return ILoadableRoute|null + * @return ILoadableRoute|IRoute|null */ - public function getRewriteRoute(): ?ILoadableRoute + public function getRewriteRoute(): null|ILoadableRoute|IRoute { return $this->rewriteRoute; } @@ -471,10 +471,10 @@ public function setRewriteUrl(string $rewriteUrl): self /** * Set rewrite callback - * @param string|\Closure $callback + * @param string|Closure $callback * @return static */ - public function setRewriteCallback($callback): self + public function setRewriteCallback(string|Closure $callback): self { $this->hasPendingRewrite = true; @@ -546,17 +546,17 @@ public function setHasPendingRewrite(bool $boolean): self return $this; } - public function __isset($name): bool + public function __isset(mixed $name): bool { return array_key_exists($name, $this->data) === true; } - public function __set($name, $value = null) + public function __set(string $name, mixed $value = null) { $this->data[$name] = $value; } - public function __get($name) + public function __get(string $name): mixed { return $this->data[$name] ?? null; } diff --git a/src/Pecee/Http/Response.php b/src/Pecee/Http/Response.php index 5e6ca474..42b9318b 100644 --- a/src/Pecee/Http/Response.php +++ b/src/Pecee/Http/Response.php @@ -2,6 +2,7 @@ namespace Pecee\Http; +use JetBrains\PhpStorm\NoReturn; use JsonSerializable; use Pecee\Exceptions\InvalidArgumentException; @@ -33,7 +34,7 @@ public function httpCode(int $code): self * @param string $url * @param ?int $httpCode * - * @return never + * @return void */ public function redirect(string $url, ?int $httpCode = null): void { @@ -92,12 +93,8 @@ public function cache(string $eTag, int $lastModifiedTime = 2592000): self * @param int $dept JSON debt. * @throws InvalidArgumentException */ - public function json($value, int $options = 0, int $dept = 512): void + public function json(array|JsonSerializable $value, int $options = 0, 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.'); - } - $this->header('Content-Type: application/json; charset=utf-8'); echo json_encode($value, $options, $dept); exit(0); diff --git a/src/Pecee/Http/Security/CookieTokenProvider.php b/src/Pecee/Http/Security/CookieTokenProvider.php index b7489538..1536f98c 100644 --- a/src/Pecee/Http/Security/CookieTokenProvider.php +++ b/src/Pecee/Http/Security/CookieTokenProvider.php @@ -10,7 +10,7 @@ class CookieTokenProvider implements ITokenProvider public const CSRF_KEY = 'CSRF-TOKEN'; /** - * @var string + * @var string|null */ protected ?string $token = null; @@ -64,7 +64,7 @@ public function validate(string $token): bool /** * Set csrf token cookie - * Overwrite this method to save the token to another storage like session etc. + * Overwrite this method to save the token to another storage like session, etc. * * @param string $token */ diff --git a/src/Pecee/Http/Url.php b/src/Pecee/Http/Url.php index 7b15ae4f..9b31321b 100644 --- a/src/Pecee/Http/Url.php +++ b/src/Pecee/Http/Url.php @@ -10,7 +10,7 @@ class Url implements JsonSerializable /** * @var string|null */ - private ?string $originalUrl = null; + private ?string $originalUrl; /** * @var string|null @@ -70,6 +70,9 @@ public function __construct(?string $url) $this->parse($url, true); } + /** + * @throws MalformedUrlException + */ public function parse(?string $url, bool $setOriginalPath = false): self { if ($url !== null) { @@ -170,16 +173,6 @@ public function setHost(string $host): self return $this; } - /** - * Get url port - * - * @return int|null - */ - public function getPort(): ?int - { - return ($this->port !== null) ? (int)$this->port : null; - } - /** * Set the port of the url * @@ -239,8 +232,8 @@ public function setPassword(string $password): self } /** - * Get path from url - * @return string + * Get a path from url + * @return string|null */ public function getPath(): ?string { @@ -248,7 +241,7 @@ public function getPath(): ?string } /** - * Get original path with no sanitization of ending trail/slash. + * Get an original path with no sanitization of ending trail/slash. * @return string|null */ public function getOriginalPath(): ?string @@ -467,7 +460,7 @@ static function ($matches): string { } /** - * Convert array to query-string params + * Convert an array to query-string params * * @param array $getParams * @param bool $includeEmpty diff --git a/src/Pecee/SimpleRouter/ClassLoader/ClassLoader.php b/src/Pecee/SimpleRouter/ClassLoader/ClassLoader.php index 82e18eea..2c27d881 100644 --- a/src/Pecee/SimpleRouter/ClassLoader/ClassLoader.php +++ b/src/Pecee/SimpleRouter/ClassLoader/ClassLoader.php @@ -13,7 +13,7 @@ class ClassLoader implements IClassLoader * @return object * @throws ClassNotFoundHttpException */ - public function loadClass(string $class) + public function loadClass(string $class): object { if (class_exists($class) === false) { throw new ClassNotFoundHttpException($class, null, sprintf('Class "%s" does not exist', $class), 404, null); @@ -29,7 +29,7 @@ public function loadClass(string $class) * @param array $parameters * @return string */ - public function loadClassMethod($class, string $method, array $parameters): string + public function loadClassMethod(object $class, string $method, array $parameters): string { return (string)call_user_func_array([$class, $method], array_values($parameters)); } diff --git a/src/Pecee/SimpleRouter/ClassLoader/IClassLoader.php b/src/Pecee/SimpleRouter/ClassLoader/IClassLoader.php index e8c60507..35918bb6 100644 --- a/src/Pecee/SimpleRouter/ClassLoader/IClassLoader.php +++ b/src/Pecee/SimpleRouter/ClassLoader/IClassLoader.php @@ -10,7 +10,7 @@ interface IClassLoader * @param string $class * @return object */ - public function loadClass(string $class); + public function loadClass(string $class): object; /** * Called when loading class method @@ -19,7 +19,7 @@ public function loadClass(string $class); * @param array $parameters * @return mixed */ - public function loadClassMethod($class, string $method, array $parameters); + public function loadClassMethod(object $class, string $method, array $parameters): mixed; /** * Called when loading method @@ -28,6 +28,6 @@ public function loadClassMethod($class, string $method, array $parameters); * @param array $parameters * @return mixed */ - public function loadClosure(Callable $closure, array $parameters); + public function loadClosure(Callable $closure, array $parameters): mixed; } \ No newline at end of file diff --git a/src/Pecee/SimpleRouter/Event/EventArgument.php b/src/Pecee/SimpleRouter/Event/EventArgument.php index 2638c78c..01c76142 100644 --- a/src/Pecee/SimpleRouter/Event/EventArgument.php +++ b/src/Pecee/SimpleRouter/Event/EventArgument.php @@ -94,7 +94,7 @@ public function __isset(string $name): bool * @param mixed $value * @throws InvalidArgumentException */ - public function __set(string $name, $value): void + public function __set(string $name, mixed $value): void { throw new InvalidArgumentException('Not supported'); } diff --git a/src/Pecee/SimpleRouter/Handlers/CallbackExceptionHandler.php b/src/Pecee/SimpleRouter/Handlers/CallbackExceptionHandler.php index 7397d22a..b5d736ba 100644 --- a/src/Pecee/SimpleRouter/Handlers/CallbackExceptionHandler.php +++ b/src/Pecee/SimpleRouter/Handlers/CallbackExceptionHandler.php @@ -10,7 +10,7 @@ * Class CallbackExceptionHandler * * Class is used to create callbacks which are fired when an exception is reached. - * This allows for easy handling 404-exception etc. without creating an custom ExceptionHandler. + * This allows for easy handling 404-exception etc. without creating a custom ExceptionHandler. * * @package \Pecee\SimpleRouter\Handlers */ diff --git a/src/Pecee/SimpleRouter/Handlers/EventHandler.php b/src/Pecee/SimpleRouter/Handlers/EventHandler.php index 3f276b43..77ab47cc 100644 --- a/src/Pecee/SimpleRouter/Handlers/EventHandler.php +++ b/src/Pecee/SimpleRouter/Handlers/EventHandler.php @@ -9,7 +9,7 @@ class EventHandler implements IEventHandler { /** - * Fires when a event is triggered. + * Fires when an event is triggered. */ public const EVENT_ALL = '*'; @@ -19,7 +19,7 @@ class EventHandler implements IEventHandler public const EVENT_INIT = 'onInit'; /** - * Fires when all routes has been loaded and rendered, just before the output is returned. + * Fires when all routes have been loaded and rendered, just before the output is returned. */ public const EVENT_LOAD = 'onLoad'; @@ -29,13 +29,13 @@ class EventHandler implements IEventHandler public const EVENT_ADD_ROUTE = 'onAddRoute'; /** - * Fires when a url-rewrite is and just before the routes are re-initialized. + * Fires when an url-rewrite is and just before the routes are re-initialized. */ public const EVENT_REWRITE = 'onRewrite'; /** * Fires when the router is booting. - * This happens just before boot-managers are rendered and before any routes has been loaded. + * This happens just before boot-managers are rendered and before any routes have been loaded. */ public const EVENT_BOOT = 'onBoot'; @@ -52,19 +52,19 @@ class EventHandler implements IEventHandler /** * 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. + * contain a certain url, usually after the EventHandler::EVENT_GET_URL event. */ public const EVENT_FIND_ROUTE = 'onFindRoute'; /** * Fires whenever the `Router::getUrl` method or `url`-helper function - * is called and the router tries to find the route. + * is called, and the router tries to find the route. */ public const EVENT_GET_URL = 'onGetUrl'; /** - * Fires when a route is matched and valid (correct request-type etc). - * and before the route is rendered. + * Fires when a route is matched and valid (correct request-type etc.). + * And before the route is rendered. */ public const EVENT_MATCH_ROUTE = 'onMatchRoute'; @@ -79,7 +79,7 @@ class EventHandler implements IEventHandler public const EVENT_LOAD_EXCEPTIONS = 'onLoadExceptions'; /** - * Fires before the router is rendering a exception-handler. + * Fires before the router is rendering an exception-handler. */ public const EVENT_RENDER_EXCEPTION = 'onRenderException'; diff --git a/src/Pecee/SimpleRouter/Route/IGroupRoute.php b/src/Pecee/SimpleRouter/Route/IGroupRoute.php index 1b5da534..d8cb068f 100644 --- a/src/Pecee/SimpleRouter/Route/IGroupRoute.php +++ b/src/Pecee/SimpleRouter/Route/IGroupRoute.php @@ -18,13 +18,13 @@ public function matchDomain(Request $request): bool; /** * Add exception handler * - * @param IExceptionHandler|string $handler + * @param string|IExceptionHandler $handler * @return static */ - public function addExceptionHandler($handler): self; + public function addExceptionHandler(IExceptionHandler|string $handler): self; /** - * Set exception-handlers for group + * Set exception-handlers for a group * * @param array $handlers * @return static @@ -39,7 +39,7 @@ public function setExceptionHandlers(array $handlers): self; public function getMergeExceptionHandlers(): bool; /** - * When enabled group will overwrite any existing exception-handlers. + * When an enabled group will overwrite any existing exception-handlers. * * @param bool $merge * @return static @@ -47,7 +47,7 @@ public function getMergeExceptionHandlers(): bool; public function setMergeExceptionHandlers(bool $merge): self; /** - * Get exception-handlers for group + * Get exception-handlers for a group * * @return array */ @@ -61,7 +61,7 @@ public function getExceptionHandlers(): array; public function getDomains(): array; /** - * Set allowed domains for group. + * Set allowed domains for a group. * * @param array $domains * @return static @@ -77,7 +77,7 @@ public function setDomains(array $domains): self; public function prependPrefix(string $url): self; /** - * Set prefix that child-routes will inherit. + * Set the prefix that child-routes will inherit. * * @param string $prefix * @return static diff --git a/src/Pecee/SimpleRouter/Route/ILoadableRoute.php b/src/Pecee/SimpleRouter/Route/ILoadableRoute.php index 753d9596..84a24d46 100644 --- a/src/Pecee/SimpleRouter/Route/ILoadableRoute.php +++ b/src/Pecee/SimpleRouter/Route/ILoadableRoute.php @@ -16,7 +16,7 @@ interface ILoadableRoute extends IRoute * @param string|null $name * @return string */ - public function findUrl(?string $method = null, $parameters = null, ?string $name = null): string; + public function findUrl(?string $method = null, array|string $parameters = null, ?string $name = null): string; /** * Loads and renders middleware-classes @@ -72,7 +72,7 @@ public function setName(string $name): self; /** * Get regular expression match used for matching route (if defined). * - * @return string + * @return string|null */ public function getMatch(): ?string; diff --git a/src/Pecee/SimpleRouter/Route/IRoute.php b/src/Pecee/SimpleRouter/Route/IRoute.php index 4ac88dbc..8c54d686 100644 --- a/src/Pecee/SimpleRouter/Route/IRoute.php +++ b/src/Pecee/SimpleRouter/Route/IRoute.php @@ -2,7 +2,9 @@ namespace Pecee\SimpleRouter\Route; +use Closure; use Pecee\Http\Request; +use Pecee\SimpleRouter\Exceptions\NotFoundHttpException; use Pecee\SimpleRouter\Router; interface IRoute @@ -22,15 +24,15 @@ public function matchRoute(string $url, Request $request): bool; * * @param Request $request * @param Router $router - * @return string - * @throws \Pecee\SimpleRouter\Exceptions\NotFoundHttpException + * @return string|null + * @throws NotFoundHttpException */ public function renderRoute(Request $request, Router $router): ?string; /** * Returns callback name/identifier for the current route based on the callback. * Useful if you need to get a unique identifier for the loaded route, for instance - * when using translations etc. + * when using translations, etc. * * @return string */ @@ -82,15 +84,15 @@ public function setParent(IRoute $parent): self; /** * Set callback * - * @param string|array|\Closure $callback + * @param array|string|Closure $callback * @return static */ - public function setCallback($callback): self; + public function setCallback(array|string|Closure $callback): self; /** - * @return string|callable + * @return mixed */ - public function getCallback(); + public function getCallback():mixed; /** * Return active method @@ -177,14 +179,14 @@ public function setParameters(array $parameters): self; public function setSettings(array $settings, bool $merge = false): self; /** - * Export route settings to array so they can be merged with another route. + * Export route settings to array, so they can be merged with another route. * * @return array */ public function toArray(): array; /** - * Get middlewares array + * Get a middlewares array * * @return array */ @@ -207,7 +209,7 @@ public function addMiddleware(string $middleware): self; public function setMiddlewares(array $middlewares): self; /** - * If enabled parameters containing null-value will not be passed along to the callback. + * If enabled, parameters containing null-value will not be passed along to the callback. * * @param bool $enabled * @return static $this diff --git a/src/Pecee/SimpleRouter/Route/LoadableRoute.php b/src/Pecee/SimpleRouter/Route/LoadableRoute.php index 72d88f9c..be00f23d 100644 --- a/src/Pecee/SimpleRouter/Route/LoadableRoute.php +++ b/src/Pecee/SimpleRouter/Route/LoadableRoute.php @@ -16,7 +16,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute protected string $url; /** - * @var string + * @var string|null */ protected ?string $name = null; @@ -48,15 +48,15 @@ public function loadMiddleware(Request $request, Router $router): void $className = get_class($middleware); - $router->debug('Loading middleware "%s"', $className); + $router->debug('Loading middleware "%s"', [$className]); $middleware->handle($request); - $router->debug('Finished loading middleware "%s"', $className); + $router->debug('Finished loading middleware "%s"', [$className]); } $router->debug('Finished loading middlewares'); } - public function matchRegex(Request $request, $url): ?bool + public function matchRegex(string $url): bool|null { /* Match on custom defined regular expression */ if ($this->regex === null) { @@ -84,7 +84,7 @@ public function setUrl(string $url): ILoadableRoute $this->url = ($url === '/') ? '/' : '/' . trim($url, '/') . '/'; $parameters = []; - if (strpos($this->url, $this->paramModifiers[0]) !== false) { + if (str_contains($this->url, $this->paramModifiers[0])) { $regex = sprintf(static::PARAMETERS_REGEX_FORMAT, $this->paramModifiers[0], $this->paramOptionalSymbol, $this->paramModifiers[1]); @@ -131,11 +131,11 @@ protected function matchGroup(string $url, Request $request): bool * Used when calling the url() helper. * * @param string|null $method - * @param string|array|null $parameters + * @param array|string|null $parameters * @param string|null $name * @return string */ - public function findUrl(?string $method = null, $parameters = null, ?string $name = null): string + public function findUrl(?string $method = null, array|string $parameters = null, ?string $name = null): string { $url = $this->getUrl(); @@ -186,7 +186,7 @@ public function findUrl(?string $method = null, $parameters = null, ?string $nam /** * Returns the provided name for the router. * - * @return string + * @return string|null */ public function getName(): ?string { @@ -231,11 +231,11 @@ public function getMatch(): string * Sets the router name, which makes it easier to obtain the url or router at a later point. * Alias for LoadableRoute::setName(). * - * @param string|array $name + * @param array|string $name * @return static * @see LoadableRoute::setName() */ - public function name($name): ILoadableRoute + public function name(array|string $name): ILoadableRoute { return $this->setName($name); } diff --git a/src/Pecee/SimpleRouter/Route/Route.php b/src/Pecee/SimpleRouter/Route/Route.php index 3ddf03f4..90d13c84 100644 --- a/src/Pecee/SimpleRouter/Route/Route.php +++ b/src/Pecee/SimpleRouter/Route/Route.php @@ -2,6 +2,7 @@ namespace Pecee\SimpleRouter\Route; +use Closure; use Pecee\Http\Request; use Pecee\SimpleRouter\Exceptions\ClassNotFoundHttpException; use Pecee\SimpleRouter\Exceptions\NotFoundHttpException; @@ -13,7 +14,7 @@ abstract class Route implements IRoute protected const PARAMETERS_DEFAULT_REGEX = '[\w-]+'; /** - * If enabled parameters containing null-value + * If enabled, parameters containing null-value * will not be passed along to the callback. * * @var bool @@ -21,7 +22,7 @@ abstract class Route implements IRoute protected bool $filterEmptyParams = true; /** - * If true the last parameter of the route will include ending trail/slash. + * If true, the last parameter of the route will include ending trail/slash. * @var bool */ protected bool $slashParameterEnabled = false; @@ -60,14 +61,10 @@ abstract class Route implements IRoute */ public function renderRoute(Request $request, Router $router): ?string { - $router->debug('Starting rendering route "%s"', get_class($this)); + $router->debug('Starting rendering route "%s"', [get_class($this)]); $callback = $this->getCallback(); - if ($callback === null) { - return null; - } - $router->debug('Parsing parameters'); $parameters = $this->getParameters(); @@ -101,7 +98,7 @@ public function renderRoute(Request $request, Router $router): ?string $namespace = $this->getNamespace(); $className = ($namespace !== null && $controller[0] !== '\\') ? $namespace . '\\' . $controller : $controller; - $router->debug('Loading class %s', $className); + $router->debug('Loading class %s', [$className]); $class = $router->getClassLoader()->loadClass($className); if ($method === null) { @@ -112,14 +109,14 @@ public function renderRoute(Request $request, Router $router): ?string throw new ClassNotFoundHttpException($className, $method, sprintf('Method "%s" does not exist in class "%s"', $method, $className), 404, null); } - $router->debug('Executing callback %s -> %s', $className, $method); + $router->debug('Executing callback %s -> %s', [$className, $method]); return $router->getClassLoader()->loadClassMethod($class, $method, $parameters); } - protected function parseParameters($route, $url, Request $request, $parameterRegex = null): ?array + protected function parseParameters(mixed $route, string $url, Request $request, mixed $parameterRegex = null): array|null { - $regex = (strpos($route, $this->paramModifiers[0]) === false) ? null : + $regex = (!str_contains($route, $this->paramModifiers[0])) ? null : sprintf ( static::PARAMETERS_REGEX_FORMAT, @@ -162,7 +159,7 @@ protected function parseParameters($route, $url, Request $request, $parameterReg } } - // Get name of last param + // Get the name of last param if (trim($urlRegex) === '' || (bool)preg_match(sprintf($this->urlRegex, $urlRegex), $url, $matches) === false) { return null; } @@ -177,6 +174,7 @@ protected function parseParameters($route, $url, Request $request, $parameterReg /* Only take matched parameters with name */ $originalPath = $request->getUrl()->getOriginalPath(); + foreach ((array)$parameters[1] as $i => $name) { // Ignore parent parameters @@ -185,7 +183,8 @@ protected function parseParameters($route, $url, Request $request, $parameterReg continue; } - // If last parameter and slash parameter is enabled, use slash according to original path (non sanitized version) + // If the last parameter and slash parameter is enabled, use slash according to an original path + //(non-sanitized version) $lastParameter = $this->paramModifiers[0] . $name . $this->paramModifiers[1] . '/'; if ($this->slashParameterEnabled && ($i === count($parameters[1]) - 1) && (substr_compare($route, $lastParameter, -strlen($lastParameter)) === 0) && $originalPath[strlen($originalPath) - 1] === '/') { $matches[$name] .= '/'; @@ -205,13 +204,13 @@ protected function parseParameters($route, $url, Request $request, $parameterReg /** * Returns callback name/identifier for the current route based on the callback. * Useful if you need to get a unique identifier for the loaded route, for instance - * when using translations etc. + * when using translations, etc. * * @return string */ public function getIdentifier(): string { - if (is_string($this->callback) === true && strpos($this->callback, '@') !== false) { + if (is_string($this->callback) === true && str_contains($this->callback, '@')) { return $this->callback; } @@ -290,10 +289,10 @@ public function setParent(IRoute $parent): IRoute /** * Set callback * - * @param string|array|\Closure $callback + * @param array|string|Closure $callback * @return static */ - public function setCallback($callback): IRoute + public function setCallback(array|string|Closure $callback): IRoute { $this->callback = $callback; @@ -301,9 +300,9 @@ public function setCallback($callback): IRoute } /** - * @return string|callable|null + * @return mixed */ - public function getCallback() + public function getCallback(): mixed { return $this->callback; } @@ -314,7 +313,7 @@ public function getMethod(): ?string return $this->callback[1]; } - if (is_string($this->callback) === true && strpos($this->callback, '@') !== false) { + if (is_string($this->callback) === true && str_contains($this->callback, '@')) { $tmp = explode('@', $this->callback); return $tmp[1]; @@ -329,7 +328,7 @@ public function getClass(): ?string return $this->callback[0]; } - if (is_string($this->callback) === true && strpos($this->callback, '@') !== false) { + if (is_string($this->callback) === true && str_contains($this->callback, '@')) { $tmp = explode('@', $this->callback); return $tmp[0]; @@ -366,7 +365,7 @@ public function setNamespace(string $namespace): IRoute $ns = $this->getNamespace(); if ($ns !== null) { - // Don't overwrite namespaces that starts with \ + // Don't overwrite namespaces that start with \ if ($ns[0] !== '\\') { $namespace .= '\\' . $ns; } else { @@ -415,7 +414,7 @@ public function getSlashParameterEnabled(): bool } /** - * Export route settings to array so they can be merged with another route. + * Export route settings to array, so they can be merged with another route. * * @return array */ @@ -519,10 +518,10 @@ public function setWhere(array $options): IRoute * Alias for LoadableRoute::where() * * @param array $options - * @return static + * @return IRoute|Route * @see LoadableRoute::where() */ - public function where(array $options) + public function where(array $options): IRoute|static { return $this->setWhere($options); } @@ -562,7 +561,7 @@ public function setParameters(array $parameters): IRoute * * @param string $middleware * @return static - * @deprecated This method is deprecated and will be removed in the near future. + * @deprecated This method is deprecated and will be removed soon. */ public function setMiddleware(string $middleware): self { @@ -606,7 +605,7 @@ public function getMiddlewares(): array } /** - * Set default regular expression used when matching parameters. + * Set the default regular expression used when matching parameters. * This is used when no custom parameter regex is found. * * @param string $regex @@ -620,7 +619,7 @@ public function setDefaultParameterRegex(string $regex): self } /** - * Get default regular expression used when matching parameters. + * Get the default regular expression used when matching parameters. * * @return string */ @@ -630,7 +629,7 @@ public function getDefaultParameterRegex(): string } /** - * If enabled parameters containing null-value will not be passed along to the callback. + * If enabled, parameters containing null-value will not be passed along to the callback. * * @param bool $enabled * @return static $this diff --git a/src/Pecee/SimpleRouter/Route/RouteController.php b/src/Pecee/SimpleRouter/Route/RouteController.php index ca48a92d..1b8a09bf 100644 --- a/src/Pecee/SimpleRouter/Route/RouteController.php +++ b/src/Pecee/SimpleRouter/Route/RouteController.php @@ -12,7 +12,7 @@ class RouteController extends LoadableRoute implements IControllerRoute protected ?string $method = null; protected array $names = []; - public function __construct($url, $controller) + public function __construct(string $url, string $controller) { $this->setUrl($url); $this->setName(trim(str_replace('/', '.', $url), '/')); @@ -32,7 +32,7 @@ public function hasName(string $name): bool } /* Remove method/type */ - if (strpos($name, '.') !== false) { + if (str_contains($name, '.')) { $method = substr($name, strrpos($name, '.') + 1); $newName = substr($name, 0, strrpos($name, '.')); @@ -46,13 +46,13 @@ public function hasName(string $name): bool /** * @param string|null $method - * @param string|array|null $parameters + * @param array|string|null $parameters * @param string|null $name * @return string */ - public function findUrl(?string $method = null, $parameters = null, ?string $name = null): string + public function findUrl(?string $method = null, array|string $parameters = null, ?string $name = null): string { - if (strpos($name, '.') !== false) { + if (str_contains($name, '.')) { $found = array_search(substr($name, strrpos($name, '.') + 1), $this->names, true); if ($found !== false) { $method = (string)$found; @@ -64,7 +64,7 @@ public function findUrl(?string $method = null, $parameters = null, ?string $nam if ($method !== null) { - /* Remove requestType from method-name, if it exists */ + /* Remove requestType from method-name if it exists */ foreach (Request::$requestTypes as $requestType) { if (stripos($method, $requestType) === 0) { @@ -96,7 +96,7 @@ public function matchRoute(string $url, Request $request): bool } /* Match global regular-expression for route */ - $regexMatch = $this->matchRegex($request, $url); + $regexMatch = $this->matchRegex($url); if ($regexMatch === false || (stripos($url, $this->url) !== 0 && strtoupper($url) !== strtoupper($this->url))) { return false; @@ -105,20 +105,18 @@ public function matchRoute(string $url, Request $request): bool $strippedUrl = trim(str_ireplace($this->url, '/', $url), '/'); $path = explode('/', $strippedUrl); - if (count($path) !== 0) { + if (count($path) === 0) return false; - $method = (isset($path[0]) === false || trim($path[0]) === '') ? $this->defaultMethod : $path[0]; - $this->method = $request->getMethod() . ucfirst($method); + $method = (isset($path[0]) === false || trim($path[0]) === '') ? $this->defaultMethod : $path[0]; - $this->parameters = array_slice($path, 1); + $this->method = $request->getMethod() . ucfirst($method); - // Set callback - $this->setCallback([$this->controller, $this->method]); + $this->parameters = array_slice($path, 1); - return true; - } + // Set callback + $this->setCallback([$this->controller, $this->method]); - return false; + return true; } /** diff --git a/src/Pecee/SimpleRouter/Route/RouteGroup.php b/src/Pecee/SimpleRouter/Route/RouteGroup.php index bcba62fa..780e952c 100644 --- a/src/Pecee/SimpleRouter/Route/RouteGroup.php +++ b/src/Pecee/SimpleRouter/Route/RouteGroup.php @@ -88,10 +88,10 @@ public function matchRoute(string $url, Request $request): bool /** * Add exception handler * - * @param IExceptionHandler|string $handler + * @param string|IExceptionHandler $handler * @return static */ - public function addExceptionHandler($handler): IGroupRoute + public function addExceptionHandler(IExceptionHandler|string $handler): IGroupRoute { $this->exceptionHandlers[] = $handler; @@ -99,7 +99,8 @@ public function addExceptionHandler($handler): IGroupRoute } /** - * Set exception-handlers for group + * Set exception-handlers for + * a group * * @param array $handlers * @return static @@ -112,7 +113,7 @@ public function setExceptionHandlers(array $handlers): IGroupRoute } /** - * Get exception-handlers for group + * Get exception-handlers for a group * * @return array */ @@ -132,7 +133,7 @@ public function getDomains(): array } /** - * Set allowed domains for group. + * Set allowed domains for a group. * * @param array $domains * @return static @@ -167,7 +168,7 @@ public function prependPrefix(string $url): IGroupRoute } /** - * Set prefix that child-routes will inherit. + * Set the prefix that child-routes will inherit. * * @return string|null */ @@ -177,7 +178,7 @@ public function getPrefix(): ?string } /** - * When enabled group will overwrite any existing exception-handlers. + * When an enabled group will overwrite any existing exception-handlers. * * @param bool $merge * @return static @@ -239,7 +240,7 @@ public function setSettings(array $settings, bool $merge = false): IRoute } /** - * Export route settings to array so they can be merged with another route. + * Export route settings to array, so they can be merged with another route. * * @return array */ diff --git a/src/Pecee/SimpleRouter/Route/RouteResource.php b/src/Pecee/SimpleRouter/Route/RouteResource.php index b797fd94..ea7b1a5f 100644 --- a/src/Pecee/SimpleRouter/Route/RouteResource.php +++ b/src/Pecee/SimpleRouter/Route/RouteResource.php @@ -30,7 +30,7 @@ class RouteResource extends LoadableRoute implements IControllerRoute protected array $names = []; protected string $controller; - public function __construct($url, $controller) + public function __construct(string $url,string $controller) { $this->setUrl($url); $this->controller = $controller; @@ -54,7 +54,7 @@ public function hasName(string $name): bool } /* Remove method/type */ - if (strpos($name, '.') !== false) { + if (str_contains($name, '.')) { $name = substr($name, 0, strrpos($name, '.')); } @@ -67,7 +67,7 @@ public function hasName(string $name): bool * @param string|null $name * @return string */ - public function findUrl(?string $method = null, $parameters = null, ?string $name = null): string + public function findUrl(?string $method = null, array|string $parameters = null, ?string $name = null): string { $url = array_search($name, $this->names, true); @@ -91,7 +91,7 @@ public function findUrl(?string $method = null, $parameters = null, ?string $nam return $url; } - protected function call($method): bool + protected function call(string $method): bool { $this->setCallback([$this->controller, $method]); @@ -105,7 +105,7 @@ public function matchRoute(string $url, Request $request): bool } /* Match global regular-expression for route */ - $regexMatch = $this->matchRegex($request, $url); + $regexMatch = $this->matchRegex($url); if ($regexMatch === false || (stripos($url, $this->url) !== 0 && strtoupper($url) !== strtoupper($this->url))) { return false; @@ -117,9 +117,6 @@ public function matchRoute(string $url, Request $request): bool $this->parameters = $this->parseParameters($route, $url, $request); /* If no custom regular expression or parameters was found on this route, we stop */ - if ($regexMatch === null && $this->parameters === null) { - return false; - } $action = strtolower(trim((string)$this->parameters['action'])); $id = $this->parameters['id']; diff --git a/src/Pecee/SimpleRouter/Route/RouteUrl.php b/src/Pecee/SimpleRouter/Route/RouteUrl.php index f0e2b8a5..9c90e856 100644 --- a/src/Pecee/SimpleRouter/Route/RouteUrl.php +++ b/src/Pecee/SimpleRouter/Route/RouteUrl.php @@ -2,6 +2,7 @@ namespace Pecee\SimpleRouter\Route; +use Closure; use Pecee\Http\Request; class RouteUrl extends LoadableRoute @@ -9,9 +10,9 @@ class RouteUrl extends LoadableRoute /** * RouteUrl constructor. * @param string $url - * @param \Closure|string $callback + * @param Closure|string|array $callback */ - public function __construct(string $url, $callback) + public function __construct(string $url, Closure|string|array $callback) { $this->setUrl($url); $this->setCallback($callback); @@ -24,7 +25,7 @@ public function matchRoute(string $url, Request $request): bool } /* Match global regular-expression for route */ - $regexMatch = $this->matchRegex($request, $url); + $regexMatch = $this->matchRegex($url); if ($regexMatch === false) { return false; diff --git a/src/Pecee/SimpleRouter/Router.php b/src/Pecee/SimpleRouter/Router.php index 3e1964a3..6d8215f2 100644 --- a/src/Pecee/SimpleRouter/Router.php +++ b/src/Pecee/SimpleRouter/Router.php @@ -3,7 +3,6 @@ namespace Pecee\SimpleRouter; use Exception; -use Pecee\Exceptions\InvalidArgumentException; use Pecee\Http\Exceptions\MalformedUrlException; use Pecee\Http\Middleware\BaseCsrfVerifier; use Pecee\Http\Request; @@ -50,7 +49,6 @@ class Router /** * List of processed routes - * @var array|ILoadableRoute[] */ protected array $processedRoutes = []; @@ -118,8 +116,8 @@ class Router 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. + * When enabled, the router will render all routes that match. + * When disabled, the router will stop execution when the first route is found. * @var bool */ protected bool $renderMultipleRoutes = false; @@ -171,7 +169,7 @@ 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 + * If a route is currently being processed, that means that the route being added is rendered from the parent * routes callback, so we add them to the stack instead. */ if ($this->isProcessingRoute === true) { @@ -229,7 +227,7 @@ protected function processRoutes(array $routes, ?IGroupRoute $group = null): voi // Loop through each route-request foreach ($routes as $route) { - $this->debug('Processing route "%s"', get_class($route)); + $this->debug('Processing route "%s"', [get_class($route)]); if ($group !== null) { /* Add the parent group */ @@ -255,7 +253,7 @@ protected function processRoutes(array $routes, ?IGroupRoute $group = null): voi } } - /* Only render partial group if it matches */ + /* Only render a partial group if it matches */ if ($route instanceof IPartialGroupRoute === true) { $this->renderAndProcess($route); continue; @@ -272,7 +270,7 @@ protected function processRoutes(array $routes, ?IGroupRoute $group = null): voi if ($route instanceof ILoadableRoute === true) { - /* Add the route to the map, so we can find the active one when all routes has been loaded */ + /* Add the route to the map, so we can find the active one when all routes have been loaded */ $this->processedRoutes[] = $route; } } @@ -304,7 +302,7 @@ public function loadRoutes(): void foreach ($this->bootManagers as $manager) { $className = get_class($manager); - $this->debug('Rendering bootmanager "%s"', $className); + $this->debug('Rendering bootmanager "%s"', [$className]); $this->fireEvents(EventHandler::EVENT_RENDER_BOOTMANAGER, [ 'bootmanagers' => $this->bootManagers, 'bootmanager' => $manager, @@ -313,7 +311,7 @@ public function loadRoutes(): void /* Render bootmanager */ $manager->boot($this, $this->request); - $this->debug('Finished rendering bootmanager "%s"', $className); + $this->debug('Finished rendering bootmanager "%s"', [$className]); } $this->debug('Finished loading routes'); @@ -324,7 +322,6 @@ public function loadRoutes(): void * * @return string|null * @throws NotFoundHttpException - * @throws \Pecee\Http\Middleware\Exceptions\TokenMismatchException * @throws HttpException * @throws Exception */ @@ -380,7 +377,7 @@ public function routeRequest(): ?string /* @var $route ILoadableRoute */ foreach ($this->processedRoutes as $key => $route) { - $this->debug('Matching route "%s"', get_class($route)); + $this->debug('Matching route "%s"', [get_class($route)]); /* Add current processing route to constants */ $this->currentProcessingRoute = $route; @@ -394,7 +391,7 @@ public function routeRequest(): ?string /* Check if request method matches */ if (count($route->getRequestMethods()) !== 0 && in_array($this->request->getMethod(), $route->getRequestMethods(), true) === false) { - $this->debug('Method "%s" not allowed', $this->request->getMethod()); + $this->debug('Method "%s" not allowed', [$this->request->getMethod()]); // Only set method not allowed is not already set if ($methodNotAllowed === null) { @@ -518,7 +515,7 @@ protected function handleRouteRewrite(string $key, string $url): ?string */ protected function handleException(Exception $e): ?string { - $this->debug('Starting exception handling for "%s"', get_class($e)); + $this->debug('Starting exception handling for "%s"', [get_class($e)]); $this->fireEvents(EventHandler::EVENT_LOAD_EXCEPTIONS, [ 'exception' => $e, @@ -538,7 +535,7 @@ protected function handleException(Exception $e): ?string 'exceptionHandlers' => $this->exceptionHandlers, ]); - $this->debug('Processing exception-handler "%s"', get_class($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); @@ -586,7 +583,7 @@ protected function handleException(Exception $e): ?string */ public function findRoute(string $name): ?ILoadableRoute { - $this->debug('Finding route by name "%s"', $name); + $this->debug('Finding route by name "%s"', [$name]); $this->fireEvents(EventHandler::EVENT_FIND_ROUTE, [ 'name' => $name, @@ -596,24 +593,24 @@ public function findRoute(string $name): ?ILoadableRoute /* 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); + $this->debug('Found route "%s" by name "%s"', [$route->getUrl(), $name]); return $route; } /* Direct match to controller */ if ($route instanceof IControllerRoute && strtoupper($route->getController()) === strtoupper($name)) { - $this->debug('Found route "%s" by controller "%s"', $route->getUrl(), $name); + $this->debug('Found route "%s" by controller "%s"', [$route->getUrl(), $name]); return $route; } /* Using @ is most definitely a controller@method or alias@method */ - if (strpos($name, '@') !== false) { + if (str_contains($name, '@')) { [$controller, $method] = array_map('strtolower', explode('@', $name)); if ($controller === strtolower((string)$route->getClass()) && $method === strtolower((string)$route->getMethod())) { - $this->debug('Found route "%s" by controller "%s" and method "%s"', $route->getUrl(), $controller, $method); + $this->debug('Found route "%s" by controller "%s" and method "%s"', [$route->getUrl(), $controller, $method]); return $route; } @@ -621,18 +618,18 @@ public function findRoute(string $name): ?ILoadableRoute /* Check if callback matches (if it's not a function) */ $callback = $route->getCallback(); - if (is_string($callback) === true && is_callable($callback) === false && strpos($name, '@') !== false && strpos($callback, '@') !== false) { + if (is_string($callback) === true && is_callable($callback) === false && str_contains($name, '@') && str_contains($callback, '@')) { /* Check if the entire callback is matching */ - if (strpos($callback, $name) === 0 || strtolower($callback) === strtolower($name)) { - $this->debug('Found route "%s" by callback "%s"', $route->getUrl(), $name); + if (str_starts_with($callback, $name) || strtolower($callback) === 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); + $this->debug('Found route "%s" by class "%s"', [$route->getUrl(), $name]); return $route; } @@ -649,20 +646,20 @@ public function findRoute(string $name): ?ILoadableRoute * * The name parameter supports the following values: * - Route name - * - Controller/resource name (with or without method) + * - Controller/resource name (with or without a method) * - Controller class name * * When searching for controller/resource by name, you can use this syntax "route.name@method". * You can also use the same syntax when searching for a specific controller-class "MyController@home". - * If no arguments is specified, it will return the url for the current loaded route. + * If no arguments are specified, it will return the url for the current loaded route. * * @param string|null $name - * @param string|array|null $parameters + * @param array|string|null $parameters * @param array|null $getParams * @return Url - * @throws InvalidArgumentException + * @throws MalformedUrlException */ - public function getUrl(?string $name = null, $parameters = null, ?array $getParams = null): Url + public function getUrl(?string $name = null, array|string $parameters = null, ?array $getParams = null): Url { $this->debug('Finding url', func_get_args()); @@ -679,7 +676,7 @@ public function getUrl(?string $name = null, $parameters = null, ?array $getPara /* Only merge $_GET when all parameters are null */ $getParams = ($name === null && $parameters === null && $getParams === null) ? $_GET : (array)$getParams; - /* Return current route if no options has been specified */ + /* Return current route if no options have been specified */ if ($name === null && $parameters === null) { return $this->request ->getUrlCopy() @@ -688,7 +685,7 @@ public function getUrl(?string $name = null, $parameters = null, ?array $getPara $loadedRoute = $this->request->getLoadedRoute(); - /* If nothing is defined and a route is loaded we use that */ + /* If nothing is defined and a route is loaded, we use that */ if ($name === null && $loadedRoute !== null) { return $this->request->getUrlCopy()->parse($loadedRoute->findUrl($loadedRoute->getMethod(), $parameters, $name))->setParams($getParams); } @@ -703,7 +700,7 @@ public function getUrl(?string $name = null, $parameters = null, ?array $getPara } /* Using @ is most definitely a controller@method or alias@method */ - if (is_string($name) === true && strpos($name, '@') !== false) { + if (is_string($name) === true && str_contains($name, '@')) { [$controller, $method] = explode('@', $name); /* Loop through all the routes to see if we can find a match */ @@ -724,7 +721,7 @@ public function getUrl(?string $name = null, $parameters = null, ?array $getPara } } - /* No result so we assume that someone is using a hardcoded url and join everything together. */ + /* No result, so we assume that someone is using a hardcoded url and join everything together. */ $url = trim(implode('/', array_merge((array)$name, (array)$parameters)), '/'); $url = (($url === '') ? '/' : '/' . $url . '/'); @@ -767,7 +764,7 @@ public function addBootManager(IRouterBootManager $bootManager): self } /** - * Get routes that has been processed. + * Get routes that have been processed. * * @return array */ @@ -809,7 +806,7 @@ public function getRequest(): Request /** * Get csrf verifier class - * @return BaseCsrfVerifier + * @return BaseCsrfVerifier|null */ public function getCsrfVerifier(): ?BaseCsrfVerifier { @@ -885,17 +882,18 @@ protected function fireEvents(string $name, array $arguments = []): void } /** - * Add new debug message + * Add a new debug message * @param string $message - * @param array $args + * @param array ...$args */ - public function debug(string $message, ...$args): void + public function debug(string $message, array ...$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), @@ -926,20 +924,10 @@ public function getDebugLog(): array return $this->debugList; } - /** - * Get the current processing route details. - * - * @return ILoadableRoute - */ - public function getCurrentProcessingRoute(): ILoadableRoute - { - return $this->currentProcessingRoute; - } - /** * Changes the rendering behavior of the router. - * When enabled the router will render all routes that matches. - * When disabled the router will stop rendering at the first route that matches. + * When enabled, the router will render all routes that match. + * When disabled, the router will stop rendering at the first route that matches. * * @param bool $bool * @return $this diff --git a/src/Pecee/SimpleRouter/SimpleRouter.php b/src/Pecee/SimpleRouter/SimpleRouter.php index 2117cf6f..8347e868 100644 --- a/src/Pecee/SimpleRouter/SimpleRouter.php +++ b/src/Pecee/SimpleRouter/SimpleRouter.php @@ -12,17 +12,16 @@ use Closure; use Exception; -use Pecee\Exceptions\InvalidArgumentException; use Pecee\Http\Middleware\BaseCsrfVerifier; use Pecee\Http\Request; use Pecee\Http\Response; use Pecee\Http\Url; use Pecee\SimpleRouter\ClassLoader\IClassLoader; use Pecee\SimpleRouter\Exceptions\HttpException; +use Pecee\SimpleRouter\Exceptions\NotFoundHttpException; use Pecee\SimpleRouter\Handlers\CallbackExceptionHandler; use Pecee\SimpleRouter\Handlers\IEventHandler; use Pecee\SimpleRouter\Route\IGroupRoute; -use Pecee\SimpleRouter\Route\ILoadableRoute; use Pecee\SimpleRouter\Route\IPartialGroupRoute; use Pecee\SimpleRouter\Route\IRoute; use Pecee\SimpleRouter\Route\RouteController; @@ -47,17 +46,15 @@ class SimpleRouter /** * Router instance - * @var Router + * @var Router|null */ protected static ?Router $router = null; /** * Start routing * - * @throws \Pecee\SimpleRouter\Exceptions\NotFoundHttpException - * @throws \Pecee\Http\Middleware\Exceptions\TokenMismatchException * @throws HttpException - * @throws Exception + * @throws NotFoundHttpException */ public static function start(): void { @@ -70,7 +67,7 @@ public static function start(): void } /** - * Start the routing an return array with debugging-information + * Start the routing and return array with debugging-information * * @return array */ @@ -82,11 +79,11 @@ public static function startDebug(): array ob_start(); static::router()->setDebugEnabled(true)->start(); $routerOutput = ob_get_clean(); - } catch (Exception $e) { + } catch (Exception) { } - // Try to parse library version + // Try to parse a library version $composerFile = dirname(__DIR__, 3) . '/composer.lock'; $version = false; @@ -124,7 +121,7 @@ public static function startDebug(): array } /** - * Set default namespace which will be prepended to all routes. + * Set the default namespace which will be prepended to all routes. * * @param string $defaultNamespace */ @@ -144,7 +141,7 @@ public static function csrfVerifier(BaseCsrfVerifier $baseCsrfVerifier): void } /** - * Add new event handler to the router + * Add a new event handler to the router * * @param IEventHandler $eventHandler */ @@ -154,7 +151,7 @@ public static function addEventHandler(IEventHandler $eventHandler): void } /** - * Boot managers allows you to alter the routes before the routing occurs. + * Boot managers allow you to alter the routes before the routing occurs. * Perfect if you want to load pretty-urls from a file or database. * * @param IRouterBootManager $bootManager @@ -183,12 +180,12 @@ public static function redirect(string $where, string $to, int $httpCode = 301): * Route the given url to your callback on GET request method. * * @param string $url - * @param string|array|Closure $callback + * @param array|string|Closure $callback * @param array|null $settings * - * @return RouteUrl|IRoute + * @return IRoute */ - public static function get(string $url, $callback, array $settings = null): IRoute + public static function get(string $url, array|string|Closure $callback, array $settings = null): IRoute { return static::match([Request::REQUEST_TYPE_GET], $url, $callback, $settings); } @@ -197,11 +194,11 @@ public static function get(string $url, $callback, array $settings = null): IRou * Route the given url to your callback on POST request method. * * @param string $url - * @param string|array|Closure $callback + * @param array|string|Closure $callback * @param array|null $settings - * @return RouteUrl|IRoute + * @return IRoute */ - public static function post(string $url, $callback, array $settings = null): IRoute + public static function post(string $url, array|string|Closure $callback, array $settings = null): IRoute { return static::match([Request::REQUEST_TYPE_POST], $url, $callback, $settings); } @@ -210,11 +207,11 @@ public static function post(string $url, $callback, array $settings = null): IRo * Route the given url to your callback on PUT request method. * * @param string $url - * @param string|array|Closure $callback + * @param array|string|Closure $callback * @param array|null $settings - * @return RouteUrl|IRoute + * @return IRoute */ - public static function put(string $url, $callback, array $settings = null): IRoute + public static function put(string $url, array|string|Closure $callback, array $settings = null): IRoute { return static::match([Request::REQUEST_TYPE_PUT], $url, $callback, $settings); } @@ -223,11 +220,11 @@ public static function put(string $url, $callback, array $settings = null): IRou * Route the given url to your callback on PATCH request method. * * @param string $url - * @param string|array|Closure $callback + * @param array|string|Closure $callback * @param array|null $settings - * @return RouteUrl|IRoute + * @return IRoute */ - public static function patch(string $url, $callback, array $settings = null): IRoute + public static function patch(string $url, array|string|Closure $callback, array $settings = null): IRoute { return static::match([Request::REQUEST_TYPE_PATCH], $url, $callback, $settings); } @@ -236,11 +233,11 @@ public static function patch(string $url, $callback, array $settings = null): IR * Route the given url to your callback on OPTIONS request method. * * @param string $url - * @param string|array|Closure $callback + * @param array|string|Closure $callback * @param array|null $settings - * @return RouteUrl|IRoute + * @return IRoute */ - public static function options(string $url, $callback, array $settings = null): IRoute + public static function options(string $url, array|string|Closure $callback, array $settings = null): IRoute { return static::match([Request::REQUEST_TYPE_OPTIONS], $url, $callback, $settings); } @@ -249,11 +246,11 @@ public static function options(string $url, $callback, array $settings = null): * Route the given url to your callback on DELETE request method. * * @param string $url - * @param string|array|Closure $callback + * @param array|string|Closure $callback * @param array|null $settings - * @return RouteUrl|IRoute + * @return IRoute */ - public static function delete(string $url, $callback, array $settings = null): IRoute + public static function delete(string $url, array|string|Closure $callback, array $settings = null): IRoute { return static::match([Request::REQUEST_TYPE_DELETE], $url, $callback, $settings); } @@ -263,8 +260,7 @@ public static function delete(string $url, $callback, array $settings = null): I * * @param array $settings * @param Closure $callback - * @return RouteGroup|IGroupRoute - * @throws InvalidArgumentException + * @return IGroupRoute */ public static function group(array $settings, Closure $callback): IGroupRoute { @@ -278,14 +274,13 @@ public static function group(array $settings, Closure $callback): IGroupRoute } /** - * Special group that has the same benefits as group but supports + * A Special group that has the same benefits as a group but supports * parameters and which are only rendered when the url matches. * * @param string $url * @param Closure $callback * @param array $settings - * @return RoutePartialGroup|IPartialGroupRoute - * @throws InvalidArgumentException + * @return IPartialGroupRoute */ public static function partialGroup(string $url, Closure $callback, array $settings = []): IPartialGroupRoute { @@ -304,12 +299,12 @@ public static function partialGroup(string $url, Closure $callback, array $setti * Alias for the form method * * @param string $url - * @param string|array|Closure $callback + * @param array|string|Closure $callback * @param array|null $settings - * @return RouteUrl|IRoute + * @return IRoute * @see SimpleRouter::form */ - public static function basic(string $url, $callback, array $settings = null): IRoute + public static function basic(string $url, array|string|Closure $callback, array $settings = null): IRoute { return static::form($url, $callback, $settings); } @@ -319,12 +314,12 @@ public static function basic(string $url, $callback, array $settings = null): IR * Route the given url to your callback on POST and GET request method. * * @param string $url - * @param string|array|Closure $callback + * @param array|string|Closure $callback * @param array|null $settings - * @return RouteUrl|IRoute + * @return IRoute * @see SimpleRouter::form */ - public static function form(string $url, $callback, array $settings = null): IRoute + public static function form(string $url, array|string|Closure $callback, array $settings = null): IRoute { return static::match([ Request::REQUEST_TYPE_GET, @@ -337,11 +332,11 @@ public static function form(string $url, $callback, array $settings = null): IRo * * @param array $requestMethods * @param string $url - * @param string|array|Closure $callback + * @param array|string|Closure $callback * @param array|null $settings - * @return RouteUrl|IRoute + * @return IRoute */ - public static function match(array $requestMethods, string $url, $callback, array $settings = null): IRoute + public static function match(array $requestMethods, string $url, array|string|Closure $callback, array $settings = null): IRoute { $route = new RouteUrl($url, $callback); $route->setRequestMethods($requestMethods); @@ -357,11 +352,11 @@ public static function match(array $requestMethods, string $url, $callback, arra * This type will route the given url to your callback and allow any type of request method * * @param string $url - * @param string|array|Closure $callback + * @param array|string|Closure $callback * @param array|null $settings - * @return RouteUrl|IRoute + * @return IRoute */ - public static function all(string $url, $callback, array $settings = null): IRoute + public static function all(string $url, array|string|Closure $callback, array $settings = null): IRoute { $route = new RouteUrl($url, $callback); @@ -378,7 +373,7 @@ public static function all(string $url, $callback, array $settings = null): IRou * @param string $url * @param string $controller * @param array|null $settings - * @return RouteController|IRoute + * @return IRoute */ public static function controller(string $url, string $controller, array $settings = null): IRoute { @@ -397,7 +392,7 @@ public static function controller(string $url, string $controller, array $settin * @param string $url * @param string $controller * @param array|null $settings - * @return RouteResource|IRoute + * @return IRoute */ public static function resource(string $url, string $controller, array $settings = null): IRoute { @@ -430,23 +425,23 @@ public static function error(Closure $callback): CallbackExceptionHandler * * The name parameter supports the following values: * - Route name - * - Controller/resource name (with or without method) + * - Controller/resource name (with or without a method) * - Controller class name * * When searching for controller/resource by name, you can use this syntax "route.name@method". * You can also use the same syntax when searching for a specific controller-class "MyController@home". - * If no arguments is specified, it will return the url for the current loaded route. + * If no arguments are specified, it will return the url for the current loaded route. * * @param string|null $name - * @param string|array|null $parameters + * @param array|string|null $parameters * @param array|null $getParams * @return Url */ - public static function getUrl(?string $name = null, $parameters = null, ?array $getParams = null): Url + public static function getUrl(?string $name = null, array|string $parameters = null, ?array $getParams = null): Url { try { return static::router()->getUrl($name, $parameters, $getParams); - } catch (Exception $e) { + } catch (Exception) { return new Url('/'); } } @@ -492,8 +487,8 @@ public static function router(): Router /** * Prepends the default namespace to all new routes added. * - * @param ILoadableRoute|IRoute $route - * @return IRoute|ILoadableRoute + * @param IRoute $route + * @return IRoute */ public static function addDefaultNamespace(IRoute $route): IRoute { @@ -506,8 +501,8 @@ public static function addDefaultNamespace(IRoute $route): IRoute /** * Changes the rendering behavior of the router. - * When enabled the router will render all routes that matches. - * When disabled the router will stop rendering at the first route that matches. + * When enabled, the router will render all routes that match. + * When disabled, the router will stop rendering at the first route that matches. * * @param bool $bool */ diff --git a/tests/Pecee/SimpleRouter/CsrfVerifierTest.php b/tests/Pecee/SimpleRouter/CsrfVerifierTest.php index 4d05b161..3637de5b 100644 --- a/tests/Pecee/SimpleRouter/CsrfVerifierTest.php +++ b/tests/Pecee/SimpleRouter/CsrfVerifierTest.php @@ -1,17 +1,24 @@ getToken(); + $_POST[BaseCsrfVerifier::POST_KEY] = $tokenProvider->getToken(); TestRouter::router()->reset(); @@ -29,7 +36,7 @@ public function testTokenPass() public function testTokenFail() { - $this->expectException(\Pecee\Http\Middleware\Exceptions\TokenMismatchException::class); + $this->expectException(TokenMismatchException::class); global $_POST; diff --git a/tests/Pecee/SimpleRouter/Dummy/ClassLoader/CustomClassLoader.php b/tests/Pecee/SimpleRouter/Dummy/ClassLoader/CustomClassLoader.php index 90ccc916..5fde99de 100644 --- a/tests/Pecee/SimpleRouter/Dummy/ClassLoader/CustomClassLoader.php +++ b/tests/Pecee/SimpleRouter/Dummy/ClassLoader/CustomClassLoader.php @@ -2,7 +2,7 @@ class CustomClassLoader implements \Pecee\SimpleRouter\ClassLoader\IClassLoader { - public function loadClass(string $class) + public function loadClass(string $class): object { return new DummyController(); } @@ -12,14 +12,19 @@ public function loadClass(string $class) * @param object $class * @param string $method * @param array $parameters - * @return object + * @return mixed */ - public function loadClassMethod($class, string $method, array $parameters) + public function loadClassMethod(object $class, string $method, array $parameters): mixed { return call_user_func_array([$class, $method], [true]); } - public function loadClosure(callable $closure, array $parameters) + /** + * @param callable $closure + * @param array $parameters + * @return mixed + */ + public function loadClosure(callable $closure, array $parameters): mixed { return call_user_func_array($closure, [true]); } diff --git a/tests/Pecee/SimpleRouter/Dummy/CsrfVerifier/DummyCsrfVerifier.php b/tests/Pecee/SimpleRouter/Dummy/CsrfVerifier/DummyCsrfVerifier.php index 8e3b5e1b..a656caa7 100644 --- a/tests/Pecee/SimpleRouter/Dummy/CsrfVerifier/DummyCsrfVerifier.php +++ b/tests/Pecee/SimpleRouter/Dummy/CsrfVerifier/DummyCsrfVerifier.php @@ -1,17 +1,19 @@ skip($request); } diff --git a/tests/Pecee/SimpleRouter/Dummy/ResourceController.php b/tests/Pecee/SimpleRouter/Dummy/ResourceController.php index bd36ab3e..08b89b3d 100644 --- a/tests/Pecee/SimpleRouter/Dummy/ResourceController.php +++ b/tests/Pecee/SimpleRouter/Dummy/ResourceController.php @@ -7,7 +7,7 @@ public function index() : ?string return 'index'; } - public function show($id) : ?string + public function show(mixed $id) : ?string { return 'show ' . $id; } @@ -22,17 +22,17 @@ public function create() : ?string return 'create'; } - public function edit($id) : ?string + public function edit(mixed $id) : ?string { return 'edit ' . $id; } - public function update($id) : ?string + public function update(mixed $id) : ?string { return 'update ' . $id; } - public function destroy($id) : ?string + public function destroy(mixed $id) : ?string { return 'destroy ' . $id; } diff --git a/tests/Pecee/SimpleRouter/InputHandlerTest.php b/tests/Pecee/SimpleRouter/InputHandlerTest.php index be506984..9b234d83 100644 --- a/tests/Pecee/SimpleRouter/InputHandlerTest.php +++ b/tests/Pecee/SimpleRouter/InputHandlerTest.php @@ -8,30 +8,30 @@ class InputHandlerTest extends \PHPUnit\Framework\TestCase { - protected $names = [ + protected array $names = [ 'Lester', 'Michael', 'Franklin', 'Trevor', ]; - protected $brands = [ + protected array $brands = [ 'Samsung', 'Apple', 'HP', 'Canon', ]; - protected $sodas = [ + protected array $sodas = [ 0 => 'Pepsi', 1 => 'Coca Cola', 2 => 'Harboe', 3 => 'Mountain Dew', ]; - protected $day = 'monday'; + protected string $day = 'monday'; - public function testPost() + public function testPost(): void { global $_POST; @@ -69,7 +69,7 @@ public function testPost() $this->assertCount(4, $objects); /* @var $object \Pecee\Http\Input\InputItem */ - foreach($objects as $i => $object) { + foreach ($objects as $i => $object) { $this->assertInstanceOf(\Pecee\Http\Input\InputItem::class, $object); $this->assertEquals($this->names[$i], $object->getValue()); } @@ -78,7 +78,7 @@ public function testPost() $_POST = []; } - public function testGet() + public function testGet(): void { global $_GET; @@ -113,7 +113,7 @@ public function testGet() $this->assertCount(4, $objects); /* @var $object \Pecee\Http\Input\InputItem */ - foreach($objects as $i => $object) { + foreach ($objects as $i => $object) { $this->assertInstanceOf(\Pecee\Http\Input\InputItem::class, $object); $this->assertEquals($this->names[$i], $object->getValue()); } @@ -122,9 +122,8 @@ public function testGet() $_GET = []; } - public function testFindInput() { - - global $_POST; + public function testFindInput(): void + { $_POST['hello'] = 'motto'; $router = TestRouter::router(); @@ -132,12 +131,12 @@ public function testFindInput() { $router->getRequest()->setMethod('post'); $inputHandler = TestRouter::request()->getInputHandler(); - $value = $inputHandler->value('hello', null, \Pecee\Http\Request::$requestTypesPost); + $value = $inputHandler->value('hello', null, ...\Pecee\Http\Request::$requestTypesPost); $this->assertEquals($_POST['hello'], $value); } - public function testFile() + public function testFile(): void { global $_FILES; @@ -271,11 +270,11 @@ public function testAll() protected function generateFile() { return [ - 'name' => uniqid('', false) . '.txt', - 'type' => 'text/plain', + 'name' => uniqid('', false) . '.txt', + 'type' => 'text/plain', 'tmp_name' => sys_get_temp_dir() . '/phpYfWUiw', - 'error' => 0, - 'size' => rand(3, 40), + 'error' => 0, + 'size' => rand(3, 40), ]; } diff --git a/tests/TestRouter.php b/tests/TestRouter.php index 0ebbff5a..db67b7b7 100644 --- a/tests/TestRouter.php +++ b/tests/TestRouter.php @@ -1,11 +1,16 @@ setHost('testhost.com'); + static::request()->setHost('https://example.com'); } public static function reset(): void @@ -13,21 +18,29 @@ public static function reset(): void static::$router = null; } + /** + * @throws \Pecee\SimpleRouter\Exceptions\HttpException + * @throws NotFoundHttpException + * @throws MalformedUrlException + */ public static function debugNoReset(string $testUrl, string $testMethod = 'get'): void { $request = static::request(); - $request->setUrl((new \Pecee\Http\Url($testUrl))); + $request->setUrl((new Url($testUrl))); $request->setMethod($testMethod); static::start(); } + /** + * @throws Exception + */ public static function debug(string $testUrl, string $testMethod = 'get', bool $reset = true): void { try { static::debugNoReset($testUrl, $testMethod); - } catch (\Exception $e) { + } catch (Exception $e) { static::$defaultNamespace = null; static::router()->reset(); throw $e; @@ -40,30 +53,32 @@ public static function debug(string $testUrl, string $testMethod = 'get', bool $ } + /** + * @throws Exception + */ public static function debugOutput(string $testUrl, string $testMethod = 'get', bool $reset = true): string { - $response = null; - // Route request ob_start(); - static::debug($testUrl, $testMethod, $reset); - $response = ob_get_clean(); + static::debug($testUrl, $testMethod, $reset); // Return response - return $response; + return ob_get_clean(); } - public static function debugOutputNoReset(string $testUrl, string $testMethod = 'get', bool $reset = true): string + /** + * @throws \Pecee\SimpleRouter\Exceptions\HttpException + * @throws NotFoundHttpException + * @throws MalformedUrlException + */ + public static function debugOutputNoReset(string $testUrl, string $testMethod = 'get'): string { - $response = null; - // Route request ob_start(); - static::debugNoReset($testUrl, $testMethod, $reset); - $response = ob_get_clean(); + static::debugNoReset($testUrl, $testMethod); // Return response - return $response; + return ob_get_clean(); } } \ No newline at end of file diff --git a/tests/debug.php b/tests/debug.php index a582af89..e0307bdd 100644 --- a/tests/debug.php +++ b/tests/debug.php @@ -4,6 +4,8 @@ use \Pecee\SimpleRouter\SimpleRouter; SimpleRouter::get('/user/{name}', 'UserController@show')->where(['name' => '[\w]+']); + $debugInfo = SimpleRouter::startDebug(); + echo sprintf('
%s
', var_export($debugInfo, true)); exit; \ No newline at end of file From 3a38c1256a5bf247c64c380c9eaca971e105d629 Mon Sep 17 00:00:00 2001 From: Lucas Silva Date: Tue, 30 Jul 2024 15:58:58 -0300 Subject: [PATCH 2/6] refactor: change function debug in router --- src/Pecee/Http/Response.php | 1 - .../SimpleRouter/Route/LoadableRoute.php | 4 +-- src/Pecee/SimpleRouter/Route/Route.php | 6 ++-- src/Pecee/SimpleRouter/Router.php | 30 +++++++++---------- 4 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/Pecee/Http/Response.php b/src/Pecee/Http/Response.php index 42b9318b..8fbcec30 100644 --- a/src/Pecee/Http/Response.php +++ b/src/Pecee/Http/Response.php @@ -2,7 +2,6 @@ namespace Pecee\Http; -use JetBrains\PhpStorm\NoReturn; use JsonSerializable; use Pecee\Exceptions\InvalidArgumentException; diff --git a/src/Pecee/SimpleRouter/Route/LoadableRoute.php b/src/Pecee/SimpleRouter/Route/LoadableRoute.php index be00f23d..a6959b5a 100644 --- a/src/Pecee/SimpleRouter/Route/LoadableRoute.php +++ b/src/Pecee/SimpleRouter/Route/LoadableRoute.php @@ -48,9 +48,9 @@ public function loadMiddleware(Request $request, Router $router): void $className = get_class($middleware); - $router->debug('Loading middleware "%s"', [$className]); + $router->debug('Loading middleware "%s"', $className); $middleware->handle($request); - $router->debug('Finished loading middleware "%s"', [$className]); + $router->debug('Finished loading middleware "%s"', $className); } $router->debug('Finished loading middlewares'); diff --git a/src/Pecee/SimpleRouter/Route/Route.php b/src/Pecee/SimpleRouter/Route/Route.php index 90d13c84..13fbe9ee 100644 --- a/src/Pecee/SimpleRouter/Route/Route.php +++ b/src/Pecee/SimpleRouter/Route/Route.php @@ -61,7 +61,7 @@ abstract class Route implements IRoute */ public function renderRoute(Request $request, Router $router): ?string { - $router->debug('Starting rendering route "%s"', [get_class($this)]); + $router->debug('Starting rendering route "%s"', get_class($this)); $callback = $this->getCallback(); @@ -98,7 +98,7 @@ public function renderRoute(Request $request, Router $router): ?string $namespace = $this->getNamespace(); $className = ($namespace !== null && $controller[0] !== '\\') ? $namespace . '\\' . $controller : $controller; - $router->debug('Loading class %s', [$className]); + $router->debug('Loading class %s', $className); $class = $router->getClassLoader()->loadClass($className); if ($method === null) { @@ -109,7 +109,7 @@ public function renderRoute(Request $request, Router $router): ?string throw new ClassNotFoundHttpException($className, $method, sprintf('Method "%s" does not exist in class "%s"', $method, $className), 404, null); } - $router->debug('Executing callback %s -> %s', [$className, $method]); + $router->debug('Executing callback %s -> %s', $className, $method); return $router->getClassLoader()->loadClassMethod($class, $method, $parameters); } diff --git a/src/Pecee/SimpleRouter/Router.php b/src/Pecee/SimpleRouter/Router.php index 6d8215f2..8fc3fd74 100644 --- a/src/Pecee/SimpleRouter/Router.php +++ b/src/Pecee/SimpleRouter/Router.php @@ -227,7 +227,7 @@ protected function processRoutes(array $routes, ?IGroupRoute $group = null): voi // Loop through each route-request foreach ($routes as $route) { - $this->debug('Processing route "%s"', [get_class($route)]); + $this->debug('Processing route "%s"', get_class($route)); if ($group !== null) { /* Add the parent group */ @@ -302,7 +302,7 @@ public function loadRoutes(): void foreach ($this->bootManagers as $manager) { $className = get_class($manager); - $this->debug('Rendering bootmanager "%s"', [$className]); + $this->debug('Rendering bootmanager "%s"', $className); $this->fireEvents(EventHandler::EVENT_RENDER_BOOTMANAGER, [ 'bootmanagers' => $this->bootManagers, 'bootmanager' => $manager, @@ -311,7 +311,7 @@ public function loadRoutes(): void /* Render bootmanager */ $manager->boot($this, $this->request); - $this->debug('Finished rendering bootmanager "%s"', [$className]); + $this->debug('Finished rendering bootmanager "%s"', $className); } $this->debug('Finished loading routes'); @@ -377,7 +377,7 @@ public function routeRequest(): ?string /* @var $route ILoadableRoute */ foreach ($this->processedRoutes as $key => $route) { - $this->debug('Matching route "%s"', [get_class($route)]); + $this->debug('Matching route "%s"', get_class($route)); /* Add current processing route to constants */ $this->currentProcessingRoute = $route; @@ -391,7 +391,7 @@ public function routeRequest(): ?string /* Check if request method matches */ if (count($route->getRequestMethods()) !== 0 && in_array($this->request->getMethod(), $route->getRequestMethods(), true) === false) { - $this->debug('Method "%s" not allowed', [$this->request->getMethod()]); + $this->debug('Method "%s" not allowed', $this->request->getMethod()); // Only set method not allowed is not already set if ($methodNotAllowed === null) { @@ -515,7 +515,7 @@ protected function handleRouteRewrite(string $key, string $url): ?string */ protected function handleException(Exception $e): ?string { - $this->debug('Starting exception handling for "%s"', [get_class($e)]); + $this->debug('Starting exception handling for "%s"', get_class($e)); $this->fireEvents(EventHandler::EVENT_LOAD_EXCEPTIONS, [ 'exception' => $e, @@ -535,7 +535,7 @@ protected function handleException(Exception $e): ?string 'exceptionHandlers' => $this->exceptionHandlers, ]); - $this->debug('Processing exception-handler "%s"', [get_class($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); @@ -583,7 +583,7 @@ protected function handleException(Exception $e): ?string */ public function findRoute(string $name): ?ILoadableRoute { - $this->debug('Finding route by name "%s"', [$name]); + $this->debug('Finding route by name "%s"', $name); $this->fireEvents(EventHandler::EVENT_FIND_ROUTE, [ 'name' => $name, @@ -593,14 +593,14 @@ public function findRoute(string $name): ?ILoadableRoute /* 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]); + $this->debug('Found route "%s" by name "%s"', $route->getUrl(), $name); return $route; } /* Direct match to controller */ if ($route instanceof IControllerRoute && strtoupper($route->getController()) === strtoupper($name)) { - $this->debug('Found route "%s" by controller "%s"', [$route->getUrl(), $name]); + $this->debug('Found route "%s" by controller "%s"', $route->getUrl(), $name); return $route; } @@ -610,7 +610,7 @@ public function findRoute(string $name): ?ILoadableRoute [$controller, $method] = array_map('strtolower', explode('@', $name)); if ($controller === strtolower((string)$route->getClass()) && $method === strtolower((string)$route->getMethod())) { - $this->debug('Found route "%s" by controller "%s" and method "%s"', [$route->getUrl(), $controller, $method]); + $this->debug('Found route "%s" by controller "%s" and method "%s"', $route->getUrl(), $controller, $method); return $route; } @@ -622,14 +622,14 @@ public function findRoute(string $name): ?ILoadableRoute /* Check if the entire callback is matching */ if (str_starts_with($callback, $name) || strtolower($callback) === strtolower($name)) { - $this->debug('Found route "%s" by callback "%s"', [$route->getUrl(), $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]); + $this->debug('Found route "%s" by class "%s"', $route->getUrl(), $name); return $route; } @@ -884,9 +884,9 @@ protected function fireEvents(string $name, array $arguments = []): void /** * Add a new debug message * @param string $message - * @param array ...$args + * @param mixed ...$args */ - public function debug(string $message, array ...$args): void + public function debug(string $message, mixed ...$args): void { if ($this->debugEnabled === false) { return; From cfb78d723986b4de2a13521e112197ba86ccd757 Mon Sep 17 00:00:00 2001 From: Lucas Silva Date: Tue, 30 Jul 2024 15:59:39 -0300 Subject: [PATCH 3/6] refactor: change function debug in router --- .github/workflows/ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f6a95662..ad168841 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,8 +17,7 @@ jobs: - ubuntu-latest - windows-latest php-version: - - 7.4 - - 8.0 + - 8.3 phpunit-version: - 8.5.32 dependencies: From 76b0785ca2f85c2515138878a6154412037281a7 Mon Sep 17 00:00:00 2001 From: Lucas Silva Date: Tue, 30 Jul 2024 16:14:54 -0300 Subject: [PATCH 4/6] refactor: change ci.yml --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ad168841..ba671411 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,5 +1,5 @@ name: CI - +run-name: ${{ github.actor }} is testing Package on: [push, pull_request] jobs: @@ -17,7 +17,7 @@ jobs: - ubuntu-latest - windows-latest php-version: - - 8.3 + - 8.2 phpunit-version: - 8.5.32 dependencies: From 99221f7a28a5af5e9dfff984c1a38951da3b14f1 Mon Sep 17 00:00:00 2001 From: Lucas Silva Date: Tue, 30 Jul 2024 16:23:01 -0300 Subject: [PATCH 5/6] refactor: change ci.yml --- .github/workflows/ci.yml | 18 ++++++------------ composer.json | 2 +- phpunit.xml | 33 +++++++++++---------------------- phpunit.xml.bak | 24 ++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 35 deletions(-) create mode 100644 phpunit.xml.bak diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ba671411..afd52f49 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,6 @@ name: CI run-name: ${{ github.actor }} is testing Package -on: [push, pull_request] +on: [ push, pull_request ] jobs: build-test: @@ -13,16 +13,10 @@ jobs: strategy: fail-fast: false matrix: - os: - - ubuntu-latest - - windows-latest - php-version: - - 8.2 - phpunit-version: - - 8.5.32 - dependencies: - - lowest - - highest + os: [ ubuntu-latest, windows-latest ] + php-version: [ 8.2 ] + phpunit-version: [ 8.5.32 ] # Consider updating this + dependencies: [ lowest, highest ] name: PHPUnit Tests steps: - name: Configure git to avoid issues with line endings @@ -34,7 +28,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-version }} - tools: composer:v5, phpunit:${{ matrix.phpunit-versions }} + tools: composer:v2, phpunit:${{ matrix.phpunit-versions }} coverage: xdebug extensions: ${{ env.PHP_EXTENSIONS }} ini-values: ${{ env.PHP_INI_VALUES }} diff --git a/composer.json b/composer.json index c48fb587..037e982f 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ "ext-json": "*" }, "require-dev": { - "phpunit/phpunit": "^8", + "phpunit/phpunit": "^11", "mockery/mockery": "^1", "phpstan/phpstan": "^1", "phpstan/phpstan-phpunit": "^1", diff --git a/phpunit.xml b/phpunit.xml index 49b5e9e2..c309643e 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,24 +1,13 @@ - - - - - tests/Pecee/SimpleRouter/ - - - - - src - - + + + + tests/Pecee/SimpleRouter/ + + + + + src + + diff --git a/phpunit.xml.bak b/phpunit.xml.bak new file mode 100644 index 00000000..49b5e9e2 --- /dev/null +++ b/phpunit.xml.bak @@ -0,0 +1,24 @@ + + + + + + tests/Pecee/SimpleRouter/ + + + + + src + + + From 5568cb98b139325a0c0274ead88458a1ff705cdb Mon Sep 17 00:00:00 2001 From: Lucas Silva Date: Tue, 30 Jul 2024 16:27:40 -0300 Subject: [PATCH 6/6] refactor: change ci.yml --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index afd52f49..2cd2bd70 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: matrix: os: [ ubuntu-latest, windows-latest ] php-version: [ 8.2 ] - phpunit-version: [ 8.5.32 ] # Consider updating this + phpunit-version: [ 11 ] # Consider updating this dependencies: [ lowest, highest ] name: PHPUnit Tests steps: @@ -28,7 +28,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-version }} - tools: composer:v2, phpunit:${{ matrix.phpunit-versions }} + tools: composer:v2, phpunit:${{ matrix.phpunit-version }} coverage: xdebug extensions: ${{ env.PHP_EXTENSIONS }} ini-values: ${{ env.PHP_INI_VALUES }}