diff --git a/composer.json b/composer.json index b9057543..51e8886e 100755 --- a/composer.json +++ b/composer.json @@ -27,11 +27,11 @@ "oat-sa/oatbox-extension-installer": "~1.1||dev-master", "ext-json": "*", "oat-sa/generis": ">=15.22", - "oat-sa/tao-core": ">=54.21.0", + "oat-sa/tao-core": ">=54.24.0", "oat-sa/extension-tao-testqti": ">=48.11.0", "oat-sa/extension-tao-delivery": ">=14.10.1", "oat-sa/extension-tao-outcome": ">=13.0.0", - "oat-sa/extension-tao-test": ">=15.15.1", + "oat-sa/extension-tao-test": ">=16.4.0", "oat-sa/extension-tao-mediamanager": ">=12.32.1", "elasticsearch/elasticsearch": "^8.0" }, diff --git a/migrations/Version202106011320101488_taoAdvancedSearch.php b/migrations/Version202106011320101488_taoAdvancedSearch.php index 3d143746..d1b93fa6 100644 --- a/migrations/Version202106011320101488_taoAdvancedSearch.php +++ b/migrations/Version202106011320101488_taoAdvancedSearch.php @@ -14,7 +14,6 @@ final class Version202106011320101488_taoAdvancedSearch extends AbstractMigration { - public function getDescription(): string { return 'Adds task queue for indexation events.'; @@ -26,10 +25,15 @@ public function up(Schema $schema): void $this->propagate($registrationService); $registrationService->__invoke([]); - if ( BrokerFactory::BROKER_MEMORY !== $this->getAssocitationService()->guessDefaultBrokerType()){ - $this->addReport(Report::createWarning( - sprintf('New worker must be created to proceed tasks from queue named `%s`',$registrationService->getQueueName()) - )); + if (BrokerFactory::BROKER_MEMORY !== $this->getAssocitationService()->guessDefaultBrokerType()) { + $this->addReport( + Report::createWarning( + sprintf( + 'New worker must be created to proceed tasks from queue named `%s`', + $registrationService->getQueueName() + ) + ) + ); } } diff --git a/migrations/Version202209081525261488_taoAdvancedSearch.php b/migrations/Version202209081525261488_taoAdvancedSearch.php index f9f10776..2908c786 100644 --- a/migrations/Version202209081525261488_taoAdvancedSearch.php +++ b/migrations/Version202209081525261488_taoAdvancedSearch.php @@ -35,7 +35,7 @@ public function up(Schema $schema): void /** @var ServiceOptions $serviceOptions */ $serviceOptions = $this->getServiceManager()->get(ServiceOptions::SERVICE_ID); - + if ($oldElasticSearch) { $serviceOptions->save(ElasticSearchConfig::class, 'hosts', $oldElasticSearch->getOption('hosts')); } diff --git a/model/Index/Report/IndexSummarizer.php b/model/Index/Report/IndexSummarizer.php index ff099da4..fd9afbcb 100644 --- a/model/Index/Report/IndexSummarizer.php +++ b/model/Index/Report/IndexSummarizer.php @@ -79,8 +79,7 @@ private function createReport( string $label, string $index, int $totalInDb - ): array - { + ): array { $totalIndexed = $this->getTotalResults($index); $percentageIndexed = $totalIndexed === 0 || $totalInDb === 0 ? 0 diff --git a/model/Metadata/Listener/MetadataInheritanceListener.php b/model/Metadata/Listener/MetadataInheritanceListener.php index c8725f7f..72ed72c3 100644 --- a/model/Metadata/Listener/MetadataInheritanceListener.php +++ b/model/Metadata/Listener/MetadataInheritanceListener.php @@ -58,5 +58,4 @@ private function getIndexer(): IndexerInterface ); return $indexer; } - } diff --git a/model/Metadata/Repository/ClassUriCachedRepository.php b/model/Metadata/Repository/ClassUriCachedRepository.php index 38a7390f..cab0d3fc 100644 --- a/model/Metadata/Repository/ClassUriCachedRepository.php +++ b/model/Metadata/Repository/ClassUriCachedRepository.php @@ -29,10 +29,11 @@ class ClassUriCachedRepository extends ConfigurableService implements ClassUriRepositoryInterface { + use OntologyAwareTrait; + private const CLASSES_INDEX = self::class . '::CLASSES_URIS'; - private const CLASSES_INDEX_TOTAL = self::class . '::CLASSES_URIS_TOTAL'; - use OntologyAwareTrait; + private const CLASSES_INDEX_TOTAL = self::class . '::CLASSES_URIS_TOTAL'; public function cacheWarmup(): void { diff --git a/model/Metadata/Service/AdvancedSearchSettingsService.php b/model/Metadata/Service/AdvancedSearchSettingsService.php index 93fc290e..e75a0ead 100644 --- a/model/Metadata/Service/AdvancedSearchSettingsService.php +++ b/model/Metadata/Service/AdvancedSearchSettingsService.php @@ -26,38 +26,47 @@ use oat\generis\model\OntologyRdfs; use oat\tao\model\AdvancedSearch\AdvancedSearchChecker; +use oat\tao\model\featureFlag\FeatureFlagCheckerInterface; +use oat\tao\model\featureFlag\Service\FeatureFlagPropertiesMapping; use oat\tao\model\Lists\Business\Contract\ClassMetadataSearcherInterface; use oat\tao\model\Lists\Business\Domain\ClassMetadataSearchRequest; use oat\tao\model\Lists\Business\Input\ClassMetadataSearchInput; use oat\tao\model\search\Contract\SearchSettingsServiceInterface; use oat\tao\model\search\ResultColumn; use oat\tao\model\search\SearchSettings; +use oat\tao\model\TaoOntology; class AdvancedSearchSettingsService implements SearchSettingsServiceInterface { private const OMIT_PROPERTIES = [ - OntologyRdfs::RDFS_LABEL + OntologyRdfs::RDFS_LABEL, + TaoOntology::PROPERTY_TRANSLATION_TYPE, + TaoOntology::PROPERTY_TRANSLATION_PROGRESS, + TaoOntology::PROPERTY_TRANSLATION_ORIGINAL_RESOURCE_URI, ]; public const DEFAULT_SORT_COLUMN = 'label.raw'; - /** @var ClassMetadataSearcherInterface */ - private $classMetadataSearcher; + private ClassMetadataSearcherInterface $classMetadataSearcher; - /** @var AdvancedSearchChecker */ - private $advancedSearchChecker; + private AdvancedSearchChecker $advancedSearchChecker; - /** @var SearchSettingsServiceInterface */ - private $defaultSearchSettingsService; + private SearchSettingsServiceInterface $defaultSearchSettingsService; + private FeatureFlagCheckerInterface $featureFlagChecker; + private FeatureFlagPropertiesMapping $featureFlagPropertiesMapping; public function __construct( ClassMetadataSearcherInterface $classMetadataSearcher, SearchSettingsServiceInterface $defaultSearchSettingsService, - AdvancedSearchChecker $advancedSearchChecker + AdvancedSearchChecker $advancedSearchChecker, + FeatureFlagCheckerInterface $featureFlagChecker, + FeatureFlagPropertiesMapping $featureFlagPropertiesMapping ) { $this->classMetadataSearcher = $classMetadataSearcher; $this->advancedSearchChecker = $advancedSearchChecker; $this->defaultSearchSettingsService = $defaultSearchSettingsService; + $this->featureFlagChecker = $featureFlagChecker; + $this->featureFlagPropertiesMapping = $featureFlagPropertiesMapping; } public function getSettingsByClassMetadataSearchRequest( @@ -68,7 +77,9 @@ public function getSettingsByClassMetadataSearchRequest( ->getSettingsByClassMetadataSearchRequest($classMetadataSearchRequest); } - $classCollection = $this->classMetadataSearcher->findAll(new ClassMetadataSearchInput($classMetadataSearchRequest)); + $classCollection = $this->classMetadataSearcher->findAll( + new ClassMetadataSearchInput($classMetadataSearchRequest) + ); if ($classMetadataSearchRequest->getStructure() === 'results') { return new SearchSettings( @@ -168,9 +179,11 @@ public function getSettingsByClassMetadataSearchRequest( ) ]; + $propertiesToHide = $this->getPropertiesToHide(); + foreach ($classCollection->getIterator() as $class) { foreach ($class->getMetaData()->getIterator() as $metadata) { - if (in_array($metadata->getPropertyUri(), self::OMIT_PROPERTIES, true)) { + if (in_array($metadata->getPropertyUri(), $propertiesToHide, true)) { continue; } @@ -190,4 +203,21 @@ public function getSettingsByClassMetadataSearchRequest( return new SearchSettings($out); } + + private function getPropertiesToHide(): array + { + $propertiesToHide = self::OMIT_PROPERTIES; + + foreach ($this->featureFlagPropertiesMapping->getAllProperties() as $featureFlag => $properties) { + if (!$this->featureFlagChecker->isEnabled($featureFlag)) { + foreach ($properties as $property) { + if (!in_array($property, $propertiesToHide, true)) { + $propertiesToHide[] = $property; + } + } + } + } + + return $propertiesToHide; + } } diff --git a/model/Metadata/Service/ClassMetadataSearcher.php b/model/Metadata/Service/ClassMetadataSearcher.php index 7e539ca0..39a8391a 100644 --- a/model/Metadata/Service/ClassMetadataSearcher.php +++ b/model/Metadata/Service/ClassMetadataSearcher.php @@ -26,6 +26,9 @@ use oat\generis\model\OntologyAwareTrait; use oat\oatbox\service\ConfigurableService; use oat\tao\model\AdvancedSearch\AdvancedSearchChecker; +use oat\tao\model\featureFlag\FeatureFlagChecker; +use oat\tao\model\featureFlag\FeatureFlagCheckerInterface; +use oat\tao\model\featureFlag\Service\FeatureFlagPropertiesMapping; use oat\tao\model\Lists\Business\Contract\ClassMetadataSearcherInterface; use oat\tao\model\Lists\Business\Domain\ClassCollection; use oat\tao\model\Lists\Business\Domain\ClassMetadata; @@ -36,14 +39,21 @@ use oat\tao\model\Lists\Business\Service\GetClassMetadataValuesService; use oat\tao\model\search\ResultSet; use oat\tao\model\search\SearchProxy; +use oat\tao\model\TaoOntology; use oat\taoAdvancedSearch\model\SearchEngine\Driver\Elasticsearch\ElasticSearch; use oat\taoAdvancedSearch\model\SearchEngine\Query; class ClassMetadataSearcher extends ConfigurableService implements ClassMetadataSearcherInterface { + use OntologyAwareTrait; + private const BASE_LIST_ITEMS_URI = '/tao/PropertyValues/get?propertyUri=%s'; - use OntologyAwareTrait; + private const UNACCEPTABLE_PROPERTIES = [ + TaoOntology::PROPERTY_TRANSLATION_TYPE, + TaoOntology::PROPERTY_TRANSLATION_PROGRESS, + TaoOntology::PROPERTY_TRANSLATION_ORIGINAL_RESOURCE_URI, + ]; public function findAll(ClassMetadataSearchInput $input): ClassCollection { @@ -89,8 +99,11 @@ private function getProperties(string $classUri): array $allProperties = [$result]; $allProperties = $this->getRelatedProperties($result, $allProperties); $allProperties = $this->getClassPathProperties($classUri, $allProperties); + $allProperties = $this->filterDuplicatedProperties($allProperties); - return $this->filterDuplicatedProperties($allProperties); + $propertiesToHide = $this->getPropertiesToHide(); + + return array_diff_key($allProperties, array_flip($propertiesToHide)); } private function getClassPathProperties(string $classUri, array $allProperties): array @@ -258,6 +271,24 @@ private function isAllowedWidget(core_kernel_classes_Property $property, array $ return $widget && $widget->getUri() && !in_array($widget->getUri(), $ignoredWidgets, true); } + private function getPropertiesToHide(): array + { + $propertiesToHide = self::UNACCEPTABLE_PROPERTIES; + $featureFlagChecker = $this->getFeatureFlagChecker(); + + foreach ($this->getFeatureFlagPropertiesMapping()->getAllProperties() as $featureFlag => $properties) { + if (!$featureFlagChecker->isEnabled($featureFlag)) { + foreach ($properties as $property) { + if (!in_array($property, $propertiesToHide, true)) { + $propertiesToHide[] = $property; + } + } + } + } + + return $propertiesToHide; + } + private function getClassMetadataSearcher(): ClassMetadataSearcherInterface { return $this->getServiceLocator()->get(ClassMetadataService::SERVICE_ID); @@ -277,4 +308,14 @@ private function getSearch(): SearchProxy { return $this->getServiceLocator()->get(SearchProxy::SERVICE_ID); } + + private function getFeatureFlagPropertiesMapping(): FeatureFlagPropertiesMapping + { + return $this->getServiceLocator()->getContainer()->get(FeatureFlagPropertiesMapping::class); + } + + private function getFeatureFlagChecker(): FeatureFlagCheckerInterface + { + return $this->getServiceLocator()->getContainer()->get(FeatureFlagChecker::class); + } } diff --git a/model/Metadata/ServiceProvider/MetadataServiceProvider.php b/model/Metadata/ServiceProvider/MetadataServiceProvider.php index b1271892..4b5d4c99 100644 --- a/model/Metadata/ServiceProvider/MetadataServiceProvider.php +++ b/model/Metadata/ServiceProvider/MetadataServiceProvider.php @@ -25,6 +25,8 @@ use oat\generis\model\DependencyInjection\ContainerServiceProviderInterface; use oat\generis\persistence\PersistenceServiceProvider; use oat\tao\model\AdvancedSearch\AdvancedSearchChecker; +use oat\tao\model\featureFlag\FeatureFlagChecker; +use oat\tao\model\featureFlag\Service\FeatureFlagPropertiesMapping; use oat\tao\model\Lists\Business\Service\ClassMetadataSearcherProxy; use oat\tao\model\search\Service\DefaultSearchSettingsService; use oat\taoAdvancedSearch\model\Metadata\Service\AdvancedSearchSettingsService; @@ -32,6 +34,7 @@ use oat\taoAdvancedSearch\model\Metadata\Specification\PropertyAllowedSpecification; use oat\taoAdvancedSearch\model\Resource\Service\ResourceIndexer; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; + use function Symfony\Component\DependencyInjection\Loader\Configurator\param; use function Symfony\Component\DependencyInjection\Loader\Configurator\service; @@ -59,6 +62,8 @@ public function __invoke(ContainerConfigurator $configurator): void service(ClassMetadataSearcherProxy::SERVICE_ID), service(DefaultSearchSettingsService::class), service(AdvancedSearchChecker::class), + service(FeatureFlagChecker::class), + service(FeatureFlagPropertiesMapping::class), ] )->public(); diff --git a/model/SearchEngine/Driver/Elasticsearch/LogIndexOperationsTrait.php b/model/SearchEngine/Driver/Elasticsearch/LogIndexOperationsTrait.php index d4061acd..f49e7c79 100644 --- a/model/SearchEngine/Driver/Elasticsearch/LogIndexOperationsTrait.php +++ b/model/SearchEngine/Driver/Elasticsearch/LogIndexOperationsTrait.php @@ -148,7 +148,7 @@ private function logIndexFailure( LoggerInterface $logger, Throwable $e, string $method, - string $script='', + string $script = '', $type = null, array $query = [] ): void { diff --git a/model/SearchEngine/Driver/Elasticsearch/QueryBuilder.php b/model/SearchEngine/Driver/Elasticsearch/QueryBuilder.php index e325967b..4ecb4812 100644 --- a/model/SearchEngine/Driver/Elasticsearch/QueryBuilder.php +++ b/model/SearchEngine/Driver/Elasticsearch/QueryBuilder.php @@ -80,6 +80,13 @@ class QueryBuilder 'RadioBox', 'SearchTextBox', 'SearchDropdown', + 'Readonly', + ]; + + private const LOGIC_MODIFIERS = [ + 'and' => 'LOGIC_AND', + 'or' => 'LOGIC_OR', + 'not' => 'LOGIC_NOT' ]; /** @var UseAclSpecification */ @@ -126,6 +133,7 @@ public function getSearchParams( ); $queryString = htmlspecialchars_decode($queryString); + $blocks = preg_split('/( AND )/i', $queryString); $index = $this->getIndexByType($type); $conditions = $this->buildConditions($index, $blocks); @@ -207,29 +215,78 @@ private function buildConditionsByType(string $type, array $blocks): array return $this->getResourceConditions($blocks); } + private function containsLogicalModifier(string $block): bool + { + foreach (self::LOGIC_MODIFIERS as $logicModifier) { + if (strpos($block, $logicModifier) !== false) { + return true; + } + } + + return false; + } + + private function buildLogicCondition(string $block): ?string + { + if (strpos($block, self::LOGIC_MODIFIERS['and']) !== false) { + $logicBlocks = preg_split('/( ' . self::LOGIC_MODIFIERS['and'] . ' )/i', $block); + $conditions = array_map([$this, 'buildConditionFromTheBlock'], $logicBlocks); + + return sprintf('(%s)', implode(' AND ', $conditions)); + } + + if (strpos($block, self::LOGIC_MODIFIERS['or']) !== false) { + $logicBlocks = preg_split('/( ' . self::LOGIC_MODIFIERS['or'] . ' )/i', $block); + $conditions = array_map([$this,'buildConditionFromTheBlock'], $logicBlocks); + + return sprintf('(%s)', implode(' OR ', $conditions)); + } + + if (strpos($block, self::LOGIC_MODIFIERS['not']) !== false) { + $logicBlocks = preg_split('/( ' . self::LOGIC_MODIFIERS['not'] . ' )/i', $block); + $conditions = array_map([$this,'buildConditionFromTheBlock'], $logicBlocks); + + return sprintf('NOT (%s)', implode(' OR ', $conditions)); + } + + return null; + } + private function getResourceConditions(array $blocks): array { + $conditions = []; - foreach ($blocks as $block) { - $queryBlock = $this->parseBlock($block); - if (empty($queryBlock->getField())) { - $conditions[] = sprintf('("%s")', $queryBlock->getTerm()); - } elseif ($this->isStandardField($queryBlock->getField())) { - $conditions[] = sprintf('(%s:"%s")', $queryBlock->getField(), $queryBlock->getTerm()); + foreach ($blocks as $block) { + if ($this->containsLogicalModifier($block)) { + $conditions[] = $this->buildLogicCondition($block); } else { - $conditions[] = $this->buildCustomConditions($queryBlock); + $conditions[] = $this->buildConditionFromTheBlock($block); } } return $conditions; } + private function buildConditionFromTheBlock(string $block): string + { + $queryBlock = $this->parseBlock($block); + if (empty($queryBlock->getField())) { + return sprintf('("%s")', $queryBlock->getTerm()); + } elseif ($this->isStandardField($queryBlock->getField())) { + return sprintf('(%s:"%s")', $queryBlock->getField(), $queryBlock->getTerm()); + } else { + return $this->buildCustomConditions($queryBlock); + } + return ''; + } + private function isStandardField(string $field): bool { return in_array(strtolower($field), self::STANDARD_FIELDS); } + private function getIndexByType(string $type): string { if (isset(self::STRUCTURE_TO_INDEX_MAP[$type])) { diff --git a/scripts/tools/CacheWarmup.php b/scripts/tools/CacheWarmup.php index 701b864d..a344d90c 100644 --- a/scripts/tools/CacheWarmup.php +++ b/scripts/tools/CacheWarmup.php @@ -76,7 +76,10 @@ protected function run(): Report $report->add( Report::createSuccess( - sprintf('Cache warmed up! ROOT classUris (%s) in cache', implode(', ', $indexableClassRepository->findAllUris())) + sprintf( + 'Cache warmed up! ROOT classUris (%s) in cache', + implode(', ', $indexableClassRepository->findAllUris()) + ) ) ); diff --git a/scripts/uninstall/UnRegisterTaskQueueServices.php b/scripts/uninstall/UnRegisterTaskQueueServices.php index 5f82e864..fe1513df 100644 --- a/scripts/uninstall/UnRegisterTaskQueueServices.php +++ b/scripts/uninstall/UnRegisterTaskQueueServices.php @@ -39,8 +39,8 @@ public function __invoke($params) return new Report(Report::TYPE_SUCCESS, 'Indexation TaskQueue `%s` was unregistered', $queueName); } - private function getAssociationService(): QueueAssociationService{ + private function getAssociationService(): QueueAssociationService + { return $this->getServiceManager()->get(QueueAssociationService::class); } - } diff --git a/tests/Unit/Metadata/Service/AdvancedSearchSettingsServiceTest.php b/tests/Unit/Metadata/Service/AdvancedSearchSettingsServiceTest.php index 14fafd4e..9c0fec0f 100644 --- a/tests/Unit/Metadata/Service/AdvancedSearchSettingsServiceTest.php +++ b/tests/Unit/Metadata/Service/AdvancedSearchSettingsServiceTest.php @@ -25,6 +25,8 @@ namespace oat\taoAdvancedSearch\tests\Unit\model\Metadata\Service; use oat\tao\model\AdvancedSearch\AdvancedSearchChecker; +use oat\tao\model\featureFlag\FeatureFlagCheckerInterface; +use oat\tao\model\featureFlag\Service\FeatureFlagPropertiesMapping; use oat\tao\model\Lists\Business\Contract\ClassMetadataSearcherInterface; use oat\tao\model\Lists\Business\Domain\ClassCollection; use oat\tao\model\Lists\Business\Domain\ClassMetadata; @@ -56,10 +58,19 @@ public function setUp(): void $this->classMetadataSearcher = $this->createMock(ClassMetadataSearcherInterface::class); $this->defaultSearchSettingsService = $this->createMock(SearchSettingsServiceInterface::class); $this->advancedSearchChecker = $this->createMock(AdvancedSearchChecker::class); + $featureFlagChecker = $this->createMock(FeatureFlagCheckerInterface::class); + $featureFlagPropertiesMapping = $this->createMock(FeatureFlagPropertiesMapping::class); + + $featureFlagPropertiesMapping + ->method('getAllProperties') + ->willReturn([]); + $this->subject = new AdvancedSearchSettingsService( $this->classMetadataSearcher, $this->defaultSearchSettingsService, - $this->advancedSearchChecker + $this->advancedSearchChecker, + $featureFlagChecker, + $featureFlagPropertiesMapping ); } diff --git a/tests/Unit/Metadata/Service/ClassMetadataSearcherTest.php b/tests/Unit/Metadata/Service/ClassMetadataSearcherTest.php index 2a359fe7..b04e13da 100644 --- a/tests/Unit/Metadata/Service/ClassMetadataSearcherTest.php +++ b/tests/Unit/Metadata/Service/ClassMetadataSearcherTest.php @@ -27,6 +27,9 @@ use oat\generis\test\ServiceManagerMockTrait; use oat\oatbox\log\LoggerService; use oat\tao\model\AdvancedSearch\AdvancedSearchChecker; +use oat\tao\model\featureFlag\FeatureFlagChecker; +use oat\tao\model\featureFlag\FeatureFlagCheckerInterface; +use oat\tao\model\featureFlag\Service\FeatureFlagPropertiesMapping; use oat\tao\model\Lists\Business\Domain\ClassCollection; use oat\tao\model\Lists\Business\Domain\ClassMetadataSearchRequest; use oat\tao\model\Lists\Business\Domain\MetadataCollection; @@ -74,6 +77,11 @@ public function setUp(): void ->method('getAdvancedSearch') ->willReturn($this->elasticSearch); + $featureFlagPropertiesMapping = $this->createMock(FeatureFlagPropertiesMapping::class); + $featureFlagPropertiesMapping + ->method('getAllProperties') + ->willReturn([]); + $this->subject = new ClassMetadataSearcher(); $this->subject->setServiceManager( $this->getServiceManagerMock( @@ -82,7 +90,9 @@ public function setUp(): void AdvancedSearchChecker::class => $this->advancedSearchChecker, SearchProxy::SERVICE_ID => $this->search, LoggerService::SERVICE_ID => $this->createMock(LoggerService::class), - Ontology::SERVICE_ID => $this->ontology + Ontology::SERVICE_ID => $this->ontology, + FeatureFlagChecker::class => $this->createMock(FeatureFlagCheckerInterface::class), + FeatureFlagPropertiesMapping::class => $featureFlagPropertiesMapping, ] ) ); diff --git a/tests/Unit/SearchEngine/Driver/Elasticsearch/QueryBuilderTest.php b/tests/Unit/SearchEngine/Driver/Elasticsearch/QueryBuilderTest.php index 9fdd9d7c..ac16f78f 100644 --- a/tests/Unit/SearchEngine/Driver/Elasticsearch/QueryBuilderTest.php +++ b/tests/Unit/SearchEngine/Driver/Elasticsearch/QueryBuilderTest.php @@ -160,8 +160,8 @@ public function queryResultsWithAccessControl(): array '\\"test\\" OR TextArea_custom_field:\\"test\\" OR ' . 'TextBox_custom_field:\\"test\\" OR ComboBox_custom_field:\\"test\\" ' . 'OR CheckBox_custom_field:\\"test\\" OR RadioBox_custom_field:\\"test\\" ' . - 'OR SearchTextBox_custom_field:\\"test\\" OR SearchDropdown_custom_field:\\"test\\")' . - ' AND (read_access:(\\"https:\\/\\/tao.docker.localhost\\/' . + 'OR SearchTextBox_custom_field:\\"test\\" OR SearchDropdown_custom_field:\\"test\\" ' . + 'OR Readonly_custom_field:\\"test\\") AND (read_access:(\\"https:\\/\\/tao.docker.localhost\\/' . 'ontologies\\/tao.rdf#i5f64514f1c36110793759fc28c0105b\\" OR \\"http:\\/\\/www.tao.lu\\/Ontologies\\/' . 'TAOItem.rdf#BackOfficeRole\\" OR ' . '\\"http:\\/\\/www.tao.lu\\/Ontologies\\/TAOItem.rdf#ItemsManagerRole\\"))"}},' . @@ -174,8 +174,8 @@ public function queryResultsWithAccessControl(): array '(HTMLArea_custom_field:\\"test\\" OR TextArea_custom_field:\\"test\\" OR ' . 'TextBox_custom_field:\\"test\\" OR ComboBox_custom_field:\\"test\\"' . ' OR CheckBox_custom_field:\\"test\\" OR RadioBox_custom_field:\\"test\\" ' . - 'OR SearchTextBox_custom_field:\\"test\\" OR SearchDropdown_custom_field:\\' . - '"test\\") AND (read_access:(\\"https:\\/\\/tao.docker.localhost\\/' . + 'OR SearchTextBox_custom_field:\\"test\\" OR SearchDropdown_custom_field:\\"test\\" ' . + 'OR Readonly_custom_field:\\"test\\") AND (read_access:(\\"https:\\/\\/tao.docker.localhost\\/' . 'ontologies\\/tao.rdf#i5f64514f1c36110793759fc28c0105b\\" OR ' . '\\"http:\\/\\/www.tao.lu\\/Ontologies\\/TAOItem.rdf#BackOfficeRole\\" OR ' . '\\"http:\\/\\/www.tao.lu\\/Ontologies\\/TAOItem.rdf#ItemsManagerRole\\"))"}},' . @@ -191,8 +191,8 @@ public function queryResultsWithAccessControl(): array 'field:\"test\" OR ComboBox_custom field:\"test\" ' . 'OR CheckBox_custom field:\"test\" OR RadioBox_custom ' . 'field:\"test\" OR SearchTextBox_custom field:\"test\" ' . - 'OR SearchDropdown_custom field:\"test\") AND ' . - '(read_access:(\"https:\/\/tao.docker.localhost\/ontologies\/tao.rdf' . + 'OR SearchDropdown_custom field:\"test\" OR Readonly_custom field:\\"test\\")' . + ' AND (read_access:(\"https:\/\/tao.docker.localhost\/ontologies\/tao.rdf' . '#i5f64514f1c36110793759fc28c0105b\" OR ' . '\"http:\/\/www.tao.lu\/Ontologies\/TAOItem.rdf#BackOfficeRole\" ' . 'OR \"http:\/\/www.tao.lu\/Ontologies\/TAOItem.rdf#ItemsManagerRole\"))"}},' . @@ -207,7 +207,8 @@ public function queryResultsWithAccessControl(): array 'field:\\"test\\" OR TextBox_custom_field:\\"test\\" OR ' . 'ComboBox_custom_field:\\"test\\" OR CheckBox_custom_field:\\"test\\" OR RadioBox_' . 'custom_field:\\"test\\" OR SearchTextBox_custom_field:\\"test\\" ' . - 'OR SearchDropdown_custom_field:\\"test\\") AND (read_access:(\\"https:\\/' . + 'OR SearchDropdown_custom_field:\\"test\\" OR Readonly_custom_field:\\"test\\")' . + ' AND (read_access:(\\"https:\\/' . '\\/tao.docker.localhost\\/ontologies\\/tao.rdf#i5f64514f1c36110793759fc28c0105b\\"' . ' OR \\"http:\\/\\/www.tao.lu\\/Ontologies\\/TAOItem.rdf#' . 'BackOfficeRole\\" OR \\"http:\\/\\/www.tao.lu\\/Ontologies\\/TAOItem.rdf#ItemsManagerRole\\"))"}}' . @@ -221,7 +222,8 @@ public function queryResultsWithAccessControl(): array '(HTMLArea_custom_field:\"test\" OR TextArea_custom_field:\"test\" OR TextBox_custom_field:\"test\" ' . 'OR ComboBox_custom_field:\"test\" OR CheckBox_custom_field:\"test\" ' . 'OR RadioBox_custom_field:\"test\" ' . - 'OR SearchTextBox_custom_field:\"test\" OR SearchDropdown_custom_field:\"test\") AND (read_access:' . + 'OR SearchTextBox_custom_field:\"test\" OR SearchDropdown_custom_field:\"test\" ' . + 'OR Readonly_custom_field:\"test\") AND (read_access:' . '(\"https:\/\/tao.docker.localhost\/ontologies\/tao.rdf#i5f64514f1c36110793759fc28c0105b\" OR ' . '\"http:\/\/www.tao.lu\/Ontologies\/TAOItem.rdf#BackOfficeRole\" OR ' . '\"http:\/\/www.tao.lu\/Ontologies\/TAOItem.rdf#ItemsManagerRole\"))"}},' . @@ -235,7 +237,8 @@ public function queryResultsWithAccessControl(): array '(HTMLArea_custom_field:\"test\" OR TextArea_custom_field:\"test\" OR TextBox_custom_field:\"test\" ' . 'OR ComboBox_custom_field:\"test\" OR CheckBox_custom_field:\"test\"' . ' OR RadioBox_custom_field:\"test\" ' . - 'OR SearchTextBox_custom_field:\"test\" OR SearchDropdown_custom_field:\"test\") AND (read_access:' . + 'OR SearchTextBox_custom_field:\"test\" OR SearchDropdown_custom_field:\"test\" ' . + 'OR Readonly_custom_field:\"test\") AND (read_access:' . '(\"https:\/\/tao.docker.localhost\/ontologies\/tao.rdf#i5f64514f1c36110793759fc28c0105b\" OR ' . '\"http:\/\/www.tao.lu\/Ontologies\/TAOItem.rdf#BackOfficeRole\" OR ' . '\"http:\/\/www.tao.lu\/Ontologies\/TAOItem.rdf#ItemsManagerRole\"))"}},' . @@ -243,6 +246,67 @@ public function queryResultsWithAccessControl(): array '"missing":"_last","unmapped_type":"long"},"label.raw":{"order":"DESC","missing":"_last",' . '"unmapped_type":"long"}}}' ], + 'Query using OR logic operator to join list field values' => [ + 'label:test AND custom_field:test LOGIC_OR custom_field:test1 ', + '{"query":{"query_string":{"default_operator":"AND","query":"(label:\"test\") AND ' . + '((HTMLArea_custom_field:\"test\" OR TextArea_custom_field:\"test\" OR TextBox_custom_field:\"test\" ' . + 'OR ComboBox_custom_field:\"test\" OR CheckBox_custom_field:\"test\" ' . + 'OR RadioBox_custom_field:\"test\" ' . + 'OR SearchTextBox_custom_field:\"test\" OR SearchDropdown_custom_field:\"test\" ' . + 'OR Readonly_custom_field:\"test\") ' . + 'OR (HTMLArea_custom_field:\"test1\" OR TextArea_custom_field:\"test1\" ' . + 'OR TextBox_custom_field:\"test1\" ' . + 'OR ComboBox_custom_field:\"test1\" OR CheckBox_custom_field:\"test1\"' . + ' OR RadioBox_custom_field:\"test1\" ' . + 'OR SearchTextBox_custom_field:\"test1\" OR SearchDropdown_custom_field:\"test1\" ' . + 'OR Readonly_custom_field:\"test1\")) AND (read_access:' . + '(\"https:\/\/tao.docker.localhost\/ontologies\/tao.rdf#i5f64514f1c36110793759fc28c0105b\" OR ' . + '\"http:\/\/www.tao.lu\/Ontologies\/TAOItem.rdf#BackOfficeRole\" OR ' . + '\"http:\/\/www.tao.lu\/Ontologies\/TAOItem.rdf#ItemsManagerRole\"))"}},"sort":{"_id":' . + '{"order":"DESC","missing":"_last","unmapped_type":"long"},"label.raw":{"order":"DESC","missing"' . + ':"_last","unmapped_type":"long"}}}', + ], + 'Query using AND logic operator to join list field values' => [ + 'label:test AND custom_field:test LOGIC_AND custom_field:test1 ', + '{"query":{"query_string":{"default_operator":"AND","query":"(label:\"test\") AND ' . + '((HTMLArea_custom_field:\"test\" OR TextArea_custom_field:\"test\" OR TextBox_custom_field:\"test\" ' . + 'OR ComboBox_custom_field:\"test\" OR CheckBox_custom_field:\"test\" ' . + 'OR RadioBox_custom_field:\"test\" ' . + 'OR SearchTextBox_custom_field:\"test\" OR SearchDropdown_custom_field:\"test\" ' . + 'OR Readonly_custom_field:\"test\") ' . + 'AND (HTMLArea_custom_field:\"test1\" OR TextArea_custom_field:\"test1\" ' . + 'OR TextBox_custom_field:\"test1\" ' . + 'OR ComboBox_custom_field:\"test1\" OR CheckBox_custom_field:\"test1\"' . + ' OR RadioBox_custom_field:\"test1\" ' . + 'OR SearchTextBox_custom_field:\"test1\" OR SearchDropdown_custom_field:\"test1\" ' . + 'OR Readonly_custom_field:\"test1\")) AND (read_access:' . + '(\"https:\/\/tao.docker.localhost\/ontologies\/tao.rdf#i5f64514f1c36110793759fc28c0105b\" OR ' . + '\"http:\/\/www.tao.lu\/Ontologies\/TAOItem.rdf#BackOfficeRole\" OR ' . + '\"http:\/\/www.tao.lu\/Ontologies\/TAOItem.rdf#ItemsManagerRole\"))"}},"sort":{"_id":' . + '{"order":"DESC","missing":"_last","unmapped_type":"long"},"label.raw":{"order":"DESC","missing"' . + ':"_last","unmapped_type":"long"}}}', + ], + 'Query using NOT logic operator to join list field values' => [ + 'label:test AND custom_field:test LOGIC_NOT custom_field:test1 ', + '{"query":{"query_string":{"default_operator":"AND","query":"(label:\"test\") AND ' . + 'NOT ((HTMLArea_custom_field:\"test\" OR TextArea_custom_field:\"test\" ' . + 'OR TextBox_custom_field:\"test\" ' . + 'OR ComboBox_custom_field:\"test\" OR CheckBox_custom_field:\"test\" ' . + 'OR RadioBox_custom_field:\"test\" ' . + 'OR SearchTextBox_custom_field:\"test\" ' . + 'OR SearchDropdown_custom_field:\"test\" OR Readonly_custom_field:\"test\") ' . + 'OR (HTMLArea_custom_field:\"test1\" OR TextArea_custom_field:\"test1\" ' . + 'OR TextBox_custom_field:\"test1\" ' . + 'OR ComboBox_custom_field:\"test1\" OR CheckBox_custom_field:\"test1\"' . + ' OR RadioBox_custom_field:\"test1\" ' . + 'OR SearchTextBox_custom_field:\"test1\" OR SearchDropdown_custom_field:\"test1\" ' . + 'OR Readonly_custom_field:\"test1\")) AND (read_access:' . + '(\"https:\/\/tao.docker.localhost\/ontologies\/tao.rdf#i5f64514f1c36110793759fc28c0105b\" OR ' . + '\"http:\/\/www.tao.lu\/Ontologies\/TAOItem.rdf#BackOfficeRole\" OR ' . + '\"http:\/\/www.tao.lu\/Ontologies\/TAOItem.rdf#ItemsManagerRole\"))"}},"sort":{"_id":' . + '{"order":"DESC","missing":"_last","unmapped_type":"long"},"label.raw":{"order":"DESC","missing"' . + ':"_last","unmapped_type":"long"}}}', + ], 'Query URIs' => [ 'https://test-act.docker.localhost/ontologies/tao.rdf#i5f200ed20e80a8c259ebe410db7f6a', '{"query":{"query_string":{"default_operator":"AND","query":"(\"https:\/\/test-act.docker.localhost\/' . @@ -335,7 +399,7 @@ public function queryResultsWithoutAccessControl(): array ':\"test\" OR ComboBox_custom_field:\"test\" ' . 'OR CheckBox_custom_field:\"test\" OR RadioBox_custom_field:' . '\"test\" OR SearchTextBox_custom_field:\"test\" ' . - 'OR SearchDropdown_custom_field:\"test\")"}},' . + 'OR SearchDropdown_custom_field:\"test\" OR Readonly_custom_field:\"test\")"}},' . '"sort":{"_id":{"order":"DESC","missing":"_last",' . '"unmapped_type":"long"},"label.raw":{"order":' . '"DESC","missing":"_last","unmapped_type":"long"}}}' @@ -345,8 +409,8 @@ public function queryResultsWithoutAccessControl(): array '{"query":{"query_string":{"default_operator":"AND","query":"(HTMLArea_custom_field:\"test\" OR ' . 'TextArea_custom_field:\"test\" OR TextBox_custom_field:\"test\" OR ComboBox_custom_field:\"test\" ' . 'OR CheckBox_custom_field:\"test\" OR RadioBox_custom_field:' . - '\"test\" OR SearchTextBox_custom_field:\"test\" ' . - 'OR SearchDropdown_custom_field:\"test\")"}},"sort":{"_id":{"order":"DESC","missing":"_last",' . + '\"test\" OR SearchTextBox_custom_field:\"test\" OR SearchDropdown_custom_field:\"test\" ' . + 'OR Readonly_custom_field:\"test\")"}},"sort":{"_id":{"order":"DESC","missing":"_last",' . '"unmapped_type":"long"},"label.raw":{"order":"DESC","missing":"_last","unmapped_type":"long"}}}' ], 'Query custom field (using space)' => [ @@ -355,8 +419,8 @@ public function queryResultsWithoutAccessControl(): array 'field:\"test\" OR TextArea_custom field:\"test\" OR TextBox_custom field:\"test\" ' . 'OR ComboBox_custom field:\"test\" OR CheckBox_custom field:\"test\" OR RadioBox_custom ' . 'field:\"test\" OR SearchTextBox_custom field:\"test\" OR SearchDropdown_custom field:' . - '\"test\")"}},"sort":{"_id":{"order":"DESC","missing":"_last","unmapped_type":"long"},' . - '"label.raw":{"order":"DESC","missing":"_last","unmapped_type":"long"}}}', + '\"test\" OR Readonly_custom field:\"test\")"}},"sort":{"_id":{"order":"DESC","missing":"_last",' . + '"unmapped_type":"long"},"label.raw":{"order":"DESC","missing":"_last","unmapped_type":"long"}}}', ], 'Query logic operator (Uppercase)' => [ 'label:test AND custom_field:test', @@ -364,8 +428,9 @@ public function queryResultsWithoutAccessControl(): array 'AND (HTMLArea_custom_field:\"test\" OR TextArea_custom_field:\"test\" OR ' . 'TextBox_custom_field:\"test\" OR ComboBox_custom_field:\"test\" OR CheckBox_custom_field:' . '\"test\" OR RadioBox_custom_field:\"test\" OR SearchTextBox_custom_field:\"test\" OR ' . - 'SearchDropdown_custom_field:\"test\")"}},"sort":{"_id":{"order":"DESC","missing":"_last"' . - ',"unmapped_type":"long"},"label.raw":{"order":"DESC","missing":"_last","unmapped_type":"long"}}}', + 'SearchDropdown_custom_field:\"test\" OR Readonly_custom_field:\"test\")"}},"sort":{"_id":{"order":' . + '"DESC","missing":"_last","unmapped_type":"long"},"label.raw":{"order":"DESC","missing":"_last",' . + '"unmapped_type":"long"}}}', ], 'Query logic operator (Lowercase)' => [ 'label:test and custom_field:test', @@ -373,8 +438,9 @@ public function queryResultsWithoutAccessControl(): array '(HTMLArea_custom_field:\"test\" OR TextArea_custom_field:\"test\" OR TextBox_custom_field:' . '\"test\" OR ComboBox_custom_field:\"test\" OR CheckBox_custom_field:\"test\" OR ' . 'RadioBox_custom_field:\"test\" OR SearchTextBox_custom_field:\"test\" OR ' . - 'SearchDropdown_custom_field:\"test\")"}},"sort":{"_id":{"order":"DESC","missing":"_last",' . - '"unmapped_type":"long"},"label.raw":{"order":"DESC","missing":"_last","unmapped_type":"long"}}}', + 'SearchDropdown_custom_field:\"test\" OR Readonly_custom_field:\"test\")"}},"sort":{"_id":{"order":' . + '"DESC","missing":"_last","unmapped_type":"long"},"label.raw":{"order":"DESC","missing":"_last",' . + '"unmapped_type":"long"}}}', ], 'Query logic operator (Mixed)' => [ 'label:test aNd custom_field:test', @@ -382,7 +448,57 @@ public function queryResultsWithoutAccessControl(): array '(HTMLArea_custom_field:\"test\" OR TextArea_custom_field:\"test\" OR TextBox_custom_field:\"test\" ' . 'OR ComboBox_custom_field:\"test\" OR CheckBox_custom_field:\"test\"' . ' OR RadioBox_custom_field:\"test\" ' . - 'OR SearchTextBox_custom_field:\"test\" OR SearchDropdown_custom_field:\"test\")"}},"sort":{"_id":' . + 'OR SearchTextBox_custom_field:\"test\" OR SearchDropdown_custom_field:\"test\" ' . + 'OR Readonly_custom_field:\"test\")"}},"sort":{"_id":' . + '{"order":"DESC","missing":"_last","unmapped_type":"long"},"label.raw":{"order":"DESC","missing"' . + ':"_last","unmapped_type":"long"}}}', + ], + 'Query using OR logic operator to join list field values' => [ + 'label:test AND custom_field:test LOGIC_OR custom_field:test1 ', + '{"query":{"query_string":{"default_operator":"AND","query":"(label:\"test\") AND ' . + '((HTMLArea_custom_field:\"test\" OR TextArea_custom_field:\"test\" OR TextBox_custom_field:\"test\" ' . + 'OR ComboBox_custom_field:\"test\" OR CheckBox_custom_field:\"test\" ' . + 'OR RadioBox_custom_field:\"test\" ' . + 'OR SearchTextBox_custom_field:\"test\" OR SearchDropdown_custom_field:\"test\" ' . + 'OR Readonly_custom_field:\"test\") OR (HTMLArea_custom_field:\"test1\" ' . + 'OR TextArea_custom_field:\"test1\" OR TextBox_custom_field:\"test1\" ' . + 'OR ComboBox_custom_field:\"test1\" OR CheckBox_custom_field:\"test1\"' . + ' OR RadioBox_custom_field:\"test1\" OR SearchTextBox_custom_field:\"test1\" ' . + 'OR SearchDropdown_custom_field:\"test1\" OR Readonly_custom_field:\"test1\"))"}},"sort":{"_id":' . + '{"order":"DESC","missing":"_last","unmapped_type":"long"},"label.raw":{"order":"DESC","missing"' . + ':"_last","unmapped_type":"long"}}}', + ], + 'Query using AND logic operator to join list field values' => [ + 'label:test AND custom_field:test LOGIC_AND custom_field:test1 ', + '{"query":{"query_string":{"default_operator":"AND","query":"(label:\"test\") AND ' . + '((HTMLArea_custom_field:\"test\" OR TextArea_custom_field:\"test\" OR TextBox_custom_field:\"test\" ' . + 'OR ComboBox_custom_field:\"test\" OR CheckBox_custom_field:\"test\" ' . + 'OR RadioBox_custom_field:\"test\" ' . + 'OR SearchTextBox_custom_field:\"test\" OR SearchDropdown_custom_field:\"test\" ' . + 'OR Readonly_custom_field:\"test\") ' . + 'AND (HTMLArea_custom_field:\"test1\" OR TextArea_custom_field:\"test1\" ' . + 'OR TextBox_custom_field:\"test1\" ' . + 'OR ComboBox_custom_field:\"test1\" OR CheckBox_custom_field:\"test1\"' . + ' OR RadioBox_custom_field:\"test1\" ' . + 'OR SearchTextBox_custom_field:\"test1\" OR SearchDropdown_custom_field:\"test1\" ' . + 'OR Readonly_custom_field:\"test1\"))"}},"sort":{"_id":' . + '{"order":"DESC","missing":"_last","unmapped_type":"long"},"label.raw":{"order":"DESC","missing"' . + ':"_last","unmapped_type":"long"}}}', + ], + 'Query using NOT logic operator to join list field values' => [ + 'label:test AND custom_field:test LOGIC_NOT custom_field:test1 ', + '{"query":{"query_string":{"default_operator":"AND","query":"(label:\"test\") AND ' . + 'NOT ((HTMLArea_custom_field:\"test\" OR TextArea_custom_field:\"test\" ' . + 'OR TextBox_custom_field:\"test\" ' . + 'OR ComboBox_custom_field:\"test\" OR CheckBox_custom_field:\"test\" ' . + 'OR RadioBox_custom_field:\"test\" ' . + 'OR SearchTextBox_custom_field:\"test\" OR SearchDropdown_custom_field:\"test\" ' . + 'OR Readonly_custom_field:\"test\") OR (HTMLArea_custom_field:\"test1\" ' . + 'OR TextArea_custom_field:\"test1\" OR TextBox_custom_field:\"test1\" ' . + 'OR ComboBox_custom_field:\"test1\" OR CheckBox_custom_field:\"test1\"' . + ' OR RadioBox_custom_field:\"test1\" ' . + 'OR SearchTextBox_custom_field:\"test1\" OR SearchDropdown_custom_field:\"test1\" ' . + 'OR Readonly_custom_field:\"test1\"))"}},"sort":{"_id":' . '{"order":"DESC","missing":"_last","unmapped_type":"long"},"label.raw":{"order":"DESC","missing"' . ':"_last","unmapped_type":"long"}}}', ],