Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14080578
D12613.id30286.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
17 KB
Referenced Files
None
Subscribers
None
D12613.id30286.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D12613: Calendar events should now auto-invite the creator
Attached
Detach File
Event Timeline
Log In to Comment