From 94a843429d025aa0a6ea5532ddbfa4df4bae97e4 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 12 Dec 2018 00:02:38 +0200 Subject: [PATCH] Added `{% render object layout: 'default' with { variable: true } %}` for Flex objects and collections --- CHANGELOG.md | 1 + .../Grav/Common/Twig/Node/TwigNodeRender.php | 73 +++++++++++++++++++ .../TokenParser/TwigTokenParserRender.php | 71 ++++++++++++++++++ system/src/Grav/Common/Twig/TwigExtension.php | 2 + 4 files changed, 147 insertions(+) create mode 100644 system/src/Grav/Common/Twig/Node/TwigNodeRender.php create mode 100644 system/src/Grav/Common/Twig/TokenParser/TwigTokenParserRender.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c30af6a0..feab885a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ * Added `Grav\Framework\Form\FormFlashFile` class which implements `UploadedFileInterface` from PSR-7 * Added `Grav\Framework\Filesystem\Filesystem` class with methods to manipulate stream URLs * Added new `$grav['filesystem']` service using an instance of the new `Filesystem` object + * Added `{% render object layout: 'default' with { variable: true } %}` for Flex objects and collections * Grav 1.6: Flex: Added support for custom object index classes (API compatibility break) 1. [](#improved) * Improved `Grav\Framework\File\Formatter` classes to have abstract parent class and some useful methods diff --git a/system/src/Grav/Common/Twig/Node/TwigNodeRender.php b/system/src/Grav/Common/Twig/Node/TwigNodeRender.php new file mode 100644 index 000000000..d94f95152 --- /dev/null +++ b/system/src/Grav/Common/Twig/Node/TwigNodeRender.php @@ -0,0 +1,73 @@ + $object, 'layout' => $layout, 'context' => $context], [], $lineno, $tag); + } + /** + * Compiles the node to PHP. + * + * @param \Twig_Compiler $compiler A Twig_Compiler instance + * @throws \LogicException + */ + public function compile(\Twig_Compiler $compiler) + { + $compiler->addDebugInfo($this); + $compiler->write('$object = ')->subcompile($this->getNode('object'))->raw(';' . PHP_EOL); + + $layout = $this->getNode('layout'); + if ($layout) { + $compiler->write('$layout = ')->subcompile($layout)->raw(';' . PHP_EOL); + } else { + $compiler->write('$layout = null;' . PHP_EOL); + } + + $context = $this->getNode('context'); + if ($context) { + $compiler->write('$attributes = ')->subcompile($context)->raw(';' . PHP_EOL); + } else { + $compiler->write('$attributes = null;' . PHP_EOL); + } + + $compiler + ->write('$html = $object->render($layout, $attributes ?? []);' . PHP_EOL) + ->write('$block = $context[\'block\'] ?? null;' . PHP_EOL) + ->write('if ($block instanceof \Grav\Framework\ContentBlock\ContentBlock && $html instanceof \Grav\Framework\ContentBlock\ContentBlock) {' . PHP_EOL) + ->indent() + ->write('$block->addBlock($html);' . PHP_EOL) + ->write('echo $html->getToken();' . PHP_EOL) + ->outdent() + ->write('} else {' . PHP_EOL) + ->indent() + ->write('echo (string)$html;' . PHP_EOL) + ->outdent() + ->write('}' . PHP_EOL) + ; + } +} diff --git a/system/src/Grav/Common/Twig/TokenParser/TwigTokenParserRender.php b/system/src/Grav/Common/Twig/TokenParser/TwigTokenParserRender.php new file mode 100644 index 000000000..fd5dc78db --- /dev/null +++ b/system/src/Grav/Common/Twig/TokenParser/TwigTokenParserRender.php @@ -0,0 +1,71 @@ +getLine(); + + [$object, $layout, $context] = $this->parseArguments($token); + + return new TwigNodeRender($object, $layout, $context, $lineno, $this->getTag()); + } + + /** + * @param \Twig_Token $token + * @return array + */ + protected function parseArguments(\Twig_Token $token) + { + $stream = $this->parser->getStream(); + + $object = $this->parser->getExpressionParser()->parseExpression(); + + $layout = null; + if ($stream->nextIf(\Twig_Token::NAME_TYPE, 'layout')) { + $stream->expect(\Twig_Token::PUNCTUATION_TYPE, ':'); + $layout = $this->parser->getExpressionParser()->parseExpression(); + } + + $context = null; + if ($stream->nextIf(\Twig_Token::NAME_TYPE, 'with')) { + $context = $this->parser->getExpressionParser()->parseExpression(); + } + + $stream->expect(\Twig_Token::BLOCK_END_TYPE); + + return [$object, $layout, $context]; + } + + /** + * Gets the tag name associated with this token parser. + * + * @return string The tag name + */ + public function getTag() + { + return 'render'; + } +} diff --git a/system/src/Grav/Common/Twig/TwigExtension.php b/system/src/Grav/Common/Twig/TwigExtension.php index fce13e7c2..f21c01863 100644 --- a/system/src/Grav/Common/Twig/TwigExtension.php +++ b/system/src/Grav/Common/Twig/TwigExtension.php @@ -14,6 +14,7 @@ use Grav\Common\Page\Collection; use Grav\Common\Page\Media; use Grav\Common\Scheduler\Cron; use Grav\Common\Security; +use Grav\Common\Twig\TokenParser\TwigTokenParserRender; use Grav\Common\Twig\TokenParser\TwigTokenParserScript; use Grav\Common\Twig\TokenParser\TwigTokenParserStyle; use Grav\Common\Twig\TokenParser\TwigTokenParserSwitch; @@ -178,6 +179,7 @@ class TwigExtension extends \Twig_Extension implements \Twig_Extension_GlobalsIn public function getTokenParsers() { return [ + new TwigTokenParserRender(), new TwigTokenParserThrow(), new TwigTokenParserTryCatch(), new TwigTokenParserScript(),