protected function loadPage()
 {
     $table = new PhabricatorCalendarEvent();
     $conn_r = $table->establishConnection('r');
     $data = queryfx_all($conn_r, 'SELECT * FROM %T %Q %Q %Q', $table->getTableName(), $this->buildWhereClause($conn_r), $this->buildOrderClause($conn_r), $this->buildLimitClause($conn_r));
     return $table->loadAllFromArray($data);
 }
 private function buildActionView(PhabricatorCalendarEvent $event)
 {
     $viewer = $this->getRequest()->getUser();
     $id = $event->getID();
     $actions = id(new PhabricatorActionListView())->setObjectURI($this->getApplicationURI('event/' . $id . '/'))->setUser($viewer);
     $can_edit = PhabricatorPolicyFilter::hasCapability($viewer, $event, PhabricatorPolicyCapability::CAN_EDIT);
     $actions->addAction(id(new PhabricatorActionView())->setName(pht('Edit Event'))->setIcon('fa-pencil')->setHref($this->getApplicationURI("event/edit/{$id}/"))->setDisabled(!$can_edit)->setWorkflow(!$can_edit));
     $actions->addAction(id(new PhabricatorActionView())->setName(pht('Cancel Event'))->setIcon('fa-times')->setHref($this->getApplicationURI("event/delete/{$id}/"))->setDisabled(!$can_edit)->setWorkflow(true));
     return $actions;
 }
 protected function newImportedEventResponse(PhabricatorCalendarEvent $event)
 {
     if (!$event->isImportedEvent()) {
         return null;
     }
     // Give the user a specific, detailed message if they try to edit an
     // imported event via common web paths. Other edits (including those via
     // the API) are blocked by the normal policy system, but this makes it more
     // clear exactly why the event can't be edited.
     return $this->newDialog()->setTitle(pht('Can Not Edit Imported Event'))->appendParagraph(pht('This event has been imported from an external source and ' . 'can not be edited.'))->addCancelButton($event->getURI(), pht('Done'));
 }
 protected function buildSideNavView(PhabricatorCalendarEvent $status = null)
 {
     $nav = new AphrontSideNavFilterView();
     $nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
     $nav->addLabel(pht('Calendar'));
     $nav->addFilter('/', pht('My Events'));
     $nav->addFilter('all/', pht('View All'));
     $nav->addFilter('event/create/', pht('Create Event'));
     if ($status && $status->getID()) {
         $nav->addFilter('event/edit/' . $status->getID() . '/', pht('Edit Event'));
     }
     $nav->addFilter('event/', pht('Upcoming Events'));
     return $nav;
 }
 protected function execute(ConduitAPIRequest $request)
 {
     $user_phid = $request->getUser()->getPHID();
     $from = $request->getValue('fromEpoch');
     $to = $request->getValue('toEpoch');
     if ($to <= $from) {
         throw new ConduitException('ERR-BAD-EPOCH');
     }
     $table = new PhabricatorCalendarEvent();
     $table->openTransaction();
     $table->beginReadLocking();
     $overlap = $table->loadAllWhere('userPHID = %s AND dateFrom < %d AND dateTo > %d', $user_phid, $to, $from);
     foreach ($overlap as $status) {
         if ($status->getDateFrom() < $from) {
             if ($status->getDateTo() > $to) {
                 // Split the interval.
                 id(new PhabricatorCalendarEvent())->setUserPHID($user_phid)->setDateFrom($to)->setDateTo($status->getDateTo())->setStatus($status->getStatus())->setDescription($status->getDescription())->save();
             }
             $status->setDateTo($from);
             $status->save();
         } else {
             if ($status->getDateTo() > $to) {
                 $status->setDateFrom($to);
                 $status->save();
             } else {
                 $status->delete();
             }
         }
     }
     $table->endReadLocking();
     $table->saveTransaction();
     return count($overlap);
 }
 protected function buildCustomEditFields($object)
 {
     $viewer = $this->getViewer();
     if ($this->getIsCreate()) {
         $invitee_phids = array($viewer->getPHID());
     } else {
         $invitee_phids = $object->getInviteePHIDsForEdit();
     }
     $frequency_map = PhabricatorCalendarEvent::getFrequencyMap();
     $frequency_options = ipull($frequency_map, 'label');
     $rrule = $object->newRecurrenceRule();
     if ($rrule) {
         $frequency = $rrule->getFrequency();
     } else {
         $frequency = null;
     }
     // At least for now, just hide "Invitees" when editing all future events.
     // This may eventually deserve a more nuanced approach.
     $is_future = $this->getSeriesEditMode() == self::MODE_FUTURE;
     $fields = array(id(new PhabricatorTextEditField())->setKey('name')->setLabel(pht('Name'))->setDescription(pht('Name of the event.'))->setIsRequired(true)->setTransactionType(PhabricatorCalendarEventNameTransaction::TRANSACTIONTYPE)->setConduitDescription(pht('Rename the event.'))->setConduitTypeDescription(pht('New event name.'))->setValue($object->getName()), id(new PhabricatorBoolEditField())->setIsLockable(false)->setIsDefaultable(false)->setKey('isAllDay')->setOptions(pht('Normal Event'), pht('All Day Event'))->setAsCheckbox(true)->setTransactionType(PhabricatorCalendarEventAllDayTransaction::TRANSACTIONTYPE)->setDescription(pht('Marks this as an all day event.'))->setConduitDescription(pht('Make the event an all day event.'))->setConduitTypeDescription(pht('Mark the event as an all day event.'))->setValue($object->getIsAllDay()), id(new PhabricatorEpochEditField())->setKey('start')->setLabel(pht('Start'))->setIsLockable(false)->setIsDefaultable(false)->setTransactionType(PhabricatorCalendarEventStartDateTransaction::TRANSACTIONTYPE)->setDescription(pht('Start time of the event.'))->setConduitDescription(pht('Change the start time of the event.'))->setConduitTypeDescription(pht('New event start time.'))->setValue($object->getStartDateTimeEpoch()), id(new PhabricatorEpochEditField())->setKey('end')->setLabel(pht('End'))->setIsLockable(false)->setIsDefaultable(false)->setTransactionType(PhabricatorCalendarEventEndDateTransaction::TRANSACTIONTYPE)->setDescription(pht('End time of the event.'))->setConduitDescription(pht('Change the end time of the event.'))->setConduitTypeDescription(pht('New event end time.'))->setValue($object->newEndDateTimeForEdit()->getEpoch()), id(new PhabricatorBoolEditField())->setKey('cancelled')->setOptions(pht('Active'), pht('Cancelled'))->setLabel(pht('Cancelled'))->setDescription(pht('Cancel the event.'))->setTransactionType(PhabricatorCalendarEventCancelTransaction::TRANSACTIONTYPE)->setIsConduitOnly(true)->setConduitDescription(pht('Cancel or restore the event.'))->setConduitTypeDescription(pht('True to cancel the event.'))->setValue($object->getIsCancelled()), id(new PhabricatorUsersEditField())->setIsLockable(false)->setIsDefaultable(false)->setKey('hostPHID')->setAliases(array('host'))->setLabel(pht('Host'))->setDescription(pht('Host of the event.'))->setTransactionType(PhabricatorCalendarEventHostTransaction::TRANSACTIONTYPE)->setIsConduitOnly($this->getIsCreate())->setConduitDescription(pht('Change the host of the event.'))->setConduitTypeDescription(pht('New event host.'))->setSingleValue($object->getHostPHID()), id(new PhabricatorDatasourceEditField())->setIsLockable(false)->setIsDefaultable(false)->setIsHidden($is_future)->setKey('inviteePHIDs')->setAliases(array('invite', 'invitee', 'invitees', 'inviteePHID'))->setLabel(pht('Invitees'))->setDatasource(new PhabricatorMetaMTAMailableDatasource())->setTransactionType(PhabricatorCalendarEventInviteTransaction::TRANSACTIONTYPE)->setDescription(pht('Users invited to the event.'))->setConduitDescription(pht('Change invited users.'))->setConduitTypeDescription(pht('New event invitees.'))->setValue($invitee_phids)->setCommentActionLabel(pht('Change Invitees')), id(new PhabricatorRemarkupEditField())->setKey('description')->setLabel(pht('Description'))->setDescription(pht('Description of the event.'))->setTransactionType(PhabricatorCalendarEventDescriptionTransaction::TRANSACTIONTYPE)->setConduitDescription(pht('Update the event description.'))->setConduitTypeDescription(pht('New event description.'))->setValue($object->getDescription()), id(new PhabricatorIconSetEditField())->setKey('icon')->setLabel(pht('Icon'))->setIconSet(new PhabricatorCalendarIconSet())->setTransactionType(PhabricatorCalendarEventIconTransaction::TRANSACTIONTYPE)->setDescription(pht('Event icon.'))->setConduitDescription(pht('Change the event icon.'))->setConduitTypeDescription(pht('New event icon.'))->setValue($object->getIcon()), id(new PhabricatorBoolEditField())->setIsHidden(true)->setIsLockable(false)->setIsDefaultable(false)->setKey('isRecurring')->setLabel(pht('Recurring'))->setOptions(pht('One-Time Event'), pht('Recurring Event'))->setTransactionType(PhabricatorCalendarEventRecurringTransaction::TRANSACTIONTYPE)->setDescription(pht('One time or recurring event.'))->setConduitDescription(pht('Make the event recurring.'))->setConduitTypeDescription(pht('Mark the event as a recurring event.'))->setValue(true), id(new PhabricatorSelectEditField())->setIsLockable(false)->setIsDefaultable(false)->setKey('frequency')->setLabel(pht('Frequency'))->setOptions($frequency_options)->setTransactionType(PhabricatorCalendarEventFrequencyTransaction::TRANSACTIONTYPE)->setDescription(pht('Recurring event frequency.'))->setConduitDescription(pht('Change the event frequency.'))->setConduitTypeDescription(pht('New event frequency.'))->setValue($frequency), id(new PhabricatorEpochEditField())->setIsLockable(false)->setIsDefaultable(false)->setAllowNull(true)->setHideTime($object->getIsAllDay())->setKey('until')->setLabel(pht('Repeat Until'))->setTransactionType(PhabricatorCalendarEventUntilDateTransaction::TRANSACTIONTYPE)->setDescription(pht('Last instance of the event.'))->setConduitDescription(pht('Change when the event repeats until.'))->setConduitTypeDescription(pht('New final event time.'))->setValue($object->getUntilDateTimeEpoch()));
     return $fields;
 }
 protected function buildApplicationCrumbs()
 {
     $crumbs = parent::buildApplicationCrumbs();
     $viewer = $this->getViewer();
     $year = $this->viewYear;
     $month = $this->viewMonth;
     $day = $this->viewDay;
     $parameters = array();
     // If the viewer clicks "Create Event" while on a particular day view,
     // default the times to that day.
     if ($year && $month && $day) {
         $datetimes = PhabricatorCalendarEvent::newDefaultEventDateTimes($viewer, PhabricatorTime::getNow());
         foreach ($datetimes as $datetime) {
             $datetime->setYear($year)->setMonth($month)->setDay($day);
         }
         list($start, $end) = $datetimes;
         $parameters['start'] = $start->getEpoch();
         $parameters['end'] = $end->getEpoch();
     }
     id(new PhabricatorCalendarEventEditEngine())->setViewer($this->getViewer())->addActionToCrumbs($crumbs, $parameters);
     return $crumbs;
 }
 private function buildRSVPActions(PhabricatorCalendarEvent $event)
 {
     $viewer = $this->getViewer();
     $id = $event->getID();
     $invite_status = $event->getUserInviteStatus($viewer->getPHID());
     $status_invited = PhabricatorCalendarEventInvitee::STATUS_INVITED;
     $is_invite_pending = $invite_status == $status_invited;
     if (!$is_invite_pending) {
         return array();
     }
     $decline_button = id(new PHUIButtonView())->setTag('a')->setIcon('fa-times grey')->setHref($this->getApplicationURI("/event/decline/{$id}/"))->setWorkflow(true)->setText(pht('Decline'));
     $accept_button = id(new PHUIButtonView())->setTag('a')->setIcon('fa-check green')->setHref($this->getApplicationURI("/event/accept/{$id}/"))->setWorkflow(true)->setText(pht('Accept'));
     return array($decline_button, $accept_button);
 }
 private function buildActionView(PhabricatorCalendarEvent $event)
 {
     $viewer = $this->getRequest()->getUser();
     $id = $event->getID();
     $is_cancelled = $event->getIsCancelled();
     $is_attending = $event->getIsUserAttending($viewer->getPHID());
     $actions = id(new PhabricatorActionListView())->setUser($viewer)->setObject($event);
     $can_edit = PhabricatorPolicyFilter::hasCapability($viewer, $event, PhabricatorPolicyCapability::CAN_EDIT);
     $edit_label = false;
     $edit_uri = false;
     if ($event->getIsGhostEvent()) {
         $index = $event->getSequenceIndex();
         $edit_label = pht('Edit This Instance');
         $edit_uri = "event/edit/{$id}/{$index}/";
     } else {
         if ($event->getIsRecurrenceException()) {
             $edit_label = pht('Edit This Instance');
             $edit_uri = "event/edit/{$id}/";
         } else {
             $edit_label = pht('Edit');
             $edit_uri = "event/edit/{$id}/";
         }
     }
     if ($edit_label && $edit_uri) {
         $actions->addAction(id(new PhabricatorActionView())->setName($edit_label)->setIcon('fa-pencil')->setHref($this->getApplicationURI($edit_uri))->setDisabled(!$can_edit)->setWorkflow(!$can_edit));
     }
     if ($is_attending) {
         $actions->addAction(id(new PhabricatorActionView())->setName(pht('Decline Event'))->setIcon('fa-user-times')->setHref($this->getApplicationURI("event/join/{$id}/"))->setWorkflow(true));
     } else {
         $actions->addAction(id(new PhabricatorActionView())->setName(pht('Join Event'))->setIcon('fa-user-plus')->setHref($this->getApplicationURI("event/join/{$id}/"))->setWorkflow(true));
     }
     $cancel_uri = $this->getApplicationURI("event/cancel/{$id}/");
     if ($event->getIsGhostEvent()) {
         $index = $event->getSequenceIndex();
         $can_reinstate = $event->getIsParentCancelled();
         $cancel_label = pht('Cancel This Instance');
         $reinstate_label = pht('Reinstate This Instance');
         $cancel_disabled = !$can_edit || $can_reinstate;
         $cancel_uri = $this->getApplicationURI("event/cancel/{$id}/{$index}/");
     } else {
         if ($event->getIsRecurrenceException()) {
             $can_reinstate = $event->getIsParentCancelled();
             $cancel_label = pht('Cancel This Instance');
             $reinstate_label = pht('Reinstate This Instance');
             $cancel_disabled = !$can_edit || $can_reinstate;
         } else {
             if ($event->getIsRecurrenceParent()) {
                 $cancel_label = pht('Cancel Recurrence');
                 $reinstate_label = pht('Reinstate Recurrence');
                 $cancel_disabled = !$can_edit;
             } else {
                 $cancel_label = pht('Cancel Event');
                 $reinstate_label = pht('Reinstate Event');
                 $cancel_disabled = !$can_edit;
             }
         }
     }
     if ($is_cancelled) {
         $actions->addAction(id(new PhabricatorActionView())->setName($reinstate_label)->setIcon('fa-plus')->setHref($cancel_uri)->setDisabled($cancel_disabled)->setWorkflow(true));
     } else {
         $actions->addAction(id(new PhabricatorActionView())->setName($cancel_label)->setIcon('fa-times')->setHref($cancel_uri)->setDisabled($cancel_disabled)->setWorkflow(true));
     }
     return $actions;
 }
