mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-27 01:02:42 +01:00
Document how to export Calendar events
Summary: Ref T10747. This explains how exports work. Also make mail exports use the same logic as other stuff. Test Plan: Read documentation. Did some exports. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10747 Differential Revision: https://secure.phabricator.com/D16680
This commit is contained in:
parent
4819446fe5
commit
ff97ed2195
5 changed files with 156 additions and 38 deletions
|
@ -2094,6 +2094,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorCalendarExportViewController' => 'applications/calendar/controller/PhabricatorCalendarExportViewController.php',
|
'PhabricatorCalendarExportViewController' => 'applications/calendar/controller/PhabricatorCalendarExportViewController.php',
|
||||||
'PhabricatorCalendarHoliday' => 'applications/calendar/storage/PhabricatorCalendarHoliday.php',
|
'PhabricatorCalendarHoliday' => 'applications/calendar/storage/PhabricatorCalendarHoliday.php',
|
||||||
'PhabricatorCalendarHolidayTestCase' => 'applications/calendar/storage/__tests__/PhabricatorCalendarHolidayTestCase.php',
|
'PhabricatorCalendarHolidayTestCase' => 'applications/calendar/storage/__tests__/PhabricatorCalendarHolidayTestCase.php',
|
||||||
|
'PhabricatorCalendarICSWriter' => 'applications/calendar/util/PhabricatorCalendarICSWriter.php',
|
||||||
'PhabricatorCalendarIconSet' => 'applications/calendar/icon/PhabricatorCalendarIconSet.php',
|
'PhabricatorCalendarIconSet' => 'applications/calendar/icon/PhabricatorCalendarIconSet.php',
|
||||||
'PhabricatorCalendarRemarkupRule' => 'applications/calendar/remarkup/PhabricatorCalendarRemarkupRule.php',
|
'PhabricatorCalendarRemarkupRule' => 'applications/calendar/remarkup/PhabricatorCalendarRemarkupRule.php',
|
||||||
'PhabricatorCalendarReplyHandler' => 'applications/calendar/mail/PhabricatorCalendarReplyHandler.php',
|
'PhabricatorCalendarReplyHandler' => 'applications/calendar/mail/PhabricatorCalendarReplyHandler.php',
|
||||||
|
@ -6866,6 +6867,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorCalendarExportViewController' => 'PhabricatorCalendarController',
|
'PhabricatorCalendarExportViewController' => 'PhabricatorCalendarController',
|
||||||
'PhabricatorCalendarHoliday' => 'PhabricatorCalendarDAO',
|
'PhabricatorCalendarHoliday' => 'PhabricatorCalendarDAO',
|
||||||
'PhabricatorCalendarHolidayTestCase' => 'PhabricatorTestCase',
|
'PhabricatorCalendarHolidayTestCase' => 'PhabricatorTestCase',
|
||||||
|
'PhabricatorCalendarICSWriter' => 'Phobject',
|
||||||
'PhabricatorCalendarIconSet' => 'PhabricatorIconSet',
|
'PhabricatorCalendarIconSet' => 'PhabricatorIconSet',
|
||||||
'PhabricatorCalendarRemarkupRule' => 'PhabricatorObjectRemarkupRule',
|
'PhabricatorCalendarRemarkupRule' => 'PhabricatorObjectRemarkupRule',
|
||||||
'PhabricatorCalendarReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler',
|
'PhabricatorCalendarReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler',
|
||||||
|
|
|
@ -6,34 +6,11 @@ abstract class PhabricatorCalendarController extends PhabricatorController {
|
||||||
PhabricatorUser $viewer,
|
PhabricatorUser $viewer,
|
||||||
$file_name,
|
$file_name,
|
||||||
array $events) {
|
array $events) {
|
||||||
$events = mpull($events, null, 'getPHID');
|
|
||||||
|
|
||||||
if ($events) {
|
$ics_data = id(new PhabricatorCalendarICSWriter())
|
||||||
$child_map = id(new PhabricatorCalendarEventQuery())
|
->setViewer($viewer)
|
||||||
->setViewer($viewer)
|
->setEvents($events)
|
||||||
->withParentEventPHIDs(array_keys($events))
|
->writeICSDocument();
|
||||||
->execute();
|
|
||||||
$child_map = mpull($child_map, null, 'getPHID');
|
|
||||||
} else {
|
|
||||||
$child_map = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
$all_events = $events + $child_map;
|
|
||||||
$child_groups = mgroup($child_map, 'getInstanceOfEventPHID');
|
|
||||||
|
|
||||||
$document_node = new PhutilCalendarDocumentNode();
|
|
||||||
|
|
||||||
foreach ($all_events as $event) {
|
|
||||||
$child_events = idx($child_groups, $event->getPHID(), array());
|
|
||||||
$event_node = $event->newIntermediateEventNode($viewer, $child_events);
|
|
||||||
$document_node->appendChild($event_node);
|
|
||||||
}
|
|
||||||
|
|
||||||
$root_node = id(new PhutilCalendarRootNode())
|
|
||||||
->appendChild($document_node);
|
|
||||||
|
|
||||||
$ics_data = id(new PhutilICSWriter())
|
|
||||||
->writeICSDocument($root_node);
|
|
||||||
|
|
||||||
return id(new AphrontFileResponse())
|
return id(new AphrontFileResponse())
|
||||||
->setDownload($file_name)
|
->setDownload($file_name)
|
||||||
|
|
|
@ -309,16 +309,10 @@ final class PhabricatorCalendarEventEditor
|
||||||
PhabricatorCalendarEvent $event) {
|
PhabricatorCalendarEvent $event) {
|
||||||
$actor = $this->getActor();
|
$actor = $this->getActor();
|
||||||
|
|
||||||
$event_node = $event->newIntermediateEventNode($actor);
|
$ics_data = id(new PhabricatorCalendarICSWriter())
|
||||||
|
->setViewer($actor)
|
||||||
$document_node = id(new PhutilCalendarDocumentNode())
|
->setEvents(array($event))
|
||||||
->appendChild($event_node);
|
->writeICSDocument();
|
||||||
|
|
||||||
$root_node = id(new PhutilCalendarRootNode())
|
|
||||||
->appendChild($document_node);
|
|
||||||
|
|
||||||
$ics_data = id(new PhutilICSWriter())
|
|
||||||
->writeICSDocument($root_node);
|
|
||||||
|
|
||||||
$ics_attachment = new PhabricatorMetaMTAAttachment(
|
$ics_attachment = new PhabricatorMetaMTAAttachment(
|
||||||
$ics_data,
|
$ics_data,
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorCalendarICSWriter extends Phobject {
|
||||||
|
|
||||||
|
private $viewer;
|
||||||
|
private $events = array();
|
||||||
|
|
||||||
|
public function setViewer(PhabricatorUser $viewer) {
|
||||||
|
$this->viewer = $viewer;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getViewer() {
|
||||||
|
return $this->viewer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setEvents(array $events) {
|
||||||
|
assert_instances_of($events, 'PhabricatorCalendarEvent');
|
||||||
|
$this->events = $events;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEvents() {
|
||||||
|
return $this->events;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function writeICSDocument() {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
$events = $this->getEvents();
|
||||||
|
|
||||||
|
$events = mpull($events, null, 'getPHID');
|
||||||
|
|
||||||
|
if ($events) {
|
||||||
|
$child_map = id(new PhabricatorCalendarEventQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withParentEventPHIDs(array_keys($events))
|
||||||
|
->execute();
|
||||||
|
$child_map = mpull($child_map, null, 'getPHID');
|
||||||
|
} else {
|
||||||
|
$child_map = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$all_events = $events + $child_map;
|
||||||
|
$child_groups = mgroup($child_map, 'getInstanceOfEventPHID');
|
||||||
|
|
||||||
|
$document_node = new PhutilCalendarDocumentNode();
|
||||||
|
|
||||||
|
foreach ($all_events as $event) {
|
||||||
|
$child_events = idx($child_groups, $event->getPHID(), array());
|
||||||
|
$event_node = $event->newIntermediateEventNode($viewer, $child_events);
|
||||||
|
$document_node->appendChild($event_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
$root_node = id(new PhutilCalendarRootNode())
|
||||||
|
->appendChild($document_node);
|
||||||
|
|
||||||
|
return id(new PhutilICSWriter())
|
||||||
|
->writeICSDocument($root_node);
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,4 +9,89 @@ Overview
|
||||||
IMPORTANT: Calendar is a prototype application. See
|
IMPORTANT: Calendar is a prototype application. See
|
||||||
@{article:User Guide: Prototype Applications}.
|
@{article:User Guide: Prototype Applications}.
|
||||||
|
|
||||||
Coming soon!
|
You can export events from Phabricator to other calendar applications like
|
||||||
|
**Google Calendar** or **Calendar.app**. This document will guide you through
|
||||||
|
how to export event data from Phabricator.
|
||||||
|
|
||||||
|
When you export events into another application, they generally will not be
|
||||||
|
editable from that application. Exporting events allows you to create one
|
||||||
|
calendar that shows all the events you care about in whatever application you
|
||||||
|
prefer (so you can keep track of everything you need to do), but does not let
|
||||||
|
you edit Phabricator events from another application.
|
||||||
|
|
||||||
|
When exporting events, you can either export individual events one at a time
|
||||||
|
or export an entire group of events (for example, all events you are attending).
|
||||||
|
|
||||||
|
|
||||||
|
Exporting a Single Event
|
||||||
|
========================
|
||||||
|
|
||||||
|
To export a single event, visit the event detail page and click
|
||||||
|
{nav Export as .ics}. This will download an `.ics` file which you can import
|
||||||
|
into most other calendar applications.
|
||||||
|
|
||||||
|
Mail you receive about events also has a copy of this `.ics` file attached to
|
||||||
|
it. You can import this `.ics` file directly.
|
||||||
|
|
||||||
|
In **Google Calendar**, use {nav Other Calendars > Import Calendar} to import
|
||||||
|
the `.ics` file.
|
||||||
|
|
||||||
|
In **Calendar.app**, use {nav File > Import...} to import the `.ics` file, or
|
||||||
|
drag the `.ics` file onto your calendar.
|
||||||
|
|
||||||
|
When you export a recurring event, the `.ics` file will contain information
|
||||||
|
about the entire event series.
|
||||||
|
|
||||||
|
If you want to update event information later, you can just repeat this
|
||||||
|
process. Calendar applications will update the existing event if you've
|
||||||
|
previously imported an older version of it.
|
||||||
|
|
||||||
|
|
||||||
|
Exporting a Group of Events
|
||||||
|
===========================
|
||||||
|
|
||||||
|
You can export a group of events matching an arbitrary query (like all events
|
||||||
|
you are attending) to keep different calendars in sync.
|
||||||
|
|
||||||
|
To export a group of events:
|
||||||
|
|
||||||
|
- Run a query in Calendar which selects the events you want to export.
|
||||||
|
- Example: All events you are attending.
|
||||||
|
- Example: All events you are invited to.
|
||||||
|
- Example: All events tagged `#meetup`.
|
||||||
|
- Select the {nav Use Results... > Export Query as .ics} action to turn
|
||||||
|
the query into an export.
|
||||||
|
- Name the export with a descritive name.
|
||||||
|
- Select a policy mode for the export (see below for discussion).
|
||||||
|
- Click {nav Create New Export} to finish the process.
|
||||||
|
|
||||||
|
The **policy modes** for exports are:
|
||||||
|
|
||||||
|
- **Public**: Only public information (visible to logged-out users) will
|
||||||
|
be exported. This mode is not available if your install does not have
|
||||||
|
public information (per `policy.allow-public` in Config).
|
||||||
|
- **Privileged**: All event information will be exported. This means that
|
||||||
|
anyone who knows the export URI can see ALL of the related event
|
||||||
|
information, as though they were logged in with your account.
|
||||||
|
|
||||||
|
WARNING: Anyone who learns the URI for an export can see the data you choose
|
||||||
|
to export, even if they don't have a Phabricator account! Be careful about how
|
||||||
|
much data you export and treat the URI as a secret. If you accidentally share
|
||||||
|
a URI, you can disable the export.
|
||||||
|
|
||||||
|
After finishing the process, you'll see a screen with some details about the
|
||||||
|
export and an **ICS URI**. This URI allows you to import the events which match
|
||||||
|
the query into another calendar application.
|
||||||
|
|
||||||
|
In **Google Calendar**, use {nav Other Calendars > Add by URL} to import the
|
||||||
|
URI.
|
||||||
|
|
||||||
|
In **Calendar.app**, use {nav File > New Calendar Subscription...} to subscribe
|
||||||
|
to the URI.
|
||||||
|
|
||||||
|
Next Steps
|
||||||
|
==========
|
||||||
|
|
||||||
|
Continue by:
|
||||||
|
|
||||||
|
- returning to the @{article:Calendar User Guide}.
|
||||||
|
|
Loading…
Reference in a new issue