Skip to content

Commit

Permalink
Use PHP generator to prevent processing of all available site
Browse files Browse the repository at this point in the history
Use PHP generator with yield to process just the available sites needed
How to test

With over 300 root pages it needs over 30 seconds to build up all available sites. With help of a PHP generator we can stop processing all available sites if just the first site is requested. It's also helpful to just check, if there are available sites.

This should speed up performance a lot.

* Remove cache storing from <has> methods of SiteRepository
* Use hasAvailableSites in ModuleController
* Remove cache-set check from tests for SiteRepository
* Repair unit tests
* Move check for duplicate sites to getAvailableSites. PhpStan
* Remove unused imports

Fixes: #3939
Ports: #4154
Replaces: #4145
  • Loading branch information
sfroemkenjw authored and dkd-kaehm committed Dec 12, 2024
1 parent 0fc8d7c commit 1d4256f
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,8 @@ protected function initializeAction(): void
*/
protected function autoSelectFirstSiteAndRootPageWhenOnlyOneSiteIsAvailable(): bool
{
$solrConfiguredSites = $this->siteRepository->getAvailableSites();
$availableSites = $this->siteFinder->getAllSites();
if (count($solrConfiguredSites) === 1 && count($availableSites) === 1) {
if (count($availableSites) === 1 && $this->siteRepository->hasExactlyOneAvailableSite()) {
$this->selectedSite = $this->siteRepository->getFirstAvailableSite();

// we only overwrite the selected pageUid when no id was passed
Expand All @@ -148,9 +147,7 @@ protected function autoSelectFirstSiteAndRootPageWhenOnlyOneSiteIsAvailable(): b
*/
protected function initializeView(ViewInterface|FluidStandaloneViewInterface $view): void
{
$sites = $this->siteRepository->getAvailableSites();

$selectOtherPage = count($sites) > 0 || $this->selectedPageUID < 1;
$selectOtherPage = $this->siteRepository->hasAvailableSites() || $this->selectedPageUID < 1;
$this->moduleTemplate->assign('showSelectOtherPage', $selectOtherPage);
$this->moduleTemplate->assign('selectedPageUID', $this->selectedPageUID);
if ($this->selectedPageUID < 1) {
Expand Down
77 changes: 62 additions & 15 deletions Classes/Domain/Site/SiteRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,12 @@ public function getSiteByRootPageId(int $rootPageId): ?Site
*/
public function getFirstAvailableSite(bool $stopOnInvalidSite = false): ?Site
{
$sites = $this->getAvailableSites($stopOnInvalidSite);
return array_shift($sites);
$siteGenerator = $this->getAvailableTYPO3ManagedSites($stopOnInvalidSite);
$siteGenerator->rewind();

$site = $siteGenerator->current();

return $site instanceof Site ? $site : null;
}

/**
Expand All @@ -119,37 +123,81 @@ public function getAvailableSites(bool $stopOnInvalidSite = false): array
$cacheId = 'SiteRepository' . '_' . 'getAvailableSites';

$sites = $this->runtimeCache->get($cacheId);
if (!empty($sites)) {
if (is_array($sites) && $sites !== []) {
return $sites;
}

$sites = $this->getAvailableTYPO3ManagedSites($stopOnInvalidSite);
$siteGenerator = $this->getAvailableTYPO3ManagedSites($stopOnInvalidSite);
$siteGenerator->rewind();

$sites = [];
foreach ($siteGenerator as $rootPageId => $site) {
if (isset($sites[$rootPageId])) {
//get each site only once
continue;
}
$sites[$rootPageId] = $site;
}
$this->runtimeCache->set($cacheId, $sites);

return $sites;
}

/**
* Check, if there are any managed sites available
*
* @throws UnexpectedTYPO3SiteInitializationException
*/
public function hasAvailableSites(bool $stopOnInvalidSite = false): bool
{
$siteGenerator = $this->getAvailableTYPO3ManagedSites($stopOnInvalidSite);
$siteGenerator->rewind();

return ($site = $siteGenerator->current()) && $site instanceof Site;
}

/**
* Check, if there is exactly one managed site available
* Needed in AbstractModuleController::autoSelectFirstSiteAndRootPageWhenOnlyOneSiteIsAvailable
*
* @throws UnexpectedTYPO3SiteInitializationException
*/
public function hasExactlyOneAvailableSite(bool $stopOnInvalidSite = false): bool
{
if (!$this->hasAvailableSites($stopOnInvalidSite)) {
return false;
}

$siteGenerator = $this->getAvailableTYPO3ManagedSites($stopOnInvalidSite);
$siteGenerator->rewind();

// We start with 1 here as we know from hasAvailableSites() above we have at least one site
$counter = 1;
foreach ($siteGenerator as $_) {
if ($counter > 1) {
return false;
}
$counter++;
}

return true;
}

/**
* Returns available TYPO3 sites
*
* @return Site[]
* @return Site[]|\Generator
*
* @throws UnexpectedTYPO3SiteInitializationException
*/
protected function getAvailableTYPO3ManagedSites(bool $stopOnInvalidSite): array
protected function getAvailableTYPO3ManagedSites(bool $stopOnInvalidSite): \Generator
{
$typo3ManagedSolrSites = [];
$typo3Sites = $this->siteFinder->getAllSites();
foreach ($typo3Sites as $typo3Site) {
foreach ($this->siteFinder->getAllSites() as $typo3Site) {
try {
$rootPageId = $typo3Site->getRootPageId();
if (isset($typo3ManagedSolrSites[$rootPageId])) {
//get each site only once
continue;
}
$typo3ManagedSolrSite = $this->buildSite($rootPageId);
if ($typo3ManagedSolrSite->isEnabled()) {
$typo3ManagedSolrSites[$rootPageId] = $typo3ManagedSolrSite;
yield $rootPageId => $typo3ManagedSolrSite;
}
} catch (Throwable $e) {
if ($stopOnInvalidSite) {
Expand All @@ -161,7 +209,6 @@ protected function getAvailableTYPO3ManagedSites(bool $stopOnInvalidSite): array
}
}
}
return $typo3ManagedSolrSites;
}

/**
Expand Down
6 changes: 2 additions & 4 deletions Classes/Report/SiteHandlingStatus.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ public function __construct(
public function getStatus(): array
{
$reports = [];
$sites = $this->siteRepository->getAvailableSites();
if (empty($sites)) {
if (!$this->siteRepository->hasAvailableSites()) {
$reports[] = GeneralUtility::makeInstance(
Status::class,
self::TITLE_SITE_HANDLING_CONFIGURATION,
Expand All @@ -79,8 +78,7 @@ public function getStatus(): array
return $reports;
}

/** @var Site $site */
foreach ($sites as $site) {
foreach ($this->siteRepository->getAvailableSites() as $site) {
if (!($site instanceof Site)) {
$reports[] = GeneralUtility::makeInstance(
Status::class,
Expand Down
6 changes: 1 addition & 5 deletions Classes/ViewHelpers/SearchFormViewHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,10 @@
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\RequestInterface;
use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder;
use TYPO3\CMS\Fluid\Core\Rendering\RenderingContext;
use TYPO3Fluid\Fluid\Core\Variables\VariableProviderInterface;

/**
* Class SearchFormViewHelper
*
*
* @property RenderingContext $renderingContext
*/
class SearchFormViewHelper extends AbstractSolrFrontendTagBasedViewHelper
{
Expand Down Expand Up @@ -87,7 +83,7 @@ public function initializeArguments(): void
public function render()
{
/** @var RequestInterface $request */
$request = $this->renderingContext->getAttribute(ServerRequestInterface::class);
$request = $this->renderingContext->getRequest();

Check failure on line 86 in Classes/ViewHelpers/SearchFormViewHelper.php

View workflow job for this annotation

GitHub Actions / TYPO3 13 on PHP 8.2

Call to an undefined method TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface::getRequest().

Check failure on line 86 in Classes/ViewHelpers/SearchFormViewHelper.php

View workflow job for this annotation

GitHub Actions / TYPO3 13.4.x-dev on PHP 8.2

Call to an undefined method TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface::getRequest().

Check failure on line 86 in Classes/ViewHelpers/SearchFormViewHelper.php

View workflow job for this annotation

GitHub Actions / TYPO3 13 on PHP 8.3

Call to an undefined method TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface::getRequest().

Check failure on line 86 in Classes/ViewHelpers/SearchFormViewHelper.php

View workflow job for this annotation

GitHub Actions / TYPO3 13.4.x-dev on PHP 8.3

Call to an undefined method TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface::getRequest().

Check failure on line 86 in Classes/ViewHelpers/SearchFormViewHelper.php

View workflow job for this annotation

GitHub Actions / TYPO3 13 on PHP 8.4

Call to an undefined method TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface::getRequest().

Check failure on line 86 in Classes/ViewHelpers/SearchFormViewHelper.php

View workflow job for this annotation

GitHub Actions / TYPO3 13.4.x-dev on PHP 8.4

Call to an undefined method TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface::getRequest().
$this->uriBuilder->setRequest($request);
$pageUid = $this->arguments['pageUid'] ?? null;
if ($pageUid === null && !empty($this->getTypoScriptConfiguration()->getSearchTargetPage())) {
Expand Down
1 change: 0 additions & 1 deletion Tests/Unit/Domain/Site/SiteRepositoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ public function canGetFirstAvailableSite(): void
$this->assertThatSitesAreCreatedWithPageIds([333], [
0 => ['language' => 0],
]);
$this->assertCacheIsWritten();

$site = $this->siteRepository->getFirstAvailableSite();
self::assertInstanceOf(Site::class, $site);
Expand Down
3 changes: 1 addition & 2 deletions Tests/Unit/ViewHelpers/SearchFormViewHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
use ApacheSolrForTypo3\Solr\ViewHelpers\SearchFormViewHelper;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Http\ServerRequest;
use TYPO3\CMS\Extbase\Mvc\ExtbaseRequestParameters;
use TYPO3\CMS\Extbase\Mvc\Request;
Expand Down Expand Up @@ -64,7 +63,7 @@ protected function setUp(): void
new TemplatePaths()
);
$request = new Request((new ServerRequest())->withAttribute('extbase', new ExtbaseRequestParameters(SearchController::class)));
$renderingContext->setAttribute(ServerRequestInterface::class, $request);
$renderingContext->setRequest($request);
$this->viewHelper->setRenderingContext($renderingContext);
$this->viewHelper->expects(self::any())->method('getTypoScriptConfiguration')->willReturn($this->typoScriptConfigurationMock);
$this->viewHelper->expects(self::any())->method('getTemplateVariableContainer')->willReturn($this->createMock(VariableProviderInterface::class));
Expand Down

0 comments on commit 1d4256f

Please sign in to comment.