@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
3final class PhabricatorActionView extends AphrontView {
4
5 private $name;
6 private $icon;
7 private $href;
8 private $disabled;
9 private $label;
10 private $workflow;
11 private $renderAsForm;
12 private $download;
13 private $sigils = array();
14 private $metadata;
15 private $selected;
16 private $openInNewWindow;
17 private $submenu = array();
18 private $hidden;
19 private $depth;
20 private $id;
21 private $order;
22 private $color;
23 private $type;
24
25 const TYPE_DIVIDER = 'type-divider';
26 const TYPE_LABEL = 'label';
27 const RED = 'action-item-red';
28 const GREEN = 'action-item-green';
29
30 public function setSelected($selected) {
31 $this->selected = $selected;
32 return $this;
33 }
34
35 public function getSelected() {
36 return $this->selected;
37 }
38
39 public function setMetadata($metadata) {
40 $this->metadata = $metadata;
41 return $this;
42 }
43
44 public function getMetadata() {
45 return $this->metadata;
46 }
47
48 public function setDownload($download) {
49 $this->download = $download;
50 return $this;
51 }
52
53 public function getDownload() {
54 return $this->download;
55 }
56
57 public function setHref($href) {
58 $this->href = $href;
59 return $this;
60 }
61
62 public function setColor($color) {
63 $this->color = $color;
64 return $this;
65 }
66
67 public function addSigil($sigil) {
68 $this->sigils[] = $sigil;
69 return $this;
70 }
71
72 public function getHref() {
73 return $this->href;
74 }
75
76 public function setIcon($icon) {
77 $this->icon = $icon;
78 return $this;
79 }
80
81 public function setName($name) {
82 $this->name = $name;
83 return $this;
84 }
85
86 public function getName() {
87 return $this->name;
88 }
89
90 public function setLabel($label) {
91 $this->label = $label;
92 return $this;
93 }
94
95 public function setDisabled($disabled) {
96 $this->disabled = $disabled;
97 return $this;
98 }
99
100 public function getDisabled() {
101 return $this->disabled;
102 }
103
104 /**
105 * @param bool $workflow
106 * @return $this
107 */
108 public function setWorkflow($workflow) {
109 $this->workflow = $workflow;
110 return $this;
111 }
112
113 public function setRenderAsForm($form) {
114 $this->renderAsForm = $form;
115 return $this;
116 }
117
118 public function setOpenInNewWindow($open_in_new_window) {
119 $this->openInNewWindow = $open_in_new_window;
120 return $this;
121 }
122
123 public function getOpenInNewWindow() {
124 return $this->openInNewWindow;
125 }
126
127 public function setID($id) {
128 $this->id = $id;
129 return $this;
130 }
131
132 public function getID() {
133 if (!$this->id) {
134 $this->id = celerity_generate_unique_node_id();
135 }
136 return $this->id;
137 }
138
139 public function setOrder($order) {
140 $this->order = $order;
141 return $this;
142 }
143
144 public function getOrder() {
145 return $this->order;
146 }
147
148 public function setType($type) {
149 $this->type = $type;
150 return $this;
151 }
152
153 public function getType() {
154 return $this->type;
155 }
156
157 public function setSubmenu(array $submenu) {
158 $this->submenu = $submenu;
159
160 if (!$this->getHref()) {
161 $this->setHref('#');
162 }
163
164 return $this;
165 }
166
167 public function getItems($depth = 0) {
168 $items = array();
169
170 $items[] = $this;
171 foreach ($this->submenu as $action) {
172 foreach ($action->getItems($depth + 1) as $item) {
173 $item
174 ->setHidden(true)
175 ->setDepth($depth + 1);
176
177 $items[] = $item;
178 }
179 }
180
181 return $items;
182 }
183
184 public function setHidden($hidden) {
185 $this->hidden = $hidden;
186 return $this;
187 }
188
189 public function getHidden() {
190 return $this->hidden;
191 }
192
193 public function setDepth($depth) {
194 $this->depth = $depth;
195 return $this;
196 }
197
198 public function getDepth() {
199 return $this->depth;
200 }
201
202 public function render() {
203 $caret_id = celerity_generate_unique_node_id();
204
205 $icon = null;
206 if ($this->icon) {
207 $color = '';
208 if ($this->disabled) {
209 $color = ' grey';
210 }
211 $icon = id(new PHUIIconView())
212 ->addClass('phabricator-action-view-icon')
213 ->setIcon($this->icon.$color);
214 }
215
216 $sigils = array();
217 if ($this->workflow) {
218 $sigils[] = 'workflow';
219 }
220
221 if ($this->download) {
222 $sigils[] = 'download';
223 }
224
225 if ($this->submenu) {
226 $sigils[] = 'keep-open';
227 }
228
229 if ($this->sigils) {
230 $sigils = array_merge($sigils, $this->sigils);
231 }
232
233 $sigils = $sigils ? implode(' ', $sigils) : null;
234
235 if ($this->href) {
236 if ($this->renderAsForm) {
237 if (!$this->hasViewer()) {
238 throw new Exception(
239 pht(
240 'Call %s when rendering an action as a form.',
241 'setViewer()'));
242 }
243
244 $item = javelin_tag(
245 'button',
246 array(
247 'class' => 'phabricator-action-view-item',
248 ),
249 array($icon, $this->name));
250
251 $item = phabricator_form(
252 $this->getViewer(),
253 array(
254 'action' => $this->getHref(),
255 'method' => 'POST',
256 'sigil' => $sigils,
257 'meta' => $this->metadata,
258 ),
259 $item);
260 } else {
261 if ($this->getOpenInNewWindow()) {
262 $target = '_blank';
263 $rel = 'noreferrer';
264 } else {
265 $target = null;
266 $rel = null;
267 }
268
269 if ($this->submenu) {
270 $caret = javelin_tag(
271 'span',
272 array(
273 'class' => 'caret-right',
274 'id' => $caret_id,
275 ),
276 '');
277 } else {
278 $caret = null;
279 }
280
281 $item = javelin_tag(
282 'a',
283 array(
284 'href' => $this->getHref(),
285 'class' => 'phabricator-action-view-item',
286 'target' => $target,
287 'rel' => $rel,
288 'sigil' => $sigils,
289 'meta' => $this->metadata,
290 ),
291 array($icon, $this->name, $caret));
292 }
293 } else {
294 $item = javelin_tag(
295 'span',
296 array(
297 'class' => 'phabricator-action-view-item',
298 'sigil' => $sigils,
299 ),
300 array($icon, $this->name, $this->renderChildren()));
301 }
302
303 $classes = array();
304 $classes[] = 'phabricator-action-view';
305
306 if ($this->disabled) {
307 $classes[] = 'phabricator-action-view-disabled';
308 }
309
310 if ($this->label) {
311 $classes[] = 'phabricator-action-view-label';
312 }
313
314 if ($this->selected) {
315 $classes[] = 'phabricator-action-view-selected';
316 }
317
318 if ($this->submenu) {
319 $classes[] = 'phabricator-action-view-submenu';
320 }
321
322 if ($this->getHref()) {
323 $classes[] = 'phabricator-action-view-href';
324 }
325
326 if ($this->icon) {
327 $classes[] = 'action-has-icon';
328 }
329
330 if ($this->color) {
331 $classes[] = $this->color;
332 }
333
334 if ($this->type) {
335 $classes[] = 'phabricator-action-view-'.$this->type;
336 }
337
338 $style = array();
339
340 if ($this->hidden) {
341 $style[] = 'display: none;';
342 }
343
344 if ($this->depth) {
345 $indent = ($this->depth * 16);
346 $style[] = "margin-left: {$indent}px;";
347 }
348
349 $sigil = null;
350 $meta = null;
351
352 if ($this->submenu) {
353 Javelin::initBehavior('phui-submenu');
354 $sigil = 'phui-submenu';
355
356 $item_ids = array();
357 foreach ($this->submenu as $subitem) {
358 $item_ids[] = $subitem->getID();
359 }
360
361 $meta = array(
362 'itemIDs' => $item_ids,
363 'caretID' => $caret_id,
364 );
365 }
366
367 return javelin_tag(
368 'li',
369 array(
370 'id' => $this->getID(),
371 'class' => implode(' ', $classes),
372 'style' => implode(' ', $style),
373 'sigil' => $sigil,
374 'meta' => $meta,
375 ),
376 $item);
377 }
378
379}