[BUGFIX] Use current domain if found in domain record 37/37037/9
authorHelmut Hummel <helmut.hummel@typo3.org>
Fri, 20 Feb 2015 15:46:55 +0000 (16:46 +0100)
committerNicole Cordes <typo3@cordes.co>
Sat, 21 Feb 2015 13:34:50 +0000 (14:34 +0100)
The introduction of domain record cache with #24389 introduced a regression.
Previously if multiple domain names were found for one subtree,
the domain name which matched the current host name was preferred.
After the introduction of the cache, only the first domain record was
considered.

This patch properly checks the domain records against the current domain
in use and selects the most appropriate one.

Releases: master, 6.2
Resolves: #62556
Change-Id: I9cae580af9c9de0c1f6ed02d5ac8ad6a90a0fa2b
Reviewed-on: http://review.typo3.org/37037
Reviewed-by: Markus Klein <klein.t3@reelworx.at>
Tested-by: Markus Klein <klein.t3@reelworx.at>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Helmut Hummel <helmut.hummel@typo3.org>
Tested-by: Helmut Hummel <helmut.hummel@typo3.org>
typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php
typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php
typo3/sysext/frontend/Tests/Unit/Controller/TypoScriptFrontendControllerTest.php

index be490f8..259645a 100644 (file)
@@ -6296,7 +6296,7 @@ class ContentObjectRenderer {
 
                                                        $targetDomain = $GLOBALS['TSFE']->getDomainNameForPid($page['uid']);
                                                        // Do not prepend the domain if it is the current hostname
-                                                       if (!$targetDomain || $targetDomain === $currentDomain) {
+                                                       if (!$targetDomain || $GLOBALS['TSFE']->domainNameMatchesCurrentRequest($targetDomain)) {
                                                                $targetDomain = '';
                                                        }
                                                }
index fe5aea8..c28c923 100644 (file)
@@ -4531,24 +4531,24 @@ class TypoScriptFrontendController {
                if ($runtimeCache->has($entryIdentifier)) {
                        $sysDomainData = $runtimeCache->get($entryIdentifier);
                } else {
-                       $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
+                       $domainRecords = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
                                'uid, pid, domainName, forced',
                                'sys_domain',
-                               'redirectTo=\'\' ' . $GLOBALS['TSFE']->sys_page->enableFields('sys_domain', 0),
+                               'redirectTo=\'\' ' . $this->sys_page->enableFields('sys_domain', 0),
                                '',
                                'sorting ASC'
                        );
 
-                       while (FALSE !== ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result))) {
+                       foreach ($domainRecords as $row) {
                                // if there is already an entry for this pid, check if we should overwrite it
                                if (isset($sysDomainData[$row['pid']])) {
-                                       // there is already a "forced" entry, which must not be overwritten
+                                       // There is already a "forced" entry, which must not be overwritten
                                        if ($sysDomainData[$row['pid']]['forced']) {
                                                continue;
                                        }
 
-                                       // there is alread a NOT-forced entry and the current one is also NOT-forced, thus keep the old
-                                       if (!$sysDomainData[$row['pid']]['forced'] && !$row['forced']) {
+                                       // The current domain record is also NOT-forced, keep the old unless the new one matches the current request
+                                       if (!$row['forced'] && !$this->domainNameMatchesCurrentRequest($row['domainName'])) {
                                                continue;
                                        }
                                }
@@ -4562,12 +4562,24 @@ class TypoScriptFrontendController {
                                );
                        }
                        $runtimeCache->set($entryIdentifier, $sysDomainData);
-                       $GLOBALS['TYPO3_DB']->sql_free_result($result);
                }
                return $sysDomainData;
        }
 
        /**
+        * Whether the given domain name (potentially including a path segment) matches currently requested host or
+        * the host including the path segment
+        *
+        * @param string $domainName
+        * @return bool
+        */
+       public function domainNameMatchesCurrentRequest($domainName) {
+               $currentDomain = GeneralUtility::getIndpEnv('HTTP_HOST');
+               $currentPathSegment = trim(preg_replace('|/[^/]*$|', '', GeneralUtility::getIndpEnv('SCRIPT_NAME')));
+               return $currentDomain === $domainName || $currentDomain . $currentPathSegment === $domainName;
+       }
+
+       /**
         * Obtains domain data for the target pid. Domain data is an array with
         * 'pid', 'domainName' and 'forced' members (see sys_domain table for
         * meaning of these fields.
index ffae23d..8058e0b 100644 (file)
@@ -30,11 +30,15 @@ class TypoScriptFrontendControllerTest extends \TYPO3\CMS\Core\Tests\UnitTestCas
                $this->subject = $this->getAccessibleMock(\TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::class, array('dummy'), array(), '', FALSE);
                $this->subject->TYPO3_CONF_VARS = $GLOBALS['TYPO3_CONF_VARS'];
                $this->subject->TYPO3_CONF_VARS['SYS']['encryptionKey'] = '170928423746123078941623042360abceb12341234231';
+
+               $pageRepository = $this->getMock(\TYPO3\CMS\Frontend\Page\PageRepository::class);
+               $this->subject->sys_page = $pageRepository;
        }
 
-       ////////////////////////////////
-       // Tests concerning rendering content
-       ////////////////////////////////
+       /**
+        * Tests concerning rendering content
+        */
+
        /**
         * @test
         */
@@ -76,9 +80,10 @@ class TypoScriptFrontendControllerTest extends \TYPO3\CMS\Core\Tests\UnitTestCas
                return $tsfe;
        }
 
