diff --git a/resources/celerity/map.php b/resources/celerity/map.php --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -103,7 +103,7 @@ 'rsrc/css/application/releeph/releeph-request-differential-create-dialog.css' => '8d8b92cd', 'rsrc/css/application/releeph/releeph-request-typeahead.css' => '667a48ae', 'rsrc/css/application/search/application-search-view.css' => '66ee5d46', - 'rsrc/css/application/search/search-results.css' => '64ad079a', + 'rsrc/css/application/search/search-results.css' => '9fc45e8d', 'rsrc/css/application/slowvote/slowvote.css' => 'a94b7230', 'rsrc/css/application/tokens/tokens.css' => '3d0f239e', 'rsrc/css/application/uiexample/example.css' => '528b19de', @@ -794,7 +794,7 @@ 'phabricator-phtize' => 'd254d646', 'phabricator-prefab' => '8d40ae75', 'phabricator-remarkup-css' => '17c0fb37', - 'phabricator-search-results-css' => '64ad079a', + 'phabricator-search-results-css' => '9fc45e8d', 'phabricator-shaped-request' => '7cbe244b', 'phabricator-slowvote-css' => 'a94b7230', 'phabricator-source-code-view-css' => '4383192f', diff --git a/src/applications/maniphest/query/ManiphestTaskQuery.php b/src/applications/maniphest/query/ManiphestTaskQuery.php --- a/src/applications/maniphest/query/ManiphestTaskQuery.php +++ b/src/applications/maniphest/query/ManiphestTaskQuery.php @@ -524,6 +524,8 @@ if (empty($fulltext_results)) { $fulltext_results = array(null); + } else { + $fulltext_results = array_keys($fulltext_results); } return qsprintf( diff --git a/src/applications/search/fulltextstorage/PhabricatorElasticFulltextStorageEngine.php b/src/applications/search/fulltextstorage/PhabricatorElasticFulltextStorageEngine.php --- a/src/applications/search/fulltextstorage/PhabricatorElasticFulltextStorageEngine.php +++ b/src/applications/search/fulltextstorage/PhabricatorElasticFulltextStorageEngine.php @@ -142,6 +142,10 @@ } private function buildSpec(PhabricatorSavedQuery $query) { + $field_title = PhabricatorSearchDocumentFieldType::FIELD_TITLE; + $field_body = PhabricatorSearchDocumentFieldType::FIELD_BODY; + $field_comment = PhabricatorSearchDocumentFieldType::FIELD_COMMENT; + $q = new PhabricatorElasticsearchQueryBuilder('bool'); $query_string = $query->getParameter('query'); if (strlen($query_string)) { @@ -153,9 +157,10 @@ 'simple_query_string' => array( 'query' => $query_string, 'fields' => array( - PhabricatorSearchDocumentFieldType::FIELD_TITLE.'.*', - PhabricatorSearchDocumentFieldType::FIELD_BODY.'.*', - PhabricatorSearchDocumentFieldType::FIELD_COMMENT.'.*', + $field_title.'.*', + $field_body, + $field_body.'.*', + $field_comment.'.*', ), 'default_operator' => 'AND', ), @@ -170,12 +175,12 @@ 'query' => $query_string, 'fields' => array( '*.raw', - PhabricatorSearchDocumentFieldType::FIELD_TITLE.'^4', - PhabricatorSearchDocumentFieldType::FIELD_BODY.'^3', - PhabricatorSearchDocumentFieldType::FIELD_COMMENT.'^1.2', + $field_title.'^4', + $field_body.'^3', + $field_comment.'^1.2', ), 'analyzer' => 'english_exact', - 'default_operator' => 'and', + 'default_operator' => 'AND', ), )); @@ -268,6 +273,20 @@ $spec['from'] = $offset; $spec['size'] = $limit; + $spec['highlight'] = array( + 'pre_tags' => array(''), + 'post_tags' => array(''), + 'fields' => array( + $field_body => array( + 'matched_fields' => array( + $field_body.'.raw', + $field_body.'.keywords', + $field_body.'.stems', + ), + ), + ), + ); + return $spec; } @@ -289,7 +308,7 @@ foreach ($this->service->getAllHostsForRole('read') as $host) { try { $response = $this->executeRequest($host, $uri, $spec); - $phids = ipull($response['hits']['hits'], '_id'); + $phids = ipull($response['hits']['hits'], null, '_id'); return $phids; } catch (Exception $e) { $exceptions[] = $e; diff --git a/src/applications/search/query/PhabricatorSearchDocumentQuery.php b/src/applications/search/query/PhabricatorSearchDocumentQuery.php --- a/src/applications/search/query/PhabricatorSearchDocumentQuery.php +++ b/src/applications/search/query/PhabricatorSearchDocumentQuery.php @@ -24,7 +24,8 @@ } protected function loadPage() { - $phids = $this->loadDocumentPHIDsWithoutPolicyChecks(); + $hits = $this->loadDocumentHitsWithoutPolicyChecks(); + $phids = array_keys($hits); $handles = id(new PhabricatorHandleQuery()) ->setViewer($this->getViewer()) @@ -34,7 +35,12 @@ // Retain engine order. $handles = array_select_keys($handles, $phids); - + foreach ($handles as $phid => $handle) { + if (isset($hits[$phid]['highlight'])) { + $highlight = array_shift($hits[$phid]['highlight']['body']); + $handle->setSubtitle(new PhutilSafeHTML($highlight)); + } + } return $handles; } @@ -69,7 +75,7 @@ return $handles; } - public function loadDocumentPHIDsWithoutPolicyChecks() { + public function loadDocumentHitsWithoutPolicyChecks() { $query = id(clone($this->savedQuery)) ->setParameter('offset', $this->getOffset()) ->setParameter('limit', $this->getRawResultLimit()); diff --git a/src/applications/search/view/PhabricatorSearchResultView.php b/src/applications/search/view/PhabricatorSearchResultView.php --- a/src/applications/search/view/PhabricatorSearchResultView.php +++ b/src/applications/search/view/PhabricatorSearchResultView.php @@ -39,6 +39,7 @@ ->setTitleText($raw_title) ->setHref($handle->getURI()) ->setImageURI($handle->getImageURI()) + ->setSubhead($handle->getSubtitle()) ->addAttribute($type_name); if ($handle->getStatus() == PhabricatorObjectHandle::STATUS_CLOSED) { diff --git a/webroot/rsrc/css/application/search/search-results.css b/webroot/rsrc/css/application/search/search-results.css --- a/webroot/rsrc/css/application/search/search-results.css +++ b/webroot/rsrc/css/application/search/search-results.css @@ -2,7 +2,7 @@ * @provides phabricator-search-results-css */ -.phui-oi-link strong { +.phui-oi-link strong, .phui-oi-subhead strong { color: {$fire}; text-decoration: underline; }