@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 PhabricatorObjectSelectorDialog extends Phobject {
4
5 private $user;
6 private $filters = array();
7 private $handles = array();
8 private $cancelURI;
9 private $submitURI;
10 private $searchURI;
11 private $selectedFilter;
12 private $excluded;
13 private $initialPHIDs;
14 private $maximumSelectionSize;
15
16 private $title;
17 private $header;
18 private $buttonText;
19 private $instructions;
20
21 public function setUser($user) {
22 $this->user = $user;
23 return $this;
24 }
25
26 public function setFilters(array $filters) {
27 $this->filters = $filters;
28 return $this;
29 }
30
31 public function setSelectedFilter($selected_filter) {
32 $this->selectedFilter = $selected_filter;
33 return $this;
34 }
35
36 public function setExcluded($excluded_phid) {
37 $this->excluded = $excluded_phid;
38 return $this;
39 }
40
41 /**
42 * @param array<PhabricatorObjectHandle> $handles
43 */
44 public function setHandles(array $handles) {
45 assert_instances_of($handles, PhabricatorObjectHandle::class);
46 $this->handles = $handles;
47 return $this;
48 }
49
50 public function setCancelURI($cancel_uri) {
51 $this->cancelURI = $cancel_uri;
52 return $this;
53 }
54
55 public function setSubmitURI($submit_uri) {
56 $this->submitURI = $submit_uri;
57 return $this;
58 }
59
60 public function setSearchURI($search_uri) {
61 $this->searchURI = $search_uri;
62 return $this;
63 }
64
65 public function setTitle($title) {
66 $this->title = $title;
67 return $this;
68 }
69
70 public function setHeader($header) {
71 $this->header = $header;
72 return $this;
73 }
74
75 public function setButtonText($button_text) {
76 $this->buttonText = $button_text;
77 return $this;
78 }
79
80 public function setInstructions($instructions) {
81 $this->instructions = $instructions;
82 return $this;
83 }
84
85 public function setInitialPHIDs(array $initial_phids) {
86 $this->initialPHIDs = $initial_phids;
87 return $this;
88 }
89
90 public function getInitialPHIDs() {
91 return $this->initialPHIDs;
92 }
93
94 public function setMaximumSelectionSize($maximum_selection_size) {
95 $this->maximumSelectionSize = $maximum_selection_size;
96 return $this;
97 }
98
99 public function getMaximumSelectionSize() {
100 return $this->maximumSelectionSize;
101 }
102
103 public function buildDialog() {
104 $user = $this->user;
105
106 $filter_id = celerity_generate_unique_node_id();
107 $query_id = celerity_generate_unique_node_id();
108 $results_id = celerity_generate_unique_node_id();
109 $current_id = celerity_generate_unique_node_id();
110 $search_id = celerity_generate_unique_node_id();
111 $form_id = celerity_generate_unique_node_id();
112
113 require_celerity_resource('phabricator-object-selector-css');
114
115 $options = array();
116 foreach ($this->filters as $key => $label) {
117 $options[] = phutil_tag(
118 'option',
119 array(
120 'value' => $key,
121 'selected' => ($key == $this->selectedFilter)
122 ? 'selected'
123 : null,
124 ),
125 $label);
126 }
127
128 $instructions = null;
129 if ($this->instructions) {
130 $instructions = phutil_tag(
131 'p',
132 array('class' => 'phabricator-object-selector-instructions'),
133 $this->instructions);
134 }
135
136 $search_box = phabricator_form(
137 $user,
138 array(
139 'method' => 'POST',
140 'action' => $this->submitURI,
141 'id' => $search_id,
142 ),
143 phutil_tag(
144 'table',
145 array('class' => 'phabricator-object-selector-search'),
146 phutil_tag('tr', array(), array(
147 phutil_tag(
148 'td',
149 array('class' => 'phabricator-object-selector-search-filter'),
150 phutil_tag('select', array('id' => $filter_id), $options)),
151 phutil_tag(
152 'td',
153 array('class' => 'phabricator-object-selector-search-text'),
154 phutil_tag('input', array('id' => $query_id, 'type' => 'text'))),
155 ))));
156
157 $result_box = phutil_tag(
158 'div',
159 array(
160 'class' => 'phabricator-object-selector-results',
161 'id' => $results_id,
162 ),
163 '');
164
165 $attached_box = phutil_tag_div(
166 'phabricator-object-selector-current',
167 phutil_tag_div(
168 'phabricator-object-selector-currently-attached',
169 array(
170 phutil_tag_div('phabricator-object-selector-header', $this->header),
171 phutil_tag('div', array('id' => $current_id)),
172 $instructions,
173 )));
174
175 $dialog = new AphrontDialogView();
176 $dialog
177 ->setUser($this->user)
178 ->setTitle($this->title)
179 ->setClass('phabricator-object-selector-dialog')
180 ->appendChild($search_box)
181 ->appendChild($result_box)
182 ->appendChild($attached_box)
183 ->setRenderDialogAsDiv()
184 ->setFormID($form_id)
185 ->addSubmitButton($this->buttonText);
186
187 if ($this->cancelURI) {
188 $dialog->addCancelButton($this->cancelURI);
189 }
190
191 $handle_views = array();
192 foreach ($this->handles as $handle) {
193 $phid = $handle->getPHID();
194 $view = new PhabricatorHandleObjectSelectorDataView($handle);
195 $handle_views[$phid] = $view->renderData();
196 }
197
198 $dialog->addHiddenInput('phids', implode(';', array_keys($this->handles)));
199
200 $initial_phids = $this->getInitialPHIDs();
201 if ($initial_phids) {
202 $initial_phids = implode(', ', $initial_phids);
203 $dialog->addHiddenInput('initialPHIDs', $initial_phids);
204 }
205
206 $maximum = $this->getMaximumSelectionSize();
207
208 Javelin::initBehavior(
209 'phabricator-object-selector',
210 array(
211 'filter' => $filter_id,
212 'query' => $query_id,
213 'search' => $search_id,
214 'results' => $results_id,
215 'current' => $current_id,
216 'form' => $form_id,
217 'exclude' => $this->excluded,
218 'uri' => $this->searchURI,
219 'handles' => $handle_views,
220 'maximum' => $maximum,
221 ));
222
223 $dialog->setResizeX(true);
224 $dialog->setResizeY($results_id);
225
226 return $dialog;
227 }
228
229}