CalendarHome.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. namespace OCA\DAV\CalDAV;
  8. use OCA\DAV\AppInfo\PluginManager;
  9. use OCA\DAV\CalDAV\Integration\ExternalCalendar;
  10. use OCA\DAV\CalDAV\Integration\ICalendarProvider;
  11. use OCA\DAV\CalDAV\Trashbin\TrashbinHome;
  12. use OCP\IConfig;
  13. use OCP\IL10N;
  14. use Psr\Log\LoggerInterface;
  15. use Sabre\CalDAV\Backend\BackendInterface;
  16. use Sabre\CalDAV\Backend\NotificationSupport;
  17. use Sabre\CalDAV\Backend\SchedulingSupport;
  18. use Sabre\CalDAV\Backend\SubscriptionSupport;
  19. use Sabre\CalDAV\Schedule\Inbox;
  20. use Sabre\CalDAV\Subscriptions\Subscription;
  21. use Sabre\DAV\Exception\MethodNotAllowed;
  22. use Sabre\DAV\Exception\NotFound;
  23. use Sabre\DAV\INode;
  24. use Sabre\DAV\MkCol;
  25. class CalendarHome extends \Sabre\CalDAV\CalendarHome {
  26. /** @var IL10N */
  27. private $l10n;
  28. /** @var IConfig */
  29. private $config;
  30. /** @var PluginManager */
  31. private $pluginManager;
  32. private ?array $cachedChildren = null;
  33. public function __construct(
  34. BackendInterface $caldavBackend,
  35. array $principalInfo,
  36. private LoggerInterface $logger,
  37. private bool $returnCachedSubscriptions,
  38. ) {
  39. parent::__construct($caldavBackend, $principalInfo);
  40. $this->l10n = \OC::$server->getL10N('dav');
  41. $this->config = \OC::$server->getConfig();
  42. $this->pluginManager = new PluginManager(
  43. \OC::$server,
  44. \OC::$server->getAppManager()
  45. );
  46. }
  47. /**
  48. * @return BackendInterface
  49. */
  50. public function getCalDAVBackend() {
  51. return $this->caldavBackend;
  52. }
  53. /**
  54. * @inheritdoc
  55. */
  56. public function createExtendedCollection($name, MkCol $mkCol): void {
  57. $reservedNames = [
  58. BirthdayService::BIRTHDAY_CALENDAR_URI,
  59. TrashbinHome::NAME,
  60. ];
  61. if (\in_array($name, $reservedNames, true) || ExternalCalendar::doesViolateReservedName($name)) {
  62. throw new MethodNotAllowed('The resource you tried to create has a reserved name');
  63. }
  64. parent::createExtendedCollection($name, $mkCol);
  65. }
  66. /**
  67. * @inheritdoc
  68. */
  69. public function getChildren() {
  70. if ($this->cachedChildren) {
  71. return $this->cachedChildren;
  72. }
  73. $calendars = $this->caldavBackend->getCalendarsForUser($this->principalInfo['uri']);
  74. $objects = [];
  75. foreach ($calendars as $calendar) {
  76. $objects[] = new Calendar($this->caldavBackend, $calendar, $this->l10n, $this->config, $this->logger);
  77. }
  78. if ($this->caldavBackend instanceof SchedulingSupport) {
  79. $objects[] = new Inbox($this->caldavBackend, $this->principalInfo['uri']);
  80. $objects[] = new Outbox($this->config, $this->principalInfo['uri']);
  81. }
  82. // We're adding a notifications node, if it's supported by the backend.
  83. if ($this->caldavBackend instanceof NotificationSupport) {
  84. $objects[] = new \Sabre\CalDAV\Notifications\Collection($this->caldavBackend, $this->principalInfo['uri']);
  85. }
  86. if ($this->caldavBackend instanceof CalDavBackend) {
  87. $objects[] = new TrashbinHome($this->caldavBackend, $this->principalInfo);
  88. }
  89. // If the backend supports subscriptions, we'll add those as well,
  90. if ($this->caldavBackend instanceof SubscriptionSupport) {
  91. foreach ($this->caldavBackend->getSubscriptionsForUser($this->principalInfo['uri']) as $subscription) {
  92. if ($this->returnCachedSubscriptions) {
  93. $objects[] = new CachedSubscription($this->caldavBackend, $subscription);
  94. } else {
  95. $objects[] = new Subscription($this->caldavBackend, $subscription);
  96. }
  97. }
  98. }
  99. foreach ($this->pluginManager->getCalendarPlugins() as $calendarPlugin) {
  100. /** @var ICalendarProvider $calendarPlugin */
  101. $calendars = $calendarPlugin->fetchAllForCalendarHome($this->principalInfo['uri']);
  102. foreach ($calendars as $calendar) {
  103. $objects[] = $calendar;
  104. }
  105. }
  106. $this->cachedChildren = $objects;
  107. return $objects;
  108. }
  109. /**
  110. * @param string $name
  111. *
  112. * @return INode
  113. */
  114. public function getChild($name) {
  115. // Special nodes
  116. if ($name === 'inbox' && $this->caldavBackend instanceof SchedulingSupport) {
  117. return new Inbox($this->caldavBackend, $this->principalInfo['uri']);
  118. }
  119. if ($name === 'outbox' && $this->caldavBackend instanceof SchedulingSupport) {
  120. return new Outbox($this->config, $this->principalInfo['uri']);
  121. }
  122. if ($name === 'notifications' && $this->caldavBackend instanceof NotificationSupport) {
  123. return new \Sabre\CalDAV\Notifications\Collection($this->caldavBackend, $this->principalInfo['uri']);
  124. }
  125. if ($name === TrashbinHome::NAME && $this->caldavBackend instanceof CalDavBackend) {
  126. return new TrashbinHome($this->caldavBackend, $this->principalInfo);
  127. }
  128. // Calendar - this covers all "regular" calendars, but not shared
  129. // only check if the method is available
  130. if ($this->caldavBackend instanceof CalDavBackend) {
  131. $calendar = $this->caldavBackend->getCalendarByUri($this->principalInfo['uri'], $name);
  132. if (!empty($calendar)) {
  133. return new Calendar($this->caldavBackend, $calendar, $this->l10n, $this->config, $this->logger);
  134. }
  135. }
  136. // Fallback to cover shared calendars
  137. foreach ($this->caldavBackend->getCalendarsForUser($this->principalInfo['uri']) as $calendar) {
  138. if ($calendar['uri'] === $name) {
  139. return new Calendar($this->caldavBackend, $calendar, $this->l10n, $this->config, $this->logger);
  140. }
  141. }
  142. if ($this->caldavBackend instanceof SubscriptionSupport) {
  143. foreach ($this->caldavBackend->getSubscriptionsForUser($this->principalInfo['uri']) as $subscription) {
  144. if ($subscription['uri'] === $name) {
  145. if ($this->returnCachedSubscriptions) {
  146. return new CachedSubscription($this->caldavBackend, $subscription);
  147. }
  148. return new Subscription($this->caldavBackend, $subscription);
  149. }
  150. }
  151. }
  152. if (ExternalCalendar::isAppGeneratedCalendar($name)) {
  153. [$appId, $calendarUri] = ExternalCalendar::splitAppGeneratedCalendarUri($name);
  154. foreach ($this->pluginManager->getCalendarPlugins() as $calendarPlugin) {
  155. /** @var ICalendarProvider $calendarPlugin */
  156. if ($calendarPlugin->getAppId() !== $appId) {
  157. continue;
  158. }
  159. if ($calendarPlugin->hasCalendarInCalendarHome($this->principalInfo['uri'], $calendarUri)) {
  160. return $calendarPlugin->getCalendarInCalendarHome($this->principalInfo['uri'], $calendarUri);
  161. }
  162. }
  163. }
  164. throw new NotFound('Node with name \'' . $name . '\' could not be found');
  165. }
  166. /**
  167. * @param array $filters
  168. * @param integer|null $limit
  169. * @param integer|null $offset
  170. */
  171. public function calendarSearch(array $filters, $limit = null, $offset = null) {
  172. $principalUri = $this->principalInfo['uri'];
  173. return $this->caldavBackend->calendarSearch($principalUri, $filters, $limit, $offset);
  174. }
  175. }