public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     if ($request->getStr('jump') != 'no') {
         $response = PhabricatorJumpNavHandler::getJumpResponse($viewer, $request->getStr('query'));
         if ($response) {
             return $response;
         }
     }
     $engine = new PhabricatorSearchApplicationSearchEngine();
     $engine->setViewer($viewer);
     // If we're coming from primary search, do some special handling to
     // interpret the scope selector and query.
     if ($request->getBool('search:primary')) {
         // If there's no query, just take the user to advanced search.
         if (!strlen($request->getStr('query'))) {
             $advanced_uri = '/search/query/advanced/';
             return id(new AphrontRedirectResponse())->setURI($advanced_uri);
         }
         // First, load or construct a template for the search by examining
         // the current search scope.
         $scope = $request->getStr('search:scope');
         $saved = null;
         if ($scope == self::SCOPE_CURRENT_APPLICATION) {
             $application = id(new PhabricatorApplicationQuery())->setViewer($viewer)->withClasses(array($request->getStr('search:application')))->executeOne();
             if ($application) {
                 $types = $application->getApplicationSearchDocumentTypes();
                 if ($types) {
                     $saved = id(new PhabricatorSavedQuery())->setEngineClassName(get_class($engine))->setParameter('types', $types)->setParameter('statuses', array('open'));
                 }
             }
         }
         if (!$saved && !$engine->isBuiltinQuery($scope)) {
             $saved = id(new PhabricatorSavedQueryQuery())->setViewer($viewer)->withQueryKeys(array($scope))->executeOne();
         }
         if (!$saved) {
             if (!$engine->isBuiltinQuery($scope)) {
                 $scope = 'all';
             }
             $saved = $engine->buildSavedQueryFromBuiltin($scope);
         }
         // Add the user's query, then save this as a new saved query and send
         // the user to the results page.
         $saved->setParameter('query', $request->getStr('query'));
         $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
         try {
             $saved->setID(null)->save();
         } catch (AphrontDuplicateKeyQueryException $ex) {
             // Ignore, this is just a repeated search.
         }
         unset($unguarded);
         $query_key = $saved->getQueryKey();
         $results_uri = $engine->getQueryResultsPageURI($query_key) . '#R';
         return id(new AphrontRedirectResponse())->setURI($results_uri);
     }
     $controller = id(new PhabricatorApplicationSearchController())->setQueryKey($request->getURIData('queryKey'))->setSearchEngine($engine)->setNavigation($this->buildSideNavView());
     return $this->delegateToController($controller);
 }
 private function buildResults()
 {
     $types = PhabricatorSearchApplicationSearchEngine::getIndexableDocumentTypes();
     $icons = mpull(PhabricatorPHIDType::getAllTypes(), 'getTypeIcon', 'getTypeConstant');
     $results = array();
     foreach ($types as $type => $name) {
         $results[$type] = id(new PhabricatorTypeaheadResult())->setPHID($type)->setName($name)->setIcon(idx($icons, $type));
     }
     return $results;
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $viewer = $request->getUser();
     if ($request->getStr('jump') != 'no') {
         $pref_jump = PhabricatorUserPreferences::PREFERENCE_SEARCHBAR_JUMP;
         if ($viewer->loadPreferences($pref_jump, 1)) {
             $response = PhabricatorJumpNavHandler::getJumpResponse($viewer, $request->getStr('query'));
             if ($response) {
                 return $response;
             }
         }
     }
     $engine = new PhabricatorSearchApplicationSearchEngine();
     $engine->setViewer($viewer);
     // NOTE: This is a little weird. If we're coming from primary search, we
     // load the user's first search filter and overwrite the "query" part of
     // it, then send them to that result page. This is sort of odd, but lets
     // users choose a default query like "Open Tasks" in a reasonable way,
     // with only this piece of somewhat-sketchy code. See discussion in T4365.
     if ($request->getBool('search:primary')) {
         $named_queries = $engine->loadEnabledNamedQueries();
         if ($named_queries) {
             $named = head($named_queries);
             $query_key = $named->getQueryKey();
             $saved = null;
             if ($engine->isBuiltinQuery($query_key)) {
                 $saved = $engine->buildSavedQueryFromBuiltin($query_key);
             } else {
                 $saved = id(new PhabricatorSavedQueryQuery())->setViewer($viewer)->withQueryKeys(array($query_key))->executeOne();
             }
             if ($saved) {
                 $saved->setParameter('query', $request->getStr('query'));
                 $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
                 try {
                     $saved->setID(null)->save();
                 } catch (AphrontDuplicateKeyQueryException $ex) {
                     // Ignore, this is just a repeated search.
                 }
                 unset($unguarded);
                 $results_uri = $engine->getQueryResultsPageURI($saved->getQueryKey()) . '#R';
                 return id(new AphrontRedirectResponse())->setURI($results_uri);
             }
         }
     }
     $controller = id(new PhabricatorApplicationSearchController($request))->setQueryKey($this->queryKey)->setSearchEngine($engine)->setNavigation($this->buildSideNavView());
     return $this->delegateToController($controller);
 }
 private function buildResults()
 {
     $viewer = $this->getViewer();
     $types = PhabricatorSearchApplicationSearchEngine::getIndexableDocumentTypes($viewer);
     $phid_types = mpull(PhabricatorPHIDType::getAllTypes(), null, 'getTypeConstant');
     $results = array();
     foreach ($types as $type => $name) {
         $type_object = idx($phid_types, $type);
         if (!$type_object) {
             continue;
         }
         $application_class = $type_object->getPHIDTypeApplicationClass();
         $application = PhabricatorApplication::getByClass($application_class);
         $application_name = $application->getName();
         $results[$type] = id(new PhabricatorTypeaheadResult())->setPHID($type)->setName($name)->addAttribute($application_name)->setIcon($type_object->getTypeIcon());
     }
     return $results;
 }
 private function getIndexConfiguration()
 {
     $data = array();
     $data['settings'] = array('index' => array('auto_expand_replicas' => '0-2', 'analysis' => array('filter' => array('trigrams_filter' => array('min_gram' => 3, 'type' => 'ngram', 'max_gram' => 3)), 'analyzer' => array('custom_trigrams' => array('type' => 'custom', 'filter' => array('lowercase', 'kstem', 'trigrams_filter'), 'tokenizer' => 'standard')))));
     $types = array_keys(PhabricatorSearchApplicationSearchEngine::getIndexableDocumentTypes());
     foreach ($types as $type) {
         // Use the custom trigram analyzer for the corpus of text
         $data['mappings'][$type]['properties']['field']['properties']['corpus'] = array('type' => 'string', 'analyzer' => 'custom_trigrams');
         // Ensure we have dateCreated since the default query requires it
         $data['mappings'][$type]['properties']['dateCreated']['type'] = 'string';
     }
     return $data;
 }
 public function executeSearch(PhabricatorSavedQuery $query)
 {
     $types = $query->getParameter('types');
     if (!$types) {
         $types = array_keys(PhabricatorSearchApplicationSearchEngine::getIndexableDocumentTypes());
     }
     // Don't use '/_search' for the case that there is something
     // else in the index (for example if 'phabricator' is only an alias to
     // some bigger index). Use '/$types/_search' instead.
     $uri = '/' . implode(',', $types) . '/_search';
     try {
         $response = $this->executeRequest($uri, $this->buildSpec($query));
     } catch (HTTPFutureHTTPResponseStatus $ex) {
         // elasticsearch probably uses Lucene query syntax:
         // http://lucene.apache.org/core/3_6_1/queryparsersyntax.html
         // Try literal search if operator search fails.
         if (!strlen($query->getParameter('query'))) {
             throw $ex;
         }
         $query = clone $query;
         $query->setParameter('query', addcslashes($query->getParameter('query'), '+-&|!(){}[]^"~*?:\\'));
         $response = $this->executeRequest($uri, $this->buildSpec($query));
     }
     $phids = ipull($response['hits']['hits'], '_id');
     return $phids;
 }