Page MenuHomePhabricator

D12613.id30286.diff
No OneTemporary

D12613.id30286.diff

diff --git a/resources/sql/autopatches/20150429.calendar.1.invitee.sql b/resources/sql/autopatches/20150429.calendar.1.invitee.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20150429.calendar.1.invitee.sql
@@ -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};
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1486,6 +1486,8 @@
'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 @@
'PhabricatorCalendarEventEditController' => 'PhabricatorCalendarController',
'PhabricatorCalendarEventEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorCalendarEventInvalidEpochException' => 'Exception',
+ 'PhabricatorCalendarEventInvitee' => array(
+ 'PhabricatorCalendarDAO',
+ 'PhabricatorPolicyInterface',
+ ),
+ 'PhabricatorCalendarEventInviteeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorCalendarEventListController' => 'PhabricatorCalendarController',
'PhabricatorCalendarEventPHIDType' => 'PhabricatorPHIDType',
'PhabricatorCalendarEventQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
diff --git a/src/applications/calendar/controller/PhabricatorCalendarEventEditController.php b/src/applications/calendar/controller/PhabricatorCalendarEventEditController.php
--- a/src/applications/calendar/controller/PhabricatorCalendarEventEditController.php
+++ b/src/applications/calendar/controller/PhabricatorCalendarEventEditController.php
@@ -16,8 +16,10 @@
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 @@
$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 @@
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 @@
->setUser($user)
->setDatasource(new PhabricatorMetaMTAMailableDatasource());
-
$form = id(new AphrontFormView())
->setUser($user)
->appendChild($name)
diff --git a/src/applications/calendar/controller/PhabricatorCalendarEventViewController.php b/src/applications/calendar/controller/PhabricatorCalendarEventViewController.php
--- a/src/applications/calendar/controller/PhabricatorCalendarEventViewController.php
+++ b/src/applications/calendar/controller/PhabricatorCalendarEventViewController.php
@@ -127,6 +127,20 @@
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(
diff --git a/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php b/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php
--- a/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php
+++ b/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php
@@ -20,6 +20,7 @@
$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 @@
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 @@
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 @@
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 @@
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:
diff --git a/src/applications/calendar/query/PhabricatorCalendarEventInviteeQuery.php b/src/applications/calendar/query/PhabricatorCalendarEventInviteeQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/query/PhabricatorCalendarEventInviteeQuery.php
@@ -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';
+ }
+
+}
diff --git a/src/applications/calendar/query/PhabricatorCalendarEventQuery.php b/src/applications/calendar/query/PhabricatorCalendarEventQuery.php
--- a/src/applications/calendar/query/PhabricatorCalendarEventQuery.php
+++ b/src/applications/calendar/query/PhabricatorCalendarEventQuery.php
@@ -121,4 +121,26 @@
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;
+ }
+
}
diff --git a/src/applications/calendar/storage/PhabricatorCalendarEvent.php b/src/applications/calendar/storage/PhabricatorCalendarEvent.php
--- a/src/applications/calendar/storage/PhabricatorCalendarEvent.php
+++ b/src/applications/calendar/storage/PhabricatorCalendarEvent.php
@@ -18,6 +18,8 @@
protected $description;
protected $isCancelled;
+ private $invitees = self::ATTACHABLE;
+
const STATUS_AWAY = 1;
const STATUS_SPORADIC = 2;
@@ -118,6 +120,15 @@
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
diff --git a/src/applications/calendar/storage/PhabricatorCalendarEventInvitee.php b/src/applications/calendar/storage/PhabricatorCalendarEventInvitee.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/storage/PhabricatorCalendarEventInvitee.php
@@ -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;
+ }
+}
diff --git a/src/applications/calendar/storage/PhabricatorCalendarEventTransaction.php b/src/applications/calendar/storage/PhabricatorCalendarEventTransaction.php
--- a/src/applications/calendar/storage/PhabricatorCalendarEventTransaction.php
+++ b/src/applications/calendar/storage/PhabricatorCalendarEventTransaction.php
@@ -9,6 +9,7 @@
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 @@
case self::TYPE_STATUS:
case self::TYPE_DESCRIPTION:
case self::TYPE_CANCEL:
+ case self::TYPE_INVITE:
$phids[] = $this->getObjectPHID();
break;
}
@@ -50,6 +52,7 @@
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 @@
case self::TYPE_STATUS:
case self::TYPE_DESCRIPTION:
case self::TYPE_CANCEL:
+ case self::TYPE_INVITE:
return 'fa-pencil';
break;
}
@@ -131,6 +135,11 @@
$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 @@
$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 @@
case self::TYPE_STATUS:
case self::TYPE_DESCRIPTION:
case self::TYPE_CANCEL:
+ case self::TYPE_INVITE:
return PhabricatorTransactions::COLOR_GREEN;
}
@@ -284,6 +300,9 @@
case self::TYPE_CANCEL:
$tags[] = self::MAILTAG_CONTENT;
break;
+ case self::TYPE_INVITE:
+ $tags[] = self::MAILTAG_CONTENT;
+ break;
}
return $tags;
}

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 23, 3:05 PM (17 h, 41 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6778762
Default Alt Text
D12613.id30286.diff (17 KB)

Event Timeline