Fluid icon indicating copy to clipboard operation
Fluid copied to clipboard

Nested SwitchViewHelpers inside RenderViewHelpers does not break after rendering case

Open georgringer opened this issue 4 years ago • 2 comments

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

georgringer avatar Mar 06 '20 21:03 georgringer

can confirm on latest master 10.4

georgringer avatar Mar 06 '20 21:03 georgringer

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>

hilburger avatar May 20 '21 19:05 hilburger