Skip to content

Commit

Permalink
Added ControllerFactory + Tests + Updated Router::map to allow adding…
Browse files Browse the repository at this point in the history
… extra args to methods
  • Loading branch information
designcise committed May 14, 2020
1 parent fbdb0a4 commit 04ce559
Show file tree
Hide file tree
Showing 5 changed files with 432 additions and 0 deletions.
80 changes: 80 additions & 0 deletions src/ControllerFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

/**
* BitFrame Framework (https://www.bitframephp.com)
*
* @author Daniyal Hamid
* @copyright Copyright (c) 2017-2020 Daniyal Hamid (https://designcise.com)
* @license https://bitframephp.com/about/license MIT License
*/

declare(strict_types=1);

namespace BitFrame\FastRoute;

use ReflectionMethod;
use Psr\Http\Message\{ServerRequestInterface, ResponseInterface};
use Psr\Http\Server\RequestHandlerInterface;
use RuntimeException;
use InvalidArgumentException;

use function array_shift;
use function sprintf;
use function is_object;
use function get_class;

/**
* Creates a new Controller with specified arguments.
*/
class ControllerFactory
{
public static function from(string $className, string $method, ...$args): callable
{
if (! method_exists($className, $method)) {
throw new RuntimeException(sprintf(
'"%s::%s()" does not exist', $className, $method
));
}

$reflection = new ReflectionMethod($className, $method);

if ($reflection->isStatic()) {
return self::fromCallable([$className, $method], $args);
}

return [new $className(...$args), $method];
}

public static function fromArray(array $controller): callable
{
if (! isset($controller[0], $controller[1])) {
throw new InvalidArgumentException(
"Array should have the class/object and method name as first arguments"
);
}

$classOrObj = array_shift($controller);
$method = array_shift($controller);

if (! method_exists($classOrObj, $method)) {
throw new RuntimeException(sprintf(
'"%s::%s()" does not exist',
(is_object($classOrObj)) ? get_class($classOrObj) : (string) $classOrObj,
$method
));
}

return self::fromCallable([$classOrObj, $method], $controller);
}

public static function fromCallable(callable $controller, array $args = []): callable
{
if (empty($args)) {
return $controller;
}

return fn (ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface => (
$controller($request, $handler, ...$args)
);
}
}
6 changes: 6 additions & 0 deletions src/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
use TypeError;
use RuntimeException;

use function is_array;

/**
* FastRoute router to manage http routes as a middleware.
*/
Expand All @@ -37,6 +39,10 @@ public function __construct()
*/
public function map($methods, string $path, $handler)
{
$handler = (is_array($handler) && isset($handler[0], $handler[1], $handler[2]))
? ControllerFactory::fromArray($handler)
: $handler;

$this->routeCollection->add((array) $methods, $path, $handler);
}

Expand Down
49 changes: 49 additions & 0 deletions test/Asset/Controller.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace BitFrame\FastRoute\Test\Asset;

use Psr\Http\Message\{ServerRequestInterface, ResponseInterface};
use Psr\Http\Server\RequestHandlerInterface;

class Controller
{
private string $foo;

public function __construct(string $foo = 'bar')
{
$this->foo = $foo;
}

public function __invoke(
ServerRequestInterface $request,
RequestHandlerInterface $handler,
string $foo = 'bar'
): ResponseInterface {
return self::staticAction($request, $handler, $foo);
}

public function indexAction(
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface {
echo $this->foo;
return $handler->handle($request);
}

public function methodAction(
ServerRequestInterface $request,
RequestHandlerInterface $handler,
string $foo = 'bar'
): ResponseInterface {
return self::staticAction($request, $handler, $foo);
}

public static function staticAction(
ServerRequestInterface $request,
RequestHandlerInterface $handler,
string $foo = 'bar'
): ResponseInterface {
echo $foo;
return $handler->handle($request);
}
}
Loading

0 comments on commit 04ce559

Please sign in to comment.