Skip to content

Commit

Permalink
Latte: runtime helpers moved to Runtime class
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Feb 4, 2023
1 parent a9b3ffe commit ceb814d
Show file tree
Hide file tree
Showing 7 changed files with 165 additions and 138 deletions.
10 changes: 8 additions & 2 deletions src/Bridges/CacheLatte/CacheExtension.php
Expand Up @@ -53,7 +53,7 @@ public function getPasses(): array
return [
'cacheInitialization' => function (TemplateNode $node): void {
if ($this->used) {
$node->head->append(new AuxiliaryNode(fn() => Nodes\CacheNode::class . '::initRuntime($this);'));
$node->head->append(new AuxiliaryNode(fn() => '$this->global->cache->initialize($this);'));
}
},
];
Expand All @@ -63,7 +63,13 @@ public function getPasses(): array
public function getProviders(): array
{
return [
'cacheStorage' => $this->storage,
'cache' => new Runtime($this->storage),
];
}


public function getCacheKey(Latte\Engine $engine): array
{
return ['version' => 2];
}
}
89 changes: 5 additions & 84 deletions src/Bridges/CacheLatte/Nodes/CacheNode.php
Expand Up @@ -9,15 +9,12 @@

namespace Nette\Bridges\CacheLatte\Nodes;

use Latte;
use Latte\Compiler\Nodes\AreaNode;
use Latte\Compiler\Nodes\Php\Expression\ArrayNode;
use Latte\Compiler\Nodes\StatementNode;
use Latte\Compiler\Position;
use Latte\Compiler\PrintContext;
use Latte\Compiler\Tag;
use Nette;
use Nette\Caching\Cache;


/**
Expand Down Expand Up @@ -45,17 +42,18 @@ public function print(PrintContext $context): string
{
return $context->format(
<<<'XX'
if (Nette\Bridges\CacheLatte\Nodes\CacheNode::createCache($this->global->cacheStorage, %dump, $this->global->cacheStack, %node?)) %line
if ($this->global->cache->createCache(%dump, %node?)) %line
try {
%node
Nette\Bridges\CacheLatte\Nodes\CacheNode::endCache($this->global->cacheStack) %line;
$this->global->cache->end() %line;
} catch (\Throwable $ʟ_e) {
Nette\Bridges\CacheLatte\Nodes\CacheNode::rollback($this->global->cacheStack); throw $ʟ_e;
$this->global->cache->rollback();
throw $ʟ_e;
}
XX,
Nette\Utils\Random::generate(),
base64_encode(random_bytes(10)),
$this->args,
$this->position,
$this->content,
Expand All @@ -69,81 +67,4 @@ public function &getIterator(): \Generator
yield $this->args;
yield $this->content;
}


/********************* run-time helpers ****************d*g**/


public static function initRuntime(Latte\Runtime\Template $template): void
{
if (!empty($template->global->cacheStack)) {
$file = (new \ReflectionClass($template))->getFileName();
if (@is_file($file)) { // @ - may trigger error
end($template->global->cacheStack)->dependencies[Cache::Files][] = $file;
}
}
}


/**
* Starts the output cache. Returns Nette\Caching\OutputHelper object if buffering was started.
* @return Nette\Caching\OutputHelper|\stdClass
*/
public static function createCache(
Nette\Caching\Storage $cacheStorage,
string $key,
?array &$parents,
?array $args = null,
) {
if ($args) {
if (array_key_exists('if', $args) && !$args['if']) {
return $parents[] = new \stdClass;
}

$key = array_merge([$key], array_intersect_key($args, range(0, count($args))));
}

if ($parents) {
end($parents)->dependencies[Cache::Items][] = $key;
}

$cache = new Cache($cacheStorage, 'Nette.Templating.Cache');
if ($helper = $cache->capture($key)) {
$parents[] = $helper;

if (isset($args['dependencies'])) {
$args += $args['dependencies']();
}

$helper->dependencies[Cache::Tags] = $args['tags'] ?? null;
$helper->dependencies[Cache::Expire] = $args['expiration'] ?? $args['expire'] ?? '+ 7 days';
}

return $helper;
}


/**
* Ends the output cache.
* @param Nette\Caching\OutputHelper[] $parents
*/
public static function endCache(array &$parents): void
{
$helper = array_pop($parents);
if ($helper instanceof Nette\Caching\OutputHelper) {
$helper->end();
}
}


/**
* @param Nette\Caching\OutputHelper[] $parents
*/
public static function rollback(array &$parents): void
{
$helper = array_pop($parents);
if ($helper instanceof Nette\Caching\OutputHelper) {
$helper->rollback();
}
}
}
98 changes: 98 additions & 0 deletions src/Bridges/CacheLatte/Runtime.php
@@ -0,0 +1,98 @@
<?php

/**
* This file is part of the Latte (https://latte.nette.org)
* Copyright (c) 2008 David Grudl (https://davidgrudl.com)
*/

declare(strict_types=1);

namespace Nette\Bridges\CacheLatte;

use Latte;
use Nette;
use Nette\Caching\Cache;
use Nette\Caching\OutputHelper;


