@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.

Users should be able to rsvp to event via email

Summary: Closes T7957, Users should be able to rsvp to event via email.

Test Plan: Create event, open invitee email, reply to email w/ !rsvp yes, refresh event, invitee should show as attending.

Reviewers: epriestley, #blessed_reviewers

Reviewed By: epriestley, #blessed_reviewers

Subscribers: Korvin, epriestley

Maniphest Tasks: T7957

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

+148 -14
+4
src/__phutil_library_map__.php
··· 1498 1498 'PhabricatorCalendarEventCommentController' => 'applications/calendar/controller/PhabricatorCalendarEventCommentController.php', 1499 1499 'PhabricatorCalendarEventEditController' => 'applications/calendar/controller/PhabricatorCalendarEventEditController.php', 1500 1500 'PhabricatorCalendarEventEditor' => 'applications/calendar/editor/PhabricatorCalendarEventEditor.php', 1501 + 'PhabricatorCalendarEventEmailCommand' => 'applications/calendar/command/PhabricatorCalendarEventEmailCommand.php', 1501 1502 'PhabricatorCalendarEventInvalidEpochException' => 'applications/calendar/exception/PhabricatorCalendarEventInvalidEpochException.php', 1502 1503 'PhabricatorCalendarEventInvitee' => 'applications/calendar/storage/PhabricatorCalendarEventInvitee.php', 1503 1504 'PhabricatorCalendarEventInviteeQuery' => 'applications/calendar/query/PhabricatorCalendarEventInviteeQuery.php', ··· 1506 1507 'PhabricatorCalendarEventMailReceiver' => 'applications/calendar/mail/PhabricatorCalendarEventMailReceiver.php', 1507 1508 'PhabricatorCalendarEventPHIDType' => 'applications/calendar/phid/PhabricatorCalendarEventPHIDType.php', 1508 1509 'PhabricatorCalendarEventQuery' => 'applications/calendar/query/PhabricatorCalendarEventQuery.php', 1510 + 'PhabricatorCalendarEventRSVPEmailCommand' => 'applications/calendar/command/PhabricatorCalendarEventRSVPEmailCommand.php', 1509 1511 'PhabricatorCalendarEventSearchEngine' => 'applications/calendar/query/PhabricatorCalendarEventSearchEngine.php', 1510 1512 'PhabricatorCalendarEventSearchIndexer' => 'applications/calendar/search/PhabricatorCalendarEventSearchIndexer.php', 1511 1513 'PhabricatorCalendarEventTransaction' => 'applications/calendar/storage/PhabricatorCalendarEventTransaction.php', ··· 4848 4850 'PhabricatorCalendarEventCommentController' => 'PhabricatorCalendarController', 4849 4851 'PhabricatorCalendarEventEditController' => 'PhabricatorCalendarController', 4850 4852 'PhabricatorCalendarEventEditor' => 'PhabricatorApplicationTransactionEditor', 4853 + 'PhabricatorCalendarEventEmailCommand' => 'MetaMTAEmailTransactionCommand', 4851 4854 'PhabricatorCalendarEventInvalidEpochException' => 'Exception', 4852 4855 'PhabricatorCalendarEventInvitee' => array( 4853 4856 'PhabricatorCalendarDAO', ··· 4859 4862 'PhabricatorCalendarEventMailReceiver' => 'PhabricatorObjectMailReceiver', 4860 4863 'PhabricatorCalendarEventPHIDType' => 'PhabricatorPHIDType', 4861 4864 'PhabricatorCalendarEventQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 4865 + 'PhabricatorCalendarEventRSVPEmailCommand' => 'PhabricatorCalendarEventEmailCommand', 4862 4866 'PhabricatorCalendarEventSearchEngine' => 'PhabricatorApplicationSearchEngine', 4863 4867 'PhabricatorCalendarEventSearchIndexer' => 'PhabricatorSearchDocumentIndexer', 4864 4868 'PhabricatorCalendarEventTransaction' => 'PhabricatorApplicationTransaction',
+11
src/applications/calendar/command/PhabricatorCalendarEventEmailCommand.php
··· 1 + <?php 2 + 3 + abstract class PhabricatorCalendarEventEmailCommand 4 + extends MetaMTAEmailTransactionCommand { 5 + 6 + public function isCommandSupportedForObject( 7 + PhabricatorApplicationTransactionInterface $object) { 8 + return ($object instanceof PhabricatorCalendarEvent); 9 + } 10 + 11 + }
+124
src/applications/calendar/command/PhabricatorCalendarEventRSVPEmailCommand.php
··· 1 + <?php 2 + 3 + final class PhabricatorCalendarEventRSVPEmailCommand 4 + extends PhabricatorCalendarEventEmailCommand { 5 + 6 + public function getCommand() { 7 + return 'rsvp'; 8 + } 9 + 10 + public function getCommandSyntax() { 11 + return '**!rsvp** //rsvp//'; 12 + } 13 + 14 + public function getCommandSummary() { 15 + return pht('RSVP to event.'); 16 + } 17 + 18 + public function getCommandDescription() { 19 + $status_attending = PhabricatorCalendarEventInvitee::STATUS_ATTENDING; 20 + $status_declined = PhabricatorCalendarEventInvitee::STATUS_DECLINED; 21 + 22 + $yes_values = implode(', ', $this->getYesValues()); 23 + $no_values = implode(', ', $this->getNoValues()); 24 + 25 + $table = array(); 26 + $table[] = '| '.pht('RSVP').' | '.pht('Keywords'); 27 + $table[] = '|---|---|'; 28 + $table[] = '| '.$status_attending.' | '.$yes_values; 29 + $table[] = '| '.$status_declined.' | '.$no_values; 30 + $table = implode("\n", $table); 31 + 32 + return pht( 33 + 'To RSVP to the event, specify the desired RSVP, like '. 34 + '`!rsvp yes`. This table shows the configured names for rsvp\'s.'. 35 + "\n\n%s\n\n". 36 + 'If you specify an invalid rsvp, the command is ignored. This '. 37 + 'command has no effect if you do not specify an rsvp.', 38 + $table); 39 + } 40 + 41 + public function buildTransactions( 42 + PhabricatorUser $viewer, 43 + PhabricatorApplicationTransactionInterface $object, 44 + PhabricatorMetaMTAReceivedMail $mail, 45 + $command, 46 + array $argv) { 47 + $status_attending = PhabricatorCalendarEventInvitee::STATUS_ATTENDING; 48 + $status_declined = PhabricatorCalendarEventInvitee::STATUS_DECLINED; 49 + $xactions = array(); 50 + 51 + $target = phutil_utf8_strtolower(implode(' ', $argv)); 52 + $rsvp = null; 53 + 54 + $yes_values = $this->getYesValues(); 55 + $no_values = $this->getNoValues(); 56 + 57 + if (in_array($target, $yes_values)) { 58 + $rsvp = $status_attending; 59 + } else if (in_array($target, $no_values)) { 60 + $rsvp = $status_declined; 61 + } else { 62 + $rsvp = null; 63 + } 64 + 65 + if ($rsvp === null) { 66 + return array(); 67 + } 68 + 69 + $xactions[] = $object->getApplicationTransactionTemplate() 70 + ->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_INVITE) 71 + ->setNewValue(array($viewer->getPHID() => $rsvp)); 72 + 73 + return $xactions; 74 + } 75 + 76 + private function getYesValues() { 77 + return array( 78 + 'yes', 79 + 'yep', 80 + 'sounds good', 81 + 'going', 82 + 'attending', 83 + 'will be there', 84 + 'sure', 85 + 'accept', 86 + 'ya', 87 + 'yeah', 88 + 'yuh', 89 + 'uhuh', 90 + 'ok', 91 + 'okay', 92 + 'yiss', 93 + 'aww yiss', 94 + 'attend', 95 + 'intend to attend', 96 + 'confirm', 97 + 'confirmed', 98 + 'bringing dessert', 99 + 'bringing desert', 100 + 'time2business', 101 + 'time4business', 102 + ); 103 + } 104 + 105 + private function getNoValues() { 106 + return array( 107 + 'no', 108 + 'nope', 109 + 'no thank you', 110 + 'next time', 111 + 'nah', 112 + 'nuh', 113 + 'huh', 114 + 'wut', 115 + 'no way', 116 + 'nuhuh', 117 + 'decline', 118 + 'declined', 119 + 'leave', 120 + 'cancel', 121 + ); 122 + } 123 + 124 + }
+8 -12
src/applications/calendar/editor/PhabricatorCalendarEventEditor.php
··· 147 147 case PhabricatorCalendarEventTransaction::TYPE_INVITE: 148 148 $map = $xaction->getNewValue(); 149 149 $phids = array_keys($map); 150 - $invitees = array(); 151 - 152 - if ($map) { 153 - $invitees = id(new PhabricatorCalendarEventInviteeQuery()) 154 - ->setViewer($this->getActor()) 155 - ->withEventPHIDs(array($object->getPHID())) 156 - ->withInviteePHIDs($phids) 157 - ->execute(); 158 - $invitees = mpull($invitees, null, 'getInviteePHID'); 159 - } 150 + $invitees = $object->getInvitees(); 151 + $invitees = mpull($invitees, null, 'getInviteePHID'); 160 152 161 153 foreach ($phids as $phid) { 162 154 $invitee = idx($invitees, $phid); ··· 165 157 ->setEventPHID($object->getPHID()) 166 158 ->setInviteePHID($phid) 167 159 ->setInviterPHID($this->getActingAsPHID()); 160 + $invitees[] = $invitee; 168 161 } 169 162 $invitee->setStatus($map[$phid]) 170 163 ->save(); 171 164 } 165 + $object->attachInvitees($invitees); 172 166 return; 173 167 case PhabricatorTransactions::TYPE_COMMENT: 174 168 case PhabricatorTransactions::TYPE_VIEW_POLICY: ··· 254 248 $phids[] = $this->getActingAsPHID(); 255 249 256 250 $invitees = $object->getInvitees(); 257 - foreach ($invitees as $phid => $status) { 251 + foreach ($invitees as $invitee) { 252 + $status = $invitee->getStatus(); 258 253 if ($status === PhabricatorCalendarEventInvitee::STATUS_ATTENDING 259 254 || $status === PhabricatorCalendarEventInvitee::STATUS_INVITED) { 260 - $phids[] = $phid; 255 + $phids[] = $invitee->getInviteePHID(); 261 256 } 262 257 } 263 258 264 259 $phids = array_unique($phids); 260 + 265 261 return $phids; 266 262 } 267 263
+1 -1
src/applications/calendar/storage/PhabricatorCalendarEvent.php
··· 42 42 } 43 43 44 44 public function save() { 45 - if ($this->getDateTo() <= $this->getDateFrom()) { 45 + if ($this->getDateTo() < $this->getDateFrom()) { 46 46 throw new PhabricatorCalendarEventInvalidEpochException(); 47 47 } 48 48
-1
src/applications/calendar/storage/PhabricatorCalendarEventTransaction.php
··· 11 11 const TYPE_CANCEL = 'calendar.cancel'; 12 12 const TYPE_INVITE = 'calendar.invite'; 13 13 14 - 15 14 const MAILTAG_RESCHEDULE = 'calendar-reschedule'; 16 15 const MAILTAG_CONTENT = 'calendar-content'; 17 16 const MAILTAG_OTHER = 'calendar-other';