Skip to content

Commit

Permalink
Latte: implemented new macro {snippetArea} [Closes #1011]
Browse files Browse the repository at this point in the history
  • Loading branch information
hrach authored and dg committed Dec 10, 2013
1 parent 4e53248 commit 82721e2
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 13 deletions.
31 changes: 21 additions & 10 deletions Nette/Latte/Macros/UIMacros.php
Expand Up @@ -50,6 +50,7 @@ public static function install(Latte\Compiler $compiler)
$me->addMacro('#', array($me, 'macroBlock'), array($me, 'macroBlockEnd'));
$me->addMacro('define', array($me, 'macroBlock'), array($me, 'macroBlockEnd'));
$me->addMacro('snippet', array($me, 'macroBlock'), array($me, 'macroBlockEnd'));
$me->addMacro('snippetArea', array($me, 'macroBlock'), array($me, 'macroBlockEnd'));
$me->addMacro('ifset', array($me, 'macroIfset'), 'endif');

$me->addMacro('widget', array($me, 'macroControl')); // deprecated - use control
Expand Down Expand Up @@ -207,6 +208,7 @@ public function macroExtends(MacroNode $node, PhpWriter $writer)
/**
* {block [[#]name]}
* {snippet [name [,]] [tag]}
* {snippetArea [name]}
* {define [#]name}
*/
public function macroBlock(MacroNode $node, PhpWriter $writer)
Expand All @@ -219,15 +221,15 @@ public function macroBlock(MacroNode $node, PhpWriter $writer)

$node->data->name = $name = ltrim($name, '#');
if ($name == NULL) {
if ($node->name !== 'snippet') {
if ($node->name === 'define') {
throw new CompileException("Missing block name.");
}

} elseif (Strings::contains($name, '$')) { // dynamic block/snippet
if ($node->name === 'snippet') {
for ($parent = $node->parentNode; $parent && $parent->name !== 'snippet'; $parent = $parent->parentNode);
for ($parent = $node->parentNode; $parent && !($parent->name === 'snippet' || $parent->name === 'snippetArea'); $parent = $parent->parentNode);
if (!$parent) {
throw new CompileException("Dynamic snippets are allowed only inside static snippet.");
throw new CompileException("Dynamic snippets are allowed only inside static snippet/snippetArea.");
}
$parent->data->dynamic = TRUE;
$node->data->leave = TRUE;
Expand All @@ -253,22 +255,22 @@ public function macroBlock(MacroNode $node, PhpWriter $writer)
}
}

// static block/snippet
if ($node->name === 'snippet') {
// static snippet/snippetArea
if ($node->name === 'snippet' || $node->name === 'snippetArea') {
if ($node->prefix && isset($node->htmlNode->attrs['id'])) {
throw new CompileException('Cannot combine HTML attribute id with n:snippet.');
}
$node->data->name = $name = '_' . $name;
}

if (isset($this->namedBlocks[$name])) {
throw new CompileException("Cannot redeclare static block '$name'");
throw new CompileException("Cannot redeclare static {$node->name} '$name'");
}

$prolog = $this->namedBlocks ? '' : "if (\$_l->extends) { ob_end_clean(); return Nette\\Latte\\Macros\\CoreMacros::includeTemplate(\$_l->extends, get_defined_vars(), \$template)->render(); }\n";
$this->namedBlocks[$name] = TRUE;

$include = 'call_user_func(reset($_l->blocks[%var]), $_l, ' . ($node->name === 'snippet' ? '$template->getParameters()' : 'get_defined_vars()') . ')';
$include = 'call_user_func(reset($_l->blocks[%var]), $_l, ' . (($node->name === 'snippet' || $node->name === 'snippetArea') ? '$template->getParameters()' : 'get_defined_vars()') . ')';
if ($node->modifiers) {
$include = "ob_start(); $include; echo %modify(ob_get_clean())";
}
Expand All @@ -287,7 +289,7 @@ public function macroBlock(MacroNode $node, PhpWriter $writer)
} elseif ($node->name === 'define') {
return $prolog;

} else {
} else { // block, snippetArea
return $writer->write($prolog . $include, $name);
}
}
Expand All @@ -296,6 +298,7 @@ public function macroBlock(MacroNode $node, PhpWriter $writer)
/**
* {/block}
* {/snippet}
* {/snippetArea}
* {/define}
*/
public function macroBlockEnd(MacroNode $node, PhpWriter $writer)
Expand All @@ -310,9 +313,15 @@ public function macroBlockEnd(MacroNode $node, PhpWriter $writer)
}

if (empty($node->data->leave)) {
if ($node->name === 'snippetArea') {
$node->content = "<?php \$_control->snippetMode = TRUE; ?>{$node->content}<?php \$_control->snippetMode = FALSE; ?>";
}
if (!empty($node->data->dynamic)) {
$node->content .= '<?php if (isset($_dynSnippets)) return $_dynSnippets; ?>';
}
if ($node->name === 'snippetArea') {
$node->content .= '<?php return FALSE; ?>';
}
$this->namedBlocks[$node->data->name] = $tmp = rtrim(ltrim($node->content, "\n"), " \t");
$node->content = substr_replace($node->content, $node->openingCode . "\n", strspn($node->content, "\n"), strlen($tmp));
$node->openingCode = "<?php ?>";
Expand Down Expand Up @@ -475,8 +484,10 @@ public static function renderSnippets(Nette\Application\UI\Control $control, \st
$function = reset($function);
$snippets = $function($local, $params);
$payload->snippets[$id = $control->getSnippetId(substr($name, 1))] = ob_get_clean();
if ($snippets) {
$payload->snippets += $snippets;
if ($snippets !== NULL) { // pass FALSE from snippetArea
if ($snippets) {
$payload->snippets += $snippets;
}
unset($payload->snippets[$id]);
}
}
Expand Down
5 changes: 4 additions & 1 deletion tests/Nette/Latte/UIMacros.renderSnippets.phpt
Expand Up @@ -73,7 +73,10 @@ Assert::same(array(
'snippet--array-1' => 'Value 1',
'snippet--array-2' => 'Value 2',
'snippet--array-3' => 'Value 3',
'snippet--' => "<div id=\"snippet--includeSay\">Hello include snippet</div>\n",
'snippet--array2-1' => 'Value 1',
'snippet--array2-2' => 'Value 2',
'snippet--array2-3' => 'Value 3',
'snippet--includeSay' => 'Hello include snippet',
'snippet-multi-1-includeSay' => 'Hello',
),
), (array) $presenter->payload);
Expand Down
10 changes: 8 additions & 2 deletions tests/Nette/Latte/templates/snippet-include.latte
Expand Up @@ -10,6 +10,12 @@
{/foreach}
{/snippet}

{snippet}
{snippetArea array2}
{foreach [1, 2, 3] as $id}
{snippet array2-$id}Value {$id}{/snippet}
{/foreach}
{/snippetArea}

{snippetArea}
{include snippet-included.latte say => 'Hello include snippet'}
{/snippet}
{/snippetArea}

0 comments on commit 82721e2

Please sign in to comment.