1*a1a3b679SAndreas Boehler<?php 2*a1a3b679SAndreas Boehler 3*a1a3b679SAndreas Boehlernamespace Sabre\CalDAV; 4*a1a3b679SAndreas Boehler 5*a1a3b679SAndreas Boehler/** 6*a1a3b679SAndreas Boehler * The CalendarObject represents a single VEVENT or VTODO within a Calendar. 7*a1a3b679SAndreas Boehler * 8*a1a3b679SAndreas Boehler * @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/). 9*a1a3b679SAndreas Boehler * @author Evert Pot (http://evertpot.com/) 10*a1a3b679SAndreas Boehler * @license http://sabre.io/license/ Modified BSD License 11*a1a3b679SAndreas Boehler */ 12*a1a3b679SAndreas Boehlerclass CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\DAVACL\IACL { 13*a1a3b679SAndreas Boehler 14*a1a3b679SAndreas Boehler /** 15*a1a3b679SAndreas Boehler * Sabre\CalDAV\Backend\BackendInterface 16*a1a3b679SAndreas Boehler * 17*a1a3b679SAndreas Boehler * @var Sabre\CalDAV\Backend\AbstractBackend 18*a1a3b679SAndreas Boehler */ 19*a1a3b679SAndreas Boehler protected $caldavBackend; 20*a1a3b679SAndreas Boehler 21*a1a3b679SAndreas Boehler /** 22*a1a3b679SAndreas Boehler * Array with information about this CalendarObject 23*a1a3b679SAndreas Boehler * 24*a1a3b679SAndreas Boehler * @var array 25*a1a3b679SAndreas Boehler */ 26*a1a3b679SAndreas Boehler protected $objectData; 27*a1a3b679SAndreas Boehler 28*a1a3b679SAndreas Boehler /** 29*a1a3b679SAndreas Boehler * Array with information about the containing calendar 30*a1a3b679SAndreas Boehler * 31*a1a3b679SAndreas Boehler * @var array 32*a1a3b679SAndreas Boehler */ 33*a1a3b679SAndreas Boehler protected $calendarInfo; 34*a1a3b679SAndreas Boehler 35*a1a3b679SAndreas Boehler /** 36*a1a3b679SAndreas Boehler * Constructor 37*a1a3b679SAndreas Boehler * 38*a1a3b679SAndreas Boehler * The following properties may be passed within $objectData: 39*a1a3b679SAndreas Boehler * 40*a1a3b679SAndreas Boehler * * calendarid - This must refer to a calendarid from a caldavBackend 41*a1a3b679SAndreas Boehler * * uri - A unique uri. Only the 'basename' must be passed. 42*a1a3b679SAndreas Boehler * * calendardata (optional) - The iCalendar data 43*a1a3b679SAndreas Boehler * * etag - (optional) The etag for this object, MUST be encloded with 44*a1a3b679SAndreas Boehler * double-quotes. 45*a1a3b679SAndreas Boehler * * size - (optional) The size of the data in bytes. 46*a1a3b679SAndreas Boehler * * lastmodified - (optional) format as a unix timestamp. 47*a1a3b679SAndreas Boehler * * acl - (optional) Use this to override the default ACL for the node. 48*a1a3b679SAndreas Boehler * 49*a1a3b679SAndreas Boehler * @param Backend\BackendInterface $caldavBackend 50*a1a3b679SAndreas Boehler * @param array $calendarInfo 51*a1a3b679SAndreas Boehler * @param array $objectData 52*a1a3b679SAndreas Boehler */ 53*a1a3b679SAndreas Boehler function __construct(Backend\BackendInterface $caldavBackend, array $calendarInfo, array $objectData) { 54*a1a3b679SAndreas Boehler 55*a1a3b679SAndreas Boehler $this->caldavBackend = $caldavBackend; 56*a1a3b679SAndreas Boehler 57*a1a3b679SAndreas Boehler if (!isset($objectData['uri'])) { 58*a1a3b679SAndreas Boehler throw new \InvalidArgumentException('The objectData argument must contain an \'uri\' property'); 59*a1a3b679SAndreas Boehler } 60*a1a3b679SAndreas Boehler 61*a1a3b679SAndreas Boehler $this->calendarInfo = $calendarInfo; 62*a1a3b679SAndreas Boehler $this->objectData = $objectData; 63*a1a3b679SAndreas Boehler 64*a1a3b679SAndreas Boehler } 65*a1a3b679SAndreas Boehler 66*a1a3b679SAndreas Boehler /** 67*a1a3b679SAndreas Boehler * Returns the uri for this object 68*a1a3b679SAndreas Boehler * 69*a1a3b679SAndreas Boehler * @return string 70*a1a3b679SAndreas Boehler */ 71*a1a3b679SAndreas Boehler function getName() { 72*a1a3b679SAndreas Boehler 73*a1a3b679SAndreas Boehler return $this->objectData['uri']; 74*a1a3b679SAndreas Boehler 75*a1a3b679SAndreas Boehler } 76*a1a3b679SAndreas Boehler 77*a1a3b679SAndreas Boehler /** 78*a1a3b679SAndreas Boehler * Returns the ICalendar-formatted object 79*a1a3b679SAndreas Boehler * 80*a1a3b679SAndreas Boehler * @return string 81*a1a3b679SAndreas Boehler */ 82*a1a3b679SAndreas Boehler function get() { 83*a1a3b679SAndreas Boehler 84*a1a3b679SAndreas Boehler // Pre-populating the 'calendardata' is optional, if we don't have it 85*a1a3b679SAndreas Boehler // already we fetch it from the backend. 86*a1a3b679SAndreas Boehler if (!isset($this->objectData['calendardata'])) { 87*a1a3b679SAndreas Boehler $this->objectData = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'], $this->objectData['uri']); 88*a1a3b679SAndreas Boehler } 89*a1a3b679SAndreas Boehler return $this->objectData['calendardata']; 90*a1a3b679SAndreas Boehler 91*a1a3b679SAndreas Boehler } 92*a1a3b679SAndreas Boehler 93*a1a3b679SAndreas Boehler /** 94*a1a3b679SAndreas Boehler * Updates the ICalendar-formatted object 95*a1a3b679SAndreas Boehler * 96*a1a3b679SAndreas Boehler * @param string|resource $calendarData 97*a1a3b679SAndreas Boehler * @return string 98*a1a3b679SAndreas Boehler */ 99*a1a3b679SAndreas Boehler function put($calendarData) { 100*a1a3b679SAndreas Boehler 101*a1a3b679SAndreas Boehler if (is_resource($calendarData)) { 102*a1a3b679SAndreas Boehler $calendarData = stream_get_contents($calendarData); 103*a1a3b679SAndreas Boehler } 104*a1a3b679SAndreas Boehler $etag = $this->caldavBackend->updateCalendarObject($this->calendarInfo['id'], $this->objectData['uri'], $calendarData); 105*a1a3b679SAndreas Boehler $this->objectData['calendardata'] = $calendarData; 106*a1a3b679SAndreas Boehler $this->objectData['etag'] = $etag; 107*a1a3b679SAndreas Boehler 108*a1a3b679SAndreas Boehler return $etag; 109*a1a3b679SAndreas Boehler 110*a1a3b679SAndreas Boehler } 111*a1a3b679SAndreas Boehler 112*a1a3b679SAndreas Boehler /** 113*a1a3b679SAndreas Boehler * Deletes the calendar object 114*a1a3b679SAndreas Boehler * 115*a1a3b679SAndreas Boehler * @return void 116*a1a3b679SAndreas Boehler */ 117*a1a3b679SAndreas Boehler function delete() { 118*a1a3b679SAndreas Boehler 119*a1a3b679SAndreas Boehler $this->caldavBackend->deleteCalendarObject($this->calendarInfo['id'], $this->objectData['uri']); 120*a1a3b679SAndreas Boehler 121*a1a3b679SAndreas Boehler } 122*a1a3b679SAndreas Boehler 123*a1a3b679SAndreas Boehler /** 124*a1a3b679SAndreas Boehler * Returns the mime content-type 125*a1a3b679SAndreas Boehler * 126*a1a3b679SAndreas Boehler * @return string 127*a1a3b679SAndreas Boehler */ 128*a1a3b679SAndreas Boehler function getContentType() { 129*a1a3b679SAndreas Boehler 130*a1a3b679SAndreas Boehler $mime = 'text/calendar; charset=utf-8'; 131*a1a3b679SAndreas Boehler if (isset($this->objectData['component']) && $this->objectData['component']) { 132*a1a3b679SAndreas Boehler $mime .= '; component=' . $this->objectData['component']; 133*a1a3b679SAndreas Boehler } 134*a1a3b679SAndreas Boehler return $mime; 135*a1a3b679SAndreas Boehler 136*a1a3b679SAndreas Boehler } 137*a1a3b679SAndreas Boehler 138*a1a3b679SAndreas Boehler /** 139*a1a3b679SAndreas Boehler * Returns an ETag for this object. 140*a1a3b679SAndreas Boehler * 141*a1a3b679SAndreas Boehler * The ETag is an arbitrary string, but MUST be surrounded by double-quotes. 142*a1a3b679SAndreas Boehler * 143*a1a3b679SAndreas Boehler * @return string 144*a1a3b679SAndreas Boehler */ 145*a1a3b679SAndreas Boehler function getETag() { 146*a1a3b679SAndreas Boehler 147*a1a3b679SAndreas Boehler if (isset($this->objectData['etag'])) { 148*a1a3b679SAndreas Boehler return $this->objectData['etag']; 149*a1a3b679SAndreas Boehler } else { 150*a1a3b679SAndreas Boehler return '"' . md5($this->get()) . '"'; 151*a1a3b679SAndreas Boehler } 152*a1a3b679SAndreas Boehler 153*a1a3b679SAndreas Boehler } 154*a1a3b679SAndreas Boehler 155*a1a3b679SAndreas Boehler /** 156*a1a3b679SAndreas Boehler * Returns the last modification date as a unix timestamp 157*a1a3b679SAndreas Boehler * 158*a1a3b679SAndreas Boehler * @return int 159*a1a3b679SAndreas Boehler */ 160*a1a3b679SAndreas Boehler function getLastModified() { 161*a1a3b679SAndreas Boehler 162*a1a3b679SAndreas Boehler return $this->objectData['lastmodified']; 163*a1a3b679SAndreas Boehler 164*a1a3b679SAndreas Boehler } 165*a1a3b679SAndreas Boehler 166*a1a3b679SAndreas Boehler /** 167*a1a3b679SAndreas Boehler * Returns the size of this object in bytes 168*a1a3b679SAndreas Boehler * 169*a1a3b679SAndreas Boehler * @return int 170*a1a3b679SAndreas Boehler */ 171*a1a3b679SAndreas Boehler function getSize() { 172*a1a3b679SAndreas Boehler 173*a1a3b679SAndreas Boehler if (array_key_exists('size', $this->objectData)) { 174*a1a3b679SAndreas Boehler return $this->objectData['size']; 175*a1a3b679SAndreas Boehler } else { 176*a1a3b679SAndreas Boehler return strlen($this->get()); 177*a1a3b679SAndreas Boehler } 178*a1a3b679SAndreas Boehler 179*a1a3b679SAndreas Boehler } 180*a1a3b679SAndreas Boehler 181*a1a3b679SAndreas Boehler /** 182*a1a3b679SAndreas Boehler * Returns the owner principal 183*a1a3b679SAndreas Boehler * 184*a1a3b679SAndreas Boehler * This must be a url to a principal, or null if there's no owner 185*a1a3b679SAndreas Boehler * 186*a1a3b679SAndreas Boehler * @return string|null 187*a1a3b679SAndreas Boehler */ 188*a1a3b679SAndreas Boehler function getOwner() { 189*a1a3b679SAndreas Boehler 190*a1a3b679SAndreas Boehler return $this->calendarInfo['principaluri']; 191*a1a3b679SAndreas Boehler 192*a1a3b679SAndreas Boehler } 193*a1a3b679SAndreas Boehler 194*a1a3b679SAndreas Boehler /** 195*a1a3b679SAndreas Boehler * Returns a group principal 196*a1a3b679SAndreas Boehler * 197*a1a3b679SAndreas Boehler * This must be a url to a principal, or null if there's no owner 198*a1a3b679SAndreas Boehler * 199*a1a3b679SAndreas Boehler * @return string|null 200*a1a3b679SAndreas Boehler */ 201*a1a3b679SAndreas Boehler function getGroup() { 202*a1a3b679SAndreas Boehler 203*a1a3b679SAndreas Boehler return null; 204*a1a3b679SAndreas Boehler 205*a1a3b679SAndreas Boehler } 206*a1a3b679SAndreas Boehler 207*a1a3b679SAndreas Boehler /** 208*a1a3b679SAndreas Boehler * Returns a list of ACE's for this node. 209*a1a3b679SAndreas Boehler * 210*a1a3b679SAndreas Boehler * Each ACE has the following properties: 211*a1a3b679SAndreas Boehler * * 'privilege', a string such as {DAV:}read or {DAV:}write. These are 212*a1a3b679SAndreas Boehler * currently the only supported privileges 213*a1a3b679SAndreas Boehler * * 'principal', a url to the principal who owns the node 214*a1a3b679SAndreas Boehler * * 'protected' (optional), indicating that this ACE is not allowed to 215*a1a3b679SAndreas Boehler * be updated. 216*a1a3b679SAndreas Boehler * 217*a1a3b679SAndreas Boehler * @return array 218*a1a3b679SAndreas Boehler */ 219*a1a3b679SAndreas Boehler function getACL() { 220*a1a3b679SAndreas Boehler 221*a1a3b679SAndreas Boehler // An alternative acl may be specified in the object data. 222*a1a3b679SAndreas Boehler if (isset($this->objectData['acl'])) { 223*a1a3b679SAndreas Boehler return $this->objectData['acl']; 224*a1a3b679SAndreas Boehler } 225*a1a3b679SAndreas Boehler 226*a1a3b679SAndreas Boehler // The default ACL 227*a1a3b679SAndreas Boehler return [ 228*a1a3b679SAndreas Boehler [ 229*a1a3b679SAndreas Boehler 'privilege' => '{DAV:}read', 230*a1a3b679SAndreas Boehler 'principal' => $this->calendarInfo['principaluri'], 231*a1a3b679SAndreas Boehler 'protected' => true, 232*a1a3b679SAndreas Boehler ], 233*a1a3b679SAndreas Boehler [ 234*a1a3b679SAndreas Boehler 'privilege' => '{DAV:}write', 235*a1a3b679SAndreas Boehler 'principal' => $this->calendarInfo['principaluri'], 236*a1a3b679SAndreas Boehler 'protected' => true, 237*a1a3b679SAndreas Boehler ], 238*a1a3b679SAndreas Boehler [ 239*a1a3b679SAndreas Boehler 'privilege' => '{DAV:}read', 240*a1a3b679SAndreas Boehler 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write', 241*a1a3b679SAndreas Boehler 'protected' => true, 242*a1a3b679SAndreas Boehler ], 243*a1a3b679SAndreas Boehler [ 244*a1a3b679SAndreas Boehler 'privilege' => '{DAV:}write', 245*a1a3b679SAndreas Boehler 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write', 246*a1a3b679SAndreas Boehler 'protected' => true, 247*a1a3b679SAndreas Boehler ], 248*a1a3b679SAndreas Boehler [ 249*a1a3b679SAndreas Boehler 'privilege' => '{DAV:}read', 250*a1a3b679SAndreas Boehler 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-read', 251*a1a3b679SAndreas Boehler 'protected' => true, 252*a1a3b679SAndreas Boehler ], 253*a1a3b679SAndreas Boehler 254*a1a3b679SAndreas Boehler ]; 255*a1a3b679SAndreas Boehler 256*a1a3b679SAndreas Boehler } 257*a1a3b679SAndreas Boehler 258*a1a3b679SAndreas Boehler /** 259*a1a3b679SAndreas Boehler * Updates the ACL 260*a1a3b679SAndreas Boehler * 261*a1a3b679SAndreas Boehler * This method will receive a list of new ACE's. 262*a1a3b679SAndreas Boehler * 263*a1a3b679SAndreas Boehler * @param array $acl 264*a1a3b679SAndreas Boehler * @return void 265*a1a3b679SAndreas Boehler */ 266*a1a3b679SAndreas Boehler function setACL(array $acl) { 267*a1a3b679SAndreas Boehler 268*a1a3b679SAndreas Boehler throw new \Sabre\DAV\Exception\MethodNotAllowed('Changing ACL is not yet supported'); 269*a1a3b679SAndreas Boehler 270*a1a3b679SAndreas Boehler } 271*a1a3b679SAndreas Boehler 272*a1a3b679SAndreas Boehler /** 273*a1a3b679SAndreas Boehler * Returns the list of supported privileges for this node. 274*a1a3b679SAndreas Boehler * 275*a1a3b679SAndreas Boehler * The returned data structure is a list of nested privileges. 276*a1a3b679SAndreas Boehler * See \Sabre\DAVACL\Plugin::getDefaultSupportedPrivilegeSet for a simple 277*a1a3b679SAndreas Boehler * standard structure. 278*a1a3b679SAndreas Boehler * 279*a1a3b679SAndreas Boehler * If null is returned from this method, the default privilege set is used, 280*a1a3b679SAndreas Boehler * which is fine for most common usecases. 281*a1a3b679SAndreas Boehler * 282*a1a3b679SAndreas Boehler * @return array|null 283*a1a3b679SAndreas Boehler */ 284*a1a3b679SAndreas Boehler function getSupportedPrivilegeSet() { 285*a1a3b679SAndreas Boehler 286*a1a3b679SAndreas Boehler return null; 287*a1a3b679SAndreas Boehler 288*a1a3b679SAndreas Boehler } 289*a1a3b679SAndreas Boehler 290*a1a3b679SAndreas Boehler} 291