Correct Aphlict websocket URI construction after PHP8 compatibility changes
[phabricator.git] / src / applications / conpherence / controller / ConpherenceUpdateController.php
bloba792a5a4d45c140ef420cc9e20b2d09e74bc3fb4
1 <?php
3 final class ConpherenceUpdateController
4 extends ConpherenceController {
6 public function handleRequest(AphrontRequest $request) {
7 $user = $request->getUser();
8 $conpherence_id = $request->getURIData('id');
9 if (!$conpherence_id) {
10 return new Aphront404Response();
13 $need_participants = false;
14 $needed_capabilities = array(PhabricatorPolicyCapability::CAN_VIEW);
15 $action = $request->getStr('action');
16 switch ($action) {
17 case ConpherenceUpdateActions::REMOVE_PERSON:
18 $person_phid = $request->getStr('remove_person');
19 if ($person_phid != $user->getPHID()) {
20 $needed_capabilities[] = PhabricatorPolicyCapability::CAN_EDIT;
22 break;
23 case ConpherenceUpdateActions::ADD_PERSON:
24 $needed_capabilities[] = PhabricatorPolicyCapability::CAN_EDIT;
25 break;
26 case ConpherenceUpdateActions::LOAD:
27 break;
29 $conpherence = id(new ConpherenceThreadQuery())
30 ->setViewer($user)
31 ->withIDs(array($conpherence_id))
32 ->needParticipants($need_participants)
33 ->requireCapabilities($needed_capabilities)
34 ->executeOne();
36 $latest_transaction_id = null;
37 $response_mode = $request->isAjax() ? 'ajax' : 'redirect';
38 $error_view = null;
39 $e_file = array();
40 $errors = array();
41 $delete_draft = false;
42 $xactions = array();
43 if ($request->isFormPost() || ($action == ConpherenceUpdateActions::LOAD)) {
44 $editor = id(new ConpherenceEditor())
45 ->setContinueOnNoEffect($request->isContinueRequest())
46 ->setContentSourceFromRequest($request)
47 ->setActor($user);
49 switch ($action) {
50 case ConpherenceUpdateActions::DRAFT:
51 $draft = PhabricatorDraft::newFromUserAndKey(
52 $user,
53 $conpherence->getPHID());
54 $draft->setDraft($request->getStr('text'));
55 $draft->replaceOrDelete();
56 return new AphrontAjaxResponse();
57 case ConpherenceUpdateActions::JOIN_ROOM:
58 $xactions[] = id(new ConpherenceTransaction())
59 ->setTransactionType(
60 ConpherenceThreadParticipantsTransaction::TRANSACTIONTYPE)
61 ->setNewValue(array('+' => array($user->getPHID())));
62 $delete_draft = true;
63 $message = $request->getStr('text');
64 if ($message) {
65 $message_xactions = $editor->generateTransactionsFromText(
66 $user,
67 $conpherence,
68 $message);
69 $xactions = array_merge($xactions, $message_xactions);
71 // for now, just redirect back to the conpherence so everything
72 // will work okay...!
73 $response_mode = 'redirect';
74 break;
75 case ConpherenceUpdateActions::MESSAGE:
76 $message = $request->getStr('text');
77 if (strlen($message)) {
78 $xactions = $editor->generateTransactionsFromText(
79 $user,
80 $conpherence,
81 $message);
82 $delete_draft = true;
83 } else {
84 $action = ConpherenceUpdateActions::LOAD;
85 $updated = false;
86 $response_mode = 'ajax';
88 break;
89 case ConpherenceUpdateActions::ADD_PERSON:
90 $person_phids = $request->getArr('add_person');
91 if (!empty($person_phids)) {
92 $xactions[] = id(new ConpherenceTransaction())
93 ->setTransactionType(
94 ConpherenceThreadParticipantsTransaction::TRANSACTIONTYPE)
95 ->setNewValue(array('+' => $person_phids));
97 break;
98 case ConpherenceUpdateActions::REMOVE_PERSON:
99 if (!$request->isContinueRequest()) {
100 // do nothing; we'll display a confirmation dialog instead
101 break;
103 $person_phid = $request->getStr('remove_person');
104 if ($person_phid) {
105 $xactions[] = id(new ConpherenceTransaction())
106 ->setTransactionType(
107 ConpherenceThreadParticipantsTransaction::TRANSACTIONTYPE)
108 ->setNewValue(array('-' => array($person_phid)));
109 $response_mode = 'go-home';
111 break;
112 case ConpherenceUpdateActions::LOAD:
113 $updated = false;
114 $response_mode = 'ajax';
115 break;
116 default:
117 throw new Exception(pht('Unknown action: %s', $action));
118 break;
121 if ($xactions) {
122 try {
123 $xactions = $editor->applyTransactions($conpherence, $xactions);
124 if ($delete_draft) {
125 $draft = PhabricatorDraft::newFromUserAndKey(
126 $user,
127 $conpherence->getPHID());
128 $draft->delete();
130 } catch (PhabricatorApplicationTransactionNoEffectException $ex) {
131 return id(new PhabricatorApplicationTransactionNoEffectResponse())
132 ->setCancelURI($this->getApplicationURI($conpherence_id.'/'))
133 ->setException($ex);
135 // xactions had no effect...!
136 if (empty($xactions)) {
137 $errors[] = pht(
138 'That was a non-update. Try cancel.');
142 if ($xactions || ($action == ConpherenceUpdateActions::LOAD)) {
143 switch ($response_mode) {
144 case 'ajax':
145 $latest_transaction_id = $request->getInt('latest_transaction_id');
146 $content = $this->loadAndRenderUpdates(
147 $action,
148 $conpherence_id,
149 $latest_transaction_id);
150 return id(new AphrontAjaxResponse())
151 ->setContent($content);
152 break;
153 case 'go-home':
154 $content = array(
155 'href' => $this->getApplicationURI(),
157 return id(new AphrontAjaxResponse())
158 ->setContent($content);
159 break;
160 case 'redirect':
161 default:
162 return id(new AphrontRedirectResponse())
163 ->setURI('/'.$conpherence->getMonogram());
164 break;
169 if ($errors) {
170 $error_view = id(new PHUIInfoView())
171 ->setErrors($errors);
174 switch ($action) {
175 case ConpherenceUpdateActions::ADD_PERSON:
176 $dialog = $this->renderAddPersonDialog($conpherence);
177 break;
178 case ConpherenceUpdateActions::REMOVE_PERSON:
179 $dialog = $this->renderRemovePersonDialog($conpherence);
180 break;
183 return
184 $dialog
185 ->setUser($user)
186 ->setWidth(AphrontDialogView::WIDTH_FORM)
187 ->setSubmitURI($this->getApplicationURI('update/'.$conpherence_id.'/'))
188 ->addSubmitButton()
189 ->addCancelButton($this->getApplicationURI($conpherence->getID().'/'));
193 private function renderAddPersonDialog(
194 ConpherenceThread $conpherence) {
196 $request = $this->getRequest();
197 $user = $request->getUser();
198 $add_person = $request->getStr('add_person');
200 $form = id(new AphrontFormView())
201 ->setUser($user)
202 ->setFullWidth(true)
203 ->appendControl(
204 id(new AphrontFormTokenizerControl())
205 ->setName('add_person')
206 ->setUser($user)
207 ->setDatasource(new PhabricatorPeopleDatasource()));
209 $view = id(new AphrontDialogView())
210 ->setTitle(pht('Add Participants'))
211 ->addHiddenInput('action', 'add_person')
212 ->addHiddenInput(
213 'latest_transaction_id',
214 $request->getInt('latest_transaction_id'))
215 ->appendForm($form);
217 return $view;
220 private function renderRemovePersonDialog(
221 ConpherenceThread $conpherence) {
223 $request = $this->getRequest();
224 $viewer = $request->getUser();
225 $remove_person = $request->getStr('remove_person');
226 $participants = $conpherence->getParticipants();
228 $removed_user = id(new PhabricatorPeopleQuery())
229 ->setViewer($viewer)
230 ->withPHIDs(array($remove_person))
231 ->executeOne();
232 if (!$removed_user) {
233 return new Aphront404Response();
236 $is_self = ($viewer->getPHID() == $removed_user->getPHID());
237 $is_last = (count($participants) == 1);
239 $test_conpherence = clone $conpherence;
240 $test_conpherence->attachParticipants(array());
241 $still_visible = PhabricatorPolicyFilter::hasCapability(
242 $removed_user,
243 $test_conpherence,
244 PhabricatorPolicyCapability::CAN_VIEW);
246 $body = array();
248 if ($is_self) {
249 $title = pht('Leave Room');
250 $body[] = pht(
251 'Are you sure you want to leave this room?');
252 } else {
253 $title = pht('Remove Participant');
254 $body[] = pht(
255 'Remove %s from this room?',
256 phutil_tag('strong', array(), $removed_user->getUsername()));
259 if ($still_visible) {
260 if ($is_self) {
261 $body[] = pht(
262 'You will be able to rejoin the room later.');
263 } else {
264 $body[] = pht(
265 'They will be able to rejoin the room later.');
267 } else {
268 if ($is_self) {
269 if ($is_last) {
270 $body[] = pht(
271 'You are the last member, so you will never be able to rejoin '.
272 'the room.');
273 } else {
274 $body[] = pht(
275 'You will not be able to rejoin the room on your own, but '.
276 'someone else can invite you later.');
278 } else {
279 $body[] = pht(
280 'They will not be able to rejoin the room unless invited '.
281 'again.');
285 $dialog = id(new AphrontDialogView())
286 ->setTitle($title)
287 ->addHiddenInput('action', 'remove_person')
288 ->addHiddenInput('remove_person', $remove_person)
289 ->addHiddenInput(
290 'latest_transaction_id',
291 $request->getInt('latest_transaction_id'))
292 ->addHiddenInput('__continue__', true);
294 foreach ($body as $paragraph) {
295 $dialog->appendParagraph($paragraph);
298 return $dialog;
301 private function loadAndRenderUpdates(
302 $action,
303 $conpherence_id,
304 $latest_transaction_id) {
306 $need_transactions = false;
307 switch ($action) {
308 case ConpherenceUpdateActions::LOAD:
309 $need_transactions = true;
310 break;
311 case ConpherenceUpdateActions::MESSAGE:
312 case ConpherenceUpdateActions::ADD_PERSON:
313 $need_transactions = true;
314 break;
315 case ConpherenceUpdateActions::REMOVE_PERSON:
316 default:
317 break;
320 $user = $this->getRequest()->getUser();
321 $conpherence = id(new ConpherenceThreadQuery())
322 ->setViewer($user)
323 ->setAfterTransactionID($latest_transaction_id)
324 ->needProfileImage(true)
325 ->needParticipants(true)
326 ->needTransactions($need_transactions)
327 ->withIDs(array($conpherence_id))
328 ->executeOne();
330 $non_update = false;
331 $participant = $conpherence->getParticipant($user->getPHID());
333 if ($need_transactions && $conpherence->getTransactions()) {
334 $data = ConpherenceTransactionRenderer::renderTransactions(
335 $user,
336 $conpherence);
337 $key = PhabricatorConpherenceColumnMinimizeSetting::SETTINGKEY;
338 $minimized = $user->getUserSetting($key);
339 if (!$minimized) {
340 $participant->markUpToDate($conpherence);
342 } else if ($need_transactions) {
343 $non_update = true;
344 $data = array();
345 } else {
346 $data = array();
348 $rendered_transactions = idx($data, 'transactions');
349 $new_latest_transaction_id = idx($data, 'latest_transaction_id');
351 $update_uri = $this->getApplicationURI('update/'.$conpherence->getID().'/');
352 $nav_item = null;
353 $header = null;
354 $people_widget = null;
355 switch ($action) {
356 case ConpherenceUpdateActions::ADD_PERSON:
357 $people_widget = id(new ConpherenceParticipantView())
358 ->setUser($user)
359 ->setConpherence($conpherence)
360 ->setUpdateURI($update_uri);
361 $people_widget = hsprintf('%s', $people_widget->render());
362 break;
363 case ConpherenceUpdateActions::REMOVE_PERSON:
364 default:
365 break;
367 $data = $conpherence->getDisplayData($user);
368 $dropdown_query = id(new AphlictDropdownDataQuery())
369 ->setViewer($user);
370 $dropdown_query->execute();
372 $map = ConpherenceRoomSettings::getSoundMap();
373 $default_receive = ConpherenceRoomSettings::DEFAULT_RECEIVE_SOUND;
374 $receive_sound = $map[$default_receive]['rsrc'];
375 $mention_sound = null;
377 // Get the user's defaults if logged in
378 if ($participant) {
379 $sounds = $this->getSoundForParticipant($user, $participant);
380 $receive_sound = $sounds[ConpherenceRoomSettings::SOUND_RECEIVE];
381 $mention_sound = $sounds[ConpherenceRoomSettings::SOUND_MENTION];
384 $content = array(
385 'non_update' => $non_update,
386 'transactions' => hsprintf('%s', $rendered_transactions),
387 'conpherence_title' => (string)$data['title'],
388 'latest_transaction_id' => $new_latest_transaction_id,
389 'nav_item' => $nav_item,
390 'conpherence_phid' => $conpherence->getPHID(),
391 'header' => $header,
392 'people_widget' => $people_widget,
393 'aphlictDropdownData' => array(
394 $dropdown_query->getNotificationData(),
395 $dropdown_query->getConpherenceData(),
397 'sound' => array(
398 'receive' => $receive_sound,
399 'mention' => $mention_sound,
403 return $content;
406 protected function getSoundForParticipant(
407 PhabricatorUser $user,
408 ConpherenceParticipant $participant) {
410 $sound_key = PhabricatorConpherenceSoundSetting::SETTINGKEY;
411 $sound_default = $user->getUserSetting($sound_key);
413 $settings = $participant->getSettings();
414 $sounds = idx($settings, 'sounds', array());
415 $map = PhabricatorConpherenceSoundSetting::getDefaultSound($sound_default);
417 $receive = idx($sounds,
418 ConpherenceRoomSettings::SOUND_RECEIVE,
419 $map[ConpherenceRoomSettings::SOUND_RECEIVE]);
420 $mention = idx($sounds,
421 ConpherenceRoomSettings::SOUND_MENTION,
422 $map[ConpherenceRoomSettings::SOUND_MENTION]);
424 $sound_map = ConpherenceRoomSettings::getSoundMap();
426 return array(
427 ConpherenceRoomSettings::SOUND_RECEIVE => $sound_map[$receive]['rsrc'],
428 ConpherenceRoomSettings::SOUND_MENTION => $sound_map[$mention]['rsrc'],