Skip to content

Commit 4bcf0c5

Browse files
authored
IBX-7653: IsContainer criterion added (#333)
1 parent 868c475 commit 4bcf0c5

File tree

9 files changed

+293
-1
lines changed

9 files changed

+293
-1
lines changed

.sonarcloud.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
sonar.exclusions=**/Tests/**/_fixtures/*
1+
sonar.exclusions=tests/**/_fixtures/**/*
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (C) Ibexa AS. All rights reserved.
5+
* @license For full copyright and license information view LICENSE file distributed with this source code.
6+
*/
7+
declare(strict_types=1);
8+
9+
namespace Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion;
10+
11+
use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion;
12+
use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\Operator\Specifications;
13+
use Ibexa\Contracts\Core\Repository\Values\Filter\FilteringCriterion;
14+
15+
final class IsContainer extends Criterion implements FilteringCriterion
16+
{
17+
public function __construct(bool $value = true)
18+
{
19+
parent::__construct(null, null, $value);
20+
}
21+
22+
public function getSpecifications(): array
23+
{
24+
return [
25+
new Specifications(
26+
Operator::EQ,
27+
Specifications::FORMAT_SINGLE,
28+
Specifications::TYPE_BOOLEAN
29+
),
30+
];
31+
}
32+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (C) Ibexa AS. All rights reserved.
5+
* @license For full copyright and license information view LICENSE file distributed with this source code.
6+
*/
7+
declare(strict_types=1);
8+
9+
namespace Ibexa\Core\Persistence\Legacy\Filter\CriterionQueryBuilder\Content;
10+
11+
use Doctrine\DBAL\ParameterType;
12+
use Ibexa\Contracts\Core\Persistence\Filter\Doctrine\FilteringQueryBuilder;
13+
use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\IsContainer;
14+
use Ibexa\Contracts\Core\Repository\Values\Filter\CriterionQueryBuilder;
15+
use Ibexa\Contracts\Core\Repository\Values\Filter\FilteringCriterion;
16+
use Ibexa\Core\Persistence\Legacy\Content\Type\Gateway;
17+
18+
/**
19+
* @internal for internal use by Repository Filtering
20+
*/
21+
final class IsContainerQueryBuilder implements CriterionQueryBuilder
22+
{
23+
public function accepts(FilteringCriterion $criterion): bool
24+
{
25+
return $criterion instanceof IsContainer;
26+
}
27+
28+
/**
29+
* @param \Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\IsContainer $criterion
30+
*/
31+
public function buildQueryConstraint(
32+
FilteringQueryBuilder $queryBuilder,
33+
FilteringCriterion $criterion
34+
): ?string {
35+
$queryBuilder
36+
->joinOnce(
37+
'content',
38+
Gateway::CONTENT_TYPE_TABLE,
39+
'content_type',
40+
'content.contentclass_id = content_type.id',
41+
);
42+
43+
/** @var array{bool} $criterionValue */
44+
$criterionValue = $criterion->value;
45+
$isContainer = reset($criterionValue);
46+
47+
return $queryBuilder->expr()->in(
48+
'content_type.is_container',
49+
$queryBuilder->createNamedParameter((int)$isContainer, ParameterType::INTEGER)
50+
);
51+
}
52+
}

src/lib/Resources/settings/search_engines/legacy/criterion_handlers_common.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,12 @@ services:
144144
- {name: ibexa.search.legacy.gateway.criterion_handler.content}
145145
- {name: ibexa.search.legacy.gateway.criterion_handler.location}
146146

147+
Ibexa\Core\Search\Legacy\Content\Common\Gateway\CriterionHandler\IsContainer:
148+
parent: Ibexa\Core\Search\Legacy\Content\Common\Gateway\CriterionHandler
149+
tags:
150+
- {name: ibexa.search.legacy.gateway.criterion_handler.content}
151+
- {name: ibexa.search.legacy.gateway.criterion_handler.location}
152+
147153
Ibexa\Core\Search\Legacy\Content\Common\Gateway\CriterionHandler\LanguageCode:
148154
class: Ibexa\Core\Search\Legacy\Content\Common\Gateway\CriterionHandler\LanguageCode
149155
parent: Ibexa\Core\Search\Legacy\Content\Common\Gateway\CriterionHandler
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (C) Ibexa AS. All rights reserved.
5+
* @license For full copyright and license information view LICENSE file distributed with this source code.
6+
*/
7+
declare(strict_types=1);
8+
9+
namespace Ibexa\Core\Search\Legacy\Content\Common\Gateway\CriterionHandler;
10+
11+
use Doctrine\DBAL\ParameterType;
12+
use Doctrine\DBAL\Query\QueryBuilder;
13+
use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion;
14+
use Ibexa\Core\Persistence\Legacy\Content\Type\Gateway as ContentTypeGateway;
15+
use Ibexa\Core\Search\Legacy\Content\Common\Gateway\CriteriaConverter;
16+
use Ibexa\Core\Search\Legacy\Content\Common\Gateway\CriterionHandler;
17+
18+
final class IsContainer extends CriterionHandler
19+
{
20+
public function accept(Criterion $criterion): bool
21+
{
22+
return $criterion instanceof Criterion\IsContainer;
23+
}
24+
25+
/**
26+
* @phpstan-param array{languages: string[]} $languageSettings
27+
*/
28+
public function handle(
29+
CriteriaConverter $converter,
30+
QueryBuilder $queryBuilder,
31+
Criterion $criterion,
32+
array $languageSettings
33+
) {
34+
/** @var array{bool} $criterionValue */
35+
$criterionValue = $criterion->value;
36+
$isContainer = reset($criterionValue);
37+
38+
$subSelect = $this->connection->createQueryBuilder();
39+
$subSelect
40+
->select(
41+
'id'
42+
)->from(
43+
ContentTypeGateway::CONTENT_TYPE_TABLE
44+
)->where(
45+
$queryBuilder->expr()->eq(
46+
'is_container',
47+
$queryBuilder->createNamedParameter((int)$isContainer, ParameterType::INTEGER)
48+
)
49+
);
50+
51+
return $queryBuilder->expr()->in(
52+
'c.contentclass_id',
53+
$subSelect->getSQL()
54+
);
55+
}
56+
}

tests/integration/Core/Repository/Filtering/BaseRepositoryFilteringTestCase.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,8 @@ public function getCriteriaForInitialData(): iterable
239239
Criterion\Operator::BETWEEN,
240240
[1080220197, 1448889046]
241241
);
242+
yield 'IsContainer=true' => new Criterion\IsContainer(true);
243+
yield 'IsContainer=false' => new Criterion\IsContainer(false);
242244
yield 'IsUserBased=true' => new Criterion\IsUserBased(true);
243245
yield 'IsUserBased=false' => new Criterion\IsUserBased(false);
244246
yield 'IsUserEnabled=true' => new Criterion\IsUserEnabled();

tests/integration/Core/Repository/SearchServiceTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,22 @@ public function getContentQuerySearches()
682682
],
683683
$fixtureDir . 'Visibility.php',
684684
],
685+
[
686+
[
687+
'query' => new Criterion\IsContainer(true),
688+
'sortClauses' => [new SortClause\ContentId()],
689+
'limit' => 5,
690+
],
691+
$fixtureDir . 'IsContainerTrue.php',
692+
],
693+
[
694+
[
695+
'query' => new Criterion\IsContainer(false),
696+
'sortClauses' => [new SortClause\ContentId()],
697+
'limit' => 5,
698+
],
699+
$fixtureDir . 'IsContainerFalse.php',
700+
],
685701
[
686702
[
687703
'query' => new Criterion\IsUserEnabled(true),
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (C) Ibexa AS. All rights reserved.
5+
* @license For full copyright and license information view LICENSE file distributed with this source code.
6+
*/
7+
use Ibexa\Contracts\Core\Repository\Values\Content\Search\SearchHit;
8+
use Ibexa\Contracts\Core\Repository\Values\Content\Search\SearchResult;
9+
10+
return new SearchResult([
11+
'facets' => [],
12+
'searchHits' => [
13+
new SearchHit([
14+
'valueObject' => [
15+
'id' => 10,
16+
'title' => 'Anonymous User',
17+
],
18+
'score' => null,
19+
'index' => null,
20+
'highlight' => null,
21+
'matchedTranslation' => 'eng-US',
22+
]),
23+
new SearchHit([
24+
'valueObject' => [
25+
'id' => 14,
26+
'title' => 'Administrator User',
27+
],
28+
'score' => null,
29+
'index' => null,
30+
'highlight' => null,
31+
'matchedTranslation' => 'eng-US',
32+
]),
33+
new SearchHit([
34+
'valueObject' => [
35+
'id' => 52,
36+
'title' => 'Common INI settings',
37+
],
38+
'score' => null,
39+
'index' => null,
40+
'highlight' => null,
41+
'matchedTranslation' => 'eng-US',
42+
]),
43+
new SearchHit([
44+
'valueObject' => [
45+
'id' => 54,
46+
'title' => 'Ibexa Demo Design (without demo content)',
47+
],
48+
'score' => null,
49+
'index' => null,
50+
'highlight' => null,
51+
'matchedTranslation' => 'eng-US',
52+
]),
53+
],
54+
'spellSuggestion' => null,
55+
'time' => 1,
56+
'timedOut' => null,
57+
'maxScore' => null,
58+
'totalCount' => 4,
59+
]);
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (C) Ibexa AS. All rights reserved.
5+
* @license For full copyright and license information view LICENSE file distributed with this source code.
6+
*/
7+
use Ibexa\Contracts\Core\Repository\Values\Content\Search\SearchHit;
8+
use Ibexa\Contracts\Core\Repository\Values\Content\Search\SearchResult;
9+
10+
return new SearchResult([
11+
'facets' => [],
12+
'searchHits' => [
13+
new SearchHit([
14+
'valueObject' => [
15+
'id' => 4,
16+
'title' => 'Users',
17+
],
18+
'score' => null,
19+
'index' => null,
20+
'highlight' => null,
21+
'matchedTranslation' => 'eng-US',
22+
]),
23+
new SearchHit([
24+
'valueObject' => [
25+
'id' => 11,
26+
'title' => 'Members',
27+
],
28+
'score' => null,
29+
'index' => null,
30+
'highlight' => null,
31+
'matchedTranslation' => 'eng-US',
32+
]),
33+
new SearchHit([
34+
'valueObject' => [
35+
'id' => 12,
36+
'title' => 'Administrator users',
37+
],
38+
'score' => null,
39+
'index' => null,
40+
'highlight' => null,
41+
'matchedTranslation' => 'eng-US',
42+
]),
43+
new SearchHit([
44+
'valueObject' => [
45+
'id' => 13,
46+
'title' => 'Editors',
47+
],
48+
'score' => null,
49+
'index' => null,
50+
'highlight' => null,
51+
'matchedTranslation' => 'eng-US',
52+
]),
53+
new SearchHit([
54+
'valueObject' => [
55+
'id' => 41,
56+
'title' => 'Media',
57+
],
58+
'score' => null,
59+
'index' => null,
60+
'highlight' => null,
61+
'matchedTranslation' => 'eng-US',
62+
]),
63+
],
64+
'spellSuggestion' => null,
65+
'time' => 1,
66+
'timedOut' => null,
67+
'maxScore' => null,
68+
'totalCount' => 14,
69+
]);

0 commit comments

Comments
 (0)