Improved handling of enums
Currently, enums can be obtained by using the f:constant ViewHelper. It might make sense to offer alternative routes to make templates more readable and flexible.
Some ideas:
<!-- this would probably require some type of EnumAccessor object in-between -->
<f:variable name="fileTypeEnum" value="{f:enum(name: 'TYPO3\CMS\Core\Resource\FileType')}" />
<f:switch expression="{file.fileType}">
<f:case value="{fileTypeEnum.AUDIO}">audio</f:case>
<f:case value="{fileTypeEnum.VIDEO}">video</f:case>
<f:defaultCase>image</f:defaultCase>
</f:switch>
<f:enum name="TYPO3\CMS\Core\Resource\FileType" as="fileTypeEnum">
{fileTypeEnum.AUDIO}
</f:enum>
<!-- This would require Fluid syntax adjustments (regular expressions...) -->
{f:constant(name: 'TYPO3\CMS\Core\Resource\FileType::AUDIO').value}
{f:enum(name: 'TYPO3\CMS\Core\Resource\FileType').AUDIO.value}
<!-- This would probably work out-of-the-box, but doesn't cover a lot of cases -->
{f:enum(name: 'TYPO3\CMS\Core\Resource\FileType::VIDEO', property: 'value')}
Thanks for discussing this yesterday! :)
Two ideas:
- Maybe f:enum could work more like f:variable, so that the resulting object could also be re-used outside its child?
<f:enum name="TYPO3\CMS\Core\Resource\FileType" as="fileTypeEnum" />
<f:switch expression="{file.fileType}" >
<f:case value="{fileTypeEnum.AUDIO}">audio</f:case>
<f:case value="{fileTypeEnum.VIDEO}">video</f:case>
<f:defaultCase>image</f:defaultCase>
</f:switch>
- Maybe to shorthand this for more readiblity, we could have an 'f:enumSwitch' like:
<f:enum name="TYPO3\CMS\Core\Resource\FileType" as="fileTypeEnum" />
<f:enumSwitch enum="TYPO3\CMS\Core\Resource\FileType" match="{file.fileType}" >
<f:case value="AUDIO">audio</f:case>
<f:case value="VIDEO">video</f:case>
<f:defaultCase>image</f:defaultCase>
</f:switch>
(So this would no longer use an expression but a very specific match reference that must return the named Enum. Then then f:case inside enumSwitch maybe could match the value keys to the referenced ENUM (otherwise we would need an f:enumCase or so?)
Another idea: If the value in question is already an enum, this could be enough:
<f:switch enum="{file.fileType}">
<f:case value="AUDIO">audio</f:case>
<f:case value="VIDEO">video</f:case>
<f:defaultCase>image</f:defaultCase>
</f:switch>
Okay, as I already made a pull request to meet my needs in #1235, i want to outline my use case. I created an ImageOrient enum to provide the possible selections from the tt_content.imageorient field, like:
enum ImageOrient: int
{
case LeftSmall = 101;
case LeftMiddle = 102;
case LeftLarge = 103;
case RightSmall = 111;
case RightMiddle = 112;
case RightLarge = 113;
public function getCssClass(): string
{
return 'ce-textpic--imageorient-' . \str_replace('_', '-', GeneralUtility::camelCaseToLowerCaseUnderscored($this->name));
}
public function getMaxWidth(): int
{
return match ($this) {
ImageOrient::LeftSmall, ImageOrient::RightSmall => 450,
ImageOrient::LeftMiddle, ImageOrient::RightMiddle => 630,
ImageOrient::LeftLarge, ImageOrient::RightLarge => 890,
};
}
}
It may be debatable for this use case, if those frontend related methods should be in an enum, but it eases reduces if/else or switch cases in Fluid a lot.
In Fluid, I can now use the view helper (as implemented as a first draft in the mentioned PR):
<f:variable name="imageOrient"><f:enum.tryFrom
enum="\MyVendor\MyExtension\ImageOrient"
value="{data.imageorient}"
/></f:variable>
Now, I can access the enum name, value or methods:
{imageOrient.name} -> returns "LeftSmall"
{imageOrient.value} -> returns 101
{imageOrient.cssClass} -> returns "ce-textpic--imageorient-left-small"
The view helper implementation can be improved, of course, like:
<f:enum enum="\MyVendor\MyExtension\ImageOrient" value="{data.imageorient} as="imageOrient"/>
which would omit the separate <f:variable> usage and just use <f:enum> instead of <f:enum.tryFrom>. Personally, I think <f:enum.tryFrom> makes clear, what this vewhelper does and would opt for that name (to solve the given use case).
What do you think?
I did something similar in the past. However, I used TYPO3's records API, which allowed me to create the enum at an earlier step by using the RecordCreationEvent, which means that the Fluid template already receives the enum (as part of the record object), not the plain value.