Skip to content

Commit 7a59a77

Browse files
committed
added bridge for Latte 3
1 parent 8bf7455 commit 7a59a77

20 files changed

+387
-11
lines changed

.github/workflows/coding-style.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
- uses: actions/checkout@v2
1111
- uses: shivammathur/setup-php@v2
1212
with:
13-
php-version: 7.2
13+
php-version: 8.0
1414
coverage: none
1515

1616
- run: composer create-project nette/code-checker temp/code-checker ^3 --no-progress
@@ -24,7 +24,7 @@ jobs:
2424
- uses: actions/checkout@v2
2525
- uses: shivammathur/setup-php@v2
2626
with:
27-
php-version: 7.4
27+
php-version: 8.0
2828
coverage: none
2929

3030
- run: composer create-project nette/coding-standard temp/coding-standard ^3 --no-progress

.github/workflows/tests.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ jobs:
5252
- uses: actions/checkout@v2
5353
- uses: shivammathur/setup-php@v2
5454
with:
55-
php-version: 7.4
55+
php-version: 8.0
5656
coverage: none
5757

5858
- run: composer install --no-progress --prefer-dist

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"require-dev": {
2323
"nette/tester": "^2.0",
2424
"nette/di": "^v3.0",
25-
"latte/latte": "^2.10",
25+
"latte/latte": "^2.11 || ^3.0",
2626
"tracy/tracy": "^2.4",
2727
"phpstan/phpstan": "^0.12"
2828
},
+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
/**
4+
* This file is part of the Nette Framework (https://nette.org)
5+
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace Nette\Bridges\CacheLatte;
11+
12+
use Latte;
13+
use Latte\Compiler\Nodes\AuxiliaryNode;
14+
use Latte\Compiler\Nodes\TemplateNode;
15+
use Latte\Compiler\Tag;
16+
use Latte\Engine;
17+
use Nette\Caching\Storage;
18+
19+
20+
/**
21+
* Latte v3 extension for Nette Caching
22+
*/
23+
final class CacheExtension extends Latte\Extension
24+
{
25+
private bool $used;
26+
private Storage $storage;
27+
28+
29+
public function __construct(Storage $storage)
30+
{
31+
$this->storage = $storage;
32+
}
33+
34+
35+
public function beforeCompile(Latte\Engine $engine): void
36+
{
37+
$this->used = false;
38+
}
39+
40+
41+
public function getTags(): array
42+
{
43+
return [
44+
'cache' => function (Tag $tag): \Generator {
45+
$this->used = true;
46+
return Nodes\CacheNode::create($tag);
47+
},
48+
];
49+
}
50+
51+
52+
public function getPasses(): array
53+
{
54+
return [
55+
'cacheInitialization' => function (TemplateNode $node): void {
56+
if ($this->used) {
57+
$node->head->append(new AuxiliaryNode(fn() => Nodes\CacheNode::class . '::initRuntime($this);'));
58+
}
59+
},
60+
];
61+
}
62+
63+
64+
public function beforeRender(Engine $engine): void
65+
{
66+
$engine->addProvider('cacheStorage', $this->storage);
67+
}
68+
}

src/Bridges/CacheLatte/CacheMacro.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616

