Skip to content

Commit a84e10c

Browse files
committed
[BUGFIX] Fix site settings hash calculation
The site-constants cache key in method `addDefaultTypoScriptConstantsFromSite` of `SysTemplateTreeBuilder` uses `json_encode()` in order to build a hash of the site settings object. With #104858 site settings were expanded to allow setting-key access via `$settings->get('foo.bar')` for defined settings and missed to adapt the `jsonSerialize()` method to continue to return the settings tree instead of the reduced settings map (which is limited to settings defined in `settings.definitions.yaml`). This leads to broken TS caches with multiple sites: Settings from one site spill over to other sites, depending on which one was called first after cache clear. A regression test replays the scenario to proof correctness of the code change. Releases: main, 13.4 Resolves: #105760 Related: #104858 Change-Id: Ied715c25265abb98681b11c13468679c0b23528a Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/87557 Tested-by: core-ci <typo3@b13.com> Tested-by: Benjamin Franzke <ben@bnf.dev> Reviewed-by: Achim Fritz <af@achimfritz.de> Tested-by: Christian Kuhn <lolli@schwarzbu.ch> Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch> Tested-by: Achim Fritz <af@achimfritz.de> Reviewed-by: Benjamin Franzke <ben@bnf.dev>
1 parent 104b087 commit a84e10c

File tree

3 files changed

+103
-1
lines changed

3 files changed

+103
-1
lines changed

typo3/sysext/core/Classes/Site/Entity/SiteSettings.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@
3030
private array $flatSettings;
3131
private array $settingsTree;
3232

33+
/**
34+
* @param array $settings key-value map of defined settings
35+
* @param array $settingsTree nested settings tree, included defined (settings.definitions.yaml) and anonymous settings (only set in settings.yaml)
36+
* @param array $flatSettings key-value map of all settings (defined and anonymous settings)
37+
*
38+
* @internal to be constructed by create() or createFromSettingsTree()
39+
*/
3340
public function __construct(array $settings, array $settingsTree, array $flatSettings)
3441
{
3542
parent::__construct($settings);
@@ -67,9 +74,12 @@ public function getAllFlat(): array
6774
return $this->flatSettings;
6875
}
6976

77+
/**
78+
* @todo Update jsonSerialize() to return settings map and settings tree values, or remove altogether.
79+
*/
7080
public function jsonSerialize(): mixed
7181
{
72-
return json_encode($this->settings);
82+
return json_encode($this->settingsTree);
7383
}
7484

7585
/**
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"pages"
2+
,"uid","pid","deleted","title","slug","is_siteroot"
3+
,1,0,0,"Brand root","/",1
4+
,2,0,0,"Tech root","/",1
5+
"sys_template"
6+
,"uid","pid","deleted","hidden","sorting","title","config"
7+
,1,1,0,0,256,"Brand root TS","page = PAGE
8+
page {
9+
10 = TEXT
10+
10.value = {$settingFromSite}
11+
}"
12+
,2,2,0,0,256,"Tech root TS","page = PAGE
13+
page {
14+
10 = TEXT
15+
10.value = {$settingFromSite}
16+
}"
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the TYPO3 CMS project.
7+
*
8+
* It is free software; you can redistribute it and/or modify it under
9+
* the terms of the GNU General Public License, either version 2
10+
* of the License, or any later version.
11+
*
12+
* For the full copyright and license information, please read the
13+
* LICENSE.txt file that was distributed with this source code.
14+
*
15+
* The TYPO3 project - inspiring people to share!
16+
*/
17+
18+
namespace TYPO3\CMS\Frontend\Tests\Functional\SiteHandling;
19+
20+
use PHPUnit\Framework\Attributes\Test;
21+
use TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait;
22+
use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
23+
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
24+
25+
/**
26+
* Test scenarios with multiple sites. Verify caches do not spill
27+
* over from one site to another and similar.
28+
*/
29+
final class MultiSiteTest extends FunctionalTestCase
30+
{
31+
use SiteBasedTestTrait;
32+
33+
protected const LANGUAGE_PRESETS = [
34+
'EN' => ['id' => 0, 'title' => 'English', 'locale' => 'en_US.UTF8'],
35+
];
36+
37+
#[Test]
38+
public function twoSysTemplateBasedSitesCalculateCorrectSiteSettingsInTypoScript(): void
39+
{
40+
$this->importCSVDataSet(__DIR__ . '/Fixtures/MultiSiteTestPageAndSysTemplateImport.csv');
41+
$this->writeSiteConfiguration(
42+
'acme-brand',
43+
[
44+
'rootPageId' => 1,
45+
'base' => 'https://acme.com/brand',
46+
'settings' => [
47+
'settingFromSite' => 'BrandFoo',
48+
],
49+
],
50+
[
51+
$this->buildDefaultLanguageConfiguration('EN', '/'),
52+
]
53+
);
54+
$this->writeSiteConfiguration(
55+
'acme-tech',
56+
[
57+
'rootPageId' => 2,
58+
'base' => 'https://acme.com/tech',
59+
'settings' => [
60+
'settingFromSite' => 'TechBar',
61+
],
62+
],
63+
[
64+
$this->buildDefaultLanguageConfiguration('EN', '/'),
65+
]
66+
);
67+
$response = $this->executeFrontendSubRequest((new InternalRequest('https://acme.com/brand')));
68+
// Site settings set this string, it is used in TypoScript of this page as constant.
69+
self::assertStringContainsString('BrandFoo', (string)$response->getBody());
70+
$response = $this->executeFrontendSubRequest((new InternalRequest('https://acme.com/tech')));
71+
// Site settings set this string, it is used in TypoScript of this page as constant.
72+
// The test verifies the correct constant value is calculated when first calling one site
73+
// and then the other one, when both have the same site setting with different values.
74+
self::assertStringContainsString('TechBar', (string)$response->getBody());
75+
}
76+
}

0 commit comments

Comments
 (0)