diff --git a/lib/Alchemy/Phrasea/SearchEngine/Elastic/ElasticSearchEngine.php b/lib/Alchemy/Phrasea/SearchEngine/Elastic/ElasticSearchEngine.php index 8d041af09f..4176f9fdde 100644 --- a/lib/Alchemy/Phrasea/SearchEngine/Elastic/ElasticSearchEngine.php +++ b/lib/Alchemy/Phrasea/SearchEngine/Elastic/ElasticSearchEngine.php @@ -16,6 +16,7 @@ use Alchemy\Phrasea\SearchEngine\Elastic\Indexer\RecordIndexer; use Alchemy\Phrasea\SearchEngine\Elastic\Indexer\TermIndexer; use Alchemy\Phrasea\SearchEngine\Elastic\RecordHelper; use Alchemy\Phrasea\SearchEngine\Elastic\Search\FacetsResponse; +use Alchemy\Phrasea\SearchEngine\Elastic\Search\QueryCompiler; use Alchemy\Phrasea\SearchEngine\Elastic\Search\QueryContext; use Alchemy\Phrasea\SearchEngine\Elastic\Structure\Structure; use Alchemy\Phrasea\SearchEngine\SearchEngineInterface; @@ -247,7 +248,9 @@ class ElasticSearchEngine implements SearchEngineInterface $options = $options ?: new SearchEngineOptions(); $context = $this->createQueryContext($options); - $recordQuery = $this->app['query_compiler']->compile($string, $context); + /** @var QueryCompiler $query_compiler */ + $query_compiler = $this->app['query_compiler']; + $recordQuery = $query_compiler->compile($string, $context); $params = $this->createRecordQueryParams($recordQuery, $options, null); @@ -276,7 +279,7 @@ class ElasticSearchEngine implements SearchEngineInterface /** @var FacetsResponse $facets */ $facets = $this->facetsResponseFactory->__invoke($res); - $query['ast'] = $this->app['query_compiler']->parse($string)->dump(); + $query['ast'] = $query_compiler->parse($string)->dump(); $query['query_main'] = $recordQuery; $query['query'] = $params['body']; $query['query_string'] = json_encode($params['body']); @@ -306,18 +309,43 @@ class ElasticSearchEngine implements SearchEngineInterface $this->locales, $this->app['locale'] ); + + return $queryContext; } + /** + * Returns an array of allowed collection base_id indexed by field name. + * + * [ + * "FieldName" => [1, 4, 5], + * "OtherFieldName" => [4], + * ] + * + * @param SearchEngineOptions $options + * @return array + */ private function getAllowedPrivateFields(SearchEngineOptions $options) { - $collections = $options->getBusinessFieldsOn(); - $private_fields = $this->structure->getPrivateFields(); - $allowed = array(); - // TODO Build a map with the collections allowed for each private field - // [ - // "FieldName" => [1, 4, 5], - // "OtherFieldName" => [4], - // ] + $fields = array_keys($this->structure->getPrivateFields()); + + $allowed = array_fill_keys($fields, []); + foreach ($options->getDataboxes() as $databox) { + $databoxFields = $databox->get_meta_structure(); + foreach ($fields as $field) { + if ($databoxFields->get_element_by_name($field)) { + $allowed[$field] += $databox->get_collection_unique_ids(); + } + } + } + + $businessCollections = array_map(function (\collection $collection) { + return $collection->get_base_id(); + }, $options->getBusinessFieldsOn()); + + // Remove collections base_id which access is restricted. + foreach ($allowed as $name => &$collections) { + $collections = array_diff($collections, $businessCollections); + } return $allowed; } diff --git a/lib/Alchemy/Phrasea/SearchEngine/SearchEngineOptions.php b/lib/Alchemy/Phrasea/SearchEngine/SearchEngineOptions.php index f9bdaf1a58..26b3c21cf9 100644 --- a/lib/Alchemy/Phrasea/SearchEngine/SearchEngineOptions.php +++ b/lib/Alchemy/Phrasea/SearchEngine/SearchEngineOptions.php @@ -39,6 +39,8 @@ class SearchEngineOptions protected $search_type = 0; /** @var \collection[] */ protected $collections = []; + /** @var null|\databox[] */ + private $databoxes; /** @var \databox_field[] */ protected $fields = []; protected $status = []; @@ -217,6 +219,8 @@ class SearchEngineOptions public function onCollections(array $collections) { $this->collections = $collections; + // Defer databox retrieval + $this->databoxes = null; return $this; } @@ -580,17 +584,10 @@ class SearchEngineOptions /** @var \collection[] $bas */ $bas = array_filter($bas, $filter); - /** @var \databox[] $databoxes */ - $databoxes = []; - - foreach ($bas as $collection) { - if (!isset($databoxes[$collection->get_sbas_id()])) { - $databoxes[$collection->get_sbas_id()] = $collection->get_databox(); - } - } + $options->onCollections($bas); if ($isAuthenticated && $acl->has_right('modifyrecord')) { - $bf = array_filter($bas, function (\collection $collection) use ($app, $acl) { + $bf = array_filter($bas, function (\collection $collection) use ($acl) { return $acl->has_right_on_base($collection->get_base_id(), 'canmodifrecord'); }); @@ -601,7 +598,7 @@ class SearchEngineOptions $fields = is_array($request->get('fields')) ? $request->get('fields') : []; if (empty($fields)) { // Select all fields (business included) - foreach ($databoxes as $databox) { + foreach ($options->getDataboxes() as $databox) { foreach ($databox->get_meta_structure() as $field) { $fields[] = $field->get_name(); } @@ -610,7 +607,7 @@ class SearchEngineOptions } $databoxFields = []; - + $databoxes = $options->getDataboxes(); foreach ($databoxes as $databox) { $metaStructure = $databox->get_meta_structure(); foreach ($fields as $field) { @@ -628,8 +625,6 @@ class SearchEngineOptions $options->setFields($databoxFields); $options->setStatus($status); - $options->onCollections($bas); - $options->setSearchType($request->get('search_type')); $options->setRecordType($request->get('record_type')); diff --git a/lib/classes/databox.php b/lib/classes/databox.php index 80ba00cd1d..fa6d8d5c0a 100644 --- a/lib/classes/databox.php +++ b/lib/classes/databox.php @@ -229,6 +229,12 @@ class databox extends base public function get_collection_unique_ids() { + static $base_ids; + + if (isset($base_ids)) { + return $base_ids; + } + $conn = $this->app['phraseanet.appbox']->get_connection(); $sql = "SELECT b.base_id FROM bas b WHERE b.sbas_id = :sbas_id AND b.active = '1'