Skip to content

Commit

Permalink
TYPO3-Documentation#14 Aggregate only major versions and render label…
Browse files Browse the repository at this point in the history
…s for highest versions

This commit replaces the all versions aggregation by only major versions.

There is also change for the search results list. Before labels for all versions assigned to the snippet were rendered. After the changes only
the highest version in given branch will be rendered. For example, if
snippet has versions `main`, `12.4`, `12.0`, `11.5`, `11.3`, `11.0`, `9.5`, only labels for
`main`,`12.4`, `11.5`, `9.5` will be rendered.

Resolves issue: TYPO3-Documentation#14
  • Loading branch information
Marcin Sągol committed Feb 15, 2024
1 parent 99cf6a2 commit ca6a00e
Show file tree
Hide file tree
Showing 8 changed files with 185 additions and 30 deletions.
2 changes: 2 additions & 0 deletions config/Elasticorn/docsearch/Mapping.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,5 @@ snippet_content:
analyzer: typo3_analyzer
content_hash:
type: keyword
major_versions:
type: keyword
2 changes: 1 addition & 1 deletion src/Dto/SearchDemand.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public static function createFromRequest(Request $request): SearchDemand
$filterMap = [
'Document Type' => 'manual_type',
'Language' => 'manual_language',
'Version' => 'manual_version',
'Version' => 'major_versions',
];
if (!\array_key_exists($filter, $filterMap)) {
continue;
Expand Down
43 changes: 43 additions & 0 deletions src/Helper/VersionFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace App\Helper;

class VersionFilter
{
/**
* Filters an array of version strings to return only the highest version for each major version.
*
* This function groups the provided versions by their major version number, then sorts and selects
* the highest version within each major version group. It is assumed that the version strings are in
* the format 'major.minor' or similar. The function returns an array of the highest versions for
* each major version.
*
* @param array<string> $versions
*/
public static function filterVersions(array $versions): array
{
$groupedVersions = [];
$nonNumericVersions = [];

foreach ($versions as $version) {
if (!is_numeric(str_replace('.', '', $version))) {
$nonNumericVersions[] = $version;
continue;
}

$majorVersion = explode('.', $version)[0];
$groupedVersions[$majorVersion][] = $version;
}

$highestVersions = [];

foreach ($groupedVersions as $minorVersions) {
usort($minorVersions, static function($a, $b) {
return version_compare($b, $a);
});
$highestVersions[] = $minorVersions[0];
}

return array_merge($highestVersions, $nonNumericVersions);
}
}
56 changes: 30 additions & 26 deletions src/Repository/ElasticRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,19 @@ public function addOrUpdateDocument(array $snippet): void
if (!ctx._source.manual_version.contains(params.manual_version)) {
ctx._source.manual_version.add(params.manual_version);
}
if (!ctx._source.major_versions.contains(params.major_version)) {
ctx._source.major_versions.add(params.major_version);
}
EOD;
$version = $snippet['manual_version'];
$majorVersion = explode('.', $version)[0];

$script = new Script($scriptCode);
$script->setParam('manual_version', $snippet['manual_version']);
$snippet['manual_version'] = [$snippet['manual_version']];
$script->setParam('manual_version', $version);
$script->setParam('major_version', $majorVersion);
$snippet['manual_version'] = [$version];
$snippet['major_versions'] = [$majorVersion];

$script->setUpsert($snippet);
$this->elasticIndex->getClient()->updateDocument($documentId, $script, $this->elasticIndex->getName());
}
Expand Down Expand Up @@ -162,6 +171,20 @@ protected function getDeleteQueryScript(): string
}
}
}
def majorVersionParam = params.manual_version.splitOnToken('.')[0];
def hasOtherWithSameMajorVersion = false;
for (def version : ctx._source.manual_version) {
def majorVersion = version.splitOnToken('.')[0];
if (majorVersion.equals(majorVersionParam)) {
hasOtherWithSameMajorVersion = true;
break;
}
}
if (!hasOtherWithSameMajorVersion && ctx._source.major_versions.contains(majorVersionParam)) {
ctx._source.major_versions.remove(ctx._source.major_versions.indexOf(majorVersionParam));
}
if (ctx._source.manual_version.size() == 0) {
ctx.op = "delete";
}
Expand Down Expand Up @@ -288,6 +311,7 @@ public function findByQuery(SearchDemand $searchDemand): array

$elasticaResultSet = $search->search();
$results = $elasticaResultSet->getResults();

$maxScore = $elasticaResultSet->getMaxScore();
$aggs = $elasticaResultSet->getAggregations();
$aggs = $this->sortAggregations($aggs);
Expand Down Expand Up @@ -340,31 +364,14 @@ private function addAggregations(Query $elasticaQuery): void
$trackerAggregation->setField('manual_title.raw');
$catAggregation->addAggregation($trackerAggregation);

// $status = new Terms('Status');
// $status->setField('status.name');
// $elasticaQuery->addAggregation($status);

// $priority = new Terms('Priority');
// $priority->setField('priority.name');
// $elasticaQuery->addAggregation($priority);

$language = new Terms('Language');
$language->setField('manual_language');
$elasticaQuery->addAggregation($language);

$t3ver = new Terms('Version');
$t3ver->setField('manual_version');
// $t3ver->setSize(50);
$elasticaQuery->addAggregation($t3ver);

