/** * This method handler is invoked during fetching of properties. * * We use this event to add calendar-auto-schedule-specific properties. * * @param PropFind $propFind * @param INode $node * @return void */ function propFind(PropFind $propFind, INode $node) { if ($node instanceof DAVACL\IPrincipal) { $caldavPlugin = $this->server->getPlugin('caldav'); $principalUrl = $node->getPrincipalUrl(); // schedule-outbox-URL property $propFind->handle('{' . self::NS_CALDAV . '}schedule-outbox-URL', function () use($principalUrl, $caldavPlugin) { $calendarHomePath = $caldavPlugin->getCalendarHomeForPrincipal($principalUrl); if (!$calendarHomePath) { return null; } $outboxPath = $calendarHomePath . '/outbox/'; return new Href($outboxPath); }); // schedule-inbox-URL property $propFind->handle('{' . self::NS_CALDAV . '}schedule-inbox-URL', function () use($principalUrl, $caldavPlugin) { $calendarHomePath = $caldavPlugin->getCalendarHomeForPrincipal($principalUrl); if (!$calendarHomePath) { return null; } $inboxPath = $calendarHomePath . '/inbox/'; return new Href($inboxPath); }); $propFind->handle('{' . self::NS_CALDAV . '}schedule-default-calendar-URL', function () use($principalUrl, $caldavPlugin) { // We don't support customizing this property yet, so in the // meantime we just grab the first calendar in the home-set. $calendarHomePath = $caldavPlugin->getCalendarHomeForPrincipal($principalUrl); if (!$calendarHomePath) { return null; } $sccs = '{' . self::NS_CALDAV . '}supported-calendar-component-set'; $result = $this->server->getPropertiesForPath($calendarHomePath, ['{DAV:}resourcetype', $sccs], 1); foreach ($result as $child) { if (!isset($child[200]['{DAV:}resourcetype']) || !$child[200]['{DAV:}resourcetype']->is('{' . self::NS_CALDAV . '}calendar') || $child[200]['{DAV:}resourcetype']->is('{http://calendarserver.org/ns/}shared')) { // Node is either not a calendar or a shared instance. continue; } if (!isset($child[200][$sccs]) || in_array('VEVENT', $child[200][$sccs]->getValue())) { // Either there is no supported-calendar-component-set // (which is fine) or we found one that supports VEVENT. return new Href($child['href']); } } }); // The server currently reports every principal to be of type // 'INDIVIDUAL' $propFind->handle('{' . self::NS_CALDAV . '}calendar-user-type', function () { return 'INDIVIDUAL'; }); } // Mapping the old property to the new property. $propFind->handle('{http://calendarserver.org/ns/}calendar-availability', function () use($propFind, $node) { // In case it wasn't clear, the only difference is that we map the // old property to a different namespace. $availProp = '{' . self::NS_CALDAV . '}calendar-availability'; $subPropFind = new PropFind($propFind->getPath(), [$availProp]); $this->server->getPropertiesByNode($subPropFind, $node); $propFind->set('{http://calendarserver.org/ns/}calendar-availability', $subPropFind->get($availProp), $subPropFind->getStatus($availProp)); }); }
/** * Prepare propfind response for the given nodes * * @param string[] $requestedProps requested properties * @param Node[] nodes nodes for which to fetch and prepare responses * @return Response[] */ public function prepareResponses($requestedProps, $nodes) { $responses = []; foreach ($nodes as $node) { $propFind = new PropFind($node->getPath(), $requestedProps); $this->server->getPropertiesByNode($propFind, $node); // copied from Sabre Server's getPropertiesForPath $result = $propFind->getResultForMultiStatus(); $result['href'] = $propFind->getPath(); $resourceType = $this->server->getResourceTypeForNode($node); if (in_array('{DAV:}collection', $resourceType) || in_array('{DAV:}principal', $resourceType)) { $result['href'] .= '/'; } $responses[] = new Response(rtrim($this->server->getBaseUri(), '/') . $node->getPath(), $result, 200); } return $responses; }