diff --git a/.sonarcloud.properties b/.sonarcloud.properties index a6f00c520f..43ab56dedb 100644 --- a/.sonarcloud.properties +++ b/.sonarcloud.properties @@ -1 +1 @@ -sonar.exclusions=**/Tests/**/_fixtures/* +sonar.exclusions=tests/**/_fixtures/**/* diff --git a/src/contracts/Repository/Values/Content/Query/Criterion/IsContainer.php b/src/contracts/Repository/Values/Content/Query/Criterion/IsContainer.php new file mode 100644 index 0000000000..4a01a3a20a --- /dev/null +++ b/src/contracts/Repository/Values/Content/Query/Criterion/IsContainer.php @@ -0,0 +1,32 @@ +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) + ); + } +} diff --git a/src/lib/Resources/settings/search_engines/legacy/criterion_handlers_common.yml b/src/lib/Resources/settings/search_engines/legacy/criterion_handlers_common.yml index e62b350481..2b5edd76c0 100644 --- a/src/lib/Resources/settings/search_engines/legacy/criterion_handlers_common.yml +++ b/src/lib/Resources/settings/search_engines/legacy/criterion_handlers_common.yml @@ -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 diff --git a/src/lib/Search/Legacy/Content/Common/Gateway/CriterionHandler/IsContainer.php b/src/lib/Search/Legacy/Content/Common/Gateway/CriterionHandler/IsContainer.php new file mode 100644 index 0000000000..80189c186e --- /dev/null +++ b/src/lib/Search/Legacy/Content/Common/Gateway/CriterionHandler/IsContainer.php @@ -0,0 +1,56 @@ +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() + ); + } +} diff --git a/tests/integration/Core/Repository/Filtering/BaseRepositoryFilteringTestCase.php b/tests/integration/Core/Repository/Filtering/BaseRepositoryFilteringTestCase.php index 9807765353..6118035a9a 100644 --- a/tests/integration/Core/Repository/Filtering/BaseRepositoryFilteringTestCase.php +++ b/tests/integration/Core/Repository/Filtering/BaseRepositoryFilteringTestCase.php @@ -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(); diff --git a/tests/integration/Core/Repository/SearchServiceTest.php b/tests/integration/Core/Repository/SearchServiceTest.php index a2175606e2..87f59cc671 100644 --- a/tests/integration/Core/Repository/SearchServiceTest.php +++ b/tests/integration/Core/Repository/SearchServiceTest.php @@ -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), diff --git a/tests/integration/Core/Repository/_fixtures/Legacy/IsContainerFalse.php b/tests/integration/Core/Repository/_fixtures/Legacy/IsContainerFalse.php new file mode 100644 index 0000000000..f2645e6790 --- /dev/null +++ b/tests/integration/Core/Repository/_fixtures/Legacy/IsContainerFalse.php @@ -0,0 +1,59 @@ + [], + '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, +]); diff --git a/tests/integration/Core/Repository/_fixtures/Legacy/IsContainerTrue.php b/tests/integration/Core/Repository/_fixtures/Legacy/IsContainerTrue.php new file mode 100644 index 0000000000..52f30b9826 --- /dev/null +++ b/tests/integration/Core/Repository/_fixtures/Legacy/IsContainerTrue.php @@ -0,0 +1,69 @@ + [], + '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, +]);