@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 PhabricatorProjectColumnEditController
4 extends PhabricatorProjectBoardController {
5
6 public function handleRequest(AphrontRequest $request) {
7 $viewer = $request->getViewer();
8 $id = $request->getURIData('id');
9 $project_id = $request->getURIData('projectID');
10
11 $project = id(new PhabricatorProjectQuery())
12 ->setViewer($viewer)
13 ->requireCapabilities(
14 array(
15 PhabricatorPolicyCapability::CAN_VIEW,
16 PhabricatorPolicyCapability::CAN_EDIT,
17 ))
18 ->withIDs(array($project_id))
19 ->needImages(true)
20 ->executeOne();
21
22 if (!$project) {
23 return new Aphront404Response();
24 }
25 $this->setProject($project);
26
27 $is_new = ($id ? false : true);
28
29 if (!$is_new) {
30 $column = id(new PhabricatorProjectColumnQuery())
31 ->setViewer($viewer)
32 ->withIDs(array($id))
33 ->requireCapabilities(
34 array(
35 PhabricatorPolicyCapability::CAN_VIEW,
36 PhabricatorPolicyCapability::CAN_EDIT,
37 ))
38 ->executeOne();
39 if (!$column) {
40 return new Aphront404Response();
41 }
42 } else {
43 $column = PhabricatorProjectColumn::initializeNewColumn($viewer);
44 }
45
46 $e_name = null;
47 $e_limit = null;
48 $e_milestone_name = null;
49
50 $v_limit = $column->getPointLimit();
51 $v_name = $column->getName();
52
53 $proxy = $column->getProxy();
54
55 // Is this a normal Column? Example: when true, this is not a Milestone.
56 $is_column = !$proxy;
57
58 // Is this a Milestone? Example: when true, this is not a normal Column.
59 $is_milestone = $proxy && $proxy->isMilestone();
60
61 // Milestone name, eventually coming from the proxed object.
62 $v_milestone_name = null;
63 if ($is_milestone) {
64 $v_milestone_name = $proxy->getName();
65 }
66
67 $validation_exception = null;
68 $view_uri = $project->getWorkboardURI();
69
70 if ($request->isFormPost()) {
71 $v_name = $request->getStr('name');
72 $v_limit = $request->getStr('limit');
73 $v_milestone_name = $request->getStr('milestone.name');
74
75 if ($is_new) {
76 $column->setProjectPHID($project->getPHID());
77 $column->attachProject($project);
78
79 $columns = id(new PhabricatorProjectColumnQuery())
80 ->setViewer($viewer)
81 ->withProjectPHIDs(array($project->getPHID()))
82 ->execute();
83
84 $new_sequence = 1;
85 if ($columns) {
86 $values = mpull($columns, 'getSequence');
87 $new_sequence = max($values) + 1;
88 }
89 $column->setSequence($new_sequence);
90 }
91
92 $xactions = array();
93 $xactions_milestone = array();
94
95 $type_name = PhabricatorProjectColumnNameTransaction::TRANSACTIONTYPE;
96 $type_limit = PhabricatorProjectColumnLimitTransaction::TRANSACTIONTYPE;
97 $type_project_name = PhabricatorProjectNameTransaction::TRANSACTIONTYPE;
98
99 if ($is_column) {
100 // Transaction for Column name.
101 $xactions[] = id(new PhabricatorProjectColumnTransaction())
102 ->setTransactionType($type_name)
103 ->setNewValue($v_name);
104 } else if ($is_milestone) {
105 // Transaction for Milestone name (that internally is a Project Name).
106 $xactions_milestone[] = id(new PhabricatorProjectTransaction())
107 ->setTransactionType($type_project_name)
108 ->setNewValue($v_milestone_name);
109 }
110
111 $xactions[] = id(new PhabricatorProjectColumnTransaction())
112 ->setTransactionType($type_limit)
113 ->setNewValue($v_limit);
114
115 try {
116 $editor = id(new PhabricatorProjectColumnTransactionEditor())
117 ->setActor($viewer)
118 ->setContinueOnNoEffect(true)
119 ->setContentSourceFromRequest($request)
120 ->applyTransactions($column, $xactions);
121 } catch (PhabricatorApplicationTransactionValidationException $ex) {
122 // Error messages related to the Column (like invalid Name, etc.)
123 $e_name = $ex->getShortMessage($type_name);
124 $e_limit = $ex->getShortMessage($type_limit);
125 $validation_exception = $ex;
126 }
127
128 // Save Milestone-related stuff but only if there were no prior problems
129 // and only if we have changes.
130 if (!$validation_exception && $xactions_milestone) {
131 try {
132 $editor_milestone = id(new PhabricatorProjectTransactionEditor())
133 ->setActor($viewer)
134 ->setContinueOnNoEffect(true)
135 ->setContentSourceFromRequest($request)
136 ->applyTransactions($proxy, $xactions_milestone);
137 } catch (PhabricatorApplicationTransactionValidationException $ex) {
138 // Error messages related to the Milestone (like invalid Name, etc.)
139 $e_milestone_name = $ex->getShortMessage($type_project_name);
140 $validation_exception = $ex;
141 }
142 }
143
144 // Refresh the page only if there are no errors to show.
145 if (!$validation_exception) {
146 return id(new AphrontRedirectResponse())->setURI($view_uri);
147 }
148 }
149
150 $form = id(new AphrontFormView())
151 ->setUser($request->getUser());
152
153 // Show the most appropriate input field for the name.
154 if ($is_column) {
155 $form->appendChild(
156 id(new AphrontFormTextControl())
157 ->setValue($v_name)
158 ->setLabel(pht('Name'))
159 ->setName('name')
160 ->setError($e_name));
161 } else if ($is_milestone) {
162 $form->appendChild(
163 id(new AphrontFormTextControl())
164 ->setValue($v_milestone_name)
165 ->setLabel(pht('Milestone Name'))
166 ->setName('milestone.name')
167 ->setError($e_milestone_name));
168 }
169
170 // The "limit" has always had a dual purpose.
171 // Let's make it more obvious.
172 if (ManiphestTaskPoints::getIsEnabled()) {
173 $limit_label = pht('Point Limit');
174 $limit_caption =
175 pht('Maximum number of points of tasks allowed in the column.');
176 } else {
177 $limit_label = pht('Count Limit');
178 $limit_caption = pht('Maximum number of tasks allowed in the column.');
179 }
180
181 $form->appendChild(
182 id(new AphrontFormTextControl())
183 ->setValue($v_limit)
184 ->setLabel($limit_label)
185 ->setName('limit')
186 ->setError($e_limit)
187 ->setCaption($limit_caption));
188
189 if ($is_new) {
190 $title = pht('Create Column');
191 $submit = pht('Create Column');
192 } else {
193 $title = pht('Edit %s', $column->getDisplayName());
194 $submit = pht('Save Column');
195 }
196
197 return $this->newDialog()
198 ->setWidth(AphrontDialogView::WIDTH_FORM)
199 ->setTitle($title)
200 ->appendForm($form)
201 ->setValidationException($validation_exception)
202 ->addCancelButton($view_uri)
203 ->addSubmitButton($submit);
204
205 }
206}