xref: /plugin/davcal/vendor/sabre/dav/lib/CalDAV/SharingPlugin.php (revision a1a3b6794e0e143a4a8b51d3185ce2d339be61ab)
1*a1a3b679SAndreas Boehler<?php
2*a1a3b679SAndreas Boehler
3*a1a3b679SAndreas Boehlernamespace Sabre\CalDAV;
4*a1a3b679SAndreas Boehler
5*a1a3b679SAndreas Boehleruse Sabre\DAV;
6*a1a3b679SAndreas Boehleruse Sabre\DAV\Xml\Property\Href;
7*a1a3b679SAndreas Boehleruse Sabre\HTTP\RequestInterface;
8*a1a3b679SAndreas Boehleruse Sabre\HTTP\ResponseInterface;
9*a1a3b679SAndreas Boehler
10*a1a3b679SAndreas Boehler/**
11*a1a3b679SAndreas Boehler * This plugin implements support for caldav sharing.
12*a1a3b679SAndreas Boehler *
13*a1a3b679SAndreas Boehler * This spec is defined at:
14*a1a3b679SAndreas Boehler * http://svn.calendarserver.org/repository/calendarserver/CalendarServer/trunk/doc/Extensions/caldav-sharing.txt
15*a1a3b679SAndreas Boehler *
16*a1a3b679SAndreas Boehler * See:
17*a1a3b679SAndreas Boehler * Sabre\CalDAV\Backend\SharingSupport for all the documentation.
18*a1a3b679SAndreas Boehler *
19*a1a3b679SAndreas Boehler * Note: This feature is experimental, and may change in between different
20*a1a3b679SAndreas Boehler * SabreDAV versions.
21*a1a3b679SAndreas Boehler *
22*a1a3b679SAndreas Boehler * @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/).
23*a1a3b679SAndreas Boehler * @author Evert Pot (http://evertpot.com/)
24*a1a3b679SAndreas Boehler * @license http://sabre.io/license/ Modified BSD License
25*a1a3b679SAndreas Boehler */
26*a1a3b679SAndreas Boehlerclass SharingPlugin extends DAV\ServerPlugin {
27*a1a3b679SAndreas Boehler
28*a1a3b679SAndreas Boehler    /**
29*a1a3b679SAndreas Boehler     * These are the various status constants used by sharing-messages.
30*a1a3b679SAndreas Boehler     */
31*a1a3b679SAndreas Boehler    const STATUS_ACCEPTED = 1;
32*a1a3b679SAndreas Boehler    const STATUS_DECLINED = 2;
33*a1a3b679SAndreas Boehler    const STATUS_DELETED = 3;
34*a1a3b679SAndreas Boehler    const STATUS_NORESPONSE = 4;
35*a1a3b679SAndreas Boehler    const STATUS_INVALID = 5;
36*a1a3b679SAndreas Boehler
37*a1a3b679SAndreas Boehler    /**
38*a1a3b679SAndreas Boehler     * Reference to SabreDAV server object.
39*a1a3b679SAndreas Boehler     *
40*a1a3b679SAndreas Boehler     * @var Sabre\DAV\Server
41*a1a3b679SAndreas Boehler     */
42*a1a3b679SAndreas Boehler    protected $server;
43*a1a3b679SAndreas Boehler
44*a1a3b679SAndreas Boehler    /**
45*a1a3b679SAndreas Boehler     * This method should return a list of server-features.
46*a1a3b679SAndreas Boehler     *
47*a1a3b679SAndreas Boehler     * This is for example 'versioning' and is added to the DAV: header
48*a1a3b679SAndreas Boehler     * in an OPTIONS response.
49*a1a3b679SAndreas Boehler     *
50*a1a3b679SAndreas Boehler     * @return array
51*a1a3b679SAndreas Boehler     */
52*a1a3b679SAndreas Boehler    function getFeatures() {
53*a1a3b679SAndreas Boehler
54*a1a3b679SAndreas Boehler        return ['calendarserver-sharing'];
55*a1a3b679SAndreas Boehler
56*a1a3b679SAndreas Boehler    }
57*a1a3b679SAndreas Boehler
58*a1a3b679SAndreas Boehler    /**
59*a1a3b679SAndreas Boehler     * Returns a plugin name.
60*a1a3b679SAndreas Boehler     *
61*a1a3b679SAndreas Boehler     * Using this name other plugins will be able to access other plugins
62*a1a3b679SAndreas Boehler     * using Sabre\DAV\Server::getPlugin
63*a1a3b679SAndreas Boehler     *
64*a1a3b679SAndreas Boehler     * @return string
65*a1a3b679SAndreas Boehler     */
66*a1a3b679SAndreas Boehler    function getPluginName() {
67*a1a3b679SAndreas Boehler
68*a1a3b679SAndreas Boehler        return 'caldav-sharing';
69*a1a3b679SAndreas Boehler
70*a1a3b679SAndreas Boehler    }
71*a1a3b679SAndreas Boehler
72*a1a3b679SAndreas Boehler    /**
73*a1a3b679SAndreas Boehler     * This initializes the plugin.
74*a1a3b679SAndreas Boehler     *
75*a1a3b679SAndreas Boehler     * This function is called by Sabre\DAV\Server, after
76*a1a3b679SAndreas Boehler     * addPlugin is called.
77*a1a3b679SAndreas Boehler     *
78*a1a3b679SAndreas Boehler     * This method should set up the required event subscriptions.
79*a1a3b679SAndreas Boehler     *
80*a1a3b679SAndreas Boehler     * @param DAV\Server $server
81*a1a3b679SAndreas Boehler     * @return void
82*a1a3b679SAndreas Boehler     */
83*a1a3b679SAndreas Boehler    function initialize(DAV\Server $server) {
84*a1a3b679SAndreas Boehler
85*a1a3b679SAndreas Boehler        $this->server = $server;
86*a1a3b679SAndreas Boehler        $server->resourceTypeMapping['Sabre\\CalDAV\\ISharedCalendar'] = '{' . Plugin::NS_CALENDARSERVER . '}shared';
87*a1a3b679SAndreas Boehler
88*a1a3b679SAndreas Boehler        array_push(
89*a1a3b679SAndreas Boehler            $this->server->protectedProperties,
90*a1a3b679SAndreas Boehler            '{' . Plugin::NS_CALENDARSERVER . '}invite',
91*a1a3b679SAndreas Boehler            '{' . Plugin::NS_CALENDARSERVER . '}allowed-sharing-modes',
92*a1a3b679SAndreas Boehler            '{' . Plugin::NS_CALENDARSERVER . '}shared-url'
93*a1a3b679SAndreas Boehler        );
94*a1a3b679SAndreas Boehler
95*a1a3b679SAndreas Boehler        $this->server->xml->elementMap['{' . Plugin::NS_CALENDARSERVER . '}share'] = 'Sabre\\CalDAV\\Xml\\Request\\Share';
96*a1a3b679SAndreas Boehler        $this->server->xml->elementMap['{' . Plugin::NS_CALENDARSERVER . '}invite-reply'] = 'Sabre\\CalDAV\\Xml\\Request\\InviteReply';
97*a1a3b679SAndreas Boehler
98*a1a3b679SAndreas Boehler        $this->server->on('propFind',     [$this, 'propFindEarly']);
99*a1a3b679SAndreas Boehler        $this->server->on('propFind',     [$this, 'propFindLate'], 150);
100*a1a3b679SAndreas Boehler        $this->server->on('propPatch',    [$this, 'propPatch'], 40);
101*a1a3b679SAndreas Boehler        $this->server->on('method:POST',  [$this, 'httpPost']);
102*a1a3b679SAndreas Boehler
103*a1a3b679SAndreas Boehler    }
104*a1a3b679SAndreas Boehler
105*a1a3b679SAndreas Boehler    /**
106*a1a3b679SAndreas Boehler     * This event is triggered when properties are requested for a certain
107*a1a3b679SAndreas Boehler     * node.
108*a1a3b679SAndreas Boehler     *
109*a1a3b679SAndreas Boehler     * This allows us to inject any properties early.
110*a1a3b679SAndreas Boehler     *
111*a1a3b679SAndreas Boehler     * @param DAV\PropFind $propFind
112*a1a3b679SAndreas Boehler     * @param DAV\INode $node
113*a1a3b679SAndreas Boehler     * @return void
114*a1a3b679SAndreas Boehler     */
115*a1a3b679SAndreas Boehler    function propFindEarly(DAV\PropFind $propFind, DAV\INode $node) {
116*a1a3b679SAndreas Boehler
117*a1a3b679SAndreas Boehler        if ($node instanceof IShareableCalendar) {
118*a1a3b679SAndreas Boehler
119*a1a3b679SAndreas Boehler            $propFind->handle('{' . Plugin::NS_CALENDARSERVER . '}invite', function() use ($node) {
120*a1a3b679SAndreas Boehler                return new Xml\Property\Invite(
121*a1a3b679SAndreas Boehler                    $node->getShares()
122*a1a3b679SAndreas Boehler                );
123*a1a3b679SAndreas Boehler            });
124*a1a3b679SAndreas Boehler
125*a1a3b679SAndreas Boehler        }
126*a1a3b679SAndreas Boehler
127*a1a3b679SAndreas Boehler        if ($node instanceof ISharedCalendar) {
128*a1a3b679SAndreas Boehler
129*a1a3b679SAndreas Boehler            $propFind->handle('{' . Plugin::NS_CALENDARSERVER . '}shared-url', function() use ($node) {
130*a1a3b679SAndreas Boehler                return new Href(
131*a1a3b679SAndreas Boehler                    $node->getSharedUrl()
132*a1a3b679SAndreas Boehler                );
133*a1a3b679SAndreas Boehler            });
134*a1a3b679SAndreas Boehler
135*a1a3b679SAndreas Boehler            $propFind->handle('{' . Plugin::NS_CALENDARSERVER . '}invite', function() use ($node) {
136*a1a3b679SAndreas Boehler
137*a1a3b679SAndreas Boehler                // Fetching owner information
138*a1a3b679SAndreas Boehler                $props = $this->server->getPropertiesForPath($node->getOwner(), [
139*a1a3b679SAndreas Boehler                    '{http://sabredav.org/ns}email-address',
140*a1a3b679SAndreas Boehler                    '{DAV:}displayname',
141*a1a3b679SAndreas Boehler                ], 0);
142*a1a3b679SAndreas Boehler
143*a1a3b679SAndreas Boehler                $ownerInfo = [
144*a1a3b679SAndreas Boehler                    'href' => $node->getOwner(),
145*a1a3b679SAndreas Boehler                ];
146*a1a3b679SAndreas Boehler
147*a1a3b679SAndreas Boehler                if (isset($props[0][200])) {
148*a1a3b679SAndreas Boehler
149*a1a3b679SAndreas Boehler                    // We're mapping the internal webdav properties to the
150*a1a3b679SAndreas Boehler                    // elements caldav-sharing expects.
151*a1a3b679SAndreas Boehler                    if (isset($props[0][200]['{http://sabredav.org/ns}email-address'])) {
152*a1a3b679SAndreas Boehler                        $ownerInfo['href'] = 'mailto:' . $props[0][200]['{http://sabredav.org/ns}email-address'];
153*a1a3b679SAndreas Boehler                    }
154*a1a3b679SAndreas Boehler                    if (isset($props[0][200]['{DAV:}displayname'])) {
155*a1a3b679SAndreas Boehler                        $ownerInfo['commonName'] = $props[0][200]['{DAV:}displayname'];
156*a1a3b679SAndreas Boehler                    }
157*a1a3b679SAndreas Boehler
158*a1a3b679SAndreas Boehler                }
159*a1a3b679SAndreas Boehler
160*a1a3b679SAndreas Boehler                return new Xml\Property\Invite(
161*a1a3b679SAndreas Boehler                    $node->getShares(),
162*a1a3b679SAndreas Boehler                    $ownerInfo
163*a1a3b679SAndreas Boehler                );
164*a1a3b679SAndreas Boehler
165*a1a3b679SAndreas Boehler            });
166*a1a3b679SAndreas Boehler
167*a1a3b679SAndreas Boehler        }
168*a1a3b679SAndreas Boehler
169*a1a3b679SAndreas Boehler    }
170*a1a3b679SAndreas Boehler
171*a1a3b679SAndreas Boehler    /**
172*a1a3b679SAndreas Boehler     * This method is triggered *after* all properties have been retrieved.
173*a1a3b679SAndreas Boehler     * This allows us to inject the correct resourcetype for calendars that
174*a1a3b679SAndreas Boehler     * have been shared.
175*a1a3b679SAndreas Boehler     *
176*a1a3b679SAndreas Boehler     * @param DAV\PropFind $propFind
177*a1a3b679SAndreas Boehler     * @param DAV\INode $node
178*a1a3b679SAndreas Boehler     * @return void
179*a1a3b679SAndreas Boehler     */
180*a1a3b679SAndreas Boehler    function propFindLate(DAV\PropFind $propFind, DAV\INode $node) {
181*a1a3b679SAndreas Boehler
182*a1a3b679SAndreas Boehler        if ($node instanceof IShareableCalendar) {
183*a1a3b679SAndreas Boehler            if ($rt = $propFind->get('{DAV:}resourcetype')) {
184*a1a3b679SAndreas Boehler                if (count($node->getShares()) > 0) {
185*a1a3b679SAndreas Boehler                    $rt->add('{' . Plugin::NS_CALENDARSERVER . '}shared-owner');
186*a1a3b679SAndreas Boehler                }
187*a1a3b679SAndreas Boehler            }
188*a1a3b679SAndreas Boehler            $propFind->handle('{' . Plugin::NS_CALENDARSERVER . '}allowed-sharing-modes', function() {
189*a1a3b679SAndreas Boehler                return new Xml\Property\AllowedSharingModes(true, false);
190*a1a3b679SAndreas Boehler            });
191*a1a3b679SAndreas Boehler
192*a1a3b679SAndreas Boehler        }
193*a1a3b679SAndreas Boehler
194*a1a3b679SAndreas Boehler    }
195*a1a3b679SAndreas Boehler
196*a1a3b679SAndreas Boehler    /**
197*a1a3b679SAndreas Boehler     * This method is trigged when a user attempts to update a node's
198*a1a3b679SAndreas Boehler     * properties.
199*a1a3b679SAndreas Boehler     *
200*a1a3b679SAndreas Boehler     * A previous draft of the sharing spec stated that it was possible to use
201*a1a3b679SAndreas Boehler     * PROPPATCH to remove 'shared-owner' from the resourcetype, thus unsharing
202*a1a3b679SAndreas Boehler     * the calendar.
203*a1a3b679SAndreas Boehler     *
204*a1a3b679SAndreas Boehler     * Even though this is no longer in the current spec, we keep this around
205*a1a3b679SAndreas Boehler     * because OS X 10.7 may still make use of this feature.
206*a1a3b679SAndreas Boehler     *
207*a1a3b679SAndreas Boehler     * @param string $path
208*a1a3b679SAndreas Boehler     * @param DAV\PropPatch $propPatch
209*a1a3b679SAndreas Boehler     * @return void
210*a1a3b679SAndreas Boehler     */
211*a1a3b679SAndreas Boehler    function propPatch($path, DAV\PropPatch $propPatch) {
212*a1a3b679SAndreas Boehler
213*a1a3b679SAndreas Boehler        $node = $this->server->tree->getNodeForPath($path);
214*a1a3b679SAndreas Boehler        if (!$node instanceof IShareableCalendar)
215*a1a3b679SAndreas Boehler            return;
216*a1a3b679SAndreas Boehler
217*a1a3b679SAndreas Boehler        $propPatch->handle('{DAV:}resourcetype', function($value) use ($node) {
218*a1a3b679SAndreas Boehler            if ($value->is('{' . Plugin::NS_CALENDARSERVER . '}shared-owner')) return false;
219*a1a3b679SAndreas Boehler            $shares = $node->getShares();
220*a1a3b679SAndreas Boehler            $remove = [];
221*a1a3b679SAndreas Boehler            foreach ($shares as $share) {
222*a1a3b679SAndreas Boehler                $remove[] = $share['href'];
223*a1a3b679SAndreas Boehler            }
224*a1a3b679SAndreas Boehler            $node->updateShares([], $remove);
225*a1a3b679SAndreas Boehler
226*a1a3b679SAndreas Boehler            return true;
227*a1a3b679SAndreas Boehler
228*a1a3b679SAndreas Boehler        });
229*a1a3b679SAndreas Boehler
230*a1a3b679SAndreas Boehler    }
231*a1a3b679SAndreas Boehler
232*a1a3b679SAndreas Boehler    /**
233*a1a3b679SAndreas Boehler     * We intercept this to handle POST requests on calendars.
234*a1a3b679SAndreas Boehler     *
235*a1a3b679SAndreas Boehler     * @param RequestInterface $request
236*a1a3b679SAndreas Boehler     * @param ResponseInterface $response
237*a1a3b679SAndreas Boehler     * @return null|bool
238*a1a3b679SAndreas Boehler     */
239*a1a3b679SAndreas Boehler    function httpPost(RequestInterface $request, ResponseInterface $response) {
240*a1a3b679SAndreas Boehler
241*a1a3b679SAndreas Boehler        $path = $request->getPath();
242*a1a3b679SAndreas Boehler
243*a1a3b679SAndreas Boehler        // Only handling xml
244*a1a3b679SAndreas Boehler        $contentType = $request->getHeader('Content-Type');
245*a1a3b679SAndreas Boehler        if (strpos($contentType, 'application/xml') === false && strpos($contentType, 'text/xml') === false)
246*a1a3b679SAndreas Boehler            return;
247*a1a3b679SAndreas Boehler
248*a1a3b679SAndreas Boehler        // Making sure the node exists
249*a1a3b679SAndreas Boehler        try {
250*a1a3b679SAndreas Boehler            $node = $this->server->tree->getNodeForPath($path);
251*a1a3b679SAndreas Boehler        } catch (DAV\Exception\NotFound $e) {
252*a1a3b679SAndreas Boehler            return;
253*a1a3b679SAndreas Boehler        }
254*a1a3b679SAndreas Boehler
255*a1a3b679SAndreas Boehler        $requestBody = $request->getBodyAsString();
256*a1a3b679SAndreas Boehler
257*a1a3b679SAndreas Boehler        // If this request handler could not deal with this POST request, it
258*a1a3b679SAndreas Boehler        // will return 'null' and other plugins get a chance to handle the
259*a1a3b679SAndreas Boehler        // request.
260*a1a3b679SAndreas Boehler        //
261*a1a3b679SAndreas Boehler        // However, we already requested the full body. This is a problem,
262*a1a3b679SAndreas Boehler        // because a body can only be read once. This is why we preemptively
263*a1a3b679SAndreas Boehler        // re-populated the request body with the existing data.
264*a1a3b679SAndreas Boehler        $request->setBody($requestBody);
265*a1a3b679SAndreas Boehler
266*a1a3b679SAndreas Boehler        $message = $this->server->xml->parse($requestBody, $request->getUrl(), $documentType);
267*a1a3b679SAndreas Boehler
268*a1a3b679SAndreas Boehler        switch ($documentType) {
269*a1a3b679SAndreas Boehler
270*a1a3b679SAndreas Boehler            // Dealing with the 'share' document, which modified invitees on a
271*a1a3b679SAndreas Boehler            // calendar.
272*a1a3b679SAndreas Boehler            case '{' . Plugin::NS_CALENDARSERVER . '}share' :
273*a1a3b679SAndreas Boehler
274*a1a3b679SAndreas Boehler                // We can only deal with IShareableCalendar objects
275*a1a3b679SAndreas Boehler                if (!$node instanceof IShareableCalendar) {
276*a1a3b679SAndreas Boehler                    return;
277*a1a3b679SAndreas Boehler                }
278*a1a3b679SAndreas Boehler
279*a1a3b679SAndreas Boehler                $this->server->transactionType = 'post-calendar-share';
280*a1a3b679SAndreas Boehler
281*a1a3b679SAndreas Boehler                // Getting ACL info
282*a1a3b679SAndreas Boehler                $acl = $this->server->getPlugin('acl');
283*a1a3b679SAndreas Boehler
284*a1a3b679SAndreas Boehler                // If there's no ACL support, we allow everything
285*a1a3b679SAndreas Boehler                if ($acl) {
286*a1a3b679SAndreas Boehler                    $acl->checkPrivileges($path, '{DAV:}write');
287*a1a3b679SAndreas Boehler                }
288*a1a3b679SAndreas Boehler
289*a1a3b679SAndreas Boehler                $node->updateShares($message->set, $message->remove);
290*a1a3b679SAndreas Boehler
291*a1a3b679SAndreas Boehler                $response->setStatus(200);
292*a1a3b679SAndreas Boehler                // Adding this because sending a response body may cause issues,
293*a1a3b679SAndreas Boehler                // and I wanted some type of indicator the response was handled.
294*a1a3b679SAndreas Boehler                $response->setHeader('X-Sabre-Status', 'everything-went-well');
295*a1a3b679SAndreas Boehler
296*a1a3b679SAndreas Boehler                // Breaking the event chain
297*a1a3b679SAndreas Boehler                return false;
298*a1a3b679SAndreas Boehler
299*a1a3b679SAndreas Boehler            // The invite-reply document is sent when the user replies to an
300*a1a3b679SAndreas Boehler            // invitation of a calendar share.
301*a1a3b679SAndreas Boehler            case '{' . Plugin::NS_CALENDARSERVER . '}invite-reply' :
302*a1a3b679SAndreas Boehler
303*a1a3b679SAndreas Boehler                // This only works on the calendar-home-root node.
304*a1a3b679SAndreas Boehler                if (!$node instanceof CalendarHome) {
305*a1a3b679SAndreas Boehler                    return;
306*a1a3b679SAndreas Boehler                }
307*a1a3b679SAndreas Boehler                $this->server->transactionType = 'post-invite-reply';
308*a1a3b679SAndreas Boehler
309*a1a3b679SAndreas Boehler                // Getting ACL info
310*a1a3b679SAndreas Boehler                $acl = $this->server->getPlugin('acl');
311*a1a3b679SAndreas Boehler
312*a1a3b679SAndreas Boehler                // If there's no ACL support, we allow everything
313*a1a3b679SAndreas Boehler                if ($acl) {
314*a1a3b679SAndreas Boehler                    $acl->checkPrivileges($path, '{DAV:}write');
315*a1a3b679SAndreas Boehler                }
316*a1a3b679SAndreas Boehler
317*a1a3b679SAndreas Boehler                $url = $node->shareReply(
318*a1a3b679SAndreas Boehler                    $message->href,
319*a1a3b679SAndreas Boehler                    $message->status,
320*a1a3b679SAndreas Boehler                    $message->calendarUri,
321*a1a3b679SAndreas Boehler                    $message->inReplyTo,
322*a1a3b679SAndreas Boehler                    $message->summary
323*a1a3b679SAndreas Boehler                );
324*a1a3b679SAndreas Boehler
325*a1a3b679SAndreas Boehler                $response->setStatus(200);
326*a1a3b679SAndreas Boehler                // Adding this because sending a response body may cause issues,
327*a1a3b679SAndreas Boehler                // and I wanted some type of indicator the response was handled.
328*a1a3b679SAndreas Boehler                $response->setHeader('X-Sabre-Status', 'everything-went-well');
329*a1a3b679SAndreas Boehler
330*a1a3b679SAndreas Boehler                if ($url) {
331*a1a3b679SAndreas Boehler                    $writer = $this->server->xml->getWriter($this->server->getBaseUri());
332*a1a3b679SAndreas Boehler                    $writer->openMemory();
333*a1a3b679SAndreas Boehler                    $writer->startDocument();
334*a1a3b679SAndreas Boehler                    $writer->startElement('{' . Plugin::NS_CALENDARSERVER . '}shared-as');
335*a1a3b679SAndreas Boehler                    $writer->write(new Href($url));
336*a1a3b679SAndreas Boehler                    $writer->endElement();
337*a1a3b679SAndreas Boehler                    $response->setHeader('Content-Type', 'application/xml');
338*a1a3b679SAndreas Boehler                    $response->setBody($writer->outputMemory());
339*a1a3b679SAndreas Boehler
340*a1a3b679SAndreas Boehler                }
341*a1a3b679SAndreas Boehler
342*a1a3b679SAndreas Boehler                // Breaking the event chain
343*a1a3b679SAndreas Boehler                return false;
344*a1a3b679SAndreas Boehler
345*a1a3b679SAndreas Boehler            case '{' . Plugin::NS_CALENDARSERVER . '}publish-calendar' :
346*a1a3b679SAndreas Boehler
347*a1a3b679SAndreas Boehler                // We can only deal with IShareableCalendar objects
348*a1a3b679SAndreas Boehler                if (!$node instanceof IShareableCalendar) {
349*a1a3b679SAndreas Boehler                    return;
350*a1a3b679SAndreas Boehler                }
351*a1a3b679SAndreas Boehler                $this->server->transactionType = 'post-publish-calendar';
352*a1a3b679SAndreas Boehler
353*a1a3b679SAndreas Boehler                // Getting ACL info
354*a1a3b679SAndreas Boehler                $acl = $this->server->getPlugin('acl');
355*a1a3b679SAndreas Boehler
356*a1a3b679SAndreas Boehler                // If there's no ACL support, we allow everything
357*a1a3b679SAndreas Boehler                if ($acl) {
358*a1a3b679SAndreas Boehler                    $acl->checkPrivileges($path, '{DAV:}write');
359*a1a3b679SAndreas Boehler                }
360*a1a3b679SAndreas Boehler
361*a1a3b679SAndreas Boehler                $node->setPublishStatus(true);
362*a1a3b679SAndreas Boehler
363*a1a3b679SAndreas Boehler                // iCloud sends back the 202, so we will too.
364*a1a3b679SAndreas Boehler                $response->setStatus(202);
365*a1a3b679SAndreas Boehler
366*a1a3b679SAndreas Boehler                // Adding this because sending a response body may cause issues,
367*a1a3b679SAndreas Boehler                // and I wanted some type of indicator the response was handled.
368*a1a3b679SAndreas Boehler                $response->setHeader('X-Sabre-Status', 'everything-went-well');
369*a1a3b679SAndreas Boehler
370*a1a3b679SAndreas Boehler                // Breaking the event chain
371*a1a3b679SAndreas Boehler                return false;
372*a1a3b679SAndreas Boehler
373*a1a3b679SAndreas Boehler            case '{' . Plugin::NS_CALENDARSERVER . '}unpublish-calendar' :
374*a1a3b679SAndreas Boehler
375*a1a3b679SAndreas Boehler                // We can only deal with IShareableCalendar objects
376*a1a3b679SAndreas Boehler                if (!$node instanceof IShareableCalendar) {
377*a1a3b679SAndreas Boehler                    return;
378*a1a3b679SAndreas Boehler                }
379*a1a3b679SAndreas Boehler                $this->server->transactionType = 'post-unpublish-calendar';
380*a1a3b679SAndreas Boehler
381*a1a3b679SAndreas Boehler                // Getting ACL info
382*a1a3b679SAndreas Boehler                $acl = $this->server->getPlugin('acl');
383*a1a3b679SAndreas Boehler
384*a1a3b679SAndreas Boehler                // If there's no ACL support, we allow everything
385*a1a3b679SAndreas Boehler                if ($acl) {
386*a1a3b679SAndreas Boehler                    $acl->checkPrivileges($path, '{DAV:}write');
387*a1a3b679SAndreas Boehler                }
388*a1a3b679SAndreas Boehler
389*a1a3b679SAndreas Boehler                $node->setPublishStatus(false);
390*a1a3b679SAndreas Boehler
391*a1a3b679SAndreas Boehler                $response->setStatus(200);
392*a1a3b679SAndreas Boehler
393*a1a3b679SAndreas Boehler                // Adding this because sending a response body may cause issues,
394*a1a3b679SAndreas Boehler                // and I wanted some type of indicator the response was handled.
395*a1a3b679SAndreas Boehler                $response->setHeader('X-Sabre-Status', 'everything-went-well');
396*a1a3b679SAndreas Boehler
397*a1a3b679SAndreas Boehler                // Breaking the event chain
398*a1a3b679SAndreas Boehler                return false;
399*a1a3b679SAndreas Boehler
400*a1a3b679SAndreas Boehler        }
401*a1a3b679SAndreas Boehler
402*a1a3b679SAndreas Boehler
403*a1a3b679SAndreas Boehler
404*a1a3b679SAndreas Boehler    }
405*a1a3b679SAndreas Boehler
406*a1a3b679SAndreas Boehler    /**
407*a1a3b679SAndreas Boehler     * Returns a bunch of meta-data about the plugin.
408*a1a3b679SAndreas Boehler     *
409*a1a3b679SAndreas Boehler     * Providing this information is optional, and is mainly displayed by the
410*a1a3b679SAndreas Boehler     * Browser plugin.
411*a1a3b679SAndreas Boehler     *
412*a1a3b679SAndreas Boehler     * The description key in the returned array may contain html and will not
413*a1a3b679SAndreas Boehler     * be sanitized.
414*a1a3b679SAndreas Boehler     *
415*a1a3b679SAndreas Boehler     * @return array
416*a1a3b679SAndreas Boehler     */
417*a1a3b679SAndreas Boehler    function getPluginInfo() {
418*a1a3b679SAndreas Boehler
419*a1a3b679SAndreas Boehler        return [
420*a1a3b679SAndreas Boehler            'name'        => $this->getPluginName(),
421*a1a3b679SAndreas Boehler            'description' => 'Adds support for caldav-sharing.',
422*a1a3b679SAndreas Boehler            'link'        => 'http://sabre.io/dav/caldav-sharing/',
423*a1a3b679SAndreas Boehler        ];
424*a1a3b679SAndreas Boehler
425*a1a3b679SAndreas Boehler    }
426*a1a3b679SAndreas Boehler}
427