Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/Tempest/Auth/src/AuthorizerMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,27 @@
namespace Tempest\Auth;

use Tempest\Container\Container;
use Tempest\Container\Tag;
use Tempest\Http\HttpMiddleware;
use Tempest\Http\HttpMiddlewareCallable;
use Tempest\Http\MatchedRoute;
use Tempest\Http\Request;
use Tempest\Http\Response;
use Tempest\Http\Responses\Forbidden;
use Tempest\Http\Route;

final readonly class AuthorizerMiddleware implements HttpMiddleware
{
public function __construct(
private Authenticator $authenticator,
private MatchedRoute $matchedRoute,
#[Tag('current')]
private Route $currentRoute,
private Container $container,
) {
}

public function __invoke(Request $request, HttpMiddlewareCallable $next): Response
{
$attribute = $this->matchedRoute
->route
$attribute = $this->currentRoute
->handler
->getAttribute(Allow::class);

Expand Down
17 changes: 8 additions & 9 deletions src/Tempest/Http/src/GenericRouter.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ public function dispatch(Request|PsrRequest $request): Response
}

$this->container->singleton(
MatchedRoute::class,
fn () => $matchedRoute,
className: Route::class,
definition: fn () => $matchedRoute,
tag: 'current'
);

$callable = $this->getCallable($matchedRoute);
Expand All @@ -69,14 +70,12 @@ public function dispatch(Request|PsrRequest $request): Response
return $response;
}

