From 31aeaf6309d3bb7e12f1ebe9b97fce2f1fccb7c1 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Tue, 23 May 2023 15:54:48 -0600 Subject: [PATCH 1/4] improved the Twig Cache Tag with customizable key (lang specific if needed) --- CHANGELOG.md | 6 ++ .../Grav/Common/Twig/Node/TwigNodeCache.php | 59 +++++++++++++++---- .../Twig/TokenParser/TwigTokenParserCache.php | 55 +++++++++-------- 3 files changed, 82 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54ca2513d5..c8638969e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# v1.7.42 +## mm/dd/2023 + +1. [](#improved) + * Added the ability to set a configurable 'key' for the Twig Cache Tag: `{% cache 'my-key' 600 %}` + # v1.7.41.1 ## 05/10/2023 diff --git a/system/src/Grav/Common/Twig/Node/TwigNodeCache.php b/system/src/Grav/Common/Twig/Node/TwigNodeCache.php index 64a13a6842..c7d4eea450 100644 --- a/system/src/Grav/Common/Twig/Node/TwigNodeCache.php +++ b/system/src/Grav/Common/Twig/Node/TwigNodeCache.php @@ -10,13 +10,15 @@ namespace Grav\Common\Twig\Node; use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; use Twig\Node\Node; +use Twig\Node\NodeOutputInterface; /** * Class TwigNodeCache * @package Grav\Common\Twig\Node */ -class TwigNodeCache extends Node +class TwigNodeCache extends Node implements NodeOutputInterface { /** * @param string $key unique name for key @@ -25,25 +27,58 @@ class TwigNodeCache extends Node * @param integer $lineno * @param string|null $tag */ - public function __construct(string $key, int $lifetime, Node $body, $lineno, $tag = null) + public function __construct(Node $body, ?AbstractExpression $key, ?AbstractExpression $lifetime, array $defaults, int $lineno, string $tag) { - parent::__construct(array('body' => $body), array( 'key' => $key, 'lifetime' => $lifetime), $lineno, $tag); + $nodes = ['body' => $body]; + + if ($key !== null) { + $nodes['key'] = $key; + } + + if ($lifetime !== null) { + $nodes['lifetime'] = $lifetime; + } + + parent::__construct($nodes, $defaults, $lineno, $tag); } - /** - * {@inheritDoc} - */ public function compile(Compiler $compiler): void { - $boo = $this->getAttribute('key'); + $compiler->addDebugInfo($this); + + + // Generate the cache key + if ($this->hasNode('key')) { + $compiler + ->write('$key = "twigcache-" . ') + ->subcompile($this->getNode('key')) + ->raw(";\n"); + } else { + $compiler + ->write('$key = ') + ->string($this->getAttribute('key')) + ->raw(";\n"); + } + + // Set the cache timeout + if ($this->hasNode('lifetime')) { + $compiler + ->write('$lifetime = ') + ->subcompile($this->getNode('lifetime')) + ->raw(";\n"); + } else { + $compiler + ->write('$lifetime = ') + ->write($this->getAttribute('lifetime')) + ->raw(";\n"); + } + $compiler - ->addDebugInfo($this) ->write("\$cache = \\Grav\\Common\\Grav::instance()['cache'];\n") - ->write("\$key = \"twigcache-\" . \"" . $this->getAttribute('key') . "\";\n") - ->write("\$lifetime = " . $this->getAttribute('lifetime') . ";\n") ->write("\$cache_body = \$cache->fetch(\$key);\n") ->write("if (\$cache_body === false) {\n") ->indent() + ->write("\\Grav\\Common\\Grav::instance()['debugger']->addMessage(\"Cache Key: \$key, Lifetime: \$lifetime\");\n") ->write("ob_start();\n") ->indent() ->subcompile($this->getNode('body')) @@ -53,6 +88,6 @@ public function compile(Compiler $compiler): void ->write("\$cache->save(\$key, \$cache_body, \$lifetime);\n") ->outdent() ->write("}\n") - ->write("echo \$cache_body;\n"); + ->write("echo '' === \$cache_body ? '' : new Markup(\$cache_body, \$this->env->getCharset());\n"); } -} +} \ No newline at end of file diff --git a/system/src/Grav/Common/Twig/TokenParser/TwigTokenParserCache.php b/system/src/Grav/Common/Twig/TokenParser/TwigTokenParserCache.php index d3658b23b2..3b030a433c 100644 --- a/system/src/Grav/Common/Twig/TokenParser/TwigTokenParserCache.php +++ b/system/src/Grav/Common/Twig/TokenParser/TwigTokenParserCache.php @@ -11,7 +11,6 @@ use Grav\Common\Grav; use Grav\Common\Twig\Node\TwigNodeCache; -use Twig\Error\SyntaxError; use Twig\Token; use Twig\TokenParser\AbstractTokenParser; @@ -22,50 +21,54 @@ * {{ some_complex_work() }} * {% endcache %} * - * Where the `600` is an optional lifetime in seconds + * Also can provide a unique key for the cache: + * + * {% cache "prefix-"~lang 600 %} + * + * Where the "prefix-"~lang will use a unique key based on the current language. "prefix-en" for example */ class TwigTokenParserCache extends AbstractTokenParser { - /** - * @param Token $token - * @return TwigNodeCache - * @throws SyntaxError - */ public function parse(Token $token) { - $lineno = $token->getLine(); $stream = $this->parser->getStream(); - $key = $this->parser->getVarName() . $lineno; - $lifetime = Grav::instance()['cache']->getLifetime(); + $lineno = $token->getLine(); - // Check for optional lifetime override - if (!$stream->test(Token::BLOCK_END_TYPE)) { - $lifetime_expr = $this->parser->getExpressionParser()->parseExpression(); - $lifetime = $lifetime_expr->getAttribute('value'); + // Parse the optional key and timeout parameters + $defaults = [ + 'key' => $this->parser->getVarName() . $lineno, + 'lifetime' => Grav::instance()['cache']->getLifetime() + ]; + + $key = null; + $lifetime = null; + while (!$stream->test(Token::BLOCK_END_TYPE)) { + if ($stream->test(Token::STRING_TYPE)) { + $key = $this->parser->getExpressionParser()->parseExpression(); + } elseif ($stream->test(Token::NUMBER_TYPE)) { + $lifetime = $this->parser->getExpressionParser()->parseExpression(); + } else { + throw new \Twig\Error\SyntaxError("Unexpected token type in cache tag.", $token->getLine(), $stream->getSourceContext()); + } } $stream->expect(Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideCacheEnd'), true); + + // Parse the content inside the cache block + $body = $this->parser->subparse([$this, 'decideCacheEnd'], true); + $stream->expect(Token::BLOCK_END_TYPE); - return new TwigNodeCache($key, $lifetime, $body, $lineno, $this->getTag()); + return new TwigNodeCache($body, $key, $lifetime, $defaults, $lineno, $this->getTag()); } - /** - * Decide if current token marks end of cache block. - * - * @param Token $token - * @return bool - */ public function decideCacheEnd(Token $token): bool { return $token->test('endcache'); } - /** - * {@inheritDoc} - */ + public function getTag(): string { return 'cache'; } -} +} \ No newline at end of file From 8dfa2110bfb23c11144f63270982e48b3f4e2b7b Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Thu, 1 Jun 2023 15:16:56 -0600 Subject: [PATCH 2/4] fix for special chars in slugs causing redirect loops --- CHANGELOG.md | 8 ++++---- system/src/Grav/Common/Service/PagesServiceProvider.php | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8638969e8..5160987e45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ -# v1.7.42 -## mm/dd/2023 +# v1.7.41.2 +## 06/01/2023 -1. [](#improved) - * Added the ability to set a configurable 'key' for the Twig Cache Tag: `{% cache 'my-key' 600 %}` +1. [](#bugfix) + * Fixed an issue with special characters in slug's would cause redirect loops # v1.7.41.1 ## 05/10/2023 diff --git a/system/src/Grav/Common/Service/PagesServiceProvider.php b/system/src/Grav/Common/Service/PagesServiceProvider.php index 0e10d144e1..a6fc59ed2b 100644 --- a/system/src/Grav/Common/Service/PagesServiceProvider.php +++ b/system/src/Grav/Common/Service/PagesServiceProvider.php @@ -59,7 +59,7 @@ public function register(Container $container) /** @var Uri $uri */ $uri = $grav['uri']; - $path = $uri->path() ?: '/'; // Don't trim to support trailing slash default routes + $path = $uri->path() ? urldecode($uri->path()) : '/'; // Don't trim to support trailing slash default routes $page = $pages->dispatch($path); // Redirection tests From 5b950ce73f902b381fb5ca859ca036911442c4c8 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Thu, 1 Jun 2023 15:17:47 -0600 Subject: [PATCH 3/4] update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5160987e45..7956dc3b02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # v1.7.41.2 ## 06/01/2023 +1. [](#improved) + * Added the ability to set a configurable 'key' for the Twig Cache Tag: `{% cache 'my-key' 600 %}` 1. [](#bugfix) * Fixed an issue with special characters in slug's would cause redirect loops From 722ce55ccbcb77606c715e9a76f1ac4811d2cd5c Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Thu, 1 Jun 2023 15:18:53 -0600 Subject: [PATCH 4/4] prepare for release --- system/defines.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/defines.php b/system/defines.php index bccdd42b45..02b37c9010 100644 --- a/system/defines.php +++ b/system/defines.php @@ -9,7 +9,7 @@ // Some standard defines define('GRAV', true); -define('GRAV_VERSION', '1.7.41.1'); +define('GRAV_VERSION', '1.7.41.2'); define('GRAV_SCHEMA', '1.7.0_2020-11-20_1'); define('GRAV_TESTING', false);