Skip to content

Commit bd46751

Browse files
committed
{default} is evaluated lazily
1 parent fca0a3e commit bd46751

File tree

3 files changed

+42
-28
lines changed

3 files changed

+42
-28
lines changed

src/Latte/Essential/Nodes/VarNode.php

+10-19
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
use Latte\Compiler\Nodes\Php\Expression\AssignNode;
1313
use Latte\Compiler\Nodes\Php\Expression\VariableNode;
14-
use Latte\Compiler\Nodes\Php\ExpressionNode;
1514
use Latte\Compiler\Nodes\Php\Scalar\NullNode;
1615
use Latte\Compiler\Nodes\StatementNode;
1716
use Latte\Compiler\PrintContext;
@@ -67,26 +66,18 @@ private static function parseAssignments(Tag $tag, bool $default): array
6766
public function print(PrintContext $context): string
6867
{
6968
$res = [];
70-
if ($this->default) {
71-
foreach ($this->assignments as $assign) {
69+
foreach ($this->assignments as $assign) {
70+
if ($this->default) {
7271
assert($assign->var instanceof VariableNode);
73-
if ($assign->var->name instanceof ExpressionNode) {
74-
$var = $assign->var->name->print($context);
75-
} else {
76-
$var = $context->encodeString($assign->var->name);
77-
}
78-
$res[] = $var . ' => ' . $assign->expr->print($context);
72+
$res[] = $context->format(
73+
'%node ??= array_key_exists(%raw, get_defined_vars()) ? null : %node',
74+
$assign->var,
75+
$context->encodeString($assign->var->name),
76+
$assign->expr,
77+
);
78+
} else {
79+
$res[] = $assign->print($context);
7980
}
80-
81-
return $context->format(
82-
'extract([%raw], EXTR_SKIP) %line;',
83-
implode(', ', $res),
84-
$this->position,
85-
);
86-
}
87-
88-
foreach ($this->assignments as $assign) {
89-
$res[] = $assign->print($context);
9081
}
9182

9283
return $context->format(

tests/tags/expected/inheritance.1.parent.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ public function prepare(): array
5353
{
5454
extract($this->params);
5555

56-
extract(['class' => null, 'namespace' => null, 'top' => true], EXTR_SKIP) /* line %d% */;
56+
$class ??= array_key_exists('class', get_defined_vars()) ? null : null;
57+
$namespace ??= array_key_exists('namespace', get_defined_vars()) ? null : null;
58+
$top ??= array_key_exists('top', get_defined_vars()) ? null : true /* line 1 */;
5759
return get_defined_vars();
5860
}
5961

tests/tags/var.default.phpt

+29-8
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,37 @@ test('{var ...}', function () use ($latte) {
4242

4343

4444
test('{default ...}', function () use ($latte) {
45-
Assert::contains("extract(['var' => null, 'var2' => null], EXTR_SKIP) /*", $latte->compile('{default $var, $var2}'));
46-
Assert::contains("extract(['var' => 123], EXTR_SKIP) /*", $latte->compile('{default $var = 123}'));
47-
Assert::contains("extract(['var1' => 123, 'var2' => 'nette framework'], EXTR_SKIP) /*", $latte->compile('{default $var1 = 123, $var2 = "nette framework"}'));
45+
Assert::match(<<<'XX'
46+
%A%
47+
$var ??= array_key_exists('var', get_defined_vars()) ? null : null;
48+
$var2 ??= array_key_exists('var2', get_defined_vars()) ? null : null /* line 1 */;
49+
%A%
50+
XX, $latte->compile('{default $var, $var2}'));
51+
52+
Assert::contains(
53+
'$var ??= array_key_exists(\'var\', get_defined_vars()) ? null : 123 /* line 1 */;',
54+
$latte->compile('{default $var = 123}'),
55+
);
56+
57+
Assert::match(<<<'XX'
58+
%A%
59+
$var1 ??= array_key_exists('var1', get_defined_vars()) ? null : 123;
60+
$var2 ??= array_key_exists('var2', get_defined_vars()) ? null : 'nette framework' /* line 1 */;
61+
%A%
62+
XX, $latte->compile('{default $var1 = 123, $var2 = "nette framework"}'));
4863

4964
// types
50-
Assert::contains("extract(['var' => 123], EXTR_SKIP) /*", $latte->compile('{default null|int|string[] $var = 123}'));
51-
Assert::contains("extract(['var1' => 123, 'var2' => 'nette framework'], EXTR_SKIP) /*", $latte->compile('{default int|string[] $var1 = 123, ?class $var2 = "nette framework"}'));
65+
Assert::contains(
66+
'$var ??= array_key_exists(\'var\', get_defined_vars()) ? null : 123 /* line 1 */;',
67+
$latte->compile('{default null|int|string[] $var = 123}'),
68+
);
69+
70+
Assert::match(<<<'XX'
71+
%A%
72+
$var1 ??= array_key_exists('var1', get_defined_vars()) ? null : 123;
73+
$var2 ??= array_key_exists('var2', get_defined_vars()) ? null : 'nette framework' /* line 1 */;
74+
%A%
75+
XX, $latte->compile('{default int|string[] $var1 = 123, ?class $var2 = "nette framework"}'));
5276

5377
// errors
5478
Assert::exception(
@@ -62,7 +86,4 @@ test('{default ...}', function () use ($latte) {
6286
Latte\CompileException::class,
6387
'Unexpected end in {default} (on line 1 at column 30)',
6488
);
65-
66-
// preprocess
67-
Assert::contains("extract(['var1' => true ? 'a' : null], EXTR_SKIP) /*", $latte->compile('{default $var1 = true ? a}'));
6889
});

0 commit comments

Comments
 (0)