Bug #86837

TypoScript Condition: tree.* broken on cached pages

Added by Philipp Seiler about 1 year ago. Updated about 1 month ago.

Status:
Closed
Priority:
Must have
Assignee:
-
Category:
Caching
Target version:
-
Start date:
2018-11-02
Due date:
% Done:

0%

TYPO3 Version:
9
PHP Version:
Tags:
Complexity:
Is Regression:
Sprint Focus:

Description

Implement a basic TypoScript condition for swapping out page content for a certain page ID:

page.10 >
page.10 = TEXT
page.10.value = foo

[3 in tree.rootLineIds]
page.10 >
page.10 = TEXT
page.10.value = bar
[END]

Clear all caches.

Call page with ID 3 results in "bar" as output. OK.
If I log the \TYPO3\CMS\Frontend\Configuration\TypoScript\ConditionMatching\ConditionMatcher constructor, the class member $tree->rootLineIds contains the rootline of the current page, just as expected (e.g.):

Array
(
    [0] => 1
    [1] => 3
)

Keep reloading the page, output stays "bar", everything OK.

Call a different page, e.g. ID 105. Results in "foo" as output. OK.
$tree->rootLineIds from the ConditionMatcher class logs as follows:

Array
(
    [0] => 1
    [1] => 2
    [2] => 105
)

Keep reloading the page, output stays "foo". BUT: $tree->rootLineIds log now shows an empty array.

Call page with ID 3 again. Output is now "foo", $tree->rootLineIds stays empty.
Condition doesn't match anymore!

Probably something wrong with cacheing.

m1.png View (819 KB) Dmitry Dulepov, 2019-05-06 13:16

m2.png View (824 KB) Dmitry Dulepov, 2019-05-06 13:18


Related issues

Related to TYPO3 Core - Bug #86807: Some symfony expression condition won't work reliable (in TypoScript) Closed 2018-10-30
Duplicates TYPO3 Core - Bug #88374: [xxx in tree.rootLineIds] TypoScript condition causes page cache regeneration on each request Resolved 2019-05-16

History

#1 Updated by Georg Ringer about 1 year ago

  • Related to Bug #86807: Some symfony expression condition won't work reliable (in TypoScript) added

#2 Updated by Georg Ringer about 1 year ago

  • Related to Bug #86763: Backend Layout Slide not working in FLUIDTEMPLATE Variables after Upgrade to 9.5.0 added

