Project

General

Profile

Actions

Bug #94125

closed

Fluid f:render with argument "contentAs" does not work as expected

Added by Gabriel Kaufmann / Typoworx NewMedia almost 3 years ago. Updated 10 months ago.

Status:
Rejected
Priority:
Should have
Assignee:
-
Category:
Fluid
Start date:
2021-05-12
Due date:
% Done:

0%

Estimated time:
TYPO3 Version:
9
PHP Version:
Tags:
Complexity:
Is Regression:
Sprint Focus:

Description

Fluid f:render with argument "contentAs" does not work as expected, as the documentation implies a delegation of the rendered content is always possible to use pre-rendered content in the given variable to output the contents using variable.

But this seems to be broken, as the variable is only set by using another rendering call or a delegate-class. There is no implicit call to VariableContainer setting the variable without these cases.

As known from other ViewHelpers a given "as" argument will return the content/result into that variable instead of implicit rendering.

Usage cases
would be to render a given wrapping HTML only in case the f:render will return a non-empty result.

Code Reference
https://github.com/TYPO3/Fluid/blob/fb42c02cb286f99ac677679f03280b2ad2d2b54e/src/ViewHelpers/RenderViewHelper.php#L145

Feature should be interesting for TYPO3 v9.5 upwards


Files

RenderViewHelper.php.issue-94125.patch (1.06 KB) RenderViewHelper.php.issue-94125.patch Patch for TYPO3Fluid\Fluid\ViewHelpers\RenderViewHelper Gabriel Kaufmann / Typoworx NewMedia, 2021-05-12 12:46
Actions #1

Updated by Gabriel Kaufmann / Typoworx NewMedia almost 3 years ago

I've made the following xclass-override which resolves my proposal:

use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;

class RenderViewHelper extends \TYPO3Fluid\Fluid\ViewHelpers\RenderViewHelper
{
    /**
     * @return mixed
     */
    public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
    {
        $content = parent::renderStatic($arguments, $renderChildrenClosure, $renderingContext);

        if(!empty($arguments['contentAs']))
        {
            $renderingContext->getVariableProvider()->add($arguments['contentAs'], $content);

            if(($content = $renderChildrenClosure()) !== NULL)
            {
                $renderingContext->getVariableProvider()->remove($arguments['contentAs']);
            }
        }

        return $content;
    }
}

And the following patch should solve this in the original class.

This would allow such cases rendering optional wraps only if content exists:

<f:render section="Footer" contentAs="footerSection">
  <div class="footer--content">
     {footerSection -> f:format.raw()}
  </div>
</f:render>
Actions #2

Updated by Simon Praetorius 10 months ago

  • Status changed from New to Rejected

The documentation states:

If used, renders the child content and adds it as a template variable with this name for use in the partial/section

So contentAs provides the tag content of f:render as a variable to the partial/section that should be rendered, not the other way around. Your XCLASS would introduce an infinite loop if you use the variable inside the partial as documented: You provide a variable which depends on the rendered partial to the partial itself.

As the tag content is already used for this feature, it isn't possible to implement your alternative behavior without introducing a breaking change and losing the other functionality.

Actions #3

Updated by Gabriel Kaufmann / Typoworx NewMedia 10 months ago

Simon Praetorius wrote in #note-2:

Your XCLASS would introduce an infinite loop if you use the variable inside the partial as documented: You provide a
variable which depends on the rendered partial to the partial itself.

Thanks for pointing that out that edge-case. Well as far as I can remember it worked at least for my case. Which not means it was perfekt. I think it would be useful to figure out the children-closure already had been invoked. May be this could be implemented in RenderingContext as kind of method return true or false being able to prevent such case where multi-invoking RenderChildrenClose will end up in a mess.

Of course there may still be cases where such an override may not work depending on how the parent-class renderer behaves. But this solution would be better than changing the render-method interface f.e. making $renderChildrenClosure optional (?\Closure $renderChildrenClosure) breaking up too much for 3rd-party code having then broken implementations.

Actions

Also available in: Atom PDF