@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at recaptime-dev/main 330 lines 10 kB view raw
1<?php 2 3final class PhabricatorSearchApplicationSearchEngine 4 extends PhabricatorApplicationSearchEngine { 5 6 private $resultSet; 7 8 public function getResultTypeDescription() { 9 return pht('Fulltext Search Results'); 10 } 11 12 public function getApplicationClassName() { 13 return PhabricatorSearchApplication::class; 14 } 15 16 public function buildSavedQueryFromRequest(AphrontRequest $request) { 17 $saved = new PhabricatorSavedQuery(); 18 19 $saved->setParameter('query', $request->getStr('query')); 20 $saved->setParameter( 21 'statuses', 22 $this->readListFromRequest($request, 'statuses')); 23 $saved->setParameter( 24 'types', 25 $this->readListFromRequest($request, 'types')); 26 27 $saved->setParameter( 28 'authorPHIDs', 29 $this->readUsersFromRequest($request, 'authorPHIDs')); 30 31 $saved->setParameter( 32 'ownerPHIDs', 33 $this->readUsersFromRequest($request, 'ownerPHIDs')); 34 35 $saved->setParameter( 36 'subscriberPHIDs', 37 $this->readSubscribersFromRequest($request, 'subscriberPHIDs')); 38 39 $saved->setParameter( 40 'projectPHIDs', 41 $this->readPHIDsFromRequest($request, 'projectPHIDs')); 42 43 return $saved; 44 } 45 46 /** 47 * @param PhabricatorSavedQuery $saved 48 * @return PhabricatorSearchDocumentQuery 49 */ 50 public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { 51 $query = new PhabricatorSearchDocumentQuery(); 52 53 // Convert the saved query into a resolved form (without typeahead 54 // functions) which the fulltext search engines can execute. 55 $config = clone $saved; 56 $viewer = $this->requireViewer(); 57 58 $datasource = id(new PhabricatorPeopleOwnerDatasource()) 59 ->setViewer($viewer); 60 $owner_phids = $this->readOwnerPHIDs($config); 61 $owner_phids = $datasource->evaluateTokens($owner_phids); 62 foreach ($owner_phids as $key => $phid) { 63 if ($phid == PhabricatorPeopleNoOwnerDatasource::FUNCTION_TOKEN) { 64 $config->setParameter('withUnowned', true); 65 unset($owner_phids[$key]); 66 } 67 if ($phid == PhabricatorPeopleAnyOwnerDatasource::FUNCTION_TOKEN) { 68 $config->setParameter('withAnyOwner', true); 69 unset($owner_phids[$key]); 70 } 71 } 72 $config->setParameter('ownerPHIDs', $owner_phids); 73 74 75 $datasource = id(new PhabricatorPeopleUserFunctionDatasource()) 76 ->setViewer($viewer); 77 $author_phids = $config->getParameter('authorPHIDs', array()); 78 $author_phids = $datasource->evaluateTokens($author_phids); 79 $config->setParameter('authorPHIDs', $author_phids); 80 81 82 $datasource = id(new PhabricatorMetaMTAMailableFunctionDatasource()) 83 ->setViewer($viewer); 84 $subscriber_phids = $config->getParameter('subscriberPHIDs', array()); 85 $subscriber_phids = $datasource->evaluateTokens($subscriber_phids); 86 $config->setParameter('subscriberPHIDs', $subscriber_phids); 87 88 89 $query->withSavedQuery($config); 90 91 return $query; 92 } 93 94 public function buildSearchForm( 95 AphrontFormView $form, 96 PhabricatorSavedQuery $saved) { 97 98 $options = array(); 99 $author_value = null; 100 $owner_value = null; 101 $subscribers_value = null; 102 $project_value = null; 103 104 $author_phids = $saved->getParameter('authorPHIDs', array()); 105 $owner_phids = $this->readOwnerPHIDs($saved); 106 $subscriber_phids = $saved->getParameter('subscriberPHIDs', array()); 107 $project_phids = $saved->getParameter('projectPHIDs', array()); 108 109 $status_values = $saved->getParameter('statuses', array()); 110 $status_values = array_fuse($status_values); 111 112 $statuses = array( 113 PhabricatorSearchRelationship::RELATIONSHIP_OPEN => pht('Open'), 114 PhabricatorSearchRelationship::RELATIONSHIP_CLOSED => pht('Closed'), 115 ); 116 $status_control = id(new AphrontFormCheckboxControl()) 117 ->setLabel(pht('Item Status')); 118 foreach ($statuses as $status => $name) { 119 $status_control->addCheckbox( 120 'statuses[]', 121 $status, 122 $name, 123 isset($status_values[$status])); 124 } 125 126 $type_values = $saved->getParameter('types', array()); 127 $type_values = array_fuse($type_values); 128 129 $types_control = id(new AphrontFormTokenizerControl()) 130 ->setLabel(pht('Item Types')) 131 ->setName('types') 132 ->setDatasource(new PhabricatorSearchDocumentTypeDatasource()) 133 ->setValue($type_values); 134 135 $form 136 ->appendChild( 137 phutil_tag( 138 'input', 139 array( 140 'type' => 'hidden', 141 'name' => 'jump', 142 'value' => 'no', 143 ))) 144 ->appendChild( 145 id(new AphrontFormTextControl()) 146 ->setLabel(pht('Query')) 147 ->setName('query') 148 ->setValue($saved->getParameter('query'))) 149 ->appendChild($status_control) 150 ->appendControl($types_control) 151 ->appendControl( 152 id(new AphrontFormTokenizerControl()) 153 ->setName('authorPHIDs') 154 ->setLabel(pht('Authors')) 155 ->setDatasource(new PhabricatorPeopleUserFunctionDatasource()) 156 ->setValue($author_phids)) 157 ->appendControl( 158 id(new AphrontFormTokenizerControl()) 159 ->setName('ownerPHIDs') 160 ->setLabel(pht('Owners')) 161 ->setDatasource(new PhabricatorPeopleOwnerDatasource()) 162 ->setValue($owner_phids)) 163 ->appendControl( 164 id(new AphrontFormTokenizerControl()) 165 ->setName('subscriberPHIDs') 166 ->setLabel(pht('Subscribers')) 167 ->setDatasource(new PhabricatorMetaMTAMailableFunctionDatasource()) 168 ->setValue($subscriber_phids)) 169 ->appendControl( 170 id(new AphrontFormTokenizerControl()) 171 ->setName('projectPHIDs') 172 ->setLabel(pht('Project Tags')) 173 ->setDatasource(new PhabricatorProjectDatasource()) 174 ->setValue($project_phids)); 175 } 176 177 protected function getURI($path) { 178 return '/search/'.$path; 179 } 180 181 protected function getBuiltinQueryNames() { 182 return array( 183 'all' => pht('All Items'), 184 'open' => pht('Open Items'), 185 'open-tasks' => pht('Open Tasks'), 186 ); 187 } 188 189 /** 190 * @return PhabricatorSavedQuery 191 */ 192 public function buildSavedQueryFromBuiltin($query_key) { 193 $query = $this->newSavedQuery(); 194 $query->setQueryKey($query_key); 195 196 switch ($query_key) { 197 case 'all': 198 return $query; 199 case 'open': 200 return $query->setParameter('statuses', array('open')); 201 case 'open-tasks': 202 return $query 203 ->setParameter('statuses', array('open')) 204 ->setParameter('types', array(ManiphestTaskPHIDType::TYPECONST)); 205 } 206 207 return parent::buildSavedQueryFromBuiltin($query_key); 208 } 209 210 /** 211 * @return array<string,string> PHIDType and its description, for example 212 * 'TASK => Maniphest Task' or 'DREV => Differential Revision' 213 */ 214 public static function getIndexableDocumentTypes( 215 ?PhabricatorUser $viewer = null) { 216 217 // TODO: This is inelegant and not very efficient, but gets us reasonable 218 // results. It would be nice to do this more elegantly. 219 220 $objects = id(new PhutilClassMapQuery()) 221 ->setAncestorClass(PhabricatorFulltextInterface::class) 222 ->execute(); 223 224 $type_map = array(); 225 foreach ($objects as $object) { 226 $phid_type = phid_get_type($object->generatePHID()); 227 $type_map[$phid_type] = $object; 228 } 229 230 if ($viewer) { 231 $types = PhabricatorPHIDType::getAllInstalledTypes($viewer); 232 } else { 233 $types = PhabricatorPHIDType::getAllTypes(); 234 } 235 236 $results = array(); 237 foreach ($types as $type) { 238 $typeconst = $type->getTypeConstant(); 239 $object = idx($type_map, $typeconst); 240 if ($object) { 241 $results[$typeconst] = $type->getTypeName(); 242 } 243 } 244 245 asort($results); 246 247 return $results; 248 } 249 250 public function shouldUseOffsetPaging() { 251 return true; 252 } 253 254 /** 255 * @param array<string,PhabricatorObjectHandle> $results Array of pairs of 256 * the object's PHID as key and the corresponding PhabricatorObjectHandle 257 * @param PhabricatorSavedQuery $query 258 * @param array<string,PhabricatorObjectHandle> $handles Unused. 259 */ 260 protected function renderResultList( 261 array $results, 262 PhabricatorSavedQuery $query, 263 array $handles) { 264 265 $result_set = $this->resultSet; 266 $fulltext_tokens = $result_set->getFulltextTokens(); 267 268 $viewer = $this->requireViewer(); 269 $list = new PHUIObjectItemListView(); 270 $list->setNoDataString(pht('No results found.')); 271 272 if ($results) { 273 $objects = id(new PhabricatorObjectQuery()) 274 ->setViewer($viewer) 275 ->withPHIDs(mpull($results, 'getPHID')) 276 ->execute(); 277 278 foreach ($results as $phid => $handle) { 279 $view = id(new PhabricatorSearchResultView()) 280 ->setHandle($handle) 281 ->setTokens($fulltext_tokens) 282 ->setObject(idx($objects, $phid)) 283 ->render(); 284 $list->addItem($view); 285 } 286 } 287 288 $fulltext_view = null; 289 if ($fulltext_tokens) { 290 require_celerity_resource('phabricator-search-results-css'); 291 292 $fulltext_view = array(); 293 foreach ($fulltext_tokens as $token) { 294 $fulltext_view[] = $token->newTag(); 295 } 296 $fulltext_view = phutil_tag( 297 'div', 298 array( 299 'class' => 'phui-fulltext-tokens', 300 ), 301 array( 302 pht('Searched For:'), 303 ' ', 304 $fulltext_view, 305 )); 306 } 307 308 $result = new PhabricatorApplicationSearchResultView(); 309 $result->setContent($fulltext_view); 310 $result->setObjectList($list); 311 312 return $result; 313 } 314 315 private function readOwnerPHIDs(PhabricatorSavedQuery $saved) { 316 $owner_phids = $saved->getParameter('ownerPHIDs', array()); 317 318 // This was an old checkbox from before typeahead functions. 319 if ($saved->getParameter('withUnowned')) { 320 $owner_phids[] = PhabricatorPeopleNoOwnerDatasource::FUNCTION_TOKEN; 321 } 322 323 return $owner_phids; 324 } 325 326 protected function didExecuteQuery(PhabricatorPolicyAwareQuery $query) { 327 $this->resultSet = $query->getFulltextResultSet(); 328 } 329 330}