1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-18 19:40:55 +01:00

Calendar events should now auto-invite the creator

Summary: Closes T7935, Calendar events should now auto-invite the creator.

Test Plan: Create event, save, event should now show creator as an invitee.

Reviewers: epriestley, #blessed_reviewers

Reviewed By: epriestley, #blessed_reviewers

Subscribers: Korvin, epriestley

Maniphest Tasks: T7935

Differential Revision: https://secure.phabricator.com/D12613
This commit is contained in:
lkassianik 2015-04-29 13:51:09 -07:00
parent f3a2d2b020
commit d4176606f9
10 changed files with 314 additions and 2 deletions

View file

@ -0,0 +1,11 @@
CREATE TABLE {$NAMESPACE}_calendar.`calendar_eventinvitee` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
`eventPHID` varbinary(64) NOT NULL,
`inviteePHID` varbinary(64) NOT NULL,
`inviterPHID` varbinary(64) NOT NULL,
`status` VARCHAR(64) COLLATE {$COLLATE_TEXT} NOT NULL,
`dateCreated` int(10) unsigned NOT NULL,
`dateModified` int(10) unsigned NOT NULL,
UNIQUE KEY `key_event` (`eventPHID`, `inviteePHID`),
KEY `key_invitee` (`inviteePHID`)
) ENGINE=InnoDB COLLATE {$COLLATE_TEXT};

View file

