diff --git a/flight/core/Dispatcher.php b/flight/core/Dispatcher.php index 0fcc39a..b1e6d73 100644 --- a/flight/core/Dispatcher.php +++ b/flight/core/Dispatcher.php @@ -7,6 +7,7 @@ namespace flight\core; use Closure; use Exception; use InvalidArgumentException; +use TypeError; /** * The Dispatcher class is responsible for dispatching events. Events @@ -192,13 +193,15 @@ class Dispatcher */ public static function execute($callback, array &$params = []) { - if (!\is_callable($callback)) { + if (is_string($callback) && !function_exists($callback)) { throw new InvalidArgumentException('Invalid callback specified.'); } - return \is_array($callback) - ? self::invokeMethod($callback, $params) - : self::callFunction($callback, $params); + if (is_array($callback)) { + return self::invokeMethod($callback, $params); + } + + return self::callFunction($callback, $params); } /** @@ -217,20 +220,21 @@ class Dispatcher /** * Invokes a method. * - * @param mixed $func Class method - * @param array $params Class method parameters + * @param array{class-string|object, string} $func Class method + * @param array &$params Class method parameters * * @return mixed Function results + * @throws TypeError For unexistent class name. */ - public static function invokeMethod($func, array &$params = []) + public static function invokeMethod(array $func, array &$params = []) { [$class, $method] = $func; - $instance = \is_object($class); + if (is_string($class) && class_exists($class)) { + $class = new $class(); + } - return ($instance) ? - $class->$method(...$params) : - $class::$method(); + return call_user_func_array([$class, $method], $params); } /** diff --git a/tests/DispatcherTest.php b/tests/DispatcherTest.php index 795d01d..97401ad 100644 --- a/tests/DispatcherTest.php +++ b/tests/DispatcherTest.php @@ -10,6 +10,7 @@ use flight\core\Dispatcher; use PharIo\Manifest\InvalidEmailException; use tests\classes\Hello; use PHPUnit\Framework\TestCase; +use TypeError; class DispatcherTest extends TestCase { @@ -120,11 +121,17 @@ class DispatcherTest extends TestCase public function testInvalidCallback(): void { - $this->expectException(Exception::class); + $this->expectException(TypeError::class); Dispatcher::execute(['NonExistentClass', 'nonExistentMethod']); } + // It will be useful for executing instance Controller methods statically + public function testCanExecuteAnNonStaticMethodStatically(): void + { + $this->assertSame('hello', Dispatcher::execute([Hello::class, 'sayHi'])); + } + public function testItThrowsAnExceptionWhenRunAnUnregistedEventName(): void { $this->expectException(Exception::class);