Skip to content

Commit 0b3d153

Browse files
committed
add RouteHandlerBuilder to pipe the action filters with the endpoint handler
1 parent 83cdcc5 commit 0b3d153

File tree

4 files changed

+95
-15
lines changed

4 files changed

+95
-15
lines changed

lib/Endpoint/EndpointRouteBuilder.php

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
use DevNet\System\MethodTrait;
1212
use DevNet\System\Runtime\LauncherProperties;
1313
use DevNet\Web\Endpoint\Route;
14+
use DevNet\Web\Middleware\RequestDelegate;
1415
use DevNet\Web\Routing\IRouteBuilder;
15-
use DevNet\Web\Routing\IRouteHandler;
1616
use DevNet\Web\Routing\IRouter;
17-
use DevNet\Web\Routing\RouteHandler;
1817
use DirectoryIterator;
1918
use ReflectionClass;
2019
use Closure;
20+
use DevNet\Web\Middleware\IRequestHandler;
2121

2222
class EndpointRouteBuilder
2323
{
@@ -45,41 +45,47 @@ public function mapGroup(string $prefix, callable $callback): void
4545
/**
4646
* Adds a route that matches HTTP requests for the specified path and HTTP method, or any HTTP method if it's not specified.
4747
*/
48-
public function mapRoute(string $path, callable $handler, ?string $method = null): IRouteHandler
48+
public function mapRoute(string $path, callable $handler, ?string $method = null): RouteHandlerBuilder
4949
{
5050
$path = $this->prefix . '/' . trim($path, '/');
51-
$routeHandler = new RouteHandler($handler);
52-
return $this->builder->map($path, $routeHandler, $method);
51+
52+
if (!$handler instanceof IRequestHandler and !$handler instanceof RequestDelegate) {
53+
$handler = new RequestDelegate($handler);
54+
}
55+
56+
$builder = new RouteHandlerBuilder($handler);
57+
$this->builder->map($path, $builder->build(), $method);
58+
return $builder;
5359
}
5460

5561
/**
5662
* Adds a route that matches HTTP GET requests for the specified path.
5763
*/
58-
public function mapGet(string $path, callable $handler): IRouteHandler
64+
public function mapGet(string $path, callable $handler): RouteHandlerBuilder
5965
{
6066
return $this->mapRoute($path, $handler, 'GET');
6167
}
6268

6369
/**
6470
* Adds a route that matches HTTP POST requests for the specified path.
6571
*/
66-
public function mapPost(string $path, callable $handler): IRouteHandler
72+
public function mapPost(string $path, callable $handler): RouteHandlerBuilder
6773
{
6874
return $this->mapRoute($path, $handler, 'POST');
6975
}
7076

7177
/**
7278
* Adds a route that matches HTTP PUT requests for the specified path.
7379
*/
74-
public function mapPut(string $path, callable $handler): IRouteHandler
80+
public function mapPut(string $path, callable $handler): RouteHandlerBuilder
7581
{
7682
return $this->mapRoute($path, $handler, 'PUT');
7783
}
7884

7985
/**
8086
* Adds a route that matches HTTP DELETE requests for the specified path.
8187
*/
82-
public function mapDelete(string $path, callable $handler): IRouteHandler
88+
public function mapDelete(string $path, callable $handler): RouteHandlerBuilder
8389
{
8490
$path = $this->prefix . '/' . trim($path, '/');
8591
return $this->mapRoute($path, $handler, 'DELETE');
@@ -88,7 +94,7 @@ public function mapDelete(string $path, callable $handler): IRouteHandler
8894
/**
8995
* Adds a route that matches HTTP PATCH requests for the specified path.
9096
*/
91-
public function mapPatch(string $path, callable $handler): IRouteHandler
97+
public function mapPatch(string $path, callable $handler): RouteHandlerBuilder
9298
{
9399
return $this->mapRoute($path, $handler, 'PATCH');
94100
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
/**
4+
* @author Mohammed Moussaoui
5+
* @license MIT license. For more license information, see the LICENSE file in the root directory.
6+
* @link https://github.com/DevNet-Framework
7+
*/
8+
9+
namespace DevNet\Web\Endpoint;
10+
11+
use DevNet\System\Exceptions\ClassException;
12+
use DevNet\Web\Middleware\IRequestHandler;
13+
use DevNet\Web\Middleware\RequestDelegate;
14+
use DevNet\Web\Routing\IRouteHandler;
15+
use DevNet\Web\Routing\RouteHandler;
16+
use ReflectionClass;
17+
18+
class RouteHandlerBuilder
19+
{
20+
private ActionDelegate $action;
21+
private array $filters = [];
22+
23+
public function __construct(IRequestHandler|RequestDelegate $target)
24+
{
25+
$this->action = new ActionDelegate(function ($context) use ($target) {
26+
return $target($context->HttpContext);
27+
});
28+
}
29+
30+
public function addFilter(callable|string $filter, ...$args): static
31+
{
32+
if (is_string($filter)) {
33+
if (!class_exists($filter)) {
34+
throw new ClassException("Could not find the class {$filter}", 0, 1);
35+
}
36+
37+
$reflection = new ReflectionClass($filter);
38+
$filter = $reflection->newInstanceArgs($args);
39+
}
40+
41+
if (is_object($filter instanceof IActionFilter)) {
42+
$this->filters[] = $filter;
43+
return $this;
44+
}
45+
46+
$this->filters[] = new ActionFilterDelegate($filter);
47+
return $this;
48+
}
49+
50+
public function build(): IRouteHandler
51+
{
52+
$action = $this->action;
53+
$handler = new RequestDelegate(function ($context) use ($action) {
54+
foreach (array_reverse($this->filters) as $filter) {
55+
$action = new ActionDelegate(function ($context) use ($filter, $action) {
56+
return $filter($context, $action);
57+
});
58+
}
59+
$actionDescriptor = new ActionDescriptor($action, 'invoke');
60+
$actionContext = new ActionContext($actionDescriptor, $context);
61+
return $action($actionContext);
62+
});
63+
64+
return new RouteHandler($handler);
65+
}
66+
}

lib/Routing/RouteBuilder.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88

99
namespace DevNet\Web\Routing;
1010

11+
use DevNet\System\Exceptions\TypeException;
1112
use DevNet\System\MethodTrait;
13+
use DevNet\Web\Middleware\IRequestHandler;
14+
use DevNet\Web\Middleware\RequestDelegate;
1215

1316
class RouteBuilder implements IRouteBuilder
1417
{
@@ -30,6 +33,10 @@ public function map(string $pattern, IRouteHandler $handler, ?string $verb = nul
3033
*/
3134
public function mapRoute(string $pattern, callable $handler, ?string $verb = null): IRouteHandler
3235
{
36+
if (!$handler instanceof IRequestHandler and !$handler instanceof RequestDelegate) {
37+
$handler = new RequestDelegate($handler);
38+
}
39+
3340
$routeHandler = new RouteHandler($handler);
3441
return $this->map($pattern, $routeHandler, $verb);
3542
}

lib/Routing/RouteHandler.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,20 @@
1010

1111
use DevNet\System\Async\Task;
1212
use DevNet\System\PropertyTrait;
13+
use DevNet\Web\Middleware\IRequestHandler;
1314
use DevNet\Web\Middleware\RequestDelegate;
1415

1516

1617
class RouteHandler implements IRouteHandler
1718
{
1819
use PropertyTrait;
1920

20-
private RequestDelegate $target;
21+
private IRequestHandler|RequestDelegate $target;
2122
private array $filters = [];
2223

23-
public function __construct(callable $target)
24+
public function __construct(IRequestHandler|RequestDelegate $target)
2425
{
25-
$this->target = new RequestDelegate($target);
26+
$this->target = $target;
2627
}
2728

2829
public function get_Target()
@@ -38,7 +39,7 @@ public function set_Target($value)
3839
public function handle(RouteContext $routeContext): Task
3940
{
4041
$handler = $this->target;
41-
$handler = function ($context) use ($handler) {
42+
$handler = new RequestDelegate(function ($context) use ($handler) {
4243
$result = $handler($context);
4344
if ($result instanceof Task) {
4445
return $result->then(function ($previous) use ($context) {
@@ -62,7 +63,7 @@ public function handle(RouteContext $routeContext): Task
6263
}
6364

6465
return Task::completedTask();
65-
};
66+
});
6667

6768
$routeContext->Handler = $handler;
6869

0 commit comments

Comments
 (0)