Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/conpherence/controller/ConpherenceController.php b/src/applications/conpherence/controller/ConpherenceController.php
index e6690a55d1..09708b7148 100644
--- a/src/applications/conpherence/controller/ConpherenceController.php
+++ b/src/applications/conpherence/controller/ConpherenceController.php
@@ -1,225 +1,221 @@
<?php
abstract class ConpherenceController extends PhabricatorController {
private $conpherence;
public function setConpherence(ConpherenceThread $conpherence) {
$this->conpherence = $conpherence;
return $this;
}
public function getConpherence() {
return $this->conpherence;
}
public function buildApplicationMenu() {
$nav = new PHUIListView();
$conpherence = $this->conpherence;
// Local Links
if ($conpherence) {
$nav->addMenuItem(
id(new PHUIListItemView())
->setName(pht('Joined Rooms'))
->setType(PHUIListItemView::TYPE_LINK)
->setHref($this->getApplicationURI()));
$nav->addMenuItem(
id(new PHUIListItemView())
->setName(pht('Edit Room'))
->setType(PHUIListItemView::TYPE_LINK)
->setHref(
$this->getApplicationURI('update/'.$conpherence->getID()).'/')
->setWorkflow(true));
$nav->addMenuItem(
id(new PHUIListItemView())
->setName(pht('Add Participants'))
->setType(PHUIListItemView::TYPE_LINK)
->setHref('#')
->addSigil('conpherence-widget-adder')
->setMetadata(array('widget' => 'widgets-people')));
}
// Global Links
$nav->newLabel(pht('Conpherence'));
$nav->newLink(
pht('New Room'),
$this->getApplicationURI('new/'));
$nav->newLink(
pht('Search Rooms'),
$this->getApplicationURI('search/'));
return $nav;
}
protected function buildHeaderPaneContent(
ConpherenceThread $conpherence,
array $policy_objects) {
assert_instances_of($policy_objects, 'PhabricatorPolicy');
$viewer = $this->getViewer();
$header = null;
if ($conpherence->getID()) {
$data = $conpherence->getDisplayData($this->getViewer());
$header = id(new PHUIHeaderView())
->setHeader($data['title'])
->setSubheader($data['topic'])
->setImage($data['image']);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$conpherence,
PhabricatorPolicyCapability::CAN_EDIT);
if ($can_edit) {
$header->setImageURL(
$this->getApplicationURI('picture/'.$conpherence->getID().'/'));
}
$participating = $conpherence->getParticipantIfExists($viewer->getPHID());
- $can_join = PhabricatorPolicyFilter::hasCapability(
- $viewer,
- $conpherence,
- PhabricatorPolicyCapability::CAN_JOIN);
$header->addActionItem(
id(new PHUIIconCircleView())
->setHref(
$this->getApplicationURI('update/'.$conpherence->getID()).'/')
->setIcon('fa-pencil')
->addClass('hide-on-device')
->setColor('violet')
->setWorkflow(true));
$header->addActionItem(
id(new PHUIIconCircleView())
->setHref(
$this->getApplicationURI('update/'.$conpherence->getID()).'/'.
'?action='.ConpherenceUpdateActions::NOTIFICATIONS)
->setIcon('fa-gear')
->addClass('hide-on-device')
->setColor('pink')
->setWorkflow(true));
$widget_key = PhabricatorConpherenceWidgetVisibleSetting::SETTINGKEY;
$widget_view = (bool)$viewer->getUserSetting($widget_key, false);
Javelin::initBehavior(
'toggle-widget',
array(
'show' => (int)$widget_view,
'settingsURI' => '/settings/adjust/?key='.$widget_key,
));
$header->addActionItem(
id(new PHUIIconCircleView())
->addSigil('conpherence-widget-toggle')
->setIcon('fa-group')
->setHref('#')
->addClass('conpherence-participant-toggle'));
Javelin::initBehavior('conpherence-search');
$header->addActionItem(
id(new PHUIIconCircleView())
->addSigil('conpherence-search-toggle')
->setIcon('fa-search')
->setHref('#')
->setColor('green')
->addClass('conpherence-search-toggle'));
- if ($can_join && !$participating) {
+ if (!$participating) {
$action = ConpherenceUpdateActions::JOIN_ROOM;
$uri = $this->getApplicationURI('update/'.$conpherence->getID().'/');
$button = phutil_tag(
'button',
array(
'type' => 'SUBMIT',
'class' => 'button green mlr',
),
pht('Join Room'));
$hidden = phutil_tag(
'input',
array(
'type' => 'hidden',
'name' => 'action',
'value' => ConpherenceUpdateActions::JOIN_ROOM,
));
$form = phabricator_form(
$viewer,
array(
'method' => 'POST',
'action' => (string)$uri,
),
array(
$hidden,
$button,
));
$header->addActionItem($form);
}
}
return $header;
}
public function buildSearchForm() {
$viewer = $this->getViewer();
$conpherence = $this->conpherence;
$name = $conpherence->getTitle();
$bar = javelin_tag(
'input',
array(
'type' => 'text',
'id' => 'conpherence-search-input',
'name' => 'fulltext',
'class' => 'conpherence-search-input',
'sigil' => 'conpherence-search-input',
'placeholder' => pht('Search %s...', $name),
));
$id = $conpherence->getID();
$form = phabricator_form(
$viewer,
array(
'method' => 'POST',
'action' => '/conpherence/threadsearch/'.$id.'/',
'sigil' => 'conpherence-search-form',
'class' => 'conpherence-search-form',
'id' => 'conpherence-search-form',
),
array(
$bar,
));
$form_view = phutil_tag(
'div',
array(
'class' => 'conpherence-search-form-view',
),
$form);
$results = phutil_tag(
'div',
array(
'id' => 'conpherence-search-results',
'class' => 'conpherence-search-results',
));
$view = phutil_tag(
'div',
array(
'class' => 'conpherence-search-window',
),
array(
$form_view,
$results,
));
return $view;
}
}
diff --git a/src/applications/conpherence/controller/ConpherenceNewRoomController.php b/src/applications/conpherence/controller/ConpherenceNewRoomController.php
index 1f27a6807e..d70395dbc9 100644
--- a/src/applications/conpherence/controller/ConpherenceNewRoomController.php
+++ b/src/applications/conpherence/controller/ConpherenceNewRoomController.php
@@ -1,126 +1,116 @@
<?php
final class ConpherenceNewRoomController extends ConpherenceController {
public function handleRequest(AphrontRequest $request) {
$user = $request->getUser();
$title = pht('New Room');
$e_title = true;
$validation_exception = null;
$conpherence = ConpherenceThread::initializeNewRoom($user);
$participants = array();
if ($request->isFormPost()) {
$editor = new ConpherenceEditor();
$xactions = array();
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(ConpherenceThreadTitleTransaction::TRANSACTIONTYPE)
->setNewValue($request->getStr('title'));
$participants = $request->getArr('participants');
$participants[] = $user->getPHID();
$participants = array_unique($participants);
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(ConpherenceTransaction::TYPE_PARTICIPANTS)
->setNewValue(array('+' => $participants));
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(ConpherenceThreadTopicTransaction::TRANSACTIONTYPE)
->setNewValue($request->getStr('topic'));
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
->setNewValue($request->getStr('viewPolicy'));
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
->setNewValue($request->getStr('editPolicy'));
- $xactions[] = id(new ConpherenceTransaction())
- ->setTransactionType(PhabricatorTransactions::TYPE_JOIN_POLICY)
- ->setNewValue($request->getStr('joinPolicy'));
try {
$editor
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true)
->setActor($user)
->applyTransactions($conpherence, $xactions);
return id(new AphrontRedirectResponse())
->setURI('/'.$conpherence->getMonogram());
} catch (PhabricatorApplicationTransactionValidationException $ex) {
$validation_exception = $ex;
$e_title = $ex->getShortMessage(
ConpherenceThreadTitleTransaction::TRANSACTIONTYPE);
$conpherence->setViewPolicy($request->getStr('viewPolicy'));
$conpherence->setEditPolicy($request->getStr('editPolicy'));
- $conpherence->setJoinPolicy($request->getStr('joinPolicy'));
}
} else {
if ($request->getStr('participant')) {
$participants[] = $request->getStr('participant');
}
}
$policies = id(new PhabricatorPolicyQuery())
->setViewer($user)
->setObject($conpherence)
->execute();
$submit_uri = $this->getApplicationURI('new/');
$cancel_uri = $this->getApplicationURI('search/');
$dialog = $this->newDialog()
->setWidth(AphrontDialogView::WIDTH_FORM)
->setValidationException($validation_exception)
->setUser($user)
->setTitle($title)
->addCancelButton($cancel_uri)
->addSubmitButton(pht('Create Room'));
$form = id(new PHUIFormLayoutView())
->setUser($user)
->appendChild(
id(new AphrontFormTextControl())
->setError($e_title)
->setLabel(pht('Name'))
->setName('title')
->setValue($request->getStr('title')))
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Topic'))
->setName('topic')
->setValue($request->getStr('topic')))
->appendChild(
id(new AphrontFormTokenizerControl())
->setName('participants')
->setUser($user)
->setDatasource(new PhabricatorPeopleDatasource())
->setValue($participants)
->setLabel(pht('Other Participants')))
->appendChild(
id(new AphrontFormPolicyControl())
->setName('viewPolicy')
->setPolicyObject($conpherence)
->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
->setPolicies($policies))
->appendChild(
id(new AphrontFormPolicyControl())
->setName('editPolicy')
->setPolicyObject($conpherence)
->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
- ->setPolicies($policies))
- ->appendChild(
- id(new AphrontFormPolicyControl())
- ->setName('joinPolicy')
- ->setPolicyObject($conpherence)
- ->setCapability(PhabricatorPolicyCapability::CAN_JOIN)
->setPolicies($policies));
$dialog->appendChild($form);
return id(new AphrontDialogResponse())->setDialog($dialog);
}
}
diff --git a/src/applications/conpherence/controller/ConpherenceUpdateController.php b/src/applications/conpherence/controller/ConpherenceUpdateController.php
index 44e6c3cf4b..b8ebe5a826 100644
--- a/src/applications/conpherence/controller/ConpherenceUpdateController.php
+++ b/src/applications/conpherence/controller/ConpherenceUpdateController.php
@@ -1,594 +1,575 @@
<?php
final class ConpherenceUpdateController
extends ConpherenceController {
public function handleRequest(AphrontRequest $request) {
$user = $request->getUser();
$conpherence_id = $request->getURIData('id');
if (!$conpherence_id) {
return new Aphront404Response();
}
$need_participants = false;
$needed_capabilities = array(PhabricatorPolicyCapability::CAN_VIEW);
$action = $request->getStr('action', ConpherenceUpdateActions::METADATA);
switch ($action) {
case ConpherenceUpdateActions::REMOVE_PERSON:
$person_phid = $request->getStr('remove_person');
if ($person_phid != $user->getPHID()) {
$needed_capabilities[] = PhabricatorPolicyCapability::CAN_EDIT;
}
break;
case ConpherenceUpdateActions::ADD_PERSON:
case ConpherenceUpdateActions::METADATA:
$needed_capabilities[] = PhabricatorPolicyCapability::CAN_EDIT;
break;
- case ConpherenceUpdateActions::JOIN_ROOM:
- $needed_capabilities[] = PhabricatorPolicyCapability::CAN_JOIN;
- break;
case ConpherenceUpdateActions::NOTIFICATIONS:
$need_participants = true;
break;
case ConpherenceUpdateActions::LOAD:
break;
}
$conpherence = id(new ConpherenceThreadQuery())
->setViewer($user)
->withIDs(array($conpherence_id))
->needParticipants($need_participants)
->requireCapabilities($needed_capabilities)
->executeOne();
$latest_transaction_id = null;
$response_mode = $request->isAjax() ? 'ajax' : 'redirect';
$error_view = null;
$e_file = array();
$errors = array();
$delete_draft = false;
$xactions = array();
if ($request->isFormPost() || ($action == ConpherenceUpdateActions::LOAD)) {
$editor = id(new ConpherenceEditor())
->setContinueOnNoEffect($request->isContinueRequest())
->setContentSourceFromRequest($request)
->setActor($user);
switch ($action) {
case ConpherenceUpdateActions::DRAFT:
$draft = PhabricatorDraft::newFromUserAndKey(
$user,
$conpherence->getPHID());
$draft->setDraft($request->getStr('text'));
$draft->replaceOrDelete();
return new AphrontAjaxResponse();
case ConpherenceUpdateActions::JOIN_ROOM:
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(
ConpherenceTransaction::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');
if (strlen($message)) {
$xactions = $editor->generateTransactionsFromText(
$user,
$conpherence,
$message);
$delete_draft = true;
} else {
$action = ConpherenceUpdateActions::LOAD;
$updated = false;
$response_mode = 'ajax';
}
break;
case ConpherenceUpdateActions::ADD_PERSON:
$person_phids = $request->getArr('add_person');
if (!empty($person_phids)) {
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(
ConpherenceTransaction::TYPE_PARTICIPANTS)
->setNewValue(array('+' => $person_phids));
}
break;
case ConpherenceUpdateActions::REMOVE_PERSON:
if (!$request->isContinueRequest()) {
// do nothing; we'll display a confirmation dialog instead
break;
}
$person_phid = $request->getStr('remove_person');
if ($person_phid) {
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(
ConpherenceTransaction::TYPE_PARTICIPANTS)
->setNewValue(array('-' => array($person_phid)));
$response_mode = 'go-home';
}
break;
case ConpherenceUpdateActions::NOTIFICATIONS:
$notifications = $request->getStr('notifications');
$participant = $conpherence->getParticipantIfExists($user->getPHID());
if (!$participant) {
return id(new Aphront404Response());
}
$participant->setSettings(array('notifications' => $notifications));
$participant->save();
return id(new AphrontRedirectResponse())
->setURI('/'.$conpherence->getMonogram());
break;
case ConpherenceUpdateActions::METADATA:
$title = $request->getStr('title');
$topic = $request->getStr('topic');
// all other metadata updates are continue requests
if (!$request->isContinueRequest()) {
break;
}
$title = $request->getStr('title');
$topic = $request->getStr('topic');
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(
ConpherenceThreadTitleTransaction::TRANSACTIONTYPE)
->setNewValue($title);
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(
ConpherenceThreadTopicTransaction::TRANSACTIONTYPE)
->setNewValue($topic);
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
->setNewValue($request->getStr('viewPolicy'));
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
->setNewValue($request->getStr('editPolicy'));
- $xactions[] = id(new ConpherenceTransaction())
- ->setTransactionType(PhabricatorTransactions::TYPE_JOIN_POLICY)
- ->setNewValue($request->getStr('joinPolicy'));
if (!$request->getExists('force_ajax')) {
$response_mode = 'redirect';
}
break;
case ConpherenceUpdateActions::LOAD:
$updated = false;
$response_mode = 'ajax';
break;
default:
throw new Exception(pht('Unknown action: %s', $action));
break;
}
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);
}
// xactions had no effect...!
if (empty($xactions)) {
$errors[] = pht(
'That was a non-update. Try cancel.');
}
}
if ($xactions || ($action == ConpherenceUpdateActions::LOAD)) {
switch ($response_mode) {
case 'ajax':
$latest_transaction_id = $request->getInt('latest_transaction_id');
$content = $this->loadAndRenderUpdates(
$action,
$conpherence_id,
$latest_transaction_id);
return id(new AphrontAjaxResponse())
->setContent($content);
break;
case 'go-home':
$content = array(
'href' => $this->getApplicationURI(),
);
return id(new AphrontAjaxResponse())
->setContent($content);
break;
case 'redirect':
default:
return id(new AphrontRedirectResponse())
->setURI('/'.$conpherence->getMonogram());
break;
}
}
}
if ($errors) {
$error_view = id(new PHUIInfoView())
->setErrors($errors);
}
switch ($action) {
case ConpherenceUpdateActions::NOTIFICATIONS:
$dialog = $this->renderPreferencesDialog($conpherence);
break;
case ConpherenceUpdateActions::ADD_PERSON:
$dialog = $this->renderAddPersonDialog($conpherence);
break;
case ConpherenceUpdateActions::REMOVE_PERSON:
$dialog = $this->renderRemovePersonDialog($conpherence);
break;
case ConpherenceUpdateActions::METADATA:
default:
$dialog = $this->renderMetadataDialog($conpherence, $error_view);
break;
}
return
$dialog
->setUser($user)
->setWidth(AphrontDialogView::WIDTH_FORM)
->setSubmitURI($this->getApplicationURI('update/'.$conpherence_id.'/'))
->addSubmitButton()
->addCancelButton($this->getApplicationURI($conpherence->getID().'/'));
}
private function renderPreferencesDialog(
ConpherenceThread $conpherence) {
$request = $this->getRequest();
$user = $request->getUser();
$participant = $conpherence->getParticipantIfExists($user->getPHID());
if (!$participant) {
- $can_join = PhabricatorPolicyFilter::hasCapability(
- $user,
- $conpherence,
- PhabricatorPolicyCapability::CAN_JOIN);
- if ($can_join) {
+ if ($user->isLoggedIn()) {
$text = pht(
'Notification settings are available after joining the room.');
- } else if ($user->isLoggedIn()) {
- $text = pht(
- 'Notification settings not applicable to rooms you can not join.');
} else {
$text = pht(
'Notification settings are available after logging in and joining '.
'the room.');
}
return id(new AphrontDialogView())
->setTitle(pht('Room Preferences'))
->appendParagraph($text);
}
$notification_key = PhabricatorConpherenceNotificationsSetting::SETTINGKEY;
$notification_default = $user->getUserSetting($notification_key);
$settings = $participant->getSettings();
$notifications = idx(
$settings,
'notifications',
$notification_default);
$form = id(new AphrontFormView())
->setUser($user)
->setFullWidth(true)
->appendControl(
id(new AphrontFormRadioButtonControl())
->addButton(
PhabricatorConpherenceNotificationsSetting::VALUE_CONPHERENCE_EMAIL,
PhabricatorConpherenceNotificationsSetting::getSettingLabel(
PhabricatorConpherenceNotificationsSetting::VALUE_CONPHERENCE_EMAIL),
'')
->addButton(
PhabricatorConpherenceNotificationsSetting::VALUE_CONPHERENCE_NOTIFY,
PhabricatorConpherenceNotificationsSetting::getSettingLabel(
PhabricatorConpherenceNotificationsSetting::VALUE_CONPHERENCE_NOTIFY),
'')
->setName('notifications')
->setValue($notifications));
return id(new AphrontDialogView())
->setTitle(pht('Room Preferences'))
->addHiddenInput('action', 'notifications')
->addHiddenInput(
'latest_transaction_id',
$request->getInt('latest_transaction_id'))
->appendForm($form);
}
private function renderAddPersonDialog(
ConpherenceThread $conpherence) {
$request = $this->getRequest();
$user = $request->getUser();
$add_person = $request->getStr('add_person');
$form = id(new AphrontFormView())
->setUser($user)
->setFullWidth(true)
->appendControl(
id(new AphrontFormTokenizerControl())
->setName('add_person')
->setUser($user)
->setDatasource(new PhabricatorPeopleDatasource()));
$view = id(new AphrontDialogView())
->setTitle(pht('Add Participants'))
->addHiddenInput('action', 'add_person')
->addHiddenInput(
'latest_transaction_id',
$request->getInt('latest_transaction_id'))
->appendForm($form);
return $view;
}
private function renderRemovePersonDialog(
ConpherenceThread $conpherence) {
$request = $this->getRequest();
$viewer = $request->getUser();
$remove_person = $request->getStr('remove_person');
$participants = $conpherence->getParticipants();
$removed_user = id(new PhabricatorPeopleQuery())
->setViewer($viewer)
->withPHIDs(array($remove_person))
->executeOne();
if (!$removed_user) {
return new Aphront404Response();
}
$is_self = ($viewer->getPHID() == $removed_user->getPHID());
$is_last = (count($participants) == 1);
$test_conpherence = clone $conpherence;
$test_conpherence->attachParticipants(array());
$still_visible = PhabricatorPolicyFilter::hasCapability(
$removed_user,
$test_conpherence,
PhabricatorPolicyCapability::CAN_VIEW);
$body = array();
if ($is_self) {
$title = pht('Leave Room');
$body[] = pht(
'Are you sure you want to leave this room?');
} else {
$title = pht('Banish User');
$body[] = pht(
'Banish %s from the realm?',
phutil_tag('strong', array(), $removed_user->getUsername()));
}
if ($still_visible) {
if ($is_self) {
$body[] = pht(
'You will be able to rejoin the room later.');
} else {
$body[] = pht(
'This user will be able to rejoin the room later.');
}
} else {
if ($is_self) {
if ($is_last) {
$body[] = pht(
'You are the last member, so you will never be able to rejoin '.
'the room.');
} else {
$body[] = pht(
'You will not be able to rejoin the room on your own, but '.
'someone else can invite you later.');
}
} else {
$body[] = pht(
'This user will not be able to rejoin the room unless invited '.
'again.');
}
}
$dialog = id(new AphrontDialogView())
->setTitle($title)
->addHiddenInput('action', 'remove_person')
->addHiddenInput('remove_person', $remove_person)
->addHiddenInput(
'latest_transaction_id',
$request->getInt('latest_transaction_id'))
->addHiddenInput('__continue__', true);
foreach ($body as $paragraph) {
$dialog->appendParagraph($paragraph);
}
return $dialog;
}
private function renderMetadataDialog(
ConpherenceThread $conpherence,
$error_view) {
$request = $this->getRequest();
$user = $request->getUser();
$title = pht('Update Room');
$form = id(new PHUIFormLayoutView())
->appendChild($error_view)
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Title'))
->setName('title')
->setValue($conpherence->getTitle()))
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Topic'))
->setName('topic')
->setValue($conpherence->getTopic()));
$policies = id(new PhabricatorPolicyQuery())
->setViewer($user)
->setObject($conpherence)
->execute();
$form
->appendChild(
id(new AphrontFormPolicyControl())
->setName('viewPolicy')
->setPolicyObject($conpherence)
->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
->setPolicies($policies))
->appendChild(
id(new AphrontFormPolicyControl())
->setName('editPolicy')
->setPolicyObject($conpherence)
->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
- ->setPolicies($policies))
- ->appendChild(
- id(new AphrontFormPolicyControl())
- ->setName('joinPolicy')
- ->setPolicyObject($conpherence)
- ->setCapability(PhabricatorPolicyCapability::CAN_JOIN)
->setPolicies($policies));
$view = id(new AphrontDialogView())
->setTitle($title)
->addHiddenInput('action', 'metadata')
->addHiddenInput(
'latest_transaction_id',
$request->getInt('latest_transaction_id'))
->addHiddenInput('__continue__', true)
->appendChild($form);
if ($request->getExists('force_ajax')) {
$view->addHiddenInput('force_ajax', true);
}
return $view;
}
private function loadAndRenderUpdates(
$action,
$conpherence_id,
$latest_transaction_id) {
$need_transactions = false;
$need_participant_cache = true;
switch ($action) {
case ConpherenceUpdateActions::METADATA:
case ConpherenceUpdateActions::LOAD:
$need_transactions = true;
break;
case ConpherenceUpdateActions::MESSAGE:
case ConpherenceUpdateActions::ADD_PERSON:
$need_transactions = true;
break;
case ConpherenceUpdateActions::REMOVE_PERSON:
case ConpherenceUpdateActions::NOTIFICATIONS:
default:
break;
}
$user = $this->getRequest()->getUser();
$conpherence = id(new ConpherenceThreadQuery())
->setViewer($user)
->setAfterTransactionID($latest_transaction_id)
->needProfileImage(true)
->needParticipantCache($need_participant_cache)
->needParticipants(true)
->needTransactions($need_transactions)
->withIDs(array($conpherence_id))
->executeOne();
$non_update = false;
if ($need_transactions && $conpherence->getTransactions()) {
$data = ConpherenceTransactionRenderer::renderTransactions(
$user,
$conpherence);
$key = PhabricatorConpherenceColumnMinimizeSetting::SETTINGKEY;
$minimized = $user->getUserSetting($key);
if (!$minimized) {
$participant_obj = $conpherence->getParticipant($user->getPHID());
$participant_obj
->markUpToDate($conpherence, $data['latest_transaction']);
}
} else if ($need_transactions) {
$non_update = true;
$data = array();
} else {
$data = array();
}
$rendered_transactions = idx($data, 'transactions');
$new_latest_transaction_id = idx($data, 'latest_transaction_id');
$update_uri = $this->getApplicationURI('update/'.$conpherence->getID().'/');
$nav_item = null;
$header = null;
$people_widget = null;
switch ($action) {
case ConpherenceUpdateActions::METADATA:
$policy_objects = id(new PhabricatorPolicyQuery())
->setViewer($user)
->setObject($conpherence)
->execute();
$header = $this->buildHeaderPaneContent(
$conpherence,
$policy_objects);
$header = hsprintf('%s', $header);
$nav_item = id(new ConpherenceThreadListView())
->setUser($user)
->setBaseURI($this->getApplicationURI())
->renderSingleThread($conpherence, $policy_objects);
$nav_item = hsprintf('%s', $nav_item);
break;
case ConpherenceUpdateActions::ADD_PERSON:
$people_widget = id(new ConpherenceParticipantView())
->setUser($user)
->setConpherence($conpherence)
->setUpdateURI($update_uri);
$people_widget = hsprintf('%s', $people_widget->render());
break;
case ConpherenceUpdateActions::REMOVE_PERSON:
case ConpherenceUpdateActions::NOTIFICATIONS:
default:
break;
}
$data = $conpherence->getDisplayData($user);
$dropdown_query = id(new AphlictDropdownDataQuery())
->setViewer($user);
$dropdown_query->execute();
$content = array(
'non_update' => $non_update,
'transactions' => hsprintf('%s', $rendered_transactions),
'conpherence_title' => (string)$data['title'],
'latest_transaction_id' => $new_latest_transaction_id,
'nav_item' => $nav_item,
'conpherence_phid' => $conpherence->getPHID(),
'header' => $header,
'people_widget' => $people_widget,
'aphlictDropdownData' => array(
$dropdown_query->getNotificationData(),
$dropdown_query->getConpherenceData(),
),
);
return $content;
}
}
diff --git a/src/applications/conpherence/controller/ConpherenceViewController.php b/src/applications/conpherence/controller/ConpherenceViewController.php
index 1fbb338822..57fe194845 100644
--- a/src/applications/conpherence/controller/ConpherenceViewController.php
+++ b/src/applications/conpherence/controller/ConpherenceViewController.php
@@ -1,253 +1,245 @@
<?php
final class ConpherenceViewController extends
ConpherenceController {
const OLDER_FETCH_LIMIT = 5;
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$user = $request->getUser();
$conpherence_id = $request->getURIData('id');
if (!$conpherence_id) {
return new Aphront404Response();
}
$query = id(new ConpherenceThreadQuery())
->setViewer($user)
->withIDs(array($conpherence_id))
->needProfileImage(true)
->needParticipantCache(true)
->needTransactions(true)
->setTransactionLimit($this->getMainQueryLimit());
$before_transaction_id = $request->getInt('oldest_transaction_id');
$after_transaction_id = $request->getInt('newest_transaction_id');
$old_message_id = $request->getURIData('messageID');
if ($before_transaction_id && ($old_message_id || $after_transaction_id)) {
throw new Aphront400Response();
}
if ($old_message_id && $after_transaction_id) {
throw new Aphront400Response();
}
$marker_type = 'older';
if ($before_transaction_id) {
$query
->setBeforeTransactionID($before_transaction_id);
}
if ($old_message_id) {
$marker_type = 'olderandnewer';
$query
->setAfterTransactionID($old_message_id - 1);
}
if ($after_transaction_id) {
$marker_type = 'newer';
$query
->setAfterTransactionID($after_transaction_id);
}
$conpherence = $query->executeOne();
if (!$conpherence) {
return new Aphront404Response();
}
$this->setConpherence($conpherence);
$transactions = $this->getNeededTransactions(
$conpherence,
$old_message_id);
$latest_transaction = head($transactions);
$participant = $conpherence->getParticipantIfExists($user->getPHID());
if ($participant) {
if (!$participant->isUpToDate($conpherence)) {
$write_guard = AphrontWriteGuard::beginScopedUnguardedWrites();
$participant->markUpToDate($conpherence, $latest_transaction);
$user->clearCacheData(PhabricatorUserMessageCountCacheType::KEY_COUNT);
unset($write_guard);
}
}
$data = ConpherenceTransactionRenderer::renderTransactions(
$user,
$conpherence,
$marker_type);
$messages = ConpherenceTransactionRenderer::renderMessagePaneContent(
$data['transactions'],
$data['oldest_transaction_id'],
$data['newest_transaction_id']);
if ($before_transaction_id || $after_transaction_id) {
$header = null;
$form = null;
$content = array('transactions' => $messages);
} else {
$policy_objects = id(new PhabricatorPolicyQuery())
->setViewer($user)
->setObject($conpherence)
->execute();
$header = $this->buildHeaderPaneContent($conpherence, $policy_objects);
$search = $this->buildSearchForm();
$form = $this->renderFormContent();
$content = array(
'header' => $header,
'search' => $search,
'transactions' => $messages,
'form' => $form,
);
}
$d_data = $conpherence->getDisplayData($user);
$content['title'] = $title = $d_data['title'];
if ($request->isAjax()) {
$dropdown_query = id(new AphlictDropdownDataQuery())
->setViewer($user);
$dropdown_query->execute();
$content['threadID'] = $conpherence->getID();
$content['threadPHID'] = $conpherence->getPHID();
$content['latestTransactionID'] = $data['latest_transaction_id'];
$content['canEdit'] = PhabricatorPolicyFilter::hasCapability(
$user,
$conpherence,
PhabricatorPolicyCapability::CAN_EDIT);
$content['aphlictDropdownData'] = array(
$dropdown_query->getNotificationData(),
$dropdown_query->getConpherenceData(),
);
return id(new AphrontAjaxResponse())->setContent($content);
}
- $can_join = PhabricatorPolicyFilter::hasCapability(
- $user,
- $conpherence,
- PhabricatorPolicyCapability::CAN_JOIN);
-
$layout = id(new ConpherenceLayoutView())
->setUser($user)
->setBaseURI($this->getApplicationURI())
->setThread($conpherence)
->setHeader($header)
->setSearch($search)
->setMessages($messages)
->setReplyForm($form)
->setLatestTransactionID($data['latest_transaction_id'])
->setRole('thread');
$participating = $conpherence->getParticipantIfExists($user->getPHID());
if (!$user->isLoggedIn()) {
$layout->addClass('conpherence-no-pontificate');
}
return $this->newPage()
->setTitle($title)
->setPageObjectPHIDs(array($conpherence->getPHID()))
->appendChild($layout);
}
private function renderFormContent() {
$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 && $user->isLoggedIn()) {
+ if (!$participating && $user->isLoggedIn()) {
return null;
}
$draft = PhabricatorDraft::newFromUserAndKey(
$user,
$conpherence->getPHID());
$update_uri = $this->getApplicationURI('update/'.$conpherence->getID().'/');
if ($user->isLoggedIn()) {
$this->initBehavior('conpherence-pontificate');
if ($participating) {
$action = ConpherenceUpdateActions::MESSAGE;
$status = new PhabricatorNotificationStatusView();
} else {
$action = ConpherenceUpdateActions::JOIN_ROOM;
$status = pht('Sending a message will also join the room.');
}
$form = id(new AphrontFormView())
->setUser($user)
->setAction($update_uri)
->addSigil('conpherence-pontificate')
->setWorkflow(true)
->addHiddenInput('action', $action)
->appendChild(
id(new PhabricatorRemarkupControl())
->setUser($user)
->setName('text')
->setSendOnEnter(true)
->setValue($draft->getDraft()));
$status_view = phutil_tag(
'div',
array(
'class' => 'conpherence-room-status',
'id' => 'conpherence-room-status',
),
$status);
$view = phutil_tag_div(
'pontificate-container', array($form, $status_view));
return $view;
} else {
// user not logged in so give them a login button.
$login_href = id(new PhutilURI('/auth/start/'))
->setQueryParam('next', '/'.$conpherence->getMonogram());
return id(new PHUIFormLayoutView())
->addClass('login-to-participate')
->appendInstructions(pht('Log in to join this room and participate.'))
->appendChild(
id(new PHUIButtonView())
->setTag('a')
->setText(pht('Login to Participate'))
->setHref((string)$login_href));
}
}
private function getNeededTransactions(
ConpherenceThread $conpherence,
$message_id) {
if ($message_id) {
$newer_transactions = $conpherence->getTransactions();
$query = id(new ConpherenceTransactionQuery())
->setViewer($this->getRequest()->getUser())
->withObjectPHIDs(array($conpherence->getPHID()))
->setAfterID($message_id)
->needHandles(true)
->setLimit(self::OLDER_FETCH_LIMIT);
$older_transactions = $query->execute();
$handles = array();
foreach ($older_transactions as $transaction) {
$handles += $transaction->getHandles();
}
$conpherence->attachHandles($conpherence->getHandles() + $handles);
$transactions = array_merge($newer_transactions, $older_transactions);
$conpherence->attachTransactions($transactions);
} else {
$transactions = $conpherence->getTransactions();
}
return $transactions;
}
private function getMainQueryLimit() {
$request = $this->getRequest();
$base_limit = ConpherenceThreadQuery::TRANSACTION_LIMIT;
if ($request->getURIData('messageID')) {
$base_limit = $base_limit - self::OLDER_FETCH_LIMIT;
}
return $base_limit;
}
}
diff --git a/src/applications/conpherence/editor/ConpherenceEditor.php b/src/applications/conpherence/editor/ConpherenceEditor.php
index 2026eb94c4..e4728f3c00 100644
--- a/src/applications/conpherence/editor/ConpherenceEditor.php
+++ b/src/applications/conpherence/editor/ConpherenceEditor.php
@@ -1,569 +1,556 @@
<?php
final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
const ERROR_EMPTY_PARTICIPANTS = 'error-empty-participants';
const ERROR_EMPTY_MESSAGE = 'error-empty-message';
public function getEditorApplicationClass() {
return 'PhabricatorConpherenceApplication';
}
public function getEditorObjectsDescription() {
return pht('Conpherence Rooms');
}
public static function createThread(
PhabricatorUser $creator,
array $participant_phids,
$title,
$message,
PhabricatorContentSource $source,
$topic) {
$conpherence = ConpherenceThread::initializeNewRoom($creator);
$errors = array();
if (empty($participant_phids)) {
$errors[] = self::ERROR_EMPTY_PARTICIPANTS;
} else {
$participant_phids[] = $creator->getPHID();
$participant_phids = array_unique($participant_phids);
}
if (empty($message)) {
$errors[] = self::ERROR_EMPTY_MESSAGE;
}
if (!$errors) {
$xactions = array();
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(ConpherenceTransaction::TYPE_PARTICIPANTS)
->setNewValue(array('+' => $participant_phids));
if ($title) {
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(
ConpherenceThreadTitleTransaction::TRANSACTIONTYPE)
->setNewValue($title);
}
if (strlen($topic)) {
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(
ConpherenceThreadTopicTransaction::TRANSACTIONTYPE)
->setNewValue($topic);
}
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)
->attachComment(
id(new ConpherenceTransactionComment())
->setContent($message)
->setConpherencePHID($conpherence->getPHID()));
id(new ConpherenceEditor())
->setActor($creator)
->setContentSource($source)
->setContinueOnNoEffect(true)
->applyTransactions($conpherence, $xactions);
}
return array($errors, $conpherence);
}
public function generateTransactionsFromText(
PhabricatorUser $viewer,
ConpherenceThread $conpherence,
$text) {
$xactions = array();
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)
->attachComment(
id(new ConpherenceTransactionComment())
->setContent($text)
->setConpherencePHID($conpherence->getPHID()));
return $xactions;
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = ConpherenceTransaction::TYPE_PARTICIPANTS;
$types[] = PhabricatorTransactions::TYPE_COMMENT;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
- $types[] = PhabricatorTransactions::TYPE_JOIN_POLICY;
return $types;
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this room.', $author);
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case ConpherenceTransaction::TYPE_PARTICIPANTS:
if ($this->getIsNewObject()) {
return array();
}
return $object->getParticipantPHIDs();
}
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case ConpherenceTransaction::TYPE_PARTICIPANTS:
return $this->getPHIDTransactionNewValue($xaction);
}
}
/**
* We really only need a read lock if we have a comment. In that case, we
* must update the messagesCount field on the conpherence and
* seenMessagesCount(s) for the participant(s).
*/
protected function shouldReadLock(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$lock = false;
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT:
$lock = true;
break;
}
return $lock;
}
/**
* We need to apply initial effects IFF the conpherence is new. We must
* save the conpherence first thing to make sure we have an id and a phid, as
* well as create the initial set of participants so that we pass policy
* checks.
*/
protected function shouldApplyInitialEffects(
PhabricatorLiskDAO $object,
array $xactions) {
return $this->getIsNewObject();
}
protected function applyInitialEffects(
PhabricatorLiskDAO $object,
array $xactions) {
$object->save();
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case ConpherenceTransaction::TYPE_PARTICIPANTS:
// Since this is a new ConpherenceThread, we have to create the
// participation data asap to pass policy checks. For existing
// ConpherenceThreads, the existing participation is correct
// at this stage. Note that later in applyCustomExternalTransaction
// this participation data will be updated, particularly the
// behindTransactionPHID which is just a generated dummy for now.
$participants = array();
$phids = $this->getPHIDTransactionNewValue($xaction, array());
foreach ($phids as $phid) {
if ($phid == $this->getActor()->getPHID()) {
$status = ConpherenceParticipationStatus::UP_TO_DATE;
$message_count = 1;
} else {
$status = ConpherenceParticipationStatus::BEHIND;
$message_count = 0;
}
$participants[$phid] =
id(new ConpherenceParticipant())
->setConpherencePHID($object->getPHID())
->setParticipantPHID($phid)
->setParticipationStatus($status)
->setDateTouched(time())
->setBehindTransactionPHID($xaction->generatePHID())
->setSeenMessageCount($message_count)
->save();
$object->attachParticipants($participants);
$object->setRecentParticipantPHIDs(array_keys($participants));
}
break;
}
}
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$make_author_recent_participant = true;
switch ($xaction->getTransactionType()) {
case ConpherenceTransaction::TYPE_PARTICIPANTS:
if (!$this->getIsNewObject()) {
$old_map = array_fuse($xaction->getOldValue());
$new_map = array_fuse($xaction->getNewValue());
// if we added people, add them to the end of "recent" participants
$add = array_keys(array_diff_key($new_map, $old_map));
// if we remove people, then definintely remove them from "recent"
// participants
$del = array_keys(array_diff_key($old_map, $new_map));
if ($add || $del) {
$participants = $object->getRecentParticipantPHIDs();
if ($add) {
$participants = array_merge($participants, $add);
}
if ($del) {
$participants = array_diff($participants, $del);
$actor = $this->requireActor();
if (in_array($actor->getPHID(), $del)) {
$make_author_recent_participant = false;
}
}
$participants = array_slice(array_unique($participants), 0, 10);
$object->setRecentParticipantPHIDs($participants);
}
}
break;
}
if ($make_author_recent_participant) {
$this->makeAuthorMostRecentParticipant($object, $xaction);
}
}
protected function applyBuiltinInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT:
$object->setMessageCount((int)$object->getMessageCount() + 1);
break;
}
return parent::applyBuiltinInternalTransaction($object, $xaction);
}
private function makeAuthorMostRecentParticipant(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$participants = $object->getRecentParticipantPHIDs();
array_unshift($participants, $xaction->getAuthorPHID());
$participants = array_slice(array_unique($participants), 0, 10);
$object->setRecentParticipantPHIDs($participants);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case ConpherenceTransaction::TYPE_PARTICIPANTS:
if ($this->getIsNewObject()) {
continue;
}
$participants = $object->getParticipants();
$old_map = array_fuse($xaction->getOldValue());
$new_map = array_fuse($xaction->getNewValue());
$remove = array_keys(array_diff_key($old_map, $new_map));
foreach ($remove as $phid) {
$remove_participant = $participants[$phid];
$remove_participant->delete();
unset($participants[$phid]);
}
$add = array_keys(array_diff_key($new_map, $old_map));
foreach ($add as $phid) {
if ($phid == $this->getActor()->getPHID()) {
$status = ConpherenceParticipationStatus::UP_TO_DATE;
$message_count = $object->getMessageCount();
} else {
$status = ConpherenceParticipationStatus::BEHIND;
$message_count = 0;
}
$participants[$phid] =
id(new ConpherenceParticipant())
->setConpherencePHID($object->getPHID())
->setParticipantPHID($phid)
->setParticipationStatus($status)
->setDateTouched(time())
->setBehindTransactionPHID($xaction->getPHID())
->setSeenMessageCount($message_count)
->save();
}
$object->attachParticipants($participants);
break;
}
}
protected function applyFinalEffects(
PhabricatorLiskDAO $object,
array $xactions) {
if (!$xactions) {
return $xactions;
}
$message_count = 0;
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT:
$message_count++;
// update everyone's participation status on a message -only-
$xaction_phid = $xaction->getPHID();
$behind = ConpherenceParticipationStatus::BEHIND;
$up_to_date = ConpherenceParticipationStatus::UP_TO_DATE;
$participants = $object->getParticipants();
$user = $this->getActor();
$time = time();
foreach ($participants as $phid => $participant) {
if ($phid != $user->getPHID()) {
if ($participant->getParticipationStatus() != $behind) {
$participant->setBehindTransactionPHID($xaction_phid);
$participant->setSeenMessageCount(
$object->getMessageCount() - $message_count);
}
$participant->setParticipationStatus($behind);
$participant->setDateTouched($time);
} else {
$participant->setSeenMessageCount($object->getMessageCount());
$participant->setBehindTransactionPHID($xaction_phid);
$participant->setParticipationStatus($up_to_date);
$participant->setDateTouched($time);
}
$participant->save();
}
PhabricatorUserCache::clearCaches(
PhabricatorUserMessageCountCacheType::KEY_COUNT,
array_keys($participants));
break;
}
}
if ($xactions) {
$data = array(
'type' => 'message',
'threadPHID' => $object->getPHID(),
'messageID' => last($xactions)->getID(),
'subscribers' => array($object->getPHID()),
);
PhabricatorNotificationClient::tryToPostMessage($data);
}
return $xactions;
}
protected function requireCapabilities(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
parent::requireCapabilities($object, $xaction);
switch ($xaction->getTransactionType()) {
case ConpherenceTransaction::TYPE_PARTICIPANTS:
$old_map = array_fuse($xaction->getOldValue());
$new_map = array_fuse($xaction->getNewValue());
$add = array_keys(array_diff_key($new_map, $old_map));
$rem = array_keys(array_diff_key($old_map, $new_map));
$actor_phid = $this->requireActor()->getPHID();
- $is_join = (($add === array($actor_phid)) && !$rem);
- $is_leave = (($rem === array($actor_phid)) && !$add);
-
- if ($is_join) {
- // You need CAN_JOIN to join a room.
- PhabricatorPolicyFilter::requireCapability(
- $this->requireActor(),
- $object,
- PhabricatorPolicyCapability::CAN_JOIN);
- } else if ($is_leave) {
- // You don't need any capabilities to leave a conpherence thread.
- } else {
- // You need CAN_EDIT to change participants other than yourself.
- PhabricatorPolicyFilter::requireCapability(
- $this->requireActor(),
- $object,
- PhabricatorPolicyCapability::CAN_EDIT);
- }
+ // You need CAN_EDIT to change participants other than yourself.
+ PhabricatorPolicyFilter::requireCapability(
+ $this->requireActor(),
+ $object,
+ PhabricatorPolicyCapability::CAN_EDIT);
+
break;
case ConpherenceThreadTitleTransaction::TRANSACTIONTYPE:
case ConpherenceThreadTopicTransaction::TRANSACTIONTYPE:
PhabricatorPolicyFilter::requireCapability(
$this->requireActor(),
$object,
PhabricatorPolicyCapability::CAN_EDIT);
break;
}
}
protected function mergeTransactions(
PhabricatorApplicationTransaction $u,
PhabricatorApplicationTransaction $v) {
$type = $u->getTransactionType();
switch ($type) {
case ConpherenceTransaction::TYPE_PARTICIPANTS:
return $this->mergePHIDOrEdgeTransactions($u, $v);
}
return parent::mergeTransactions($u, $v);
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new ConpherenceReplyHandler())
->setActor($this->getActor())
->setMailReceiver($object);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$id = $object->getID();
$title = $object->getTitle();
if (!$title) {
$title = pht(
'%s sent you a message.',
$this->getActor()->getUserName());
}
$phid = $object->getPHID();
return id(new PhabricatorMetaMTAMail())
->setSubject("Z{$id}: {$title}")
->addHeader('Thread-Topic', "Z{$id}: {$phid}");
}
protected function getMailTo(PhabricatorLiskDAO $object) {
$to_phids = array();
$participants = $object->getParticipants();
if (!$participants) {
return $to_phids;
}
$participant_phids = mpull($participants, 'getParticipantPHID');
$users = id(new PhabricatorPeopleQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPHIDs($participant_phids)
->needUserSettings(true)
->execute();
$users = mpull($users, null, 'getPHID');
$notification_key = PhabricatorConpherenceNotificationsSetting::SETTINGKEY;
$notification_email =
PhabricatorConpherenceNotificationsSetting::VALUE_CONPHERENCE_EMAIL;
foreach ($participants as $phid => $participant) {
$user = idx($users, $phid);
if ($user) {
$default = $user->getUserSetting($notification_key);
} else {
$default = $notification_email;
}
$settings = $participant->getSettings();
$notifications = idx($settings, 'notifications', $default);
if ($notifications == $notification_email) {
$to_phids[] = $phid;
}
}
return $to_phids;
}
protected function getMailCC(PhabricatorLiskDAO $object) {
return array();
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
$body->addLinkSection(
pht('CONPHERENCE DETAIL'),
PhabricatorEnv::getProductionURI('/'.$object->getMonogram()));
return $body;
}
protected function addEmailPreferenceSectionToMailBody(
PhabricatorMetaMTAMailBody $body,
PhabricatorLiskDAO $object,
array $xactions) {
$href = PhabricatorEnv::getProductionURI(
'/'.$object->getMonogram().'?settings');
$label = pht('EMAIL PREFERENCES FOR THIS ROOM');
$body->addLinkSection($label, $href);
}
protected function getMailSubjectPrefix() {
return PhabricatorEnv::getEnvConfig('metamta.conpherence.subject-prefix');
}
protected function supportsSearch() {
return true;
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
switch ($type) {
case ConpherenceTransaction::TYPE_PARTICIPANTS:
foreach ($xactions as $xaction) {
$new_phids = $this->getPHIDTransactionNewValue($xaction, array());
$old_phids = nonempty($object->getParticipantPHIDs(), array());
$phids = array_diff($new_phids, $old_phids);
if (!$phids) {
continue;
}
$users = id(new PhabricatorPeopleQuery())
->setViewer($this->requireActor())
->withPHIDs($phids)
->execute();
$users = mpull($users, null, 'getPHID');
foreach ($phids as $phid) {
if (isset($users[$phid])) {
continue;
}
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht('New room participant "%s" is not a valid user.', $phid),
$xaction);
}
}
break;
}
return $errors;
}
}
diff --git a/src/applications/conpherence/storage/ConpherenceThread.php b/src/applications/conpherence/storage/ConpherenceThread.php
index 17a3de6c50..db6d4a7e61 100644
--- a/src/applications/conpherence/storage/ConpherenceThread.php
+++ b/src/applications/conpherence/storage/ConpherenceThread.php
@@ -1,420 +1,416 @@
<?php
final class ConpherenceThread extends ConpherenceDAO
implements
PhabricatorPolicyInterface,
PhabricatorApplicationTransactionInterface,
PhabricatorMentionableInterface,
PhabricatorDestructibleInterface,
PhabricatorNgramsInterface {
protected $title;
protected $topic;
protected $profileImagePHID;
protected $messageCount;
protected $recentParticipantPHIDs = array();
protected $mailKey;
protected $viewPolicy;
protected $editPolicy;
protected $joinPolicy;
private $participants = self::ATTACHABLE;
private $transactions = self::ATTACHABLE;
private $profileImageFile = self::ATTACHABLE;
private $handles = self::ATTACHABLE;
public static function initializeNewRoom(PhabricatorUser $sender) {
$default_policy = id(new ConpherenceThreadMembersPolicyRule())
->getObjectPolicyFullKey();
return id(new ConpherenceThread())
->setMessageCount(0)
->setTitle('')
->setTopic('')
->attachParticipants(array())
->setViewPolicy($default_policy)
->setEditPolicy($default_policy)
- ->setJoinPolicy($default_policy);
+ ->setJoinPolicy('');
}
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'recentParticipantPHIDs' => self::SERIALIZATION_JSON,
),
self::CONFIG_COLUMN_SCHEMA => array(
'title' => 'text255?',
'topic' => 'text255',
'messageCount' => 'uint64',
'mailKey' => 'text20',
'joinPolicy' => 'policy',
'profileImagePHID' => 'phid?',
),
self::CONFIG_KEY_SCHEMA => array(
'key_phid' => null,
'phid' => array(
'columns' => array('phid'),
'unique' => true,
),
),
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhabricatorConpherenceThreadPHIDType::TYPECONST);
}
public function save() {
if (!$this->getMailKey()) {
$this->setMailKey(Filesystem::readRandomCharacters(20));
}
return parent::save();
}
public function getMonogram() {
return 'Z'.$this->getID();
}
public function attachParticipants(array $participants) {
assert_instances_of($participants, 'ConpherenceParticipant');
$this->participants = $participants;
return $this;
}
public function getParticipants() {
return $this->assertAttached($this->participants);
}
public function getParticipant($phid) {
$participants = $this->getParticipants();
return $participants[$phid];
}
public function getParticipantIfExists($phid, $default = null) {
$participants = $this->getParticipants();
return idx($participants, $phid, $default);
}
public function getParticipantPHIDs() {
$participants = $this->getParticipants();
return array_keys($participants);
}
public function attachHandles(array $handles) {
assert_instances_of($handles, 'PhabricatorObjectHandle');
$this->handles = $handles;
return $this;
}
public function getHandles() {
return $this->assertAttached($this->handles);
}
public function attachTransactions(array $transactions) {
assert_instances_of($transactions, 'ConpherenceTransaction');
$this->transactions = $transactions;
return $this;
}
public function getTransactions($assert_attached = true) {
return $this->assertAttached($this->transactions);
}
public function hasAttachedTransactions() {
return $this->transactions !== self::ATTACHABLE;
}
public function getTransactionsFrom($begin = 0, $amount = null) {
$length = count($this->transactions);
return array_slice(
$this->getTransactions(),
$length - $begin - $amount,
$amount);
}
public function getProfileImageURI() {
return $this->getProfileImageFile()->getBestURI();
}
public function attachProfileImageFile(PhabricatorFile $file) {
$this->profileImageFile = $file;
return $this;
}
public function getProfileImageFile() {
return $this->assertAttached($this->profileImageFile);
}
/**
* Get a thread title which doesn't require handles to be attached.
*
* This is a less rich title than @{method:getDisplayTitle}, but does not
* require handles to be attached. We use it to build thread handles without
* risking cycles or recursion while querying.
*
* @return string Lower quality human-readable title.
*/
public function getStaticTitle() {
$title = $this->getTitle();
if (strlen($title)) {
return $title;
}
return pht('Private Room');
}
/**
* Get the thread's display title for a user.
*
* If a thread doesn't have a title set, this will return a string describing
* recent participants.
*
* @param PhabricatorUser Viewer.
* @return string Thread title.
*/
public function getDisplayTitle(PhabricatorUser $viewer) {
$title = $this->getTitle();
if (strlen($title)) {
return $title;
}
return $this->getRecentParticipantsString($viewer);
}
/**
* Get recent participants (other than the viewer) as a string.
*
* For example, this method might return "alincoln, htaft, gwashington...".
*
* @param PhabricatorUser Viewer.
* @return string Description of other participants.
*/
private function getRecentParticipantsString(PhabricatorUser $viewer) {
$handles = $this->getHandles();
$phids = $this->getOtherRecentParticipantPHIDs($viewer);
if (count($phids) == 0) {
$phids[] = $viewer->getPHID();
$more = false;
} else {
$limit = 3;
$more = (count($phids) > $limit);
$phids = array_slice($phids, 0, $limit);
}
$names = array_select_keys($handles, $phids);
$names = mpull($names, 'getName');
$names = implode(', ', $names);
if ($more) {
$names = $names.'...';
}
return $names;
}
/**
* Get PHIDs for recent participants who are not the viewer.
*
* @param PhabricatorUser Viewer.
* @return list<phid> Participants who are not the viewer.
*/
private function getOtherRecentParticipantPHIDs(PhabricatorUser $viewer) {
$phids = $this->getRecentParticipantPHIDs();
$phids = array_fuse($phids);
unset($phids[$viewer->getPHID()]);
return array_values($phids);
}
public function getDisplayData(PhabricatorUser $viewer) {
$handles = $this->getHandles();
if ($this->hasAttachedTransactions()) {
$transactions = $this->getTransactions();
} else {
$transactions = array();
}
$img_src = $this->getProfileImageURI();
$message_transaction = null;
foreach ($transactions as $transaction) {
if ($message_transaction) {
break;
}
switch ($transaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT:
$message_transaction = $transaction;
break;
default:
break;
}
}
if ($message_transaction) {
$message_handle = $handles[$message_transaction->getAuthorPHID()];
$subtitle = sprintf(
'%s: %s',
$message_handle->getName(),
id(new PhutilUTF8StringTruncator())
->setMaximumGlyphs(60)
->truncateString(
$message_transaction->getComment()->getContent()));
} else {
// Kinda lame, but maybe add last message to cache?
$subtitle = pht('No recent messages');
}
$user_participation = $this->getParticipantIfExists($viewer->getPHID());
if ($user_participation) {
$user_seen_count = $user_participation->getSeenMessageCount();
} else {
$user_seen_count = 0;
}
$unread_count = $this->getMessageCount() - $user_seen_count;
$title = $this->getDisplayTitle($viewer);
$topic = $this->getTopic();
return array(
'title' => $title,
'topic' => $topic,
'subtitle' => $subtitle,
'unread_count' => $unread_count,
'epoch' => $this->getDateModified(),
'image' => $img_src,
);
}
/* -( PhabricatorPolicyInterface Implementation )-------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
- PhabricatorPolicyCapability::CAN_JOIN,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return $this->getViewPolicy();
case PhabricatorPolicyCapability::CAN_EDIT:
return $this->getEditPolicy();
- case PhabricatorPolicyCapability::CAN_JOIN:
- return $this->getJoinPolicy();
}
return PhabricatorPolicies::POLICY_NOONE;
}
public function hasAutomaticCapability($capability, PhabricatorUser $user) {
// this bad boy isn't even created yet so go nuts $user
if (!$this->getID()) {
return true;
}
switch ($capability) {
case PhabricatorPolicyCapability::CAN_EDIT:
- case PhabricatorPolicyCapability::CAN_JOIN:
return false;
}
$participants = $this->getParticipants();
return isset($participants[$user->getPHID()]);
}
public function describeAutomaticCapability($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return pht('Participants in a room can always view it.');
break;
}
}
public static function loadViewPolicyObjects(
PhabricatorUser $viewer,
array $conpherences) {
assert_instances_of($conpherences, __CLASS__);
$policies = array();
foreach ($conpherences as $room) {
$policies[$room->getViewPolicy()] = 1;
}
$policy_objects = array();
if ($policies) {
$policy_objects = id(new PhabricatorPolicyQuery())
->setViewer($viewer)
->withPHIDs(array_keys($policies))
->execute();
}
return $policy_objects;
}
public function getPolicyIconName(array $policy_objects) {
assert_instances_of($policy_objects, 'PhabricatorPolicy');
$icon = $policy_objects[$this->getViewPolicy()]->getIcon();
return $icon;
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
public function getApplicationTransactionEditor() {
return new ConpherenceEditor();
}
public function getApplicationTransactionObject() {
return $this;
}
public function getApplicationTransactionTemplate() {
return new ConpherenceTransaction();
}
public function willRenderTimeline(
PhabricatorApplicationTransactionView $timeline,
AphrontRequest $request) {
return $timeline;
}
/* -( PhabricatorNgramInterface )------------------------------------------ */
public function newNgrams() {
return array(
id(new ConpherenceThreadTitleNgrams())
->setValue($this->getTitle()),
);
}
/* -( PhabricatorDestructibleInterface )----------------------------------- */
public function destroyObjectPermanently(
PhabricatorDestructionEngine $engine) {
$this->openTransaction();
$this->delete();
$participants = id(new ConpherenceParticipant())
->loadAllWhere('conpherencePHID = %s', $this->getPHID());
foreach ($participants as $participant) {
$participant->delete();
}
$this->saveTransaction();
}
}
diff --git a/src/applications/conpherence/storage/ConpherenceTransaction.php b/src/applications/conpherence/storage/ConpherenceTransaction.php
index b449037235..c692dffb98 100644
--- a/src/applications/conpherence/storage/ConpherenceTransaction.php
+++ b/src/applications/conpherence/storage/ConpherenceTransaction.php
@@ -1,142 +1,106 @@
<?php
final class ConpherenceTransaction
extends PhabricatorModularTransaction {
const TYPE_PARTICIPANTS = 'participants';
const TYPE_DATE_MARKER = 'date-marker';
public function getApplicationName() {
return 'conpherence';
}
public function getApplicationTransactionType() {
return PhabricatorConpherenceThreadPHIDType::TYPECONST;
}
public function getApplicationTransactionCommentObject() {
return new ConpherenceTransactionComment();
}
public function getBaseTransactionClass() {
return 'ConpherenceThreadTransactionType';
}
public function getNoEffectDescription() {
switch ($this->getTransactionType()) {
case self::TYPE_PARTICIPANTS:
return pht(
'You can not add a participant who has already been added.');
break;
}
return parent::getNoEffectDescription();
}
public function shouldHide() {
$old = $this->getOldValue();
switch ($this->getTransactionType()) {
case self::TYPE_PARTICIPANTS:
return ($old === null);
case self::TYPE_DATE_MARKER:
return false;
}
return parent::shouldHide();
}
public function getTitle() {
$author_phid = $this->getAuthorPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
- case PhabricatorTransactions::TYPE_VIEW_POLICY:
- case PhabricatorTransactions::TYPE_EDIT_POLICY:
- case PhabricatorTransactions::TYPE_JOIN_POLICY:
- return $this->getRoomTitle();
- break;
case self::TYPE_PARTICIPANTS:
$add = array_diff($new, $old);
$rem = array_diff($old, $new);
if ($add && $rem) {
$title = pht(
'%s edited participant(s), added %d: %s; removed %d: %s.',
$this->renderHandleLink($author_phid),
count($add),
$this->renderHandleList($add),
count($rem),
$this->renderHandleList($rem));
} else if ($add) {
$title = pht(
'%s added %d participant(s): %s.',
$this->renderHandleLink($author_phid),
count($add),
$this->renderHandleList($add));
} else {
$title = pht(
'%s removed %d participant(s): %s.',
$this->renderHandleLink($author_phid),
count($rem),
$this->renderHandleList($rem));
}
return $title;
break;
}
return parent::getTitle();
}
- private function getRoomTitle() {
- $author_phid = $this->getAuthorPHID();
-
- $old = $this->getOldValue();
- $new = $this->getNewValue();
-
- switch ($this->getTransactionType()) {
- case PhabricatorTransactions::TYPE_VIEW_POLICY:
- return pht(
- '%s changed the visibility of this room from "%s" to "%s".',
- $this->renderHandleLink($author_phid),
- $this->renderPolicyName($old, 'old'),
- $this->renderPolicyName($new, 'new'));
- break;
- case PhabricatorTransactions::TYPE_EDIT_POLICY:
- return pht(
- '%s changed the edit policy of this room from "%s" to "%s".',
- $this->renderHandleLink($author_phid),
- $this->renderPolicyName($old, 'old'),
- $this->renderPolicyName($new, 'new'));
- break;
- case PhabricatorTransactions::TYPE_JOIN_POLICY:
- return pht(
- '%s changed the join policy of this room from "%s" to "%s".',
- $this->renderHandleLink($author_phid),
- $this->renderPolicyName($old, 'old'),
- $this->renderPolicyName($new, 'new'));
- break;
- }
- }
-
public function getRequiredHandlePHIDs() {
$phids = parent::getRequiredHandlePHIDs();
$old = $this->getOldValue();
$new = $this->getNewValue();
$phids[] = $this->getAuthorPHID();
switch ($this->getTransactionType()) {
case self::TYPE_DATE_MARKER:
break;
case self::TYPE_PARTICIPANTS:
$phids = array_merge($phids, $this->getOldValue());
$phids = array_merge($phids, $this->getNewValue());
break;
}
return $phids;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jun 10, 10:17 PM (1 d, 4 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
141186
Default Alt Text
(76 KB)

Event Timeline