Skip to content

Create custom Sort Clause

To create a custom Sort Clause, do the following.

Create Sort Clause class

First, add a ScoreSortClause.php file with the Sort Clause class:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<?php

declare(strict_types=1);

namespace App\Query\SortClause\Solr;

use Ibexa\Contracts\Core\Repository\Values\Content\Query;
use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause;

final class ScoreSortClause extends SortClause
{
    public function __construct(string $sortDirection = Query::SORT_ASC)
    {
        parent::__construct('_score', $sortDirection);
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<?php

declare(strict_types=1);

namespace App\Query\SortClause\Elasticsearch;

use Ibexa\Contracts\Core\Repository\Values\Content\Query;
use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause;

final class ScoreSortClause extends SortClause
{
    public function __construct(string $sortDirection = Query::SORT_ASC)
    {
        parent::__construct('_score', $sortDirection);
    }
}

Create Sort Clause visitor

Then, add a ScoreVisitor class that implements SortClauseVisitor:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<?php

declare(strict_types=1);

namespace App\Query\SortClause\Solr;

use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause;
use Ibexa\Contracts\Solr\Query\SortClauseVisitor;

class ScoreVisitor extends SortClauseVisitor
{
    public function canVisit(SortClause $sortClause): bool
    {
        return $sortClause instanceof SortClause\Score;
    }

    public function visit(SortClause $sortClause): string
    {
        return 'score ' . $this->getDirection($sortClause);
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php

declare(strict_types=1);

namespace App\Query\SortClause\Elasticsearch;

use Ibexa\Contracts\Core\Repository\Values\Content\Query;
use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause;
use Ibexa\Contracts\Elasticsearch\Query\LanguageFilter;
use Ibexa\Contracts\Elasticsearch\Query\SortClauseVisitor;

final class ScoreVisitor implements SortClauseVisitor
{
    public function supports(SortClause $sortClause, LanguageFilter $languageFilter): bool
    {
        return $sortClause instanceof ScoreSortClause;
    }

    public function visit(SortClauseVisitor $visitor, SortClause $sortClause, LanguageFilter $languageFilter): array
    {
        $order = $sortClause->direction === Query::SORT_ASC ? 'asc' : 'desc';

        return [
            '_score' => [
                'order' => $order,
            ],
        ];
    }
}

The supports() method checks if the implementation can handle the given Sort Clause. The visit() method contains the logic that translates Sort Clause information into data understandable by the search engine. The visit() method takes the Sort Clause visitor, the Sort Clause itself and the language filter as arguments.

Finally, register the visitor as a service.

Sort Clauses can be valid for both content and Location search. To choose the search type, use either content or location in the tag when registering the visitor as a service:

1
2
3
4
5
services:
    App\Query\SortClause\Solr\ScoreVisitor:
        tags:
            - { name: ibexa.search.solr.query.content.sort_clause.visitor }
            - { name: ibexa.search.solr.query.location.sort_clause.visitor }
1
2
3
4
5
services:
    App\Query\SortClause\Elasticsearch\ScoreVisitor:
        tags:
            - { name: ibexa.search.elasticsearch.query.content.sort_clause.visitor }
            - { name: ibexa.search.elasticsearch.query.location.sort_clause.visitor }