[TASK] Deprecate old TypoScript condition syntax 09/58109/10
authorFrank Naegler <frank.naegler@typo3.org>
Fri, 31 Aug 2018 20:19:21 +0000 (22:19 +0200)
committerJan Helke <typo3@helke.de>
Fri, 7 Sep 2018 14:04:34 +0000 (16:04 +0200)
Since the symfony expression language is available for TypoScript
conditions, the old condition syntax is being deprecated.

Resolves: #86068
Releases: master
Change-Id: Iae1f4b6e400afbab233561af54c98bc4a4a40792
Reviewed-on: https://review.typo3.org/58109
Reviewed-by: Andreas Wolf <andreas.wolf@typo3.org>
Tested-by: Andreas Wolf <andreas.wolf@typo3.org>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Richard Haeser <richard@maxserv.com>
Tested-by: Richard Haeser <richard@maxserv.com>
Reviewed-by: Jan Helke <typo3@helke.de>
Tested-by: Jan Helke <typo3@helke.de>
21 files changed:
typo3/sysext/backend/Classes/Configuration/TypoScript/ConditionMatching/ConditionMatcher.php
typo3/sysext/backend/Tests/Unit/Configuration/TypoScript/ConditionMatching/ConditionMatcherTest.php
typo3/sysext/backend/Tests/Unit/Configuration/TypoScript/ConditionMatching/Fixtures/TestCondition.php [deleted file]
typo3/sysext/backend/Tests/Unit/Configuration/TypoScript/ConditionMatching/Fixtures/TestConditionException.php [deleted file]
typo3/sysext/backend/Tests/UnitDeprecated/Configuration/TypoScript/ConditionMatching/ConditionMatcherTest.php [new file with mode: 0644]
typo3/sysext/backend/Tests/UnitDeprecated/Configuration/TypoScript/ConditionMatching/Fixtures/TestCondition.php [new file with mode: 0644]
typo3/sysext/backend/Tests/UnitDeprecated/Configuration/TypoScript/ConditionMatching/Fixtures/TestConditionException.php [new file with mode: 0644]
typo3/sysext/core/Classes/Configuration/TypoScript/ConditionMatching/AbstractConditionMatcher.php
typo3/sysext/core/Classes/Utility/GeneralUtility.php
typo3/sysext/core/Configuration/DefaultConfiguration.php
typo3/sysext/core/Configuration/DefaultConfigurationDescription.yaml
typo3/sysext/core/Documentation/Changelog/9.4/Feature-85829-ImplementSymfonyExpressionLanguageForTypoScriptConditions.rst
typo3/sysext/core/Documentation/Changelog/master/Deprecation-86068-DeprecateOldConditionSyntax.rst [new file with mode: 0644]
typo3/sysext/core/Tests/Unit/Configuration/TypoScript/ConditionMatching/AbstractConditionMatcherTest.php
typo3/sysext/frontend/Classes/Configuration/TypoScript/ConditionMatching/ConditionMatcher.php
typo3/sysext/frontend/Tests/Unit/Configuration/TypoScript/ConditionMatching/ConditionMatcherTest.php
typo3/sysext/frontend/Tests/Unit/Configuration/TypoScript/ConditionMatching/Fixtures/TestCondition.php [deleted file]
typo3/sysext/frontend/Tests/Unit/Configuration/TypoScript/ConditionMatching/Fixtures/TestConditionException.php [deleted file]
typo3/sysext/frontend/Tests/UnitDeprecated/Configuration/TypoScript/ConditionMatching/ConditionMatcherTest.php [new file with mode: 0644]
typo3/sysext/frontend/Tests/UnitDeprecated/Configuration/TypoScript/ConditionMatching/Fixtures/TestCondition.php [new file with mode: 0644]
typo3/sysext/frontend/Tests/UnitDeprecated/Configuration/TypoScript/ConditionMatching/Fixtures/TestConditionException.php [new file with mode: 0644]

