[FEATURE] Add TypoScript conditions based on the site configuration 11/56711/3
authorGeorg Ringer <georg.ringer@gmail.com>
Tue, 17 Apr 2018 14:19:36 +0000 (16:19 +0200)
committerAndreas Wolf <andreas.wolf@typo3.org>
Fri, 4 May 2018 13:11:39 +0000 (15:11 +0200)
Two new TypoScript conditions are added to check for the currently
used site configuration of a Frontend Request.

[site = identifier = angelo]
[site = base = https://www.benni.com/]
[siteLanguage = typo3Language = default]
[siteLanguage = locale = de_CH.UTF-8]

Resolves: #84760
Releases: master
Change-Id: I6914211871de1cfc15c5ac0e4ed5ed2d245b39e8
Reviewed-on: https://review.typo3.org/56711
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: Wouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Andreas Wolf <andreas.wolf@typo3.org>
Tested-by: Andreas Wolf <andreas.wolf@typo3.org>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
typo3/sysext/core/Documentation/Changelog/master/Feature-84760-TypoScriptConditionsForSiteAndSiteLanguage.rst [new file with mode: 0644]
typo3/sysext/frontend/Classes/Configuration/TypoScript/ConditionMatching/ConditionMatcher.php
typo3/sysext/frontend/Tests/Unit/Configuration/TypoScript/ConditionMatching/ConditionMatcherTest.php

diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-84760-TypoScriptConditionsForSiteAndSiteLanguage.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-84760-TypoScriptConditionsForSiteAndSiteLanguage.rst
new file mode 100644 (file)
index 0000000..cbe3811
--- /dev/null
@@ -0,0 +1,34 @@
+.. include:: ../../Includes.txt
+
+=================================================================
+Feature: #84760 - TypoScript conditions for site and siteLanguage
+=================================================================
+
+See :issue:`84760`
+
+Description
+===========
+
+Two new TypoScript conditions have been added which makes it possible to interact on the new site configuration.
+
+**Condition for the properties of a site object**
+
+.. code-block:: typoscript
+
+The identifier of the site name is evaluated:
+
+       [site = identifier = someIdentifier, base = https://www.typo3.org/]
+               page.30.value = fo
+       [global]
+
+**Condition for the site language**
+
+Any property of the current site language is evaluated:
+
+.. code-block:: typoscript
+
+       [siteLanguage = locale = de_CH.UTF-8, title = Switzerland]
+               page.40.value = bar
+       [global]
+
+.. index:: TypoScript
\ No newline at end of file
index 8bcc5b3..c3db655 100644 (file)
@@ -1,4 +1,5 @@
 <?php
+
 namespace TYPO3\CMS\Frontend\Configuration\TypoScript\ConditionMatching;
 
 /*
@@ -14,7 +15,9 @@ namespace TYPO3\CMS\Frontend\Configuration\TypoScript\ConditionMatching;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Psr\Http\Message\ServerRequestInterface;
 use TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher;
+use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -43,46 +46,87 @@ class ConditionMatcher extends AbstractConditionMatcher
             return $result;
         }
         switch ($key) {
-                case 'usergroup':
-                    $groupList = $this->getGroupList();
-                    // '0,-1' is the default usergroups when not logged in!
-                    if ($groupList !== '0,-1') {
-                        $values = GeneralUtility::trimExplode(',', $value, true);
-                        foreach ($values as $test) {
-                            if ($test === '*' || GeneralUtility::inList($groupList, $test)) {
+            case 'usergroup':
+                $groupList = $this->getGroupList();
+                // '0,-1' is the default usergroups when not logged in!
+                if ($groupList !== '0,-1') {
+                    $values = GeneralUtility::trimExplode(',', $value, true);
+                    foreach ($values as $test) {
+                        if ($test === '*' || GeneralUtility::inList($groupList, $test)) {
+                            return true;
+                        }
+                    }
+                }
+                break;
+            case 'treeLevel':
+                $values = GeneralUtility::trimExplode(',', $value, true);
+                $treeLevel = count($this->rootline) - 1;
+                foreach ($values as $test) {
+                    if ($test == $treeLevel) {
+                        return true;
+                    }
+                }
+                break;
+            case 'PIDupinRootline':
+            case 'PIDinRootline':
+                $values = GeneralUtility::trimExplode(',', $value, true);
+                if ($key === 'PIDinRootline' || !in_array($this->pageId, $values)) {
+                    foreach ($values as $test) {
+                        foreach ($this->rootline as $rlDat) {
+                            if ($rlDat['uid'] == $test) {
                                 return true;
                             }
                         }
                     }
-                    break;
-                case 'treeLevel':
+                }
+                break;
+            case 'site':
+                $siteLanguage = $this->getCurrentSiteLanguage();
+                if ($siteLanguage instanceof SiteLanguage) {
+                    $site = $siteLanguage->getSite();
                     $values = GeneralUtility::trimExplode(',', $value, true);
-                    $treeLevel = count($this->rootline) - 1;
                     foreach ($values as $test) {
-                        if ($test == $treeLevel) {
-                            return true;
+                        $point = strcspn($test, '=');
+                        $testValue = substr($test, $point + 1);
+                        $testValue = trim($testValue);
+                        $theVarName = trim(substr($test, 0, $point));
+                        $methodName = 'get' . ucfirst($theVarName);
+                        if (method_exists($site, $methodName)) {
+                            $sitePropertyValue = call_user_func([$site, $methodName]);
+                            // loose check on purpose in order to check for integer values
+                            if ($testValue == $sitePropertyValue) {
+                                return true;
+                            }
                         }
                     }
-                    break;
-                case 'PIDupinRootline':
-                case 'PIDinRootline':
+                }
+                break;
+            case 'siteLanguage':
+                $siteLanguage = $this->getCurrentSiteLanguage();
+                if ($siteLanguage instanceof SiteLanguage) {
                     $values = GeneralUtility::trimExplode(',', $value, true);
-                    if ($key === 'PIDinRootline' || !in_array($this->pageId, $values)) {
-                        foreach ($values as $test) {
-                            foreach ($this->rootline as $rlDat) {
-                                if ($rlDat['uid'] == $test) {
-                                    return true;
-                                }
+                    foreach ($values as $test) {
+                        $point = strcspn($test, '=');
+                        $testValue = substr($test, $point + 1);
+                        $testValue = trim($testValue);
+                        $theVarName = trim(substr($test, 0, $point));
+                        $methodName = 'get' . ucfirst($theVarName);
+                        if (method_exists($siteLanguage, $methodName)) {
+                            $languagePropertyValue = call_user_func([$siteLanguage, $methodName]);
+                            // loose check on purpose in order to check for integer values
+                            if ($testValue == $languagePropertyValue) {
+                                return true;
                             }
                         }
                     }
-                    break;
-                default:
-                    $conditionResult = $this->evaluateCustomDefinedCondition($string);
-                    if ($conditionResult !== null) {
-                        return $conditionResult;
-                    }
-            }
+                }
+                break;
+            default:
+                $conditionResult = $this->evaluateCustomDefinedCondition($string);
+                if ($conditionResult !== null) {
+                    return $conditionResult;
+                }
+        }
 
         return false;
     }
@@ -222,4 +266,18 @@ class ConditionMatcher extends AbstractConditionMatcher
     {
         return $GLOBALS['TSFE'];
     }
+
+    /**
+     * Returns the currently configured "site language" if a site is configured (= resolved) in the current request.
+     *
+     * @internal
+     */
+    protected function getCurrentSiteLanguage(): ?SiteLanguage
+    {
+        if ($GLOBALS['TYPO3_REQUEST'] instanceof ServerRequestInterface
+            && $GLOBALS['TYPO3_REQUEST']->getAttribute('language') instanceof SiteLanguage) {
+            return $GLOBALS['TYPO3_REQUEST']->getAttribute('language');
+        }
+        return null;
+    }
 }
index a378654..6c87e06 100644 (file)
@@ -17,6 +17,8 @@ namespace TYPO3\CMS\Frontend\Tests\Unit\Configuration\TypoScript\ConditionMatchi
 
 use Prophecy\Argument;
 use TYPO3\CMS\Core\Configuration\TypoScript\Exception\InvalidTypoScriptConditionException;
+use TYPO3\CMS\Core\Http\ServerRequest;
+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;
@@ -664,6 +666,102 @@ class ConditionMatcherTest extends UnitTestCase
     }
 
     /**
+     * Tests whether any property of a site language matches the request
+     *
+     * @test
+     */
+    public function siteLanguageMatchesCondition(): void
+    {
+        $site = new Site('angelo', 13, [
+            'languages' => [
+                [
+                    'languageId' => 0,
+                    'title' => 'United States',
+                    'locale' => 'en_US.UTF-8',
+                ],
+                [
+                    'languageId' => 2,
+                    'title' => 'UK',
+                    'locale' => 'en_UK.UTF-8',
+                ]
+            ]
+        ]);
+        $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
+        $GLOBALS['TYPO3_REQUEST'] = $GLOBALS['TYPO3_REQUEST']->withAttribute('language', $site->getLanguageById(0));
+        $this->assertTrue($this->matchCondition->match('[siteLanguage = locale = en_US.UTF-8]'));
+        $this->assertTrue($this->matchCondition->match('[siteLanguage = locale = de_DE, locale = en_US.UTF-8]'));
+    }
+
+    /**
+     * Tests whether any property of a site language does NOT match the request
+     *
+     * @test
+     */
+    public function siteLanguageDoesNotMatchCondition(): void
+    {
+        $site = new Site('angelo', 13, [
+            'languages' => [
+                [
+                    'languageId' => 0,
+                    'title' => 'United States',
+                    'locale' => 'en_US.UTF-8',
+                ],
+                [
+                    'languageId' => 2,
+                    'title' => 'UK',
+                    'locale' => 'en_UK.UTF-8',
+                ]
+            ]
+        ]);
+        $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
+        $GLOBALS['TYPO3_REQUEST'] = $GLOBALS['TYPO3_REQUEST']->withAttribute('language', $site->getLanguageById(0));
+        $this->assertFalse($this->matchCondition->match('[siteLanguage = locale = en_UK.UTF-8]'));
+        $this->assertFalse($this->matchCondition->match('[siteLanguage = locale = de_DE, title = UK]'));
+    }
+
+    /**
+     * Tests whether any property of a site matches the request
+     *
+     * @test
+     */
+    public function siteMatchesCondition(): void
+    {
+        $site = new Site('angelo', 13, ['languages' => [], 'base' => 'https://typo3.org/']);
+        $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
+        $GLOBALS['TYPO3_REQUEST'] = $GLOBALS['TYPO3_REQUEST']->withAttribute('language', $site->getLanguageById(0));
+        $this->assertTrue($this->matchCondition->match('[site = identifier = angelo]'));
+        $this->assertTrue($this->matchCondition->match('[site = rootPageId = 13]'));
+        $this->assertTrue($this->matchCondition->match('[site = base = https://typo3.org/]'));
+    }
+
+    /**
+     * Tests whether any property of a site that does NOT match the request
+     *
+     * @test
+     */
+    public function siteDoesNotMatchCondition(): void
+    {
+        $site = new Site('angelo', 13, [
+            'languages' => [
+                [
+                    'languageId' => 0,
+                    'title' => 'United States',
+                    'locale' => 'en_US.UTF-8',
+                ],
+                [
+                    'languageId' => 2,
+                    'title' => 'UK',
+                    'locale' => 'en_UK.UTF-8',
+                ]
+            ]
+        ]);
+        $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
+        $GLOBALS['TYPO3_REQUEST'] = $GLOBALS['TYPO3_REQUEST']->withAttribute('language', $site->getLanguageById(0));
+        $this->assertFalse($this->matchCondition->match('[site = identifier = berta]'));
+        $this->assertFalse($this->matchCondition->match('[site = rootPageId = 14, rootPageId=23]'));
+    }
+
+    /**
      * @test
      */
     public function matchThrowsExceptionIfConditionClassDoesNotInheritFromAbstractCondition(): void