From 0a9f741da0ade63515fc27a91f3f57c62ecbef31 Mon Sep 17 00:00:00 2001 From: Martin Ficzel Date: Thu, 5 May 2022 14:20:40 +0200 Subject: [PATCH 1/5] TASK: Adjust guzzle requirements to be in line with neos 8 and use flushByTags --- Classes/Aspects/ContentCacheAspect.php | 6 ++---- Classes/Middleware/RequestCacheMiddleware.php | 6 +++--- composer.json | 4 ++-- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Classes/Aspects/ContentCacheAspect.php b/Classes/Aspects/ContentCacheAspect.php index 871650f..2deddcd 100644 --- a/Classes/Aspects/ContentCacheAspect.php +++ b/Classes/Aspects/ContentCacheAspect.php @@ -46,10 +46,8 @@ public function interceptNodeCacheFlush(JoinPointInterface $joinPoint) $object = $joinPoint->getProxy(); $tags = ObjectAccess::getProperty($object, 'tagsToFlush', true); - foreach ($tags as $tag => $_) { - $tag = $this->sanitizeTag($tag); - $this->cacheFrontend->flushByTag($tag); - } + $tags = array_map([$this, 'sanitizeTag'],$tags); + $this->cacheFrontend->flushByTags($tags); } /** diff --git a/Classes/Middleware/RequestCacheMiddleware.php b/Classes/Middleware/RequestCacheMiddleware.php index e4e209d..dd9c6dc 100644 --- a/Classes/Middleware/RequestCacheMiddleware.php +++ b/Classes/Middleware/RequestCacheMiddleware.php @@ -9,7 +9,7 @@ use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; -use function GuzzleHttp\Psr7\parse_response; +use GuzzleHttp\Psr7\Message; use function GuzzleHttp\Psr7\str; class RequestCacheMiddleware implements MiddlewareInterface @@ -72,7 +72,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface if ($cacheEntry = $this->cacheFrontend->get($entryIdentifier)) { $age = time() - $cacheEntry['timestamp']; - $response = parse_response($cacheEntry['response']); + $response = Message::parseResponse($cacheEntry['response']); return $response ->withHeader('Age', $age) ->withHeader(self::HEADER_INFO, 'HIT: ' . $entryIdentifier); @@ -105,7 +105,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface ->withHeader('Cache-Control', 'public, max-age=' . $publicLifetime); } - $this->cacheFrontend->set($entryIdentifier,[ 'timestamp' => time(), 'response' => str($response) ], $tags, $lifetime); + $this->cacheFrontend->set($entryIdentifier,[ 'timestamp' => time(), 'response' => Message::toString($response) ], $tags, $lifetime); $response->getBody()->rewind(); return $response->withHeader(self::HEADER_INFO, 'MISS: ' . $entryIdentifier); } diff --git a/composer.json b/composer.json index 1cd83b6..bcdbb31 100644 --- a/composer.json +++ b/composer.json @@ -4,8 +4,8 @@ "name": "flowpack/fullpagecache", "license": "MIT", "require": { - "neos/neos": "^7.0 || ^8.0 || dev-master", - "guzzlehttp/psr7": "~1.4" + "neos/neos": "^8.0 || dev-master", + "guzzlehttp/psr7": "^1.7, !=1.8.0 || ~2.0" }, "autoload": { "psr-4": { From d7475c85971896f0466a2541cb7ee857b804620b Mon Sep 17 00:00:00 2001 From: Sebastian Helzle Date: Thu, 5 May 2022 15:02:07 +0200 Subject: [PATCH 2/5] TASK: Update code for PHP 8 --- Classes/Aspects/ContentCacheAspect.php | 38 ++++---------- Classes/Cache/MetadataAwareStringFrontend.php | 41 ++++++--------- .../FusionAutoconfigurationMiddleware.php | 25 ++++------ Classes/Middleware/RequestCacheMiddleware.php | 50 ++++++------------- 4 files changed, 51 insertions(+), 103 deletions(-) diff --git a/Classes/Aspects/ContentCacheAspect.php b/Classes/Aspects/ContentCacheAspect.php index 2deddcd..2e44835 100644 --- a/Classes/Aspects/ContentCacheAspect.php +++ b/Classes/Aspects/ContentCacheAspect.php @@ -4,44 +4,31 @@ use Neos\Cache\Frontend\StringFrontend; use Neos\Flow\Annotations as Flow; use Neos\Flow\Aop\JoinPointInterface; +use Neos\Utility\Exception\PropertyNotAccessibleException; use Neos\Utility\ObjectAccess; -/** - * @Flow\Aspect - * @Flow\Scope("singleton") - */ +#[Flow\Aspect] +#[Flow\Scope("singleton")] class ContentCacheAspect { - private $hadUncachedSegments = false; + private bool $hadUncachedSegments = false; - private $cacheTags = []; - - /** - * @var null|int - */ - private $shortestLifetime = null; - - /** - * @Flow\Inject - * @var StringFrontend - */ - protected $cacheFrontend; + #[Flow\Inject] + protected StringFrontend $cacheFrontend; /** * @Flow\Before("method(Neos\Fusion\Core\Cache\ContentCache->(createUncachedSegment)())") */ - public function grabUncachedSegment(JoinPointInterface $joinPoint) + public function grabUncachedSegment(JoinPointInterface $joinPoint): void { $this->hadUncachedSegments = true; } /** - * @Flow\Before("method(Neos\Neos\Fusion\Cache\ContentCacheFlusher->shutdownObject())") - * @param JoinPointInterface $joinPoint - * - * @throws \Neos\Utility\Exception\PropertyNotAccessibleException + * @throws PropertyNotAccessibleException */ - public function interceptNodeCacheFlush(JoinPointInterface $joinPoint) + #[Flow\Before("method(Neos\Neos\Fusion\Cache\ContentCacheFlusher->shutdownObject())")] + public function interceptNodeCacheFlush(JoinPointInterface $joinPoint): void { $object = $joinPoint->getProxy(); @@ -50,9 +37,6 @@ public function interceptNodeCacheFlush(JoinPointInterface $joinPoint) $this->cacheFrontend->flushByTags($tags); } - /** - * @return bool - */ public function hasUncachedSegments(): bool { return $this->hadUncachedSegments; @@ -64,7 +48,7 @@ public function hasUncachedSegments(): bool * @param string $tag A tag which possibly contains non-allowed characters, for example "NodeType_Acme.Com:Page" * @return string A cleaned up tag, for example "NodeType_Acme_Com-Page" */ - protected function sanitizeTag($tag) + protected function sanitizeTag(string $tag): string { return strtr($tag, '.:', '_-'); } diff --git a/Classes/Cache/MetadataAwareStringFrontend.php b/Classes/Cache/MetadataAwareStringFrontend.php index 59c7ace..835e9ea 100644 --- a/Classes/Cache/MetadataAwareStringFrontend.php +++ b/Classes/Cache/MetadataAwareStringFrontend.php @@ -13,42 +13,35 @@ */ class MetadataAwareStringFrontend extends StringFrontend { - const SEPARATOR = '|'; + protected const SEPARATOR = '|'; /** * Store metadata of all loaded cache entries indexed by identifier - * - * @var array */ - protected $metadata = []; + protected array $metadata = []; - /** - * @Flow\Inject - * @var Environment - */ - protected $environment; + #[Flow\Inject] + protected Environment $environment; - /** - * @Flow\Inject - * @var LoggerInterface - */ - protected $logger; + #[Flow\Inject] + protected LoggerInterface $logger; /** * Set a cache entry and store additional metadata (tags and lifetime) * * {@inheritdoc} */ - public function set(string $entryIdentifier, $content, array $tags = [], int $lifetime = null) + public function set(string $entryIdentifier, $string, array $tags = [], int $lifetime = null): void { - $content = $this->insertMetadata($content, $entryIdentifier, $tags, $lifetime); + $content = $this->insertMetadata($string, $entryIdentifier, $tags, $lifetime); parent::set($entryIdentifier, $content, $tags, $lifetime); } /** * {@inheritdoc} + * @throws InvalidDataTypeException */ - public function get(string $entryIdentifier) + public function get(string $entryIdentifier): bool|string { $content = parent::get($entryIdentifier); if ($content !== false) { @@ -60,6 +53,7 @@ public function get(string $entryIdentifier) /** * {@inheritdoc} + * @throws InvalidDataTypeException */ public function getByTag(string $tag): array { @@ -74,18 +68,13 @@ public function getByTag(string $tag): array /** * Insert metadata into the content * - * @param string $content * @param string $entryIdentifier The identifier metadata * @param array $tags The tags metadata - * @param integer $lifetime The lifetime metadata + * @param integer|null $lifetime The lifetime metadata * @return string The content including the serialized metadata - * @throws InvalidDataTypeException */ - protected function insertMetadata($content, $entryIdentifier, array $tags, $lifetime) + protected function insertMetadata(string $content, string $entryIdentifier, array $tags, int $lifetime = null): string { - if (!is_string($content)) { - throw new InvalidDataTypeException('Given data is of type "' . gettype($content) . '", but a string is expected for string cache.', 1433155737); - } $metadata = [ 'identifier' => $entryIdentifier, 'tags' => $tags, @@ -105,7 +94,7 @@ protected function insertMetadata($content, $entryIdentifier, array $tags, $life * @return string The content without metadata * @throws InvalidDataTypeException */ - protected function extractMetadata($entryIdentifier, $content) + protected function extractMetadata(string $entryIdentifier, string $content): string { $separatorIndex = strpos($content, self::SEPARATOR); if ($separatorIndex === false) { @@ -136,7 +125,7 @@ protected function extractMetadata($entryIdentifier, $content) /** * @return array Metadata of all loaded entries (indexed by identifier) */ - public function getAllMetadata() + public function getAllMetadata(): array { return $this->metadata; } diff --git a/Classes/Middleware/FusionAutoconfigurationMiddleware.php b/Classes/Middleware/FusionAutoconfigurationMiddleware.php index f06d087..1381280 100644 --- a/Classes/Middleware/FusionAutoconfigurationMiddleware.php +++ b/Classes/Middleware/FusionAutoconfigurationMiddleware.php @@ -16,22 +16,19 @@ class FusionAutoconfigurationMiddleware implements MiddlewareInterface public const HEADER_ENABLED = 'X-FullPageCache-EnableFusionAutoconfiguration'; /** - * @Flow\Inject * @var MetadataAwareStringFrontend */ + #[Flow\Inject] protected $contentCache; /** - * @Flow\Inject * @var ContentCacheAspect */ + #[Flow\Inject] protected $contentCacheAspect; - /** - * @var boolean - * @Flow\InjectConfiguration(path="enabled") - */ - protected $enabled; + #[Flow\InjectConfiguration('enabled')] + protected bool $enabled; public function process(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface { @@ -43,13 +40,13 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface if (!$response->hasHeader(self::HEADER_ENABLED)) { return $response; - } else { - $response = $response->withoutHeader(self::HEADER_ENABLED); } - list($hasUncachedSegments, $tags, $lifetime) = $this->getFusionCacheInformations(); + $response = $response->withoutHeader(self::HEADER_ENABLED); + + [$hasUncachedSegments, $tags, $lifetime] = $this->getFusionCacheInformations(); - if ($response->hasHeader('Set-Cookie') || $hasUncachedSegments) { + if ($hasUncachedSegments || $response->hasHeader('Set-Cookie')) { return $response; } @@ -63,7 +60,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface if ($lifetime) { $response = $response - ->withHeader(RequestCacheMiddleware::HEADER_LIFTIME, $lifetime); + ->withHeader(RequestCacheMiddleware::HEADER_LIFETIME, $lifetime); } return $response; @@ -80,8 +77,8 @@ public function getFusionCacheInformations(): array $tags = []; $entriesMetadata = $this->contentCache->getAllMetadata(); foreach ($entriesMetadata as $identifier => $metadata) { - $entryTags = isset($metadata['tags']) ? $metadata['tags'] : []; - $entryLifetime = isset($metadata['lifetime']) ? $metadata['lifetime'] : null; + $entryTags = $metadata['tags'] ?? []; + $entryLifetime = $metadata['lifetime'] ?? null; if ($entryLifetime !== null) { if ($lifetime === null) { $lifetime = $entryLifetime; diff --git a/Classes/Middleware/RequestCacheMiddleware.php b/Classes/Middleware/RequestCacheMiddleware.php index dd9c6dc..1c3b2ae 100644 --- a/Classes/Middleware/RequestCacheMiddleware.php +++ b/Classes/Middleware/RequestCacheMiddleware.php @@ -18,45 +18,30 @@ class RequestCacheMiddleware implements MiddlewareInterface public const HEADER_INFO = 'X-FullPageCache-Info'; - public const HEADER_LIFTIME = 'X-FullPageCache-Lifetime'; + public const HEADER_LIFETIME = 'X-FullPageCache-Lifetime'; public const HEADER_TAGS = 'X-FullPageCache-Tags'; - /** - * @var boolean - * @Flow\InjectConfiguration(path="enabled") - */ - protected $enabled; + #[Flow\InjectConfiguration('enabled')] + protected bool $enabled; /** - * @Flow\Inject * @var VariableFrontend */ + #[Flow\Inject] protected $cacheFrontend; - /** - * @var array - * @Flow\InjectConfiguration(path="request.queryParams.allow") - */ - protected $allowedQueryParams; + #[Flow\InjectConfiguration('request.queryParams.allow')] + protected array $allowedQueryParams; - /** - * @var array - * @Flow\InjectConfiguration(path="request.queryParams.ignore") - */ - protected $ignoredQueryParams; + #[Flow\InjectConfiguration('request.queryParams.ignore')] + protected array $ignoredQueryParams; - /** - * @var array - * @Flow\InjectConfiguration(path="request.cookieParams.ignore") - */ - protected $ignoredCookieParams; + #[Flow\InjectConfiguration('request.cookieParams.ignore')] + protected array $ignoredCookieParams; - /** - * @var boolean - * @Flow\InjectConfiguration(path="maxPublicCacheTime") - */ - protected $maxPublicCacheTime; + #[Flow\InjectConfiguration('maxPublicCacheTime')] + protected int $maxPublicCacheTime; public function process(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface { @@ -81,11 +66,11 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface $response = $next->handle($request->withHeader(self::HEADER_ENABLED, '')); if ($response->hasHeader(self::HEADER_ENABLED)) { - $lifetime = $response->hasHeader(self::HEADER_LIFTIME) ? (int)$response->getHeaderLine(self::HEADER_LIFTIME) : null; + $lifetime = $response->hasHeader(self::HEADER_LIFETIME) ? (int)$response->getHeaderLine(self::HEADER_LIFETIME) : null; $tags = $response->hasHeader(self::HEADER_TAGS) ? $response->getHeader(self::HEADER_TAGS) : []; $response = $response ->withoutHeader(self::HEADER_ENABLED) - ->withoutHeader(self::HEADER_LIFTIME) + ->withoutHeader(self::HEADER_LIFETIME) ->withoutHeader(self::HEADER_TAGS); $publicLifetime = 0; @@ -113,11 +98,6 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface return $response; } - - /** - * @param ServerRequestInterface $request - * @return string|null - */ protected function getCacheIdentifierForRequestIfCacheable(ServerRequestInterface $request): ?string { if (!in_array(strtoupper($request->getMethod()), ['GET', 'HEAD'])) { @@ -126,7 +106,6 @@ protected function getCacheIdentifierForRequestIfCacheable(ServerRequestInterfac $requestQueryParams = $request->getQueryParams(); $allowedQueryParams = []; - $ignoredQueryParams = []; $disallowedQueryParams = []; foreach ($requestQueryParams as $key => $value) { switch (true) { @@ -134,7 +113,6 @@ protected function getCacheIdentifierForRequestIfCacheable(ServerRequestInterfac $allowedQueryParams[$key] = $value; break; case (in_array($key, $this->ignoredQueryParams)): - $ignoredQueryParams[$key] = $value; break; default: $disallowedQueryParams[$key] = $value; From fb818290cd57bd89c92569116714dd428ac6bfb8 Mon Sep 17 00:00:00 2001 From: Sebastian Helzle Date: Thu, 5 May 2022 15:19:47 +0200 Subject: [PATCH 3/5] TASK: Fix typo --- Classes/Middleware/FusionAutoconfigurationMiddleware.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Classes/Middleware/FusionAutoconfigurationMiddleware.php b/Classes/Middleware/FusionAutoconfigurationMiddleware.php index 1381280..a178ae8 100644 --- a/Classes/Middleware/FusionAutoconfigurationMiddleware.php +++ b/Classes/Middleware/FusionAutoconfigurationMiddleware.php @@ -44,7 +44,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface $response = $response->withoutHeader(self::HEADER_ENABLED); - [$hasUncachedSegments, $tags, $lifetime] = $this->getFusionCacheInformations(); + [$hasUncachedSegments, $tags, $lifetime] = $this->getFusionCacheInformation(); if ($hasUncachedSegments || $response->hasHeader('Set-Cookie')) { return $response; @@ -71,7 +71,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface * * @return array with first "hasUncachedSegments", "tags" and "lifetime" */ - public function getFusionCacheInformations(): array + public function getFusionCacheInformation(): array { $lifetime = null; $tags = []; From 197d1f733484f357c49f90b0dc859b342567e58a Mon Sep 17 00:00:00 2001 From: Sebastian Helzle Date: Fri, 13 May 2022 10:00:26 +0200 Subject: [PATCH 4/5] TASK: Resolve more PHP warnings --- .../Middleware/FusionAutoconfigurationMiddleware.php | 8 ++++---- Classes/Middleware/RequestCacheMiddleware.php | 11 +++++------ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Classes/Middleware/FusionAutoconfigurationMiddleware.php b/Classes/Middleware/FusionAutoconfigurationMiddleware.php index a178ae8..d4feeab 100644 --- a/Classes/Middleware/FusionAutoconfigurationMiddleware.php +++ b/Classes/Middleware/FusionAutoconfigurationMiddleware.php @@ -30,13 +30,13 @@ class FusionAutoconfigurationMiddleware implements MiddlewareInterface #[Flow\InjectConfiguration('enabled')] protected bool $enabled; - public function process(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { if (!$this->enabled || !$request->hasHeader(RequestCacheMiddleware::HEADER_ENABLED)) { - return $next->handle($request)->withoutHeader(self::HEADER_ENABLED); + return $handler->handle($request)->withoutHeader(self::HEADER_ENABLED); } - $response = $next->handle($request); + $response = $handler->handle($request); if (!$response->hasHeader(self::HEADER_ENABLED)) { return $response; @@ -76,7 +76,7 @@ public function getFusionCacheInformation(): array $lifetime = null; $tags = []; $entriesMetadata = $this->contentCache->getAllMetadata(); - foreach ($entriesMetadata as $identifier => $metadata) { + foreach ($entriesMetadata as $metadata) { $entryTags = $metadata['tags'] ?? []; $entryLifetime = $metadata['lifetime'] ?? null; if ($entryLifetime !== null) { diff --git a/Classes/Middleware/RequestCacheMiddleware.php b/Classes/Middleware/RequestCacheMiddleware.php index 1c3b2ae..3a4035c 100644 --- a/Classes/Middleware/RequestCacheMiddleware.php +++ b/Classes/Middleware/RequestCacheMiddleware.php @@ -3,14 +3,13 @@ namespace Flowpack\FullPageCache\Middleware; +use GuzzleHttp\Psr7\Message; use Neos\Flow\Annotations as Flow; use Neos\Cache\Frontend\VariableFrontend; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; -use GuzzleHttp\Psr7\Message; -use function GuzzleHttp\Psr7\str; class RequestCacheMiddleware implements MiddlewareInterface { @@ -43,16 +42,16 @@ class RequestCacheMiddleware implements MiddlewareInterface #[Flow\InjectConfiguration('maxPublicCacheTime')] protected int $maxPublicCacheTime; - public function process(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { if (!$this->enabled) { - return $next->handle($request); + return $handler->handle($request); } $entryIdentifier = $this->getCacheIdentifierForRequestIfCacheable($request); if (is_null($entryIdentifier)) { - return $next->handle($request)->withHeader(self::HEADER_INFO, 'SKIP'); + return $handler->handle($request)->withHeader(self::HEADER_INFO, 'SKIP'); } if ($cacheEntry = $this->cacheFrontend->get($entryIdentifier)) { @@ -63,7 +62,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface ->withHeader(self::HEADER_INFO, 'HIT: ' . $entryIdentifier); } - $response = $next->handle($request->withHeader(self::HEADER_ENABLED, '')); + $response = $handler->handle($request->withHeader(self::HEADER_ENABLED, '')); if ($response->hasHeader(self::HEADER_ENABLED)) { $lifetime = $response->hasHeader(self::HEADER_LIFETIME) ? (int)$response->getHeaderLine(self::HEADER_LIFETIME) : null; From 4d815f99fe5ad55280206e4ae95a8f88f888b057 Mon Sep 17 00:00:00 2001 From: Sebastian Helzle Date: Mon, 16 May 2022 09:15:11 +0200 Subject: [PATCH 5/5] TASK: Allow lazy injection --- Classes/Aspects/ContentCacheAspect.php | 5 ++++- Classes/Cache/MetadataAwareStringFrontend.php | 10 ++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Classes/Aspects/ContentCacheAspect.php b/Classes/Aspects/ContentCacheAspect.php index 2e44835..2421880 100644 --- a/Classes/Aspects/ContentCacheAspect.php +++ b/Classes/Aspects/ContentCacheAspect.php @@ -13,8 +13,11 @@ class ContentCacheAspect { private bool $hadUncachedSegments = false; + /** + * @var StringFrontend + */ #[Flow\Inject] - protected StringFrontend $cacheFrontend; + protected $cacheFrontend; /** * @Flow\Before("method(Neos\Fusion\Core\Cache\ContentCache->(createUncachedSegment)())") diff --git a/Classes/Cache/MetadataAwareStringFrontend.php b/Classes/Cache/MetadataAwareStringFrontend.php index 835e9ea..60a0f99 100644 --- a/Classes/Cache/MetadataAwareStringFrontend.php +++ b/Classes/Cache/MetadataAwareStringFrontend.php @@ -20,11 +20,17 @@ class MetadataAwareStringFrontend extends StringFrontend */ protected array $metadata = []; + /** + * @var Environment + */ #[Flow\Inject] - protected Environment $environment; + protected $environment; + /** + * @var LoggerInterface + */ #[Flow\Inject] - protected LoggerInterface $logger; + protected $logger; /** * Set a cache entry and store additional metadata (tags and lifetime)