Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/conpherence/controller/ConpherenceParticipantController.php b/src/applications/conpherence/controller/ConpherenceParticipantController.php
index 843600dd57..a82439f311 100644
--- a/src/applications/conpherence/controller/ConpherenceParticipantController.php
+++ b/src/applications/conpherence/controller/ConpherenceParticipantController.php
@@ -1,38 +1,38 @@
<?php
final class ConpherenceParticipantController extends ConpherenceController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$conpherence_id = $request->getURIData('id');
if (!$conpherence_id) {
return new Aphront404Response();
}
$conpherence = id(new ConpherenceThreadQuery())
->setViewer($viewer)
->withIDs(array($conpherence_id))
- ->needWidgetData(true)
+ ->needParticipants(true)
->executeOne();
if (!$conpherence) {
return new Aphront404Response();
}
$uri = $this->getApplicationURI('update/'.$conpherence->getID().'/');
$content = id(new ConpherenceParticipantView())
->setUser($this->getViewer())
->setConpherence($conpherence)
->setUpdateURI($uri);
$content = array('widgets' => $content);
return id(new AphrontAjaxResponse())->setContent($content);
}
}
diff --git a/src/applications/conpherence/controller/ConpherenceUpdateController.php b/src/applications/conpherence/controller/ConpherenceUpdateController.php
index 4581058162..f8602a15cf 100644
--- a/src/applications/conpherence/controller/ConpherenceUpdateController.php
+++ b/src/applications/conpherence/controller/ConpherenceUpdateController.php
@@ -1,678 +1,678 @@
<?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))
->needFilePHIDs(true)
->needOrigPics(true)
->needCropPics(true)
->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:
$top = $request->getInt('image_y');
$left = $request->getInt('image_x');
$file_id = $request->getInt('file_id');
$title = $request->getStr('title');
$topic = $request->getStr('topic');
if ($file_id) {
$orig_file = id(new PhabricatorFileQuery())
->setViewer($user)
->withIDs(array($file_id))
->executeOne();
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(ConpherenceTransaction::TYPE_PICTURE)
->setNewValue($orig_file);
$okay = $orig_file->isTransformableImage();
if ($okay) {
$xformer = new PhabricatorImageTransformer();
$crop_file = $xformer->executeConpherenceTransform(
$orig_file,
0,
0,
ConpherenceImageData::CROP_WIDTH,
ConpherenceImageData::CROP_HEIGHT);
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(
ConpherenceTransaction::TYPE_PICTURE_CROP)
->setNewValue($crop_file->getPHID());
}
$response_mode = 'redirect';
}
// all other metadata updates are continue requests
if (!$request->isContinueRequest()) {
break;
}
if ($top !== null || $left !== null) {
$file = $conpherence->getImage(ConpherenceImageData::SIZE_ORIG);
$xformer = new PhabricatorImageTransformer();
$xformed = $xformer->executeConpherenceTransform(
$file,
$top,
$left,
ConpherenceImageData::CROP_WIDTH,
ConpherenceImageData::CROP_HEIGHT);
$image_phid = $xformed->getPHID();
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(
ConpherenceTransaction::TYPE_PICTURE_CROP)
->setNewValue($image_phid);
}
$title = $request->getStr('title');
$topic = $request->getStr('topic');
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(ConpherenceTransaction::TYPE_TITLE)
->setNewValue($title);
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(ConpherenceTransaction::TYPE_TOPIC)
->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) {
$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()));
require_celerity_resource('conpherence-update-css');
$view = id(new AphrontDialogView())
->setTitle(pht('Add Participants'))
->addHiddenInput('action', 'add_person')
->addHiddenInput(
'latest_transaction_id',
$request->getInt('latest_transaction_id'))
->appendForm($form);
if ($request->getExists('minimal_display')) {
$view->addHiddenInput('minimal_display', true);
}
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.');
}
}
require_celerity_resource('conpherence-update-css');
$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()));
$nopic = $this->getRequest()->getExists('nopic');
$image = $conpherence->getImage(ConpherenceImageData::SIZE_ORIG);
if ($nopic) {
// do not render any pic related controls
} else if ($image) {
$crop_uri = $conpherence->loadImageURI(ConpherenceImageData::SIZE_CROP);
$form
->appendChild(
id(new AphrontFormMarkupControl())
->setLabel(pht('Image'))
->setValue(phutil_tag(
'img',
array(
'src' => $crop_uri,
))))
->appendChild(
id(new ConpherencePicCropControl())
->setLabel(pht('Crop Image'))
->setValue($image))
->appendChild(
id(new ConpherenceFormDragAndDropUploadControl())
->setLabel(pht('Change Image')));
} else {
$form
->appendChild(
id(new ConpherenceFormDragAndDropUploadControl())
->setLabel(pht('Image')));
}
$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));
require_celerity_resource('conpherence-update-css');
$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('minimal_display')) {
$view->addHiddenInput('minimal_display', true);
}
if ($request->getExists('force_ajax')) {
$view->addHiddenInput('force_ajax', true);
}
return $view;
}
private function loadAndRenderUpdates(
$action,
$conpherence_id,
$latest_transaction_id) {
$minimal_display = $this->getRequest()->getExists('minimal_display');
$need_widget_data = false;
$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;
$need_widget_data = !$minimal_display;
break;
case ConpherenceUpdateActions::REMOVE_PERSON:
case ConpherenceUpdateActions::NOTIFICATIONS:
default:
break;
}
$user = $this->getRequest()->getUser();
$conpherence = id(new ConpherenceThreadQuery())
->setViewer($user)
->setAfterTransactionID($latest_transaction_id)
->needCropPics(true)
->needParticipantCache($need_participant_cache)
- ->needWidgetData($need_widget_data)
+ ->needParticipants(true)
->needTransactions($need_transactions)
->withIDs(array($conpherence_id))
->executeOne();
$non_update = false;
if ($need_transactions && $conpherence->getTransactions()) {
$data = ConpherenceTransactionRenderer::renderTransactions(
$user,
$conpherence,
!$minimal_display);
$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;
if (!$minimal_display) {
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/query/ConpherenceThreadQuery.php b/src/applications/conpherence/query/ConpherenceThreadQuery.php
index 6a70faf29f..dc1e761c43 100644
--- a/src/applications/conpherence/query/ConpherenceThreadQuery.php
+++ b/src/applications/conpherence/query/ConpherenceThreadQuery.php
@@ -1,447 +1,343 @@
<?php
final class ConpherenceThreadQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
const TRANSACTION_LIMIT = 100;
private $phids;
private $ids;
private $participantPHIDs;
private $needParticipants;
- private $needWidgetData;
private $needCropPics;
private $needOrigPics;
private $needTransactions;
private $needParticipantCache;
private $needFilePHIDs;
private $afterTransactionID;
private $beforeTransactionID;
private $transactionLimit;
private $fulltext;
public function needFilePHIDs($need_file_phids) {
$this->needFilePHIDs = $need_file_phids;
return $this;
}
public function needParticipantCache($participant_cache) {
$this->needParticipantCache = $participant_cache;
return $this;
}
public function needParticipants($need) {
$this->needParticipants = $need;
return $this;
}
- public function needWidgetData($need_widget_data) {
- $this->needWidgetData = $need_widget_data;
- return $this;
- }
-
public function needCropPics($need) {
$this->needCropPics = $need;
return $this;
}
public function needOrigPics($need_widget_data) {
$this->needOrigPics = $need_widget_data;
return $this;
}
public function needTransactions($need_transactions) {
$this->needTransactions = $need_transactions;
return $this;
}
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withParticipantPHIDs(array $phids) {
$this->participantPHIDs = $phids;
return $this;
}
public function setAfterTransactionID($id) {
$this->afterTransactionID = $id;
return $this;
}
public function setBeforeTransactionID($id) {
$this->beforeTransactionID = $id;
return $this;
}
public function setTransactionLimit($transaction_limit) {
$this->transactionLimit = $transaction_limit;
return $this;
}
public function getTransactionLimit() {
return $this->transactionLimit;
}
public function withFulltext($query) {
$this->fulltext = $query;
return $this;
}
protected function loadPage() {
$table = new ConpherenceThread();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT thread.* FROM %T thread %Q %Q %Q %Q %Q',
$table->getTableName(),
$this->buildJoinClause($conn_r),
$this->buildWhereClause($conn_r),
$this->buildGroupClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$conpherences = $table->loadAllFromArray($data);
if ($conpherences) {
$conpherences = mpull($conpherences, null, 'getPHID');
$this->loadParticipantsAndInitHandles($conpherences);
if ($this->needParticipantCache) {
$this->loadCoreHandles($conpherences, 'getRecentParticipantPHIDs');
}
- if ($this->needWidgetData || $this->needParticipants) {
+ if ($this->needParticipants) {
$this->loadCoreHandles($conpherences, 'getParticipantPHIDs');
}
if ($this->needTransactions) {
$this->loadTransactionsAndHandles($conpherences);
}
- if ($this->needFilePHIDs || $this->needWidgetData) {
+ if ($this->needFilePHIDs) {
$this->loadFilePHIDs($conpherences);
}
- if ($this->needWidgetData) {
- $this->loadWidgetData($conpherences);
- }
if ($this->needOrigPics || $this->needCropPics) {
$this->initImages($conpherences);
}
if ($this->needOrigPics) {
$this->loadOrigPics($conpherences);
}
if ($this->needCropPics) {
$this->loadCropPics($conpherences);
}
}
return $conpherences;
}
protected function buildGroupClause(AphrontDatabaseConnection $conn_r) {
if ($this->participantPHIDs !== null || strlen($this->fulltext)) {
return 'GROUP BY thread.id';
} else {
return $this->buildApplicationSearchGroupClause($conn_r);
}
}
protected function buildJoinClause(AphrontDatabaseConnection $conn_r) {
$joins = array();
if ($this->participantPHIDs !== null) {
$joins[] = qsprintf(
$conn_r,
'JOIN %T p ON p.conpherencePHID = thread.phid',
id(new ConpherenceParticipant())->getTableName());
}
if (strlen($this->fulltext)) {
$joins[] = qsprintf(
$conn_r,
'JOIN %T idx ON idx.threadPHID = thread.phid',
id(new ConpherenceIndex())->getTableName());
}
$joins[] = $this->buildApplicationSearchJoinClause($conn_r);
return implode(' ', $joins);
}
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
$where[] = $this->buildPagingClause($conn_r);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'thread.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'thread.phid IN (%Ls)',
$this->phids);
}
if ($this->participantPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'p.participantPHID IN (%Ls)',
$this->participantPHIDs);
}
if (strlen($this->fulltext)) {
$where[] = qsprintf(
$conn_r,
'MATCH(idx.corpus) AGAINST (%s IN BOOLEAN MODE)',
$this->fulltext);
}
return $this->formatWhereClause($where);
}
private function loadParticipantsAndInitHandles(array $conpherences) {
$participants = id(new ConpherenceParticipant())
->loadAllWhere('conpherencePHID IN (%Ls)', array_keys($conpherences));
$map = mgroup($participants, 'getConpherencePHID');
foreach ($conpherences as $current_conpherence) {
$conpherence_phid = $current_conpherence->getPHID();
$conpherence_participants = idx(
$map,
$conpherence_phid,
array());
$conpherence_participants = mpull(
$conpherence_participants,
null,
'getParticipantPHID');
$current_conpherence->attachParticipants($conpherence_participants);
$current_conpherence->attachHandles(array());
}
return $this;
}
private function loadCoreHandles(
array $conpherences,
$method) {
$handle_phids = array();
foreach ($conpherences as $conpherence) {
$handle_phids[$conpherence->getPHID()] =
$conpherence->$method();
}
$flat_phids = array_mergev($handle_phids);
$viewer = $this->getViewer();
$handles = $viewer->loadHandles($flat_phids);
$handles = iterator_to_array($handles);
foreach ($handle_phids as $conpherence_phid => $phids) {
$conpherence = $conpherences[$conpherence_phid];
$conpherence->attachHandles(
$conpherence->getHandles() + array_select_keys($handles, $phids));
}
return $this;
}
private function loadTransactionsAndHandles(array $conpherences) {
$query = id(new ConpherenceTransactionQuery())
->setViewer($this->getViewer())
->withObjectPHIDs(array_keys($conpherences))
->needHandles(true);
// We have to flip these for the underyling query class. The semantics of
// paging are tricky business.
if ($this->afterTransactionID) {
$query->setBeforeID($this->afterTransactionID);
} else if ($this->beforeTransactionID) {
$query->setAfterID($this->beforeTransactionID);
}
if ($this->getTransactionLimit()) {
// fetch an extra for "show older" scenarios
$query->setLimit($this->getTransactionLimit() + 1);
}
$transactions = $query->execute();
$transactions = mgroup($transactions, 'getObjectPHID');
foreach ($conpherences as $phid => $conpherence) {
$current_transactions = idx($transactions, $phid, array());
$handles = array();
foreach ($current_transactions as $transaction) {
$handles += $transaction->getHandles();
}
$conpherence->attachHandles($conpherence->getHandles() + $handles);
$conpherence->attachTransactions($current_transactions);
}
return $this;
}
private function loadFilePHIDs(array $conpherences) {
$edge_type = PhabricatorObjectHasFileEdgeType::EDGECONST;
$file_edges = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(array_keys($conpherences))
->withEdgeTypes(array($edge_type))
->execute();
foreach ($file_edges as $conpherence_phid => $data) {
$conpherence = $conpherences[$conpherence_phid];
$conpherence->attachFilePHIDs(array_keys($data[$edge_type]));
}
return $this;
}
- private function loadWidgetData(array $conpherences) {
- $participant_phids = array();
- $file_phids = array();
- foreach ($conpherences as $conpherence) {
- $participant_phids[] = array_keys($conpherence->getParticipants());
- $file_phids[] = $conpherence->getFilePHIDs();
- }
- $participant_phids = array_mergev($participant_phids);
- $file_phids = array_mergev($file_phids);
-
- $epochs = CalendarTimeUtil::getCalendarEventEpochs(
- $this->getViewer());
- $start_epoch = $epochs['start_epoch'];
- $end_epoch = $epochs['end_epoch'];
-
- $events = array();
- if ($participant_phids) {
- // TODO: All of this Calendar code is probably extra-broken, but none
- // of it is currently reachable in the UI.
- $events = id(new PhabricatorCalendarEventQuery())
- ->setViewer($this->getViewer())
- ->withInvitedPHIDs($participant_phids)
- ->withIsCancelled(false)
- ->withDateRange($start_epoch, $end_epoch)
- ->execute();
- $events = mpull($events, null, 'getPHID');
- }
-
- $invitees = array();
- foreach ($events as $event_phid => $event) {
- foreach ($event->getInvitees() as $invitee) {
- $invitees[$invitee->getInviteePHID()][$event_phid] = true;
- }
- }
-
- // attached files
- $files = array();
- $file_author_phids = array();
- $authors = array();
- if ($file_phids) {
- $files = id(new PhabricatorFileQuery())
- ->setViewer($this->getViewer())
- ->withPHIDs($file_phids)
- ->execute();
- $files = mpull($files, null, 'getPHID');
- $file_author_phids = mpull($files, 'getAuthorPHID', 'getPHID');
- $authors = id(new PhabricatorHandleQuery())
- ->setViewer($this->getViewer())
- ->withPHIDs($file_author_phids)
- ->execute();
- $authors = mpull($authors, null, 'getPHID');
- }
-
- foreach ($conpherences as $phid => $conpherence) {
- $participant_phids = array_keys($conpherence->getParticipants());
- $widget_data = array();
-
- $event_phids = array();
- $participant_invites = array_select_keys($invitees, $participant_phids);
- foreach ($participant_invites as $invite_set) {
- $event_phids += $invite_set;
- }
- $thread_events = array_select_keys($events, array_keys($event_phids));
- $thread_events = msort($thread_events, 'getDateFrom');
- $widget_data['events'] = $thread_events;
-
- $conpherence_files = array();
- $files_authors = array();
- foreach ($conpherence->getFilePHIDs() as $curr_phid) {
- $curr_file = idx($files, $curr_phid);
- if (!$curr_file) {
- // this file was deleted or user doesn't have permission to see it
- // this is generally weird
- continue;
- }
- $conpherence_files[$curr_phid] = $curr_file;
- // some files don't have authors so be careful
- $current_author = null;
- $current_author_phid = idx($file_author_phids, $curr_phid);
- if ($current_author_phid) {
- $current_author = $authors[$current_author_phid];
- }
- $files_authors[$curr_phid] = $current_author;
- }
- $widget_data += array(
- 'files' => $conpherence_files,
- 'files_authors' => $files_authors,
- );
-
- $conpherence->attachWidgetData($widget_data);
- }
-
- return $this;
- }
-
private function loadOrigPics(array $conpherences) {
return $this->loadPics(
$conpherences,
ConpherenceImageData::SIZE_ORIG);
}
private function loadCropPics(array $conpherences) {
return $this->loadPics(
$conpherences,
ConpherenceImageData::SIZE_CROP);
}
private function initImages($conpherences) {
foreach ($conpherences as $conpherence) {
$conpherence->attachImages(array());
}
}
private function loadPics(array $conpherences, $size) {
$conpherence_pic_phids = array();
foreach ($conpherences as $conpherence) {
$phid = $conpherence->getImagePHID($size);
if ($phid) {
$conpherence_pic_phids[$conpherence->getPHID()] = $phid;
}
}
if (!$conpherence_pic_phids) {
return $this;
}
$files = id(new PhabricatorFileQuery())
->setViewer($this->getViewer())
->withPHIDs($conpherence_pic_phids)
->execute();
$files = mpull($files, null, 'getPHID');
foreach ($conpherence_pic_phids as $conpherence_phid => $pic_phid) {
$conpherences[$conpherence_phid]->setImage($files[$pic_phid], $size);
}
return $this;
}
public function getQueryApplicationClass() {
return 'PhabricatorConpherenceApplication';
}
protected function getPrimaryTableAlias() {
return 'thread';
}
}
diff --git a/src/applications/conpherence/storage/ConpherenceThread.php b/src/applications/conpherence/storage/ConpherenceThread.php
index 5a999f0422..ec8449f87f 100644
--- a/src/applications/conpherence/storage/ConpherenceThread.php
+++ b/src/applications/conpherence/storage/ConpherenceThread.php
@@ -1,477 +1,468 @@
<?php
final class ConpherenceThread extends ConpherenceDAO
implements
PhabricatorPolicyInterface,
PhabricatorApplicationTransactionInterface,
PhabricatorMentionableInterface,
PhabricatorDestructibleInterface {
protected $title;
protected $topic;
protected $imagePHIDs = array();
protected $messageCount;
protected $recentParticipantPHIDs = array();
protected $mailKey;
protected $viewPolicy;
protected $editPolicy;
protected $joinPolicy;
private $participants = self::ATTACHABLE;
private $transactions = self::ATTACHABLE;
private $handles = self::ATTACHABLE;
private $filePHIDs = self::ATTACHABLE;
- private $widgetData = self::ATTACHABLE;
private $images = self::ATTACHABLE;
public static function initializeNewRoom(PhabricatorUser $sender) {
$default_policy = id(new ConpherenceThreadMembersPolicyRule())
->getObjectPolicyFullKey();
return id(new ConpherenceThread())
->setMessageCount(0)
->setTitle('')
->setTopic('')
->attachParticipants(array())
->attachFilePHIDs(array())
->attachImages(array())
->setViewPolicy($default_policy)
->setEditPolicy($default_policy)
->setJoinPolicy($default_policy);
}
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'recentParticipantPHIDs' => self::SERIALIZATION_JSON,
'imagePHIDs' => self::SERIALIZATION_JSON,
),
self::CONFIG_COLUMN_SCHEMA => array(
'title' => 'text255?',
'topic' => 'text255',
'messageCount' => 'uint64',
'mailKey' => 'text20',
'joinPolicy' => 'policy',
),
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 getImagePHID($size) {
$image_phids = $this->getImagePHIDs();
return idx($image_phids, $size);
}
public function setImagePHID($phid, $size) {
$image_phids = $this->getImagePHIDs();
$image_phids[$size] = $phid;
return $this->setImagePHIDs($image_phids);
}
public function getImage($size) {
$images = $this->getImages();
return idx($images, $size);
}
public function setImage(PhabricatorFile $file, $size) {
$files = $this->getImages();
$files[$size] = $file;
return $this->attachImages($files);
}
public function attachImages(array $files) {
assert_instances_of($files, 'PhabricatorFile');
$this->images = $files;
return $this;
}
private function getImages() {
return $this->assertAttached($this->images);
}
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 attachFilePHIDs(array $file_phids) {
$this->filePHIDs = $file_phids;
return $this;
}
public function getFilePHIDs() {
return $this->assertAttached($this->filePHIDs);
}
- public function attachWidgetData(array $widget_data) {
- $this->widgetData = $widget_data;
- return $this;
- }
- public function getWidgetData() {
- return $this->assertAttached($this->widgetData);
- }
-
public function loadImageURI($size) {
$file = $this->getImage($size);
if ($file) {
return $file->getBestURI();
}
return PhabricatorUser::getDefaultProfileImageURI();
}
/**
* 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();
}
if ($transactions) {
$subtitle_mode = 'message';
} else {
$subtitle_mode = 'recent';
}
$lucky_phid = head($this->getOtherRecentParticipantPHIDs($viewer));
if ($lucky_phid) {
$lucky_handle = $handles[$lucky_phid];
} else {
// This will be just the user talking to themselves. Weirdo.
$lucky_handle = reset($handles);
}
$img_src = null;
$size = ConpherenceImageData::SIZE_CROP;
if ($this->getImagePHID($size)) {
$img_src = $this->getImage($size)->getBestURI();
} else if ($lucky_handle) {
$img_src = $lucky_handle->getImageURI();
}
$message_title = null;
if ($subtitle_mode == 'message') {
$message_transaction = null;
foreach ($transactions as $transaction) {
switch ($transaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT:
$message_transaction = $transaction;
break 2;
default:
break;
}
}
if ($message_transaction) {
$message_handle = $handles[$message_transaction->getAuthorPHID()];
$message_title = sprintf(
'%s: %s',
$message_handle->getName(),
id(new PhutilUTF8StringTruncator())
->setMaximumGlyphs(60)
->truncateString(
$message_transaction->getComment()->getContent()));
}
}
switch ($subtitle_mode) {
case 'recent':
$subtitle = $this->getRecentParticipantsString($viewer);
break;
case 'message':
if ($message_title) {
$subtitle = $message_title;
} else {
$subtitle = $this->getRecentParticipantsString($viewer);
}
break;
}
$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;
}
/* -( 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();
}
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Nov 6, 9:24 AM (9 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
321806
Default Alt Text
(52 KB)

Event Timeline