Skip to content

Commit

Permalink
[FEATURE] Allow defining arguments for f:render with f:variable
Browse files Browse the repository at this point in the history
This patch allows you to define arguments that get passed to
f:render by using f:variable in the tag contents.

```xml
<f:render partial="Something">
   <f:variable name="arg1">Special value for arg1 variable</f:variable>
   <f:variable name="arg2">Special value for arg2 variable</f:variable>
</f:render>
```

Any argument specified with f:variable this way will override
the argument of the same name if it was passed in the “arguments”
array as well. The combined result will be used as variables for the
sub-rendering call.

References: #427
  • Loading branch information
NamelessCoder committed Feb 14, 2019
1 parent 60545b6 commit 30721a5
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 1 deletion.
11 changes: 11 additions & 0 deletions examples/Resources/Private/Singles/Variables.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@
}
}"/>

<!-- Passing arguments to a sections/partials using f:render in tag content -->
<f:render section="Tertiary">
<f:variable name="arg1">First argument</f:variable>
<f:variable name="arg2">Second argument</f:variable>
</f:render>

</f:section>

<f:section name="Secondary">
Expand All @@ -49,3 +55,8 @@
Received $array.xyz.foobar with value {array.xyz.foobar}
Received $myVariable with value {myVariable}
</f:section>

<f:section name="Tertiary">
Input variable "arg1" was: {arg1}
Input variable "arg2" was: {arg2}
</f:section>
48 changes: 48 additions & 0 deletions src/Core/ViewHelper/ViewHelperVariableContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* See LICENSE.txt that was shipped with this package.
*/

use TYPO3Fluid\Fluid\Core\Variables\VariableProviderInterface;
use TYPO3Fluid\Fluid\View\ViewInterface;

/**
Expand All @@ -29,6 +30,53 @@ class ViewHelperVariableContainer
*/
protected $view;

/**
* Push a new delegate variable container to a stack. Done before you start
* sub-rendering with a ViewHelper that requires a special container for
* variables which is capable of being used in multidepth stacks without
* overriding the last instance or last set of variables.
*
* @param string $viewHelperClassName
* @param VariableProviderInterface $variableProvider
*/
public function pushDelegateVariableContainer($viewHelperClassName, VariableProviderInterface $variableProvider)
{
if (!isset($this->objects[$viewHelperClassName]['delegateVariableProviderStack'])) {
$this->objects[$viewHelperClassName]['delegateVariableProviderStack'] = [];
}
$this->objects[$viewHelperClassName]['delegateVariableProviderStack'][] = $variableProvider;
}

/**
* Get the topmost delegate variable container that was previously pushed
* onto the stack by pushDelegateVariableContainer().
*
* @param string $viewHelperClassName
* @return VariableProviderInterface|null
*/
public function getTopmostDelegateVariableContainer($viewHelperClassName)
{
if (!isset($this->objects[$viewHelperClassName]['delegateVariableProviderStack'])) {
return null;
}
return end($this->objects[$viewHelperClassName]['delegateVariableProviderStack']);
}

/**
* Return and remove the topmost delegate variable container. Done after
* completion of a sub-rendering that uses a delegate variable provider.
*
* @param string $viewHelperClassName
* @return VariableProviderInterface|null
*/
public function popDelegateVariableContainer($viewHelperClassName)
{
if (isset($this->objects[$viewHelperClassName]['delegateVariableProviderStack'])) {
return array_pop($this->objects[$viewHelperClassName]['delegateVariableProviderStack']);
}
return null;
}

/**
* Add a variable to the Variable Container. Make sure that $viewHelperName is ALWAYS set
* to your fully qualified ViewHelper Class Name
Expand Down
14 changes: 14 additions & 0 deletions src/ViewHelpers/RenderViewHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,21 @@ public static function renderStatic(array $arguments, \Closure $renderChildrenCl
$delegate = $arguments['delegate'];
/** @var RenderableInterface $renderable */
$renderable = $arguments['renderable'];


// Prepare a delegate variable provider that will be possible to extract after rendering the child closure.
// Any variable defined therein gets used as argument and overrides any argument of the same name.
// Note: not using late static binding here is a conscious decision: if late static binding had been used
// then f:variable would not be able to reference this ViewHelper class' stack variable correctly.
$viewHelperVariableContainer = $renderingContext->getViewHelperVariableContainer();
$collector = $renderingContext->getVariableProvider()->getScopeCopy($variables);

$viewHelperVariableContainer->pushDelegateVariableContainer(self::class, $collector);

$tagContent = $renderChildrenClosure();

$variables = $viewHelperVariableContainer->popDelegateVariableContainer(self::class)->getAll();

if ($arguments['contentAs']) {
$variables[$arguments['contentAs']] = $tagContent;
}
Expand Down
3 changes: 3 additions & 0 deletions src/ViewHelpers/VariableViewHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ public static function renderStatic(
) {
$value = $renderChildrenClosure();
$renderingContext->getVariableProvider()->add($arguments['name'], $value);
if ($delegateVariableProvider = $renderingContext->getViewHelperVariableContainer()->getTopmostDelegateVariableContainer(RenderViewHelper::class)) {
$delegateVariableProvider->add($arguments['name'], $value);
}
}

}
4 changes: 3 additions & 1 deletion tests/Functional/ExamplesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,9 @@ public function getExampleScriptTestValues()
'Received $array.printf with formatted string Formatted string, value: formatted',
'Received $array.baz with value 42',
'Received $array.xyz.foobar with value Escaped sub-string',
'Received $myVariable with value Nice string'
'Received $myVariable with value Nice string',
'Input variable "arg1" was: First argument',
'Input variable "arg2" was: Second argument',
]
],
'example_variableprovider.php' => [
Expand Down

0 comments on commit 30721a5

Please sign in to comment.