AbsenceService.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. namespace OCA\DAV\Service;
  8. use InvalidArgumentException;
  9. use OCA\DAV\BackgroundJob\OutOfOfficeEventDispatcherJob;
  10. use OCA\DAV\CalDAV\TimezoneService;
  11. use OCA\DAV\Db\Absence;
  12. use OCA\DAV\Db\AbsenceMapper;
  13. use OCP\AppFramework\Db\DoesNotExistException;
  14. use OCP\AppFramework\Utility\ITimeFactory;
  15. use OCP\BackgroundJob\IJobList;
  16. use OCP\EventDispatcher\IEventDispatcher;
  17. use OCP\IUser;
  18. use OCP\User\Events\OutOfOfficeChangedEvent;
  19. use OCP\User\Events\OutOfOfficeClearedEvent;
  20. use OCP\User\Events\OutOfOfficeScheduledEvent;
  21. use OCP\User\IOutOfOfficeData;
  22. class AbsenceService {
  23. public function __construct(
  24. private AbsenceMapper $absenceMapper,
  25. private IEventDispatcher $eventDispatcher,
  26. private IJobList $jobList,
  27. private TimezoneService $timezoneService,
  28. private ITimeFactory $timeFactory,
  29. ) {
  30. }
  31. /**
  32. * @param string $firstDay The first day (inclusive) of the absence formatted as YYYY-MM-DD.
  33. * @param string $lastDay The last day (inclusive) of the absence formatted as YYYY-MM-DD.
  34. *
  35. * @throws \OCP\DB\Exception
  36. * @throws InvalidArgumentException If no user with the given user id exists.
  37. */
  38. public function createOrUpdateAbsence(
  39. IUser $user,
  40. string $firstDay,
  41. string $lastDay,
  42. string $status,
  43. string $message,
  44. ?string $replacementUserId = null,
  45. ?string $replacementUserDisplayName = null,
  46. ): Absence {
  47. try {
  48. $absence = $this->absenceMapper->findByUserId($user->getUID());
  49. } catch (DoesNotExistException) {
  50. $absence = new Absence();
  51. }
  52. $absence->setUserId($user->getUID());
  53. $absence->setFirstDay($firstDay);
  54. $absence->setLastDay($lastDay);
  55. $absence->setStatus($status);
  56. $absence->setMessage($message);
  57. $absence->setReplacementUserId($replacementUserId);
  58. $absence->setReplacementUserDisplayName($replacementUserDisplayName);
  59. if ($absence->getId() === null) {
  60. $absence = $this->absenceMapper->insert($absence);
  61. $eventData = $absence->toOutOufOfficeData(
  62. $user,
  63. $this->timezoneService->getUserTimezone($user->getUID()) ?? $this->timezoneService->getDefaultTimezone(),
  64. );
  65. $this->eventDispatcher->dispatchTyped(new OutOfOfficeScheduledEvent($eventData));
  66. } else {
  67. $absence = $this->absenceMapper->update($absence);
  68. $eventData = $absence->toOutOufOfficeData(
  69. $user,
  70. $this->timezoneService->getUserTimezone($user->getUID()) ?? $this->timezoneService->getDefaultTimezone(),
  71. );
  72. $this->eventDispatcher->dispatchTyped(new OutOfOfficeChangedEvent($eventData));
  73. }
  74. $now = $this->timeFactory->getTime();
  75. if ($eventData->getStartDate() > $now) {
  76. $this->jobList->scheduleAfter(
  77. OutOfOfficeEventDispatcherJob::class,
  78. $eventData->getStartDate(),
  79. [
  80. 'id' => $absence->getId(),
  81. 'event' => OutOfOfficeEventDispatcherJob::EVENT_START,
  82. ],
  83. );
  84. }
  85. if ($eventData->getEndDate() > $now) {
  86. $this->jobList->scheduleAfter(
  87. OutOfOfficeEventDispatcherJob::class,
  88. $eventData->getEndDate(),
  89. [
  90. 'id' => $absence->getId(),
  91. 'event' => OutOfOfficeEventDispatcherJob::EVENT_END,
  92. ],
  93. );
  94. }
  95. return $absence;
  96. }
  97. /**
  98. * @throws \OCP\DB\Exception
  99. */
  100. public function clearAbsence(IUser $user): void {
  101. try {
  102. $absence = $this->absenceMapper->findByUserId($user->getUID());
  103. } catch (DoesNotExistException $e) {
  104. // Nothing to clear
  105. return;
  106. }
  107. $this->absenceMapper->delete($absence);
  108. $this->jobList->remove(OutOfOfficeEventDispatcherJob::class);
  109. $eventData = $absence->toOutOufOfficeData(
  110. $user,
  111. $this->timezoneService->getUserTimezone($user->getUID()) ?? $this->timezoneService->getDefaultTimezone(),
  112. );
  113. $this->eventDispatcher->dispatchTyped(new OutOfOfficeClearedEvent($eventData));
  114. }
  115. public function getAbsence(string $userId): ?Absence {
  116. try {
  117. return $this->absenceMapper->findByUserId($userId);
  118. } catch (DoesNotExistException $e) {
  119. return null;
  120. }
  121. }
  122. public function getCurrentAbsence(IUser $user): ?IOutOfOfficeData {
  123. try {
  124. $absence = $this->absenceMapper->findByUserId($user->getUID());
  125. $oooData = $absence->toOutOufOfficeData(
  126. $user,
  127. $this->timezoneService->getUserTimezone($user->getUID()) ?? $this->timezoneService->getDefaultTimezone(),
  128. );
  129. if ($this->isInEffect($oooData)) {
  130. return $oooData;
  131. }
  132. } catch (DoesNotExistException) {
  133. // Nothing there to process
  134. }
  135. return null;
  136. }
  137. public function isInEffect(IOutOfOfficeData $absence): bool {
  138. $now = $this->timeFactory->getTime();
  139. return $absence->getStartDate() <= $now && $absence->getEndDate() >= $now;
  140. }
  141. }