//
// $targetver = new Terms('Target Version');
// $targetver->setField('fixed_version.name');
// $elasticaQuery->addAggregation($targetver);

// $phpVer = new Terms('PHP Version');
// $phpVer->setField('php_version');
// $elasticaQuery->addAggregation($phpVer);
$majorVersionsAgg = new Terms('Version');
$majorVersionsAgg->setField('major_versions');
$majorVersionsAgg->setSize(10);
$elasticaQuery->addAggregation($majorVersionsAgg);
}

/**
Expand All @@ -374,9 +381,6 @@ protected function getPages($currentPage): array
{
$numPages = ceil($this->totalHits / $this->perPage);
$i = 0;
/*
*
*/
$maxPages = $numPages;
if ($numPages > 15 && $currentPage <= 7) {
$numPages = 15;
Expand Down
2 changes: 2 additions & 0 deletions src/Twig/AppExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Twig;

use App\Helper\VersionFilter;
use App\Helper\VersionSorter;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Twig\Environment;
Expand All @@ -23,6 +24,7 @@ public function getFunctions(): array
new TwigFunction('render_single_asset', $this->renderSingleAsset(...)),
new TwigFunction('aggregationBucket', $this->aggregationBucket(...), ['is_safe' => ['html']]),
new TwigFunction('sortVersions', VersionSorter::sortVersions(...)),
new TwigFunction('filterVersions', VersionFilter::filterVersions(...)),
];
}

Expand Down
2 changes: 1 addition & 1 deletion templates/search/search.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
<span class="badge badge-secondary text-decoration-none">{{ hit.data.manual_type }}</span>
{% set slugParts = hit.data.manual_slug|split('/') %}
{% set versionInSlug = hit.data.manual_version|filter(item => item in slugParts) | first %}
{% for version in sortVersions(hit.data.manual_version, 'desc') %}
{% for version in sortVersions(filterVersions(hit.data.manual_version), 'desc') %}
{% if version != versionInSlug %}
{% set versionBadgeSlug = hit.data.manual_slug|replace({ (versionInSlug): version }) %}
{% else %}
Expand Down
4 changes: 2 additions & 2 deletions tests/Unit/Dto/SearchDemandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public function createFromRequestWithMultipleFilters(): void
'Document Type' => ['manual' => 'true'],
'Invalid Filter' => ['value' => 'true'],
'Language' => ['en-us' => 'true', 'de-de' => 'false'],
'Version' => ['12.4' => 'true', '11.5' => 'true'],
'Version' => ['12' => 'true', '11' => 'true'],
]]
);

Expand All @@ -78,7 +78,7 @@ public function createFromRequestWithMultipleFilters(): void
$this->assertSame([
'manual_type' => ['manual'],
'manual_language' => ['en-us'],
'manual_version' => ['12.4', '11.5'],
'major_versions' => [12, 11],
], $searchDemand->getFilters());
}

Expand Down
104 changes: 104 additions & 0 deletions tests/Unit/Helper/VersionFilterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php

declare(strict_types=1);

namespace App\Tests\Unit\Helper;

use App\Helper\VersionFilter;
use PHPUnit\Framework\TestCase;

class VersionFilterTest extends TestCase
{
/**
* @test
*/
public function emptyArray(): void
{
self::assertSame([], VersionFilter::filterVersions([]));
}

/**
* @test
*/
public function singleVersion(): void
{
self::assertSame(['12.1'], VersionFilter::filterVersions(['12.1']));
}

/**
* @test
*/
public function multipleVersionsOneMajor(): void
{
$versions = ['12.1', '12.4', '12.2'];
$expected = ['12.4'];

self::assertSame($expected, VersionFilter::filterVersions($versions));
}

/**
* @test
*/
public function multipleVersionsMultipleMajors(): void
{
$versions = ['12.1', '12.4', '11.3', '11.5', '10.1'];
$expected = ['12.4', '11.5', '10.1'];

self::assertSame($expected, VersionFilter::filterVersions($versions));
}

/**
* @test
*/
public function unorderedVersions(): void
{
$versions = ['11.3', '12.1', '11.5', '12.4', '10.1'];
$expected = ['11.5', '12.4', '10.1'];

self::assertSame($expected, VersionFilter::filterVersions($versions));
}

/**
* @test
*/
public function versionsWithSameMajorAndMinor(): void
{
$versions = ['12.0', '12.0', '11.0', '11.1'];
$expected = ['12.0', '11.1'];

self::assertSame($expected, VersionFilter::filterVersions($versions));
}

/**
* @test
*/
public function versionsWithOnlyMajor(): void
{
$versions = ['12', '12', '11', '10'];
$expected = ['12', '11', '10'];

self::assertSame($expected, VersionFilter::filterVersions($versions));
}

/**
* @test
*/
public function nonNumericVersions(): void
{
$versions = ['12.1', 'main', '11.2', 'master', '11.3'];
$expected = ['12.1', '11.3', 'main', 'master'];

$this->assertSame($expected, VersionFilter::filterVersions($versions));
}

/**
* @test
*/
public function onlyNonNumericVersions(): void
{
$versions = ['main', 'master'];
$expected = ['main', 'master'];

$this->assertSame($expected, VersionFilter::filterVersions($versions));
}
}

0 comments on commit ca6a00e

Please sign in to comment.