@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 PholioMockViewController extends PholioController {
4
5 private $maniphestTaskPHIDs = array();
6
7 private function setManiphestTaskPHIDs($maniphest_task_phids) {
8 $this->maniphestTaskPHIDs = $maniphest_task_phids;
9 return $this;
10 }
11 private function getManiphestTaskPHIDs() {
12 return $this->maniphestTaskPHIDs;
13 }
14
15 public function shouldAllowPublic() {
16 return true;
17 }
18
19 public function handleRequest(AphrontRequest $request) {
20 $viewer = $request->getViewer();
21 $id = $request->getURIData('id');
22 $image_id = $request->getURIData('imageID');
23
24 $mock = id(new PholioMockQuery())
25 ->setViewer($viewer)
26 ->withIDs(array($id))
27 ->needImages(true)
28 ->needInlineComments(true)
29 ->executeOne();
30
31 if (!$mock) {
32 return new Aphront404Response();
33 }
34
35 $phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
36 $mock->getPHID(),
37 PholioMockHasTaskEdgeType::EDGECONST);
38 $this->setManiphestTaskPHIDs($phids);
39
40 $title = $mock->getName();
41
42 if ($mock->isClosed()) {
43 $header_icon = 'fa-ban';
44 $header_name = pht('Closed');
45 $header_color = 'dark';
46 } else {
47 $header_icon = 'fa-square-o';
48 $header_name = pht('Open');
49 $header_color = 'bluegrey';
50 }
51
52 $header = id(new PHUIHeaderView())
53 ->setHeader($title)
54 ->setViewer($viewer)
55 ->setStatus($header_icon, $header_color, $header_name)
56 ->setPolicyObject($mock)
57 ->setHeaderIcon('fa-camera-retro');
58
59 $timeline = $this->buildTransactionTimeline(
60 $mock,
61 new PholioTransactionQuery());
62 $timeline->setMock($mock);
63
64 $timeline->setQuoteRef($mock->getMonogram());
65
66 $curtain = $this->buildCurtainView($mock);
67 $details = $this->buildDescriptionView($mock);
68
69 require_celerity_resource('pholio-css');
70 require_celerity_resource('pholio-inline-comments-css');
71
72 $comment_form_id = celerity_generate_unique_node_id();
73 $mock_view = id(new PholioMockImagesView())
74 ->setRequestURI($request->getRequestURI())
75 ->setCommentFormID($comment_form_id)
76 ->setViewer($viewer)
77 ->setMock($mock)
78 ->setImageID($image_id);
79
80 $output = id(new PHUIObjectBoxView())
81 ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
82 ->appendChild($mock_view);
83
84 $add_comment = $this->buildAddCommentView($mock, $comment_form_id);
85 $add_comment->setTransactionTimeline($timeline);
86
87 $crumbs = $this->buildApplicationCrumbs();
88 $crumbs->addTextCrumb($mock->getMonogram(), $mock->getURI());
89 $crumbs->setBorder(true);
90
91 $thumb_grid = id(new PholioMockThumbGridView())
92 ->setViewer($viewer)
93 ->setMock($mock);
94
95 $view = id(new PHUITwoColumnView())
96 ->setHeader($header)
97 ->setCurtain($curtain)
98 ->setMainColumn(
99 array(
100 $output,
101 $thumb_grid,
102 $details,
103 $timeline,
104 $add_comment,
105 ));
106
107 return $this->newPage()
108 ->setTitle(pht('%s %s', $mock->getMonogram(), $title))
109 ->setCrumbs($crumbs)
110 ->setPageObjectPHIDs(array($mock->getPHID()))
111 ->addQuicksandConfig(
112 array('mockViewConfig' => $mock_view->getBehaviorConfig()))
113 ->appendChild($view);
114 }
115
116 private function buildCurtainView(PholioMock $mock) {
117 $viewer = $this->getViewer();
118
119 $curtain = $this->newCurtainView($mock);
120
121 $can_edit = PhabricatorPolicyFilter::hasCapability(
122 $viewer,
123 $mock,
124 PhabricatorPolicyCapability::CAN_EDIT);
125
126 $curtain->addAction(
127 id(new PhabricatorActionView())
128 ->setIcon('fa-pencil')
129 ->setName(pht('Edit Mock'))
130 ->setHref($this->getApplicationURI('/edit/'.$mock->getID().'/'))
131 ->setDisabled(!$can_edit)
132 ->setWorkflow(!$can_edit));
133
134 if ($mock->isClosed()) {
135 $curtain->addAction(
136 id(new PhabricatorActionView())
137 ->setIcon('fa-check')
138 ->setName(pht('Open Mock'))
139 ->setHref($this->getApplicationURI('/archive/'.$mock->getID().'/'))
140 ->setDisabled(!$can_edit)
141 ->setWorkflow(true));
142 } else {
143 $curtain->addAction(
144 id(new PhabricatorActionView())
145 ->setIcon('fa-ban')
146 ->setName(pht('Close Mock'))
147 ->setHref($this->getApplicationURI('/archive/'.$mock->getID().'/'))
148 ->setDisabled(!$can_edit)
149 ->setWorkflow(true));
150 }
151
152 $relationship_list = PhabricatorObjectRelationshipList::newForObject(
153 $viewer,
154 $mock);
155
156 $relationship_submenu = $relationship_list->newActionMenu();
157 if ($relationship_submenu) {
158 $curtain->addAction($relationship_submenu);
159 }
160
161 if ($this->getManiphestTaskPHIDs()) {
162 $curtain->newPanel()
163 ->setHeaderText(pht('Maniphest Tasks'))
164 ->appendChild(
165 $viewer->renderHandleList($this->getManiphestTaskPHIDs()));
166 }
167
168 $curtain->newPanel()
169 ->setHeaderText(pht('Authored By'))
170 ->appendChild($this->buildAuthorPanel($mock));
171
172 return $curtain;
173 }
174
175 private function buildDescriptionView(PholioMock $mock) {
176 $viewer = $this->getViewer();
177
178 $properties = id(new PHUIPropertyListView())
179 ->setViewer($viewer);
180 $description = $mock->getDescription();
181
182 if (strlen($description)) {
183 $properties->addTextContent(
184 new PHUIRemarkupView($viewer, $description));
185 return id(new PHUIObjectBoxView())
186 ->setHeaderText(pht('Mock Description'))
187 ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
188 ->appendChild($properties);
189 }
190
191 return null;
192 }
193
194 private function buildAuthorPanel(PholioMock $mock) {
195 $viewer = $this->getViewer();
196 $author_phid = $mock->getAuthorPHID();
197 $handles = $viewer->loadHandles(array($author_phid));
198
199 $author_uri = $handles[$author_phid]->getImageURI();
200 $author_href = $handles[$author_phid]->getURI();
201 $author = $viewer->renderHandle($author_phid)->render();
202
203 $content = phutil_tag('strong', array(), $author);
204 $date = phabricator_date($mock->getDateCreated(), $viewer);
205 $content = pht('%s, %s', $content, $date);
206 $authored_by = id(new PHUIHeadThingView())
207 ->setImage($author_uri)
208 ->setImageHref($author_href)
209 ->setContent($content);
210
211 return $authored_by;
212 }
213
214 private function buildAddCommentView(PholioMock $mock, $comment_form_id) {
215 $viewer = $this->getViewer();
216
217 $draft = PhabricatorDraft::newFromUserAndKey($viewer, $mock->getPHID());
218
219 $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
220 $title = $is_serious
221 ? pht('Add Comment')
222 : pht('History Beckons');
223
224 $form = id(new PhabricatorApplicationTransactionCommentView())
225 ->setViewer($viewer)
226 ->setObject($mock)
227 ->setFormID($comment_form_id)
228 ->setDraft($draft)
229 ->setHeaderText($title)
230 ->setSubmitButtonName(pht('Add Comment'))
231 ->setAction($this->getApplicationURI('/comment/'.$mock->getID().'/'))
232 ->setRequestURI($this->getRequest()->getRequestURI());
233
234 return $form;
235 }
236
237}