@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 PholioInlineController extends PholioController {
4
5 public function handleRequest(AphrontRequest $request) {
6 $viewer = $request->getViewer();
7 $id = $request->getURIData('id');
8
9 if ($id) {
10 $inline = id(new PholioTransactionComment())->load($id);
11
12 if (!$inline) {
13 return new Aphront404Response();
14 }
15
16 if ($inline->getTransactionPHID()) {
17 $mode = 'view';
18 } else {
19 if ($inline->getAuthorPHID() == $viewer->getPHID()) {
20 $mode = 'edit';
21 } else {
22 return new Aphront404Response();
23 }
24 }
25 } else {
26 $mock = id(new PholioMockQuery())
27 ->setViewer($viewer)
28 ->withIDs(array($request->getInt('mockID')))
29 ->executeOne();
30
31 if (!$mock) {
32 return new Aphront404Response();
33 }
34
35 $inline = id(new PholioTransactionComment())
36 ->setImageID($request->getInt('imageID'))
37 ->setX($request->getInt('startX'))
38 ->setY($request->getInt('startY'))
39 ->setCommentVersion(1)
40 ->setAuthorPHID($viewer->getPHID())
41 ->setEditPolicy($viewer->getPHID())
42 ->setViewPolicy(PhabricatorPolicies::POLICY_PUBLIC)
43 ->setContentSourceFromRequest($request)
44 ->setWidth($request->getInt('endX') - $request->getInt('startX'))
45 ->setHeight($request->getInt('endY') - $request->getInt('startY'));
46
47 $mode = 'new';
48 }
49
50 $v_content = $inline->getContent();
51
52 // TODO: Not correct, but we don't always have a mock right now.
53 $mock_uri = '/';
54
55 if ($mode == 'view') {
56 require_celerity_resource('pholio-inline-comments-css');
57 $image = id(new PholioImageQuery())
58 ->setViewer($viewer)
59 ->withIDs(array($inline->getImageID()))
60 ->executeOne();
61
62 $handles = $this->loadViewerHandles(array($inline->getAuthorPHID()));
63 $author_handle = $handles[$inline->getAuthorPHID()];
64
65 $file = $image->getFile();
66 if (!$file->isViewableImage()) {
67 throw new Exception(pht('File is not viewable.'));
68 }
69
70 $image_uri = $file->getBestURI();
71
72 $thumb = id(new PHUIImageMaskView())
73 ->addClass('mrl')
74 ->setImage($image_uri)
75 ->setDisplayHeight(200)
76 ->setDisplayWidth(498)
77 ->withMask(true)
78 ->centerViewOnPoint(
79 $inline->getX(), $inline->getY(),
80 $inline->getHeight(), $inline->getWidth());
81
82 $comment_head = phutil_tag(
83 'div',
84 array(
85 'class' => 'pholio-inline-comment-head',
86 ),
87 $author_handle->renderLink());
88
89 $inline_content = new PHUIRemarkupView($viewer, $inline->getContent());
90 $comment_body = phutil_tag(
91 'div',
92 array(
93 'class' => 'pholio-inline-comment-body',
94 ),
95 $inline_content);
96
97 return $this->newDialog()
98 ->setTitle(pht('Inline Comment'))
99 ->appendChild($thumb)
100 ->appendChild($comment_head)
101 ->appendChild($comment_body)
102 ->addCancelButton($mock_uri, pht('Close'));
103 }
104
105 $error = null;
106 if ($request->isFormPost()) {
107 $v_content = $request->getStr('content');
108
109 if (strlen($v_content)) {
110 $inline->setContent($v_content);
111 $inline->save();
112 $dictionary = $inline->toDictionary();
113 } else if ($inline->getID()) {
114 $inline->delete();
115 $dictionary = array();
116 } else {
117 $error = pht('Comment cannot be empty.');
118 }
119
120 if ($error === null) {
121 return id(new AphrontAjaxResponse())->setContent($dictionary);
122 }
123 }
124
125 switch ($mode) {
126 case 'edit':
127 $title = pht('Edit Inline Comment');
128 $submit_text = pht('Save Draft');
129 break;
130 case 'new':
131 $title = pht('New Inline Comment');
132 $submit_text = pht('Save Draft');
133 break;
134 }
135
136 $form = id(new AphrontFormView())
137 ->setUser($viewer);
138
139 if ($mode == 'new') {
140 $params = array(
141 'mockID' => $request->getInt('mockID'),
142 'imageID' => $request->getInt('imageID'),
143 'startX' => $request->getInt('startX'),
144 'startY' => $request->getInt('startY'),
145 'endX' => $request->getInt('endX'),
146 'endY' => $request->getInt('endY'),
147 );
148 foreach ($params as $key => $value) {
149 $form->addHiddenInput($key, $value);
150 }
151 }
152
153 $form
154 ->appendChild(
155 id(new PhabricatorRemarkupControl())
156 ->setUser($viewer)
157 ->setName('content')
158 ->setLabel(pht('Comment'))
159 ->setError($error)
160 ->setValue($v_content));
161
162 return $this->newDialog()
163 ->setTitle($title)
164 ->setWidth(AphrontDialogView::WIDTH_FORM)
165 ->appendChild($form->buildLayoutView())
166 ->addCancelButton($mock_uri)
167 ->addSubmitButton($submit_text);
168 }
169
170}