@ -1486,6 +1486,8 @@ phutil_register_library_map(array(
'PhabricatorCalendarEventEditController' => 'applications/calendar/controller/PhabricatorCalendarEventEditController.php',
'PhabricatorCalendarEventEditor' => 'applications/calendar/editor/PhabricatorCalendarEventEditor.php',
'PhabricatorCalendarEventInvalidEpochException' => 'applications/calendar/exception/PhabricatorCalendarEventInvalidEpochException.php',
'PhabricatorCalendarEventInvitee' => 'applications/calendar/storage/PhabricatorCalendarEventInvitee.php',
'PhabricatorCalendarEventInviteeQuery' => 'applications/calendar/query/PhabricatorCalendarEventInviteeQuery.php',
'PhabricatorCalendarEventListController' => 'applications/calendar/controller/PhabricatorCalendarEventListController.php',
'PhabricatorCalendarEventPHIDType' => 'applications/calendar/phid/PhabricatorCalendarEventPHIDType.php',
'PhabricatorCalendarEventQuery' => 'applications/calendar/query/PhabricatorCalendarEventQuery.php',
@ -4817,6 +4819,11 @@ phutil_register_library_map(array(
'PhabricatorCalendarEventEditController' => 'PhabricatorCalendarController',
'PhabricatorCalendarEventEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorCalendarEventInvalidEpochException' => 'Exception',
'PhabricatorCalendarEventInvitee' => array(
'PhabricatorCalendarDAO',
'PhabricatorPolicyInterface',
),
'PhabricatorCalendarEventInviteeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorCalendarEventListController' => 'PhabricatorCalendarController',
'PhabricatorCalendarEventPHIDType' => 'PhabricatorPHIDType',
'PhabricatorCalendarEventQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',

View file

@ -16,8 +16,10 @@ final class PhabricatorCalendarEventEditController
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$user_phid = $user->getPHID();
$error_name = true;
$validation_exception = null;
$invitees = null;
$start_time = id(new AphrontFormDateControl())
->setUser($user)
@ -40,6 +42,9 @@ final class PhabricatorCalendarEventEditController
$page_title = pht('Create Event');
$redirect = 'created';
$subscribers = array();
$invitees = array(
$user_phid => PhabricatorCalendarEventInvitee::STATUS_ATTENDING,
);
} else {
$event = id(new PhabricatorCalendarEventQuery())
->setViewer($user)
@ -112,6 +117,14 @@ final class PhabricatorCalendarEventEditController
PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION)
->setNewValue($description);
if ($invitees) {
$xactions[] = id(new PhabricatorCalendarEventTransaction())
->setTransactionType(
PhabricatorCalendarEventTransaction::TYPE_INVITE)
->setNewValue($invitees);
}
$editor = id(new PhabricatorCalendarEventEditor())
->setActor($user)
->setContentSourceFromRequest($request)
@ -160,7 +173,6 @@ final class PhabricatorCalendarEventEditController
->setUser($user)
->setDatasource(new PhabricatorMetaMTAMailableDatasource());
$form = id(new AphrontFormView())
->setUser($user)
->appendChild($name)

View file

@ -127,6 +127,20 @@ final class PhabricatorCalendarEventViewController
pht('Ends'),
phabricator_datetime($event->getDateTo(), $viewer));
$invitees = $event->getInvitees();
$invitee_list = new PHUIStatusListView();
foreach ($invitees as $invitee) {
$item = new PHUIStatusItemView();
$invitee_phid = $invitee->getInviteePHID();
$target = $viewer->renderHandle($invitee_phid);
$item->setTarget($target);
$invitee_list->addItem($item);
}
$properties->addProperty(
pht('Invitees'),
$invitee_list);
$properties->invokeWillRenderEvent();
$properties->addSectionHeader(

View file

@ -20,6 +20,7 @@ final class PhabricatorCalendarEventEditor
$types[] = PhabricatorCalendarEventTransaction::TYPE_STATUS;
$types[] = PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION;
$types[] = PhabricatorCalendarEventTransaction::TYPE_CANCEL;
$types[] = PhabricatorCalendarEventTransaction::TYPE_INVITE;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
@ -47,6 +48,30 @@ final class PhabricatorCalendarEventEditor
return $object->getDescription();
case PhabricatorCalendarEventTransaction::TYPE_CANCEL:
return $object->getIsCancelled();
case PhabricatorCalendarEventTransaction::TYPE_INVITE:
$map = $xaction->getNewValue();
$phids = array_keys($map);
$invitees = array();
if ($map && !$this->getIsNewObject()) {
$invitees = id(new PhabricatorCalendarEventInviteeQuery())
->setViewer($this->getActor())
->withEventPHIDs(array($object->getPHID()))
->withInviteePHIDs($phids)
->execute();
$invitees = mpull($invitees, null, 'getInviteePHID');
}
$old = array();
foreach ($phids as $phid) {
$invitee = idx($invitees, $phid);
if ($invitee) {
$old[$phid] = $invitee->getStatus();
} else {
$old[$phid] = PhabricatorCalendarEventInvitee::STATUS_UNINVITED;
}
}
return $old;
}
return parent::getCustomTransactionOldValue($object, $xaction);
@ -55,13 +80,13 @@ final class PhabricatorCalendarEventEditor
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorCalendarEventTransaction::TYPE_NAME:
case PhabricatorCalendarEventTransaction::TYPE_START_DATE:
case PhabricatorCalendarEventTransaction::TYPE_END_DATE:
case PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION:
case PhabricatorCalendarEventTransaction::TYPE_CANCEL:
case PhabricatorCalendarEventTransaction::TYPE_INVITE:
return $xaction->getNewValue();
case PhabricatorCalendarEventTransaction::TYPE_STATUS:
return (int)$xaction->getNewValue();
@ -93,6 +118,7 @@ final class PhabricatorCalendarEventEditor
case PhabricatorCalendarEventTransaction::TYPE_CANCEL:
$object->setIsCancelled((int)$xaction->getNewValue());
return;
case PhabricatorCalendarEventTransaction::TYPE_INVITE:
case PhabricatorTransactions::TYPE_VIEW_POLICY:
case PhabricatorTransactions::TYPE_EDIT_POLICY:
case PhabricatorTransactions::TYPE_EDGE:
@ -114,6 +140,33 @@ final class PhabricatorCalendarEventEditor
case PhabricatorCalendarEventTransaction::TYPE_STATUS:
case PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION:
case PhabricatorCalendarEventTransaction::TYPE_CANCEL:
return;
case PhabricatorCalendarEventTransaction::TYPE_INVITE:
$map = $xaction->getNewValue();
$phids = array_keys($map);
$invitees = array();
if ($map) {
$invitees = id(new PhabricatorCalendarEventInviteeQuery())
->setViewer($this->getActor())
->withEventPHIDs(array($object->getPHID()))
->withInviteePHIDs($phids)
->execute();
$invitees = mpull($invitees, null, 'getInviteePHID');
}
foreach ($phids as $phid) {
$invitee = idx($invitees, $phid);
if (!$invitee) {
$invitee = id(new PhabricatorCalendarEventInvitee())
->setEventPHID($object->getPHID())
->setInviteePHID($phid)
->setInviterPHID($this->getActingAsPHID());
}
$invitee->setStatus($map[$phid])
->save();
}
return;
case PhabricatorTransactions::TYPE_VIEW_POLICY:
case PhabricatorTransactions::TYPE_EDIT_POLICY:
case PhabricatorTransactions::TYPE_EDGE:

View file

@ -0,0 +1,99 @@
<?php
final class PhabricatorCalendarEventInviteeQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $eventPHIDs;
private $inviteePHIDs;
private $inviterPHIDs;
private $statuses;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withEventPHIDs(array $phids) {
$this->eventPHIDs = $phids;
return $this;
}
public function withInviteePHIDs(array $phids) {
$this->inviteePHIDs = $phids;
return $this;
}
public function withInviterPHIDs(array $phids) {
$this->inviterPHIDs = $phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
protected function loadPage() {
$table = new PhabricatorCalendarEventInvitee();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->eventPHIDs) {
$where[] = qsprintf(
$conn_r,
'eventPHID IN (%Ls)',
$this->eventPHIDs);
}
if ($this->inviteePHIDs) {
$where[] = qsprintf(
$conn_r,
'inviteePHID IN (%Ls)',
$this->inviteePHIDs);
}
if ($this->inviterPHIDs) {
$where[] = qsprintf(
$conn_r,
'inviterPHID IN (%Ls)',
$this->inviterPHIDs);
}
if ($this->statuses) {
$where[] = qsprintf(
$conn_r,
'status = %d',
$this->statuses);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorCalendarApplication';
}
}

View file

@ -121,4 +121,26 @@ final class PhabricatorCalendarEventQuery
return 'PhabricatorCalendarApplication';
}
protected function willFilterPage(array $events) {
$phids = array();
foreach ($events as $event) {
$phids[] = $event->getPHID();
}
$invitees = id(new PhabricatorCalendarEventInviteeQuery())
->setViewer($this->getViewer())
->withEventPHIDs($phids)
->execute();
$invitees = mgroup($invitees, 'getEventPHID');
foreach ($events as $event) {
$event_invitees = idx($invitees, $event->getPHID(), array());
$event->attachInvitees($event_invitees);
}
return $events;
}
}

