xref: /plugin/davcal/vendor/sabre/dav/lib/CalDAV/Xml/Property/Invite.php (revision a1a3b6794e0e143a4a8b51d3185ce2d339be61ab)
1*a1a3b679SAndreas Boehler<?php
2*a1a3b679SAndreas Boehler
3*a1a3b679SAndreas Boehlernamespace Sabre\CalDAV\Xml\Property;
4*a1a3b679SAndreas Boehler
5*a1a3b679SAndreas Boehleruse Sabre\Xml\Element;
6*a1a3b679SAndreas Boehleruse Sabre\Xml\Reader;
7*a1a3b679SAndreas Boehleruse Sabre\Xml\Writer;
8*a1a3b679SAndreas Boehleruse Sabre\CalDAV\Plugin;
9*a1a3b679SAndreas Boehleruse Sabre\CalDAV\SharingPlugin;
10*a1a3b679SAndreas Boehler
11*a1a3b679SAndreas Boehler/**
12*a1a3b679SAndreas Boehler * Invite property
13*a1a3b679SAndreas Boehler *
14*a1a3b679SAndreas Boehler * This property encodes the 'invite' property, as defined by
15*a1a3b679SAndreas Boehler * the 'caldav-sharing-02' spec, in the http://calendarserver.org/ns/
16*a1a3b679SAndreas Boehler * namespace.
17*a1a3b679SAndreas Boehler *
18*a1a3b679SAndreas Boehler * @see https://trac.calendarserver.org/browser/CalendarServer/trunk/doc/Extensions/caldav-sharing-02.txt
19*a1a3b679SAndreas Boehler * @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/).
20*a1a3b679SAndreas Boehler * @author Evert Pot (http://evertpot.com/)
21*a1a3b679SAndreas Boehler * @license http://sabre.io/license/ Modified BSD License
22*a1a3b679SAndreas Boehler */
23*a1a3b679SAndreas Boehlerclass Invite implements Element {
24*a1a3b679SAndreas Boehler
25*a1a3b679SAndreas Boehler    /**
26*a1a3b679SAndreas Boehler     * The list of users a calendar has been shared to.
27*a1a3b679SAndreas Boehler     *
28*a1a3b679SAndreas Boehler     * @var array
29*a1a3b679SAndreas Boehler     */
30*a1a3b679SAndreas Boehler    protected $users;
31*a1a3b679SAndreas Boehler
32*a1a3b679SAndreas Boehler    /**
33*a1a3b679SAndreas Boehler     * The organizer contains information about the person who shared the
34*a1a3b679SAndreas Boehler     * object.
35*a1a3b679SAndreas Boehler     *
36*a1a3b679SAndreas Boehler     * @var array
37*a1a3b679SAndreas Boehler     */
38*a1a3b679SAndreas Boehler    protected $organizer;
39*a1a3b679SAndreas Boehler
40*a1a3b679SAndreas Boehler    /**
41*a1a3b679SAndreas Boehler     * Creates the property.
42*a1a3b679SAndreas Boehler     *
43*a1a3b679SAndreas Boehler     * Users is an array. Each element of the array has the following
44*a1a3b679SAndreas Boehler     * properties:
45*a1a3b679SAndreas Boehler     *
46*a1a3b679SAndreas Boehler     *   * href - Often a mailto: address
47*a1a3b679SAndreas Boehler     *   * commonName - Optional, for example a first and lastname for a user.
48*a1a3b679SAndreas Boehler     *   * status - One of the SharingPlugin::STATUS_* constants.
49*a1a3b679SAndreas Boehler     *   * readOnly - true or false
50*a1a3b679SAndreas Boehler     *   * summary - Optional, description of the share
51*a1a3b679SAndreas Boehler     *
52*a1a3b679SAndreas Boehler     * The organizer key is optional to specify. It's only useful when a
53*a1a3b679SAndreas Boehler     * 'sharee' requests the sharing information.
54*a1a3b679SAndreas Boehler     *
55*a1a3b679SAndreas Boehler     * The organizer may have the following properties:
56*a1a3b679SAndreas Boehler     *   * href - Often a mailto: address.
57*a1a3b679SAndreas Boehler     *   * commonName - Optional human-readable name.
58*a1a3b679SAndreas Boehler     *   * firstName - Optional first name.
59*a1a3b679SAndreas Boehler     *   * lastName - Optional last name.
60*a1a3b679SAndreas Boehler     *
61*a1a3b679SAndreas Boehler     * If you wonder why these two structures are so different, I guess a
62*a1a3b679SAndreas Boehler     * valid answer is that the current spec is still a draft.
63*a1a3b679SAndreas Boehler     *
64*a1a3b679SAndreas Boehler     * @param array $users
65*a1a3b679SAndreas Boehler     */
66*a1a3b679SAndreas Boehler    function __construct(array $users, array $organizer = null) {
67*a1a3b679SAndreas Boehler
68*a1a3b679SAndreas Boehler        $this->users = $users;
69*a1a3b679SAndreas Boehler        $this->organizer = $organizer;
70*a1a3b679SAndreas Boehler
71*a1a3b679SAndreas Boehler    }
72*a1a3b679SAndreas Boehler
73*a1a3b679SAndreas Boehler    /**
74*a1a3b679SAndreas Boehler     * Returns the list of users, as it was passed to the constructor.
75*a1a3b679SAndreas Boehler     *
76*a1a3b679SAndreas Boehler     * @return array
77*a1a3b679SAndreas Boehler     */
78*a1a3b679SAndreas Boehler    function getValue() {
79*a1a3b679SAndreas Boehler
80*a1a3b679SAndreas Boehler        return $this->users;
81*a1a3b679SAndreas Boehler
82*a1a3b679SAndreas Boehler    }
83*a1a3b679SAndreas Boehler
84*a1a3b679SAndreas Boehler    /**
85*a1a3b679SAndreas Boehler     * The xmlSerialize metod is called during xml writing.
86*a1a3b679SAndreas Boehler     *
87*a1a3b679SAndreas Boehler     * Use the $writer argument to write its own xml serialization.
88*a1a3b679SAndreas Boehler     *
89*a1a3b679SAndreas Boehler     * An important note: do _not_ create a parent element. Any element
90*a1a3b679SAndreas Boehler     * implementing XmlSerializble should only ever write what's considered
91*a1a3b679SAndreas Boehler     * its 'inner xml'.
92*a1a3b679SAndreas Boehler     *
93*a1a3b679SAndreas Boehler     * The parent of the current element is responsible for writing a
94*a1a3b679SAndreas Boehler     * containing element.
95*a1a3b679SAndreas Boehler     *
96*a1a3b679SAndreas Boehler     * This allows serializers to be re-used for different element names.
97*a1a3b679SAndreas Boehler     *
98*a1a3b679SAndreas Boehler     * If you are opening new elements, you must also close them again.
99*a1a3b679SAndreas Boehler     *
100*a1a3b679SAndreas Boehler     * @param Writer $writer
101*a1a3b679SAndreas Boehler     * @return void
102*a1a3b679SAndreas Boehler     */
103*a1a3b679SAndreas Boehler    function xmlSerialize(Writer $writer) {
104*a1a3b679SAndreas Boehler
105*a1a3b679SAndreas Boehler        $cs = '{' . Plugin::NS_CALENDARSERVER . '}';
106*a1a3b679SAndreas Boehler
107*a1a3b679SAndreas Boehler        if (!is_null($this->organizer)) {
108*a1a3b679SAndreas Boehler
109*a1a3b679SAndreas Boehler            $writer->startElement($cs . 'organizer');
110*a1a3b679SAndreas Boehler            $writer->writeElement('{DAV:}href', $this->organizer['href']);
111*a1a3b679SAndreas Boehler
112*a1a3b679SAndreas Boehler            if (isset($this->organizer['commonName']) && $this->organizer['commonName']) {
113*a1a3b679SAndreas Boehler                $writer->writeElement($cs . 'common-name', $this->organizer['commonName']);
114*a1a3b679SAndreas Boehler            }
115*a1a3b679SAndreas Boehler            if (isset($this->organizer['firstName']) && $this->organizer['firstName']) {
116*a1a3b679SAndreas Boehler                $writer->writeElement($cs . 'first-name', $this->organizer['firstName']);
117*a1a3b679SAndreas Boehler            }
118*a1a3b679SAndreas Boehler            if (isset($this->organizer['lastName']) && $this->organizer['lastName']) {
119*a1a3b679SAndreas Boehler                $writer->writeElement($cs . 'last-name', $this->organizer['lastName']);
120*a1a3b679SAndreas Boehler            }
121*a1a3b679SAndreas Boehler            $writer->endElement(); // organizer
122*a1a3b679SAndreas Boehler
123*a1a3b679SAndreas Boehler        }
124*a1a3b679SAndreas Boehler
125*a1a3b679SAndreas Boehler        foreach ($this->users as $user) {
126*a1a3b679SAndreas Boehler
127*a1a3b679SAndreas Boehler            $writer->startElement($cs . 'user');
128*a1a3b679SAndreas Boehler            $writer->writeElement('{DAV:}href', $user['href']);
129*a1a3b679SAndreas Boehler            if (isset($user['commonName']) && $user['commonName']) {
130*a1a3b679SAndreas Boehler                $writer->writeElement($cs . 'common-name', $user['commonName']);
131*a1a3b679SAndreas Boehler            }
132*a1a3b679SAndreas Boehler            switch ($user['status']) {
133*a1a3b679SAndreas Boehler
134*a1a3b679SAndreas Boehler                case SharingPlugin::STATUS_ACCEPTED :
135*a1a3b679SAndreas Boehler                    $writer->writeElement($cs . 'invite-accepted');
136*a1a3b679SAndreas Boehler                    break;
137*a1a3b679SAndreas Boehler                case SharingPlugin::STATUS_DECLINED :
138*a1a3b679SAndreas Boehler                    $writer->writeElement($cs . 'invite-declined');
139*a1a3b679SAndreas Boehler                    break;
140*a1a3b679SAndreas Boehler                case SharingPlugin::STATUS_NORESPONSE :
141*a1a3b679SAndreas Boehler                    $writer->writeElement($cs . 'invite-noresponse');
142*a1a3b679SAndreas Boehler                    break;
143*a1a3b679SAndreas Boehler                case SharingPlugin::STATUS_INVALID :
144*a1a3b679SAndreas Boehler                    $writer->writeElement($cs . 'invite-invalid');
145*a1a3b679SAndreas Boehler                    break;
146*a1a3b679SAndreas Boehler            }
147*a1a3b679SAndreas Boehler
148*a1a3b679SAndreas Boehler            $writer->startElement($cs . 'access');
149*a1a3b679SAndreas Boehler            if ($user['readOnly']) {
150*a1a3b679SAndreas Boehler                $writer->writeElement($cs . 'read');
151*a1a3b679SAndreas Boehler            } else {
152*a1a3b679SAndreas Boehler                $writer->writeElement($cs . 'read-write');
153*a1a3b679SAndreas Boehler            }
154*a1a3b679SAndreas Boehler            $writer->endElement(); // access
155*a1a3b679SAndreas Boehler
156*a1a3b679SAndreas Boehler            if (isset($user['summary']) && $user['summary']) {
157*a1a3b679SAndreas Boehler                $writer->writeElement($cs . 'summary', $user['summary']);
158*a1a3b679SAndreas Boehler            }
159*a1a3b679SAndreas Boehler
160*a1a3b679SAndreas Boehler            $writer->endElement(); //user
161*a1a3b679SAndreas Boehler
162*a1a3b679SAndreas Boehler        }
163*a1a3b679SAndreas Boehler
164*a1a3b679SAndreas Boehler    }
165*a1a3b679SAndreas Boehler
166*a1a3b679SAndreas Boehler    /**
167*a1a3b679SAndreas Boehler     * The deserialize method is called during xml parsing.
168*a1a3b679SAndreas Boehler     *
169*a1a3b679SAndreas Boehler     * This method is called statictly, this is because in theory this method
170*a1a3b679SAndreas Boehler     * may be used as a type of constructor, or factory method.
171*a1a3b679SAndreas Boehler     *
172*a1a3b679SAndreas Boehler     * Often you want to return an instance of the current class, but you are
173*a1a3b679SAndreas Boehler     * free to return other data as well.
174*a1a3b679SAndreas Boehler     *
175*a1a3b679SAndreas Boehler     * You are responsible for advancing the reader to the next element. Not
176*a1a3b679SAndreas Boehler     * doing anything will result in a never-ending loop.
177*a1a3b679SAndreas Boehler     *
178*a1a3b679SAndreas Boehler     * If you just want to skip parsing for this element altogether, you can
179*a1a3b679SAndreas Boehler     * just call $reader->next();
180*a1a3b679SAndreas Boehler     *
181*a1a3b679SAndreas Boehler     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
182*a1a3b679SAndreas Boehler     * the next element.
183*a1a3b679SAndreas Boehler     *
184*a1a3b679SAndreas Boehler     * @param Reader $reader
185*a1a3b679SAndreas Boehler     * @return mixed
186*a1a3b679SAndreas Boehler     */
187*a1a3b679SAndreas Boehler    static function xmlDeserialize(Reader $reader) {
188*a1a3b679SAndreas Boehler
189*a1a3b679SAndreas Boehler        $cs = '{' . Plugin::NS_CALENDARSERVER . '}';
190*a1a3b679SAndreas Boehler
191*a1a3b679SAndreas Boehler        $users = [];
192*a1a3b679SAndreas Boehler
193*a1a3b679SAndreas Boehler        foreach ($reader->parseInnerTree() as $elem) {
194*a1a3b679SAndreas Boehler
195*a1a3b679SAndreas Boehler            if ($elem['name'] !== $cs . 'user')
196*a1a3b679SAndreas Boehler                continue;
197*a1a3b679SAndreas Boehler
198*a1a3b679SAndreas Boehler            $user = [
199*a1a3b679SAndreas Boehler                'href'       => null,
200*a1a3b679SAndreas Boehler                'commonName' => null,
201*a1a3b679SAndreas Boehler                'readOnly'   => null,
202*a1a3b679SAndreas Boehler                'summary'    => null,
203*a1a3b679SAndreas Boehler                'status'     => null,
204*a1a3b679SAndreas Boehler            ];
205*a1a3b679SAndreas Boehler
206*a1a3b679SAndreas Boehler            foreach ($elem['value'] as $userElem) {
207*a1a3b679SAndreas Boehler
208*a1a3b679SAndreas Boehler                switch ($userElem['name']) {
209*a1a3b679SAndreas Boehler                    case $cs . 'invite-accepted' :
210*a1a3b679SAndreas Boehler                        $user['status'] = SharingPlugin::STATUS_ACCEPTED;
211*a1a3b679SAndreas Boehler                        break;
212*a1a3b679SAndreas Boehler                    case $cs . 'invite-declined' :
213*a1a3b679SAndreas Boehler                        $user['status'] = SharingPlugin::STATUS_DECLINED;
214*a1a3b679SAndreas Boehler                        break;
215*a1a3b679SAndreas Boehler                    case $cs . 'invite-noresponse' :
216*a1a3b679SAndreas Boehler                        $user['status'] = SharingPlugin::STATUS_NORESPONSE;
217*a1a3b679SAndreas Boehler                        break;
218*a1a3b679SAndreas Boehler                    case $cs . 'invite-invalid' :
219*a1a3b679SAndreas Boehler                        $user['status'] = SharingPlugin::STATUS_INVALID;
220*a1a3b679SAndreas Boehler                        break;
221*a1a3b679SAndreas Boehler                    case '{DAV:}href' :
222*a1a3b679SAndreas Boehler                        $user['href'] = $userElem['value'];
223*a1a3b679SAndreas Boehler                        break;
224*a1a3b679SAndreas Boehler                    case $cs . 'common-name' :
225*a1a3b679SAndreas Boehler                        $user['commonName'] = $userElem['value'];
226*a1a3b679SAndreas Boehler                        break;
227*a1a3b679SAndreas Boehler                    case $cs . 'access' :
228*a1a3b679SAndreas Boehler                        foreach ($userElem['value'] as $accessHref) {
229*a1a3b679SAndreas Boehler                            if ($accessHref['name'] === $cs . 'read') {
230*a1a3b679SAndreas Boehler                                $user['readOnly'] = true;
231*a1a3b679SAndreas Boehler                            }
232*a1a3b679SAndreas Boehler                        }
233*a1a3b679SAndreas Boehler                        break;
234*a1a3b679SAndreas Boehler                    case $cs . 'summary' :
235*a1a3b679SAndreas Boehler                        $user['summary'] = $userElem['value'];
236*a1a3b679SAndreas Boehler                        break;
237*a1a3b679SAndreas Boehler
238*a1a3b679SAndreas Boehler                }
239*a1a3b679SAndreas Boehler
240*a1a3b679SAndreas Boehler            }
241*a1a3b679SAndreas Boehler            if (!$user['status']) {
242*a1a3b679SAndreas Boehler                throw new \InvalidArgumentException('Every user must have one of cs:invite-accepted, cs:invite-declined, cs:invite-noresponse or cs:invite-invalid');
243*a1a3b679SAndreas Boehler            }
244*a1a3b679SAndreas Boehler
245*a1a3b679SAndreas Boehler            $users[] = $user;
246*a1a3b679SAndreas Boehler
247*a1a3b679SAndreas Boehler        }
248*a1a3b679SAndreas Boehler
249*a1a3b679SAndreas Boehler        return new self($users);
250*a1a3b679SAndreas Boehler
251*a1a3b679SAndreas Boehler    }
252*a1a3b679SAndreas Boehler}
253