Fluid
Fluid copied to clipboard
Nested SwitchViewHelpers inside RenderViewHelpers does not break after rendering case
This is a copy of https://forge.typo3.org/issues/86425
Setup:
Create a Fluid Template containing a simple f:switch:
<f:switch expression="1">
<f:case value="1">
Case 1<br>
<f:render partial="Test" arguments="{val: 1}" />
</f:case>
<f:defaultCase>
Default 1<br>
</f:defaultCase>
</f:switch>
Create Partial Test:
<f:switch expression="{val}">
<f:case value="2">
Case 2
</f:case>
<f:defaultCase>
Default 2
<f:render partial="Test" arguments="{val: 2}" />
</f:defaultCase>
</f:switch>
Expected output: Case 1 Default 2 Case 2
Actual output: Default 1
This happens because in the ViewHelperVariableContainer the break
variable of the OriginalSwitchViewHelper is getting overridden.
I have tried the following permutations of ViewHelpers. Note: Render2 is another partial called Test2. No Errors: Switch -> Case -> Switch -> Case Switch -> Case -> Switch -> Default Switch -> Default -> Switch -> Case Switch -> Default -> Switch -> Default Switch -> Case -> Switch -> Case -> Switch -> Case Switch -> Case -> Switch -> Case -> Switch -> Default
Switch -> Case -> Render -> Switch -> Case Switch -> Case -> Render -> Switch -> Default Switch -> Default -> Render -> Switch -> Case Switch -> Default -> Render -> Switch -> Default
Switch -> Case -> Render -> Render2 -> Switch -> Case Switch -> Case -> Render -> Render2 -> Switch -> Default Switch -> Case -> Render -> Render -> Case Switch -> Case -> Render -> Render -> Default
Switch -> Case -> Render -> Switch -> Case -> Render -> Switch -> Case Switch -> Case -> Render -> Switch -> Case -> Render -> Switch -> Default Switch -> Case -> Render -> Switch -> Case -> Render2 -> Switch -> Case Switch -> Case -> Render -> Switch -> Case -> Render2 -> Switch -> Default Switch -> Case -> Render -> Switch -> Default -> Render2 -> Switch -> Case Switch -> Case -> Render -> Switch -> Default -> Render2 -> Switch -> Default
The following parmutations produce the error: Switch -> Case -> Render -> Switch -> Default -> Render -> Switch -> Case Switch -> Case -> Render -> Switch -> Default -> Render -> Switch -> Default
Now the funny part begins. This permutations produces the expected output: Switch -> Case -> Render -> If -> Then -> Switch -> Default -> Render -> If -> Else -> Switch -> Case Here is the fluid content for partial 'Test' for this permutation:
<f:if condition="{val} != 2">
<f:then>
<f:switch expression="{val}">
<f:case value="2">
Case 2
</f:case>
<f:defaultCase>
Default 2
<f:render partial="Test" arguments="{val: 2}" />
</f:defaultCase>
</f:switch>
</f:then>
<f:else>
<f:switch expression="1">
<f:case value="1">
Case 3
</f:case>
<f:defaultCase>Default 3</f:defaultCase>
</f:switch>
</f:else>
</f:if>
But the following variant prduces the error: Switch -> Case -> Render -> If -> Then -> Switch -> Default -> Render -> If -> Then -> Switch -> Case
<f:if condition="{val} != 2">
<f:then>
<f:switch expression="{val}">
<f:case value="3">
Case 2
</f:case>
<f:defaultCase>
Default 2
<f:render partial="Test" arguments="{val: 3}" />
</f:defaultCase>
</f:switch>
</f:then>
<f:else>
<f:switch expression="1">
<f:case value="1">
Case 3
</f:case>
<f:defaultCase>Default 3</f:defaultCase>
</f:switch>
</f:else>
</f:if>
It seems that it has something to do with equal instances of the switch ViewHelper. So I tried the following code inside a partial (the template only renders the partial with val=1, without any other code in it): Render -> Switch -> Case -> Render -> Switch -> Default -> Render -> Switch -> Case
<f:switch expression="{val}">
<f:case value="1">
Case 1
<f:render partial="Test" arguments="{val: 3}" />
</f:case>
<f:case value="2">
Case 2
</f:case>
<f:defaultCase>
Default 1
<f:render partial="Test" arguments="{val: 2}" />
</f:defaultCase>
</f:switch>
Expected output: Case 1 Default 1 Case 2 Actual output: Default 1 Case 2
Again, this permutations work: Render -> Switch -> Case -> Render-> Switch -> Default Render -> Switch -> Case -> Render -> Switch -> Case -> Render -> Switch -> Default
Adding another Rendering with switch/case to the non working example produces the expected output again: Render -> Switch -> Case -> Render -> Switch -> Default -> Render -> Switch -> Case -> Switch -> Case
<f:switch expression="{val}">
<f:case value="1">
Case 1
<f:render partial="Test" arguments="{val: 3}" />
</f:case>
<f:case value="2">
Case 2
<f:render partial="Test" arguments="{val: 4}" />
</f:case>
<f:case value="4">
Case 3
</f:case>
<f:defaultCase>
Default 1
<f:render partial="Test" arguments="{val: 2}" />
</f:defaultCase>
</f:switch>
Expected and actual output: Case 1 Default 1 Case 2 Case 3
can confirm on latest master 10.4
Me too. Could this be a duplicate of this report? https://github.com/TYPO3/Fluid/issues/428
in my case I get an exception saying
Fluid parse error in template partial_List/Cards-Item-TextOverlay_2dfc4d21e136809d3560113a54808794ca8636d8, line 10 at character 42. Error: You closed a templating tag which you never opened! (error code 1224485838). Template source chunk: </f:case>
My template file:
<f:case value="21">
<!-- TEMPLATE 21: Cards Text-Overlay ganz-spaltig -->
<div class="list-unstyled news-list-view news-template-21 bs4" id="news-container-{contentObjectData.uid}">
<div class="row">
<f:if condition="{settings.hidePagination}">
<f:then>
<f:for each="{news}" as="newsItem" iteration="iterator">
<div class="col-md-12">
<f:render partial="List/Cards-Item-TextOverlay"
arguments="{newsItem: newsItem,settings:settings,iterator:iterator}"/>
</div>
</f:for>
</f:then>
<f:else>
<n:widget.paginate objects="{news}" as="paginatedNews"
configuration="{settings.list.paginate}"
initial="{offset:settings.offset,limit:settings.limit,recordId:contentObjectData.uid}">
<f:for each="{paginatedNews}" as="newsItem" iteration="iterator">
<div class="col-md-12">
<f:render partial="List/Cards-Item-TextOverlay"
arguments="{newsItem: newsItem,settings:settings,iterator:iterator}"/>
</div>
</f:for>
</n:widget.paginate>
</f:else>
</f:if>
</div>
</div>
</f:case>
The part in the partial:
<f:switch expression=”{settings.templateLayout}”>
<f:case value=”21”>
<f:variable name="classValueA">mb-0</f:variable>
</f:case>
<f:case value=”25”>
<f:variable name="classValueA">mb-1</f:variable>
</f:case>
<f:defaultCase>mb-5</f:defaultCase>
</f:switch>