xref: /plugin/davcal/vendor/sabre/dav/lib/CardDAV/AddressBook.php (revision a1a3b6794e0e143a4a8b51d3185ce2d339be61ab)
1*a1a3b679SAndreas Boehler<?php
2*a1a3b679SAndreas Boehler
3*a1a3b679SAndreas Boehlernamespace Sabre\CardDAV;
4*a1a3b679SAndreas Boehler
5*a1a3b679SAndreas Boehleruse Sabre\DAV;
6*a1a3b679SAndreas Boehleruse Sabre\DAVACL;
7*a1a3b679SAndreas Boehler
8*a1a3b679SAndreas Boehler/**
9*a1a3b679SAndreas Boehler * The AddressBook class represents a CardDAV addressbook, owned by a specific user
10*a1a3b679SAndreas Boehler *
11*a1a3b679SAndreas Boehler * The AddressBook can contain multiple vcards
12*a1a3b679SAndreas Boehler *
13*a1a3b679SAndreas Boehler * @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/).
14*a1a3b679SAndreas Boehler * @author Evert Pot (http://evertpot.com/)
15*a1a3b679SAndreas Boehler * @license http://sabre.io/license/ Modified BSD License
16*a1a3b679SAndreas Boehler */
17*a1a3b679SAndreas Boehlerclass AddressBook extends DAV\Collection implements IAddressBook, DAV\IProperties, DAVACL\IACL, DAV\Sync\ISyncCollection, DAV\IMultiGet {
18*a1a3b679SAndreas Boehler
19*a1a3b679SAndreas Boehler    /**
20*a1a3b679SAndreas Boehler     * This is an array with addressbook information
21*a1a3b679SAndreas Boehler     *
22*a1a3b679SAndreas Boehler     * @var array
23*a1a3b679SAndreas Boehler     */
24*a1a3b679SAndreas Boehler    protected $addressBookInfo;
25*a1a3b679SAndreas Boehler
26*a1a3b679SAndreas Boehler    /**
27*a1a3b679SAndreas Boehler     * CardDAV backend
28*a1a3b679SAndreas Boehler     *
29*a1a3b679SAndreas Boehler     * @var Backend\BackendInterface
30*a1a3b679SAndreas Boehler     */
31*a1a3b679SAndreas Boehler    protected $carddavBackend;
32*a1a3b679SAndreas Boehler
33*a1a3b679SAndreas Boehler    /**
34*a1a3b679SAndreas Boehler     * Constructor
35*a1a3b679SAndreas Boehler     *
36*a1a3b679SAndreas Boehler     * @param Backend\BackendInterface $carddavBackend
37*a1a3b679SAndreas Boehler     * @param array $addressBookInfo
38*a1a3b679SAndreas Boehler     */
39*a1a3b679SAndreas Boehler    function __construct(Backend\BackendInterface $carddavBackend, array $addressBookInfo) {
40*a1a3b679SAndreas Boehler
41*a1a3b679SAndreas Boehler        $this->carddavBackend = $carddavBackend;
42*a1a3b679SAndreas Boehler        $this->addressBookInfo = $addressBookInfo;
43*a1a3b679SAndreas Boehler
44*a1a3b679SAndreas Boehler    }
45*a1a3b679SAndreas Boehler
46*a1a3b679SAndreas Boehler    /**
47*a1a3b679SAndreas Boehler     * Returns the name of the addressbook
48*a1a3b679SAndreas Boehler     *
49*a1a3b679SAndreas Boehler     * @return string
50*a1a3b679SAndreas Boehler     */
51*a1a3b679SAndreas Boehler    function getName() {
52*a1a3b679SAndreas Boehler
53*a1a3b679SAndreas Boehler        return $this->addressBookInfo['uri'];
54*a1a3b679SAndreas Boehler
55*a1a3b679SAndreas Boehler    }
56*a1a3b679SAndreas Boehler
57*a1a3b679SAndreas Boehler    /**
58*a1a3b679SAndreas Boehler     * Returns a card
59*a1a3b679SAndreas Boehler     *
60*a1a3b679SAndreas Boehler     * @param string $name
61*a1a3b679SAndreas Boehler     * @return \ICard
62*a1a3b679SAndreas Boehler     */
63*a1a3b679SAndreas Boehler    function getChild($name) {
64*a1a3b679SAndreas Boehler
65*a1a3b679SAndreas Boehler        $obj = $this->carddavBackend->getCard($this->addressBookInfo['id'], $name);
66*a1a3b679SAndreas Boehler        if (!$obj) throw new DAV\Exception\NotFound('Card not found');
67*a1a3b679SAndreas Boehler        return new Card($this->carddavBackend, $this->addressBookInfo, $obj);
68*a1a3b679SAndreas Boehler
69*a1a3b679SAndreas Boehler    }
70*a1a3b679SAndreas Boehler
71*a1a3b679SAndreas Boehler    /**
72*a1a3b679SAndreas Boehler     * Returns the full list of cards
73*a1a3b679SAndreas Boehler     *
74*a1a3b679SAndreas Boehler     * @return array
75*a1a3b679SAndreas Boehler     */
76*a1a3b679SAndreas Boehler    function getChildren() {
77*a1a3b679SAndreas Boehler
78*a1a3b679SAndreas Boehler        $objs = $this->carddavBackend->getCards($this->addressBookInfo['id']);
79*a1a3b679SAndreas Boehler        $children = [];
80*a1a3b679SAndreas Boehler        foreach ($objs as $obj) {
81*a1a3b679SAndreas Boehler            $obj['acl'] = $this->getChildACL();
82*a1a3b679SAndreas Boehler            $children[] = new Card($this->carddavBackend, $this->addressBookInfo, $obj);
83*a1a3b679SAndreas Boehler        }
84*a1a3b679SAndreas Boehler        return $children;
85*a1a3b679SAndreas Boehler
86*a1a3b679SAndreas Boehler    }
87*a1a3b679SAndreas Boehler
88*a1a3b679SAndreas Boehler    /**
89*a1a3b679SAndreas Boehler     * This method receives a list of paths in it's first argument.
90*a1a3b679SAndreas Boehler     * It must return an array with Node objects.
91*a1a3b679SAndreas Boehler     *
92*a1a3b679SAndreas Boehler     * If any children are not found, you do not have to return them.
93*a1a3b679SAndreas Boehler     *
94*a1a3b679SAndreas Boehler     * @param string[] $paths
95*a1a3b679SAndreas Boehler     * @return array
96*a1a3b679SAndreas Boehler     */
97*a1a3b679SAndreas Boehler    function getMultipleChildren(array $paths) {
98*a1a3b679SAndreas Boehler
99*a1a3b679SAndreas Boehler        $objs = $this->carddavBackend->getMultipleCards($this->addressBookInfo['id'], $paths);
100*a1a3b679SAndreas Boehler        $children = [];
101*a1a3b679SAndreas Boehler        foreach ($objs as $obj) {
102*a1a3b679SAndreas Boehler            $obj['acl'] = $this->getChildACL();
103*a1a3b679SAndreas Boehler            $children[] = new Card($this->carddavBackend, $this->addressBookInfo, $obj);
104*a1a3b679SAndreas Boehler        }
105*a1a3b679SAndreas Boehler        return $children;
106*a1a3b679SAndreas Boehler
107*a1a3b679SAndreas Boehler    }
108*a1a3b679SAndreas Boehler
109*a1a3b679SAndreas Boehler    /**
110*a1a3b679SAndreas Boehler     * Creates a new directory
111*a1a3b679SAndreas Boehler     *
112*a1a3b679SAndreas Boehler     * We actually block this, as subdirectories are not allowed in addressbooks.
113*a1a3b679SAndreas Boehler     *
114*a1a3b679SAndreas Boehler     * @param string $name
115*a1a3b679SAndreas Boehler     * @return void
116*a1a3b679SAndreas Boehler     */
117*a1a3b679SAndreas Boehler    function createDirectory($name) {
118*a1a3b679SAndreas Boehler
119*a1a3b679SAndreas Boehler        throw new DAV\Exception\MethodNotAllowed('Creating collections in addressbooks is not allowed');
120*a1a3b679SAndreas Boehler
121*a1a3b679SAndreas Boehler    }
122*a1a3b679SAndreas Boehler
123*a1a3b679SAndreas Boehler    /**
124*a1a3b679SAndreas Boehler     * Creates a new file
125*a1a3b679SAndreas Boehler     *
126*a1a3b679SAndreas Boehler     * The contents of the new file must be a valid VCARD.
127*a1a3b679SAndreas Boehler     *
128*a1a3b679SAndreas Boehler     * This method may return an ETag.
129*a1a3b679SAndreas Boehler     *
130*a1a3b679SAndreas Boehler     * @param string $name
131*a1a3b679SAndreas Boehler     * @param resource $vcardData
132*a1a3b679SAndreas Boehler     * @return string|null
133*a1a3b679SAndreas Boehler     */
134*a1a3b679SAndreas Boehler    function createFile($name, $vcardData = null) {
135*a1a3b679SAndreas Boehler
136*a1a3b679SAndreas Boehler        if (is_resource($vcardData)) {
137*a1a3b679SAndreas Boehler            $vcardData = stream_get_contents($vcardData);
138*a1a3b679SAndreas Boehler        }
139*a1a3b679SAndreas Boehler        // Converting to UTF-8, if needed
140*a1a3b679SAndreas Boehler        $vcardData = DAV\StringUtil::ensureUTF8($vcardData);
141*a1a3b679SAndreas Boehler
142*a1a3b679SAndreas Boehler        return $this->carddavBackend->createCard($this->addressBookInfo['id'], $name, $vcardData);
143*a1a3b679SAndreas Boehler
144*a1a3b679SAndreas Boehler    }
145*a1a3b679SAndreas Boehler
146*a1a3b679SAndreas Boehler    /**
147*a1a3b679SAndreas Boehler     * Deletes the entire addressbook.
148*a1a3b679SAndreas Boehler     *
149*a1a3b679SAndreas Boehler     * @return void
150*a1a3b679SAndreas Boehler     */
151*a1a3b679SAndreas Boehler    function delete() {
152*a1a3b679SAndreas Boehler
153*a1a3b679SAndreas Boehler        $this->carddavBackend->deleteAddressBook($this->addressBookInfo['id']);
154*a1a3b679SAndreas Boehler
155*a1a3b679SAndreas Boehler    }
156*a1a3b679SAndreas Boehler
157*a1a3b679SAndreas Boehler    /**
158*a1a3b679SAndreas Boehler     * Renames the addressbook
159*a1a3b679SAndreas Boehler     *
160*a1a3b679SAndreas Boehler     * @param string $newName
161*a1a3b679SAndreas Boehler     * @return void
162*a1a3b679SAndreas Boehler     */
163*a1a3b679SAndreas Boehler    function setName($newName) {
164*a1a3b679SAndreas Boehler
165*a1a3b679SAndreas Boehler        throw new DAV\Exception\MethodNotAllowed('Renaming addressbooks is not yet supported');
166*a1a3b679SAndreas Boehler
167*a1a3b679SAndreas Boehler    }
168*a1a3b679SAndreas Boehler
169*a1a3b679SAndreas Boehler    /**
170*a1a3b679SAndreas Boehler     * Returns the last modification date as a unix timestamp.
171*a1a3b679SAndreas Boehler     *
172*a1a3b679SAndreas Boehler     * @return void
173*a1a3b679SAndreas Boehler     */
174*a1a3b679SAndreas Boehler    function getLastModified() {
175*a1a3b679SAndreas Boehler
176*a1a3b679SAndreas Boehler        return null;
177*a1a3b679SAndreas Boehler
178*a1a3b679SAndreas Boehler    }
179*a1a3b679SAndreas Boehler
180*a1a3b679SAndreas Boehler    /**
181*a1a3b679SAndreas Boehler     * Updates properties on this node.
182*a1a3b679SAndreas Boehler     *
183*a1a3b679SAndreas Boehler     * This method received a PropPatch object, which contains all the
184*a1a3b679SAndreas Boehler     * information about the update.
185*a1a3b679SAndreas Boehler     *
186*a1a3b679SAndreas Boehler     * To update specific properties, call the 'handle' method on this object.
187*a1a3b679SAndreas Boehler     * Read the PropPatch documentation for more information.
188*a1a3b679SAndreas Boehler     *
189*a1a3b679SAndreas Boehler     * @param DAV\PropPatch $propPatch
190*a1a3b679SAndreas Boehler     * @return void
191*a1a3b679SAndreas Boehler     */
192*a1a3b679SAndreas Boehler    function propPatch(DAV\PropPatch $propPatch) {
193*a1a3b679SAndreas Boehler
194*a1a3b679SAndreas Boehler        return $this->carddavBackend->updateAddressBook($this->addressBookInfo['id'], $propPatch);
195*a1a3b679SAndreas Boehler
196*a1a3b679SAndreas Boehler    }
197*a1a3b679SAndreas Boehler
198*a1a3b679SAndreas Boehler    /**
199*a1a3b679SAndreas Boehler     * Returns a list of properties for this nodes.
200*a1a3b679SAndreas Boehler     *
201*a1a3b679SAndreas Boehler     * The properties list is a list of propertynames the client requested,
202*a1a3b679SAndreas Boehler     * encoded in clark-notation {xmlnamespace}tagname
203*a1a3b679SAndreas Boehler     *
204*a1a3b679SAndreas Boehler     * If the array is empty, it means 'all properties' were requested.
205*a1a3b679SAndreas Boehler     *
206*a1a3b679SAndreas Boehler     * @param array $properties
207*a1a3b679SAndreas Boehler     * @return array
208*a1a3b679SAndreas Boehler     */
209*a1a3b679SAndreas Boehler    function getProperties($properties) {
210*a1a3b679SAndreas Boehler
211*a1a3b679SAndreas Boehler        $response = [];
212*a1a3b679SAndreas Boehler        foreach ($properties as $propertyName) {
213*a1a3b679SAndreas Boehler
214*a1a3b679SAndreas Boehler            if (isset($this->addressBookInfo[$propertyName])) {
215*a1a3b679SAndreas Boehler
216*a1a3b679SAndreas Boehler                $response[$propertyName] = $this->addressBookInfo[$propertyName];
217*a1a3b679SAndreas Boehler
218*a1a3b679SAndreas Boehler            }
219*a1a3b679SAndreas Boehler
220*a1a3b679SAndreas Boehler        }
221*a1a3b679SAndreas Boehler
222*a1a3b679SAndreas Boehler        return $response;
223*a1a3b679SAndreas Boehler
224*a1a3b679SAndreas Boehler    }
225*a1a3b679SAndreas Boehler
226*a1a3b679SAndreas Boehler    /**
227*a1a3b679SAndreas Boehler     * Returns the owner principal
228*a1a3b679SAndreas Boehler     *
229*a1a3b679SAndreas Boehler     * This must be a url to a principal, or null if there's no owner
230*a1a3b679SAndreas Boehler     *
231*a1a3b679SAndreas Boehler     * @return string|null
232*a1a3b679SAndreas Boehler     */
233*a1a3b679SAndreas Boehler    function getOwner() {
234*a1a3b679SAndreas Boehler
235*a1a3b679SAndreas Boehler        return $this->addressBookInfo['principaluri'];
236*a1a3b679SAndreas Boehler
237*a1a3b679SAndreas Boehler    }
238*a1a3b679SAndreas Boehler
239*a1a3b679SAndreas Boehler    /**
240*a1a3b679SAndreas Boehler     * Returns a group principal
241*a1a3b679SAndreas Boehler     *
242*a1a3b679SAndreas Boehler     * This must be a url to a principal, or null if there's no owner
243*a1a3b679SAndreas Boehler     *
244*a1a3b679SAndreas Boehler     * @return string|null
245*a1a3b679SAndreas Boehler     */
246*a1a3b679SAndreas Boehler    function getGroup() {
247*a1a3b679SAndreas Boehler
248*a1a3b679SAndreas Boehler        return null;
249*a1a3b679SAndreas Boehler
250*a1a3b679SAndreas Boehler    }
251*a1a3b679SAndreas Boehler
252*a1a3b679SAndreas Boehler    /**
253*a1a3b679SAndreas Boehler     * Returns a list of ACE's for this node.
254*a1a3b679SAndreas Boehler     *
255*a1a3b679SAndreas Boehler     * Each ACE has the following properties:
256*a1a3b679SAndreas Boehler     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
257*a1a3b679SAndreas Boehler     *     currently the only supported privileges
258*a1a3b679SAndreas Boehler     *   * 'principal', a url to the principal who owns the node
259*a1a3b679SAndreas Boehler     *   * 'protected' (optional), indicating that this ACE is not allowed to
260*a1a3b679SAndreas Boehler     *      be updated.
261*a1a3b679SAndreas Boehler     *
262*a1a3b679SAndreas Boehler     * @return array
263*a1a3b679SAndreas Boehler     */
264*a1a3b679SAndreas Boehler    function getACL() {
265*a1a3b679SAndreas Boehler
266*a1a3b679SAndreas Boehler        return [
267*a1a3b679SAndreas Boehler            [
268*a1a3b679SAndreas Boehler                'privilege' => '{DAV:}read',
269*a1a3b679SAndreas Boehler                'principal' => $this->getOwner(),
270*a1a3b679SAndreas Boehler                'protected' => true,
271*a1a3b679SAndreas Boehler            ],
272*a1a3b679SAndreas Boehler            [
273*a1a3b679SAndreas Boehler                'privilege' => '{DAV:}write',
274*a1a3b679SAndreas Boehler                'principal' => $this->getOwner(),
275*a1a3b679SAndreas Boehler                'protected' => true,
276*a1a3b679SAndreas Boehler            ],
277*a1a3b679SAndreas Boehler
278*a1a3b679SAndreas Boehler        ];
279*a1a3b679SAndreas Boehler
280*a1a3b679SAndreas Boehler    }
281*a1a3b679SAndreas Boehler
282*a1a3b679SAndreas Boehler    /**
283*a1a3b679SAndreas Boehler     * This method returns the ACL's for card nodes in this address book.
284*a1a3b679SAndreas Boehler     * The result of this method automatically gets passed to the
285*a1a3b679SAndreas Boehler     * card nodes in this address book.
286*a1a3b679SAndreas Boehler     *
287*a1a3b679SAndreas Boehler     * @return array
288*a1a3b679SAndreas Boehler     */
289*a1a3b679SAndreas Boehler    function getChildACL() {
290*a1a3b679SAndreas Boehler
291*a1a3b679SAndreas Boehler        return [
292*a1a3b679SAndreas Boehler            [
293*a1a3b679SAndreas Boehler                'privilege' => '{DAV:}read',
294*a1a3b679SAndreas Boehler                'principal' => $this->getOwner(),
295*a1a3b679SAndreas Boehler                'protected' => true,
296*a1a3b679SAndreas Boehler            ],
297*a1a3b679SAndreas Boehler            [
298*a1a3b679SAndreas Boehler                'privilege' => '{DAV:}write',
299*a1a3b679SAndreas Boehler                'principal' => $this->getOwner(),
300*a1a3b679SAndreas Boehler                'protected' => true,
301*a1a3b679SAndreas Boehler            ],
302*a1a3b679SAndreas Boehler        ];
303*a1a3b679SAndreas Boehler
304*a1a3b679SAndreas Boehler    }
305*a1a3b679SAndreas Boehler
306*a1a3b679SAndreas Boehler    /**
307*a1a3b679SAndreas Boehler     * Updates the ACL
308*a1a3b679SAndreas Boehler     *
309*a1a3b679SAndreas Boehler     * This method will receive a list of new ACE's.
310*a1a3b679SAndreas Boehler     *
311*a1a3b679SAndreas Boehler     * @param array $acl
312*a1a3b679SAndreas Boehler     * @return void
313*a1a3b679SAndreas Boehler     */
314*a1a3b679SAndreas Boehler    function setACL(array $acl) {
315*a1a3b679SAndreas Boehler
316*a1a3b679SAndreas Boehler        throw new DAV\Exception\MethodNotAllowed('Changing ACL is not yet supported');
317*a1a3b679SAndreas Boehler
318*a1a3b679SAndreas Boehler    }
319*a1a3b679SAndreas Boehler
320*a1a3b679SAndreas Boehler    /**
321*a1a3b679SAndreas Boehler     * Returns the list of supported privileges for this node.
322*a1a3b679SAndreas Boehler     *
323*a1a3b679SAndreas Boehler     * The returned data structure is a list of nested privileges.
324*a1a3b679SAndreas Boehler     * See Sabre\DAVACL\Plugin::getDefaultSupportedPrivilegeSet for a simple
325*a1a3b679SAndreas Boehler     * standard structure.
326*a1a3b679SAndreas Boehler     *
327*a1a3b679SAndreas Boehler     * If null is returned from this method, the default privilege set is used,
328*a1a3b679SAndreas Boehler     * which is fine for most common usecases.
329*a1a3b679SAndreas Boehler     *
330*a1a3b679SAndreas Boehler     * @return array|null
331*a1a3b679SAndreas Boehler     */
332*a1a3b679SAndreas Boehler    function getSupportedPrivilegeSet() {
333*a1a3b679SAndreas Boehler
334*a1a3b679SAndreas Boehler        return null;
335*a1a3b679SAndreas Boehler
336*a1a3b679SAndreas Boehler    }
337*a1a3b679SAndreas Boehler
338*a1a3b679SAndreas Boehler    /**
339*a1a3b679SAndreas Boehler     * This method returns the current sync-token for this collection.
340*a1a3b679SAndreas Boehler     * This can be any string.
341*a1a3b679SAndreas Boehler     *
342*a1a3b679SAndreas Boehler     * If null is returned from this function, the plugin assumes there's no
343*a1a3b679SAndreas Boehler     * sync information available.
344*a1a3b679SAndreas Boehler     *
345*a1a3b679SAndreas Boehler     * @return string|null
346*a1a3b679SAndreas Boehler     */
347*a1a3b679SAndreas Boehler    function getSyncToken() {
348*a1a3b679SAndreas Boehler
349*a1a3b679SAndreas Boehler        if (
350*a1a3b679SAndreas Boehler            $this->carddavBackend instanceof Backend\SyncSupport &&
351*a1a3b679SAndreas Boehler            isset($this->addressBookInfo['{DAV:}sync-token'])
352*a1a3b679SAndreas Boehler        ) {
353*a1a3b679SAndreas Boehler            return $this->addressBookInfo['{DAV:}sync-token'];
354*a1a3b679SAndreas Boehler        }
355*a1a3b679SAndreas Boehler        if (
356*a1a3b679SAndreas Boehler            $this->carddavBackend instanceof Backend\SyncSupport &&
357*a1a3b679SAndreas Boehler            isset($this->addressBookInfo['{http://sabredav.org/ns}sync-token'])
358*a1a3b679SAndreas Boehler        ) {
359*a1a3b679SAndreas Boehler            return $this->addressBookInfo['{http://sabredav.org/ns}sync-token'];
360*a1a3b679SAndreas Boehler        }
361*a1a3b679SAndreas Boehler
362*a1a3b679SAndreas Boehler    }
363*a1a3b679SAndreas Boehler
364*a1a3b679SAndreas Boehler    /**
365*a1a3b679SAndreas Boehler     * The getChanges method returns all the changes that have happened, since
366*a1a3b679SAndreas Boehler     * the specified syncToken and the current collection.
367*a1a3b679SAndreas Boehler     *
368*a1a3b679SAndreas Boehler     * This function should return an array, such as the following:
369*a1a3b679SAndreas Boehler     *
370*a1a3b679SAndreas Boehler     * [
371*a1a3b679SAndreas Boehler     *   'syncToken' => 'The current synctoken',
372*a1a3b679SAndreas Boehler     *   'added'   => [
373*a1a3b679SAndreas Boehler     *      'new.txt',
374*a1a3b679SAndreas Boehler     *   ],
375*a1a3b679SAndreas Boehler     *   'modified'   => [
376*a1a3b679SAndreas Boehler     *      'modified.txt',
377*a1a3b679SAndreas Boehler     *   ],
378*a1a3b679SAndreas Boehler     *   'deleted' => [
379*a1a3b679SAndreas Boehler     *      'foo.php.bak',
380*a1a3b679SAndreas Boehler     *      'old.txt'
381*a1a3b679SAndreas Boehler     *   ]
382*a1a3b679SAndreas Boehler     * ];
383*a1a3b679SAndreas Boehler     *
384*a1a3b679SAndreas Boehler     * The syncToken property should reflect the *current* syncToken of the
385*a1a3b679SAndreas Boehler     * collection, as reported getSyncToken(). This is needed here too, to
386*a1a3b679SAndreas Boehler     * ensure the operation is atomic.
387*a1a3b679SAndreas Boehler     *
388*a1a3b679SAndreas Boehler     * If the syncToken is specified as null, this is an initial sync, and all
389*a1a3b679SAndreas Boehler     * members should be reported.
390*a1a3b679SAndreas Boehler     *
391*a1a3b679SAndreas Boehler     * The modified property is an array of nodenames that have changed since
392*a1a3b679SAndreas Boehler     * the last token.
393*a1a3b679SAndreas Boehler     *
394*a1a3b679SAndreas Boehler     * The deleted property is an array with nodenames, that have been deleted
395*a1a3b679SAndreas Boehler     * from collection.
396*a1a3b679SAndreas Boehler     *
397*a1a3b679SAndreas Boehler     * The second argument is basically the 'depth' of the report. If it's 1,
398*a1a3b679SAndreas Boehler     * you only have to report changes that happened only directly in immediate
399*a1a3b679SAndreas Boehler     * descendants. If it's 2, it should also include changes from the nodes
400*a1a3b679SAndreas Boehler     * below the child collections. (grandchildren)
401*a1a3b679SAndreas Boehler     *
402*a1a3b679SAndreas Boehler     * The third (optional) argument allows a client to specify how many
403*a1a3b679SAndreas Boehler     * results should be returned at most. If the limit is not specified, it
404*a1a3b679SAndreas Boehler     * should be treated as infinite.
405*a1a3b679SAndreas Boehler     *
406*a1a3b679SAndreas Boehler     * If the limit (infinite or not) is higher than you're willing to return,
407*a1a3b679SAndreas Boehler     * you should throw a Sabre\DAV\Exception\TooMuchMatches() exception.
408*a1a3b679SAndreas Boehler     *
409*a1a3b679SAndreas Boehler     * If the syncToken is expired (due to data cleanup) or unknown, you must
410*a1a3b679SAndreas Boehler     * return null.
411*a1a3b679SAndreas Boehler     *
412*a1a3b679SAndreas Boehler     * The limit is 'suggestive'. You are free to ignore it.
413*a1a3b679SAndreas Boehler     *
414*a1a3b679SAndreas Boehler     * @param string $syncToken
415*a1a3b679SAndreas Boehler     * @param int $syncLevel
416*a1a3b679SAndreas Boehler     * @param int $limit
417*a1a3b679SAndreas Boehler     * @return array
418*a1a3b679SAndreas Boehler     */
419*a1a3b679SAndreas Boehler    function getChanges($syncToken, $syncLevel, $limit = null) {
420*a1a3b679SAndreas Boehler
421*a1a3b679SAndreas Boehler        if (!$this->carddavBackend instanceof Backend\SyncSupport) {
422*a1a3b679SAndreas Boehler            return null;
423*a1a3b679SAndreas Boehler        }
424*a1a3b679SAndreas Boehler
425*a1a3b679SAndreas Boehler        return $this->carddavBackend->getChangesForAddressBook(
426*a1a3b679SAndreas Boehler            $this->addressBookInfo['id'],
427*a1a3b679SAndreas Boehler            $syncToken,
428*a1a3b679SAndreas Boehler            $syncLevel,
429*a1a3b679SAndreas Boehler            $limit
430*a1a3b679SAndreas Boehler        );
431*a1a3b679SAndreas Boehler
432*a1a3b679SAndreas Boehler    }
433*a1a3b679SAndreas Boehler}
434