Path: blob/master/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php
12256 views
<?php12final class PhabricatorCalendarEventEditor3extends PhabricatorApplicationTransactionEditor {45private $oldIsAllDay;6private $newIsAllDay;78public function getEditorApplicationClass() {9return 'PhabricatorCalendarApplication';10}1112public function getEditorObjectsDescription() {13return pht('Calendar');14}1516public function getCreateObjectTitle($author, $object) {17return pht('%s created this event.', $author);18}1920public function getCreateObjectTitleForFeed($author, $object) {21return pht('%s created %s.', $author, $object);22}2324protected function shouldApplyInitialEffects(25PhabricatorLiskDAO $object,26array $xactions) {27return true;28}2930public function getOldIsAllDay() {31return $this->oldIsAllDay;32}3334public function getNewIsAllDay() {35return $this->newIsAllDay;36}3738protected function applyInitialEffects(39PhabricatorLiskDAO $object,40array $xactions) {4142$actor = $this->requireActor();43if ($object->getIsStub()) {44$this->materializeStub($object);45}4647// Before doing anything, figure out if the event will be an all day event48// or not after the edit. This affects how we store datetime values, and49// whether we render times or not.50$old_allday = $object->getIsAllDay();51$new_allday = $old_allday;52$type_allday = PhabricatorCalendarEventAllDayTransaction::TRANSACTIONTYPE;53foreach ($xactions as $xaction) {54if ($xaction->getTransactionType() != $type_allday) {55continue;56}57$new_allday = (bool)$xaction->getNewValue();58}5960$this->oldIsAllDay = $old_allday;61$this->newIsAllDay = $new_allday;62}6364private function materializeStub(PhabricatorCalendarEvent $event) {65if (!$event->getIsStub()) {66throw new Exception(67pht('Can not materialize an event stub: this event is not a stub.'));68}6970$actor = $this->getActor();7172$invitees = $event->getInvitees();7374$event->copyFromParent($actor);75$event->setIsStub(0);7677$event->openTransaction();78$event->save();79foreach ($invitees as $invitee) {80$invitee81->setEventPHID($event->getPHID())82->save();83}84$event->saveTransaction();8586$event->attachInvitees($invitees);87}8889public function getTransactionTypes() {90$types = parent::getTransactionTypes();9192$types[] = PhabricatorTransactions::TYPE_COMMENT;93$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;94$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;9596return $types;97}9899protected function adjustObjectForPolicyChecks(100PhabricatorLiskDAO $object,101array $xactions) {102103$copy = parent::adjustObjectForPolicyChecks($object, $xactions);104foreach ($xactions as $xaction) {105switch ($xaction->getTransactionType()) {106case PhabricatorCalendarEventHostTransaction::TRANSACTIONTYPE:107$copy->setHostPHID($xaction->getNewValue());108break;109case PhabricatorCalendarEventInviteTransaction::TRANSACTIONTYPE:110PhabricatorPolicyRule::passTransactionHintToRule(111$copy,112new PhabricatorCalendarEventInviteesPolicyRule(),113array_fuse($xaction->getNewValue()));114break;115}116}117118return $copy;119}120121122protected function applyFinalEffects(123PhabricatorLiskDAO $object,124array $xactions) {125126// Clear the availability caches for users whose availability is affected127// by this edit.128129$phids = mpull($object->getInvitees(), 'getInviteePHID');130$phids = array_fuse($phids);131132$invalidate_all = false;133$invalidate_phids = array();134foreach ($xactions as $xaction) {135switch ($xaction->getTransactionType()) {136case PhabricatorCalendarEventUntilDateTransaction::TRANSACTIONTYPE:137case PhabricatorCalendarEventStartDateTransaction::TRANSACTIONTYPE:138case PhabricatorCalendarEventEndDateTransaction::TRANSACTIONTYPE:139case PhabricatorCalendarEventCancelTransaction::TRANSACTIONTYPE:140case PhabricatorCalendarEventAllDayTransaction::TRANSACTIONTYPE:141// For these kinds of changes, we need to invalidate the availabilty142// caches for all attendees.143$invalidate_all = true;144break;145case PhabricatorCalendarEventAcceptTransaction::TRANSACTIONTYPE:146case PhabricatorCalendarEventDeclineTransaction::TRANSACTIONTYPE:147$acting_phid = $this->getActingAsPHID();148$invalidate_phids[$acting_phid] = $acting_phid;149break;150case PhabricatorCalendarEventInviteTransaction::TRANSACTIONTYPE:151foreach ($xaction->getOldValue() as $phid) {152// Add the possibly un-invited user to the list of potentially153// affected users if they are't already present.154$phids[$phid] = $phid;155156$invalidate_phids[$phid] = $phid;157}158159foreach ($xaction->getNewValue() as $phid) {160$invalidate_phids[$phid] = $phid;161}162break;163}164}165166if (!$invalidate_all) {167$phids = array_select_keys($phids, $invalidate_phids);168}169170if ($phids) {171$object->applyViewerTimezone($this->getActor());172173$user = new PhabricatorUser();174$conn_w = $user->establishConnection('w');175queryfx(176$conn_w,177'UPDATE %T SET availabilityCacheTTL = NULL178WHERE phid IN (%Ls)',179$user->getTableName(),180$phids);181}182183return $xactions;184}185186187protected function validateAllTransactions(188PhabricatorLiskDAO $object,189array $xactions) {190191$start_date_xaction =192PhabricatorCalendarEventStartDateTransaction::TRANSACTIONTYPE;193$end_date_xaction =194PhabricatorCalendarEventEndDateTransaction::TRANSACTIONTYPE;195$is_recurrence_xaction =196PhabricatorCalendarEventRecurringTransaction::TRANSACTIONTYPE;197$recurrence_end_xaction =198PhabricatorCalendarEventUntilDateTransaction::TRANSACTIONTYPE;199200$start_date = $object->getStartDateTimeEpoch();201$end_date = $object->getEndDateTimeEpoch();202$recurrence_end = $object->getUntilDateTimeEpoch();203$is_recurring = $object->getIsRecurring();204205$errors = array();206207foreach ($xactions as $xaction) {208if ($xaction->getTransactionType() == $start_date_xaction) {209$start_date = $xaction->getNewValue()->getEpoch();210} else if ($xaction->getTransactionType() == $end_date_xaction) {211$end_date = $xaction->getNewValue()->getEpoch();212} else if ($xaction->getTransactionType() == $recurrence_end_xaction) {213$recurrence_end = $xaction->getNewValue()->getEpoch();214} else if ($xaction->getTransactionType() == $is_recurrence_xaction) {215$is_recurring = $xaction->getNewValue();216}217}218219if ($start_date > $end_date) {220$errors[] = new PhabricatorApplicationTransactionValidationError(221$end_date_xaction,222pht('Invalid'),223pht('End date must be after start date.'),224null);225}226227if ($recurrence_end && !$is_recurring) {228$errors[] = new PhabricatorApplicationTransactionValidationError(229$recurrence_end_xaction,230pht('Invalid'),231pht('Event must be recurring to have a recurrence end date.').232null);233}234235return $errors;236}237238protected function shouldPublishFeedStory(239PhabricatorLiskDAO $object,240array $xactions) {241242if ($object->isImportedEvent()) {243return false;244}245246return true;247}248249protected function supportsSearch() {250return true;251}252253protected function shouldSendMail(254PhabricatorLiskDAO $object,255array $xactions) {256257if ($object->isImportedEvent()) {258return false;259}260261return true;262}263264protected function getMailSubjectPrefix() {265return pht('[Calendar]');266}267268protected function getMailTo(PhabricatorLiskDAO $object) {269$phids = array();270271if ($object->getHostPHID()) {272$phids[] = $object->getHostPHID();273}274$phids[] = $this->getActingAsPHID();275276$invitees = $object->getInvitees();277foreach ($invitees as $invitee) {278$status = $invitee->getStatus();279if ($status === PhabricatorCalendarEventInvitee::STATUS_ATTENDING280|| $status === PhabricatorCalendarEventInvitee::STATUS_INVITED) {281$phids[] = $invitee->getInviteePHID();282}283}284285$phids = array_unique($phids);286287return $phids;288}289290public function getMailTagsMap() {291return array(292PhabricatorCalendarEventTransaction::MAILTAG_CONTENT =>293pht(294"An event's name, status, invite list, ".295"icon, and description changes."),296PhabricatorCalendarEventTransaction::MAILTAG_RESCHEDULE =>297pht(298"An event's start and end date ".299"and cancellation status changes."),300PhabricatorCalendarEventTransaction::MAILTAG_OTHER =>301pht('Other event activity not listed above occurs.'),302);303}304305protected function buildReplyHandler(PhabricatorLiskDAO $object) {306return id(new PhabricatorCalendarReplyHandler())307->setMailReceiver($object);308}309310protected function buildMailTemplate(PhabricatorLiskDAO $object) {311$name = $object->getName();312$monogram = $object->getMonogram();313314return id(new PhabricatorMetaMTAMail())315->setSubject("{$monogram}: {$name}");316}317318protected function buildMailBody(319PhabricatorLiskDAO $object,320array $xactions) {321322$body = parent::buildMailBody($object, $xactions);323324$description = $object->getDescription();325if ($this->getIsNewObject()) {326if (strlen($description)) {327$body->addRemarkupSection(328pht('EVENT DESCRIPTION'),329$description);330}331}332333$body->addLinkSection(334pht('EVENT DETAIL'),335PhabricatorEnv::getProductionURI($object->getURI()));336337$ics_attachment = $this->newICSAttachment($object);338$body->addAttachment($ics_attachment);339340return $body;341}342343protected function shouldApplyHeraldRules(344PhabricatorLiskDAO $object,345array $xactions) {346return true;347}348349protected function buildHeraldAdapter(350PhabricatorLiskDAO $object,351array $xactions) {352353return id(new PhabricatorCalendarEventHeraldAdapter())354->setObject($object);355}356357private function newICSAttachment(358PhabricatorCalendarEvent $event) {359$actor = $this->getActor();360361$ics_data = id(new PhabricatorCalendarICSWriter())362->setViewer($actor)363->setEvents(array($event))364->writeICSDocument();365366$ics_attachment = new PhabricatorMailAttachment(367$ics_data,368$event->getICSFilename(),369'text/calendar');370371return $ics_attachment;372}373374}375376377