Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NGSTACK-822 adding sorting option to netgen site search #48

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 45 additions & 2 deletions bundle/QueryType/SearchQueryType.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,25 @@
use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery;
use Ibexa\Contracts\Core\Repository\Values\Content\Query;
use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion;
use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause;
use Ibexa\Contracts\Core\SiteAccess\ConfigResolverInterface;
use Ibexa\Core\QueryType\OptionsResolverBasedQueryType;
use Netgen\Bundle\SiteBundle\API\Search\Criterion\FullText;
use Netgen\IbexaSiteApi\API\Site;
use Symfony\Component\OptionsResolver\OptionsResolver;

use function class_exists;
use function count;
use function in_array;
use function is_a;
use function trim;

final class SearchQueryType extends OptionsResolverBasedQueryType
{
public function __construct(private Site $site, private ConfigResolverInterface $configResolver) {}
public function __construct(
private readonly Site $site,
private readonly ConfigResolverInterface $configResolver,
) {}

public static function getName(): string
{
Expand All @@ -27,19 +34,32 @@ public static function getName(): string

protected function configureOptions(OptionsResolver $optionsResolver): void
{
$optionsResolver->setRequired(['search_text', 'content_types', 'subtree']);
$optionsResolver->setRequired(['search_text', 'content_types', 'subtree', 'sort', 'order']);

$optionsResolver->setAllowedTypes('search_text', 'string');
$optionsResolver->setAllowedTypes('content_types', 'string[]');
$optionsResolver->setAllowedTypes('sort', 'string[]');
$optionsResolver->setAllowedTypes('subtree', ['int', 'string']);

$optionsResolver->setAllowedValues(
'search_text',
static fn (string $searchText): bool => trim($searchText) !== '',
);

$optionsResolver->setAllowedValues(
'sort',
fn (array $classNames): bool => $this->validateSortConfig($classNames),
);

$optionsResolver->setAllowedValues(
'order',
static fn (string $order): bool => in_array($order, [Query::SORT_ASC, Query::SORT_DESC], true),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't setAllowedValues accept the array of allowed values, instead of a boolean?

From Syfmony docs:

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefault('transport', 'sendmail');
        $resolver->setAllowedValues('transport', ['sendmail', 'mail', 'smtp']);
    }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, disregard, it also accepts a closure with bool return type.

);

$optionsResolver->setDefault('content_types', $this->configResolver->getParameter('search.content_types', 'ngsite'));
$optionsResolver->setDefault('subtree', $this->site->getSettings()->rootLocationId);
$optionsResolver->setDefault('sort', [SortClause\DatePublished::class]);
$optionsResolver->setDefault('order', Query::SORT_DESC);
}

protected function doGetQuery(array $parameters): Query
Expand All @@ -59,6 +79,29 @@ protected function doGetQuery(array $parameters): Query
$query->query = new FullText(trim($parameters['search_text']));
$query->filter = new Criterion\LogicalAnd($criteria);

$sortClauses = [];

/** @var class-string<\Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause> $className */
foreach ($parameters['sort'] as $className) {
$sortClauses[] = new $className($parameters['order']);
}

$query->sortClauses = $sortClauses;

return $query;
}

/**
* @param string[] $classNames
*/
private function validateSortConfig(array $classNames): bool
{
foreach ($classNames as $className) {
if (!class_exists($className) || !is_a($className, SortClause::class, true)) {
return false;
}
}

return true;
}
}
Loading