From 2eeef9aa053994ff4d57f7ce52aa5e3d779d0351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Burnichon?= Date: Mon, 25 May 2015 15:49:08 +0200 Subject: [PATCH] Split Query provider into controller/provider --- lib/Alchemy/Phrasea/Application.php | 4 +- .../Controller/Prod/QueryController.php | 216 +++++++++++++++++ .../Phrasea/ControllerProvider/Prod/Push.php | 1 + .../Phrasea/ControllerProvider/Prod/Query.php | 229 ++---------------- 4 files changed, 244 insertions(+), 206 deletions(-) create mode 100644 lib/Alchemy/Phrasea/Controller/Prod/QueryController.php diff --git a/lib/Alchemy/Phrasea/Application.php b/lib/Alchemy/Phrasea/Application.php index 5b972d58ce..904002ae3c 100644 --- a/lib/Alchemy/Phrasea/Application.php +++ b/lib/Alchemy/Phrasea/Application.php @@ -12,7 +12,6 @@ namespace Alchemy\Phrasea; use Alchemy\Geonames\GeonamesServiceProvider; -use Alchemy\Phrasea\ControllerProvider\Prod\Query; use Alchemy\Phrasea\ControllerProvider\Prod\Records; use Alchemy\Phrasea\ControllerProvider\Prod\Root as Prod; use Alchemy\Phrasea\ControllerProvider\Prod\Share; @@ -315,6 +314,7 @@ class Application extends SilexApplication 'Alchemy\Phrasea\ControllerProvider\Prod\Printer' => [], 'Alchemy\Phrasea\ControllerProvider\Prod\Property' => [], 'Alchemy\Phrasea\ControllerProvider\Prod\Push' => [], + 'Alchemy\Phrasea\ControllerProvider\Prod\Query' => [], 'Alchemy\Phrasea\ControllerProvider\Datafiles' => [], 'Alchemy\Phrasea\ControllerProvider\Lightbox' => [], 'Alchemy\Phrasea\ControllerProvider\MediaAccessor' => [], @@ -625,7 +625,6 @@ class Application extends SilexApplication $this->mount('/login/', new Login()); $this->mount('/developers/', new Developers()); - $this->mount('/prod/query/', new Query()); $this->mount('/prod/story', new Story()); $this->mount('/prod/WorkZone', new WorkZone()); $this->mount('/prod/lists', new UsrLists()); @@ -679,6 +678,7 @@ class Application extends SilexApplication '/prod/order/' => 'Alchemy\Phrasea\ControllerProvider\Prod\Order', '/prod/printer/' => 'Alchemy\Phrasea\ControllerProvider\Prod\Printer', '/prod/push/' => 'Alchemy\Phrasea\ControllerProvider\Prod\Push', + '/prod/query/' => 'Alchemy\Phrasea\ControllerProvider\Prod\Query', '/prod/records/edit' => 'Alchemy\Phrasea\ControllerProvider\Prod\Edit', '/prod/records/movecollection' => 'Alchemy\Phrasea\ControllerProvider\Prod\MoveCollection', '/prod/records/property' => 'Alchemy\Phrasea\ControllerProvider\Prod\Property', diff --git a/lib/Alchemy/Phrasea/Controller/Prod/QueryController.php b/lib/Alchemy/Phrasea/Controller/Prod/QueryController.php new file mode 100644 index 0000000000..0da8cfed01 --- /dev/null +++ b/lib/Alchemy/Phrasea/Controller/Prod/QueryController.php @@ -0,0 +1,216 @@ +request->get('qry'); + + $json = []; + + $options = SearchEngineOptions::fromRequest($app, $request); + + $form = $options->serialize(); + + $perPage = (int) $app['settings']->getUserSetting($app['authentication']->getUser(), 'images_per_page'); + + $page = (int) $request->request->get('pag'); + $firstPage = $page < 1; + + if ($page < 1) { + $app['phraseanet.SE']->resetCache(); + $page = 1; + } + + /** @var SearchEngineResult $result */ + $result = $app['phraseanet.SE']->query($query, (($page - 1) * $perPage), $perPage, $options); + + $app['manipulator.user']->logQuery($app['authentication']->getUser(), $result->getQuery()); + + 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); + } + + $proposals = $firstPage ? $result->getProposals() : false; + + $npages = $result->getTotalPages($perPage); + + $page = $result->getCurrentPage($perPage); + + $string = ''; + + if ($npages > 1) { + + $d2top = ($npages - $page); + $d2bottom = $page; + + if (min($d2top, $d2bottom) < 4) { + if ($d2bottom < 4) { + if($page != 1){ + $string .= ""; + } + for ($i = 1; ($i <= 4 && (($i <= $npages) === true)); $i++) { + if ($i == $page) + $string .= ''; + else + $string .= "" . $i . ""; + } + if ($npages > 4) + $string .= ""; + $string .= ""; + } else { + $start = $npages - 4; + if (($start) > 0){ + $string .= ""; + $string .= ""; + }else + $start = 1; + for ($i = ($start); $i <= $npages; $i++) { + if ($i == $page) + $string .= ''; + else + $string .= "" . $i . ""; + } + if($page < $npages){ + $string .= ""; + } + } + } else { + $string .= ""; + + for ($i = ($page - 2); $i <= ($page + 2); $i++) { + if ($i == $page) + $string .= ''; + else + $string .= "" . $i . ""; + } + + $string .= ""; + } + } + $string .= '
'; + + $explain = "
"; + + $explain .= ""; + + if ($result->getTotal() != $result->getAvailable()) { + $explain .= $app->trans('reponses:: %available% Resultats rappatries sur un total de %total% trouves', ['available' => $result->getAvailable(), '%total%' => $result->getTotal()]); + } else { + $explain .= $app->trans('reponses:: %total% Resultats', ['%total%' => $result->getTotal()]); + } + + $explain .= " "; + $explain .= '
' . $result->getDuration() . ' s
dans index ' . $result->getIndexes(); + $explain .= "
"; + + $infoResult = '
' . $app->trans('%number% documents
selectionnes', ['%number%' => '']).'
' .$app->trans('%total% reponses', ['%total%' => ''.$result->getTotal().'']) . ''; + + $json['infos'] = $infoResult; + $json['navigation'] = $string; + + $prop = null; + + if ($firstPage) { + $propals = $result->getSuggestions(); + if (count($propals) > 0) { + foreach ($propals as $prop_array) { + if ($prop_array->getSuggestion() !== $query && $prop_array->getHits() > $result->getTotal()) { + $prop = $prop_array->getSuggestion(); + break; + } + } + } + } + + if ($result->getTotal() === 0) { + $template = 'prod/results/help.html.twig'; + } else { + $template = 'prod/results/records.html.twig'; + } + + $json['results'] = $app['twig']->render($template, ['results'=> $result]); + + $json['query'] = $query; + + /** Debug */ + $json['parsed_query'] = $result->getQuery(); + /** End debug */ + + $json['facets'] = $result->getFacets(); + $json['phrasea_props'] = $proposals; + $json['total_answers'] = (int) $result->getAvailable(); + $json['next_page'] = ($page < $npages && $result->getAvailable() > 0) ? ($page + 1) : false; + $json['prev_page'] = ($page > 1 && $result->getAvailable() > 0) ? ($page - 1) : false; + $json['form'] = $form; + + return $app->json($json); + } + + /** + * Get a preview answer train + * + * @param Application $app + * @param Request $request + * @return Response + */ + public function queryAnswerTrain(Application $app, Request $request) + { + if (null === $optionsSerial = $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); + + $index = ($pos - 3) < 0 ? 0 : ($pos - 3); + return $app->json([ + 'current' => $app['twig']->render('prod/preview/result_train.html.twig', [ + 'records' => $record->get_train(), + 'index' => $index, + 'selected' => $pos + ]) + ]); + } +} diff --git a/lib/Alchemy/Phrasea/ControllerProvider/Prod/Push.php b/lib/Alchemy/Phrasea/ControllerProvider/Prod/Push.php index 0b940db422..bf24f3fe28 100644 --- a/lib/Alchemy/Phrasea/ControllerProvider/Prod/Push.php +++ b/lib/Alchemy/Phrasea/ControllerProvider/Prod/Push.php @@ -42,6 +42,7 @@ class Push implements ControllerProviderInterface, ServiceProviderInterface { // no-op } + public function connect(Application $app) { $controllers = $this->createAuthenticatedCollection($app); diff --git a/lib/Alchemy/Phrasea/ControllerProvider/Prod/Query.php b/lib/Alchemy/Phrasea/ControllerProvider/Prod/Query.php index ae50112ec5..f3e039987c 100644 --- a/lib/Alchemy/Phrasea/ControllerProvider/Prod/Query.php +++ b/lib/Alchemy/Phrasea/ControllerProvider/Prod/Query.php @@ -11,23 +11,40 @@ namespace Alchemy\Phrasea\ControllerProvider\Prod; +use Alchemy\Phrasea\Application as PhraseaApplication; +use Alchemy\Phrasea\Controller\Prod\QueryController; use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait; -use Alchemy\Phrasea\SearchEngine\SearchEngineOptions; -use Alchemy\Phrasea\SearchEngine\SearchEngineResult; use Silex\Application; use Silex\ControllerProviderInterface; -use Symfony\Component\HttpFoundation\JsonResponse; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; +use Silex\ServiceProviderInterface; -class Query implements ControllerProviderInterface +class Query implements ControllerProviderInterface, ServiceProviderInterface { use ControllerProviderTrait; + public function register(Application $app) + { + $app['controller.prod.query'] = $app->share(function (PhraseaApplication $app) { + return (new QueryController($app)) + ->setDataboxLoggerLocator($app['phraseanet.logger']) + ->setDispatcher($app['dispatcher']) + ->setEntityManagerLocator(function () use ($app) { + return $app['orm.em']; + }) + ->setUserQueryFactory(function () use ($app) { + return $app['phraseanet.user-query']; + }) + ; + }); + } + + public function boot(Application $app) + { + // no-op + } + public function connect(Application $app) { - $app['controller.prod.query'] = $this; - $controllers = $this->createAuthenticatedCollection($app); $controllers->post('/', 'controller.prod.query:query') @@ -41,200 +58,4 @@ class Query implements ControllerProviderInterface return $controllers; } - - /** - * Query Phraseanet to fetch records - * - * @param Application $app - * @param Request $request - * @return JsonResponse - */ - public function query(Application $app, Request $request) - { - $query = (string) $request->request->get('qry'); - - $json = []; - - $options = SearchEngineOptions::fromRequest($app, $request); - - $form = $options->serialize(); - - $perPage = (int) $app['settings']->getUserSetting($app['authentication']->getUser(), 'images_per_page'); - - $page = (int) $request->request->get('pag'); - $firstPage = $page < 1; - - if ($page < 1) { - $app['phraseanet.SE']->resetCache(); - $page = 1; - } - - /** @var SearchEngineResult $result */ - $result = $app['phraseanet.SE']->query($query, (($page - 1) * $perPage), $perPage, $options); - - $app['manipulator.user']->logQuery($app['authentication']->getUser(), $result->getQuery()); - - 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); - } - - $proposals = $firstPage ? $result->getProposals() : false; - - $npages = $result->getTotalPages($perPage); - - $page = $result->getCurrentPage($perPage); - - $string = ''; - - if ($npages > 1) { - - $d2top = ($npages - $page); - $d2bottom = $page; - - if (min($d2top, $d2bottom) < 4) { - if ($d2bottom < 4) { - if($page != 1){ - $string .= ""; - } - for ($i = 1; ($i <= 4 && (($i <= $npages) === true)); $i++) { - if ($i == $page) - $string .= ''; - else - $string .= "" . $i . ""; - } - if ($npages > 4) - $string .= ""; - $string .= ""; - } else { - $start = $npages - 4; - if (($start) > 0){ - $string .= ""; - $string .= ""; - }else - $start = 1; - for ($i = ($start); $i <= $npages; $i++) { - if ($i == $page) - $string .= ''; - else - $string .= "" . $i . ""; - } - if($page < $npages){ - $string .= ""; - } - } - } else { - $string .= ""; - - for ($i = ($page - 2); $i <= ($page + 2); $i++) { - if ($i == $page) - $string .= ''; - else - $string .= "" . $i . ""; - } - - $string .= ""; - } - } - $string .= '
'; - - $explain = "
"; - - $explain .= ""; - - if ($result->getTotal() != $result->getAvailable()) { - $explain .= $app->trans('reponses:: %available% Resultats rappatries sur un total de %total% trouves', ['available' => $result->getAvailable(), '%total%' => $result->getTotal()]); - } else { - $explain .= $app->trans('reponses:: %total% Resultats', ['%total%' => $result->getTotal()]); - } - - $explain .= " "; - $explain .= '
' . $result->getDuration() . ' s
dans index ' . $result->getIndexes(); - $explain .= "
"; - - $infoResult = '
' . $app->trans('%number% documents
selectionnes', ['%number%' => '']).'
' .$app->trans('%total% reponses', ['%total%' => ''.$result->getTotal().'']) . ''; - - $json['infos'] = $infoResult; - $json['navigation'] = $string; - - $prop = null; - - if ($firstPage) { - $propals = $result->getSuggestions(); - if (count($propals) > 0) { - foreach ($propals as $prop_array) { - if ($prop_array->getSuggestion() !== $query && $prop_array->getHits() > $result->getTotal()) { - $prop = $prop_array->getSuggestion(); - break; - } - } - } - } - - if ($result->getTotal() === 0) { - $template = 'prod/results/help.html.twig'; - } else { - $template = 'prod/results/records.html.twig'; - } - - $json['results'] = $app['twig']->render($template, ['results'=> $result]); - - $json['query'] = $query; - - /** Debug */ - $json['parsed_query'] = $result->getQuery(); - /** End debug */ - - $json['facets'] = $result->getFacets(); - $json['phrasea_props'] = $proposals; - $json['total_answers'] = (int) $result->getAvailable(); - $json['next_page'] = ($page < $npages && $result->getAvailable() > 0) ? ($page + 1) : false; - $json['prev_page'] = ($page > 1 && $result->getAvailable() > 0) ? ($page - 1) : false; - $json['form'] = $form; - - return $app->json($json); - } - - /** - * Get a preview answer train - * - * @param Application $app - * @param Request $request - * @return JsonResponse - */ - public function queryAnswerTrain(Application $app, Request $request) - { - if (null === $optionsSerial = $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); - - $index = ($pos - 3) < 0 ? 0 : ($pos - 3); - return $app->json([ - 'current' => $app['twig']->render('prod/preview/result_train.html.twig', [ - 'records' => $record->get_train(), - 'index' => $index, - 'selected' => $pos - ]) - ]); - } }