Пример #1
0
 private function getSearchedFields(SearchEngineOptions $options)
 {
     $fields = [];
     foreach ($options->getFields() as $field) {
         $fields[] = $field->get_name();
     }
     return $fields;
 }
Пример #2
0
 public function testRouteCaptionSearchEngine()
 {
     $route_base = '/prod/tooltip/caption/' . self::$DI['record_1']->get_sbas_id() . '/' . self::$DI['record_1']->get_record_id() . '/%s/';
     $routes = [sprintf($route_base, 'answer'), sprintf($route_base, 'lazaret'), sprintf($route_base, 'preview'), sprintf($route_base, 'basket'), sprintf($route_base, 'overview')];
     foreach ($routes as $route) {
         $option = new SearchEngineOptions();
         $crawler = self::$DI['client']->request('POST', $route, ['options_serial' => $option->serialize()]);
         $this->assertTrue(self::$DI['client']->getResponse()->isOk());
     }
 }
Пример #3
0
 /**
  * @covers Alchemy\Phrasea\Controller\Prod\Query::queryAnswerTrain
  */
 public function testQueryAnswerTrain()
 {
     $app = $this->mockElasticsearchResult(self::$DI['record_2']);
     $this->authenticate($app);
     $options = new SearchEngineOptions();
     $options->onCollections($app->getAclForUser($app->getAuthenticatedUser())->get_granted_base());
     $serializedOptions = $options->serialize();
     $client = $this->getClient();
     $client->request('POST', '/prod/query/answer-train/', ['options_serial' => $serializedOptions, 'pos' => 0, 'query' => '']);
     $response = $client->getResponse();
     $this->assertTrue($response->isOk());
     $datas = (array) json_decode($response->getContent());
     $this->assertArrayHasKey('current', $datas);
     unset($response, $datas);
 }
Пример #4
0
 /**
  * Get record detailed view
  *
  * @param Application $app
  * @param Request     $request
  *
  * @return JsonResponse
  */
 public function getRecord(Application $app, Request $request)
 {
     if (!$request->isXmlHttpRequest()) {
         $app->abort(400);
     }
     $searchEngine = $options = null;
     $train = '';
     if ('' === ($env = strtoupper($request->get('env', '')))) {
         $app->abort(400, '`env` parameter is missing');
     }
     // Use $request->get as HTTP method can be POST or GET
     if ('RESULT' == ($env = strtoupper($request->get('env', '')))) {
         try {
             $options = SearchEngineOptions::hydrate($app, $request->get('options_serial'));
             $searchEngine = $app['phraseanet.SE'];
         } catch (\Exception $e) {
             $app->abort(400, 'Search-engine options are not valid or missing');
         }
     }
     $pos = (int) $request->get('pos', 0);
     $query = $request->get('query', '');
     $reloadTrain = !!$request->get('roll', false);
     $record = new \record_preview($app, $env, $pos < 0 ? 0 : $pos, $request->get('cont', ''), $searchEngine, $query, $options);
     if ($record->is_from_reg()) {
         $train = $app['twig']->render('prod/preview/reg_train.html.twig', ['record' => $record]);
     }
     if ($record->is_from_basket() && $reloadTrain) {
         $train = $app['twig']->render('prod/preview/basket_train.html.twig', ['record' => $record]);
     }
     if ($record->is_from_feed()) {
         $train = $app['twig']->render('prod/preview/feed_train.html.twig', ['record' => $record]);
     }
     return $app->json(["desc" => $app['twig']->render('prod/preview/caption.html.twig', ['record' => $record, 'highlight' => $query, 'searchEngine' => $searchEngine, 'searchOptions' => $options]), "html_preview" => $app['twig']->render('common/preview.html.twig', ['record' => $record]), "others" => $app['twig']->render('prod/preview/appears_in.html.twig', ['parents' => $record->get_grouping_parents(), 'baskets' => $record->get_container_baskets($app['EM'], $app['authentication']->getUser())]), "current" => $train, "history" => $app['twig']->render('prod/preview/short_history.html.twig', ['record' => $record]), "popularity" => $app['twig']->render('prod/preview/popularity.html.twig', ['record' => $record]), "tools" => $app['twig']->render('prod/preview/tools.html.twig', ['record' => $record]), "pos" => $record->get_number(), "title" => str_replace(['[[em]]', '[[/em]]'], ['<em>', '</em>'], $record->get_title($query, $searchEngine))]);
 }
