Deprecation: #104789 - renderStatic() for Fluid ViewHelpers

See forge#104789

Description

The usage of renderStatic() for Fluid ViewHelpers has been deprecated. Also, Fluid standalone traits \TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithContentArgumentAndRenderStatic and \TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic have been marked as deprecated.

Impact

Using one of the mentioned traits or renderStatic() in ViewHelpers logs a deprecation level error message in Fluid standalone v4. renderStatic() will no longer be called in Fluid standalone v5. renderStatic() and both traits continue to work without deprecation level error message in Fluid standalone v2.

Affected installations

Instances with custom ViewHelpers using any variant of renderStatic() are affected.

Migration

ViewHelpers should always use render() as their primary rendering method.

ViewHelpers using just renderStatic() without any trait or with the trait \CompileWithRenderStatic can be migrated by converting the static rendering method to a non-static method:

Before:

class MyViewHelper extends AbstractViewHelper
{
    use CompileWithRenderStatic;

    public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext): string
    {
        return $renderChildrenClosure();
    }
}
Copied!

After:

class MyViewHelper extends AbstractViewHelper
{
    public function render(): string
    {
        return $this->renderChildren();
    }
}
Copied!

ViewHelpers using \TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithContentArgumentAndRenderStatic can use the new contentArgumentName feature added with Fluid v2.15:

Before:

class MyViewHelper extends AbstractViewHelper
{
    use CompileWithContentArgumentAndRenderStatic;

    public function initializeArguments(): void
    {
        $this->registerArgument('value', 'string', 'a value');
    }

    public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext): string
    {
        return $renderChildrenClosure();
    }

    public function resolveContentArgumentName(): string
    {
        return 'value';
    }
}
Copied!

After:

class MyViewHelper extends AbstractViewHelper
{
    public function initializeArguments(): void
    {
        $this->registerArgument('value', 'string', 'a value');
    }

    public function render(): string
    {
        return $this->renderChildren();
    }

    public function getContentArgumentName(): string
    {
        return 'value';
    }
}
Copied!

Here is a basic recipe to perform this migration, preferably utilizing statical code analysis/replacement tools on your *ViewHelper.php files:

  • Find definitions of renderStatic
  • Rename method to render(), remove the arguments, remove static declaration
  • Within that method:

    • Replace $arguments with $this->arguments
    • Replace $renderingContext with $this->renderingContext
    • Replace $renderChildrenClosure() with $this->renderChildren()
    • Replace remaining $renderChildrenClosure usages with proper closure handling, like $this->renderChildren(...).
  • Replace resolveContentArgumentName( with getContentArgumentName(
  • Remove the mentioned definitions:

    • use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
    • use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
    • use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithContentArgumentAndRenderStatic;
    • use CompileWithRenderStatic; (class trait)
    • use CompileWithContentArgumentAndRenderStatic; (class trait)
  • (Optionally remove custom phpdoc annotations to the renderStatic parameters)
  • If you previously called ViewHelper's renderStatic methods in other places, you may utilize something like:

    $this->renderingContext->getViewHelperInvoker()->invoke(
        MyViewHelper::class,
        $arguments,
        $this->renderingContext,
        $this->renderChildren(...),
    );
    Copied!