<?php

$table = new PhabricatorCalendarEvent();
$conn = $table->establishConnection('w');
$table_name = 'calendar_event';
// Long ago, "All Day" events were stored with a start and end date set to
// the earliest possible start and end seconds for the corresponding days. We
// then moved to store all day events with their "date" epochs as UTC, separate
// from individual event times. Both systems were later replaced with use of
// CalendarDateTime.
$zone_min = new DateTimeZone('Pacific/Midway');
$zone_max = new DateTimeZone('Pacific/Kiritimati');
$zone_utc = new DateTimeZone('UTC');
foreach (new LiskRawMigrationIterator($conn, $table_name) as $row) {
    $parameters = phutil_json_decode($row['parameters']);
    if (isset($parameters['startDateTime'])) {
        // This event has already been migrated.
        continue;
    }
    $is_all_day = $row['isAllDay'];
    if (empty($row['allDayDateFrom'])) {
        // No "allDayDateFrom" means this is an old event which was never migrated
        // by the earlier "20160715.event.03.allday.php" migration. The dateFrom
        // and dateTo will be minimum and maximum earthly seconds for the event. We
        // convert them to UTC if they were in extreme timezones.
        $epoch_min = $row['dateFrom'];
        $epoch_max = $row['dateTo'];
        if ($is_all_day) {
            $date_min = new DateTime('@' . $epoch_min);
            $date_max = new DateTime('@' . $epoch_max);
            $date_min->setTimeZone($zone_min);
<?php

echo pht('Retro-naming unnamed events.') . "\n";
$table = new PhabricatorCalendarEvent();
$conn_w = $table->establishConnection('w');
$iterator = new LiskMigrationIterator($table);
foreach ($iterator as $event) {
    $id = $event->getID();
    if (strlen($event->getName()) == 0) {
        echo pht('Renaming event %d...', $id) . "\n";
        $viewer = PhabricatorUser::getOmnipotentUser();
        // NOTE: This uses PeopleQuery directly, instead of HandleQuery, to avoid
        // performing cache fills as a side effect; the caches were added by a
        // later patch. See T8209.
        $user = id(new PhabricatorPeopleQuery())->setViewer($viewer)->withPHIDs(array($event->getUserPHID()))->executeOne();
        if ($user) {
            $new_name = $user->getUsername();
        } else {
            $new_name = pht('Unnamed Event');
        }
        queryfx($conn_w, 'UPDATE %T SET name = %s WHERE id = %d', $table->getTableName(), $new_name, $id);
    }
}
echo pht('Done.') . "\n";
 private function newICSAttachment(PhabricatorCalendarEvent $event)
 {
     $actor = $this->getActor();
     $event_node = $event->newIntermediateEventNode($actor);
     $document_node = id(new PhutilCalendarDocumentNode())->appendChild($event_node);
     $root_node = id(new PhutilCalendarRootNode())->appendChild($document_node);
     $ics_data = id(new PhutilICSWriter())->writeICSDocument($root_node);
     $ics_attachment = new PhabricatorMetaMTAAttachment($ics_data, $event->getICSFilename(), 'text/calendar');
     return $ics_attachment;
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $user_phid = $viewer->getPHID();
     $this->id = $request->getURIData('id');
     $error_name = true;
     $error_recurrence_end_date = null;
     $error_start_date = true;
     $error_end_date = true;
     $validation_exception = null;
     $is_recurring_id = celerity_generate_unique_node_id();
     $recurrence_end_date_id = celerity_generate_unique_node_id();
     $frequency_id = celerity_generate_unique_node_id();
     $all_day_id = celerity_generate_unique_node_id();
     $start_date_id = celerity_generate_unique_node_id();
     $end_date_id = celerity_generate_unique_node_id();
     $next_workflow = $request->getStr('next');
     $uri_query = $request->getStr('query');
     if ($this->isCreate()) {
         $mode = $request->getStr('mode');
         $event = PhabricatorCalendarEvent::initializeNewCalendarEvent($viewer, $mode);
         $create_start_year = $request->getInt('year');
         $create_start_month = $request->getInt('month');
         $create_start_day = $request->getInt('day');
         $create_start_time = $request->getStr('time');
         if ($create_start_year) {
             $start = AphrontFormDateControlValue::newFromParts($viewer, $create_start_year, $create_start_month, $create_start_day, $create_start_time);
             if (!$start->isValid()) {
                 return new Aphront400Response();
             }
             $start_value = AphrontFormDateControlValue::newFromEpoch($viewer, $start->getEpoch());
             $end = clone $start_value->getDateTime();
             $end->modify('+1 hour');
             $end_value = AphrontFormDateControlValue::newFromEpoch($viewer, $end->format('U'));
         } else {
             list($start_value, $end_value) = $this->getDefaultTimeValues($viewer);
         }
         $recurrence_end_date_value = clone $end_value;
         $recurrence_end_date_value->setOptional(true);
         $submit_label = pht('Create');
         $page_title = pht('Create Event');
         $redirect = 'created';
         $subscribers = array();
         $invitees = array($user_phid);
         $cancel_uri = $this->getApplicationURI();
     } else {
         $event = id(new PhabricatorCalendarEventQuery())->setViewer($viewer)->withIDs(array($this->id))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
         if (!$event) {
             return new Aphront404Response();
         }
         if ($request->getURIData('sequence')) {
             $index = $request->getURIData('sequence');
             $result = $this->getEventAtIndexForGhostPHID($viewer, $event->getPHID(), $index);
             if ($result) {
                 return id(new AphrontRedirectResponse())->setURI('/calendar/event/edit/' . $result->getID() . '/');
             }
             $event = $this->createEventFromGhost($viewer, $event, $index);
             return id(new AphrontRedirectResponse())->setURI('/calendar/event/edit/' . $event->getID() . '/');
         }
         $end_value = AphrontFormDateControlValue::newFromEpoch($viewer, $event->getDateTo());
         $start_value = AphrontFormDateControlValue::newFromEpoch($viewer, $event->getDateFrom());
         $recurrence_end_date_value = id(clone $end_value)->setOptional(true);
         $submit_label = pht('Update');
         $page_title = pht('Update Event');
         $subscribers = PhabricatorSubscribersQuery::loadSubscribersForPHID($event->getPHID());
         $invitees = array();
         foreach ($event->getInvitees() as $invitee) {
             if ($invitee->isUninvited()) {
                 continue;
             } else {
                 $invitees[] = $invitee->getInviteePHID();
             }
         }
         $cancel_uri = '/' . $event->getMonogram();
     }
     if ($this->isCreate()) {
         $projects = array();
     } else {
         $projects = PhabricatorEdgeQuery::loadDestinationPHIDs($event->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
         $projects = array_reverse($projects);
     }
     $name = $event->getName();
     $description = $event->getDescription();
     $is_all_day = $event->getIsAllDay();
     $is_recurring = $event->getIsRecurring();
     $is_parent = $event->getIsRecurrenceParent();
     $frequency = idx($event->getRecurrenceFrequency(), 'rule');
     $icon = $event->getIcon();
     $edit_policy = $event->getEditPolicy();
     $view_policy = $event->getViewPolicy();
     $space = $event->getSpacePHID();
     if ($request->isFormPost()) {
         $xactions = array();
         $name = $request->getStr('name');
         $start_value = AphrontFormDateControlValue::newFromRequest($request, 'start');
         $end_value = AphrontFormDateControlValue::newFromRequest($request, 'end');
         $recurrence_end_date_value = AphrontFormDateControlValue::newFromRequest($request, 'recurrenceEndDate');
         $recurrence_end_date_value->setOptional(true);
         $projects = $request->getArr('projects');
         $description = $request->getStr('description');
         $subscribers = $request->getArr('subscribers');
         $edit_policy = $request->getStr('editPolicy');
         $view_policy = $request->getStr('viewPolicy');
         $space = $request->getStr('spacePHID');
         $is_recurring = $request->getStr('isRecurring') ? 1 : 0;
         $frequency = $request->getStr('frequency');
         $is_all_day = $request->getStr('isAllDay');
         $icon = $request->getStr('icon');
         $invitees = $request->getArr('invitees');
         $new_invitees = $this->getNewInviteeList($invitees, $event);
         $status_attending = PhabricatorCalendarEventInvitee::STATUS_ATTENDING;
         if ($this->isCreate()) {
             $status = idx($new_invitees, $viewer->getPHID());
             if ($status) {
                 $new_invitees[$viewer->getPHID()] = $status_attending;
             }
         }
         $xactions[] = id(new PhabricatorCalendarEventTransaction())->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_NAME)->setNewValue($name);
         if ($is_recurring && $this->isCreate()) {
             $xactions[] = id(new PhabricatorCalendarEventTransaction())->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_RECURRING)->setNewValue($is_recurring);
             $xactions[] = id(new PhabricatorCalendarEventTransaction())->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_FREQUENCY)->setNewValue(array('rule' => $frequency));
             if (!$recurrence_end_date_value->isDisabled()) {
                 $xactions[] = id(new PhabricatorCalendarEventTransaction())->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE)->setNewValue($recurrence_end_date_value);
             }
         }
         if ($is_recurring && $this->isCreate() || !$is_parent) {
             $xactions[] = id(new PhabricatorCalendarEventTransaction())->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_ALL_DAY)->setNewValue($is_all_day);
             $xactions[] = id(new PhabricatorCalendarEventTransaction())->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_ICON)->setNewValue($icon);
             $xactions[] = id(new PhabricatorCalendarEventTransaction())->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_START_DATE)->setNewValue($start_value);
             $xactions[] = id(new PhabricatorCalendarEventTransaction())->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_END_DATE)->setNewValue($end_value);
         }
         $xactions[] = id(new PhabricatorCalendarEventTransaction())->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)->setNewValue(array('=' => array_fuse($subscribers)));
         $xactions[] = id(new PhabricatorCalendarEventTransaction())->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_INVITE)->setNewValue($new_invitees);
         $xactions[] = id(new PhabricatorCalendarEventTransaction())->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION)->setNewValue($description);
         $xactions[] = id(new PhabricatorCalendarEventTransaction())->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)->setNewValue($request->getStr('viewPolicy'));
         $xactions[] = id(new PhabricatorCalendarEventTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)->setNewValue($request->getStr('editPolicy'));
         $xactions[] = id(new PhabricatorCalendarEventTransaction())->setTransactionType(PhabricatorTransactions::TYPE_SPACE)->setNewValue($space);
         $editor = id(new PhabricatorCalendarEventEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true);
         try {
             $proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
             $xactions[] = id(new PhabricatorCalendarEventTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', $proj_edge_type)->setNewValue(array('=' => array_fuse($projects)));
             $xactions = $editor->applyTransactions($event, $xactions);
             $response = id(new AphrontRedirectResponse());
             switch ($next_workflow) {
                 case 'day':
                     if (!$uri_query) {
                         $uri_query = 'month';
                     }
                     $year = $start_value->getDateTime()->format('Y');
                     $month = $start_value->getDateTime()->format('m');
                     $day = $start_value->getDateTime()->format('d');
                     $response->setURI('/calendar/query/' . $uri_query . '/' . $year . '/' . $month . '/' . $day . '/');
                     break;
                 default:
                     $response->setURI('/E' . $event->getID());
                     break;
             }
             return $response;
         } catch (PhabricatorApplicationTransactionValidationException $ex) {
             $validation_exception = $ex;
             $error_name = $ex->getShortMessage(PhabricatorCalendarEventTransaction::TYPE_NAME);
             $error_start_date = $ex->getShortMessage(PhabricatorCalendarEventTransaction::TYPE_START_DATE);
             $error_end_date = $ex->getShortMessage(PhabricatorCalendarEventTransaction::TYPE_END_DATE);
             $error_recurrence_end_date = $ex->getShortMessage(PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE);
         }
     }
     $is_recurring_checkbox = null;
     $recurrence_end_date_control = null;
     $recurrence_frequency_select = null;
     $all_day_checkbox = null;
     $start_control = null;
     $end_control = null;
     $recurring_date_edit_label = null;
     $current_policies = id(new PhabricatorPolicyQuery())->setViewer($viewer)->setObject($event)->execute();
     $name = id(new AphrontFormTextControl())->setLabel(pht('Name'))->setName('name')->setValue($name)->setError($error_name);
     if ($this->isCreate()) {
         Javelin::initBehavior('recurring-edit', array('isRecurring' => $is_recurring_id, 'frequency' => $frequency_id, 'recurrenceEndDate' => $recurrence_end_date_id));
         $is_recurring_checkbox = id(new AphrontFormCheckboxControl())->addCheckbox('isRecurring', 1, pht('Recurring Event'), $is_recurring, $is_recurring_id);
         $recurrence_end_date_control = id(new AphrontFormDateControl())->setUser($viewer)->setName('recurrenceEndDate')->setLabel(pht('Recurrence End Date'))->setError($error_recurrence_end_date)->setValue($recurrence_end_date_value)->setID($recurrence_end_date_id)->setIsTimeDisabled(true)->setIsDisabled($recurrence_end_date_value->isDisabled())->setAllowNull(true);
         $recurrence_frequency_select = id(new AphrontFormSelectControl())->setName('frequency')->setOptions(array(PhabricatorCalendarEvent::FREQUENCY_DAILY => pht('Daily'), PhabricatorCalendarEvent::FREQUENCY_WEEKLY => pht('Weekly'), PhabricatorCalendarEvent::FREQUENCY_MONTHLY => pht('Monthly'), PhabricatorCalendarEvent::FREQUENCY_YEARLY => pht('Yearly')))->setValue($frequency)->setLabel(pht('Recurring Event Frequency'))->setID($frequency_id)->setDisabled(!$is_recurring);
     }
     if ($this->isCreate() || !$is_parent && !$this->isCreate()) {
         Javelin::initBehavior('event-all-day', array('allDayID' => $all_day_id, 'startDateID' => $start_date_id, 'endDateID' => $end_date_id));
         $all_day_checkbox = id(new AphrontFormCheckboxControl())->addCheckbox('isAllDay', 1, pht('All Day Event'), $is_all_day, $all_day_id);
         $start_control = id(new AphrontFormDateControl())->setUser($viewer)->setName('start')->setLabel(pht('Start'))->setError($error_start_date)->setValue($start_value)->setID($start_date_id)->setIsTimeDisabled($is_all_day)->setEndDateID($end_date_id);
         $end_control = id(new AphrontFormDateControl())->setUser($viewer)->setName('end')->setLabel(pht('End'))->setError($error_end_date)->setValue($end_value)->setID($end_date_id)->setIsTimeDisabled($is_all_day);
     } else {
         if ($is_parent) {
             $recurring_date_edit_label = id(new AphrontFormStaticControl())->setUser($viewer)->setValue(pht('Date and time of recurring event cannot be edited.'));
             if (!$recurrence_end_date_value->isDisabled()) {
                 $disabled_recurrence_end_date_value = $recurrence_end_date_value->getValueAsFormat('M d, Y');
                 $recurrence_end_date_control = id(new AphrontFormStaticControl())->setUser($viewer)->setLabel(pht('Recurrence End Date'))->setValue($disabled_recurrence_end_date_value)->setDisabled(true);
             }
             $recurrence_frequency_select = id(new AphrontFormSelectControl())->setName('frequency')->setOptions(array('daily' => pht('Daily'), 'weekly' => pht('Weekly'), 'monthly' => pht('Monthly'), 'yearly' => pht('Yearly')))->setValue($frequency)->setLabel(pht('Recurring Event Frequency'))->setID($frequency_id)->setDisabled(true);
             $all_day_checkbox = id(new AphrontFormCheckboxControl())->addCheckbox('isAllDay', 1, pht('All Day Event'), $is_all_day, $all_day_id)->setDisabled(true);
             $start_disabled = $start_value->getValueAsFormat('M d, Y, g:i A');
             $end_disabled = $end_value->getValueAsFormat('M d, Y, g:i A');
             $start_control = id(new AphrontFormStaticControl())->setUser($viewer)->setLabel(pht('Start'))->setValue($start_disabled)->setDisabled(true);
             $end_control = id(new AphrontFormStaticControl())->setUser($viewer)->setLabel(pht('End'))->setValue($end_disabled);
         }
     }
     $projects = id(new AphrontFormTokenizerControl())->setLabel(pht('Projects'))->setName('projects')->setValue($projects)->setUser($viewer)->setDatasource(new PhabricatorProjectDatasource());
     $description = id(new PhabricatorRemarkupControl())->setLabel(pht('Description'))->setName('description')->setValue($description)->setUser($viewer);
     $view_policies = id(new AphrontFormPolicyControl())->setUser($viewer)->setValue($view_policy)->setCapability(PhabricatorPolicyCapability::CAN_VIEW)->setPolicyObject($event)->setPolicies($current_policies)->setSpacePHID($space)->setName('viewPolicy');
     $edit_policies = id(new AphrontFormPolicyControl())->setUser($viewer)->setValue($edit_policy)->setCapability(PhabricatorPolicyCapability::CAN_EDIT)->setPolicyObject($event)->setPolicies($current_policies)->setName('editPolicy');
     $subscribers = id(new AphrontFormTokenizerControl())->setLabel(pht('Subscribers'))->setName('subscribers')->setValue($subscribers)->setUser($viewer)->setDatasource(new PhabricatorMetaMTAMailableDatasource());
     $invitees = id(new AphrontFormTokenizerControl())->setLabel(pht('Invitees'))->setName('invitees')->setValue($invitees)->setUser($viewer)->setDatasource(new PhabricatorMetaMTAMailableDatasource());
     if ($this->isCreate()) {
         $icon_uri = $this->getApplicationURI('icon/');
     } else {
         $icon_uri = $this->getApplicationURI('icon/' . $event->getID() . '/');
     }
     $icon_display = PhabricatorCalendarIcon::renderIconForChooser($icon);
     $icon = id(new AphrontFormChooseButtonControl())->setLabel(pht('Icon'))->setName('icon')->setDisplayValue($icon_display)->setButtonText(pht('Choose Icon...'))->setChooseURI($icon_uri)->setValue($icon);
     $form = id(new AphrontFormView())->addHiddenInput('next', $next_workflow)->addHiddenInput('query', $uri_query)->setUser($viewer)->appendChild($name);
     if ($recurring_date_edit_label) {
         $form->appendControl($recurring_date_edit_label);
     }
     if ($is_recurring_checkbox) {
         $form->appendChild($is_recurring_checkbox);
     }
     if ($recurrence_end_date_control) {
         $form->appendChild($recurrence_end_date_control);
     }
     if ($recurrence_frequency_select) {
         $form->appendControl($recurrence_frequency_select);
     }
     $form->appendChild($all_day_checkbox)->appendChild($start_control)->appendChild($end_control)->appendControl($view_policies)->appendControl($edit_policies)->appendControl($subscribers)->appendControl($invitees)->appendChild($projects)->appendChild($description)->appendChild($icon);
     if ($request->isAjax()) {
         return $this->newDialog()->setTitle($page_title)->setWidth(AphrontDialogView::WIDTH_FULL)->appendForm($form)->addCancelButton($cancel_uri)->addSubmitButton($submit_label);
     }
     $submit = id(new AphrontFormSubmitControl())->addCancelButton($cancel_uri)->setValue($submit_label);
     $form->appendChild($submit);
     $form_box = id(new PHUIObjectBoxView())->setHeaderText($page_title)->setForm($form);
     $crumbs = $this->buildApplicationCrumbs();
     if (!$this->isCreate()) {
         $crumbs->addTextCrumb('E' . $event->getId(), '/E' . $event->getId());
     }
     $crumbs->addTextCrumb($page_title);
     $object_box = id(new PHUIObjectBoxView())->setHeaderText($page_title)->setValidationException($validation_exception)->appendChild($form);
     return $this->buildApplicationPage(array($crumbs, $object_box), array('title' => $page_title));
 }
 private function newICSAttachment(PhabricatorCalendarEvent $event)
 {
     $actor = $this->getActor();
     $ics_data = id(new PhabricatorCalendarICSWriter())->setViewer($actor)->setEvents(array($event))->writeICSDocument();
     $ics_attachment = new PhabricatorMetaMTAAttachment($ics_data, $event->getICSFilename(), 'text/calendar');
     return $ics_attachment;
 }
Exemplo n.º 15
0
<?php

$table = new PhabricatorCalendarEvent();
$conn_w = $table->establishConnection('w');
echo "Assigning PHIDs to events...\n";
foreach (new LiskMigrationIterator($table) as $event) {
    $id = $event->getID();
    echo "Updating event {$id}...\n";
    if ($event->getPHID()) {
        continue;
    }
    queryfx($conn_w, 'UPDATE %T SET phid = %s WHERE id = %d', $table->getTableName(), $table->generatePHID(), $id);
}
echo "Done.\n";
 protected function newEditableObject()
 {
     return PhabricatorCalendarEvent::initializeNewCalendarEvent($this->getViewer());
 }
 protected function loadPage()
 {
     $table = new PhabricatorCalendarEvent();
     $conn_r = $table->establishConnection('r');
     $viewer = $this->getViewer();
     $data = queryfx_all($conn_r, 'SELECT event.* FROM %T event %Q %Q %Q %Q %Q', $table->getTableName(), $this->buildJoinClause($conn_r), $this->buildWhereClause($conn_r), $this->buildGroupClause($conn_r), $this->buildOrderClause($conn_r), $this->buildLimitClause($conn_r));
     $events = $table->loadAllFromArray($data);
     foreach ($events as $event) {
         $event->applyViewerTimezone($this->getViewer());
     }
     if (!$this->generateGhosts) {
         return $events;
     }
     $enforced_end = null;
     foreach ($events as $key => $event) {
         $sequence_start = 0;
         $sequence_end = null;
         $duration = $event->getDateTo() - $event->getDateFrom();
         $end = null;
         $instance_of = $event->getInstanceOfEventPHID();
         if ($instance_of == null && $this->isCancelled !== null) {
             if ($event->getIsCancelled() != $this->isCancelled) {
                 unset($events[$key]);
                 continue;
             }
         }
         if ($event->getIsRecurring() && $instance_of == null) {
             $frequency = $event->getFrequencyUnit();
             $modify_key = '+1 ' . $frequency;
             if ($this->rangeBegin && $this->rangeBegin > $event->getDateFrom()) {
                 $max_date = $this->rangeBegin - $duration;
                 $date = $event->getDateFrom();
                 $datetime = PhabricatorTime::getDateTimeFromEpoch($date, $viewer);
                 while ($date < $max_date) {
                     // TODO: optimize this to not loop through all off-screen events
                     $sequence_start++;
                     $datetime = PhabricatorTime::getDateTimeFromEpoch($date, $viewer);
                     $date = $datetime->modify($modify_key)->format('U');
                 }
                 $start = $this->rangeBegin;
             } else {
                 $start = $event->getDateFrom() - $duration;
             }
             $date = $start;
             $datetime = PhabricatorTime::getDateTimeFromEpoch($date, $viewer);
             if ($this->rangeEnd && $event->getRecurrenceEndDate() && $this->rangeEnd < $event->getRecurrenceEndDate()) {
                 $end = $this->rangeEnd;
             } else {
                 if ($event->getRecurrenceEndDate()) {
                     $end = $event->getRecurrenceEndDate();
                 } else {
                     if ($this->rangeEnd) {
                         $end = $this->rangeEnd;
                     } else {
                         if ($enforced_end) {
                             if ($end) {
                                 $end = min($end, $enforced_end);
                             } else {
                                 $end = $enforced_end;
                             }
                         }
                     }
                 }
             }
             if ($end) {
                 $sequence_end = $sequence_start;
                 while ($date < $end) {
                     $sequence_end++;
                     $datetime->modify($modify_key);
                     $date = $datetime->format('U');
                     if ($sequence_end > $this->getRawResultLimit() + $sequence_start) {
                         break;
                     }
                 }
             } else {
                 $sequence_end = $this->getRawResultLimit() + $sequence_start;
             }
             $sequence_start = max(1, $sequence_start);
             for ($index = $sequence_start; $index < $sequence_end; $index++) {
                 $events[] = $event->generateNthGhost($index, $viewer);
             }
             if (count($events) >= $this->getRawResultLimit()) {
                 $events = msort($events, 'getDateFrom');
                 $events = array_slice($events, 0, $this->getRawResultLimit(), true);
                 $enforced_end = last($events)->getDateFrom();
             }
         }
     }
     $map = array();
     $instance_sequence_pairs = array();
     foreach ($events as $key => $event) {
         if ($event->getIsGhostEvent()) {
             $index = $event->getSequenceIndex();
             $instance_sequence_pairs[] = array($event->getPHID(), $index);
             $map[$event->getPHID()][$index] = $key;
         }
     }
     if (count($instance_sequence_pairs) > 0) {
         $sub_query = id(new PhabricatorCalendarEventQuery())->setViewer($viewer)->setParentQuery($this)->withInstanceSequencePairs($instance_sequence_pairs)->execute();
         foreach ($sub_query as $edited_ghost) {
             $indexes = idx($map, $edited_ghost->getInstanceOfEventPHID());
             $key = idx($indexes, $edited_ghost->getSequenceIndex());
             $events[$key] = $edited_ghost;
         }
         $id_map = array();
         foreach ($events as $key => $event) {
             if ($event->getIsGhostEvent()) {
                 continue;
             }
             if (isset($id_map[$event->getID()])) {
                 unset($events[$key]);
             } else {
                 $id_map[$event->getID()] = true;
             }
         }
     }
     return $events;
 }
<?php

echo pht('Adding %s to events.', 'mailkeys') . "\n";
$table = new PhabricatorCalendarEvent();
$conn_w = $table->establishConnection('w');
$iterator = new LiskMigrationIterator($table);
foreach ($iterator as $event) {
    $id = $event->getID();
    echo pht('Populating event %d...', $id) . "\n";
    queryfx($conn_w, 'UPDATE %T SET mailKey = %s WHERE id = %d', $table->getTableName(), Filesystem::readRandomCharacters(20), $id);
}
echo pht('Done.') . "\n";
 public function canDeleteAnyEvents(PhabricatorUser $viewer, PhabricatorCalendarImport $import)
 {
     $table = new PhabricatorCalendarEvent();
     $conn = $table->establishConnection('r');
     // Using a CalendarEventQuery here was failing oddly in a way that was
     // difficult to reproduce locally (see T11808). Just check the table
     // directly; this is significantly more efficient anyway.
     $any_event = queryfx_all($conn, 'SELECT phid FROM %T WHERE importSourcePHID = %s LIMIT 1', $table->getTableName(), $import->getPHID());
     return (bool) $any_event;
 }
 private function getRecurrenceLimit(PhabricatorCalendarEvent $event, $raw_limit)
 {
     $count = $event->getRecurrenceCount();
     if ($count && $count <= $raw_limit) {
         return $count - 1;
     }
     return $raw_limit;
 }
