1<?php 2 3use \Sabre\VObject; 4use \Sabre\CalDAV; 5use \Sabre\DAV; 6use \Sabre\DAV\Exception\Forbidden; 7/** 8 * PDO CalDAV backend for DokuWiki - based on Sabre's CalDAV backend 9 * 10 * This backend is used to store calendar-data in a PDO database, such as 11 * sqlite or MySQL 12 * 13 * @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/). 14 * @author Evert Pot (http://evertpot.com/) 15 * @license http://sabre.io/license/ Modified BSD License 16 */ 17class DokuWikiSabreCalendarBackend extends \Sabre\CalDAV\Backend\AbstractBackend 18{ 19 20 21 /** 22 * DokuWiki PlugIn Helper 23 */ 24 protected $hlp = null; 25 /** 26 27 /** 28 * List of CalDAV properties, and how they map to database fieldnames 29 * Add your own properties by simply adding on to this array. 30 * 31 * Note that only string-based properties are supported here. 32 * 33 * @var array 34 */ 35 public $propertyMap = array( 36 '{DAV:}displayname' => 'displayname', 37 '{urn:ietf:params:xml:ns:caldav}calendar-description' => 'description', 38 '{urn:ietf:params:xml:ns:caldav}calendar-timezone' => 'timezone', 39 //'{http://apple.com/ns/ical/}calendar-order' => 'calendarorder', 40 //'{http://apple.com/ns/ical/}calendar-color' => 'calendarcolor', 41 ); 42 43 /** 44 * Creates the backend 45 * 46 * @param \PDO $pdo 47 */ 48 function __construct(&$hlp) 49 { 50 51 $this->hlp = $hlp; 52 53 } 54 55 /** 56 * Returns a list of calendars for a principal. 57 * 58 * Every project is an array with the following keys: 59 * * id, a unique id that will be used by other functions to modify the 60 * calendar. This can be the same as the uri or a database key. 61 * * uri. This is just the 'base uri' or 'filename' of the calendar. 62 * * principaluri. The owner of the calendar. Almost always the same as 63 * principalUri passed to this method. 64 * 65 * Furthermore it can contain webdav properties in clark notation. A very 66 * common one is '{DAV:}displayname'. 67 * 68 * Many clients also require: 69 * {urn:ietf:params:xml:ns:caldav}supported-calendar-component-set 70 * For this property, you can just return an instance of 71 * Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet. 72 * 73 * If you return {http://sabredav.org/ns}read-only and set the value to 1, 74 * ACL will automatically be put in read-only mode. 75 * 76 * @param string $principalUri 77 * @return array 78 */ 79 function getCalendarsForUser($principalUri) 80 { 81 \dokuwiki\Logger::debug('DAVCAL', 'getCalendarsForUser called for: '.$principalUri, __FILE__, __LINE__); 82 $fields = array_values($this->propertyMap); 83 $fields[] = 'id'; 84 $fields[] = 'uri'; 85 $fields[] = 'synctoken'; 86 $fields[] = 'components'; 87 $fields[] = 'principaluri'; 88 $fields[] = 'transparent'; 89 90 $idInfo = $this->hlp->getCalendarIdsForUser($principalUri); 91 $calendars = array(); 92 foreach($idInfo as $id => $data) 93 { 94 $row = $this->hlp->getCalendarSettings($id); 95 96 // Skip this calendar if settings couldn't be retrieved 97 if (!$row) { 98 \dokuwiki\Logger::debug('DAVCAL', 'Skipping calendar '.$id.' - settings not found', __FILE__, __LINE__); 99 continue; 100 } 101 102 $components = array(); 103 if ($row['components']) 104 { 105 $components = explode(',', $row['components']); 106 } 107 108 $calendar = array( 109 'id' => $row['id'], 110 'uri' => $row['uri'], 111 'principaluri' => $principalUri,//Overwrite principaluri from database, we actually don't need it. 112 '{' . CalDAV\Plugin::NS_CALENDARSERVER . '}getctag' => 'http://sabre.io/ns/sync/' . ($row['synctoken'] ? $row['synctoken'] : '0'), 113 '{http://sabredav.org/ns}sync-token' => $row['synctoken'] ? $row['synctoken'] : '0', 114 '{' . CalDAV\Plugin::NS_CALDAV . '}supported-calendar-component-set' => new CalDAV\Xml\Property\SupportedCalendarComponentSet($components), 115 //'{' . CalDAV\Plugin::NS_CALDAV . '}schedule-calendar-transp' => new CalDAV\Xml\Property\ScheduleCalendarTransp($row['transparent'] ? 'transparent' : 'opaque'), 116 ); 117 if(isset($idInfo[$id]['readonly']) && $idInfo[$id]['readonly'] === true) 118 $calendar['{http://sabredav.org/ns}read-only'] = '1'; 119 120 121 foreach ($this->propertyMap as $xmlName => $dbName) 122 { 123 $calendar[$xmlName] = $row[$dbName]; 124 } 125 126 $calendars[] = $calendar; 127 128 } 129 \dokuwiki\Logger::debug('DAVCAL', 'Calendars returned: '.count($calendars), __FILE__, __LINE__); 130 return $calendars; 131 132 } 133 134 /** 135 * Creates a new calendar for a principal. 136 * 137 * If the creation was a success, an id must be returned that can be used 138 * to reference this calendar in other methods, such as updateCalendar. 139 * 140 * @param string $principalUri 141 * @param string $calendarUri 142 * @param array $properties 143 * @return string 144 */ 145 function createCalendar($principalUri, $calendarUri, array $properties) 146 { 147 \dokuwiki\Logger::debug('DAVCAL', 'createCalendar called, returning false', __FILE__, __LINE__); 148 return false; 149 } 150 151 /** 152 * Updates properties for a calendar. 153 * 154 * The list of mutations is stored in a Sabre\DAV\PropPatch object. 155 * To do the actual updates, you must tell this object which properties 156 * you're going to process with the handle() method. 157 * 158 * Calling the handle method is like telling the PropPatch object "I 159 * promise I can handle updating this property". 160 * 161 * Read the PropPatch documenation for more info and examples. 162 * 163 * @param string $calendarId 164 * @param \Sabre\DAV\PropPatch $propPatch 165 * @return void 166 */ 167 function updateCalendar($calendarId, \Sabre\DAV\PropPatch $propPatch) 168 { 169 \dokuwiki\Logger::debug('DAVCAL', 'updateCalendar for calendarId '.$calendarId, __FILE__, __LINE__); 170 $supportedProperties = array_keys($this->propertyMap); 171 172 $propPatch->handle($supportedProperties, function($mutations) use ($calendarId) 173 { 174 foreach ($mutations as $propertyName => $propertyValue) 175 { 176 177 switch ($propertyName) 178 { 179 case '{DAV:}displayname' : 180 \dokuwiki\Logger::debug('DAVCAL', 'updateCalendarName', __FILE__, __LINE__); 181 $this->hlp->updateCalendarName($calendarId, $propertyValue); 182 break; 183 case '{urn:ietf:params:xml:ns:caldav}calendar-description': 184 \dokuwiki\Logger::debug('DAVCAL', 'updateCalendarDescription', __FILE__, __LINE__); 185 $this->hlp->updateCalendarDescription($calendarId, $propertyValue); 186 break; 187 case '{urn:ietf:params:xml:ns:caldav}calendar-timezone': 188 \dokuwiki\Logger::debug('DAVCAL', 'updateCalendarTimezone', __FILE__, __LINE__); 189 $this->hlp->updateCalendarTimezone($calendarId, $propertyValue); 190 break; 191 default : 192 break; 193 } 194 195 } 196 return true; 197 198 }); 199 200 } 201 202 /** 203 * Delete a calendar and all it's objects 204 * 205 * @param string $calendarId 206 * @return void 207 */ 208 function deleteCalendar($calendarId) 209 { 210 \dokuwiki\Logger::debug('DAVCAL', 'deleteCalendar called, returning false', __FILE__, __LINE__); 211 return; 212 } 213 214 /** 215 * Returns all calendar objects within a calendar. 216 * 217 * Every item contains an array with the following keys: 218 * * calendardata - The iCalendar-compatible calendar data 219 * * uri - a unique key which will be used to construct the uri. This can 220 * be any arbitrary string, but making sure it ends with '.ics' is a 221 * good idea. This is only the basename, or filename, not the full 222 * path. 223 * * lastmodified - a timestamp of the last modification time 224 * * etag - An arbitrary string, surrounded by double-quotes. (e.g.: 225 * ' "abcdef"') 226 * * size - The size of the calendar objects, in bytes. 227 * * component - optional, a string containing the type of object, such 228 * as 'vevent' or 'vtodo'. If specified, this will be used to populate 229 * the Content-Type header. 230 * 231 * Note that the etag is optional, but it's highly encouraged to return for 232 * speed reasons. 233 * 234 * The calendardata is also optional. If it's not returned 235 * 'getCalendarObject' will be called later, which *is* expected to return 236 * calendardata. 237 * 238 * If neither etag or size are specified, the calendardata will be 239 * used/fetched to determine these numbers. If both are specified the 240 * amount of times this is needed is reduced by a great degree. 241 * 242 * @param string $calendarId 243 * @return array 244 */ 245 function getCalendarObjects($calendarId) 246 { 247 \dokuwiki\Logger::debug('DAVCAL', 'getCalendarObjects for calendarId '.$calendarId, __FILE__, __LINE__); 248 $arr = $this->hlp->getCalendarObjects($calendarId); 249 $result = array(); 250 foreach ($arr as $row) 251 { 252 $result[] = array( 253 'id' => $row['id'], 254 'uri' => $row['uri'], 255 'lastmodified' => $row['lastmodified'], 256 'etag' => '"' . $row['etag'] . '"', 257 'calendarid' => $row['calendarid'], 258 'size' => (int)$row['size'], 259 'component' => strtolower($row['componenttype']), 260 ); 261 } 262 \dokuwiki\Logger::debug('DAVCAL', 'Calendar objects returned: '.count($result), __FILE__, __LINE__); 263 return $result; 264 265 } 266 267 /** 268 * Returns information from a single calendar object, based on it's object 269 * uri. 270 * 271 * The object uri is only the basename, or filename and not a full path. 272 * 273 * The returned array must have the same keys as getCalendarObjects. The 274 * 'calendardata' object is required here though, while it's not required 275 * for getCalendarObjects. 276 * 277 * This method must return null if the object did not exist. 278 * 279 * @param string $calendarId 280 * @param string $objectUri 281 * @return array|null 282 */ 283 function getCalendarObject($calendarId, $objectUri) 284 { 285 \dokuwiki\Logger::debug('DAVCAL', 'getCalendarObject for calendarId '.$calendarId.' and objectUri '.$objectUri, __FILE__, __LINE__); 286 $row = $this->hlp->getCalendarObjectByUri($calendarId, $objectUri); 287 \dokuwiki\Logger::debug('DAVCAL', 'Calendar object row: '.($row ? 'found' : 'not found'), __FILE__, __LINE__); 288 if (!$row) 289 return null; 290 291 return array( 292 'id' => $row['id'], 293 'uri' => $row['uri'], 294 'lastmodified' => $row['lastmodified'], 295 'etag' => '"' . $row['etag'] . '"', 296 'calendarid' => $row['calendarid'], 297 'size' => (int)$row['size'], 298 'calendardata' => $row['calendardata'], 299 'component' => strtolower($row['componenttype']), 300 ); 301 302 } 303 304 /** 305 * Returns a list of calendar objects. 306 * 307 * This method should work identical to getCalendarObject, but instead 308 * return all the calendar objects in the list as an array. 309 * 310 * If the backend supports this, it may allow for some speed-ups. 311 * 312 * @param mixed $calendarId 313 * @param array $uris 314 * @return array 315 */ 316 function getMultipleCalendarObjects($calendarId, array $uris) 317 { 318 \dokuwiki\Logger::debug('DAVCAL', 'getMultipleCalendarObjects for calendarId '.$calendarId, __FILE__, __LINE__); 319 \dokuwiki\Logger::debug('DAVCAL', 'URIs requested: '.count($uris), __FILE__, __LINE__); 320 $arr = $this->hlp->getMultipleCalendarObjectsByUri($calendarId, $uris); 321 322 $result = array(); 323 foreach($arr as $row) 324 { 325 326 $result[] = array( 327 'id' => $row['id'], 328 'uri' => $row['uri'], 329 'lastmodified' => $row['lastmodified'], 330 'etag' => '"' . $row['etag'] . '"', 331 'calendarid' => $row['calendarid'], 332 'size' => (int)$row['size'], 333 'calendardata' => $row['calendardata'], 334 'component' => strtolower($row['componenttype']), 335 ); 336 337 } 338 \dokuwiki\Logger::debug('DAVCAL', 'Multiple calendar objects returned: '.count($result), __FILE__, __LINE__); 339 return $result; 340 341 } 342 343 344 /** 345 * Creates a new calendar object. 346 * 347 * The object uri is only the basename, or filename and not a full path. 348 * 349 * It is possible return an etag from this function, which will be used in 350 * the response to this PUT request. Note that the ETag must be surrounded 351 * by double-quotes. 352 * 353 * However, you should only really return this ETag if you don't mangle the 354 * calendar-data. If the result of a subsequent GET to this object is not 355 * the exact same as this request body, you should omit the ETag. 356 * 357 * @param mixed $calendarId 358 * @param string $objectUri 359 * @param string $calendarData 360 * @return string|null 361 */ 362 function createCalendarObject($calendarId, $objectUri, $calendarData) 363 { 364 \dokuwiki\Logger::debug('DAVCAL', 'createCalendarObject for calendarId '.$calendarId.' and objectUri '.$objectUri, __FILE__, __LINE__); 365 \dokuwiki\Logger::debug('DAVCAL', 'Calendar data length: '.strlen($calendarData), __FILE__, __LINE__); 366 $etag = $this->hlp->addCalendarEntryToCalendarByICS($calendarId, $objectUri, $calendarData); 367 \dokuwiki\Logger::debug('DAVCAL', 'ETag generated: '.$etag, __FILE__, __LINE__); 368 369 return '"' . $etag . '"'; 370 } 371 372 /** 373 * Updates an existing calendarobject, based on it's uri. 374 * 375 * The object uri is only the basename, or filename and not a full path. 376 * 377 * It is possible return an etag from this function, which will be used in 378 * the response to this PUT request. Note that the ETag must be surrounded 379 * by double-quotes. 380 * 381 * However, you should only really return this ETag if you don't mangle the 382 * calendar-data. If the result of a subsequent GET to this object is not 383 * the exact same as this request body, you should omit the ETag. 384 * 385 * @param mixed $calendarId 386 * @param string $objectUri 387 * @param string $calendarData 388 * @return string|null 389 */ 390 function updateCalendarObject($calendarId, $objectUri, $calendarData) 391 { 392 \dokuwiki\Logger::debug('DAVCAL', 'updateCalendarObject for calendarId '.$calendarId.' and objectUri '.$objectUri, __FILE__, __LINE__); 393 \dokuwiki\Logger::debug('DAVCAL', 'Calendar data length: '.strlen($calendarData), __FILE__, __LINE__); 394 $etag = $this->hlp->editCalendarEntryToCalendarByICS($calendarId, $objectUri, $calendarData); 395 \dokuwiki\Logger::debug('DAVCAL', 'ETag generated: '.$etag, __FILE__, __LINE__); 396 return '"' . $etag. '"'; 397 398 } 399 400 401 402 /** 403 * Deletes an existing calendar object. 404 * 405 * The object uri is only the basename, or filename and not a full path. 406 * 407 * @param string $calendarId 408 * @param string $objectUri 409 * @return void 410 */ 411 function deleteCalendarObject($calendarId, $objectUri) 412 { 413 \dokuwiki\Logger::debug('DAVCAL', 'deleteCalendarObject for calendarId '.$calendarId.' and objectUri '.$objectUri, __FILE__, __LINE__); 414 $this->hlp->deleteCalendarEntryForCalendarByUri($calendarId, $objectUri); 415 416 } 417 418 /** 419 * Performs a calendar-query on the contents of this calendar. 420 * 421 * The calendar-query is defined in RFC4791 : CalDAV. Using the 422 * calendar-query it is possible for a client to request a specific set of 423 * object, based on contents of iCalendar properties, date-ranges and 424 * iCalendar component types (VTODO, VEVENT). 425 * 426 * This method should just return a list of (relative) urls that match this 427 * query. 428 * 429 * The list of filters are specified as an array. The exact array is 430 * documented by \Sabre\CalDAV\CalendarQueryParser. 431 * 432 * Note that it is extremely likely that getCalendarObject for every path 433 * returned from this method will be called almost immediately after. You 434 * may want to anticipate this to speed up these requests. 435 * 436 * This method provides a default implementation, which parses *all* the 437 * iCalendar objects in the specified calendar. 438 * 439 * This default may well be good enough for personal use, and calendars 440 * that aren't very large. But if you anticipate high usage, big calendars 441 * or high loads, you are strongly adviced to optimize certain paths. 442 * 443 * The best way to do so is override this method and to optimize 444 * specifically for 'common filters'. 445 * 446 * Requests that are extremely common are: 447 * * requests for just VEVENTS 448 * * requests for just VTODO 449 * * requests with a time-range-filter on a VEVENT. 450 * 451 * ..and combinations of these requests. It may not be worth it to try to 452 * handle every possible situation and just rely on the (relatively 453 * easy to use) CalendarQueryValidator to handle the rest. 454 * 455 * Note that especially time-range-filters may be difficult to parse. A 456 * time-range filter specified on a VEVENT must for instance also handle 457 * recurrence rules correctly. 458 * A good example of how to interprete all these filters can also simply 459 * be found in \Sabre\CalDAV\CalendarQueryFilter. This class is as correct 460 * as possible, so it gives you a good idea on what type of stuff you need 461 * to think of. 462 * 463 * This specific implementation (for the PDO) backend optimizes filters on 464 * specific components, and VEVENT time-ranges. 465 * 466 * @param string $calendarId 467 * @param array $filters 468 * @return array 469 */ 470 function calendarQuery($calendarId, array $filters) 471 { 472 \dokuwiki\Logger::debug('DAVCAL', 'calendarQuery for calendarId '.$calendarId, __FILE__, __LINE__); 473 \dokuwiki\Logger::debug('DAVCAL', 'Filters count: '.count($filters), __FILE__, __LINE__); 474 $result = $this->hlp->calendarQuery($calendarId, $filters); 475 \dokuwiki\Logger::debug('DAVCAL', 'Query results: '.count($result), __FILE__, __LINE__); 476 return $result; 477 } 478 479 /** 480 * Searches through all of a users calendars and calendar objects to find 481 * an object with a specific UID. 482 * 483 * This method should return the path to this object, relative to the 484 * calendar home, so this path usually only contains two parts: 485 * 486 * calendarpath/objectpath.ics 487 * 488 * If the uid is not found, return null. 489 * 490 * This method should only consider * objects that the principal owns, so 491 * any calendars owned by other principals that also appear in this 492 * collection should be ignored. 493 * 494 * @param string $principalUri 495 * @param string $uid 496 * @return string|null 497 */ 498 function getCalendarObjectByUID($principalUri, $uid) 499 { 500 \dokuwiki\Logger::debug('DAVCAL', 'getCalendarObjectByUID for principalUri '.$principalUri.' and uid '.$uid, __FILE__, __LINE__); 501 $calids = array_keys($this->hlp->getCalendarIsForUser($principalUri)); 502 $event = $this->hlp->getEventWithUid($uid); 503 504 if(in_array($event['calendarid'], $calids)) 505 { 506 $settings = $this->hlp->getCalendarSettings($event['calendarid']); 507 return $settings['uri'] . '/' . $event['uri']; 508 } 509 return null; 510 } 511 512 /** 513 * The getChanges method returns all the changes that have happened, since 514 * the specified syncToken in the specified calendar. 515 * 516 * This function should return an array, such as the following: 517 * 518 * [ 519 * 'syncToken' => 'The current synctoken', 520 * 'added' => [ 521 * 'new.txt', 522 * ], 523 * 'modified' => [ 524 * 'modified.txt', 525 * ], 526 * 'deleted' => [ 527 * 'foo.php.bak', 528 * 'old.txt' 529 * ] 530 * ]; 531 * 532 * The returned syncToken property should reflect the *current* syncToken 533 * of the calendar, as reported in the {http://sabredav.org/ns}sync-token 534 * property this is needed here too, to ensure the operation is atomic. 535 * 536 * If the $syncToken argument is specified as null, this is an initial 537 * sync, and all members should be reported. 538 * 539 * The modified property is an array of nodenames that have changed since 540 * the last token. 541 * 542 * The deleted property is an array with nodenames, that have been deleted 543 * from collection. 544 * 545 * The $syncLevel argument is basically the 'depth' of the report. If it's 546 * 1, you only have to report changes that happened only directly in 547 * immediate descendants. If it's 2, it should also include changes from 548 * the nodes below the child collections. (grandchildren) 549 * 550 * The $limit argument allows a client to specify how many results should 551 * be returned at most. If the limit is not specified, it should be treated 552 * as infinite. 553 * 554 * If the limit (infinite or not) is higher than you're willing to return, 555 * you should throw a Sabre\DAV\Exception\TooMuchMatches() exception. 556 * 557 * If the syncToken is expired (due to data cleanup) or unknown, you must 558 * return null. 559 * 560 * The limit is 'suggestive'. You are free to ignore it. 561 * 562 * @param string $calendarId 563 * @param string $syncToken 564 * @param int $syncLevel 565 * @param int $limit 566 * @return array 567 */ 568 function getChangesForCalendar($calendarId, $syncToken, $syncLevel, $limit = null) 569 { 570 \dokuwiki\Logger::debug('DAVCAL', 'getChangesForCalendar for calendarId '.$calendarId.' and syncToken '.$syncToken.' and syncLevel '.$syncLevel, __FILE__, __LINE__); 571 $result = $this->hlp->getChangesForCalendar($calendarId, $syncToken, $syncLevel, $limit); 572 \dokuwiki\Logger::debug('DAVCAL', 'Changes result: '.($result ? 'found' : 'not found'), __FILE__, __LINE__); 573 return $result; 574 } 575 576 /** 577 * Returns a list of subscriptions for a principal. 578 * 579 * Every subscription is an array with the following keys: 580 * * id, a unique id that will be used by other functions to modify the 581 * subscription. This can be the same as the uri or a database key. 582 * * uri. This is just the 'base uri' or 'filename' of the subscription. 583 * * principaluri. The owner of the subscription. Almost always the same as 584 * principalUri passed to this method. 585 * * source. Url to the actual feed 586 * 587 * Furthermore, all the subscription info must be returned too: 588 * 589 * 1. {DAV:}displayname 590 * 2. {http://apple.com/ns/ical/}refreshrate 591 * 3. {http://calendarserver.org/ns/}subscribed-strip-todos (omit if todos 592 * should not be stripped). 593 * 4. {http://calendarserver.org/ns/}subscribed-strip-alarms (omit if alarms 594 * should not be stripped). 595 * 5. {http://calendarserver.org/ns/}subscribed-strip-attachments (omit if 596 * attachments should not be stripped). 597 * 7. {http://apple.com/ns/ical/}calendar-color 598 * 8. {http://apple.com/ns/ical/}calendar-order 599 * 9. {urn:ietf:params:xml:ns:caldav}supported-calendar-component-set 600 * (should just be an instance of 601 * Sabre\CalDAV\Property\SupportedCalendarComponentSet, with a bunch of 602 * default components). 603 * 604 * @param string $principalUri 605 * @return array 606 */ 607 function getSubscriptionsForUser($principalUri) 608 { 609 \dokuwiki\Logger::debug('DAVCAL', 'getSubscriptionsForUser with principalUri '.$principalUri.', returning empty array()', __FILE__, __LINE__); 610 return array(); 611 612 } 613 614 /** 615 * Creates a new subscription for a principal. 616 * 617 * If the creation was a success, an id must be returned that can be used to reference 618 * this subscription in other methods, such as updateSubscription. 619 * 620 * @param string $principalUri 621 * @param string $uri 622 * @param array $properties 623 * @return mixed 624 */ 625 function createSubscription($principalUri, $uri, array $properties) 626 { 627 \dokuwiki\Logger::debug('DAVCAL', 'createSubscription for principalUri '.$principalUri.' and uri '.$uri.', returning null', __FILE__, __LINE__); 628 return null; 629 630 } 631 632 /** 633 * Updates a subscription 634 * 635 * The list of mutations is stored in a Sabre\DAV\PropPatch object. 636 * To do the actual updates, you must tell this object which properties 637 * you're going to process with the handle() method. 638 * 639 * Calling the handle method is like telling the PropPatch object "I 640 * promise I can handle updating this property". 641 * 642 * Read the PropPatch documenation for more info and examples. 643 * 644 * @param mixed $subscriptionId 645 * @param \Sabre\DAV\PropPatch $propPatch 646 * @return void 647 */ 648 function updateSubscription($subscriptionId, DAV\PropPatch $propPatch) 649 { 650 \dokuwiki\Logger::debug('DAVCAL', 'updateSubscription with subscriptionId '.$subscriptionId.', returning false', __FILE__, __LINE__); 651 return; 652 } 653 654 /** 655 * Deletes a subscription 656 * 657 * @param mixed $subscriptionId 658 * @return void 659 */ 660 function deleteSubscription($subscriptionId) 661 { 662 \dokuwiki\Logger::debug('DAVCAL', 'deleteSubscription with subscriptionId '.$subscriptionId.', returning', __FILE__, __LINE__); 663 return; 664 665 } 666 667 /** 668 * Returns a single scheduling object. 669 * 670 * The returned array should contain the following elements: 671 * * uri - A unique basename for the object. This will be used to 672 * construct a full uri. 673 * * calendardata - The iCalendar object 674 * * lastmodified - The last modification date. Can be an int for a unix 675 * timestamp, or a PHP DateTime object. 676 * * etag - A unique token that must change if the object changed. 677 * * size - The size of the object, in bytes. 678 * 679 * @param string $principalUri 680 * @param string $objectUri 681 * @return array 682 */ 683 function getSchedulingObject($principalUri, $objectUri) 684 { 685 \dokuwiki\Logger::debug('DAVCAL', 'getSchedulingObject with principalUri '.$principalUri.' and objectUri '.$objectUri.', returning null', __FILE__, __LINE__); 686 return null; 687 688 } 689 690 /** 691 * Returns all scheduling objects for the inbox collection. 692 * 693 * These objects should be returned as an array. Every item in the array 694 * should follow the same structure as returned from getSchedulingObject. 695 * 696 * The main difference is that 'calendardata' is optional. 697 * 698 * @param string $principalUri 699 * @return array 700 */ 701 function getSchedulingObjects($principalUri) 702 { 703 \dokuwiki\Logger::debug('DAVCAL', 'getSchedulingObjects for principalUri '.$principalUri.', returning null', __FILE__, __LINE__); 704 return null; 705 706 } 707 708 /** 709 * Deletes a scheduling object 710 * 711 * @param string $principalUri 712 * @param string $objectUri 713 * @return void 714 */ 715 function deleteSchedulingObject($principalUri, $objectUri) 716 { 717 \dokuwiki\Logger::debug('DAVCAL', 'deleteSchedulingObject for principalUri '.$principalUri.' and objectUri '.$objectUri.', returning', __FILE__, __LINE__); 718 return; 719 } 720 721 /** 722 * Creates a new scheduling object. This should land in a users' inbox. 723 * 724 * @param string $principalUri 725 * @param string $objectUri 726 * @param string $objectData 727 * @return void 728 */ 729 function createSchedulingObject($principalUri, $objectUri, $objectData) 730 { 731 \dokuwiki\Logger::debug('DAVCAL', 'createSchedulingObject with principalUri '.$principalUri.' and objectUri '.$objectUri.', returning', __FILE__, __LINE__); 732 return; 733 734 } 735 736} 737