Breaking: #108148 - Strict Types in Fluid ViewHelpers
See forge#108148
Description
With Fluid 5, various changes have been made to use stricter types in the context of ViewHelpers. This has consequences in three areas:
- Validation of arguments passed to ViewHelpers (see #1194 on GitHub)
- Passing
nullvalues to ViewHelpers that generate a HTML tag, also known as tag-based ViewHelpers (see #1233 on GitHub) - Required type declarations for custom ViewHelper implementations (see #1219 on GitHub)
Impact
ViewHelper argument validation
Fluid ViewHelpers now use stricter validation for their arguments by default.
The previous argument validation had numerous blind spots, which meant that
ViewHelper implementations couldn't really rely on the type requirements
specified in the ViewHelper's API. The new implementation performs a stricter
validation, which means that Fluid might reject arguments passed to ViewHelpers
that were previously considered valid (but which the ViewHelper in question
usually didn't know how to handle). The new implementation does however deal
with simple type conversions automatically, so that a ViewHelper that requires
a
string still can receive an
int as input.
For integrators, this change might reject certain ViewHelper arguments that were previously valid, but not covered by the ViewHelper's specified API.
For developers of custom ViewHelpers, this change allows to get rid of custom validation logic that was previously necessary due to Fluid's spotty validation.
Note that the Argument ViewHelper <f:argument>, which can be used to define an API for a template, is not affected by this change, as it already used the improved validation from the beginning.
Passing
null to tag-based ViewHelpers
Previously, Fluid's
Tag class, which is used to create HTML tags
in tag-based ViewHelpers, treated
null values as empty strings, leading
to an HTML tag with an empty HTML attribute. With Fluid 5,
null values lead
to the HTML attribute being omitted from the resulting HTML tag.
Example:
<f:form.textfield name="myTextBox" placeholder="{variableThatMightBeNull}" />
If the variable is
null (the PHP value), Fluid 4 and below generated
the following output:
<input type="text" name="myTextBox" placeholder="" />
Fluid 5 omits the
placeholder="":
<input type="text" name="myTextBox" />
In most cases, the impact of this change is non-existent. However, there are
some edge cases where this change is relevant. In TYPO3 Core, the
<f:
ViewHelper needed to be adjusted to always render the
alt attribute,
even if its internal value is
null, to match the previous output and
to produce valid HTML code.
TYPO3 Core ships with the following tag-based ViewHelpers:
<f:andmedia> <f:image> <f:andasset. css> <f:asset. script> <f:andform> <f:form.*> <f:, except forlink.*> <f:, which uses TypoScript internallylink. typolink> <f:be. link> <be:link.*> <be:thumbnail>
Type declarations in ViewHelper classes
Fluid's View now requires proper return types for all ViewHelper
methods. Thus, custom ViewHelper implementations need to be adjusted accordingly.
This is backwards-compatible to previous TYPO3 versions.
Affected installations
All installations need to verify that
- ViewHelpers aren't called with invalid argument types
nullvalues passed to tag-based ViewHelpers don't lead to unexpected HTML output- Custom ViewHelper implementations specify proper return types
Migration
Custom ViewHelper implementations need to make sure that they declare proper return types in the ViewHelper class to conform to Fluid 5's interface changes, for example:
initializemust specifyArguments () voidas return typerendershould specify a return type other than() void. Even though a specific type is recommended, it is not required, andmixedcan be used as well.
Note that properties in ViewHelper classes are not affected. The following example doesn't need to be adjusted, no types can/should be specified for these properties:
class MyViewHelper extends AbstractViewHelper
{
protected $escapeOutput = false;
protected $escapeChildren = false;
}
Unfortunately, the other changes concern runtime characteristics of Fluid templates, as they depend on the concrete values of variables that are passed to a template. Thus, it is not possible to scan for affected templates automatically.
However, the majority of issues these changes in Fluid might uncover in existing projects would have already been classified as a bug (in the template or extension code) before this Fluid change, such as passing an array to a ViewHelper that expects a string.