Skip to content

Commit

Permalink
BlockMacros: {define} accepts named parameters [Closes #184][Closes #198
Browse files Browse the repository at this point in the history
]
  • Loading branch information
dg committed Nov 22, 2020
1 parent af2fe44 commit 712e2bc
Show file tree
Hide file tree
Showing 10 changed files with 259 additions and 9 deletions.
13 changes: 10 additions & 3 deletions src/Latte/Macros/BlockMacros.php
Expand Up @@ -84,7 +84,7 @@ public function finalize()
$compiler = $this->getCompiler();
foreach ($this->placeholders as $key => [$index, $blockName]) {
$block = $this->blocks[$index][$blockName] ?? $this->blocks[Template::LAYER_LOCAL][$blockName] ?? null;
$compiler->placeholders[$key] = $block
$compiler->placeholders[$key] = $block && !$block->hasArgs
? 'get_defined_vars()'
: '[]';
}
Expand Down Expand Up @@ -336,18 +336,25 @@ public function macroDefine(MacroNode $node, PhpWriter $writer): string
if ($tokens->nextToken($tokens::T_SYMBOL, '?', 'null', '\\')) { // type
$tokens->nextAll($tokens::T_SYMBOL, '\\', '|', '[', ']', 'null');
}
$args[] = $tokens->consumeValue($tokens::T_VARIABLE);
$arg = $tokens->consumeValue($tokens::T_VARIABLE);
$args[] = $writer->write(
'%raw = $__args[%var] ?? $__args[%var] ?? null;',
$arg,
count($args),
substr($arg, 1)
);
if ($tokens->isNext()) {
$tokens->consumeValue(',');
}
}

$extendsCheck = $this->blocks[Template::LAYER_TOP] || count($this->blocks) > 1 || $node->parentNode;
$block = $this->addBlock($node, $layer);
$block->hasArgs = (bool) $args;

$data->after = function () use ($node, $block, $args) {
$args = $args
? ('[' . implode(', ', $args) . '] = $__args + [' . str_repeat('null, ', count($args)) . '];')
? implode('', $args)
: null;
$this->extractMethod($node, $block, $args);
};
Expand Down
3 changes: 3 additions & 0 deletions src/Latte/Runtime/Block.php
Expand Up @@ -21,4 +21,7 @@ final class Block

/** @var callable[] used by Template */
public $functions = [];

/** @var bool used by BlockMacros */
public $hasArgs = false;
}
78 changes: 78 additions & 0 deletions tests/Latte/BlockMacros.define.args.phpt
Expand Up @@ -44,6 +44,7 @@ Assert::matchFile(
);


//typehints
$template = <<<'XX'
{define test $var1, ?stdClass $var2, \C\B|null $var3}
{/define}
Expand All @@ -55,3 +56,80 @@ Assert::matchFile(
__DIR__ . '/expected/BlockMacros.define.typehints.phtml',
$latte->compile($template)
);


// named arguments
$template = <<<'XX'
named arguments
{define test $var1, $var2, $var3}
Variables {$var1}, {$var2}, {$var3}
{/define}
a) {include test, 1, var1 => 2}
b) {include test, var2 => 1}
c) {include test, hello => 1}
d) {include test, var2 => 1, 2} // invalid
XX;

Assert::matchFile(
__DIR__ . '/expected/BlockMacros.define.args2.phtml',
$latte->compile($template)
);
Assert::matchFile(
__DIR__ . '/expected/BlockMacros.define.args2.html',
$latte->renderToString($template, ['var3' => 'outer'])
);


// named arguments (order dependent)
$template = <<<'XX'
named arguments order
a) {include test, 1, var1 => 2}
b) {include test, var2 => 1}
c) {include test, hello => 1}
{define test $var1, $var2, $var3}
Variables {$var1}, {$var2}, {$var3}
{/define}
XX;

Assert::matchFile(
__DIR__ . '/expected/BlockMacros.define.args3.phtml',
$latte->compile($template)
);


// named arguments (file dependent)
$latte->setLoader(new Latte\Loaders\StringLoader([
'main' => '
named arguments import
{import import.latte}
a) {include test, 1, var1 => 2}
b) {include test, var2 => 1}
c) {include test, hello => 1}',

'import.latte' => '
{define test $var1, $var2, $var3}
Variables {$var1}, {$var2}, {$var3}
{/define}',
]));

Assert::matchFile(
__DIR__ . '/expected/BlockMacros.define.args4.phtml',
$latte->compile('main')
);
Assert::matchFile(
__DIR__ . '/expected/BlockMacros.define.args4.html',
$latte->renderToString('main', ['var3' => 'outer'])
);
12 changes: 7 additions & 5 deletions tests/Latte/expected/BlockMacros.define.args1.phtml
Expand Up @@ -16,7 +16,7 @@ final class Template%a% extends Latte\Runtime\Template
}
echo '
a) ';
$this->renderBlock($__nm = 'test', [1] + get_defined_vars(), 'html');
$this->renderBlock($__nm = 'test', [1] + [], 'html');
echo '
Expand All @@ -27,19 +27,21 @@ b) ';
';
$var1 = 'outer';
echo 'c) ';
$this->renderBlock($__nm = 'test', get_defined_vars(), 'html');
$this->renderBlock($__nm = 'test', [], 'html');
echo '
d) ';
$this->renderBlock($__nm = 'test', [null] + get_defined_vars(), 'html');
$this->renderBlock($__nm = 'test', [null] + [], 'html');
return get_defined_vars();
}


