formFactory = $formFactory; $this->em = $em; $this->tokenStorage = $tokenStorage; $this->sourceManager = $sourceManager; $this->queryManager = $queryManager; $this->extractor = $extractor; } /** * Make simple search without saving query in database. * Fetched documents are cached but not indexed. * * @Roles("ROLE_SUBSCRIBER") * * @Route("/search", methods={ "POST" }) * @ApiDoc( * resource="Search", * section="Query", * input={ * "class"="AppBundle\Form\SearchRequest\SimpleQuerySearchRequestType", * "name"=false * }, * output={ * "class"="", * "data"={ * "documents"={ * "class"="Pagination", * "groups"={ "document" } * }, * "advancedFilters"={ * "dataType"="array", * "required"=true, * "readonly"=true, * "description"="Array of advanced filters values for this search request." * }, * "stats"={ * "dataType"="object", * "required"=true, * "readonly"=true, * "description"="Internal statistics, showed only in staging and local developers machine.", * "children"={ * "totalOnPage"={ * "dataType"="integer", * "required"=true, * "readonly"=true, * "description"="Total founded document on current page." * }, * "newDocuments"={ * "dataType"="integer", * "required"=true, * "readonly"=true, * "description"="Number of documents that were not in our database." * }, * "alreadyExistsDocuments"={ * "dataType"="integer", * "required"=true, * "readonly"=true, * "description"="Number of documents that already in our database." * }, * "fromCache"={ * "dataType"="boolean", * "required"=true, * "readonly"=true, * "description"="Flag, all documents fetched from our internal cache if set." * }, * "expiresAt"={ * "dataType"="datetime", * "required"=true, * "readonly"=true, * "description"="When this query is expired." * } * } * } * } * }, * statusCodes={ * 200="Search completed.", * 400="Invalid data provided" * } * ) * * @param Request $request A Request instance. * * @return array|\ApiBundle\Response\ViewInterface */ public function searchAction(Request $request) { $form = $this->createForm(SimpleQuerySearchRequestType::class); $form->submit($request->request->all()); if ($form->isValid()) { $user = $this->getCurrentUser(); try { $user->useLimit(AppLimitEnum::searches()); } catch (LimitExceedException $exception) { return $this->generateResponse([ 'failedRestriction' => AppLimitEnum::SEARCHES, 'restrictions' => $user->getRestrictions(), ], 402); } $this->em->persist($user); $this->em->flush(); /** @var SearchRequestBuilderInterface $builder */ $builder = $form->getData(); $searchRequest = $builder ->setFields([ FieldNameEnum::TITLE, FieldNameEnum::MAIN, ]) ->addSort(FieldNameEnum::PUBLISHED, 'desc') ->build(); $response = $this->queryManager->searchAndCache( $searchRequest, $request->request->get('filters', []), $request->request->get('advancedFilters', []) ); $query = $response->getQuery(); $response->mapDocuments(function (ArticleDocumentInterface $document) use ($query) { return $document->mapNormalizedData(function (array $data) use ($query) { $result = $this->extractor->extract( $data['content'], $query->getRaw(), ThemeOptionExtractEnum::start(), true ); $data['content'] = $result->getText() . ( mb_strlen($data['content']) > $result->getLength() ? '...' : '' ); return $data; }); }); $result = [ 'documents' => $this->paginate($response, $builder->getPage(), $builder->getLimit()), 'advancedFilters' => $searchRequest->getAvailableAdvancedFilters() ?: (object) [], ]; // // Return internal statistic. // $result['stats'] = [ 'newDocuments' => $response->getUniqueCount(), 'alreadyExistsDocuments' => $response->count() - $response->getUniqueCount(), 'fromCache' => $response->isFromCache(), 'expiresAt' => $query->getExpirationDate()->format('c'), ]; // // Return meta information about query. // $sources = $this->sourceManager->getSourcesForQuery($query, [ 'id', 'title', 'type' ]); $sourceLists = $this->sourceManager->getSourceListsForQuery($query, [ 'id', 'name' ]); $result['meta'] = [ 'type' => 'query', 'status' => 'synced', 'search' => [ 'query' => $query->getRaw(), 'filters' => $query->getRawFilters() ?: (object) [], 'advancedFilters' => $query->getRawAdvancedFilters() ?: (object) [], ], 'sources' => $sources, 'sourceLists' => $sourceLists, ]; return $this->generateResponse($result); } return $this->generateResponse($form, 400); } }