Page MenuHomePhabricator

D16286.id39160.diff
No OneTemporary

D16286.id39160.diff

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
@@ -2021,24 +2021,40 @@
'PhabricatorCalendarDAO' => 'applications/calendar/storage/PhabricatorCalendarDAO.php',
'PhabricatorCalendarEditEngine' => 'applications/calendar/editor/PhabricatorCalendarEditEngine.php',
'PhabricatorCalendarEvent' => 'applications/calendar/storage/PhabricatorCalendarEvent.php',
+ 'PhabricatorCalendarEventAcceptTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventAcceptTransaction.php',
+ 'PhabricatorCalendarEventAllDayTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventAllDayTransaction.php',
'PhabricatorCalendarEventCancelController' => 'applications/calendar/controller/PhabricatorCalendarEventCancelController.php',
+ 'PhabricatorCalendarEventCancelTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventCancelTransaction.php',
+ 'PhabricatorCalendarEventDateTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventDateTransaction.php',
+ 'PhabricatorCalendarEventDeclineTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventDeclineTransaction.php',
+ 'PhabricatorCalendarEventDescriptionTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventDescriptionTransaction.php',
'PhabricatorCalendarEventDragController' => 'applications/calendar/controller/PhabricatorCalendarEventDragController.php',
'PhabricatorCalendarEventEditController' => 'applications/calendar/controller/PhabricatorCalendarEventEditController.php',
'PhabricatorCalendarEventEditor' => 'applications/calendar/editor/PhabricatorCalendarEventEditor.php',
'PhabricatorCalendarEventEmailCommand' => 'applications/calendar/command/PhabricatorCalendarEventEmailCommand.php',
+ 'PhabricatorCalendarEventEndDateTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventEndDateTransaction.php',
+ 'PhabricatorCalendarEventFrequencyTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventFrequencyTransaction.php',
'PhabricatorCalendarEventFulltextEngine' => 'applications/calendar/search/PhabricatorCalendarEventFulltextEngine.php',
+ 'PhabricatorCalendarEventIconTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventIconTransaction.php',
+ 'PhabricatorCalendarEventInviteTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventInviteTransaction.php',
'PhabricatorCalendarEventInvitee' => 'applications/calendar/storage/PhabricatorCalendarEventInvitee.php',
'PhabricatorCalendarEventInviteeQuery' => 'applications/calendar/query/PhabricatorCalendarEventInviteeQuery.php',
'PhabricatorCalendarEventJoinController' => 'applications/calendar/controller/PhabricatorCalendarEventJoinController.php',
'PhabricatorCalendarEventListController' => 'applications/calendar/controller/PhabricatorCalendarEventListController.php',
'PhabricatorCalendarEventMailReceiver' => 'applications/calendar/mail/PhabricatorCalendarEventMailReceiver.php',
+ 'PhabricatorCalendarEventNameTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventNameTransaction.php',
'PhabricatorCalendarEventPHIDType' => 'applications/calendar/phid/PhabricatorCalendarEventPHIDType.php',
'PhabricatorCalendarEventQuery' => 'applications/calendar/query/PhabricatorCalendarEventQuery.php',
'PhabricatorCalendarEventRSVPEmailCommand' => 'applications/calendar/command/PhabricatorCalendarEventRSVPEmailCommand.php',
+ 'PhabricatorCalendarEventRecurringTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventRecurringTransaction.php',
+ 'PhabricatorCalendarEventReplyTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventReplyTransaction.php',
'PhabricatorCalendarEventSearchEngine' => 'applications/calendar/query/PhabricatorCalendarEventSearchEngine.php',
+ 'PhabricatorCalendarEventStartDateTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventStartDateTransaction.php',
'PhabricatorCalendarEventTransaction' => 'applications/calendar/storage/PhabricatorCalendarEventTransaction.php',
'PhabricatorCalendarEventTransactionComment' => 'applications/calendar/storage/PhabricatorCalendarEventTransactionComment.php',
'PhabricatorCalendarEventTransactionQuery' => 'applications/calendar/query/PhabricatorCalendarEventTransactionQuery.php',
+ 'PhabricatorCalendarEventTransactionType' => 'applications/calendar/xaction/PhabricatorCalendarEventTransactionType.php',
+ 'PhabricatorCalendarEventUntilDateTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventUntilDateTransaction.php',
'PhabricatorCalendarEventViewController' => 'applications/calendar/controller/PhabricatorCalendarEventViewController.php',
'PhabricatorCalendarHoliday' => 'applications/calendar/storage/PhabricatorCalendarHoliday.php',
'PhabricatorCalendarHolidayTestCase' => 'applications/calendar/storage/__tests__/PhabricatorCalendarHolidayTestCase.php',
@@ -6629,12 +6645,22 @@
'PhabricatorSpacesInterface',
'PhabricatorFulltextInterface',
),
+ 'PhabricatorCalendarEventAcceptTransaction' => 'PhabricatorCalendarEventReplyTransaction',
+ 'PhabricatorCalendarEventAllDayTransaction' => 'PhabricatorCalendarEventTransactionType',
'PhabricatorCalendarEventCancelController' => 'PhabricatorCalendarController',
+ 'PhabricatorCalendarEventCancelTransaction' => 'PhabricatorCalendarEventTransactionType',
+ 'PhabricatorCalendarEventDateTransaction' => 'PhabricatorCalendarEventTransactionType',
+ 'PhabricatorCalendarEventDeclineTransaction' => 'PhabricatorCalendarEventReplyTransaction',
+ 'PhabricatorCalendarEventDescriptionTransaction' => 'PhabricatorCalendarEventTransactionType',
'PhabricatorCalendarEventDragController' => 'PhabricatorCalendarController',
'PhabricatorCalendarEventEditController' => 'PhabricatorCalendarController',
'PhabricatorCalendarEventEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorCalendarEventEmailCommand' => 'MetaMTAEmailTransactionCommand',
+ 'PhabricatorCalendarEventEndDateTransaction' => 'PhabricatorCalendarEventDateTransaction',
+ 'PhabricatorCalendarEventFrequencyTransaction' => 'PhabricatorCalendarEventTransactionType',
'PhabricatorCalendarEventFulltextEngine' => 'PhabricatorFulltextEngine',
+ 'PhabricatorCalendarEventIconTransaction' => 'PhabricatorCalendarEventTransactionType',
+ 'PhabricatorCalendarEventInviteTransaction' => 'PhabricatorCalendarEventTransactionType',
'PhabricatorCalendarEventInvitee' => array(
'PhabricatorCalendarDAO',
'PhabricatorPolicyInterface',
@@ -6643,13 +6669,19 @@
'PhabricatorCalendarEventJoinController' => 'PhabricatorCalendarController',
'PhabricatorCalendarEventListController' => 'PhabricatorCalendarController',
'PhabricatorCalendarEventMailReceiver' => 'PhabricatorObjectMailReceiver',
+ 'PhabricatorCalendarEventNameTransaction' => 'PhabricatorCalendarEventTransactionType',
'PhabricatorCalendarEventPHIDType' => 'PhabricatorPHIDType',
'PhabricatorCalendarEventQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorCalendarEventRSVPEmailCommand' => 'PhabricatorCalendarEventEmailCommand',
+ 'PhabricatorCalendarEventRecurringTransaction' => 'PhabricatorCalendarEventTransactionType',
+ 'PhabricatorCalendarEventReplyTransaction' => 'PhabricatorCalendarEventTransactionType',
'PhabricatorCalendarEventSearchEngine' => 'PhabricatorApplicationSearchEngine',
- 'PhabricatorCalendarEventTransaction' => 'PhabricatorApplicationTransaction',
+ 'PhabricatorCalendarEventStartDateTransaction' => 'PhabricatorCalendarEventDateTransaction',
+ 'PhabricatorCalendarEventTransaction' => 'PhabricatorModularTransaction',
'PhabricatorCalendarEventTransactionComment' => 'PhabricatorApplicationTransactionComment',
'PhabricatorCalendarEventTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
+ 'PhabricatorCalendarEventTransactionType' => 'PhabricatorModularTransactionType',
+ 'PhabricatorCalendarEventUntilDateTransaction' => 'PhabricatorCalendarEventDateTransaction',
'PhabricatorCalendarEventViewController' => 'PhabricatorCalendarController',
'PhabricatorCalendarHoliday' => 'PhabricatorCalendarDAO',
'PhabricatorCalendarHolidayTestCase' => 'PhabricatorTestCase',
diff --git a/src/applications/calendar/command/PhabricatorCalendarEventRSVPEmailCommand.php b/src/applications/calendar/command/PhabricatorCalendarEventRSVPEmailCommand.php
--- a/src/applications/calendar/command/PhabricatorCalendarEventRSVPEmailCommand.php
+++ b/src/applications/calendar/command/PhabricatorCalendarEventRSVPEmailCommand.php
@@ -44,32 +44,24 @@
PhabricatorMetaMTAReceivedMail $mail,
$command,
array $argv) {
- $status_attending = PhabricatorCalendarEventInvitee::STATUS_ATTENDING;
- $status_declined = PhabricatorCalendarEventInvitee::STATUS_DECLINED;
- $xactions = array();
$target = phutil_utf8_strtolower(implode(' ', $argv));
- $rsvp = null;
$yes_values = $this->getYesValues();
$no_values = $this->getNoValues();
if (in_array($target, $yes_values)) {
- $rsvp = $status_attending;
+ $rsvp = PhabricatorCalendarEventAcceptTransaction::TRANSACTIONTYPE;
} else if (in_array($target, $no_values)) {
- $rsvp = $status_declined;
+ $rsvp = PhabricatorCalendarEventDeclineTransaction::TRANSACTIONTYPE;
} else {
- $rsvp = null;
- }
-
- if ($rsvp === null) {
return array();
}
+ $xactions = array();
$xactions[] = $object->getApplicationTransactionTemplate()
- ->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_INVITE)
- ->setNewValue(array($viewer->getPHID() => $rsvp));
-
+ ->setTransactionType($rsvp)
+ ->setNewValue(true);
return $xactions;
}
diff --git a/src/applications/calendar/controller/PhabricatorCalendarEventCancelController.php b/src/applications/calendar/controller/PhabricatorCalendarEventCancelController.php
--- a/src/applications/calendar/controller/PhabricatorCalendarEventCancelController.php
+++ b/src/applications/calendar/controller/PhabricatorCalendarEventCancelController.php
@@ -38,7 +38,7 @@
$xaction = id(new PhabricatorCalendarEventTransaction())
->setTransactionType(
- PhabricatorCalendarEventTransaction::TYPE_CANCEL)
+ PhabricatorCalendarEventCancelTransaction::TRANSACTIONTYPE)
->setNewValue(!$is_cancelled);
$editor = id(new PhabricatorCalendarEventEditor())
diff --git a/src/applications/calendar/controller/PhabricatorCalendarEventDragController.php b/src/applications/calendar/controller/PhabricatorCalendarEventDragController.php
--- a/src/applications/calendar/controller/PhabricatorCalendarEventDragController.php
+++ b/src/applications/calendar/controller/PhabricatorCalendarEventDragController.php
@@ -41,13 +41,14 @@
$viewer,
$end));
-
$xactions[] = id(new PhabricatorCalendarEventTransaction())
- ->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_START_DATE)
+ ->setTransactionType(
+ PhabricatorCalendarEventStartDateTransaction::TRANSACTIONTYPE)
->setNewValue($start_value);
$xactions[] = id(new PhabricatorCalendarEventTransaction())
- ->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_END_DATE)
+ ->setTransactionType(
+ PhabricatorCalendarEventEndDateTransaction::TRANSACTIONTYPE)
->setNewValue($end_value);
$editor = id(new PhabricatorCalendarEventEditor())
diff --git a/src/applications/calendar/controller/PhabricatorCalendarEventJoinController.php b/src/applications/calendar/controller/PhabricatorCalendarEventJoinController.php
--- a/src/applications/calendar/controller/PhabricatorCalendarEventJoinController.php
+++ b/src/applications/calendar/controller/PhabricatorCalendarEventJoinController.php
@@ -33,9 +33,11 @@
$validation_exception = null;
if ($request->isFormPost()) {
if ($is_join) {
- $xaction_type = PhabricatorCalendarEventTransaction::TYPE_ACCEPT;
+ $xaction_type =
+ PhabricatorCalendarEventAcceptTransaction::TRANSACTIONTYPE;
} else {
- $xaction_type = PhabricatorCalendarEventTransaction::TYPE_DECLINE;
+ $xaction_type =
+ PhabricatorCalendarEventDeclineTransaction::TRANSACTIONTYPE;
}
$xaction = id(new PhabricatorCalendarEventTransaction())
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
@@ -120,7 +120,7 @@
if ($event->isChildEvent()) {
$edit_label = pht('Edit This Instance');
} else {
- $edit_label = pht('Edit');
+ $edit_label = pht('Edit Event');
}
$curtain = $this->newCurtainView($event);
diff --git a/src/applications/calendar/editor/PhabricatorCalendarEditEngine.php b/src/applications/calendar/editor/PhabricatorCalendarEditEngine.php
--- a/src/applications/calendar/editor/PhabricatorCalendarEditEngine.php
+++ b/src/applications/calendar/editor/PhabricatorCalendarEditEngine.php
@@ -81,7 +81,8 @@
->setLabel(pht('Name'))
->setDescription(pht('Name of the event.'))
->setIsRequired(true)
- ->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_NAME)
+ ->setTransactionType(
+ PhabricatorCalendarEventNameTransaction::TRANSACTIONTYPE)
->setConduitDescription(pht('Rename the event.'))
->setConduitTypeDescription(pht('New event name.'))
->setValue($object->getName()),
@@ -90,7 +91,7 @@
->setLabel(pht('Description'))
->setDescription(pht('Description of the event.'))
->setTransactionType(
- PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION)
+ PhabricatorCalendarEventDescriptionTransaction::TRANSACTIONTYPE)
->setConduitDescription(pht('Update the event description.'))
->setConduitTypeDescription(pht('New event description.'))
->setValue($object->getDescription()),
@@ -100,7 +101,7 @@
->setLabel(pht('Cancelled'))
->setDescription(pht('Cancel the event.'))
->setTransactionType(
- PhabricatorCalendarEventTransaction::TYPE_CANCEL)
+ PhabricatorCalendarEventCancelTransaction::TRANSACTIONTYPE)
->setIsConduitOnly(true)
->setConduitDescription(pht('Cancel or restore the event.'))
->setConduitTypeDescription(pht('True to cancel the event.'))
@@ -110,7 +111,8 @@
->setAliases(array('invite', 'invitee', 'invitees', 'inviteePHID'))
->setLabel(pht('Invitees'))
->setDatasource(new PhabricatorMetaMTAMailableDatasource())
- ->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_INVITE)
+ ->setTransactionType(
+ PhabricatorCalendarEventInviteTransaction::TRANSACTIONTYPE)
->setDescription(pht('Users invited to the event.'))
->setConduitDescription(pht('Change invited users.'))
->setConduitTypeDescription(pht('New event invitees.'))
@@ -124,7 +126,7 @@
->setLabel(pht('Recurring'))
->setOptions(pht('One-Time Event'), pht('Recurring Event'))
->setTransactionType(
- PhabricatorCalendarEventTransaction::TYPE_RECURRING)
+ PhabricatorCalendarEventRecurringTransaction::TRANSACTIONTYPE)
->setDescription(pht('One time or recurring event.'))
->setConduitDescription(pht('Make the event recurring.'))
->setConduitTypeDescription(pht('Mark the event as a recurring event.'))
@@ -135,7 +137,7 @@
->setLabel(pht('Frequency'))
->setOptions($frequency_options)
->setTransactionType(
- PhabricatorCalendarEventTransaction::TYPE_FREQUENCY)
+ PhabricatorCalendarEventFrequencyTransaction::TRANSACTIONTYPE)
->setDescription(pht('Recurring event frequency.'))
->setConduitDescription(pht('Change the event frequency.'))
->setConduitTypeDescription(pht('New event frequency.'))
@@ -148,7 +150,7 @@
->setKey('until')
->setLabel(pht('Repeat Until'))
->setTransactionType(
- PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE)
+ PhabricatorCalendarEventUntilDateTransaction::TRANSACTIONTYPE)
->setDescription(pht('Last instance of the event.'))
->setConduitDescription(pht('Change when the event repeats until.'))
->setConduitTypeDescription(pht('New final event time.'))
@@ -159,7 +161,8 @@
->setKey('isAllDay')
->setLabel(pht('All Day'))
->setOptions(pht('Normal Event'), pht('All Day Event'))
- ->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_ALL_DAY)
+ ->setTransactionType(
+ PhabricatorCalendarEventAllDayTransaction::TRANSACTIONTYPE)
->setDescription(pht('Marks this as an all day event.'))
->setConduitDescription(pht('Make the event an all day event.'))
->setConduitTypeDescription(pht('Mark the event as an all day event.'))
@@ -169,7 +172,7 @@
->setKey('start')
->setLabel(pht('Start'))
->setTransactionType(
- PhabricatorCalendarEventTransaction::TYPE_START_DATE)
+ PhabricatorCalendarEventStartDateTransaction::TRANSACTIONTYPE)
->setDescription(pht('Start time of the event.'))
->setConduitDescription(pht('Change the start time of the event.'))
->setConduitTypeDescription(pht('New event start time.'))
@@ -179,7 +182,7 @@
->setKey('end')
->setLabel(pht('End'))
->setTransactionType(
- PhabricatorCalendarEventTransaction::TYPE_END_DATE)
+ PhabricatorCalendarEventEndDateTransaction::TRANSACTIONTYPE)
->setDescription(pht('End time of the event.'))
->setConduitDescription(pht('Change the end time of the event.'))
->setConduitTypeDescription(pht('New event end time.'))
@@ -189,7 +192,8 @@
->setKey('icon')
->setLabel(pht('Icon'))
->setIconSet(new PhabricatorCalendarIconSet())
- ->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_ICON)
+ ->setTransactionType(
+ PhabricatorCalendarEventIconTransaction::TRANSACTIONTYPE)
->setDescription(pht('Event icon.'))
->setConduitDescription(pht('Change the event icon.'))
->setConduitTypeDescription(pht('New event icon.'))
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
@@ -58,21 +58,6 @@
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
- $types[] = PhabricatorCalendarEventTransaction::TYPE_NAME;
- $types[] = PhabricatorCalendarEventTransaction::TYPE_START_DATE;
- $types[] = PhabricatorCalendarEventTransaction::TYPE_END_DATE;
- $types[] = PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION;
- $types[] = PhabricatorCalendarEventTransaction::TYPE_CANCEL;
- $types[] = PhabricatorCalendarEventTransaction::TYPE_INVITE;
- $types[] = PhabricatorCalendarEventTransaction::TYPE_ALL_DAY;
- $types[] = PhabricatorCalendarEventTransaction::TYPE_ICON;
- $types[] = PhabricatorCalendarEventTransaction::TYPE_ACCEPT;
- $types[] = PhabricatorCalendarEventTransaction::TYPE_DECLINE;
-
- $types[] = PhabricatorCalendarEventTransaction::TYPE_RECURRING;
- $types[] = PhabricatorCalendarEventTransaction::TYPE_FREQUENCY;
- $types[] = PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE;
-
$types[] = PhabricatorTransactions::TYPE_COMMENT;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
@@ -80,217 +65,6 @@
return $types;
}
- protected function getCustomTransactionOldValue(
- PhabricatorLiskDAO $object,
- PhabricatorApplicationTransaction $xaction) {
- switch ($xaction->getTransactionType()) {
- case PhabricatorCalendarEventTransaction::TYPE_RECURRING:
- return (int)$object->getIsRecurring();
- case PhabricatorCalendarEventTransaction::TYPE_FREQUENCY:
- return $object->getFrequencyUnit();
- case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE:
- return $object->getRecurrenceEndDate();
- case PhabricatorCalendarEventTransaction::TYPE_NAME:
- return $object->getName();
- case PhabricatorCalendarEventTransaction::TYPE_START_DATE:
- return $object->getDateFrom();
- case PhabricatorCalendarEventTransaction::TYPE_END_DATE:
- return $object->getDateTo();
- case PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION:
- return $object->getDescription();
- case PhabricatorCalendarEventTransaction::TYPE_CANCEL:
- return $object->getIsCancelled();
- case PhabricatorCalendarEventTransaction::TYPE_ALL_DAY:
- return (int)$object->getIsAllDay();
- case PhabricatorCalendarEventTransaction::TYPE_ICON:
- return $object->getIcon();
- case PhabricatorCalendarEventTransaction::TYPE_ACCEPT:
- case PhabricatorCalendarEventTransaction::TYPE_DECLINE:
- $actor_phid = $this->getActingAsPHID();
- return $object->getUserInviteStatus($actor_phid);
- case PhabricatorCalendarEventTransaction::TYPE_INVITE:
- $invitees = $object->getInvitees();
- return mpull($invitees, 'getStatus', 'getInviteePHID');
- }
-
- return parent::getCustomTransactionOldValue($object, $xaction);
- }
-
- protected function getCustomTransactionNewValue(
- PhabricatorLiskDAO $object,
- PhabricatorApplicationTransaction $xaction) {
- switch ($xaction->getTransactionType()) {
- case PhabricatorCalendarEventTransaction::TYPE_FREQUENCY:
- case PhabricatorCalendarEventTransaction::TYPE_NAME:
- case PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION:
- case PhabricatorCalendarEventTransaction::TYPE_CANCEL:
- case PhabricatorCalendarEventTransaction::TYPE_ICON:
- return $xaction->getNewValue();
- case PhabricatorCalendarEventTransaction::TYPE_ACCEPT:
- return PhabricatorCalendarEventInvitee::STATUS_ATTENDING;
- case PhabricatorCalendarEventTransaction::TYPE_DECLINE:
- return PhabricatorCalendarEventInvitee::STATUS_DECLINED;
- case PhabricatorCalendarEventTransaction::TYPE_ALL_DAY:
- case PhabricatorCalendarEventTransaction::TYPE_RECURRING:
- return (int)$xaction->getNewValue();
- case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE:
- case PhabricatorCalendarEventTransaction::TYPE_START_DATE:
- case PhabricatorCalendarEventTransaction::TYPE_END_DATE:
- return $xaction->getNewValue()->getEpoch();
- case PhabricatorCalendarEventTransaction::TYPE_INVITE:
- $status_invited = PhabricatorCalendarEventInvitee::STATUS_INVITED;
- $status_uninvited = PhabricatorCalendarEventInvitee::STATUS_UNINVITED;
- $status_attending = PhabricatorCalendarEventInvitee::STATUS_ATTENDING;
-
- $invitees = $object->getInvitees();
- foreach ($invitees as $key => $invitee) {
- if ($invitee->getStatus() == $status_uninvited) {
- unset($invitees[$key]);
- }
- }
- $invitees = mpull($invitees, null, 'getInviteePHID');
-
- $new = $xaction->getNewValue();
- $new = array_fuse($new);
-
- $all = array_keys($invitees + $new);
- $map = array();
- foreach ($all as $phid) {
- $is_old = isset($invitees[$phid]);
- $is_new = isset($new[$phid]);
-
- if ($is_old && !$is_new) {
- $map[$phid] = $status_uninvited;
- } else if (!$is_old && $is_new) {
- $map[$phid] = $status_invited;
- } else {
- $map[$phid] = $invitees[$phid]->getStatus();
- }
- }
-
- // If we're creating this event and the actor is inviting themselves,
- // mark them as attending.
- if ($this->getIsNewObject()) {
- $acting_phid = $this->getActingAsPHID();
- if (isset($map[$acting_phid])) {
- $map[$acting_phid] = $status_attending;
- }
- }
-
- return $map;
- }
-
- return parent::getCustomTransactionNewValue($object, $xaction);
- }
-
- protected function applyCustomInternalTransaction(
- PhabricatorLiskDAO $object,
- PhabricatorApplicationTransaction $xaction) {
-
- switch ($xaction->getTransactionType()) {
- case PhabricatorCalendarEventTransaction::TYPE_RECURRING:
- return $object->setIsRecurring((int)$xaction->getNewValue());
- case PhabricatorCalendarEventTransaction::TYPE_FREQUENCY:
- return $object->setRecurrenceFrequency(
- array(
- 'rule' => $xaction->getNewValue(),
- ));
- case PhabricatorCalendarEventTransaction::TYPE_NAME:
- $object->setName($xaction->getNewValue());
- return;
- case PhabricatorCalendarEventTransaction::TYPE_START_DATE:
- $object->setDateFrom($xaction->getNewValue());
- return;
- case PhabricatorCalendarEventTransaction::TYPE_END_DATE:
- $object->setDateTo($xaction->getNewValue());
- return;
- case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE:
- $object->setRecurrenceEndDate($xaction->getNewValue());
- return;
- case PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION:
- $object->setDescription($xaction->getNewValue());
- return;
- case PhabricatorCalendarEventTransaction::TYPE_CANCEL:
- $object->setIsCancelled((int)$xaction->getNewValue());
- return;
- case PhabricatorCalendarEventTransaction::TYPE_ALL_DAY:
- $object->setIsAllDay((int)$xaction->getNewValue());
- return;
- case PhabricatorCalendarEventTransaction::TYPE_ICON:
- $object->setIcon($xaction->getNewValue());
- return;
- case PhabricatorCalendarEventTransaction::TYPE_INVITE:
- case PhabricatorCalendarEventTransaction::TYPE_ACCEPT:
- case PhabricatorCalendarEventTransaction::TYPE_DECLINE:
- return;
- }
-
- return parent::applyCustomInternalTransaction($object, $xaction);
- }
-
- protected function applyCustomExternalTransaction(
- PhabricatorLiskDAO $object,
- PhabricatorApplicationTransaction $xaction) {
-
- switch ($xaction->getTransactionType()) {
- case PhabricatorCalendarEventTransaction::TYPE_RECURRING:
- case PhabricatorCalendarEventTransaction::TYPE_FREQUENCY:
- case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE:
- 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_ALL_DAY:
- case PhabricatorCalendarEventTransaction::TYPE_ICON:
- return;
- case PhabricatorCalendarEventTransaction::TYPE_INVITE:
- $map = $xaction->getNewValue();
- $phids = array_keys($map);
- $invitees = $object->getInvitees();
- $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());
- $invitees[] = $invitee;
- }
- $invitee->setStatus($map[$phid])
- ->save();
- }
- $object->attachInvitees($invitees);
- return;
- case PhabricatorCalendarEventTransaction::TYPE_ACCEPT:
- case PhabricatorCalendarEventTransaction::TYPE_DECLINE:
- $acting_phid = $this->getActingAsPHID();
-
- $invitees = $object->getInvitees();
- $invitees = mpull($invitees, null, 'getInviteePHID');
-
- $invitee = idx($invitees, $acting_phid);
- if (!$invitee) {
- $invitee = id(new PhabricatorCalendarEventInvitee())
- ->setEventPHID($object->getPHID())
- ->setInviteePHID($acting_phid)
- ->setInviterPHID($acting_phid);
- $invitees[$acting_phid] = $invitee;
- }
-
- $invitee
- ->setStatus($xaction->getNewValue())
- ->save();
-
- $object->attachInvitees($invitees);
- return;
- }
-
- return parent::applyCustomExternalTransaction($object, $xaction);
- }
-
protected function applyFinalEffects(
PhabricatorLiskDAO $object,
array $xactions) {
@@ -302,26 +76,21 @@
$invalidate_phids = array();
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
- case PhabricatorCalendarEventTransaction::TYPE_ICON:
- break;
- case PhabricatorCalendarEventTransaction::TYPE_RECURRING:
- case PhabricatorCalendarEventTransaction::TYPE_FREQUENCY:
- case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE:
- case PhabricatorCalendarEventTransaction::TYPE_START_DATE:
- case PhabricatorCalendarEventTransaction::TYPE_END_DATE:
- case PhabricatorCalendarEventTransaction::TYPE_CANCEL:
- case PhabricatorCalendarEventTransaction::TYPE_ALL_DAY:
+ case PhabricatorCalendarEventUntilDateTransaction::TRANSACTIONTYPE:
+ case PhabricatorCalendarEventStartDateTransaction::TRANSACTIONTYPE:
+ case PhabricatorCalendarEventEndDateTransaction::TRANSACTIONTYPE:
+ case PhabricatorCalendarEventCancelTransaction::TRANSACTIONTYPE:
+ case PhabricatorCalendarEventAllDayTransaction::TRANSACTIONTYPE:
// For these kinds of changes, we need to invalidate the availabilty
// caches for all attendees.
$invalidate_all = true;
break;
-
- case PhabricatorCalendarEventTransaction::TYPE_ACCEPT:
- case PhabricatorCalendarEventTransaction::TYPE_DECLINE:
+ case PhabricatorCalendarEventAcceptTransaction::TRANSACTIONTYPE:
+ case PhabricatorCalendarEventDeclineTransaction::TRANSACTIONTYPE:
$acting_phid = $this->getActingAsPHID();
$invalidate_phids[$acting_phid] = $acting_phid;
break;
- case PhabricatorCalendarEventTransaction::TYPE_INVITE:
+ case PhabricatorCalendarEventInviteTransaction::TRANSACTIONTYPE:
foreach ($xaction->getNewValue() as $phid => $ignored) {
$invalidate_phids[$phid] = $phid;
}
@@ -357,14 +126,15 @@
protected function validateAllTransactions(
PhabricatorLiskDAO $object,
array $xactions) {
+
$start_date_xaction =
- PhabricatorCalendarEventTransaction::TYPE_START_DATE;
+ PhabricatorCalendarEventStartDateTransaction::TRANSACTIONTYPE;
$end_date_xaction =
- PhabricatorCalendarEventTransaction::TYPE_END_DATE;
+ PhabricatorCalendarEventEndDateTransaction::TRANSACTIONTYPE;
$is_recurrence_xaction =
- PhabricatorCalendarEventTransaction::TYPE_RECURRING;
+ PhabricatorCalendarEventRecurringTransaction::TRANSACTIONTYPE;
$recurrence_end_xaction =
- PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE;
+ PhabricatorCalendarEventUntilDateTransaction::TRANSACTIONTYPE;
$start_date = $object->getDateFrom();
$end_date = $object->getDateTo();
@@ -386,19 +156,16 @@
}
if ($start_date > $end_date) {
- $type = PhabricatorCalendarEventTransaction::TYPE_END_DATE;
$errors[] = new PhabricatorApplicationTransactionValidationError(
- $type,
+ $end_date_xaction,
pht('Invalid'),
pht('End date must be after start date.'),
null);
}
if ($recurrence_end && !$is_recurring) {
- $type =
- PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE;
$errors[] = new PhabricatorApplicationTransactionValidationError(
- $type,
+ $recurrence_end_xaction,
pht('Invalid'),
pht('Event must be recurring to have a recurrence end date.').
null);
@@ -407,97 +174,6 @@
return $errors;
}
- protected function validateTransaction(
- PhabricatorLiskDAO $object,
- $type,
- array $xactions) {
-
- $errors = parent::validateTransaction($object, $type, $xactions);
-
- switch ($type) {
- case PhabricatorCalendarEventTransaction::TYPE_NAME:
- $missing = $this->validateIsEmptyTextField(
- $object->getName(),
- $xactions);
-
- if ($missing) {
- $error = new PhabricatorApplicationTransactionValidationError(
- $type,
- pht('Required'),
- pht('Event name is required.'),
- nonempty(last($xactions), null));
-
- $error->setIsMissingFieldError(true);
- $errors[] = $error;
- }
- break;
- case PhabricatorCalendarEventTransaction::TYPE_INVITE:
- $old = $object->getInvitees();
- $old = mpull($old, null, 'getInviteePHID');
- foreach ($xactions as $xaction) {
- $new = $xaction->getNewValue();
- $new = array_fuse($new);
- $add = array_diff_key($new, $old);
- if (!$add) {
- continue;
- }
-
- // In the UI, we only allow you to invite mailable objects, but there
- // is no definitive marker for "invitable object" today. Just allow
- // any valid object to be invited.
- $objects = id(new PhabricatorObjectQuery())
- ->setViewer($this->getActor())
- ->withPHIDs($add)
- ->execute();
- $objects = mpull($objects, null, 'getPHID');
- foreach ($add as $phid) {
- if (isset($objects[$phid])) {
- continue;
- }
-
- $errors[] = new PhabricatorApplicationTransactionValidationError(
- $type,
- pht('Invalid'),
- pht(
- 'Invitee "%s" identifies an object that does not exist or '.
- 'which you do not have permission to view.',
- $phid));
- }
- }
- break;
- case PhabricatorCalendarEventTransaction::TYPE_START_DATE:
- case PhabricatorCalendarEventTransaction::TYPE_END_DATE:
- case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE:
- foreach ($xactions as $xaction) {
- if ($xaction->getNewValue()->isValid()) {
- continue;
- }
-
- switch ($type) {
- case PhabricatorCalendarEventTransaction::TYPE_START_DATE:
- $message = pht('Start date is invalid.');
- break;
- case PhabricatorCalendarEventTransaction::TYPE_END_DATE:
- $message = pht('End date is invalid.');
- break;
- case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE:
- $message = pht('Repeat until date is invalid.');
- break;
- }
-
- $errors[] = new PhabricatorApplicationTransactionValidationError(
- $type,
- pht('Invalid'),
- $message,
- $xaction);
- }
- break;
-
- }
-
- return $errors;
- }
-
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
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
@@ -1,22 +1,7 @@
<?php
final class PhabricatorCalendarEventTransaction
- extends PhabricatorApplicationTransaction {
-
- const TYPE_NAME = 'calendar.name';
- const TYPE_START_DATE = 'calendar.startdate';
- const TYPE_END_DATE = 'calendar.enddate';
- const TYPE_DESCRIPTION = 'calendar.description';
- const TYPE_CANCEL = 'calendar.cancel';
- const TYPE_ALL_DAY = 'calendar.allday';
- const TYPE_ICON = 'calendar.icon';
- const TYPE_INVITE = 'calendar.invite';
- const TYPE_ACCEPT = 'calendar.accept';
- const TYPE_DECLINE = 'calendar.decline';
-
- const TYPE_RECURRING = 'calendar.recurring';
- const TYPE_FREQUENCY = 'calendar.frequency';
- const TYPE_RECURRENCE_END_DATE = 'calendar.recurrenceenddate';
+ extends PhabricatorModularTransaction {
const MAILTAG_RESCHEDULE = 'calendar-reschedule';
const MAILTAG_CONTENT = 'calendar-content';
@@ -34,580 +19,25 @@
return new PhabricatorCalendarEventTransactionComment();
}
- public function getRequiredHandlePHIDs() {
- $phids = parent::getRequiredHandlePHIDs();
-
- switch ($this->getTransactionType()) {
- case self::TYPE_NAME:
- case self::TYPE_START_DATE:
- case self::TYPE_END_DATE:
- case self::TYPE_DESCRIPTION:
- case self::TYPE_CANCEL:
- case self::TYPE_ALL_DAY:
- case self::TYPE_RECURRING:
- case self::TYPE_FREQUENCY:
- case self::TYPE_RECURRENCE_END_DATE:
- $phids[] = $this->getObjectPHID();
- break;
- case self::TYPE_INVITE:
- $new = $this->getNewValue();
- foreach ($new as $phid => $status) {
- $phids[] = $phid;
- }
- break;
- }
-
- return $phids;
- }
-
- public function shouldHide() {
- $old = $this->getOldValue();
- switch ($this->getTransactionType()) {
- case self::TYPE_START_DATE:
- case self::TYPE_END_DATE:
- case self::TYPE_DESCRIPTION:
- case self::TYPE_CANCEL:
- case self::TYPE_ALL_DAY:
- case self::TYPE_INVITE:
- case self::TYPE_RECURRING:
- case self::TYPE_FREQUENCY:
- case self::TYPE_RECURRENCE_END_DATE:
- return ($old === null);
- }
- return parent::shouldHide();
- }
-
- public function getIcon() {
- switch ($this->getTransactionType()) {
- case self::TYPE_ICON:
- return $this->getNewValue();
- case self::TYPE_NAME:
- case self::TYPE_START_DATE:
- case self::TYPE_END_DATE:
- case self::TYPE_DESCRIPTION:
- case self::TYPE_ALL_DAY:
- case self::TYPE_CANCEL:
- case self::TYPE_RECURRING:
- case self::TYPE_FREQUENCY:
- case self::TYPE_RECURRENCE_END_DATE:
- return 'fa-pencil';
- break;
- case self::TYPE_INVITE:
- return 'fa-user-plus';
- break;
- }
- return parent::getIcon();
- }
-
- public function getTitle() {
- $author_phid = $this->getAuthorPHID();
- $object_phid = $this->getObjectPHID();
-
- $old = $this->getOldValue();
- $new = $this->getNewValue();
-
- $type = $this->getTransactionType();
- switch ($type) {
- case self::TYPE_NAME:
- if ($old === null) {
- return pht(
- '%s created this event.',
- $this->renderHandleLink($author_phid));
- } else {
- return pht(
- '%s changed the name of this event from %s to %s.',
- $this->renderHandleLink($author_phid),
- $old,
- $new);
- }
- case self::TYPE_START_DATE:
- if ($old) {
- return pht(
- '%s edited the start date of this event.',
- $this->renderHandleLink($author_phid));
- }
- break;
- case self::TYPE_END_DATE:
- if ($old) {
- return pht(
- '%s edited the end date of this event.',
- $this->renderHandleLink($author_phid));
- }
- break;
- case self::TYPE_DESCRIPTION:
- return pht(
- "%s updated the event's description.",
- $this->renderHandleLink($author_phid));
- case self::TYPE_ALL_DAY:
- if ($new) {
- return pht(
- '%s made this an all day event.',
- $this->renderHandleLink($author_phid));
- } else {
- return pht(
- '%s converted this from an all day event.',
- $this->renderHandleLink($author_phid));
- }
- case self::TYPE_ICON:
- $set = new PhabricatorCalendarIconSet();
- return pht(
- '%s set this event\'s icon to %s.',
- $this->renderHandleLink($author_phid),
- $set->getIconLabel($new));
- break;
- case self::TYPE_CANCEL:
- if ($new) {
- return pht(
- '%s cancelled this event.',
- $this->renderHandleLink($author_phid));
- } else {
- return pht(
- '%s reinstated this event.',
- $this->renderHandleLink($author_phid));
- }
- case self::TYPE_ACCEPT:
- return pht(
- '%s is attending this event.',
- $this->renderHandleLink($author_phid));
- case self::TYPE_DECLINE:
- return pht(
- '%s declined this event.',
- $this->renderHandleLink($author_phid));
- case self::TYPE_INVITE:
- $text = null;
-
- list($old, $new) = $this->getSimpleInvites($old, $new);
-
- if (count($old) === 1
- && count($new) === 1
- && isset($old[$author_phid])) {
- // user joined/declined/accepted event themself
- $old_status = $old[$author_phid];
- $new_status = $new[$author_phid];
-
- if ($old_status !== $new_status) {
- switch ($new_status) {
- case PhabricatorCalendarEventInvitee::STATUS_INVITED:
- $text = pht(
- '%s has joined this event.',
- $this->renderHandleLink($author_phid));
- break;
- case PhabricatorCalendarEventInvitee::STATUS_ATTENDING:
- $text = pht(
- '%s is attending this event.',
- $this->renderHandleLink($author_phid));
- break;
- case PhabricatorCalendarEventInvitee::STATUS_DECLINED:
- case PhabricatorCalendarEventInvitee::STATUS_UNINVITED:
- $text = pht(
- '%s has declined this event.',
- $this->renderHandleLink($author_phid));
- break;
- default:
- $text = pht(
- '%s has changed their status for this event.',
- $this->renderHandleLink($author_phid));
- break;
- }
- }
- } else {
- // user changed status for many users
- $self_joined = null;
- $self_declined = null;
- $added = array();
- $uninvited = array();
-
- foreach ($new as $phid => $status) {
- if ($status == PhabricatorCalendarEventInvitee::STATUS_INVITED
- || $status == PhabricatorCalendarEventInvitee::STATUS_ATTENDING) {
- // added users
- $added[] = $phid;
- } else if (
- $status == PhabricatorCalendarEventInvitee::STATUS_DECLINED
- || $status == PhabricatorCalendarEventInvitee::STATUS_UNINVITED) {
- $uninvited[] = $phid;
- }
- }
-
- $count_added = count($added);
- $count_uninvited = count($uninvited);
- $added_text = null;
- $uninvited_text = null;
-
- if ($count_added > 0 && $count_uninvited == 0) {
- $added_text = $this->renderHandleList($added);
- $text = pht('%s invited %s.',
- $this->renderHandleLink($author_phid),
- $added_text);
- } else if ($count_added > 0 && $count_uninvited > 0) {
- $added_text = $this->renderHandleList($added);
- $uninvited_text = $this->renderHandleList($uninvited);
- $text = pht('%s invited %s and uninvited %s.',
- $this->renderHandleLink($author_phid),
- $added_text,
- $uninvited_text);
- } else if ($count_added == 0 && $count_uninvited > 0) {
- $uninvited_text = $this->renderHandleList($uninvited);
- $text = pht('%s uninvited %s.',
- $this->renderHandleLink($author_phid),
- $uninvited_text);
- } else {
- $text = pht('%s updated the invitee list.',
- $this->renderHandleLink($author_phid));
- }
- }
- return $text;
- case self::TYPE_RECURRING:
- $text = pht('%s made this event recurring.',
- $this->renderHandleLink($author_phid));
- return $text;
- case self::TYPE_FREQUENCY:
- $rule = $new;
- if (is_array($rule)) {
- $rule = idx($rule, 'rule');
- }
-
- $text = '';
- switch ($rule) {
- case PhabricatorCalendarEvent::FREQUENCY_DAILY:
- $text = pht('%s set this event to repeat daily.',
- $this->renderHandleLink($author_phid));
- break;
- case PhabricatorCalendarEvent::FREQUENCY_WEEKLY:
- $text = pht('%s set this event to repeat weekly.',
- $this->renderHandleLink($author_phid));
- break;
- case PhabricatorCalendarEvent::FREQUENCY_MONTHLY:
- $text = pht('%s set this event to repeat monthly.',
- $this->renderHandleLink($author_phid));
- break;
- case PhabricatorCalendarEvent::FREQUENCY_YEARLY:
- $text = pht('%s set this event to repeat yearly.',
- $this->renderHandleLink($author_phid));
- break;
- }
- return $text;
- case self::TYPE_RECURRENCE_END_DATE:
- $text = pht('%s has changed the recurrence end date of this event.',
- $this->renderHandleLink($author_phid));
- return $text;
- }
- return parent::getTitle();
- }
-
- public function getTitleForFeed() {
- $author_phid = $this->getAuthorPHID();
- $object_phid = $this->getObjectPHID();
-
- $old = $this->getOldValue();
- $new = $this->getNewValue();
-
- $viewer = $this->getViewer();
-
- $type = $this->getTransactionType();
- switch ($type) {
- case self::TYPE_NAME:
- if ($old === null) {
- return pht(
- '%s created %s.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid));
- } else {
- return pht(
- '%s changed the name of %s from %s to %s.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid),
- $old,
- $new);
- }
- case self::TYPE_START_DATE:
- if ($old) {
- $old = phabricator_datetime($old, $viewer);
- $new = phabricator_datetime($new, $viewer);
- return pht(
- '%s changed the start date of %s from %s to %s.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid),
- $old,
- $new);
- }
- break;
- case self::TYPE_END_DATE:
- if ($old) {
- $old = phabricator_datetime($old, $viewer);
- $new = phabricator_datetime($new, $viewer);
- return pht(
- '%s edited the end date of %s from %s to %s.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid),
- $old,
- $new);
- }
- break;
- case self::TYPE_DESCRIPTION:
- return pht(
- '%s updated the description of %s.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid));
- case self::TYPE_ALL_DAY:
- if ($new) {
- return pht(
- '%s made %s an all day event.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid));
- } else {
- return pht(
- '%s converted %s from an all day event.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid));
- }
- case self::TYPE_ICON:
- $set = new PhabricatorCalendarIconSet();
- return pht(
- '%s set the icon for %s to %s.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid),
- $set->getIconLabel($new));
- case self::TYPE_CANCEL:
- if ($new) {
- return pht(
- '%s cancelled %s.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid));
- } else {
- return pht(
- '%s reinstated %s.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid));
- }
- case self::TYPE_ACCEPT:
- return pht(
- '%s is attending %s.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid));
- case self::TYPE_DECLINE:
- return pht(
- '%s declined %s.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid));
- case self::TYPE_INVITE:
- $text = null;
-
- list($old, $new) = $this->getSimpleInvites($old, $new);
-
- if (count($old) === 1
- && count($new) === 1
- && isset($old[$author_phid])) {
- // user joined/declined/accepted event themself
- $old_status = $old[$author_phid];
- $new_status = $new[$author_phid];
-
- if ($old_status !== $new_status) {
- switch ($new_status) {
- case PhabricatorCalendarEventInvitee::STATUS_INVITED:
- $text = pht(
- '%s has joined %s.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid));
- break;
- case PhabricatorCalendarEventInvitee::STATUS_ATTENDING:
- $text = pht(
- '%s is attending %s.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid));
- break;
- case PhabricatorCalendarEventInvitee::STATUS_DECLINED:
- case PhabricatorCalendarEventInvitee::STATUS_UNINVITED:
- $text = pht(
- '%s has declined %s.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid));
- break;
- default:
- $text = pht(
- '%s has changed their status of %s.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid));
- break;
- }
- }
- } else {
- // user changed status for many users
- $self_joined = null;
- $self_declined = null;
- $added = array();
- $uninvited = array();
-
- foreach ($new as $phid => $status) {
- if ($status == PhabricatorCalendarEventInvitee::STATUS_INVITED
- || $status == PhabricatorCalendarEventInvitee::STATUS_ATTENDING) {
- // added users
- $added[] = $phid;
- } else if (
- $status == PhabricatorCalendarEventInvitee::STATUS_DECLINED
- || $status == PhabricatorCalendarEventInvitee::STATUS_UNINVITED) {
- $uninvited[] = $phid;
- }
- }
-
- $count_added = count($added);
- $count_uninvited = count($uninvited);
- $added_text = null;
- $uninvited_text = null;
-
- if ($count_added > 0 && $count_uninvited == 0) {
- $added_text = $this->renderHandleList($added);
- $text = pht('%s invited %s to %s.',
- $this->renderHandleLink($author_phid),
- $added_text,
- $this->renderHandleLink($object_phid));
- } else if ($count_added > 0 && $count_uninvited > 0) {
- $added_text = $this->renderHandleList($added);
- $uninvited_text = $this->renderHandleList($uninvited);
- $text = pht('%s invited %s and uninvited %s to %s.',
- $this->renderHandleLink($author_phid),
- $added_text,
- $uninvited_text,
- $this->renderHandleLink($object_phid));
- } else if ($count_added == 0 && $count_uninvited > 0) {
- $uninvited_text = $this->renderHandleList($uninvited);
- $text = pht('%s uninvited %s to %s.',
- $this->renderHandleLink($author_phid),
- $uninvited_text,
- $this->renderHandleLink($object_phid));
- } else {
- $text = pht('%s updated the invitee list of %s.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid));
- }
- }
- return $text;
- case self::TYPE_RECURRING:
- $text = pht('%s made %s a recurring event.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid));
- return $text;
- case self::TYPE_FREQUENCY:
- $rule = $new;
- if (is_array($rule)) {
- $rule = idx($rule, 'rule');
- }
-
- $text = '';
- switch ($rule) {
- case PhabricatorCalendarEvent::FREQUENCY_DAILY:
- $text = pht('%s set %s to repeat daily.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid));
- break;
- case PhabricatorCalendarEvent::FREQUENCY_WEEKLY:
- $text = pht('%s set %s to repeat weekly.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid));
- break;
- case PhabricatorCalendarEvent::FREQUENCY_MONTHLY:
- $text = pht('%s set %s to repeat monthly.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid));
- break;
- case PhabricatorCalendarEvent::FREQUENCY_YEARLY:
- $text = pht('%s set %s to repeat yearly.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid));
- break;
- }
- return $text;
- case self::TYPE_RECURRENCE_END_DATE:
- $text = pht('%s set the recurrence end date of %s to %s.',
- $this->renderHandleLink($author_phid),
- $this->renderHandleLink($object_phid),
- $new);
- return $text;
- }
-
- return parent::getTitleForFeed();
- }
-
- public function getColor() {
- $old = $this->getOldValue();
- $new = $this->getNewValue();
-
- switch ($this->getTransactionType()) {
- case self::TYPE_NAME:
- case self::TYPE_START_DATE:
- case self::TYPE_END_DATE:
- case self::TYPE_DESCRIPTION:
- case self::TYPE_CANCEL:
- case self::TYPE_INVITE:
- return PhabricatorTransactions::COLOR_GREEN;
- }
-
- return parent::getColor();
- }
-
-
- public function hasChangeDetails() {
- switch ($this->getTransactionType()) {
- case self::TYPE_DESCRIPTION:
- return ($this->getOldValue() !== null);
- }
-
- return parent::hasChangeDetails();
- }
-
- public function renderChangeDetails(PhabricatorUser $viewer) {
- switch ($this->getTransactionType()) {
- case self::TYPE_DESCRIPTION:
- $old = $this->getOldValue();
- $new = $this->getNewValue();
-
- return $this->renderTextCorpusChangeDetails(
- $viewer,
- $old,
- $new);
- }
-
- return parent::renderChangeDetails($viewer);
+ public function getBaseTransactionClass() {
+ return 'PhabricatorCalendarEventTransactionType';
}
public function getMailTags() {
$tags = array();
switch ($this->getTransactionType()) {
- case self::TYPE_NAME:
- case self::TYPE_DESCRIPTION:
- case self::TYPE_INVITE:
- case self::TYPE_ICON:
+ case PhabricatorCalendarEventNameTransaction::TRANSACTIONTYPE:
+ case PhabricatorCalendarEventDescriptionTransaction::TRANSACTIONTYPE:
+ case PhabricatorCalendarEventInviteTransaction::TRANSACTIONTYPE:
$tags[] = self::MAILTAG_CONTENT;
break;
- case self::TYPE_START_DATE:
- case self::TYPE_END_DATE:
- case self::TYPE_CANCEL:
+ case PhabricatorCalendarEventStartDateTransaction::TRANSACTIONTYPE:
+ case PhabricatorCalendarEventEndDateTransaction::TRANSACTIONTYPE:
+ case PhabricatorCalendarEventCancelTransaction::TRANSACTIONTYPE:
$tags[] = self::MAILTAG_RESCHEDULE;
break;
}
return $tags;
}
- private function getSimpleInvites(array $old, array $new) {
- // Fill in any new invitees as "uninvited" in the old data, to make
- // some of the rendering logic a little easier.
- $status_uninvited = PhabricatorCalendarEventInvitee::STATUS_UNINVITED;
- $old = $old + array_fill_keys(array_keys($new), $status_uninvited);
-
- $all = $old + $new;
- foreach (array_keys($all) as $key) {
- // If the invitee exists in both the old and new lists with the same
- // value, remove it from both.
- if (isset($old[$key]) && isset($new[$key])) {
- if ($old[$key] == $new[$key]) {
- unset($old[$key]);
- unset($new[$key]);
- }
- }
- }
-
- return array($old, $new);
- }
-
-
}
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarEventAcceptTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarEventAcceptTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/xaction/PhabricatorCalendarEventAcceptTransaction.php
@@ -0,0 +1,25 @@
+<?php
+
+final class PhabricatorCalendarEventAcceptTransaction
+ extends PhabricatorCalendarEventReplyTransaction {
+
+ const TRANSACTIONTYPE = 'calendar.accept';
+
+ public function generateNewValue($object, $value) {
+ return PhabricatorCalendarEventInvitee::STATUS_ATTENDING;
+ }
+
+ public function getTitle() {
+ return pht(
+ '%s is attending this event.',
+ $this->renderAuthor());
+ }
+
+ public function getTitleForFeed() {
+ return pht(
+ '%s is attending %s.',
+ $this->renderAuthor(),
+ $this->renderObject());
+ }
+
+}
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarEventAllDayTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarEventAllDayTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/xaction/PhabricatorCalendarEventAllDayTransaction.php
@@ -0,0 +1,46 @@
+<?php
+
+final class PhabricatorCalendarEventAllDayTransaction
+ extends PhabricatorCalendarEventTransactionType {
+
+ const TRANSACTIONTYPE = 'calendar.allday';
+
+ public function generateOldValue($object) {
+ return (int)$object->getIsAllDay();
+ }
+
+ public function generateNewValue($object, $value) {
+ return (int)$value;
+ }
+
+ public function applyInternalEffects($object, $value) {
+ $object->setIsAllDay($value);
+ }
+
+ public function getTitle() {
+ if ($this->getNewValue()) {
+ return pht(
+ '%s changed this as an all day event.',
+ $this->renderAuthor());
+ } else {
+ return pht(
+ '%s conveted this from an all day event.',
+ $this->renderAuthor());
+ }
+ }
+
+ public function getTitleForFeed() {
+ if ($this->getNewValue()) {
+ return pht(
+ '%s changed %s to an all day event.',
+ $this->renderAuthor(),
+ $this->renderObject());
+ } else {
+ return pht(
+ '%s converted %s from an all day event.',
+ $this->renderAuthor(),
+ $this->renderObject());
+ }
+ }
+
+}
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarEventCancelTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarEventCancelTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/xaction/PhabricatorCalendarEventCancelTransaction.php
@@ -0,0 +1,46 @@
+<?php
+
+final class PhabricatorCalendarEventCancelTransaction
+ extends PhabricatorCalendarEventTransactionType {
+
+ const TRANSACTIONTYPE = 'calendar.cancel';
+
+ public function generateOldValue($object) {
+ return (int)$object->getIsCancelled();
+ }
+
+ public function generateNewValue($object, $value) {
+ return (int)$value;
+ }
+
+ public function applyInternalEffects($object, $value) {
+ $object->setIsCancelled($value);
+ }
+
+ public function getTitle() {
+ if ($this->getNewValue()) {
+ return pht(
+ '%s cancelled this event.',
+ $this->renderAuthor());
+ } else {
+ return pht(
+ '%s reinstated this event.',
+ $this->renderAuthor());
+ }
+ }
+
+ public function getTitleForFeed() {
+ if ($this->getNewValue()) {
+ return pht(
+ '%s cancelled %s.',
+ $this->renderAuthor(),
+ $this->renderObject());
+ } else {
+ return pht(
+ '%s reinstated %s.',
+ $this->renderAuthor(),
+ $this->renderObject());
+ }
+ }
+
+}
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarEventDateTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarEventDateTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/xaction/PhabricatorCalendarEventDateTransaction.php
@@ -0,0 +1,27 @@
+<?php
+
+abstract class PhabricatorCalendarEventDateTransaction
+ extends PhabricatorCalendarEventTransactionType {
+
+ abstract protected function getInvalidDateMessage();
+
+ public function generateNewValue($object, $value) {
+ return $value->getEpoch();
+ }
+
+ public function validateTransactions($object, array $xactions) {
+ $errors = array();
+
+ foreach ($xactions as $xaction) {
+ if ($xaction->getNewValue()->isValid()) {
+ continue;
+ }
+
+ $message = $this->getInvalidDateMessage();
+ $errors[] = $this->newInvalidError($message, $xaction);
+ }
+
+ return $errors;
+ }
+
+}
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarEventDeclineTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarEventDeclineTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/xaction/PhabricatorCalendarEventDeclineTransaction.php
@@ -0,0 +1,25 @@
+<?php
+
+final class PhabricatorCalendarEventDeclineTransaction
+ extends PhabricatorCalendarEventReplyTransaction {
+
+ const TRANSACTIONTYPE = 'calendar.decline';
+
+ public function generateNewValue($object, $value) {
+ return PhabricatorCalendarEventInvitee::STATUS_DECLINED;
+ }
+
+ public function getTitle() {
+ return pht(
+ '%s declined this event.',
+ $this->renderAuthor());
+ }
+
+ public function getTitleForFeed() {
+ return pht(
+ '%s declined %s.',
+ $this->renderAuthor(),
+ $this->renderObject());
+ }
+
+}
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarEventDescriptionTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarEventDescriptionTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/xaction/PhabricatorCalendarEventDescriptionTransaction.php
@@ -0,0 +1,42 @@
+<?php
+
+final class PhabricatorCalendarEventDescriptionTransaction
+ extends PhabricatorCalendarEventTransactionType {
+
+ const TRANSACTIONTYPE = 'calendar.description';
+
+ public function generateOldValue($object) {
+ return $object->getDescription();
+ }
+
+ public function applyInternalEffects($object, $value) {
+ $object->setDescription($value);
+ }
+
+ public function getTitle() {
+ return pht(
+ '%s updated the event description.',
+ $this->renderAuthor());
+ }
+
+ public function getTitleForFeed() {
+ return pht(
+ '%s updated the event description for %s.',
+ $this->renderAuthor(),
+ $this->renderObject());
+ }
+
+ public function hasChangeDetailView() {
+ return true;
+ }
+
+ public function newChangeDetailView() {
+ $viewer = $this->getViewer();
+
+ return id(new PhabricatorApplicationTransactionTextDiffDetailView())
+ ->setViewer($viewer)
+ ->setOldText($this->getOldValue())
+ ->setNewText($this->getNewValue());
+ }
+
+}
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarEventEndDateTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarEventEndDateTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/xaction/PhabricatorCalendarEventEndDateTransaction.php
@@ -0,0 +1,37 @@
+<?php
+
+final class PhabricatorCalendarEventEndDateTransaction
+ extends PhabricatorCalendarEventDateTransaction {
+
+ const TRANSACTIONTYPE = 'calendar.enddate';
+
+ public function generateOldValue($object) {
+ return $object->getDateTo();
+ }
+
+ public function applyInternalEffects($object, $value) {
+ $object->setDateTo($value);
+ }
+
+ public function getTitle() {
+ return pht(
+ '%s changed the end date for this event from %s to %s.',
+ $this->renderAuthor(),
+ $this->renderOldDate(),
+ $this->renderNewDate());
+ }
+
+ public function getTitleForFeed() {
+ return pht(
+ '%s changed the end date for %s from %s to %s.',
+ $this->renderAuthor(),
+ $this->renderObject(),
+ $this->renderOldDate(),
+ $this->renderNewDate());
+ }
+
+ protected function getInvalidDateMessage() {
+ return pht('End date is invalid.');
+ }
+
+}
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarEventFrequencyTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarEventFrequencyTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/xaction/PhabricatorCalendarEventFrequencyTransaction.php
@@ -0,0 +1,75 @@
+<?php
+
+final class PhabricatorCalendarEventFrequencyTransaction
+ extends PhabricatorCalendarEventTransactionType {
+
+ const TRANSACTIONTYPE = 'calendar.frequency';
+
+ public function generateOldValue($object) {
+ return $object->getFrequencyUnit();
+ }
+
+ public function applyInternalEffects($object, $value) {
+ $object->setRecurrenceFrequency(
+ array(
+ 'rule' => $value,
+ ));
+ }
+
+ public function getTitle() {
+ $frequency = $this->getFrequencyUnit($this->getNewValue());
+ switch ($frequency) {
+ case PhabricatorCalendarEvent::FREQUENCY_DAILY:
+ return pht(
+ '%s set this event to repeat daily.',
+ $this->renderAuthor());
+ case PhabricatorCalendarEvent::FREQUENCY_WEEKLY:
+ return pht(
+ '%s set this event to repeat weekly.',
+ $this->renderAuthor());
+ case PhabricatorCalendarEvent::FREQUENCY_MONTHLY:
+ return pht(
+ '%s set this event to repeat monthly.',
+ $this->renderAuthor());
+ case PhabricatorCalendarEvent::FREQUENCY_YEARLY:
+ return pht(
+ '%s set this event to repeat yearly.',
+ $this->renderAuthor());
+ }
+ }
+
+ public function getTitleForFeed() {
+ $frequency = $this->getFrequencyUnit($this->getNewValue());
+ switch ($frequency) {
+ case PhabricatorCalendarEvent::FREQUENCY_DAILY:
+ return pht(
+ '%s set %s to repeat daily.',
+ $this->renderAuthor(),
+ $this->renderObject());
+ case PhabricatorCalendarEvent::FREQUENCY_WEEKLY:
+ return pht(
+ '%s set %s to repeat weekly.',
+ $this->renderAuthor(),
+ $this->renderObject());
+ case PhabricatorCalendarEvent::FREQUENCY_MONTHLY:
+ return pht(
+ '%s set %s to repeat monthly.',
+ $this->renderAuthor(),
+ $this->renderObject());
+ case PhabricatorCalendarEvent::FREQUENCY_YEARLY:
+ return pht(
+ '%s set %s to repeat yearly.',
+ $this->renderAuthor(),
+ $this->renderObject());
+ }
+ }
+
+ private function getFrequencyUnit($value) {
+ if (is_array($value)) {
+ $value = idx($value, 'rule');
+ } else {
+ return $value;
+ }
+ }
+
+}
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarEventIconTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarEventIconTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/xaction/PhabricatorCalendarEventIconTransaction.php
@@ -0,0 +1,44 @@
+<?php
+
+final class PhabricatorCalendarEventIconTransaction
+ extends PhabricatorCalendarEventTransactionType {
+
+ const TRANSACTIONTYPE = 'calendar.icon';
+
+ public function generateOldValue($object) {
+ return $object->getIcon();
+ }
+
+ public function applyInternalEffects($object, $value) {
+ $object->setIcon($value);
+ }
+
+ public function getTitle() {
+ $old = $this->getIconLabel($this->getOldValue());
+ $new = $this->getIconLabel($this->getNewValue());
+
+ return pht(
+ '%s changed the event icon from %s to %s.',
+ $this->renderAuthor(),
+ $this->renderValue($old),
+ $this->renderValue($new));
+ }
+
+ public function getTitleForFeed() {
+ $old = $this->getIconLabel($this->getOldValue());
+ $new = $this->getIconLabel($this->getNewValue());
+
+ return pht(
+ '%s changed the icon for %s from %s to %s.',
+ $this->renderAuthor(),
+ $this->renderObject(),
+ $this->renderValue($old),
+ $this->renderValue($new));
+ }
+
+ private function getIconLabel($icon) {
+ $set = new PhabricatorCalendarIconSet();
+ return $set->getIconLabel($icon);
+ }
+
+}
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarEventInviteTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarEventInviteTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/xaction/PhabricatorCalendarEventInviteTransaction.php
@@ -0,0 +1,191 @@
+<?php
+
+final class PhabricatorCalendarEventInviteTransaction
+ extends PhabricatorCalendarEventTransactionType {
+
+ const TRANSACTIONTYPE = 'calendar.invite';
+
+ public function generateOldValue($object) {
+ $status_uninvited = PhabricatorCalendarEventInvitee::STATUS_UNINVITED;
+
+ $invitees = $object->getInvitees();
+ foreach ($invitees as $key => $invitee) {
+ if ($invitee->getStatus() == $status_uninvited) {
+ unset($invitees[$key]);
+ }
+ }
+
+ return mpull($invitees, 'getStatus', 'getInviteePHID');
+ }
+
+ public function generateNewValue($object, $value) {
+ $status_invited = PhabricatorCalendarEventInvitee::STATUS_INVITED;
+ $status_uninvited = PhabricatorCalendarEventInvitee::STATUS_UNINVITED;
+ $status_attending = PhabricatorCalendarEventInvitee::STATUS_ATTENDING;
+
+ $invitees = $this->generateOldValue($object);
+
+ $new = array_fuse($value);
+
+ $all = array_keys($invitees + $new);
+ $map = array();
+ foreach ($all as $phid) {
+ $is_old = isset($invitees[$phid]);
+ $is_new = isset($new[$phid]);
+
+ if ($is_old && !$is_new) {
+ $map[$phid] = $status_uninvited;
+ } else if (!$is_old && $is_new) {
+ $map[$phid] = $status_invited;
+ } else {
+ $map[$phid] = $invitees[$phid];
+ }
+ }
+
+ // If we're creating this event and the actor is inviting themselves,
+ // mark them as attending.
+ if ($this->isNewObject()) {
+ $acting_phid = $this->getActingAsPHID();
+ if (isset($map[$acting_phid])) {
+ $map[$acting_phid] = $status_attending;
+ }
+ }
+
+ return $map;
+ }
+
+ public function applyExternalEffects($object, $value) {
+ $phids = array_keys($value);
+ $invitees = $object->getInvitees();
+ $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());
+ $invitees[] = $invitee;
+ }
+ $invitee->setStatus($value[$phid])
+ ->save();
+ }
+
+ $object->attachInvitees($invitees);
+ }
+
+ public function validateTransactions($object, array $xactions) {
+ $actor = $this->getActor();
+
+ $errors = array();
+
+ $old = $object->getInvitees();
+ $old = mpull($old, null, 'getInviteePHID');
+ foreach ($xactions as $xaction) {
+ $new = $xaction->getNewValue();
+ $new = array_fuse($new);
+ $add = array_diff_key($new, $old);
+ if (!$add) {
+ continue;
+ }
+
+ // In the UI, we only allow you to invite mailable objects, but there
+ // is no definitive marker for "invitable object" today. Just allow
+ // any valid object to be invited.
+ $objects = id(new PhabricatorObjectQuery())
+ ->setViewer($actor)
+ ->withPHIDs($add)
+ ->execute();
+ $objects = mpull($objects, null, 'getPHID');
+ foreach ($add as $phid) {
+ if (isset($objects[$phid])) {
+ continue;
+ }
+
+ $errors[] = $this->newInvalidError(
+ pht(
+ 'Invitee "%s" identifies an object that does not exist or '.
+ 'which you do not have permission to view.',
+ $phid),
+ $xaction);
+ }
+ }
+
+ return $errors;
+ }
+
+ public function getIcon() {
+ return 'fa-user-plus';
+ }
+
+ public function getTitle() {
+ list($add, $rem) = $this->getChanges();
+
+ if ($add && !$rem) {
+ return pht(
+ '%s invited %s attendee(s): %s.',
+ $this->renderAuthor(),
+ phutil_count($add),
+ $this->renderHandleList($add));
+ } else if (!$add && $rem) {
+ return pht(
+ '%s uninvited %s attendee(s): %s.',
+ $this->renderAuthor(),
+ phutil_count($rem),
+ $this->renderHandleList($rem));
+ } else {
+ return pht(
+ '%s invited %s attendee(s): %s; uninvinted %s attendee(s): %s.',
+ $this->renderAuthor(),
+ phutil_count($add),
+ $this->renderHandleList($add),
+ phutil_count($rem),
+ $this->renderHandleList($rem));
+ }
+ }
+
+ public function getTitleForFeed() {
+ list($add, $rem) = $this->getChanges();
+
+ if ($add && !$rem) {
+ return pht(
+ '%s invited %s attendee(s) to %s: %s.',
+ $this->renderAuthor(),
+ phutil_count($add),
+ $this->renderObject(),
+ $this->renderHandleList($add));
+ } else if (!$add && $rem) {
+ return pht(
+ '%s uninvited %s attendee(s) to %s: %s.',
+ $this->renderAuthor(),
+ phutil_count($rem),
+ $this->renderObject(),
+ $this->renderHandleList($rem));
+ } else {
+ return pht(
+ '%s updated the invite list for %s, invited %s: %s; '.
+ 'uninvinted %s: %s.',
+ $this->renderAuthor(),
+ $this->renderObject(),
+ phutil_count($add),
+ $this->renderHandleList($add),
+ phutil_count($rem),
+ $this->renderHandleList($rem));
+ }
+ }
+
+ private function getChanges() {
+ $old = $this->getOldValue();
+ $new = $this->getNewValue();
+
+ $add = array_diff_key($new, $old);
+ $rem = array_diff_key($old, $new);
+
+ $add = array_keys($add);
+ $rem = array_keys($rem);
+
+ return array(array_fuse($add), array_fuse($rem));
+ }
+
+}
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarEventNameTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarEventNameTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/xaction/PhabricatorCalendarEventNameTransaction.php
@@ -0,0 +1,44 @@
+<?php
+
+final class PhabricatorCalendarEventNameTransaction
+ extends PhabricatorCalendarEventTransactionType {
+
+ const TRANSACTIONTYPE = 'calendar.name';
+
+ public function generateOldValue($object) {
+ return $object->getName();
+ }
+
+ public function applyInternalEffects($object, $value) {
+ $object->setName($value);
+ }
+
+ public function getTitle() {
+ return pht(
+ '%s renamed this event from %s to %s.',
+ $this->renderAuthor(),
+ $this->renderOldValue(),
+ $this->renderNewValue());
+ }
+
+ public function getTitleForFeed() {
+ return pht(
+ '%s renamed %s from %s to %s.',
+ $this->renderAuthor(),
+ $this->renderObject(),
+ $this->renderOldValue(),
+ $this->renderNewValue());
+ }
+
+ public function validateTransactions($object, array $xactions) {
+ $errors = array();
+
+ if ($this->isEmptyTextTransaction($object->getName(), $xactions)) {
+ $errors[] = $this->newRequiredError(
+ pht('Events must have a name.'));
+ }
+
+ return $errors;
+ }
+
+}
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarEventRecurringTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarEventRecurringTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/xaction/PhabricatorCalendarEventRecurringTransaction.php
@@ -0,0 +1,44 @@
+<?php
+
+final class PhabricatorCalendarEventRecurringTransaction
+ extends PhabricatorCalendarEventTransactionType {
+
+ const TRANSACTIONTYPE = 'calendar.recurring';
+
+ public function generateOldValue($object) {
+ return (int)$object->getIsRecurring();
+ }
+
+ public function generateNewValue($object, $value) {
+ return (int)$value;
+ }
+
+ public function applyInternalEffects($object, $value) {
+ $object->setIsRecurring($value);
+ }
+
+ public function validateTransactions($object, array $xactions) {
+ $errors = array();
+
+ $old = $object->getIsRecurring();
+ foreach ($xactions as $xaction) {
+ if ($this->getIsNewObject()) {
+ continue;
+ }
+
+ if ($xaction->getNewValue() == $old) {
+ continue;
+ }
+
+ $errors[] = $this->newInvalidError(
+ pht(
+ 'An event can only be made recurring when it is created. '.
+ 'You can not convert an existing event into a recurring '.
+ 'event or vice versa.'),
+ $xaction);
+ }
+
+ return $errors;
+ }
+
+}
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarEventReplyTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarEventReplyTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/xaction/PhabricatorCalendarEventReplyTransaction.php
@@ -0,0 +1,33 @@
+<?php
+
+abstract class PhabricatorCalendarEventReplyTransaction
+ extends PhabricatorCalendarEventTransactionType {
+
+ public function generateOldValue($object) {
+ $actor_phid = $this->getActingAsPHID();
+ return $object->getUserInviteStatus($actor_phid);
+ }
+
+ public function applyExternalEffects($object, $value) {
+ $acting_phid = $this->getActingAsPHID();
+
+ $invitees = $object->getInvitees();
+ $invitees = mpull($invitees, null, 'getInviteePHID');
+
+ $invitee = idx($invitees, $acting_phid);
+ if (!$invitee) {
+ $invitee = id(new PhabricatorCalendarEventInvitee())
+ ->setEventPHID($object->getPHID())
+ ->setInviteePHID($acting_phid)
+ ->setInviterPHID($acting_phid);
+ $invitees[$acting_phid] = $invitee;
+ }
+
+ $invitee
+ ->setStatus($value)
+ ->save();
+
+ $object->attachInvitees($invitees);
+ }
+
+}
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarEventStartDateTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarEventStartDateTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/xaction/PhabricatorCalendarEventStartDateTransaction.php
@@ -0,0 +1,37 @@
+<?php
+
+final class PhabricatorCalendarEventStartDateTransaction
+ extends PhabricatorCalendarEventDateTransaction {
+
+ const TRANSACTIONTYPE = 'calendar.startdate';
+
+ public function generateOldValue($object) {
+ return $object->getDateFrom();
+ }
+
+ public function applyInternalEffects($object, $value) {
+ $object->setDateFrom($value);
+ }
+
+ public function getTitle() {
+ return pht(
+ '%s changed the start date for this event from %s to %s.',
+ $this->renderAuthor(),
+ $this->renderOldDate(),
+ $this->renderNewDate());
+ }
+
+ public function getTitleForFeed() {
+ return pht(
+ '%s changed the start date for %s from %s to %s.',
+ $this->renderAuthor(),
+ $this->renderObject(),
+ $this->renderOldDate(),
+ $this->renderNewDate());
+ }
+
+ protected function getInvalidDateMessage() {
+ return pht('Start date is invalid.');
+ }
+
+}
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarEventTransactionType.php b/src/applications/calendar/xaction/PhabricatorCalendarEventTransactionType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/xaction/PhabricatorCalendarEventTransactionType.php
@@ -0,0 +1,4 @@
+<?php
+
+abstract class PhabricatorCalendarEventTransactionType
+ extends PhabricatorModularTransactionType {}
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarEventUntilDateTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarEventUntilDateTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/xaction/PhabricatorCalendarEventUntilDateTransaction.php
@@ -0,0 +1,35 @@
+<?php
+
+final class PhabricatorCalendarEventUntilDateTransaction
+ extends PhabricatorCalendarEventDateTransaction {
+
+ const TRANSACTIONTYPE = 'calendar.recurrenceenddate';
+
+ public function generateOldValue($object) {
+ return $object->getRecurrenceEndDate();
+ }
+
+ public function applyInternalEffects($object, $value) {
+ $object->setRecurrenceEndDate($value);
+ }
+
+ public function getTitle() {
+ return pht(
+ '%s changed this event to repeat until %s.',
+ $this->renderAuthor(),
+ $this->renderNewDate());
+ }
+
+ public function getTitleForFeed() {
+ return pht(
+ '%s changed %s to repeat until %s.',
+ $this->renderAuthor(),
+ $this->renderObject(),
+ $this->renderNewDate());
+ }
+
+ protected function getInvalidDateMessage() {
+ return pht('Repeat until date is invalid.');
+ }
+
+}
diff --git a/src/applications/phid/view/PHUIHandleListView.php b/src/applications/phid/view/PHUIHandleListView.php
--- a/src/applications/phid/view/PHUIHandleListView.php
+++ b/src/applications/phid/view/PHUIHandleListView.php
@@ -12,6 +12,7 @@
private $handleList;
private $asInline;
+ private $asText;
public function setHandleList(PhabricatorHandleList $list) {
$this->handleList = $list;
@@ -27,6 +28,15 @@
return $this->asInline;
}
+ public function setAsText($as_text) {
+ $this->asText = $as_text;
+ return $this;
+ }
+
+ public function getAsText() {
+ return $this->asText;
+ }
+
protected function getTagName() {
// TODO: It would be nice to render this with a proper <ul />, at least in
// block mode, but don't stir the waters up too much for now.
@@ -37,9 +47,9 @@
$list = $this->handleList;
$items = array();
foreach ($list as $handle) {
- $view = $list->renderHandle($handle->getPHID());
-
- $view->setShowHovercard(true);
+ $view = $list->renderHandle($handle->getPHID())
+ ->setShowHovercard(true)
+ ->setAsText($this->getAsText());
$items[] = $view;
}
diff --git a/src/applications/transactions/storage/PhabricatorModularTransactionType.php b/src/applications/transactions/storage/PhabricatorModularTransactionType.php
--- a/src/applications/transactions/storage/PhabricatorModularTransactionType.php
+++ b/src/applications/transactions/storage/PhabricatorModularTransactionType.php
@@ -86,6 +86,14 @@
return $this->viewer;
}
+ final public function getActor() {
+ return $this->getEditor()->getActor();
+ }
+
+ final public function getActingAsPHID() {
+ return $this->getEditor()->getActingAsPHID();
+ }
+
final public function setEditor(
PhabricatorApplicationTransactionEditor $editor) {
$this->editor = $editor;
@@ -141,6 +149,19 @@
return $display;
}
+ final protected function renderHandleList(array $phids) {
+ $viewer = $this->getViewer();
+ $display = $viewer->renderHandleList($phids)
+ ->setAsInline(true);
+
+ $rendering_target = $this->getStorage()->getRenderingTarget();
+ if ($rendering_target == PhabricatorApplicationTransaction::TARGET_TEXT) {
+ $display->setAsText(true);
+ }
+
+ return $display;
+ }
+
final protected function renderValue($value) {
$rendering_target = $this->getStorage()->getRenderingTarget();
if ($rendering_target == PhabricatorApplicationTransaction::TARGET_TEXT) {
@@ -155,6 +176,32 @@
$value);
}
+ final protected function renderOldValue() {
+ return $this->renderValue($this->getOldValue());
+ }
+
+ final protected function renderNewValue() {
+ return $this->renderValue($this->getNewValue());
+ }
+
+ final protected function renderDate($epoch) {
+ $viewer = $this->getViewer();
+
+ $display = phabricator_datetime($epoch, $viewer);
+
+ // TODO: When rendering for email, include the UTC offset. See T10633.
+
+ return $this->renderValue($display);
+ }
+
+ final protected function renderOldDate() {
+ return $this->renderDate($this->getOldValue());
+ }
+
+ final protected function renderNewDate() {
+ return $this->renderDate($this->getNewValue());
+ }
+
final protected function newError($title, $message, $xaction = null) {
return new PhabricatorApplicationTransactionValidationError(
$this->getTransactionTypeConstant(),
@@ -163,4 +210,26 @@
$xaction);
}
+ final protected function newRequiredError($message, $xaction = null) {
+ return $this->newError(pht('Required'), $message, $xaction)
+ ->setIsMissingFieldError(true);
+ }
+
+ final protected function newInvalidError($message, $xaction = null) {
+ return $this->newError(pht('Invalid'), $message, $xaction);
+ }
+
+ final protected function isNewObject() {
+ return $this->getEditor()->getIsNewObject();
+ }
+
+ final protected function isEmptyTextTransaction($value, array $xactions) {
+ foreach ($xactions as $xaction) {
+ $value = $xaction->getNewValue();
+ }
+
+ return !strlen($value);
+ }
+
+
}
diff --git a/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php b/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php
--- a/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php
+++ b/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php
@@ -1560,6 +1560,24 @@
),
),
),
+
+ '%s invited %s attendee(s): %s.' =>
+ '%s invited: %3$s.',
+
+ '%s uninvited %s attendee(s): %s.' =>
+ '%s uninvited: %3$s.',
+
+ '%s invited %s attendee(s): %s; uninvinted %s attendee(s): %s.' =>
+ '%s invited: %3$s; uninvited: %5$s.',
+
+ '%s invited %s attendee(s) to %s: %s.' =>
+ '%s added invites for %3$s: %4$s.',
+
+ '%s uninvited %s attendee(s) to %s: %s.' =>
+ '%s removed invites for %3$s: %4$s.',
+
+ '%s updated the invite list for %s, invited %s: %s; uninvinted %s: %s.' =>
+ '%s updated the invite list for %s, invited: %4$s; uninvited: %6$s.',
);
}

File Metadata

Mime Type
text/plain
Expires
Thu, Mar 20, 2:14 PM (2 d, 15 h ago)
Storage Engine
amazon-s3
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
phabricator/secure/o4/cz/scpxdgxo7hwsaxhj
Default Alt Text
D16286.id39160.diff (86 KB)

Event Timeline