From f610adfc145f20177af6c95196e46837784f13af Mon Sep 17 00:00:00 2001 From: Austin Collier Date: Tue, 19 Mar 2024 09:03:41 -0600 Subject: [PATCH] lots more testing around containers --- flight/core/Dispatcher.php | 29 +++++++++++++++-- tests/DispatcherTest.php | 5 +-- tests/EngineTest.php | 64 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 4 deletions(-) diff --git a/flight/core/Dispatcher.php b/flight/core/Dispatcher.php index 67a92f9..41d9d39 100644 --- a/flight/core/Dispatcher.php +++ b/flight/core/Dispatcher.php @@ -333,7 +333,10 @@ class Dispatcher ) ) { $container_handler = $this->container_handler; - $class = $this->resolveContainerClass($container_handler, $class, $params); + $resolved_class = $this->resolveContainerClass($container_handler, $class, $params); + if($resolved_class !== null) { + $class = $resolved_class; + } } if (is_string($class) && class_exists($class)) { @@ -357,6 +360,21 @@ class Dispatcher $class = new $class(); } + // Final check to make sure it's actually a class and a method, or throw an error + if (is_object($class) === false) { + if(ob_get_level() > 1) { + ob_end_clean(); + } + throw new Exception("Class '$class' not found. Is it being correctly autoloaded with Flight::path()?"); + } + + if (method_exists($class, $method) === false) { + if(ob_get_level() > 1) { + ob_end_clean(); + } + throw new Exception("Method '".get_class($class)."::$method' not found."); + } + return call_user_func_array([ $class, $method ], $params); } @@ -403,7 +421,14 @@ class Dispatcher // Just a callable where you configure the behavior (Dice, PHP-DI, etc.) } elseif (is_callable($container_handler) === true) { - $class_object = call_user_func($container_handler, $class, $params); + + // This is to catch all the error that could be thrown by whatever container you are using + try { + $class_object = call_user_func($container_handler, $class, $params); + } catch (Exception $e) { + // could not resolve a class for some reason + $class_object = null; + } } return $class_object; diff --git a/tests/DispatcherTest.php b/tests/DispatcherTest.php index 2fd0d90..7cf2c24 100644 --- a/tests/DispatcherTest.php +++ b/tests/DispatcherTest.php @@ -123,7 +123,8 @@ class DispatcherTest extends TestCase public function testInvalidCallback(): void { - $this->expectException(TypeError::class); + $this->expectException(Exception::class); + $this->expectExceptionMessage("Class 'NonExistentClass' not found. Is it being correctly autoloaded with Flight::path()?"); $this->dispatcher->execute(['NonExistentClass', 'nonExistentMethod']); } @@ -133,7 +134,7 @@ class DispatcherTest extends TestCase $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Invalid callback specified.'); - $this->dispatcher->execute('inexistentGlobalFunction'); + $this->dispatcher->execute('nonexistentGlobalFunction'); } public function testInvalidCallbackBecauseConstructorParameters(): void diff --git a/tests/EngineTest.php b/tests/EngineTest.php index 157bbb6..dc5947b 100644 --- a/tests/EngineTest.php +++ b/tests/EngineTest.php @@ -692,6 +692,38 @@ class EngineTest extends TestCase $this->expectOutputString('yay! I injected a collection, and it has 1 items'); } + public function testContainerDiceBadClass() { + $engine = new Engine(); + $dice = new \Dice\Dice(); + $engine->registerContainerHandler(function ($class, $params) use ($dice) { + return $dice->create($class, $params); + }); + + $engine->route('/container', 'BadClass->testTheContainer'); + $engine->request()->url = '/container'; + + $this->expectException(Exception::class); + $this->expectExceptionMessage("Class 'BadClass' not found. Is it being correctly autoloaded with Flight::path()?"); + + $engine->start(); + } + + public function testContainerDiceBadMethod() { + $engine = new Engine(); + $dice = new \Dice\Dice(); + $engine->registerContainerHandler(function ($class, $params) use ($dice) { + return $dice->create($class, $params); + }); + + $engine->route('/container', Container::class.'->badMethod'); + $engine->request()->url = '/container'; + + $this->expectException(Exception::class); + $this->expectExceptionMessage("Method 'tests\classes\Container::badMethod' not found."); + + $engine->start(); + } + public function testContainerPsr11() { $engine = new Engine(); $container = new \League\Container\Container(); @@ -705,4 +737,36 @@ class EngineTest extends TestCase $this->expectOutputString('yay! I injected a collection, and it has 1 items'); } + + public function testContainerPsr11ClassNotFound() { + $engine = new Engine(); + $container = new \League\Container\Container(); + $container->add(Container::class)->addArgument(Collection::class); + $container->add(Collection::class); + $engine->registerContainerHandler($container); + + $engine->route('/container', 'BadClass->testTheContainer'); + $engine->request()->url = '/container'; + + $this->expectException(Exception::class); + $this->expectExceptionMessage("Class 'BadClass' not found. Is it being correctly autoloaded with Flight::path()?"); + + $engine->start(); + } + + public function testContainerPsr11MethodNotFound() { + $engine = new Engine(); + $container = new \League\Container\Container(); + $container->add(Container::class)->addArgument(Collection::class); + $container->add(Collection::class); + $engine->registerContainerHandler($container); + + $engine->route('/container', Container::class.'->badMethod'); + $engine->request()->url = '/container'; + + $this->expectException(Exception::class); + $this->expectExceptionMessage("Method 'tests\classes\Container::badMethod' not found."); + + $engine->start(); + } }