@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 PhabricatorProjectTriggerEditController
4 extends PhabricatorProjectTriggerController {
5
6 public function handleRequest(AphrontRequest $request) {
7 $request = $this->getRequest();
8 $viewer = $request->getViewer();
9
10 $id = $request->getURIData('id');
11 if ($id) {
12 $trigger = id(new PhabricatorProjectTriggerQuery())
13 ->setViewer($viewer)
14 ->withIDs(array($id))
15 ->requireCapabilities(
16 array(
17 PhabricatorPolicyCapability::CAN_VIEW,
18 PhabricatorPolicyCapability::CAN_EDIT,
19 ))
20 ->executeOne();
21 if (!$trigger) {
22 return new Aphront404Response();
23 }
24 } else {
25 $trigger = PhabricatorProjectTrigger::initializeNewTrigger();
26 }
27
28 $trigger->setViewer($viewer);
29
30 $column_phid = $request->getStr('columnPHID');
31 if ($column_phid) {
32 $column = id(new PhabricatorProjectColumnQuery())
33 ->setViewer($viewer)
34 ->withPHIDs(array($column_phid))
35 ->requireCapabilities(
36 array(
37 PhabricatorPolicyCapability::CAN_VIEW,
38 PhabricatorPolicyCapability::CAN_EDIT,
39 ))
40 ->executeOne();
41 if (!$column) {
42 return new Aphront404Response();
43 }
44 $board_uri = $column->getWorkboardURI();
45 } else {
46 $column = null;
47 $board_uri = null;
48 }
49
50 if ($board_uri) {
51 $cancel_uri = $board_uri;
52 } else if ($trigger->getID()) {
53 $cancel_uri = $trigger->getURI();
54 } else {
55 $cancel_uri = $this->getApplicationURI('trigger/');
56 }
57
58 $v_name = $trigger->getName();
59 $v_edit = $trigger->getEditPolicy();
60 $v_rules = $trigger->getTriggerRules();
61
62 $e_name = null;
63 $e_edit = null;
64
65 $validation_exception = null;
66 if ($request->isFormPost()) {
67 try {
68 $v_name = $request->getStr('name');
69 $v_edit = $request->getStr('editPolicy');
70
71 // Read the JSON rules from the request and convert them back into
72 // "TriggerRule" objects so we can render the correct form state
73 // if the user is modifying the rules
74 $raw_rules = $request->getStr('rules');
75 $raw_rules = phutil_json_decode($raw_rules);
76
77 $copy = clone $trigger;
78 $copy->setRuleset($raw_rules);
79 $v_rules = $copy->getTriggerRules();
80
81 $xactions = array();
82 if (!$trigger->getID()) {
83 $xactions[] = $trigger->getApplicationTransactionTemplate()
84 ->setTransactionType(PhabricatorTransactions::TYPE_CREATE)
85 ->setNewValue(true);
86 }
87
88 $xactions[] = $trigger->getApplicationTransactionTemplate()
89 ->setTransactionType(
90 PhabricatorProjectTriggerNameTransaction::TRANSACTIONTYPE)
91 ->setNewValue($v_name);
92
93 $xactions[] = $trigger->getApplicationTransactionTemplate()
94 ->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
95 ->setNewValue($v_edit);
96
97 $xactions[] = $trigger->getApplicationTransactionTemplate()
98 ->setTransactionType(
99 PhabricatorProjectTriggerRulesetTransaction::TRANSACTIONTYPE)
100 ->setNewValue($raw_rules);
101
102 $editor = $trigger->getApplicationTransactionEditor()
103 ->setActor($viewer)
104 ->setContentSourceFromRequest($request)
105 ->setContinueOnNoEffect(true);
106
107 $editor->applyTransactions($trigger, $xactions);
108
109 $next_uri = $trigger->getURI();
110
111 if ($column) {
112 $column_xactions = array();
113
114 $column_xactions[] = $column->getApplicationTransactionTemplate()
115 ->setTransactionType(
116 PhabricatorProjectColumnTriggerTransaction::TRANSACTIONTYPE)
117 ->setNewValue($trigger->getPHID());
118
119 $column_editor = $column->getApplicationTransactionEditor()
120 ->setActor($viewer)
121 ->setContentSourceFromRequest($request)
122 ->setContinueOnNoEffect(true)
123 ->setContinueOnMissingFields(true);
124
125 $column_editor->applyTransactions($column, $column_xactions);
126
127 $next_uri = $column->getWorkboardURI();
128 }
129
130 return id(new AphrontRedirectResponse())->setURI($next_uri);
131 } catch (PhabricatorApplicationTransactionValidationException $ex) {
132 $validation_exception = $ex;
133
134 $e_name = $ex->getShortMessage(
135 PhabricatorProjectTriggerNameTransaction::TRANSACTIONTYPE);
136
137 $e_edit = $ex->getShortMessage(
138 PhabricatorTransactions::TYPE_EDIT_POLICY);
139
140 $trigger->setEditPolicy($v_edit);
141 }
142 }
143
144 if ($trigger->getID()) {
145 $title = $trigger->getObjectName();
146 $submit = pht('Save Trigger');
147 $header = pht('Edit Trigger: %s', $trigger->getObjectName());
148 } else {
149 $title = pht('New Trigger');
150 $submit = pht('Create Trigger');
151 $header = pht('New Trigger');
152 }
153
154 $form_id = celerity_generate_unique_node_id();
155 $table_id = celerity_generate_unique_node_id();
156 $create_id = celerity_generate_unique_node_id();
157 $input_id = celerity_generate_unique_node_id();
158
159 $form = id(new AphrontFormView())
160 ->setViewer($viewer)
161 ->setID($form_id);
162
163 if ($column) {
164 $form->addHiddenInput('columnPHID', $column->getPHID());
165 }
166
167 $form->appendControl(
168 id(new AphrontFormTextControl())
169 ->setLabel(pht('Name'))
170 ->setName('name')
171 ->setValue($v_name)
172 ->setError($e_name)
173 ->setPlaceholder($trigger->getDefaultName()));
174
175 $policies = id(new PhabricatorPolicyQuery())
176 ->setViewer($viewer)
177 ->setObject($trigger)
178 ->execute();
179
180 $form->appendControl(
181 id(new AphrontFormPolicyControl())
182 ->setName('editPolicy')
183 ->setPolicyObject($trigger)
184 ->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
185 ->setPolicies($policies)
186 ->setError($e_edit));
187
188 $form->appendChild(
189 phutil_tag(
190 'input',
191 array(
192 'type' => 'hidden',
193 'name' => 'rules',
194 'id' => $input_id,
195 )));
196
197 $form->appendChild(
198 id(new PHUIFormInsetView())
199 ->setTitle(pht('Rules'))
200 ->setDescription(
201 pht(
202 'When a card is dropped into a column which uses this trigger:'))
203 ->setRightButton(
204 javelin_tag(
205 'a',
206 array(
207 'href' => '#',
208 'class' => 'button button-green',
209 'id' => $create_id,
210 'mustcapture' => true,
211 ),
212 pht('New Rule')))
213 ->setContent(
214 javelin_tag(
215 'table',
216 array(
217 'id' => $table_id,
218 'class' => 'trigger-rules-table',
219 ))));
220
221 $this->setupEditorBehavior(
222 $trigger,
223 $v_rules,
224 $form_id,
225 $table_id,
226 $create_id,
227 $input_id);
228
229 $form->appendControl(
230 id(new AphrontFormSubmitControl())
231 ->setValue($submit)
232 ->addCancelButton($cancel_uri));
233
234 $header = id(new PHUIHeaderView())
235 ->setHeader($header);
236
237 $box_view = id(new PHUIObjectBoxView())
238 ->setHeader($header)
239 ->setValidationException($validation_exception)
240 ->appendChild($form);
241
242 $column_view = id(new PHUITwoColumnView())
243 ->setFooter($box_view);
244
245 $crumbs = $this->buildApplicationCrumbs()
246 ->setBorder(true);
247
248 if ($column) {
249 $crumbs->addTextCrumb(
250 pht(
251 '%s: %s',
252 $column->getProject()->getDisplayName(),
253 $column->getName()),
254 $board_uri);
255 }
256
257 $crumbs->addTextCrumb($title);
258
259 return $this->newPage()
260 ->setTitle($title)
261 ->setCrumbs($crumbs)
262 ->appendChild($column_view);
263 }
264
265 private function setupEditorBehavior(
266 PhabricatorProjectTrigger $trigger,
267 array $rule_list,
268 $form_id,
269 $table_id,
270 $create_id,
271 $input_id) {
272
273 $rule_list = mpull($rule_list, 'toDictionary');
274 $rule_list = array_values($rule_list);
275
276 $type_list = PhabricatorProjectTriggerRule::getAllTriggerRules();
277
278 foreach ($type_list as $rule) {
279 $rule->setViewer($this->getViewer());
280 }
281 $type_list = mpull($type_list, 'newTemplate');
282 $type_list = array_values($type_list);
283
284 require_celerity_resource('project-triggers-css');
285
286 Javelin::initBehavior(
287 'trigger-rule-editor',
288 array(
289 'formNodeID' => $form_id,
290 'tableNodeID' => $table_id,
291 'createNodeID' => $create_id,
292 'inputNodeID' => $input_id,
293
294 'rules' => $rule_list,
295 'types' => $type_list,
296 ));
297 }
298
299}