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