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

Calendar events should now auto-invite the creator

Summary: Closes T7935, Calendar events should now auto-invite the creator.

Test Plan: Create event, save, event should now show creator as an invitee.

Reviewers: epriestley, #blessed_reviewers

Reviewed By: epriestley, #blessed_reviewers

Subscribers: Korvin, epriestley

Maniphest Tasks: T7935

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

+314 -2
+11
resources/sql/autopatches/20150429.calendar.1.invitee.sql
··· 1 + CREATE TABLE {$NAMESPACE}_calendar.`calendar_eventinvitee` ( 2 + `id` int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, 3 + `eventPHID` varbinary(64) NOT NULL, 4 + `inviteePHID` varbinary(64) NOT NULL, 5 + `inviterPHID` varbinary(64) NOT NULL, 6 + `status` VARCHAR(64) COLLATE {$COLLATE_TEXT} NOT NULL, 7 + `dateCreated` int(10) unsigned NOT NULL, 8 + `dateModified` int(10) unsigned NOT NULL, 9 + UNIQUE KEY `key_event` (`eventPHID`, `inviteePHID`), 10 + KEY `key_invitee` (`inviteePHID`) 11 + ) ENGINE=InnoDB COLLATE {$COLLATE_TEXT};
+7
src/__phutil_library_map__.php
··· 1486 1486 'PhabricatorCalendarEventEditController' => 'applications/calendar/controller/PhabricatorCalendarEventEditController.php', 1487 1487 'PhabricatorCalendarEventEditor' => 'applications/calendar/editor/PhabricatorCalendarEventEditor.php', 1488 1488 'PhabricatorCalendarEventInvalidEpochException' => 'applications/calendar/exception/PhabricatorCalendarEventInvalidEpochException.php', 1489 + 'PhabricatorCalendarEventInvitee' => 'applications/calendar/storage/PhabricatorCalendarEventInvitee.php', 1490 + 'PhabricatorCalendarEventInviteeQuery' => 'applications/calendar/query/PhabricatorCalendarEventInviteeQuery.php', 1489 1491 'PhabricatorCalendarEventListController' => 'applications/calendar/controller/PhabricatorCalendarEventListController.php', 1490 1492 'PhabricatorCalendarEventPHIDType' => 'applications/calendar/phid/PhabricatorCalendarEventPHIDType.php', 1491 1493 'PhabricatorCalendarEventQuery' => 'applications/calendar/query/PhabricatorCalendarEventQuery.php', ··· 4817 4819 'PhabricatorCalendarEventEditController' => 'PhabricatorCalendarController', 4818 4820 'PhabricatorCalendarEventEditor' => 'PhabricatorApplicationTransactionEditor', 4819 4821 'PhabricatorCalendarEventInvalidEpochException' => 'Exception', 4822 + 'PhabricatorCalendarEventInvitee' => array( 4823 + 'PhabricatorCalendarDAO', 4824 + 'PhabricatorPolicyInterface', 4825 + ), 4826 + 'PhabricatorCalendarEventInviteeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 4820 4827 'PhabricatorCalendarEventListController' => 'PhabricatorCalendarController', 4821 4828 'PhabricatorCalendarEventPHIDType' => 'PhabricatorPHIDType', 4822 4829 'PhabricatorCalendarEventQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
+13 -1
src/applications/calendar/controller/PhabricatorCalendarEventEditController.php
··· 16 16 public function processRequest() { 17 17 $request = $this->getRequest(); 18 18 $user = $request->getUser(); 19 + $user_phid = $user->getPHID(); 19 20 $error_name = true; 20 21 $validation_exception = null; 22 + $invitees = null; 21 23 22 24 $start_time = id(new AphrontFormDateControl()) 23 25 ->setUser($user) ··· 40 42 $page_title = pht('Create Event'); 41 43 $redirect = 'created'; 42 44 $subscribers = array(); 45 + $invitees = array( 46 + $user_phid => PhabricatorCalendarEventInvitee::STATUS_ATTENDING, 47 + ); 43 48 } else { 44 49 $event = id(new PhabricatorCalendarEventQuery()) 45 50 ->setViewer($user) ··· 112 117 PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION) 113 118 ->setNewValue($description); 114 119 120 + if ($invitees) { 121 + $xactions[] = id(new PhabricatorCalendarEventTransaction()) 122 + ->setTransactionType( 123 + PhabricatorCalendarEventTransaction::TYPE_INVITE) 124 + ->setNewValue($invitees); 125 + } 126 + 127 + 115 128 $editor = id(new PhabricatorCalendarEventEditor()) 116 129 ->setActor($user) 117 130 ->setContentSourceFromRequest($request) ··· 159 172 ->setValue($subscribers) 160 173 ->setUser($user) 161 174 ->setDatasource(new PhabricatorMetaMTAMailableDatasource()); 162 - 163 175 164 176 $form = id(new AphrontFormView()) 165 177 ->setUser($user)
+14
src/applications/calendar/controller/PhabricatorCalendarEventViewController.php
··· 127 127 pht('Ends'), 128 128 phabricator_datetime($event->getDateTo(), $viewer)); 129 129 130 + $invitees = $event->getInvitees(); 131 + $invitee_list = new PHUIStatusListView(); 132 + foreach ($invitees as $invitee) { 133 + $item = new PHUIStatusItemView(); 134 + $invitee_phid = $invitee->getInviteePHID(); 135 + $target = $viewer->renderHandle($invitee_phid); 136 + $item->setTarget($target); 137 + $invitee_list->addItem($item); 138 + } 139 + 140 + $properties->addProperty( 141 + pht('Invitees'), 142 + $invitee_list); 143 + 130 144 $properties->invokeWillRenderEvent(); 131 145 132 146 $properties->addSectionHeader(
+54 -1
src/applications/calendar/editor/PhabricatorCalendarEventEditor.php
··· 20 20 $types[] = PhabricatorCalendarEventTransaction::TYPE_STATUS; 21 21 $types[] = PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION; 22 22 $types[] = PhabricatorCalendarEventTransaction::TYPE_CANCEL; 23 + $types[] = PhabricatorCalendarEventTransaction::TYPE_INVITE; 23 24 24 25 $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; 25 26 $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; ··· 47 48 return $object->getDescription(); 48 49 case PhabricatorCalendarEventTransaction::TYPE_CANCEL: 49 50 return $object->getIsCancelled(); 51 + case PhabricatorCalendarEventTransaction::TYPE_INVITE: 52 + $map = $xaction->getNewValue(); 53 + $phids = array_keys($map); 54 + $invitees = array(); 55 + 56 + if ($map && !$this->getIsNewObject()) { 57 + $invitees = id(new PhabricatorCalendarEventInviteeQuery()) 58 + ->setViewer($this->getActor()) 59 + ->withEventPHIDs(array($object->getPHID())) 60 + ->withInviteePHIDs($phids) 61 + ->execute(); 62 + $invitees = mpull($invitees, null, 'getInviteePHID'); 63 + } 64 + 65 + $old = array(); 66 + foreach ($phids as $phid) { 67 + $invitee = idx($invitees, $phid); 68 + if ($invitee) { 69 + $old[$phid] = $invitee->getStatus(); 70 + } else { 71 + $old[$phid] = PhabricatorCalendarEventInvitee::STATUS_UNINVITED; 72 + } 73 + } 74 + return $old; 50 75 } 51 76 52 77 return parent::getCustomTransactionOldValue($object, $xaction); ··· 55 80 protected function getCustomTransactionNewValue( 56 81 PhabricatorLiskDAO $object, 57 82 PhabricatorApplicationTransaction $xaction) { 58 - 59 83 switch ($xaction->getTransactionType()) { 60 84 case PhabricatorCalendarEventTransaction::TYPE_NAME: 61 85 case PhabricatorCalendarEventTransaction::TYPE_START_DATE: 62 86 case PhabricatorCalendarEventTransaction::TYPE_END_DATE: 63 87 case PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION: 64 88 case PhabricatorCalendarEventTransaction::TYPE_CANCEL: 89 + case PhabricatorCalendarEventTransaction::TYPE_INVITE: 65 90 return $xaction->getNewValue(); 66 91 case PhabricatorCalendarEventTransaction::TYPE_STATUS: 67 92 return (int)$xaction->getNewValue(); ··· 93 118 case PhabricatorCalendarEventTransaction::TYPE_CANCEL: 94 119 $object->setIsCancelled((int)$xaction->getNewValue()); 95 120 return; 121 + case PhabricatorCalendarEventTransaction::TYPE_INVITE: 96 122 case PhabricatorTransactions::TYPE_VIEW_POLICY: 97 123 case PhabricatorTransactions::TYPE_EDIT_POLICY: 98 124 case PhabricatorTransactions::TYPE_EDGE: ··· 114 140 case PhabricatorCalendarEventTransaction::TYPE_STATUS: 115 141 case PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION: 116 142 case PhabricatorCalendarEventTransaction::TYPE_CANCEL: 143 + return; 144 + case PhabricatorCalendarEventTransaction::TYPE_INVITE: 145 + $map = $xaction->getNewValue(); 146 + $phids = array_keys($map); 147 + $invitees = array(); 148 + 149 + if ($map) { 150 + $invitees = id(new PhabricatorCalendarEventInviteeQuery()) 151 + ->setViewer($this->getActor()) 152 + ->withEventPHIDs(array($object->getPHID())) 153 + ->withInviteePHIDs($phids) 154 + ->execute(); 155 + $invitees = mpull($invitees, null, 'getInviteePHID'); 156 + } 157 + 158 + foreach ($phids as $phid) { 159 + $invitee = idx($invitees, $phid); 160 + if (!$invitee) { 161 + $invitee = id(new PhabricatorCalendarEventInvitee()) 162 + ->setEventPHID($object->getPHID()) 163 + ->setInviteePHID($phid) 164 + ->setInviterPHID($this->getActingAsPHID()); 165 + } 166 + $invitee->setStatus($map[$phid]) 167 + ->save(); 168 + } 169 + return; 117 170 case PhabricatorTransactions::TYPE_VIEW_POLICY: 118 171 case PhabricatorTransactions::TYPE_EDIT_POLICY: 119 172 case PhabricatorTransactions::TYPE_EDGE:
+99
src/applications/calendar/query/PhabricatorCalendarEventInviteeQuery.php
··· 1 + <?php 2 + 3 + final class PhabricatorCalendarEventInviteeQuery 4 + extends PhabricatorCursorPagedPolicyAwareQuery { 5 + 6 + private $ids; 7 + private $eventPHIDs; 8 + private $inviteePHIDs; 9 + private $inviterPHIDs; 10 + private $statuses; 11 + 12 + public function withIDs(array $ids) { 13 + $this->ids = $ids; 14 + return $this; 15 + } 16 + 17 + public function withEventPHIDs(array $phids) { 18 + $this->eventPHIDs = $phids; 19 + return $this; 20 + } 21 + 22 + public function withInviteePHIDs(array $phids) { 23 + $this->inviteePHIDs = $phids; 24 + return $this; 25 + } 26 + 27 + public function withInviterPHIDs(array $phids) { 28 + $this->inviterPHIDs = $phids; 29 + return $this; 30 + } 31 + 32 + public function withStatuses(array $statuses) { 33 + $this->statuses = $statuses; 34 + return $this; 35 + } 36 + 37 + protected function loadPage() { 38 + $table = new PhabricatorCalendarEventInvitee(); 39 + $conn_r = $table->establishConnection('r'); 40 + 41 + $data = queryfx_all( 42 + $conn_r, 43 + 'SELECT * FROM %T %Q %Q %Q', 44 + $table->getTableName(), 45 + $this->buildWhereClause($conn_r), 46 + $this->buildOrderClause($conn_r), 47 + $this->buildLimitClause($conn_r)); 48 + 49 + return $table->loadAllFromArray($data); 50 + } 51 + 52 + protected function buildWhereClause(AphrontDatabaseConnection $conn_r) { 53 + $where = array(); 54 + 55 + if ($this->ids !== null) { 56 + $where[] = qsprintf( 57 + $conn_r, 58 + 'id IN (%Ld)', 59 + $this->ids); 60 + } 61 + 62 + if ($this->eventPHIDs) { 63 + $where[] = qsprintf( 64 + $conn_r, 65 + 'eventPHID IN (%Ls)', 66 + $this->eventPHIDs); 67 + } 68 + 69 + if ($this->inviteePHIDs) { 70 + $where[] = qsprintf( 71 + $conn_r, 72 + 'inviteePHID IN (%Ls)', 73 + $this->inviteePHIDs); 74 + } 75 + 76 + if ($this->inviterPHIDs) { 77 + $where[] = qsprintf( 78 + $conn_r, 79 + 'inviterPHID IN (%Ls)', 80 + $this->inviterPHIDs); 81 + } 82 + 83 + if ($this->statuses) { 84 + $where[] = qsprintf( 85 + $conn_r, 86 + 'status = %d', 87 + $this->statuses); 88 + } 89 + 90 + $where[] = $this->buildPagingClause($conn_r); 91 + 92 + return $this->formatWhereClause($where); 93 + } 94 + 95 + public function getQueryApplicationClass() { 96 + return 'PhabricatorCalendarApplication'; 97 + } 98 + 99 + }
+22
src/applications/calendar/query/PhabricatorCalendarEventQuery.php
··· 121 121 return 'PhabricatorCalendarApplication'; 122 122 } 123 123 124 + 125 + protected function willFilterPage(array $events) { 126 + $phids = array(); 127 + 128 + foreach ($events as $event) { 129 + $phids[] = $event->getPHID(); 130 + } 131 + 132 + $invitees = id(new PhabricatorCalendarEventInviteeQuery()) 133 + ->setViewer($this->getViewer()) 134 + ->withEventPHIDs($phids) 135 + ->execute(); 136 + $invitees = mgroup($invitees, 'getEventPHID'); 137 + 138 + foreach ($events as $event) { 139 + $event_invitees = idx($invitees, $event->getPHID(), array()); 140 + $event->attachInvitees($event_invitees); 141 + } 142 + 143 + return $events; 144 + } 145 + 124 146 }
+11
src/applications/calendar/storage/PhabricatorCalendarEvent.php
··· 18 18 protected $description; 19 19 protected $isCancelled; 20 20 21 + private $invitees = self::ATTACHABLE; 22 + 21 23 const STATUS_AWAY = 1; 22 24 const STATUS_SPORADIC = 2; 23 25 ··· 116 118 $user_phids); 117 119 118 120 return mpull($statuses, null, 'getUserPHID'); 121 + } 122 + 123 + public function getInvitees() { 124 + return $this->assertAttached($this->invitees); 125 + } 126 + 127 + public function attachInvitees(array $invitees) { 128 + $this->invitees = $invitees; 129 + return $this; 119 130 } 120 131 121 132 /**
+64
src/applications/calendar/storage/PhabricatorCalendarEventInvitee.php
··· 1 + <?php 2 + 3 + final class PhabricatorCalendarEventInvitee extends PhabricatorCalendarDAO 4 + implements PhabricatorPolicyInterface { 5 + 6 + protected $eventPHID; 7 + protected $inviteePHID; 8 + protected $inviterPHID; 9 + protected $status; 10 + 11 + const STATUS_INVITED = 'invited'; 12 + const STATUS_ATTENDING = 'attending'; 13 + const STATUS_DECLINED = 'declined'; 14 + const STATUS_UNINVITED = 'uninvited'; 15 + 16 + public static function initializeNewCalendarEventInvitee( 17 + PhabricatorUser $actor, $event) { 18 + return id(new PhabricatorCalendarEventInvitee()) 19 + ->setInviterPHID($actor->getPHID()) 20 + ->setStatus(self::STATUS_INVITED) 21 + ->setEventPHID($event->getPHID()); 22 + } 23 + 24 + protected function getConfiguration() { 25 + return array( 26 + self::CONFIG_COLUMN_SCHEMA => array( 27 + 'status' => 'text64', 28 + ), 29 + self::CONFIG_KEY_SCHEMA => array( 30 + 'key_event' => array( 31 + 'columns' => array('eventPHID', 'inviteePHID'), 32 + 'unique' => true, 33 + ), 34 + 'key_invitee' => array( 35 + 'columns' => array('inviteePHID'), 36 + ), 37 + ), 38 + ) + parent::getConfiguration(); 39 + } 40 + 41 + /* -( PhabricatorPolicyInterface )----------------------------------------- */ 42 + 43 + 44 + public function getCapabilities() { 45 + return array( 46 + PhabricatorPolicyCapability::CAN_VIEW, 47 + ); 48 + } 49 + 50 + public function getPolicy($capability) { 51 + switch ($capability) { 52 + case PhabricatorPolicyCapability::CAN_VIEW: 53 + return PhabricatorPolicies::getMostOpenPolicy(); 54 + } 55 + } 56 + 57 + public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { 58 + return false; 59 + } 60 + 61 + public function describeAutomaticCapability($capability) { 62 + return null; 63 + } 64 + }
+19
src/applications/calendar/storage/PhabricatorCalendarEventTransaction.php
··· 9 9 const TYPE_STATUS = 'calendar.status'; 10 10 const TYPE_DESCRIPTION = 'calendar.description'; 11 11 const TYPE_CANCEL = 'calendar.cancel'; 12 + const TYPE_INVITE = 'calendar.invite'; 12 13 13 14 const MAILTAG_CONTENT = 'calendar-content'; 14 15 const MAILTAG_OTHER = 'calendar-other'; ··· 35 36 case self::TYPE_STATUS: 36 37 case self::TYPE_DESCRIPTION: 37 38 case self::TYPE_CANCEL: 39 + case self::TYPE_INVITE: 38 40 $phids[] = $this->getObjectPHID(); 39 41 break; 40 42 } ··· 50 52 case self::TYPE_STATUS: 51 53 case self::TYPE_DESCRIPTION: 52 54 case self::TYPE_CANCEL: 55 + case self::TYPE_INVITE: 53 56 return ($old === null); 54 57 } 55 58 return parent::shouldHide(); ··· 63 66 case self::TYPE_STATUS: 64 67 case self::TYPE_DESCRIPTION: 65 68 case self::TYPE_CANCEL: 69 + case self::TYPE_INVITE: 66 70 return 'fa-pencil'; 67 71 break; 68 72 } ··· 131 135 $this->renderHandleLink($author_phid)); 132 136 break; 133 137 } 138 + case self::TYPE_INVITE: 139 + return pht( 140 + "%s updated the event's invitee list.", 141 + $this->renderHandleLink($author_phid)); 142 + break; 134 143 } 135 144 136 145 return parent::getTitle(); ··· 216 225 $this->renderHandleLink($object_phid)); 217 226 break; 218 227 } 228 + case self::TYPE_INVITE: 229 + return pht( 230 + '%s updated the invitee list of %s.', 231 + $this->renderHandleLink($author_phid), 232 + $this->renderHandleLink($object_phid)); 233 + break; 219 234 } 220 235 221 236 return parent::getTitleForFeed(); ··· 232 247 case self::TYPE_STATUS: 233 248 case self::TYPE_DESCRIPTION: 234 249 case self::TYPE_CANCEL: 250 + case self::TYPE_INVITE: 235 251 return PhabricatorTransactions::COLOR_GREEN; 236 252 } 237 253 ··· 282 298 $tags[] = self::MAILTAG_CONTENT; 283 299 break; 284 300 case self::TYPE_CANCEL: 301 + $tags[] = self::MAILTAG_CONTENT; 302 + break; 303 + case self::TYPE_INVITE: 285 304 $tags[] = self::MAILTAG_CONTENT; 286 305 break; 287 306 }