@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.

Move People to SearchFields

Summary:
Ref T8441. Ref T7715. This is the second of three ApplicationSearch + CustomField use cases (Maniphest is the third).

Also add a way to set a default ordering for the fields.

Test Plan:
- Performed searches with each field.
- Added a custom field and searched for it.
- Observed desired ordering.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T7715, T8441

Differential Revision: https://secure.phabricator.com/D13190

+148 -158
+78 -155
src/applications/people/query/PhabricatorPeopleSearchEngine.php
··· 11 11 return 'PhabricatorPeopleApplication'; 12 12 } 13 13 14 - public function getCustomFieldObject() { 14 + public function newResultObject() { 15 15 return new PhabricatorUser(); 16 16 } 17 17 18 - public function buildSavedQueryFromRequest(AphrontRequest $request) { 19 - $saved = new PhabricatorSavedQuery(); 18 + protected function buildCustomSearchFields() { 19 + return array( 20 + id(new PhabricatorSearchStringListField()) 21 + ->setLabel(pht('Usernames')) 22 + ->setKey('usernames') 23 + ->setAliases(array('username')), 24 + id(new PhabricatorSearchTextField()) 25 + ->setLabel(pht('Name Contains')) 26 + ->setKey('nameLike'), 27 + id(new PhabricatorSearchThreeStateField()) 28 + ->setLabel(pht('Administrators')) 29 + ->setKey('isAdmin') 30 + ->setOptions( 31 + pht('(Show All)'), 32 + pht('Show Only Administrators'), 33 + pht('Hide Administrators')), 34 + id(new PhabricatorSearchThreeStateField()) 35 + ->setLabel(pht('Disabled')) 36 + ->setKey('isDisabled') 37 + ->setOptions( 38 + pht('(Show All)'), 39 + pht('Show Only Disabled Users'), 40 + pht('Hide Disabled Users')), 41 + id(new PhabricatorSearchThreeStateField()) 42 + ->setLabel(pht('Bots')) 43 + ->setKey('isSystemAgent') 44 + ->setOptions( 45 + pht('(Show All)'), 46 + pht('Show Only Bots'), 47 + pht('Hide Bots')), 48 + id(new PhabricatorSearchThreeStateField()) 49 + ->setLabel(pht('Mailing Lists')) 50 + ->setKey('isMailingList') 51 + ->setOptions( 52 + pht('(Show All)'), 53 + pht('Show Only Mailing Lists'), 54 + pht('Hide Mailing Lists')), 55 + id(new PhabricatorSearchThreeStateField()) 56 + ->setLabel(pht('Needs Approval')) 57 + ->setKey('needsApproval') 58 + ->setOptions( 59 + pht('(Show All)'), 60 + pht('Show Only Unapproved Users'), 61 + pht('Hide Unappproved Users')), 62 + id(new PhabricatorSearchDateField()) 63 + ->setKey('createdStart') 64 + ->setLabel(pht('Joined After')), 65 + id(new PhabricatorSearchDateField()) 66 + ->setKey('createdEnd') 67 + ->setLabel(pht('Joined Before')), 68 + ); 69 + } 20 70 21 - $saved->setParameter('usernames', $request->getStrList('usernames')); 22 - $saved->setParameter('nameLike', $request->getStr('nameLike')); 23 - 24 - $saved->setParameter( 25 - 'isAdmin', 26 - $this->readBoolFromRequest($request, 'isAdmin')); 27 - 28 - $saved->setParameter( 29 - 'isDisabled', 30 - $this->readBoolFromRequest($request, 'isDisabled')); 31 - 32 - $saved->setParameter( 33 - 'isSystemAgent', 34 - $this->readBoolFromRequest($request, 'isSystemAgent')); 35 - 36 - $saved->setParameter( 37 - 'isMailingList', 38 - $this->readBoolFromRequest($request, 'isMailingList')); 39 - 40 - $saved->setParameter( 41 - 'needsApproval', 42 - $this->readBoolFromRequest($request, 'needsApproval')); 43 - 44 - $saved->setParameter('createdStart', $request->getStr('createdStart')); 45 - $saved->setParameter('createdEnd', $request->getStr('createdEnd')); 46 - 47 - $this->readCustomFieldsFromRequest($request, $saved); 48 - 49 - return $saved; 71 + protected function getDefaultFieldOrder() { 72 + return array( 73 + '...', 74 + 'createdStart', 75 + 'createdEnd', 76 + ); 50 77 } 51 78 52 - public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { 79 + public function buildQueryFromParameters(array $map) { 53 80 $query = id(new PhabricatorPeopleQuery()) 54 81 ->needPrimaryEmail(true) 55 82 ->needProfileImage(true); ··· 68 95 $query->withPHIDs(array($viewer->getPHID())); 69 96 } 70 97 71 - $usernames = $saved->getParameter('usernames', array()); 72 - if ($usernames) { 73 - $query->withUsernames($usernames); 98 + if ($map['usernames']) { 99 + $query->withUsernames($map['usernames']); 74 100 } 75 101 76 - $like = $saved->getParameter('nameLike'); 77 - if ($like) { 78 - $query->withNameLike($like); 102 + if ($map['nameLike']) { 103 + $query->withNameLike($map['nameLike']); 79 104 } 80 105 81 - $is_admin = $saved->getParameter('isAdmin'); 82 - $is_disabled = $saved->getParameter('isDisabled'); 83 - $is_system_agent = $saved->getParameter('isSystemAgent'); 84 - $is_mailing_list = $saved->getParameter('isMailingList'); 85 - $needs_approval = $saved->getParameter('needsApproval'); 86 - 87 - if ($is_admin !== null) { 88 - $query->withIsAdmin($is_admin); 106 + if ($map['isAdmin'] !== null) { 107 + $query->withIsAdmin($map['isAdmin']); 89 108 } 90 109 91 - if ($is_disabled !== null) { 92 - $query->withIsDisabled($is_disabled); 110 + if ($map['isDisabled'] !== null) { 111 + $query->withIsDisabled($map['isDisabled']); 93 112 } 94 113 95 - if ($is_system_agent !== null) { 96 - $query->withIsSystemAgent($is_system_agent); 114 + if ($map['isMailingList'] !== null) { 115 + $query->withIsMailingList($map['isMailingList']); 97 116 } 98 117 99 - if ($is_mailing_list !== null) { 100 - $query->withIsMailingList($is_mailing_list); 118 + if ($map['isSystemAgent'] !== null) { 119 + $query->withIsSystemAgent($map['isSystemAgent']); 101 120 } 102 121 103 - if ($needs_approval !== null) { 104 - $query->withIsApproved(!$needs_approval); 122 + if ($map['needsApproval'] !== null) { 123 + $query->withIsApproved(!$map['needsApproval']); 105 124 } 106 125 107 - $start = $this->parseDateTime($saved->getParameter('createdStart')); 108 - $end = $this->parseDateTime($saved->getParameter('createdEnd')); 109 - 110 - if ($start) { 111 - $query->withDateCreatedAfter($start); 126 + if ($map['createdStart']) { 127 + $query->withDateCreatedAfter($map['createdStart']); 112 128 } 113 129 114 - if ($end) { 115 - $query->withDateCreatedBefore($end); 130 + if ($map['createdEnd']) { 131 + $query->withDateCreatedBefore($map['createdEnd']); 116 132 } 117 133 118 - $this->applyCustomFieldsToQuery($query, $saved); 119 - 120 134 return $query; 121 - } 122 - 123 - public function buildSearchForm( 124 - AphrontFormView $form, 125 - PhabricatorSavedQuery $saved) { 126 - 127 - $usernames = $saved->getParameter('usernames', array()); 128 - $like = $saved->getParameter('nameLike'); 129 - 130 - $is_admin = $this->getBoolFromQuery($saved, 'isAdmin'); 131 - $is_disabled = $this->getBoolFromQuery($saved, 'isDisabled'); 132 - $is_system_agent = $this->getBoolFromQuery($saved, 'isSystemAgent'); 133 - $is_mailing_list = $this->getBoolFromQuery($saved, 'isMailingList'); 134 - $needs_approval = $this->getBoolFromQuery($saved, 'needsApproval'); 135 - 136 - $form 137 - ->appendChild( 138 - id(new AphrontFormTextControl()) 139 - ->setName('usernames') 140 - ->setLabel(pht('Usernames')) 141 - ->setValue(implode(', ', $usernames))) 142 - ->appendChild( 143 - id(new AphrontFormTextControl()) 144 - ->setName('nameLike') 145 - ->setLabel(pht('Name Contains')) 146 - ->setValue($like)) 147 - ->appendChild( 148 - id(new AphrontFormSelectControl()) 149 - ->setName('isAdmin') 150 - ->setLabel(pht('Administrators')) 151 - ->setValue($is_admin) 152 - ->setOptions( 153 - array( 154 - '' => pht('(Show All)'), 155 - 'true' => pht('Show Only Administrators'), 156 - 'false' => pht('Hide Administrators'), 157 - ))) 158 - ->appendChild( 159 - id(new AphrontFormSelectControl()) 160 - ->setName('isDisabled') 161 - ->setLabel(pht('Disabled')) 162 - ->setValue($is_disabled) 163 - ->setOptions( 164 - array( 165 - '' => pht('(Show All)'), 166 - 'true' => pht('Show Only Disabled Users'), 167 - 'false' => pht('Hide Disabled Users'), 168 - ))) 169 - ->appendChild( 170 - id(new AphrontFormSelectControl()) 171 - ->setName('isSystemAgent') 172 - ->setLabel(pht('Bots')) 173 - ->setValue($is_system_agent) 174 - ->setOptions( 175 - array( 176 - '' => pht('(Show All)'), 177 - 'true' => pht('Show Only Bots'), 178 - 'false' => pht('Hide Bots'), 179 - ))) 180 - ->appendChild( 181 - id(new AphrontFormSelectControl()) 182 - ->setName('isMailingList') 183 - ->setLabel(pht('Mailing Lists')) 184 - ->setValue($is_mailing_list) 185 - ->setOptions( 186 - array( 187 - '' => pht('(Show All)'), 188 - 'true' => pht('Show Only Mailing Lists'), 189 - 'false' => pht('Hide Mailing Lists'), 190 - ))) 191 - ->appendChild( 192 - id(new AphrontFormSelectControl()) 193 - ->setName('needsApproval') 194 - ->setLabel(pht('Needs Approval')) 195 - ->setValue($needs_approval) 196 - ->setOptions( 197 - array( 198 - '' => pht('(Show All)'), 199 - 'true' => pht('Show Only Unapproved Users'), 200 - 'false' => pht('Hide Unapproved Users'), 201 - ))); 202 - 203 - $this->appendCustomFieldsToForm($form, $saved); 204 - 205 - $this->buildDateRange( 206 - $form, 207 - $saved, 208 - 'createdStart', 209 - pht('Joined After'), 210 - 'createdEnd', 211 - pht('Joined Before')); 212 135 } 213 136 214 137 protected function getURI($path) {
+70 -3
src/applications/search/engine/PhabricatorApplicationSearchEngine.php
··· 200 200 $fields[] = $custom_field; 201 201 } 202 202 203 - return $fields; 203 + $field_map = array(); 204 + foreach ($fields as $field) { 205 + $key = $field->getKey(); 206 + if (isset($field_map[$key])) { 207 + throw new Exception( 208 + pht( 209 + 'Two fields in this SearchEngine use the same key ("%s"), but '. 210 + 'each field must use a unique key.', 211 + $key)); 212 + } 213 + $field_map[$key] = $field; 214 + } 215 + 216 + return $this->adjustFieldsForDisplay($field_map); 217 + } 218 + 219 + private function adjustFieldsForDisplay(array $field_map) { 220 + $order = $this->getDefaultFieldOrder(); 221 + 222 + $head_keys = array(); 223 + $tail_keys = array(); 224 + $seen_tail = false; 225 + foreach ($order as $order_key) { 226 + if ($order_key === '...') { 227 + $seen_tail = true; 228 + continue; 229 + } 230 + 231 + if (!$seen_tail) { 232 + $head_keys[] = $order_key; 233 + } else { 234 + $tail_keys[] = $order_key; 235 + } 236 + } 237 + 238 + $head = array_select_keys($field_map, $head_keys); 239 + $body = array_diff_key($field_map, array_fuse($tail_keys)); 240 + $tail = array_select_keys($field_map, $tail_keys); 241 + 242 + return $head + $body + $tail; 204 243 } 205 244 206 245 protected function buildCustomSearchFields() { 207 246 throw new PhutilMethodNotImplementedException(); 247 + } 248 + 249 + 250 + /** 251 + * Define the default display order for fields by returning a list of 252 + * field keys. 253 + * 254 + * You can use the special key `...` to mean "all unspecified fields go 255 + * here". This lets you easily put important fields at the top of the form, 256 + * standard fields in the middle of the form, and less important fields at 257 + * the bottom. 258 + * 259 + * For example, you might return a list like this: 260 + * 261 + * return array( 262 + * 'authorPHIDs', 263 + * 'reviewerPHIDs', 264 + * '...', 265 + * 'createdAfter', 266 + * 'createdBefore', 267 + * ); 268 + * 269 + * Any unspecified fields (including custom fields and fields added 270 + * automatically by infrastruture) will be put in the middle. 271 + * 272 + * @return list<string> Default ordering for field keys. 273 + */ 274 + protected function getDefaultFieldOrder() { 275 + return array(); 208 276 } 209 277 210 278 public function getErrors() { ··· 1101 1169 return 'custom:'.$field->getFieldIndex(); 1102 1170 } 1103 1171 1104 - 1105 - protected function buildCustomFieldSearchFields() { 1172 + private function buildCustomFieldSearchFields() { 1106 1173 $list = $this->getCustomFieldList(); 1107 1174 if (!$list) { 1108 1175 return array();