public function blockTest(array $__args): void
{
extract($this->params);
[$var1, $var2, $var3] = $__args + [null, null, null, ];
$var1 = $__args[0] ?? $__args['var1'] ?? null;
$var2 = $__args[1] ?? $__args['var2'] ?? null;
$var3 = $__args[2] ?? $__args['var3'] ?? null;
echo ' Variables ';
echo LR\Filters::escapeHtmlText($var1) /* line 2 */;
echo ', ';
Expand All @@ -54,7 +56,7 @@ d) ';
{
extract($this->params);
extract($__args);
$this->renderBlock($__nm = 'test', ['hello'] + get_defined_vars(), 'html');
$this->renderBlock($__nm = 'test', ['hello'] + [], 'html');

}

Expand Down
14 changes: 14 additions & 0 deletions tests/Latte/expected/BlockMacros.define.args2.html
@@ -0,0 +1,14 @@
named arguments


a) Variables 1, ,


b) Variables , 1,


c) Variables , ,


d) Variables 2, 1,
// invalid
55 changes: 55 additions & 0 deletions tests/Latte/expected/BlockMacros.define.args2.phtml
@@ -0,0 +1,55 @@
<?php
%A%

final class Template%a% extends Latte\Runtime\Template
{
protected const BLOCKS = [
['test' => 'blockTest'],
];


public function main(): array
{
extract($this->params);
echo 'named arguments
';
if ($this->getParentName()) {
return get_defined_vars();
}
echo '
a) ';
$this->renderBlock($__nm = 'test', [1, 'var1' => 2] + [], 'html');
echo '
b) ';
$this->renderBlock($__nm = 'test', ['var2' => 1] + [], 'html');
echo '
c) ';
$this->renderBlock($__nm = 'test', ['hello' => 1] + [], 'html');
echo '
d) ';
$this->renderBlock($__nm = 'test', ['var2' => 1, 2] + [], 'html');
echo ' // invalid';
return get_defined_vars();
}


public function blockTest(array $__args): void
{
extract($this->params);
$var1 = $__args[0] ?? $__args['var1'] ?? null;
$var2 = $__args[1] ?? $__args['var2'] ?? null;
$var3 = $__args[2] ?? $__args['var3'] ?? null;
echo ' Variables ';
echo LR\Filters::escapeHtmlText($var1) /* line 4 */;
echo ', ';
echo LR\Filters::escapeHtmlText($var2) /* line 4 */;
echo ', ';
echo LR\Filters::escapeHtmlText($var3) /* line 4 */;
echo "\n";
}

}
51 changes: 51 additions & 0 deletions tests/Latte/expected/BlockMacros.define.args3.phtml
@@ -0,0 +1,51 @@
<?php
%A%

final class Template%a% extends Latte\Runtime\Template
{
protected const BLOCKS = [
['test' => 'blockTest'],
];


public function main(): array
{
extract($this->params);
echo 'named arguments order
a) ';
$this->renderBlock($__nm = 'test', [1, 'var1' => 2] + [], 'html');
echo '
b) ';
$this->renderBlock($__nm = 'test', ['var2' => 1] + [], 'html');
echo '
c) ';
$this->renderBlock($__nm = 'test', ['hello' => 1] + [], 'html');
echo '
';
if ($this->getParentName()) {
return get_defined_vars();
}
return get_defined_vars();
}


public function blockTest(array $__args): void
{
extract($this->params);
$var1 = $__args[0] ?? $__args['var1'] ?? null;
$var2 = $__args[1] ?? $__args['var2'] ?? null;
$var3 = $__args[2] ?? $__args['var3'] ?? null;
echo ' Variables ';
echo LR\Filters::escapeHtmlText($var1) /* line 10 */;
echo ', ';
echo LR\Filters::escapeHtmlText($var2) /* line 10 */;
echo ', ';
echo LR\Filters::escapeHtmlText($var3) /* line 10 */;
echo "\n";
}

}
11 changes: 11 additions & 0 deletions tests/Latte/expected/BlockMacros.define.args4.html
@@ -0,0 +1,11 @@

named arguments import


a) Variables 1, ,


b) Variables , 1,


c) Variables , ,
29 changes: 29 additions & 0 deletions tests/Latte/expected/BlockMacros.define.args4.phtml
@@ -0,0 +1,29 @@
<?php
%A%

final class Template%a% extends Latte\Runtime\Template
{

public function main(): array
{
extract($this->params);
echo '
named arguments import
';
$this->createTemplate("import.latte", $this->params, "import")->render();
echo '
a) ';
$this->renderBlock($__nm = 'test', [1, 'var1' => 2] + [], 'html');
echo '
b) ';
$this->renderBlock($__nm = 'test', ['var2' => 1] + [], 'html');
echo '
c) ';
$this->renderBlock($__nm = 'test', ['hello' => 1] + [], 'html');
return get_defined_vars();
}

}
2 changes: 1 addition & 1 deletion tests/Latte/expected/BlockMacros.define.typehints.phtml
Expand Up @@ -15,7 +15,7 @@ final class Template%a% extends Latte\Runtime\Template
return get_defined_vars();
}
echo "\n";
$this->renderBlock($__nm = 'test', [1] + get_defined_vars(), 'html');
$this->renderBlock($__nm = 'test', [1] + [], 'html');
return get_defined_vars();
}

Expand Down

0 comments on commit 712e2bc

Please sign in to comment.