ExternalCalendar.php 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-License-Identifier: AGPL-3.0-or-later
  5. */
  6. namespace OCA\DAV\CalDAV\Integration;
  7. use Sabre\CalDAV;
  8. use Sabre\DAV;
  9. /**
  10. * Class ExternalCalendar
  11. *
  12. * @package OCA\DAV\CalDAV\Integration
  13. * @since 19.0.0
  14. */
  15. abstract class ExternalCalendar implements CalDAV\ICalendar, DAV\IProperties {
  16. /** @var string */
  17. private const PREFIX = 'app-generated';
  18. /**
  19. * @var string
  20. *
  21. * Double dash is a valid delimiter,
  22. * because it will always split the calendarURIs correctly:
  23. * - our prefix contains only one dash and won't be split
  24. * - appIds are not allowed to contain dashes as per spec:
  25. * > must contain only lowercase ASCII characters and underscore
  26. * - explode has a limit of three, so even if the app-generated
  27. * calendar uri has double dashes, it won't be split
  28. */
  29. private const DELIMITER = '--';
  30. /** @var string */
  31. private $appId;
  32. /** @var string */
  33. private $calendarUri;
  34. /**
  35. * ExternalCalendar constructor.
  36. *
  37. * @param string $appId
  38. * @param string $calendarUri
  39. */
  40. public function __construct(string $appId, string $calendarUri) {
  41. $this->appId = $appId;
  42. $this->calendarUri = $calendarUri;
  43. }
  44. /**
  45. * @inheritDoc
  46. */
  47. final public function getName() {
  48. return implode(self::DELIMITER, [
  49. self::PREFIX,
  50. $this->appId,
  51. $this->calendarUri,
  52. ]);
  53. }
  54. /**
  55. * @inheritDoc
  56. */
  57. final public function setName($name) {
  58. throw new DAV\Exception\MethodNotAllowed('Renaming calendars is not yet supported');
  59. }
  60. /**
  61. * @inheritDoc
  62. */
  63. final public function createDirectory($name) {
  64. throw new DAV\Exception\MethodNotAllowed('Creating collections in calendar objects is not allowed');
  65. }
  66. /**
  67. * Checks whether the calendar uri is app-generated
  68. *
  69. * @param string $calendarUri
  70. * @return bool
  71. */
  72. public static function isAppGeneratedCalendar(string $calendarUri):bool {
  73. return str_starts_with($calendarUri, self::PREFIX) && substr_count($calendarUri, self::DELIMITER) >= 2;
  74. }
  75. /**
  76. * Splits an app-generated calendar-uri into appId and calendarUri
  77. *
  78. * @param string $calendarUri
  79. * @return array
  80. */
  81. public static function splitAppGeneratedCalendarUri(string $calendarUri):array {
  82. $array = array_slice(explode(self::DELIMITER, $calendarUri, 3), 1);
  83. // Check the array has expected amount of elements
  84. // and none of them is an empty string
  85. if (\count($array) !== 2 || \in_array('', $array, true)) {
  86. throw new \InvalidArgumentException('Provided calendar uri was not app-generated');
  87. }
  88. return $array;
  89. }
  90. /**
  91. * Checks whether a calendar-name, the user wants to create, violates
  92. * the reserved name for calendar uris
  93. *
  94. * @param string $calendarUri
  95. * @return bool
  96. */
  97. public static function doesViolateReservedName(string $calendarUri):bool {
  98. return str_starts_with($calendarUri, self::PREFIX);
  99. }
  100. }