Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/calendar/controller/PhabricatorCalendarExportICSController.php
12256 views
1
<?php
2
3
final class PhabricatorCalendarExportICSController
4
extends PhabricatorCalendarController {
5
6
public function shouldRequireLogin() {
7
// Export URIs are available if you know the secret key. We can't do any
8
// other kind of authentication because third-party applications like
9
// Google Calendar and Calendar.app need to be able to fetch these URIs.
10
return false;
11
}
12
13
public function handleRequest(AphrontRequest $request) {
14
$omnipotent = PhabricatorUser::getOmnipotentUser();
15
16
// NOTE: We're using the omnipotent viewer to fetch the export, but the
17
// URI must contain the secret key. Once we load the export we'll figure
18
// out who the effective viewer is.
19
$export = id(new PhabricatorCalendarExportQuery())
20
->setViewer($omnipotent)
21
->withSecretKeys(array($request->getURIData('secretKey')))
22
->executeOne();
23
if (!$export) {
24
return new Aphront404Response();
25
}
26
27
if ($export->getIsDisabled()) {
28
return new Aphront404Response();
29
}
30
31
$author = id(new PhabricatorPeopleQuery())
32
->setViewer($omnipotent)
33
->withPHIDs(array($export->getAuthorPHID()))
34
->needUserSettings(true)
35
->executeOne();
36
if (!$author) {
37
return new Aphront404Response();
38
}
39
40
$mode = $export->getPolicyMode();
41
switch ($mode) {
42
case PhabricatorCalendarExport::MODE_PUBLIC:
43
$viewer = new PhabricatorUser();
44
break;
45
case PhabricatorCalendarExport::MODE_PRIVILEGED:
46
$viewer = $author;
47
break;
48
default:
49
throw new Exception(
50
pht(
51
'This export has an invalid mode ("%s").',
52
$mode));
53
}
54
55
$engine = id(new PhabricatorCalendarEventSearchEngine())
56
->setViewer($viewer);
57
58
$query_key = $export->getQueryKey();
59
$saved = id(new PhabricatorSavedQueryQuery())
60
->setViewer($omnipotent)
61
->withEngineClassNames(array(get_class($engine)))
62
->withQueryKeys(array($query_key))
63
->executeOne();
64
if (!$saved) {
65
$saved = $engine->buildSavedQueryFromBuiltin($query_key);
66
}
67
68
if (!$saved) {
69
return new Aphront404Response();
70
}
71
72
$saved = clone $saved;
73
74
// Mark this as a query for export, so we get the correct ghost/recurring
75
// behaviors. We also want to load all matching events.
76
$saved->setParameter('export', true);
77
$saved->setParameter('limit', 0xFFFF);
78
79
// Remove any range constraints. We always export all matching events into
80
// ICS files.
81
$saved->setParameter('rangeStart', null);
82
$saved->setParameter('rangeEnd', null);
83
$saved->setParameter('upcoming', null);
84
85
// The "month" and "day" display modes imply time ranges.
86
$saved->setParameter('display', 'list');
87
88
$query = $engine->buildQueryFromSavedQuery($saved);
89
90
$events = $query
91
->setViewer($viewer)
92
->execute();
93
94
return $this->newICSResponse(
95
$viewer,
96
$export->getICSFilename(),
97
$events);
98
}
99
100
}
101
102