Lots more tests. Now will dynamically create object with engine instance.

pull/559/head
Austin Collier 10 months ago
parent f752073f7d
commit dbf05ebf40

@ -138,6 +138,9 @@ class Engine
$this->dispatcher->reset();
}
// Add this class to Dispatcher
$this->dispatcher->setEngine($this);
// Register default components
$this->loader->register('request', Request::class);
$this->loader->register('response', Response::class);

@ -6,6 +6,7 @@ namespace flight\core;
use Closure;
use Exception;
use flight\Engine;
use InvalidArgumentException;
use ReflectionClass;
use TypeError;
@ -26,7 +27,10 @@ class Dispatcher
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;
protected $container_exception = null;
/** @var ?Engine $engine Engine instance */
protected ?Engine $engine = null;
/** @var array<string, Closure(): (void|mixed)> Mapped events. */
protected array $events = [];
@ -57,6 +61,11 @@ class Dispatcher
$this->containerHandler = $containerHandler;
}
public function setEngine(Engine $engine): void
{
$this->engine = $engine;
}
/**
* Dispatches an event.
*
@ -346,20 +355,22 @@ class Dispatcher
}
// If this tried to resolve a class in a container and failed somehow, throw the exception
if (isset($resolvedClass) === false && self::$container_exception !== null) {
if (isset($resolvedClass) === false && $this->container_exception !== null) {
$this->fixOutputBuffering();
throw self::$container_exception;
throw $this->container_exception;
}
// If we made it this far, we can forget the container exception and move on...
self::$container_exception = null;
// Class is there, but no method
if (method_exists($class, $method) === false) {
if (is_object($class) === true && method_exists($class, $method) === false) {
$this->fixOutputBuffering();
throw new Exception("Class found, but method '".get_class($class)."::$method' not found.");
}
// Class is a string, and method exists, create the object by hand and inject only the Engine
if (is_string($class) === true) {
$class = new $class($this->engine);
}
return call_user_func_array([ $class, $method ], $params);
}
@ -418,7 +429,7 @@ class Dispatcher
// 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;
$this->container_exception = $e;
}
}

@ -4,13 +4,16 @@ declare(strict_types=1);
namespace tests;
use ArgumentCountError;
use Closure;
use Exception;
use flight\core\Dispatcher;
use flight\Engine;
use InvalidArgumentException;
use PharIo\Manifest\InvalidEmailException;
use tests\classes\Hello;
use PHPUnit\Framework\TestCase;
use tests\classes\ContainerDefault;
use tests\classes\TesterClass;
use TypeError;
@ -21,7 +24,6 @@ class DispatcherTest extends TestCase
protected function setUp(): void
{
$this->dispatcher = new Dispatcher();
Dispatcher::$container_exception = null;
}
public function testClosureMapping(): void
@ -247,4 +249,57 @@ class DispatcherTest extends TestCase
$this->assertSame('param1', $class->param2);
}
public function testExecuteStringClassBadConstructParams(): void
{
$this->expectException(ArgumentCountError::class);
$this->expectExceptionMessageMatches('#Too few arguments to function tests\\\\classes\\\\TesterClass::__construct\(\), 1 passed .+ and exactly 6 expected#');
$this->dispatcher->execute(TesterClass::class . '->instanceMethod');
}
public function testExecuteStringClassNoConstruct(): void
{
$result = $this->dispatcher->execute(Hello::class . '->sayHi');
$this->assertSame('hello', $result);
}
public function testExecuteStringClassNoConstructDoubleColon(): void
{
$result = $this->dispatcher->execute(Hello::class . '::sayHi');
$this->assertSame('hello', $result);
}
public function testExecuteStringClassNoConstructArraySyntax(): void
{
$result = $this->dispatcher->execute([ Hello::class, 'sayHi' ]);
$this->assertSame('hello', $result);
}
public function testExecuteStringClassDefaultContainer(): void
{
$this->dispatcher->setEngine(new Engine);
$result = $this->dispatcher->execute(ContainerDefault::class . '->testTheContainer');
$this->assertSame('You got it boss!', $result);
}
public function testExecuteStringClassDefaultContainerDoubleColon(): void
{
$this->dispatcher->setEngine(new Engine);
$result = $this->dispatcher->execute(ContainerDefault::class . '::testTheContainer');
$this->assertSame('You got it boss!', $result);
}
public function testExecuteStringClassDefaultContainerArraySyntax(): void
{
$this->dispatcher->setEngine(new Engine);
$result = $this->dispatcher->execute([ ContainerDefault::class, 'testTheContainer' ]);
$this->assertSame('You got it boss!', $result);
}
public function testExecuteStringClassDefaultContainerButForgotInjectingEngine(): void
{
$this->expectException(TypeError::class);
$this->expectExceptionMessageMatches('#Argument 1 passed to tests\\\\classes\\\\ContainerDefault::__construct\(\) must be an instance of flight\\\\Engine, null given#');
$result = $this->dispatcher->execute([ ContainerDefault::class, 'testTheContainer' ]);
}
}

@ -21,7 +21,6 @@ class EngineTest extends TestCase
public function setUp(): void
{
$_SERVER = [];
Dispatcher::$container_exception = null;
}
public function tearDown(): void
@ -751,8 +750,6 @@ 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() {
@ -775,8 +772,6 @@ class EngineTest extends TestCase
$this->expectExceptionMessage("Class found, but method 'tests\classes\Container::badMethod' not found.");
$engine->start();
$this->assertNull(Dispatcher::$container_exception);
}
public function testContainerPsr11() {

@ -16,7 +16,6 @@ class MapTest extends TestCase
protected function setUp(): void
{
Dispatcher::$container_exception = null;
$this->app = new Engine();
}

@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace tests\classes;
use flight\Engine;
class ContainerDefault
{
protected Engine $app;
public function __construct(Engine $engine)
{
$engine->set('test_me_out', 'You got it boss!');
$this->app = $engine;
}
public function testTheContainer()
{
return $this->app->get('test_me_out');
}
}
Loading…
Cancel
Save