Page MenuHomePhabricator

D8862.id.diff
No OneTemporary

D8862.id.diff

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
@@ -76,33 +76,92 @@
$link);
}
+
+ /**
+ * Find the words which are part of the query string, and bold them in a
+ * result string. This makes it easier for users to see why a result
+ * matched their query.
+ */
private function emboldenQuery($str) {
- if (!$this->query) {
+ $query = $this->query->getParameter('query');
+
+ if (!strlen($query) || !strlen($str)) {
return $str;
}
- $query = $this->query->getParameter('query');
+ // This algorithm is safe but not especially fast, so don't bother if
+ // we're dealing with a lot of data. This mostly prevents silly/malicious
+ // queries from doing anything bad.
+ if (strlen($query) + strlen($str) > 2048) {
+ return $str;
+ }
- $quoted_regexp = '/"([^"]*)"/';
- $matches = array(1 => array());
- preg_match_all($quoted_regexp, $query, $matches);
- $quoted_queries = $matches[1];
- $query = preg_replace($quoted_regexp, '', $query);
-
- $query = preg_split('/\s+[+|]?/u', $query);
- $query = array_filter($query);
- $query = array_merge($query, $quoted_queries);
- $str = phutil_escape_html($str);
- foreach ($query as $word) {
- $word = phutil_escape_html($word);
- $word = preg_quote($word, '/');
- $word = preg_replace('/\\\\\*$/', '\w*', $word);
- $str = preg_replace(
- '/(?:^|\b)('.$word.')(?:\b|$)/i',
- '<strong>\1</strong>',
- $str);
+ // Keep track of which characters we're going to make bold. This is
+ // byte oriented, but we'll make sure we don't put a bold in the middle
+ // of a character later.
+ $bold = array_fill(0, strlen($str), false);
+
+ // Split the query into words.
+ $parts = preg_split('/ +/', $query);
+
+ // Find all occurrences of each word, and mark them to be emboldened.
+ foreach ($parts as $part) {
+ $part = trim($part);
+ $part = trim($part, '"+');
+ if (!strlen($part)) {
+ continue;
+ }
+
+ $matches = null;
+ $has_matches = preg_match_all(
+ '/(?:^|\b)('.preg_quote($part, '/').')/i',
+ $str,
+ $matches,
+ PREG_OFFSET_CAPTURE);
+
+ if (!$has_matches) {
+ continue;
+ }
+
+ // Flag the matching part of the range for boldening.
+ foreach ($matches[1] as $match) {
+ $offset = $match[1];
+ for ($ii = 0; $ii < strlen($match[0]); $ii++) {
+ $bold[$offset + $ii] = true;
+ }
+ }
}
- return phutil_safe_html($str);
+
+ // Split the string into ranges, applying bold styling as required.
+ $out = array();
+ $buf = '';
+ $pos = 0;
+ $is_bold = false;
+ foreach (phutil_utf8v($str) as $chr) {
+ if ($bold[$pos] != $is_bold) {
+ if (strlen($buf)) {
+ if ($is_bold) {
+ $out[] = phutil_tag('strong', array(), $buf);
+ } else {
+ $out[] = $buf;
+ }
+ $buf = '';
+ }
+ $is_bold = !$is_bold;
+ }
+ $buf .= $chr;
+ $pos += strlen($chr);
+ }
+
+ if (strlen($buf)) {
+ if ($is_bold) {
+ $out[] = phutil_tag('strong', array(), $buf);
+ } else {
+ $out[] = $buf;
+ }
+ }
+
+ return $out;
}
}

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 10, 5:31 PM (1 w, 2 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6716170
Default Alt Text
D8862.id.diff (3 KB)

Event Timeline