diff --git a/src/Cache/Control/GeneratesEtagInterface.php b/src/Cache/Control/GeneratesEtagInterface.php index 1e8ff34..49df214 100644 --- a/src/Cache/Control/GeneratesEtagInterface.php +++ b/src/Cache/Control/GeneratesEtagInterface.php @@ -4,5 +4,5 @@ interface GeneratesEtagInterface { - public function getEtagComponents(): array; + public function getEtagComponents(array $context): array; } diff --git a/src/Hooks/Api/Invoker.php b/src/Hooks/Api/Invoker.php index 5e1ed81..fd3d811 100644 --- a/src/Hooks/Api/Invoker.php +++ b/src/Hooks/Api/Invoker.php @@ -110,7 +110,7 @@ public function process(ServerRequestInterface $request, ResponseInterface $resp } if ($component instanceof GeneratesEtagInterface) { - $response = $response->withHeader("ETag", $etag = "W\\" . md5(implode($component->getEtagComponents()))); + $response = $response->withHeader("ETag", $etag = "W\\" . md5(implode('', $component->getEtagComponents($arguments)))); if(($_SERVER['HTTP_IF_NONE_MATCH'] ?? null) && $etag === $_SERVER['HTTP_IF_NONE_MATCH']) { return $response->withStatus(304)->withHeader('Cache-Control', $tokenizer->render()); } diff --git a/src/Hooks/Html/Renderer.php b/src/Hooks/Html/Renderer.php index e8e9566..17e1033 100644 --- a/src/Hooks/Html/Renderer.php +++ b/src/Hooks/Html/Renderer.php @@ -42,6 +42,14 @@ public function process(ServerRequestInterface $request, ResponseInterface $resp $root = $this->container->make($this->root); $rendered = $this->container->call($root->render(...)); $rendered = $this->compiler->compile($rendered); + + if(!empty($this->compiler->etagDescription)) { + $response = $response->withHeader('ETag', $etag = "W\\".md5(implode("", $this->compiler->etagDescription))); + if(($_SERVER['HTTP_IF_NONE_MATCH'] ?? null) && $etag === $_SERVER['HTTP_IF_NONE_MATCH']) { + return $response->withStatus(304)->withHeader('Cache-Control', $this->compiler->tokenizer->render()); + } + } + return $response->withBody($this->psr17Factory->createStream($rendered))->withHeader('Cache-Control', $this->compiler->tokenizer->render()); } } diff --git a/src/Template/Parser/StreamingCompiler.php b/src/Template/Parser/StreamingCompiler.php index 85c6364..2a48f5f 100644 --- a/src/Template/Parser/StreamingCompiler.php +++ b/src/Template/Parser/StreamingCompiler.php @@ -3,6 +3,7 @@ namespace Bottledcode\SwytchFramework\Template\Parser; use Bottledcode\SwytchFramework\Cache\AbstractCache; +use Bottledcode\SwytchFramework\Cache\Control\GeneratesEtagInterface; use Bottledcode\SwytchFramework\Cache\Control\Tokenizer; use Bottledcode\SwytchFramework\Template\Functional\DataProvider; use Bottledcode\SwytchFramework\Template\Functional\RewritingTag; @@ -47,6 +48,8 @@ class StreamingCompiler private int $fragmentLength = 0; private bool $shallow = false; + public array $etagDescription = []; + public function __construct( public FactoryInterface $factory, private EscaperInterface $blobber, @@ -792,6 +795,11 @@ private function renderComponent(Document $document): Document } $rendering = $component->renderToString($this->attributes); + + if($component->rawComponent instanceof GeneratesEtagInterface) { + $this->etagDescription = array_merge_recursive($this->etagDescription, $component->rawComponent->getEtagComponents($this->attributes)); + } + $rendering = $this->blobber->makeBlobs($rendering); // stupid hack to get around the fact that we are lexigraphically parsing the document instead // of creating a tree.