diff --git a/app/Bootstrap/AppManager.php b/app/Bootstrap/AppManager.php index 55d93cc..bfe90ca 100644 --- a/app/Bootstrap/AppManager.php +++ b/app/Bootstrap/AppManager.php @@ -2,6 +2,7 @@ namespace App\Bootstrap; +use App\Middleware; use App\Providers; use DI\Bridge\Slim\Bridge; use DI\Container; @@ -19,6 +20,11 @@ class AppManager Providers\TwigProvider::class, ]; + /** @const Constant description */ + protected const MIDDLEWARES = [ + Middleware\StripBasePathMiddleware::class, + ]; + /** @var Container The applicaiton container */ protected $container; @@ -48,8 +54,10 @@ class AppManager public function __invoke(): App { $this->registerProviders(); + $app = Bridge::create($this->container); + $this->registerMiddlewares($app); - return Bridge::create($this->container); + return $app; } /** @@ -67,4 +75,20 @@ class AppManager ); }); } + + /** + * Register application middleware. + * + * @param \Slim\App $app + * + * @return void + */ + protected function registerMiddlewares(App $app): void + { + Collection::make(self::MIDDLEWARES)->merge( + $this->config->get('app.middlewares', []) + )->each(function (string $middleware) use ($app) { + $app->add($middleware); + }); + } } diff --git a/app/Middleware/StripBasePathMiddleware.php b/app/Middleware/StripBasePathMiddleware.php new file mode 100644 index 0000000..3706e72 --- /dev/null +++ b/app/Middleware/StripBasePathMiddleware.php @@ -0,0 +1,57 @@ +container = $container; + } + + /** + * Canonicalize the received path variable. + * + * @param \Slim\Psr7\Request $request + * @param \Slim\Psr7\Response $response + * @param callable $next + * + * @return void + */ + public function __invoke( + ServerRequestInterface $request, + RequestHandlerInterface $handler + ): Response { + $path = $request->getUri()->getPath(); + + $request = $request->withUri( + $request->getUri()->withPath($this->stripBasePath($path)) + ); + + return $handler->handle($request); + } + + /** + * Strip the base URL path from a path string. + * + * @param string $path + * + * @return string + */ + protected function stripBasePath(string $path): string + { + $pattern = sprintf('/^%s/', preg_quote(dirname($_SERVER['SCRIPT_NAME']), '/')); + + return preg_replace($pattern, '', $path); + } +} diff --git a/app/config/app.php b/app/config/app.php index 4cef9c1..3e383e0 100644 --- a/app/config/app.php +++ b/app/config/app.php @@ -65,4 +65,13 @@ return [ 'providers' => [ // ... ], + + /** + * Additional middlewares to be registered. + * + * Default value: [] + */ + 'middlewares' => [ + // ... + ], ]; diff --git a/tests/Support/HelpersTest.php b/tests/Support/HelpersTest.php index 8901dee..f5f9d7c 100644 --- a/tests/Support/HelpersTest.php +++ b/tests/Support/HelpersTest.php @@ -4,6 +4,7 @@ namespace Tests\Support; use App\Support\Helpers; use PHPUnit\Framework\TestCase; +use RuntimeException; class HelpersTest extends TestCase { @@ -47,4 +48,25 @@ class HelpersTest extends TestCase $this->assertEquals('Test charlie; please ignore', $env); } + + public function test_it_can_get_a_relative_path_from_one_path_to_another(): void + { + $relativePath = Helpers::realativePath('foo/bar', 'foo/bar/baz/qux'); + + $this->assertEquals('baz/qux', $relativePath); + } + + public function test_it_cat_get_a_relative_path_to_itself(): void + { + $relativePath = Helpers::realativePath('foo/bar/baz', 'foo/bar/baz'); + + $this->assertEquals('', $relativePath); + } + + public function test_it_can_get_a_relative_path_between_two_unrelated_paths(): void + { + $path = $this->expectException(RuntimeException::class); + + Helpers::realativePath('foo/bar', 'baz/qux'); + } }