[TASK] Streamline expressionLanguage usage in core 32/58232/33
authorSusanne Moog <susanne.moog@typo3.org>
Sat, 8 Sep 2018 14:12:08 +0000 (16:12 +0200)
committerFrank Naegler <frank.naegler@typo3.org>
Thu, 20 Sep 2018 12:55:02 +0000 (14:55 +0200)
* provide same functions across contexts / methods
* provide same way to extend expressionLanguage everywhere
* provide way to load context specific variables and functions
* prepare compile step

Resolves: #86196
Related: #86243
Releases: master
Change-Id: I86cc04ec7051293c195879f823d90d894d160ff0
Reviewed-on: https://review.typo3.org/58232
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
Reviewed-by: Frank Naegler <frank.naegler@typo3.org>
Tested-by: Frank Naegler <frank.naegler@typo3.org>
31 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/UnitDeprecated/Configuration/TypoScript/ConditionMatching/ConditionMatcherTest.php
typo3/sysext/core/Classes/Configuration/TypoScript/ConditionMatching/AbstractConditionMatcher.php
typo3/sysext/core/Classes/ExpressionLanguage/AbstractProvider.php
typo3/sysext/core/Classes/ExpressionLanguage/DefaultFunctionsProvider.php [deleted file]
typo3/sysext/core/Classes/ExpressionLanguage/DefaultProvider.php
typo3/sysext/core/Classes/ExpressionLanguage/FunctionsProvider/DefaultFunctionsProvider.php [new file with mode: 0644]
typo3/sysext/core/Classes/ExpressionLanguage/FunctionsProvider/Typo3ConditionFunctionsProvider.php [new file with mode: 0644]
typo3/sysext/core/Classes/ExpressionLanguage/ProviderConfigurationLoader.php [new file with mode: 0644]
typo3/sysext/core/Classes/ExpressionLanguage/ProviderInterface.php
typo3/sysext/core/Classes/ExpressionLanguage/RequestWrapper.php
typo3/sysext/core/Classes/ExpressionLanguage/Resolver.php
typo3/sysext/core/Classes/ExpressionLanguage/TypoScriptConditionFunctionsProvider.php [deleted file]
typo3/sysext/core/Classes/ExpressionLanguage/TypoScriptConditionProvider.php
typo3/sysext/core/Classes/ExpressionLanguage/TypoScriptFrontendConditionFunctionsProvider.php [deleted file]
typo3/sysext/core/Configuration/ExpressionLanguage.php [new file with mode: 0644]
typo3/sysext/core/Documentation/Changelog/9.4/Feature-85828-MoveSymfonyExpressionLanguageHandlingIntoEXTcore.rst
typo3/sysext/core/Documentation/Changelog/9.4/Feature-85829-ImplementSymfonyExpressionLanguageForTypoScriptConditions.rst
typo3/sysext/core/Tests/Unit/Configuration/TypoScript/ConditionMatching/AbstractConditionMatcherTest.php
typo3/sysext/core/Tests/Unit/ExpressionLanguage/ResolverTest.php
typo3/sysext/core/composer.json
typo3/sysext/form/Classes/Domain/Condition/ConditionProvider.php
typo3/sysext/form/Classes/Domain/Condition/ExpressionLanguageVariableProviderInterface.php [deleted file]
typo3/sysext/form/Classes/Domain/Condition/Functions/FormConditionFunctionsProvider.php [new file with mode: 0644]
typo3/sysext/form/Classes/Domain/Runtime/FormRuntime.php
typo3/sysext/form/Configuration/ExpressionLanguage.php [new file with mode: 0644]
typo3/sysext/form/composer.json
typo3/sysext/frontend/Classes/Configuration/TypoScript/ConditionMatching/ConditionMatcher.php
typo3/sysext/frontend/Tests/Unit/Configuration/TypoScript/ConditionMatching/ConditionMatcherTest.php
typo3/sysext/frontend/Tests/UnitDeprecated/Configuration/TypoScript/ConditionMatching/ConditionMatcherTest.php

index 800282a..cee7a17 100644 (file)
@@ -18,7 +18,7 @@ use TYPO3\CMS\Backend\Controller\EditDocumentController;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher;
 use TYPO3\CMS\Core\Context\Context;
-use TYPO3\CMS\Core\ExpressionLanguage\TypoScriptConditionProvider;
+use TYPO3\CMS\Core\ExpressionLanguage\Resolver;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -55,12 +55,15 @@ class ConditionMatcher extends AbstractConditionMatcher
         $backend->user->userId = $backendUserAspect->get('id') ?? 0;
         $backend->user->userGroupList = implode(',', $backendUserAspect->get('groupIds'));
 
-        $typoScriptConditionProvider = GeneralUtility::makeInstance(TypoScriptConditionProvider::class, [
-            'tree' => $tree,
-            'backend' => $backend,
-            'page' => $this->getPage(),
-        ]);
-        parent::__construct($typoScriptConditionProvider);
+        $this->expressionLanguageResolver = GeneralUtility::makeInstance(
+            Resolver::class,
+            'typoscript',
+            [
+                'tree' => $tree,
+                'backend' => $backend,
+                'page' => $this->getPage(),
+            ]
+        );
     }
 
     /**
index c7e831b..ca72d31 100644 (file)
@@ -14,12 +14,17 @@ namespace TYPO3\CMS\Backend\Tests\Unit\Configuration\TypoScript\ConditionMatchin
  * The TYPO3 project - inspiring people to share!
  */
 
+use Prophecy\Argument;
 use TYPO3\CMS\Backend\Configuration\TypoScript\ConditionMatching\ConditionMatcher;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Cache\CacheManager;
+use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
 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\Package\PackageInterface;
