diff --git a/.gitignore b/.gitignore index 1874088..0775ac0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ Documentation/* !Documentation/*.rst + +.idea/ diff --git a/Classes/Http/ContentDimensionDetection/BackendUriDimensionPresetDetector.php b/Classes/Http/ContentDimensionDetection/BackendUriDimensionPresetDetector.php index f6aa24b..765e2fc 100644 --- a/Classes/Http/ContentDimensionDetection/BackendUriDimensionPresetDetector.php +++ b/Classes/Http/ContentDimensionDetection/BackendUriDimensionPresetDetector.php @@ -12,7 +12,7 @@ */ use Neos\ContentRepository\Domain\Utility\NodePaths; -use Neos\Flow\Http; +use Psr\Http\Message\ServerRequestInterface; /** * Backend URI based dimension preset detector @@ -27,13 +27,13 @@ final class BackendUriDimensionPresetDetector implements ContentDimensionPresetD /** * @param string $dimensionName * @param array $presets - * @param Http\Component\ComponentContext $componentContext + * @param ServerRequestInterface $request * @param array|null $overrideOptions * @return array|null */ - public function detectPreset(string $dimensionName, array $presets, Http\Component\ComponentContext $componentContext, array $overrideOptions = null) + public function detectPreset(string $dimensionName, array $presets, ServerRequestInterface $request, array $overrideOptions = null) { - $path = $componentContext->getHttpRequest()->getUri()->getPath(); + $path = $request->getUri()->getPath(); $path = '/' . mb_substr($path, mb_strpos($path, '@')); if (mb_strpos($path, '.') !== false) { $path = mb_substr($path, 0, mb_strrpos($path, '.')); diff --git a/Classes/Http/ContentDimensionDetection/ContentDimensionPresetDetectorInterface.php b/Classes/Http/ContentDimensionDetection/ContentDimensionPresetDetectorInterface.php index 905f95a..c1f14d9 100644 --- a/Classes/Http/ContentDimensionDetection/ContentDimensionPresetDetectorInterface.php +++ b/Classes/Http/ContentDimensionDetection/ContentDimensionPresetDetectorInterface.php @@ -11,7 +11,7 @@ * source code. */ -use Neos\Flow\Http; +use Psr\Http\Message\ServerRequestInterface; /** * Interface to detect the current request's dimension preset @@ -31,9 +31,9 @@ interface ContentDimensionPresetDetectorInterface * * @param string $dimensionName * @param array $presets - * @param Http\Component\ComponentContext $componentContext + * @param ServerRequestInterface $request * @param array $overrideOptions * @return array|null */ - public function detectPreset(string $dimensionName, array $presets, Http\Component\ComponentContext $componentContext, array $overrideOptions = null); + public function detectPreset(string $dimensionName, array $presets, ServerRequestInterface $request, array $overrideOptions = null); } diff --git a/Classes/Http/ContentDimensionDetection/SubdomainDimensionPresetDetector.php b/Classes/Http/ContentDimensionDetection/SubdomainDimensionPresetDetector.php index 83fe3e8..f6ade7a 100644 --- a/Classes/Http/ContentDimensionDetection/SubdomainDimensionPresetDetector.php +++ b/Classes/Http/ContentDimensionDetection/SubdomainDimensionPresetDetector.php @@ -11,7 +11,7 @@ * source code. */ -use Neos\Flow\Http; +use Psr\Http\Message\ServerRequestInterface; /** * Subdomain based dimension preset detector @@ -26,13 +26,13 @@ final class SubdomainDimensionPresetDetector implements ContentDimensionPresetDe /** * @param string $dimensionName * @param array $presets - * @param Http\Component\ComponentContext $componentContext + * @param ServerRequestInterface $request * @param array|null $overrideOptions * @return array|null */ - public function detectPreset(string $dimensionName, array $presets, Http\Component\ComponentContext $componentContext, array $overrideOptions = null) + public function detectPreset(string $dimensionName, array $presets, ServerRequestInterface $request, array $overrideOptions = null) { - $host = $componentContext->getHttpRequest()->getUri()->getHost(); + $host = $request->getUri()->getHost(); foreach ($presets as $availablePreset) { if (empty($availablePreset['resolutionValue'])) { // we leave the decision about how to handle empty values to the detection component diff --git a/Classes/Http/ContentDimensionDetection/TopLevelDomainDimensionPresetDetector.php b/Classes/Http/ContentDimensionDetection/TopLevelDomainDimensionPresetDetector.php index d801ea5..239f833 100644 --- a/Classes/Http/ContentDimensionDetection/TopLevelDomainDimensionPresetDetector.php +++ b/Classes/Http/ContentDimensionDetection/TopLevelDomainDimensionPresetDetector.php @@ -11,7 +11,7 @@ * source code. */ -use Neos\Flow\Http; +use Psr\Http\Message\ServerRequestInterface; /** * Top level domain based dimension preset detector @@ -26,13 +26,13 @@ final class TopLevelDomainDimensionPresetDetector implements ContentDimensionPre /** * @param string $dimensionName * @param array $presets - * @param Http\Component\ComponentContext $componentContext + * @param ServerRequestInterface $request * @param array|null $overrideOptions * @return array|null */ - public function detectPreset(string $dimensionName, array $presets, Http\Component\ComponentContext $componentContext, array $overrideOptions = null) + public function detectPreset(string $dimensionName, array $presets, ServerRequestInterface $request, array $overrideOptions = null) { - $host = $componentContext->getHttpRequest()->getUri()->getHost(); + $host = $request->getUri()->getHost(); $hostLength = mb_strlen($host); foreach ($presets as $preset) { $pivot = $hostLength - mb_strlen($preset['resolutionValue']); diff --git a/Classes/Http/ContentDimensionDetection/UriPathSegmentDimensionPresetDetector.php b/Classes/Http/ContentDimensionDetection/UriPathSegmentDimensionPresetDetector.php index 788830d..521061d 100644 --- a/Classes/Http/ContentDimensionDetection/UriPathSegmentDimensionPresetDetector.php +++ b/Classes/Http/ContentDimensionDetection/UriPathSegmentDimensionPresetDetector.php @@ -11,8 +11,8 @@ * source code. */ -use Neos\Flow\Http; use Neos\Utility\Arrays; +use Psr\Http\Message\ServerRequestInterface; /** * URI path segment based dimension preset detector @@ -30,14 +30,14 @@ final class UriPathSegmentDimensionPresetDetector implements ContentDimensionPre /** * @param string $dimensionName * @param array $presets - * @param Http\Component\ComponentContext $componentContext + * @param ServerRequestInterface $request * @param array|null $overrideOptions * @return array|null */ - public function detectPreset(string $dimensionName, array $presets, Http\Component\ComponentContext $componentContext, array $overrideOptions = null) + public function detectPreset(string $dimensionName, array $presets, ServerRequestInterface $request, array $overrideOptions = null) { $options = $overrideOptions ? Arrays::arrayMergeRecursiveOverrule($this->defaultOptions, $overrideOptions) : $this->defaultOptions; - $requestPath = $componentContext->getHttpRequest()->getUri()->getPath(); + $requestPath = $request->getUri()->getPath(); if (!empty($requestPath) && $requestPath !== '/' && mb_strpos($requestPath, '/') !== false) { $pathSegments = explode('/', ($requestPath)); diff --git a/Classes/Http/ContentDimensionLinking/UriPathSegmentDimensionPresetLinkProcessor.php b/Classes/Http/ContentDimensionLinking/UriPathSegmentDimensionPresetLinkProcessor.php index 2301779..6ca786c 100644 --- a/Classes/Http/ContentDimensionLinking/UriPathSegmentDimensionPresetLinkProcessor.php +++ b/Classes/Http/ContentDimensionLinking/UriPathSegmentDimensionPresetLinkProcessor.php @@ -46,6 +46,6 @@ public function processUriConstraints( $pathSegmentPart = $options['offset'] > 0 ? $options['delimiter'] : ''; $pathSegmentPart .= ($preset['resolutionValue'] ?? $preset['uriSegment']); - return $uriConstraints->withPathPrefix($pathSegmentPart . '/', true); + return $uriConstraints->withPathPrefix($pathSegmentPart, true); } } diff --git a/Classes/Http/DetectContentSubgraphComponent.php b/Classes/Http/DetectContentSubgraphMiddleware.php similarity index 80% rename from Classes/Http/DetectContentSubgraphComponent.php rename to Classes/Http/DetectContentSubgraphMiddleware.php index 4a005cd..7f4e604 100644 --- a/Classes/Http/DetectContentSubgraphComponent.php +++ b/Classes/Http/DetectContentSubgraphMiddleware.php @@ -15,15 +15,21 @@ use Neos\ContentRepository\Domain\Service\ContextFactoryInterface; use Neos\ContentRepository\Domain\Utility\NodePaths; use Neos\Flow\Annotations as Flow; -use Neos\Flow\Http; + +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Server\MiddlewareInterface; +use Psr\Http\Server\RequestHandlerInterface; + use Neos\Flow\Mvc\Routing\Dto\RouteParameters; -use Neos\Flow\Mvc\Routing\RoutingComponent; +use Neos\Flow\Http\ServerRequestAttributes; + use Flowpack\Neos\DimensionResolver\Http\ContentDimensionDetection\DimensionPresetDetectorResolver; /** * The HTTP component for detecting the requested dimension space point */ -final class DetectContentSubgraphComponent implements Http\Component\ComponentInterface +final class DetectContentSubgraphMiddleware implements MiddlewareInterface { /** * @Flow\Inject @@ -56,33 +62,42 @@ final class DetectContentSubgraphComponent implements Http\Component\ComponentIn protected $uriPathSegmentDelimiter; /** - * @param Http\Component\ComponentContext $componentContext + * @param ServerRequestInterface $request + * @param RequestHandlerInterface $next * @throws Exception\InvalidDimensionPresetDetectorException + * @return ResponseInterface */ - public function handle(Http\Component\ComponentContext $componentContext) + public function process(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface { $uriPathSegmentUsed = false; - $dimensionValues = $this->detectDimensionSpacePoint($componentContext, $uriPathSegmentUsed); - $workspaceName = $this->detectContentStream($componentContext); + $dimensionValues = $this->detectDimensionSpacePoint($request, $uriPathSegmentUsed); + $workspaceName = $this->detectContentStream($request); + + $existingParameters = $request->getAttribute(ServerRequestAttributes::ROUTING_PARAMETERS); + if ($existingParameters === null) { + $existingParameters = RouteParameters::createEmpty(); + } - $existingParameters = $componentContext->getParameter(RoutingComponent::class, 'parameters') ?? RouteParameters::createEmpty(); $parameters = $existingParameters ->withParameter('dimensionValues', json_encode($dimensionValues)) ->withParameter('workspaceName', $workspaceName) ->withParameter('uriPathSegmentUsed', $uriPathSegmentUsed); - $componentContext->setParameter(RoutingComponent::class, 'parameters', $parameters); + + $request = $request->withAttribute(ServerRequestAttributes::ROUTING_PARAMETERS, $parameters); + return $next->handle($request); } /** - * @param Http\Component\ComponentContext $componentContext + * @param ServerRequestInterface $request * @param bool $uriPathSegmentUsed * @return array * @throws Exception\InvalidDimensionPresetDetectorException */ - protected function detectDimensionSpacePoint(Http\Component\ComponentContext $componentContext, bool &$uriPathSegmentUsed): array + protected function detectDimensionSpacePoint(ServerRequestInterface $request, bool &$uriPathSegmentUsed): array { $coordinates = []; - $path = $componentContext->getHttpRequest()->getUri()->getPath(); + + $path = $request->getUri()->getPath(); $isContextPath = NodePaths::isContextPath($path); $backendUriDimensionPresetDetector = new ContentDimensionDetection\BackendUriDimensionPresetDetector(); @@ -96,12 +111,12 @@ protected function detectDimensionSpacePoint(Http\Component\ComponentContext $co $options['defaultPresetIdentifier'] = $presetConfiguration['defaultPreset']; if ($isContextPath) { - $preset = $backendUriDimensionPresetDetector->detectPreset($dimensionName, $presetConfiguration['presets'], $componentContext); + $preset = $backendUriDimensionPresetDetector->detectPreset($dimensionName, $presetConfiguration['presets'], $request); if ($preset) { $coordinates[$dimensionName] = $preset['values']; if ($detector instanceof ContentDimensionDetection\UriPathSegmentDimensionPresetDetector) { // we might have to remove the uri path segment anyway - $uriPathSegmentPreset = $detector->detectPreset($dimensionName, $presetConfiguration['presets'], $componentContext, $options); + $uriPathSegmentPreset = $detector->detectPreset($dimensionName, $presetConfiguration['presets'], $request, $options); if ($uriPathSegmentPreset) { $uriPathSegmentUsed = true; } @@ -114,7 +129,7 @@ protected function detectDimensionSpacePoint(Http\Component\ComponentContext $co if ($resolutionMode === ContentDimensionResolutionMode::RESOLUTION_MODE_URIPATHSEGMENT) { $options['delimiter'] = $this->uriPathSegmentDelimiter; } - $preset = $detector->detectPreset($dimensionName, $presetConfiguration['presets'], $componentContext, $options); + $preset = $detector->detectPreset($dimensionName, $presetConfiguration['presets'], $request, $options); if ($preset && $resolutionMode === ContentDimensionResolutionMode::RESOLUTION_MODE_URIPATHSEGMENT) { $uriPathSegmentUsed = true; $uriPathSegmentOffset++; @@ -175,14 +190,14 @@ protected function generateOptionsFromLegacyConfiguration(array $presetConfigura } /** - * @param Http\Component\ComponentContext $componentContext + * @param ServerRequestInterface $request * @return string */ - protected function detectContentStream(Http\Component\ComponentContext $componentContext): string + protected function detectContentStream(ServerRequestInterface $request): string { $contentStreamIdentifier = 'live'; - $requestPath = $componentContext->getHttpRequest()->getUri()->getPath(); + $requestPath = $request->getUri()->getPath(); $requestPath = mb_substr($requestPath, mb_strrpos($requestPath, '/')); if ($requestPath !== '' && NodePaths::isContextPath($requestPath)) { try { diff --git a/Classes/Routing/FrontendNodeRoutePartHandler.php b/Classes/Routing/FrontendNodeRoutePartHandler.php index e0856f6..a055861 100644 --- a/Classes/Routing/FrontendNodeRoutePartHandler.php +++ b/Classes/Routing/FrontendNodeRoutePartHandler.php @@ -14,7 +14,7 @@ use Flowpack\Neos\DimensionResolver\Http; use Neos\Flow\Annotations as Flow; -use Neos\Flow\Log\PsrSystemLoggerInterface; +use Psr\Log\LoggerInterface; use Neos\Flow\Mvc\Routing\Dto\MatchResult; use Neos\Flow\Mvc\Routing\Dto\ResolveResult; use Neos\Flow\Mvc\Routing\Dto\RouteTags; @@ -37,8 +37,8 @@ class FrontendNodeRoutePartHandler extends DynamicRoutePart implements FrontendNodeRoutePartHandlerInterface { /** - * @Flow\Inject - * @var PsrSystemLoggerInterface + * @Flow\Inject(name="Neos.Flow:SystemLogger") + * @var LoggerInterface */ protected $systemLogger; diff --git a/Configuration/Settings.yaml b/Configuration/Settings.yaml index 01dae34..6f09890 100644 --- a/Configuration/Settings.yaml +++ b/Configuration/Settings.yaml @@ -4,11 +4,11 @@ Flowpack: contentDimensions: resolution: uriPathSegmentDelimiter: '_' + Neos: Flow: http: - chain: - preprocess: - chain: - detectContentSubgraph: - component: Flowpack\Neos\DimensionResolver\Http\DetectContentSubgraphComponent + middlewares: + 'detectContentSubgraph': + position: 'before routing' + middleware: 'Flowpack\Neos\DimensionResolver\Http\DetectContentSubgraphMiddleware' diff --git a/Documentation/index.rst b/Documentation/index.rst index b4ed965..cfe77e0 100644 --- a/Documentation/index.rst +++ b/Documentation/index.rst @@ -241,7 +241,7 @@ Those complex scenarios are better served using individual implementations than To enable developers to deal with this in a nice way, there are predefined ways to deal with both detection and link processing. -Detection is done via an HTTP component that can be replaced via configuration: +Detection is done via an HTTP middleware that can be replaced via configuration: .. code-block:: yaml @@ -252,7 +252,7 @@ Detection is done via an HTTP component that can be replaced via configuration: preprocess: chain: detectContentSubgraph: - component: Flowpack\Neos\DimensionResolver\Http\DetectContentSubgraphComponent + component: Flowpack\Neos\DimensionResolver\Http\DetectContentSubgraphMiddleware Link processing is done by the ``Flowpack\Neos\DimensionResolver\Http\ContentSubgraphUriProcessorInterface``. To introduce your custom behaviour, implement the interface and declare it in ``Objects.yaml`` as usual in Flow. diff --git a/Tests/Functional/Http/DetectContentSubgraphComponentTest.php b/Tests/Functional/Http/DetectContentSubgraphMiddlewareTest.php similarity index 91% rename from Tests/Functional/Http/DetectContentSubgraphComponentTest.php rename to Tests/Functional/Http/DetectContentSubgraphMiddlewareTest.php index fc20d7a..f3bd619 100644 --- a/Tests/Functional/Http/DetectContentSubgraphComponentTest.php +++ b/Tests/Functional/Http/DetectContentSubgraphMiddlewareTest.php @@ -16,12 +16,12 @@ use Neos\Flow\Mvc\Routing\RoutingComponent; use Neos\Flow\Tests\FunctionalTestCase; use Flowpack\Neos\DimensionResolver\Http\ContentDimensionResolutionMode; -use Flowpack\Neos\DimensionResolver\Http\DetectContentSubgraphComponent; +use Flowpack\Neos\DimensionResolver\Http\DetectContentSubgraphMiddleware; /** * Test case for the BackendUriDimensionPresetDetector */ -class DetectContentSubgraphComponentTest extends FunctionalTestCase +class DetectContentSubgraphMiddlewareTest extends FunctionalTestCase { /** * @var array @@ -110,9 +110,9 @@ public function handleAddsCorrectSubgraphIdentityToComponentContextWithAllDimens $dimensionPresetSource = $this->objectManager->get(ContentDimensionPresetSourceInterface::class); $dimensionPresetSource->setConfiguration($this->dimensionPresets); - $detectSubgraphComponent = new DetectContentSubgraphComponent(); + $detectSubgraphMiddleware = new DetectContentSubgraphMiddleware(); - $detectSubgraphComponent->handle($componentContext); + $detectSubgraphMiddleware->handle($componentContext); /** @var RouteParameters $routeParameters */ $routeParameters = $componentContext->getParameter(RoutingComponent::class, 'parameters'); @@ -135,11 +135,11 @@ public function handleAddsCorrectSubgraphIdentityToComponentContextWithAllDimens $dimensionPresetSource = $this->objectManager->get(ContentDimensionPresetSourceInterface::class); $dimensionPresetSource->setConfiguration($this->dimensionPresets); - $detectSubgraphComponent = new DetectContentSubgraphComponent(); + $detectSubgraphMiddleware = new DetectContentSubgraphMiddleware(); - $this->inject($detectSubgraphComponent, 'uriPathSegmentDelimiter', '-'); + $this->inject($detectSubgraphMiddleware, 'uriPathSegmentDelimiter', '-'); - $detectSubgraphComponent->handle($componentContext); + $detectSubgraphMiddleware->handle($componentContext); /** @var RouteParameters $routeParameters */ $routeParameters = $componentContext->getParameter(RoutingComponent::class, 'parameters'); @@ -162,9 +162,9 @@ public function handleAddsCorrectSubgraphIdentityToComponentContextWithMinimalDi $dimensionPresetSource = $this->objectManager->get(ContentDimensionPresetSourceInterface::class); $dimensionPresetSource->setConfiguration($this->dimensionPresets); - $detectSubgraphComponent = new DetectContentSubgraphComponent(); + $detectSubgraphMiddleware = new DetectContentSubgraphMiddleware(); - $detectSubgraphComponent->handle($componentContext); + $detectSubgraphMiddleware->handle($componentContext); /** @var RouteParameters $routeParameters */ $routeParameters = $componentContext->getParameter(RoutingComponent::class, 'parameters'); @@ -188,9 +188,9 @@ public function handleAddsCorrectSubgraphIdentityToComponentContextWithDimension $dimensionPresetSource = $this->objectManager->get(ContentDimensionPresetSourceInterface::class); $dimensionPresetSource->setConfiguration($this->dimensionPresets); - $detectSubgraphComponent = new DetectContentSubgraphComponent(); + $detectSubgraphMiddleware = new DetectContentSubgraphMiddleware(); - $detectSubgraphComponent->handle($componentContext); + $detectSubgraphMiddleware->handle($componentContext); /** @var RouteParameters $routeParameters */ $routeParameters = $componentContext->getParameter(RoutingComponent::class, 'parameters'); diff --git a/Tests/Unit/Http/ContentDimensionDetection/DimensionPresetDetectorResolverTest.php b/Tests/Unit/Http/ContentDimensionDetection/DimensionPresetDetectorResolverTest.php index 6c32481..9da3b1f 100644 --- a/Tests/Unit/Http/ContentDimensionDetection/DimensionPresetDetectorResolverTest.php +++ b/Tests/Unit/Http/ContentDimensionDetection/DimensionPresetDetectorResolverTest.php @@ -17,7 +17,7 @@ use Flowpack\Neos\DimensionResolver\Tests\Unit\Http\ContentDimensionDetection\Fixtures\ValidDummyDimensionPresetDetector; /** - * Test case for the DetectContentSubgraphComponent + * Test case for the DetectContentSubgraphMiddleware */ class DimensionPresetDetectorResolverTest extends UnitTestCase { diff --git a/Tests/Unit/Http/ContentDimensionLinking/DimensionPresetLinkProcessorResolverTest.php b/Tests/Unit/Http/ContentDimensionLinking/DimensionPresetLinkProcessorResolverTest.php index dab8fca..1b7ad36 100644 --- a/Tests/Unit/Http/ContentDimensionLinking/DimensionPresetLinkProcessorResolverTest.php +++ b/Tests/Unit/Http/ContentDimensionLinking/DimensionPresetLinkProcessorResolverTest.php @@ -17,7 +17,7 @@ use Flowpack\Neos\DimensionResolver\Tests\Unit\Http\ContentDimensionLinking\Fixtures\ValidDummyDimensionPresetLinkProcessor; /** - * Test case for the DetectContentSubgraphComponent + * Test case for the DetectContentSubgraphMiddleware */ class DimensionPresetLinkProcessorResolverTest extends UnitTestCase { diff --git a/composer.json b/composer.json index 51de055..1fa567f 100644 --- a/composer.json +++ b/composer.json @@ -4,8 +4,8 @@ "license": "GPL-3.0+", "description": "A support package for Neos CMS that allows for arbitrary content dimension resolution.", "require": { - "neos/neos": "~3.3.0||~4.0||~5.0||dev-master", - "neos/flow": "~4.3.0||~5.0||~6.0||dev-master" + "neos/neos": "~7.0||dev-master", + "neos/flow": "~7.0||dev-master" }, "autoload": { "psr-4": {