Skip to content

Commit 6860df9

Browse files
committed
[FEATURE] calculate site hash by site-identifier strategy by setting
Adds new SiteHash calculation strategy, which can be enabled by extension setting `siteHashStrategy`. The old strategy is currently as default, the new will become default on EXT:solr 13.1.x+ The new strategy for site-hash can be enabled by setting `$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['solr']['siteHashStrategy'] = 1` The `document.site` will contain the site-identifier instead of domain, if the site-hash strategy is set to Identifier. Fixes: #3459
1 parent 56493ee commit 6860df9

28 files changed

+562
-70
lines changed

Build/Test/IntegrationTests.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,6 @@
3030
</testsuites>
3131
<php>
3232
<ini name="display_errors" value="1"/>
33-
<env name="TYPO3_CONTEXT" value="Testing"/>
33+
<env name="TYPO3_CONTEXT" value="Testing" force="true"/>
3434
</php>
3535
</phpunit>

Build/Test/UnitTests.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
</testsuites>
3131
<php>
3232
<ini name="display_errors" value="1"/>
33-
<env name="TYPO3_CONTEXT" value="Testing"/>
33+
<env name="TYPO3_CONTEXT" value="Testing" force="true"/>
3434
</php>
3535
<extensions>
3636
<bootstrap class="DG\BypassFinals\PHPUnitExtension"/>

