Added more tests. Captured callable exception thrown

pull/559/head
Austin Collier 10 months ago
parent f610adfc14
commit 3f887e305f

@ -220,13 +220,13 @@ class Engine
/**
* Registers the container handler
*
* @param callable $callback Callback function that sets the container and how it will inject classes
* @param callable|object $containerHandler Callback function or PSR-11 Container object that sets the container and how it will inject classes
*
* @return void
*/
public function registerContainerHandler($callback): void
public function registerContainerHandler($containerHandler): void
{
$this->dispatcher->setContainerHandler($callback);
$this->dispatcher->setContainerHandler($containerHandler);
}
/**

@ -25,6 +25,9 @@ class Dispatcher
public const FILTER_AFTER = 'after';
private const FILTER_TYPES = [self::FILTER_BEFORE, self::FILTER_AFTER];
/** @var mixed $container_exception Exception message if thrown by setting the container as a callable method */
public static $container_exception = null;
/** @var array<string, Closure(): (void|mixed)> Mapped events. */
protected array $events = [];
@ -40,18 +43,18 @@ class Dispatcher
*
* @var callable|object|null
*/
protected $container_handler = null;
protected $containerHandler = null;
/**
* Sets the dependency injection container handler.
*
* @param callable|object $container_handler Dependency injection container
* @param callable|object $containerHandler Dependency injection container
*
* @return void
*/
public function setContainerHandler($container_handler): void
public function setContainerHandler($containerHandler): void
{
$this->container_handler = $container_handler;
$this->containerHandler = $containerHandler;
}
/**
@ -246,11 +249,7 @@ class Dispatcher
$this->handleInvalidCallbackType($callback);
if (is_array($callback) === true) {
return $this->invokeMethod($callback, $params);
}
return $this->callFunction($callback, $params);
return $this->invokeCallable($callback, $params);
}
/**
@ -311,6 +310,7 @@ class Dispatcher
* @return mixed Function results
* @throws TypeError For nonexistent class name.
* @throws InvalidArgumentException If the constructor requires parameters
* @version 3.7.0
*/
public function invokeCallable($func, array &$params = [])
{
@ -321,9 +321,9 @@ class Dispatcher
[$class, $method] = $func;
// Only execute this if it's not a Flight class
// Only execute the container handler if it's not a Flight class
if (
$this->container_handler !== null &&
$this->containerHandler !== null &&
(
(
is_object($class) === true &&
@ -332,13 +332,15 @@ class Dispatcher
is_string($class) === true
)
) {
$container_handler = $this->container_handler;
$resolved_class = $this->resolveContainerClass($container_handler, $class, $params);
if($resolved_class !== null) {
$class = $resolved_class;
$containerHandler = $this->containerHandler;
$resolvedClass = $this->resolveContainerClass($containerHandler, $class, $params);
if($resolvedClass !== null) {
$class = $resolvedClass;
}
}
// If there's no container handler set, you can use [ 'className', 'methodName' ]
// to call a method dynamically. Nothing is injected into the class though.
if (is_string($class) && class_exists($class)) {
$constructor = (new ReflectionClass($class))->getConstructor();
$constructorParamsNumber = 0;
@ -362,17 +364,20 @@ class Dispatcher
// 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) {
// Cause PHPUnit has 1 level of output buffering by default
if(ob_get_level() > (getenv('PHPUNIT_TEST') ? 1 : 0)) {
ob_end_clean();
}
throw new Exception("Class '$class' not found. Is it being correctly autoloaded with Flight::path()?");
}
// Class is there, but no method
if (method_exists($class, $method) === false) {
if(ob_get_level() > 1) {
// Cause PHPUnit has 1 level of output buffering by default
if(ob_get_level() > (getenv('PHPUNIT_TEST') ? 1 : 0)) {
ob_end_clean();
}
throw new Exception("Method '".get_class($class)."::$method' not found.");
throw new Exception("Class found, but method '".get_class($class)."::$method' not found.");
}
return call_user_func_array([ $class, $method ], $params);
@ -428,6 +433,12 @@ class Dispatcher
} catch (Exception $e) {
// could not resolve a class for some reason
$class_object = null;
// If the container throws an exception, we need to catch it
// and store it somewhere. If we just let it throw itself, it
// doesn't properly close the output buffers and can cause other
// issues.
self::$container_exception = $e;
}
}

@ -192,7 +192,7 @@ class DispatcherTest extends TestCase
{
set_error_handler(function (int $errno, string $errstr): void {
$this->assertSame(E_USER_NOTICE, $errno);
$this->assertSame("Event 'myMethod' has been overriden!", $errstr);
$this->assertSame("Event 'myMethod' has been overridden!", $errstr);
});
$this->dispatcher->set('myMethod', function (): string {
@ -200,10 +200,10 @@ class DispatcherTest extends TestCase
});
$this->dispatcher->set('myMethod', function (): string {
return 'Overriden';
return 'Overridden';
});
$this->assertSame('Overriden', $this->dispatcher->run('myMethod'));
$this->assertSame('Overridden', $this->dispatcher->run('myMethod'));
restore_error_handler();
}
@ -219,7 +219,7 @@ class DispatcherTest extends TestCase
return 'Original';
})
->hook('myMethod', 'invalid', function (array &$params, &$output): void {
$output = 'Overriden';
$output = 'Overridden';
});
$this->assertSame('Original', $this->dispatcher->run('myMethod'));

@ -6,6 +6,7 @@ namespace tests;
use Exception;
use Flight;
use flight\core\Dispatcher;
use flight\Engine;
use flight\net\Request;
use flight\net\Response;
@ -706,6 +707,8 @@ class EngineTest extends TestCase
$this->expectExceptionMessage("Class 'BadClass' not found. Is it being correctly autoloaded with Flight::path()?");
$engine->start();
$this->assertEquals('Class BadClass not found', Dispatcher::$container_exception->getMessage());
}
public function testContainerDiceBadMethod() {
@ -719,9 +722,11 @@ class EngineTest extends TestCase
$engine->request()->url = '/container';
$this->expectException(Exception::class);
$this->expectExceptionMessage("Method 'tests\classes\Container::badMethod' not found.");
$this->expectExceptionMessage("Class found, but method 'tests\classes\Container::badMethod' not found.");
$engine->start();
$this->assertNull(Dispatcher::$container_exception);
}
public function testContainerPsr11() {
@ -765,7 +770,7 @@ class EngineTest extends TestCase
$engine->request()->url = '/container';
$this->expectException(Exception::class);
$this->expectExceptionMessage("Method 'tests\classes\Container::badMethod' not found.");
$this->expectExceptionMessage("Class found, but method 'tests\classes\Container::badMethod' not found.");
$engine->start();
}

Loading…
Cancel
Save