@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<?php
2
3abstract class PhabricatorProjectUserListView
4 extends AphrontView {
5
6 private $project;
7 private $userPHIDs;
8 private $limit;
9 private $background;
10 private $showNote;
11
12 public function setProject(PhabricatorProject $project) {
13 $this->project = $project;
14 return $this;
15 }
16
17 public function getProject() {
18 return $this->project;
19 }
20
21 public function setUserPHIDs(array $user_phids) {
22 $this->userPHIDs = $user_phids;
23 return $this;
24 }
25
26 public function getUserPHIDs() {
27 return $this->userPHIDs;
28 }
29
30 public function setLimit($limit) {
31 $this->limit = $limit;
32 return $this;
33 }
34
35 public function getLimit() {
36 return $this->limit;
37 }
38
39 public function setBackground($color) {
40 $this->background = $color;
41 return $this;
42 }
43
44 public function setShowNote($show) {
45 $this->showNote = $show;
46 return $this;
47 }
48
49 abstract protected function canEditList();
50 abstract protected function getNoDataString();
51 abstract protected function getRemoveURI($phid);
52 abstract protected function getHeaderText();
53 abstract protected function getMembershipNote();
54
55 public function render() {
56 $viewer = $this->getViewer();
57 $project = $this->getProject();
58 $user_phids = $this->getUserPHIDs();
59
60 $can_edit = $this->canEditList();
61 $supports_edit = $project->supportsEditMembers();
62 $no_data = $this->getNoDataString();
63
64 $list = id(new PHUIObjectItemListView())
65 ->setNoDataString($no_data);
66
67 $limit = $this->getLimit();
68 $is_panel = (bool)$limit;
69
70 $handles = $viewer->loadHandles($user_phids);
71
72 // Reorder users in display order. We're going to put the viewer first
73 // if they're a member, then enabled users, then disabled/invalid users.
74
75 $phid_map = array();
76 foreach ($user_phids as $user_phid) {
77 $handle = $handles[$user_phid];
78
79 $is_viewer = ($user_phid === $viewer->getPHID());
80 $is_enabled = ($handle->isComplete() && !$handle->isDisabled());
81
82 // If we're showing the main member list, show oldest to newest. If we're
83 // showing only a slice in a panel, show newest to oldest.
84 if ($limit) {
85 $order_scalar = 1;
86 } else {
87 $order_scalar = -1;
88 }
89
90 // If viewer is an admin, list enabled accounts with MFA before others.
91 if ($viewer->getIsAdmin()) {
92 $has_mfa = $handle->getUserIsEnrolledInMultiFactor() && $is_enabled;
93 $phid_map[$user_phid] = id(new PhutilSortVector())
94 ->addInt($is_viewer ? 0 : 1)
95 ->addInt($has_mfa ? 0 : 1)
96 ->addInt($is_enabled ? 0 : 1)
97 ->addInt($order_scalar * count($phid_map));
98 } else {
99 $phid_map[$user_phid] = id(new PhutilSortVector())
100 ->addInt($is_viewer ? 0 : 1)
101 ->addInt($is_enabled ? 0 : 1)
102 ->addInt($order_scalar * count($phid_map));
103 }
104 }
105 $phid_map = msortv($phid_map, 'getSelf');
106
107 $handles = iterator_to_array($handles);
108 $handles = array_select_keys($handles, array_keys($phid_map));
109
110 if ($limit) {
111 $handles = array_slice($handles, 0, $limit);
112 }
113
114 foreach ($handles as $user_phid => $handle) {
115 $item = id(new PHUIObjectItemView())
116 ->setHeader($handle->getFullName())
117 ->setHref($handle->getURI())
118 ->setImageURI($handle->getImageURI());
119
120 if ($handle->isDisabled()) {
121 if ($is_panel) {
122 // Don't show disabled users in the panel view at all.
123 continue;
124 }
125
126 $item
127 ->setDisabled(true)
128 ->addIcon('fa-ban', pht('Disabled'));
129 }
130
131 $icon = id(new PHUIIconView())
132 ->setIcon($handle->getIcon());
133
134 $subtitle = $handle->getSubtitle();
135
136 $item->addAttribute(array($icon, ' ', $subtitle));
137
138 if ($viewer->getIsAdmin() && $handle->getUserIsEnrolledInMultiFactor()) {
139 $item->addIcon('fa-lock', pht('Has MFA'));
140 }
141
142 if ($supports_edit && !$is_panel) {
143 $remove_uri = $this->getRemoveURI($user_phid);
144
145 $item->addAction(
146 id(new PHUIListItemView())
147 ->setIcon('fa-times')
148 ->setName(pht('Remove'))
149 ->setHref($remove_uri)
150 ->setDisabled(!$can_edit)
151 ->setWorkflow(true));
152 }
153
154 $list->addItem($item);
155 }
156
157 if ($user_phids) {
158 $header_text = pht(
159 '%s (%s)',
160 $this->getHeaderText(),
161 phutil_count($user_phids));
162 } else {
163 $header_text = $this->getHeaderText();
164 }
165
166 $id = $project->getID();
167
168 $header = id(new PHUIHeaderView())
169 ->setHeader($header_text);
170
171 if ($limit) {
172 $list->newTailButton()
173 ->setText(pht('View All'))
174 ->setHref("/project/members/{$id}/");
175 }
176
177 $box = id(new PHUIObjectBoxView())
178 ->setHeader($header)
179 ->setObjectList($list);
180
181 if ($this->showNote) {
182 if ($this->getMembershipNote()) {
183 $info = id(new PHUIInfoView())
184 ->setSeverity(PHUIInfoView::SEVERITY_PLAIN)
185 ->appendChild($this->getMembershipNote());
186 $box->setInfoView($info);
187 }
188 }
189
190 if ($this->background) {
191 $box->setBackground($this->background);
192 }
193
194 return $box;
195 }
196
197}