Classes/Domain/Search/ApacheSolrDocument/Builder.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use ApacheSolrForTypo3\Solr\Domain\Site\Site;
2222
use ApacheSolrForTypo3\Solr\Domain\Site\SiteRepository;
2323
use ApacheSolrForTypo3\Solr\Domain\Variants\IdBuilder;
24+
use ApacheSolrForTypo3\Solr\System\Configuration\ExtensionConfiguration;
2425
use ApacheSolrForTypo3\Solr\System\Solr\Document\Document;
2526
use ApacheSolrForTypo3\Solr\Typo3PageContentExtractor;
2627
use ApacheSolrForTypo3\Solr\Util;
@@ -40,6 +41,7 @@ class Builder
4041
{
4142
public function __construct(
4243
protected readonly IdBuilder $variantIdBuilder,
44+
protected ExtensionConfiguration $extensionConfiguration,
4345
) {}
4446

4547
/**
@@ -64,7 +66,10 @@ public function fromPage(
6466
$documentId = $this->getPageDocumentId($pageInformation, $pageArguments, $siteLanguage, $accessGroups, $mountPointParameter);
6567

6668
$document->setField('id', $documentId);
67-
$document->setField('site', $site->getDomain());
69+
$document->setField('site', $site->getSiteIdentifier());
70+
if ($this->extensionConfiguration->getSiteHashStrategy() === 0) {
71+
$document->setField('site', $site->getDomain());
72+
}
6873
$document->setField('siteHash', $site->getSiteHash());
6974
$document->setField('appKey', 'EXT:solr');
7075
$document->setField('type', 'pages');

Classes/Domain/Search/Query/QueryBuilder.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ public function useSiteHashFromAllowedSites(string $allowedSites): QueryBuilder
274274
$allowedSites = GeneralUtility::trimExplode(',', $allowedSites);
275275
$filters = [];
276276
foreach ($allowedSites as $site) {
277-
$siteHash = $this->siteHashService->getSiteHashForDomain($site);
277+
$siteHash = $this->siteHashService->getSiteHashForSiteIdentifier($site);
278278
$filters[] = 'siteHash:"' . $siteHash . '"';
279279
}
280280

Classes/Domain/Site/Site.php

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -284,18 +284,16 @@ public function getPages(
284284
return $this->pagesRepository->findAllSubPageIdsByRootPage($pageId, $initialPagesAdditionalWhereClause);
285285
}
286286

287-
/**
288-
* Generates the site's unique Site Hash.
289-
*
290-
* The Site Hash is build from the site's main domain, the system encryption
291-
* key, and the extension "tx_solr". These components are concatenated and
292-
* sha1-hashed.
293-
*/
294287
public function getSiteHash(): string
295288
{
296289
return $this->siteHash;
297290
}
298291

292+
public function getSiteIdentifier(): string
293+
{
294+
return $this->typo3SiteObject->getIdentifier();
295+
}
296+
299297
/**
300298
* Gets the site's main domain.
301299
*

Classes/Domain/Site/SiteHashService.php

Lines changed: 106 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,31 @@
1717

1818
namespace ApacheSolrForTypo3\Solr\Domain\Site;
1919

20+
use ApacheSolrForTypo3\Solr\Event\Site\AfterSiteHashHasBeenDeterminedForSiteEvent;
21+
use ApacheSolrForTypo3\Solr\System\Configuration\ExtensionConfiguration;
2022
use ApacheSolrForTypo3\Solr\System\Util\SiteUtility;
23+
use Psr\EventDispatcher\EventDispatcherInterface;
24+
use TYPO3\CMS\Core\Core\Environment;
2125
use TYPO3\CMS\Core\Exception\SiteNotFoundException;
26+
use TYPO3\CMS\Core\Site\Entity\Site as TYPO3Site;
2227
use TYPO3\CMS\Core\Site\SiteFinder;
28+
use TYPO3\CMS\Core\Utility\GeneralUtility;
2329

2430
/**
2531
* SiteHashService
2632
*
27-
* Responsible to provide sitehash related service methods.
33+
* Responsible to provide site-hash related service methods.
2834
*/
2935
class SiteHashService
3036
{
31-
protected SiteFinder $siteFinder;
37+
protected EventDispatcherInterface $eventDispatcher;
3238

33-
public function __construct(SiteFinder $siteFinder)
34-
{
35-
$this->siteFinder = $siteFinder;
39+
public function __construct(
40+
protected SiteFinder $siteFinder,
41+
protected ExtensionConfiguration $extensionConfiguration,
42+
?EventDispatcherInterface $eventDispatcherInterface = null,
43+
) {
44+
$this->eventDispatcher = $eventDispatcherInterface ?? GeneralUtility::makeInstance(EventDispatcherInterface::class);
3645
}
3746

3847
/**
@@ -52,32 +61,98 @@ public function getAllowedSitesForPageIdAndAllowedSitesConfiguration(
5261
?string $allowedSitesConfiguration = '',
5362
): string {
5463
if ($allowedSitesConfiguration === '__all') {
55-
return $this->getDomainListOfAllSites();
64+
return $this->extensionConfiguration->getSiteHashStrategy() === 1
65+
? $this->getIdentifiersOfAllSites()
66+
: $this->getDomainListOfAllSites();
5667
}
5768
if ($allowedSitesConfiguration === '*') {
5869
return '*';
5970
}
6071
// we thread empty allowed site configurations as __solr_current_site since this is the default behaviour
6172
$allowedSitesConfiguration = empty($allowedSitesConfiguration) ? '__solr_current_site' : $allowedSitesConfiguration;
62-
return $this->getDomainByPageIdAndReplaceMarkers($pageId, $allowedSitesConfiguration);
73+
74+
if ($this->extensionConfiguration->getSiteHashStrategy() === 0) {
75+
return $this->getDomainByPageIdAndReplaceMarkers($pageId, $allowedSitesConfiguration);
76+
}
77+
return $this->getSiteIdentifierByPageIdAndReplaceMarkers($pageId, $allowedSitesConfiguration);
78+
}
79+
80+
public function getSiteHash(TYPO3Site $site): string
81+
{
82+
static $siteHashes = [];
83+
if (isset($siteHashes[$site->getIdentifier()])) {
84+
return $siteHashes[$site->getIdentifier()];
85+
}
86+
87+
$siteHash = $this->getSiteHashForSiteIdentifier($site->getIdentifier());
88+
89+
$event = $this->eventDispatcher->dispatch(
90+
new AfterSiteHashHasBeenDeterminedForSiteEvent(
91+
$siteHash,
92+
$site,
93+
$this->extensionConfiguration,
94+
),
95+
);
96+
$siteHashes[$site->getIdentifier()] = $event->getSiteHash();
97+
return $siteHashes[$site->getIdentifier()];
6398
}
6499

65100
/**
66101
* Gets the site hash for a given domain
102+
*
103+
* @deprecated The method SiteHashService::getSiteHashForDomain() is deprecated and will be removed in version 13.1.x+.
104+
* Use SiteHashService::getSiteHashForSiteIdentifier() or SiteHashService::getSiteHash() instead.
67105
*/
68106
public function getSiteHashForDomain(string $domain): string
107+
{
108+
trigger_error(
109+
'The method SiteHashService::getSiteHashForDomain() is deprecated and will be removed in version 13.1.x+.' .
110+
'Use SiteHashService::getSiteHashForSiteIdentifier() or SiteHashService::getSiteHash() instead.',
111+
E_USER_DEPRECATED,
112+
);
113+
return $this->getSiteHashForSiteIdentifier($domain);
114+
}
115+
116+
/**
117+
* Gets the site hash for a given site-identifier
118+
*/
119+
public function getSiteHashForSiteIdentifier(string $siteIdentifier): string
69120
{
70121
static $siteHashes = [];
71-
if (isset($siteHashes[$domain])) {
72-
return $siteHashes[$domain];
122+
if (isset($siteHashes[$siteIdentifier])) {
123+
return $siteHashes[$siteIdentifier];
124+
}
125+
126+
$applicationContext = (string)Environment::getContext();
127+
if ($this->extensionConfiguration->getSiteHashStrategy() === 0) {
128+
$applicationContext = '';
129+
}
130+
$siteHashes[$siteIdentifier] = sha1($applicationContext . $siteIdentifier . $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] . 'tx_solr');
131+
return $siteHashes[$siteIdentifier];
132+
}
133+
134+
/**
135+
* Returns a comma separated list of all site-identifiers.
136+
*/
137+
protected function getIdentifiersOfAllSites(): string
138+
{
139+
$sites = $this->siteFinder->getAllSites();
140+
$siteIdentifiers = [];
141+
foreach ($sites as $typo3Site) {
142+
$connections = SiteUtility::getAllSolrConnectionConfigurations($typo3Site);
143+
if (!empty($connections)) {
144+
$siteIdentifiers[] = $typo3Site->getIdentifier();
145+
}
73146
}
74147

75-
$siteHashes[$domain] = sha1($domain . $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] . 'tx_solr');
76-
return $siteHashes[$domain];
148+
return implode(',', $siteIdentifiers);
77149
}
78150

79151
/**
80152
* Returns a comma separated list of all domains from all sites.
153+
*
154+
* @deprecated SiteHashService::getDomainListOfAllSites() is deprecated and will be removed in v14.
155+
* Use SiteHashService::getIdentifiersOfAllSites() instead.
81156
*/
82157
protected function getDomainListOfAllSites(): string
83158
{
@@ -93,9 +168,29 @@ protected function getDomainListOfAllSites(): string
93168
return implode(',', $domains);
94169
}
95170

171+
/**
172+
* Retrieves the site identifier of the site that belongs to the passed pageId and replaces their markers __solr_current_site
173+
* and __current_site.
174+
*/
175+
protected function getSiteIdentifierByPageIdAndReplaceMarkers(int $pageId, string $allowedSitesConfiguration): string
176+
{
177+
try {
178+
$typo3Site = $this->siteFinder->getSiteByPageId($pageId);
179+
$siteIdentifierOfPage = $typo3Site->getIdentifier();
180+
} catch (SiteNotFoundException) {
181+
return '';
182+
}
183+
184+
$allowedSites = str_replace(['__solr_current_site', '__current_site'], $siteIdentifierOfPage, $allowedSitesConfiguration);
185+
return (string)$allowedSites;
186+
}
187+
96188
/**
97189
* Retrieves the domain of the site that belongs to the passed pageId and replaces their markers __solr_current_site
98190
* and __current_site.
191+
*
192+
* @deprecated SiteHashService::getDomainByPageIdAndReplaceMarkers() is deprecated and will be removed in v14.
193+
* Use SiteHashService::getSiteIdentifierByPageIdAndReplaceMarkers() instead.
99194
*/
100195
protected function getDomainByPageIdAndReplaceMarkers(int $pageId, string $allowedSitesConfiguration): string
101196
{

Classes/Domain/Site/SiteRepository.php

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,14 +250,27 @@ protected function buildSite(int $rootPageId): ?Site
250250
return $this->buildTypo3ManagedSite($rootPageRecord);
251251
}
252252

253+
/**
254+
* Returns the site hash for given site.
255+
*/
256+
protected function getSiteHash(CoreSite $site): string
257+
{
258+
/** @var SiteHashService $siteHashService */
259+
$siteHashService = GeneralUtility::makeInstance(SiteHashService::class);
260+
return $siteHashService->getSiteHash($site);
261+
}
262+
253263
/**
254264
* Returns the site hash for given domain.
265+
*
266+
* @deprecated SiteRepository::getSiteHashForDomain() is soft deprecated and will be removed in v13.1.x+.
267+
* The SiteRepository::getSiteHash() will be used instead.
255268
*/
256269
protected function getSiteHashForDomain(string $domain): string
257270
{
258271
/** @var SiteHashService $siteHashService */
259272
$siteHashService = GeneralUtility::makeInstance(SiteHashService::class);
260-
return $siteHashService->getSiteHashForDomain($domain);
273+
return $siteHashService->getSiteHashForSiteIdentifier($domain);
261274
}
262275

263276
/**
@@ -302,7 +315,11 @@ protected function buildTypo3ManagedSite(array $rootPageRecord): ?Site
302315
);
303316
$domain = $event->getDomain();
304317

305-
$siteHash = $this->getSiteHashForDomain($domain);
318+
$siteHash = $this->getSiteHash($typo3Site);
319+
if ($this->extensionConfiguration->getSiteHashStrategy() === 0) {
320+
$siteHash = $this->getSiteHashForDomain($domain);
321+
}
322+
306323
$defaultLanguage = $typo3Site->getDefaultLanguage()->getLanguageId();
307324
$pageRepository = GeneralUtility::makeInstance(PagesRepository::class);
308325
$availableLanguageIds = array_map(static function ($language) {

Classes/Eid/ApiEid.php

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class ApiEid
4040
'siteHash' => [
4141
'params' => [
4242
'required' => [
43-
'domain',
43+
'siteIdentifier',
4444
],
4545
],
4646
],
@@ -53,6 +53,12 @@ class ApiEid
5353
*/
5454
public function main(ServerRequestInterface $request): ResponseInterface
5555
{
56+
$queryParams = $request->getQueryParams();
57+
// @todo, remove this backwards-compatibility-adjustment together with siteHashStrategy setting.
58+
if (isset($queryParams['domain'])) {
59+
$queryParams['siteIdentifier'] = $queryParams['domain'];
60+
$request = $request->withQueryParams($queryParams);
61+
}
5662
$this->validateRequest($request);
5763
return $this->{'get' . ucfirst($request->getQueryParams()['api']) . 'Response'}($request);
5864
}
@@ -64,13 +70,26 @@ public function main(ServerRequestInterface $request): ResponseInterface
6470
*/
6571
protected function getSiteHashResponse(ServerRequestInterface $request): JsonResponse
6672
{
67-
$domain = $request->getQueryParams()['domain'];
73+
$queryParams = $request->getQueryParams();
74+
$siteIdentifier = $queryParams['siteIdentifier'];
6875

6976
/** @var SiteHashService $siteHashService */
7077
$siteHashService = GeneralUtility::makeInstance(SiteHashService::class);
71-
$siteHash = $siteHashService->getSiteHashForDomain($domain);
78+
$siteHash = $siteHashService->getSiteHashForSiteIdentifier($siteIdentifier);
79+
$jsonResponseContents = [
80+
'sitehash' => $siteHash,
81+
];
82+
// @todo, remove this backwards-compatibility-adjustment together with siteHashStrategy setting.
83+
if (isset($queryParams['domain'])) {
84+
$deprecationMessage = 'The domain parameter for eID=tx_solr_api - api=siteHash is deprecated, please use siteIdentifier instead.';
85+
trigger_error(
86+
$deprecationMessage,
87+
E_USER_DEPRECATED,
88+
);
89+
$jsonResponseContents['deprecation notice'] = $deprecationMessage;
90+
}
7291
return new JsonResponse(
73-
['sitehash' => $siteHash],
92+
$jsonResponseContents,
7493
);
7594
}
7695

@@ -106,6 +125,7 @@ protected function validateRequest(ServerRequestInterface $request): void
106125
}
107126

108127
$requiredApiParams = $this->getApiMethodDefinitions()[$params['api']]['params']['required'] ?? [];
128+
109129
$requiredApiParams[] = 'eID';
110130
$missingParams = array_values(array_diff($requiredApiParams, array_keys($request->getQueryParams())));
111131
if (!empty($missingParams)) {

Classes/Event/Site/AfterDomainHasBeenDeterminedForSiteEvent.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222

2323
/**
2424
* This event is dispatched when determining which domain to use for a site
25+
*
26+
* @deprecated AfterDomainHasBeenDeterminedForSiteEvent is deprecated and will be removed in v13.1.x+.
27+
* Use AfterSiteHashHasBeenDeterminedForSiteEvent instead.
2528
*/
2629
final class AfterDomainHasBeenDeterminedForSiteEvent
2730
{

0 commit comments

Comments
 (0)