1717
/**
18-
* Macro {cache} ... {/cache}
18+
* Macro {cache} ... {/cache} for Latte v2
1919
*/
2020
final class CacheMacro implements Latte\IMacro
2121
{
+149
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
<?php
2+
3+
/**
4+
* This file is part of the Latte (https://latte.nette.org)
5+
* Copyright (c) 2008 David Grudl (https://davidgrudl.com)
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace Nette\Bridges\CacheLatte\Nodes;
11+
12+
use Latte;
13+
use Latte\Compiler\Nodes\AreaNode;
14+
use Latte\Compiler\Nodes\Php\Expression\ArrayNode;
15+
use Latte\Compiler\Nodes\StatementNode;
16+
use Latte\Compiler\Position;
17+
use Latte\Compiler\PrintContext;
18+
use Latte\Compiler\Tag;
19+
use Nette;
20+
use Nette\Caching\Cache;
21+
22+
23+
/**
24+
* {cache} ... {/cache}
25+
*/
26+
class CacheNode extends StatementNode
27+
{
28+
public ArrayNode $args;
29+
public AreaNode $content;
30+
public ?Position $endLine;
31+
32+
33+
/** @return \Generator<int, ?array, array{AreaNode, ?Tag}, static> */
34+
public static function create(Tag $tag): \Generator
35+
{
36+
$node = new static;
37+
$node->args = $tag->parser->parseArguments();
38+
[$node->content, $endTag] = yield;
39+
$node->endLine = $endTag?->position;
40+
return $node;
41+
}
42+
43+
44+
public function print(PrintContext $context): string
45+
{
46+
return $context->format(
47+
<<<'XX'
48+
if (Nette\Bridges\CacheLatte\Nodes\CacheNode::createCache($this->global->cacheStorage, %dump, $this->global->cacheStack, %node?)) %line
49+
try {
50+
%node
51+
Nette\Bridges\CacheLatte\Nodes\CacheNode::endCache($this->global->cacheStack) %line;
52+
} catch (\Throwable $ʟ_e) {
53+
Nette\Bridges\CacheLatte\Nodes\CacheNode::rollback($this->global->cacheStack); throw $ʟ_e;
54+
}
55+
56+
57+
XX,
58+
Nette\Utils\Random::generate(),
59+
$this->args,
60+
$this->position,
61+
$this->content,
62+
$this->endLine,
63+
);
64+
}
65+
66+
67+
public function &getIterator(): \Generator
68+
{
69+
yield $this->args;
70+
yield $this->content;
71+
}
72+
73+
74+
/********************* run-time helpers ****************d*g**/
75+
76+
77+
public static function initRuntime(Latte\Runtime\Template $template): void
78+
{
79+
if (!empty($template->global->cacheStack)) {
80+
$file = (new \ReflectionClass($template))->getFileName();
81+
if (@is_file($file)) { // @ - may trigger error
82+
end($template->global->cacheStack)->dependencies[Cache::Files][] = $file;
83+
}
84+
}
85+
}
86+
87+
88+
/**
89+
* Starts the output cache. Returns Nette\Caching\OutputHelper object if buffering was started.
90+
* @return Nette\Caching\OutputHelper|\stdClass
91+
*/
92+
public static function createCache(
93+
Nette\Caching\Storage $cacheStorage,
94+
string $key,
95+
?array &$parents,
96+
?array $args = null,
97+
) {
98+
if ($args) {
99+
if (array_key_exists('if', $args) && !$args['if']) {
100+
return $parents[] = new \stdClass;
101+
}
102+
103+
$key = array_merge([$key], array_intersect_key($args, range(0, count($args))));
104+
}
105+
106+
if ($parents) {
107+
end($parents)->dependencies[Cache::Items][] = $key;
108+
}
109+
110+
$cache = new Cache($cacheStorage, 'Nette.Templating.Cache');
111+
if ($helper = $cache->capture($key)) {
112+
$parents[] = $helper;
113+
114+
if (isset($args['dependencies'])) {
115+
$args += $args['dependencies']();
116+
}
117+
118+
$helper->dependencies[Cache::Tags] = $args['tags'] ?? null;
119+
$helper->dependencies[Cache::Expire] = $args['expiration'] ?? $args['expire'] ?? '+ 7 days';
120+
}
121+
122+
return $helper;
123+
}
124+
125+
126+
/**
127+
* Ends the output cache.
128+
* @param Nette\Caching\OutputHelper[] $parents
129+
*/
130+
public static function endCache(array &$parents): void
131+
{
132+
$helper = array_pop($parents);
133+
if ($helper instanceof Nette\Caching\OutputHelper) {
134+
$helper->end();
135+
}
136+
}
137+
138+
139+
/**
140+
* @param Nette\Caching\OutputHelper[] $parents
141+
*/
142+
public static function rollback(array &$parents): void
143+
{
144+
$helper = array_pop($parents);
145+
if ($helper instanceof Nette\Caching\OutputHelper) {
146+
$helper->rollback();
147+
}
148+
}
149+
}

tests/Bridges.Latte/CacheMacro.cache.phpt renamed to tests/Bridges.Latte2/CacheMacro.cache.phpt

+4-1
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@ declare(strict_types=1);
99
use Nette\Bridges\CacheLatte\CacheMacro;
1010
use Tester\Assert;
1111

12-
1312
require __DIR__ . '/../bootstrap.php';
1413

14+
if (version_compare(Latte\Engine::VERSION, '3', '>')) {
15+
Tester\Environment::skip('Test for Latte 2');
16+
}
17+
1518

1619
$latte = new Latte\Engine;
1720
$latte->setTempDirectory(getTempDir());

tests/Bridges.Latte/CacheMacro.createCache.phpt renamed to tests/Bridges.Latte2/CacheMacro.createCache.phpt

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@ use Nette\Caching\Cache;
1111
use Nette\Caching\Storages\DevNullStorage;
1212
use Tester\Assert;
1313

14-
1514
require __DIR__ . '/../bootstrap.php';
1615

16+
if (version_compare(Latte\Engine::VERSION, '3', '>')) {
17+
Tester\Environment::skip('Test for Latte 2');
18+
}
19+
20+
1721
test('', function () {
1822
$parents = [];
1923
$dp = [Cache::Tags => ['rum', 'cola']];

tests/Bridges.Latte/expected/CacheMacro.cache.inc.phtml renamed to tests/Bridges.Latte2/expected/CacheMacro.cache.inc.phtml

+1-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
echo LR\Filters::escapeHtmlText(($this->filters->lower)($title)) /* line %d% */;
66
echo "\n";
77
Nette\Bridges\CacheLatte\CacheMacro::endCache($this->global->cacheStack) /* line %d% */;
8-
}
9-
catch (\Throwable $ʟ_e) {
8+
} catch (\Throwable $ʟ_e) {
109
Nette\Bridges\CacheLatte\CacheMacro::rollback($this->global->cacheStack);
1110
throw $ʟ_e;
1211
}

tests/Bridges.Latte/expected/CacheMacro.cache.phtml renamed to tests/Bridges.Latte2/expected/CacheMacro.cache.phtml

+1-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@
1313
$this->createTemplate('include.cache.latte', ['localvar' => 11] + $this->params, 'include')->renderToContentType('html') /* line %d% */;
1414
echo "\n";
1515
Nette\Bridges\CacheLatte\CacheMacro::endCache($this->global->cacheStack, [$id, 'tags' => 'mytag']) /* line %d% */;
16-
}
17-
catch (\Throwable $ʟ_e) {
16+
} catch (\Throwable $ʟ_e) {
1817
Nette\Bridges\CacheLatte\CacheMacro::rollback($this->global->cacheStack);
1918
throw $ʟ_e;
2019
}

tests/Bridges.Latte3/CacheNode.phpt

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Nette\Bridges\CacheLatte\Nodes\CacheNode;
6+
use Nette\Caching\Cache;
7+
use Nette\Caching\Storages\DevNullStorage;
8+
use Tester\Assert;
9+
10+
require __DIR__ . '/../bootstrap.php';
11+
12+
if (version_compare(Latte\Engine::VERSION, '3', '<')) {
13+
Tester\Environment::skip('Test for Latte 3');
14+
}
15+
16+
17+
test('', function () {
18+
$parents = [];
19+
$dp = [Cache::Tags => ['rum', 'cola']];
20+
$outputHelper = CacheNode::createCache(new DevNullStorage, 'test', $parents, $dp);
21+
Assert::type(Nette\Caching\OutputHelper::class, $outputHelper);
22+
CacheNode::endCache($parents);
23+
Assert::same($dp + [Cache::Expire => '+ 7 days'], $outputHelper->dependencies);
24+
});
25+
26+
test('', function () {
27+
$parents = [];
28+
$dp = [Cache::Tags => ['rum', 'cola']];
29+
$dpFallback = function () use ($dp) {
30+
return $dp;
31+
};
32+
$outputHelper = CacheNode::createCache(new DevNullStorage, 'test', $parents, ['dependencies' => $dpFallback]);
33+
CacheNode::endCache($parents);
34+
Assert::same($dp + [Cache::Expire => '+ 7 days'], $outputHelper->dependencies);
35+
});
36+
37+
test('', function () {
38+
$parents = [];
39+
$dp = [
40+
Cache::Tags => ['rum', 'cola'],
41+
Cache::Expire => '+ 1 days',
42+
];
43+
$dpFallback = function () use ($dp) {
44+
return $dp;
45+
};
46+
$outputHelper = CacheNode::createCache(new DevNullStorage, 'test', $parents, ['dependencies' => $dpFallback]);
47+
CacheNode::endCache($parents);
48+
Assert::same($dp, $outputHelper->dependencies);
49+
});
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Noncached content
2+
3+
4+
<h1>HELLO</h1>
5+
6+
<p>Included file (11)</p>
7+
8+
hello
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
%A%
3+
if (Nette\Bridges\CacheLatte\Nodes\CacheNode::createCache($this->global->cacheStorage, '%[\w]+%', $this->global->cacheStack)) /* line %d% */
4+
try {
5+
echo ' ';
6+
echo LR\Filters::escapeHtmlText(($this->filters->lower)($title)) /* line %d% */;
7+
echo "\n";
8+
9+
Nette\Bridges\CacheLatte\Nodes\CacheNode::endCache($this->global->cacheStack) /* line %d% */;
10+
} catch (\Throwable $ʟ_e) {
11+
Nette\Bridges\CacheLatte\Nodes\CacheNode::rollback($this->global->cacheStack);
12+
throw $ʟ_e;
13+
}
14+
%A%

0 commit comments

Comments
 (0)