/**
* Runtime helpers for Latte v3.
* @internal
*/
class Runtime
{
/** @var array<int, OutputHelper|\stdClass> */
private array $stack = [];


public function __construct(
private Nette\Caching\Storage $storage,
) {
}


public function initialize(Latte\Runtime\Template $template): void
{
if ($this->stack) {
$file = (new \ReflectionClass($template))->getFileName();
if (@is_file($file)) { // @ - may trigger error
end($this->stack)->dependencies[Cache::Files][] = $file;
}
}
}


/**
* Starts the output cache. Returns true if buffering was started.
*/
public function createCache(string $key, ?array $args = null): bool
{
if ($args) {
if (array_key_exists('if', $args) && !$args['if']) {
$this->stack[] = new \stdClass;
return true;
}

$key = array_merge([$key], array_intersect_key($args, range(0, count($args))));
}

if ($this->stack) {
end($this->stack)->dependencies[Cache::Items][] = $key;
}

$cache = new Cache($this->storage, 'Nette.Templating.Cache');
if ($helper = $cache->capture($key)) {
$this->stack[] = $helper;

if (isset($args['dependencies'])) {
$args += $args['dependencies']();
}

$helper->dependencies[Cache::Tags] = $args['tags'] ?? null;
$helper->dependencies[Cache::Expire] = $args['expiration'] ?? $args['expire'] ?? '+ 7 days';
}

return (bool) $helper;
}


/**
* Ends the output cache.
*/
public function end(): void
{
$helper = array_pop($this->stack);
if ($helper instanceof OutputHelper) {
$helper->end();
}
}


public function rollback(): void
{
$helper = array_pop($this->stack);
if ($helper instanceof OutputHelper) {
$helper->rollback();
}
}
}
45 changes: 0 additions & 45 deletions tests/Bridges.Latte3/CacheNode.phpt

This file was deleted.

47 changes: 47 additions & 0 deletions tests/Bridges.Latte3/Runtime.phpt
@@ -0,0 +1,47 @@
<?php

declare(strict_types=1);

use Nette\Bridges\CacheLatte\Runtime;
use Nette\Caching\Cache;
use Nette\Caching\Storages\DevNullStorage;
use Tester\Assert;

require __DIR__ . '/../bootstrap.php';

if (version_compare(Latte\Engine::VERSION, '3', '<')) {
Tester\Environment::skip('Test for Latte 3');
}


test('', function () {
$runtime = new Runtime(new DevNullStorage);
$dp = [Cache::Tags => ['rum', 'cola']];
Assert::true($runtime->createCache('test', $dp));
$stack = Assert::with($runtime, fn() => $this->stack);
$runtime->end();
Assert::same($dp + [Cache::Expire => '+ 7 days'], $stack[0]->dependencies);
});

test('', function () {
$runtime = new Runtime(new DevNullStorage);
$dp = [Cache::Tags => ['rum', 'cola']];
$dpFallback = fn() => $dp;
Assert::true($runtime->createCache('test', ['dependencies' => $dpFallback]));
$stack = Assert::with($runtime, fn() => $this->stack);
$runtime->end();
Assert::same($dp + [Cache::Expire => '+ 7 days'], $stack[0]->dependencies);
});

test('', function () {
$runtime = new Runtime(new DevNullStorage);
$dp = [
Cache::Tags => ['rum', 'cola'],
Cache::Expire => '+ 1 days',
];
$dpFallback = fn() => $dp;
Assert::true($runtime->createCache('test', ['dependencies' => $dpFallback]));
$stack = Assert::with($runtime, fn() => $this->stack);
$runtime->end();
Assert::same($dp, $stack[0]->dependencies);
});
6 changes: 3 additions & 3 deletions tests/Bridges.Latte3/expected/cache.inc.php
@@ -1,14 +1,14 @@
<?php
%A%
if (Nette\Bridges\CacheLatte\Nodes\CacheNode::createCache($this->global->cacheStorage, '%[\w]+%', $this->global->cacheStack)) /* line %d% */
if ($this->global->cache->createCache('%a%')) /* line %d% */
try {
echo ' ';
echo LR\Filters::escapeHtmlText(($this->filters->lower)($title)) /* line %d% */;
echo "\n";

Nette\Bridges\CacheLatte\Nodes\CacheNode::endCache($this->global->cacheStack) /* line %d% */;
$this->global->cache->end() /* line %d% */;
} catch (\Throwable $ʟ_e) {
Nette\Bridges\CacheLatte\Nodes\CacheNode::rollback($this->global->cacheStack);
$this->global->cache->rollback();
throw $ʟ_e;
}
%A%
8 changes: 4 additions & 4 deletions tests/Bridges.Latte3/expected/cache.php
Expand Up @@ -3,7 +3,7 @@
echo 'Noncached content
';
if (Nette\Bridges\CacheLatte\Nodes\CacheNode::createCache($this->global->cacheStorage, '%[\w]+%', $this->global->cacheStack, [$id, 'tags' => 'mytag'])) /* line %d% */
if ($this->global->cache->createCache('%a%', [$id, 'tags' => 'mytag'])) /* line %d% */
try {
echo '
<h1>';
Expand All @@ -14,9 +14,9 @@
$this->createTemplate('include.cache.latte', ['localvar' => 11] + $this->params, 'include')->renderToContentType('html') /* line %d% */;
echo "\n";

Nette\Bridges\CacheLatte\Nodes\CacheNode::endCache($this->global->cacheStack) /* line %d% */;
$this->global->cache->end() /* line %d% */;
} catch (\Throwable $ʟ_e) {
Nette\Bridges\CacheLatte\Nodes\CacheNode::rollback($this->global->cacheStack);
$this->global->cache->rollback();
throw $ʟ_e;
}
}
Expand All @@ -25,5 +25,5 @@
public function prepare(): array
{
%A%
Nette\Bridges\CacheLatte\Nodes\CacheNode::initRuntime($this);
$this->global->cache->initialize($this);
%A%

0 comments on commit ceb814d

Please sign in to comment.