1*a1a3b679SAndreas Boehler<?php 2*a1a3b679SAndreas Boehler 3*a1a3b679SAndreas Boehlernamespace Sabre\CalDAV; 4*a1a3b679SAndreas Boehler 5*a1a3b679SAndreas Boehleruse Sabre\DAV; 6*a1a3b679SAndreas Boehleruse Sabre\DAVACL; 7*a1a3b679SAndreas Boehleruse Sabre\DAV\PropPatch; 8*a1a3b679SAndreas Boehler 9*a1a3b679SAndreas Boehler/** 10*a1a3b679SAndreas Boehler * This object represents a CalDAV calendar. 11*a1a3b679SAndreas Boehler * 12*a1a3b679SAndreas Boehler * A calendar can contain multiple TODO and or Events. These are represented 13*a1a3b679SAndreas Boehler * as \Sabre\CalDAV\CalendarObject objects. 14*a1a3b679SAndreas Boehler * 15*a1a3b679SAndreas Boehler * @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/). 16*a1a3b679SAndreas Boehler * @author Evert Pot (http://evertpot.com/) 17*a1a3b679SAndreas Boehler * @license http://sabre.io/license/ Modified BSD License 18*a1a3b679SAndreas Boehler */ 19*a1a3b679SAndreas Boehlerclass Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection, DAV\IMultiGet { 20*a1a3b679SAndreas Boehler 21*a1a3b679SAndreas Boehler /** 22*a1a3b679SAndreas Boehler * This is an array with calendar information 23*a1a3b679SAndreas Boehler * 24*a1a3b679SAndreas Boehler * @var array 25*a1a3b679SAndreas Boehler */ 26*a1a3b679SAndreas Boehler protected $calendarInfo; 27*a1a3b679SAndreas Boehler 28*a1a3b679SAndreas Boehler /** 29*a1a3b679SAndreas Boehler * CalDAV backend 30*a1a3b679SAndreas Boehler * 31*a1a3b679SAndreas Boehler * @var Backend\BackendInterface 32*a1a3b679SAndreas Boehler */ 33*a1a3b679SAndreas Boehler protected $caldavBackend; 34*a1a3b679SAndreas Boehler 35*a1a3b679SAndreas Boehler /** 36*a1a3b679SAndreas Boehler * Constructor 37*a1a3b679SAndreas Boehler * 38*a1a3b679SAndreas Boehler * @param Backend\BackendInterface $caldavBackend 39*a1a3b679SAndreas Boehler * @param array $calendarInfo 40*a1a3b679SAndreas Boehler */ 41*a1a3b679SAndreas Boehler function __construct(Backend\BackendInterface $caldavBackend, $calendarInfo) { 42*a1a3b679SAndreas Boehler 43*a1a3b679SAndreas Boehler $this->caldavBackend = $caldavBackend; 44*a1a3b679SAndreas Boehler $this->calendarInfo = $calendarInfo; 45*a1a3b679SAndreas Boehler 46*a1a3b679SAndreas Boehler } 47*a1a3b679SAndreas Boehler 48*a1a3b679SAndreas Boehler /** 49*a1a3b679SAndreas Boehler * Returns the name of the calendar 50*a1a3b679SAndreas Boehler * 51*a1a3b679SAndreas Boehler * @return string 52*a1a3b679SAndreas Boehler */ 53*a1a3b679SAndreas Boehler function getName() { 54*a1a3b679SAndreas Boehler 55*a1a3b679SAndreas Boehler return $this->calendarInfo['uri']; 56*a1a3b679SAndreas Boehler 57*a1a3b679SAndreas Boehler } 58*a1a3b679SAndreas Boehler 59*a1a3b679SAndreas Boehler /** 60*a1a3b679SAndreas Boehler * Updates properties on this node. 61*a1a3b679SAndreas Boehler * 62*a1a3b679SAndreas Boehler * This method received a PropPatch object, which contains all the 63*a1a3b679SAndreas Boehler * information about the update. 64*a1a3b679SAndreas Boehler * 65*a1a3b679SAndreas Boehler * To update specific properties, call the 'handle' method on this object. 66*a1a3b679SAndreas Boehler * Read the PropPatch documentation for more information. 67*a1a3b679SAndreas Boehler * 68*a1a3b679SAndreas Boehler * @param PropPatch $propPatch 69*a1a3b679SAndreas Boehler * @return void 70*a1a3b679SAndreas Boehler */ 71*a1a3b679SAndreas Boehler function propPatch(PropPatch $propPatch) { 72*a1a3b679SAndreas Boehler 73*a1a3b679SAndreas Boehler return $this->caldavBackend->updateCalendar($this->calendarInfo['id'], $propPatch); 74*a1a3b679SAndreas Boehler 75*a1a3b679SAndreas Boehler } 76*a1a3b679SAndreas Boehler 77*a1a3b679SAndreas Boehler /** 78*a1a3b679SAndreas Boehler * Returns the list of properties 79*a1a3b679SAndreas Boehler * 80*a1a3b679SAndreas Boehler * @param array $requestedProperties 81*a1a3b679SAndreas Boehler * @return array 82*a1a3b679SAndreas Boehler */ 83*a1a3b679SAndreas Boehler function getProperties($requestedProperties) { 84*a1a3b679SAndreas Boehler 85*a1a3b679SAndreas Boehler $response = []; 86*a1a3b679SAndreas Boehler 87*a1a3b679SAndreas Boehler foreach ($this->calendarInfo as $propName => $propValue) { 88*a1a3b679SAndreas Boehler 89*a1a3b679SAndreas Boehler if ($propName[0] === '{') 90*a1a3b679SAndreas Boehler $response[$propName] = $this->calendarInfo[$propName]; 91*a1a3b679SAndreas Boehler 92*a1a3b679SAndreas Boehler } 93*a1a3b679SAndreas Boehler return $response; 94*a1a3b679SAndreas Boehler 95*a1a3b679SAndreas Boehler } 96*a1a3b679SAndreas Boehler 97*a1a3b679SAndreas Boehler /** 98*a1a3b679SAndreas Boehler * Returns a calendar object 99*a1a3b679SAndreas Boehler * 100*a1a3b679SAndreas Boehler * The contained calendar objects are for example Events or Todo's. 101*a1a3b679SAndreas Boehler * 102*a1a3b679SAndreas Boehler * @param string $name 103*a1a3b679SAndreas Boehler * @return \Sabre\CalDAV\ICalendarObject 104*a1a3b679SAndreas Boehler */ 105*a1a3b679SAndreas Boehler function getChild($name) { 106*a1a3b679SAndreas Boehler 107*a1a3b679SAndreas Boehler $obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'], $name); 108*a1a3b679SAndreas Boehler 109*a1a3b679SAndreas Boehler if (!$obj) throw new DAV\Exception\NotFound('Calendar object not found'); 110*a1a3b679SAndreas Boehler 111*a1a3b679SAndreas Boehler $obj['acl'] = $this->getChildACL(); 112*a1a3b679SAndreas Boehler 113*a1a3b679SAndreas Boehler return new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj); 114*a1a3b679SAndreas Boehler 115*a1a3b679SAndreas Boehler } 116*a1a3b679SAndreas Boehler 117*a1a3b679SAndreas Boehler /** 118*a1a3b679SAndreas Boehler * Returns the full list of calendar objects 119*a1a3b679SAndreas Boehler * 120*a1a3b679SAndreas Boehler * @return array 121*a1a3b679SAndreas Boehler */ 122*a1a3b679SAndreas Boehler function getChildren() { 123*a1a3b679SAndreas Boehler 124*a1a3b679SAndreas Boehler $objs = $this->caldavBackend->getCalendarObjects($this->calendarInfo['id']); 125*a1a3b679SAndreas Boehler $children = []; 126*a1a3b679SAndreas Boehler foreach ($objs as $obj) { 127*a1a3b679SAndreas Boehler $obj['acl'] = $this->getChildACL(); 128*a1a3b679SAndreas Boehler $children[] = new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj); 129*a1a3b679SAndreas Boehler } 130*a1a3b679SAndreas Boehler return $children; 131*a1a3b679SAndreas Boehler 132*a1a3b679SAndreas Boehler } 133*a1a3b679SAndreas Boehler 134*a1a3b679SAndreas Boehler /** 135*a1a3b679SAndreas Boehler * This method receives a list of paths in it's first argument. 136*a1a3b679SAndreas Boehler * It must return an array with Node objects. 137*a1a3b679SAndreas Boehler * 138*a1a3b679SAndreas Boehler * If any children are not found, you do not have to return them. 139*a1a3b679SAndreas Boehler * 140*a1a3b679SAndreas Boehler * @param string[] $paths 141*a1a3b679SAndreas Boehler * @return array 142*a1a3b679SAndreas Boehler */ 143*a1a3b679SAndreas Boehler function getMultipleChildren(array $paths) { 144*a1a3b679SAndreas Boehler 145*a1a3b679SAndreas Boehler $objs = $this->caldavBackend->getMultipleCalendarObjects($this->calendarInfo['id'], $paths); 146*a1a3b679SAndreas Boehler $children = []; 147*a1a3b679SAndreas Boehler foreach ($objs as $obj) { 148*a1a3b679SAndreas Boehler $obj['acl'] = $this->getChildACL(); 149*a1a3b679SAndreas Boehler $children[] = new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj); 150*a1a3b679SAndreas Boehler } 151*a1a3b679SAndreas Boehler return $children; 152*a1a3b679SAndreas Boehler 153*a1a3b679SAndreas Boehler } 154*a1a3b679SAndreas Boehler 155*a1a3b679SAndreas Boehler /** 156*a1a3b679SAndreas Boehler * Checks if a child-node exists. 157*a1a3b679SAndreas Boehler * 158*a1a3b679SAndreas Boehler * @param string $name 159*a1a3b679SAndreas Boehler * @return bool 160*a1a3b679SAndreas Boehler */ 161*a1a3b679SAndreas Boehler function childExists($name) { 162*a1a3b679SAndreas Boehler 163*a1a3b679SAndreas Boehler $obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'], $name); 164*a1a3b679SAndreas Boehler if (!$obj) 165*a1a3b679SAndreas Boehler return false; 166*a1a3b679SAndreas Boehler else 167*a1a3b679SAndreas Boehler return true; 168*a1a3b679SAndreas Boehler 169*a1a3b679SAndreas Boehler } 170*a1a3b679SAndreas Boehler 171*a1a3b679SAndreas Boehler /** 172*a1a3b679SAndreas Boehler * Creates a new directory 173*a1a3b679SAndreas Boehler * 174*a1a3b679SAndreas Boehler * We actually block this, as subdirectories are not allowed in calendars. 175*a1a3b679SAndreas Boehler * 176*a1a3b679SAndreas Boehler * @param string $name 177*a1a3b679SAndreas Boehler * @return void 178*a1a3b679SAndreas Boehler */ 179*a1a3b679SAndreas Boehler function createDirectory($name) { 180*a1a3b679SAndreas Boehler 181*a1a3b679SAndreas Boehler throw new DAV\Exception\MethodNotAllowed('Creating collections in calendar objects is not allowed'); 182*a1a3b679SAndreas Boehler 183*a1a3b679SAndreas Boehler } 184*a1a3b679SAndreas Boehler 185*a1a3b679SAndreas Boehler /** 186*a1a3b679SAndreas Boehler * Creates a new file 187*a1a3b679SAndreas Boehler * 188*a1a3b679SAndreas Boehler * The contents of the new file must be a valid ICalendar string. 189*a1a3b679SAndreas Boehler * 190*a1a3b679SAndreas Boehler * @param string $name 191*a1a3b679SAndreas Boehler * @param resource $calendarData 192*a1a3b679SAndreas Boehler * @return string|null 193*a1a3b679SAndreas Boehler */ 194*a1a3b679SAndreas Boehler function createFile($name, $calendarData = null) { 195*a1a3b679SAndreas Boehler 196*a1a3b679SAndreas Boehler if (is_resource($calendarData)) { 197*a1a3b679SAndreas Boehler $calendarData = stream_get_contents($calendarData); 198*a1a3b679SAndreas Boehler } 199*a1a3b679SAndreas Boehler return $this->caldavBackend->createCalendarObject($this->calendarInfo['id'], $name, $calendarData); 200*a1a3b679SAndreas Boehler 201*a1a3b679SAndreas Boehler } 202*a1a3b679SAndreas Boehler 203*a1a3b679SAndreas Boehler /** 204*a1a3b679SAndreas Boehler * Deletes the calendar. 205*a1a3b679SAndreas Boehler * 206*a1a3b679SAndreas Boehler * @return void 207*a1a3b679SAndreas Boehler */ 208*a1a3b679SAndreas Boehler function delete() { 209*a1a3b679SAndreas Boehler 210*a1a3b679SAndreas Boehler $this->caldavBackend->deleteCalendar($this->calendarInfo['id']); 211*a1a3b679SAndreas Boehler 212*a1a3b679SAndreas Boehler } 213*a1a3b679SAndreas Boehler 214*a1a3b679SAndreas Boehler /** 215*a1a3b679SAndreas Boehler * Renames the calendar. Note that most calendars use the 216*a1a3b679SAndreas Boehler * {DAV:}displayname to display a name to display a name. 217*a1a3b679SAndreas Boehler * 218*a1a3b679SAndreas Boehler * @param string $newName 219*a1a3b679SAndreas Boehler * @return void 220*a1a3b679SAndreas Boehler */ 221*a1a3b679SAndreas Boehler function setName($newName) { 222*a1a3b679SAndreas Boehler 223*a1a3b679SAndreas Boehler throw new DAV\Exception\MethodNotAllowed('Renaming calendars is not yet supported'); 224*a1a3b679SAndreas Boehler 225*a1a3b679SAndreas Boehler } 226*a1a3b679SAndreas Boehler 227*a1a3b679SAndreas Boehler /** 228*a1a3b679SAndreas Boehler * Returns the last modification date as a unix timestamp. 229*a1a3b679SAndreas Boehler * 230*a1a3b679SAndreas Boehler * @return void 231*a1a3b679SAndreas Boehler */ 232*a1a3b679SAndreas Boehler function getLastModified() { 233*a1a3b679SAndreas Boehler 234*a1a3b679SAndreas Boehler return null; 235*a1a3b679SAndreas Boehler 236*a1a3b679SAndreas Boehler } 237*a1a3b679SAndreas Boehler 238*a1a3b679SAndreas Boehler /** 239*a1a3b679SAndreas Boehler * Returns the owner principal 240*a1a3b679SAndreas Boehler * 241*a1a3b679SAndreas Boehler * This must be a url to a principal, or null if there's no owner 242*a1a3b679SAndreas Boehler * 243*a1a3b679SAndreas Boehler * @return string|null 244*a1a3b679SAndreas Boehler */ 245*a1a3b679SAndreas Boehler function getOwner() { 246*a1a3b679SAndreas Boehler 247*a1a3b679SAndreas Boehler return $this->calendarInfo['principaluri']; 248*a1a3b679SAndreas Boehler 249*a1a3b679SAndreas Boehler } 250*a1a3b679SAndreas Boehler 251*a1a3b679SAndreas Boehler /** 252*a1a3b679SAndreas Boehler * Returns a group principal 253*a1a3b679SAndreas Boehler * 254*a1a3b679SAndreas Boehler * This must be a url to a principal, or null if there's no owner 255*a1a3b679SAndreas Boehler * 256*a1a3b679SAndreas Boehler * @return string|null 257*a1a3b679SAndreas Boehler */ 258*a1a3b679SAndreas Boehler function getGroup() { 259*a1a3b679SAndreas Boehler 260*a1a3b679SAndreas Boehler return null; 261*a1a3b679SAndreas Boehler 262*a1a3b679SAndreas Boehler } 263*a1a3b679SAndreas Boehler 264*a1a3b679SAndreas Boehler /** 265*a1a3b679SAndreas Boehler * Returns a list of ACE's for this node. 266*a1a3b679SAndreas Boehler * 267*a1a3b679SAndreas Boehler * Each ACE has the following properties: 268*a1a3b679SAndreas Boehler * * 'privilege', a string such as {DAV:}read or {DAV:}write. These are 269*a1a3b679SAndreas Boehler * currently the only supported privileges 270*a1a3b679SAndreas Boehler * * 'principal', a url to the principal who owns the node 271*a1a3b679SAndreas Boehler * * 'protected' (optional), indicating that this ACE is not allowed to 272*a1a3b679SAndreas Boehler * be updated. 273*a1a3b679SAndreas Boehler * 274*a1a3b679SAndreas Boehler * @return array 275*a1a3b679SAndreas Boehler */ 276*a1a3b679SAndreas Boehler function getACL() { 277*a1a3b679SAndreas Boehler 278*a1a3b679SAndreas Boehler $acl = [ 279*a1a3b679SAndreas Boehler [ 280*a1a3b679SAndreas Boehler 'privilege' => '{DAV:}read', 281*a1a3b679SAndreas Boehler 'principal' => $this->getOwner(), 282*a1a3b679SAndreas Boehler 'protected' => true, 283*a1a3b679SAndreas Boehler ], 284*a1a3b679SAndreas Boehler [ 285*a1a3b679SAndreas Boehler 'privilege' => '{DAV:}read', 286*a1a3b679SAndreas Boehler 'principal' => $this->getOwner() . '/calendar-proxy-write', 287*a1a3b679SAndreas Boehler 'protected' => true, 288*a1a3b679SAndreas Boehler ], 289*a1a3b679SAndreas Boehler [ 290*a1a3b679SAndreas Boehler 'privilege' => '{DAV:}read', 291*a1a3b679SAndreas Boehler 'principal' => $this->getOwner() . '/calendar-proxy-read', 292*a1a3b679SAndreas Boehler 'protected' => true, 293*a1a3b679SAndreas Boehler ], 294*a1a3b679SAndreas Boehler [ 295*a1a3b679SAndreas Boehler 'privilege' => '{' . Plugin::NS_CALDAV . '}read-free-busy', 296*a1a3b679SAndreas Boehler 'principal' => '{DAV:}authenticated', 297*a1a3b679SAndreas Boehler 'protected' => true, 298*a1a3b679SAndreas Boehler ], 299*a1a3b679SAndreas Boehler 300*a1a3b679SAndreas Boehler ]; 301*a1a3b679SAndreas Boehler if (empty($this->calendarInfo['{http://sabredav.org/ns}read-only'])) { 302*a1a3b679SAndreas Boehler $acl[] = [ 303*a1a3b679SAndreas Boehler 'privilege' => '{DAV:}write', 304*a1a3b679SAndreas Boehler 'principal' => $this->getOwner(), 305*a1a3b679SAndreas Boehler 'protected' => true, 306*a1a3b679SAndreas Boehler ]; 307*a1a3b679SAndreas Boehler $acl[] = [ 308*a1a3b679SAndreas Boehler 'privilege' => '{DAV:}write', 309*a1a3b679SAndreas Boehler 'principal' => $this->getOwner() . '/calendar-proxy-write', 310*a1a3b679SAndreas Boehler 'protected' => true, 311*a1a3b679SAndreas Boehler ]; 312*a1a3b679SAndreas Boehler } 313*a1a3b679SAndreas Boehler 314*a1a3b679SAndreas Boehler return $acl; 315*a1a3b679SAndreas Boehler 316*a1a3b679SAndreas Boehler } 317*a1a3b679SAndreas Boehler 318*a1a3b679SAndreas Boehler /** 319*a1a3b679SAndreas Boehler * This method returns the ACL's for calendar objects in this calendar. 320*a1a3b679SAndreas Boehler * The result of this method automatically gets passed to the 321*a1a3b679SAndreas Boehler * calendar-object nodes in the calendar. 322*a1a3b679SAndreas Boehler * 323*a1a3b679SAndreas Boehler * @return array 324*a1a3b679SAndreas Boehler */ 325*a1a3b679SAndreas Boehler function getChildACL() { 326*a1a3b679SAndreas Boehler 327*a1a3b679SAndreas Boehler $acl = [ 328*a1a3b679SAndreas Boehler [ 329*a1a3b679SAndreas Boehler 'privilege' => '{DAV:}read', 330*a1a3b679SAndreas Boehler 'principal' => $this->getOwner(), 331*a1a3b679SAndreas Boehler 'protected' => true, 332*a1a3b679SAndreas Boehler ], 333*a1a3b679SAndreas Boehler 334*a1a3b679SAndreas Boehler [ 335*a1a3b679SAndreas Boehler 'privilege' => '{DAV:}read', 336*a1a3b679SAndreas Boehler 'principal' => $this->getOwner() . '/calendar-proxy-write', 337*a1a3b679SAndreas Boehler 'protected' => true, 338*a1a3b679SAndreas Boehler ], 339*a1a3b679SAndreas Boehler [ 340*a1a3b679SAndreas Boehler 'privilege' => '{DAV:}read', 341*a1a3b679SAndreas Boehler 'principal' => $this->getOwner() . '/calendar-proxy-read', 342*a1a3b679SAndreas Boehler 'protected' => true, 343*a1a3b679SAndreas Boehler ], 344*a1a3b679SAndreas Boehler 345*a1a3b679SAndreas Boehler ]; 346*a1a3b679SAndreas Boehler if (empty($this->calendarInfo['{http://sabredav.org/ns}read-only'])) { 347*a1a3b679SAndreas Boehler $acl[] = [ 348*a1a3b679SAndreas Boehler 'privilege' => '{DAV:}write', 349*a1a3b679SAndreas Boehler 'principal' => $this->getOwner(), 350*a1a3b679SAndreas Boehler 'protected' => true, 351*a1a3b679SAndreas Boehler ]; 352*a1a3b679SAndreas Boehler $acl[] = [ 353*a1a3b679SAndreas Boehler 'privilege' => '{DAV:}write', 354*a1a3b679SAndreas Boehler 'principal' => $this->getOwner() . '/calendar-proxy-write', 355*a1a3b679SAndreas Boehler 'protected' => true, 356*a1a3b679SAndreas Boehler ]; 357*a1a3b679SAndreas Boehler 358*a1a3b679SAndreas Boehler } 359*a1a3b679SAndreas Boehler return $acl; 360*a1a3b679SAndreas Boehler 361*a1a3b679SAndreas Boehler } 362*a1a3b679SAndreas Boehler 363*a1a3b679SAndreas Boehler /** 364*a1a3b679SAndreas Boehler * Updates the ACL 365*a1a3b679SAndreas Boehler * 366*a1a3b679SAndreas Boehler * This method will receive a list of new ACE's. 367*a1a3b679SAndreas Boehler * 368*a1a3b679SAndreas Boehler * @param array $acl 369*a1a3b679SAndreas Boehler * @return void 370*a1a3b679SAndreas Boehler */ 371*a1a3b679SAndreas Boehler function setACL(array $acl) { 372*a1a3b679SAndreas Boehler 373*a1a3b679SAndreas Boehler throw new DAV\Exception\MethodNotAllowed('Changing ACL is not yet supported'); 374*a1a3b679SAndreas Boehler 375*a1a3b679SAndreas Boehler } 376*a1a3b679SAndreas Boehler 377*a1a3b679SAndreas Boehler /** 378*a1a3b679SAndreas Boehler * Returns the list of supported privileges for this node. 379*a1a3b679SAndreas Boehler * 380*a1a3b679SAndreas Boehler * The returned data structure is a list of nested privileges. 381*a1a3b679SAndreas Boehler * See \Sabre\DAVACL\Plugin::getDefaultSupportedPrivilegeSet for a simple 382*a1a3b679SAndreas Boehler * standard structure. 383*a1a3b679SAndreas Boehler * 384*a1a3b679SAndreas Boehler * If null is returned from this method, the default privilege set is used, 385*a1a3b679SAndreas Boehler * which is fine for most common usecases. 386*a1a3b679SAndreas Boehler * 387*a1a3b679SAndreas Boehler * @return array|null 388*a1a3b679SAndreas Boehler */ 389*a1a3b679SAndreas Boehler function getSupportedPrivilegeSet() { 390*a1a3b679SAndreas Boehler 391*a1a3b679SAndreas Boehler $default = DAVACL\Plugin::getDefaultSupportedPrivilegeSet(); 392*a1a3b679SAndreas Boehler 393*a1a3b679SAndreas Boehler // We need to inject 'read-free-busy' in the tree, aggregated under 394*a1a3b679SAndreas Boehler // {DAV:}read. 395*a1a3b679SAndreas Boehler foreach ($default['aggregates'] as &$agg) { 396*a1a3b679SAndreas Boehler 397*a1a3b679SAndreas Boehler if ($agg['privilege'] !== '{DAV:}read') continue; 398*a1a3b679SAndreas Boehler 399*a1a3b679SAndreas Boehler $agg['aggregates'][] = [ 400*a1a3b679SAndreas Boehler 'privilege' => '{' . Plugin::NS_CALDAV . '}read-free-busy', 401*a1a3b679SAndreas Boehler ]; 402*a1a3b679SAndreas Boehler 403*a1a3b679SAndreas Boehler } 404*a1a3b679SAndreas Boehler return $default; 405*a1a3b679SAndreas Boehler 406*a1a3b679SAndreas Boehler } 407*a1a3b679SAndreas Boehler 408*a1a3b679SAndreas Boehler /** 409*a1a3b679SAndreas Boehler * Performs a calendar-query on the contents of this calendar. 410*a1a3b679SAndreas Boehler * 411*a1a3b679SAndreas Boehler * The calendar-query is defined in RFC4791 : CalDAV. Using the 412*a1a3b679SAndreas Boehler * calendar-query it is possible for a client to request a specific set of 413*a1a3b679SAndreas Boehler * object, based on contents of iCalendar properties, date-ranges and 414*a1a3b679SAndreas Boehler * iCalendar component types (VTODO, VEVENT). 415*a1a3b679SAndreas Boehler * 416*a1a3b679SAndreas Boehler * This method should just return a list of (relative) urls that match this 417*a1a3b679SAndreas Boehler * query. 418*a1a3b679SAndreas Boehler * 419*a1a3b679SAndreas Boehler * The list of filters are specified as an array. The exact array is 420*a1a3b679SAndreas Boehler * documented by Sabre\CalDAV\CalendarQueryParser. 421*a1a3b679SAndreas Boehler * 422*a1a3b679SAndreas Boehler * @param array $filters 423*a1a3b679SAndreas Boehler * @return array 424*a1a3b679SAndreas Boehler */ 425*a1a3b679SAndreas Boehler function calendarQuery(array $filters) { 426*a1a3b679SAndreas Boehler 427*a1a3b679SAndreas Boehler return $this->caldavBackend->calendarQuery($this->calendarInfo['id'], $filters); 428*a1a3b679SAndreas Boehler 429*a1a3b679SAndreas Boehler } 430*a1a3b679SAndreas Boehler 431*a1a3b679SAndreas Boehler /** 432*a1a3b679SAndreas Boehler * This method returns the current sync-token for this collection. 433*a1a3b679SAndreas Boehler * This can be any string. 434*a1a3b679SAndreas Boehler * 435*a1a3b679SAndreas Boehler * If null is returned from this function, the plugin assumes there's no 436*a1a3b679SAndreas Boehler * sync information available. 437*a1a3b679SAndreas Boehler * 438*a1a3b679SAndreas Boehler * @return string|null 439*a1a3b679SAndreas Boehler */ 440*a1a3b679SAndreas Boehler function getSyncToken() { 441*a1a3b679SAndreas Boehler 442*a1a3b679SAndreas Boehler if ( 443*a1a3b679SAndreas Boehler $this->caldavBackend instanceof Backend\SyncSupport && 444*a1a3b679SAndreas Boehler isset($this->calendarInfo['{DAV:}sync-token']) 445*a1a3b679SAndreas Boehler ) { 446*a1a3b679SAndreas Boehler return $this->calendarInfo['{DAV:}sync-token']; 447*a1a3b679SAndreas Boehler } 448*a1a3b679SAndreas Boehler if ( 449*a1a3b679SAndreas Boehler $this->caldavBackend instanceof Backend\SyncSupport && 450*a1a3b679SAndreas Boehler isset($this->calendarInfo['{http://sabredav.org/ns}sync-token']) 451*a1a3b679SAndreas Boehler ) { 452*a1a3b679SAndreas Boehler return $this->calendarInfo['{http://sabredav.org/ns}sync-token']; 453*a1a3b679SAndreas Boehler } 454*a1a3b679SAndreas Boehler 455*a1a3b679SAndreas Boehler } 456*a1a3b679SAndreas Boehler 457*a1a3b679SAndreas Boehler /** 458*a1a3b679SAndreas Boehler * The getChanges method returns all the changes that have happened, since 459*a1a3b679SAndreas Boehler * the specified syncToken and the current collection. 460*a1a3b679SAndreas Boehler * 461*a1a3b679SAndreas Boehler * This function should return an array, such as the following: 462*a1a3b679SAndreas Boehler * 463*a1a3b679SAndreas Boehler * [ 464*a1a3b679SAndreas Boehler * 'syncToken' => 'The current synctoken', 465*a1a3b679SAndreas Boehler * 'added' => [ 466*a1a3b679SAndreas Boehler * 'new.txt', 467*a1a3b679SAndreas Boehler * ], 468*a1a3b679SAndreas Boehler * 'modified' => [ 469*a1a3b679SAndreas Boehler * 'modified.txt', 470*a1a3b679SAndreas Boehler * ], 471*a1a3b679SAndreas Boehler * 'deleted' => [ 472*a1a3b679SAndreas Boehler * 'foo.php.bak', 473*a1a3b679SAndreas Boehler * 'old.txt' 474*a1a3b679SAndreas Boehler * ] 475*a1a3b679SAndreas Boehler * ]; 476*a1a3b679SAndreas Boehler * 477*a1a3b679SAndreas Boehler * The syncToken property should reflect the *current* syncToken of the 478*a1a3b679SAndreas Boehler * collection, as reported getSyncToken(). This is needed here too, to 479*a1a3b679SAndreas Boehler * ensure the operation is atomic. 480*a1a3b679SAndreas Boehler * 481*a1a3b679SAndreas Boehler * If the syncToken is specified as null, this is an initial sync, and all 482*a1a3b679SAndreas Boehler * members should be reported. 483*a1a3b679SAndreas Boehler * 484*a1a3b679SAndreas Boehler * The modified property is an array of nodenames that have changed since 485*a1a3b679SAndreas Boehler * the last token. 486*a1a3b679SAndreas Boehler * 487*a1a3b679SAndreas Boehler * The deleted property is an array with nodenames, that have been deleted 488*a1a3b679SAndreas Boehler * from collection. 489*a1a3b679SAndreas Boehler * 490*a1a3b679SAndreas Boehler * The second argument is basically the 'depth' of the report. If it's 1, 491*a1a3b679SAndreas Boehler * you only have to report changes that happened only directly in immediate 492*a1a3b679SAndreas Boehler * descendants. If it's 2, it should also include changes from the nodes 493*a1a3b679SAndreas Boehler * below the child collections. (grandchildren) 494*a1a3b679SAndreas Boehler * 495*a1a3b679SAndreas Boehler * The third (optional) argument allows a client to specify how many 496*a1a3b679SAndreas Boehler * results should be returned at most. If the limit is not specified, it 497*a1a3b679SAndreas Boehler * should be treated as infinite. 498*a1a3b679SAndreas Boehler * 499*a1a3b679SAndreas Boehler * If the limit (infinite or not) is higher than you're willing to return, 500*a1a3b679SAndreas Boehler * you should throw a Sabre\DAV\Exception\TooMuchMatches() exception. 501*a1a3b679SAndreas Boehler * 502*a1a3b679SAndreas Boehler * If the syncToken is expired (due to data cleanup) or unknown, you must 503*a1a3b679SAndreas Boehler * return null. 504*a1a3b679SAndreas Boehler * 505*a1a3b679SAndreas Boehler * The limit is 'suggestive'. You are free to ignore it. 506*a1a3b679SAndreas Boehler * 507*a1a3b679SAndreas Boehler * @param string $syncToken 508*a1a3b679SAndreas Boehler * @param int $syncLevel 509*a1a3b679SAndreas Boehler * @param int $limit 510*a1a3b679SAndreas Boehler * @return array 511*a1a3b679SAndreas Boehler */ 512*a1a3b679SAndreas Boehler function getChanges($syncToken, $syncLevel, $limit = null) { 513*a1a3b679SAndreas Boehler 514*a1a3b679SAndreas Boehler if (!$this->caldavBackend instanceof Backend\SyncSupport) { 515*a1a3b679SAndreas Boehler return null; 516*a1a3b679SAndreas Boehler } 517*a1a3b679SAndreas Boehler 518*a1a3b679SAndreas Boehler return $this->caldavBackend->getChangesForCalendar( 519*a1a3b679SAndreas Boehler $this->calendarInfo['id'], 520*a1a3b679SAndreas Boehler $syncToken, 521*a1a3b679SAndreas Boehler $syncLevel, 522*a1a3b679SAndreas Boehler $limit 523*a1a3b679SAndreas Boehler ); 524*a1a3b679SAndreas Boehler 525*a1a3b679SAndreas Boehler } 526*a1a3b679SAndreas Boehler 527*a1a3b679SAndreas Boehler} 528