private function getCallable(MatchedRoute $matchedRoute): HttpMiddlewareCallable
private function getCallable(Route $route): HttpMiddlewareCallable
{
$route = $matchedRoute->route;

$callControllerAction = function (Request $request) use ($route, $matchedRoute) {
$callControllerAction = function (Request $request) use ($route) {
$response = $this->container->invoke(
$route->handler,
...$matchedRoute->params,
...$route->params,
);

if ($response === null) {
Expand Down Expand Up @@ -164,13 +163,13 @@ private function createResponse(Response|View $input): Response
return $input;
}

private function resolveRequest(PsrRequest $psrRequest, MatchedRoute $matchedRoute): Request
private function resolveRequest(PsrRequest $psrRequest, Route $matchedRoute): Request
{
// Let's find out if our input request data matches what the route's action needs
$requestClass = GenericRequest::class;

// We'll loop over all the handler's parameters
foreach ($matchedRoute->route->handler->getParameters() as $parameter) {
foreach ($matchedRoute->handler->getParameters() as $parameter) {

// If the parameter's type is an instance of Request…
if ($parameter->getType()->matches(Request::class)) {
Expand Down
13 changes: 9 additions & 4 deletions src/Tempest/Http/src/Route.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
public readonly bool $isDynamic;

/** @var string[] Route parameters */
public readonly array $params;
public array $params;

public const string DEFAULT_MATCHING_GROUP = '[^/]++';

Expand Down Expand Up @@ -48,7 +48,7 @@
/** @return string[] */
public static function getRouteParams(string $uriPart): array
{
$regex = '#\{'. self::ROUTE_PARAM_NAME_REGEX . self::ROUTE_PARAM_CUSTOM_REGEX .'\}#';
$regex = '#\{' . self::ROUTE_PARAM_NAME_REGEX . self::ROUTE_PARAM_CUSTOM_REGEX . '\}#';

preg_match_all($regex, $uriPart, $matches);

Expand All @@ -58,15 +58,20 @@
/**
* Splits the route URI into separate segments
*
* @example '/test/{id}/edit' becomes ['test', '{id}', 'edit']
* @return string[]
* @example '/test/{id}/edit' becomes ['test', '{id}', 'edit']
*/
public function split(): array
{
$parts = explode('/', $this->uri);

return array_values(
array_filter($parts, static fn (string $part) => $part !== '')
array_filter($parts, static fn (string $part) => $part !== ''),
);
}

public function setParams(array $params): self
{
$this->params = $params;

Check failure on line 75 in src/Tempest/Http/src/Route.php

View workflow job for this annotation

GitHub Actions / Run Static Analysis: PHPStan

Method Tempest\Http\Route::setParams() should return Tempest\Http\Route but return statement is missing.
}
}
4 changes: 2 additions & 2 deletions src/Tempest/Http/src/RouteEnumBindingInitializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ public function canInitialize(ClassReflector $class): bool

public function initialize(ClassReflector $class, Container $container): object
{
$matchedRoute = $container->get(MatchedRoute::class);
$matchedRoute = $container->get(Route::class, tag: 'current');

$parameter = null;

foreach ($matchedRoute->route->handler->getParameters() as $searchParameter) {
foreach ($matchedRoute->handler->getParameters() as $searchParameter) {
if ($searchParameter->getType()->equals($class->getType())) {
$parameter = $searchParameter;

Expand Down
4 changes: 2 additions & 2 deletions src/Tempest/Http/src/RouteModelBindingInitializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ public function canInitialize(ClassReflector $class): bool

public function initialize(ClassReflector $class, Container $container): object
{
$matchedRoute = $container->get(MatchedRoute::class);
$matchedRoute = $container->get(Route::class, tag: 'current');

$parameter = null;

foreach ($matchedRoute->route->handler->getParameters() as $searchParameter) {
foreach ($matchedRoute->handler->getParameters() as $searchParameter) {
if ($searchParameter->getType()->equals($class->getType())) {
$parameter = $searchParameter;

Expand Down
18 changes: 6 additions & 12 deletions src/Tempest/Http/src/Routing/Matching/GenericRouteMatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
namespace Tempest\Http\Routing\Matching;

use Psr\Http\Message\ServerRequestInterface as PsrRequest;
use Tempest\Http\MatchedRoute;
use Tempest\Http\Route;
use Tempest\Http\RouteConfig;
use Tempest\Http\Routing\Construction\MarkedRoute;
Expand All @@ -16,7 +15,7 @@ public function __construct(private RouteConfig $routeConfig)
{
}

public function match(PsrRequest $request): ?MatchedRoute
public function match(PsrRequest $request): ?Route
{
// Try to match routes without any parameters
if (($staticRoute = $this->matchStaticRoute($request)) !== null) {
Expand All @@ -27,18 +26,12 @@ public function match(PsrRequest $request): ?MatchedRoute
return $this->matchDynamicRoute($request);
}

private function matchStaticRoute(PsrRequest $request): ?MatchedRoute
private function matchStaticRoute(PsrRequest $request): ?Route
{
$staticRoute = $this->routeConfig->staticRoutes[$request->getMethod()][$request->getUri()->getPath()] ?? null;

if ($staticRoute === null) {
return null;
}

return new MatchedRoute($staticRoute, []);
return $this->routeConfig->staticRoutes[$request->getMethod()][$request->getUri()->getPath()] ?? null;
}

private function matchDynamicRoute(PsrRequest $request): ?MatchedRoute
private function matchDynamicRoute(PsrRequest $request): ?Route
{
// If there are no routes for the given request method, we immediately stop
$routesForMethod = $this->routeConfig->dynamicRoutes[$request->getMethod()] ?? null;
Expand All @@ -62,7 +55,7 @@ private function matchDynamicRoute(PsrRequest $request): ?MatchedRoute
// Extract the parameters based on the route and matches
$routeParams = $this->extractParams($route, $routingMatches);

return new MatchedRoute($route, $routeParams);
return $route->setParams($routeParams);
}

/**
Expand All @@ -74,6 +67,7 @@ private function matchDynamicRoute(PsrRequest $request): ?MatchedRoute
private function extractParams(Route $route, array $routeMatches): array
{
$valueMap = [];

foreach ($route->params as $i => $param) {
$valueMap[$param] = $routeMatches[$i + 1];
}
Expand Down
4 changes: 2 additions & 2 deletions src/Tempest/Http/src/Routing/Matching/RouteMatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
namespace Tempest\Http\Routing\Matching;

use Psr\Http\Message\ServerRequestInterface as PsrRequest;
use Tempest\Http\MatchedRoute;
use Tempest\Http\Route;

interface RouteMatcher
{
public function match(PsrRequest $request): ?MatchedRoute;
public function match(PsrRequest $request): ?Route;
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ public function test_match_on_static_route(): void
$matchedRoute = $this->subject->match($request);

$this->assertEquals([], $matchedRoute->params);
$this->assertFalse($matchedRoute->route->isDynamic);
$this->assertEquals('/static', $matchedRoute->route->uri);
$this->assertFalse($matchedRoute->isDynamic);
$this->assertEquals('/static', $matchedRoute->uri);
}

public function test_match_returns_null_on_unknown_route(): void
Expand Down Expand Up @@ -85,8 +85,8 @@ public function test_match_on_dynamic_route(): void
$matchedRoute = $this->subject->match($request);

$this->assertEquals([ 'id' => '5' ], $matchedRoute->params);
$this->assertTrue($matchedRoute->route->isDynamic);
$this->assertEquals('/dynamic/{id}', $matchedRoute->route->uri);
$this->assertTrue($matchedRoute->isDynamic);
$this->assertEquals('/dynamic/{id}', $matchedRoute->uri);
}

public function test_match_on_dynamic_route_with_many_parameters(): void
Expand All @@ -96,7 +96,7 @@ public function test_match_on_dynamic_route_with_many_parameters(): void
$matchedRoute = $this->subject->match($request);

$this->assertEquals([ 'id' => '6', 'tag' => 'brendt', 'name' => 'brent' ], $matchedRoute->params);
$this->assertTrue($matchedRoute->route->isDynamic);
$this->assertEquals('/dynamic/{id}/{tag}/{name}/{id}', $matchedRoute->route->uri);
$this->assertTrue($matchedRoute->isDynamic);
$this->assertEquals('/dynamic/{id}/{tag}/{name}/{id}', $matchedRoute->uri);
}
}
Loading