[TASK] Import forward-compatible Fluid compiling Traits 76/50676/4
authorClaus Due <claus@namelesscoder.net>
Wed, 16 Nov 2016 13:47:11 +0000 (14:47 +0100)
committerChristian Kuhn <lolli@schwarzbu.ch>
Fri, 18 Nov 2016 19:01:09 +0000 (20:01 +0100)
This change will allow third party ViewHelpers to
adopt the traits and benefit from
the same compiling support in TYPO3 7.6 as on v8.5+.

Change-Id: I6ac8eb59b4fde37a472d2a1e113fb7c0ec4b71a9
Resolves: #78718
Releases: 7.6
Reviewed-on: https://review.typo3.org/50676
Reviewed-by: Helmut Hummel <typo3@helhum.io>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
composer.json
composer.lock
typo3/sysext/fluid/Resources/PHP/Traits/CompileWithContentArgumentAndRenderStatic.php [new file with mode: 0644]
typo3/sysext/fluid/Resources/PHP/Traits/CompileWithRenderStatic.php [new file with mode: 0644]
typo3/sysext/fluid/composer.json

index 5513c35..de0dac4 100644 (file)
                        "TYPO3\\CMS\\Workspaces\\": "typo3/sysext/workspaces/Classes/"
                },
                "classmap": [
-                       "typo3/sysext/core/Resources/PHP/"
+                       "typo3/sysext/core/Resources/PHP/",
+                       "typo3/sysext/fluid/Resources/PHP/"
                ],
                "files": [
                        "typo3/sysext/core/Resources/PHP/GlobalDebugFunctions.php"
index 4ee4cf9..f5fe1b6 100644 (file)
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "hash": "eb6e28f7d80103f5c919b68e238e5c21",
+    "hash": "eefa09bcf4e772af6f855ca0f2df0510",
     "content-hash": "26df927d26dda8dbb6aa07ec809a53a9",
     "packages": [
         {
diff --git a/typo3/sysext/fluid/Resources/PHP/Traits/CompileWithContentArgumentAndRenderStatic.php b/typo3/sysext/fluid/Resources/PHP/Traits/CompileWithContentArgumentAndRenderStatic.php
new file mode 100644 (file)
index 0000000..b585012
--- /dev/null
@@ -0,0 +1,129 @@
+<?php
+namespace TYPO3Fluid\Fluid\Core\ViewHelper\Traits;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Fluid\Core\Compiler\TemplateCompiler;
+use TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\AbstractNode;
+use TYPO3\CMS\Fluid\Core\ViewHelper\Exception;
+
+/**
+ * Trait CompilableWithContentArgumentAndRenderStatic
+ *
+ * Provides default methods for rendering and compiling
+ * any ViewHelper that conforms to the `renderStatic`
+ * method pattern but has the added common use case that
+ * an argument value must be checked and used instead of
+ * the normal render children closure, if that named
+ * argument is specified and not empty.
+ */
+trait CompileWithContentArgumentAndRenderStatic {
+
+    /**
+     * Name of variable that contains the value to use
+     * instead of render children closure, if specified.
+     * If no name is provided here, the first variable
+     * registered in `initializeArguments` of the ViewHelper
+     * will be used.
+     *
+     * Note: it is significantly better practice to define
+     * this property in your ViewHelper class and so fix it
+     * to one particular argument instead of resolving,
+     * especially when your ViewHelper is called multiple
+     * times within an uncompiled template!
+     *
+     * @var string
+     */
+    protected $contentArgumentName;
+
+    /**
+     * @return \Closure
+     */
+    abstract protected function buildRenderChildrenClosure();
+
+    /**
+     * @return mixed
+     */
+    abstract public function prepareArguments();
+
+    /**
+     * Default render method to render ViewHelper with
+     * first defined optional argument as content.
+     *
+     * @return string Rendered string
+     * @api
+     */
+    public function render() {
+        $argumentName = $this->resolveContentArgumentName();
+        $arguments = $this->arguments;
+        if (!empty($argumentName) && isset($arguments[$argumentName])) {
+            $renderChildrenClosure = function() use ($arguments, $argumentName) { return $arguments[$argumentName]; };
+        } else {
+            $renderChildrenClosure = $this->buildRenderChildrenClosure();
+        }
+        return static::renderStatic(
+            $arguments,
+            $renderChildrenClosure,
+            $this->renderingContext
+        );
+    }
+
+    /**
+     * @param string $argumentsName
+     * @param string $closureName
+     * @param string $initializationPhpCode
+     * @param AbstractNode $node
+     * @param TemplateCompiler $compiler
+     * @return string
+     */
+    public function compile(
+        $argumentsName,
+        $closureName,
+        &$initializationPhpCode,
+        AbstractNode $node,
+        TemplateCompiler $compiler
+    ) {
+        $contentArgumentName = $this->resolveContentArgumentName();
+        return sprintf(
+            '%s::renderStatic(%s, isset(%s[\'%s\']) ? function() use (%s); return %s[\'%s\']; } : %s, $renderingContext)',
+            static::class,
+            $argumentsName,
+            $argumentsName,
+            $contentArgumentName,
+            $argumentsName,
+            $argumentsName,
+            $contentArgumentName,
+            $closureName
+        );
+    }
+
+    /**
+     * @return string
+     * @throws Exception
+     */
+    protected function resolveContentArgumentName() {
+        if (empty($this->contentArgumentName)) {
+            foreach ($this->prepareArguments() as $registeredArgument) {
+                if (!$registeredArgument->isRequired()) {
+                    return $registeredArgument->getName();
+                }
+            }
+            throw new Exception(
+                'Attempting to compile %s failed. Chosen compile method requires that ViewHelper has ' .
+                'at least one registered and optional argument'
+            );
+        }
+        return $this->contentArgumentName;
+    }
+}
diff --git a/typo3/sysext/fluid/Resources/PHP/Traits/CompileWithRenderStatic.php b/typo3/sysext/fluid/Resources/PHP/Traits/CompileWithRenderStatic.php
new file mode 100644 (file)
index 0000000..7877a14
--- /dev/null
@@ -0,0 +1,72 @@
+<?php
+namespace TYPO3Fluid\Fluid\Core\ViewHelper\Traits;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Fluid\Core\Compiler\TemplateCompiler;
+use TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\AbstractNode;
+
+/**
+ * Trait CompilableWithRenderStatic
+ *
+ * Provides default methods for rendering and compiling
+ * any ViewHelper that conforms to the `renderStatic`
+ * method pattern.
+ */
+trait CompileWithRenderStatic
+{
+
+    /**
+     * @return \Closure
+     */
+    abstract function buildRenderChildrenClosure();
+
+    /**
+     * Default render method - simply calls renderStatic() with a
+     * prepared set of arguments.
+     *
+     * @return string Rendered string
+     * @api
+     */
+    public function render() {
+        return static::renderStatic(
+            $this->arguments,
+            $this->buildRenderChildrenClosure(),
+            $this->renderingContext
+        );
+    }
+
+    /**
+     * @param string $argumentsName
+     * @param string $closureName
+     * @param string $initializationPhpCode
+     * @param AbstractNode $node
+     * @param TemplateCompiler $compiler
+     * @return string
+     */
+    public function compile(
+        $argumentsName,
+        $closureName,
+        &$initializationPhpCode,
+        AbstractNode $node,
+        TemplateCompiler $compiler
+    ) {
+        return sprintf(
+            '%s::renderStatic(%s, %s, $renderingContext)',
+            static::class,
+            $argumentsName,
+            $closureName
+        );
+    }
+}
index 88af6dc..d4e6151 100644 (file)
@@ -23,7 +23,8 @@
        "autoload": {
                "psr-4": {
                        "TYPO3\\CMS\\Fluid\\": "Classes/"
-               }
+               },
+               "classmap": ["Resources/PHP/"]
        },
        "autoload-dev": {
                "psr-4": {