View file

@ -18,6 +18,8 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO
protected $description;
protected $isCancelled;
private $invitees = self::ATTACHABLE;
const STATUS_AWAY = 1;
const STATUS_SPORADIC = 2;
@ -118,6 +120,15 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO
return mpull($statuses, null, 'getUserPHID');
}
public function getInvitees() {
return $this->assertAttached($this->invitees);
}
public function attachInvitees(array $invitees) {
$this->invitees = $invitees;
return $this;
}
/**
* Validates data and throws exceptions for non-sensical status
* windows

View file

@ -0,0 +1,64 @@
<?php
final class PhabricatorCalendarEventInvitee extends PhabricatorCalendarDAO
implements PhabricatorPolicyInterface {
protected $eventPHID;
protected $inviteePHID;
protected $inviterPHID;
protected $status;
const STATUS_INVITED = 'invited';
const STATUS_ATTENDING = 'attending';
const STATUS_DECLINED = 'declined';
const STATUS_UNINVITED = 'uninvited';
public static function initializeNewCalendarEventInvitee(
PhabricatorUser $actor, $event) {
return id(new PhabricatorCalendarEventInvitee())
->setInviterPHID($actor->getPHID())
->setStatus(self::STATUS_INVITED)
->setEventPHID($event->getPHID());
}
protected function getConfiguration() {
return array(
self::CONFIG_COLUMN_SCHEMA => array(
'status' => 'text64',
),
self::CONFIG_KEY_SCHEMA => array(
'key_event' => array(
'columns' => array('eventPHID', 'inviteePHID'),
'unique' => true,
),
'key_invitee' => array(
'columns' => array('inviteePHID'),
),
),
) + parent::getConfiguration();
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return PhabricatorPolicies::getMostOpenPolicy();
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return false;
}
public function describeAutomaticCapability($capability) {
return null;
}
}

View file

@ -9,6 +9,7 @@ final class PhabricatorCalendarEventTransaction
const TYPE_STATUS = 'calendar.status';
const TYPE_DESCRIPTION = 'calendar.description';
const TYPE_CANCEL = 'calendar.cancel';
const TYPE_INVITE = 'calendar.invite';
const MAILTAG_CONTENT = 'calendar-content';
const MAILTAG_OTHER = 'calendar-other';
@ -35,6 +36,7 @@ final class PhabricatorCalendarEventTransaction
case self::TYPE_STATUS:
case self::TYPE_DESCRIPTION:
case self::TYPE_CANCEL:
case self::TYPE_INVITE:
$phids[] = $this->getObjectPHID();
break;
}
@ -50,6 +52,7 @@ final class PhabricatorCalendarEventTransaction
case self::TYPE_STATUS:
case self::TYPE_DESCRIPTION:
case self::TYPE_CANCEL:
case self::TYPE_INVITE:
return ($old === null);
}
return parent::shouldHide();
@ -63,6 +66,7 @@ final class PhabricatorCalendarEventTransaction
case self::TYPE_STATUS:
case self::TYPE_DESCRIPTION:
case self::TYPE_CANCEL:
case self::TYPE_INVITE:
return 'fa-pencil';
break;
}
@ -131,6 +135,11 @@ final class PhabricatorCalendarEventTransaction
$this->renderHandleLink($author_phid));
break;
}
case self::TYPE_INVITE:
return pht(
"%s updated the event's invitee list.",
$this->renderHandleLink($author_phid));
break;
}
return parent::getTitle();
@ -216,6 +225,12 @@ final class PhabricatorCalendarEventTransaction
$this->renderHandleLink($object_phid));
break;
}
case self::TYPE_INVITE:
return pht(
'%s updated the invitee list of %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
break;
}
return parent::getTitleForFeed();
@ -232,6 +247,7 @@ final class PhabricatorCalendarEventTransaction
case self::TYPE_STATUS:
case self::TYPE_DESCRIPTION:
case self::TYPE_CANCEL:
case self::TYPE_INVITE:
return PhabricatorTransactions::COLOR_GREEN;
}
@ -284,6 +300,9 @@ final class PhabricatorCalendarEventTransaction
case self::TYPE_CANCEL:
$tags[] = self::MAILTAG_CONTENT;
break;
case self::TYPE_INVITE:
$tags[] = self::MAILTAG_CONTENT;
break;
}
return $tags;
}