[BUGFIX] Use current domain if found in domain record 69/37069/4
authorHelmut Hummel <helmut.hummel@typo3.org>
Fri, 20 Feb 2015 15:46:55 +0000 (16:46 +0100)
committerHelmut Hummel <helmut.hummel@typo3.org>
Sat, 21 Feb 2015 14:12:21 +0000 (15:12 +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/37069
Reviewed-by: Markus Klein <klein.t3@reelworx.at>
Tested-by: Markus Klein <klein.t3@reelworx.at>
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 1cb16e9..e491dc7 100644 (file)
@@ -6051,7 +6051,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 10e0d20..25b36b9 100644 (file)
@@ -5000,24 +5000,24 @@ if (version == "n3") {
                if ($runtimeCache->has($entryIdentifier)) {
                        $sysDomainData = $runtimeCache->get($entryIdentifier);
                } else {
-                       $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
+                       $domainRecords = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
                                '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;
                                        }
                                }
@@ -5030,12 +5030,24 @@ if (version == "n3") {
                                );
                        }
                        $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 babb05e..49de81f 100644 (file)
@@ -13,6 +13,8 @@ namespace TYPO3\CMS\Frontend\Tests\Unit\Controller;
  *
  * The TYPO3 project - inspiring people to share!
  */
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
 /**
  * Testcase for TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
  *
@@ -29,6 +31,9 @@ class TypoScriptFrontendControllerTest extends \TYPO3\CMS\Core\Tests\UnitTestCas
                $this->fixture = $this->getAccessibleMock('\\TYPO3\\CMS\\Frontend\\Controller\\TypoScriptFrontendController', array('dummy'), array(), '', FALSE);
                $this->fixture->TYPO3_CONF_VARS = $GLOBALS['TYPO3_CONF_VARS'];
                $this->fixture->TYPO3_CONF_VARS['SYS']['encryptionKey'] = '170928423746123078941623042360abceb12341234231';
+
+               $pageRepository = $this->getMock('TYPO3\\CMS\\Frontend\\Page\\PageRepository');
+               $this->fixture->sys_page = $pageRepository;
        }
 
        ////////////////////////////////
@@ -131,4 +136,148 @@ class TypoScriptFrontendControllerTest extends \TYPO3\CMS\Core\Tests\UnitTestCas
                $refValue = $this->fixture->_callRef('roundTripCryptString', $clearText);
                $this->assertEquals($clearText, $this->fixture->_callRef('roundTripCryptString', $refValue));
        }
+
+       /**
+        * 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(
+                               'pid' => '1',
+                               'domainName' => 'typo3.org',
+                               'forced' => 0,
+                       ),
+                       'foo.bar' => array(
+                               'pid' => '1',
+                               'domainName' => 'foo.bar',
+                               'forced' => 0,
+                       ),
+                       'example.com' => array(
+                               'pid' => '1',
+                               'domainName' => 'example.com',
+                               'forced' => 0,
+                       ),
+               );
+               $GLOBALS['TYPO3_DB'] = $this->getMock('TYPO3\\CMS\\Core\\Database\\DatabaseConnection', array('exec_SELECTgetRows'));
+               $GLOBALS['TYPO3_DB']->expects($this->any())->method('exec_SELECTgetRows')->willReturn($domainRecords);
+               GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Cache\\CacheManager')->getCache('cache_runtime')->flush();
+               $expectedResult = array(
+                       $domainRecords[$currentDomain]['pid'] => $domainRecords[$currentDomain],
+               );
+               $this->assertEquals($expectedResult, $this->fixture->_call('getSysDomainCache'));
+       }
+
+       /**
+        * @param string $currentDomain
+        * @test
+        * @dataProvider getSysDomainCacheDataProvider
+        */
+       public function getSysDomainCacheReturnsForcedDomainRecord($currentDomain) {
+               $_SERVER['HTTP_HOST'] = $currentDomain;
+               $domainRecords = array(
+                       'typo3.org' => array(
+                               'pid' => '1',
+                               'domainName' => 'typo3.org',
+                               'forced' => 0,
+                       ),
+                       'foo.bar' => array(
+                               'pid' => '1',
+                               'domainName' => 'foo.bar',
+                               'forced' => 1,
+                       ),
+                       'example.com' => array(
+                               'pid' => '1',
+                               'domainName' => 'example.com',
+                               'forced' => 0,
+                       ),
+               );
+               $GLOBALS['TYPO3_DB'] = $this->getMock('TYPO3\\CMS\\Core\\Database\\DatabaseConnection', array('exec_SELECTgetRows'));
+               $GLOBALS['TYPO3_DB']->expects($this->any())->method('exec_SELECTgetRows')->willReturn($domainRecords);
+               GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Cache\\CacheManager')->getCache('cache_runtime')->flush();
+               $expectedResult = array(
+                       $domainRecords[$currentDomain]['pid'] => $domainRecords['foo.bar'],
+               );
+               $this->assertEquals($expectedResult, $this->fixture->_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->fixture->domainNameMatchesCurrentRequest($domainRecord));
+       }
+
 }