Пример #5
0
 /**
  * @covers Alchemy\Phrasea\Controller\Prod\Query::queryAnswerTrain
  */
 public function testQueryAnswerTrain()
 {
     if (!extension_loaded('phrasea2')) {
         $this->markTestSkipped('Phrasea2 is required for this test');
     }
     $this->authenticate(self::$DI['app']);
     self::$DI['record_2'];
     $options = new SearchEngineOptions();
     $options->onCollections(self::$DI['app']['acl']->get(self::$DI['app']['authentication']->getUser())->get_granted_base());
     $serializedOptions = $options->serialize();
     self::$DI['client']->request('POST', '/prod/query/answer-train/', ['options_serial' => $serializedOptions, 'pos' => 0, 'query' => '']);
     $response = self::$DI['client']->getResponse();
     $this->assertTrue($response->isOk());
     $datas = (array) json_decode($response->getContent());
     $this->assertArrayHasKey('current', $datas);
     unset($response, $datas);
 }
 /**
  * @covers Alchemy\Phrasea\SearchEngine\SearchEngineOptions::fromRequest
  */
 public function testFromRequestEmptyUnauthenticated()
 {
     $options = SearchEngineOptions::fromRequest(self::$DI['app'], new Request());
     $this->assertEquals([], $options->getCollections());
     $this->assertEquals([], $options->getFields());
     $this->assertEquals(null, $options->getRecordType());
     $this->assertEquals('0', $options->getSearchType());
     $this->assertEquals(null, $options->getMaxDate());
     $this->assertEquals(null, $options->getMinDate());
     $this->assertEquals([], $options->getDateFields());
     $this->assertEquals('desc', $options->getSortOrder());
     $this->assertEquals(null, $options->getSortBy());
     $this->assertEquals(false, $options->isStemmed());
 }
Пример #7
0
 public function displayCaption(Application $app, $sbas_id, $record_id, $context)
 {
     $number = (int) $app['request']->get('number');
     $record = new \record_adapter($app, $sbas_id, $record_id, $number);
     $search_engine = $search_engine_options = null;
     if ($context == 'answer') {
         try {
             $search_engine_options = SearchEngineOptions::hydrate($app, $app['request']->request->get('options_serial'));
             $search_engine = $app['phraseanet.SE'];
         } catch (\Exception $e) {
             $search_engine = null;
         }
     }
     return $app['twig']->render('prod/Tooltip/Caption.html.twig', ['record' => $record, 'view' => $context, 'highlight' => $app['request']->request->get('query'), 'searchEngine' => $search_engine, 'searchOptions' => $search_engine_options]);
 }
Пример #8
0
 /**
  * Get a preview answer train
  *
  * @param  Application  $app
  * @param  Request      $request
  * @return JsonResponse
  */
 public function queryAnswerTrain(Application $app, Request $request)
 {
     if (null === ($optionsSerial = $request->request->get('options_serial'))) {
         $app->abort(400, 'Search engine options are missing');
     }
     try {
         $options = SearchEngineOptions::hydrate($app, $optionsSerial);
     } catch (\Exception $e) {
         $app->abort(400, 'Provided search engine options are not valid');
     }
     $pos = (int) $request->request->get('pos', 0);
     $query = $request->request->get('query', '');
     $record = new \record_preview($app, 'RESULT', $pos, '', $app['phraseanet.SE'], $query, $options);
     return $app->json(['current' => $app['twig']->render('prod/preview/result_train.html.twig', ['records' => $record->get_train($pos, $query, $app['phraseanet.SE']), 'selected' => $pos])]);
 }
 private function getQueryIndex($query, SearchEngineOptions $options)
 {
     $index = '*';
     $index_keys = [];
     foreach ($options->getDataboxes() as $databox) {
         $index_keys[] = $this->CRCdatabox($databox);
     }
     if (count($index_keys) > 0) {
         if ($options->getFields() || $options->getBusinessFieldsOn()) {
             if ($query !== '' && $options->isStemmed() && $options->getLocale()) {
                 $index = 'metadatas' . implode('_stemmed_' . $options->getLocale() . ', metadatas', $index_keys) . '_stemmed_' . $options->getLocale();
                 $index .= ', metas_realtime_stemmed_' . $options->getLocale() . '_' . implode(', metas_realtime_stemmed_' . $options->getLocale() . '_', $index_keys);
             } else {
                 $index = 'metadatas' . implode(',metadatas', $index_keys);
                 $index .= ', metas_realtime' . implode(', metas_realtime', $index_keys);
             }
         } else {
             if ($query !== '' && $options->isStemmed() && $options->getLocale()) {
                 $index = 'documents' . implode('_stemmed_' . $options->getLocale() . ', documents', $index_keys) . '_stemmed_' . $options->getLocale();
                 $index .= ', docs_realtime_stemmed_' . $options->getLocale() . '_' . implode(', docs_realtime_stemmed_' . $options->getLocale() . '_', $index_keys);
             } else {
                 $index = 'documents' . implode(', documents', $index_keys);
                 $index .= ', docs_realtime' . implode(', docs_realtime', $index_keys);
             }
         }
     }
     return $index;
 }
