1*a1a3b679SAndreas Boehler<?php 2*a1a3b679SAndreas Boehler 3*a1a3b679SAndreas Boehlernamespace Sabre\CalDAV\Notifications; 4*a1a3b679SAndreas Boehler 5*a1a3b679SAndreas Boehleruse Sabre\DAV; 6*a1a3b679SAndreas Boehleruse Sabre\DAV\PropFind; 7*a1a3b679SAndreas Boehleruse Sabre\DAV\INode as BaseINode; 8*a1a3b679SAndreas Boehleruse Sabre\DAV\ServerPlugin; 9*a1a3b679SAndreas Boehleruse Sabre\DAV\Server; 10*a1a3b679SAndreas Boehleruse Sabre\DAVACL; 11*a1a3b679SAndreas Boehleruse Sabre\HTTP\RequestInterface; 12*a1a3b679SAndreas Boehleruse Sabre\HTTP\ResponseInterface; 13*a1a3b679SAndreas Boehler 14*a1a3b679SAndreas Boehler/** 15*a1a3b679SAndreas Boehler * Notifications plugin 16*a1a3b679SAndreas Boehler * 17*a1a3b679SAndreas Boehler * This plugin implements several features required by the caldav-notification 18*a1a3b679SAndreas Boehler * draft specification. 19*a1a3b679SAndreas Boehler * 20*a1a3b679SAndreas Boehler * Before version 2.1.0 this functionality was part of Sabre\CalDAV\Plugin but 21*a1a3b679SAndreas Boehler * this has since been split up. 22*a1a3b679SAndreas Boehler * 23*a1a3b679SAndreas Boehler * @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/). 24*a1a3b679SAndreas Boehler * @author Evert Pot (http://evertpot.com/) 25*a1a3b679SAndreas Boehler * @license http://sabre.io/license/ Modified BSD License 26*a1a3b679SAndreas Boehler */ 27*a1a3b679SAndreas Boehlerclass Plugin extends ServerPlugin { 28*a1a3b679SAndreas Boehler 29*a1a3b679SAndreas Boehler /** 30*a1a3b679SAndreas Boehler * This is the namespace for the proprietary calendarserver extensions 31*a1a3b679SAndreas Boehler */ 32*a1a3b679SAndreas Boehler const NS_CALENDARSERVER = 'http://calendarserver.org/ns/'; 33*a1a3b679SAndreas Boehler 34*a1a3b679SAndreas Boehler /** 35*a1a3b679SAndreas Boehler * Reference to the main server object. 36*a1a3b679SAndreas Boehler * 37*a1a3b679SAndreas Boehler * @var Server 38*a1a3b679SAndreas Boehler */ 39*a1a3b679SAndreas Boehler protected $server; 40*a1a3b679SAndreas Boehler 41*a1a3b679SAndreas Boehler /** 42*a1a3b679SAndreas Boehler * Returns a plugin name. 43*a1a3b679SAndreas Boehler * 44*a1a3b679SAndreas Boehler * Using this name other plugins will be able to access other plugins 45*a1a3b679SAndreas Boehler * using \Sabre\DAV\Server::getPlugin 46*a1a3b679SAndreas Boehler * 47*a1a3b679SAndreas Boehler * @return string 48*a1a3b679SAndreas Boehler */ 49*a1a3b679SAndreas Boehler function getPluginName() { 50*a1a3b679SAndreas Boehler 51*a1a3b679SAndreas Boehler return 'notifications'; 52*a1a3b679SAndreas Boehler 53*a1a3b679SAndreas Boehler } 54*a1a3b679SAndreas Boehler 55*a1a3b679SAndreas Boehler /** 56*a1a3b679SAndreas Boehler * This initializes the plugin. 57*a1a3b679SAndreas Boehler * 58*a1a3b679SAndreas Boehler * This function is called by Sabre\DAV\Server, after 59*a1a3b679SAndreas Boehler * addPlugin is called. 60*a1a3b679SAndreas Boehler * 61*a1a3b679SAndreas Boehler * This method should set up the required event subscriptions. 62*a1a3b679SAndreas Boehler * 63*a1a3b679SAndreas Boehler * @param Server $server 64*a1a3b679SAndreas Boehler * @return void 65*a1a3b679SAndreas Boehler */ 66*a1a3b679SAndreas Boehler function initialize(Server $server) { 67*a1a3b679SAndreas Boehler 68*a1a3b679SAndreas Boehler $this->server = $server; 69*a1a3b679SAndreas Boehler $server->on('method:GET', [$this, 'httpGet'], 90); 70*a1a3b679SAndreas Boehler $server->on('propFind', [$this, 'propFind']); 71*a1a3b679SAndreas Boehler 72*a1a3b679SAndreas Boehler $server->xml->namespaceMap[self::NS_CALENDARSERVER] = 'cs'; 73*a1a3b679SAndreas Boehler $server->resourceTypeMapping['\\Sabre\\CalDAV\\Notifications\\ICollection'] = '{' . self::NS_CALENDARSERVER . '}notification'; 74*a1a3b679SAndreas Boehler 75*a1a3b679SAndreas Boehler array_push($server->protectedProperties, 76*a1a3b679SAndreas Boehler '{' . self::NS_CALENDARSERVER . '}notification-URL', 77*a1a3b679SAndreas Boehler '{' . self::NS_CALENDARSERVER . '}notificationtype' 78*a1a3b679SAndreas Boehler ); 79*a1a3b679SAndreas Boehler 80*a1a3b679SAndreas Boehler } 81*a1a3b679SAndreas Boehler 82*a1a3b679SAndreas Boehler /** 83*a1a3b679SAndreas Boehler * PropFind 84*a1a3b679SAndreas Boehler * 85*a1a3b679SAndreas Boehler * @param PropFind $propFind 86*a1a3b679SAndreas Boehler * @param BaseINode $node 87*a1a3b679SAndreas Boehler * @return void 88*a1a3b679SAndreas Boehler */ 89*a1a3b679SAndreas Boehler function propFind(PropFind $propFind, BaseINode $node) { 90*a1a3b679SAndreas Boehler 91*a1a3b679SAndreas Boehler $caldavPlugin = $this->server->getPlugin('caldav'); 92*a1a3b679SAndreas Boehler 93*a1a3b679SAndreas Boehler if ($node instanceof DAVACL\IPrincipal) { 94*a1a3b679SAndreas Boehler 95*a1a3b679SAndreas Boehler $principalUrl = $node->getPrincipalUrl(); 96*a1a3b679SAndreas Boehler 97*a1a3b679SAndreas Boehler // notification-URL property 98*a1a3b679SAndreas Boehler $propFind->handle('{' . self::NS_CALENDARSERVER . '}notification-URL', function() use ($principalUrl, $caldavPlugin) { 99*a1a3b679SAndreas Boehler 100*a1a3b679SAndreas Boehler $notificationPath = $caldavPlugin->getCalendarHomeForPrincipal($principalUrl) . '/notifications/'; 101*a1a3b679SAndreas Boehler return new DAV\Xml\Property\Href($notificationPath); 102*a1a3b679SAndreas Boehler 103*a1a3b679SAndreas Boehler }); 104*a1a3b679SAndreas Boehler 105*a1a3b679SAndreas Boehler } 106*a1a3b679SAndreas Boehler 107*a1a3b679SAndreas Boehler if ($node instanceof INode) { 108*a1a3b679SAndreas Boehler 109*a1a3b679SAndreas Boehler $propFind->handle( 110*a1a3b679SAndreas Boehler '{' . self::NS_CALENDARSERVER . '}notificationtype', 111*a1a3b679SAndreas Boehler [$node, 'getNotificationType'] 112*a1a3b679SAndreas Boehler ); 113*a1a3b679SAndreas Boehler 114*a1a3b679SAndreas Boehler } 115*a1a3b679SAndreas Boehler 116*a1a3b679SAndreas Boehler } 117*a1a3b679SAndreas Boehler 118*a1a3b679SAndreas Boehler /** 119*a1a3b679SAndreas Boehler * This event is triggered before the usual GET request handler. 120*a1a3b679SAndreas Boehler * 121*a1a3b679SAndreas Boehler * We use this to intercept GET calls to notification nodes, and return the 122*a1a3b679SAndreas Boehler * proper response. 123*a1a3b679SAndreas Boehler * 124*a1a3b679SAndreas Boehler * @param RequestInterface $request 125*a1a3b679SAndreas Boehler * @param ResponseInterface $response 126*a1a3b679SAndreas Boehler * @return void 127*a1a3b679SAndreas Boehler */ 128*a1a3b679SAndreas Boehler function httpGet(RequestInterface $request, ResponseInterface $response) { 129*a1a3b679SAndreas Boehler 130*a1a3b679SAndreas Boehler $path = $request->getPath(); 131*a1a3b679SAndreas Boehler 132*a1a3b679SAndreas Boehler try { 133*a1a3b679SAndreas Boehler $node = $this->server->tree->getNodeForPath($path); 134*a1a3b679SAndreas Boehler } catch (DAV\Exception\NotFound $e) { 135*a1a3b679SAndreas Boehler return; 136*a1a3b679SAndreas Boehler } 137*a1a3b679SAndreas Boehler 138*a1a3b679SAndreas Boehler if (!$node instanceof INode) 139*a1a3b679SAndreas Boehler return; 140*a1a3b679SAndreas Boehler 141*a1a3b679SAndreas Boehler $writer = $this->server->xml->getWriter(); 142*a1a3b679SAndreas Boehler $writer->contextUri = $this->server->getBaseUri(); 143*a1a3b679SAndreas Boehler $writer->openMemory(); 144*a1a3b679SAndreas Boehler $writer->startDocument('1.0', 'UTF-8'); 145*a1a3b679SAndreas Boehler $writer->startElement('{http://calendarserver.org/ns/}notification'); 146*a1a3b679SAndreas Boehler $node->getNotificationType()->xmlSerializeFull($writer); 147*a1a3b679SAndreas Boehler $writer->endElement(); 148*a1a3b679SAndreas Boehler 149*a1a3b679SAndreas Boehler $response->setHeader('Content-Type', 'application/xml'); 150*a1a3b679SAndreas Boehler $response->setHeader('ETag', $node->getETag()); 151*a1a3b679SAndreas Boehler $response->setStatus(200); 152*a1a3b679SAndreas Boehler $response->setBody($writer->outputMemory()); 153*a1a3b679SAndreas Boehler 154*a1a3b679SAndreas Boehler // Return false to break the event chain. 155*a1a3b679SAndreas Boehler return false; 156*a1a3b679SAndreas Boehler 157*a1a3b679SAndreas Boehler } 158*a1a3b679SAndreas Boehler 159*a1a3b679SAndreas Boehler /** 160*a1a3b679SAndreas Boehler * Returns a bunch of meta-data about the plugin. 161*a1a3b679SAndreas Boehler * 162*a1a3b679SAndreas Boehler * Providing this information is optional, and is mainly displayed by the 163*a1a3b679SAndreas Boehler * Browser plugin. 164*a1a3b679SAndreas Boehler * 165*a1a3b679SAndreas Boehler * The description key in the returned array may contain html and will not 166*a1a3b679SAndreas Boehler * be sanitized. 167*a1a3b679SAndreas Boehler * 168*a1a3b679SAndreas Boehler * @return array 169*a1a3b679SAndreas Boehler */ 170*a1a3b679SAndreas Boehler function getPluginInfo() { 171*a1a3b679SAndreas Boehler 172*a1a3b679SAndreas Boehler return [ 173*a1a3b679SAndreas Boehler 'name' => $this->getPluginName(), 174*a1a3b679SAndreas Boehler 'description' => 'Adds support for caldav-notifications, which is required to enable caldav-sharing.', 175*a1a3b679SAndreas Boehler 'link' => 'http://sabre.io/dav/caldav-sharing/', 176*a1a3b679SAndreas Boehler ]; 177*a1a3b679SAndreas Boehler 178*a1a3b679SAndreas Boehler } 179*a1a3b679SAndreas Boehler 180*a1a3b679SAndreas Boehler} 181