3 final class PhabricatorPeopleSearchEngine
4 extends PhabricatorApplicationSearchEngine
{
6 public function getResultTypeDescription() {
10 public function getApplicationClassName() {
11 return 'PhabricatorPeopleApplication';
14 public function newQuery() {
15 return id(new PhabricatorPeopleQuery())
16 ->needPrimaryEmail(true)
17 ->needProfileImage(true);
20 protected function buildCustomSearchFields() {
22 id(new PhabricatorSearchStringListField())
23 ->setLabel(pht('Usernames'))
25 ->setAliases(array('username'))
26 ->setDescription(pht('Find users by exact username.')),
27 id(new PhabricatorSearchTextField())
28 ->setLabel(pht('Name Contains'))
31 pht('Find users whose usernames contain a substring.')),
32 id(new PhabricatorSearchThreeStateField())
33 ->setLabel(pht('Administrators'))
37 pht('Show Only Administrators'),
38 pht('Hide Administrators'))
41 'Pass true to find only administrators, or false to omit '.
43 id(new PhabricatorSearchThreeStateField())
44 ->setLabel(pht('Disabled'))
45 ->setKey('isDisabled')
48 pht('Show Only Disabled Users'),
49 pht('Hide Disabled Users'))
52 'Pass true to find only disabled users, or false to omit '.
54 id(new PhabricatorSearchThreeStateField())
55 ->setLabel(pht('Bots'))
57 ->setAliases(array('isSystemAgent'))
60 pht('Show Only Bots'),
64 'Pass true to find only bots, or false to omit bots.')),
65 id(new PhabricatorSearchThreeStateField())
66 ->setLabel(pht('Mailing Lists'))
67 ->setKey('isMailingList')
70 pht('Show Only Mailing Lists'),
71 pht('Hide Mailing Lists'))
74 'Pass true to find only mailing lists, or false to omit '.
76 id(new PhabricatorSearchThreeStateField())
77 ->setLabel(pht('Needs Approval'))
78 ->setKey('needsApproval')
81 pht('Show Only Unapproved Users'),
82 pht('Hide Unapproved Users'))
85 'Pass true to find only users awaiting administrative approval, '.
86 'or false to omit these users.')),
89 $viewer = $this->requireViewer();
90 if ($viewer->getIsAdmin()) {
91 $fields[] = id(new PhabricatorSearchThreeStateField())
92 ->setLabel(pht('Has MFA'))
96 pht('Show Only Users With MFA'),
97 pht('Hide Users With MFA'))
100 'Pass true to find only users who are enrolled in MFA, or false '.
101 'to omit these users.'));
104 $fields[] = id(new PhabricatorSearchDateField())
105 ->setKey('createdStart')
106 ->setLabel(pht('Joined After'))
108 pht('Find user accounts created after a given time.'));
110 $fields[] = id(new PhabricatorSearchDateField())
111 ->setKey('createdEnd')
112 ->setLabel(pht('Joined Before'))
114 pht('Find user accounts created before a given time.'));
119 protected function getDefaultFieldOrder() {
127 protected function buildQueryFromParameters(array $map) {
128 $query = $this->newQuery();
130 $viewer = $this->requireViewer();
132 // If the viewer can't browse the user directory, restrict the query to
133 // just the user's own profile. This is a little bit silly, but serves to
134 // restrict users from creating a dashboard panel which essentially just
135 // contains a user directory anyway.
136 $can_browse = PhabricatorPolicyFilter
::hasCapability(
138 $this->getApplication(),
139 PeopleBrowseUserDirectoryCapability
::CAPABILITY
);
141 $query->withPHIDs(array($viewer->getPHID()));
144 if ($map['usernames']) {
145 $query->withUsernames($map['usernames']);
148 if ($map['nameLike']) {
149 $query->withNameLike($map['nameLike']);
152 if ($map['isAdmin'] !== null) {
153 $query->withIsAdmin($map['isAdmin']);
156 if ($map['isDisabled'] !== null) {
157 $query->withIsDisabled($map['isDisabled']);
160 if ($map['isMailingList'] !== null) {
161 $query->withIsMailingList($map['isMailingList']);
164 if ($map['isBot'] !== null) {
165 $query->withIsSystemAgent($map['isBot']);
168 if ($map['needsApproval'] !== null) {
169 $query->withIsApproved(!$map['needsApproval']);
172 if (idx($map, 'mfa') !== null) {
173 $viewer = $this->requireViewer();
174 if (!$viewer->getIsAdmin()) {
175 throw new PhabricatorSearchConstraintException(
177 'The "Has MFA" query constraint may only be used by '.
178 'administrators, to prevent attackers from using it to target '.
182 $query->withIsEnrolledInMultiFactor($map['mfa']);
185 if ($map['createdStart']) {
186 $query->withDateCreatedAfter($map['createdStart']);
189 if ($map['createdEnd']) {
190 $query->withDateCreatedBefore($map['createdEnd']);
196 protected function getURI($path) {
197 return '/people/'.$path;
200 protected function getBuiltinQueryNames() {
202 'active' => pht('Active'),
206 $viewer = $this->requireViewer();
207 if ($viewer->getIsAdmin()) {
208 $names['approval'] = pht('Approval Queue');
214 public function buildSavedQueryFromBuiltin($query_key) {
215 $query = $this->newSavedQuery();
216 $query->setQueryKey($query_key);
218 switch ($query_key) {
223 ->setParameter('isDisabled', false);
226 ->setParameter('needsApproval', true)
227 ->setParameter('isDisabled', false);
230 return parent
::buildSavedQueryFromBuiltin($query_key);
233 protected function renderResultList(
235 PhabricatorSavedQuery
$query,
238 assert_instances_of($users, 'PhabricatorUser');
240 $request = $this->getRequest();
241 $viewer = $this->requireViewer();
243 $list = new PHUIObjectItemListView();
245 $is_approval = ($query->getQueryKey() == 'approval');
247 foreach ($users as $user) {
248 $primary_email = $user->loadPrimaryEmail();
249 if ($primary_email && $primary_email->getIsVerified()) {
250 $email = pht('Verified');
252 $email = pht('Unverified');
255 $item = new PHUIObjectItemView();
256 $item->setHeader($user->getFullName())
257 ->setHref('/p/'.$user->getUsername().'/')
258 ->addAttribute(phabricator_datetime($user->getDateCreated(), $viewer))
259 ->addAttribute($email)
260 ->setImageURI($user->getProfileImageURI());
262 if ($is_approval && $primary_email) {
263 $item->addAttribute($primary_email->getAddress());
266 if ($user->getIsDisabled()) {
267 $item->addIcon('fa-ban', pht('Disabled'));
268 $item->setDisabled(true);
272 if (!$user->getIsApproved()) {
273 $item->addIcon('fa-clock-o', pht('Needs Approval'));
277 if ($user->getIsAdmin()) {
278 $item->addIcon('fa-star', pht('Admin'));
281 if ($user->getIsSystemAgent()) {
282 $item->addIcon('fa-desktop', pht('Bot'));
285 if ($user->getIsMailingList()) {
286 $item->addIcon('fa-envelope-o', pht('Mailing List'));
289 if ($viewer->getIsAdmin()) {
290 if ($user->getIsEnrolledInMultiFactor()) {
291 $item->addIcon('fa-lock', pht('Has MFA'));
295 if ($viewer->getIsAdmin()) {
296 $user_id = $user->getID();
299 id(new PHUIListItemView())
301 ->setName(pht('Disable'))
303 ->setHref($this->getApplicationURI('disapprove/'.$user_id.'/')));
305 id(new PHUIListItemView())
306 ->setIcon('fa-thumbs-o-up')
307 ->setName(pht('Approve'))
309 ->setHref($this->getApplicationURI('approve/'.$user_id.'/')));
313 $list->addItem($item);
316 $result = new PhabricatorApplicationSearchResultView();
317 $result->setObjectList($list);
318 $result->setNoDataString(pht('No accounts found.'));
323 protected function newExportFields() {
325 id(new PhabricatorStringExportField())
327 ->setLabel(pht('Username')),
328 id(new PhabricatorStringExportField())
330 ->setLabel(pht('Real Name')),
334 protected function newExportData(array $users) {
335 $viewer = $this->requireViewer();
338 foreach ($users as $user) {
340 'username' => $user->getUsername(),
341 'realName' => $user->getRealName(),