@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at recaptime-dev/main 100 lines 3.0 kB view raw
1<?php 2 3final 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}