Skip to content

Commit

Permalink
IBX-7653: IsContainer criterion added (#333)
Browse files Browse the repository at this point in the history
  • Loading branch information
tischsoic authored May 16, 2024
1 parent 868c475 commit 4bcf0c5
Show file tree
Hide file tree
Showing 9 changed files with 293 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .sonarcloud.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sonar.exclusions=**/Tests/**/_fixtures/*
sonar.exclusions=tests/**/_fixtures/**/*
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion;

use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion;
use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\Operator\Specifications;
use Ibexa\Contracts\Core\Repository\Values\Filter\FilteringCriterion;

final class IsContainer extends Criterion implements FilteringCriterion
{
public function __construct(bool $value = true)
{
parent::__construct(null, null, $value);
}

public function getSpecifications(): array
{
return [
new Specifications(
Operator::EQ,
Specifications::FORMAT_SINGLE,
Specifications::TYPE_BOOLEAN
),
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Core\Persistence\Legacy\Filter\CriterionQueryBuilder\Content;

use Doctrine\DBAL\ParameterType;
use Ibexa\Contracts\Core\Persistence\Filter\Doctrine\FilteringQueryBuilder;
use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\IsContainer;
use Ibexa\Contracts\Core\Repository\Values\Filter\CriterionQueryBuilder;
use Ibexa\Contracts\Core\Repository\Values\Filter\FilteringCriterion;
use Ibexa\Core\Persistence\Legacy\Content\Type\Gateway;

/**
* @internal for internal use by Repository Filtering
*/
final class IsContainerQueryBuilder implements CriterionQueryBuilder
{
public function accepts(FilteringCriterion $criterion): bool
{
return $criterion instanceof IsContainer;
}

/**
* @param \Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\IsContainer $criterion
*/
public function buildQueryConstraint(
FilteringQueryBuilder $queryBuilder,
FilteringCriterion $criterion
): ?string {
$queryBuilder
->joinOnce(
'content',
Gateway::CONTENT_TYPE_TABLE,
'content_type',
'content.contentclass_id = content_type.id',
);

/** @var array{bool} $criterionValue */
$criterionValue = $criterion->value;
$isContainer = reset($criterionValue);

return $queryBuilder->expr()->in(
'content_type.is_container',
$queryBuilder->createNamedParameter((int)$isContainer, ParameterType::INTEGER)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ services:
- {name: ibexa.search.legacy.gateway.criterion_handler.content}
- {name: ibexa.search.legacy.gateway.criterion_handler.location}

Ibexa\Core\Search\Legacy\Content\Common\Gateway\CriterionHandler\IsContainer:
parent: Ibexa\Core\Search\Legacy\Content\Common\Gateway\CriterionHandler
tags:
- {name: ibexa.search.legacy.gateway.criterion_handler.content}
- {name: ibexa.search.legacy.gateway.criterion_handler.location}

Ibexa\Core\Search\Legacy\Content\Common\Gateway\CriterionHandler\LanguageCode:
class: Ibexa\Core\Search\Legacy\Content\Common\Gateway\CriterionHandler\LanguageCode
parent: Ibexa\Core\Search\Legacy\Content\Common\Gateway\CriterionHandler
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Core\Search\Legacy\Content\Common\Gateway\CriterionHandler;

use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Query\QueryBuilder;
use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion;
use Ibexa\Core\Persistence\Legacy\Content\Type\Gateway as ContentTypeGateway;
use Ibexa\Core\Search\Legacy\Content\Common\Gateway\CriteriaConverter;
use Ibexa\Core\Search\Legacy\Content\Common\Gateway\CriterionHandler;

final class IsContainer extends CriterionHandler
{
public function accept(Criterion $criterion): bool
{
return $criterion instanceof Criterion\IsContainer;
}

/**
* @phpstan-param array{languages: string[]} $languageSettings
*/
public function handle(
CriteriaConverter $converter,
QueryBuilder $queryBuilder,
Criterion $criterion,
array $languageSettings
) {
/** @var array{bool} $criterionValue */
$criterionValue = $criterion->value;
$isContainer = reset($criterionValue);

$subSelect = $this->connection->createQueryBuilder();
$subSelect
->select(
'id'
)->from(
ContentTypeGateway::CONTENT_TYPE_TABLE
)->where(
$queryBuilder->expr()->eq(
'is_container',
$queryBuilder->createNamedParameter((int)$isContainer, ParameterType::INTEGER)
)
);

return $queryBuilder->expr()->in(
'c.contentclass_id',
$subSelect->getSQL()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ public function getCriteriaForInitialData(): iterable
Criterion\Operator::BETWEEN,
[1080220197, 1448889046]
);
yield 'IsContainer=true' => new Criterion\IsContainer(true);
yield 'IsContainer=false' => new Criterion\IsContainer(false);
yield 'IsUserBased=true' => new Criterion\IsUserBased(true);
yield 'IsUserBased=false' => new Criterion\IsUserBased(false);
yield 'IsUserEnabled=true' => new Criterion\IsUserEnabled();
Expand Down
16 changes: 16 additions & 0 deletions tests/integration/Core/Repository/SearchServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,22 @@ public function getContentQuerySearches()
],
$fixtureDir . 'Visibility.php',
],
[
[
'query' => new Criterion\IsContainer(true),
'sortClauses' => [new SortClause\ContentId()],
'limit' => 5,
],
$fixtureDir . 'IsContainerTrue.php',
],
[
[
'query' => new Criterion\IsContainer(false),
'sortClauses' => [new SortClause\ContentId()],
'limit' => 5,
],
$fixtureDir . 'IsContainerFalse.php',
],
[
[
'query' => new Criterion\IsUserEnabled(true),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
use Ibexa\Contracts\Core\Repository\Values\Content\Search\SearchHit;
use Ibexa\Contracts\Core\Repository\Values\Content\Search\SearchResult;

return new SearchResult([
'facets' => [],
'searchHits' => [
new SearchHit([
'valueObject' => [
'id' => 10,
'title' => 'Anonymous User',
],
'score' => null,
'index' => null,
'highlight' => null,
'matchedTranslation' => 'eng-US',
]),
new SearchHit([
'valueObject' => [
'id' => 14,
'title' => 'Administrator User',
],
'score' => null,
'index' => null,
'highlight' => null,
'matchedTranslation' => 'eng-US',
]),
new SearchHit([
'valueObject' => [
'id' => 52,
'title' => 'Common INI settings',
],
'score' => null,
'index' => null,
'highlight' => null,
'matchedTranslation' => 'eng-US',
]),
new SearchHit([
'valueObject' => [
'id' => 54,
'title' => 'Ibexa Demo Design (without demo content)',
],
'score' => null,
'index' => null,
'highlight' => null,
'matchedTranslation' => 'eng-US',
]),
],
'spellSuggestion' => null,
'time' => 1,
'timedOut' => null,
'maxScore' => null,
'totalCount' => 4,
]);
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
use Ibexa\Contracts\Core\Repository\Values\Content\Search\SearchHit;
use Ibexa\Contracts\Core\Repository\Values\Content\Search\SearchResult;

return new SearchResult([
'facets' => [],
'searchHits' => [
new SearchHit([
'valueObject' => [
'id' => 4,
'title' => 'Users',
],
'score' => null,
'index' => null,
'highlight' => null,
'matchedTranslation' => 'eng-US',
]),
new SearchHit([
'valueObject' => [
'id' => 11,
'title' => 'Members',
],
'score' => null,
'index' => null,
'highlight' => null,
'matchedTranslation' => 'eng-US',
]),
new SearchHit([
'valueObject' => [
'id' => 12,
'title' => 'Administrator users',
],
'score' => null,
'index' => null,
'highlight' => null,
'matchedTranslation' => 'eng-US',
]),
new SearchHit([
'valueObject' => [
'id' => 13,
'title' => 'Editors',
],
'score' => null,
'index' => null,
'highlight' => null,
'matchedTranslation' => 'eng-US',
]),
new SearchHit([
'valueObject' => [
'id' => 41,
'title' => 'Media',
],
'score' => null,
'index' => null,
'highlight' => null,
'matchedTranslation' => 'eng-US',
]),
],
'spellSuggestion' => null,
'time' => 1,
'timedOut' => null,
'maxScore' => null,
'totalCount' => 14,
]);

0 comments on commit 4bcf0c5

Please sign in to comment.