Merge branch 'release/1.7.41.2'

This commit is contained in:
Andy Miller 2023-06-01 15:19:12 -06:00
commit d4c617ff19
No known key found for this signature in database
GPG Key ID: 9F2CF38AEBDB0AE0
5 changed files with 86 additions and 40 deletions

View File

@ -1,3 +1,11 @@
# 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

View File

@ -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);

View File

@ -59,7 +59,7 @@ class PagesServiceProvider implements ServiceProviderInterface
/** @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

View File

@ -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 @@ class TwigNodeCache extends Node
->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");
}
}
}

View File

@ -11,7 +11,6 @@ namespace Grav\Common\Twig\TokenParser;
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 @@ use Twig\TokenParser\AbstractTokenParser;
* {{ 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';
}
}
}