Page MenuHomePhabricator

D17608.diff
No OneTemporary

D17608.diff

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/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -2833,6 +2833,7 @@
'PhabricatorFulltextEngineExtensionModule' => 'applications/search/index/PhabricatorFulltextEngineExtensionModule.php',
'PhabricatorFulltextIndexEngineExtension' => 'applications/search/engineextension/PhabricatorFulltextIndexEngineExtension.php',
'PhabricatorFulltextInterface' => 'applications/search/interface/PhabricatorFulltextInterface.php',
+ 'PhabricatorFulltextResult' => 'applications/search/fulltextstorage/PhabricatorFulltextResult.php',
'PhabricatorFulltextStorageEngine' => 'applications/search/fulltextstorage/PhabricatorFulltextStorageEngine.php',
'PhabricatorFundApplication' => 'applications/fund/application/PhabricatorFundApplication.php',
'PhabricatorGDSetupCheck' => 'applications/config/check/PhabricatorGDSetupCheck.php',
@@ -3807,6 +3808,8 @@
'PhabricatorSearchRelationshipSourceController' => 'applications/search/controller/PhabricatorSearchRelationshipSourceController.php',
'PhabricatorSearchResultBucket' => 'applications/search/buckets/PhabricatorSearchResultBucket.php',
'PhabricatorSearchResultBucketGroup' => 'applications/search/buckets/PhabricatorSearchResultBucketGroup.php',
+ 'PhabricatorSearchResultEngineExtension' => 'applications/search/engineextension/PhabricatorSearchResultEngineExtension.php',
+ 'PhabricatorSearchResultHighlightsEngineExtension' => 'applications/search/engineextension/PhabricatorSearchResultHighlightsEngineExtension.php',
'PhabricatorSearchResultView' => 'applications/search/view/PhabricatorSearchResultView.php',
'PhabricatorSearchSchemaSpec' => 'applications/search/storage/PhabricatorSearchSchemaSpec.php',
'PhabricatorSearchScopeSetting' => 'applications/settings/setting/PhabricatorSearchScopeSetting.php',
@@ -7960,6 +7963,7 @@
'PhabricatorFulltextEngineExtension' => 'Phobject',
'PhabricatorFulltextEngineExtensionModule' => 'PhabricatorConfigModule',
'PhabricatorFulltextIndexEngineExtension' => 'PhabricatorIndexEngineExtension',
+ 'PhabricatorFulltextResult' => 'PhabricatorPolicyInterface',
'PhabricatorFulltextStorageEngine' => 'Phobject',
'PhabricatorFundApplication' => 'PhabricatorApplication',
'PhabricatorGDSetupCheck' => 'PhabricatorSetupCheck',
@@ -9127,6 +9131,8 @@
'PhabricatorSearchRelationshipSourceController' => 'PhabricatorSearchBaseController',
'PhabricatorSearchResultBucket' => 'Phobject',
'PhabricatorSearchResultBucketGroup' => 'Phobject',
+ 'PhabricatorSearchResultEngineExtension' => 'Phobject',
+ 'PhabricatorSearchResultHighlightsEngineExtension' => 'PhabricatorSearchResultEngineExtension',
'PhabricatorSearchResultView' => 'AphrontView',
'PhabricatorSearchSchemaSpec' => 'PhabricatorConfigSchemaSpec',
'PhabricatorSearchScopeSetting' => 'PhabricatorInternalSetting',
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/engineextension/PhabricatorSearchResultEngineExtension.php b/src/applications/search/engineextension/PhabricatorSearchResultEngineExtension.php
new file mode 100644
--- /dev/null
+++ b/src/applications/search/engineextension/PhabricatorSearchResultEngineExtension.php
@@ -0,0 +1,63 @@
+<?php
+
+abstract class PhabricatorSearchResultEngineExtension extends Phobject {
+
+ private $viewer;
+
+ final public function getExtensionKey() {
+ return $this->getPhobjectClassConstant('EXTENSIONKEY');
+ }
+
+ final public function setViewer($viewer) {
+ $this->viewer = $viewer;
+ return $this;
+ }
+
+ final public function getViewer() {
+ return $this->viewer;
+ }
+
+ abstract public function isExtensionEnabled();
+
+ abstract public function getExtensionName();
+
+ abstract public function canRenderItemView(PhabricatorFulltextResult $result);
+
+ public function getExtensionOrder() {
+ return 5000;
+ }
+
+ public function willRenderItemView(array $objects) {
+ return null;
+ }
+
+ abstract public function renderItemView(
+ PHUIObjectItemView $item,
+ PhabricatorFulltextResult $result);
+
+
+ final public static function getAllExtensions() {
+ return id(new PhutilClassMapQuery())
+ ->setAncestorClass(__CLASS__)
+ ->setUniqueMethod('getExtensionKey')
+ ->setSortMethod('getExtensionOrder')
+ ->execute();
+ }
+
+ /**
+ * @return PhabricatorSearchResultEngineExtension[]
+ */
+ final public static function getAllEnabledExtensions() {
+ $extensions = self::getAllExtensions();
+
+ foreach ($extensions as $key => $extension) {
+ if (!$extension->isExtensionEnabled()) {
+ unset($extensions[$key]);
+ }
+ }
+
+ return $extensions;
+ }
+
+
+}
diff --git a/src/applications/search/engineextension/PhabricatorSearchResultHighlightsEngineExtension.php b/src/applications/search/engineextension/PhabricatorSearchResultHighlightsEngineExtension.php
new file mode 100644
--- /dev/null
+++ b/src/applications/search/engineextension/PhabricatorSearchResultHighlightsEngineExtension.php
@@ -0,0 +1,42 @@
+<?php
+
+class PhabricatorSearchResultHighlightsEngineExtension
+ extends PhabricatorSearchResultEngineExtension {
+
+ const EXTENSIONKEY = 'highlights';
+
+ public function isExtensionEnabled() {
+ return true;
+ }
+
+ public function getExtensionName() {
+ return 'SearchResultHighlights';
+ }
+
+ public function canRenderItemView(PhabricatorFulltextResult $result) {
+ return true;
+ }
+
+ public function renderItemView(
+ PHUIObjectItemView $item,
+ PhabricatorFulltextResult $result) {
+
+ $highlights = $result->getHighlights('body');
+ if ($highlights) {
+ $highlight_view = phutil_tag_div('phui-oi-subhead',
+ array(
+ phutil_tag('span', array(
+ 'class' => 'visual-only phui-icon-view phui-font-fa fa-quote-left',
+ )),
+ ' ',
+ phutil_safe_html($highlights),
+ ' ... ',
+ ));
+ $item->appendChild($highlight_view);
+
+ }
+
+ return $item;
+ }
+
+}
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('<strong>'),
+ 'post_tags' => array('</strong>'),
+ 'fields' => array(
+ $field_body => array(
+ 'matched_fields' => array(
+ $field_body.'.raw',
+ $field_body.'.keywords',
+ $field_body.'.stems',
+ ),
+ ),
+ ),
+ );
+
return $spec;
}
@@ -289,8 +308,18 @@
foreach ($this->service->getAllHostsForRole('read') as $host) {
try {
$response = $this->executeRequest($host, $uri, $spec);
- $phids = ipull($response['hits']['hits'], '_id');
- return $phids;
+
+ $hits = array();
+ foreach ($response['hits']['hits'] as $hit) {
+ $phid = $hit['_id'];
+ $result = new PhabricatorFulltextResult($phid);
+ if (isset($hit['highlight'])) {
+ $result->setHighlights($hit['highlight']);
+ }
+ $hits[$phid] = $result;
+ }
+ // phlog($hits);
+ return $hits;
} catch (Exception $e) {
$exceptions[] = $e;
}
diff --git a/src/applications/search/fulltextstorage/PhabricatorFulltextResult.php b/src/applications/search/fulltextstorage/PhabricatorFulltextResult.php
new file mode 100644
--- /dev/null
+++ b/src/applications/search/fulltextstorage/PhabricatorFulltextResult.php
@@ -0,0 +1,74 @@
+<?php
+
+class PhabricatorFulltextResult
+ implements PhabricatorPolicyInterface {
+
+ protected $handle;
+ protected $fields = array();
+ protected $phid;
+ protected $type;
+
+ public function __construct($phid) {
+ $this->setPHID($phid);
+ }
+
+ public function setPHID($phid) {
+ $this->phid = $phid;
+ $this->type = phid_get_type($phid);
+ return $this;
+ }
+
+ public function getPHID() {
+ return $this->phid;
+ }
+
+ public function getType() {
+ return $this->type;
+ }
+
+ /**
+ * @return PhabricatorObjectHandle
+ */
+ public function getHandle() {
+ return $this->handle;
+ }
+
+ public function setHandle($handle) {
+ $this->handle = $handle;
+ return $this;
+ }
+
+ public function setHighlights($highlights) {
+ if (!$highlights) {
+ return;
+ }
+
+ foreach ($highlights as $field => $values) {
+ $this->fields[$field] = implode(' ... ', array_slice($values, 0, 2));
+ }
+ }
+
+ public function getHighlights($field = 'all') {
+ if ($field == 'all') {
+ return phutil_safe_html(implode('<br/>', $this->fields));
+ } else if (!isset($this->fields[$field])) {
+ return '';
+ }
+ return phutil_safe_html($this->fields[$field]);
+ }
+
+/* -( PhabricatorPolicyInterface )----------------------------------------- */
+
+ public function getCapabilities() {
+ return $this->handle->getCapabilities();
+ }
+
+ public function getPolicy($capability) {
+ return $this->handle->getPolicy($capability);
+ }
+
+ public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
+ return $this->handle->hasAutomaticCapability($capability, $viewer);
+ }
+
+}
diff --git a/src/applications/search/query/PhabricatorSearchApplicationSearchEngine.php b/src/applications/search/query/PhabricatorSearchApplicationSearchEngine.php
--- a/src/applications/search/query/PhabricatorSearchApplicationSearchEngine.php
+++ b/src/applications/search/query/PhabricatorSearchApplicationSearchEngine.php
@@ -253,9 +253,9 @@
->withPHIDs(mpull($results, 'getPHID'))
->execute();
- foreach ($results as $phid => $handle) {
+ foreach ($results as $phid => $result) {
$view = id(new PhabricatorSearchResultView())
- ->setHandle($handle)
+ ->setFulltextResult($result)
->setQuery($query)
->setObject(idx($objects, $phid))
->render();
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();
+ $results = $this->loadDocumentHitsWithoutPolicyChecks();
+ $phids = array_keys($results);
$handles = id(new PhabricatorHandleQuery())
->setViewer($this->getViewer())
@@ -32,13 +33,14 @@
->withPHIDs($phids)
->execute();
- // Retain engine order.
- $handles = array_select_keys($handles, $phids);
+ foreach ($phids as $phid) {
+ $results[$phid]->setHandle($handles[$phid]);
+ }
- return $handles;
+ return $results;
}
- protected function willFilterPage(array $handles) {
+ protected function willFilterPage(array $results) {
// NOTE: This is used by the object selector dialog to exclude the object
// you're looking at, so that, e.g., a task can't be set as a dependency
// of itself in the UI.
@@ -51,25 +53,26 @@
$exclude = array_fuse($exclude_phids);
}
- foreach ($handles as $key => $handle) {
+ foreach ($results as $key => $result) {
+ $handle = $result->getHandle();
if (!$handle->isComplete()) {
- unset($handles[$key]);
+ unset($results[$key]);
continue;
}
if ($handle->getPolicyFiltered()) {
- unset($handles[$key]);
+ unset($results[$key]);
continue;
}
if (isset($exclude[$handle->getPHID()])) {
- unset($handles[$key]);
+ unset($results[$key]);
continue;
}
}
- return $handles;
+ return $results;
}
- 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
@@ -5,12 +5,19 @@
private $handle;
private $query;
private $object;
+ private $result;
public function setHandle(PhabricatorObjectHandle $handle) {
$this->handle = $handle;
return $this;
}
+ public function setFulltextResult(PhabricatorFulltextResult $result) {
+ $this->result = $result;
+ $this->setHandle($result->getHandle());
+ return $this;
+ }
+
public function setQuery(PhabricatorSavedQuery $query) {
$this->query = $query;
return $this;
@@ -46,6 +53,13 @@
$item->addAttribute(pht('Closed'));
}
+ $ext = PhabricatorSearchResultEngineExtension::getAllEnabledExtensions();
+ foreach ($ext as $extension) {
+ if ($extension->canRenderItemView($this->result)) {
+ $item = $extension->renderItemView($item, $this->result);
+ }
+ }
+
return $item;
}
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;
}

File Metadata

Mime Type
text/plain
Expires
Sun, Feb 23, 6:53 AM (6 h, 36 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7185154
Default Alt Text
D17608.diff (16 KB)

Event Timeline