public function macroBlock(MacroNode $node, PhpWriter $writer)
{
$name = $node->tokenizer->fetchWord();
if ($node->name === 'block' && $name === FALSE) {
// anonymous block
return $node->modifiers === '' ? '' : 'ob_start(function () {})';
}
$node->data->name = $name = ltrim($name, '#');
if ($name == NULL) {
if ($node->name === 'define') {
throw new CompileException('Missing block name.');
}
} elseif (strpos($name, '$') !== FALSE) {
// dynamic block/snippet
if ($node->name === 'snippet') {
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/snippetArea.');
}
$parent->data->dynamic = TRUE;
$node->data->leave = TRUE;
$node->closingCode = "<?php \$this->global->snippetDriver->leave(); ?>";
$enterCode = '$this->global->snippetDriver->enter(' . $writer->formatWord($name) . ', "' . SnippetDriver::TYPE_DYNAMIC . '");';
if ($node->prefix) {
$node->attrCode = $writer->write("<?php echo ' id=\"' . htmlSpecialChars(\$this->global->snippetDriver->getHtmlId({$writer->formatWord($name)})) . '\"' ?>");
return $writer->write($enterCode);
}
$tag = trim($node->tokenizer->fetchWord(), '<>');
if ($tag) {
trigger_error('HTML tag specified in {snippet} is deprecated, use n:snippet.', E_USER_DEPRECATED);
}
$tag = $tag ? $tag : 'div';
$node->closingCode .= "\n</{$tag}>";
$this->checkExtraArgs($node);
return $writer->write("?>\n<{$tag} id=\"<?php echo htmlSpecialChars(\$this->global->snippetDriver->getHtmlId({$writer->formatWord($name)})) ?>\"><?php " . $enterCode);
} else {
$node->data->leave = TRUE;
$node->data->func = $this->generateMethodName($name);
$fname = $writer->formatWord($name);
$node->closingCode = '<?php ' . ($node->name === 'define' ? '' : "\$this->renderBlock({$fname}, get_defined_vars());") . ' ?>';
$blockType = var_export(implode($node->context), TRUE);
$this->checkExtraArgs($node);
return "\$this->checkBlockContentType({$blockType}, {$fname});" . "\$this->blockQueue[{$fname}][] = [\$this, '{$node->data->func}'];";
}
}
// 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 {$node->name} '{$name}'");
}
$extendsCheck = $this->namedBlocks ? '' : 'if ($this->getParentName()) return get_defined_vars();';
$this->namedBlocks[$name] = TRUE;
if (Helpers::removeFilter($node->modifiers, 'escape')) {
trigger_error('Macro ' . $node->getNotation() . ' provides auto-escaping, remove |escape.');
}
if (Helpers::startsWith($node->context[1], Latte\Compiler::CONTEXT_HTML_ATTRIBUTE)) {
$node->context[1] = '';
$node->modifiers .= '|escape';
} elseif ($node->modifiers) {
$node->modifiers .= '|escape';
}
$this->blockTypes[$name] = implode($node->context);
$include = '$this->renderBlock(%var, ' . ($node->name === 'snippet' || $node->name === 'snippetArea' ? '$this->params' : 'get_defined_vars()') . ($node->modifiers ? ', function ($s, $type) { $_fi = new LR\\FilterInfo($type); return %modifyContent($s); }' : '') . ')';
if ($node->name === 'snippet') {
if ($node->prefix) {
if (isset($node->htmlNode->macroAttrs['foreach'])) {
trigger_error('Combination of n:snippet with n:foreach is invalid, use n:inner-foreach.', E_USER_WARNING);
}
$node->attrCode = $writer->write('<?php echo \' id="\' . htmlSpecialChars($this->global->snippetDriver->getHtmlId(%var)) . \'"\' ?>', (string) substr($name, 1));
return $writer->write($include, $name);
}
$tag = trim($node->tokenizer->fetchWord(), '<>');
if ($tag) {
trigger_error('HTML tag specified in {snippet} is deprecated, use n:snippet.', E_USER_DEPRECATED);
}
$tag = $tag ? $tag : 'div';
$this->checkExtraArgs($node);
return $writer->write("?>\n<{$tag} id=\"<?php echo htmlSpecialChars(\$this->global->snippetDriver->getHtmlId(%var)) ?>\"><?php {$include} ?>\n</{$tag}><?php ", (string) substr($name, 1), $name);
} elseif ($node->name === 'define') {
$tokens = $node->tokenizer;
$args = [];
while ($tokens->isNext()) {
$args[] = $tokens->expectNextValue($tokens::T_VARIABLE);
if ($tokens->isNext()) {
$tokens->expectNextValue(',');
}
}
if ($args) {
$node->data->args = 'list(' . implode(', ', $args) . ') = $_args + [' . str_repeat('NULL, ', count($args)) . '];';
}
return $extendsCheck;
} else {
// block, snippetArea
$this->checkExtraArgs($node);
return $writer->write($extendsCheck . $include, $name);
}
}