#3 Updated by Georg Ringer about 1 year ago

  • Related to deleted (Bug #86763: Backend Layout Slide not working in FLUIDTEMPLATE Variables after Upgrade to 9.5.0)

#4 Updated by Frank Naegler about 1 year ago

  • Status changed from New to Needs Feedback

I have tried to reproduce this issue, but with and without cache it works for me very well.
Can you please check the current master version and maybe provide more information about your setup?

#5 Updated by Philipp Seiler about 1 year ago

No, still doesn't work.

I found out, that as soon as I activate an applicationContext-condition, the bug appears:

[applicationContext == 'Development']
anything
[END]

Also EXT:news extension includes a condition, that triggers the bug as well:

[globalVar = LIT:0<{$styles.content.textmedia.maxW}]
    plugin.tx_news.settings.detail.media.image.lightbox {
        enabled = {$styles.content.textmedia.linkWrap.lightboxEnabled}
        class = {$styles.content.textmedia.linkWrap.lightboxCssClass}
        width = {$styles.content.textmedia.linkWrap.width}
        height = {$styles.content.textmedia.linkWrap.height}
    }
[global]

#6 Updated by Frank Naegler about 1 year ago

that is very wiered... also with the additional conditions I can't reproduce the problem. :(
can you provide more info? maybe the complete TypoScript?

Is the feature toggle "TypoScript.strictSyntax" enabled or disabled?

#7 Updated by Philipp Seiler about 1 year ago

Latest typo3-9 master branch. Local, pretty much bare development system, nothing is included at the root template.

Manually set root template setup:

page = PAGE
page {
    type = 0
}

page.10 >
page.10 = TEXT
page.10.value = This is any page

[3 in tree.rootLineIds]
page.10 >
page.10 = TEXT
page.10.value = This is page 3
[END]

1. Call index.php?id=1, output is: This is any page
2. Reload index.php?id=1, output is: This is any page
3. Call index.php?id=3, output is: This is page 3
4. Reload index.php?id=3, output is: This is page 3
5. Call index.php?id=1, output is: This is any page
6. Reload index.php?id=1, output is: This is any page
7. Call index.php?id=3, output is: This is page 3
8. Reload index.php?id=3, output is: This is page 3

OK.

Change root template setup to:

page = PAGE
page {
    type = 0
}

page.10 >
page.10 = TEXT
page.10.value = This is any page

[3 in tree.rootLineIds]
page.10 >
page.10 = TEXT
page.10.value = This is page 3
[END]

[applicationContext == 'Development']
page.20 >
page.20 = TEXT
page.20.value = Development context is active
[END]

1. Call index.php?id=1, output is: This is any pageDevelopment context is active
2. Reload index.php?id=1, output is: This is any pageDevelopment context is active
3. Call index.php?id=3, output is: This is page 3Development context is active
4. Reload index.php?id=3, output is: This is any pageDevelopment context is active => Incorrect
5. Call index.php?id=1, output is: This is any pageDevelopment context is active
6. Reload index.php?id=1, output is: This is any pageDevelopment context is active
7. Call index.php?id=3, output is: This is any pageDevelopment context is active => Incorrect
8. Reload index.php?id=3, output is: This is any pageDevelopment context is active => Incorrect

Not OK.

Procedure described does not change, whether TypoScript.strictSyntax is enabled or not.

#8 Updated by Philipp Seiler 12 months ago

I've implemented a quick bugfix for this:

TYPO3\CMS\Frontend\Configuration\TypoScript\ConditionMatching\ConditionMatcher:

/**
 * Determines the rootline for the current page.
 *
 * @return array The rootline for the current page.
 * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
 */
protected function determineRootline()
{
    return (array)$this->getTypoScriptFrontendController()->tmpl->rootLine;
}

This method gets the current rootline from the template. That rootline is determined within TemplateService in a method called start(...). However, this method is not called, if the template has been cached. Therefore rootline is not created, and the condition fails.

Simple fix: Don't use rootline from TemplateService, but from FrontendController itself. This should always return the current rootline, no matter if the Template has been cached already. This seems to work for now, but sideffects may be possible.

protected function determineRootline()
{
    return (array)$this->getTypoScriptFrontendController()->rootLine;
}

#9 Updated by Sebastian Klein 12 months ago

I was able to reproduce the behaviour as described by Philipp.

Philipp's suggested change does fix this issue as well as mine in #86807.

I'm as well incapable to predict further impacts of this change. Maybe it can be a hint to narrow down the original issue.

#10 Updated by taywa gmbh 12 months ago

It looks like this problem is not exclusive for tree.rootLineIds, but applies also to tree.level.

page.10.variables.foo = TEXT
page.10.variables.foo.value = bar

[tree.level == 3]
page.10.variables.foo.value = foo
[end]

After clearing cache, this works as long no page from another level is loaded. After that it always shows "bar", also on 3 level pages

#11 Updated by Simon Würstle 12 months ago

What I just found out: when you use "tree.rootLineIds" the caching of all pages which are affected by this condition is deactivated. This does not happen if you use the old syntax.

#12 Updated by Stefan Hekele 8 months ago

Can confirm the problem still exists with TYPO3 9.5.5.
I'll try to reproduce it with just a core installation.

#13 Updated by Stefan Hekele 8 months ago

Steps to reproduce (TYPO3 9.5.5):

  1. Create new TYPO3 installation
    composer create-project typo3/cms-base-distribution typo3_9
  2. Go through install wizard and create backend user, let wizard create empty page
  3. Go into backend, edit typoscript record on start page (uid 1), add the following setup:
    page.5 = TEXT
    [tree.level == 0]
        page.5.value = level 0
    [tree.level == 1]
        page.5.value = level 1
    [END]
    
  4. Create one new subpage, called 1, and enable it
  5. Open http://localhost/en/1 (output level 1 => OK)
  6. Open http://localhost/ (output level 0 => OK)
  7. Reload http://localhost/en/1 (output level 0 => NOT OK)
Debugging:
  1. Set breakpoint in typo3/sysext/frontend/Classes/Configuration/TypoScript/ConditionMatching/ConditionMatcher.php at protected function determineRootline()
  2. Open the newly created page (direct subpage of starting page, should match tree.level == 1)
    1. Uncached page hit: $GLOBALS["TSFE"]->tmpl->rootLine is filled, and function returns expected array
    2. Cached page hit: $GLOBALS["TSFE"]->tmpl->rootLine is empty, and function returns empty array

Due to determineRootline returning an empty array if the page is already in the cache,
$tree created in ConditionMatcher __construct has level 0, and no rootline, nor rootline Ids.

Due to that, all tree conditions evaluate incorrectly for cached pages, not only resulting in incorrect output,
but also severely affecting frontend performance due to cache misses.

#14 Updated by Stefan Hekele 8 months ago

  • Subject changed from TypoScript Condition: rootLineIds not created correctly to TypoScript Condition: tree.* broken on cached pages

#15 Updated by Denis Mir 8 months ago

We can confirm this issue as well. Recognized it for "tree.rootLineIds" which works for non cached pages but on cached pages it is not evaluated and we get the default value that we defined.

#16 Updated by Sven Juergens 8 months ago

same problem here we use the condition tree.rootlines to change Google Analytics vars.
and here we have the problem that the variables are definitely wrong and they still show the rootpage vars.

#17 Updated by Dmitry Dulepov 6 months ago

I can confirm this too. The following causes pages to be never found in cache:

[1 in tree.RootLineIds]

When generating TSFE->newHash in getFromCache(), matching conditions look like this:

But in TSFE->generatePage_preProcessing() it looks like this:

Using the fix from Philipp solves the issue.

#18 Updated by Dmitry Dulepov 6 months ago

Update: if you use solr, this will not work. This change works until a proper fix is developed:

    protected function determineRootline()
    {
        return (array)($this->getTypoScriptFrontendController()->tmpl->rootLine ?? $this->getTypoScriptFrontendController()->rootLine);
    }

#19 Updated by Sven Juergens about 1 month ago

hello, is this bug still present in the current 9.5.9?
I can not reproduce the steps right now

#20 Updated by Daniel Siepmann about 1 month ago

  • Duplicates Bug #88374: [xxx in tree.rootLineIds] TypoScript condition causes page cache regeneration on each request added

#21 Updated by Daniel Siepmann about 1 month ago

Should be fixed by duplicate issue #88374.
Just added a reference.

#22 Updated by Lars Peter Søndergaard about 1 month ago

I downgraded an installation I'm working on to TYPO3 9.5.7 where this issue still exists and could reproduce the bug.
After updating to 9.5.9 again, I could not reproduce it.

So it might be fixed.

#23 Updated by Susanne Moog about 1 month ago

  • Status changed from Needs Feedback to Closed

Closed as duplicate of #88374.

Also available in: Atom PDF