diff --git a/src/applications/conpherence/__tests__/ConpherenceRoomTestCase.php b/src/applications/conpherence/__tests__/ConpherenceRoomTestCase.php index cd7912f280..b44873c931 100644 --- a/src/applications/conpherence/__tests__/ConpherenceRoomTestCase.php +++ b/src/applications/conpherence/__tests__/ConpherenceRoomTestCase.php @@ -1,144 +1,170 @@ true, ); } public function testOneUserRoomCreate() { $creator = $this->generateNewTestUser(); $participant_phids = array($creator->getPHID()); $conpherence = $this->createRoom($creator, $participant_phids); $this->assertTrue((bool)$conpherence->getID()); $this->assertEqual(1, count($conpherence->getParticipants())); $this->assertEqual( $participant_phids, $conpherence->getRecentParticipantPHIDs()); } public function testNUserRoomCreate() { $creator = $this->generateNewTestUser(); $friend_1 = $this->generateNewTestUser(); $friend_2 = $this->generateNewTestUser(); $friend_3 = $this->generateNewTestUser(); $participant_phids = array( $creator->getPHID(), $friend_1->getPHID(), $friend_2->getPHID(), $friend_3->getPHID(), ); $conpherence = $this->createRoom($creator, $participant_phids); $this->assertTrue((bool)$conpherence->getID()); $this->assertEqual(4, count($conpherence->getParticipants())); $this->assertEqual( $participant_phids, $conpherence->getRecentParticipantPHIDs()); } public function testRoomParticipantAddition() { $creator = $this->generateNewTestUser(); $friend_1 = $this->generateNewTestUser(); $friend_2 = $this->generateNewTestUser(); $friend_3 = $this->generateNewTestUser(); $participant_phids = array( $creator->getPHID(), $friend_1->getPHID(), ); $conpherence = $this->createRoom($creator, $participant_phids); $this->assertTrue((bool)$conpherence->getID()); $this->assertEqual(2, count($conpherence->getParticipants())); $this->assertEqual( $participant_phids, $conpherence->getRecentParticipantPHIDs()); // test add by creator $participant_phids[] = $friend_2->getPHID(); $this->addParticipants($creator, $conpherence, array($friend_2->getPHID())); $this->assertEqual( $participant_phids, $conpherence->getRecentParticipantPHIDs()); // test policy error as another user tries to add $caught = null; try { $this->addParticipants( $friend_2, $conpherence, array($friend_3->getPHID())); } catch (PhabricatorPolicyException $ex) { $caught = $ex; } $this->assertTrue($caught instanceof PhabricatorPolicyException); // update edit policy so user has a chance $this->changeEditPolicy($creator, $conpherence, 'users'); // test add by other participant, so recent participation should // meaningfully change $participant_phids = array( $friend_2->getPHID(), // actor $creator->getPHID(), // last actor $friend_1->getPHID(), $friend_3->getPHID(), // new addition ); $this->addParticipants( $friend_2, $conpherence, array($friend_3->getPHID())); $this->assertEqual( $participant_phids, $conpherence->getRecentParticipantPHIDs()); } + public function testRoomParticipantDeletion() { + $creator = $this->generateNewTestUser(); + $friend_1 = $this->generateNewTestUser(); + $friend_2 = $this->generateNewTestUser(); + $friend_3 = $this->generateNewTestUser(); + + $participant_map = array( + $creator->getPHID() => $creator, + $friend_1->getPHID() => $friend_1, + $friend_2->getPHID() => $friend_2, + $friend_3->getPHID() => $friend_3, + ); + + $conpherence = $this->createRoom( + $creator, + array_keys($participant_map)); + + foreach ($participant_map as $phid => $user) { + $this->removeParticipants($user, $conpherence, array($phid)); + unset($participant_map[$phid]); + $this->assertEqual( + count($participant_map), + count($conpherence->getParticipants())); + } + } + private function createRoom( PhabricatorUser $creator, array $participant_phids) { $conpherence = ConpherenceThread::initializeNewRoom($creator); $xactions = array(); $xactions[] = id(new ConpherenceTransaction()) ->setTransactionType(ConpherenceTransactionType::TYPE_PARTICIPANTS) ->setNewValue(array('+' => $participant_phids)); $xactions[] = id(new ConpherenceTransaction()) ->setTransactionType(ConpherenceTransactionType::TYPE_TITLE) ->setNewValue('Test'); id(new ConpherenceEditor()) ->setActor($creator) ->setContentSource(PhabricatorContentSource::newConsoleSource()) ->setContinueOnNoEffect(true) ->applyTransactions($conpherence, $xactions); return $conpherence; } private function changeEditPolicy( PhabricatorUser $actor, ConpherenceThread $room, $policy) { $xactions = array(); $xactions[] = id(new ConpherenceTransaction()) ->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY) ->setNewValue($policy); id(new ConpherenceEditor()) ->setActor($actor) ->setContentSource(PhabricatorContentSource::newConsoleSource()) ->setContinueOnNoEffect(true) ->applyTransactions($room, $xactions); } } diff --git a/src/applications/conpherence/__tests__/ConpherenceTestCase.php b/src/applications/conpherence/__tests__/ConpherenceTestCase.php index c3454f26df..ff7ddd5e5b 100644 --- a/src/applications/conpherence/__tests__/ConpherenceTestCase.php +++ b/src/applications/conpherence/__tests__/ConpherenceTestCase.php @@ -1,20 +1,35 @@ setTransactionType(ConpherenceTransactionType::TYPE_PARTICIPANTS) ->setNewValue(array('+' => $participant_phids)),); $editor = id(new ConpherenceEditor()) ->setActor($actor) ->setContentSource(PhabricatorContentSource::newConsoleSource()) ->applyTransactions($conpherence, $xactions); } + protected function removeParticipants( + PhabricatorUser $actor, + ConpherenceThread $conpherence, + array $participant_phids) { + + $xactions = array(id(new ConpherenceTransaction()) + ->setTransactionType(ConpherenceTransactionType::TYPE_PARTICIPANTS) + ->setNewValue(array('-' => $participant_phids)),); + $editor = id(new ConpherenceEditor()) + ->setActor($actor) + ->setContentSource(PhabricatorContentSource::newConsoleSource()) + ->applyTransactions($conpherence, $xactions); + } + + } diff --git a/src/applications/conpherence/__tests__/ConpherenceThreadTestCase.php b/src/applications/conpherence/__tests__/ConpherenceThreadTestCase.php index 928ce162e7..4ed21f2f26 100644 --- a/src/applications/conpherence/__tests__/ConpherenceThreadTestCase.php +++ b/src/applications/conpherence/__tests__/ConpherenceThreadTestCase.php @@ -1,102 +1,128 @@ true, ); } public function testOneUserThreadCreate() { $creator = $this->generateNewTestUser(); $participant_phids = array($creator->getPHID()); $conpherence = $this->createThread($creator, $participant_phids); $this->assertTrue((bool)$conpherence->getID()); $this->assertEqual(1, count($conpherence->getParticipants())); $this->assertEqual( $participant_phids, $conpherence->getRecentParticipantPHIDs()); } public function testNUserThreadCreate() { $creator = $this->generateNewTestUser(); $friend_1 = $this->generateNewTestUser(); $friend_2 = $this->generateNewTestUser(); $friend_3 = $this->generateNewTestUser(); $participant_phids = array( $creator->getPHID(), $friend_1->getPHID(), $friend_2->getPHID(), $friend_3->getPHID(), ); $conpherence = $this->createThread($creator, $participant_phids); $this->assertTrue((bool)$conpherence->getID()); $this->assertEqual(4, count($conpherence->getParticipants())); $this->assertEqual( $participant_phids, $conpherence->getRecentParticipantPHIDs()); } public function testThreadParticipantAddition() { $creator = $this->generateNewTestUser(); $friend_1 = $this->generateNewTestUser(); $friend_2 = $this->generateNewTestUser(); $friend_3 = $this->generateNewTestUser(); $participant_phids = array( $creator->getPHID(), $friend_1->getPHID(), ); $conpherence = $this->createThread($creator, $participant_phids); $this->assertTrue((bool)$conpherence->getID()); $this->assertEqual(2, count($conpherence->getParticipants())); $this->assertEqual( $participant_phids, $conpherence->getRecentParticipantPHIDs()); // test add by creator $participant_phids[] = $friend_2->getPHID(); $this->addParticipants($creator, $conpherence, array($friend_2->getPHID())); $this->assertEqual( $participant_phids, $conpherence->getRecentParticipantPHIDs()); // test add by other participant, so recent participation should // meaningfully change $participant_phids = array( $friend_2->getPHID(), // actor $creator->getPHID(), // last actor $friend_1->getPHID(), $friend_3->getPHID(), // new addition ); $this->addParticipants( $friend_2, $conpherence, array($friend_3->getPHID())); $this->assertEqual( $participant_phids, $conpherence->getRecentParticipantPHIDs()); } + public function testThreadParticipantDeletion() { + $creator = $this->generateNewTestUser(); + $friend_1 = $this->generateNewTestUser(); + $friend_2 = $this->generateNewTestUser(); + $friend_3 = $this->generateNewTestUser(); + + $participant_map = array( + $creator->getPHID() => $creator, + $friend_1->getPHID() => $friend_1, + $friend_2->getPHID() => $friend_2, + $friend_3->getPHID() => $friend_3, + ); + + $conpherence = $this->createThread( + $creator, + array_keys($participant_map)); + + foreach ($participant_map as $phid => $user) { + $this->removeParticipants($user, $conpherence, array($phid)); + unset($participant_map[$phid]); + $this->assertEqual( + count($participant_map), + count($conpherence->getParticipants())); + } + } + private function createThread( PhabricatorUser $creator, array $participant_phids) { list($errors, $conpherence) = ConpherenceEditor::createThread( $creator, $participant_phids, 'Test', 'Test', PhabricatorContentSource::newConsoleSource()); return $conpherence; } } diff --git a/src/applications/conpherence/controller/ConpherenceNewController.php b/src/applications/conpherence/controller/ConpherenceNewController.php index 24e3c80785..a08b105008 100644 --- a/src/applications/conpherence/controller/ConpherenceNewController.php +++ b/src/applications/conpherence/controller/ConpherenceNewController.php @@ -1,108 +1,107 @@ getRequest(); + public function handleRequest(AphrontRequest $request) { $user = $request->getUser(); $title = pht('New Message'); $participants = array(); $participant_prefill = null; $message = ''; $e_participants = null; $e_message = null; $errors = array(); // this comes from ajax requests from all over. should be a single phid. if ($request->isFormPost()) { $participants = $request->getArr('participants'); $message = $request->getStr('message'); list($error_codes, $conpherence) = ConpherenceEditor::createThread( $user, $participants, $conpherence_title = null, $message, PhabricatorContentSource::newFromRequest($request)); if ($error_codes) { foreach ($error_codes as $error_code) { switch ($error_code) { case ConpherenceEditor::ERROR_EMPTY_MESSAGE: $e_message = pht('Required'); $errors[] = pht( 'You can not send an empty message.'); break; case ConpherenceEditor::ERROR_EMPTY_PARTICIPANTS: $e_participants = pht('Required'); $errors[] = pht( 'You must choose at least one recipient for your '. 'message.'); break; } } } else { $uri = $this->getApplicationURI($conpherence->getID()); return id(new AphrontRedirectResponse()) ->setURI($uri); } } else { $participant_prefill = $request->getStr('participant'); if ($participant_prefill) { $participants[] = $participant_prefill; } } $participant_handles = array(); if ($participants) { $participant_handles = id(new PhabricatorHandleQuery()) ->setViewer($user) ->withPHIDs($participants) ->execute(); } $submit_uri = $this->getApplicationURI('new/'); $cancel_uri = $this->getApplicationURI(); // TODO - we can get a better cancel_uri once we get better at crazy // ajax jonx T2086 if ($participant_prefill) { $handle = $participant_handles[$participant_prefill]; $cancel_uri = $handle->getURI(); } $dialog = id(new AphrontDialogView()) ->setWidth(AphrontDialogView::WIDTH_FORM) ->setErrors($errors) ->setUser($user) ->setTitle($title) ->addCancelButton($cancel_uri) ->addSubmitButton(pht('Send Message')); $form = id(new PHUIFormLayoutView()) ->setUser($user) ->setFullWidth(true) ->appendChild( id(new AphrontFormTokenizerControl()) ->setName('participants') ->setValue($participant_handles) ->setUser($user) ->setDatasource(new PhabricatorPeopleDatasource()) ->setLabel(pht('To')) ->setError($e_participants)) ->appendChild( id(new PhabricatorRemarkupControl()) ->setUser($user) ->setName('message') ->setValue($message) ->setLabel(pht('Message')) ->setError($e_message)); $dialog->appendChild($form); return id(new AphrontDialogResponse())->setDialog($dialog); } } diff --git a/src/applications/conpherence/controller/ConpherenceNotificationPanelController.php b/src/applications/conpherence/controller/ConpherenceNotificationPanelController.php index c46b975c4b..91f8fb8ba4 100644 --- a/src/applications/conpherence/controller/ConpherenceNotificationPanelController.php +++ b/src/applications/conpherence/controller/ConpherenceNotificationPanelController.php @@ -1,101 +1,100 @@ getRequest(); + public function handleRequest(AphrontRequest $request) { $user = $request->getUser(); $conpherences = array(); $unread_status = ConpherenceParticipationStatus::BEHIND; $participant_data = id(new ConpherenceParticipantQuery()) ->withParticipantPHIDs(array($user->getPHID())) ->setLimit(5) ->execute(); if ($participant_data) { $conpherences = id(new ConpherenceThreadQuery()) ->setViewer($user) ->withPHIDs(array_keys($participant_data)) ->needParticipantCache(true) ->execute(); } if ($conpherences) { require_celerity_resource('conpherence-notification-css'); // re-order the conpherences based on participation data $conpherences = array_select_keys( $conpherences, array_keys($participant_data)); $view = new AphrontNullView(); foreach ($conpherences as $conpherence) { $p_data = $participant_data[$conpherence->getPHID()]; $d_data = $conpherence->getDisplayData($user); $classes = array( 'phabricator-notification', 'conpherence-notification', ); if ($p_data->getParticipationStatus() == $unread_status) { $classes[] = 'phabricator-notification-unread'; } $uri = $this->getApplicationURI($conpherence->getID().'/'); $title = $d_data['title']; $subtitle = $d_data['subtitle']; $unread_count = $d_data['unread_count']; $epoch = $d_data['epoch']; $image = $d_data['image']; $msg_view = id(new ConpherenceMenuItemView()) ->setUser($user) ->setTitle($title) ->setSubtitle($subtitle) ->setHref($uri) ->setEpoch($epoch) ->setImageURI($image) ->setUnreadCount($unread_count); $view->appendChild(javelin_tag( 'div', array( 'class' => implode(' ', $classes), 'sigil' => 'notification', 'meta' => array( 'href' => $uri, ), ), $msg_view)); } $content = $view->render(); } else { $content = phutil_tag_div( 'phabricator-notification no-notifications', pht('You have no messages.')); } $content = hsprintf( '
%s
'. '%s', phutil_tag( 'a', array( 'href' => '/conpherence/', ), pht('Messages')), $content); $unread = id(new ConpherenceParticipantCountQuery()) ->withParticipantPHIDs(array($user->getPHID())) ->withParticipationStatus($unread_status) ->execute(); $unread_count = idx($unread, $user->getPHID(), 0); $json = array( 'content' => $content, 'number' => (int)$unread_count, ); return id(new AphrontAjaxResponse())->setContent($json); } }