Skip to content

Commit

Permalink
[FEATURE] Add timeframe filter to statistics module
Browse files Browse the repository at this point in the history
Relates: #4228
  • Loading branch information
BastiLu authored and dkd-kaehm committed Dec 11, 2024
1 parent a3da67a commit 56dd3fe
Show file tree
Hide file tree
Showing 7 changed files with 321 additions and 84 deletions.
72 changes: 35 additions & 37 deletions Classes/Controller/Backend/Search/InfoModuleController.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

use ApacheSolrForTypo3\Solr\Api;
use ApacheSolrForTypo3\Solr\Domain\Search\ApacheSolrDocument\Repository as ApacheSolrDocumentRepository;
use ApacheSolrForTypo3\Solr\Domain\Search\Statistics\StatisticsFilterDto;
use ApacheSolrForTypo3\Solr\Domain\Search\Statistics\StatisticsRepository;
use ApacheSolrForTypo3\Solr\Domain\Site\Exception\UnexpectedTYPO3SiteInitializationException;
use ApacheSolrForTypo3\Solr\System\Solr\ResponseAdapter;
Expand Down Expand Up @@ -51,16 +52,21 @@ protected function initializeAction(): void
*
* @noinspection PhpUnused
*/
public function indexAction(): ResponseInterface
{
public function indexAction(
?StatisticsFilterDto $statisticsFilter = null,
int $activeTabId = 0,
string $operation = ''
): ResponseInterface {
$this->initializeAction();

$this->moduleTemplate->assign('activeTabId', $activeTabId);
if ($this->selectedSite === null) {
$this->moduleTemplate->assign('can_not_proceed', true);
return $this->moduleTemplate->renderResponse('Index');
}

$this->collectConnectionInfos();
$this->collectStatistics();
$this->collectStatistics($statisticsFilter, $operation);
$this->collectIndexFieldsInfo();
$this->collectIndexInspectorInfo();

Expand Down Expand Up @@ -133,65 +139,41 @@ protected function collectConnectionInfos(): void
*
* @throws DBALException
*/
protected function collectStatistics(): void
protected function collectStatistics(?StatisticsFilterDto $statisticsFilterDto, string $operation): void
{
$frameWorkConfiguration = $this->configurationManager->getConfiguration(
ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT,
'solr'
);
$statisticsConfig = $frameWorkConfiguration['plugin.']['tx_solr.']['statistics.'] ?? [];

$topHitsLimit = (int)($statisticsConfig['topHits.']['limit'] ?? 5);
$noHitsLimit = (int)($statisticsConfig['noHits.']['limit'] ?? 5);

$queriesDays = (int)($statisticsConfig['queries.']['days'] ?? 30);
$statisticsFilter = $this->getStatisticsFilter($statisticsFilterDto, $operation);

$siteRootPageId = $this->selectedSite->getRootPageId();
/** @var StatisticsRepository $statisticsRepository */
$statisticsRepository = GeneralUtility::makeInstance(StatisticsRepository::class);

$this->moduleTemplate->assign(
'top_search_phrases',
$statisticsRepository->getTopKeyWordsWithHits(
$siteRootPageId,
(int)($statisticsConfig['topHits.']['days'] ?? 30),
$topHitsLimit
)
$statisticsRepository->getTopKeyWordsWithHits($statisticsFilter)
);
$this->moduleTemplate->assign(
'top_search_phrases_without_hits',
$statisticsRepository->getTopKeyWordsWithoutHits(
$siteRootPageId,
(int)($statisticsConfig['noHits.']['days'] ?? 30),
$noHitsLimit
)
$statisticsRepository->getTopKeyWordsWithoutHits($statisticsFilter)
);
$this->moduleTemplate->assign(
'search_phrases_statistics',
$statisticsRepository->getSearchStatistics(
$siteRootPageId,
$queriesDays,
(int)($statisticsConfig['queries.']['limit'] ?? 100)
)
$statisticsRepository->getSearchStatistics($statisticsFilter)
);

$labels = [];
$data = [];
$chartData = $statisticsRepository->getQueriesOverTime(
$siteRootPageId,
$queriesDays,
86400
);
$chartData = $statisticsRepository->getQueriesOverTime($statisticsFilter, 86400);

foreach ($chartData as $bucket) {
// @todo Replace deprecated strftime in php 8.1. Suppress warning for now
$labels[] = @strftime('%x', $bucket['timestamp']);
$data[] = (int)$bucket['numQueries'];
}

$this->moduleTemplate->assign('statisticsFilter', $statisticsFilter);
$this->moduleTemplate->assign('queriesChartLabels', json_encode($labels));
$this->moduleTemplate->assign('queriesChartData', json_encode($data));
$this->moduleTemplate->assign('topHitsLimit', $topHitsLimit);
$this->moduleTemplate->assign('noHitsLimit', $noHitsLimit);
$this->moduleTemplate->assign('topHitsLimit', $statisticsFilter->getTopHitsLimit());
$this->moduleTemplate->assign('noHitsLimit', $statisticsFilter->getNoHitsLimit());
}

/**
Expand Down Expand Up @@ -322,4 +304,20 @@ protected function getCoreMetrics(ResponseAdapter $lukeData, array $fields): arr
'numberOfFields' => count($fields),
];
}

protected function getStatisticsFilter(?StatisticsFilterDto $statisticsFilterDto, string $operation): StatisticsFilterDto
{
$frameWorkConfiguration = $this->configurationManager->getConfiguration(
ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT,
'solr'
);
$statisticsConfig = $frameWorkConfiguration['plugin.']['tx_solr.']['statistics.'] ?? [];

if ($statisticsFilterDto === null || $operation === 'reset-filters') {
$statisticsFilterDto = GeneralUtility::makeInstance(StatisticsFilterDto::class);
}

return $statisticsFilterDto->setFromTypoScriptConstants($statisticsConfig)
->setSiteRootPageId($this->selectedSite->getRootPageId());
}
}
149 changes: 149 additions & 0 deletions Classes/Domain/Search/Statistics/StatisticsFilterDto.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
<?php

declare(strict_types=1);

namespace ApacheSolrForTypo3\Solr\Domain\Search\Statistics;

use DateTime;

final class StatisticsFilterDto
{
/** typoscript constants */
private int $siteRootPageId = 0;
private int $topHitsLimit = 5;
private int $noHitsLimit = 5;
private int $queriesLimit = 100;
private int $topHitsDays = 30;
private int $noHitsDays = 30;
private int $queriesDays = 30;

/** Override properties */
private ?DateTime $startDate = null;
private ?DateTime $endDate = null;

public function __construct()
{
$this->startDate = DateTime::createFromFormat('U', (string)$this->getQueriesStartDate());
$this->endDate = DateTime::createFromFormat('U', (string)$this->getEndDateTimestamp());
}

public function setFromTypoScriptConstants(array $settings): StatisticsFilterDto
{
$this->topHitsLimit = (int)($settings['topHits.']['limit'] ?? 5);
$this->noHitsLimit = (int)($settings['noHits.']['limit'] ?? 5);
$this->queriesLimit = (int)($settings['queries.']['limit'] ?? 100);
$this->topHitsDays = (int)($settings['topHits.']['days'] ?? 30);
$this->noHitsDays = (int)($settings['noHits.']['days'] ?? 30);
$this->queriesDays = (int)($settings['queries.']['days'] ?? 30);

return $this;
}

public function setSiteRootPageId(int $siteRootPageId): StatisticsFilterDto
{
$this->siteRootPageId = $siteRootPageId;
return $this;
}

public function setStartDate(?DateTime $startDate): StatisticsFilterDto
{
$this->startDate = $startDate;
return $this;
}

public function setEndDate(?DateTime $endDate): StatisticsFilterDto
{
$this->endDate = $endDate;
return $this;
}

public function getTopHitsDays(): int
{
return $this->topHitsDays;
}

public function getNoHitsDays(): int
{
return $this->noHitsDays;
}

public function getQueriesDays(): int
{
return $this->queriesDays;
}

public function getSiteRootPageId(): int
{
return $this->siteRootPageId;
}

public function getTopHitsLimit(): int
{
return $this->topHitsLimit;
}

public function getNoHitsLimit(): int
{
return $this->noHitsLimit;
}

public function getQueriesLimit(): int
{
return $this->queriesLimit;
}

public function getStartDate(): ?DateTime
{
return $this->startDate;
}

public function getEndDate(): ?DateTime
{
return $this->endDate;
}

public function getTopHitsStartDate(): int
{
if ($this->startDate !== null) {
return $this->startDate->getTimestamp();
}

return $this->getTimeStampSinceDays($this->topHitsDays);
}

public function getNoHitsStartDate(): int
{
if ($this->startDate !== null) {
return $this->startDate->getTimestamp();
}

return $this->getTimeStampSinceDays($this->noHitsDays);
}

public function getQueriesStartDate(): int
{
if ($this->startDate !== null) {
return $this->startDate->getTimestamp();
}

return $this->getTimeStampSinceDays($this->queriesDays);
}

/**
* End date can not be set by default in typoscript constants and is always now, so one override getter is enough
*/
public function getEndDateTimestamp(): int
{
if ($this->endDate !== null) {
return $this->endDate->getTimestamp();
}

return $this->getTimeStampSinceDays(0);
}

protected function getTimeStampSinceDays(int $days): int
{
$now = time();
return $now - 86400 * $days; // 86400 seconds/day
}
}
Loading

0 comments on commit 56dd3fe

Please sign in to comment.