index b9cc0f8..800282a 100644 (file)
@@ -69,9 +69,14 @@ class ConditionMatcher extends AbstractConditionMatcher
      * @param string $string The condition to match against its criteria.
      * @return bool Whether the condition matched
      * @see \TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser::parse()
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function evaluateCondition($string)
     {
+        if ($this->strictSyntaxEnabled()) {
+            trigger_error('The old condition syntax has been deprecated and will be removed in TYPO3 CMS 10, use the new expression language. condition: [' . $string . ']', E_USER_DEPRECATED);
+        }
+
         list($key, $value) = GeneralUtility::trimExplode('=', $string, false, 2);
         $result = $this->evaluateConditionCommon($key, $value);
         if (is_bool($result)) {
@@ -134,7 +139,7 @@ class ConditionMatcher extends AbstractConditionMatcher
      *
      * @param string $var Identifier
      * @return mixed The value of the variable pointed to or NULL if variable did not exist
-     * @access private
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function getVariable($var)
     {
@@ -146,6 +151,7 @@ class ConditionMatcher extends AbstractConditionMatcher
      * Get the usergroup list of the current user.
      *
      * @return string The usergroup list of the current user
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function getGroupList()
     {
@@ -159,6 +165,7 @@ class ConditionMatcher extends AbstractConditionMatcher
      * the accordant conditions (e.g. PIDinRootline) will return "FALSE"
      *
      * @return int The determined page id or otherwise 0
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function determinePageId()
     {
@@ -198,6 +205,7 @@ class ConditionMatcher extends AbstractConditionMatcher
      * Gets the properties for the current page.
      *
      * @return array The properties for the current page.
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function getPage()
     {
@@ -212,6 +220,7 @@ class ConditionMatcher extends AbstractConditionMatcher
      * @param int $id Id of the accordant record
      * @param bool $ignoreTable Whether to ignore the page, if TRUE a positive
      * @return int Id of the page the record is persisted on
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function getPageIdByRecord($table, $id, $ignoreTable = false)
     {
@@ -234,6 +243,7 @@ class ConditionMatcher extends AbstractConditionMatcher
      *
      * @param int $pageId The pid the check for as parent page
      * @return bool TRUE if the is currently a new page record being edited with $pid as uid of the parent page
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function isNewPageWithPageId($pageId)
     {
@@ -271,6 +281,7 @@ class ConditionMatcher extends AbstractConditionMatcher
      * 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()
     {
@@ -282,6 +293,7 @@ class ConditionMatcher extends AbstractConditionMatcher
      * Get the id of the current user.
      *
      * @return int The id of the current user
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function getUserId()
     {
@@ -292,6 +304,7 @@ class ConditionMatcher extends AbstractConditionMatcher
      * Determines if a user is logged in.
      *
      * @return bool Determines if a user is logged in
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function isUserLoggedIn()
     {
@@ -302,6 +315,7 @@ class ConditionMatcher extends AbstractConditionMatcher
      * Determines whether the current user is admin.
      *
      * @return bool Whether the current user is admin
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function isAdminUser()
     {
@@ -310,6 +324,7 @@ class ConditionMatcher extends AbstractConditionMatcher
 
     /**
      * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function getBackendUserAuthentication()
     {
index c1810db..c7e831b 100644 (file)
@@ -15,7 +15,6 @@ namespace TYPO3\CMS\Backend\Tests\Unit\Configuration\TypoScript\ConditionMatchin
  */
 
 use TYPO3\CMS\Backend\Configuration\TypoScript\ConditionMatching\ConditionMatcher;
-use TYPO3\CMS\Backend\Tests\Unit\Configuration\TypoScript\ConditionMatching\Fixtures\TestConditionException;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\Context\Context;
 use TYPO3\CMS\Core\Context\UserAspect;
@@ -49,13 +48,16 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
     protected $testTableName;
 
     /**
+     * @var bool Reset singletons
+     */
+    protected $resetSingletonInstances = true;
+
+    /**
      * Set up tests
      */
     protected function setUp()
     {
-        $this->resetSingletonInstances = true;
         $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
-
         $this->testTableName = 'conditionMatcherTestTable';
         $this->testGlobalNamespace = $this->getUniqueId('TEST');
         $GLOBALS['TCA'][$this->testTableName] = ['ctrl' => []];
@@ -113,93 +115,12 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
     }
 
     /**
-     * Tests whether a faulty expression fails.
-     *
-     * @test
-     */
-    public function simulateDisabledMatchAllConditionsFailsOnFaultyExpression()
-    {
-        $this->assertFalse($this->matchCondition->match('[nullCondition = This expression would return FALSE in general]'));
-    }
-
-    /**
-     * Tests whether simulating positive matches for all conditions succeeds.
-     *
-     * @test
-     */
-    public function simulateEnabledMatchAllConditionsSucceeds()
-    {
-        $this->matchCondition->setSimulateMatchResult(true);
-        $this->assertTrue($this->matchCondition->match('[nullCondition = This expression would return FALSE in general]'));
-    }
-
-    /**
-     * Tests whether simulating positive matches for specific conditions succeeds.
-     *
-     * @test
-     */
-    public function simulateEnabledMatchSpecificConditionsSucceeds()
-    {
-        $testCondition = '[' . $this->getUniqueId('test') . ' = Any condition to simulate a positive match]';
-        $this->matchCondition->setSimulateMatchConditions([$testCondition]);
-        $this->assertTrue($this->matchCondition->match($testCondition));
-    }
-
-    /**
-     * Tests whether the language comparison matches.
-     *
-     * @test
-     */
-    public function languageConditionMatchesSingleLanguageExpression()
-    {
-        $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-de,de;q=0.8,en-us;q=0.5,en;q=0.3';
-        $this->assertTrue($this->matchCondition->match('[language = *de*]'));
-        $this->assertTrue($this->matchCondition->match('[language = *de-de*]'));
-        // Test expression language
-        // @TODO: this test fails, because setting values after init does not work
-        // $this->assertTrue($this->matchCondition->match('[like(request("getAttributes")["normalizedParams"].getHttpAcceptLanguage(), "**de*")]'));
-        // $this->assertTrue($this->matchCondition->match('[like(request("getAttributes")["normalizedParams"].getHttpAcceptLanguage(), "**de-de*")]'));
-    }
-
-    /**
-     * Tests whether the language comparison matches.
-     *
-     * @test
-     */
-    public function languageConditionMatchesMultipleLanguagesExpression()
-    {
-        $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-de,de;q=0.8,en-us;q=0.5,en;q=0.3';
-        $this->assertTrue($this->matchCondition->match('[language = *en*,*de*]'));
-        $this->assertTrue($this->matchCondition->match('[language = *en-us*,*de-de*]'));
-        // Test expression language
-        // @TODO: this test fails, because setting values after init does not work
-        // $this->assertTrue($this->matchCondition->match('[like(request("getAttributes")["normalizedParams"].getHttpAcceptLanguage(), "*en*,*de*")]'));
-        // $this->assertTrue($this->matchCondition->match('[like(request("getAttributes")["normalizedParams"].getHttpAcceptLanguage(), "*en-us*,*de-de*")]'));
-    }
-
-    /**
-     * Tests whether the language comparison matches.
-     *
-     * @test
-     */
-    public function languageConditionMatchesCompleteLanguagesExpression()
-    {
-        $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-de,de;q=0.8,en-us;q=0.5,en;q=0.3';
-        $this->assertTrue($this->matchCondition->match('[language = de-de,de;q=0.8,en-us;q=0.5,en;q=0.3]'));
-        // Test expression language
-        // @TODO: this test fails, because setting values after init does not work
-        // $this->assertTrue($this->matchCondition->match('[request("getAttributes")["normalizedParams"].getHttpAcceptLanguage() == "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"]'));
-    }
-
-    /**
      * Tests whether usergroup comparison matches.
      *
      * @test
      */
     public function usergroupConditionMatchesSingleGroupId()
     {
-        $this->assertTrue($this->matchCondition->match('[usergroup = 13]'));
-        // Test expression language
         $this->assertTrue($this->matchCondition->match('[usergroup(13)]'));
         $this->assertTrue($this->matchCondition->match('[usergroup("13")]'));
         $this->assertTrue($this->matchCondition->match('[usergroup(\'13\')]'));
@@ -212,8 +133,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
      */
     public function usergroupConditionMatchesMultipleUserGroupId()
     {
-        $this->assertTrue($this->matchCondition->match('[usergroup = 999,15,14,13]'));
-        // Test expression language
         $this->assertTrue($this->matchCondition->match('[usergroup("999,15,14,13")]'));
         $this->assertTrue($this->matchCondition->match('[usergroup(\'999,15,14,13\')]'));
     }
@@ -225,8 +144,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
      */
     public function loginUserConditionMatchesAnyLoggedInUser()
     {
-        $this->assertTrue($this->matchCondition->match('[loginUser = *]'));
-        // Test expression language
         $this->assertTrue($this->matchCondition->match('[loginUser("*")]'));
         $this->assertTrue($this->matchCondition->match('[loginUser(\'*\')]'));
     }
@@ -238,8 +155,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
      */
     public function loginUserConditionMatchesSingleLoggedInUser()
     {
-        $this->assertTrue($this->matchCondition->match('[loginUser = 13]'));
-        // Test expression language
         $this->assertTrue($this->matchCondition->match('[loginUser(13)]'));
         $this->assertTrue($this->matchCondition->match('[loginUser("13")]'));
         $this->assertTrue($this->matchCondition->match('[loginUser(\'13\')]'));
@@ -253,8 +168,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
     public function loginUserConditionDoesNotMatchSingleLoggedInUser()
     {
         $GLOBALS['BE_USER']->user['uid'] = 13;
-        $this->assertFalse($this->matchCondition->match('[loginUser = 999]'));
-        // Test expression language
         $this->assertFalse($this->matchCondition->match('[loginUser(999)]'));
         $this->assertFalse($this->matchCondition->match('[loginUser("999")]'));
         $this->assertFalse($this->matchCondition->match('[loginUser(\'999\')]'));
@@ -267,8 +180,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
      */
     public function loginUserConditionMatchesMultipleLoggedInUsers()
     {
-        $this->assertTrue($this->matchCondition->match('[loginUser = 999,13]'));
-        // Test expression language
         $this->assertTrue($this->matchCondition->match('[loginUser("999,13")]'));
         $this->assertTrue($this->matchCondition->match('[loginUser(\'999,13\')]'));
     }
@@ -280,283 +191,12 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
      */
     public function adminUserConditionMatchesAdminUser()
     {
-        $this->assertTrue($this->matchCondition->match('[adminUser = 1]'));
-        // Test expression language
         $this->assertTrue($this->matchCondition->match('[backend.user.isAdmin == true]'));
         $this->assertTrue($this->matchCondition->match('[backend.user.isAdmin != false]'));
         $this->assertTrue($this->matchCondition->match('[backend.user.isAdmin]'));
     }
 
     /**
-     * Tests whether checkinf for an admin user matches
-     *
-     * @test
-     */
-    public function adminUserConditionMatchesRegularUser()
-    {
-        $GLOBALS['BE_USER']->user['uid'] = 14;
-        $GLOBALS['BE_USER']->user['admin'] = 0;
-        $this->assertTrue($this->matchCondition->match('[adminUser = 0]'));
-    }
-
-    /**
-     * Tests whether checkinf for an admin user matches
-     *
-     * @test
-     */
-    public function adminUserConditionDoesNotMatchRegularUser()
-    {
-        $GLOBALS['BE_USER']->user['uid'] = 14;
-        $GLOBALS['BE_USER']->user['admin'] = 0;
-        $this->assertFalse($this->matchCondition->match('[adminUser = 1]'));
-    }
-
-    /**
-     * Tests whether numerical comparison matches.
-     *
-     * @test
-     */
-    public function globalVarConditionMatchesOnEqualExpression()
-    {
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10 = 10]'), '1');
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.1 = 10.1]'), '2');
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10 == 10]'), '3');
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.1 == 10.1]'), '4');
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:0 = 0]'), '5');
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:0 == 0]'), '6');
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether numerical comparison matches.
-     *
-     * @test
-     */
-    public function globalVarConditionMatchesOnEqualExpressionWithMultipleValues()
-    {
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10 = 10|20|30]'));
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.1 = 10.1|20.2|30.3]'));
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:20 = 10|20|30]'));
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:20.2 = 10.1|20.2|30.3]'));
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10 == 10|20|30]'));
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.1 == 10.1|20.2|30.3]'));
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:20 == 10|20|30]'));
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:20.2 == 10.1|20.2|30.3]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether numerical comparison matches.
-     *
-     * @test
-     */
-    public function globalVarConditionMatchesOnNotEqualExpression()
-    {
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10 != 20]'));
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.1 != 10.2]'));
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:0 != 1]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether numerical comparison does not match.
-     *
-     * @test
-     */
-    public function globalVarConditionDoesNotMatchOnNotEqualExpression()
-    {
-        $this->assertFalse($this->matchCondition->match('[globalVar = LIT:10 != 10]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether numerical comparison matches.
-     *
-     * @test
-     */
-    public function globalVarConditionMatchesOnNotEqualExpressionWithMultipleValues()
-    {
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10 != 20|30]'));
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.1 != 10.2|20.3]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether numerical comparison matches.
-     *
-     * @test
-     */
-    public function globalVarConditionMatchesOnLowerThanExpression()
-    {
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10 < 20]'));
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.1 < 10.2]'));
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:0 < 1]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether numerical comparison matches.
-     *
-     * @test
-     */
-    public function globalVarConditionMatchesOnLowerThanOrEqualExpression()
-    {
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10 <= 10]'));
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10 <= 20]'));
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.1 <= 10.1]'));
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.1 <= 10.2]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether numerical comparison matches.
-     *
-     * @test
-     */
-    public function globalVarConditionMatchesOnGreaterThanExpression()
-    {
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:20 > 10]'));
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.2 > 10.1]'));
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:1 > 0]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether numerical comparison matches.
-     *
-     * @test
-     */
-    public function globalVarConditionMatchesOnGreaterThanOrEqualExpression()
-    {
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10 >= 10]'));
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:20 >= 10]'));
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.1 >= 10.1]'));
-        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.2 >= 10.1]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether numerical comparison matches.
-     *
-     * @test
-     */
-    public function globalVarConditionMatchesOnEmptyExpressionWithNoValueSet()
-    {
-        $testKey = $this->getUniqueId('test');
-        $this->assertTrue($this->matchCondition->match('[globalVar = GP:' . $testKey . '=]'));
-        $this->assertTrue($this->matchCondition->match('[globalVar = GP:' . $testKey . ' = ]'));
-        // Test expression language
-        // Access request by request() method
-    }
-
-    /**
-     * Tests whether numerical comparison matches.
-     *
-     * @test
-     */
-    public function globalVarConditionDoesNotMatchOnEmptyExpressionWithValueSetToZero()
-    {
-        $testKey = $this->getUniqueId('test');
-        $_GET = [];
-        $_POST = [$testKey => 0];
-        $this->assertFalse($this->matchCondition->match('[globalVar = GP:' . $testKey . '=]'));
-        $this->assertFalse($this->matchCondition->match('[globalVar = GP:' . $testKey . ' = ]'));
-    }
-
-    /**
-     * Tests whether string comparison matches.
-     *
-     * @test
-     */
-    public function globalStringConditionMatchesOnEqualExpression()
-    {
-        $this->assertTrue($this->matchCondition->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3.Test.Condition]'));
-        $this->assertFalse($this->matchCondition->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether string comparison matches.
-     *
-     * @test
-     */
-    public function globalStringConditionMatchesOnEmptyExpressionWithValueSetToEmptyString()
-    {
-        $testKey = $this->getUniqueId('test');
-        $_GET = [];
-        $_POST = [$testKey => ''];
-        $this->assertTrue($this->matchCondition->match('[globalString = GP:' . $testKey . '=]'));
-        $this->assertTrue($this->matchCondition->match('[globalString = GP:' . $testKey . ' = ]'));
-        // Test expression language
-        // Access request by request() method
-    }
-
-    /**
-     * Tests whether string comparison matches.
-     *
-     * @test
-     */
-    public function globalStringConditionMatchesOnEmptyLiteralExpressionWithValueSetToEmptyString()
-    {
-        $this->assertTrue($this->matchCondition->match('[globalString = LIT:=]'));
-        $this->assertTrue($this->matchCondition->match('[globalString = LIT: = ]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether string comparison matches.
-     *
-     * @test
-     */
-    public function globalStringConditionMatchesWildcardExpression()
-    {
-        $this->assertTrue($this->matchCondition->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3?Test?Condition]'));
-        $this->assertTrue($this->matchCondition->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3.T*t.Condition]'));
-        $this->assertTrue($this->matchCondition->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3?T*t?Condition]'));
-        // globalString is not implemented, because globalVar did the job
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether string comparison matches.
-     *
-     * @test
-     */
-    public function globalStringConditionMatchesRegularExpression()
-    {
-        $this->assertTrue($this->matchCondition->match('[globalString = LIT:TYPO3.Test.Condition = /^[A-Za-z3.]+$/]'));
-        $this->assertTrue($this->matchCondition->match('[globalString = LIT:TYPO3.Test.Condition = /^TYPO3\\..+Condition$/]'));
-        $this->assertFalse($this->matchCondition->match('[globalString = LIT:TYPO3.Test.Condition = /^FALSE/]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether string comparison matches.
-     *
-     * @test
-     */
-    public function globalStringConditionMatchesEmptyRegularExpression()
-    {
-        $testKey = $this->getUniqueId('test');
-        $_SERVER[$testKey] = '';
-        $this->assertTrue($this->matchCondition->match('[globalString = _SERVER|' . $testKey . ' = /^$/]'));
-        // Test expression language
-        // Access request by request() method
-    }
-
-    /**
      * Tests whether treeLevel comparison matches.
      *
      * @test
@@ -564,8 +204,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
     public function treeLevelConditionMatchesSingleValue()
     {
         $this->matchCondition->setRootline($this->rootline);
-        $this->assertTrue($this->matchCondition->match('[treeLevel = 2]'));
-        // Test expression language
         $this->assertTrue($this->matchCondition->match('[tree.level == 2]'));
     }
 
@@ -577,8 +215,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
     public function treeLevelConditionMatchesMultipleValues()
     {
         $this->matchCondition->setRootline($this->rootline);
-        $this->assertTrue($this->matchCondition->match('[treeLevel = 999,998,2]'));
-        // Test expression language
         $this->assertTrue($this->matchCondition->match('[tree.level in [999,998,2]]'));
     }
 
@@ -590,62 +226,7 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
     public function treeLevelConditionDoesNotMatchFaultyValue()
     {
         $this->matchCondition->setRootline($this->rootline);
-        $this->assertFalse($this->matchCondition->match('[treeLevel = 999]'));
-        // Test expression language
-        $this->assertFalse($this->matchCondition->match('[treeLevel == 999]'));
-    }
-
-    /**
-     * Tests whether treeLevel comparison matches when creating new pages.
-     *
-     * @test
-     */
-    public function treeLevelConditionMatchesCurrentPageIdWhileEditingNewPage()
-    {
-        $GLOBALS['SOBE'] = $this->createMock(\TYPO3\CMS\Backend\Controller\EditDocumentController::class);
-        $GLOBALS['SOBE']->elementsData = [
-            [
-                'table' => 'pages',
-                'uid' => 'NEW4adc6021e37e7',
-                'pid' => 121,
-                'cmd' => 'new',
-                'deleteAccess' => 0
-            ]
-        ];
-        $GLOBALS['SOBE']->data = [];
-        $this->matchCondition->setRootline($this->rootline);
-        $this->matchCondition->setPageId(121);
-        $this->assertTrue($this->matchCondition->match('[treeLevel = 3]'));
-    }
-
-    /**
-     * Tests whether treeLevel comparison matches when creating new pages.
-     *
-     * @test
-     */
-    public function treeLevelConditionMatchesCurrentPageIdWhileSavingNewPage()
-    {
-        $GLOBALS['SOBE'] = $this->createMock(\TYPO3\CMS\Backend\Controller\EditDocumentController::class);
-        $GLOBALS['SOBE']->elementsData = [
-            [
-                'table' => 'pages',
-                /// 999 is the uid of the page that was just created
-                'uid' => 999,
-                'pid' => 121,
-                'cmd' => 'edit',
-                'deleteAccess' => 1
-            ]
-        ];
-        $GLOBALS['SOBE']->data = [
-            'pages' => [
-                'NEW4adc6021e37e7' => [
-                    'pid' => 121
-                ]
-            ]
-        ];
-        $this->matchCondition->setRootline($this->rootline);
-        $this->matchCondition->setPageId(121);
-        $this->assertTrue($this->matchCondition->match('[treeLevel = 3]'));
+        $this->assertFalse($this->matchCondition->match('[tree.level == 999]'));
     }
 
     /**
@@ -657,8 +238,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
     {
         $this->matchCondition->setRootline($this->rootline);
         $this->matchCondition->setPageId(121);
-        $this->assertTrue($this->matchCondition->match('[PIDupinRootline = 111]'));
-        // Test expression language
         $this->assertTrue($this->matchCondition->match('[111 in tree.rootLineIds]'));
         $this->assertTrue($this->matchCondition->match('["111" in tree.rootLineIds]'));
         $this->assertTrue($this->matchCondition->match('[\'111\' in tree.rootLineIds]'));
@@ -669,104 +248,14 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
      *
      * @test
      */
-    public function PIDupinRootlineConditionMatchesMultiplePageIdsInRootline()
-    {
-        $this->matchCondition->setRootline($this->rootline);
-        $this->matchCondition->setPageId(121);
-        $this->assertTrue($this->matchCondition->match('[PIDupinRootline = 999,111,101]'));
-        // Test expression language
-        $this->assertTrue($this->matchCondition->match('[999 in tree.rootLineIds][111 in tree.rootLineIds][101 in tree.rootLineIds]'));
-    }
-
-    /**
-     * Tests whether a page Id is found in the previous rootline entries.
-     *
-     * @test
-     */
     public function PIDupinRootlineConditionDoesNotMatchPageIdNotInRootline()
     {
         $this->matchCondition->setRootline($this->rootline);
         $this->matchCondition->setPageId(121);
-        $this->assertFalse($this->matchCondition->match('[PIDupinRootline = 999]'));
-        // Test expression language
         $this->assertFalse($this->matchCondition->match('[999 in tree.rootLineIds]'));
     }
 
     /**
-     * Tests whether a page Id is found in the previous rootline entries.
-     *
-     * @test
-     */
-    public function PIDupinRootlineConditionDoesNotMatchLastPageIdInRootline()
-    {
-        $this->matchCondition->setRootline($this->rootline);
-        $this->matchCondition->setPageId(121);
-        $this->assertFalse($this->matchCondition->match('[PIDupinRootline = 121]'));
-        // Test expression language
-        // @TODO: this test fails, because setting values after init does not work
-        // $this->assertFalse($this->matchCondition->match('[page.uid != 121 && 121 in rootLineUids]'));
-    }
-
-    /**
-     * Tests whether a page Id is found in the previous rootline entries.
-     *
-     * @test
-     */
-    public function PIDupinRootlineConditionMatchesCurrentPageIdWhileEditingNewPage()
-    {
-        $GLOBALS['SOBE'] = $this->createMock(\TYPO3\CMS\Backend\Controller\EditDocumentController::class);
-        $GLOBALS['SOBE']->elementsData = [
-            [
-                'table' => 'pages',
-                'uid' => 'NEW4adc6021e37e7',
-                'pid' => 121,
-                'cmd' => 'new',
-                'deleteAccess' => 0
-            ]
-        ];
-        $GLOBALS['SOBE']->data = [];
-        $this->matchCondition->setRootline($this->rootline);
-        $this->matchCondition->setPageId(121);
-        $this->assertTrue($this->matchCondition->match('[PIDupinRootline = 121]'));
-        // Test expression language
-        // page is not available here because, page is initialized with BackendUtility::getRecord()
-        // $this->assertTrue($this->matchCondition->match('[page.uid != 999 && 999 in rootLineUids]'));
-    }
-
-    /**
-     * Tests whether a page Id is found in the previous rootline entries.
-     *
-     * @test
-     */
-    public function PIDupinRootlineConditionMatchesCurrentPageIdWhileSavingNewPage()
-    {
-        $GLOBALS['SOBE'] = $this->createMock(\TYPO3\CMS\Backend\Controller\EditDocumentController::class);
-        $GLOBALS['SOBE']->elementsData = [
-            [
-                'table' => 'pages',
-                /// 999 is the uid of the page that was just created
-                'uid' => 999,
-                'pid' => 121,
-                'cmd' => 'edit',
-                'deleteAccess' => 1
-            ]
-        ];
-        $GLOBALS['SOBE']->data = [
-            'pages' => [
-                'NEW4adc6021e37e7' => [
-                    'pid' => 121
-                ]
-            ]
-        ];
-        $this->matchCondition->setRootline($this->rootline);
-        $this->matchCondition->setPageId(121);
-        $this->assertTrue($this->matchCondition->match('[PIDupinRootline = 121]'));
-        // Test expression language
-        // page is not available here because, page is initialized with BackendUtility::getRecord()
-        // $this->assertTrue($this->matchCondition->match('[page.uid != 121 && 121 in rootLineUids]'));
-    }
-
-    /**
      * Tests whether a page Id is found in all rootline entries.
      *
      * @test
@@ -775,8 +264,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
     {
         $this->matchCondition->setRootline($this->rootline);
         $this->matchCondition->setPageId(121);
-        $this->assertTrue($this->matchCondition->match('[PIDinRootline = 111]'));
-        // Test expression language
         $this->assertTrue($this->matchCondition->match('[111 in tree.rootLineIds]'));
     }
 
@@ -785,26 +272,10 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
      *
      * @test
      */
-    public function PIDinRootlineConditionMatchesMultiplePageIdsInRootline()
-    {
-        $this->matchCondition->setRootline($this->rootline);
-        $this->matchCondition->setPageId(121);
-        $this->assertTrue($this->matchCondition->match('[PIDinRootline = 999,111,101]'));
-        // Test expression language
-        $this->assertTrue($this->matchCondition->match('[999 in tree.rootLineIds][111 in tree.rootLineIds][101 in tree.rootLineIds]'));
-    }
-
-    /**
-     * Tests whether a page Id is found in all rootline entries.
-     *
-     * @test
-     */
     public function PIDinRootlineConditionMatchesLastPageIdInRootline()
     {
         $this->matchCondition->setRootline($this->rootline);
         $this->matchCondition->setPageId(121);
-        $this->assertTrue($this->matchCondition->match('[PIDinRootline = 121]'));
-        // Test expression language
         $this->assertTrue($this->matchCondition->match('[121 in tree.rootLineIds]'));
     }
 
@@ -817,8 +288,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
     {
         $this->matchCondition->setRootline($this->rootline);
         $this->matchCondition->setPageId(121);
-        $this->assertFalse($this->matchCondition->match('[PIDinRootline = 999]'));
-        // Test expression language
         $this->assertFalse($this->matchCondition->match('[999 in tree.rootLineIds]'));
     }
 
@@ -830,8 +299,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
      */
     public function compatVersionConditionMatchesOlderRelease()
     {
-        $this->assertTrue($this->matchCondition->match('[compatVersion = 7.0]'));
-        // Test expression language
         $this->assertTrue($this->matchCondition->match('[compatVersion(7.0)]'));
         $this->assertTrue($this->matchCondition->match('[compatVersion("7.0")]'));
         $this->assertTrue($this->matchCondition->match('[compatVersion(\'7.0\')]'));
@@ -845,8 +312,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
      */
     public function compatVersionConditionMatchesSameRelease()
     {
-        $this->assertTrue($this->matchCondition->match('[compatVersion = ' . TYPO3_branch . ']'));
-        // Test expression language
         $this->assertTrue($this->matchCondition->match('[compatVersion(' . TYPO3_branch . ')]'));
         $this->assertTrue($this->matchCondition->match('[compatVersion("' . TYPO3_branch . '")]'));
         $this->assertTrue($this->matchCondition->match('[compatVersion(\'' . TYPO3_branch . '\')]'));
@@ -860,40 +325,12 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
      */
     public function compatVersionConditionDoesNotMatchNewerRelease()
     {
-        $this->assertFalse($this->matchCondition->match('[compatVersion = 15.0]'));
-        // Test expression language
         $this->assertFalse($this->matchCondition->match('[compatVersion(15.0)]'));
         $this->assertFalse($this->matchCondition->match('[compatVersion("15.0")]'));
         $this->assertFalse($this->matchCondition->match('[compatVersion(\'15.0\')]'));
     }
 
     /**
-     * Tests whether the generic fetching of variables works with the namespace 'GP'.
-     *
-     * @test
-     */
-    public function genericGetVariablesSucceedsWithNamespaceGP()
-    {
-        $_GET = ['testGet' => 'getTest'];
-        $_POST = ['testPost' => 'postTest'];
-        $this->assertTrue($this->matchCondition->match('[globalString = GP:testGet = getTest]'));
-        $this->assertTrue($this->matchCondition->match('[globalString = GP:testPost = postTest]'));
-    }
-
-    /**
-     * Tests whether the generic fetching of variables does not work with the namespace 'TSFE',
-     * since we are in the backend context here.
-     *
-     * @test
-     */
-    public function genericGetVariablesFailsWithNamespaceTSFE()
-    {
-        $GLOBALS['TSFE'] = new \stdClass();
-        $GLOBALS['TSFE']->id = 1234567;
-        $this->assertFalse($this->matchCondition->match('[globalString = TSFE:id = 1234567]'));
-    }
-
-    /**
      * Tests whether the generic fetching of variables works with the namespace 'ENV'.
      *
      * @test
@@ -902,161 +339,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
     {
         $testKey = $this->getUniqueId('test');
         putenv($testKey . '=testValue');
-        $this->assertTrue($this->matchCondition->match('[globalString = ENV:' . $testKey . ' = testValue]'));
-        // Test expression language
         $this->assertTrue($this->matchCondition->match('[getenv("' . $testKey . '") == "testValue"]'));
     }
-
-    /**
-     * Tests whether the generic fetching of variables works with the namespace 'IENV'.
-     *
-     * @test
-     */
-    public function genericGetVariablesSucceedsWithNamespaceIENV()
-    {
-        $_SERVER['HTTP_HOST'] = GeneralUtility::getIndpEnv('TYPO3_HOST_ONLY') . ':1234567';
-        // getIndpEnv() is polluted after above call, clear cache to have it recalculate for subject execption
-        GeneralUtility::flushInternalRuntimeCaches();
-        $this->assertTrue($this->matchCondition->match('[globalString = IENV:TYPO3_PORT = 1234567]'));
-        // Test expression language
-        // Access to global variables is not possible in expression language
-    }
-
-    /**
-     * Tests whether the generic fetching of variables works with any global namespace.
-     *
-     * @test
-     */
-    public function genericGetVariablesSucceedsWithAnyGlobalNamespace()
-    {
-        $GLOBALS[$this->testGlobalNamespace] = [
-            'first' => 'testFirst',
-            'second' => ['third' => 'testThird']
-        ];
-        $this->assertTrue($this->matchCondition->match('[globalString = ' . $this->testGlobalNamespace . '|first = testFirst]'));
-        $this->assertTrue($this->matchCondition->match('[globalString = ' . $this->testGlobalNamespace . '|second|third = testThird]'));
-        // Test expression language
-        // Access to global variables is not possible in expression language, because access to $GLOBALS is bad...
-    }
-
-    /**
-     * Tests whether determining a pageId works.
-     *
-     * @test
-     */
-    public function pageIdCanBeDeterminedWhileCallingModuleWithPageTree()
-    {
-        $_GET['id'] = 999;
-        $this->matchCondition->match('[globalVar = LIT:10 = 10]');
-        $this->assertEquals(999, $this->matchCondition->getPageId());
-    }
-
-    /**
-     * Tests whether determining a pageId works.
-     *
-     * @test
-     */
-    public function pageIdCanBeDeterminedWhileEditingAPageRecord()
-    {
-        $_GET['edit']['pages'][999] = 'edit';
-        $this->matchCondition->match('[globalVar = LIT:10 = 10]');
-        $this->assertEquals(999, $this->matchCondition->getPageId());
-    }
-
-    /**
-     * Tests whether determining a pageId works.
-     *
-     * @test
-     */
-    public function pageIdCanBeDeterminedWhileEditingARegularRecord()
-    {
-        $this->setUpDatabaseMockForDeterminePageId();
-        $_GET['edit'][$this->testTableName][13] = 'edit';
-        $this->matchCondition->match('[globalVar = LIT:10 = 10]');
-        $this->assertEquals(999, $this->matchCondition->getPageId());
-    }
-
-    /**
-     * Tests whether determining a pageId works.
-     *
-     * @test
-     */
-    public function pageIdCanBeDeterminedWhileCreatingARecord()
-    {
-        $_GET['edit']['pages'][999] = 'new';
-        $this->matchCondition->match('[globalVar = LIT:10 = 10]');
-        $this->assertEquals(999, $this->matchCondition->getPageId());
-    }
-
-    /**
-     * Tests whether determining a pageId works.
-     *
-     * @test
-     */
-    public function pageIdCanBeDeterminedWhileCreatingARecordAfterAnExistingRecord()
-    {
-        $this->setUpDatabaseMockForDeterminePageId();
-        $_GET['edit'][$this->testTableName][-13] = 'new';
-        $this->matchCondition->match('[globalVar = LIT:10 = 10]');
-        $this->assertEquals(999, $this->matchCondition->getPageId());
-    }
-
-    /**
-     * Tests whether determining a pageId works.
-     *
-     * @test
-     */
-    public function pageIdCanBeDeterminedWhileDeletingAPageRecord()
-    {
-        $_GET['cmd']['pages'][999]['delete'] = 1;
-        $this->matchCondition->match('[globalVar = LIT:10 = 10]');
-        $this->assertEquals(999, $this->matchCondition->getPageId());
-    }
-
-    /**
-     * Tests whether determining a pageId works.
-     *
-     * @test
-     */
-    public function pageIdCanBeDeterminedWhileCopyingARecordToAnotherPage()
-    {
-        $_GET['cmd']['pages'][121]['copy'] = 999;
-        $this->matchCondition->match('[globalVar = LIT:10 = 10]');
-        $this->assertEquals(999, $this->matchCondition->getPageId());
-    }
-
-    /**
-     * Tests whether determining a pageId works.
-     *
-     * @test
-     */
-    public function pageIdCanBeDeterminedWhileCopyingARecordAfterAnExistingRecord()
-    {
-        $this->setUpDatabaseMockForDeterminePageId();
-        $_GET['cmd'][$this->testTableName][121]['copy'] = -13;
-        $this->matchCondition->match('[globalVar = LIT:10 = 10]');
-        $this->assertEquals(999, $this->matchCondition->getPageId());
-    }
-
-    /**
-     * Tests whether determining a pageId works.
-     *
-     * @test
-     */
-    public function pageIdCanBeDeterminedWhileMovingARecordToAnotherPage()
-    {
-        $_GET['cmd']['pages'][121]['move'] = 999;
-        $this->matchCondition->match('[globalVar = LIT:10 = 10]');
-        $this->assertEquals(999, $this->matchCondition->getPageId());
-    }
-
-    /**
-     * @test
-     */
-    public function matchCallsTestConditionAndHandsOverParameters()
-    {
-        $this->expectException(TestConditionException::class);
-        $this->expectExceptionCode(1476109533);
-        $this->matchCondition->match('[TYPO3\\CMS\\Backend\\Tests\\Unit\\Configuration\\TypoScript\\ConditionMatching\\Fixtures\\TestCondition = 7, != 6]');
-    }
 }
diff --git a/typo3/sysext/backend/Tests/Unit/Configuration/TypoScript/ConditionMatching/Fixtures/TestCondition.php b/typo3/sysext/backend/Tests/Unit/Configuration/TypoScript/ConditionMatching/Fixtures/TestCondition.php
deleted file mode 100644 (file)
index a3a6acb..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-namespace TYPO3\CMS\Backend\Tests\Unit\Configuration\TypoScript\ConditionMatching\Fixtures;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-/**
- * Fixture for custom conditions
- */
-class TestCondition extends \TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractCondition
-{
-    /**
-     * Test matcher tests input parameters.
-     *
-     * @param array $conditionParameters
-     * @throws TestConditionException
-     * @return bool
-     */
-    public function matchCondition(array $conditionParameters)
-    {
-        // Throw an exception if everything is fine, this exception is *expected* in the according unit test
-        if ($conditionParameters[0] === '= 7' && $conditionParameters[1] === '!= 6') {
-            throw new TestConditionException('All Ok', 1476109533);
-        }
-    }
-}
diff --git a/typo3/sysext/backend/Tests/Unit/Configuration/TypoScript/ConditionMatching/Fixtures/TestConditionException.php b/typo3/sysext/backend/Tests/Unit/Configuration/TypoScript/ConditionMatching/Fixtures/TestConditionException.php
deleted file mode 100644 (file)
index 9e279b1..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-namespace TYPO3\CMS\Backend\Tests\Unit\Configuration\TypoScript\ConditionMatching\Fixtures;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-/**
- * Exception thrown by TestCondition
- */
-class TestConditionException extends \Exception
-{
-}
diff --git a/typo3/sysext/backend/Tests/UnitDeprecated/Configuration/TypoScript/ConditionMatching/ConditionMatcherTest.php b/typo3/sysext/backend/Tests/UnitDeprecated/Configuration/TypoScript/ConditionMatching/ConditionMatcherTest.php
new file mode 100644 (file)
index 0000000..3ab7f19
--- /dev/null
@@ -0,0 +1,1065 @@
+<?php
+namespace TYPO3\CMS\Backend\Tests\UnitDeprecated\Configuration\TypoScript\ConditionMatching;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Configuration\TypoScript\ConditionMatching\ConditionMatcher;
+use TYPO3\CMS\Backend\Tests\UnitDeprecated\Configuration\TypoScript\ConditionMatching\Fixtures\TestConditionException;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Context\Context;
+use TYPO3\CMS\Core\Context\UserAspect;
+use TYPO3\CMS\Core\Http\ServerRequest;
+use TYPO3\CMS\Core\Log\Logger;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * Testcase for class \TYPO3\CMS\Backend\Configuration\TypoScript\ConditionMatching\ConditionMatcher.
+ */
+class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
+{
+    /**
+     * @var array
+     */
+    protected $rootline;
+
+    /**
+     * @var \TYPO3\CMS\Backend\Configuration\TypoScript\ConditionMatching\ConditionMatcher
+     */
+    protected $matchCondition;
+
+    /**
+     * @var string
+     */
+    protected $testGlobalNamespace;
+
+    /**
+     * @var string
+     */
+    protected $testTableName;
+
+    /**
+     * @var bool Reset singletons
+     */
+    protected $resetSingletonInstances = true;
+
+    /**
+     * Set up tests
+     */
+    protected function setUp()
+    {
+        $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
+        $this->testTableName = 'conditionMatcherTestTable';
+        $this->testGlobalNamespace = $this->getUniqueId('TEST');
+        $GLOBALS['TCA'][$this->testTableName] = ['ctrl' => []];
+        $GLOBALS[$this->testGlobalNamespace] = [];
+        $this->setUpBackend();
+        $this->matchCondition = $this->getAccessibleMock(ConditionMatcher::class, ['determineRootline'], [], '', false);
+        $this->matchCondition->method('determineRootline')->willReturn([
+            2 => ['uid' => 121, 'pid' => 111],
+            1 => ['uid' => 111, 'pid' => 101],
+            0 => ['uid' => 101, 'pid' => 0]
+        ]);
+        $this->matchCondition->__construct();
+        $loggerProphecy = $this->prophesize(Logger::class);
+        $this->matchCondition->setLogger($loggerProphecy->reveal());
+    }
+
+    /**
+     * Set up a backend
+     */
+    private function setUpBackend()
+    {
+        $this->rootline = [
+            2 => ['uid' => 121, 'pid' => 111],
+            1 => ['uid' => 111, 'pid' => 101],
+            0 => ['uid' => 101, 'pid' => 0]
+        ];
+        $GLOBALS['BE_USER'] = $this->getMockBuilder(BackendUserAuthentication::class)
+            ->setMethods(['dummy'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $GLOBALS['BE_USER']->groupList = '13,14,15';
+        $GLOBALS['BE_USER']->user['uid'] = 13;
+        $GLOBALS['BE_USER']->user['admin'] = 1;
+
+        GeneralUtility::makeInstance(Context::class)
+            ->setAspect('backend.user', new UserAspect($GLOBALS['BE_USER']));
+    }
+
+    /**
+     * Set up database mock
+     */
+    private function setUpDatabaseMockForDeterminePageId()
+    {
+        $this->matchCondition = $this->getAccessibleMock(ConditionMatcher::class, ['determineRootline', 'determinePageId'], [], '', false);
+        $this->matchCondition->method('determineRootline')->willReturn([
+            2 => ['uid' => 121, 'pid' => 111],
+            1 => ['uid' => 111, 'pid' => 101],
+            0 => ['uid' => 101, 'pid' => 0]
+        ]);
+        $this->matchCondition->__construct();
+        $loggerProphecy = $this->prophesize(Logger::class);
+        $this->matchCondition->setLogger($loggerProphecy->reveal());
+
+        $this->matchCondition->expects($this->once())->method('determinePageId')->willReturn(999);
+    }
+
+    /**
+     * Tests whether a faulty expression fails.
+     *
+     * @test
+     */
+    public function simulateDisabledMatchAllConditionsFailsOnFaultyExpression()
+    {
+        $this->assertFalse($this->matchCondition->match('[nullCondition = This expression would return FALSE in general]'));
+    }
+
+    /**
+     * Tests whether simulating positive matches for all conditions succeeds.
+     *
+     * @test
+     */
+    public function simulateEnabledMatchAllConditionsSucceeds()
+    {
+        $this->matchCondition->setSimulateMatchResult(true);
+        $this->assertTrue($this->matchCondition->match('[nullCondition = This expression would return FALSE in general]'));
+    }
+
+    /**
+     * Tests whether simulating positive matches for specific conditions succeeds.
+     *
+     * @test
+     */
+    public function simulateEnabledMatchSpecificConditionsSucceeds()
+    {
+        $testCondition = '[' . $this->getUniqueId('test') . ' = Any condition to simulate a positive match]';
+        $this->matchCondition->setSimulateMatchConditions([$testCondition]);
+        $this->assertTrue($this->matchCondition->match($testCondition));
+    }
+
+    /**
+     * Tests whether the language comparison matches.
+     *
+     * @test
+     */
+    public function languageConditionMatchesSingleLanguageExpression()
+    {
+        $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-de,de;q=0.8,en-us;q=0.5,en;q=0.3';
+        $this->assertTrue($this->matchCondition->match('[language = *de*]'));
+        $this->assertTrue($this->matchCondition->match('[language = *de-de*]'));
+        // Test expression language
+        // @TODO: this test fails, because setting values after init does not work
+        // $this->assertTrue($this->matchCondition->match('[like(request("getAttributes")["normalizedParams"].getHttpAcceptLanguage(), "**de*")]'));
+        // $this->assertTrue($this->matchCondition->match('[like(request("getAttributes")["normalizedParams"].getHttpAcceptLanguage(), "**de-de*")]'));
+    }
+
+    /**
+     * Tests whether the language comparison matches.
+     *
+     * @test
+     */
+    public function languageConditionMatchesMultipleLanguagesExpression()
+    {
+        $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-de,de;q=0.8,en-us;q=0.5,en;q=0.3';
+        $this->assertTrue($this->matchCondition->match('[language = *en*,*de*]'));
+        $this->assertTrue($this->matchCondition->match('[language = *en-us*,*de-de*]'));
+        // Test expression language
+        // @TODO: this test fails, because setting values after init does not work
+        // $this->assertTrue($this->matchCondition->match('[like(request("getAttributes")["normalizedParams"].getHttpAcceptLanguage(), "*en*,*de*")]'));
+        // $this->assertTrue($this->matchCondition->match('[like(request("getAttributes")["normalizedParams"].getHttpAcceptLanguage(), "*en-us*,*de-de*")]'));
+    }
+
+    /**
+     * Tests whether the language comparison matches.
+     *
+     * @test
+     */
+    public function languageConditionMatchesCompleteLanguagesExpression()
+    {
+        $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-de,de;q=0.8,en-us;q=0.5,en;q=0.3';
+        $this->assertTrue($this->matchCondition->match('[language = de-de,de;q=0.8,en-us;q=0.5,en;q=0.3]'));
+        // Test expression language
+        // @TODO: this test fails, because setting values after init does not work
+        // $this->assertTrue($this->matchCondition->match('[request("getAttributes")["normalizedParams"].getHttpAcceptLanguage() == "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"]'));
+    }
+
+    /**
+     * Tests whether usergroup comparison matches.
+     *
+     * @test
+     */
+    public function usergroupConditionMatchesSingleGroupId()
+    {
+        $this->assertTrue($this->matchCondition->match('[usergroup = 13]'));
+        // Test expression language
+        $this->assertTrue($this->matchCondition->match('[usergroup(13)]'));
+        $this->assertTrue($this->matchCondition->match('[usergroup("13")]'));
+        $this->assertTrue($this->matchCondition->match('[usergroup(\'13\')]'));
+    }
+
+    /**
+     * Tests whether usergroup comparison matches.
+     *
+     * @test
+     */
+    public function usergroupConditionMatchesMultipleUserGroupId()
+    {
+        $this->assertTrue($this->matchCondition->match('[usergroup = 999,15,14,13]'));
+        // Test expression language
+        $this->assertTrue($this->matchCondition->match('[usergroup("999,15,14,13")]'));
+        $this->assertTrue($this->matchCondition->match('[usergroup(\'999,15,14,13\')]'));
+    }
+
+    /**
+     * Tests whether user comparison matches.
+     *
+     * @test
+     */
+    public function loginUserConditionMatchesAnyLoggedInUser()
+    {
+        $this->assertTrue($this->matchCondition->match('[loginUser = *]'));
+        // Test expression language
+        $this->assertTrue($this->matchCondition->match('[loginUser("*")]'));
+        $this->assertTrue($this->matchCondition->match('[loginUser(\'*\')]'));
+    }
+
+    /**
+     * Tests whether user comparison matches.
+     *
+     * @test
+     */
+    public function loginUserConditionMatchesSingleLoggedInUser()
+    {
+        $this->assertTrue($this->matchCondition->match('[loginUser = 13]'));
+        // Test expression language
+        $this->assertTrue($this->matchCondition->match('[loginUser(13)]'));
+        $this->assertTrue($this->matchCondition->match('[loginUser("13")]'));
+        $this->assertTrue($this->matchCondition->match('[loginUser(\'13\')]'));
+    }
+
+    /**
+     * Tests whether user comparison matches.
+     *
+     * @test
+     */
+    public function loginUserConditionDoesNotMatchSingleLoggedInUser()
+    {
+        $GLOBALS['BE_USER']->user['uid'] = 13;
+        $this->assertFalse($this->matchCondition->match('[loginUser = 999]'));
+        // Test expression language
+        $this->assertFalse($this->matchCondition->match('[loginUser(999)]'));
+        $this->assertFalse($this->matchCondition->match('[loginUser("999")]'));
+        $this->assertFalse($this->matchCondition->match('[loginUser(\'999\')]'));
+    }
+
+    /**
+     * Tests whether user comparison matches.
+     *
+     * @test
+     */
+    public function loginUserConditionMatchesMultipleLoggedInUsers()
+    {
+        $this->assertTrue($this->matchCondition->match('[loginUser = 999,13]'));
+        // Test expression language
+        $this->assertTrue($this->matchCondition->match('[loginUser("999,13")]'));
+        $this->assertTrue($this->matchCondition->match('[loginUser(\'999,13\')]'));
+    }
+
+    /**
+     * Tests whether checkinf for an admin user matches
+     *
+     * @test
+     */
+    public function adminUserConditionMatchesAdminUser()
+    {
+        $this->assertTrue($this->matchCondition->match('[adminUser = 1]'));
+        // Test expression language
+        $this->assertTrue($this->matchCondition->match('[backend.user.isAdmin == true]'));
+        $this->assertTrue($this->matchCondition->match('[backend.user.isAdmin != false]'));
+        $this->assertTrue($this->matchCondition->match('[backend.user.isAdmin]'));
+    }
+
+    /**
+     * Tests whether checkinf for an admin user matches
+     *
+     * @test
+     */
+    public function adminUserConditionMatchesRegularUser()
+    {
+        $GLOBALS['BE_USER']->user['uid'] = 14;
+        $GLOBALS['BE_USER']->user['admin'] = 0;
+        $this->assertTrue($this->matchCondition->match('[adminUser = 0]'));
+    }
+
+    /**
+     * Tests whether checkinf for an admin user matches
+     *
+     * @test
+     */
+    public function adminUserConditionDoesNotMatchRegularUser()
+    {
+        $GLOBALS['BE_USER']->user['uid'] = 14;
+        $GLOBALS['BE_USER']->user['admin'] = 0;
+        $this->assertFalse($this->matchCondition->match('[adminUser = 1]'));
+    }
+
+    /**
+     * Tests whether numerical comparison matches.
+     *
+     * @test
+     */
+    public function globalVarConditionMatchesOnEqualExpression()
+    {
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10 = 10]'), '1');
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.1 = 10.1]'), '2');
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10 == 10]'), '3');
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.1 == 10.1]'), '4');
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:0 = 0]'), '5');
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:0 == 0]'), '6');
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether numerical comparison matches.
+     *
+     * @test
+     */
+    public function globalVarConditionMatchesOnEqualExpressionWithMultipleValues()
+    {
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10 = 10|20|30]'));
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.1 = 10.1|20.2|30.3]'));
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:20 = 10|20|30]'));
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:20.2 = 10.1|20.2|30.3]'));
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10 == 10|20|30]'));
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.1 == 10.1|20.2|30.3]'));
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:20 == 10|20|30]'));
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:20.2 == 10.1|20.2|30.3]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether numerical comparison matches.
+     *
+     * @test
+     */
+    public function globalVarConditionMatchesOnNotEqualExpression()
+    {
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10 != 20]'));
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.1 != 10.2]'));
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:0 != 1]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether numerical comparison does not match.
+     *
+     * @test
+     */
+    public function globalVarConditionDoesNotMatchOnNotEqualExpression()
+    {
+        $this->assertFalse($this->matchCondition->match('[globalVar = LIT:10 != 10]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether numerical comparison matches.
+     *
+     * @test
+     */
+    public function globalVarConditionMatchesOnNotEqualExpressionWithMultipleValues()
+    {
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10 != 20|30]'));
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.1 != 10.2|20.3]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether numerical comparison matches.
+     *
+     * @test
+     */
+    public function globalVarConditionMatchesOnLowerThanExpression()
+    {
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10 < 20]'));
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.1 < 10.2]'));
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:0 < 1]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether numerical comparison matches.
+     *
+     * @test
+     */
+    public function globalVarConditionMatchesOnLowerThanOrEqualExpression()
+    {
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10 <= 10]'));
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10 <= 20]'));
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.1 <= 10.1]'));
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.1 <= 10.2]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether numerical comparison matches.
+     *
+     * @test
+     */
+    public function globalVarConditionMatchesOnGreaterThanExpression()
+    {
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:20 > 10]'));
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.2 > 10.1]'));
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:1 > 0]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether numerical comparison matches.
+     *
+     * @test
+     */
+    public function globalVarConditionMatchesOnGreaterThanOrEqualExpression()
+    {
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10 >= 10]'));
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:20 >= 10]'));
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.1 >= 10.1]'));
+        $this->assertTrue($this->matchCondition->match('[globalVar = LIT:10.2 >= 10.1]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether numerical comparison matches.
+     *
+     * @test
+     */
+    public function globalVarConditionMatchesOnEmptyExpressionWithNoValueSet()
+    {
+        $testKey = $this->getUniqueId('test');
+        $this->assertTrue($this->matchCondition->match('[globalVar = GP:' . $testKey . '=]'));
+        $this->assertTrue($this->matchCondition->match('[globalVar = GP:' . $testKey . ' = ]'));
+        // Test expression language
+        // Access request by request() method
+    }
+
+    /**
+     * Tests whether numerical comparison matches.
+     *
+     * @test
+     */
+    public function globalVarConditionDoesNotMatchOnEmptyExpressionWithValueSetToZero()
+    {
+        $testKey = $this->getUniqueId('test');
+        $_GET = [];
+        $_POST = [$testKey => 0];
+        $this->assertFalse($this->matchCondition->match('[globalVar = GP:' . $testKey . '=]'));
+        $this->assertFalse($this->matchCondition->match('[globalVar = GP:' . $testKey . ' = ]'));
+    }
+
+    /**
+     * Tests whether string comparison matches.
+     *
+     * @test
+     */
+    public function globalStringConditionMatchesOnEqualExpression()
+    {
+        $this->assertTrue($this->matchCondition->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3.Test.Condition]'));
+        $this->assertFalse($this->matchCondition->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether string comparison matches.
+     *
+     * @test
+     */
+    public function globalStringConditionMatchesOnEmptyExpressionWithValueSetToEmptyString()
+    {
+        $testKey = $this->getUniqueId('test');
+        $_GET = [];
+        $_POST = [$testKey => ''];
+        $this->assertTrue($this->matchCondition->match('[globalString = GP:' . $testKey . '=]'));
+        $this->assertTrue($this->matchCondition->match('[globalString = GP:' . $testKey . ' = ]'));
+        // Test expression language
+        // Access request by request() method
+    }
+
+    /**
+     * Tests whether string comparison matches.
+     *
+     * @test
+     */
+    public function globalStringConditionMatchesOnEmptyLiteralExpressionWithValueSetToEmptyString()
+    {
+        $this->assertTrue($this->matchCondition->match('[globalString = LIT:=]'));
+        $this->assertTrue($this->matchCondition->match('[globalString = LIT: = ]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether string comparison matches.
+     *
+     * @test
+     */
+    public function globalStringConditionMatchesWildcardExpression()
+    {
+        $this->assertTrue($this->matchCondition->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3?Test?Condition]'));
+        $this->assertTrue($this->matchCondition->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3.T*t.Condition]'));
+        $this->assertTrue($this->matchCondition->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3?T*t?Condition]'));
+        // globalString is not implemented, because globalVar did the job
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether string comparison matches.
+     *
+     * @test
+     */
+    public function globalStringConditionMatchesRegularExpression()
+    {
+        $this->assertTrue($this->matchCondition->match('[globalString = LIT:TYPO3.Test.Condition = /^[A-Za-z3.]+$/]'));
+        $this->assertTrue($this->matchCondition->match('[globalString = LIT:TYPO3.Test.Condition = /^TYPO3\\..+Condition$/]'));
+        $this->assertFalse($this->matchCondition->match('[globalString = LIT:TYPO3.Test.Condition = /^FALSE/]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether string comparison matches.
+     *
+     * @test
+     */
+    public function globalStringConditionMatchesEmptyRegularExpression()
+    {
+        $testKey = $this->getUniqueId('test');
+        $_SERVER[$testKey] = '';
+        $this->assertTrue($this->matchCondition->match('[globalString = _SERVER|' . $testKey . ' = /^$/]'));
+        // Test expression language
+        // Access request by request() method
+    }
+
+    /**
+     * Tests whether treeLevel comparison matches.
+     *
+     * @test
+     */
+    public function treeLevelConditionMatchesSingleValue()
+    {
+        $this->matchCondition->setRootline($this->rootline);
+        $this->assertTrue($this->matchCondition->match('[treeLevel = 2]'));
+        // Test expression language
+        $this->assertTrue($this->matchCondition->match('[tree.level == 2]'));
+    }
+
+    /**
+     * Tests whether treeLevel comparison matches.
+     *
+     * @test
+     */
+    public function treeLevelConditionMatchesMultipleValues()
+    {
+        $this->matchCondition->setRootline($this->rootline);
+        $this->assertTrue($this->matchCondition->match('[treeLevel = 999,998,2]'));
+        // Test expression language
+        $this->assertTrue($this->matchCondition->match('[tree.level in [999,998,2]]'));
+    }
+
+    /**
+     * Tests whether treeLevel comparison matches.
+     *
+     * @test
+     */
+    public function treeLevelConditionDoesNotMatchFaultyValue()
+    {
+        $this->matchCondition->setRootline($this->rootline);
+        $this->assertFalse($this->matchCondition->match('[treeLevel = 999]'));
+        // Test expression language
+        $this->assertFalse($this->matchCondition->match('[treeLevel == 999]'));
+    }
+
+    /**
+     * Tests whether treeLevel comparison matches when creating new pages.
+     *
+     * @test
+     */
+    public function treeLevelConditionMatchesCurrentPageIdWhileEditingNewPage()
+    {
+        $GLOBALS['SOBE'] = $this->createMock(\TYPO3\CMS\Backend\Controller\EditDocumentController::class);
+        $GLOBALS['SOBE']->elementsData = [
+            [
+                'table' => 'pages',
+                'uid' => 'NEW4adc6021e37e7',
+                'pid' => 121,
+                'cmd' => 'new',
+                'deleteAccess' => 0
+            ]
+        ];
+        $GLOBALS['SOBE']->data = [];
+        $this->matchCondition->setRootline($this->rootline);
+        $this->matchCondition->setPageId(121);
+        $this->assertTrue($this->matchCondition->match('[treeLevel = 3]'));
+    }
+
+    /**
+     * Tests whether treeLevel comparison matches when creating new pages.
+     *
+     * @test
+     */
+    public function treeLevelConditionMatchesCurrentPageIdWhileSavingNewPage()
+    {
+        $GLOBALS['SOBE'] = $this->createMock(\TYPO3\CMS\Backend\Controller\EditDocumentController::class);
+        $GLOBALS['SOBE']->elementsData = [
+            [
+                'table' => 'pages',
+                /// 999 is the uid of the page that was just created
+                'uid' => 999,
+                'pid' => 121,
+                'cmd' => 'edit',
+                'deleteAccess' => 1
+            ]
+        ];
+        $GLOBALS['SOBE']->data = [
+            'pages' => [
+                'NEW4adc6021e37e7' => [
+                    'pid' => 121
+                ]
+            ]
+        ];
+        $this->matchCondition->setRootline($this->rootline);
+        $this->matchCondition->setPageId(121);
+        $this->assertTrue($this->matchCondition->match('[treeLevel = 3]'));
+    }
+
+    /**
+     * Tests whether a page Id is found in the previous rootline entries.
+     *
+     * @test
+     */
+    public function PIDupinRootlineConditionMatchesSinglePageIdInRootline()
+    {
+        $this->matchCondition->setRootline($this->rootline);
+        $this->matchCondition->setPageId(121);
+        $this->assertTrue($this->matchCondition->match('[PIDupinRootline = 111]'));
+        // Test expression language
+        $this->assertTrue($this->matchCondition->match('[111 in tree.rootLineIds]'));
+        $this->assertTrue($this->matchCondition->match('["111" in tree.rootLineIds]'));
+        $this->assertTrue($this->matchCondition->match('[\'111\' in tree.rootLineIds]'));
+    }
+
+    /**
+     * Tests whether a page Id is found in the previous rootline entries.
+     *
+     * @test
+     */
+    public function PIDupinRootlineConditionMatchesMultiplePageIdsInRootline()
+    {
+        $this->matchCondition->setRootline($this->rootline);
+        $this->matchCondition->setPageId(121);
+        $this->assertTrue($this->matchCondition->match('[PIDupinRootline = 999,111,101]'));
+        // Test expression language
+        $this->assertTrue($this->matchCondition->match('[999 in tree.rootLineIds][111 in tree.rootLineIds][101 in tree.rootLineIds]'));
+    }
+
+    /**
+     * Tests whether a page Id is found in the previous rootline entries.
+     *
+     * @test
+     */
+    public function PIDupinRootlineConditionDoesNotMatchPageIdNotInRootline()
+    {
+        $this->matchCondition->setRootline($this->rootline);
+        $this->matchCondition->setPageId(121);
+        $this->assertFalse($this->matchCondition->match('[PIDupinRootline = 999]'));
+        // Test expression language
+        $this->assertFalse($this->matchCondition->match('[999 in tree.rootLineIds]'));
+    }
+
+    /**
+     * Tests whether a page Id is found in the previous rootline entries.
+     *
+     * @test
+     */
+    public function PIDupinRootlineConditionDoesNotMatchLastPageIdInRootline()
+    {
+        $this->matchCondition->setRootline($this->rootline);
+        $this->matchCondition->setPageId(121);
+        $this->assertFalse($this->matchCondition->match('[PIDupinRootline = 121]'));
+        // Test expression language
+        // @TODO: this test fails, because setting values after init does not work
+        // $this->assertFalse($this->matchCondition->match('[page.uid != 121 && 121 in rootLineUids]'));
+    }
+
+    /**
+     * Tests whether a page Id is found in the previous rootline entries.
+     *
+     * @test
+     */
+    public function PIDupinRootlineConditionMatchesCurrentPageIdWhileEditingNewPage()
+    {
+        $GLOBALS['SOBE'] = $this->createMock(\TYPO3\CMS\Backend\Controller\EditDocumentController::class);
+        $GLOBALS['SOBE']->elementsData = [
+            [
+                'table' => 'pages',
+                'uid' => 'NEW4adc6021e37e7',
+                'pid' => 121,
+                'cmd' => 'new',
+                'deleteAccess' => 0
+            ]
+        ];
+        $GLOBALS['SOBE']->data = [];
+        $this->matchCondition->setRootline($this->rootline);
+        $this->matchCondition->setPageId(121);
+        $this->assertTrue($this->matchCondition->match('[PIDupinRootline = 121]'));
+        // Test expression language
+        // page is not available here because, page is initialized with BackendUtility::getRecord()
+        // $this->assertTrue($this->matchCondition->match('[page.uid != 999 && 999 in rootLineUids]'));
+    }
+
+    /**
+     * Tests whether a page Id is found in the previous rootline entries.
+     *
+     * @test
+     */
+    public function PIDupinRootlineConditionMatchesCurrentPageIdWhileSavingNewPage()
+    {
+        $GLOBALS['SOBE'] = $this->createMock(\TYPO3\CMS\Backend\Controller\EditDocumentController::class);
+        $GLOBALS['SOBE']->elementsData = [
+            [
+                'table' => 'pages',
+                /// 999 is the uid of the page that was just created
+                'uid' => 999,
+                'pid' => 121,
+                'cmd' => 'edit',
+                'deleteAccess' => 1
+            ]
+        ];
+        $GLOBALS['SOBE']->data = [
+            'pages' => [
+                'NEW4adc6021e37e7' => [
+                    'pid' => 121
+                ]
+            ]
+        ];
+        $this->matchCondition->setRootline($this->rootline);
+        $this->matchCondition->setPageId(121);
+        $this->assertTrue($this->matchCondition->match('[PIDupinRootline = 121]'));
+        // Test expression language
+        // page is not available here because, page is initialized with BackendUtility::getRecord()
+        // $this->assertTrue($this->matchCondition->match('[page.uid != 121 && 121 in rootLineUids]'));
+    }
+
+    /**
+     * Tests whether a page Id is found in all rootline entries.
+     *
+     * @test
+     */
+    public function PIDinRootlineConditionMatchesSinglePageIdInRootline()
+    {
+        $this->matchCondition->setRootline($this->rootline);
+        $this->matchCondition->setPageId(121);
+        $this->assertTrue($this->matchCondition->match('[PIDinRootline = 111]'));
+        // Test expression language
+        $this->assertTrue($this->matchCondition->match('[111 in tree.rootLineIds]'));
+    }
+
+    /**
+     * Tests whether a page Id is found in all rootline entries.
+     *
+     * @test
+     */
+    public function PIDinRootlineConditionMatchesMultiplePageIdsInRootline()
+    {
+        $this->matchCondition->setRootline($this->rootline);
+        $this->matchCondition->setPageId(121);
+        $this->assertTrue($this->matchCondition->match('[PIDinRootline = 999,111,101]'));
+        // Test expression language
+        $this->assertTrue($this->matchCondition->match('[999 in tree.rootLineIds][111 in tree.rootLineIds][101 in tree.rootLineIds]'));
+    }
+
+    /**
+     * Tests whether a page Id is found in all rootline entries.
+     *
+     * @test
+     */
+    public function PIDinRootlineConditionMatchesLastPageIdInRootline()
+    {
+        $this->matchCondition->setRootline($this->rootline);
+        $this->matchCondition->setPageId(121);
+        $this->assertTrue($this->matchCondition->match('[PIDinRootline = 121]'));
+        // Test expression language
+        $this->assertTrue($this->matchCondition->match('[121 in tree.rootLineIds]'));
+    }
+
+    /**
+     * Tests whether a page Id is found in all rootline entries.
+     *
+     * @test
+     */
+    public function PIDinRootlineConditionDoesNotMatchPageIdNotInRootline()
+    {
+        $this->matchCondition->setRootline($this->rootline);
+        $this->matchCondition->setPageId(121);
+        $this->assertFalse($this->matchCondition->match('[PIDinRootline = 999]'));
+        // Test expression language
+        $this->assertFalse($this->matchCondition->match('[999 in tree.rootLineIds]'));
+    }
+
+    /**
+     * Tests whether the compatibility version can be evaluated.
+     * (e.g. 7.9 is compatible to 7.0 but not to 15.0)
+     *
+     * @test
+     */
+    public function compatVersionConditionMatchesOlderRelease()
+    {
+        $this->assertTrue($this->matchCondition->match('[compatVersion = 7.0]'));
+        // Test expression language
+        $this->assertTrue($this->matchCondition->match('[compatVersion(7.0)]'));
+        $this->assertTrue($this->matchCondition->match('[compatVersion("7.0")]'));
+        $this->assertTrue($this->matchCondition->match('[compatVersion(\'7.0\')]'));
+    }
+
+    /**
+     * Tests whether the compatibility version can be evaluated.
+     * (e.g. 7.9 is compatible to 7.0 but not to 15.0)
+     *
+     * @test
+     */
+    public function compatVersionConditionMatchesSameRelease()
+    {
+        $this->assertTrue($this->matchCondition->match('[compatVersion = ' . TYPO3_branch . ']'));
+        // Test expression language
+        $this->assertTrue($this->matchCondition->match('[compatVersion(' . TYPO3_branch . ')]'));
+        $this->assertTrue($this->matchCondition->match('[compatVersion("' . TYPO3_branch . '")]'));
+        $this->assertTrue($this->matchCondition->match('[compatVersion(\'' . TYPO3_branch . '\')]'));
+    }
+
+    /**
+     * Tests whether the compatibility version can be evaluated.
+     * (e.g. 7.9 is compatible to 7.0 but not to 15.0)
+     *
+     * @test
+     */
+    public function compatVersionConditionDoesNotMatchNewerRelease()
+    {
+        $this->assertFalse($this->matchCondition->match('[compatVersion = 15.0]'));
+        // Test expression language
+        $this->assertFalse($this->matchCondition->match('[compatVersion(15.0)]'));
+        $this->assertFalse($this->matchCondition->match('[compatVersion("15.0")]'));
+        $this->assertFalse($this->matchCondition->match('[compatVersion(\'15.0\')]'));
+    }
+
+    /**
+     * Tests whether the generic fetching of variables works with the namespace 'GP'.
+     *
+     * @test
+     */
+    public function genericGetVariablesSucceedsWithNamespaceGP()
+    {
+        $_GET = ['testGet' => 'getTest'];
+        $_POST = ['testPost' => 'postTest'];
+        $this->assertTrue($this->matchCondition->match('[globalString = GP:testGet = getTest]'));
+        $this->assertTrue($this->matchCondition->match('[globalString = GP:testPost = postTest]'));
+    }
+
+    /**
+     * Tests whether the generic fetching of variables does not work with the namespace 'TSFE',
+     * since we are in the backend context here.
+     *
+     * @test
+     */
+    public function genericGetVariablesFailsWithNamespaceTSFE()
+    {
+        $GLOBALS['TSFE'] = new \stdClass();
+        $GLOBALS['TSFE']->id = 1234567;
+        $this->assertFalse($this->matchCondition->match('[globalString = TSFE:id = 1234567]'));
+    }
+
+    /**
+     * Tests whether the generic fetching of variables works with the namespace 'ENV'.
+     *
+     * @test
+     */
+    public function genericGetVariablesSucceedsWithNamespaceENV()
+    {
+        $testKey = $this->getUniqueId('test');
+        putenv($testKey . '=testValue');
+        $this->assertTrue($this->matchCondition->match('[globalString = ENV:' . $testKey . ' = testValue]'));
+        // Test expression language
+        $this->assertTrue($this->matchCondition->match('[getenv("' . $testKey . '") == "testValue"]'));
+    }
+
+    /**
+     * Tests whether the generic fetching of variables works with the namespace 'IENV'.
+     *
+     * @test
+     */
+    public function genericGetVariablesSucceedsWithNamespaceIENV()
+    {
+        $_SERVER['HTTP_HOST'] = GeneralUtility::getIndpEnv('TYPO3_HOST_ONLY') . ':1234567';
+        // getIndpEnv() is polluted after above call, clear cache to have it recalculate for subject execption
+        GeneralUtility::flushInternalRuntimeCaches();
+        $this->assertTrue($this->matchCondition->match('[globalString = IENV:TYPO3_PORT = 1234567]'));
+        // Test expression language
+        // Access to global variables is not possible in expression language
+    }
+
+    /**
+     * Tests whether the generic fetching of variables works with any global namespace.
+     *
+     * @test
+     */
+    public function genericGetVariablesSucceedsWithAnyGlobalNamespace()
+    {
+        $GLOBALS[$this->testGlobalNamespace] = [
+            'first' => 'testFirst',
+            'second' => ['third' => 'testThird']
+        ];
+        $this->assertTrue($this->matchCondition->match('[globalString = ' . $this->testGlobalNamespace . '|first = testFirst]'));
+        $this->assertTrue($this->matchCondition->match('[globalString = ' . $this->testGlobalNamespace . '|second|third = testThird]'));
+        // Test expression language
+        // Access to global variables is not possible in expression language, because access to $GLOBALS is bad...
+    }
+
+    /**
+     * Tests whether determining a pageId works.
+     *
+     * @test
+     */
+    public function pageIdCanBeDeterminedWhileCallingModuleWithPageTree()
+    {
+        $_GET['id'] = 999;
+        $this->matchCondition->match('[globalVar = LIT:10 = 10]');
+        $this->assertEquals(999, $this->matchCondition->getPageId());
+    }
+
+    /**
+     * Tests whether determining a pageId works.
+     *
+     * @test
+     */
+    public function pageIdCanBeDeterminedWhileEditingAPageRecord()
+    {
+        $_GET['edit']['pages'][999] = 'edit';
+        $this->matchCondition->match('[globalVar = LIT:10 = 10]');
+        $this->assertEquals(999, $this->matchCondition->getPageId());
+    }
+
+    /**
+     * Tests whether determining a pageId works.
+     *
+     * @test
+     */
+    public function pageIdCanBeDeterminedWhileEditingARegularRecord()
+    {
+        $this->setUpDatabaseMockForDeterminePageId();
+        $_GET['edit'][$this->testTableName][13] = 'edit';
+        $this->matchCondition->match('[globalVar = LIT:10 = 10]');
+        $this->assertEquals(999, $this->matchCondition->getPageId());
+    }
+
+    /**
+     * Tests whether determining a pageId works.
+     *
+     * @test
+     */
+    public function pageIdCanBeDeterminedWhileCreatingARecord()
+    {
+        $_GET['edit']['pages'][999] = 'new';
+        $this->matchCondition->match('[globalVar = LIT:10 = 10]');
+        $this->assertEquals(999, $this->matchCondition->getPageId());
+    }
+
+    /**
+     * Tests whether determining a pageId works.
+     *
+     * @test
+     */
+    public function pageIdCanBeDeterminedWhileCreatingARecordAfterAnExistingRecord()
+    {
+        $this->setUpDatabaseMockForDeterminePageId();
+        $_GET['edit'][$this->testTableName][-13] = 'new';
+        $this->matchCondition->match('[globalVar = LIT:10 = 10]');
+        $this->assertEquals(999, $this->matchCondition->getPageId());
+    }
+
+    /**
+     * Tests whether determining a pageId works.
+     *
+     * @test
+     */
+    public function pageIdCanBeDeterminedWhileDeletingAPageRecord()
+    {
+        $_GET['cmd']['pages'][999]['delete'] = 1;
+        $this->matchCondition->match('[globalVar = LIT:10 = 10]');
+        $this->assertEquals(999, $this->matchCondition->getPageId());
+    }
+
+    /**
+     * Tests whether determining a pageId works.
+     *
+     * @test
+     */
+    public function pageIdCanBeDeterminedWhileCopyingARecordToAnotherPage()
+    {
+        $_GET['cmd']['pages'][121]['copy'] = 999;
+        $this->matchCondition->match('[globalVar = LIT:10 = 10]');
+        $this->assertEquals(999, $this->matchCondition->getPageId());
+    }
+
+    /**
+     * Tests whether determining a pageId works.
+     *
+     * @test
+     */
+    public function pageIdCanBeDeterminedWhileCopyingARecordAfterAnExistingRecord()
+    {
+        $this->setUpDatabaseMockForDeterminePageId();
+        $_GET['cmd'][$this->testTableName][121]['copy'] = -13;
+        $this->matchCondition->match('[globalVar = LIT:10 = 10]');
+        $this->assertEquals(999, $this->matchCondition->getPageId());
+    }
+
+    /**
+     * Tests whether determining a pageId works.
+     *
+     * @test
+     */
+    public function pageIdCanBeDeterminedWhileMovingARecordToAnotherPage()
+    {
+        $_GET['cmd']['pages'][121]['move'] = 999;
+        $this->matchCondition->match('[globalVar = LIT:10 = 10]');
+        $this->assertEquals(999, $this->matchCondition->getPageId());
+    }
+
+    /**
+     * @test
+     */
+    public function matchCallsTestConditionAndHandsOverParameters()
+    {
+        $this->expectException(TestConditionException::class);
+        $this->expectExceptionCode(1476109533);
+        $this->matchCondition->match('[TYPO3\\CMS\\Backend\\Tests\\UnitDeprecated\\Configuration\\TypoScript\\ConditionMatching\\Fixtures\\TestCondition = 7, != 6]');
+    }
+}
diff --git a/typo3/sysext/backend/Tests/UnitDeprecated/Configuration/TypoScript/ConditionMatching/Fixtures/TestCondition.php b/typo3/sysext/backend/Tests/UnitDeprecated/Configuration/TypoScript/ConditionMatching/Fixtures/TestCondition.php
new file mode 100644 (file)
index 0000000..bfc8719
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+namespace TYPO3\CMS\Backend\Tests\UnitDeprecated\Configuration\TypoScript\ConditionMatching\Fixtures;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * Fixture for custom conditions
+ */
+class TestCondition extends \TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractCondition
+{
+    /**
+     * Test matcher tests input parameters.
+     *
+     * @param array $conditionParameters
+     * @throws TestConditionException
+     * @return bool
+     */
+    public function matchCondition(array $conditionParameters)
+    {
+        // Throw an exception if everything is fine, this exception is *expected* in the according unit test
+        if ($conditionParameters[0] === '= 7' && $conditionParameters[1] === '!= 6') {
+            throw new TestConditionException('All Ok', 1476109533);
+        }
+    }
+}
diff --git a/typo3/sysext/backend/Tests/UnitDeprecated/Configuration/TypoScript/ConditionMatching/Fixtures/TestConditionException.php b/typo3/sysext/backend/Tests/UnitDeprecated/Configuration/TypoScript/ConditionMatching/Fixtures/TestConditionException.php
new file mode 100644 (file)
index 0000000..ee2f039
--- /dev/null
@@ -0,0 +1,22 @@
+<?php
+namespace TYPO3\CMS\Backend\Tests\UnitDeprecated\Configuration\TypoScript\ConditionMatching\Fixtures;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * Exception thrown by TestCondition
+ */
+class TestConditionException extends \Exception
+{
+}
index c666b58..47f7f0f 100644 (file)
@@ -17,6 +17,7 @@ namespace TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching;
 use Psr\Log\LoggerAwareInterface;
 use Psr\Log\LoggerAwareTrait;
 use Symfony\Component\ExpressionLanguage\SyntaxError;
+use TYPO3\CMS\Core\Configuration\Features;
 use TYPO3\CMS\Core\ExpressionLanguage\Resolver;
 use TYPO3\CMS\Core\ExpressionLanguage\TypoScriptConditionProvider;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -74,6 +75,14 @@ abstract class AbstractConditionMatcher implements LoggerAwareInterface
     }
 
     /**
+     * @return bool
+     */
+    protected function strictSyntaxEnabled(): bool
+    {
+        return GeneralUtility::makeInstance(Features::class)->isFeatureEnabled('TypoScript.strictSyntax');
+    }
+
+    /**
      * Sets the id of the page to evaluate conditions for.
      *
      * @param int $pageId Id of the page (must be positive)
@@ -146,6 +155,7 @@ abstract class AbstractConditionMatcher implements LoggerAwareInterface
      *
      * @param string $expression The expression to be normalized (e.g. "[A] && [B] OR [C]")
      * @return string The normalized expression (e.g. "[A]&&[B]||[C]")
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function normalizeExpression($expression)
     {
@@ -189,8 +199,14 @@ abstract class AbstractConditionMatcher implements LoggerAwareInterface
         if ($normalizedExpression[0] === '[' && substr($normalizedExpression, -1) === ']') {
             $innerExpression = substr($normalizedExpression, 1, -1);
             $orParts = explode(']||[', $innerExpression);
+            if ($this->strictSyntaxEnabled() && count($orParts) > 1) {
+                trigger_error('Multiple conditions blocks combined with AND, OR, && or || have been deprecated and will be removed in TYPO3 CMS 10, use the new expression language.', E_USER_DEPRECATED);
+            }
             foreach ($orParts as $orPart) {
                 $andParts = explode(']&&[', $orPart);
+                if ($this->strictSyntaxEnabled() && count($andParts) > 1) {
+                    trigger_error('Multiple conditions blocks combined with AND, OR, && or || have been deprecated and will be removed in TYPO3 CMS 10, use the new expression language.', E_USER_DEPRECATED);
+                }
                 foreach ($andParts as $andPart) {
                     $result = $this->evaluateExpression($andPart);
                     if (!is_bool($result)) {
@@ -241,6 +257,7 @@ abstract class AbstractConditionMatcher implements LoggerAwareInterface
      * @param string $key The condition to match against its criteria.
      * @param string $value
      * @return bool|null Result of the evaluation; NULL if condition could not be evaluated
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function evaluateConditionCommon($key, $value)
     {
@@ -394,6 +411,7 @@ abstract class AbstractConditionMatcher implements LoggerAwareInterface
      * @param string $condition The condition to match
      * @return bool|null Result of the evaluation; NULL if condition could not be evaluated
      * @throws \TYPO3\CMS\Core\Configuration\TypoScript\Exception\InvalidTypoScriptConditionException
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function evaluateCustomDefinedCondition($condition)
     {
@@ -427,6 +445,7 @@ abstract class AbstractConditionMatcher implements LoggerAwareInterface
      *
      * @param string $arguments
      * @return array
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function parseUserFuncArguments($arguments)
     {
@@ -466,6 +485,7 @@ abstract class AbstractConditionMatcher implements LoggerAwareInterface
      *
      * @param array $vars
      * @return mixed Whatever value. If none, then NULL.
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function getVariableCommon(array $vars)
     {
@@ -514,6 +534,7 @@ abstract class AbstractConditionMatcher implements LoggerAwareInterface
      * @param string $test The value to compare with on the form [operator][number]. Eg. "< 123
      * @param float $leftValue The value on the left side
      * @return bool If $value is "50" and $test is "< 123" then it will return TRUE.
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function compareNumber($test, $leftValue)
     {
@@ -570,6 +591,7 @@ abstract class AbstractConditionMatcher implements LoggerAwareInterface
      * @param string $haystack The string in which to find $needle.
      * @param string $needle The string to find in $haystack
      * @return bool Returns TRUE if $needle matches or is found in (according to wildcards) in $haystack. Eg. if $haystack is "Netscape 6.5" and $needle is "Net*" or "Net*ape" then it returns TRUE.
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function searchStringWildcard($haystack, $needle)
     {
@@ -583,6 +605,7 @@ abstract class AbstractConditionMatcher implements LoggerAwareInterface
      * @param string $var Global var key, eg. "HTTP_GET_VAR" or "HTTP_GET_VARS|id" to get the GET parameter "id" back.
      * @param array $source Alternative array than $GLOBAL to get variables from.
      * @return mixed Whatever value. If none, then blank string.
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function getGlobal($var, $source = null)
     {
@@ -615,6 +638,7 @@ abstract class AbstractConditionMatcher implements LoggerAwareInterface
      * @param string $string The condition to match against its criteria.
      * @return bool Whether the condition matched
      * @see \TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser::parse()
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     abstract protected function evaluateCondition($string);
 
@@ -629,6 +653,7 @@ abstract class AbstractConditionMatcher implements LoggerAwareInterface
      *
      * @param string $name The name of the variable to fetch the value from
      * @return mixed The value of the given variable (string) or NULL if variable did not exist
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     abstract protected function getVariable($name);
 
@@ -636,6 +661,7 @@ abstract class AbstractConditionMatcher implements LoggerAwareInterface
      * Gets the usergroup list of the current user.
      *
      * @return string The usergroup list of the current user
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     abstract protected function getGroupList();
 
@@ -643,6 +669,7 @@ abstract class AbstractConditionMatcher implements LoggerAwareInterface
      * Determines the current page Id.
      *
      * @return int The current page Id
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     abstract protected function determinePageId();
 
@@ -650,6 +677,7 @@ abstract class AbstractConditionMatcher implements LoggerAwareInterface
      * Gets the properties for the current page.
      *
      * @return array The properties for the current page.
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     abstract protected function getPage();
 
@@ -657,6 +685,7 @@ abstract class AbstractConditionMatcher implements LoggerAwareInterface
      * 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.
      */
     abstract protected function determineRootline();
 
@@ -664,6 +693,7 @@ abstract class AbstractConditionMatcher implements LoggerAwareInterface
      * Gets the id of the current user.
      *
      * @return int The id of the current user
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     abstract protected function getUserId();
 
@@ -671,6 +701,7 @@ abstract class AbstractConditionMatcher implements LoggerAwareInterface
      * Determines if a user is logged in.
      *
      * @return bool Determines if a user is logged in
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     abstract protected function isUserLoggedIn();
 }
index d5763e8..8e604db 100644 (file)
@@ -2637,6 +2637,18 @@ class GeneralUtility
     }
 
     /**
+     * This method is only for testing and should never be used outside tests-
+     *
+     * @param $envName
+     * @param $value
+     * @internal
+     */
+    public static function setIndpEnv($envName, $value)
+    {
+        self::$indpEnvCache[$envName] = $value;
+    }
+
+    /**
      * Abstraction method which returns System Environment Variables regardless of server OS, CGI/MODULE version etc. Basically this is SERVER variables for most of them.
      * This should be used instead of getEnv() and $_SERVER/ENV_VARS to get reliable values for all situations.
      *
index 70e95d6..8d2d52e 100644 (file)
@@ -73,7 +73,8 @@ return [
         'folderCreateMask' => '2775',
         'features' => [
             'redirects.hitCount' => false,
-            'unifiedPageTranslationHandling' => false
+            'unifiedPageTranslationHandling' => false,
+            'TypoScript.strictSyntax' => true,
         ],
         'createGroup' => '',
         'sitename' => 'TYPO3',
index af73f9a..b908f70 100644 (file)
@@ -221,6 +221,9 @@ SYS:
               unifiedPageTranslationHandling:
                 type: bool
                 description: 'If on, TCA configuration for pages_language_overlay is never loaded and the database table "pages_language_overlay" is not created by core. Enable this feature if no extensions fiddles with table pages_language_overlay to have a slightly quicker system with less deprecation log entries.'
+              TypoScript.strictSyntax:
+                type: bool
+                description: 'If on, TypoScript is parsed in strict syntax modes. Enabling this feature means old condition syntax (which is deprecated) will trigger deprecation messages.'
         availablePasswordHashAlgorithms:
             type: array
             description: 'A list of available password hash mechanisms. Extensions may register additional mechanisms here. This is usually not extended in LocalConfiguration.php.'
index c199f49..64024a9 100644 (file)
@@ -33,10 +33,10 @@ Here are some examples to understand the power of the expression language:
    # This condition does match if "foo" **not** matches the regExp: `/bar/`
    [END]
 
-   [applicationContext == "Production"] && [userId == 15] && [globalVar('TSFE:id') == 125]
-   # This condition match if application context is "Production" AND logged in user has the uid 15 AND current page is 125
+   [applicationContext == "Production"] && [userId == 15]
+   # This condition match if application context is "Production" AND logged in user has the uid 15
    # This condition could also be combined in one condition:
-   # [applicationContext("Production") && userId == 15 && globalVar('TSFE:id') == 125]
+   # [applicationContext == "Production" && userId == 15]
    [END]
 
    [request.getNormalizedParams().getHttpHost() == 'typo3.org']
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-86068-DeprecateOldConditionSyntax.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-86068-DeprecateOldConditionSyntax.rst
new file mode 100644 (file)
index 0000000..028c1c0
--- /dev/null
@@ -0,0 +1,42 @@
+.. include:: ../../Includes.txt
+
+====================================================
+Deprecation: #86068 - Deprecate old condition syntax
+====================================================
+
+See :issue:`86068`
+
+Description
+===========
+
+The Symfony expression language is available for TypoScript since :issue:`85829` has been merged.
+Following that the classic TypoScript condition syntax has been deprecated.
+
+For detailed information about the new expression language see `#85829 <Feature-85829-ImplementSymfonyExpressionLanguageForTypoScriptConditions.rst>`_
+
+
+Impact
+======
+
+Using the old condition syntax will trigger a deprecation message.
+
+Also the combination of multiple condition blocks with ``AND``, ``OR``, ``&&`` and ``||`` has been
+deprecated and will trigger a deprecation message.
+
+To prevent deprecation messages use the new expression language for conditions. If this is not
+possible, the feature flag ``TypoScript.strictSyntax`` can be disabled.
+
+
+Affected Installations
+======================
+
+TYPO3 installations with extensions which define conditions using the old syntax or setups which
+make use of the old conditions.
+
+
+Migration
+=========
+
+The old conditions can be replaced with the new expression language.
+
+.. index:: Backend, Frontend, TSConfig, TypoScript, NotScanned, ext:core
index 11acd1b..a176f0e 100644 (file)
@@ -60,9 +60,13 @@ class AbstractConditionMatcherTest extends UnitTestCase
         $this->resetSingletonInstances = true;
         $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
 
-        $typoScriptConditionProvider = GeneralUtility::makeInstance(TypoScriptConditionProvider::class);
-
+        $this->initConditionMatcher();
         $this->backupApplicationContext = GeneralUtility::getApplicationContext();
+    }
+
+    protected function initConditionMatcher()
+    {
+        $typoScriptConditionProvider = GeneralUtility::makeInstance(TypoScriptConditionProvider::class);
         $this->conditionMatcher = $this->getMockForAbstractClass(AbstractConditionMatcher::class, [$typoScriptConditionProvider]);
         $this->evaluateConditionCommonMethod = new \ReflectionMethod(AbstractConditionMatcher::class, 'evaluateConditionCommon');
         $this->evaluateConditionCommonMethod->setAccessible(true);
@@ -309,11 +313,9 @@ class AbstractConditionMatcherTest extends UnitTestCase
         // Do not trigger proxy stuff of GeneralUtility::getIndPEnv
         unset($GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyIP']);
 
-        $_SERVER['REMOTE_ADDR'] = $actualIp;
+        GeneralUtility::setIndpEnv('REMOTE_ADDR', $actualIp);
         $GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask'] = $devIpMask;
-
-        $this->assertSame($expectedResult, $this->evaluateConditionCommonMethod->invokeArgs($this->conditionMatcher, ['IP', 'devIP']));
-        // Test expression language
+        $this->initConditionMatcher();
         $this->assertSame($expectedResult, $this->evaluateExpressionMethod->invokeArgs($this->conditionMatcher, ['ip("devIP")']));
     }
 
index f58ffbc..78885d7 100644 (file)
@@ -75,9 +75,14 @@ class ConditionMatcher extends AbstractConditionMatcher
      * @return bool Whether the condition matched
      * @see \TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser::parse()
      * @throws \TYPO3\CMS\Core\Configuration\TypoScript\Exception\InvalidTypoScriptConditionException
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function evaluateCondition($string)
     {
+        if ($this->strictSyntaxEnabled()) {
+            trigger_error('The old condition syntax has been deprecated and will be removed in TYPO3 CMS 10, use the new expression language. condition: [' . $string . ']', E_USER_DEPRECATED);
+        }
+
         list($key, $value) = GeneralUtility::trimExplode('=', $string, false, 2);
         $result = $this->evaluateConditionCommon($key, $value);
         if (is_bool($result)) {
@@ -179,6 +184,7 @@ class ConditionMatcher extends AbstractConditionMatcher
      *
      * @param string $var Identifier
      * @return mixed|null The value of the variable pointed to or NULL if variable did not exist
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function getVariable($var)
     {
@@ -215,6 +221,7 @@ class ConditionMatcher extends AbstractConditionMatcher
      *
      * @param string $var Session key
      * @return mixed|null The value of the variable pointed to or NULL if variable did not exist
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function getSessionVariable(string $var)
     {
@@ -241,6 +248,7 @@ class ConditionMatcher extends AbstractConditionMatcher
      * Get the usergroup list of the current user.
      *
      * @return string The usergroup list of the current user
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function getGroupList(): string
     {
@@ -253,6 +261,7 @@ class ConditionMatcher extends AbstractConditionMatcher
      * Determines the current page Id.
      *
      * @return int The current page Id
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function determinePageId()
     {
@@ -263,6 +272,7 @@ class ConditionMatcher extends AbstractConditionMatcher
      * Gets the properties for the current page.
      *
      * @return array The properties for the current page.
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function getPage()
     {
@@ -275,6 +285,7 @@ class ConditionMatcher extends AbstractConditionMatcher
      * 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()
     {
@@ -285,6 +296,7 @@ class ConditionMatcher extends AbstractConditionMatcher
      * Get the id of the current user.
      *
      * @return int The id of the current user
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function getUserId(): int
     {
@@ -296,6 +308,7 @@ class ConditionMatcher extends AbstractConditionMatcher
      * Determines if a user is logged in.
      *
      * @return bool Determines if a user is logged in
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function isUserLoggedIn(): bool
     {
@@ -306,6 +319,7 @@ class ConditionMatcher extends AbstractConditionMatcher
 
     /**
      * @return \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function getTypoScriptFrontendController()
     {
@@ -315,7 +329,7 @@ class ConditionMatcher extends AbstractConditionMatcher
     /**
      * Returns the currently configured "site language" if a site is configured (= resolved) in the current request.
      *
-     * @internal
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function getCurrentSiteLanguage(): ?SiteLanguage
     {
@@ -329,7 +343,7 @@ class ConditionMatcher extends AbstractConditionMatcher
     /**
      * Returns the currently configured site if a site is configured (= resolved) in the current request.
      *
-     * @internal
+     * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
      */
     protected function getCurrentSite(): ?Site
     {
index 5327d26..3fd3fc5 100644 (file)
@@ -16,16 +16,13 @@ namespace TYPO3\CMS\Frontend\Tests\Unit\Configuration\TypoScript\ConditionMatchi
  */
 
 use Prophecy\Argument;
-use TYPO3\CMS\Core\Configuration\TypoScript\Exception\InvalidTypoScriptConditionException;
 use TYPO3\CMS\Core\Context\Context;
 use TYPO3\CMS\Core\Context\UserAspect;
 use TYPO3\CMS\Core\Http\ServerRequest;
 use TYPO3\CMS\Core\Log\Logger;
 use TYPO3\CMS\Core\Site\Entity\Site;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication;
 use TYPO3\CMS\Frontend\Configuration\TypoScript\ConditionMatching\ConditionMatcher;
-use TYPO3\CMS\Frontend\Tests\Unit\Configuration\TypoScript\ConditionMatching\Fixtures\TestConditionException;
 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
 
 /**
@@ -43,9 +40,13 @@ class ConditionMatcherTest extends UnitTestCase
      */
     protected $testGlobalNamespace;
 
+    /**
+     * @var bool Reset singletons
+     */
+    protected $resetSingletonInstances = true;
+
     protected function setUp(): void
     {
-        $this->resetSingletonInstances = true;
         $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
 
         $this->testGlobalNamespace = $this->getUniqueId('TEST');
@@ -78,91 +79,6 @@ class ConditionMatcherTest extends UnitTestCase
     }
 
     /**
-     * Tests whether a faulty expression fails.
-     *
-     * @test
-     */
-    public function simulateDisabledMatchAllConditionsFailsOnFaultyExpression(): void
-    {
-        $this->getFreshConditionMatcher();
-        $this->assertFalse($this->subject->match('[nullCondition = This expression would return FALSE in general]'));
-    }
-
-    /**
-     * Tests whether simulating positive matches for all conditions succeeds.
-     *
-     * @test
-     */
-    public function simulateEnabledMatchAllConditionsSucceeds(): void
-    {
-        $this->getFreshConditionMatcher();
-        $this->subject->setSimulateMatchResult(true);
-        $this->assertTrue($this->subject->match('[nullCondition = This expression would return FALSE in general]'));
-    }
-
-    /**
-     * Tests whether simulating positive matches for specific conditions succeeds.
-     *
-     * @test
-     */
-    public function simulateEnabledMatchSpecificConditionsSucceeds(): void
-    {
-        $this->getFreshConditionMatcher();
-        $testCondition = '[' . $this->getUniqueId('test') . ' = Any condition to simulate a positive match]';
-        $this->subject->setSimulateMatchConditions([$testCondition]);
-        $this->assertTrue($this->subject->match($testCondition));
-    }
-
-    /**
-     * Tests whether the language comparison matches.
-     *
-     * @test
-     */
-    public function languageConditionMatchesSingleLanguageExpression(): void
-    {
-        $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-de,de;q=0.8,en-us;q=0.5,en;q=0.3';
-        $this->getFreshConditionMatcher();
-        $this->assertTrue($this->subject->match('[language = *de*]'));
-        $this->assertTrue($this->subject->match('[language = *de-de*]'));
-        // Test expression language
-        // @TODO: not work yet, looks like test setup issue
-//        $this->assertTrue($this->subject->match('[like(request.getNormalizedParams().getHttpAcceptLanguage(), "**de*")]'));
-//        $this->assertTrue($this->subject->match('[like(request.getNormalizedParams().getHttpAcceptLanguage(), "**de-de*")]'));
-    }
-
-    /**
-     * Tests whether the language comparison matches.
-     *
-     * @test
-     */
-    public function languageConditionMatchesMultipleLanguagesExpression(): void
-    {
-        $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-de,de;q=0.8,en-us;q=0.5,en;q=0.3';
-        $this->getFreshConditionMatcher();
-        $this->assertTrue($this->subject->match('[language = *en*,*de*]'));
-        $this->assertTrue($this->subject->match('[language = *en-us*,*de-de*]'));
-        // Test expression language
-        // @TODO: not work yet, looks like test setup issue
-//        $this->assertTrue($this->subject->match('[like(request.getNormalizedParams().getHttpAcceptLanguage(), "*en*,*de*")]'));
-//        $this->assertTrue($this->subject->match('[like(request.getNormalizedParams().getHttpAcceptLanguage(), "*en-us*,*de-de*")]'));
-    }
-
-    /**
-     * Tests whether the language comparison matches.
-     *
-     * @test
-     */
-    public function languageConditionMatchesCompleteLanguagesExpression(): void
-    {
-        $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-de,de;q=0.8,en-us;q=0.5,en;q=0.3';
-        $this->getFreshConditionMatcher();
-        $this->assertTrue($this->subject->match('[language = de-de,de;q=0.8,en-us;q=0.5,en;q=0.3]'));
-        // Test expression language
-        // @TODO: not work yet, looks like test setup issue
-//        $this->assertTrue($this->subject->match('[request.getNormalizedParams().getHttpAcceptLanguage() == "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"]'));
-    }
-
-    /**
      * Tests whether usergroup comparison matches.
      *
      * @test
@@ -174,8 +90,6 @@ class ConditionMatcherTest extends UnitTestCase
         ]));
         $loggerProphecy = $this->prophesize(Logger::class);
         $subject->setLogger($loggerProphecy->reveal());
-        $this->assertTrue($subject->match('[usergroup = 13]'));
-        // Test expression language
         $this->assertTrue($subject->match('[usergroup(13)]'));
         $this->assertTrue($subject->match('[usergroup("13")]'));
         $this->assertTrue($subject->match('[usergroup(\'13\')]'));
@@ -193,8 +107,6 @@ class ConditionMatcherTest extends UnitTestCase
         ]));
         $loggerProphecy = $this->prophesize(Logger::class);
         $subject->setLogger($loggerProphecy->reveal());
-        $this->assertTrue($subject->match('[usergroup = 999,15,14,13]'));
-        // Test expression language
         $this->assertFalse($subject->match('[usergroup(999,15,14,13)]'));
         $this->assertTrue($subject->match('[usergroup("999,15,14,13")]'));
         $this->assertTrue($subject->match('[usergroup(\'999,15,14,13\')]'));
@@ -212,8 +124,6 @@ class ConditionMatcherTest extends UnitTestCase
         ]));
         $loggerProphecy = $this->prophesize(Logger::class);
         $subject->setLogger($loggerProphecy->reveal());
-        $this->assertFalse($subject->match('[usergroup = 0,-1]'));
-        // Test expression language
         $this->assertFalse($subject->match('[usergroup("0,-1")]'));
         $this->assertFalse($subject->match('[usergroup(\'0,-1\')]'));
     }
@@ -226,9 +136,6 @@ class ConditionMatcherTest extends UnitTestCase
     public function loginUserConditionMatchesAnyLoggedInUser(): void
     {
         $this->getFreshConditionMatcher();
-        // @TODO: not work yet, looks like test setup issue
-        $this->assertTrue($this->subject->match('[loginUser = *]'));
-        // Test expression language
         $this->assertTrue($this->subject->match('[loginUser("*")]'));
         $this->assertTrue($this->subject->match('[loginUser(\'*\')]'));
     }
@@ -241,9 +148,6 @@ class ConditionMatcherTest extends UnitTestCase
     public function loginUserConditionMatchesSingleLoggedInUser(): void
     {
         $this->getFreshConditionMatcher();
-        // @TODO: not work yet, looks like test setup issue
-        $this->assertTrue($this->subject->match('[loginUser = 13]'));
-        // Test expression language
         $this->assertTrue($this->subject->match('[loginUser(13)]'));
         $this->assertTrue($this->subject->match('[loginUser("13")]'));
         $this->assertTrue($this->subject->match('[loginUser(\'13\')]'));
@@ -257,9 +161,6 @@ class ConditionMatcherTest extends UnitTestCase
     public function loginUserConditionMatchesMultipleLoggedInUsers(): void
     {
         $this->getFreshConditionMatcher();
-        // @TODO: not work yet, looks like test setup issue
-        $this->assertTrue($this->subject->match('[loginUser = 999,13]'));
-        // Test expression language
         $this->assertTrue($this->subject->match('[loginUser("999,13")]'));
         $this->assertTrue($this->subject->match('[loginUser(\'999,13\')]'));
     }
@@ -278,9 +179,6 @@ class ConditionMatcherTest extends UnitTestCase
         ]));
         $loggerProphecy = $this->prophesize(Logger::class);
         $subject->setLogger($loggerProphecy->reveal());
-        $this->assertFalse($subject->match('[loginUser = *]'));
-        $this->assertFalse($subject->match('[loginUser = 13]'));
-        // Test expression language
         $this->assertFalse($subject->match('[loginUser("*")]'));
         $this->assertTrue($subject->match('[loginUser("*") == false]'));
         $this->assertFalse($subject->match('[loginUser("13")]'));
@@ -301,271 +199,17 @@ class ConditionMatcherTest extends UnitTestCase
         ]));
         $loggerProphecy = $this->prophesize(Logger::class);
         $subject->setLogger($loggerProphecy->reveal());
-        $this->assertTrue($subject->match('[loginUser = ]'));
-        // Test expression language
         $this->assertTrue($subject->match('[loginUser(\'*\') == false]'));
         $this->assertTrue($subject->match('[loginUser("*") == false]'));
     }
 
     /**
-     * Tests whether numerical comparison matches.
-     *
-     * @test
-     */
-    public function globalVarConditionMatchesOnEqualExpression(): void
-    {
-        $this->assertTrue($this->subject->match('[globalVar = LIT:10 = 10]'));
-        $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 = 10.1]'));
-        $this->assertTrue($this->subject->match('[globalVar = LIT:10 == 10]'));
-        $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 == 10.1]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether numerical comparison matches.
-     *
-     * @test
-     */
-    public function globalVarConditionMatchesOnEqualExpressionWithMultipleValues(): void
-    {
-        $this->assertTrue($this->subject->match('[globalVar = LIT:10 = 10|20|30]'));
-        $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 = 10.1|20.2|30.3]'));
-        $this->assertTrue($this->subject->match('[globalVar = LIT:20 = 10|20|30]'));
-        $this->assertTrue($this->subject->match('[globalVar = LIT:20.2 = 10.1|20.2|30.3]'));
-        $this->assertTrue($this->subject->match('[globalVar = LIT:10 == 10|20|30]'));
-        $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 == 10.1|20.2|30.3]'));
-        $this->assertTrue($this->subject->match('[globalVar = LIT:20 == 10|20|30]'));
-        $this->assertTrue($this->subject->match('[globalVar = LIT:20.2 == 10.1|20.2|30.3]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether numerical comparison matches.
-     *
-     * @test
-     */
-    public function globalVarConditionMatchesOnNotEqualExpression(): void
-    {
-        $this->assertTrue($this->subject->match('[globalVar = LIT:10 != 20]'));
-        $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 != 10.2]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether numerical comparison does not match.
-     *
-     * @test
-     */
-    public function globalVarConditionDoesNotMatchOnNotEqualExpression(): void
-    {
-        $this->assertFalse($this->subject->match('[globalVar = LIT:10 != 10]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether numerical comparison matches.
-     *
-     * @test
-     */
-    public function globalVarConditionMatchesOnNotEqualExpressionWithMultipleValues(): void
-    {
-        $this->assertTrue($this->subject->match('[globalVar = LIT:10 != 20|30]'));
-        $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 != 10.2|20.3]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether numerical comparison matches.
-     *
-     * @test
-     */
-    public function globalVarConditionMatchesOnLowerThanExpression(): void
-    {
-        $this->assertTrue($this->subject->match('[globalVar = LIT:10 < 20]'));
-        $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 < 10.2]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether numerical comparison matches.
-     *
-     * @test
-     */
-    public function globalVarConditionMatchesOnLowerThanOrEqualExpression(): void
-    {
-        $this->assertTrue($this->subject->match('[globalVar = LIT:10 <= 10]'));
-        $this->assertTrue($this->subject->match('[globalVar = LIT:10 <= 20]'));
-        $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 <= 10.1]'));
-        $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 <= 10.2]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether numerical comparison matches.
-     *
-     * @test
-     */
-    public function globalVarConditionMatchesOnGreaterThanExpression(): void
-    {
-        $this->assertTrue($this->subject->match('[globalVar = LIT:20 > 10]'));
-        $this->assertTrue($this->subject->match('[globalVar = LIT:10.2 > 10.1]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether numerical comparison matches.
-     *
-     * @test
-     */
-    public function globalVarConditionMatchesOnGreaterThanOrEqualExpression(): void
-    {
-        $this->assertTrue($this->subject->match('[globalVar = LIT:10 >= 10]'));
-        $this->assertTrue($this->subject->match('[globalVar = LIT:20 >= 10]'));
-        $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 >= 10.1]'));
-        $this->assertTrue($this->subject->match('[globalVar = LIT:10.2 >= 10.1]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether numerical comparison matches.
-     *
-     * @test
-     */
-    public function globalVarConditionMatchesOnEmptyExpressionWithNoValueSet(): void
-    {
-        $testKey = $this->getUniqueId('test');
-        $this->assertTrue($this->subject->match('[globalVar = GP:' . $testKey . '=]'));
-        $this->assertTrue($this->subject->match('[globalVar = GP:' . $testKey . ' = ]'));
-    }
-
-    /**
-     * Tests whether numerical comparison matches.
-     *
-     * @test
-     */
-    public function globalVarConditionDoesNotMatchOnEmptyExpressionWithValueSetToZero(): void
-    {
-        $testKey = $this->getUniqueId('test');
-        $_GET = [];
-        $_POST = [$testKey => 0];
-        $this->assertFalse($this->subject->match('[globalVar = GP:' . $testKey . '=]'));
-        $this->assertFalse($this->subject->match('[globalVar = GP:' . $testKey . ' = ]'));
-    }
-
-    /**
-     * Tests whether an array with zero as key matches its value
-     *
-     * @test
-     */
-    public function globalVarConditionMatchesOnArrayExpressionWithZeroAsKey(): void
-    {
-        $testKey = $this->getUniqueId('test');
-        $testValue = '1';
-        $_GET = [];
-        $_POST = [$testKey => ['0' => $testValue]];
-        $this->assertTrue($this->subject->match('[globalVar = GP:' . $testKey . '|0=' . $testValue . ']'));
-    }
-
-    /**
-     * Tests whether string comparison matches.
-     *
-     * @test
-     */
-    public function globalStringConditionMatchesOnEqualExpression(): void
-    {
-        $this->assertTrue($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3.Test.Condition]'));
-        $this->assertFalse($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether string comparison matches.
-     *
-     * @test
-     */
-    public function globalStringConditionMatchesOnEmptyExpressionWithValueSetToEmptyString(): void
-    {
-        $testKey = $this->getUniqueId('test');
-        $_GET = [];
-        $_POST = [$testKey => ''];
-        $this->assertTrue($this->subject->match('[globalString = GP:' . $testKey . '=]'));
-        $this->assertTrue($this->subject->match('[globalString = GP:' . $testKey . ' = ]'));
-    }
-
-    /**
-     * Tests whether string comparison matches.
-     *
-     * @test
-     */
-    public function globalStringConditionMatchesOnEmptyLiteralExpressionWithValueSetToEmptyString(): void
-    {
-        $this->assertTrue($this->subject->match('[globalString = LIT:=]'));
-        $this->assertTrue($this->subject->match('[globalString = LIT: = ]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether string comparison matches.
-     *
-     * @test
-     */
-    public function globalStringConditionMatchesWildcardExpression(): void
-    {
-        $this->assertTrue($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3?Test?Condition]'));
-        $this->assertTrue($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3.T*t.Condition]'));
-        $this->assertTrue($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3?T*t?Condition]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether string comparison matches.
-     *
-     * @test
-     */
-    public function globalStringConditionMatchesRegularExpression(): void
-    {
-        $this->assertTrue($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = /^[A-Za-z3.]+$/]'));
-        $this->assertTrue($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = /^TYPO3\\..+Condition$/]'));
-        $this->assertFalse($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = /^FALSE/]'));
-        // Test expression language
-        // Access with LIT is not possible in expression language, because constants available as variable
-    }
-
-    /**
-     * Tests whether string comparison matches.
-     *
-     * @test
-     */
-    public function globalStringConditionMatchesEmptyRegularExpression(): void
-    {
-        $testKey = $this->getUniqueId('test');
-        $GLOBALS['_SERVER'][$testKey] = '';
-        $this->assertTrue($this->subject->match('[globalString = _SERVER|' . $testKey . ' = /^$/]'));
-        // Test expression language
-        // Access request by request() method
-    }
-
-    /**
      * Tests whether treeLevel comparison matches.
      *
      * @test
      */
     public function treeLevelConditionMatchesSingleValue(): void
     {
-        $this->assertTrue($this->subject->match('[treeLevel = 2]'));
-        // Test expression language
         $this->assertTrue($this->subject->match('[tree.level == 2]'));
     }
 
@@ -576,8 +220,6 @@ class ConditionMatcherTest extends UnitTestCase
      */
     public function treeLevelConditionMatchesMultipleValues(): void
     {
-        $this->assertTrue($this->subject->match('[treeLevel = 999,998,2]'));
-        // Test expression language
         $this->assertTrue($this->subject->match('[tree.level in [999,998,2]]'));
     }
 
@@ -588,37 +230,10 @@ class ConditionMatcherTest extends UnitTestCase
      */
     public function treeLevelConditionDoesNotMatchFaultyValue(): void
     {
-        $this->assertFalse($this->subject->match('[treeLevel = 999]'));
-        // Test expression language
         $this->assertFalse($this->subject->match('[tree.level == 999]'));
     }
 
     /**
-     * @return array
-     */
-    public function pageDataProvider(): array
-    {
-        return [
-            '[page|layout = 0]' => ['[page|layout = 0]', true],
-            '[page|layout = 1]' => ['[page|layout = 1]', false],
-            '[page|title = Foo]' => ['[page|title = Foo]', true],
-        ];
-    }
-
-    /**
-     * @test
-     * @dataProvider pageDataProvider
-     * @param string $expression
-     * @param bool $expected
-     */
-    public function checkConditionMatcherForPage(string $expression, bool $expected): void
-    {
-        $GLOBALS['TSFE']->page = ['title' => 'Foo', 'layout' => 0];
-        $this->getFreshConditionMatcher();
-        $this->assertSame($expected, $this->subject->match($expression));
-    }
-
-    /**
      * Tests whether a page Id is found in the previous rootline entries.
      *
      * @test
@@ -627,8 +242,6 @@ class ConditionMatcherTest extends UnitTestCase
     {
         $GLOBALS['TSFE']->id = 121;
         $this->getFreshConditionMatcher();
-        $this->assertTrue($this->subject->match('[PIDupinRootline = 111]'));
-        // Test expression language
         $this->assertTrue($this->subject->match('[111 in tree.rootLineIds]'));
         $this->assertTrue($this->subject->match('["111" in tree.rootLineIds]'));
         $this->assertTrue($this->subject->match('[\'111\' in tree.rootLineIds]'));
@@ -639,44 +252,14 @@ class ConditionMatcherTest extends UnitTestCase
      *
      * @test
      */
-    public function PIDupinRootlineConditionMatchesMultiplePageIdsInRootline(): void
-    {
-        $GLOBALS['TSFE']->id = 121;
-        $this->getFreshConditionMatcher();
-        $this->assertTrue($this->subject->match('[PIDupinRootline = 999,111,101]'));
-        // Test expression language
-        $this->assertTrue($this->subject->match('[999 in tree.rootLineIds][111 in tree.rootLineIds][101 in tree.rootLineIds]'));
-    }
-
-    /**
-     * Tests whether a page Id is found in the previous rootline entries.
-     *
-     * @test
-     */
     public function PIDupinRootlineConditionDoesNotMatchPageIdNotInRootline(): void
     {
         $GLOBALS['TSFE']->id = 121;
         $this->getFreshConditionMatcher();
-        $this->assertFalse($this->subject->match('[PIDupinRootline = 999]'));
-        // Test expression language
         $this->assertFalse($this->subject->match('[999 in tree.rootLineIds]'));
     }
 
     /**
-     * Tests whether a page Id is found in the previous rootline entries.
-     *
-     * @test
-     */
-    public function PIDupinRootlineConditionDoesNotMatchLastPageIdInRootline(): void
-    {
-        $GLOBALS['TSFE']->id = 121;
-        $this->getFreshConditionMatcher();
-        $this->assertFalse($this->subject->match('[PIDupinRootline = 121]'));
-        // Test expression language
-        $this->assertFalse($this->subject->match('[page.uid != 121 && 121 in rootLineUids]'));
-    }
-
-    /**
      * Tests whether a page Id is found in all rootline entries.
      *
      * @test
@@ -685,8 +268,6 @@ class ConditionMatcherTest extends UnitTestCase
     {
         $GLOBALS['TSFE']->id = 121;
         $this->getFreshConditionMatcher();
-        $this->assertTrue($this->subject->match('[PIDinRootline = 111]'));
-        // Test expression language
         $this->assertTrue($this->subject->match('[111 in tree.rootLineIds]'));
     }
 
@@ -695,26 +276,10 @@ class ConditionMatcherTest extends UnitTestCase
      *
      * @test
      */
-    public function PIDinRootlineConditionMatchesMultiplePageIdsInRootline(): void
-    {
-        $GLOBALS['TSFE']->id = 121;
-        $this->getFreshConditionMatcher();
-        $this->assertTrue($this->subject->match('[PIDinRootline = 999,111,101]'));
-        // Test expression language
-        $this->assertTrue($this->subject->match('[999 in tree.rootLineIds][111 in tree.rootLineIds][101 in tree.rootLineIds]'));
-    }
-
-    /**
-     * Tests whether a page Id is found in all rootline entries.
-     *
-     * @test
-     */
     public function PIDinRootlineConditionMatchesLastPageIdInRootline(): void
     {
         $GLOBALS['TSFE']->id = 121;
         $this->getFreshConditionMatcher();
-        $this->assertTrue($this->subject->match('[PIDinRootline = 121]'));
-        // Test expression language
         $this->assertTrue($this->subject->match('[121 in tree.rootLineIds]'));
     }
 
@@ -726,8 +291,6 @@ class ConditionMatcherTest extends UnitTestCase
     public function PIDinRootlineConditionDoesNotMatchPageIdNotInRootline(): void
     {
         $GLOBALS['TSFE']->id = 121;
-        $this->assertFalse($this->subject->match('[PIDinRootline = 999]'));
-        // Test expression language
         $this->assertFalse($this->subject->match('[999 in tree.rootLineIds]'));
     }
 
@@ -739,8 +302,6 @@ class ConditionMatcherTest extends UnitTestCase
      */
     public function compatVersionConditionMatchesOlderRelease(): void
     {
-        $this->assertTrue($this->subject->match('[compatVersion = 7.0]'));
-        // Test expression language
         $this->assertTrue($this->subject->match('[compatVersion(7.0)]'));
         $this->assertTrue($this->subject->match('[compatVersion("7.0")]'));
         $this->assertTrue($this->subject->match('[compatVersion(\'7.0\')]'));
@@ -754,8 +315,6 @@ class ConditionMatcherTest extends UnitTestCase
      */
     public function compatVersionConditionMatchesSameRelease(): void
     {
-        $this->assertTrue($this->subject->match('[compatVersion = ' . TYPO3_branch . ']'));
-        // Test expression language
         $this->assertTrue($this->subject->match('[compatVersion(' . TYPO3_branch . ')]'));
     }
 
@@ -767,28 +326,12 @@ class ConditionMatcherTest extends UnitTestCase
      */
     public function compatVersionConditionDoesNotMatchNewerRelease(): void
     {
-        $this->assertFalse($this->subject->match('[compatVersion = 15.0]'));
-        // Test expression language
         $this->assertFalse($this->subject->match('[compatVersion(15.0)]'));
         $this->assertFalse($this->subject->match('[compatVersion("15.0")]'));
         $this->assertFalse($this->subject->match('[compatVersion(\'15.0\')]'));
     }
 
     /**
-     * Tests whether the generic fetching of variables works with the namespace 'GP'.
-     *
-     * @test
-     */
-    public function genericGetVariablesSucceedsWithNamespaceGP(): void
-    {
-        $_GET = ['testGet' => 'getTest'];
-        $_POST = ['testPost' => 'postTest'];
-        $this->getFreshConditionMatcher();
-        $this->assertTrue($this->subject->match('[globalString = GP:testGet = getTest]'));
-        $this->assertTrue($this->subject->match('[globalString = GP:testPost = postTest]'));
-    }
-
-    /**
      * Tests whether the generic fetching of variables works with the namespace 'TSFE'.
      *
      * @test
@@ -800,9 +343,6 @@ class ConditionMatcherTest extends UnitTestCase
         $GLOBALS['TSFE']->testSimpleObject->testSimpleVariable = 'testValue';
 
         $this->getFreshConditionMatcher();
-        $this->assertTrue($this->subject->match('[globalString = TSFE:id = 1234567]'));
-        $this->assertTrue($this->subject->match('[globalString = TSFE:testSimpleObject|testSimpleVariable = testValue]'));
-        // Test expression language
         $this->assertTrue($this->subject->match('[getTSFE().id == 1234567]'));
         $this->assertTrue($this->subject->match('[getTSFE().testSimpleObject.testSimpleVariable == "testValue"]'));
     }
@@ -819,8 +359,6 @@ class ConditionMatcherTest extends UnitTestCase
         $GLOBALS['TSFE']->fe_user = $prophecy->reveal();
 
         $this->getFreshConditionMatcher();
-        $this->assertTrue($this->subject->match('[globalString = session:foo|bar = 1234567]'));
-        // Test expression language
         $this->assertTrue($this->subject->match('[session("foo|bar") == 1234567]'));
     }
 
@@ -834,45 +372,10 @@ class ConditionMatcherTest extends UnitTestCase
         $testKey = $this->getUniqueId('test');
         putenv($testKey . '=testValue');
         $this->getFreshConditionMatcher();
-        $this->assertTrue($this->subject->match('[globalString = ENV:' . $testKey . ' = testValue]'));
-        // Test expression language
         $this->assertTrue($this->subject->match('[getenv("' . $testKey . '") == "testValue"]'));
     }
 
     /**
-     * Tests whether the generic fetching of variables works with the namespace 'IENV'.
-     *
-     * @test
-     */
-    public function genericGetVariablesSucceedsWithNamespaceIENV(): void
-    {
-        $_SERVER['HTTP_HOST'] = GeneralUtility::getIndpEnv('TYPO3_HOST_ONLY') . ':1234567';
-        // getIndpEnv() is polluted after above call, clear cache to have it recalculate for subject execption
-        GeneralUtility::flushInternalRuntimeCaches();
-        $this->getFreshConditionMatcher();
-        $this->assertTrue($this->subject->match('[globalString = IENV:TYPO3_PORT = 1234567]'));
-        // Test expression language
-        // @TODO: not work yet, looks like test setup issue
-//        $this->assertTrue($this->subject->match('[request.getNormalizedParams().getRequestPort() == 1234567]'));
-    }
-
-    /**
-     * Tests whether the generic fetching of variables works with any global namespace.
-     *
-     * @test
-     */
-    public function genericGetVariablesSucceedsWithAnyGlobalNamespace(): void
-    {
-        $GLOBALS[$this->testGlobalNamespace] = [
-            'first' => 'testFirst',
-            'second' => ['third' => 'testThird']
-        ];
-        $this->getFreshConditionMatcher();
-        $this->assertTrue($this->subject->match('[globalString = ' . $this->testGlobalNamespace . '|first = testFirst]'));
-        $this->assertTrue($this->subject->match('[globalString = ' . $this->testGlobalNamespace . '|second|third = testThird]'));
-    }
-
-    /**
      * Tests whether any property of a site language matches the request
      *
      * @test
@@ -896,9 +399,6 @@ class ConditionMatcherTest extends UnitTestCase
         $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
         $GLOBALS['TYPO3_REQUEST'] = $GLOBALS['TYPO3_REQUEST']->withAttribute('language', $site->getLanguageById(0));
         $this->getFreshConditionMatcher();
-        $this->assertTrue($this->subject->match('[siteLanguage = locale = en_US.UTF-8]'));
-        $this->assertTrue($this->subject->match('[siteLanguage = locale = de_DE, locale = en_US.UTF-8]'));
-        // Test expression language
         $this->assertTrue($this->subject->match('[siteLanguage("locale") == "en_US.UTF-8"]'));
         $this->assertTrue($this->subject->match('[siteLanguage("locale") in ["de_DE", "en_US.UTF-8"]]'));
     }
@@ -927,9 +427,6 @@ class ConditionMatcherTest extends UnitTestCase
         $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
         $GLOBALS['TYPO3_REQUEST'] = $GLOBALS['TYPO3_REQUEST']->withAttribute('language', $site->getLanguageById(0));
         $this->getFreshConditionMatcher();
-        $this->assertFalse($this->subject->match('[siteLanguage = locale = en_UK.UTF-8]'));
-        $this->assertFalse($this->subject->match('[siteLanguage = locale = de_DE, title = UK]'));
-        // Test expression language
         $this->assertFalse($this->subject->match('[siteLanguage("locale") == "en_UK.UTF-8"]'));
         $this->assertFalse($this->subject->match('[siteLanguage("locale") == "de_DE" && siteLanguage("title") == "UK"]'));
     }
@@ -945,10 +442,6 @@ class ConditionMatcherTest extends UnitTestCase
         $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
         $GLOBALS['TYPO3_REQUEST'] = $GLOBALS['TYPO3_REQUEST']->withAttribute('site', $site);
         $this->getFreshConditionMatcher();
-        $this->assertTrue($this->subject->match('[site = identifier = angelo]'));
-        $this->assertTrue($this->subject->match('[site = rootPageId = 13]'));
-        $this->assertTrue($this->subject->match('[site = base = https://typo3.org/]'));
-        // Test expression language
         $this->assertTrue($this->subject->match('[site("identifier") == "angelo"]'));
         $this->assertTrue($this->subject->match('[site("rootPageId") == 13]'));
         $this->assertTrue($this->subject->match('[site("base") == "https://typo3.org/"]'));
@@ -978,36 +471,7 @@ class ConditionMatcherTest extends UnitTestCase
         $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
         $GLOBALS['TYPO3_REQUEST'] = $GLOBALS['TYPO3_REQUEST']->withAttribute('site', $site);
         $this->getFreshConditionMatcher();
-        $this->assertFalse($this->subject->match('[site = identifier = berta]'));
-        $this->assertFalse($this->subject->match('[site = rootPageId = 14, rootPageId=23]'));
-        // Test expression language
         $this->assertFalse($this->subject->match('[site("identifier") == "berta"]'));
         $this->assertFalse($this->subject->match('[site("rootPageId") == 14 && site("rootPageId") == 23]'));
     }
-
-    /**
-     * @test
-     */
-    public function matchThrowsExceptionIfConditionClassDoesNotInheritFromAbstractCondition(): void
-    {
-        $this->expectException(InvalidTypoScriptConditionException::class);
-        $this->expectExceptionCode(1410286153);
-        $this->getFreshConditionMatcher();
-        $loggerProphecy = $this->prophesize(Logger::class);
-        $this->subject->setLogger($loggerProphecy->reveal());
-        $this->subject->match('[stdClass = foo]');
-    }
-
-    /**
-     * @test
-     */
-    public function matchCallsTestConditionAndHandsOverParameters(): void
-    {
-        $this->expectException(TestConditionException::class);
-        $this->expectExceptionCode(1411581139);
-        $this->getFreshConditionMatcher();
-        $loggerProphecy = $this->prophesize(Logger::class);
-        $this->subject->setLogger($loggerProphecy->reveal());
-        $this->subject->match('[TYPO3\\CMS\\Frontend\\Tests\\Unit\\Configuration\\TypoScript\\ConditionMatching\\Fixtures\\TestCondition = 7, != 6]');
-    }
 }
diff --git a/typo3/sysext/frontend/Tests/Unit/Configuration/TypoScript/ConditionMatching/Fixtures/TestCondition.php b/typo3/sysext/frontend/Tests/Unit/Configuration/TypoScript/ConditionMatching/Fixtures/TestCondition.php
deleted file mode 100644 (file)
index 38c8b6e..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-namespace TYPO3\CMS\Frontend\Tests\Unit\Configuration\TypoScript\ConditionMatching\Fixtures;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-/**
- * Fixture for custom conditions
- */
-class TestCondition extends \TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractCondition
-{
-    /**
-     * Test matcher tests input parameters.
-     *
-     * @param array $conditionParameters
-     * @throws TestConditionException
-     * @return bool
-     */
-    public function matchCondition(array $conditionParameters)
-    {
-        // Throw an exception if everything is fine, this exception is *expected* in the according unit test
-        if ($conditionParameters[0] === '= 7' && $conditionParameters[1] === '!= 6') {
-            throw new TestConditionException('All Ok', 1411581139);
-        }
-    }
-}
diff --git a/typo3/sysext/frontend/Tests/Unit/Configuration/TypoScript/ConditionMatching/Fixtures/TestConditionException.php b/typo3/sysext/frontend/Tests/Unit/Configuration/TypoScript/ConditionMatching/Fixtures/TestConditionException.php
deleted file mode 100644 (file)
index 0eb3965..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-namespace TYPO3\CMS\Frontend\Tests\Unit\Configuration\TypoScript\ConditionMatching\Fixtures;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-/**
- * Exception thrown by TestCondition
- */
-class TestConditionException extends \Exception
-{
-}
diff --git a/typo3/sysext/frontend/Tests/UnitDeprecated/Configuration/TypoScript/ConditionMatching/ConditionMatcherTest.php b/typo3/sysext/frontend/Tests/UnitDeprecated/Configuration/TypoScript/ConditionMatching/ConditionMatcherTest.php
new file mode 100644 (file)
index 0000000..06a8494
--- /dev/null
@@ -0,0 +1,1017 @@
+<?php
+declare(strict_types = 1);
+namespace TYPO3\CMS\Frontend\Tests\UnitDeprecated\Configuration\TypoScript\ConditionMatching;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use Prophecy\Argument;
+use TYPO3\CMS\Core\Configuration\TypoScript\Exception\InvalidTypoScriptConditionException;
+use TYPO3\CMS\Core\Context\Context;
+use TYPO3\CMS\Core\Context\UserAspect;
+use TYPO3\CMS\Core\Http\ServerRequest;
+use TYPO3\CMS\Core\Log\Logger;
+use TYPO3\CMS\Core\Site\Entity\Site;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication;
+use TYPO3\CMS\Frontend\Configuration\TypoScript\ConditionMatching\ConditionMatcher;
+use TYPO3\CMS\Frontend\Tests\UnitDeprecated\Configuration\TypoScript\ConditionMatching\Fixtures\TestConditionException;
+use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
+
+/**
+ * Test case
+ */
+class ConditionMatcherTest extends UnitTestCase
+{
+    /**
+     * @var ConditionMatcher
+     */
+    protected $subject;
+
+    /**
+     * @var string
+     */
+    protected $testGlobalNamespace;
+
+    /**
+     * @var bool Reset singletons
+     */
+    protected $resetSingletonInstances = true;
+
+    protected function setUp(): void
+    {
+        $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
+
+        $this->testGlobalNamespace = $this->getUniqueId('TEST');
+        $GLOBALS[$this->testGlobalNamespace] = [];
+        $GLOBALS['TSFE'] = new \stdClass();
+        $GLOBALS['TSFE']->page = [];
+        $GLOBALS['TSFE']->tmpl = new \stdClass();
+        $GLOBALS['TSFE']->tmpl->rootLine = [
+            2 => ['uid' => 121, 'pid' => 111],
+            1 => ['uid' => 111, 'pid' => 101],
+            0 => ['uid' => 101, 'pid' => 0]
+        ];
+
+        $frontedUserAuthentication = $this->getMockBuilder(FrontendUserAuthentication::class)
+            ->setMethods(['dummy'])
+            ->getMock();
+
+        $frontedUserAuthentication->user['uid'] = 13;
+        $frontedUserAuthentication->groupData['uid'] = [14];
+        $GLOBALS['TSFE']->fe_user = $frontedUserAuthentication;
+        $this->getFreshConditionMatcher();
+    }
+
+    protected function getFreshConditionMatcher()
+    {
+        $this->subject = new ConditionMatcher(new Context([
+            'frontend.user' => new UserAspect($GLOBALS['TSFE']->fe_user)
+        ]));
+        $this->subject->setLogger($this->prophesize(Logger::class)->reveal());
+    }
+
+    /**
+     * Tests whether a faulty expression fails.
+     *
+     * @test
+     */
+    public function simulateDisabledMatchAllConditionsFailsOnFaultyExpression(): void
+    {
+        $this->getFreshConditionMatcher();
+        $this->assertFalse($this->subject->match('[nullCondition = This expression would return FALSE in general]'));
+    }
+
+    /**
+     * Tests whether simulating positive matches for all conditions succeeds.
+     *
+     * @test
+     */
+    public function simulateEnabledMatchAllConditionsSucceeds(): void
+    {
+        $this->getFreshConditionMatcher();
+        $this->subject->setSimulateMatchResult(true);
+        $this->assertTrue($this->subject->match('[nullCondition = This expression would return FALSE in general]'));
+    }
+
+    /**
+     * Tests whether simulating positive matches for specific conditions succeeds.
+     *
+     * @test
+     */
+    public function simulateEnabledMatchSpecificConditionsSucceeds(): void
+    {
+        $this->getFreshConditionMatcher();
+        $testCondition = '[' . $this->getUniqueId('test') . ' = Any condition to simulate a positive match]';
+        $this->subject->setSimulateMatchConditions([$testCondition]);
+        $this->assertTrue($this->subject->match($testCondition));
+    }
+
+    /**
+     * Tests whether the language comparison matches.
+     *
+     * @test
+     */
+    public function languageConditionMatchesSingleLanguageExpression(): void
+    {
+        $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-de,de;q=0.8,en-us;q=0.5,en;q=0.3';
+        $this->getFreshConditionMatcher();
+        $this->assertTrue($this->subject->match('[language = *de*]'));
+        $this->assertTrue($this->subject->match('[language = *de-de*]'));
+        // Test expression language
+        // @TODO: not work yet, looks like test setup issue
+//        $this->assertTrue($this->subject->match('[like(request.getNormalizedParams().getHttpAcceptLanguage(), "**de*")]'));
+//        $this->assertTrue($this->subject->match('[like(request.getNormalizedParams().getHttpAcceptLanguage(), "**de-de*")]'));
+    }
+
+    /**
+     * Tests whether the language comparison matches.
+     *
+     * @test
+     */
+    public function languageConditionMatchesMultipleLanguagesExpression(): void
+    {
+        $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-de,de;q=0.8,en-us;q=0.5,en;q=0.3';
+        $this->getFreshConditionMatcher();
+        $this->assertTrue($this->subject->match('[language = *en*,*de*]'));
+        $this->assertTrue($this->subject->match('[language = *en-us*,*de-de*]'));
+        // Test expression language
+        // @TODO: not work yet, looks like test setup issue
+//        $this->assertTrue($this->subject->match('[like(request.getNormalizedParams().getHttpAcceptLanguage(), "*en*,*de*")]'));
+//        $this->assertTrue($this->subject->match('[like(request.getNormalizedParams().getHttpAcceptLanguage(), "*en-us*,*de-de*")]'));
+    }
+
+    /**
+     * Tests whether the language comparison matches.
+     *
+     * @test
+     */
+    public function languageConditionMatchesCompleteLanguagesExpression(): void
+    {
+        $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-de,de;q=0.8,en-us;q=0.5,en;q=0.3';
+        $this->getFreshConditionMatcher();
+        $this->assertTrue($this->subject->match('[language = de-de,de;q=0.8,en-us;q=0.5,en;q=0.3]'));
+        // Test expression language
+        // @TODO: not work yet, looks like test setup issue
+//        $this->assertTrue($this->subject->match('[request.getNormalizedParams().getHttpAcceptLanguage() == "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"]'));
+    }
+
+    /**
+     * Tests whether usergroup comparison matches.
+     *
+     * @test
+     */
+    public function usergroupConditionMatchesSingleGroupId(): void
+    {
+        $subject = new ConditionMatcher(new Context([
+            'frontend.user' => new UserAspect(new FrontendUserAuthentication(), [13, 14, 15])
+        ]));
+        $loggerProphecy = $this->prophesize(Logger::class);
+        $subject->setLogger($loggerProphecy->reveal());
+        $this->assertTrue($subject->match('[usergroup = 13]'));
+        // Test expression language
+        $this->assertTrue($subject->match('[usergroup(13)]'));
+        $this->assertTrue($subject->match('[usergroup("13")]'));
+        $this->assertTrue($subject->match('[usergroup(\'13\')]'));
+    }
+
+    /**
+     * Tests whether usergroup comparison matches.
+     *
+     * @test
+     */
+    public function usergroupConditionMatchesMultipleUserGroupId(): void
+    {
+        $subject = new ConditionMatcher(new Context([
+            'frontend.user' => new UserAspect(new FrontendUserAuthentication(), [13, 14, 15])
+        ]));
+        $loggerProphecy = $this->prophesize(Logger::class);
+        $subject->setLogger($loggerProphecy->reveal());
+        $this->assertTrue($subject->match('[usergroup = 999,15,14,13]'));
+        // Test expression language
+        $this->assertFalse($subject->match('[usergroup(999,15,14,13)]'));
+        $this->assertTrue($subject->match('[usergroup("999,15,14,13")]'));
+        $this->assertTrue($subject->match('[usergroup(\'999,15,14,13\')]'));
+    }
+
+    /**
+     * Tests whether usergroup comparison matches.
+     *
+     * @test
+     */
+    public function usergroupConditionDoesNotMatchDefaulUserGroupIds(): void
+    {
+        $subject = new ConditionMatcher(new Context([
+            'frontend.user' => new UserAspect(new FrontendUserAuthentication(), [0, -1])
+        ]));
+        $loggerProphecy = $this->prophesize(Logger::class);
+        $subject->setLogger($loggerProphecy->reveal());
+        $this->assertFalse($subject->match('[usergroup = 0,-1]'));
+        // Test expression language
+        $this->assertFalse($subject->match('[usergroup("0,-1")]'));
+        $this->assertFalse($subject->match('[usergroup(\'0,-1\')]'));
+    }
+
+    /**
+     * Tests whether user comparison matches.
+     *
+     * @test
+     */
+    public function loginUserConditionMatchesAnyLoggedInUser(): void
+    {
+        $this->getFreshConditionMatcher();
+        // @TODO: not work yet, looks like test setup issue
+        $this->assertTrue($this->subject->match('[loginUser = *]'));
+        // Test expression language
+        $this->assertTrue($this->subject->match('[loginUser("*")]'));
+        $this->assertTrue($this->subject->match('[loginUser(\'*\')]'));
+    }
+
+    /**
+     * Tests whether user comparison matches.
+     *
+     * @test
+     */
+    public function loginUserConditionMatchesSingleLoggedInUser(): void
+    {
+        $this->getFreshConditionMatcher();
+        // @TODO: not work yet, looks like test setup issue
+        $this->assertTrue($this->subject->match('[loginUser = 13]'));
+        // Test expression language
+        $this->assertTrue($this->subject->match('[loginUser(13)]'));
+        $this->assertTrue($this->subject->match('[loginUser("13")]'));
+        $this->assertTrue($this->subject->match('[loginUser(\'13\')]'));
+    }
+
+    /**
+     * Tests whether user comparison matches.
+     *
+     * @test
+     */
+    public function loginUserConditionMatchesMultipleLoggedInUsers(): void
+    {
+        $this->getFreshConditionMatcher();
+        // @TODO: not work yet, looks like test setup issue
+        $this->assertTrue($this->subject->match('[loginUser = 999,13]'));
+        // Test expression language
+        $this->assertTrue($this->subject->match('[loginUser("999,13")]'));
+        $this->assertTrue($this->subject->match('[loginUser(\'999,13\')]'));
+    }
+
+    /**
+     * Tests whether user comparison matches.
+     *
+     * @test
+     */
+    public function loginUserConditionDoesNotMatchIfNotUserIsLoggedId(): void
+    {
+        $user = new FrontendUserAuthentication();
+        $user->user['uid'] = 13;
+        $subject = new ConditionMatcher(new Context([
+            'frontend.user' => new UserAspect($user)
+        ]));
+        $loggerProphecy = $this->prophesize(Logger::class);
+        $subject->setLogger($loggerProphecy->reveal());
+        $this->assertFalse($subject->match('[loginUser = *]'));
+        $this->assertFalse($subject->match('[loginUser = 13]'));
+        // Test expression language
+        $this->assertFalse($subject->match('[loginUser("*")]'));
+        $this->assertTrue($subject->match('[loginUser("*") == false]'));
+        $this->assertFalse($subject->match('[loginUser("13")]'));
+        $this->assertFalse($subject->match('[loginUser(\'*\')]'));
+        $this->assertFalse($subject->match('[loginUser(\'13\')]'));
+    }
+
+    /**
+     * Tests whether user is not logged in
+     *
+     * @test
+     */
+    public function loginUserConditionMatchIfUserIsNotLoggedIn(): void
+    {
+        $user = new FrontendUserAuthentication();
+        $subject = new ConditionMatcher(new Context([
+            'frontend.user' => new UserAspect($user)
+        ]));
+        $loggerProphecy = $this->prophesize(Logger::class);
+        $subject->setLogger($loggerProphecy->reveal());
+        $this->assertTrue($subject->match('[loginUser = ]'));
+        // Test expression language
+        $this->assertTrue($subject->match('[loginUser(\'*\') == false]'));
+        $this->assertTrue($subject->match('[loginUser("*") == false]'));
+    }
+
+    /**
+     * Tests whether numerical comparison matches.
+     *
+     * @test
+     */
+    public function globalVarConditionMatchesOnEqualExpression(): void
+    {
+        $this->assertTrue($this->subject->match('[globalVar = LIT:10 = 10]'));
+        $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 = 10.1]'));
+        $this->assertTrue($this->subject->match('[globalVar = LIT:10 == 10]'));
+        $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 == 10.1]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether numerical comparison matches.
+     *
+     * @test
+     */
+    public function globalVarConditionMatchesOnEqualExpressionWithMultipleValues(): void
+    {
+        $this->assertTrue($this->subject->match('[globalVar = LIT:10 = 10|20|30]'));
+        $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 = 10.1|20.2|30.3]'));
+        $this->assertTrue($this->subject->match('[globalVar = LIT:20 = 10|20|30]'));
+        $this->assertTrue($this->subject->match('[globalVar = LIT:20.2 = 10.1|20.2|30.3]'));
+        $this->assertTrue($this->subject->match('[globalVar = LIT:10 == 10|20|30]'));
+        $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 == 10.1|20.2|30.3]'));
+        $this->assertTrue($this->subject->match('[globalVar = LIT:20 == 10|20|30]'));
+        $this->assertTrue($this->subject->match('[globalVar = LIT:20.2 == 10.1|20.2|30.3]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether numerical comparison matches.
+     *
+     * @test
+     */
+    public function globalVarConditionMatchesOnNotEqualExpression(): void
+    {
+        $this->assertTrue($this->subject->match('[globalVar = LIT:10 != 20]'));
+        $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 != 10.2]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether numerical comparison does not match.
+     *
+     * @test
+     */
+    public function globalVarConditionDoesNotMatchOnNotEqualExpression(): void
+    {
+        $this->assertFalse($this->subject->match('[globalVar = LIT:10 != 10]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether numerical comparison matches.
+     *
+     * @test
+     */
+    public function globalVarConditionMatchesOnNotEqualExpressionWithMultipleValues(): void
+    {
+        $this->assertTrue($this->subject->match('[globalVar = LIT:10 != 20|30]'));
+        $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 != 10.2|20.3]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether numerical comparison matches.
+     *
+     * @test
+     */
+    public function globalVarConditionMatchesOnLowerThanExpression(): void
+    {
+        $this->assertTrue($this->subject->match('[globalVar = LIT:10 < 20]'));
+        $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 < 10.2]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether numerical comparison matches.
+     *
+     * @test
+     */
+    public function globalVarConditionMatchesOnLowerThanOrEqualExpression(): void
+    {
+        $this->assertTrue($this->subject->match('[globalVar = LIT:10 <= 10]'));
+        $this->assertTrue($this->subject->match('[globalVar = LIT:10 <= 20]'));
+        $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 <= 10.1]'));
+        $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 <= 10.2]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether numerical comparison matches.
+     *
+     * @test
+     */
+    public function globalVarConditionMatchesOnGreaterThanExpression(): void
+    {
+        $this->assertTrue($this->subject->match('[globalVar = LIT:20 > 10]'));
+        $this->assertTrue($this->subject->match('[globalVar = LIT:10.2 > 10.1]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether numerical comparison matches.
+     *
+     * @test
+     */
+    public function globalVarConditionMatchesOnGreaterThanOrEqualExpression(): void
+    {
+        $this->assertTrue($this->subject->match('[globalVar = LIT:10 >= 10]'));
+        $this->assertTrue($this->subject->match('[globalVar = LIT:20 >= 10]'));
+        $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 >= 10.1]'));
+        $this->assertTrue($this->subject->match('[globalVar = LIT:10.2 >= 10.1]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether numerical comparison matches.
+     *
+     * @test
+     */
+    public function globalVarConditionMatchesOnEmptyExpressionWithNoValueSet(): void
+    {
+        $testKey = $this->getUniqueId('test');
+        $this->assertTrue($this->subject->match('[globalVar = GP:' . $testKey . '=]'));
+        $this->assertTrue($this->subject->match('[globalVar = GP:' . $testKey . ' = ]'));
+    }
+
+    /**
+     * Tests whether numerical comparison matches.
+     *
+     * @test
+     */
+    public function globalVarConditionDoesNotMatchOnEmptyExpressionWithValueSetToZero(): void
+    {
+        $testKey = $this->getUniqueId('test');
+        $_GET = [];
+        $_POST = [$testKey => 0];
+        $this->assertFalse($this->subject->match('[globalVar = GP:' . $testKey . '=]'));
+        $this->assertFalse($this->subject->match('[globalVar = GP:' . $testKey . ' = ]'));
+    }
+
+    /**
+     * Tests whether an array with zero as key matches its value
+     *
+     * @test
+     */
+    public function globalVarConditionMatchesOnArrayExpressionWithZeroAsKey(): void
+    {
+        $testKey = $this->getUniqueId('test');
+        $testValue = '1';
+        $_GET = [];
+        $_POST = [$testKey => ['0' => $testValue]];
+        $this->assertTrue($this->subject->match('[globalVar = GP:' . $testKey . '|0=' . $testValue . ']'));
+    }
+
+    /**
+     * Tests whether string comparison matches.
+     *
+     * @test
+     */
+    public function globalStringConditionMatchesOnEqualExpression(): void
+    {
+        $this->assertTrue($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3.Test.Condition]'));
+        $this->assertFalse($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether string comparison matches.
+     *
+     * @test
+     */
+    public function globalStringConditionMatchesOnEmptyExpressionWithValueSetToEmptyString(): void
+    {
+        $testKey = $this->getUniqueId('test');
+        $_GET = [];
+        $_POST = [$testKey => ''];
+        $this->assertTrue($this->subject->match('[globalString = GP:' . $testKey . '=]'));
+        $this->assertTrue($this->subject->match('[globalString = GP:' . $testKey . ' = ]'));
+    }
+
+    /**
+     * Tests whether string comparison matches.
+     *
+     * @test
+     */
+    public function globalStringConditionMatchesOnEmptyLiteralExpressionWithValueSetToEmptyString(): void
+    {
+        $this->assertTrue($this->subject->match('[globalString = LIT:=]'));
+        $this->assertTrue($this->subject->match('[globalString = LIT: = ]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether string comparison matches.
+     *
+     * @test
+     */
+    public function globalStringConditionMatchesWildcardExpression(): void
+    {
+        $this->assertTrue($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3?Test?Condition]'));
+        $this->assertTrue($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3.T*t.Condition]'));
+        $this->assertTrue($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3?T*t?Condition]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether string comparison matches.
+     *
+     * @test
+     */
+    public function globalStringConditionMatchesRegularExpression(): void
+    {
+        $this->assertTrue($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = /^[A-Za-z3.]+$/]'));
+        $this->assertTrue($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = /^TYPO3\\..+Condition$/]'));
+        $this->assertFalse($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = /^FALSE/]'));
+        // Test expression language
+        // Access with LIT is not possible in expression language, because constants available as variable
+    }
+
+    /**
+     * Tests whether string comparison matches.
+     *
+     * @test
+     */
+    public function globalStringConditionMatchesEmptyRegularExpression(): void
+    {
+        $testKey = $this->getUniqueId('test');
+        $GLOBALS['_SERVER'][$testKey] = '';
+        $this->assertTrue($this->subject->match('[globalString = _SERVER|' . $testKey . ' = /^$/]'));
+        // Test expression language
+        // Access request by request() method
+    }
+
+    /**
+     * Tests whether treeLevel comparison matches.
+     *
+     * @test
+     */
+    public function treeLevelConditionMatchesSingleValue(): void
+    {
+        $this->assertTrue($this->subject->match('[treeLevel = 2]'));
+        // Test expression language
+        $this->assertTrue($this->subject->match('[tree.level == 2]'));
+    }
+
+    /**
+     * Tests whether treeLevel comparison matches.
+     *
+     * @test
+     */
+    public function treeLevelConditionMatchesMultipleValues(): void
+    {
+        $this->assertTrue($this->subject->match('[treeLevel = 999,998,2]'));
+        // Test expression language
+        $this->assertTrue($this->subject->match('[tree.level in [999,998,2]]'));
+    }
+
+    /**
+     * Tests whether treeLevel comparison matches.
+     *
+     * @test
+     */
+    public function treeLevelConditionDoesNotMatchFaultyValue(): void
+    {
+        $this->assertFalse($this->subject->match('[treeLevel = 999]'));
+        // Test expression language
+        $this->assertFalse($this->subject->match('[tree.level == 999]'));
+    }
+
+    /**
+     * @return array
+     */
+    public function pageDataProvider(): array
+    {
+        return [
+            '[page|layout = 0]' => ['[page|layout = 0]', true],
+            '[page|layout = 1]' => ['[page|layout = 1]', false],
+            '[page|title = Foo]' => ['[page|title = Foo]', true],
+        ];
+    }
+
+    /**
+     * @test
+     * @dataProvider pageDataProvider
+     * @param string $expression
+     * @param bool $expected
+     */
+    public function checkConditionMatcherForPage(string $expression, bool $expected): void
+    {
+        $GLOBALS['TSFE']->page = ['title' => 'Foo', 'layout' => 0];
+        $this->getFreshConditionMatcher();
+        $this->assertSame($expected, $this->subject->match($expression));
+    }
+
+    /**
+     * Tests whether a page Id is found in the previous rootline entries.
+     *
+     * @test
+     */
+    public function PIDupinRootlineConditionMatchesSinglePageIdInRootline(): void
+    {
+        $GLOBALS['TSFE']->id = 121;
+        $this->getFreshConditionMatcher();
+        $this->assertTrue($this->subject->match('[PIDupinRootline = 111]'));
+        // Test expression language
+        $this->assertTrue($this->subject->match('[111 in tree.rootLineIds]'));
+        $this->assertTrue($this->subject->match('["111" in tree.rootLineIds]'));
+        $this->assertTrue($this->subject->match('[\'111\' in tree.rootLineIds]'));
+    }
+
+    /**
+     * Tests whether a page Id is found in the previous rootline entries.
+     *
+     * @test
+     */
+    public function PIDupinRootlineConditionMatchesMultiplePageIdsInRootline(): void
+    {
+        $GLOBALS['TSFE']->id = 121;
+        $this->getFreshConditionMatcher();
+        $this->assertTrue($this->subject->match('[PIDupinRootline = 999,111,101]'));
+        // Test expression language
+        $this->assertTrue($this->subject->match('[999 in tree.rootLineIds][111 in tree.rootLineIds][101 in tree.rootLineIds]'));
+    }
+
+    /**
+     * Tests whether a page Id is found in the previous rootline entries.
+     *
+     * @test
+     */
+    public function PIDupinRootlineConditionDoesNotMatchPageIdNotInRootline(): void
+    {
+        $GLOBALS['TSFE']->id = 121;
+        $this->getFreshConditionMatcher();
+        $this->assertFalse($this->subject->match('[PIDupinRootline = 999]'));
+        // Test expression language
+        $this->assertFalse($this->subject->match('[999 in tree.rootLineIds]'));
+    }
+
+    /**
+     * Tests whether a page Id is found in the previous rootline entries.
+     *
+     * @test
+     */
+    public function PIDupinRootlineConditionDoesNotMatchLastPageIdInRootline(): void
+    {
+        $GLOBALS['TSFE']->id = 121;
+        $this->getFreshConditionMatcher();
+        $this->assertFalse($this->subject->match('[PIDupinRootline = 121]'));
+        // Test expression language
+        $this->assertFalse($this->subject->match('[page.uid != 121 && 121 in rootLineUids]'));
+    }
+
+    /**
+     * Tests whether a page Id is found in all rootline entries.
+     *
+     * @test
+     */
+    public function PIDinRootlineConditionMatchesSinglePageIdInRootline(): void
+    {
+        $GLOBALS['TSFE']->id = 121;
+        $this->getFreshConditionMatcher();
+        $this->assertTrue($this->subject->match('[PIDinRootline = 111]'));
+        // Test expression language
+        $this->assertTrue($this->subject->match('[111 in tree.rootLineIds]'));
+    }
+
+    /**
+     * Tests whether a page Id is found in all rootline entries.
+     *
+     * @test
+     */
+    public function PIDinRootlineConditionMatchesMultiplePageIdsInRootline(): void
+    {
+        $GLOBALS['TSFE']->id = 121;
+        $this->getFreshConditionMatcher();
+        $this->assertTrue($this->subject->match('[PIDinRootline = 999,111,101]'));
+        // Test expression language
+        $this->assertTrue($this->subject->match('[999 in tree.rootLineIds][111 in tree.rootLineIds][101 in tree.rootLineIds]'));
+    }
+
+    /**
+     * Tests whether a page Id is found in all rootline entries.
+     *
+     * @test
+     */
+    public function PIDinRootlineConditionMatchesLastPageIdInRootline(): void
+    {
+        $GLOBALS['TSFE']->id = 121;
+        $this->getFreshConditionMatcher();
+        $this->assertTrue($this->subject->match('[PIDinRootline = 121]'));
+        // Test expression language
+        $this->assertTrue($this->subject->match('[121 in tree.rootLineIds]'));
+    }
+
+    /**
+     * Tests whether a page Id is found in all rootline entries.
+     *
+     * @test
+     */
+    public function PIDinRootlineConditionDoesNotMatchPageIdNotInRootline(): void
+    {
+        $GLOBALS['TSFE']->id = 121;
+        $this->assertFalse($this->subject->match('[PIDinRootline = 999]'));
+        // Test expression language
+        $this->assertFalse($this->subject->match('[999 in tree.rootLineIds]'));
+    }
+
+    /**
+     * Tests whether the compatibility version can be evaluated.
+     * (e.g. 7.9 is compatible to 7.0 but not to 15.0)
+     *
+     * @test
+     */
+    public function compatVersionConditionMatchesOlderRelease(): void
+    {
+        $this->assertTrue($this->subject->match('[compatVersion = 7.0]'));
+        // Test expression language
+        $this->assertTrue($this->subject->match('[compatVersion(7.0)]'));
+        $this->assertTrue($this->subject->match('[compatVersion("7.0")]'));
+        $this->assertTrue($this->subject->match('[compatVersion(\'7.0\')]'));
+    }
+
+    /**
+     * Tests whether the compatibility version can be evaluated.
+     * (e.g. 7.9 is compatible to 7.0 but not to 15.0)
+     *
+     * @test
+     */
+    public function compatVersionConditionMatchesSameRelease(): void
+    {
+        $this->assertTrue($this->subject->match('[compatVersion = ' . TYPO3_branch . ']'));
+        // Test expression language
+        $this->assertTrue($this->subject->match('[compatVersion(' . TYPO3_branch . ')]'));
+    }
+
+    /**
+     * Tests whether the compatibility version can be evaluated.
+     * (e.g. 7.9 is compatible to 7.0 but not to 15.0)
+     *
+     * @test
+     */
+    public function compatVersionConditionDoesNotMatchNewerRelease(): void
+    {
+        $this->assertFalse($this->subject->match('[compatVersion = 15.0]'));
+        // Test expression language
+        $this->assertFalse($this->subject->match('[compatVersion(15.0)]'));
+        $this->assertFalse($this->subject->match('[compatVersion("15.0")]'));
+        $this->assertFalse($this->subject->match('[compatVersion(\'15.0\')]'));
+    }
+
+    /**
+     * Tests whether the generic fetching of variables works with the namespace 'GP'.
+     *
+     * @test
+     */
+    public function genericGetVariablesSucceedsWithNamespaceGP(): void
+    {
+        $_GET = ['testGet' => 'getTest'];
+        $_POST = ['testPost' => 'postTest'];
+        $this->getFreshConditionMatcher();
+        $this->assertTrue($this->subject->match('[globalString = GP:testGet = getTest]'));
+        $this->assertTrue($this->subject->match('[globalString = GP:testPost = postTest]'));
+    }
+
+    /**
+     * Tests whether the generic fetching of variables works with the namespace 'TSFE'.
+     *
+     * @test
+     */
+    public function genericGetVariablesSucceedsWithNamespaceTSFE(): void
+    {
+        $GLOBALS['TSFE']->id = 1234567;
+        $GLOBALS['TSFE']->testSimpleObject = new \stdClass();
+        $GLOBALS['TSFE']->testSimpleObject->testSimpleVariable = 'testValue';
+
+        $this->getFreshConditionMatcher();
+        $this->assertTrue($this->subject->match('[globalString = TSFE:id = 1234567]'));
+        $this->assertTrue($this->subject->match('[globalString = TSFE:testSimpleObject|testSimpleVariable = testValue]'));
+        // Test expression language
+        $this->assertTrue($this->subject->match('[getTSFE().id == 1234567]'));
+        $this->assertTrue($this->subject->match('[getTSFE().testSimpleObject.testSimpleVariable == "testValue"]'));
+    }
+
+    /**
+     * Tests whether the generic fetching of variables works with the namespace 'session'.
+     *
+     * @test
+     */
+    public function genericGetVariablesSucceedsWithNamespaceSession(): void
+    {
+        $prophecy = $this->prophesize(FrontendUserAuthentication::class);
+        $prophecy->getSessionData(Argument::exact('foo'))->willReturn(['bar' => 1234567]);
+        $GLOBALS['TSFE']->fe_user = $prophecy->reveal();
+
+        $this->getFreshConditionMatcher();
+        $this->assertTrue($this->subject->match('[globalString = session:foo|bar = 1234567]'));
+        // Test expression language
+        $this->assertTrue($this->subject->match('[session("foo|bar") == 1234567]'));
+    }
+
+    /**
+     * Tests whether the generic fetching of variables works with the namespace 'ENV'.
+     *
+     * @test
+     */
+    public function genericGetVariablesSucceedsWithNamespaceENV(): void
+    {
+        $testKey = $this->getUniqueId('test');
+        putenv($testKey . '=testValue');
+        $this->getFreshConditionMatcher();
+        $this->assertTrue($this->subject->match('[globalString = ENV:' . $testKey . ' = testValue]'));
+        // Test expression language
+        $this->assertTrue($this->subject->match('[getenv("' . $testKey . '") == "testValue"]'));
+    }
+
+    /**
+     * Tests whether the generic fetching of variables works with the namespace 'IENV'.
+     *
+     * @test
+     */
+    public function genericGetVariablesSucceedsWithNamespaceIENV(): void
+    {
+        $_SERVER['HTTP_HOST'] = GeneralUtility::getIndpEnv('TYPO3_HOST_ONLY') . ':1234567';
+        // getIndpEnv() is polluted after above call, clear cache to have it recalculate for subject execption
+        GeneralUtility::flushInternalRuntimeCaches();
+        $this->getFreshConditionMatcher();
+        $this->assertTrue($this->subject->match('[globalString = IENV:TYPO3_PORT = 1234567]'));
+        // Test expression language
+        // @TODO: not work yet, looks like test setup issue
+//        $this->assertTrue($this->subject->match('[request.getNormalizedParams().getRequestPort() == 1234567]'));
+    }
+
+    /**
+     * Tests whether the generic fetching of variables works with any global namespace.
+     *
+     * @test
+     */
+    public function genericGetVariablesSucceedsWithAnyGlobalNamespace(): void
+    {
+        $GLOBALS[$this->testGlobalNamespace] = [
+            'first' => 'testFirst',
+            'second' => ['third' => 'testThird']
+        ];
+        $this->getFreshConditionMatcher();
+        $this->assertTrue($this->subject->match('[globalString = ' . $this->testGlobalNamespace . '|first = testFirst]'));
+        $this->assertTrue($this->subject->match('[globalString = ' . $this->testGlobalNamespace . '|second|third = testThird]'));
+    }
+
+    /**
+     * Tests whether any property of a site language matches the request
+     *
+     * @test
+     */
+    public function siteLanguageMatchesCondition(): void
+    {
+        $site = new Site('angelo', 13, [
+            'languages' => [
+                [
+                    'languageId' => 0,
+                    'title' => 'United States',
+                    'locale' => 'en_US.UTF-8',
+                ],
+                [
+                    'languageId' => 2,
+                    'title' => 'UK',
+                    'locale' => 'en_UK.UTF-8',
+                ]
+            ]
+        ]);
+        $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
+        $GLOBALS['TYPO3_REQUEST'] = $GLOBALS['TYPO3_REQUEST']->withAttribute('language', $site->getLanguageById(0));
+        $this->getFreshConditionMatcher();
+        $this->assertTrue($this->subject->match('[siteLanguage = locale = en_US.UTF-8]'));
+        $this->assertTrue($this->subject->match('[siteLanguage = locale = de_DE, locale = en_US.UTF-8]'));
+        // Test expression language
+        $this->assertTrue($this->subject->match('[siteLanguage("locale") == "en_US.UTF-8"]'));
+        $this->assertTrue($this->subject->match('[siteLanguage("locale") in ["de_DE", "en_US.UTF-8"]]'));
+    }
+
+    /**
+     * Tests whether any property of a site language does NOT match the request
+     *
+     * @test
+     */
+    public function siteLanguageDoesNotMatchCondition(): void
+    {
+        $site = new Site('angelo', 13, [
+            'languages' => [
+                [
+                    'languageId' => 0,
+                    'title' => 'United States',
+                    'locale' => 'en_US.UTF-8',
+                ],
+                [
+                    'languageId' => 2,
+                    'title' => 'UK',
+                    'locale' => 'en_UK.UTF-8',
+                ]
+            ]
+        ]);
+        $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
+        $GLOBALS['TYPO3_REQUEST'] = $GLOBALS['TYPO3_REQUEST']->withAttribute('language', $site->getLanguageById(0));
+        $this->getFreshConditionMatcher();
+        $this->assertFalse($this->subject->match('[siteLanguage = locale = en_UK.UTF-8]'));
+        $this->assertFalse($this->subject->match('[siteLanguage = locale = de_DE, title = UK]'));
+        // Test expression language
+        $this->assertFalse($this->subject->match('[siteLanguage("locale") == "en_UK.UTF-8"]'));
+        $this->assertFalse($this->subject->match('[siteLanguage("locale") == "de_DE" && siteLanguage("title") == "UK"]'));
+    }
+
+    /**
+     * Tests whether any property of a site matches the request
+     *
+     * @test
+     */
+    public function siteMatchesCondition(): void
+    {
+        $site = new Site('angelo', 13, ['languages' => [], 'base' => 'https://typo3.org/']);
+        $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
+        $GLOBALS['TYPO3_REQUEST'] = $GLOBALS['TYPO3_REQUEST']->withAttribute('site', $site);
+        $this->getFreshConditionMatcher();
+        $this->assertTrue($this->subject->match('[site = identifier = angelo]'));
+        $this->assertTrue($this->subject->match('[site = rootPageId = 13]'));
+        $this->assertTrue($this->subject->match('[site = base = https://typo3.org/]'));
+        // Test expression language
+        $this->assertTrue($this->subject->match('[site("identifier") == "angelo"]'));
+        $this->assertTrue($this->subject->match('[site("rootPageId") == 13]'));
+        $this->assertTrue($this->subject->match('[site("base") == "https://typo3.org/"]'));
+    }
+
+    /**
+     * Tests whether any property of a site that does NOT match the request
+     *
+     * @test
+     */
+    public function siteDoesNotMatchCondition(): void
+    {
+        $site = new Site('angelo', 13, [
+            'languages' => [
+                [
+                    'languageId' => 0,
+                    'title' => 'United States',
+                    'locale' => 'en_US.UTF-8',
+                ],
+                [
+                    'languageId' => 2,
+                    'title' => 'UK',
+                    'locale' => 'en_UK.UTF-8',
+                ]
+            ]
+        ]);
+        $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
+        $GLOBALS['TYPO3_REQUEST'] = $GLOBALS['TYPO3_REQUEST']->withAttribute('site', $site);
+        $this->getFreshConditionMatcher();
+        $this->assertFalse($this->subject->match('[site = identifier = berta]'));
+        $this->assertFalse($this->subject->match('[site = rootPageId = 14, rootPageId=23]'));
+        // Test expression language
+        $this->assertFalse($this->subject->match('[site("identifier") == "berta"]'));
+        $this->assertFalse($this->subject->match('[site("rootPageId") == 14 && site("rootPageId") == 23]'));
+    }
+
+    /**
+     * @test
+     */
+    public function matchThrowsExceptionIfConditionClassDoesNotInheritFromAbstractCondition(): void
+    {
+        $this->expectException(InvalidTypoScriptConditionException::class);
+        $this->expectExceptionCode(1410286153);
+        $this->getFreshConditionMatcher();
+        $loggerProphecy = $this->prophesize(Logger::class);
+        $this->subject->setLogger($loggerProphecy->reveal());
+        $this->subject->match('[stdClass = foo]');
+    }
+
+    /**
+     * @test
+     */
+    public function matchCallsTestConditionAndHandsOverParameters(): void
+    {
+        $this->expectException(TestConditionException::class);
+        $this->expectExceptionCode(1411581139);
+        $this->getFreshConditionMatcher();
+        $loggerProphecy = $this->prophesize(Logger::class);
+        $this->subject->setLogger($loggerProphecy->reveal());
+        $this->subject->match('[TYPO3\\CMS\\Frontend\\Tests\\UnitDeprecated\\Configuration\\TypoScript\\ConditionMatching\\Fixtures\\TestCondition = 7, != 6]');
+    }
+}
diff --git a/typo3/sysext/frontend/Tests/UnitDeprecated/Configuration/TypoScript/ConditionMatching/Fixtures/TestCondition.php b/typo3/sysext/frontend/Tests/UnitDeprecated/Configuration/TypoScript/ConditionMatching/Fixtures/TestCondition.php
new file mode 100644 (file)
index 0000000..d2b6a3f
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+namespace TYPO3\CMS\Frontend\Tests\UnitDeprecated\Configuration\TypoScript\ConditionMatching\Fixtures;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * Fixture for custom conditions
+ */
+class TestCondition extends \TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractCondition
+{
+    /**
+     * Test matcher tests input parameters.
+     *
+     * @param array $conditionParameters
+     * @throws TestConditionException
+     * @return bool
+     */
+    public function matchCondition(array $conditionParameters)
+    {
+        // Throw an exception if everything is fine, this exception is *expected* in the according unit test
+        if ($conditionParameters[0] === '= 7' && $conditionParameters[1] === '!= 6') {
+            throw new TestConditionException('All Ok', 1411581139);
+        }
+    }
+}
diff --git a/typo3/sysext/frontend/Tests/UnitDeprecated/Configuration/TypoScript/ConditionMatching/Fixtures/TestConditionException.php b/typo3/sysext/frontend/Tests/UnitDeprecated/Configuration/TypoScript/ConditionMatching/Fixtures/TestConditionException.php
new file mode 100644 (file)
index 0000000..86bef22
--- /dev/null
@@ -0,0 +1,22 @@
+<?php
+namespace TYPO3\CMS\Frontend\Tests\UnitDeprecated\Configuration\TypoScript\ConditionMatching\Fixtures;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * Exception thrown by TestCondition
+ */
+class TestConditionException extends \Exception
+{
+}