Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14033354
D8862.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
3 KB
Referenced Files
None
Subscribers
None
D8862.id.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D8862: Write search bolding in a way which is certainly HTML-safe
Attached
Detach File
Event Timeline
Log In to Comment