+use TYPO3\CMS\Core\Package\PackageManager;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -58,6 +63,21 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
     protected function setUp()
     {
         $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
+        $cacheFrontendProphecy = $this->prophesize(FrontendInterface::class);
+        $cacheFrontendProphecy->has(Argument::any())->willReturn(false);
+        $cacheFrontendProphecy->set(Argument::any(), Argument::any())->willReturn(null);
+        $cacheManagerProphecy = $this->prophesize(CacheManager::class);
+        $cacheManagerProphecy->getCache('cache_core')->willReturn($cacheFrontendProphecy->reveal());
+        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
+
+        $packageManagerProphecy = $this->prophesize(PackageManager::class);
+        $corePackageProphecy = $this->prophesize(PackageInterface::class);
+        $corePackageProphecy->getPackagePath()->willReturn(__DIR__ . '/../../../../../../../sysext/core/');
+        $packageManagerProphecy->getActivePackages()->willReturn([
+            $corePackageProphecy->reveal()
+        ]);
+        GeneralUtility::setSingletonInstance(PackageManager::class, $packageManagerProphecy->reveal());
+
         $this->testTableName = 'conditionMatcherTestTable';
         $this->testGlobalNamespace = $this->getUniqueId('TEST');
         $GLOBALS['TCA'][$this->testTableName] = ['ctrl' => []];
index 3ab7f19..14d4012 100644 (file)
@@ -14,13 +14,18 @@ namespace TYPO3\CMS\Backend\Tests\UnitDeprecated\Configuration\TypoScript\Condit
  * The TYPO3 project - inspiring people to share!
  */
 
+use Prophecy\Argument;
 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\Cache\CacheManager;
+use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
 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\Package\PackageInterface;
+use TYPO3\CMS\Core\Package\PackageManager;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -59,6 +64,20 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
     protected function setUp()
     {
         $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
+        $cacheFrontendProphecy = $this->prophesize(FrontendInterface::class);
+        $cacheFrontendProphecy->has(Argument::any())->willReturn(false);
+        $cacheFrontendProphecy->set(Argument::any(), Argument::any())->willReturn(null);
+        $cacheManagerProphecy = $this->prophesize(CacheManager::class);
+        $cacheManagerProphecy->getCache('cache_core')->willReturn($cacheFrontendProphecy->reveal());
+        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
+
+        $packageManagerProphecy = $this->prophesize(PackageManager::class);
+        $corePackageProphecy = $this->prophesize(PackageInterface::class);
+        $corePackageProphecy->getPackagePath()->willReturn(__DIR__ . '/../../../../../../../sysext/core/');
+        $packageManagerProphecy->getActivePackages()->willReturn([
+            $corePackageProphecy->reveal()
+        ]);
+        GeneralUtility::setSingletonInstance(PackageManager::class, $packageManagerProphecy->reveal());
         $this->testTableName = 'conditionMatcherTestTable';
         $this->testGlobalNamespace = $this->getUniqueId('TEST');
         $GLOBALS['TCA'][$this->testTableName] = ['ctrl' => []];
@@ -158,10 +177,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
         $_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*")]'));
     }
 
     /**
@@ -174,10 +189,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
         $_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*")]'));
     }
 
     /**
@@ -189,9 +200,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
     {
         $_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"]'));
     }
 
     /**
@@ -202,10 +210,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
     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\')]'));
     }
 
     /**
@@ -216,9 +220,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\')]'));
     }
 
     /**
@@ -229,9 +230,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(\'*\')]'));
     }
 
     /**
@@ -242,10 +240,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\')]'));
     }
 
     /**
@@ -257,10 +251,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
     {
         $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\')]'));
     }
 
     /**
@@ -271,9 +261,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\')]'));
     }
 
     /**
@@ -284,10 +271,6 @@ 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]'));
     }
 
     /**
@@ -327,8 +310,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
         $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
     }
 
     /**
@@ -346,8 +327,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
         $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
     }
 
     /**
@@ -360,8 +339,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
         $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
     }
 
     /**
@@ -372,8 +349,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
     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
     }
 
     /**
@@ -385,8 +360,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
     {
         $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
     }
 
     /**
@@ -399,8 +372,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
         $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
     }
 
     /**
@@ -414,8 +385,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
         $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
     }
 
     /**
@@ -428,8 +397,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
         $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
     }
 
     /**
@@ -443,8 +410,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
         $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
     }
 
     /**
@@ -457,8 +422,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
         $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
     }
 
     /**
@@ -484,8 +447,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
     {
         $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
     }
 
     /**
@@ -500,8 +461,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
         $_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
     }
 
     /**
@@ -513,8 +472,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
     {
         $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
     }
 
     /**
@@ -541,8 +498,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
         $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
     }
 
     /**
@@ -555,8 +510,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
         $testKey = $this->getUniqueId('test');
         $_SERVER[$testKey] = '';
         $this->assertTrue($this->matchCondition->match('[globalString = _SERVER|' . $testKey . ' = /^$/]'));
-        // Test expression language
-        // Access request by request() method
     }
 
     /**
@@ -568,8 +521,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
     {
         $this->matchCondition->setRootline($this->rootline);
         $this->assertTrue($this->matchCondition->match('[treeLevel = 2]'));
-        // Test expression language
-        $this->assertTrue($this->matchCondition->match('[tree.level == 2]'));
     }
 
     /**
@@ -581,8 +532,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
     {
         $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]]'));
     }
 
     /**
@@ -594,8 +543,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
     {
         $this->matchCondition->setRootline($this->rootline);
         $this->assertFalse($this->matchCondition->match('[treeLevel = 999]'));
-        // Test expression language
-        $this->assertFalse($this->matchCondition->match('[treeLevel == 999]'));
     }
 
     /**
@@ -661,10 +608,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]'));
     }
 
     /**
@@ -677,8 +620,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
         $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]'));
     }
 
     /**
@@ -691,8 +632,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
         $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]'));
     }
 
     /**
@@ -705,9 +644,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
         $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]'));
     }
 
     /**
@@ -731,9 +667,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
         $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]'));
     }
 
     /**
@@ -764,9 +697,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
         $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]'));
     }
 
     /**
@@ -779,8 +709,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]'));
     }
 
     /**
@@ -793,8 +721,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
         $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]'));
     }
 
     /**
@@ -807,8 +733,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
         $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]'));
     }
 
     /**
@@ -821,8 +745,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]'));
     }
 
     /**
@@ -834,10 +756,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\')]'));
     }
 
     /**
@@ -849,10 +767,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 . '\')]'));
     }
 
     /**
@@ -864,10 +778,6 @@ 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\')]'));
     }
 
     /**
@@ -906,8 +816,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"]'));
     }
 
     /**
@@ -921,8 +829,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
         // 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
     }
 
     /**
@@ -938,8 +844,6 @@ class ConditionMatcherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
         ];
         $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...
     }
 
     /**
index 168fcc0..10835a2 100644 (file)
@@ -21,7 +21,7 @@ use TYPO3\CMS\Core\Configuration\Features;
 use TYPO3\CMS\Core\Configuration\TypoScript\Exception\InvalidTypoScriptConditionException;
 use TYPO3\CMS\Core\Error\Exception;
 use TYPO3\CMS\Core\ExpressionLanguage\Resolver;
-use TYPO3\CMS\Core\ExpressionLanguage\TypoScriptConditionProvider;
+use TYPO3\CMS\Core\Log\LogLevel;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\StringUtility;
 use TYPO3\CMS\Core\Utility\VersionNumberUtility;
@@ -71,11 +71,6 @@ abstract class AbstractConditionMatcher implements LoggerAwareInterface
      */
     protected $expressionLanguageResolver;
 
-    public function __construct(TypoScriptConditionProvider $typoScriptConditionProvider)
-    {
-        $this->expressionLanguageResolver = GeneralUtility::makeInstance(Resolver::class, $typoScriptConditionProvider);
-    }
-
     /**
      * @return bool
      */
@@ -245,10 +240,11 @@ abstract class AbstractConditionMatcher implements LoggerAwareInterface
             if (strpos($exception->getMessage(), 'Unexpected character "="') !== false) {
                 $message .= ' It looks like an old condition with only one equal sign.';
             }
-            $this->logger->warning($message, [
-                'expression' => $expression,
-                'exception' => $exception
-            ]);
+            $this->logger->log(
+                $this->strictSyntaxEnabled() ? LogLevel::WARNING : LogLevel::INFO,
+                $message,
+                ['expression' => $expression]
+            );
         } catch (\Throwable $exception) {
             // The following error handling is required to mitigate a missing type check
             // in the Symfony Expression Language handling. In case a condition
index 90ea8af..3a6ae6a 100644 (file)
@@ -19,7 +19,6 @@ use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
 
 /**
  * Class AbstractProvider
- * @internal
  */
 abstract class AbstractProvider implements ProviderInterface
 {
diff --git a/typo3/sysext/core/Classes/ExpressionLanguage/DefaultFunctionsProvider.php b/typo3/sysext/core/Classes/ExpressionLanguage/DefaultFunctionsProvider.php
deleted file mode 100644 (file)
index 9446104..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-declare(strict_types = 1);
-namespace TYPO3\CMS\Core\ExpressionLanguage;
-
-/*
- * 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 Symfony\Component\ExpressionLanguage\ExpressionFunction;
-use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
-use TYPO3\CMS\Core\Context\Context;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Core\Utility\StringUtility;
-
-/**
- * Class DefaultFunctionsProvider
- * @internal
- */
-class DefaultFunctionsProvider implements ExpressionFunctionProviderInterface
-{
-    /**
-     * @return ExpressionFunction[] An array of Function instances
-     */
-    public function getFunctions()
-    {
-        return [
-            $this->getLikeFunction(),
-            $this->getEnvFunction(),
-            $this->getDateFunction(),
-        ];
-    }
-
-    protected function getLikeFunction(): ExpressionFunction
-    {
-        return new ExpressionFunction('like', function ($str) {
-            // Not implemented, we only use the evaluator
-        }, function ($arguments, $haystack, $needle) {
-            $result = StringUtility::searchStringWildcard((string)$haystack, (string)$needle);
-            return $result;
-        });
-    }
-
-    protected function getEnvFunction(): ExpressionFunction
-    {
-        return ExpressionFunction::fromPhp('getenv');
-    }
-
-    protected function getDateFunction(): ExpressionFunction
-    {
-        return new ExpressionFunction('date', function ($str) {
-            // Not implemented, we only use the evaluator
-        }, function ($arguments, $format) {
-            return GeneralUtility::makeInstance(Context::class)
-                ->getAspect('date')->getDateTime()->format($format);
-        });
-    }
-}
index cbbb75b..149fcb5 100644 (file)
@@ -15,10 +15,16 @@ namespace TYPO3\CMS\Core\ExpressionLanguage;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\ExpressionLanguage\FunctionsProvider\DefaultFunctionsProvider;
+
 /**
  * Class DefaultProvider
  * @internal
  */
 class DefaultProvider extends AbstractProvider
 {
+    public function __construct()
+    {
+        $this->expressionLanguageProviders[] = DefaultFunctionsProvider::class;
+    }
 }
diff --git a/typo3/sysext/core/Classes/ExpressionLanguage/FunctionsProvider/DefaultFunctionsProvider.php b/typo3/sysext/core/Classes/ExpressionLanguage/FunctionsProvider/DefaultFunctionsProvider.php
new file mode 100644 (file)
index 0000000..e4a7699
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+declare(strict_types = 1);
+namespace TYPO3\CMS\Core\ExpressionLanguage\FunctionsProvider;
+
+/*
+ * 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 Symfony\Component\ExpressionLanguage\ExpressionFunction;
+use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
+use TYPO3\CMS\Core\Context\Context;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\StringUtility;
+
+/**
+ * Class DefaultFunctionsProvider
+ * @internal
+ */
+class DefaultFunctionsProvider implements ExpressionFunctionProviderInterface
+{
+    /**
+     * @return ExpressionFunction[] An array of Function instances
+     */
+    public function getFunctions()
+    {
+        return [
+            $this->getLikeFunction(),
+            $this->getEnvFunction(),
+            $this->getDateFunction(),
+        ];
+    }
+
+    protected function getLikeFunction(): ExpressionFunction
+    {
+        return new ExpressionFunction('like', function ($str) {
+            // Not implemented, we only use the evaluator
+        }, function ($arguments, $haystack, $needle) {
+            $result = StringUtility::searchStringWildcard((string)$haystack, (string)$needle);
+            return $result;
+        });
+    }
+
+    protected function getEnvFunction(): ExpressionFunction
+    {
+        return ExpressionFunction::fromPhp('getenv');
+    }
+
+    protected function getDateFunction(): ExpressionFunction
+    {
+        return new ExpressionFunction('date', function ($str) {
+            // Not implemented, we only use the evaluator
+        }, function ($arguments, $format) {
+            return GeneralUtility::makeInstance(Context::class)
+                ->getAspect('date')->getDateTime()->format($format);
+        });
+    }
+}
diff --git a/typo3/sysext/core/Classes/ExpressionLanguage/FunctionsProvider/Typo3ConditionFunctionsProvider.php b/typo3/sysext/core/Classes/ExpressionLanguage/FunctionsProvider/Typo3ConditionFunctionsProvider.php
new file mode 100644 (file)
index 0000000..e3d3245
--- /dev/null
@@ -0,0 +1,188 @@
+<?php
+declare(strict_types = 1);
+namespace TYPO3\CMS\Core\ExpressionLanguage\FunctionsProvider;
+
+/*
+ * 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 Symfony\Component\ExpressionLanguage\ExpressionFunction;
+use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
+use TYPO3\CMS\Core\ExpressionLanguage\RequestWrapper;
+use TYPO3\CMS\Core\Site\Entity\Site;
+use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\VersionNumberUtility;
+
+/**
+ * Class TypoScriptConditionProvider
+ * @internal
+ */
+class Typo3ConditionFunctionsProvider implements ExpressionFunctionProviderInterface
+{
+    /**
+     * @return ExpressionFunction[] An array of Function instances
+     */
+    public function getFunctions()
+    {
+        return [
+            $this->getIpFunction(),
+            $this->getCompatVersionFunction(),
+            $this->getLoginUserFunction(),
+            $this->getTSFEFunction(),
+            $this->getUsergroupFunction(),
+            $this->getSessionFunction(),
+            $this->getSiteFunction(),
+            $this->getSiteLanguageFunction(),
+        ];
+    }
+
+    protected function getIpFunction(): ExpressionFunction
+    {
+        return new ExpressionFunction('ip', function ($str) {
+            // Not implemented, we only use the evaluator
+        }, function ($arguments, $str) {
+            if ($str === 'devIP') {
+                $str = trim($GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask']);
+            }
+            return (bool)GeneralUtility::cmpIP(GeneralUtility::getIndpEnv('REMOTE_ADDR'), $str);
+        });
+    }
+
+    protected function getCompatVersionFunction(): ExpressionFunction
+    {
+        return new ExpressionFunction('compatVersion', function ($str) {
+            // Not implemented, we only use the evaluator
+        }, function ($arguments, $str) {
+            return VersionNumberUtility::convertVersionNumberToInteger(TYPO3_branch) >= VersionNumberUtility::convertVersionNumberToInteger($str);
+        });
+    }
+
+    protected function getLoginUserFunction(): ExpressionFunction
+    {
+        return new ExpressionFunction('loginUser', function ($str) {
+            // Not implemented, we only use the evaluator
+        }, function ($arguments, $str) {
+            $user = $arguments['backend']->user ?? $arguments['frontend']->user;
+            if ($user->isLoggedIn) {
+                foreach (GeneralUtility::trimExplode(',', $str, true) as $test) {
+                    if ($test === '*' || (string)$user->userId === (string)$test) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        });
+    }
+
+    protected function getTSFEFunction(): ExpressionFunction
+    {
+        return new ExpressionFunction('getTSFE', function ($str) {
+            // Not implemented, we only use the evaluator
+        }, function ($arguments) {
+            return $GLOBALS['TSFE'];
+        });
+    }
+
+    protected function getUsergroupFunction(): ExpressionFunction
+    {
+        return new ExpressionFunction('usergroup', function ($str) {
+            // Not implemented, we only use the evaluator
+        }, function ($arguments, $str) {
+            $user = $arguments['backend']->user ?? $arguments['frontend']->user;
+            $groupList = $user->userGroupList ?? '';
+            // '0,-1' is the default usergroups string when not logged in!
+            if ($groupList !== '0,-1' && $groupList !== '') {
+                foreach (GeneralUtility::trimExplode(',', $str, true) as $test) {
+                    if ($test === '*' || GeneralUtility::inList($groupList, $test)) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        });
+    }
+
+    protected function getSessionFunction(): ExpressionFunction
+    {
+        return new ExpressionFunction(
+            'session',
+            function ($str) {
+                // Not implemented, we only use the evaluator
+            },
+            function ($arguments, $str) {
+                $retVal = null;
+                $keyParts = explode('|', $str);
+                $sessionKey = array_shift($keyParts);
+                // @todo fetch data from be session if available
+                $tsfe = $GLOBALS['TSFE'] ?? null;
+                if ($tsfe && is_object($tsfe->fe_user)) {
+                    $retVal = $tsfe->fe_user->getSessionData($sessionKey);
+                    foreach ($keyParts as $keyPart) {
+                        if (is_object($retVal)) {
+                            $retVal = $retVal->{$keyPart};
+                        } elseif (is_array($retVal)) {
+                            $retVal = $retVal[$keyPart];
+                        } else {
+                            break;
+                        }
+                    }
+                }
+                return $retVal;
+            }
+        );
+    }
+
+    protected function getSiteFunction(): ExpressionFunction
+    {
+        return new ExpressionFunction(
+            'site',
+            function ($str) {
+                // Not implemented, we only use the evaluator
+            },
+            function ($arguments, $str) {
+                /** @var RequestWrapper $requestWrapper */
+                $requestWrapper = $arguments['request'];
+                $site = $requestWrapper->getSite();
+                if ($site instanceof Site) {
+                    $methodName = 'get' . ucfirst(trim($str));
+                    if (method_exists($site, $methodName)) {
+                        return $site->$methodName();
+                    }
+                }
+                return null;
+            }
+        );
+    }
+
+    protected function getSiteLanguageFunction(): ExpressionFunction
+    {
+        return new ExpressionFunction(
+            'siteLanguage',
+            function ($str) {
+                // Not implemented, we only use the evaluator
+            },
+            function ($arguments, $str) {
+                /** @var RequestWrapper $requestWrapper */
+                $requestWrapper = $arguments['request'];
+                $siteLanguage = $requestWrapper->getSiteLanguage();
+                if ($siteLanguage instanceof SiteLanguage) {
+                    $methodName = 'get' . ucfirst(trim($str));
+                    if (method_exists($siteLanguage, $methodName)) {
+                        return $siteLanguage->$methodName();
+                    }
+                }
+                return null;
+            }
+        );
+    }
+}
diff --git a/typo3/sysext/core/Classes/ExpressionLanguage/ProviderConfigurationLoader.php b/typo3/sysext/core/Classes/ExpressionLanguage/ProviderConfigurationLoader.php
new file mode 100644 (file)
index 0000000..acc1d7e
--- /dev/null
@@ -0,0 +1,51 @@
+<?php
+declare(strict_types = 1);
+
+namespace TYPO3\CMS\Core\ExpressionLanguage;
+
+use TYPO3\CMS\Core\Cache\CacheManager;
+use TYPO3\CMS\Core\Package\PackageManager;
+use TYPO3\CMS\Core\Service\DependencyOrderingService;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * Class ProviderConfigurationLoader
+ * This class resolves the expression language provider configuration and store in a cache.
+ */
+class ProviderConfigurationLoader
+{
+    protected $cacheIdentifier = 'expressionLanguageProviders';
+
+    /**
+     * @return array
+     * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
+     */
+    public function getExpressionLanguageProviders(): array
+    {
+        $packageManager = GeneralUtility::makeInstance(
+            PackageManager::class,
+            GeneralUtility::makeInstance(DependencyOrderingService::class)
+        );
+        $cache = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_core');
+
+        if ($cache->has($this->cacheIdentifier)) {
+            /** @noinspection PhpUndefinedMethodInspection the method require() will be added to the interface in v10 */
+            return $cache->require($this->cacheIdentifier);
+        }
+
+        $packages = $packageManager->getActivePackages();
+        $providers = [];
+        foreach ($packages as $package) {
+            $packageConfiguration = $package->getPackagePath() . 'Configuration/ExpressionLanguage.php';
+            if (file_exists($packageConfiguration)) {
+                $providersInPackage = require $packageConfiguration;
+                if (is_array($providersInPackage)) {
+                    $providers[] = $providersInPackage;
+                }
+            }
+        }
+        $providers = count($providers) > 0 ? array_merge_recursive(...$providers) : $providers;
+        $cache->set($this->cacheIdentifier, 'return ' . var_export($providers, true) . ';');
+        return $providers ?? [];
+    }
+}
index 3611e0b..4438b43 100644 (file)
@@ -19,7 +19,6 @@ use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
 
 /**
  * Interface ProviderInterface
- * @internal
  */
 interface ProviderInterface
 {
index e59cb61..9a5ad58 100644 (file)
@@ -17,6 +17,7 @@ namespace TYPO3\CMS\Core\ExpressionLanguage;
 
 use Psr\Http\Message\ServerRequestInterface;
 use TYPO3\CMS\Core\Http\NormalizedParams;
+use TYPO3\CMS\Core\Http\ServerRequest;
 use TYPO3\CMS\Core\Site\Entity\Site;
 use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
 
@@ -25,6 +26,9 @@ use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
  * This class provides access to some methods of the ServerRequest object.
  * To prevent access to all methods of the ServerRequest object within conditions,
  * this class was introduced to control which methods are exposed.
+ *
+ * Additionally this class can be used to simulate a request for condition matching in case the condition matcher calls
+ * should be simulated (for example simulating parsing of TypoScript on CLI)
  * @internal
  */
 class RequestWrapper
@@ -34,9 +38,9 @@ class RequestWrapper
      */
     protected $request;
 
-    public function __construct()
+    public function __construct(?ServerRequestInterface $request)
     {
-        $this->request = $GLOBALS['TYPO3_REQUEST'];
+        $this->request = $request ?? new ServerRequest();
     }
 
     public function getQueryParams(): array
index eefb07c..013463d 100644 (file)
@@ -16,10 +16,10 @@ namespace TYPO3\CMS\Core\ExpressionLanguage;
  */
 
 use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
  * Class Resolver
- * @internal
  */
 class Resolver
 {
@@ -39,13 +39,31 @@ class Resolver
     public $expressionLanguageVariables = [];
 
     /**
-     * @param ProviderInterface $provider
+     * @param string $context
+     * @param array $variables
      */
-    public function __construct(ProviderInterface $provider)
+    public function __construct(string $context, array $variables)
     {
-        $this->provider = $provider;
-        $this->expressionLanguage = new ExpressionLanguage(null, $provider->getExpressionLanguageProviders());
-        $this->expressionLanguageVariables = $provider->getExpressionLanguageVariables();
+        $functionProviderInstances = [];
+        $providers = GeneralUtility::makeInstance(ProviderConfigurationLoader::class)->getExpressionLanguageProviders()[$context] ?? [];
+        // Always add default provider
+        array_unshift($providers, DefaultProvider::class);
+        $providers = array_unique($providers);
+        $functionProviders = [];
+        $generalVariables = [];
+        foreach ($providers as $provider) {
+            /** @var ProviderInterface $providerInstance */
+            $providerInstance = GeneralUtility::makeInstance($provider);
+            $functionProviders[] = $providerInstance->getExpressionLanguageProviders();
+            $generalVariables[] = $providerInstance->getExpressionLanguageVariables();
+        }
+        $functionProviders = array_merge(...$functionProviders);
+        $generalVariables = array_replace_recursive(...$generalVariables);
+        $this->expressionLanguageVariables = array_replace_recursive($generalVariables, $variables);
+        foreach ($functionProviders as $functionProvider) {
+            $functionProviderInstances[] = GeneralUtility::makeInstance($functionProvider);
+        }
+        $this->expressionLanguage = new ExpressionLanguage(null, $functionProviderInstances);
     }
 
     /**
diff --git a/typo3/sysext/core/Classes/ExpressionLanguage/TypoScriptConditionFunctionsProvider.php b/typo3/sysext/core/Classes/ExpressionLanguage/TypoScriptConditionFunctionsProvider.php
deleted file mode 100644 (file)
index e0d8d11..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-<?php
-declare(strict_types = 1);
-namespace TYPO3\CMS\Core\ExpressionLanguage;
-
-/*
- * 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 Symfony\Component\ExpressionLanguage\ExpressionFunction;
-use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Core\Utility\VersionNumberUtility;
-
-/**
- * Class TypoScriptConditionProvider
- * @internal
- */
-class TypoScriptConditionFunctionsProvider implements ExpressionFunctionProviderInterface
-{
-    /**
-     * @return ExpressionFunction[] An array of Function instances
-     */
-    public function getFunctions()
-    {
-        return [
-            $this->getIpFunction(),
-            $this->getCompatVersionFunction(),
-            $this->getLoginUserFunction(),
-            $this->getTSFEFunction(),
-            $this->getUsergroupFunction(),
-        ];
-    }
-
-    protected function getIpFunction(): ExpressionFunction
-    {
-        return new ExpressionFunction('ip', function ($str) {
-            // Not implemented, we only use the evaluator
-        }, function ($arguments, $str) {
-            if ($str === 'devIP') {
-                $str = trim($GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask']);
-            }
-            return (bool)GeneralUtility::cmpIP(GeneralUtility::getIndpEnv('REMOTE_ADDR'), $str);
-        });
-    }
-
-    protected function getCompatVersionFunction(): ExpressionFunction
-    {
-        return new ExpressionFunction('compatVersion', function ($str) {
-            // Not implemented, we only use the evaluator
-        }, function ($arguments, $str) {
-            return VersionNumberUtility::convertVersionNumberToInteger(TYPO3_branch) >= VersionNumberUtility::convertVersionNumberToInteger($str);
-        });
-    }
-
-    protected function getLoginUserFunction(): ExpressionFunction
-    {
-        return new ExpressionFunction('loginUser', function ($str) {
-            // Not implemented, we only use the evaluator
-        }, function ($arguments, $str) {
-            $user = $arguments['backend']->user ?? $arguments['frontend']->user;
-            if ($user->isLoggedIn) {
-                foreach (GeneralUtility::trimExplode(',', $str, true) as $test) {
-                    if ($test === '*' || (string)$user->userId === (string)$test) {
-                        return true;
-                    }
-                }
-            }
-            return false;
-        });
-    }
-
-    protected function getTSFEFunction(): ExpressionFunction
-    {
-        return new ExpressionFunction('getTSFE', function ($str) {
-            // Not implemented, we only use the evaluator
-        }, function ($arguments) {
-            return $GLOBALS['TSFE'];
-        });
-    }
-
-    protected function getUsergroupFunction(): ExpressionFunction
-    {
-        return new ExpressionFunction('usergroup', function ($str) {
-            // Not implemented, we only use the evaluator
-        }, function ($arguments, $str) {
-            $user = $arguments['backend']->user ?? $arguments['frontend']->user;
-            $groupList = $user->userGroupList ?? '';
-            // '0,-1' is the default usergroups string when not logged in!
-            if ($groupList !== '0,-1' && $groupList !== '') {
-                foreach (GeneralUtility::trimExplode(',', $str, true) as $test) {
-                    if ($test === '*' || GeneralUtility::inList($groupList, $test)) {
-                        return true;
-                    }
-                }
-            }
-            return false;
-        });
-    }
-}
index 6ec9ca0..c38d32c 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 declare(strict_types = 1);
+
 namespace TYPO3\CMS\Core\ExpressionLanguage;
 
 /*
@@ -15,41 +16,29 @@ namespace TYPO3\CMS\Core\ExpressionLanguage;
  * The TYPO3 project - inspiring people to share!
  */
 
-use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
+use TYPO3\CMS\Core\ExpressionLanguage\FunctionsProvider\Typo3ConditionFunctionsProvider;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
  * Class TypoScriptConditionProvider
+ *
  * @internal
  */
 class TypoScriptConditionProvider extends AbstractProvider
 {
-    public function __construct(array $expressionLanguageVariables = [], array $expressionLanguageProviders = [])
+    public function __construct()
     {
         $typo3 = new \stdClass();
         $typo3->version = TYPO3_version;
         $typo3->branch = TYPO3_branch;
         $typo3->devIpMask = trim($GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask']);
-        $this->expressionLanguageVariables = array_merge([
-            'request' => GeneralUtility::makeInstance(RequestWrapper::class),
+        $this->expressionLanguageVariables = [
+            'request' => GeneralUtility::makeInstance(RequestWrapper::class, $GLOBALS['TYPO3_REQUEST'] ?? null),
             'applicationContext' => (string)GeneralUtility::getApplicationContext(),
             'typo3' => $typo3,
-        ], $expressionLanguageVariables);
-
-        $this->expressionLanguageProviders = $expressionLanguageProviders;
-        $this->initFunctions();
-    }
-
-    protected function initFunctions(): void
-    {
-        $this->expressionLanguageProviders[] = GeneralUtility::makeInstance(DefaultFunctionsProvider::class);
-        $this->expressionLanguageProviders[] = GeneralUtility::makeInstance(TypoScriptConditionFunctionsProvider::class);
-
-        foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][__CLASS__]['additionalExpressionLanguageProvider'] ?? [] as $className) {
-            $expressionLanguageProvider = GeneralUtility::makeInstance($className);
-            if ($expressionLanguageProvider instanceof ExpressionFunctionProviderInterface) {
-                $this->expressionLanguageProviders[] = $expressionLanguageProvider;
-            }
-        }
+        ];
+        $this->expressionLanguageProviders = [
+            Typo3ConditionFunctionsProvider::class
+        ];
     }
 }
diff --git a/typo3/sysext/core/Classes/ExpressionLanguage/TypoScriptFrontendConditionFunctionsProvider.php b/typo3/sysext/core/Classes/ExpressionLanguage/TypoScriptFrontendConditionFunctionsProvider.php
deleted file mode 100644 (file)
index 50b601c..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-<?php
-declare(strict_types = 1);
-namespace TYPO3\CMS\Core\ExpressionLanguage;
-
-/*
- * 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 Symfony\Component\ExpressionLanguage\ExpressionFunction;
-use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
-use TYPO3\CMS\Core\Site\Entity\Site;
-use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
-
-/**
- * Class TypoScriptFrontendConditionFunctionsProvider
- * @internal
- */
-class TypoScriptFrontendConditionFunctionsProvider implements ExpressionFunctionProviderInterface
-{
-    /**
-     * @return ExpressionFunction[] An array of Function instances
-     */
-    public function getFunctions()
-    {
-        $functions = [
-            $this->getSessionFunction(),
-            $this->getSiteFunction(),
-            $this->getSiteLanguageFunction(),
-        ];
-
-        return $functions;
-    }
-
-    protected function getSessionFunction(): ExpressionFunction
-    {
-        return new ExpressionFunction('session', function ($str) {
-            // Not implemented, we only use the evaluator
-        }, function ($arguments, $str) {
-            $retVal = null;
-            $keyParts = explode('|', $str);
-            $sessionKey = array_shift($keyParts);
-            $tsfe = $GLOBALS['TSFE'];
-            if ($tsfe && is_object($tsfe->fe_user)) {
-                $retVal = $tsfe->fe_user->getSessionData($sessionKey);
-                foreach ($keyParts as $keyPart) {
-                    if (is_object($retVal)) {
-                        $retVal = $retVal->{$keyPart};
-                    } elseif (is_array($retVal)) {
-                        $retVal = $retVal[$keyPart];
-                    } else {
-                        break;
-                    }
-                }
-            }
-            return $retVal;
-        });
-    }
-
-    protected function getSiteFunction(): ExpressionFunction
-    {
-        return new ExpressionFunction('site', function ($str) {
-            // Not implemented, we only use the evaluator
-        }, function ($arguments, $str) {
-            /** @var RequestWrapper $requestWrapper */
-            $requestWrapper = $arguments['request'];
-            $site = $requestWrapper->getSite();
-            if ($site instanceof Site) {
-                $methodName = 'get' . ucfirst(trim($str));
-                if (method_exists($site, $methodName)) {
-                    return $site->$methodName();
-                }
-            }
-            return null;
-        });
-    }
-
-    protected function getSiteLanguageFunction(): ExpressionFunction
-    {
-        return new ExpressionFunction('siteLanguage', function ($str) {
-            // Not implemented, we only use the evaluator
-        }, function ($arguments, $str) {
-            /** @var RequestWrapper $requestWrapper */
-            $requestWrapper = $arguments['request'];
-            $siteLanguage = $requestWrapper->getSiteLanguage();
-            if ($siteLanguage instanceof SiteLanguage) {
-                $methodName = 'get' . ucfirst(trim($str));
-                if (method_exists($siteLanguage, $methodName)) {
-                    return $siteLanguage->$methodName();
-                }
-            }
-            return null;
-        });
-    }
-}
diff --git a/typo3/sysext/core/Configuration/ExpressionLanguage.php b/typo3/sysext/core/Configuration/ExpressionLanguage.php
new file mode 100644 (file)
index 0000000..77e46ca
--- /dev/null
@@ -0,0 +1,11 @@
+<?php
+
+return [
+    'default' => [
+        // The DefaultProvider is loaded every time
+        // \TYPO3\CMS\Core\ExpressionLanguage\DefaultProvider::class,
+    ],
+    'typoscript' => [
+        \TYPO3\CMS\Core\ExpressionLanguage\TypoScriptConditionProvider::class,
+    ]
+];
index 243f629..33f5250 100644 (file)
@@ -20,13 +20,100 @@ For a custom implementation the :php:`\TYPO3\CMS\Core\ExpressionLanguage\Abstrac
 The provider can provide additional variables and expression functions to extend the expression language.
 For a custom implementation check out the :php:`\TYPO3\CMS\Form\Domain\Condition\ConditionProvider` class.
 
-A usage example:
+An example with the DefaultProvider:
 
 .. code-block:: php
 
-   $provider = GeneralUtility::makeInstance(\TYPO3\CMS\Core\ExpressionLanguage\DefaultProvider::class);
-   $conditionResolver = GeneralUtility::makeInstance(\TYPO3\CMS\Core\ExpressionLanguage\Resolver::class, $provider);
-   $conditionResolver->evaluate('1 < 2'); // result is true
+   $resolver = GeneralUtility::makeInstance(
+      Resolver::class,
+      'default',
+      [
+         'foo' => 1,
+         'bar' => 2,
+      ]
+   );
+   $resolver->evaluate('1 < 2'); // result is true
+   $resolver->evaluate('foo < bar'); // result is true
+   $resolver->evaluate('bar < foo'); // result is false
+
+
+An example with a custom Provider:
+
+First you have to configure a provider, create a file in your extension with the path and name :file:`EXT:my_ext\Configuration\ExpressionLanguage.php`:
+
+.. code-block:: php
+
+   <?php
+      return [
+         'my-context-identifier' => [
+            \TYPO3\CMS\MyExt\ExpressionLanguage\MyCustomProvider::class,
+         ]
+      ];
+
+
+Next implement your provider class :php:`\TYPO3\CMS\MyExt\ExpressionLanguage\MyCustomProvider::class`
+
+.. code-block:: php
+
+   class MyCustomProvider extends \TYPO3\CMS\Core\ExpressionLanguage\AbstractProvider
+   {
+      public function __construct(ServerRequestInterface $request)
+      {
+         $this->expressionLanguageVariables = [
+            'foo' => 1,
+            'bar' => 2,
+         ];
+         $this->expressionLanguageProviders = [
+            // We use the existing Typo3ConditionsFunctions...
+            Typo3ConditionFunctionsProvider::class,
+            // ... and our custom function provider
+            MyCustomFunctionsProvider::class
+         ];
+      }
+   }
+
+
+Next implement your provider class :php:`\TYPO3\CMS\MyExt\ExpressionLanguage\MyCustomFunctionProvider::class`
+
+.. code-block:: php
+
+   class MyCustomFunctionProvider implements ExpressionFunctionProviderInterface
+   {
+      public function getFunctions()
+      {
+         return [
+            $this->getFooFunction(),
+         ];
+      }
+
+      protected function getFooFunction(): ExpressionFunction
+      {
+         return new ExpressionFunction('compatVersion', function ($str) {
+            // Not implemented, we only use the evaluator
+         }, function ($arguments, $str) {
+            return $str === 'foo';
+         });
+      }
+   }
+
+
+And now we use it:
+
+.. code-block:: php
+
+   $resolver = GeneralUtility::makeInstance(
+      Resolver::class,
+      'my-context-identifier',
+      [
+         'baz' => 3,
+      ]
+   );
+   $resolver->evaluate('1 < 2'); // result is true
+   $resolver->evaluate('foo < bar'); // result is true
+   $resolver->evaluate('bar < baz'); // result is true
+   $resolver->evaluate('bar < foo'); // result is false
+   $resolver->evaluate('foo("foo")'); // result is true
+   $resolver->evaluate('foo("bar")'); // result is false
 
 
 Impact
index 3ffac0a..9a55296 100644 (file)
@@ -200,18 +200,23 @@ Extending the expression language with own functions (like old userFunc)
 ------------------------------------------------------------------------
 
 It is possible to extend the expression language with own functions like before userFunc in the old conditions.
-An example could be :php:`TYPO3\CMS\Core\ExpressionLanguage\TypoScriptConditionFunctionsProvider` which implements
+An example could be :php:`TYPO3\CMS\Core\ExpressionLanguage\FunctionsProvider\TypoScriptConditionFunctionsProvider` which implements
 the most core functions.
 
+Please read .. _the introduction: https://docs.typo3.org/typo3cms/extensions/core/Changelog/9.4/Feature-85828-MoveSymfonyExpressionLanguageHandlingIntoEXTcore.html first.
+
 Add new methods by implementing own providers which implement the :php:`ExpressionFunctionProviderInterface` and
-register the provider in :file:`ext_localconf.php`:
+register the provider for the key `typoscript` in your own :file:`Configuration\ExpressionLanguage.php` file:
 
 .. code-block:: php
 
-   if (!is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['TYPO3\CMS\Core\ExpressionLanguage\TypoScriptConditionProvider']['additionalExpressionLanguageProvider'])) {
-      $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['TYPO3\CMS\Core\ExpressionLanguage\TypoScriptConditionProvider']['additionalExpressionLanguageProvider'] = [];
-   }
-   $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['TYPO3\CMS\Core\ExpressionLanguage\TypoScriptConditionProvider']['additionalExpressionLanguageProvider'][] = \My\NameSpace\Provider\TypoScriptConditionProvider::class;
+      return [
+         'typoscript' => [
+            \TYPO3\CMS\MyExt\ExpressionLanguage\MyCustomProvider::class,
+         ]
+      ];
+
 
+The code above will extend the TypoScript condition configuration with your own provider, which provide your own functions.
 
 .. index:: Backend, Frontend, TypoScript, ext:core
index a176f0e..358acb0 100644 (file)
@@ -15,13 +15,18 @@ namespace TYPO3\CMS\Core\Tests\Unit\Configuration\TypoScript\ConditionMatching;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Prophecy\Argument;
+use TYPO3\CMS\Backend\Configuration\TypoScript\ConditionMatching\ConditionMatcher;
+use TYPO3\CMS\Core\Cache\CacheManager;
+use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
 use TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher;
 use TYPO3\CMS\Core\Context\Context;
 use TYPO3\CMS\Core\Context\DateTimeAspect;
 use TYPO3\CMS\Core\Core\ApplicationContext;
-use TYPO3\CMS\Core\ExpressionLanguage\TypoScriptConditionProvider;
 use TYPO3\CMS\Core\Http\ServerRequest;
 use TYPO3\CMS\Core\Log\Logger;
+use TYPO3\CMS\Core\Package\PackageInterface;
+use TYPO3\CMS\Core\Package\PackageManager;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
 
@@ -59,6 +64,20 @@ class AbstractConditionMatcherTest extends UnitTestCase
 
         $this->resetSingletonInstances = true;
         $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
+        $cacheFrontendProphecy = $this->prophesize(FrontendInterface::class);
+        $cacheFrontendProphecy->has(Argument::any())->willReturn(false);
+        $cacheFrontendProphecy->set(Argument::any(), Argument::any())->willReturn(null);
+        $cacheManagerProphecy = $this->prophesize(CacheManager::class);
+        $cacheManagerProphecy->getCache('cache_core')->willReturn($cacheFrontendProphecy->reveal());
+        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
+
+        $packageManagerProphecy = $this->prophesize(PackageManager::class);
+        $corePackageProphecy = $this->prophesize(PackageInterface::class);
+        $corePackageProphecy->getPackagePath()->willReturn(__DIR__ . '/../../../../../../../sysext/core/');
+        $packageManagerProphecy->getActivePackages()->willReturn([
+            $corePackageProphecy->reveal()
+        ]);
+        GeneralUtility::setSingletonInstance(PackageManager::class, $packageManagerProphecy->reveal());
 
         $this->initConditionMatcher();
         $this->backupApplicationContext = GeneralUtility::getApplicationContext();
@@ -66,8 +85,8 @@ class AbstractConditionMatcherTest extends UnitTestCase
 
     protected function initConditionMatcher()
     {
-        $typoScriptConditionProvider = GeneralUtility::makeInstance(TypoScriptConditionProvider::class);
-        $this->conditionMatcher = $this->getMockForAbstractClass(AbstractConditionMatcher::class, [$typoScriptConditionProvider]);
+        // test the abstract methods via the backend condition matcher
+        $this->conditionMatcher = $this->getAccessibleMock(ConditionMatcher::class, ['determineRootline']);
         $this->evaluateConditionCommonMethod = new \ReflectionMethod(AbstractConditionMatcher::class, 'evaluateConditionCommon');
         $this->evaluateConditionCommonMethod->setAccessible(true);
         $this->evaluateExpressionMethod = new \ReflectionMethod(AbstractConditionMatcher::class, 'evaluateExpression');
@@ -316,7 +335,8 @@ class AbstractConditionMatcherTest extends UnitTestCase
         GeneralUtility::setIndpEnv('REMOTE_ADDR', $actualIp);
         $GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask'] = $devIpMask;
         $this->initConditionMatcher();
-        $this->assertSame($expectedResult, $this->evaluateExpressionMethod->invokeArgs($this->conditionMatcher, ['ip("devIP")']));
+        $result = $this->evaluateExpressionMethod->invokeArgs($this->conditionMatcher, ['ip("devIP")']);
+        $this->assertSame($expectedResult, $result);
     }
 
     /**
index 3ba92e0..31cc2a5 100644 (file)
@@ -15,10 +15,17 @@ namespace TYPO3\CMS\Core\Tests\Unit\ExpressionLanguage;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Prophecy\Argument;
 use Symfony\Component\ExpressionLanguage\ExpressionFunction;
-use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
+use TYPO3\CMS\Core\Cache\CacheManager;
+use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
 use TYPO3\CMS\Core\ExpressionLanguage\DefaultProvider;
+use TYPO3\CMS\Core\ExpressionLanguage\FunctionsProvider\DefaultFunctionsProvider;
 use TYPO3\CMS\Core\ExpressionLanguage\Resolver;
+use TYPO3\CMS\Core\Http\ServerRequest;
+use TYPO3\CMS\Core\Package\PackageInterface;
+use TYPO3\CMS\Core\Package\PackageManager;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
 
 /**
@@ -26,6 +33,27 @@ use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
  */
 class ResolverTest extends UnitTestCase
 {
+    public function setUp()
+    {
+        parent::setUp();
+        $this->resetSingletonInstances = true;
+
+        $cacheFrontendProphecy = $this->prophesize(FrontendInterface::class);
+        $cacheFrontendProphecy->has(Argument::any())->willReturn(false);
+        $cacheFrontendProphecy->set(Argument::any(), Argument::any())->willReturn(null);
+        $cacheManagerProphecy = $this->prophesize(CacheManager::class);
+        $cacheManagerProphecy->getCache('cache_core')->willReturn($cacheFrontendProphecy->reveal());
+        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
+
+        $packageManagerProphecy = $this->prophesize(PackageManager::class);
+        $corePackageProphecy = $this->prophesize(PackageInterface::class);
+        $corePackageProphecy->getPackagePath()->willReturn(__DIR__ . '/../../../../../../../sysext/core/');
+        $packageManagerProphecy->getActivePackages()->willReturn([
+            $corePackageProphecy->reveal()
+        ]);
+        GeneralUtility::setSingletonInstance(PackageManager::class, $packageManagerProphecy->reveal());
+    }
+
     /**
      * @return array
      */
@@ -50,7 +78,8 @@ class ResolverTest extends UnitTestCase
      */
     public function basicExpressionHandlingResultsWorksAsExpected(string $expression, $expectedResult)
     {
-        $expressionLanguageResolver = new Resolver(new DefaultProvider());
+        $request = new ServerRequest();
+        $expressionLanguageResolver = new Resolver('default', [], $request);
         $this->assertSame($expectedResult, $expressionLanguageResolver->evaluate($expression));
     }
 
@@ -86,7 +115,9 @@ class ResolverTest extends UnitTestCase
             'varTrue' => true,
             'varFalse' => false,
          ]);
-        $expressionLanguageResolver = new Resolver($contextProphecy->reveal());
+        $request = new ServerRequest();
+        GeneralUtility::addInstance(DefaultProvider::class, $contextProphecy->reveal());
+        $expressionLanguageResolver = new Resolver('default', [], $request);
         $this->assertSame($expectedResult, $expressionLanguageResolver->evaluate($expression));
     }
 
@@ -111,7 +142,7 @@ class ResolverTest extends UnitTestCase
      */
     public function basicExpressionHandlingWithCustomVariablesAndExpressionLanguageProviderWorksAsExpected(string $expression, $expectedResult)
     {
-        $expressionProvider = $this->prophesize(ExpressionFunctionProviderInterface::class);
+        $expressionProvider = $this->prophesize(DefaultFunctionsProvider::class);
         $expressionProvider->getFunctions()->willReturn([
             new ExpressionFunction('testMeLowercase', function ($str) {
                 return sprintf('(is_string(%1$s) ? strtolower(%1$s) : %1$s)', $str);
@@ -120,12 +151,15 @@ class ResolverTest extends UnitTestCase
             })
         ]);
         $contextProphecy = $this->prophesize(DefaultProvider::class);
-        $contextProphecy->getExpressionLanguageProviders()->willReturn([$expressionProvider->reveal()]);
+        $contextProphecy->getExpressionLanguageProviders()->willReturn([DefaultFunctionsProvider::class]);
         $contextProphecy->getExpressionLanguageVariables()->willReturn([
             'var1' => 'FOO',
             'var2' => 'foo'
          ]);
-        $expressionLanguageResolver = new Resolver($contextProphecy->reveal());
+        $request = new ServerRequest();
+        GeneralUtility::addInstance(DefaultProvider::class, $contextProphecy->reveal());
+        GeneralUtility::addInstance(DefaultFunctionsProvider::class, $expressionProvider->reveal());
+        $expressionLanguageResolver = new Resolver('default', [], $request);
         $this->assertSame($expectedResult, $expressionLanguageResolver->evaluate($expression));
     }
 }
index b8e3c68..4378357 100644 (file)
@@ -29,6 +29,7 @@
                "nikic/php-parser": "^4.0",
                "psr/container": "^1.0",
                "psr/http-message": "~1.0",
+               "psr/http-server-handler": "^1.0",
                "psr/http-server-middleware": "^1.0",
                "psr/log": "~1.0.0",
                "swiftmailer/swiftmailer": "~5.4.5",
index 2881a6b..74dd016 100644 (file)
@@ -15,96 +15,23 @@ namespace TYPO3\CMS\Form\Domain\Condition;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Psr\Http\Message\ServerRequestInterface;
 use TYPO3\CMS\Core\ExpressionLanguage\AbstractProvider;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Form\Domain\Exception;
-use TYPO3\CMS\Form\Domain\Runtime\FormRuntime;
-use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
-use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
+use TYPO3\CMS\Form\Domain\Condition\Functions\FormConditionFunctionsProvider;
 
 /**
  * Scope: frontend
- * **This class is NOT meant to be sub classed by developers.**
+ * **This classis NOT meant to be sub classed by developers .**
  *
  * @internal
- */
  */
 class ConditionProvider extends AbstractProvider
 {
-    /**
-     * @param FormRuntime $formRuntime
-     */
-    public function __construct(FormRuntime $formRuntime)
+    public function __construct(ServerRequestInterface $request)
     {
-        $this->expressionLanguageVariables = $this->getInitialExpressionLanguageVariables($formRuntime);
-
-        $conditionContextDefinition = $formRuntime->getFormDefinition()->getConditionContextDefinition();
-
-        foreach ($conditionContextDefinition['expressionLanguageProvider'] ?? [] as $expressionLanguageProviderName => $expressionLanguageProviderDefinition) {
-            if (!isset($expressionLanguageProviderDefinition['implementationClassName'])) {
-                throw new Exception(sprintf('The "implementationClassName" was not set for expression language provider "%s".', $expressionLanguageProviderName), 1526695869);
-            }
-            $implementationClassName = $expressionLanguageProviderDefinition['implementationClassName'];
-
-            /** @see https://symfony.com/doc/4.0/components/expression_language/extending.html#using-expression-providers */
-            $this->expressionLanguageProviders[] = new $implementationClassName();
-        }
-
-        foreach ($conditionContextDefinition['expressionLanguageVariableProvider'] ?? [] as $expressionLanguageVariableProviderName => $expressionLanguageVariableProviderDefinition) {
-            if (!isset($expressionLanguageVariableProviderDefinition['implementationClassName'])) {
-                throw new Exception(sprintf('The "implementationClassName" was not set for expression language variable provider "%s".', $expressionLanguageVariableProviderName), 1526695870);
-            }
-
-            $implementationClassName = $expressionLanguageVariableProviderDefinition['implementationClassName'];
-            $expressionLanguageVariableProvider = new $implementationClassName($formRuntime);
-            if (!($expressionLanguageVariableProvider instanceof ExpressionLanguageVariableProviderInterface)) {
-                throw new Exception(sprintf('The expression language provider "%s" must implement "%s".', $implementationClassName, ExpressionLanguageVariableProviderInterface::class), 1526695874);
-            }
-            /** @see https://symfony.com/doc/4.0/components/expression_language.html#passing-in-variables */
-            $this->expressionLanguageVariables[$expressionLanguageVariableProvider->getVariableName()] = $expressionLanguageVariableProvider->getVariableValue();
-        }
-    }
-
-    /**
-     * @param FormRuntime $formRuntime
-     * @return array
-     */
-    protected function getInitialExpressionLanguageVariables(FormRuntime $formRuntime): array
-    {
-        $formValues = array_replace_recursive($formRuntime->getFormState()->getFormValues(), $formRuntime->getRequest()->getArguments());
-        $page = $formRuntime->getCurrentPage() ?? $formRuntime->getFormDefinition()->getPageByIndex(0);
-
-        $finisherIdentifier = '';
-        if ($formRuntime->getCurrentFinisher() !== null) {
-            $finisherIdentifier = (new \ReflectionClass($formRuntime->getCurrentFinisher()))->getShortName();
-            $finisherIdentifier = preg_replace('/Finisher$/', '', $finisherIdentifier);
-        }
-
-        $contentObjectData = [];
-        if (
-            TYPO3_MODE === 'FE'
-            && $this->getTypoScriptFrontendController()->cObj instanceof ContentObjectRenderer
-        ) {
-            $contentObjectData = $this->getTypoScriptFrontendController()->cObj->data;
-        }
-
-        return [
-            'formRuntime' => $formRuntime,
-            // some shortcuts
-            'formValues' => $formValues,
-            'stepIdentifier' => $page->getIdentifier(),
-            'stepType' => $page->getType(),
-            'finisherIdentifier' => $finisherIdentifier,
-            'siteLanguage' => $formRuntime->getCurrentSiteLanguage(),
-            'applicationContext' => GeneralUtility::getApplicationContext()->__toString(),
-            'contentObject' => $contentObjectData,
+        parent::__construct($request);
+        $this->expressionLanguageProviders = [
+            FormConditionFunctionsProvider::class
         ];
     }
-
-    /**
-     * @return TypoScriptFrontendController
-     */
-    protected function getTypoScriptFrontendController(): TypoScriptFrontendController
-    {
-        return $GLOBALS['TSFE'];
-    }
 }
diff --git a/typo3/sysext/form/Classes/Domain/Condition/ExpressionLanguageVariableProviderInterface.php b/typo3/sysext/form/Classes/Domain/Condition/ExpressionLanguageVariableProviderInterface.php
deleted file mode 100644 (file)
index feaa915..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-declare(strict_types = 1);
-namespace TYPO3\CMS\Form\Domain\Condition;
-
-/*
- * 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\Form\Domain\Runtime\FormRuntime;
-
-/**
- * Scope: frontend / backend
- * @api
- */
-interface ExpressionLanguageVariableProviderInterface
-{
-
-    /**
-     * @param FormRuntime $formRuntime
-     */
-    public function __construct(FormRuntime $formRuntime);
-
-    /**
-     * @return string
-     */
-    public function getVariableName(): string;
-
-    /**
-     * @return mixed
-     */
-    public function getVariableValue();
-}
diff --git a/typo3/sysext/form/Classes/Domain/Condition/Functions/FormConditionFunctionsProvider.php b/typo3/sysext/form/Classes/Domain/Condition/Functions/FormConditionFunctionsProvider.php
new file mode 100644 (file)
index 0000000..06a4016
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+declare(strict_types = 1);
+
+namespace TYPO3\CMS\Form\Domain\Condition\Functions;
+
+use Symfony\Component\ExpressionLanguage\ExpressionFunction;
+use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
+
+class FormConditionFunctionsProvider implements ExpressionFunctionProviderInterface
+{
+
+    /**
+     * @return ExpressionFunction[] An array of Function instances
+     */
+    public function getFunctions()
+    {
+        return [
+            $this->getFormValueFunction()
+        ];
+    }
+
+    /**
+     * Shortcut function to access field values
+     *
+     * @return \Symfony\Component\ExpressionLanguage\ExpressionFunction
+     */
+    protected function getFormValueFunction(): ExpressionFunction
+    {
+        return new ExpressionFunction(
+            'getFormValue',
+            function ($str) {
+                // Not implemented, we only use the evaluator
+            },
+            function ($arguments, $field) {
+                return $arguments['formValues'][$field] ?? null;
+            }
+        );
+    }
+}
index 082f878..32aba76 100644 (file)
@@ -20,6 +20,7 @@ namespace TYPO3\CMS\Form\Domain\Runtime;
 use Psr\Http\Message\ServerRequestInterface;
 use TYPO3\CMS\Core\Context\Context;
 use TYPO3\CMS\Core\ExpressionLanguage\Resolver;
+use TYPO3\CMS\Core\Http\ServerRequest;
 use TYPO3\CMS\Core\Site\Entity\Site;
 use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
 use TYPO3\CMS\Core\Utility\ArrayUtility;
@@ -32,7 +33,6 @@ use TYPO3\CMS\Extbase\Mvc\Web\Request;
 use TYPO3\CMS\Extbase\Mvc\Web\Response;
 use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder;
 use TYPO3\CMS\Extbase\Property\Exception as PropertyException;
-use TYPO3\CMS\Form\Domain\Condition\ConditionProvider;
 use TYPO3\CMS\Form\Domain\Exception\RenderingException;
 use TYPO3\CMS\Form\Domain\Finishers\FinisherContext;
 use TYPO3\CMS\Form\Domain\Finishers\FinisherInterface;
@@ -1061,8 +1061,31 @@ class FormRuntime implements RootRenderableInterface, \ArrayAccess
      */
     protected function getConditionResolver(): Resolver
     {
-        $conditionResolver = GeneralUtility::makeInstance(Resolver::class, GeneralUtility::makeInstance(ConditionProvider::class, $this));
-        return $conditionResolver;
+        $formValues = array_replace_recursive(
+            $this->getFormState()->getFormValues(),
+            $this->getRequest()->getArguments()
+        );
+        $page = $this->getCurrentPage() ?? $this->getFormDefinition()->getPageByIndex(0);
+
+        $finisherIdentifier = '';
+        if ($this->getCurrentFinisher() !== null) {
+            $finisherIdentifier = (new \ReflectionClass($this->getCurrentFinisher()))->getShortName();
+            $finisherIdentifier = preg_replace('/Finisher$/', '', $finisherIdentifier);
+        }
+
+        return GeneralUtility::makeInstance(
+            Resolver::class,
+            'form',
+            [
+                // some shortcuts
+                'formRuntime' => $this,
+                'formValues' => $formValues,
+                'stepIdentifier' => $page->getIdentifier(),
+                'stepType' => $page->getType(),
+                'finisherIdentifier' => $finisherIdentifier,
+            ],
+            $GLOBALS['TYPO3_REQUEST'] ?? GeneralUtility::makeInstance(ServerRequest::class)
+        );
     }
 
     /**
diff --git a/typo3/sysext/form/Configuration/ExpressionLanguage.php b/typo3/sysext/form/Configuration/ExpressionLanguage.php
new file mode 100644 (file)
index 0000000..6072a6e
--- /dev/null
@@ -0,0 +1,8 @@
+<?php
+
+return [
+    'form' => [
+        \TYPO3\CMS\Core\ExpressionLanguage\TypoScriptConditionProvider::class,
+        \TYPO3\CMS\Form\Domain\Condition\ConditionProvider::class
+    ],
+];
index 4aeafc7..75c5f93 100644 (file)
@@ -13,6 +13,7 @@
                "sort-packages": true
        },
        "require": {
+               "psr/http-message": "~1.0",
                "typo3/cms-core": "9.5.*@dev"
        },
        "conflict": {
index 78885d7..d7aabbd 100644 (file)
@@ -19,8 +19,7 @@ use Psr\Http\Message\ServerRequestInterface;
 use TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher;
 use TYPO3\CMS\Core\Context\Context;
 use TYPO3\CMS\Core\Context\UserAspect;
-use TYPO3\CMS\Core\ExpressionLanguage\TypoScriptConditionProvider;
-use TYPO3\CMS\Core\ExpressionLanguage\TypoScriptFrontendConditionFunctionsProvider;
+use TYPO3\CMS\Core\ExpressionLanguage\Resolver;
 use TYPO3\CMS\Core\Site\Entity\Site;
 use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -57,14 +56,15 @@ class ConditionMatcher extends AbstractConditionMatcher
         $frontend->user->userId = $frontendUserAspect->get('id') ?? 0;
         $frontend->user->userGroupList = implode(',', $frontendUserAspect->get('groupIds'));
 
-        $typoScriptConditionProvider = GeneralUtility::makeInstance(TypoScriptConditionProvider::class, [
-            'tree' => $tree,
-            'frontend' => $frontend,
-            'page' => $this->getPage(),
-        ], [
-            GeneralUtility::makeInstance(TypoScriptFrontendConditionFunctionsProvider::class)
-        ]);
-        parent::__construct($typoScriptConditionProvider);
+        $this->expressionLanguageResolver = GeneralUtility::makeInstance(
+            Resolver::class,
+            'typoscript',
+            [
+                'tree' => $tree,
+                'frontend' => $frontend,
+                'page' => $this->getPage(),
+            ]
+        );
     }
 
     /**
index 3fd3fc5..0429128 100644 (file)
@@ -16,11 +16,16 @@ namespace TYPO3\CMS\Frontend\Tests\Unit\Configuration\TypoScript\ConditionMatchi
  */
 
 use Prophecy\Argument;
+use TYPO3\CMS\Core\Cache\CacheManager;
+use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
 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\Package\PackageInterface;
+use TYPO3\CMS\Core\Package\PackageManager;
 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\TestingFramework\Core\Unit\UnitTestCase;
@@ -48,6 +53,20 @@ class ConditionMatcherTest extends UnitTestCase
     protected function setUp(): void
     {
         $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
+        $cacheFrontendProphecy = $this->prophesize(FrontendInterface::class);
+        $cacheFrontendProphecy->has(Argument::any())->willReturn(false);
+        $cacheFrontendProphecy->set(Argument::any(), Argument::any())->willReturn(null);
+        $cacheManagerProphecy = $this->prophesize(CacheManager::class);
+        $cacheManagerProphecy->getCache('cache_core')->willReturn($cacheFrontendProphecy->reveal());
+        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
+
+        $packageManagerProphecy = $this->prophesize(PackageManager::class);
+        $corePackageProphecy = $this->prophesize(PackageInterface::class);
+        $corePackageProphecy->getPackagePath()->willReturn(__DIR__ . '/../../../../../../../sysext/core/');
+        $packageManagerProphecy->getActivePackages()->willReturn([
+            $corePackageProphecy->reveal()
+        ]);
+        GeneralUtility::setSingletonInstance(PackageManager::class, $packageManagerProphecy->reveal());
 
         $this->testGlobalNamespace = $this->getUniqueId('TEST');
         $GLOBALS[$this->testGlobalNamespace] = [];
@@ -396,7 +415,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"]'));
@@ -424,7 +442,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"]'));
@@ -439,7 +456,6 @@ class ConditionMatcherTest extends UnitTestCase
     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"]'));
@@ -468,7 +484,6 @@ 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"]'));
index 06a8494..7c74ec3 100644 (file)
@@ -16,11 +16,15 @@ namespace TYPO3\CMS\Frontend\Tests\UnitDeprecated\Configuration\TypoScript\Condi
  */
 
 use Prophecy\Argument;
+use TYPO3\CMS\Core\Cache\CacheManager;
+use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
 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\Package\PackageInterface;
+use TYPO3\CMS\Core\Package\PackageManager;
 use TYPO3\CMS\Core\Site\Entity\Site;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication;
@@ -51,6 +55,20 @@ class ConditionMatcherTest extends UnitTestCase
     protected function setUp(): void
     {
         $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
+        $cacheFrontendProphecy = $this->prophesize(FrontendInterface::class);
+        $cacheFrontendProphecy->has(Argument::any())->willReturn(false);
+        $cacheFrontendProphecy->set(Argument::any(), Argument::any())->willReturn(null);
+        $cacheManagerProphecy = $this->prophesize(CacheManager::class);
+        $cacheManagerProphecy->getCache('cache_core')->willReturn($cacheFrontendProphecy->reveal());
+        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
+
+        $packageManagerProphecy = $this->prophesize(PackageManager::class);
+        $corePackageProphecy = $this->prophesize(PackageInterface::class);
+        $corePackageProphecy->getPackagePath()->willReturn(__DIR__ . '/../../../../../../../sysext/core/');
+        $packageManagerProphecy->getActivePackages()->willReturn([
+            $corePackageProphecy->reveal()
+        ]);
+        GeneralUtility::setSingletonInstance(PackageManager::class, $packageManagerProphecy->reveal());
 
         $this->testGlobalNamespace = $this->getUniqueId('TEST');
         $GLOBALS[$this->testGlobalNamespace] = [];
@@ -128,10 +146,6 @@ class ConditionMatcherTest extends UnitTestCase
         $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*")]'));
     }
 
     /**
@@ -145,10 +159,6 @@ class ConditionMatcherTest extends UnitTestCase
         $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*")]'));
     }
 
     /**
@@ -161,9 +171,6 @@ class ConditionMatcherTest extends UnitTestCase
         $_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"]'));
     }
 
     /**
@@ -179,10 +186,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\')]'));
     }
 
     /**
@@ -198,10 +201,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\')]'));
     }
 
     /**
@@ -217,9 +216,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\')]'));
     }
 
     /**
@@ -232,9 +228,6 @@ class ConditionMatcherTest extends UnitTestCase
         $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(\'*\')]'));
     }
 
     /**
@@ -247,10 +240,6 @@ class ConditionMatcherTest extends UnitTestCase
         $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\')]'));
     }
 
     /**
@@ -263,9 +252,6 @@ class ConditionMatcherTest extends UnitTestCase
         $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\')]'));
     }
 
     /**
@@ -284,12 +270,6 @@ class ConditionMatcherTest extends UnitTestCase
         $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\')]'));
     }
 
     /**
@@ -306,9 +286,6 @@ 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]'));
     }
 
     /**
@@ -322,8 +299,6 @@ class ConditionMatcherTest extends UnitTestCase
         $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
     }
 
     /**
@@ -341,8 +316,6 @@ class ConditionMatcherTest extends UnitTestCase
         $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
     }
 
     /**
@@ -354,8 +327,6 @@ class ConditionMatcherTest extends UnitTestCase
     {
         $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
     }
 
     /**
@@ -366,8 +337,6 @@ class ConditionMatcherTest extends UnitTestCase
     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
     }
 
     /**
@@ -379,8 +348,6 @@ class ConditionMatcherTest extends UnitTestCase
     {
         $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
     }
 
     /**
@@ -392,8 +359,6 @@ class ConditionMatcherTest extends UnitTestCase
     {
         $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
     }
 
     /**
@@ -407,8 +372,6 @@ class ConditionMatcherTest extends UnitTestCase
         $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
     }
 
     /**
@@ -420,8 +383,6 @@ class ConditionMatcherTest extends UnitTestCase
     {
         $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
     }
 
     /**
@@ -435,8 +396,6 @@ class ConditionMatcherTest extends UnitTestCase
         $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
     }
 
     /**
@@ -488,8 +447,6 @@ class ConditionMatcherTest extends UnitTestCase
     {
         $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
     }
 
     /**
@@ -515,8 +472,6 @@ class ConditionMatcherTest extends UnitTestCase
     {
         $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
     }
 
     /**
@@ -529,8 +484,6 @@ class ConditionMatcherTest extends UnitTestCase
         $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
     }
 
     /**
@@ -543,8 +496,6 @@ class ConditionMatcherTest extends UnitTestCase
         $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
     }
 
     /**
@@ -557,8 +508,6 @@ class ConditionMatcherTest extends UnitTestCase
         $testKey = $this->getUniqueId('test');
         $GLOBALS['_SERVER'][$testKey] = '';
         $this->assertTrue($this->subject->match('[globalString = _SERVER|' . $testKey . ' = /^$/]'));
-        // Test expression language
-        // Access request by request() method
     }
 
     /**
@@ -569,8 +518,6 @@ class ConditionMatcherTest extends UnitTestCase
     public function treeLevelConditionMatchesSingleValue(): void
     {
         $this->assertTrue($this->subject->match('[treeLevel = 2]'));
-        // Test expression language
-        $this->assertTrue($this->subject->match('[tree.level == 2]'));
     }
 
     /**
@@ -581,8 +528,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]]'));
     }
 
     /**
@@ -593,8 +538,6 @@ 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]'));
     }
 
     /**
@@ -632,10 +575,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]'));
     }
 
     /**
@@ -648,8 +587,6 @@ class ConditionMatcherTest extends UnitTestCase
         $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]'));
     }
 
     /**
@@ -662,8 +599,6 @@ class ConditionMatcherTest extends UnitTestCase
         $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]'));
     }
 
     /**
@@ -676,8 +611,6 @@ class ConditionMatcherTest extends UnitTestCase
         $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]'));
     }
 
     /**
@@ -690,8 +623,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]'));
     }
 
     /**
@@ -704,8 +635,6 @@ class ConditionMatcherTest extends UnitTestCase
         $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]'));
     }
 
     /**
@@ -718,8 +647,6 @@ class ConditionMatcherTest extends UnitTestCase
         $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]'));
     }
 
     /**
@@ -731,8 +658,6 @@ class ConditionMatcherTest extends UnitTestCase
     {
         $GLOBALS['TSFE']->id = 121;
         $this->assertFalse($this->subject->match('[PIDinRootline = 999]'));
-        // Test expression language
-        $this->assertFalse($this->subject->match('[999 in tree.rootLineIds]'));
     }
 
     /**
@@ -744,10 +669,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\')]'));
     }
 
     /**
@@ -759,8 +680,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 . ')]'));
     }
 
     /**
@@ -772,10 +691,6 @@ 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\')]'));
     }
 
     /**
@@ -806,9 +721,6 @@ class ConditionMatcherTest extends UnitTestCase
         $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"]'));
     }
 
     /**
@@ -824,8 +736,6 @@ class ConditionMatcherTest extends UnitTestCase
 
         $this->getFreshConditionMatcher();
         $this->assertTrue($this->subject->match('[globalString = session:foo|bar = 1234567]'));
-        // Test expression language
-        $this->assertTrue($this->subject->match('[session("foo|bar") == 1234567]'));
     }
 
     /**
@@ -839,8 +749,6 @@ class ConditionMatcherTest extends UnitTestCase
         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"]'));
     }
 
     /**
@@ -855,9 +763,6 @@ class ConditionMatcherTest extends UnitTestCase
         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]'));
     }
 
     /**
@@ -902,9 +807,6 @@ class ConditionMatcherTest extends UnitTestCase
         $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"]]'));
     }
 
     /**
@@ -933,9 +835,6 @@ class ConditionMatcherTest extends UnitTestCase
         $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"]'));
     }
 
     /**
@@ -952,10 +851,6 @@ class ConditionMatcherTest extends UnitTestCase
         $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/"]'));
     }
 
     /**
@@ -984,9 +879,6 @@ class ConditionMatcherTest extends UnitTestCase
         $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]'));
     }
 
     /**