Conpherence - implement join / view rules for rooms

Summary:
Ref T7585. This implements everything specified, with a few caveats

- since rooms you have yet to join can't be viewed in the column yet, the column view has some bugs and isn't expected to work.
- the room you're looking at is just pre-pending to the top of the "recent" list

Test Plan: made a room that no one could join. verified when viewing that there was no comment ui. made a room that others could join. verified folks who had yet to join had a "join" button with an area for text. tried joining with / without message text and it worked in both cases

Reviewers: chad, epriestley

Reviewed By: epriestley

Subscribers: Korvin, epriestley

Maniphest Tasks: T7585

Differential Revision: https://secure.phabricator.com/D12149
This commit is contained in:
Bob Trahan
2015-03-24 18:38:16 -07:00
parent aa310230b6
commit 25767096c9
11 changed files with 178 additions and 62 deletions

View File

@@ -5,6 +5,7 @@ final class ConpherenceUpdateActions extends ConpherenceConstants {
const METADATA = 'metadata';
const MESSAGE = 'message';
const DRAFT = 'draft';
const JOIN_ROOM = 'join_room';
const ADD_PERSON = 'add_person';
const REMOVE_PERSON = 'remove_person';
const NOTIFICATIONS = 'notifications';

View File

@@ -69,11 +69,23 @@ final class ConpherenceListController extends ConpherenceController {
if ($conpherence->getTitle()) {
$title = $conpherence->getTitle();
}
$cursor = $conpherence->getParticipant($user->getPHID());
$data = $this->loadParticipationWithMidCursor($cursor);
$all_participation = $data['participation'];
$scroll_up_participant = $data['scroll_up_participant'];
$scroll_down_participant = $data['scroll_down_participant'];
$cursor = $conpherence->getParticipantIfExists($user->getPHID());
if ($cursor) {
$data = $this->loadParticipationWithMidCursor($cursor);
$all_participation = $data['all_participation'];
$scroll_up_participant = $data['scroll_up_participant'];
$scroll_down_participant = $data['scroll_down_participant'];
} else {
$data = $this->loadDefaultParticipation($too_many);
$all_participation = $data['all_participation'];
$scroll_down_participant = $data['scroll_down_participant'];
$menu_participation = $this->getEmptyParticipant()
->setConpherencePHID($conpherence->getPHID())
->setParticipantPHID($user->getPHID());
$all_participation =
array($conpherence->getPHID() => $menu_participation) +
$all_participation;
}
break;
case self::PAGING_MODE:
$direction = $request->getStr('direction');
@@ -108,16 +120,9 @@ final class ConpherenceListController extends ConpherenceController {
break;
case self::UNSELECTED_MODE:
default:
$too_many = ConpherenceParticipantQuery::LIMIT + 1;
$all_participation = id(new ConpherenceParticipantQuery())
->withParticipantPHIDs(array($user->getPHID()))
->setLimit($too_many)
->execute();
if (count($all_participation) == $too_many) {
$node = end($all_participation);
unset($all_participation[$node->getConpherencePHID()]);
$scroll_down_participant = $node;
}
$data = $this->loadDefaultParticipation($too_many);
$all_participation = $data['all_participation'];
$scroll_down_participant = $data['scroll_down_participant'];
break;
}
@@ -171,6 +176,26 @@ final class ConpherenceListController extends ConpherenceController {
}
private function loadDefaultParticipation($too_many) {
$viewer = $this->getRequest()->getUser();
$scroll_down_participant = $this->getEmptyParticipant();
$all_participation = id(new ConpherenceParticipantQuery())
->withParticipantPHIDs(array($viewer->getPHID()))
->setLimit($too_many)
->execute();
if (count($all_participation) == $too_many) {
$node = end($all_participation);
unset($all_participation[$node->getConpherencePHID()]);
$scroll_down_participant = $node;
}
return array(
'all_participation' => $all_participation,
'scroll_down_participant' => $scroll_down_participant,);
}
/**
* Handles the curious case when we are visiting a conpherence directly
* by issuing two separate queries. Otherwise, additional conpherences
@@ -224,7 +249,7 @@ final class ConpherenceListController extends ConpherenceController {
return array(
'scroll_up_participant' => $scroll_up_participant,
'scroll_down_participant' => $scroll_down_participant,
'participation' => $participation,
'all_participation' => $participation,
);
}

View File

@@ -53,6 +53,28 @@ final class ConpherenceUpdateController
$draft->setDraft($request->getStr('text'));
$draft->replaceOrDelete();
return new AphrontAjaxResponse();
case ConpherenceUpdateActions::JOIN_ROOM:
PhabricatorPolicyFilter::requireCapability(
$user,
$conpherence,
PhabricatorPolicyCapability::CAN_JOIN);
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(
ConpherenceTransactionType::TYPE_PARTICIPANTS)
->setNewValue(array('+' => array($user->getPHID())));
$delete_draft = true;
$message = $request->getStr('text');
if ($message) {
$message_xactions = $editor->generateTransactionsFromText(
$user,
$conpherence,
$message);
$xactions = array_merge($xactions, $message_xactions);
}
// for now, just redirect back to the conpherence so everything
// will work okay...!
$response_mode = 'redirect';
break;
case ConpherenceUpdateActions::MESSAGE:
$message = $request->getStr('text');
$xactions = $editor->generateTransactionsFromText(
@@ -86,7 +108,10 @@ final class ConpherenceUpdateController
break;
case ConpherenceUpdateActions::NOTIFICATIONS:
$notifications = $request->getStr('notifications');
$participant = $conpherence->getParticipant($user->getPHID());
$participant = $conpherence->getParticipantIfExists($user->getPHID());
if (!$participant) {
return id(new Aphront404Response());
}
$participant->setSettings(array('notifications' => $notifications));
$participant->save();
$result = pht(
@@ -126,23 +151,23 @@ final class ConpherenceUpdateController
break;
}
if ($xactions || ($action == ConpherenceUpdateActions::LOAD)) {
if ($xactions) {
try {
$xactions = $editor->applyTransactions($conpherence, $xactions);
if ($delete_draft) {
$draft = PhabricatorDraft::newFromUserAndKey(
$user,
$conpherence->getPHID());
$draft->delete();
}
} catch (PhabricatorApplicationTransactionNoEffectException $ex) {
return id(new PhabricatorApplicationTransactionNoEffectResponse())
->setCancelURI($this->getApplicationURI($conpherence_id.'/'))
->setException($ex);
if ($xactions) {
try {
$xactions = $editor->applyTransactions($conpherence, $xactions);
if ($delete_draft) {
$draft = PhabricatorDraft::newFromUserAndKey(
$user,
$conpherence->getPHID());
$draft->delete();
}
} catch (PhabricatorApplicationTransactionNoEffectException $ex) {
return id(new PhabricatorApplicationTransactionNoEffectResponse())
->setCancelURI($this->getApplicationURI($conpherence_id.'/'))
->setException($ex);
}
}
if ($xactions || ($action == ConpherenceUpdateActions::LOAD)) {
switch ($response_mode) {
case 'ajax':
$latest_transaction_id = $request->getInt('latest_transaction_id');

View File

@@ -27,12 +27,14 @@ final class ConpherenceViewController extends
}
$this->setConpherence($conpherence);
$participant = $conpherence->getParticipant($user->getPHID());
$transactions = $conpherence->getTransactions();
$latest_transaction = head($transactions);
$write_guard = AphrontWriteGuard::beginScopedUnguardedWrites();
$participant->markUpToDate($conpherence, $latest_transaction);
unset($write_guard);
$participant = $conpherence->getParticipantIfExists($user->getPHID());
if ($participant) {
$write_guard = AphrontWriteGuard::beginScopedUnguardedWrites();
$participant->markUpToDate($conpherence, $latest_transaction);
unset($write_guard);
}
$data = ConpherenceTransactionView::renderTransactions(
$user,
@@ -85,9 +87,24 @@ final class ConpherenceViewController extends
$conpherence = $this->getConpherence();
$user = $this->getRequest()->getUser();
$can_join = PhabricatorPolicyFilter::hasCapability(
$user,
$conpherence,
PhabricatorPolicyCapability::CAN_JOIN);
$participating = $conpherence->getParticipantIfExists($user->getPHID());
if (!$can_join && !$participating) {
return null;
}
$draft = PhabricatorDraft::newFromUserAndKey(
$user,
$conpherence->getPHID());
if ($participating) {
$action = ConpherenceUpdateActions::MESSAGE;
$button_text = pht('Send');
} else {
$action = ConpherenceUpdateActions::JOIN_ROOM;
$button_text = pht('Join');
}
$update_uri = $this->getApplicationURI('update/'.$conpherence->getID().'/');
$this->initBehavior('conpherence-pontificate');
@@ -98,7 +115,7 @@ final class ConpherenceViewController extends
->addSigil('conpherence-pontificate')
->setWorkflow(true)
->setUser($user)
->addHiddenInput('action', 'message')
->addHiddenInput('action', $action)
->appendChild(
id(new PhabricatorRemarkupControl())
->setUser($user)
@@ -106,7 +123,7 @@ final class ConpherenceViewController extends
->setValue($draft->getDraft()))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Send')))
->setValue($button_text))
->render();
return $form;

View File

@@ -130,8 +130,24 @@ final class ConpherenceWidgetController extends ConpherenceController {
private function renderSettingsWidgetPaneContent() {
$viewer = $this->getViewer();
$conpherence = $this->getConpherence();
$participants = $conpherence->getParticipants();
$participant = $participants[$viewer->getPHID()];
$participant = $conpherence->getParticipantIfExists($viewer->getPHID());
if (!$participant) {
$can_join = PhabricatorPolicyFilter::hasCapability(
$viewer,
$conpherence,
PhabricatorPolicyCapability::CAN_JOIN);
if ($can_join) {
$text = pht('Settings are available after joining the room.');
} else {
$text = pht('Settings not applicable to rooms you can not join.');
}
return phutil_tag(
'div',
array(
'class' => 'no-settings',
),
$text);
}
$default = ConpherenceSettings::EMAIL_ALWAYS;
$preference = $this->getUserPreferences();
if ($preference) {

View File

@@ -321,6 +321,15 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
PhabricatorLiskDAO $object,
array $xactions) {
$message_count = 0;
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT:
$message_count++;
break;
}
}
// update everyone's participation status on the last xaction -only-
$xaction = end($xactions);
$xaction_phid = $xaction->getPHID();
@@ -333,8 +342,8 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
if ($phid != $user->getPHID()) {
if ($participant->getParticipationStatus() != $behind) {
$participant->setBehindTransactionPHID($xaction_phid);
// decrement one as this is the message putting them behind!
$participant->setSeenMessageCount($object->getMessageCount() - 1);
$participant->setSeenMessageCount(
$object->getMessageCount() - $message_count);
}
$participant->setParticipationStatus($behind);
$participant->setDateTouched($time);

View File

@@ -98,9 +98,9 @@ final class ConpherenceThread extends ConpherenceDAO
$participants = $this->getParticipants();
return $participants[$phid];
}
public function getParticipantIfExists($phid) {
public function getParticipantIfExists($phid, $default = null) {
$participants = $this->getParticipants();
return idx($participants, $phid);
return idx($participants, $phid, $default);
}
public function getParticipantPHIDs() {
@@ -221,7 +221,10 @@ final class ConpherenceThread extends ConpherenceDAO
);
}
/* -( PhabricatorPolicyInterface Implementation )-------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,

View File

@@ -393,6 +393,10 @@ abstract class PhabricatorApplicationTransactionEditor
case PhabricatorTransactions::TYPE_EDIT_POLICY:
$object->setEditPolicy($xaction->getNewValue());
break;
case PhabricatorTransactions::TYPE_JOIN_POLICY:
$object->setJoinPolicy($xaction->getNewValue());
break;
case PhabricatorTransactions::TYPE_CUSTOMFIELD:
$field = $this->getCustomFieldForTransaction($object, $xaction);
return $field->applyApplicationTransactionInternalEffects($xaction);