ExternalCalendar.php 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  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. /**
  31. * ExternalCalendar constructor.
  32. *
  33. * @param string $appId
  34. * @param string $calendarUri
  35. */
  36. public function __construct(
  37. private string $appId,
  38. private string $calendarUri,
  39. ) {
  40. }
  41. /**
  42. * @inheritDoc
  43. */
  44. final public function getName() {
  45. return implode(self::DELIMITER, [
  46. self::PREFIX,
  47. $this->appId,
  48. $this->calendarUri,
  49. ]);
  50. }
  51. /**
  52. * @inheritDoc
  53. */
  54. final public function setName($name) {
  55. throw new DAV\Exception\MethodNotAllowed('Renaming calendars is not yet supported');
  56. }
  57. /**
  58. * @inheritDoc
  59. */
  60. final public function createDirectory($name) {
  61. throw new DAV\Exception\MethodNotAllowed('Creating collections in calendar objects is not allowed');
  62. }
  63. /**
  64. * Checks whether the calendar uri is app-generated
  65. *
  66. * @param string $calendarUri
  67. * @return bool
  68. */
  69. public static function isAppGeneratedCalendar(string $calendarUri):bool {
  70. return str_starts_with($calendarUri, self::PREFIX) && substr_count($calendarUri, self::DELIMITER) >= 2;
  71. }
  72. /**
  73. * Splits an app-generated calendar-uri into appId and calendarUri
  74. *
  75. * @param string $calendarUri
  76. * @return array
  77. */
  78. public static function splitAppGeneratedCalendarUri(string $calendarUri):array {
  79. $array = array_slice(explode(self::DELIMITER, $calendarUri, 3), 1);
  80. // Check the array has expected amount of elements
  81. // and none of them is an empty string
  82. if (\count($array) !== 2 || \in_array('', $array, true)) {
  83. throw new \InvalidArgumentException('Provided calendar uri was not app-generated');
  84. }
  85. return $array;
  86. }
  87. /**
  88. * Checks whether a calendar-name, the user wants to create, violates
  89. * the reserved name for calendar uris
  90. *
  91. * @param string $calendarUri
  92. * @return bool
  93. */
  94. public static function doesViolateReservedName(string $calendarUri):bool {
  95. return str_starts_with($calendarUri, self::PREFIX);
  96. }
  97. }