The new version requires PHP 5.4 and uses Traits to further reduce code duplication. The Traits can be used in your own ViewHelpers as well. Read the article to learn how.
VHS 2.3.0 was released to TER earlier today. It features a lot of important bugfixes and a few breaking changes (mostly in rarely used ViewHelpers and most with safe deprecation). You can find the list of most important changes in our brand new change log (thanks to Viktor Livakivskyi for that one!):
The change log explains and links to explanations for each change - so the rest of this article will be dedicated to describing one of the technical changes that can be an advantage in your own extensions as well. The feature is ViewHelper Traits.
By using the Traits feature of PHP we can limit the amount of duplicated code, avoid static utilities (which are notoriously bad for testing) and remain within the class scope of ViewHelpers. The methods added by each Trait is then used by the actual ViewHelper class (basically, they are wrapper methods that perform repetitive tasks).
A few but vital Traits have been added in this first version that uses Traits. You implement each of the Traits exactly like you would a normal Trait (which basically means you add a use TraitClassName in the top inside your class' body). The Traits of VHS are all located in the FluidTYPO3\Vhs\Traits namespace - so when we refer for example to the TagViewHelperTrait, the full class name FluidTYPO3\Vhs\Traits\TagViewHelperTrait is implied.
This Trait currently contains a single method that allows an argument value to be retrieved from an argument, if provided, otherwise from the tag content (e.g. $this->renderChildren().). The first and main argument of your ViewHelper can have a default value of NULL and this method can then get the value from tag contents.
And can be implemented as seen in:
The Trait has yet to be implemented in other ViewHelpers but is fully compatible with current usages of optional main arguments that can come from the tag content.
This Trait is specialised for ViewHelpers that accept multiple input types that are turned into arrays which are manipulated. For example, almost every ViewHelper in v:iterator.* fits this description. When implemented, the Trait adds methods to quickly retrieve and convert an argument from its original type to an array (supporting things like CSV values, ObjectStorage, QueryResult, plain Iterators...). Also contained is a method that can safely merge arrays without warnings, by switching between array merging functions that have changed in TYPO3 itself.
There's a very simple example of the usage in v:iterator.pop:
As the name implies, this Trait is dedicated to supporting ViewHelpers that generate (X/HTML) tags. Implementing it will replace and extend the registerUniversalTagAttributes method on your ViewHelper, giving the ViewHelper more tag options (mostly HTML5-specific). Although the same can be achieved by using the additionalAttributes property of tag ViewHelpers, it helps accessibility to explicitly document these in the XSD itself.
The Trait also adds shortcut methods to render the main tag as well as additional child tags that the ViewHelper may generate, along with two key options: hideIfEmpty and forceClosingTag which do the same as the corresponding instructions on the TagBuilder - but allows the behavior to be controlled through the ViewHelper's public API, too.
There is a good, albeit fairly elaborate example of such usage in v:media.video which supports multiple video sources and creates multiple tags:
This Trait is perhaps the most useful of them all. It wraps the complete behavior of the conventional as argument. This is the argument that, when provided, makes the ViewHelper assign a new template variable, render the child content and return that result. And when not provided, makes the ViewHelper return the value of what would have been assigned as template variable otherwise.
You have probably already used several ViewHelpers from VHS which support this special as argument. In each and every one of those ViewHelpers the exact same behavior was repeated. It is this special behavior that was extracted into a Trait.
In addition to giving you an easy way to implement an as argument and behavior in your own ViewHelper, it also provides you with a method that will render the tag content with additional/modified variables - all while keeping backups of any possibly existing variables of the same name.
There is an easily digested example of the usage in v:page.rootLine:
Look for the extra registerAsArgument() call in initializeArguments and the wrapper method used in the render() method. Together, they make the behavior described above. No further logic required.
As you can see from the pull request on https://github.com/FluidTYPO3/vhs/pull/679 - which unfortunately raised some complexity/inheritance concerns but was very helpful in the creation of the new Traits - there is a particular ViewHelperTrait under consideration: one which allows a ViewHelper to use a slide and possibly slideCollect arguments and which is ideal to implement in ViewHelpers that for example resolve resources from a page but desires sliding (TYPO3 term for value inheritance) for the value or resource the ViewHelper retrieves. Possibly complemented by one or more Traits that specifically deal with FAL resources in a way that links a sliding and FAL capabilities.
If you know of a repetitive task related to ViewHelpers or see a use case for a new Trait which was not mentioned above, don't hesitate to discuss this with us! If VHS can benefit from a reusable Trait then everyone else will be able to use that Trait as well. The fewer different implementations there are of ViewHelper-related logic the more consistent the Fluid user experience will be as a whole.
We hope you enjoy the shiny new VHS version!
The FluidTYPO3 Team