diff --git a/.gitignore b/.gitignore index 8dc5dfc..6e51a97 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ composer.lock vendor/ -tests/tmp/* .idea/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 72c98f1..0595845 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,11 +3,25 @@ sudo: false language: php php: - - 7.1 + - 7.2 before_script: - - curl -sS http://getcomposer.org/installer | php - - php composer.phar install --prefer-source --no-interaction + - mkdir -p _clover + - ls -al script: - - ./vendor/bin/phpunit + - ./vendor/bin/phpunit --coverage-clover _clover/clover.xml + +install: + # Install composer packages + - travis_retry composer install --no-interaction --no-suggest + # Install coveralls.phar + - wget -c -nc --retry-connrefused --tries=0 https://github.com/php-coveralls/php-coveralls/releases/download/v2.0.0/php-coveralls.phar -O coveralls.phar + - chmod +x coveralls.phar + - php coveralls.phar --version + +after_success: + # Submit coverage report to Coveralls servers, see .coveralls.yml + - travis_retry php coveralls.phar -v + # Submit coverage report to codecov.io + - bash <(curl -s https://codecov.io/bash) \ No newline at end of file diff --git a/README.md b/README.md index 21dfc5a..701c012 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,7 @@ SimpleRouter::get('/', function() { ### Support the project -If you like simple-router and wish to see the continued development and maintenance of the project, -please consider showing your support by buying me a coffee. Supporters will be listed under the credits section of this documentation. +If you like simple-router and wish to see the continued development and maintenance of the project, please consider showing your support by buying me a coffee. Supporters will be listed under the credits section of this documentation. You can donate any amount of your choice by [clicking here](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=NNX4D2RUSALCN). @@ -52,9 +51,6 @@ You can donate any amount of your choice by [clicking here](https://www.paypal.c - [Partial groups](#partial-groups) - [Form Method Spoofing](#form-method-spoofing) - [Accessing The Current Route](#accessing-the-current-route) - - [Dependency injection](#dependency-injection) - - [Enabling dependency injection](#enabling-dependency-injection) - - [More reading](#more-reading) - [Other examples](#other-examples) - [CSRF-protection](#csrf-protection) - [Adding CSRF-verifier](#adding-csrf-verifier) @@ -91,6 +87,8 @@ You can donate any amount of your choice by [clicking here](https://www.paypal.c - [Changing current route](#changing-current-route) - [Bootmanager: loading routes dynamically](#bootmanager-loading-routes-dynamically) - [Adding routes manually](#adding-routes-manually) + - [Custom class-loader](#custom-class-loader) + - [Integrating with php-di](#Integrating-with-php-di) - [Parameters](#parameters) - [Extending](#extending) - [Help and support](#help-and-support) @@ -125,7 +123,7 @@ composer require pecee/simple-router The goal of this project is to create a router that is more or less 100% compatible with the Laravel documentation, while remaining as simple as possible, and as easy to integrate and change without compromising either speed or complexity. Being lightweight is the #1 priority. -We've included a simple demo project for the router which can be found in the `demo-project` folder. This project should give you a basic understanding of how to setup and use simple-php-router project. +We've included a simple demo project for the router which can be found [here](https://github.com/skipperbent/simple-router-demo). This project should give you a basic understanding of how to setup and use simple-php-router project. Please note that the demo-project only covers how to integrate the `simple-php-router` in a project without an existing framework. If you are using a framework in your project, the implementation might vary. @@ -252,6 +250,7 @@ To add `favicon.ico` to the IIS ignore-list, add the following line to the ` ``` @@ -259,6 +258,7 @@ You can also make one exception for files with some extensions: If you are using `$_SERVER['ORIG_PATH_INFO']`, you will get `\index.php\` as part of the returned value. **Example:** + ``` /index.php/test/mypage.php ``` @@ -697,88 +697,6 @@ SimpleRouter::request()->getLoadedRoute(); request()->getLoadedRoute(); ``` -## Dependency injection - -simple-router supports dependency injection using the [`php-di`](http://php-di.org/) library. - -Dependency injection allows the framework to automatically "inject" (load) classes added as parameters. This can simplify your code, as you can avoid creating new instances of objects you are using often in your `Controllers` etc. - -Here's a basic example of a controller class using dependency injection: - -```php -namespace Demo\Controllers; - -class DefaultController { - - public function login(User $user): string - { - // ... - } - -} -``` - -The example above will automatically create a new instance of the `User` from the `$user` parameter. This means that the `$user` class contains a new instance of the `User` class and we won't need to create a new instance our self. - -**WARNING:** dependency injection can have some negative impact in performance. If you experience any performance issues, we recommend disabling this functionality. - -### Enabling dependency injection - -Dependency injection is disabled per default to avoid any performance issues. - -Before enabling dependency injection, we recommend that you read the [Container configuration](http://php-di.org/doc/container-configuration.html) section of the php-di documentation. This section covers how to configure php-di to different environments and speed-up the performance. - -#### Enabling for development environment - -The example below should ONLY be used on a development environment. - -```php -// Create our new php-di container -$container = (new \DI\ContainerBuilder()) - ->useAutowiring(true) - ->build(); - -// Add our container to simple-router and enable dependency injection -SimpleRouter::enableDependencyInjection($container); -``` - -Please check the [More reading](#more-reading) section of the documentation for useful php-di links and tutorials. - -#### Enabling for production environment - -The example below compiles the injections, which can help speed up performance. - -**Note:** You should change the `$cacheDir` to a cache-storage within your project. - -```php -// Cache directory -$cacheDir = sys_get_temp_dir('simple-router'); - -// Create our new php-di container -$container = (new \DI\ContainerBuilder()) - ->enableCompilation($cacheDir) - ->writeProxiesToFile(true, $cacheDir . '/proxies') - ->useAutowiring(true) - ->build(); - -// Add our container to simple-router and enable dependency injection -SimpleRouter::enableDependencyInjection($container); -``` - -Please check the [More reading](#more-reading) section of the documentation for useful php-di links and tutorials. - -### More reading - -For more information about dependency injection, configuration and settings - we recommend that you check the php-di documentation or some of the useful links we've gathered below. - -#### Useful links - -- [php-di documentation](http://php-di.org/doc/) -- [Understanding dependency injection](http://php-di.org/doc/understanding-di.html) -- [Best practices guide](http://php-di.org/doc/best-practices.html) -- [Configuring the container](http://php-di.org/doc/container-configuration.html) -- [Definitions](http://php-di.org/doc/definition.html) - ## Other examples You can find many more examples in the `routes.php` example-file below: @@ -1502,7 +1420,7 @@ class CustomRouterRules implement IRouterBootManager // If the current url matches the rewrite url, we use our custom route - if($request->getUrl()->getPath() === $url) { + if($request->getUrl()->contains($url)) { $request->setRewriteUrl($rule); } } @@ -1550,6 +1468,119 @@ $route->setPrefix('v1'); $router->addRoute($route); ``` +## Custom class loader + +You can easily extend simple-router to support custom injection frameworks like php-di by taking advantage of the ability to add your custom class-loader. + +Class-loaders must inherit the `IClassLoader` interface. + +**Example:** + +```php +class MyCustomClassLoader implements IClassLoader +{ + /** + * Load class + * + * @param string $class + * @return object + * @throws NotFoundHttpException + */ + public function loadClass(string $class) + { + if (\class_exists($class) === false) { + throw new NotFoundHttpException(sprintf('Class "%s" does not exist', $class), 404); + } + + return new $class(); + } + + /** + * Load closure + * + * @param Callable $closure + * @param array $parameters + * @return mixed + */ + public function loadClosure(Callable $closure, array $parameters) + { + return \call_user_func_array($closure, $parameters); + } + +} +``` + +Next, we need to configure our `routes.php` so the router uses our `MyCustomClassLoader` class for loading classes. This can be done by adding the following line to your `routes.php` file. + +```php +SimpleRouter::setCustomClassLoader(new MyCustomClassLoader()); +``` + +### Integrating with php-di + +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 +class MyCustomClassLoader implements IClassLoader +{ + + protected $container; + + public function __construct() + { + // Create our new php-di container + $container = (new \DI\ContainerBuilder()) + ->useAutowiring(true) + ->build(); + } + + /** + * Load class + * + * @param string $class + * @return object + * @throws NotFoundHttpException + */ + public function loadClass(string $class) + { + if (class_exists($class) === false) { + 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(); + } + + /** + * Load closure + * + * @param Callable $closure + * @param array $parameters + * @return mixed + */ + 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); + } + +} +``` + ## Parameters This section contains advanced tips & tricks on extending the usage for parameters. diff --git a/composer.json b/composer.json index 5d285cd..8514aee 100644 --- a/composer.json +++ b/composer.json @@ -28,8 +28,7 @@ ], "require": { "php": ">=7.1", - "ext-json": "*", - "php-di/php-di": "^6.0" + "ext-json": "*" }, "require-dev": { "phpunit/phpunit": "^6.0", diff --git a/src/Pecee/Http/Input/InputHandler.php b/src/Pecee/Http/Input/InputHandler.php index e485505..c6a000d 100644 --- a/src/Pecee/Http/Input/InputHandler.php +++ b/src/Pecee/Http/Input/InputHandler.php @@ -319,7 +319,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/SimpleRouter/ClassLoader/ClassLoader.php b/src/Pecee/SimpleRouter/ClassLoader/ClassLoader.php index c928339..f1e5729 100644 --- a/src/Pecee/SimpleRouter/ClassLoader/ClassLoader.php +++ b/src/Pecee/SimpleRouter/ClassLoader/ClassLoader.php @@ -2,44 +2,21 @@ namespace Pecee\SimpleRouter\ClassLoader; -use DI\Container; -use Pecee\SimpleRouter\Exceptions\NotFoundHttpException; +use Pecee\SimpleRouter\Exceptions\ClassNotFoundHttpException; class ClassLoader implements IClassLoader { - /** - * Dependency injection enabled - * @var bool - */ - protected $useDependencyInjection = false; - - /** - * @var Container|null - */ - protected $container; - /** * Load class * * @param string $class - * @return mixed + * @return object * @throws NotFoundHttpException */ public function loadClass(string $class) { if (class_exists($class) === false) { - throw new NotFoundHttpException(sprintf('Class "%s" does not exist', $class), 404); - } - - if ($this->useDependencyInjection === true) { - $container = $this->getContainer(); - if ($container !== null) { - try { - return $container->get($class); - } catch (\Exception $e) { - throw new NotFoundHttpException($e->getMessage(), (int)$e->getCode(), $e->getPrevious()); - } - } + throw new ClassNotFoundHttpException(sprintf('Class "%s" does not exist', $class), 404, null, $class); } return new $class(); @@ -51,68 +28,10 @@ class ClassLoader implements IClassLoader * @param Callable $closure * @param array $parameters * @return mixed - * @throws NotFoundHttpException */ public function loadClosure(Callable $closure, array $parameters) { - if ($this->useDependencyInjection === true) { - $container = $this->getContainer(); - if ($container !== null) { - try { - return $container->call($closure, $parameters); - } catch (\Exception $e) { - throw new NotFoundHttpException($e->getMessage(), (int)$e->getCode(), $e->getPrevious()); - } - } - } - return \call_user_func_array($closure, $parameters); } - /** - * Get dependency injector container. - * - * @return Container|null - */ - public function getContainer(): ?Container - { - return $this->container; - } - - /** - * Set the dependency-injector container. - * - * @param Container $container - * @return ClassLoader - */ - public function setContainer(Container $container): self - { - $this->container = $container; - - return $this; - } - - /** - * Enable or disable dependency injection. - * - * @param bool $enabled - * @return static - */ - public function useDependencyInjection(bool $enabled): self - { - $this->useDependencyInjection = $enabled; - - return $this; - } - - /** - * Return true if dependency injection is enabled. - * - * @return bool - */ - public function isDependencyInjectionEnabled(): bool - { - return $this->useDependencyInjection; - } - } diff --git a/src/Pecee/SimpleRouter/ClassLoader/IClassLoader.php b/src/Pecee/SimpleRouter/ClassLoader/IClassLoader.php index f9c00a4..8eb8cd1 100644 --- a/src/Pecee/SimpleRouter/ClassLoader/IClassLoader.php +++ b/src/Pecee/SimpleRouter/ClassLoader/IClassLoader.php @@ -5,8 +5,20 @@ namespace Pecee\SimpleRouter\ClassLoader; interface IClassLoader { + /** + * Called when loading class + * @param string $class + * @return object + */ public function loadClass(string $class); + /** + * Called when loading method + * + * @param callable $closure + * @param array $parameters + * @return mixed + */ public function loadClosure(Callable $closure, array $parameters); } diff --git a/src/Pecee/SimpleRouter/Exceptions/ClassNotFoundHttpException.php b/src/Pecee/SimpleRouter/Exceptions/ClassNotFoundHttpException.php new file mode 100644 index 0000000..d283874 --- /dev/null +++ b/src/Pecee/SimpleRouter/Exceptions/ClassNotFoundHttpException.php @@ -0,0 +1,38 @@ +class = $class; + $this->method = $method; + } + + /** + * Get class name + * @return string + */ + public function getClass(): string + { + return $this->class; + } + + /** + * Get method + * @return string|null + */ + public function getMethod(): ?string + { + return $this->method; + } + +} \ No newline at end of file diff --git a/src/Pecee/SimpleRouter/Handlers/EventHandler.php b/src/Pecee/SimpleRouter/Handlers/EventHandler.php index 9ac42ec..70b37b3 100644 --- a/src/Pecee/SimpleRouter/Handlers/EventHandler.php +++ b/src/Pecee/SimpleRouter/Handlers/EventHandler.php @@ -143,7 +143,7 @@ class EventHandler implements IEventHandler * Get events. * * @param string|null $name Filter events by name. - * @param array ...$names Add multiple names... + * @param array|string ...$names Add multiple names... * @return array */ public function getEvents(?string $name, ...$names): array diff --git a/src/Pecee/SimpleRouter/Route/Route.php b/src/Pecee/SimpleRouter/Route/Route.php index 3e9370c..1696c98 100644 --- a/src/Pecee/SimpleRouter/Route/Route.php +++ b/src/Pecee/SimpleRouter/Route/Route.php @@ -4,6 +4,7 @@ namespace Pecee\SimpleRouter\Route; use Pecee\Http\Middleware\IMiddleware; use Pecee\Http\Request; +use Pecee\SimpleRouter\Exceptions\ClassNotFoundHttpException; use Pecee\SimpleRouter\Exceptions\NotFoundHttpException; use Pecee\SimpleRouter\Router; @@ -77,7 +78,6 @@ abstract class Route implements IRoute $router->debug('Executing callback'); /* When the callback is a function */ - return $router->getClassLoader()->loadClosure($callback, $parameters); } @@ -95,7 +95,7 @@ abstract class Route implements IRoute } if (method_exists($class, $method) === false) { - throw new NotFoundHttpException(sprintf('Method "%s" does not exist in class "%s"', $method, $className), 404); + throw new ClassNotFoundHttpException(sprintf('Method "%s" does not exist in class "%s"', $method, $className), 404, null, $className, $method); } $router->debug('Executing callback'); @@ -250,7 +250,7 @@ abstract class Route implements IRoute /** * Set callback * - * @param string|array\Closure $callback + * @param string|array|\Closure $callback * @return static */ public function setCallback($callback): IRoute diff --git a/src/Pecee/SimpleRouter/Router.php b/src/Pecee/SimpleRouter/Router.php index 6f8781d..99ecb07 100644 --- a/src/Pecee/SimpleRouter/Router.php +++ b/src/Pecee/SimpleRouter/Router.php @@ -276,6 +276,13 @@ class Router { $this->debug('Loading routes'); + $this->fireEvents(EventHandler::EVENT_LOAD_ROUTES, [ + 'routes' => $this->routes, + ]); + + /* Loop through each route-request */ + $this->processRoutes($this->routes); + $this->fireEvents(EventHandler::EVENT_BOOT, [ 'bootmanagers' => $this->bootManagers, ]); @@ -298,13 +305,6 @@ class Router $this->debug('Finished rendering bootmanager "%s"', $className); } - $this->fireEvents(EventHandler::EVENT_LOAD_ROUTES, [ - 'routes' => $this->routes, - ]); - - /* Loop through each route-request */ - $this->processRoutes($this->routes); - $this->debug('Finished loading routes'); } @@ -313,7 +313,7 @@ class Router * * @return string|null * @throws NotFoundHttpException - * @throws TokenMismatchException + * @throws \Pecee\Http\Middleware\Exceptions\TokenMismatchException * @throws HttpException * @throws \Exception */ diff --git a/src/Pecee/SimpleRouter/SimpleRouter.php b/src/Pecee/SimpleRouter/SimpleRouter.php index 2e79055..d11d255 100644 --- a/src/Pecee/SimpleRouter/SimpleRouter.php +++ b/src/Pecee/SimpleRouter/SimpleRouter.php @@ -10,7 +10,6 @@ namespace Pecee\SimpleRouter; -use DI\Container; use Pecee\Exceptions\InvalidArgumentException; use Pecee\Http\Middleware\BaseCsrfVerifier; use Pecee\Http\Request; @@ -59,6 +58,11 @@ class SimpleRouter */ public static function start(): void { + // Set default namespaces + foreach (static::router()->getRoutes() as $route) { + static::addDefaultNamespace($route); + } + echo static::router()->start(); } @@ -307,8 +311,8 @@ class SimpleRouter * @param string $url * @param string|array|\Closure $callback * @param array|null $settings - * @see SimpleRouter::form * @return RouteUrl + * @see SimpleRouter::form */ public static function basic(string $url, $callback, array $settings = null): IRoute { @@ -322,14 +326,14 @@ class SimpleRouter * @param string $url * @param string|array|\Closure $callback * @param array|null $settings - * @see SimpleRouter::form * @return RouteUrl + * @see SimpleRouter::form */ public static function form(string $url, $callback, array $settings = null): IRoute { return static::match([ Request::REQUEST_TYPE_GET, - Request::REQUEST_TYPE_POST + Request::REQUEST_TYPE_POST, ], $url, $callback, $settings); } @@ -346,7 +350,6 @@ class SimpleRouter { $route = new RouteUrl($url, $callback); $route->setRequestMethods($requestMethods); - $route = static::addDefaultNamespace($route); if ($settings !== null) { $route->setSettings($settings); @@ -366,7 +369,6 @@ class SimpleRouter public static function all(string $url, $callback, array $settings = null) { $route = new RouteUrl($url, $callback); - $route = static::addDefaultNamespace($route); if ($settings !== null) { $route->setSettings($settings); @@ -386,7 +388,6 @@ class SimpleRouter public static function controller(string $url, string $controller, array $settings = null) { $route = new RouteController($url, $controller); - $route = static::addDefaultNamespace($route); if ($settings !== null) { $route->setSettings($settings); @@ -406,7 +407,6 @@ class SimpleRouter public static function resource(string $url, string $controller, array $settings = null) { $route = new RouteResource($url, $controller); - $route = static::addDefaultNamespace($route); if ($settings !== null) { $route->setSettings($settings); @@ -511,22 +511,19 @@ class SimpleRouter { if (static::$defaultNamespace !== null) { - $callback = $route->getCallback(); + $ns = static::$defaultNamespace; + $namespace = $route->getNamespace(); - /* Only add default namespace on relative callbacks */ - if ($callback === null || (\is_string($callback) === true && $callback[0] !== '\\')) { - - $namespace = static::$defaultNamespace; - - $currentNamespace = $route->getNamespace(); - - if ($currentNamespace !== null) { - $namespace .= '\\' . $currentNamespace; + if ($namespace !== null) { + // Don't overwrite namespaces that starts with \ + if ($namespace[0] !== '\\') { + $ns .= '\\' . $namespace; + } else { + $ns = $namespace; } - - $route->setDefaultNamespace($namespace); - } + + $route->setNamespace($ns); } return $route; @@ -545,17 +542,12 @@ class SimpleRouter } /** - * Enable or disable dependency injection - * - * @param Container $container - * @return IClassLoader + * Set custom class-loader class used. + * @param IClassLoader $classLoader */ - public static function enableDependencyInjection(Container $container): IClassLoader + public static function setCustomClassLoader(IClassLoader $classLoader): void { - return static::router() - ->getClassLoader() - ->useDependencyInjection(true) - ->setContainer($container); + static::router()->setClassLoader($classLoader); } /** diff --git a/tests/Pecee/SimpleRouter/BootManagerTest.php b/tests/Pecee/SimpleRouter/BootManagerTest.php new file mode 100644 index 0000000..925ea97 --- /dev/null +++ b/tests/Pecee/SimpleRouter/BootManagerTest.php @@ -0,0 +1,49 @@ + '/about', + '/contact' => '/', + ])); + + TestRouter::debug('/contact'); + + $this->assertTrue($result); + } + + public function testFindUrlFromBootManager() + { + TestRouter::get('/', 'DummyController@method1'); + TestRouter::get('/about', 'DummyController@method2')->name('about'); + TestRouter::get('/contact', 'DummyController@method3')->name('contact'); + + $result = false; + + // Add boot-manager + TestRouter::addBootManager(new FindUrlBootManager($result)); + + TestRouter::debug('/'); + + $this->assertTrue($result); + } + +} \ No newline at end of file diff --git a/tests/Pecee/SimpleRouter/ClassLoaderTest.php b/tests/Pecee/SimpleRouter/ClassLoaderTest.php new file mode 100644 index 0000000..79f6095 --- /dev/null +++ b/tests/Pecee/SimpleRouter/ClassLoaderTest.php @@ -0,0 +1,30 @@ +assertEquals('method3', $classLoaderClass); + $this->assertTrue($result); + + TestRouter::router()->reset(); + } + +} \ No newline at end of file diff --git a/tests/Pecee/SimpleRouter/DependencyInjectionTest.php b/tests/Pecee/SimpleRouter/DependencyInjectionTest.php deleted file mode 100644 index 8863f19..0000000 --- a/tests/Pecee/SimpleRouter/DependencyInjectionTest.php +++ /dev/null @@ -1,53 +0,0 @@ -useAutowiring(true) - ->ignorePhpDocErrors(true) - ->build(); - - TestRouter::enableDependencyInjection($container); - - $className = null; - - TestRouter::get('/', function (DummyMiddleware $url) use (&$className) { - $className = \get_class($url); - }); - - TestRouter::debug('/'); - - $this->assertEquals(DummyMiddleware::class, $className); - } - - public function testDependencyInjectionProduction() - { - $cacheDir = dirname(__DIR__, 2) . '/tmp'; - - $builder = new \DI\ContainerBuilder(); - $builder - ->enableCompilation($cacheDir) - ->writeProxiesToFile(true, $cacheDir . '/proxies') - ->ignorePhpDocErrors(true) - ->useAutowiring(true); - - $container = $builder->build(); - - TestRouter::enableDependencyInjection($container); - - $className = null; - - TestRouter::get('/', function (DummyMiddleware $url) use (&$className) { - $className = \get_class($url); - }); - - TestRouter::debug('/'); - - $this->assertEquals(DummyMiddleware::class, $className); - } -} \ No newline at end of file diff --git a/tests/Pecee/SimpleRouter/Dummy/ClassLoader/CustomClassLoader.php b/tests/Pecee/SimpleRouter/Dummy/ClassLoader/CustomClassLoader.php new file mode 100644 index 0000000..17bff54 --- /dev/null +++ b/tests/Pecee/SimpleRouter/Dummy/ClassLoader/CustomClassLoader.php @@ -0,0 +1,14 @@ + true]); + } +} \ No newline at end of file diff --git a/tests/Pecee/SimpleRouter/Dummy/DummyController.php b/tests/Pecee/SimpleRouter/Dummy/DummyController.php index 4150118..3b25e5d 100644 --- a/tests/Pecee/SimpleRouter/Dummy/DummyController.php +++ b/tests/Pecee/SimpleRouter/Dummy/DummyController.php @@ -16,6 +16,11 @@ class DummyController public function method2() { + } + + public function method3() + { + return 'method3'; } public function param($params = null) diff --git a/tests/Pecee/SimpleRouter/Dummy/Managers/FindUrlBootManager.php b/tests/Pecee/SimpleRouter/Dummy/Managers/FindUrlBootManager.php new file mode 100644 index 0000000..f8bdcf3 --- /dev/null +++ b/tests/Pecee/SimpleRouter/Dummy/Managers/FindUrlBootManager.php @@ -0,0 +1,26 @@ +result = &$result; + } + + /** + * Called when router loads it's routes + * + * @param \Pecee\SimpleRouter\Router $router + * @param \Pecee\Http\Request $request + */ + public function boot(\Pecee\SimpleRouter\Router $router, \Pecee\Http\Request $request): void + { + $contact = $router->findRoute('contact'); + + if($contact !== null) { + $this->result = true; + } + } +} \ No newline at end of file diff --git a/tests/Pecee/SimpleRouter/Dummy/Managers/TestBootManager.php b/tests/Pecee/SimpleRouter/Dummy/Managers/TestBootManager.php index 8516aae..1617b46 100644 --- a/tests/Pecee/SimpleRouter/Dummy/Managers/TestBootManager.php +++ b/tests/Pecee/SimpleRouter/Dummy/Managers/TestBootManager.php @@ -3,13 +3,11 @@ class TestBootManager implements \Pecee\SimpleRouter\IRouterBootManager { - protected $routes; - protected $aliasUrl; + protected $rewrite; - public function __construct(array $routes, string $aliasUrl) + public function __construct(array $rewrite) { - $this->routes = $routes; - $this->aliasUrl = $aliasUrl; + $this->rewrite = $rewrite; } /** @@ -20,11 +18,11 @@ class TestBootManager implements \Pecee\SimpleRouter\IRouterBootManager */ public function boot(\Pecee\SimpleRouter\Router $router, \Pecee\Http\Request $request): void { - foreach ($this->routes as $url) { + foreach ($this->rewrite as $url => $rewrite) { // If the current url matches the rewrite url, we use our custom route if ($request->getUrl()->contains($url) === true) { - $request->setRewriteUrl($this->aliasUrl); + $request->setRewriteUrl($rewrite); } } diff --git a/tests/Pecee/SimpleRouter/EventHandlerTest.php b/tests/Pecee/SimpleRouter/EventHandlerTest.php index 8fa873d..faaa5d9 100644 --- a/tests/Pecee/SimpleRouter/EventHandlerTest.php +++ b/tests/Pecee/SimpleRouter/EventHandlerTest.php @@ -50,8 +50,8 @@ class EventHandlerTest extends \PHPUnit\Framework\TestCase // Add boot-manager TestRouter::addBootManager(new TestBootManager([ - '/test', - ], '/')); + '/test' => '/', + ])); // Start router TestRouter::debug('/non-existing'); @@ -61,7 +61,6 @@ class EventHandlerTest extends \PHPUnit\Framework\TestCase public function testAllEvent() { - $status = false; $eventHandler = new EventHandler(); diff --git a/tests/Pecee/SimpleRouter/RouterUrlTest.php b/tests/Pecee/SimpleRouter/RouterUrlTest.php index 8a1d1fa..f9b0d4b 100644 --- a/tests/Pecee/SimpleRouter/RouterUrlTest.php +++ b/tests/Pecee/SimpleRouter/RouterUrlTest.php @@ -218,7 +218,57 @@ class RouterUrlTest extends \PHPUnit\Framework\TestCase TestRouter::debug('/'); - $this->assertCount(2, $result); + $this->assertCount(2, $result); + } + + public function testDefaultNamespace() + { + TestRouter::setDefaultNamespace('\\Default\\Namespace'); + + TestRouter::get('/', 'DummyController@method1', ['as' => 'home']); + + TestRouter::group([ + 'namespace' => 'Appended\Namespace', + 'prefix' => '/horses', + ], function () { + + TestRouter::get('/', 'DummyController@method1'); + + TestRouter::group([ + 'namespace' => '\\New\\Namespace', + 'prefix' => '/race', + ], function () { + + TestRouter::get('/', 'DummyController@method1'); + + }); + }); + + // Test appended namespace + + $class = null; + + try { + TestRouter::debugNoReset('/horses/'); + } catch (\Pecee\SimpleRouter\Exceptions\ClassNotFoundHttpException $e) { + $class = $e->getClass(); + } + + $this->assertEquals('\\Default\\Namespace\\Appended\Namespace\\DummyController', $class); + + // Test overwritten namespace + + $class = null; + + try { + TestRouter::debugNoReset('/horses/race'); + } catch (\Pecee\SimpleRouter\Exceptions\ClassNotFoundHttpException $e) { + $class = $e->getClass(); + } + + $this->assertEquals('\\New\\Namespace\\DummyController', $class); + + TestRouter::router()->reset(); } } \ No newline at end of file