Bug #86915

Symfony Expression TypoScript conditions fail at nested arrays

Added by Lars Peter Søndergaard 4 months ago. Updated 2 months ago.

Status:
Resolved
Priority:
Must have
Assignee:
-
Category:
TypoScript
Target version:
-
Start date:
2018-11-13
Due date:
% Done:

100%

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

Description

Hi,

conditions that try to access values of nested array do not yet work properly with the new symfony expression language.

Example

This works:

[request.getQueryParams()["foobar"] == "baz"]
    page.16 = TEXT
    page.16.value = FOOBAR
[END]

This does not:

[request.getQueryParams()["tx_news_pi1"]["action"] == "detail"]
    page.16 = TEXT
    page.16.value = FOOBAR
[END]

The condition passed to Resolver::evaluate turns out to be:

request.getQueryParams()["tx_news_pi1" 

in the latter case, presumably splitting at ][ due to old syntax (just a guess though).


Related issues

Related to TYPO3 Core - Bug #87021: Using "getTSFE().beUserLogin == 1" as expression in an TypoScript condition leads to an error in the Symfony Expression Language Under Review 2018-11-28

Associated revisions

Revision c443d5cc (diff)
Added by Wolfgang Klinger 4 months ago

[BUGFIX] Fix nested arrays in conditions

The RequestWrapper::getParsedBody method must return an array,
otherwise the a condition like [request.getParsedBody()['foo'] == 1]
results in a silent exception if the body is empty.

ConditionMatcher::normalizeExpression is now using an advanced regex
to handle multiple [] parts correctly.

Resolves: #86915
Releases: master
Change-Id: Ia3f951d1a3994d545025691e35521ca05b97a39a
Reviewed-on: https://review.typo3.org/58935
Tested-by: TYPO3com <>
Tested-by: Joerg Kummer <>
Reviewed-by: Raphael Graf <>
Reviewed-by: Anja Leichsenring <>
Tested-by: Anja Leichsenring <>
Reviewed-by: Markus Klein <>
Tested-by: Markus Klein <>

History

#1 Updated by Josef Glatz 4 months ago

  • Category set to TypoScript

#2 Updated by Josef Glatz 4 months ago

  • Priority changed from Should have to Must have

#3 Updated by Josef Glatz 4 months ago

I also can reproduce the issue in another way:

# Default PAGE object:
page = PAGE
page.10 = TEXT
page.10.value = HELLO WORLD! Please open the page with e.g. Get parameter: ?type=1

foo = PAGE
foo.typeNum = 1
[request.getParsedBody()['type'] > 0 || request.getQueryParams()['type'] > 0]
foo.1 = TEXT
foo.1.value = <h1>1</h1>
[ (request.getParsedBody()['type'] > 0) || (request.getQueryParams()['type'] > 0) ]
foo.2 = TEXT
foo.2.value = <h1>2</h1>
[ (request.getParsedBody()['type'] > 0) or (request.getQueryParams()['type'] > 0) ]
foo.3 = TEXT
foo.3.value = <h1>3</h1>
[request.getParsedBody()['type'] > 0] || [request.getQueryParams()['type'] > 0]
foo.4 = TEXT
foo.4.value = <h1>4</h1>
[request.getParsedBody()['type'] > 0] or [request.getQueryParams()['type'] > 0]
foo.5 = TEXT
foo.5.value = <h1>5</h1>
[global]

For clarification: the actual working foo.4 and foo.5 objects are deprecated in v9. One of the first three should at least work - if I understand Frank correct.


While discussing with Frank,

he came up with the conclusion that the pre-v9 existing TypoScript condition matcher is not completely aware of the new possibilities. As the way to add multiple condition blocks is deprecated, this issue must be fixed.


The following condition work for me as an example

[{$site.dummyFrontend} == 1 && request.getQueryParams()['preview'] != 1]

#4 Updated by Gerrit Code Review 4 months ago

  • Status changed from New to Under Review

Patch set 1 for branch master of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/58935

#5 Updated by Gerrit Code Review 4 months ago

Patch set 2 for branch master of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/58935

#6 Updated by Josef Glatz 4 months ago

Patch set 2 fits at first glance, but it works partially

All 5 objects are displayed with patch set 2.
Using the following test scenario, the following object does not match
  • foo.8/?type=1&tx_news_pi1[news]=1

I've extended the test scenario "v2", now it looks like

foo = PAGE
foo.typeNum = 1

[request.getParsedBody()['type'] > 0 || request.getQueryParams()['type'] > 0]
foo.1 = TEXT
foo.1.value = <h1>1 <small>combined</small></h1>

[ (request.getParsedBody()['type'] > 0) || (request.getQueryParams()['type'] > 0) ]
foo.2 = TEXT
foo.2.value = <h1>2 <small>combined</small></h1>

[ (request.getParsedBody()['type'] > 0) or (request.getQueryParams()['type'] > 0) ]
foo.3 = TEXT
foo.3.value = <h1>3 <small>combined</small></h1>

[request.getParsedBody()['type'] > 0] || [request.getQueryParams()['type'] > 0]
foo.4 = TEXT
foo.4.value = <h1>4</h1>

[request.getParsedBody()['type'] > 0] or [request.getQueryParams()['type'] > 0]
foo.5 = TEXT
foo.5.value = <h1>5</h1>

[request.getParsedBody()['type'] > 1] or [request.getQueryParams()['type'] > 1]
foo.6 = TEXT
foo.6.value = <h1>6 <small>greater then 1</small></h1>

[request.getParsedBody()['type'] > 0 or request.getQueryParams()['type'] == 1]
foo.7 = TEXT
foo.7.value = <h1>7 <small>combined</small></h1>

[request.getParsedBody()['tx_news_pi1']['news'] > 0 || request.getQueryParams()['tx_news_pi1']['news'] > 0]
foo.8 = TEXT
foo.8.value = <h1>8, tx_news_pi1|news <small>combined</small> </h1>

[request.getQueryParams()['tx_news_pi1']['news'] > 0]
foo.9 = TEXT
foo.9.value = <h1>9, tx_news_pi1|news only getQuery</h1>
[global]

Snippet also available as raw version: https://pastebin.com/raw/gmxeRJLa


Adopting the Get Params to /?type=1&tx_news_pi1[news]=1

... doesn't match
  • foo.8 which looks like [request.getParsedBody()['tx_news_pi1']['news'] > 0 || request.getQueryParams()['tx_news_pi1']['news'] > 0]

#7 Updated by Wolfgang Klinger 4 months ago

@ Josef: this one can't be fixed by TYPO3 if the parsing is completely left to symfony's expression language … because the symfony parser throws an exception if an array in a condition does not exist and therefore the whole condition fails (even if there's an OR condition like in your example … see \Symfony\Component\ExpressionLanguage\Node\GetAttrNode::evaluate for details)

#8 Updated by Josef Glatz 4 months ago

  • Related to Bug #87021: Using "getTSFE().beUserLogin == 1" as expression in an TypoScript condition leads to an error in the Symfony Expression Language added

#9 Updated by Gerrit Code Review 4 months ago

Patch set 3 for branch master of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/58935

#10 Updated by Gerrit Code Review 4 months ago

Patch set 4 for branch master of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/58935

#11 Updated by Gerrit Code Review 4 months ago

Patch set 5 for branch master of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/58935

#12 Updated by Gerrit Code Review 4 months ago

Patch set 6 for branch master of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/58935

#13 Updated by Gerrit Code Review 4 months ago

Patch set 7 for branch master of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/58935

#14 Updated by Gerrit Code Review 4 months ago

Patch set 8 for branch master of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/58935

#15 Updated by Wolfgang Klinger 4 months ago

  • Status changed from Under Review to Resolved
  • % Done changed from 0 to 100

#16 Updated by Wolfgang Klinger 2 months ago

This works without any patch (TYPO3 9.5.3):

[(request.getQueryParams()['tx_news_pi1'])['news'] > 0]

Also available in: Atom PDF