Commit bc125626 authored by lauriii's avatar lauriii Committed by JohnAlbin

Issue #2821512 by lauriii, Fabianx, joelpittet: Render array generator

parent 7e783bcd
......@@ -4,3 +4,9 @@ services:
arguments: ['@app.root', '@module_handler', '@theme_handler']
tags:
- { name: twig.loader, priority: 200 }
components.twig.extension:
class: Drupal\components\Template\TwigExtension
arguments: ['@renderer']
tags:
- { name: twig.extension, priority: 150 }
<?php
namespace Drupal\components\Template;
use Drupal\Core\Render\RendererInterface;
/**
* A class providing components's Twig extensions.
*/
class TwigExtension extends \Twig_Extension {
/**
* The renderer.
*
* @var \Drupal\Core\Render\RendererInterface
*/
protected $renderer;
/**
* TwigExtension constructor.
*
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer.
*/
public function __construct(RendererInterface $renderer) {
$this->renderer = $renderer;
}
/**
* {@inheritdoc}
*/
public function getTokenParsers() {
return [
new TwigThemeTokenParser(),
];
}
/**
* {@inheritdoc}
*/
public function getFunctions() {
return [
new \Twig_SimpleFunction('theme', [$this, 'theme']),
];
}
/**
* {@inheritdoc}
*/
public function getName() {
return 'components';
}
/**
* Callback for theme function in Twig.
*
* @param string $theme
* The theme definition key.
* @param array $variables
* The variables passed for rendering.
*
* @return \Drupal\Component\Render\MarkupInterface
* The renderer markup.
*/
public function theme($theme, array $variables) {
$render_array = ['#theme' => $theme];
foreach ($variables as $key => $variable) {
$render_array['#' . $key] = $variable;
}
return $this->render($render_array);
}
/**
* Renders a render array.
*
* @param array $render_array
* The render array.
*
* @return \Drupal\Component\Render\MarkupInterface
* The renderer markup.
*/
protected function render(array $render_array) {
// This is a render array, with special simple cases already handled.
// Early return if this element was pre-rendered (no need to re-render).
if (isset($render_array['#printed']) && $render_array['#printed'] == TRUE && isset($render_array['#markup']) && strlen($render_array['#markup']) > 0) {
return $render_array['#markup'];
}
$render_array['#printed'] = FALSE;
return $this->renderer->render($render_array);
}
}
<?php
namespace Drupal\components\Template;
/**
* Represents a call to theme() as a Twig node.
*/
class TwigNodeTheme extends \Twig_Node implements \Twig_NodeOutputInterface {
public function __construct(\Twig_Node_Expression $theme, \Twig_Node_Expression $variables = NULL, $lineno, $tag = NULL) {
parent::__construct(
['theme' => $theme, 'variables' => $variables],
[],
$lineno,
$tag
);
}
/**
* Compiles the template.
*
* @param \Twig_Compiler $compiler
* The compiler.
*/
public function compile(\Twig_Compiler $compiler) {
$expression = new \Twig_Node_Expression_Function(
'theme',
new \Twig_Node([$this->getNode('theme'), $this->getNode('variables')]),
$this->getLine()
);
$compiler->addDebugInfo($this)
->subcompile(new \Twig_Node_Print($expression, $this->getLine()));
}
}
<?php
namespace Drupal\components\Template;
/**
* Generates a render array and renders that.
*
* @code
* {%
* theme 'item_list' with {
* items: [],
* }
* %}
* @endcode
*/
class TwigThemeTokenParser extends \Twig_TokenParser {
/**
* {@inheritdoc}
*/
public function parse(\Twig_Token $token) {
$expr = $this->parser->getExpressionParser()->parseExpression();
return new TwigNodeTheme($expr, $this->parseArguments(), $token->getLine(), $this->getTag());
}
/**
* Parses the arguments.
*
* @return \Twig_Node_Expression
* A node expression containing the variables list.
*/
protected function parseArguments() {
$stream = $this->parser->getStream();
$variables = NULL;
if ($stream->nextIf(\Twig_Token::NAME_TYPE, 'with')) {
$variables = $this->parser->getExpressionParser()->parseExpression();
}
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
return $variables;
}
/**
* {@inheritdoc}
*/
public function getTag() {
return 'theme';
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment