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; }