diff --git a/README.md b/README.md index 5e2e293..4ef8f16 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,6 @@ You can donate any amount of your choice by [clicking here](https://www.paypal.c - [Namespaces](#namespaces) - [Subdomain-routing](#subdomain-routing) - [Route prefixes](#route-prefixes) - - [Partial groups](#partial-groups) - [Form Method Spoofing](#form-method-spoofing) - [Accessing The Current Route](#accessing-the-current-route) - [Other examples](#other-examples) @@ -631,6 +630,23 @@ SimpleRouter::group(['namespace' => 'Admin'], function () { }); ``` +You can add parameters to the prefixes of your routes. + +Parameters from your previous routes will be injected +into your routes after any route-required parameters, starting from oldest to newest. + +```php +SimpleRouter::group(['prefix' => '/lang/{lang}'], function ($language) { + + SimpleRouter::get('/about', function($language) { + + // Will match /lang/da/about + + }); + +}); +``` + ### Subdomain-routing Route groups may also be used to handle sub-domain routing. Sub-domains may be assigned route parameters just like route urls, allowing you to capture a portion of the sub-domain for usage in your route or controller. The sub-domain may be specified using the `domain` key on the group attribute array: @@ -655,30 +671,16 @@ SimpleRouter::group(['prefix' => '/admin'], function () { }); ``` -## Partial groups - -Partial router groups has the same benefits as a normal group, but supports parameters and are only rendered once the url has matched. -Partial groups will render once a part of the url has matched. - -This can be extremely useful in situations, where you only want special routes to be added, when a certain criteria or logic has been met. - -**NOTE:** Use partial groups with caution as routes added within are only rendered and available once the url of the partial-group has matched. This can cause `url()` not to find urls for the routes added within. - -**Example:** +You can also use parameters in your groups: ```php -SimpleRouter::partialGroup('/lang/{language}', function ($language) { - - SimpleRouter::get('/', function($language) { - - // Matches The "/lang/da" URL - +SimpleRouter::group(['prefix' => '/lang/{language}'], function ($language) { + SimpleRouter::get('/users', function ($language) { + // Matches The "/lang/da/users" URL }); - }); ``` - ## Form Method Spoofing HTML forms do not support `PUT`, `PATCH` or `DELETE` actions. So, when defining `PUT`, `PATCH` or `DELETE` routes that are called from an HTML form, you will need to add a hidden `_method` field to the form. The value sent with the `_method` field will be used as the HTTP request method: @@ -1493,6 +1495,18 @@ class MyCustomClassLoader implements IClassLoader return new $class(); } + + /** + * Called when loading class method + * @param object $class + * @param string $method + * @param array $parameters + * @return object + */ + public function loadClassMethod($class, string $method, array $parameters) + { + return call_user_func_array([$class, $method], array_values($parameters)); + } /** * Load closure @@ -1503,7 +1517,7 @@ class MyCustomClassLoader implements IClassLoader */ public function loadClosure(Callable $closure, array $parameters) { - return \call_user_func_array($closure, $parameters); + return \call_user_func_array($closure, array_values($parameters)); } } @@ -1520,6 +1534,8 @@ SimpleRouter::setCustomClassLoader(new MyCustomClassLoader()); php-di support was discontinued by version 4.3, however you can easily add it again by creating your own class-loader like the example below: ```php +use Pecee\SimpleRouter\Exceptions\ClassNotFoundHttpException; + class MyCustomClassLoader implements IClassLoader { @@ -1528,7 +1544,7 @@ class MyCustomClassLoader implements IClassLoader public function __construct() { // Create our new php-di container - $container = (new \DI\ContainerBuilder()) + $this->container = (new \DI\ContainerBuilder()) ->useAutowiring(true) ->build(); } @@ -1546,15 +1562,27 @@ class MyCustomClassLoader implements IClassLoader throw new NotFoundHttpException(sprintf('Class "%s" does not exist', $class), 404); } - if ($this->container !== null) { - try { - return $this->container->get($class); - } catch (\Exception $e) { - throw new NotFoundHttpException($e->getMessage(), (int)$e->getCode(), $e->getPrevious()); - } - } - - return new $class(); + try { + return $this->container->get($class); + } catch (\Exception $e) { + throw new NotFoundHttpException($e->getMessage(), (int)$e->getCode(), $e->getPrevious()); + } + } + + /** + * Called when loading class method + * @param object $class + * @param string $method + * @param array $parameters + * @return object + */ + public function loadClassMethod($class, string $method, array $parameters) + { + try { + return $this->container->call([$class, $method], $parameters); + } catch (\Exception $e) { + throw new NotFoundHttpException($e->getMessage(), (int)$e->getCode(), $e->getPrevious()); + } } /** @@ -1564,19 +1592,14 @@ class MyCustomClassLoader implements IClassLoader * @param array $parameters * @return mixed */ - public function loadClosure(Callable $closure, array $parameters) + public function loadClosure(callable $closure, array $parameters) { - if ($this->container !== null) { - try { - return $this->container->call($closure, $parameters); - } catch (\Exception $e) { - throw new NotFoundHttpException($e->getMessage(), (int)$e->getCode(), $e->getPrevious()); - } - } - - return \call_user_func_array($closure, $parameters); + try { + return $this->container->call($closure, $parameters); + } catch (\Exception $e) { + throw new NotFoundHttpException($e->getMessage(), (int)$e->getCode(), $e->getPrevious()); + } } - } ``` diff --git a/src/Pecee/Http/Exceptions/MalformedUrlException.php b/src/Pecee/Http/Exceptions/MalformedUrlException.php index 8556d1b..7f7fc14 100644 --- a/src/Pecee/Http/Exceptions/MalformedUrlException.php +++ b/src/Pecee/Http/Exceptions/MalformedUrlException.php @@ -2,7 +2,9 @@ namespace Pecee\Http\Exceptions; -class MalformedUrlException extends \Exception +use Exception; + +class MalformedUrlException extends Exception { } \ No newline at end of file diff --git a/src/Pecee/Http/Input/InputHandler.php b/src/Pecee/Http/Input/InputHandler.php index 13bfe5c..9586720 100644 --- a/src/Pecee/Http/Input/InputHandler.php +++ b/src/Pecee/Http/Input/InputHandler.php @@ -63,7 +63,7 @@ class InputHandler public function parseInputs(): void { /* Parse get requests */ - if (\count($_GET) !== 0) { + if (count($_GET) !== 0) { $this->originalParams = $_GET; $this->get = $this->parseInputItem($this->originalParams); } @@ -85,12 +85,12 @@ class InputHandler } } - if (\count($this->originalPost) !== 0) { + if (count($this->originalPost) !== 0) { $this->post = $this->parseInputItem($this->originalPost); } /* Parse get requests */ - if (\count($_FILES) !== 0) { + if (count($_FILES) !== 0) { $this->originalFile = $_FILES; $this->file = $this->parseFiles($this->originalFile); } @@ -108,13 +108,13 @@ class InputHandler foreach ($files as $key => $value) { // Parse multi dept file array - if(isset($value['name']) === false && \is_array($value) === true) { + if(isset($value['name']) === false && is_array($value) === true) { $list[$key] = $this->parseFiles($value, $key); continue; } // Handle array input - if (\is_array($value['name']) === false) { + if (is_array($value['name']) === false) { $values['index'] = $parentKey ?? $key; try { @@ -156,7 +156,7 @@ class InputHandler foreach ($values as $key => $value) { - if (\is_array($original['name'][$key]) === false) { + if (is_array($original['name'][$key]) === false) { try { @@ -210,7 +210,7 @@ class InputHandler foreach ($array as $key => $value) { // Handle array input - if (\is_array($value) === true) { + if (is_array($value) === true) { $value = $this->parseInputItem($value); } @@ -231,15 +231,19 @@ class InputHandler { $element = null; - if (\count($methods) === 0 || \in_array(Request::REQUEST_TYPE_GET, $methods, true) === true) { + if(count($methods) > 0) { + $methods = is_array(...$methods) ? array_values(...$methods) : $methods; + } + + if (count($methods) === 0 || in_array(Request::REQUEST_TYPE_GET, $methods, true) === true) { $element = $this->get($index); } - if (($element === null && \count($methods) === 0) || (\count($methods) !== 0 && \in_array(Request::REQUEST_TYPE_POST, $methods, true) === true)) { + if (($element === null && count($methods) === 0) || (count($methods) !== 0 && in_array(Request::REQUEST_TYPE_POST, $methods, true) === true)) { $element = $this->post($index); } - if (($element === null && \count($methods) === 0) || (\count($methods) !== 0 && \in_array('file', $methods, true) === true)) { + if (($element === null && count($methods) === 0) || (count($methods) !== 0 && in_array('file', $methods, true) === true)) { $element = $this->file($index); } @@ -256,7 +260,7 @@ class InputHandler $item = $item->getValue(); } - $output[$key] = \is_array($item) ? $this->getValueFromArray($item) : $item; + $output[$key] = is_array($item) ? $this->getValueFromArray($item) : $item; } return $output; @@ -279,13 +283,13 @@ class InputHandler } /* Handle collection */ - if (\is_array($input) === true) { + if (is_array($input) === true) { $output = $this->getValueFromArray($input); - return (\count($output) === 0) ? $defaultValue : $output; + return (count($output) === 0) ? $defaultValue : $output; } - return ($input === null || (\is_string($input) && trim($input) === '')) ? $defaultValue : $input; + return ($input === null || (is_string($input) && trim($input) === '')) ? $defaultValue : $input; } /** @@ -344,7 +348,7 @@ class InputHandler public function all(array $filter = []): array { $output = $this->originalParams + $this->originalPost + $this->originalFile; - $output = (\count($filter) > 0) ? \array_intersect_key($output, \array_flip($filter)) : $output; + $output = (count($filter) > 0) ? array_intersect_key($output, array_flip($filter)) : $output; foreach ($filter as $filterKey) { if (array_key_exists($filterKey, $output) === false) { diff --git a/src/Pecee/Http/Input/InputItem.php b/src/Pecee/Http/Input/InputItem.php index 2322bd3..85ae93d 100644 --- a/src/Pecee/Http/Input/InputItem.php +++ b/src/Pecee/Http/Input/InputItem.php @@ -2,7 +2,10 @@ namespace Pecee\Http\Input; -class InputItem implements IInputItem, \IteratorAggregate +use ArrayIterator; +use IteratorAggregate; + +class InputItem implements IInputItem, IteratorAggregate { public $index; public $name; @@ -75,11 +78,11 @@ class InputItem implements IInputItem, \IteratorAggregate public function __toString(): string { $value = $this->getValue(); - return (\is_array($value) === true) ? json_encode($value) : $value; + return (is_array($value) === true) ? json_encode($value) : $value; } - public function getIterator(): \ArrayIterator + public function getIterator(): ArrayIterator { - return new \ArrayIterator($this->getValue()); + return new ArrayIterator($this->getValue()); } } \ No newline at end of file diff --git a/src/Pecee/Http/Middleware/BaseCsrfVerifier.php b/src/Pecee/Http/Middleware/BaseCsrfVerifier.php index 392bcf9..44540ca 100644 --- a/src/Pecee/Http/Middleware/BaseCsrfVerifier.php +++ b/src/Pecee/Http/Middleware/BaseCsrfVerifier.php @@ -30,17 +30,17 @@ class BaseCsrfVerifier implements IMiddleware */ protected function skip(Request $request): bool { - if ($this->except === null || \count($this->except) === 0) { + if ($this->except === null || count($this->except) === 0) { return false; } - $max = \count($this->except) - 1; + $max = count($this->except) - 1; for ($i = $max; $i >= 0; $i--) { $url = $this->except[$i]; $url = rtrim($url, '/'); - if ($url[\strlen($url) - 1] === '*') { + if ($url[strlen($url) - 1] === '*') { $url = rtrim($url, '*'); $skip = $request->getUrl()->contains($url); } else { diff --git a/src/Pecee/Http/Middleware/Exceptions/TokenMismatchException.php b/src/Pecee/Http/Middleware/Exceptions/TokenMismatchException.php index 7e07c7a..78f24cc 100644 --- a/src/Pecee/Http/Middleware/Exceptions/TokenMismatchException.php +++ b/src/Pecee/Http/Middleware/Exceptions/TokenMismatchException.php @@ -2,7 +2,9 @@ namespace Pecee\Http\Middleware\Exceptions; -class TokenMismatchException extends \Exception +use Exception; + +class TokenMismatchException extends Exception { } \ No newline at end of file diff --git a/src/Pecee/Http/Request.php b/src/Pecee/Http/Request.php index fddb573..84f6d04 100644 --- a/src/Pecee/Http/Request.php +++ b/src/Pecee/Http/Request.php @@ -369,7 +369,7 @@ class Request */ public function isPostBack(): bool { - return \in_array($this->getMethod(), static::$requestTypesPost, true); + return in_array($this->getMethod(), static::$requestTypesPost, true); } /** @@ -475,7 +475,7 @@ class Request */ public function getLoadedRoute(): ?ILoadableRoute { - return (\count($this->loadedRoutes) > 0) ? end($this->loadedRoutes) : null; + return (count($this->loadedRoutes) > 0) ? end($this->loadedRoutes) : null; } /** diff --git a/src/Pecee/Http/Response.php b/src/Pecee/Http/Response.php index e7a7da9..44a2ee0 100644 --- a/src/Pecee/Http/Response.php +++ b/src/Pecee/Http/Response.php @@ -2,6 +2,7 @@ namespace Pecee\Http; +use JsonSerializable; use Pecee\Exceptions\InvalidArgumentException; class Response @@ -85,14 +86,14 @@ class Response /** * Json encode - * @param array|\JsonSerializable $value + * @param array|JsonSerializable $value * @param ?int $options JSON options Bitmask consisting of JSON_HEX_QUOT, JSON_HEX_TAG, JSON_HEX_AMP, JSON_HEX_APOS, JSON_NUMERIC_CHECK, JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES, JSON_FORCE_OBJECT, JSON_PRESERVE_ZERO_FRACTION, JSON_UNESCAPED_UNICODE, JSON_PARTIAL_OUTPUT_ON_ERROR. * @param int $dept JSON debt. * @throws InvalidArgumentException */ public function json($value, ?int $options = null, int $dept = 512): void { - if (($value instanceof \JsonSerializable) === false && \is_array($value) === false) { + 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.'); } diff --git a/src/Pecee/Http/Security/CookieTokenProvider.php b/src/Pecee/Http/Security/CookieTokenProvider.php index 35f1021..6c9cbc9 100644 --- a/src/Pecee/Http/Security/CookieTokenProvider.php +++ b/src/Pecee/Http/Security/CookieTokenProvider.php @@ -2,6 +2,7 @@ namespace Pecee\Http\Security; +use Exception; use Pecee\Http\Security\Exceptions\SecurityException; class CookieTokenProvider implements ITokenProvider @@ -34,7 +35,7 @@ class CookieTokenProvider implements ITokenProvider { try { return bin2hex(random_bytes(32)); - } catch (\Exception $e) { + } catch (Exception $e) { throw new SecurityException($e->getMessage(), (int)$e->getCode(), $e->getPrevious()); } } diff --git a/src/Pecee/Http/Security/Exceptions/SecurityException.php b/src/Pecee/Http/Security/Exceptions/SecurityException.php index b7d2dc2..0588d72 100644 --- a/src/Pecee/Http/Security/Exceptions/SecurityException.php +++ b/src/Pecee/Http/Security/Exceptions/SecurityException.php @@ -2,7 +2,9 @@ namespace Pecee\Http\Security\Exceptions; -class SecurityException extends \Exception +use Exception; + +class SecurityException extends Exception { } \ No newline at end of file diff --git a/src/Pecee/Http/Url.php b/src/Pecee/Http/Url.php index 256e4a5..fb3c9c9 100644 --- a/src/Pecee/Http/Url.php +++ b/src/Pecee/Http/Url.php @@ -2,9 +2,10 @@ namespace Pecee\Http; +use JsonSerializable; use Pecee\Http\Exceptions\MalformedUrlException; -class Url implements \JsonSerializable +class Url implements JsonSerializable { private $originalUrl; @@ -409,7 +410,7 @@ class Url implements \JsonSerializable */ public static function arrayToParams(array $getParams = [], bool $includeEmpty = true): string { - if (\count($getParams) !== 0) { + if (count($getParams) !== 0) { if ($includeEmpty === false) { $getParams = array_filter($getParams, static function ($item) { diff --git a/src/Pecee/SimpleRouter/ClassLoader/ClassLoader.php b/src/Pecee/SimpleRouter/ClassLoader/ClassLoader.php index 027028e..cb70e69 100644 --- a/src/Pecee/SimpleRouter/ClassLoader/ClassLoader.php +++ b/src/Pecee/SimpleRouter/ClassLoader/ClassLoader.php @@ -22,6 +22,18 @@ class ClassLoader implements IClassLoader return new $class(); } + /** + * Called when loading class method + * @param object $class + * @param string $method + * @param array $parameters + * @return object + */ + public function loadClassMethod($class, string $method, array $parameters) + { + return call_user_func_array([$class, $method], array_values($parameters)); + } + /** * Load closure * @@ -31,7 +43,7 @@ class ClassLoader implements IClassLoader */ public function loadClosure(Callable $closure, array $parameters) { - return \call_user_func_array($closure, $parameters); + return call_user_func_array($closure, array_values($parameters)); } } \ No newline at end of file diff --git a/src/Pecee/SimpleRouter/ClassLoader/IClassLoader.php b/src/Pecee/SimpleRouter/ClassLoader/IClassLoader.php index 8eb8cd1..2ac88bd 100644 --- a/src/Pecee/SimpleRouter/ClassLoader/IClassLoader.php +++ b/src/Pecee/SimpleRouter/ClassLoader/IClassLoader.php @@ -12,6 +12,15 @@ interface IClassLoader */ public function loadClass(string $class); + /** + * Called when loading class method + * @param object $class + * @param string $method + * @param array $parameters + * @return object + */ + public function loadClassMethod($class, string $method, array $parameters); + /** * Called when loading method * @@ -21,4 +30,4 @@ interface IClassLoader */ public function loadClosure(Callable $closure, array $parameters); -} +} \ No newline at end of file diff --git a/src/Pecee/SimpleRouter/Event/EventArgument.php b/src/Pecee/SimpleRouter/Event/EventArgument.php index 092f9a0..fc88cd0 100644 --- a/src/Pecee/SimpleRouter/Event/EventArgument.php +++ b/src/Pecee/SimpleRouter/Event/EventArgument.php @@ -2,6 +2,7 @@ namespace Pecee\SimpleRouter\Event; +use InvalidArgumentException; use Pecee\Http\Request; use Pecee\SimpleRouter\Router; @@ -91,11 +92,11 @@ class EventArgument implements IEventArgument /** * @param string $name * @param mixed $value - * @throws \InvalidArgumentException + * @throws InvalidArgumentException */ public function __set(string $name, $value) { - throw new \InvalidArgumentException('Not supported'); + throw new InvalidArgumentException('Not supported'); } /** diff --git a/src/Pecee/SimpleRouter/Exceptions/HttpException.php b/src/Pecee/SimpleRouter/Exceptions/HttpException.php index e03c4a7..4a63af8 100644 --- a/src/Pecee/SimpleRouter/Exceptions/HttpException.php +++ b/src/Pecee/SimpleRouter/Exceptions/HttpException.php @@ -2,7 +2,9 @@ namespace Pecee\SimpleRouter\Exceptions; -class HttpException extends \Exception +use Exception; + +class HttpException extends Exception { } \ No newline at end of file diff --git a/src/Pecee/SimpleRouter/Handlers/CallbackExceptionHandler.php b/src/Pecee/SimpleRouter/Handlers/CallbackExceptionHandler.php index 296c228..adc8ebe 100644 --- a/src/Pecee/SimpleRouter/Handlers/CallbackExceptionHandler.php +++ b/src/Pecee/SimpleRouter/Handlers/CallbackExceptionHandler.php @@ -2,6 +2,8 @@ namespace Pecee\SimpleRouter\Handlers; +use Closure; +use Exception; use Pecee\Http\Request; /** @@ -17,19 +19,19 @@ class CallbackExceptionHandler implements IExceptionHandler protected $callback; - public function __construct(\Closure $callback) + public function __construct(Closure $callback) { $this->callback = $callback; } /** * @param Request $request - * @param \Exception $error + * @param Exception $error */ - public function handleError(Request $request, \Exception $error): void + public function handleError(Request $request, Exception $error): void { /* Fire exceptions */ - \call_user_func($this->callback, + call_user_func($this->callback, $request, $error ); diff --git a/src/Pecee/SimpleRouter/Handlers/DebugEventHandler.php b/src/Pecee/SimpleRouter/Handlers/DebugEventHandler.php index fe4a954..92ff158 100644 --- a/src/Pecee/SimpleRouter/Handlers/DebugEventHandler.php +++ b/src/Pecee/SimpleRouter/Handlers/DebugEventHandler.php @@ -2,6 +2,7 @@ namespace Pecee\SimpleRouter\Handlers; +use Closure; use Pecee\SimpleRouter\Event\EventArgument; use Pecee\SimpleRouter\Router; @@ -10,7 +11,7 @@ class DebugEventHandler implements IEventHandler /** * Debug callback - * @var \Closure + * @var Closure */ protected $callback; @@ -52,9 +53,9 @@ class DebugEventHandler implements IEventHandler /** * Set debug callback * - * @param \Closure $event + * @param Closure $event */ - public function setCallback(\Closure $event): void + public function setCallback(Closure $event): void { $this->callback = $event; } diff --git a/src/Pecee/SimpleRouter/Handlers/EventHandler.php b/src/Pecee/SimpleRouter/Handlers/EventHandler.php index 70b37b3..7bd1f76 100644 --- a/src/Pecee/SimpleRouter/Handlers/EventHandler.php +++ b/src/Pecee/SimpleRouter/Handlers/EventHandler.php @@ -2,6 +2,7 @@ namespace Pecee\SimpleRouter\Handlers; +use Closure; use Pecee\SimpleRouter\Event\EventArgument; use Pecee\SimpleRouter\Router; @@ -125,10 +126,10 @@ class EventHandler implements IEventHandler * Register new event * * @param string $name - * @param \Closure $callback + * @param Closure $callback * @return static */ - public function register(string $name, \Closure $callback): IEventHandler + public function register(string $name, Closure $callback): IEventHandler { if (isset($this->registeredEvents[$name]) === true) { $this->registeredEvents[$name][] = $callback; @@ -175,7 +176,7 @@ class EventHandler implements IEventHandler { $events = $this->getEvents(static::EVENT_ALL, $name); - /* @var $event \Closure */ + /* @var $event Closure */ foreach ($events as $event) { $event(new EventArgument($name, $router, $eventArgs)); } diff --git a/src/Pecee/SimpleRouter/Handlers/IExceptionHandler.php b/src/Pecee/SimpleRouter/Handlers/IExceptionHandler.php index b32a86d..4436c3e 100644 --- a/src/Pecee/SimpleRouter/Handlers/IExceptionHandler.php +++ b/src/Pecee/SimpleRouter/Handlers/IExceptionHandler.php @@ -2,14 +2,15 @@ namespace Pecee\SimpleRouter\Handlers; +use Exception; use Pecee\Http\Request; interface IExceptionHandler { /** * @param Request $request - * @param \Exception $error + * @param Exception $error */ - public function handleError(Request $request, \Exception $error): void; + public function handleError(Request $request, Exception $error): void; } \ No newline at end of file diff --git a/src/Pecee/SimpleRouter/Route/LoadableRoute.php b/src/Pecee/SimpleRouter/Route/LoadableRoute.php index edf414e..68654a2 100644 --- a/src/Pecee/SimpleRouter/Route/LoadableRoute.php +++ b/src/Pecee/SimpleRouter/Route/LoadableRoute.php @@ -34,7 +34,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute foreach ($this->getMiddlewares() as $middleware) { - if (\is_object($middleware) === false) { + if (is_object($middleware) === false) { $middleware = $router->getClassLoader()->loadClass($middleware); } @@ -42,7 +42,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute throw new HttpException($middleware . ' must be inherit the IMiddleware interface'); } - $className = \get_class($middleware); + $className = get_class($middleware); $router->debug('Loading middleware "%s"', $className); $middleware->handle($request); @@ -116,7 +116,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute $group = $this->getGroup(); - if ($group !== null && \count($group->getDomains()) !== 0) { + if ($group !== null && count($group->getDomains()) !== 0) { $url = '//' . $group->getDomains()[0] . $url; } @@ -132,7 +132,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute foreach (array_keys($params) as $param) { - if ($parameters === '' || (\is_array($parameters) === true && \count($parameters) === 0)) { + if ($parameters === '' || (is_array($parameters) === true && count($parameters) === 0)) { $value = ''; } else { $p = (array)$parameters; diff --git a/src/Pecee/SimpleRouter/Route/Route.php b/src/Pecee/SimpleRouter/Route/Route.php index 72c96c6..0d300ae 100644 --- a/src/Pecee/SimpleRouter/Route/Route.php +++ b/src/Pecee/SimpleRouter/Route/Route.php @@ -2,7 +2,6 @@ namespace Pecee\SimpleRouter\Route; -use Pecee\Http\Middleware\IMiddleware; use Pecee\Http\Request; use Pecee\SimpleRouter\Exceptions\ClassNotFoundHttpException; use Pecee\SimpleRouter\Exceptions\NotFoundHttpException; @@ -52,7 +51,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(); @@ -74,7 +73,7 @@ abstract class Route implements IRoute } /* Render callback function */ - if (\is_callable($callback) === true) { + if (is_callable($callback) === true) { $router->debug('Executing callback'); /* When the callback is a function */ @@ -98,9 +97,9 @@ abstract class Route implements IRoute throw new ClassNotFoundHttpException($className, $method, sprintf('Method "%s" does not exist in class "%s"', $method, $className), 404, null); } - $router->debug('Executing callback'); + $router->debug('Executing callback %s -> %s', $className, $method); - return \call_user_func_array([$class, $method], $parameters); + return $router->getClassLoader()->loadClassMethod($class, $method, $parameters); } protected function parseParameters($route, $url, $parameterRegex = null): ?array @@ -127,7 +126,7 @@ abstract class Route implements IRoute $regex = ''; - if ($key < \count($parameters[1])) { + if ($key < count($parameters[1])) { $name = $parameters[1][$key]; @@ -153,12 +152,27 @@ abstract class Route implements IRoute if (isset($parameters[1]) === true) { + $groupParameters = $this->getGroup() !== null ? $this->getGroup()->getParameters() : []; + + $lastParams = []; + /* Only take matched parameters with name */ foreach ((array)$parameters[1] as $name) { + + // Ignore parent parameters + if(isset($groupParameters[$name]) === true) { + $lastParams[$name] = $matches[$name]; + continue; + } + $values[$name] = (isset($matches[$name]) === true && $matches[$name] !== '') ? $matches[$name] : null; } + + $values = array_merge($values, $lastParams); } + $this->originalParameters = $values; + return $values; } @@ -171,7 +185,7 @@ abstract class Route implements IRoute */ public function getIdentifier(): string { - if (\is_string($this->callback) === true && strpos($this->callback, '@') !== false) { + if (is_string($this->callback) === true && strpos($this->callback, '@') !== false) { return $this->callback; } @@ -230,7 +244,6 @@ abstract class Route implements IRoute $this->group = $group; /* Add/merge parent settings with child */ - return $this->setSettings($group->toArray(), true); } @@ -270,11 +283,11 @@ abstract class Route implements IRoute public function getMethod(): ?string { - if (\is_array($this->callback) === true && \count($this->callback) > 1) { + if (is_array($this->callback) === true && count($this->callback) > 1) { return $this->callback[1]; } - if (\is_string($this->callback) === true && strpos($this->callback, '@') !== false) { + if (is_string($this->callback) === true && strpos($this->callback, '@') !== false) { $tmp = explode('@', $this->callback); return $tmp[1]; @@ -285,11 +298,11 @@ abstract class Route implements IRoute public function getClass(): ?string { - if (\is_array($this->callback) === true && \count($this->callback) > 0) { + if (is_array($this->callback) === true && count($this->callback) > 0) { return $this->callback[0]; } - if (\is_string($this->callback) === true && strpos($this->callback, '@') !== false) { + if (is_string($this->callback) === true && strpos($this->callback, '@') !== false) { $tmp = explode('@', $this->callback); return $tmp[0]; @@ -360,15 +373,15 @@ abstract class Route implements IRoute $values['namespace'] = $this->namespace; } - if (\count($this->requestMethods) !== 0) { + if (count($this->requestMethods) !== 0) { $values['method'] = $this->requestMethods; } - if (\count($this->where) !== 0) { + if (count($this->where) !== 0) { $values['where'] = $this->where; } - if (\count($this->middlewares) !== 0) { + if (count($this->middlewares) !== 0) { $values['middleware'] = $this->middlewares; } @@ -462,7 +475,7 @@ abstract class Route implements IRoute /* Sort the parameters after the user-defined param order, if any */ $parameters = []; - if (\count($this->originalParameters) !== 0) { + if (count($this->originalParameters) !== 0) { $parameters = $this->originalParameters; } @@ -477,14 +490,6 @@ abstract class Route implements IRoute */ public function setParameters(array $parameters): IRoute { - /* - * If this is the first time setting parameters we store them so we - * later can organize the array, in case somebody tried to sort the array. - */ - if (\count($parameters) !== 0 && \count($this->originalParameters) === 0) { - $this->originalParameters = $parameters; - } - $this->parameters = array_merge($this->parameters, $parameters); return $this; diff --git a/src/Pecee/SimpleRouter/Route/RouteController.php b/src/Pecee/SimpleRouter/Route/RouteController.php index 2b00ec5..2238b9d 100644 --- a/src/Pecee/SimpleRouter/Route/RouteController.php +++ b/src/Pecee/SimpleRouter/Route/RouteController.php @@ -35,7 +35,7 @@ class RouteController extends LoadableRoute implements IControllerRoute $method = substr($name, strrpos($name, '.') + 1); $newName = substr($name, 0, strrpos($name, '.')); - if (\in_array($method, $this->names, true) === true && strtolower($this->name) === strtolower($newName)) { + if (in_array($method, $this->names, true) === true && strtolower($this->name) === strtolower($newName)) { return true; } } @@ -67,7 +67,7 @@ class RouteController extends LoadableRoute implements IControllerRoute foreach (Request::$requestTypes as $requestType) { if (stripos($method, $requestType) === 0) { - $method = (string)substr($method, \strlen($requestType)); + $method = (string)substr($method, strlen($requestType)); break; } } @@ -77,7 +77,7 @@ class RouteController extends LoadableRoute implements IControllerRoute $group = $this->getGroup(); - if ($group !== null && \count($group->getDomains()) !== 0) { + if ($group !== null && count($group->getDomains()) !== 0) { $url .= '//' . $group->getDomains()[0]; } @@ -102,12 +102,12 @@ class RouteController extends LoadableRoute implements IControllerRoute $strippedUrl = trim(str_ireplace($this->url, '/', $url), '/'); $path = explode('/', $strippedUrl); - if (\count($path) !== 0) { + if (count($path) !== 0) { $method = (isset($path[0]) === false || trim($path[0]) === '') ? $this->defaultMethod : $path[0]; $this->method = $request->getMethod() . ucfirst($method); - $this->parameters = \array_slice($path, 1); + $this->parameters = array_slice($path, 1); // Set callback $this->setCallback([$this->controller, $this->method]); diff --git a/src/Pecee/SimpleRouter/Route/RouteGroup.php b/src/Pecee/SimpleRouter/Route/RouteGroup.php index 68e9e75..d605091 100644 --- a/src/Pecee/SimpleRouter/Route/RouteGroup.php +++ b/src/Pecee/SimpleRouter/Route/RouteGroup.php @@ -7,6 +7,7 @@ use Pecee\SimpleRouter\Handlers\IExceptionHandler; class RouteGroup extends Route implements IGroupRoute { + protected $urlRegex = '/^%s\/?/u'; protected $prefix; protected $name; protected $domains = []; @@ -20,7 +21,7 @@ class RouteGroup extends Route implements IGroupRoute */ public function matchDomain(Request $request): bool { - if ($this->domains === null || \count($this->domains) === 0) { + if ($this->domains === null || count($this->domains) === 0) { return true; } @@ -33,7 +34,7 @@ class RouteGroup extends Route implements IGroupRoute $parameters = $this->parseParameters($domain, $request->getHost(), '.*'); - if ($parameters !== null && \count($parameters) !== 0) { + if ($parameters !== null && count($parameters) !== 0) { $this->parameters = $parameters; return true; } @@ -55,16 +56,27 @@ class RouteGroup extends Route implements IGroupRoute return false; } - // Parse parameter + if ($this->prefix !== null) { + /* Parse parameters from current route */ + $parameters = $this->parseParameters($this->prefix, $url); - $prefix = $this->prefix; + /* If no custom regular expression or parameters was found on this route, we stop */ + if ($parameters === null) { + return false; + } + + /* Set the parameters */ + $this->setParameters($parameters); + } + + $parsedPrefix = $this->prefix; foreach ($this->getParameters() as $parameter => $value) { - $prefix = str_ireplace('{' . $parameter . '}', $value, $prefix); + $parsedPrefix = str_ireplace('{' . $parameter . '}', $value, $parsedPrefix); } /* Skip if prefix doesn't match */ - if ($this->prefix !== null && stripos($url, $prefix) === false) { + if ($this->prefix !== null && stripos($url, $parsedPrefix) === false) { return false; } @@ -204,7 +216,7 @@ class RouteGroup extends Route implements IGroupRoute $values['as'] = $this->name; } - if (\count($this->parameters) !== 0) { + if (count($this->parameters) !== 0) { $values['parameters'] = $this->parameters; } diff --git a/src/Pecee/SimpleRouter/Route/RoutePartialGroup.php b/src/Pecee/SimpleRouter/Route/RoutePartialGroup.php index 1e1a51b..901bd45 100644 --- a/src/Pecee/SimpleRouter/Route/RoutePartialGroup.php +++ b/src/Pecee/SimpleRouter/Route/RoutePartialGroup.php @@ -1,47 +1,11 @@ urlRegex = '/^%s\/?/u'; - } - - /** - * Method called to check if route matches - * - * @param string $url - * @param Request $request - * @return bool - */ - public function matchRoute(string $url, Request $request): bool - { - if ($this->getGroup() !== null && $this->getGroup()->matchRoute($url, $request) === false) { - return false; - } - - if ($this->prefix !== null) { - /* Parse parameters from current route */ - $parameters = $this->parseParameters($this->prefix, $url); - - /* If no custom regular expression or parameters was found on this route, we stop */ - if ($parameters === null) { - return false; - } - - /* Set the parameters */ - $this->setParameters($parameters); - } - - return $this->matchDomain($request); - } - } \ No newline at end of file diff --git a/src/Pecee/SimpleRouter/Route/RouteResource.php b/src/Pecee/SimpleRouter/Route/RouteResource.php index 73ea662..ceeb18c 100644 --- a/src/Pecee/SimpleRouter/Route/RouteResource.php +++ b/src/Pecee/SimpleRouter/Route/RouteResource.php @@ -120,7 +120,7 @@ class RouteResource extends LoadableRoute implements IControllerRoute } // Update - if ($id !== null && \in_array($method, [Request::REQUEST_TYPE_PATCH, Request::REQUEST_TYPE_PUT], true) === true) { + if ($id !== null && in_array($method, [Request::REQUEST_TYPE_PATCH, Request::REQUEST_TYPE_PUT], true) === true) { return $this->call($this->methodNames['update']); } diff --git a/src/Pecee/SimpleRouter/Router.php b/src/Pecee/SimpleRouter/Router.php index 91b7b67..72dd297 100644 --- a/src/Pecee/SimpleRouter/Router.php +++ b/src/Pecee/SimpleRouter/Router.php @@ -2,6 +2,7 @@ namespace Pecee\SimpleRouter; +use Exception; use Pecee\Exceptions\InvalidArgumentException; use Pecee\Http\Exceptions\MalformedUrlException; use Pecee\Http\Middleware\BaseCsrfVerifier; @@ -188,7 +189,7 @@ class Router $route->renderRoute($this->request, $this); $this->isProcessingRoute = false; - if (\count($this->routeStack) !== 0) { + if (count($this->routeStack) !== 0) { /* Pop and grab the routes added when executing group callback earlier */ $stack = $this->routeStack; @@ -225,7 +226,7 @@ class Router /* @var $route IRoute */ 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 */ @@ -238,7 +239,7 @@ class Router if ($route->matchRoute($url, $this->request) === true) { /* Add exception handlers */ - if (\count($route->getExceptionHandlers()) !== 0) { + if (count($route->getExceptionHandlers()) !== 0) { /** @noinspection AdditionOperationOnArraysInspection */ $exceptionHandlers += $route->getExceptionHandlers(); } @@ -292,7 +293,7 @@ class Router /* @var $manager IRouterBootManager */ foreach ($this->bootManagers as $manager) { - $className = \get_class($manager); + $className = get_class($manager); $this->debug('Rendering bootmanager "%s"', $className); $this->fireEvents(EventHandler::EVENT_RENDER_BOOTMANAGER, [ 'bootmanagers' => $this->bootManagers, @@ -315,7 +316,7 @@ class Router * @throws NotFoundHttpException * @throws \Pecee\Http\Middleware\Exceptions\TokenMismatchException * @throws HttpException - * @throws \Exception + * @throws Exception */ public function start(): ?string { @@ -351,7 +352,7 @@ class Router * * @return string|null * @throws HttpException - * @throws \Exception + * @throws Exception */ public function routeRequest(): ?string { @@ -365,7 +366,7 @@ class Router /* @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)); /* If the route matches */ if ($route->matchRoute($url, $this->request) === true) { @@ -375,7 +376,7 @@ class Router ]); /* Check if request method matches */ - if (\count($route->getRequestMethods()) !== 0 && \in_array($this->request->getMethod(), $route->getRequestMethods(), true) === false) { + if (count($route->getRequestMethods()) !== 0 && in_array($this->request->getMethod(), $route->getRequestMethods(), true) === false) { $this->debug('Method "%s" not allowed', $this->request->getMethod()); // Only set method not allowed is not already set @@ -425,7 +426,7 @@ class Router } } - } catch (\Exception $e) { + } catch (Exception $e) { $this->handleException($e); } @@ -434,7 +435,7 @@ class Router $this->handleException(new NotFoundHttpException($message, 403)); } - if (\count($this->request->getLoadedRoutes()) === 0) { + if (count($this->request->getLoadedRoutes()) === 0) { $rewriteUrl = $this->request->getRewriteUrl(); @@ -459,7 +460,7 @@ class Router * @param string $url * @return string|null * @throws HttpException - * @throws \Exception + * @throws Exception */ protected function handleRouteRewrite(string $key, string $url): ?string { @@ -493,14 +494,14 @@ class Router } /** - * @param \Exception $e + * @param Exception $e * @return string|null - * @throws \Exception + * @throws Exception * @throws HttpException */ - protected function handleException(\Exception $e): ?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, @@ -510,7 +511,7 @@ class Router /* @var $handler IExceptionHandler */ foreach ($this->exceptionHandlers as $key => $handler) { - if (\is_object($handler) === false) { + if (is_object($handler) === false) { $handler = new $handler(); } @@ -520,7 +521,7 @@ class Router '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); @@ -549,7 +550,7 @@ class Router return $this->routeRequest(); } - } catch (\Exception $e) { + } catch (Exception $e) { } @@ -592,7 +593,7 @@ class Router } /* Using @ is most definitely a controller@method or alias@method */ - if (\is_string($name) === true && strpos($name, '@') !== false) { + if (is_string($name) === true && strpos($name, '@') !== false) { [$controller, $method] = array_map('strtolower', explode('@', $name)); if ($controller === strtolower($route->getClass()) && $method === strtolower($route->getMethod())) { @@ -604,7 +605,7 @@ class Router /* Check if callback matches (if it's not a function) */ $callback = $route->getCallback(); - if (\is_string($name) === true && \is_string($callback) === true && \is_callable($callback) === false && strpos($name, '@') !== false && strpos($callback, '@') !== false) { + if (is_string($name) === true && is_string($callback) === true && is_callable($callback) === false && strpos($name, '@') !== false && strpos($callback, '@') !== false) { /* Check if the entire callback is matching */ if (strpos($callback, $name) === 0 || strtolower($callback) === strtolower($name)) { @@ -647,7 +648,7 @@ class Router */ public function getUrl(?string $name = null, $parameters = null, ?array $getParams = null): Url { - $this->debug('Finding url', \func_get_args()); + $this->debug('Finding url', func_get_args()); $this->fireEvents(EventHandler::EVENT_GET_URL, [ 'name' => $name, @@ -655,7 +656,7 @@ class Router 'getParams' => $getParams, ]); - if ($getParams !== null && \is_array($getParams) === false) { + if ($getParams !== null && is_array($getParams) === false) { throw new InvalidArgumentException('Invalid type for getParams. Must be array or null'); } @@ -696,7 +697,7 @@ class Router } /* Using @ is most definitely a controller@method or alias@method */ - if (\is_string($name) === true && strpos($name, '@') !== false) { + if (is_string($name) === true && strpos($name, '@') !== false) { [$controller, $method] = explode('@', $name); /* Loop through all the routes to see if we can find a match */ @@ -876,7 +877,7 @@ class Router */ protected function fireEvents(string $name, array $arguments = []): void { - if (\count($this->eventHandlers) === 0) { + if (count($this->eventHandlers) === 0) { return; } diff --git a/src/Pecee/SimpleRouter/SimpleRouter.php b/src/Pecee/SimpleRouter/SimpleRouter.php index 408a8d2..74b3a79 100644 --- a/src/Pecee/SimpleRouter/SimpleRouter.php +++ b/src/Pecee/SimpleRouter/SimpleRouter.php @@ -10,6 +10,8 @@ namespace Pecee\SimpleRouter; +use Closure; +use Exception; use Pecee\Exceptions\InvalidArgumentException; use Pecee\Http\Middleware\BaseCsrfVerifier; use Pecee\Http\Request; @@ -54,7 +56,7 @@ class SimpleRouter * @throws \Pecee\SimpleRouter\Exceptions\NotFoundHttpException * @throws \Pecee\Http\Middleware\Exceptions\TokenMismatchException * @throws HttpException - * @throws \Exception + * @throws Exception */ public static function start(): void { @@ -79,18 +81,18 @@ class SimpleRouter ob_start(); static::router()->setDebugEnabled(true)->start(); $routerOutput = ob_get_clean(); - } catch (\Exception $e) { + } catch (Exception $e) { } // Try to parse library version - $composerFile = \dirname(__DIR__, 3) . '/composer.lock'; + $composerFile = dirname(__DIR__, 3) . '/composer.lock'; $version = false; if (is_file($composerFile) === true) { $composerInfo = json_decode(file_get_contents($composerFile), true); - if (isset($composerInfo['packages']) === true && \is_array($composerInfo['packages']) === true) { + if (isset($composerInfo['packages']) === true && is_array($composerInfo['packages']) === true) { foreach ($composerInfo['packages'] as $package) { if (isset($package['name']) === true && strtolower($package['name']) === 'pecee/simple-router') { $version = $package['version']; @@ -180,7 +182,7 @@ class SimpleRouter * Route the given url to your callback on GET request method. * * @param string $url - * @param string|array|\Closure $callback + * @param string|array|Closure $callback * @param array|null $settings * * @return RouteUrl @@ -194,7 +196,7 @@ class SimpleRouter * Route the given url to your callback on POST request method. * * @param string $url - * @param string|array|\Closure $callback + * @param string|array|Closure $callback * @param array|null $settings * @return RouteUrl */ @@ -207,7 +209,7 @@ class SimpleRouter * Route the given url to your callback on PUT request method. * * @param string $url - * @param string|array|\Closure $callback + * @param string|array|Closure $callback * @param array|null $settings * @return RouteUrl */ @@ -220,7 +222,7 @@ class SimpleRouter * Route the given url to your callback on PATCH request method. * * @param string $url - * @param string|array|\Closure $callback + * @param string|array|Closure $callback * @param array|null $settings * @return RouteUrl */ @@ -233,7 +235,7 @@ class SimpleRouter * Route the given url to your callback on OPTIONS request method. * * @param string $url - * @param string|array|\Closure $callback + * @param string|array|Closure $callback * @param array|null $settings * @return RouteUrl */ @@ -246,7 +248,7 @@ class SimpleRouter * Route the given url to your callback on DELETE request method. * * @param string $url - * @param string|array|\Closure $callback + * @param string|array|Closure $callback * @param array|null $settings * @return RouteUrl */ @@ -259,13 +261,13 @@ class SimpleRouter * Groups allows for encapsulating routes with special settings. * * @param array $settings - * @param \Closure $callback + * @param Closure $callback * @return RouteGroup * @throws InvalidArgumentException */ - public static function group(array $settings, \Closure $callback): IGroupRoute + public static function group(array $settings, Closure $callback): IGroupRoute { - if (\is_callable($callback) === false) { + if (is_callable($callback) === false) { throw new InvalidArgumentException('Invalid callback provided. Only functions or methods supported'); } @@ -283,14 +285,14 @@ class SimpleRouter * parameters and which are only rendered when the url matches. * * @param string $url - * @param \Closure $callback + * @param Closure $callback * @param array $settings * @return RoutePartialGroup * @throws InvalidArgumentException */ - public static function partialGroup(string $url, \Closure $callback, array $settings = []): IPartialGroupRoute + public static function partialGroup(string $url, Closure $callback, array $settings = []): IPartialGroupRoute { - if (\is_callable($callback) === false) { + if (is_callable($callback) === false) { throw new InvalidArgumentException('Invalid callback provided. Only functions or methods supported'); } @@ -309,7 +311,7 @@ class SimpleRouter * Alias for the form method * * @param string $url - * @param string|array|\Closure $callback + * @param string|array|Closure $callback * @param array|null $settings * @return RouteUrl * @see SimpleRouter::form @@ -324,7 +326,7 @@ class SimpleRouter * Route the given url to your callback on POST and GET request method. * * @param string $url - * @param string|array|\Closure $callback + * @param string|array|Closure $callback * @param array|null $settings * @return RouteUrl * @see SimpleRouter::form @@ -342,7 +344,7 @@ class SimpleRouter * * @param array $requestMethods * @param string $url - * @param string|array|\Closure $callback + * @param string|array|Closure $callback * @param array|null $settings * @return RouteUrl|IRoute */ @@ -362,7 +364,7 @@ class SimpleRouter * 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 string|array|Closure $callback * @param array|null $settings * @return RouteUrl|IRoute */ @@ -418,10 +420,10 @@ class SimpleRouter /** * Add exception callback handler. * - * @param \Closure $callback + * @param Closure $callback * @return CallbackExceptionHandler $callbackHandler */ - public static function error(\Closure $callback): CallbackExceptionHandler + public static function error(Closure $callback): CallbackExceptionHandler { $routes = static::router()->getRoutes(); @@ -458,7 +460,7 @@ class SimpleRouter { try { return static::router()->getUrl($name, $parameters, $getParams); - } catch (\Exception $e) { + } catch (Exception $e) { return new Url('/'); } } diff --git a/tests/Pecee/SimpleRouter/Dummy/ClassLoader/CustomClassLoader.php b/tests/Pecee/SimpleRouter/Dummy/ClassLoader/CustomClassLoader.php index 17bff54..ee5ebe6 100644 --- a/tests/Pecee/SimpleRouter/Dummy/ClassLoader/CustomClassLoader.php +++ b/tests/Pecee/SimpleRouter/Dummy/ClassLoader/CustomClassLoader.php @@ -7,8 +7,20 @@ class CustomClassLoader implements \Pecee\SimpleRouter\ClassLoader\IClassLoader return new DummyController(); } + /** + * Called when loading class method + * @param object $class + * @param string $method + * @param array $parameters + * @return object + */ + public function loadClassMethod($class, string $method, array $parameters) + { + return call_user_func_array([$class, $method], ['result' => true]); + } + public function loadClosure(callable $closure, array $parameters) { - return \call_user_func_array($closure, ['result' => true]); + return call_user_func_array($closure, ['result' => true]); } } \ No newline at end of file diff --git a/tests/Pecee/SimpleRouter/InputHandlerTest.php b/tests/Pecee/SimpleRouter/InputHandlerTest.php index 11dcf28..be50698 100644 --- a/tests/Pecee/SimpleRouter/InputHandlerTest.php +++ b/tests/Pecee/SimpleRouter/InputHandlerTest.php @@ -122,7 +122,20 @@ class InputHandlerTest extends \PHPUnit\Framework\TestCase $_GET = []; } + public function testFindInput() { + global $_POST; + $_POST['hello'] = 'motto'; + + $router = TestRouter::router(); + $router->reset(); + $router->getRequest()->setMethod('post'); + $inputHandler = TestRouter::request()->getInputHandler(); + + $value = $inputHandler->value('hello', null, \Pecee\Http\Request::$requestTypesPost); + + $this->assertEquals($_POST['hello'], $value); + } public function testFile() { diff --git a/tests/Pecee/SimpleRouter/RouterPartialGroupTest.php b/tests/Pecee/SimpleRouter/RouterPartialGroupTest.php index 40e288a..df78d9f 100644 --- a/tests/Pecee/SimpleRouter/RouterPartialGroupTest.php +++ b/tests/Pecee/SimpleRouter/RouterPartialGroupTest.php @@ -70,4 +70,47 @@ class RouterPartialGroupTest extends \PHPUnit\Framework\TestCase } + public function testPhp8CallUserFunc() { + + TestRouter::router()->reset(); + + $result = false; + $lang = 'de'; + + TestRouter::group(['prefix' => '/lang'], function() use(&$result) { + TestRouter::get('/{lang}', function ($lang) use(&$result) { + $result = $lang; + }); + }); + + TestRouter::debug("/lang/$lang"); + + $this->assertEquals($lang, $result); + + // Test partial group + + $lang = 'de'; + $userId = 22; + + $result1 = false; + $result2 = false; + + TestRouter::partialGroup( + '/lang/{lang}/', + function ($lang) use(&$result1, &$result2) { + + $result1 = $lang; + + TestRouter::get('/user/{userId}', function ($userId) use(&$result2) { + $result2 = $userId; + }); + }); + + TestRouter::debug("/lang/$lang/user/$userId"); + + $this->assertEquals($lang, $result1); + $this->assertEquals($userId, $result2); + + } + } \ No newline at end of file diff --git a/tests/Pecee/SimpleRouter/RouterUrlTest.php b/tests/Pecee/SimpleRouter/RouterUrlTest.php index f9b0d4b..7e619a6 100644 --- a/tests/Pecee/SimpleRouter/RouterUrlTest.php +++ b/tests/Pecee/SimpleRouter/RouterUrlTest.php @@ -271,4 +271,81 @@ class RouterUrlTest extends \PHPUnit\Framework\TestCase TestRouter::router()->reset(); } + public function testGroupPrefix() { + + $result = false; + + TestRouter::group(['prefix' => '/lang/{lang}'], function () use(&$result) { + + TestRouter::get('/test', function() use(&$result) { + $result = true; + }); + }); + + TestRouter::debug('/lang/da/test'); + + $this->assertTrue($result); + + // Test group prefix sub-route + + $result = null; + $expectedResult = 28; + + TestRouter::group(['prefix' => '/lang/{lang}'], function () use(&$result) { + + TestRouter::get('/horse/{horseType}', function($horseType) use(&$result) { + $result = false; + }); + + TestRouter::get('/user/{userId}', function($userId) use(&$result) { + $result = $userId; + }); + }); + + TestRouter::debug("/lang/da/user/$expectedResult"); + + $this->assertEquals($expectedResult, $result); + + } + + public function testPassParameter() { + + $result = false; + $expectedLanguage = 'da'; + + TestRouter::group(['prefix' => '/lang/{lang}'], function ($language) use(&$result) { + + TestRouter::get('/test', function($language) use(&$result) { + $result = $language; + }); + + }); + + TestRouter::debug("/lang/$expectedLanguage/test"); + + $this->assertEquals($expectedLanguage, $result); + + } + + public function testPassParameterDeep() { + + $result = false; + $expectedLanguage = 'da'; + + TestRouter::group(['prefix' => '/lang/{lang}'], function ($language) use(&$result) { + + TestRouter::group(['prefix' => '/admin'], function($language) use(&$result) { + TestRouter::get('/test', function($language) use(&$result) { + $result = $language; + }); + }); + + }); + + TestRouter::debug("/lang/$expectedLanguage/admin/test"); + + $this->assertEquals($expectedLanguage, $result); + + } + } \ No newline at end of file