Skip to content

Commit

Permalink
Merge pull request #2860 from adriansuter/patch-route-context-base-path
Browse files Browse the repository at this point in the history
[4.x] Add base path to `$request` and use `RouteContext` to read
  • Loading branch information
l0gicgate committed Oct 5, 2019
2 parents 80a52f7 + de91cf0 commit 3224271
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 7 deletions.
2 changes: 1 addition & 1 deletion Slim/App.php
Expand Up @@ -70,7 +70,7 @@ public function __construct(
);

$this->routeResolver = $routeResolver ?? new RouteResolver($this->routeCollector);
$routeRunner = new RouteRunner($this->routeResolver, $this->routeCollector->getRouteParser());
$routeRunner = new RouteRunner($this->routeResolver, $this->routeCollector->getRouteParser(), $this);

if (!$middlewareDispatcher) {
$middlewareDispatcher = new MiddlewareDispatcher($routeRunner, $this->callableResolver, $container);
Expand Down
24 changes: 22 additions & 2 deletions Slim/Routing/RouteContext.php
Expand Up @@ -25,12 +25,13 @@ public static function fromRequest(ServerRequestInterface $serverRequest): self
$route = $serverRequest->getAttribute('route');
$routeParser = $serverRequest->getAttribute('routeParser');
$routingResults = $serverRequest->getAttribute('routingResults');
$basePath = $serverRequest->getAttribute('basePath');

if ($routeParser === null || $routingResults === null) {
throw new RuntimeException('Cannot create RouteContext before routing has been completed');
}

return new self($route, $routeParser, $routingResults);
return new self($route, $routeParser, $routingResults, $basePath);
}

/**
Expand All @@ -48,19 +49,27 @@ public static function fromRequest(ServerRequestInterface $serverRequest): self
*/
private $routingResults;

/**
* @var string|null
*/
private $basePath;

/**
* @param RouteInterface|null $route
* @param RouteParserInterface $routeParser
* @param RoutingResults $routingResults
* @param string|null $basePath
*/
private function __construct(
?RouteInterface $route,
RouteParserInterface $routeParser,
RoutingResults $routingResults
RoutingResults $routingResults,
?string $basePath = null
) {
$this->route = $route;
$this->routeParser = $routeParser;
$this->routingResults = $routingResults;
$this->basePath = $basePath;
}

/**
Expand All @@ -86,4 +95,15 @@ public function getRoutingResults(): RoutingResults
{
return $this->routingResults;
}

/**
* @return string
*/
public function getBasePath(): string
{
if ($this->basePath === null) {
throw new RuntimeException('No base path defined.');
}
return $this->basePath;
}
}
23 changes: 19 additions & 4 deletions Slim/Routing/RouteRunner.php
Expand Up @@ -14,6 +14,7 @@
use Psr\Http\Server\RequestHandlerInterface;
use Slim\Exception\HttpMethodNotAllowedException;
use Slim\Exception\HttpNotFoundException;
use Slim\Interfaces\RouteCollectorProxyInterface;
use Slim\Interfaces\RouteParserInterface;
use Slim\Interfaces\RouteResolverInterface;
use Slim\Middleware\RoutingMiddleware;
Expand All @@ -31,13 +32,23 @@ class RouteRunner implements RequestHandlerInterface
private $routeParser;

/**
* @param RouteResolverInterface $routeResolver
* @param RouteParserInterface $routeParser
* @var RouteCollectorProxyInterface|null
*/
public function __construct(RouteResolverInterface $routeResolver, RouteParserInterface $routeParser)
{
private $routeCollectorProxy;

/**
* @param RouteResolverInterface $routeResolver
* @param RouteParserInterface $routeParser
* @param RouteCollectorProxyInterface|null $routeCollectorProxy
*/
public function __construct(
RouteResolverInterface $routeResolver,
RouteParserInterface $routeParser,
?RouteCollectorProxyInterface $routeCollectorProxy = null
) {
$this->routeResolver = $routeResolver;
$this->routeParser = $routeParser;
$this->routeCollectorProxy = $routeCollectorProxy;
}

/**
Expand All @@ -60,6 +71,10 @@ public function handle(ServerRequestInterface $request): ResponseInterface
$request = $routingMiddleware->performRouting($request);
}

if ($this->routeCollectorProxy !== null) {
$request = $request->withAttribute('basePath', $this->routeCollectorProxy->getBasePath());
}

/** @var Route $route */
$route = $request->getAttribute('route');
return $route->run($request);
Expand Down
21 changes: 21 additions & 0 deletions tests/Routing/RouteContextTest.php
Expand Up @@ -10,6 +10,7 @@
namespace Slim\Tests\Routing;

use Psr\Http\Message\ServerRequestInterface;
use RuntimeException;
use Slim\Interfaces\RouteInterface;
use Slim\Interfaces\RouteParserInterface;
use Slim\Routing\RouteContext;
Expand All @@ -25,6 +26,7 @@ public function testCanCreateInstanceFromServerRequest(): void
$routingResults = $this->createMock(RoutingResults::class);

$serverRequest = $this->createServerRequest('/')
->withAttribute('basePath', '')
->withAttribute('route', $route)
->withAttribute('routeParser', $routeParser)
->withAttribute('routingResults', $routingResults);
Expand All @@ -34,6 +36,7 @@ public function testCanCreateInstanceFromServerRequest(): void
$this->assertSame($route, $routeContext->getRoute());
$this->assertSame($routeParser, $routeContext->getRouteParser());
$this->assertSame($routingResults, $routeContext->getRoutingResults());
$this->assertSame('', $routeContext->getBasePath());
}

public function testCanCreateInstanceWithoutRoute(): void
Expand All @@ -47,6 +50,23 @@ public function testCanCreateInstanceWithoutRoute(): void
$this->assertNull($routeContext->getRoute());
$this->assertNotNull($routeContext->getRouteParser());
$this->assertNotNull($routeContext->getRoutingResults());
$this->assertNotNull($routeContext->getBasePath());
}

public function testCanCreateInstanceWithoutBasePathAndThrowExceptionIfGetBasePathIsCalled(): void
{
$serverRequest = $this->createServerRequestWithRouteAttributes();

// Route attribute is not required
$serverRequest = $serverRequest->withoutAttribute('basePath');

$routeContext = RouteContext::fromRequest($serverRequest);
$this->assertNotNull($routeContext->getRoute());
$this->assertNotNull($routeContext->getRouteParser());
$this->assertNotNull($routeContext->getRoutingResults());

$this->expectException(RuntimeException::class);
$routeContext->getBasePath();
}

public function requiredRouteContextRequestAttributes(): array
Expand Down Expand Up @@ -76,6 +96,7 @@ private function createServerRequestWithRouteAttributes(): ServerRequestInterfac
$routingResults = $this->createMock(RoutingResults::class);

return $this->createServerRequest('/')
->withAttribute('basePath', '')
->withAttribute('route', $route)
->withAttribute('routeParser', $routeParser)
->withAttribute('routingResults', $routingResults);
Expand Down

0 comments on commit 3224271

Please sign in to comment.