Пример #10
0
 private function buildACLsFilters(array $aclRules, SearchEngineOptions $options)
 {
     $filters = [];
     $collections = $options->getCollections();
     $collectionsWoRules = [];
     $collectionsWoRules['terms']['base_id'] = [];
     foreach ($aclRules as $baseId => $flagsRules) {
         if (!array_key_exists($baseId, $collections)) {
             // no need to add a filter if the collection is not searched
             continue;
         }
         $ruleFilter = $baseFilter = [];
         // filter on base
         $baseFilter['term']['base_id'] = $baseId;
         $ruleFilter['bool']['must'][] = $baseFilter;
         // filter by flags
         foreach ($flagsRules as $flagName => $flagRule) {
             // only add filter if one of the status state is not allowed / allowed
             if ($flagRule === self::FLAG_ALLOW_BOTH) {
                 continue;
             }
             $flagFilter = [];
             $flagField = sprintf('flags.%s', $flagName);
             $flagFilter['term'][$flagField] = $flagRule === self::FLAG_SET_ONLY ? true : false;
             $ruleFilter['bool']['must'][] = $flagFilter;
         }
         if (count($ruleFilter['bool']['must']) > 1) {
             // some rules found, add the filter
             $filters[] = $ruleFilter;
         } else {
             // no rules for this collection, add it to the 'simple' list
             $collectionsWoRules['terms']['base_id'][] = $baseId;
         }
     }
     if (count($collectionsWoRules['terms']['base_id']) > 0) {
         // collections w/o rules : add a simple list ?
         if (count($filters) > 0) {
             // no need to add a big 'should' filter only on collections
             $filters[] = $collectionsWoRules;
         }
     }
     if (count($filters) > 0) {
         return ['bool' => ['should' => $filters]];
     } else {
         return [];
     }
 }
Пример #11
0
 /**
  * Get a preview answer train
  *
  * @param  Request $request
  * @return Response
  */
 public function queryAnswerTrain(Request $request)
 {
     if (null === ($optionsSerial = $request->get('options_serial'))) {
         $this->app->abort(400, 'Search engine options are missing');
     }
     try {
         $options = SearchEngineOptions::hydrate($this->app, $optionsSerial);
     } catch (\Exception $e) {
         $this->app->abort(400, 'Provided search engine options are not valid');
     }
     $pos = (int) $request->request->get('pos', 0);
     $query = $request->request->get('query', '');
     $record = new \record_preview($this->app, 'RESULT', $pos, '', $this->getSearchEngine(), $query, $options);
     $index = $pos - 3 < 0 ? 0 : $pos - 3;
     return $this->app->json(['current' => $this->render('prod/preview/result_train.html.twig', ['records' => $record->get_train(), 'index' => $index, 'selected' => $pos])]);
 }
Пример #12
0
 private function createSortQueryParams(SearchEngineOptions $options)
 {
     $sort = [];
     if ($options->getSortBy() === 'score') {
         $sort['_score'] = $options->getSortOrder();
     }
     $sort['created_on'] = $options->getSortOrder();
     return $sort;
 }
 protected function getDefaultOptions()
 {
     $appbox = self::$DI['app']['phraseanet.appbox'];
     foreach ($appbox->get_databoxes() as $databox) {
         break;
     }
     $options = new SearchEngineOptions();
     $options->onCollections($databox->get_collections());
     return $options;
 }
