[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 final class PhabricatorSearchResultView extends AphrontView { 4 5 private $handle; 6 private $query; 7 private $object; 8 9 public function setHandle(PhabricatorObjectHandle $handle) { 10 $this->handle = $handle; 11 return $this; 12 } 13 14 public function setQuery(PhabricatorSavedQuery $query) { 15 $this->query = $query; 16 return $this; 17 } 18 19 public function setObject($object) { 20 $this->object = $object; 21 return $this; 22 } 23 24 public function render() { 25 $handle = $this->handle; 26 if (!$handle->isComplete()) { 27 return; 28 } 29 30 $type_name = nonempty($handle->getTypeName(), 'Document'); 31 32 require_celerity_resource('phabricator-search-results-css'); 33 34 $link = phutil_tag( 35 'a', 36 array( 37 'href' => $handle->getURI(), 38 ), 39 PhabricatorEnv::getProductionURI($handle->getURI())); 40 41 $img = $handle->getImageURI(); 42 43 if ($img) { 44 $img = phutil_tag( 45 'div', 46 array( 47 'class' => 'result-image', 48 'style' => "background-image: url('{$img}');", 49 ), 50 ''); 51 } 52 53 $title = $this->emboldenQuery($handle->getFullName()); 54 if ($handle->getStatus() == PhabricatorObjectHandleStatus::STATUS_CLOSED) { 55 $title = phutil_tag('del', array(), $title); 56 } 57 58 return hsprintf( 59 '<div class="phabricator-search-result">'. 60 '%s'. 61 '<div class="result-desc">'. 62 '%s'. 63 '<div class="result-type">%s · %s</div>'. 64 '</div>'. 65 '<div style="clear: both;"></div>'. 66 '</div>', 67 $img, 68 phutil_tag( 69 'a', 70 array( 71 'class' => 'result-name', 72 'href' => $handle->getURI(), 73 ), 74 $title), 75 $type_name, 76 $link); 77 } 78 79 80 /** 81 * Find the words which are part of the query string, and bold them in a 82 * result string. This makes it easier for users to see why a result 83 * matched their query. 84 */ 85 private function emboldenQuery($str) { 86 $query = $this->query->getParameter('query'); 87 88 if (!strlen($query) || !strlen($str)) { 89 return $str; 90 } 91 92 // This algorithm is safe but not especially fast, so don't bother if 93 // we're dealing with a lot of data. This mostly prevents silly/malicious 94 // queries from doing anything bad. 95 if (strlen($query) + strlen($str) > 2048) { 96 return $str; 97 } 98 99 // Keep track of which characters we're going to make bold. This is 100 // byte oriented, but we'll make sure we don't put a bold in the middle 101 // of a character later. 102 $bold = array_fill(0, strlen($str), false); 103 104 // Split the query into words. 105 $parts = preg_split('/ +/', $query); 106 107 // Find all occurrences of each word, and mark them to be emboldened. 108 foreach ($parts as $part) { 109 $part = trim($part); 110 $part = trim($part, '"+'); 111 if (!strlen($part)) { 112 continue; 113 } 114 115 $matches = null; 116 $has_matches = preg_match_all( 117 '/(?:^|\b)('.preg_quote($part, '/').')/i', 118 $str, 119 $matches, 120 PREG_OFFSET_CAPTURE); 121 122 if (!$has_matches) { 123 continue; 124 } 125 126 // Flag the matching part of the range for boldening. 127 foreach ($matches[1] as $match) { 128 $offset = $match[1]; 129 for ($ii = 0; $ii < strlen($match[0]); $ii++) { 130 $bold[$offset + $ii] = true; 131 } 132 } 133 } 134 135 // Split the string into ranges, applying bold styling as required. 136 $out = array(); 137 $buf = ''; 138 $pos = 0; 139 $is_bold = false; 140 foreach (phutil_utf8v($str) as $chr) { 141 if ($bold[$pos] != $is_bold) { 142 if (strlen($buf)) { 143 if ($is_bold) { 144 $out[] = phutil_tag('strong', array(), $buf); 145 } else { 146 $out[] = $buf; 147 } 148 $buf = ''; 149 } 150 $is_bold = !$is_bold; 151 } 152 $buf .= $chr; 153 $pos += strlen($chr); 154 } 155 156 if (strlen($buf)) { 157 if ($is_bold) { 158 $out[] = phutil_tag('strong', array(), $buf); 159 } else { 160 $out[] = $buf; 161 } 162 } 163 164 return $out; 165 } 166 167 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |