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; }
<?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; }