Skip to content

Commit 2bfc034

Browse files
committed
added bridge for Latte 3
1 parent c025df0 commit 2bfc034

File tree

59 files changed

+1749
-134
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+1749
-134
lines changed

.github/workflows/coding-style.yml

Lines changed: 1 addition & 1 deletion
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

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ jobs:
4949
- uses: actions/checkout@v2
5050
- uses: shivammathur/setup-php@v2
5151
with:
52-
php-version: 7.4
52+
php-version: 8.0
5353
coverage: none
5454

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

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"nette/forms": "^3.0",
3232
"nette/robot-loader": "^3.2",
3333
"nette/security": "^3.0",
34-
"latte/latte": "^2.10.2",
34+
"latte/latte": "^2.10.2 || ^3.0",
3535
"tracy/tracy": "^2.6",
3636
"mockery/mockery": "^1.0",
3737
"phpstan/phpstan-nette": "^0.12"
@@ -41,7 +41,7 @@
4141
"nette/di": "<3.0.7",
4242
"nette/forms": "<3.0",
4343
"nette/schema": "<1.2",
44-
"latte/latte": "<2.7.1 || >=3.0",
44+
"latte/latte": "<2.7.1 || >=3.1",
4545
"tracy/tracy": "<2.5"
4646
},
4747
"autoload": {

src/Bridges/ApplicationDI/LatteExtension.php

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public function getConfigSchema(): Nette\Schema\Schema
4141
'debugger' => Expect::anyOf(true, false, 'all'),
4242
'xhtml' => Expect::bool(false)->deprecated(),
4343
'macros' => Expect::arrayOf('string'),
44+
'extensions' => Expect::arrayOf('string|Nette\DI\Definitions\Statement'),
4445
'templateClass' => Expect::string(),
4546
'strictTypes' => Expect::bool(false),
4647
]);
@@ -62,21 +63,25 @@ public function loadConfiguration()
6263
->setFactory(Latte\Engine::class)
6364
->addSetup('setTempDirectory', [$this->tempDir])
6465
->addSetup('setAutoRefresh', [$this->debugMode])
66+
->addSetup('setStrictTypes', [$config->strictTypes]);
67+
68+
if (version_compare(Latte\Engine::VERSION, '3', '<')) {
69+
$latteFactory
6570
->addSetup('setContentType', [$config->xhtml ? Latte\Compiler::CONTENT_XHTML : Latte\Compiler::CONTENT_HTML])
6671
->addSetup('Nette\Utils\Html::$xhtml = ?', [$config->xhtml]);
67-
68-
if ($config->strictTypes) {
69-
$latteFactory->addSetup('setStrictTypes', [true]);
72+
foreach ($config->macros as $macro) {
73+
$this->addMacro($macro);
74+
}
75+
} else {
76+
foreach ($config->extensions as $extension) {
77+
$this->addExtension($extension);
78+
}
7079
}
7180

7281
$builder->addDefinition($this->prefix('templateFactory'))
7382
->setFactory(ApplicationLatte\TemplateFactory::class)
7483
->setArguments(['templateClass' => $config->templateClass]);
7584

76-
foreach ($config->macros as $macro) {
77-
$this->addMacro($macro);
78-
}
79-
8085
if ($this->name === 'latte') {
8186
$builder->addAlias('nette.latteFactory', $this->prefix('latteFactory'));
8287
$builder->addAlias('nette.templateFactory', $this->prefix('templateFactory'));
@@ -142,4 +147,18 @@ public function addMacro(string $macro): void
142147
$definition->addSetup('?->onCompile[] = function ($engine) { ' . $macro . '($engine->getCompiler()); }', ['@self']);
143148
}
144149
}
150+
151+
152+
/** @param Nette\DI\Definitions\Statement|string $extension */
153+
public function addExtension($extension): void
154+
{
155+
$extension = is_string($extension)
156+
? new Nette\DI\Definitions\Statement($extension)
157+
: $extension;
158+
159+
$builder = $this->getContainerBuilder();
160+
$builder->getDefinition($this->prefix('latteFactory'))
161+
->getResultDefinition()
162+
->addSetup('addExtension', [$extension]);
163+
}
145164
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
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\ApplicationLatte\Nodes;
11+
12+
use Latte;
13+
use Latte\Compiler\Escaper;
14+
use Latte\Compiler\Nodes\Php\Expression\ArrayItemNode;
15+
use Latte\Compiler\Nodes\Php\Expression\ArrayNode;
16+
use Latte\Compiler\Nodes\Php\ExpressionNode;
17+
use Latte\Compiler\Nodes\Php\ModifierNode;
18+
use Latte\Compiler\Nodes\Php\Scalar\StringNode;
19+
use Latte\Compiler\Nodes\StatementNode;
20+
use Latte\Compiler\PrintContext;
21+
use Latte\Compiler\Tag;
22+
use Nette\Utils\Strings;
23+
24+
25+
/**
26+
* {control name[:method] [params]}
27+
*/
28+
class ControlNode extends StatementNode
29+
{
30+
public ExpressionNode $name;
31+
public ?ExpressionNode $method = null;
32+
public ArrayNode $args;
33+
public ?bool $escape = null;
34+
35+
36+
public static function create(Tag $tag): static
37+
{
38+
$tag->outputMode = $tag::OutputRemoveIndentation;
39+
$tag->expectArguments();
40+
$stream = $tag->parser->stream;
41+
$node = new static;
42+
$node->name = $tag->parser->parseUnquotedStringOrExpression(colon: false);
43+
if ($stream->tryConsume(':')) {
44+
$node->method = $tag->parser->parseExpression();
45+
}
46+
47+
$stream->tryConsume(',');
48+
$start = $stream->getIndex();
49+
$node->args = $tag->parser->parseArguments();
50+
$start -= $stream->getIndex();
51+
$depth = $wrap = null;
52+
for (; $start < 0; $start++) {
53+
$token = $stream->peek($start);
54+
match (true) {
55+
$token->is('[') => $depth++,
56+
$token->is(']') => $depth--,
57+
$token->is('=>') && !$depth => $wrap = true,
58+
default => null,
59+
};
60+
}
61+
62+
if ($wrap) {
63+
$node->args = new ArrayNode([new ArrayItemNode($node->args)]);
64+
}
65+
66+
$modifier = $tag->parser->parseModifier();
67+
foreach ($modifier->filters as $filter) {
68+
match ($filter->name->name) {
69+
'noescape' => $node->escape = false,
70+
default => throw new Latte\CompileException('Only modifier |noescape is allowed here.', $tag->position),
71+
};
72+
}
73+
74+
return $node;
75+
}
76+
77+
78+
public function print(PrintContext $context): string
79+
{
80+
if ($this->escape === null && $context->getEscaper()->getState() !== Escaper::HtmlText) {
81+
$this->escape = true;
82+
}
83+
84+
$method = match (true) {
85+
!$this->method => 'render',
86+
$this->method instanceof StringNode && Strings::match($this->method->value, '#^\w*$#D') => 'render' . ucfirst($this->method->value),
87+
default => "{'render' . " . $this->method->print($context) . '}',
88+
};
89+
90+
$fetchCode = $context->format(
91+
$this->name instanceof StringNode
92+
? '$ʟ_tmp = $this->global->uiControl->getComponent(%node);'
93+
: 'if (!is_object($ʟ_tmp = %node)) $ʟ_tmp = $this->global->uiControl->getComponent($ʟ_tmp);',
94+
$this->name,
95+
);
96+
97+
if ($this->escape) {
98+
return $context->format(
99+
<<<'XX'
100+
%raw
101+
if ($ʟ_tmp instanceof Nette\Application\UI\Renderable) $ʟ_tmp->redrawControl(null, false);
102+
ob_start(fn() => '');
103+
$ʟ_tmp->%raw(%args) %line;
104+
$ʟ_fi = new LR\FilterInfo(%dump); echo %modifyContent(ob_get_clean());
105+
106+
107+
XX,
108+
$fetchCode,
109+
$method,
110+
$this->args,
111+
$this->position,
112+
Latte\ContentType::Html,
113+
new ModifierNode([], $this->escape),
114+
);
115+
116+
} else {
117+
return $context->format(
118+
<<<'XX'
119+
%raw
120+
if ($ʟ_tmp instanceof Nette\Application\UI\Renderable) $ʟ_tmp->redrawControl(null, false);
121+
$ʟ_tmp->%raw(%args) %line;
122+
123+
124+
XX,
125+
$fetchCode,
126+
$method,
127+
$this->args,
128+
$this->position,
129+
);
130+
}
131+
}
132+
133+
134+
public function &getIterator(): \Generator
135+
{
136+
yield $this->name;
137+
if ($this->method) {
138+
yield $this->method;
139+
}
140+
yield $this->args;
141+
}
142+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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\ApplicationLatte\Nodes;
11+
12+
use Latte\Compiler\Nodes\AreaNode;
13+
use Latte\Compiler\Nodes\Php\Expression\ArrayNode;
14+
use Latte\Compiler\Nodes\Php\ExpressionNode;
15+
use Latte\Compiler\Nodes\StatementNode;
16+
use Latte\Compiler\PrintContext;
17+
use Latte\Compiler\Tag;
18+
19+
20+
/**
21+
* {ifCurrent destination [,] [params]}
22+
* @deprecated use {if isLinkCurrent('...')}
23+
*/
24+
class IfCurrentNode extends StatementNode
25+
{
26+
public ?ExpressionNode $destination = null;
27+
public ?ArrayNode $args = null;
28+
public AreaNode $content;
29+
30+
31+
public static function create(Tag $tag): \Generator
32+
{
33+
trigger_error("Tag {ifCurrent} is deprecated, use {if isLinkCurrent('...')} instead (on line {$tag->position->line})", E_USER_DEPRECATED);
34+
$node = new static;
35+
if (!$tag->parser->isEnd()) {
36+
$node->destination = $tag->parser->parseUnquotedStringOrExpression();
37+
$tag->parser->stream->tryConsume(',');
38+
$node->args = $tag->parser->parseArguments();
39+
}
40+
41+
[$node->content] = yield;
42+
return $node;
43+
}
44+
45+
46+
public function print(PrintContext $context): string
47+
{
48+
return $this->destination
49+
? $context->format(
50+
'if ($this->global->uiPresenter->isLinkCurrent(%node, %args?)) { %node } ',
51+
$this->destination,
52+
$this->args,
53+
$this->content,
54+
)
55+
: $context->format(
56+
'if ($this->global->uiPresenter->getLastCreatedRequestFlag("current")) { %node } ',
57+
$this->content,
58+
);
59+
}
60+
61+
62+
public function &getIterator(): \Generator
63+
{
64+
if ($this->destination) {
65+
yield $this->destination;
66+
yield $this->args;
67+
}
68+
yield $this->content;
69+
}
70+
}

0 commit comments

Comments
 (0)