@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Convert Calendar to Modular Transactions

Summary:
Ref T9275. Swaps Calendar over to modular transactions. Theoretically, this has almost no effect on anything.

Ref T10633. I didn't actually do anything here yet, but this gets us ready to put timestamps in email.

Test Plan: Created and edited a bunch of events, nothing seemed catastrophically broken.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T9275, T10633

Differential Revision: https://secure.phabricator.com/D16286

+942 -953
+33 -1
src/__phutil_library_map__.php
··· 2021 2021 'PhabricatorCalendarDAO' => 'applications/calendar/storage/PhabricatorCalendarDAO.php', 2022 2022 'PhabricatorCalendarEditEngine' => 'applications/calendar/editor/PhabricatorCalendarEditEngine.php', 2023 2023 'PhabricatorCalendarEvent' => 'applications/calendar/storage/PhabricatorCalendarEvent.php', 2024 + 'PhabricatorCalendarEventAcceptTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventAcceptTransaction.php', 2025 + 'PhabricatorCalendarEventAllDayTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventAllDayTransaction.php', 2024 2026 'PhabricatorCalendarEventCancelController' => 'applications/calendar/controller/PhabricatorCalendarEventCancelController.php', 2027 + 'PhabricatorCalendarEventCancelTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventCancelTransaction.php', 2028 + 'PhabricatorCalendarEventDateTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventDateTransaction.php', 2029 + 'PhabricatorCalendarEventDeclineTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventDeclineTransaction.php', 2030 + 'PhabricatorCalendarEventDescriptionTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventDescriptionTransaction.php', 2025 2031 'PhabricatorCalendarEventDragController' => 'applications/calendar/controller/PhabricatorCalendarEventDragController.php', 2026 2032 'PhabricatorCalendarEventEditController' => 'applications/calendar/controller/PhabricatorCalendarEventEditController.php', 2027 2033 'PhabricatorCalendarEventEditor' => 'applications/calendar/editor/PhabricatorCalendarEventEditor.php', 2028 2034 'PhabricatorCalendarEventEmailCommand' => 'applications/calendar/command/PhabricatorCalendarEventEmailCommand.php', 2035 + 'PhabricatorCalendarEventEndDateTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventEndDateTransaction.php', 2036 + 'PhabricatorCalendarEventFrequencyTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventFrequencyTransaction.php', 2029 2037 'PhabricatorCalendarEventFulltextEngine' => 'applications/calendar/search/PhabricatorCalendarEventFulltextEngine.php', 2038 + 'PhabricatorCalendarEventIconTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventIconTransaction.php', 2039 + 'PhabricatorCalendarEventInviteTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventInviteTransaction.php', 2030 2040 'PhabricatorCalendarEventInvitee' => 'applications/calendar/storage/PhabricatorCalendarEventInvitee.php', 2031 2041 'PhabricatorCalendarEventInviteeQuery' => 'applications/calendar/query/PhabricatorCalendarEventInviteeQuery.php', 2032 2042 'PhabricatorCalendarEventJoinController' => 'applications/calendar/controller/PhabricatorCalendarEventJoinController.php', 2033 2043 'PhabricatorCalendarEventListController' => 'applications/calendar/controller/PhabricatorCalendarEventListController.php', 2034 2044 'PhabricatorCalendarEventMailReceiver' => 'applications/calendar/mail/PhabricatorCalendarEventMailReceiver.php', 2045 + 'PhabricatorCalendarEventNameTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventNameTransaction.php', 2035 2046 'PhabricatorCalendarEventPHIDType' => 'applications/calendar/phid/PhabricatorCalendarEventPHIDType.php', 2036 2047 'PhabricatorCalendarEventQuery' => 'applications/calendar/query/PhabricatorCalendarEventQuery.php', 2037 2048 'PhabricatorCalendarEventRSVPEmailCommand' => 'applications/calendar/command/PhabricatorCalendarEventRSVPEmailCommand.php', 2049 + 'PhabricatorCalendarEventRecurringTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventRecurringTransaction.php', 2050 + 'PhabricatorCalendarEventReplyTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventReplyTransaction.php', 2038 2051 'PhabricatorCalendarEventSearchEngine' => 'applications/calendar/query/PhabricatorCalendarEventSearchEngine.php', 2052 + 'PhabricatorCalendarEventStartDateTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventStartDateTransaction.php', 2039 2053 'PhabricatorCalendarEventTransaction' => 'applications/calendar/storage/PhabricatorCalendarEventTransaction.php', 2040 2054 'PhabricatorCalendarEventTransactionComment' => 'applications/calendar/storage/PhabricatorCalendarEventTransactionComment.php', 2041 2055 'PhabricatorCalendarEventTransactionQuery' => 'applications/calendar/query/PhabricatorCalendarEventTransactionQuery.php', 2056 + 'PhabricatorCalendarEventTransactionType' => 'applications/calendar/xaction/PhabricatorCalendarEventTransactionType.php', 2057 + 'PhabricatorCalendarEventUntilDateTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventUntilDateTransaction.php', 2042 2058 'PhabricatorCalendarEventViewController' => 'applications/calendar/controller/PhabricatorCalendarEventViewController.php', 2043 2059 'PhabricatorCalendarHoliday' => 'applications/calendar/storage/PhabricatorCalendarHoliday.php', 2044 2060 'PhabricatorCalendarHolidayTestCase' => 'applications/calendar/storage/__tests__/PhabricatorCalendarHolidayTestCase.php', ··· 6629 6645 'PhabricatorSpacesInterface', 6630 6646 'PhabricatorFulltextInterface', 6631 6647 ), 6648 + 'PhabricatorCalendarEventAcceptTransaction' => 'PhabricatorCalendarEventReplyTransaction', 6649 + 'PhabricatorCalendarEventAllDayTransaction' => 'PhabricatorCalendarEventTransactionType', 6632 6650 'PhabricatorCalendarEventCancelController' => 'PhabricatorCalendarController', 6651 + 'PhabricatorCalendarEventCancelTransaction' => 'PhabricatorCalendarEventTransactionType', 6652 + 'PhabricatorCalendarEventDateTransaction' => 'PhabricatorCalendarEventTransactionType', 6653 + 'PhabricatorCalendarEventDeclineTransaction' => 'PhabricatorCalendarEventReplyTransaction', 6654 + 'PhabricatorCalendarEventDescriptionTransaction' => 'PhabricatorCalendarEventTransactionType', 6633 6655 'PhabricatorCalendarEventDragController' => 'PhabricatorCalendarController', 6634 6656 'PhabricatorCalendarEventEditController' => 'PhabricatorCalendarController', 6635 6657 'PhabricatorCalendarEventEditor' => 'PhabricatorApplicationTransactionEditor', 6636 6658 'PhabricatorCalendarEventEmailCommand' => 'MetaMTAEmailTransactionCommand', 6659 + 'PhabricatorCalendarEventEndDateTransaction' => 'PhabricatorCalendarEventDateTransaction', 6660 + 'PhabricatorCalendarEventFrequencyTransaction' => 'PhabricatorCalendarEventTransactionType', 6637 6661 'PhabricatorCalendarEventFulltextEngine' => 'PhabricatorFulltextEngine', 6662 + 'PhabricatorCalendarEventIconTransaction' => 'PhabricatorCalendarEventTransactionType', 6663 + 'PhabricatorCalendarEventInviteTransaction' => 'PhabricatorCalendarEventTransactionType', 6638 6664 'PhabricatorCalendarEventInvitee' => array( 6639 6665 'PhabricatorCalendarDAO', 6640 6666 'PhabricatorPolicyInterface', ··· 6643 6669 'PhabricatorCalendarEventJoinController' => 'PhabricatorCalendarController', 6644 6670 'PhabricatorCalendarEventListController' => 'PhabricatorCalendarController', 6645 6671 'PhabricatorCalendarEventMailReceiver' => 'PhabricatorObjectMailReceiver', 6672 + 'PhabricatorCalendarEventNameTransaction' => 'PhabricatorCalendarEventTransactionType', 6646 6673 'PhabricatorCalendarEventPHIDType' => 'PhabricatorPHIDType', 6647 6674 'PhabricatorCalendarEventQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 6648 6675 'PhabricatorCalendarEventRSVPEmailCommand' => 'PhabricatorCalendarEventEmailCommand', 6676 + 'PhabricatorCalendarEventRecurringTransaction' => 'PhabricatorCalendarEventTransactionType', 6677 + 'PhabricatorCalendarEventReplyTransaction' => 'PhabricatorCalendarEventTransactionType', 6649 6678 'PhabricatorCalendarEventSearchEngine' => 'PhabricatorApplicationSearchEngine', 6650 - 'PhabricatorCalendarEventTransaction' => 'PhabricatorApplicationTransaction', 6679 + 'PhabricatorCalendarEventStartDateTransaction' => 'PhabricatorCalendarEventDateTransaction', 6680 + 'PhabricatorCalendarEventTransaction' => 'PhabricatorModularTransaction', 6651 6681 'PhabricatorCalendarEventTransactionComment' => 'PhabricatorApplicationTransactionComment', 6652 6682 'PhabricatorCalendarEventTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 6683 + 'PhabricatorCalendarEventTransactionType' => 'PhabricatorModularTransactionType', 6684 + 'PhabricatorCalendarEventUntilDateTransaction' => 'PhabricatorCalendarEventDateTransaction', 6653 6685 'PhabricatorCalendarEventViewController' => 'PhabricatorCalendarController', 6654 6686 'PhabricatorCalendarHoliday' => 'PhabricatorCalendarDAO', 6655 6687 'PhabricatorCalendarHolidayTestCase' => 'PhabricatorTestCase',
+5 -13
src/applications/calendar/command/PhabricatorCalendarEventRSVPEmailCommand.php
··· 44 44 PhabricatorMetaMTAReceivedMail $mail, 45 45 $command, 46 46 array $argv) { 47 - $status_attending = PhabricatorCalendarEventInvitee::STATUS_ATTENDING; 48 - $status_declined = PhabricatorCalendarEventInvitee::STATUS_DECLINED; 49 - $xactions = array(); 50 47 51 48 $target = phutil_utf8_strtolower(implode(' ', $argv)); 52 - $rsvp = null; 53 49 54 50 $yes_values = $this->getYesValues(); 55 51 $no_values = $this->getNoValues(); 56 52 57 53 if (in_array($target, $yes_values)) { 58 - $rsvp = $status_attending; 54 + $rsvp = PhabricatorCalendarEventAcceptTransaction::TRANSACTIONTYPE; 59 55 } else if (in_array($target, $no_values)) { 60 - $rsvp = $status_declined; 56 + $rsvp = PhabricatorCalendarEventDeclineTransaction::TRANSACTIONTYPE; 61 57 } else { 62 - $rsvp = null; 63 - } 64 - 65 - if ($rsvp === null) { 66 58 return array(); 67 59 } 68 60 61 + $xactions = array(); 69 62 $xactions[] = $object->getApplicationTransactionTemplate() 70 - ->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_INVITE) 71 - ->setNewValue(array($viewer->getPHID() => $rsvp)); 72 - 63 + ->setTransactionType($rsvp) 64 + ->setNewValue(true); 73 65 return $xactions; 74 66 } 75 67
+1 -1
src/applications/calendar/controller/PhabricatorCalendarEventCancelController.php
··· 38 38 39 39 $xaction = id(new PhabricatorCalendarEventTransaction()) 40 40 ->setTransactionType( 41 - PhabricatorCalendarEventTransaction::TYPE_CANCEL) 41 + PhabricatorCalendarEventCancelTransaction::TRANSACTIONTYPE) 42 42 ->setNewValue(!$is_cancelled); 43 43 44 44 $editor = id(new PhabricatorCalendarEventEditor())
+4 -3
src/applications/calendar/controller/PhabricatorCalendarEventDragController.php
··· 41 41 $viewer, 42 42 $end)); 43 43 44 - 45 44 $xactions[] = id(new PhabricatorCalendarEventTransaction()) 46 - ->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_START_DATE) 45 + ->setTransactionType( 46 + PhabricatorCalendarEventStartDateTransaction::TRANSACTIONTYPE) 47 47 ->setNewValue($start_value); 48 48 49 49 $xactions[] = id(new PhabricatorCalendarEventTransaction()) 50 - ->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_END_DATE) 50 + ->setTransactionType( 51 + PhabricatorCalendarEventEndDateTransaction::TRANSACTIONTYPE) 51 52 ->setNewValue($end_value); 52 53 53 54 $editor = id(new PhabricatorCalendarEventEditor())
+4 -2
src/applications/calendar/controller/PhabricatorCalendarEventJoinController.php
··· 33 33 $validation_exception = null; 34 34 if ($request->isFormPost()) { 35 35 if ($is_join) { 36 - $xaction_type = PhabricatorCalendarEventTransaction::TYPE_ACCEPT; 36 + $xaction_type = 37 + PhabricatorCalendarEventAcceptTransaction::TRANSACTIONTYPE; 37 38 } else { 38 - $xaction_type = PhabricatorCalendarEventTransaction::TYPE_DECLINE; 39 + $xaction_type = 40 + PhabricatorCalendarEventDeclineTransaction::TRANSACTIONTYPE; 39 41 } 40 42 41 43 $xaction = id(new PhabricatorCalendarEventTransaction())
+1 -1
src/applications/calendar/controller/PhabricatorCalendarEventViewController.php
··· 120 120 if ($event->isChildEvent()) { 121 121 $edit_label = pht('Edit This Instance'); 122 122 } else { 123 - $edit_label = pht('Edit'); 123 + $edit_label = pht('Edit Event'); 124 124 } 125 125 126 126 $curtain = $this->newCurtainView($event);
+15 -11
src/applications/calendar/editor/PhabricatorCalendarEditEngine.php
··· 81 81 ->setLabel(pht('Name')) 82 82 ->setDescription(pht('Name of the event.')) 83 83 ->setIsRequired(true) 84 - ->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_NAME) 84 + ->setTransactionType( 85 + PhabricatorCalendarEventNameTransaction::TRANSACTIONTYPE) 85 86 ->setConduitDescription(pht('Rename the event.')) 86 87 ->setConduitTypeDescription(pht('New event name.')) 87 88 ->setValue($object->getName()), ··· 90 91 ->setLabel(pht('Description')) 91 92 ->setDescription(pht('Description of the event.')) 92 93 ->setTransactionType( 93 - PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION) 94 + PhabricatorCalendarEventDescriptionTransaction::TRANSACTIONTYPE) 94 95 ->setConduitDescription(pht('Update the event description.')) 95 96 ->setConduitTypeDescription(pht('New event description.')) 96 97 ->setValue($object->getDescription()), ··· 100 101 ->setLabel(pht('Cancelled')) 101 102 ->setDescription(pht('Cancel the event.')) 102 103 ->setTransactionType( 103 - PhabricatorCalendarEventTransaction::TYPE_CANCEL) 104 + PhabricatorCalendarEventCancelTransaction::TRANSACTIONTYPE) 104 105 ->setIsConduitOnly(true) 105 106 ->setConduitDescription(pht('Cancel or restore the event.')) 106 107 ->setConduitTypeDescription(pht('True to cancel the event.')) ··· 110 111 ->setAliases(array('invite', 'invitee', 'invitees', 'inviteePHID')) 111 112 ->setLabel(pht('Invitees')) 112 113 ->setDatasource(new PhabricatorMetaMTAMailableDatasource()) 113 - ->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_INVITE) 114 + ->setTransactionType( 115 + PhabricatorCalendarEventInviteTransaction::TRANSACTIONTYPE) 114 116 ->setDescription(pht('Users invited to the event.')) 115 117 ->setConduitDescription(pht('Change invited users.')) 116 118 ->setConduitTypeDescription(pht('New event invitees.')) ··· 124 126 ->setLabel(pht('Recurring')) 125 127 ->setOptions(pht('One-Time Event'), pht('Recurring Event')) 126 128 ->setTransactionType( 127 - PhabricatorCalendarEventTransaction::TYPE_RECURRING) 129 + PhabricatorCalendarEventRecurringTransaction::TRANSACTIONTYPE) 128 130 ->setDescription(pht('One time or recurring event.')) 129 131 ->setConduitDescription(pht('Make the event recurring.')) 130 132 ->setConduitTypeDescription(pht('Mark the event as a recurring event.')) ··· 135 137 ->setLabel(pht('Frequency')) 136 138 ->setOptions($frequency_options) 137 139 ->setTransactionType( 138 - PhabricatorCalendarEventTransaction::TYPE_FREQUENCY) 140 + PhabricatorCalendarEventFrequencyTransaction::TRANSACTIONTYPE) 139 141 ->setDescription(pht('Recurring event frequency.')) 140 142 ->setConduitDescription(pht('Change the event frequency.')) 141 143 ->setConduitTypeDescription(pht('New event frequency.')) ··· 148 150 ->setKey('until') 149 151 ->setLabel(pht('Repeat Until')) 150 152 ->setTransactionType( 151 - PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE) 153 + PhabricatorCalendarEventUntilDateTransaction::TRANSACTIONTYPE) 152 154 ->setDescription(pht('Last instance of the event.')) 153 155 ->setConduitDescription(pht('Change when the event repeats until.')) 154 156 ->setConduitTypeDescription(pht('New final event time.')) ··· 159 161 ->setKey('isAllDay') 160 162 ->setLabel(pht('All Day')) 161 163 ->setOptions(pht('Normal Event'), pht('All Day Event')) 162 - ->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_ALL_DAY) 164 + ->setTransactionType( 165 + PhabricatorCalendarEventAllDayTransaction::TRANSACTIONTYPE) 163 166 ->setDescription(pht('Marks this as an all day event.')) 164 167 ->setConduitDescription(pht('Make the event an all day event.')) 165 168 ->setConduitTypeDescription(pht('Mark the event as an all day event.')) ··· 169 172 ->setKey('start') 170 173 ->setLabel(pht('Start')) 171 174 ->setTransactionType( 172 - PhabricatorCalendarEventTransaction::TYPE_START_DATE) 175 + PhabricatorCalendarEventStartDateTransaction::TRANSACTIONTYPE) 173 176 ->setDescription(pht('Start time of the event.')) 174 177 ->setConduitDescription(pht('Change the start time of the event.')) 175 178 ->setConduitTypeDescription(pht('New event start time.')) ··· 179 182 ->setKey('end') 180 183 ->setLabel(pht('End')) 181 184 ->setTransactionType( 182 - PhabricatorCalendarEventTransaction::TYPE_END_DATE) 185 + PhabricatorCalendarEventEndDateTransaction::TRANSACTIONTYPE) 183 186 ->setDescription(pht('End time of the event.')) 184 187 ->setConduitDescription(pht('Change the end time of the event.')) 185 188 ->setConduitTypeDescription(pht('New event end time.')) ··· 189 192 ->setKey('icon') 190 193 ->setLabel(pht('Icon')) 191 194 ->setIconSet(new PhabricatorCalendarIconSet()) 192 - ->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_ICON) 195 + ->setTransactionType( 196 + PhabricatorCalendarEventIconTransaction::TRANSACTIONTYPE) 193 197 ->setDescription(pht('Event icon.')) 194 198 ->setConduitDescription(pht('Change the event icon.')) 195 199 ->setConduitTypeDescription(pht('New event icon.'))
+15 -339
src/applications/calendar/editor/PhabricatorCalendarEventEditor.php
··· 58 58 public function getTransactionTypes() { 59 59 $types = parent::getTransactionTypes(); 60 60 61 - $types[] = PhabricatorCalendarEventTransaction::TYPE_NAME; 62 - $types[] = PhabricatorCalendarEventTransaction::TYPE_START_DATE; 63 - $types[] = PhabricatorCalendarEventTransaction::TYPE_END_DATE; 64 - $types[] = PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION; 65 - $types[] = PhabricatorCalendarEventTransaction::TYPE_CANCEL; 66 - $types[] = PhabricatorCalendarEventTransaction::TYPE_INVITE; 67 - $types[] = PhabricatorCalendarEventTransaction::TYPE_ALL_DAY; 68 - $types[] = PhabricatorCalendarEventTransaction::TYPE_ICON; 69 - $types[] = PhabricatorCalendarEventTransaction::TYPE_ACCEPT; 70 - $types[] = PhabricatorCalendarEventTransaction::TYPE_DECLINE; 71 - 72 - $types[] = PhabricatorCalendarEventTransaction::TYPE_RECURRING; 73 - $types[] = PhabricatorCalendarEventTransaction::TYPE_FREQUENCY; 74 - $types[] = PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE; 75 - 76 61 $types[] = PhabricatorTransactions::TYPE_COMMENT; 77 62 $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; 78 63 $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; ··· 80 65 return $types; 81 66 } 82 67 83 - protected function getCustomTransactionOldValue( 84 - PhabricatorLiskDAO $object, 85 - PhabricatorApplicationTransaction $xaction) { 86 - switch ($xaction->getTransactionType()) { 87 - case PhabricatorCalendarEventTransaction::TYPE_RECURRING: 88 - return (int)$object->getIsRecurring(); 89 - case PhabricatorCalendarEventTransaction::TYPE_FREQUENCY: 90 - return $object->getFrequencyUnit(); 91 - case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE: 92 - return $object->getRecurrenceEndDate(); 93 - case PhabricatorCalendarEventTransaction::TYPE_NAME: 94 - return $object->getName(); 95 - case PhabricatorCalendarEventTransaction::TYPE_START_DATE: 96 - return $object->getDateFrom(); 97 - case PhabricatorCalendarEventTransaction::TYPE_END_DATE: 98 - return $object->getDateTo(); 99 - case PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION: 100 - return $object->getDescription(); 101 - case PhabricatorCalendarEventTransaction::TYPE_CANCEL: 102 - return $object->getIsCancelled(); 103 - case PhabricatorCalendarEventTransaction::TYPE_ALL_DAY: 104 - return (int)$object->getIsAllDay(); 105 - case PhabricatorCalendarEventTransaction::TYPE_ICON: 106 - return $object->getIcon(); 107 - case PhabricatorCalendarEventTransaction::TYPE_ACCEPT: 108 - case PhabricatorCalendarEventTransaction::TYPE_DECLINE: 109 - $actor_phid = $this->getActingAsPHID(); 110 - return $object->getUserInviteStatus($actor_phid); 111 - case PhabricatorCalendarEventTransaction::TYPE_INVITE: 112 - $invitees = $object->getInvitees(); 113 - return mpull($invitees, 'getStatus', 'getInviteePHID'); 114 - } 115 - 116 - return parent::getCustomTransactionOldValue($object, $xaction); 117 - } 118 - 119 - protected function getCustomTransactionNewValue( 120 - PhabricatorLiskDAO $object, 121 - PhabricatorApplicationTransaction $xaction) { 122 - switch ($xaction->getTransactionType()) { 123 - case PhabricatorCalendarEventTransaction::TYPE_FREQUENCY: 124 - case PhabricatorCalendarEventTransaction::TYPE_NAME: 125 - case PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION: 126 - case PhabricatorCalendarEventTransaction::TYPE_CANCEL: 127 - case PhabricatorCalendarEventTransaction::TYPE_ICON: 128 - return $xaction->getNewValue(); 129 - case PhabricatorCalendarEventTransaction::TYPE_ACCEPT: 130 - return PhabricatorCalendarEventInvitee::STATUS_ATTENDING; 131 - case PhabricatorCalendarEventTransaction::TYPE_DECLINE: 132 - return PhabricatorCalendarEventInvitee::STATUS_DECLINED; 133 - case PhabricatorCalendarEventTransaction::TYPE_ALL_DAY: 134 - case PhabricatorCalendarEventTransaction::TYPE_RECURRING: 135 - return (int)$xaction->getNewValue(); 136 - case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE: 137 - case PhabricatorCalendarEventTransaction::TYPE_START_DATE: 138 - case PhabricatorCalendarEventTransaction::TYPE_END_DATE: 139 - return $xaction->getNewValue()->getEpoch(); 140 - case PhabricatorCalendarEventTransaction::TYPE_INVITE: 141 - $status_invited = PhabricatorCalendarEventInvitee::STATUS_INVITED; 142 - $status_uninvited = PhabricatorCalendarEventInvitee::STATUS_UNINVITED; 143 - $status_attending = PhabricatorCalendarEventInvitee::STATUS_ATTENDING; 144 - 145 - $invitees = $object->getInvitees(); 146 - foreach ($invitees as $key => $invitee) { 147 - if ($invitee->getStatus() == $status_uninvited) { 148 - unset($invitees[$key]); 149 - } 150 - } 151 - $invitees = mpull($invitees, null, 'getInviteePHID'); 152 - 153 - $new = $xaction->getNewValue(); 154 - $new = array_fuse($new); 155 - 156 - $all = array_keys($invitees + $new); 157 - $map = array(); 158 - foreach ($all as $phid) { 159 - $is_old = isset($invitees[$phid]); 160 - $is_new = isset($new[$phid]); 161 - 162 - if ($is_old && !$is_new) { 163 - $map[$phid] = $status_uninvited; 164 - } else if (!$is_old && $is_new) { 165 - $map[$phid] = $status_invited; 166 - } else { 167 - $map[$phid] = $invitees[$phid]->getStatus(); 168 - } 169 - } 170 - 171 - // If we're creating this event and the actor is inviting themselves, 172 - // mark them as attending. 173 - if ($this->getIsNewObject()) { 174 - $acting_phid = $this->getActingAsPHID(); 175 - if (isset($map[$acting_phid])) { 176 - $map[$acting_phid] = $status_attending; 177 - } 178 - } 179 - 180 - return $map; 181 - } 182 - 183 - return parent::getCustomTransactionNewValue($object, $xaction); 184 - } 185 - 186 - protected function applyCustomInternalTransaction( 187 - PhabricatorLiskDAO $object, 188 - PhabricatorApplicationTransaction $xaction) { 189 - 190 - switch ($xaction->getTransactionType()) { 191 - case PhabricatorCalendarEventTransaction::TYPE_RECURRING: 192 - return $object->setIsRecurring((int)$xaction->getNewValue()); 193 - case PhabricatorCalendarEventTransaction::TYPE_FREQUENCY: 194 - return $object->setRecurrenceFrequency( 195 - array( 196 - 'rule' => $xaction->getNewValue(), 197 - )); 198 - case PhabricatorCalendarEventTransaction::TYPE_NAME: 199 - $object->setName($xaction->getNewValue()); 200 - return; 201 - case PhabricatorCalendarEventTransaction::TYPE_START_DATE: 202 - $object->setDateFrom($xaction->getNewValue()); 203 - return; 204 - case PhabricatorCalendarEventTransaction::TYPE_END_DATE: 205 - $object->setDateTo($xaction->getNewValue()); 206 - return; 207 - case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE: 208 - $object->setRecurrenceEndDate($xaction->getNewValue()); 209 - return; 210 - case PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION: 211 - $object->setDescription($xaction->getNewValue()); 212 - return; 213 - case PhabricatorCalendarEventTransaction::TYPE_CANCEL: 214 - $object->setIsCancelled((int)$xaction->getNewValue()); 215 - return; 216 - case PhabricatorCalendarEventTransaction::TYPE_ALL_DAY: 217 - $object->setIsAllDay((int)$xaction->getNewValue()); 218 - return; 219 - case PhabricatorCalendarEventTransaction::TYPE_ICON: 220 - $object->setIcon($xaction->getNewValue()); 221 - return; 222 - case PhabricatorCalendarEventTransaction::TYPE_INVITE: 223 - case PhabricatorCalendarEventTransaction::TYPE_ACCEPT: 224 - case PhabricatorCalendarEventTransaction::TYPE_DECLINE: 225 - return; 226 - } 227 - 228 - return parent::applyCustomInternalTransaction($object, $xaction); 229 - } 230 - 231 - protected function applyCustomExternalTransaction( 232 - PhabricatorLiskDAO $object, 233 - PhabricatorApplicationTransaction $xaction) { 234 - 235 - switch ($xaction->getTransactionType()) { 236 - case PhabricatorCalendarEventTransaction::TYPE_RECURRING: 237 - case PhabricatorCalendarEventTransaction::TYPE_FREQUENCY: 238 - case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE: 239 - case PhabricatorCalendarEventTransaction::TYPE_NAME: 240 - case PhabricatorCalendarEventTransaction::TYPE_START_DATE: 241 - case PhabricatorCalendarEventTransaction::TYPE_END_DATE: 242 - case PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION: 243 - case PhabricatorCalendarEventTransaction::TYPE_CANCEL: 244 - case PhabricatorCalendarEventTransaction::TYPE_ALL_DAY: 245 - case PhabricatorCalendarEventTransaction::TYPE_ICON: 246 - return; 247 - case PhabricatorCalendarEventTransaction::TYPE_INVITE: 248 - $map = $xaction->getNewValue(); 249 - $phids = array_keys($map); 250 - $invitees = $object->getInvitees(); 251 - $invitees = mpull($invitees, null, 'getInviteePHID'); 252 - 253 - foreach ($phids as $phid) { 254 - $invitee = idx($invitees, $phid); 255 - if (!$invitee) { 256 - $invitee = id(new PhabricatorCalendarEventInvitee()) 257 - ->setEventPHID($object->getPHID()) 258 - ->setInviteePHID($phid) 259 - ->setInviterPHID($this->getActingAsPHID()); 260 - $invitees[] = $invitee; 261 - } 262 - $invitee->setStatus($map[$phid]) 263 - ->save(); 264 - } 265 - $object->attachInvitees($invitees); 266 - return; 267 - case PhabricatorCalendarEventTransaction::TYPE_ACCEPT: 268 - case PhabricatorCalendarEventTransaction::TYPE_DECLINE: 269 - $acting_phid = $this->getActingAsPHID(); 270 - 271 - $invitees = $object->getInvitees(); 272 - $invitees = mpull($invitees, null, 'getInviteePHID'); 273 - 274 - $invitee = idx($invitees, $acting_phid); 275 - if (!$invitee) { 276 - $invitee = id(new PhabricatorCalendarEventInvitee()) 277 - ->setEventPHID($object->getPHID()) 278 - ->setInviteePHID($acting_phid) 279 - ->setInviterPHID($acting_phid); 280 - $invitees[$acting_phid] = $invitee; 281 - } 282 - 283 - $invitee 284 - ->setStatus($xaction->getNewValue()) 285 - ->save(); 286 - 287 - $object->attachInvitees($invitees); 288 - return; 289 - } 290 - 291 - return parent::applyCustomExternalTransaction($object, $xaction); 292 - } 293 - 294 68 protected function applyFinalEffects( 295 69 PhabricatorLiskDAO $object, 296 70 array $xactions) { ··· 302 76 $invalidate_phids = array(); 303 77 foreach ($xactions as $xaction) { 304 78 switch ($xaction->getTransactionType()) { 305 - case PhabricatorCalendarEventTransaction::TYPE_ICON: 306 - break; 307 - case PhabricatorCalendarEventTransaction::TYPE_RECURRING: 308 - case PhabricatorCalendarEventTransaction::TYPE_FREQUENCY: 309 - case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE: 310 - case PhabricatorCalendarEventTransaction::TYPE_START_DATE: 311 - case PhabricatorCalendarEventTransaction::TYPE_END_DATE: 312 - case PhabricatorCalendarEventTransaction::TYPE_CANCEL: 313 - case PhabricatorCalendarEventTransaction::TYPE_ALL_DAY: 79 + case PhabricatorCalendarEventUntilDateTransaction::TRANSACTIONTYPE: 80 + case PhabricatorCalendarEventStartDateTransaction::TRANSACTIONTYPE: 81 + case PhabricatorCalendarEventEndDateTransaction::TRANSACTIONTYPE: 82 + case PhabricatorCalendarEventCancelTransaction::TRANSACTIONTYPE: 83 + case PhabricatorCalendarEventAllDayTransaction::TRANSACTIONTYPE: 314 84 // For these kinds of changes, we need to invalidate the availabilty 315 85 // caches for all attendees. 316 86 $invalidate_all = true; 317 87 break; 318 - 319 - case PhabricatorCalendarEventTransaction::TYPE_ACCEPT: 320 - case PhabricatorCalendarEventTransaction::TYPE_DECLINE: 88 + case PhabricatorCalendarEventAcceptTransaction::TRANSACTIONTYPE: 89 + case PhabricatorCalendarEventDeclineTransaction::TRANSACTIONTYPE: 321 90 $acting_phid = $this->getActingAsPHID(); 322 91 $invalidate_phids[$acting_phid] = $acting_phid; 323 92 break; 324 - case PhabricatorCalendarEventTransaction::TYPE_INVITE: 93 + case PhabricatorCalendarEventInviteTransaction::TRANSACTIONTYPE: 325 94 foreach ($xaction->getNewValue() as $phid => $ignored) { 326 95 $invalidate_phids[$phid] = $phid; 327 96 } ··· 357 126 protected function validateAllTransactions( 358 127 PhabricatorLiskDAO $object, 359 128 array $xactions) { 129 + 360 130 $start_date_xaction = 361 - PhabricatorCalendarEventTransaction::TYPE_START_DATE; 131 + PhabricatorCalendarEventStartDateTransaction::TRANSACTIONTYPE; 362 132 $end_date_xaction = 363 - PhabricatorCalendarEventTransaction::TYPE_END_DATE; 133 + PhabricatorCalendarEventEndDateTransaction::TRANSACTIONTYPE; 364 134 $is_recurrence_xaction = 365 - PhabricatorCalendarEventTransaction::TYPE_RECURRING; 135 + PhabricatorCalendarEventRecurringTransaction::TRANSACTIONTYPE; 366 136 $recurrence_end_xaction = 367 - PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE; 137 + PhabricatorCalendarEventUntilDateTransaction::TRANSACTIONTYPE; 368 138 369 139 $start_date = $object->getDateFrom(); 370 140 $end_date = $object->getDateTo(); ··· 386 156 } 387 157 388 158 if ($start_date > $end_date) { 389 - $type = PhabricatorCalendarEventTransaction::TYPE_END_DATE; 390 159 $errors[] = new PhabricatorApplicationTransactionValidationError( 391 - $type, 160 + $end_date_xaction, 392 161 pht('Invalid'), 393 162 pht('End date must be after start date.'), 394 163 null); 395 164 } 396 165 397 166 if ($recurrence_end && !$is_recurring) { 398 - $type = 399 - PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE; 400 167 $errors[] = new PhabricatorApplicationTransactionValidationError( 401 - $type, 168 + $recurrence_end_xaction, 402 169 pht('Invalid'), 403 170 pht('Event must be recurring to have a recurrence end date.'). 404 171 null); 405 - } 406 - 407 - return $errors; 408 - } 409 - 410 - protected function validateTransaction( 411 - PhabricatorLiskDAO $object, 412 - $type, 413 - array $xactions) { 414 - 415 - $errors = parent::validateTransaction($object, $type, $xactions); 416 - 417 - switch ($type) { 418 - case PhabricatorCalendarEventTransaction::TYPE_NAME: 419 - $missing = $this->validateIsEmptyTextField( 420 - $object->getName(), 421 - $xactions); 422 - 423 - if ($missing) { 424 - $error = new PhabricatorApplicationTransactionValidationError( 425 - $type, 426 - pht('Required'), 427 - pht('Event name is required.'), 428 - nonempty(last($xactions), null)); 429 - 430 - $error->setIsMissingFieldError(true); 431 - $errors[] = $error; 432 - } 433 - break; 434 - case PhabricatorCalendarEventTransaction::TYPE_INVITE: 435 - $old = $object->getInvitees(); 436 - $old = mpull($old, null, 'getInviteePHID'); 437 - foreach ($xactions as $xaction) { 438 - $new = $xaction->getNewValue(); 439 - $new = array_fuse($new); 440 - $add = array_diff_key($new, $old); 441 - if (!$add) { 442 - continue; 443 - } 444 - 445 - // In the UI, we only allow you to invite mailable objects, but there 446 - // is no definitive marker for "invitable object" today. Just allow 447 - // any valid object to be invited. 448 - $objects = id(new PhabricatorObjectQuery()) 449 - ->setViewer($this->getActor()) 450 - ->withPHIDs($add) 451 - ->execute(); 452 - $objects = mpull($objects, null, 'getPHID'); 453 - foreach ($add as $phid) { 454 - if (isset($objects[$phid])) { 455 - continue; 456 - } 457 - 458 - $errors[] = new PhabricatorApplicationTransactionValidationError( 459 - $type, 460 - pht('Invalid'), 461 - pht( 462 - 'Invitee "%s" identifies an object that does not exist or '. 463 - 'which you do not have permission to view.', 464 - $phid)); 465 - } 466 - } 467 - break; 468 - case PhabricatorCalendarEventTransaction::TYPE_START_DATE: 469 - case PhabricatorCalendarEventTransaction::TYPE_END_DATE: 470 - case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE: 471 - foreach ($xactions as $xaction) { 472 - if ($xaction->getNewValue()->isValid()) { 473 - continue; 474 - } 475 - 476 - switch ($type) { 477 - case PhabricatorCalendarEventTransaction::TYPE_START_DATE: 478 - $message = pht('Start date is invalid.'); 479 - break; 480 - case PhabricatorCalendarEventTransaction::TYPE_END_DATE: 481 - $message = pht('End date is invalid.'); 482 - break; 483 - case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE: 484 - $message = pht('Repeat until date is invalid.'); 485 - break; 486 - } 487 - 488 - $errors[] = new PhabricatorApplicationTransactionValidationError( 489 - $type, 490 - pht('Invalid'), 491 - $message, 492 - $xaction); 493 - } 494 - break; 495 - 496 172 } 497 173 498 174 return $errors;
+9 -579
src/applications/calendar/storage/PhabricatorCalendarEventTransaction.php
··· 1 1 <?php 2 2 3 3 final class PhabricatorCalendarEventTransaction 4 - extends PhabricatorApplicationTransaction { 5 - 6 - const TYPE_NAME = 'calendar.name'; 7 - const TYPE_START_DATE = 'calendar.startdate'; 8 - const TYPE_END_DATE = 'calendar.enddate'; 9 - const TYPE_DESCRIPTION = 'calendar.description'; 10 - const TYPE_CANCEL = 'calendar.cancel'; 11 - const TYPE_ALL_DAY = 'calendar.allday'; 12 - const TYPE_ICON = 'calendar.icon'; 13 - const TYPE_INVITE = 'calendar.invite'; 14 - const TYPE_ACCEPT = 'calendar.accept'; 15 - const TYPE_DECLINE = 'calendar.decline'; 16 - 17 - const TYPE_RECURRING = 'calendar.recurring'; 18 - const TYPE_FREQUENCY = 'calendar.frequency'; 19 - const TYPE_RECURRENCE_END_DATE = 'calendar.recurrenceenddate'; 4 + extends PhabricatorModularTransaction { 20 5 21 6 const MAILTAG_RESCHEDULE = 'calendar-reschedule'; 22 7 const MAILTAG_CONTENT = 'calendar-content'; ··· 34 19 return new PhabricatorCalendarEventTransactionComment(); 35 20 } 36 21 37 - public function getRequiredHandlePHIDs() { 38 - $phids = parent::getRequiredHandlePHIDs(); 39 - 40 - switch ($this->getTransactionType()) { 41 - case self::TYPE_NAME: 42 - case self::TYPE_START_DATE: 43 - case self::TYPE_END_DATE: 44 - case self::TYPE_DESCRIPTION: 45 - case self::TYPE_CANCEL: 46 - case self::TYPE_ALL_DAY: 47 - case self::TYPE_RECURRING: 48 - case self::TYPE_FREQUENCY: 49 - case self::TYPE_RECURRENCE_END_DATE: 50 - $phids[] = $this->getObjectPHID(); 51 - break; 52 - case self::TYPE_INVITE: 53 - $new = $this->getNewValue(); 54 - foreach ($new as $phid => $status) { 55 - $phids[] = $phid; 56 - } 57 - break; 58 - } 59 - 60 - return $phids; 61 - } 62 - 63 - public function shouldHide() { 64 - $old = $this->getOldValue(); 65 - switch ($this->getTransactionType()) { 66 - case self::TYPE_START_DATE: 67 - case self::TYPE_END_DATE: 68 - case self::TYPE_DESCRIPTION: 69 - case self::TYPE_CANCEL: 70 - case self::TYPE_ALL_DAY: 71 - case self::TYPE_INVITE: 72 - case self::TYPE_RECURRING: 73 - case self::TYPE_FREQUENCY: 74 - case self::TYPE_RECURRENCE_END_DATE: 75 - return ($old === null); 76 - } 77 - return parent::shouldHide(); 78 - } 79 - 80 - public function getIcon() { 81 - switch ($this->getTransactionType()) { 82 - case self::TYPE_ICON: 83 - return $this->getNewValue(); 84 - case self::TYPE_NAME: 85 - case self::TYPE_START_DATE: 86 - case self::TYPE_END_DATE: 87 - case self::TYPE_DESCRIPTION: 88 - case self::TYPE_ALL_DAY: 89 - case self::TYPE_CANCEL: 90 - case self::TYPE_RECURRING: 91 - case self::TYPE_FREQUENCY: 92 - case self::TYPE_RECURRENCE_END_DATE: 93 - return 'fa-pencil'; 94 - break; 95 - case self::TYPE_INVITE: 96 - return 'fa-user-plus'; 97 - break; 98 - } 99 - return parent::getIcon(); 100 - } 101 - 102 - public function getTitle() { 103 - $author_phid = $this->getAuthorPHID(); 104 - $object_phid = $this->getObjectPHID(); 105 - 106 - $old = $this->getOldValue(); 107 - $new = $this->getNewValue(); 108 - 109 - $type = $this->getTransactionType(); 110 - switch ($type) { 111 - case self::TYPE_NAME: 112 - if ($old === null) { 113 - return pht( 114 - '%s created this event.', 115 - $this->renderHandleLink($author_phid)); 116 - } else { 117 - return pht( 118 - '%s changed the name of this event from %s to %s.', 119 - $this->renderHandleLink($author_phid), 120 - $old, 121 - $new); 122 - } 123 - case self::TYPE_START_DATE: 124 - if ($old) { 125 - return pht( 126 - '%s edited the start date of this event.', 127 - $this->renderHandleLink($author_phid)); 128 - } 129 - break; 130 - case self::TYPE_END_DATE: 131 - if ($old) { 132 - return pht( 133 - '%s edited the end date of this event.', 134 - $this->renderHandleLink($author_phid)); 135 - } 136 - break; 137 - case self::TYPE_DESCRIPTION: 138 - return pht( 139 - "%s updated the event's description.", 140 - $this->renderHandleLink($author_phid)); 141 - case self::TYPE_ALL_DAY: 142 - if ($new) { 143 - return pht( 144 - '%s made this an all day event.', 145 - $this->renderHandleLink($author_phid)); 146 - } else { 147 - return pht( 148 - '%s converted this from an all day event.', 149 - $this->renderHandleLink($author_phid)); 150 - } 151 - case self::TYPE_ICON: 152 - $set = new PhabricatorCalendarIconSet(); 153 - return pht( 154 - '%s set this event\'s icon to %s.', 155 - $this->renderHandleLink($author_phid), 156 - $set->getIconLabel($new)); 157 - break; 158 - case self::TYPE_CANCEL: 159 - if ($new) { 160 - return pht( 161 - '%s cancelled this event.', 162 - $this->renderHandleLink($author_phid)); 163 - } else { 164 - return pht( 165 - '%s reinstated this event.', 166 - $this->renderHandleLink($author_phid)); 167 - } 168 - case self::TYPE_ACCEPT: 169 - return pht( 170 - '%s is attending this event.', 171 - $this->renderHandleLink($author_phid)); 172 - case self::TYPE_DECLINE: 173 - return pht( 174 - '%s declined this event.', 175 - $this->renderHandleLink($author_phid)); 176 - case self::TYPE_INVITE: 177 - $text = null; 178 - 179 - list($old, $new) = $this->getSimpleInvites($old, $new); 180 - 181 - if (count($old) === 1 182 - && count($new) === 1 183 - && isset($old[$author_phid])) { 184 - // user joined/declined/accepted event themself 185 - $old_status = $old[$author_phid]; 186 - $new_status = $new[$author_phid]; 187 - 188 - if ($old_status !== $new_status) { 189 - switch ($new_status) { 190 - case PhabricatorCalendarEventInvitee::STATUS_INVITED: 191 - $text = pht( 192 - '%s has joined this event.', 193 - $this->renderHandleLink($author_phid)); 194 - break; 195 - case PhabricatorCalendarEventInvitee::STATUS_ATTENDING: 196 - $text = pht( 197 - '%s is attending this event.', 198 - $this->renderHandleLink($author_phid)); 199 - break; 200 - case PhabricatorCalendarEventInvitee::STATUS_DECLINED: 201 - case PhabricatorCalendarEventInvitee::STATUS_UNINVITED: 202 - $text = pht( 203 - '%s has declined this event.', 204 - $this->renderHandleLink($author_phid)); 205 - break; 206 - default: 207 - $text = pht( 208 - '%s has changed their status for this event.', 209 - $this->renderHandleLink($author_phid)); 210 - break; 211 - } 212 - } 213 - } else { 214 - // user changed status for many users 215 - $self_joined = null; 216 - $self_declined = null; 217 - $added = array(); 218 - $uninvited = array(); 219 - 220 - foreach ($new as $phid => $status) { 221 - if ($status == PhabricatorCalendarEventInvitee::STATUS_INVITED 222 - || $status == PhabricatorCalendarEventInvitee::STATUS_ATTENDING) { 223 - // added users 224 - $added[] = $phid; 225 - } else if ( 226 - $status == PhabricatorCalendarEventInvitee::STATUS_DECLINED 227 - || $status == PhabricatorCalendarEventInvitee::STATUS_UNINVITED) { 228 - $uninvited[] = $phid; 229 - } 230 - } 231 - 232 - $count_added = count($added); 233 - $count_uninvited = count($uninvited); 234 - $added_text = null; 235 - $uninvited_text = null; 236 - 237 - if ($count_added > 0 && $count_uninvited == 0) { 238 - $added_text = $this->renderHandleList($added); 239 - $text = pht('%s invited %s.', 240 - $this->renderHandleLink($author_phid), 241 - $added_text); 242 - } else if ($count_added > 0 && $count_uninvited > 0) { 243 - $added_text = $this->renderHandleList($added); 244 - $uninvited_text = $this->renderHandleList($uninvited); 245 - $text = pht('%s invited %s and uninvited %s.', 246 - $this->renderHandleLink($author_phid), 247 - $added_text, 248 - $uninvited_text); 249 - } else if ($count_added == 0 && $count_uninvited > 0) { 250 - $uninvited_text = $this->renderHandleList($uninvited); 251 - $text = pht('%s uninvited %s.', 252 - $this->renderHandleLink($author_phid), 253 - $uninvited_text); 254 - } else { 255 - $text = pht('%s updated the invitee list.', 256 - $this->renderHandleLink($author_phid)); 257 - } 258 - } 259 - return $text; 260 - case self::TYPE_RECURRING: 261 - $text = pht('%s made this event recurring.', 262 - $this->renderHandleLink($author_phid)); 263 - return $text; 264 - case self::TYPE_FREQUENCY: 265 - $rule = $new; 266 - if (is_array($rule)) { 267 - $rule = idx($rule, 'rule'); 268 - } 269 - 270 - $text = ''; 271 - switch ($rule) { 272 - case PhabricatorCalendarEvent::FREQUENCY_DAILY: 273 - $text = pht('%s set this event to repeat daily.', 274 - $this->renderHandleLink($author_phid)); 275 - break; 276 - case PhabricatorCalendarEvent::FREQUENCY_WEEKLY: 277 - $text = pht('%s set this event to repeat weekly.', 278 - $this->renderHandleLink($author_phid)); 279 - break; 280 - case PhabricatorCalendarEvent::FREQUENCY_MONTHLY: 281 - $text = pht('%s set this event to repeat monthly.', 282 - $this->renderHandleLink($author_phid)); 283 - break; 284 - case PhabricatorCalendarEvent::FREQUENCY_YEARLY: 285 - $text = pht('%s set this event to repeat yearly.', 286 - $this->renderHandleLink($author_phid)); 287 - break; 288 - } 289 - return $text; 290 - case self::TYPE_RECURRENCE_END_DATE: 291 - $text = pht('%s has changed the recurrence end date of this event.', 292 - $this->renderHandleLink($author_phid)); 293 - return $text; 294 - } 295 - return parent::getTitle(); 296 - } 297 - 298 - public function getTitleForFeed() { 299 - $author_phid = $this->getAuthorPHID(); 300 - $object_phid = $this->getObjectPHID(); 301 - 302 - $old = $this->getOldValue(); 303 - $new = $this->getNewValue(); 304 - 305 - $viewer = $this->getViewer(); 306 - 307 - $type = $this->getTransactionType(); 308 - switch ($type) { 309 - case self::TYPE_NAME: 310 - if ($old === null) { 311 - return pht( 312 - '%s created %s.', 313 - $this->renderHandleLink($author_phid), 314 - $this->renderHandleLink($object_phid)); 315 - } else { 316 - return pht( 317 - '%s changed the name of %s from %s to %s.', 318 - $this->renderHandleLink($author_phid), 319 - $this->renderHandleLink($object_phid), 320 - $old, 321 - $new); 322 - } 323 - case self::TYPE_START_DATE: 324 - if ($old) { 325 - $old = phabricator_datetime($old, $viewer); 326 - $new = phabricator_datetime($new, $viewer); 327 - return pht( 328 - '%s changed the start date of %s from %s to %s.', 329 - $this->renderHandleLink($author_phid), 330 - $this->renderHandleLink($object_phid), 331 - $old, 332 - $new); 333 - } 334 - break; 335 - case self::TYPE_END_DATE: 336 - if ($old) { 337 - $old = phabricator_datetime($old, $viewer); 338 - $new = phabricator_datetime($new, $viewer); 339 - return pht( 340 - '%s edited the end date of %s from %s to %s.', 341 - $this->renderHandleLink($author_phid), 342 - $this->renderHandleLink($object_phid), 343 - $old, 344 - $new); 345 - } 346 - break; 347 - case self::TYPE_DESCRIPTION: 348 - return pht( 349 - '%s updated the description of %s.', 350 - $this->renderHandleLink($author_phid), 351 - $this->renderHandleLink($object_phid)); 352 - case self::TYPE_ALL_DAY: 353 - if ($new) { 354 - return pht( 355 - '%s made %s an all day event.', 356 - $this->renderHandleLink($author_phid), 357 - $this->renderHandleLink($object_phid)); 358 - } else { 359 - return pht( 360 - '%s converted %s from an all day event.', 361 - $this->renderHandleLink($author_phid), 362 - $this->renderHandleLink($object_phid)); 363 - } 364 - case self::TYPE_ICON: 365 - $set = new PhabricatorCalendarIconSet(); 366 - return pht( 367 - '%s set the icon for %s to %s.', 368 - $this->renderHandleLink($author_phid), 369 - $this->renderHandleLink($object_phid), 370 - $set->getIconLabel($new)); 371 - case self::TYPE_CANCEL: 372 - if ($new) { 373 - return pht( 374 - '%s cancelled %s.', 375 - $this->renderHandleLink($author_phid), 376 - $this->renderHandleLink($object_phid)); 377 - } else { 378 - return pht( 379 - '%s reinstated %s.', 380 - $this->renderHandleLink($author_phid), 381 - $this->renderHandleLink($object_phid)); 382 - } 383 - case self::TYPE_ACCEPT: 384 - return pht( 385 - '%s is attending %s.', 386 - $this->renderHandleLink($author_phid), 387 - $this->renderHandleLink($object_phid)); 388 - case self::TYPE_DECLINE: 389 - return pht( 390 - '%s declined %s.', 391 - $this->renderHandleLink($author_phid), 392 - $this->renderHandleLink($object_phid)); 393 - case self::TYPE_INVITE: 394 - $text = null; 395 - 396 - list($old, $new) = $this->getSimpleInvites($old, $new); 397 - 398 - if (count($old) === 1 399 - && count($new) === 1 400 - && isset($old[$author_phid])) { 401 - // user joined/declined/accepted event themself 402 - $old_status = $old[$author_phid]; 403 - $new_status = $new[$author_phid]; 404 - 405 - if ($old_status !== $new_status) { 406 - switch ($new_status) { 407 - case PhabricatorCalendarEventInvitee::STATUS_INVITED: 408 - $text = pht( 409 - '%s has joined %s.', 410 - $this->renderHandleLink($author_phid), 411 - $this->renderHandleLink($object_phid)); 412 - break; 413 - case PhabricatorCalendarEventInvitee::STATUS_ATTENDING: 414 - $text = pht( 415 - '%s is attending %s.', 416 - $this->renderHandleLink($author_phid), 417 - $this->renderHandleLink($object_phid)); 418 - break; 419 - case PhabricatorCalendarEventInvitee::STATUS_DECLINED: 420 - case PhabricatorCalendarEventInvitee::STATUS_UNINVITED: 421 - $text = pht( 422 - '%s has declined %s.', 423 - $this->renderHandleLink($author_phid), 424 - $this->renderHandleLink($object_phid)); 425 - break; 426 - default: 427 - $text = pht( 428 - '%s has changed their status of %s.', 429 - $this->renderHandleLink($author_phid), 430 - $this->renderHandleLink($object_phid)); 431 - break; 432 - } 433 - } 434 - } else { 435 - // user changed status for many users 436 - $self_joined = null; 437 - $self_declined = null; 438 - $added = array(); 439 - $uninvited = array(); 440 - 441 - foreach ($new as $phid => $status) { 442 - if ($status == PhabricatorCalendarEventInvitee::STATUS_INVITED 443 - || $status == PhabricatorCalendarEventInvitee::STATUS_ATTENDING) { 444 - // added users 445 - $added[] = $phid; 446 - } else if ( 447 - $status == PhabricatorCalendarEventInvitee::STATUS_DECLINED 448 - || $status == PhabricatorCalendarEventInvitee::STATUS_UNINVITED) { 449 - $uninvited[] = $phid; 450 - } 451 - } 452 - 453 - $count_added = count($added); 454 - $count_uninvited = count($uninvited); 455 - $added_text = null; 456 - $uninvited_text = null; 457 - 458 - if ($count_added > 0 && $count_uninvited == 0) { 459 - $added_text = $this->renderHandleList($added); 460 - $text = pht('%s invited %s to %s.', 461 - $this->renderHandleLink($author_phid), 462 - $added_text, 463 - $this->renderHandleLink($object_phid)); 464 - } else if ($count_added > 0 && $count_uninvited > 0) { 465 - $added_text = $this->renderHandleList($added); 466 - $uninvited_text = $this->renderHandleList($uninvited); 467 - $text = pht('%s invited %s and uninvited %s to %s.', 468 - $this->renderHandleLink($author_phid), 469 - $added_text, 470 - $uninvited_text, 471 - $this->renderHandleLink($object_phid)); 472 - } else if ($count_added == 0 && $count_uninvited > 0) { 473 - $uninvited_text = $this->renderHandleList($uninvited); 474 - $text = pht('%s uninvited %s to %s.', 475 - $this->renderHandleLink($author_phid), 476 - $uninvited_text, 477 - $this->renderHandleLink($object_phid)); 478 - } else { 479 - $text = pht('%s updated the invitee list of %s.', 480 - $this->renderHandleLink($author_phid), 481 - $this->renderHandleLink($object_phid)); 482 - } 483 - } 484 - return $text; 485 - case self::TYPE_RECURRING: 486 - $text = pht('%s made %s a recurring event.', 487 - $this->renderHandleLink($author_phid), 488 - $this->renderHandleLink($object_phid)); 489 - return $text; 490 - case self::TYPE_FREQUENCY: 491 - $rule = $new; 492 - if (is_array($rule)) { 493 - $rule = idx($rule, 'rule'); 494 - } 495 - 496 - $text = ''; 497 - switch ($rule) { 498 - case PhabricatorCalendarEvent::FREQUENCY_DAILY: 499 - $text = pht('%s set %s to repeat daily.', 500 - $this->renderHandleLink($author_phid), 501 - $this->renderHandleLink($object_phid)); 502 - break; 503 - case PhabricatorCalendarEvent::FREQUENCY_WEEKLY: 504 - $text = pht('%s set %s to repeat weekly.', 505 - $this->renderHandleLink($author_phid), 506 - $this->renderHandleLink($object_phid)); 507 - break; 508 - case PhabricatorCalendarEvent::FREQUENCY_MONTHLY: 509 - $text = pht('%s set %s to repeat monthly.', 510 - $this->renderHandleLink($author_phid), 511 - $this->renderHandleLink($object_phid)); 512 - break; 513 - case PhabricatorCalendarEvent::FREQUENCY_YEARLY: 514 - $text = pht('%s set %s to repeat yearly.', 515 - $this->renderHandleLink($author_phid), 516 - $this->renderHandleLink($object_phid)); 517 - break; 518 - } 519 - return $text; 520 - case self::TYPE_RECURRENCE_END_DATE: 521 - $text = pht('%s set the recurrence end date of %s to %s.', 522 - $this->renderHandleLink($author_phid), 523 - $this->renderHandleLink($object_phid), 524 - $new); 525 - return $text; 526 - } 527 - 528 - return parent::getTitleForFeed(); 529 - } 530 - 531 - public function getColor() { 532 - $old = $this->getOldValue(); 533 - $new = $this->getNewValue(); 534 - 535 - switch ($this->getTransactionType()) { 536 - case self::TYPE_NAME: 537 - case self::TYPE_START_DATE: 538 - case self::TYPE_END_DATE: 539 - case self::TYPE_DESCRIPTION: 540 - case self::TYPE_CANCEL: 541 - case self::TYPE_INVITE: 542 - return PhabricatorTransactions::COLOR_GREEN; 543 - } 544 - 545 - return parent::getColor(); 546 - } 547 - 548 - 549 - public function hasChangeDetails() { 550 - switch ($this->getTransactionType()) { 551 - case self::TYPE_DESCRIPTION: 552 - return ($this->getOldValue() !== null); 553 - } 554 - 555 - return parent::hasChangeDetails(); 556 - } 557 - 558 - public function renderChangeDetails(PhabricatorUser $viewer) { 559 - switch ($this->getTransactionType()) { 560 - case self::TYPE_DESCRIPTION: 561 - $old = $this->getOldValue(); 562 - $new = $this->getNewValue(); 563 - 564 - return $this->renderTextCorpusChangeDetails( 565 - $viewer, 566 - $old, 567 - $new); 568 - } 569 - 570 - return parent::renderChangeDetails($viewer); 22 + public function getBaseTransactionClass() { 23 + return 'PhabricatorCalendarEventTransactionType'; 571 24 } 572 25 573 26 public function getMailTags() { 574 27 $tags = array(); 575 28 switch ($this->getTransactionType()) { 576 - case self::TYPE_NAME: 577 - case self::TYPE_DESCRIPTION: 578 - case self::TYPE_INVITE: 579 - case self::TYPE_ICON: 29 + case PhabricatorCalendarEventNameTransaction::TRANSACTIONTYPE: 30 + case PhabricatorCalendarEventDescriptionTransaction::TRANSACTIONTYPE: 31 + case PhabricatorCalendarEventInviteTransaction::TRANSACTIONTYPE: 580 32 $tags[] = self::MAILTAG_CONTENT; 581 33 break; 582 - case self::TYPE_START_DATE: 583 - case self::TYPE_END_DATE: 584 - case self::TYPE_CANCEL: 34 + case PhabricatorCalendarEventStartDateTransaction::TRANSACTIONTYPE: 35 + case PhabricatorCalendarEventEndDateTransaction::TRANSACTIONTYPE: 36 + case PhabricatorCalendarEventCancelTransaction::TRANSACTIONTYPE: 585 37 $tags[] = self::MAILTAG_RESCHEDULE; 586 38 break; 587 39 } 588 40 return $tags; 589 41 } 590 - 591 - private function getSimpleInvites(array $old, array $new) { 592 - // Fill in any new invitees as "uninvited" in the old data, to make 593 - // some of the rendering logic a little easier. 594 - $status_uninvited = PhabricatorCalendarEventInvitee::STATUS_UNINVITED; 595 - $old = $old + array_fill_keys(array_keys($new), $status_uninvited); 596 - 597 - $all = $old + $new; 598 - foreach (array_keys($all) as $key) { 599 - // If the invitee exists in both the old and new lists with the same 600 - // value, remove it from both. 601 - if (isset($old[$key]) && isset($new[$key])) { 602 - if ($old[$key] == $new[$key]) { 603 - unset($old[$key]); 604 - unset($new[$key]); 605 - } 606 - } 607 - } 608 - 609 - return array($old, $new); 610 - } 611 - 612 42 613 43 }
+25
src/applications/calendar/xaction/PhabricatorCalendarEventAcceptTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorCalendarEventAcceptTransaction 4 + extends PhabricatorCalendarEventReplyTransaction { 5 + 6 + const TRANSACTIONTYPE = 'calendar.accept'; 7 + 8 + public function generateNewValue($object, $value) { 9 + return PhabricatorCalendarEventInvitee::STATUS_ATTENDING; 10 + } 11 + 12 + public function getTitle() { 13 + return pht( 14 + '%s is attending this event.', 15 + $this->renderAuthor()); 16 + } 17 + 18 + public function getTitleForFeed() { 19 + return pht( 20 + '%s is attending %s.', 21 + $this->renderAuthor(), 22 + $this->renderObject()); 23 + } 24 + 25 + }
+46
src/applications/calendar/xaction/PhabricatorCalendarEventAllDayTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorCalendarEventAllDayTransaction 4 + extends PhabricatorCalendarEventTransactionType { 5 + 6 + const TRANSACTIONTYPE = 'calendar.allday'; 7 + 8 + public function generateOldValue($object) { 9 + return (int)$object->getIsAllDay(); 10 + } 11 + 12 + public function generateNewValue($object, $value) { 13 + return (int)$value; 14 + } 15 + 16 + public function applyInternalEffects($object, $value) { 17 + $object->setIsAllDay($value); 18 + } 19 + 20 + public function getTitle() { 21 + if ($this->getNewValue()) { 22 + return pht( 23 + '%s changed this as an all day event.', 24 + $this->renderAuthor()); 25 + } else { 26 + return pht( 27 + '%s conveted this from an all day event.', 28 + $this->renderAuthor()); 29 + } 30 + } 31 + 32 + public function getTitleForFeed() { 33 + if ($this->getNewValue()) { 34 + return pht( 35 + '%s changed %s to an all day event.', 36 + $this->renderAuthor(), 37 + $this->renderObject()); 38 + } else { 39 + return pht( 40 + '%s converted %s from an all day event.', 41 + $this->renderAuthor(), 42 + $this->renderObject()); 43 + } 44 + } 45 + 46 + }
+46
src/applications/calendar/xaction/PhabricatorCalendarEventCancelTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorCalendarEventCancelTransaction 4 + extends PhabricatorCalendarEventTransactionType { 5 + 6 + const TRANSACTIONTYPE = 'calendar.cancel'; 7 + 8 + public function generateOldValue($object) { 9 + return (int)$object->getIsCancelled(); 10 + } 11 + 12 + public function generateNewValue($object, $value) { 13 + return (int)$value; 14 + } 15 + 16 + public function applyInternalEffects($object, $value) { 17 + $object->setIsCancelled($value); 18 + } 19 + 20 + public function getTitle() { 21 + if ($this->getNewValue()) { 22 + return pht( 23 + '%s cancelled this event.', 24 + $this->renderAuthor()); 25 + } else { 26 + return pht( 27 + '%s reinstated this event.', 28 + $this->renderAuthor()); 29 + } 30 + } 31 + 32 + public function getTitleForFeed() { 33 + if ($this->getNewValue()) { 34 + return pht( 35 + '%s cancelled %s.', 36 + $this->renderAuthor(), 37 + $this->renderObject()); 38 + } else { 39 + return pht( 40 + '%s reinstated %s.', 41 + $this->renderAuthor(), 42 + $this->renderObject()); 43 + } 44 + } 45 + 46 + }
+27
src/applications/calendar/xaction/PhabricatorCalendarEventDateTransaction.php
··· 1 + <?php 2 + 3 + abstract class PhabricatorCalendarEventDateTransaction 4 + extends PhabricatorCalendarEventTransactionType { 5 + 6 + abstract protected function getInvalidDateMessage(); 7 + 8 + public function generateNewValue($object, $value) { 9 + return $value->getEpoch(); 10 + } 11 + 12 + public function validateTransactions($object, array $xactions) { 13 + $errors = array(); 14 + 15 + foreach ($xactions as $xaction) { 16 + if ($xaction->getNewValue()->isValid()) { 17 + continue; 18 + } 19 + 20 + $message = $this->getInvalidDateMessage(); 21 + $errors[] = $this->newInvalidError($message, $xaction); 22 + } 23 + 24 + return $errors; 25 + } 26 + 27 + }
+25
src/applications/calendar/xaction/PhabricatorCalendarEventDeclineTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorCalendarEventDeclineTransaction 4 + extends PhabricatorCalendarEventReplyTransaction { 5 + 6 + const TRANSACTIONTYPE = 'calendar.decline'; 7 + 8 + public function generateNewValue($object, $value) { 9 + return PhabricatorCalendarEventInvitee::STATUS_DECLINED; 10 + } 11 + 12 + public function getTitle() { 13 + return pht( 14 + '%s declined this event.', 15 + $this->renderAuthor()); 16 + } 17 + 18 + public function getTitleForFeed() { 19 + return pht( 20 + '%s declined %s.', 21 + $this->renderAuthor(), 22 + $this->renderObject()); 23 + } 24 + 25 + }
+42
src/applications/calendar/xaction/PhabricatorCalendarEventDescriptionTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorCalendarEventDescriptionTransaction 4 + extends PhabricatorCalendarEventTransactionType { 5 + 6 + const TRANSACTIONTYPE = 'calendar.description'; 7 + 8 + public function generateOldValue($object) { 9 + return $object->getDescription(); 10 + } 11 + 12 + public function applyInternalEffects($object, $value) { 13 + $object->setDescription($value); 14 + } 15 + 16 + public function getTitle() { 17 + return pht( 18 + '%s updated the event description.', 19 + $this->renderAuthor()); 20 + } 21 + 22 + public function getTitleForFeed() { 23 + return pht( 24 + '%s updated the event description for %s.', 25 + $this->renderAuthor(), 26 + $this->renderObject()); 27 + } 28 + 29 + public function hasChangeDetailView() { 30 + return true; 31 + } 32 + 33 + public function newChangeDetailView() { 34 + $viewer = $this->getViewer(); 35 + 36 + return id(new PhabricatorApplicationTransactionTextDiffDetailView()) 37 + ->setViewer($viewer) 38 + ->setOldText($this->getOldValue()) 39 + ->setNewText($this->getNewValue()); 40 + } 41 + 42 + }
+37
src/applications/calendar/xaction/PhabricatorCalendarEventEndDateTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorCalendarEventEndDateTransaction 4 + extends PhabricatorCalendarEventDateTransaction { 5 + 6 + const TRANSACTIONTYPE = 'calendar.enddate'; 7 + 8 + public function generateOldValue($object) { 9 + return $object->getDateTo(); 10 + } 11 + 12 + public function applyInternalEffects($object, $value) { 13 + $object->setDateTo($value); 14 + } 15 + 16 + public function getTitle() { 17 + return pht( 18 + '%s changed the end date for this event from %s to %s.', 19 + $this->renderAuthor(), 20 + $this->renderOldDate(), 21 + $this->renderNewDate()); 22 + } 23 + 24 + public function getTitleForFeed() { 25 + return pht( 26 + '%s changed the end date for %s from %s to %s.', 27 + $this->renderAuthor(), 28 + $this->renderObject(), 29 + $this->renderOldDate(), 30 + $this->renderNewDate()); 31 + } 32 + 33 + protected function getInvalidDateMessage() { 34 + return pht('End date is invalid.'); 35 + } 36 + 37 + }
+75
src/applications/calendar/xaction/PhabricatorCalendarEventFrequencyTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorCalendarEventFrequencyTransaction 4 + extends PhabricatorCalendarEventTransactionType { 5 + 6 + const TRANSACTIONTYPE = 'calendar.frequency'; 7 + 8 + public function generateOldValue($object) { 9 + return $object->getFrequencyUnit(); 10 + } 11 + 12 + public function applyInternalEffects($object, $value) { 13 + $object->setRecurrenceFrequency( 14 + array( 15 + 'rule' => $value, 16 + )); 17 + } 18 + 19 + public function getTitle() { 20 + $frequency = $this->getFrequencyUnit($this->getNewValue()); 21 + switch ($frequency) { 22 + case PhabricatorCalendarEvent::FREQUENCY_DAILY: 23 + return pht( 24 + '%s set this event to repeat daily.', 25 + $this->renderAuthor()); 26 + case PhabricatorCalendarEvent::FREQUENCY_WEEKLY: 27 + return pht( 28 + '%s set this event to repeat weekly.', 29 + $this->renderAuthor()); 30 + case PhabricatorCalendarEvent::FREQUENCY_MONTHLY: 31 + return pht( 32 + '%s set this event to repeat monthly.', 33 + $this->renderAuthor()); 34 + case PhabricatorCalendarEvent::FREQUENCY_YEARLY: 35 + return pht( 36 + '%s set this event to repeat yearly.', 37 + $this->renderAuthor()); 38 + } 39 + } 40 + 41 + public function getTitleForFeed() { 42 + $frequency = $this->getFrequencyUnit($this->getNewValue()); 43 + switch ($frequency) { 44 + case PhabricatorCalendarEvent::FREQUENCY_DAILY: 45 + return pht( 46 + '%s set %s to repeat daily.', 47 + $this->renderAuthor(), 48 + $this->renderObject()); 49 + case PhabricatorCalendarEvent::FREQUENCY_WEEKLY: 50 + return pht( 51 + '%s set %s to repeat weekly.', 52 + $this->renderAuthor(), 53 + $this->renderObject()); 54 + case PhabricatorCalendarEvent::FREQUENCY_MONTHLY: 55 + return pht( 56 + '%s set %s to repeat monthly.', 57 + $this->renderAuthor(), 58 + $this->renderObject()); 59 + case PhabricatorCalendarEvent::FREQUENCY_YEARLY: 60 + return pht( 61 + '%s set %s to repeat yearly.', 62 + $this->renderAuthor(), 63 + $this->renderObject()); 64 + } 65 + } 66 + 67 + private function getFrequencyUnit($value) { 68 + if (is_array($value)) { 69 + $value = idx($value, 'rule'); 70 + } else { 71 + return $value; 72 + } 73 + } 74 + 75 + }
+44
src/applications/calendar/xaction/PhabricatorCalendarEventIconTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorCalendarEventIconTransaction 4 + extends PhabricatorCalendarEventTransactionType { 5 + 6 + const TRANSACTIONTYPE = 'calendar.icon'; 7 + 8 + public function generateOldValue($object) { 9 + return $object->getIcon(); 10 + } 11 + 12 + public function applyInternalEffects($object, $value) { 13 + $object->setIcon($value); 14 + } 15 + 16 + public function getTitle() { 17 + $old = $this->getIconLabel($this->getOldValue()); 18 + $new = $this->getIconLabel($this->getNewValue()); 19 + 20 + return pht( 21 + '%s changed the event icon from %s to %s.', 22 + $this->renderAuthor(), 23 + $this->renderValue($old), 24 + $this->renderValue($new)); 25 + } 26 + 27 + public function getTitleForFeed() { 28 + $old = $this->getIconLabel($this->getOldValue()); 29 + $new = $this->getIconLabel($this->getNewValue()); 30 + 31 + return pht( 32 + '%s changed the icon for %s from %s to %s.', 33 + $this->renderAuthor(), 34 + $this->renderObject(), 35 + $this->renderValue($old), 36 + $this->renderValue($new)); 37 + } 38 + 39 + private function getIconLabel($icon) { 40 + $set = new PhabricatorCalendarIconSet(); 41 + return $set->getIconLabel($icon); 42 + } 43 + 44 + }
+191
src/applications/calendar/xaction/PhabricatorCalendarEventInviteTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorCalendarEventInviteTransaction 4 + extends PhabricatorCalendarEventTransactionType { 5 + 6 + const TRANSACTIONTYPE = 'calendar.invite'; 7 + 8 + public function generateOldValue($object) { 9 + $status_uninvited = PhabricatorCalendarEventInvitee::STATUS_UNINVITED; 10 + 11 + $invitees = $object->getInvitees(); 12 + foreach ($invitees as $key => $invitee) { 13 + if ($invitee->getStatus() == $status_uninvited) { 14 + unset($invitees[$key]); 15 + } 16 + } 17 + 18 + return mpull($invitees, 'getStatus', 'getInviteePHID'); 19 + } 20 + 21 + public function generateNewValue($object, $value) { 22 + $status_invited = PhabricatorCalendarEventInvitee::STATUS_INVITED; 23 + $status_uninvited = PhabricatorCalendarEventInvitee::STATUS_UNINVITED; 24 + $status_attending = PhabricatorCalendarEventInvitee::STATUS_ATTENDING; 25 + 26 + $invitees = $this->generateOldValue($object); 27 + 28 + $new = array_fuse($value); 29 + 30 + $all = array_keys($invitees + $new); 31 + $map = array(); 32 + foreach ($all as $phid) { 33 + $is_old = isset($invitees[$phid]); 34 + $is_new = isset($new[$phid]); 35 + 36 + if ($is_old && !$is_new) { 37 + $map[$phid] = $status_uninvited; 38 + } else if (!$is_old && $is_new) { 39 + $map[$phid] = $status_invited; 40 + } else { 41 + $map[$phid] = $invitees[$phid]; 42 + } 43 + } 44 + 45 + // If we're creating this event and the actor is inviting themselves, 46 + // mark them as attending. 47 + if ($this->isNewObject()) { 48 + $acting_phid = $this->getActingAsPHID(); 49 + if (isset($map[$acting_phid])) { 50 + $map[$acting_phid] = $status_attending; 51 + } 52 + } 53 + 54 + return $map; 55 + } 56 + 57 + public function applyExternalEffects($object, $value) { 58 + $phids = array_keys($value); 59 + $invitees = $object->getInvitees(); 60 + $invitees = mpull($invitees, null, 'getInviteePHID'); 61 + 62 + foreach ($phids as $phid) { 63 + $invitee = idx($invitees, $phid); 64 + if (!$invitee) { 65 + $invitee = id(new PhabricatorCalendarEventInvitee()) 66 + ->setEventPHID($object->getPHID()) 67 + ->setInviteePHID($phid) 68 + ->setInviterPHID($this->getActingAsPHID()); 69 + $invitees[] = $invitee; 70 + } 71 + $invitee->setStatus($value[$phid]) 72 + ->save(); 73 + } 74 + 75 + $object->attachInvitees($invitees); 76 + } 77 + 78 + public function validateTransactions($object, array $xactions) { 79 + $actor = $this->getActor(); 80 + 81 + $errors = array(); 82 + 83 + $old = $object->getInvitees(); 84 + $old = mpull($old, null, 'getInviteePHID'); 85 + foreach ($xactions as $xaction) { 86 + $new = $xaction->getNewValue(); 87 + $new = array_fuse($new); 88 + $add = array_diff_key($new, $old); 89 + if (!$add) { 90 + continue; 91 + } 92 + 93 + // In the UI, we only allow you to invite mailable objects, but there 94 + // is no definitive marker for "invitable object" today. Just allow 95 + // any valid object to be invited. 96 + $objects = id(new PhabricatorObjectQuery()) 97 + ->setViewer($actor) 98 + ->withPHIDs($add) 99 + ->execute(); 100 + $objects = mpull($objects, null, 'getPHID'); 101 + foreach ($add as $phid) { 102 + if (isset($objects[$phid])) { 103 + continue; 104 + } 105 + 106 + $errors[] = $this->newInvalidError( 107 + pht( 108 + 'Invitee "%s" identifies an object that does not exist or '. 109 + 'which you do not have permission to view.', 110 + $phid), 111 + $xaction); 112 + } 113 + } 114 + 115 + return $errors; 116 + } 117 + 118 + public function getIcon() { 119 + return 'fa-user-plus'; 120 + } 121 + 122 + public function getTitle() { 123 + list($add, $rem) = $this->getChanges(); 124 + 125 + if ($add && !$rem) { 126 + return pht( 127 + '%s invited %s attendee(s): %s.', 128 + $this->renderAuthor(), 129 + phutil_count($add), 130 + $this->renderHandleList($add)); 131 + } else if (!$add && $rem) { 132 + return pht( 133 + '%s uninvited %s attendee(s): %s.', 134 + $this->renderAuthor(), 135 + phutil_count($rem), 136 + $this->renderHandleList($rem)); 137 + } else { 138 + return pht( 139 + '%s invited %s attendee(s): %s; uninvinted %s attendee(s): %s.', 140 + $this->renderAuthor(), 141 + phutil_count($add), 142 + $this->renderHandleList($add), 143 + phutil_count($rem), 144 + $this->renderHandleList($rem)); 145 + } 146 + } 147 + 148 + public function getTitleForFeed() { 149 + list($add, $rem) = $this->getChanges(); 150 + 151 + if ($add && !$rem) { 152 + return pht( 153 + '%s invited %s attendee(s) to %s: %s.', 154 + $this->renderAuthor(), 155 + phutil_count($add), 156 + $this->renderObject(), 157 + $this->renderHandleList($add)); 158 + } else if (!$add && $rem) { 159 + return pht( 160 + '%s uninvited %s attendee(s) to %s: %s.', 161 + $this->renderAuthor(), 162 + phutil_count($rem), 163 + $this->renderObject(), 164 + $this->renderHandleList($rem)); 165 + } else { 166 + return pht( 167 + '%s updated the invite list for %s, invited %s: %s; '. 168 + 'uninvinted %s: %s.', 169 + $this->renderAuthor(), 170 + $this->renderObject(), 171 + phutil_count($add), 172 + $this->renderHandleList($add), 173 + phutil_count($rem), 174 + $this->renderHandleList($rem)); 175 + } 176 + } 177 + 178 + private function getChanges() { 179 + $old = $this->getOldValue(); 180 + $new = $this->getNewValue(); 181 + 182 + $add = array_diff_key($new, $old); 183 + $rem = array_diff_key($old, $new); 184 + 185 + $add = array_keys($add); 186 + $rem = array_keys($rem); 187 + 188 + return array(array_fuse($add), array_fuse($rem)); 189 + } 190 + 191 + }
+44
src/applications/calendar/xaction/PhabricatorCalendarEventNameTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorCalendarEventNameTransaction 4 + extends PhabricatorCalendarEventTransactionType { 5 + 6 + const TRANSACTIONTYPE = 'calendar.name'; 7 + 8 + public function generateOldValue($object) { 9 + return $object->getName(); 10 + } 11 + 12 + public function applyInternalEffects($object, $value) { 13 + $object->setName($value); 14 + } 15 + 16 + public function getTitle() { 17 + return pht( 18 + '%s renamed this event from %s to %s.', 19 + $this->renderAuthor(), 20 + $this->renderOldValue(), 21 + $this->renderNewValue()); 22 + } 23 + 24 + public function getTitleForFeed() { 25 + return pht( 26 + '%s renamed %s from %s to %s.', 27 + $this->renderAuthor(), 28 + $this->renderObject(), 29 + $this->renderOldValue(), 30 + $this->renderNewValue()); 31 + } 32 + 33 + public function validateTransactions($object, array $xactions) { 34 + $errors = array(); 35 + 36 + if ($this->isEmptyTextTransaction($object->getName(), $xactions)) { 37 + $errors[] = $this->newRequiredError( 38 + pht('Events must have a name.')); 39 + } 40 + 41 + return $errors; 42 + } 43 + 44 + }
+44
src/applications/calendar/xaction/PhabricatorCalendarEventRecurringTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorCalendarEventRecurringTransaction 4 + extends PhabricatorCalendarEventTransactionType { 5 + 6 + const TRANSACTIONTYPE = 'calendar.recurring'; 7 + 8 + public function generateOldValue($object) { 9 + return (int)$object->getIsRecurring(); 10 + } 11 + 12 + public function generateNewValue($object, $value) { 13 + return (int)$value; 14 + } 15 + 16 + public function applyInternalEffects($object, $value) { 17 + $object->setIsRecurring($value); 18 + } 19 + 20 + public function validateTransactions($object, array $xactions) { 21 + $errors = array(); 22 + 23 + $old = $object->getIsRecurring(); 24 + foreach ($xactions as $xaction) { 25 + if ($this->getIsNewObject()) { 26 + continue; 27 + } 28 + 29 + if ($xaction->getNewValue() == $old) { 30 + continue; 31 + } 32 + 33 + $errors[] = $this->newInvalidError( 34 + pht( 35 + 'An event can only be made recurring when it is created. '. 36 + 'You can not convert an existing event into a recurring '. 37 + 'event or vice versa.'), 38 + $xaction); 39 + } 40 + 41 + return $errors; 42 + } 43 + 44 + }
+33
src/applications/calendar/xaction/PhabricatorCalendarEventReplyTransaction.php
··· 1 + <?php 2 + 3 + abstract class PhabricatorCalendarEventReplyTransaction 4 + extends PhabricatorCalendarEventTransactionType { 5 + 6 + public function generateOldValue($object) { 7 + $actor_phid = $this->getActingAsPHID(); 8 + return $object->getUserInviteStatus($actor_phid); 9 + } 10 + 11 + public function applyExternalEffects($object, $value) { 12 + $acting_phid = $this->getActingAsPHID(); 13 + 14 + $invitees = $object->getInvitees(); 15 + $invitees = mpull($invitees, null, 'getInviteePHID'); 16 + 17 + $invitee = idx($invitees, $acting_phid); 18 + if (!$invitee) { 19 + $invitee = id(new PhabricatorCalendarEventInvitee()) 20 + ->setEventPHID($object->getPHID()) 21 + ->setInviteePHID($acting_phid) 22 + ->setInviterPHID($acting_phid); 23 + $invitees[$acting_phid] = $invitee; 24 + } 25 + 26 + $invitee 27 + ->setStatus($value) 28 + ->save(); 29 + 30 + $object->attachInvitees($invitees); 31 + } 32 + 33 + }
+37
src/applications/calendar/xaction/PhabricatorCalendarEventStartDateTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorCalendarEventStartDateTransaction 4 + extends PhabricatorCalendarEventDateTransaction { 5 + 6 + const TRANSACTIONTYPE = 'calendar.startdate'; 7 + 8 + public function generateOldValue($object) { 9 + return $object->getDateFrom(); 10 + } 11 + 12 + public function applyInternalEffects($object, $value) { 13 + $object->setDateFrom($value); 14 + } 15 + 16 + public function getTitle() { 17 + return pht( 18 + '%s changed the start date for this event from %s to %s.', 19 + $this->renderAuthor(), 20 + $this->renderOldDate(), 21 + $this->renderNewDate()); 22 + } 23 + 24 + public function getTitleForFeed() { 25 + return pht( 26 + '%s changed the start date for %s from %s to %s.', 27 + $this->renderAuthor(), 28 + $this->renderObject(), 29 + $this->renderOldDate(), 30 + $this->renderNewDate()); 31 + } 32 + 33 + protected function getInvalidDateMessage() { 34 + return pht('Start date is invalid.'); 35 + } 36 + 37 + }
+4
src/applications/calendar/xaction/PhabricatorCalendarEventTransactionType.php
··· 1 + <?php 2 + 3 + abstract class PhabricatorCalendarEventTransactionType 4 + extends PhabricatorModularTransactionType {}
+35
src/applications/calendar/xaction/PhabricatorCalendarEventUntilDateTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorCalendarEventUntilDateTransaction 4 + extends PhabricatorCalendarEventDateTransaction { 5 + 6 + const TRANSACTIONTYPE = 'calendar.recurrenceenddate'; 7 + 8 + public function generateOldValue($object) { 9 + return $object->getRecurrenceEndDate(); 10 + } 11 + 12 + public function applyInternalEffects($object, $value) { 13 + $object->setRecurrenceEndDate($value); 14 + } 15 + 16 + public function getTitle() { 17 + return pht( 18 + '%s changed this event to repeat until %s.', 19 + $this->renderAuthor(), 20 + $this->renderNewDate()); 21 + } 22 + 23 + public function getTitleForFeed() { 24 + return pht( 25 + '%s changed %s to repeat until %s.', 26 + $this->renderAuthor(), 27 + $this->renderObject(), 28 + $this->renderNewDate()); 29 + } 30 + 31 + protected function getInvalidDateMessage() { 32 + return pht('Repeat until date is invalid.'); 33 + } 34 + 35 + }
+13 -3
src/applications/phid/view/PHUIHandleListView.php
··· 12 12 13 13 private $handleList; 14 14 private $asInline; 15 + private $asText; 15 16 16 17 public function setHandleList(PhabricatorHandleList $list) { 17 18 $this->handleList = $list; ··· 27 28 return $this->asInline; 28 29 } 29 30 31 + public function setAsText($as_text) { 32 + $this->asText = $as_text; 33 + return $this; 34 + } 35 + 36 + public function getAsText() { 37 + return $this->asText; 38 + } 39 + 30 40 protected function getTagName() { 31 41 // TODO: It would be nice to render this with a proper <ul />, at least in 32 42 // block mode, but don't stir the waters up too much for now. ··· 37 47 $list = $this->handleList; 38 48 $items = array(); 39 49 foreach ($list as $handle) { 40 - $view = $list->renderHandle($handle->getPHID()); 41 - 42 - $view->setShowHovercard(true); 50 + $view = $list->renderHandle($handle->getPHID()) 51 + ->setShowHovercard(true) 52 + ->setAsText($this->getAsText()); 43 53 44 54 $items[] = $view; 45 55 }
+69
src/applications/transactions/storage/PhabricatorModularTransactionType.php
··· 86 86 return $this->viewer; 87 87 } 88 88 89 + final public function getActor() { 90 + return $this->getEditor()->getActor(); 91 + } 92 + 93 + final public function getActingAsPHID() { 94 + return $this->getEditor()->getActingAsPHID(); 95 + } 96 + 89 97 final public function setEditor( 90 98 PhabricatorApplicationTransactionEditor $editor) { 91 99 $this->editor = $editor; ··· 141 149 return $display; 142 150 } 143 151 152 + final protected function renderHandleList(array $phids) { 153 + $viewer = $this->getViewer(); 154 + $display = $viewer->renderHandleList($phids) 155 + ->setAsInline(true); 156 + 157 + $rendering_target = $this->getStorage()->getRenderingTarget(); 158 + if ($rendering_target == PhabricatorApplicationTransaction::TARGET_TEXT) { 159 + $display->setAsText(true); 160 + } 161 + 162 + return $display; 163 + } 164 + 144 165 final protected function renderValue($value) { 145 166 $rendering_target = $this->getStorage()->getRenderingTarget(); 146 167 if ($rendering_target == PhabricatorApplicationTransaction::TARGET_TEXT) { ··· 155 176 $value); 156 177 } 157 178 179 + final protected function renderOldValue() { 180 + return $this->renderValue($this->getOldValue()); 181 + } 182 + 183 + final protected function renderNewValue() { 184 + return $this->renderValue($this->getNewValue()); 185 + } 186 + 187 + final protected function renderDate($epoch) { 188 + $viewer = $this->getViewer(); 189 + 190 + $display = phabricator_datetime($epoch, $viewer); 191 + 192 + // TODO: When rendering for email, include the UTC offset. See T10633. 193 + 194 + return $this->renderValue($display); 195 + } 196 + 197 + final protected function renderOldDate() { 198 + return $this->renderDate($this->getOldValue()); 199 + } 200 + 201 + final protected function renderNewDate() { 202 + return $this->renderDate($this->getNewValue()); 203 + } 204 + 158 205 final protected function newError($title, $message, $xaction = null) { 159 206 return new PhabricatorApplicationTransactionValidationError( 160 207 $this->getTransactionTypeConstant(), ··· 162 209 $message, 163 210 $xaction); 164 211 } 212 + 213 + final protected function newRequiredError($message, $xaction = null) { 214 + return $this->newError(pht('Required'), $message, $xaction) 215 + ->setIsMissingFieldError(true); 216 + } 217 + 218 + final protected function newInvalidError($message, $xaction = null) { 219 + return $this->newError(pht('Invalid'), $message, $xaction); 220 + } 221 + 222 + final protected function isNewObject() { 223 + return $this->getEditor()->getIsNewObject(); 224 + } 225 + 226 + final protected function isEmptyTextTransaction($value, array $xactions) { 227 + foreach ($xactions as $xaction) { 228 + $value = $xaction->getNewValue(); 229 + } 230 + 231 + return !strlen($value); 232 + } 233 + 165 234 166 235 }
+18
src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php
··· 1560 1560 ), 1561 1561 ), 1562 1562 ), 1563 + 1564 + '%s invited %s attendee(s): %s.' => 1565 + '%s invited: %3$s.', 1566 + 1567 + '%s uninvited %s attendee(s): %s.' => 1568 + '%s uninvited: %3$s.', 1569 + 1570 + '%s invited %s attendee(s): %s; uninvinted %s attendee(s): %s.' => 1571 + '%s invited: %3$s; uninvited: %5$s.', 1572 + 1573 + '%s invited %s attendee(s) to %s: %s.' => 1574 + '%s added invites for %3$s: %4$s.', 1575 + 1576 + '%s uninvited %s attendee(s) to %s: %s.' => 1577 + '%s removed invites for %3$s: %4$s.', 1578 + 1579 + '%s updated the invite list for %s, invited %s: %s; uninvinted %s: %s.' => 1580 + '%s updated the invite list for %s, invited: %4$s; uninvited: %6$s.', 1563 1581 ); 1564 1582 } 1565 1583