Skip to content

Commit 04ce559

Browse files
committed
Added ControllerFactory + Tests + Updated Router::map to allow adding extra args to methods
1 parent fbdb0a4 commit 04ce559

File tree

5 files changed

+432
-0
lines changed

5 files changed

+432
-0
lines changed

src/ControllerFactory.php

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
/**
4+
* BitFrame Framework (https://www.bitframephp.com)
5+
*
6+
* @author Daniyal Hamid
7+
* @copyright Copyright (c) 2017-2020 Daniyal Hamid (https://designcise.com)
8+
* @license https://bitframephp.com/about/license MIT License
9+
*/
10+
11+
declare(strict_types=1);
12+
13+
namespace BitFrame\FastRoute;
14+
15+
use ReflectionMethod;
16+
use Psr\Http\Message\{ServerRequestInterface, ResponseInterface};
17+
use Psr\Http\Server\RequestHandlerInterface;
18+
use RuntimeException;
19+
use InvalidArgumentException;
20+
21+
use function array_shift;
22+
use function sprintf;
23+
use function is_object;
24+
use function get_class;
25+
26+
/**
27+
* Creates a new Controller with specified arguments.
28+
*/
29+
class ControllerFactory
30+
{
31+
public static function from(string $className, string $method, ...$args): callable
32+
{
33+
if (! method_exists($className, $method)) {
34+
throw new RuntimeException(sprintf(
35+
'"%s::%s()" does not exist', $className, $method
36+
));
37+
}
38+
39+
$reflection = new ReflectionMethod($className, $method);
40+
41+
if ($reflection->isStatic()) {
42+
return self::fromCallable([$className, $method], $args);
43+
}
44+
45+
return [new $className(...$args), $method];
46+
}
47+
48+
public static function fromArray(array $controller): callable
49+
{
50+
if (! isset($controller[0], $controller[1])) {
51+
throw new InvalidArgumentException(
52+
"Array should have the class/object and method name as first arguments"
53+
);
54+
}
55+
56+
$classOrObj = array_shift($controller);
57+
$method = array_shift($controller);
58+
59+
if (! method_exists($classOrObj, $method)) {
60+
throw new RuntimeException(sprintf(
61+
'"%s::%s()" does not exist',
62+
(is_object($classOrObj)) ? get_class($classOrObj) : (string) $classOrObj,
63+
$method
64+
));
65+
}
66+
67+
return self::fromCallable([$classOrObj, $method], $controller);
68+
}
69+
70+
public static function fromCallable(callable $controller, array $args = []): callable
71+
{
72+
if (empty($args)) {
73+
return $controller;
74+
}
75+
76+
return fn (ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface => (
77+
$controller($request, $handler, ...$args)
78+
);
79+
}
80+
}

src/Router.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
use TypeError;
1919
use RuntimeException;
2020

21+
use function is_array;
22+
2123
/**
2224
* FastRoute router to manage http routes as a middleware.
2325
*/
@@ -37,6 +39,10 @@ public function __construct()
3739
*/
3840
public function map($methods, string $path, $handler)
3941
{
42+
$handler = (is_array($handler) && isset($handler[0], $handler[1], $handler[2]))
43+
? ControllerFactory::fromArray($handler)
44+
: $handler;
45+
4046
$this->routeCollection->add((array) $methods, $path, $handler);
4147
}
4248

test/Asset/Controller.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
namespace BitFrame\FastRoute\Test\Asset;
4+
5+
use Psr\Http\Message\{ServerRequestInterface, ResponseInterface};
6+
use Psr\Http\Server\RequestHandlerInterface;
7+
8+
class Controller
9+
{
10+
private string $foo;
11+
12+
public function __construct(string $foo = 'bar')
13+
{
14+
$this->foo = $foo;
15+
}
16+
17+
public function __invoke(
18+
ServerRequestInterface $request,
19+
RequestHandlerInterface $handler,
20+
string $foo = 'bar'
21+
): ResponseInterface {
22+
return self::staticAction($request, $handler, $foo);
23+
}
24+
25+
public function indexAction(
26+
ServerRequestInterface $request,
27+
RequestHandlerInterface $handler
28+
): ResponseInterface {
29+
echo $this->foo;
30+
return $handler->handle($request);
31+
}
32+
33+
public function methodAction(
34+
ServerRequestInterface $request,
35+
RequestHandlerInterface $handler,
36+
string $foo = 'bar'
37+
): ResponseInterface {
38+
return self::staticAction($request, $handler, $foo);
39+
}
40+
41+
public static function staticAction(
42+
ServerRequestInterface $request,
43+
RequestHandlerInterface $handler,
44+
string $foo = 'bar'
45+
): ResponseInterface {
46+
echo $foo;
47+
return $handler->handle($request);
48+
}
49+
}

0 commit comments

Comments
 (0)