Пример #14
0
 /**
  * Queries database to fetch documents
  *
  * @param  Application $app
  * @param  Request     $request
  * @return Response
  */
 public function query(Application $app, Request $request)
 {
     $query = $this->buildQueryFromRequest($request);
     $displayMode = explode('X', $request->request->get('mod', '3X6'));
     if (count($displayMode) === 1) {
         $modRow = (int) $displayMode[0];
         $modCol = 1;
     } else {
         $modRow = (int) $displayMode[0];
         $modCol = (int) $displayMode[1];
     }
     $perPage = $modCol * $modRow;
     $options = SearchEngineOptions::fromRequest($app, $request);
     $currentPage = (int) $request->request->get('pag', 0);
     if ($currentPage < 1) {
         $app['phraseanet.SE']->resetCache();
         $currentPage = 1;
     }
     $result = $app['phraseanet.SE']->query($query, ($currentPage - 1) * $perPage, $perPage, $options);
     $userQuery = new UserQuery();
     $userQuery->setUser($app['authentication']->getUser());
     $userQuery->setQuery($query);
     $app['EM']->persist($userQuery);
     $app['EM']->flush();
     if ($app['settings']->getUserSetting($app['authentication']->getUser(), 'start_page') === 'LAST_QUERY') {
         $app['manipulator.user']->setUserSetting($app['authentication']->getUser(), 'start_page_query', $query);
     }
     foreach ($options->getDataboxes() as $databox) {
         $colls = array_map(function (\collection $collection) {
             return $collection->get_coll_id();
         }, array_filter($options->getCollections(), function (\collection $collection) use($databox) {
             return $collection->get_databox()->get_sbas_id() == $databox->get_sbas_id();
         }));
         $app['phraseanet.SE.logger']->log($databox, $result->getQuery(), $result->getTotal(), $colls);
     }
     $searchData = $result->getResults();
     if (count($searchData) === 0) {
         return new Response($app['twig']->render("client/help.html.twig"));
     }
     $resultData = [];
     foreach ($searchData as $record) {
         try {
             $record->get_subdef('document');
             $lightInfo = $app['twig']->render('common/technical_datas.html.twig', ['record' => $record]);
         } catch (\Exception $e) {
             $lightInfo = '';
         }
         $caption = $app['twig']->render('common/caption.html.twig', ['view' => 'answer', 'record' => $record]);
         $docType = $record->get_type();
         $isVideo = $docType == 'video';
         $isAudio = $docType == 'audio';
         $isImage = $docType == 'image';
         $isDocument = $docType == 'document';
         if (!$isVideo && !$isAudio) {
             $isImage = true;
         }
         $canDownload = $app['acl']->get($app['authentication']->getUser())->has_right_on_base($record->get_base_id(), 'candwnldpreview') || $app['acl']->get($app['authentication']->getUser())->has_right_on_base($record->get_base_id(), 'candwnldhd') || $app['acl']->get($app['authentication']->getUser())->has_right_on_base($record->get_base_id(), 'cancmd');
         try {
             $previewExists = $record->get_preview()->is_physically_present();
         } catch (\Exception $e) {
             $previewExists = false;
         }
         $resultData[] = ['record' => $record, 'mini_logo' => \collection::getLogo($record->get_base_id(), $app), 'preview_exists' => $previewExists, 'light_info' => $lightInfo, 'caption' => $caption, 'is_video' => $isVideo, 'is_audio' => $isAudio, 'is_image' => $isImage, 'is_document' => $isDocument, 'can_download' => $canDownload, 'can_add_to_basket' => $app['acl']->get($app['authentication']->getUser())->has_right_on_base($record->get_base_id(), 'canputinalbum')];
     }
     return new Response($app['twig']->render("client/answers.html.twig", ['mod_col' => $modCol, 'mod_row' => $modRow, 'result_data' => $resultData, 'per_page' => $perPage, 'search_engine' => $app['phraseanet.SE'], 'search_engine_option' => $options->serialize(), 'history' => \queries::history($app, $app['authentication']->getUser()->getId()), 'result' => $result, 'proposals' => $currentPage === 1 ? $result->getProposals() : null, 'help' => count($resultData) === 0 ? $this->getHelpStartPage($app) : '']));
 }
Пример #15
0
 /**
  * @covers Alchemy\Phrasea\Controller\Prod\Records::getRecord
  */
 public function testGetRecordDetailResult()
 {
     if (!extension_loaded('phrasea2')) {
         $this->markTestSkipped('Phrasea2 is required for this test');
     }
     $this->authenticate(self::$DI['app']);
     self::$DI['record_1'];
     $options = new SearchEngineOptions();
     $acl = self::$DI['app']['acl']->get(self::$DI['app']['authentication']->getUser());
     $options->onCollections($acl->get_granted_base());
     $serializedOptions = $options->serialize();
     $this->XMLHTTPRequest('POST', '/prod/records/', ['env' => 'RESULT', 'options_serial' => $serializedOptions, 'pos' => 0, 'query' => '']);
     $response = self::$DI['client']->getResponse();
     $data = json_decode($response->getContent(), true);
     $this->assertArrayHasKey('desc', $data);
     $this->assertArrayHasKey('html_preview', $data);
     $this->assertArrayHasKey('current', $data);
     $this->assertArrayHasKey('others', $data);
     $this->assertArrayHasKey('history', $data);
     $this->assertArrayHasKey('popularity', $data);
     $this->assertArrayHasKey('tools', $data);
     $this->assertArrayHasKey('pos', $data);
     $this->assertArrayHasKey('title', $data);
     unset($response, $data);
 }