-       //////////////////////
-       // Tests concerning sL
-       //////////////////////
+       /**
+        * Tests concerning sL
+        */
+
        /**
         * @test
         */
@@ -87,4 +92,153 @@ class TypoScriptFrontendControllerTest extends \TYPO3\CMS\Core\Tests\UnitTestCas
                $this->assertEquals($string, $this->subject->sL($string));
        }
 
+       /**
+        * Tests concerning getSysDomainCache
+        */
+
+       /**
+        * @return array
+        */
+       public function getSysDomainCacheDataProvider() {
+               return array(
+                       'typo3.org' => array(
+                               'typo3.org',
+                       ),
+                       'foo.bar' => array(
+                               'foo.bar',
+                       ),
+                       'example.com' => array(
+                               'example.com',
+                       ),
+               );
+       }
+
+       /**
+        * @param string $currentDomain
+        * @test
+        * @dataProvider getSysDomainCacheDataProvider
+        */
+       public function getSysDomainCacheReturnsCurrentDomainRecord($currentDomain) {
+               $_SERVER['HTTP_HOST'] = $currentDomain;
+               $domainRecords = array(
+                       'typo3.org' => array(
+                               'uid' => '1',
+                               'pid' => '1',
+                               'domainName' => 'typo3.org',
+                               'forced' => 0,
+                       ),
+                       'foo.bar' => array(
+                               'uid' => '2',
+                               'pid' => '1',
+                               'domainName' => 'foo.bar',
+                               'forced' => 0,
+                       ),
+                       'example.com' => array(
+                               'uid' => '3',
+                               'pid' => '1',
+                               'domainName' => 'example.com',
+                               'forced' => 0,
+                       ),
+               );
+               $GLOBALS['TYPO3_DB'] = $this->getMock(\TYPO3\CMS\Core\Database\DatabaseConnection::class, array('exec_SELECTgetRows'));
+               $GLOBALS['TYPO3_DB']->expects($this->any())->method('exec_SELECTgetRows')->willReturn($domainRecords);
+               \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('cache_runtime')->flush();
+               $expectedResult = array(
+                       $domainRecords[$currentDomain]['pid'] => $domainRecords[$currentDomain],
+               );
+               $this->assertEquals($expectedResult, $this->subject->_call('getSysDomainCache'));
+       }
+
+       /**
+        * @param string $currentDomain
+        * @test
+        * @dataProvider getSysDomainCacheDataProvider
+        */
+       public function getSysDomainCacheReturnsForcedDomainRecord($currentDomain) {
+               $_SERVER['HTTP_HOST'] = $currentDomain;
+               $domainRecords = array(
+                       'typo3.org' => array(
+                               'uid' => '1',
+                               'pid' => '1',
+                               'domainName' => 'typo3.org',
+                               'forced' => 0,
+                       ),
+                       'foo.bar' => array(
+                               'uid' => '2',
+                               'pid' => '1',
+                               'domainName' => 'foo.bar',
+                               'forced' => 1,
+                       ),
+                       'example.com' => array(
+                               'uid' => '3',
+                               'pid' => '1',
+                               'domainName' => 'example.com',
+                               'forced' => 0,
+                       ),
+               );
+               $GLOBALS['TYPO3_DB'] = $this->getMock(\TYPO3\CMS\Core\Database\DatabaseConnection::class, array('exec_SELECTgetRows'));
+               $GLOBALS['TYPO3_DB']->expects($this->any())->method('exec_SELECTgetRows')->willReturn($domainRecords);
+               \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('cache_runtime')->flush();
+               $expectedResult = array(
+                       $domainRecords[$currentDomain]['pid'] => $domainRecords['foo.bar'],
+               );
+               $this->assertEquals($expectedResult, $this->subject->_call('getSysDomainCache'));
+       }
+
+       /**
+        * Tests concerning domainNameMatchesCurrentRequest
+        */
+
+       /**
+        * @return array
+        */
+       public function domainNameMatchesCurrentRequestDataProvider() {
+               return array(
+                       'same domains' => array(
+                               'typo3.org',
+                               'typo3.org',
+                               '/index.php',
+                               TRUE,
+                       ),
+                       'same domains with subdomain' => array(
+                               'www.typo3.org',
+                               'www.typo3.org',
+                               '/index.php',
+                               TRUE,
+                       ),
+                       'different domains' => array(
+                               'foo.bar',
+                               'typo3.org',
+                               '/index.php',
+                               FALSE,
+                       ),
+                       'domain record with script name' => array(
+                               'typo3.org',
+                               'typo3.org/foo/bar',
+                               '/foo/bar/index.php',
+                               TRUE,
+                       ),
+                       'domain record with wrong script name' => array(
+                               'typo3.org',
+                               'typo3.org/foo/bar',
+                               '/bar/foo/index.php',
+                               FALSE,
+                       ),
+               );
+       }
+
+       /**
+        * @param string $currentDomain
+        * @param string $domainRecord
+        * @param string $scriptName
+        * @param bool $expectedResult
+        * @test
+        * @dataProvider domainNameMatchesCurrentRequestDataProvider
+        */
+       public function domainNameMatchesCurrentRequest($currentDomain, $domainRecord, $scriptName, $expectedResult) {
+               $_SERVER['HTTP_HOST'] = $currentDomain;
+               $_SERVER['SCRIPT_NAME'] = $scriptName;
+               $this->assertEquals($expectedResult, $this->subject->domainNameMatchesCurrentRequest($domainRecord));
+       }
+
 }