<?php

$table = new PhabricatorCalendarEvent();
$conn = $table->establishConnection('w');
// Previously, "All Day" events were stored with a start and end date set to
// the earliest possible start and end seconds for the corresponding days. We
// now store all day events with their "date" epochs as UTC, separate from
// individual event times.
$zone_min = new DateTimeZone('Pacific/Midway');
$zone_max = new DateTimeZone('Pacific/Kiritimati');
$zone_utc = new DateTimeZone('UTC');
foreach (new LiskMigrationIterator($table) as $event) {
    // If this event has already migrated, skip it.
    if ($event->getAllDayDateFrom()) {
        continue;
    }
    $is_all_day = $event->getIsAllDay();
    $epoch_min = $event->getDateFrom();
    $epoch_max = $event->getDateTo();
    $date_min = new DateTime('@' . $epoch_min);
    $date_max = new DateTime('@' . $epoch_max);
    if ($is_all_day) {
        $date_min->setTimeZone($zone_min);
        $date_min->modify('+2 days');
        $date_max->setTimeZone($zone_max);
        $date_max->modify('-2 days');
    } else {
        $date_min->setTimeZone($zone_utc);
        $date_max->setTimeZone($zone_utc);
    }
    $string_min = $date_min->format('Y-m-d');
 private function buildDescriptionView(PhabricatorCalendarEvent $event)
 {
     $viewer = $this->getViewer();
     $properties = id(new PHUIPropertyListView())->setUser($viewer);
     if (strlen($event->getDescription())) {
         $description = new PHUIRemarkupView($viewer, $event->getDescription());
         $properties->addTextContent($description);
         return $properties;
     }
     return null;
 }