Пример #16
0
 /**
  * Parses the query for search engine
  *
  * @param  integer       $sbas
  * @param  string        $query
  * @return PhraseaEngine
  */
 private function singleParse($sbas, $query, SearchEngineOptions $options)
 {
     $this->qp[$sbas] = new PhraseaEngineQueryParser($this->app, $options->getLocale());
     $this->qp[$sbas]->debug = false;
     $simple_treeq = $this->qp[$sbas]->parsequery($query);
     $this->qp[$sbas]->priority_opk($simple_treeq);
     $this->qp[$sbas]->distrib_opk($simple_treeq);
     $this->needthesaurus[$sbas] = false;
     $this->indep_treeq[$sbas] = $this->qp[$sbas]->extendThesaurusOnTerms($simple_treeq, true, true, false);
     $this->needthesaurus[$sbas] = $this->qp[$sbas]->containsColonOperator($this->indep_treeq[$sbas]);
     return $this;
 }
Пример #17
0
 /**
  * @covers Alchemy\Phrasea\Controller\Prod\Records::getRecord
  */
 public function testGetRecordDetailResult()
 {
     $app = $this->mockElasticsearchResult(self::$DI['record_1']);
     $this->authenticate($app);
     $options = new SearchEngineOptions();
     $acl = $app->getAclForUser($app->getAuthenticatedUser());
     $options->onCollections($acl->get_granted_base());
     $serializedOptions = $options->serialize();
     $this->XMLHTTPRequest('POST', '/prod/records/', ['env' => 'RESULT', 'options_serial' => $serializedOptions, 'pos' => 0, 'query' => '']);
     $response = self::$DI['client']->getResponse();
     $data = json_decode($response->getContent(), true);
     $this->assertArrayHasKey('desc', $data);
     $this->assertArrayHasKey('html_preview', $data);
     $this->assertArrayHasKey('current', $data);
     $this->assertArrayHasKey('others', $data);
     $this->assertArrayHasKey('history', $data);
     $this->assertArrayHasKey('popularity', $data);
     $this->assertArrayHasKey('tools', $data);
     $this->assertArrayHasKey('pos', $data);
     $this->assertArrayHasKey('title', $data);
     unset($response, $data);
 }
Пример #18
0
 private function prepare_search_request(Application $app, Request $request)
 {
     $options = SearchEngineOptions::fromRequest($app, $request);
     $offsetStart = (int) ($request->get('offset_start') ?: 0);
     $perPage = (int) $request->get('per_page') ?: 10;
     $query = (string) $request->get('query');
     $app['phraseanet.SE']->resetCache();
     $search_result = $app['phraseanet.SE']->query($query, $offsetStart, $perPage, $options);
     $app['manipulator.user']->logQuery($app['authentication']->getUser(), $search_result->getQuery());
     foreach ($options->getDataboxes() as $databox) {
         $colls = array_map(function (\collection $collection) {
             return $collection->get_coll_id();
         }, array_filter($options->getCollections(), function (\collection $collection) use($databox) {
             return $collection->get_databox()->get_sbas_id() == $databox->get_sbas_id();
         }));
         $app['phraseanet.SE.logger']->log($databox, $search_result->getQuery(), $search_result->getTotal(), $colls);
     }
     $app['phraseanet.SE']->clearCache();
     $ret = ['offset_start' => $offsetStart, 'per_page' => $perPage, 'available_results' => $search_result->getAvailable(), 'total_results' => $search_result->getTotal(), 'error' => $search_result->getError(), 'warning' => $search_result->getWarning(), 'query_time' => $search_result->getDuration(), 'search_indexes' => $search_result->getIndexes(), 'suggestions' => array_map(function (SearchEngineSuggestion $suggestion) {
         return $suggestion->toArray();
     }, $search_result->getSuggestions()->toArray()), 'results' => [], 'query' => $search_result->getQuery()];
     return [$ret, $search_result];
 }