From 3ed0f3c6a804a8e18fdc888e4350eed791f4b93e Mon Sep 17 00:00:00 2001 From: "Frederic G. MARAND" Date: Sat, 11 Apr 2015 22:32:23 +0200 Subject: [PATCH] Issue #2464045: Moved twig_render_var() to TwigExtension and inline render(). --- core/lib/Drupal/Core/Template/TwigExtension.php | 70 +++++++++++++++++++- core/lib/Drupal/Core/Template/TwigNodeTrans.php | 2 +- core/lib/Drupal/Core/Template/TwigNodeVisitor.php | 4 +- .../Drupal/Tests/Core/Theme/TwigEngineTest.php | 2 +- core/themes/engines/twig/twig.engine | 59 ----------------- 5 files changed, 71 insertions(+), 66 deletions(-) diff --git a/core/lib/Drupal/Core/Template/TwigExtension.php b/core/lib/Drupal/Core/Template/TwigExtension.php index a2b1f59..f64c672 100644 --- a/core/lib/Drupal/Core/Template/TwigExtension.php +++ b/core/lib/Drupal/Core/Template/TwigExtension.php @@ -58,6 +58,70 @@ public function __construct(RendererInterface $renderer) { } /** + * Wrapper around render() for twig printed output. + * + * If an object is passed that has no __toString method an exception is thrown; + * other objects are casted to string. However in the case that the object is an + * instance of a Twig_Markup object it is returned directly to support auto + * escaping. + * + * If an array is passed it is rendered via render() and scalar values are + * returned directly. + * + * @param mixed $arg + * String, Object or Render Array. + * + * @return mixed + * The rendered output or an Twig_Markup object. + * + * @see render + * @see TwigNodeVisitor + */ + public function renderVar($arg) { + // Check for a numeric zero int or float. + if ($arg === 0 || $arg === 0.0) { + return 0; + } + + // Return early for NULL and also true for empty arrays. + if ($arg == NULL) { + return NULL; + } + + // Optimize for strings as it is likely they come from the escape filter. + if (is_string($arg)) { + return $arg; + } + + if (is_scalar($arg)) { + return $arg; + } + + if (is_object($arg)) { + if (method_exists($arg, '__toString')) { + return (string) $arg; + } + // You can't throw exceptions in the magic PHP __toString methods, see + // http://php.net/manual/en/language.oop5.magic.php#object.tostring so + // we also support a toString method. + elseif (method_exists($arg, 'toString')) { + return $arg->toString(); + } + else { + throw new Exception(t('Object of type "@class" cannot be printed.', array('@class' => get_class($arg)))); + } + } + + // 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($arg['#printed']) && $arg['#printed'] == TRUE && isset($arg['#markup']) && strlen($arg['#markup']) > 0) { + return $arg['#markup']; + } + show($arg); + return $this->renderer->render($arg); + } + + /** * Sets the URL generator. * * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator @@ -89,7 +153,7 @@ public function setLinkGenerator(LinkGeneratorInterface $link_generator) { public function getFunctions() { return array( // This function will receive a renderable array, if an array is detected. - new \Twig_SimpleFunction('render_var', 'twig_render_var'), + new \Twig_SimpleFunction('render_var', array($this, 'renderVar')), // The url and path function are defined in close parallel to those found // in \Symfony\Bridge\Twig\Extension\RoutingExtension new \Twig_SimpleFunction('url', array($this, 'getUrl'), array('is_safe_callback' => array($this, 'isUrlGenerationSafe'))), @@ -132,7 +196,7 @@ public function getFilters() { new \Twig_SimpleFilter('clean_class', '\Drupal\Component\Utility\Html::getClass'), new \Twig_SimpleFilter('clean_id', '\Drupal\Component\Utility\Html::getId'), // This filter will render a renderable array to use the string results. - new \Twig_SimpleFilter('render', 'twig_render_var'), + new \Twig_SimpleFilter('render', array($this, 'renderVar')), ); } @@ -141,7 +205,7 @@ public function getFilters() { */ public function getNodeVisitors() { // The node visitor is needed to wrap all variables with - // render_var -> twig_render_var() function. + // render_var -> TwigExtension->renderVar() function. return array( new TwigNodeVisitor(), ); diff --git a/core/lib/Drupal/Core/Template/TwigNodeTrans.php b/core/lib/Drupal/Core/Template/TwigNodeTrans.php index c4fd4ef..1bacb9e 100644 --- a/core/lib/Drupal/Core/Template/TwigNodeTrans.php +++ b/core/lib/Drupal/Core/Template/TwigNodeTrans.php @@ -136,7 +136,7 @@ protected function compileString(\Twig_NodeInterface $body) { $args = $n; - // Support twig_render_var function in chain. + // Support TwigExtension->renderVar() function in chain. if ($args instanceof \Twig_Node_Expression_Function) { $args = $n->getNode('arguments')->getNode(0); } diff --git a/core/lib/Drupal/Core/Template/TwigNodeVisitor.php b/core/lib/Drupal/Core/Template/TwigNodeVisitor.php index 4915c16..a08ec2d 100644 --- a/core/lib/Drupal/Core/Template/TwigNodeVisitor.php +++ b/core/lib/Drupal/Core/Template/TwigNodeVisitor.php @@ -11,7 +11,7 @@ * Provides a Twig_NodeVisitor to change the generated parse-tree. * * This is used to ensure that everything printed is wrapped via the - * twig_render_var() function in order to just write {{ content }} + * TwigExtension->renderVar() function in order to just write {{ content }} * in templates instead of having to write {{ render_var(content) }}. * * @see twig_render @@ -29,7 +29,7 @@ function enterNode(\Twig_NodeInterface $node, \Twig_Environment $env) { * {@inheritdoc} */ function leaveNode(\Twig_NodeInterface $node, \Twig_Environment $env) { - // We use this to inject a call to render_var -> twig_render_var() + // We use this to inject a call to render_var -> TwigExtension->renderVar() // before anything is printed. if ($node instanceof \Twig_Node_Print) { if (!empty($this->skipRenderVarFunction)) { diff --git a/core/tests/Drupal/Tests/Core/Theme/TwigEngineTest.php b/core/tests/Drupal/Tests/Core/Theme/TwigEngineTest.php index baf45c1..5fd176d 100644 --- a/core/tests/Drupal/Tests/Core/Theme/TwigEngineTest.php +++ b/core/tests/Drupal/Tests/Core/Theme/TwigEngineTest.php @@ -37,7 +37,7 @@ protected function setUp() { } /** - * Tests output of integer and double 0 values of twig_render_var(). + * Tests output of integer and double 0 values of TwigExtension->renderVar(). * * @see https://www.drupal.org/node/2417733 */ diff --git a/core/themes/engines/twig/twig.engine b/core/themes/engines/twig/twig.engine index 324203e..b828e72 100644 --- a/core/themes/engines/twig/twig.engine +++ b/core/themes/engines/twig/twig.engine @@ -107,65 +107,6 @@ function twig_render_template($template_file, array $variables) { } /** - * Wrapper around render() for twig printed output. - * - * If an object is passed that has no __toString method an exception is thrown; - * other objects are casted to string. However in the case that the object is an - * instance of a Twig_Markup object it is returned directly to support auto - * escaping. - * - * If an array is passed it is rendered via render() and scalar values are - * returned directly. - * - * @param mixed $arg - * String, Object or Render Array. - * - * @return mixed - * The rendered output or an Twig_Markup object. - * - * @see render - * @see TwigNodeVisitor - */ -function twig_render_var($arg) { - // Check for a numeric zero int or float. - if ($arg === 0 || $arg === 0.0) { - return 0; - } - - // Return early for NULL and also true for empty arrays. - if ($arg == NULL) { - return NULL; - } - - // Optimize for strings as it is likely they come from the escape filter. - if (is_string($arg)) { - return $arg; - } - - if (is_scalar($arg)) { - return $arg; - } - - if (is_object($arg)) { - if (method_exists($arg, '__toString')) { - return (string) $arg; - } - // You can't throw exceptions in the magic PHP __toString methods, see - // http://php.net/manual/en/language.oop5.magic.php#object.tostring so - // we also support a toString method. - elseif (method_exists($arg, 'toString')) { - return $arg->toString(); - } - else { - throw new Exception(t('Object of type "@class" cannot be printed.', array('@class' => get_class($arg)))); - } - } - - // This is a normal render array. - return render($arg); -} - -/** * Removes child elements from a copy of the original array. * * Creates a copy of the renderable array and removes child elements by key -- 1.7.9.5