ReminderServiceTest.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * @copyright Copyright (c) 2019, Thomas Citharel
  5. *
  6. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  7. * @author Georg Ehrke <oc.list@georgehrke.com>
  8. * @author Roeland Jago Douma <roeland@famdouma.nl>
  9. * @author Thomas Citharel <nextcloud@tcit.fr>
  10. * @author Richard Steinmetz <richard@steinmetz.cloud>
  11. *
  12. * @license GNU AGPL version 3 or any later version
  13. *
  14. * This program is free software: you can redistribute it and/or modify
  15. * it under the terms of the GNU Affero General Public License as
  16. * published by the Free Software Foundation, either version 3 of the
  17. * License, or (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU Affero General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU Affero General Public License
  25. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  26. *
  27. */
  28. namespace OCA\DAV\Tests\unit\CalDAV\Reminder;
  29. use DateTime;
  30. use DateTimeZone;
  31. use OCA\DAV\CalDAV\CalDavBackend;
  32. use OCA\DAV\CalDAV\Reminder\Backend;
  33. use OCA\DAV\CalDAV\Reminder\INotificationProvider;
  34. use OCA\DAV\CalDAV\Reminder\NotificationProviderManager;
  35. use OCA\DAV\CalDAV\Reminder\ReminderService;
  36. use OCA\DAV\Connector\Sabre\Principal;
  37. use OCP\AppFramework\Utility\ITimeFactory;
  38. use OCP\IConfig;
  39. use OCP\IGroupManager;
  40. use OCP\IUser;
  41. use OCP\IUserManager;
  42. use PHPUnit\Framework\MockObject\MockObject;
  43. use Psr\Log\LoggerInterface;
  44. use Test\TestCase;
  45. class ReminderServiceTest extends TestCase {
  46. /** @var Backend|MockObject */
  47. private $backend;
  48. /** @var NotificationProviderManager|MockObject */
  49. private $notificationProviderManager;
  50. /** @var IUserManager|MockObject */
  51. private $userManager;
  52. /** @var IGroupManager|MockObject*/
  53. private $groupManager;
  54. /** @var CalDavBackend|MockObject */
  55. private $caldavBackend;
  56. /** @var ITimeFactory|MockObject */
  57. private $timeFactory;
  58. /** @var IConfig|MockObject */
  59. private $config;
  60. /** @var ReminderService */
  61. private $reminderService;
  62. /** @var MockObject|LoggerInterface */
  63. private $logger;
  64. /** @var MockObject|Principal */
  65. private $principalConnector;
  66. public const CALENDAR_DATA = <<<EOD
  67. BEGIN:VCALENDAR
  68. PRODID:-//Nextcloud calendar v1.6.4
  69. BEGIN:VEVENT
  70. CREATED:20160602T133732
  71. DTSTAMP:20160602T133732
  72. LAST-MODIFIED:20160602T133732
  73. UID:wej2z68l9h
  74. SUMMARY:Test Event
  75. LOCATION:Somewhere ...
  76. DESCRIPTION:maybe ....
  77. DTSTART;TZID=Europe/Berlin;VALUE=DATE:20160609
  78. DTEND;TZID=Europe/Berlin;VALUE=DATE:20160610
  79. BEGIN:VALARM
  80. ACTION:EMAIL
  81. TRIGGER:-PT15M
  82. END:VALARM
  83. BEGIN:VALARM
  84. ACTION:DISPLAY
  85. TRIGGER;VALUE=DATE-TIME:20160608T000000Z
  86. END:VALARM
  87. END:VEVENT
  88. END:VCALENDAR
  89. EOD;
  90. public const CALENDAR_DATA_REPEAT = <<<EOD
  91. BEGIN:VCALENDAR
  92. PRODID:-//Nextcloud calendar v1.6.4
  93. BEGIN:VEVENT
  94. CREATED:20160602T133732
  95. DTSTAMP:20160602T133732
  96. LAST-MODIFIED:20160602T133732
  97. UID:wej2z68l9h
  98. SUMMARY:Test Event
  99. LOCATION:Somewhere ...
  100. DESCRIPTION:maybe ....
  101. DTSTART;TZID=Europe/Berlin;VALUE=DATE:20160609
  102. DTEND;TZID=Europe/Berlin;VALUE=DATE:20160610
  103. BEGIN:VALARM
  104. ACTION:EMAIL
  105. TRIGGER:-PT15M
  106. REPEAT:4
  107. DURATION:PT2M
  108. END:VALARM
  109. END:VEVENT
  110. END:VCALENDAR
  111. EOD;
  112. public const CALENDAR_DATA_RECURRING = <<<EOD
  113. BEGIN:VCALENDAR
  114. PRODID:-//Nextcloud calendar v1.6.4
  115. BEGIN:VEVENT
  116. CREATED:20160602T133732
  117. DTSTAMP:20160602T133732
  118. LAST-MODIFIED:20160602T133732
  119. UID:wej2z68l9h
  120. SUMMARY:Test Event
  121. LOCATION:Somewhere ...
  122. DESCRIPTION:maybe ....
  123. DTSTART;TZID=Europe/Berlin;VALUE=DATE:20160609
  124. DTEND;TZID=Europe/Berlin;VALUE=DATE:20160610
  125. RRULE:FREQ=WEEKLY
  126. BEGIN:VALARM
  127. ACTION:EMAIL
  128. TRIGGER:-PT15M
  129. END:VALARM
  130. BEGIN:VALARM
  131. ACTION:EMAIL
  132. TRIGGER:-P8D
  133. END:VALARM
  134. END:VEVENT
  135. END:VCALENDAR
  136. EOD;
  137. public const CALENDAR_DATA_RECURRING_REPEAT = <<<EOD
  138. BEGIN:VCALENDAR
  139. PRODID:-//Nextcloud calendar v1.6.4
  140. BEGIN:VEVENT
  141. CREATED:20160602T133732
  142. DTSTAMP:20160602T133732
  143. LAST-MODIFIED:20160602T133732
  144. UID:wej2z68l9h
  145. SUMMARY:Test Event
  146. LOCATION:Somewhere ...
  147. DESCRIPTION:maybe ....
  148. DTSTART;TZID=Europe/Berlin;VALUE=DATE:20160609
  149. DTEND;TZID=Europe/Berlin;VALUE=DATE:20160610
  150. RRULE:FREQ=WEEKLY
  151. BEGIN:VALARM
  152. ACTION:EMAIL
  153. TRIGGER:-PT15M
  154. REPEAT:4
  155. DURATION:PT2M
  156. END:VALARM
  157. BEGIN:VALARM
  158. ACTION:EMAIL
  159. TRIGGER:-P8D
  160. END:VALARM
  161. END:VEVENT
  162. END:VCALENDAR
  163. EOD;
  164. public const CALENDAR_DATA_NO_ALARM = <<<EOD
  165. BEGIN:VCALENDAR
  166. PRODID:-//Nextcloud calendar v1.6.4
  167. BEGIN:VEVENT
  168. CREATED:20160602T133732
  169. DTSTAMP:20160602T133732
  170. LAST-MODIFIED:20160602T133732
  171. UID:wej2z68l9h
  172. SUMMARY:Test Event
  173. LOCATION:Somewhere ...
  174. DESCRIPTION:maybe ....
  175. DTSTART;TZID=Europe/Berlin;VALUE=DATE:20160609
  176. DTEND;TZID=Europe/Berlin;VALUE=DATE:20160610
  177. END:VEVENT
  178. END:VCALENDAR
  179. EOD;
  180. private const CALENDAR_DATA_ONE_TIME = <<<EOD
  181. BEGIN:VCALENDAR
  182. PRODID:-//IDN nextcloud.com//Calendar app 4.3.0-alpha.0//EN
  183. CALSCALE:GREGORIAN
  184. VERSION:2.0
  185. BEGIN:VEVENT
  186. CREATED:20230203T154600Z
  187. DTSTAMP:20230203T154602Z
  188. LAST-MODIFIED:20230203T154602Z
  189. SEQUENCE:2
  190. UID:f6a565b6-f9a8-4d1e-9d01-c8dcbe716b7e
  191. DTSTART;TZID=Europe/Vienna:20230204T090000
  192. DTEND;TZID=Europe/Vienna:20230204T120000
  193. STATUS:CONFIRMED
  194. SUMMARY:TEST
  195. BEGIN:VALARM
  196. ACTION:DISPLAY
  197. TRIGGER;RELATED=START:-PT1H
  198. END:VALARM
  199. END:VEVENT
  200. BEGIN:VTIMEZONE
  201. TZID:Europe/Vienna
  202. BEGIN:DAYLIGHT
  203. TZOFFSETFROM:+0100
  204. TZOFFSETTO:+0200
  205. TZNAME:CEST
  206. DTSTART:19700329T020000
  207. RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
  208. END:DAYLIGHT
  209. BEGIN:STANDARD
  210. TZOFFSETFROM:+0200
  211. TZOFFSETTO:+0100
  212. TZNAME:CET
  213. DTSTART:19701025T030000
  214. RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
  215. END:STANDARD
  216. END:VTIMEZONE
  217. END:VCALENDAR
  218. EOD;
  219. private const CALENDAR_DATA_ALL_DAY = <<<EOD
  220. BEGIN:VCALENDAR
  221. PRODID:-//IDN nextcloud.com//Calendar app 4.3.0-alpha.0//EN
  222. CALSCALE:GREGORIAN
  223. VERSION:2.0
  224. BEGIN:VEVENT
  225. CREATED:20230203T113430Z
  226. DTSTAMP:20230203T113432Z
  227. LAST-MODIFIED:20230203T113432Z
  228. SEQUENCE:2
  229. UID:a163a056-ba26-44a2-8080-955f19611a8f
  230. DTSTART;VALUE=DATE:20230204
  231. DTEND;VALUE=DATE:20230205
  232. STATUS:CONFIRMED
  233. SUMMARY:TEST
  234. BEGIN:VALARM
  235. ACTION:EMAIL
  236. TRIGGER;RELATED=START:-PT1H
  237. END:VALARM
  238. END:VEVENT
  239. END:VCALENDAR
  240. EOD;
  241. private const PAGO_PAGO_VTIMEZONE_ICS = <<<ICS
  242. BEGIN:VCALENDAR
  243. BEGIN:VTIMEZONE
  244. TZID:Pacific/Pago_Pago
  245. BEGIN:STANDARD
  246. TZOFFSETFROM:-1100
  247. TZOFFSETTO:-1100
  248. TZNAME:SST
  249. DTSTART:19700101T000000
  250. END:STANDARD
  251. END:VTIMEZONE
  252. END:VCALENDAR
  253. ICS;
  254. /** @var null|string */
  255. private $oldTimezone;
  256. protected function setUp(): void {
  257. parent::setUp();
  258. $this->backend = $this->createMock(Backend::class);
  259. $this->notificationProviderManager = $this->createMock(NotificationProviderManager::class);
  260. $this->userManager = $this->createMock(IUserManager::class);
  261. $this->groupManager = $this->createMock(IGroupManager::class);
  262. $this->caldavBackend = $this->createMock(CalDavBackend::class);
  263. $this->timeFactory = $this->createMock(ITimeFactory::class);
  264. $this->config = $this->createMock(IConfig::class);
  265. $this->logger = $this->createMock(LoggerInterface::class);
  266. $this->principalConnector = $this->createMock(Principal::class);
  267. $this->caldavBackend->method('getShares')->willReturn([]);
  268. $this->reminderService = new ReminderService(
  269. $this->backend,
  270. $this->notificationProviderManager,
  271. $this->userManager,
  272. $this->groupManager,
  273. $this->caldavBackend,
  274. $this->timeFactory,
  275. $this->config,
  276. $this->logger,
  277. $this->principalConnector,
  278. );
  279. }
  280. public function testOnCalendarObjectDelete():void {
  281. $this->backend->expects($this->once())
  282. ->method('cleanRemindersForEvent')
  283. ->with(44);
  284. $objectData = [
  285. 'id' => '44',
  286. 'component' => 'vevent',
  287. ];
  288. $this->reminderService->onCalendarObjectDelete($objectData);
  289. }
  290. public function testOnCalendarObjectCreateSingleEntry():void {
  291. $objectData = [
  292. 'calendardata' => self::CALENDAR_DATA,
  293. 'id' => '42',
  294. 'calendarid' => '1337',
  295. 'component' => 'vevent',
  296. ];
  297. $this->backend->expects($this->exactly(2))
  298. ->method('insertReminder')
  299. ->withConsecutive(
  300. [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'de919af7429d3b5c11e8b9d289b411a6', 'EMAIL', true, 1465429500, false],
  301. [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', '35b3eae8e792aa2209f0b4e1a302f105', 'DISPLAY', false, 1465344000, false]
  302. )
  303. ->willReturn(1);
  304. $this->timeFactory->expects($this->once())
  305. ->method('getDateTime')
  306. ->with()
  307. ->willReturn(DateTime::createFromFormat(DateTime::ATOM, '2016-06-08T00:00:00+00:00'));
  308. $this->reminderService->onCalendarObjectCreate($objectData);
  309. }
  310. /**
  311. * RFC5545 says DTSTART is REQUIRED, but we have seen event without the prop
  312. */
  313. public function testOnCalendarObjectCreateNoDtstart(): void {
  314. $calendarData = <<<EOD
  315. BEGIN:VCALENDAR
  316. PRODID:-//Nextcloud calendar v1.6.4
  317. BEGIN:VEVENT
  318. CREATED:20160602T133732
  319. DTSTAMP:20160602T133732
  320. LAST-MODIFIED:20160602T133732
  321. UID:wej2z68l9h
  322. SUMMARY:Test Event
  323. BEGIN:VALARM
  324. ACTION:EMAIL
  325. TRIGGER:-PT15M
  326. END:VALARM
  327. BEGIN:VALARM
  328. ACTION:DISPLAY
  329. TRIGGER;VALUE=DATE-TIME:20160608T000000Z
  330. END:VALARM
  331. END:VEVENT
  332. END:VCALENDAR
  333. EOD;
  334. $objectData = [
  335. 'calendardata' => $calendarData,
  336. 'id' => '42',
  337. 'calendarid' => '1337',
  338. 'component' => 'vevent',
  339. ];
  340. $this->backend->expects($this->never())
  341. ->method('insertReminder')
  342. ->withConsecutive(
  343. [1337, 42, 'wej2z68l9h', false, null, false, '5c70531aab15c92b52518ae10a2f78a4', 'de919af7429d3b5c11e8b9d289b411a6', 'EMAIL', true, 1465429500, false],
  344. [1337, 42, 'wej2z68l9h', false, null, false, '5c70531aab15c92b52518ae10a2f78a4', '35b3eae8e792aa2209f0b4e1a302f105', 'DISPLAY', false, 1465344000, false]
  345. )
  346. ->willReturn(1);
  347. $this->reminderService->onCalendarObjectCreate($objectData);
  348. }
  349. public function testOnCalendarObjectCreateSingleEntryWithRepeat(): void {
  350. $objectData = [
  351. 'calendardata' => self::CALENDAR_DATA_REPEAT,
  352. 'id' => '42',
  353. 'calendarid' => '1337',
  354. 'component' => 'vevent',
  355. ];
  356. $this->backend->expects($this->exactly(5))
  357. ->method('insertReminder')
  358. ->withConsecutive(
  359. [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429500, false],
  360. [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429620, true],
  361. [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429740, true],
  362. [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429860, true],
  363. [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429980, true]
  364. )
  365. ->willReturn(1);
  366. $this->timeFactory->expects($this->once())
  367. ->method('getDateTime')
  368. ->with()
  369. ->willReturn(DateTime::createFromFormat(DateTime::ATOM, '2016-06-08T00:00:00+00:00'));
  370. $this->reminderService->onCalendarObjectCreate($objectData);
  371. }
  372. public function testOnCalendarObjectCreateRecurringEntry(): void {
  373. $objectData = [
  374. 'calendardata' => self::CALENDAR_DATA_RECURRING,
  375. 'id' => '42',
  376. 'calendarid' => '1337',
  377. 'component' => 'vevent',
  378. ];
  379. $this->backend->expects($this->exactly(2))
  380. ->method('insertReminder')
  381. ->withConsecutive(
  382. [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'de919af7429d3b5c11e8b9d289b411a6', 'EMAIL', true, 1467243900, false],
  383. [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', '8996992118817f9f311ac5cc56d1cc97', 'EMAIL', true, 1467158400, false]
  384. )
  385. ->willReturn(1);
  386. $this->timeFactory->expects($this->once())
  387. ->method('getDateTime')
  388. ->willReturn(DateTime::createFromFormat(DateTime::ATOM, '2016-06-29T00:00:00+00:00'));
  389. $this->reminderService->onCalendarObjectCreate($objectData);
  390. }
  391. public function testOnCalendarObjectCreateEmpty():void {
  392. $objectData = [
  393. 'calendardata' => self::CALENDAR_DATA_NO_ALARM,
  394. 'id' => '42',
  395. 'calendarid' => '1337',
  396. 'component' => 'vevent',
  397. ];
  398. $this->backend->expects($this->never())
  399. ->method('insertReminder');
  400. $this->reminderService->onCalendarObjectCreate($objectData);
  401. }
  402. public function testOnCalendarObjectCreateAllDayWithoutTimezone(): void {
  403. $objectData = [
  404. 'calendardata' => self::CALENDAR_DATA_ALL_DAY,
  405. 'id' => '42',
  406. 'calendarid' => '1337',
  407. 'component' => 'vevent',
  408. ];
  409. $this->timeFactory->expects($this->once())
  410. ->method('getDateTime')
  411. ->with()
  412. ->willReturn(DateTime::createFromFormat(DateTime::ATOM, '2023-02-03T13:28:00+00:00'));
  413. $this->caldavBackend->expects(self::once())
  414. ->method('getCalendarById')
  415. ->with(1337)
  416. ->willReturn([
  417. '{urn:ietf:params:xml:ns:caldav}calendar-timezone' => null,
  418. ]);
  419. // One hour before midnight relative to the server's time
  420. $expectedReminderTimstamp = (new DateTime('2023-02-03T23:00:00'))->getTimestamp();
  421. $this->backend->expects(self::once())
  422. ->method('insertReminder')
  423. ->with(1337, 42, self::anything(), false, 1675468800, false, self::anything(), self::anything(), 'EMAIL', true, $expectedReminderTimstamp, false);
  424. $this->reminderService->onCalendarObjectCreate($objectData);
  425. }
  426. public function testOnCalendarObjectCreateAllDayWithTimezone(): void {
  427. $objectData = [
  428. 'calendardata' => self::CALENDAR_DATA_ALL_DAY,
  429. 'id' => '42',
  430. 'calendarid' => '1337',
  431. 'component' => 'vevent',
  432. ];
  433. $this->timeFactory->expects($this->once())
  434. ->method('getDateTime')
  435. ->with()
  436. ->willReturn(DateTime::createFromFormat(DateTime::ATOM, '2023-02-03T13:28:00+00:00'));
  437. $this->caldavBackend->expects(self::once())
  438. ->method('getCalendarById')
  439. ->with(1337)
  440. ->willReturn([
  441. '{urn:ietf:params:xml:ns:caldav}calendar-timezone' => self::PAGO_PAGO_VTIMEZONE_ICS,
  442. ]);
  443. // One hour before midnight relative to the timezone
  444. $expectedReminderTimstamp = (new DateTime('2023-02-03T23:00:00', new DateTimeZone('Pacific/Pago_Pago')))->getTimestamp();
  445. $this->backend->expects(self::once())
  446. ->method('insertReminder')
  447. ->with(1337, 42, 'a163a056-ba26-44a2-8080-955f19611a8f', false, self::anything(), false, self::anything(), self::anything(), 'EMAIL', true, $expectedReminderTimstamp, false);
  448. $this->reminderService->onCalendarObjectCreate($objectData);
  449. }
  450. public function testOnCalendarObjectCreateRecurringEntryWithRepeat():void {
  451. $objectData = [
  452. 'calendardata' => self::CALENDAR_DATA_RECURRING_REPEAT,
  453. 'id' => '42',
  454. 'calendarid' => '1337',
  455. 'component' => 'vevent',
  456. ];
  457. $this->caldavBackend->expects(self::once())
  458. ->method('getCalendarById')
  459. ->with(1337)
  460. ->willReturn([
  461. '{urn:ietf:params:xml:ns:caldav}calendar-timezone' => null,
  462. ]);
  463. $this->backend->expects($this->exactly(6))
  464. ->method('insertReminder')
  465. ->withConsecutive(
  466. [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467243900, false],
  467. [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467244020, true],
  468. [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467244140, true],
  469. [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467244260, true],
  470. [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467244380, true],
  471. [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', '8996992118817f9f311ac5cc56d1cc97', 'EMAIL', true, 1467158400, false]
  472. )
  473. ->willReturn(1);
  474. $this->timeFactory->expects($this->once())
  475. ->method('getDateTime')
  476. ->with()
  477. ->willReturn(DateTime::createFromFormat(DateTime::ATOM, '2016-06-29T00:00:00+00:00'));
  478. $this->reminderService->onCalendarObjectCreate($objectData);
  479. }
  480. public function testOnCalendarObjectCreateWithEventTimezoneAndCalendarTimezone():void {
  481. $objectData = [
  482. 'calendardata' => self::CALENDAR_DATA_ONE_TIME,
  483. 'id' => '42',
  484. 'calendarid' => '1337',
  485. 'component' => 'vevent',
  486. ];
  487. $this->caldavBackend->expects(self::once())
  488. ->method('getCalendarById')
  489. ->with(1337)
  490. ->willReturn([
  491. '{urn:ietf:params:xml:ns:caldav}calendar-timezone' => self::PAGO_PAGO_VTIMEZONE_ICS,
  492. ]);
  493. $expectedReminderTimstamp = (new DateTime('2023-02-04T08:00:00', new DateTimeZone('Europe/Vienna')))->getTimestamp();
  494. $this->backend->expects(self::once())
  495. ->method('insertReminder')
  496. ->withConsecutive(
  497. [1337, 42, self::anything(), false, self::anything(), false, self::anything(), self::anything(), self::anything(), true, $expectedReminderTimstamp, false],
  498. )
  499. ->willReturn(1);
  500. $this->caldavBackend->expects(self::once())
  501. ->method('getCalendarById')
  502. ->with(1337)
  503. ->willReturn([
  504. '{urn:ietf:params:xml:ns:caldav}calendar-timezone' => null,
  505. ]);
  506. $this->timeFactory->expects($this->once())
  507. ->method('getDateTime')
  508. ->with()
  509. ->willReturn(DateTime::createFromFormat(DateTime::ATOM, '2023-02-03T13:28:00+00:00'));
  510. ;
  511. $this->reminderService->onCalendarObjectCreate($objectData);
  512. }
  513. public function testProcessReminders():void {
  514. $this->backend->expects($this->once())
  515. ->method('getRemindersToProcess')
  516. ->with()
  517. ->willReturn([
  518. [
  519. 'id' => 1,
  520. 'calendar_id' => 1337,
  521. 'object_id' => 42,
  522. 'uid' => 'wej2z68l9h',
  523. 'is_recurring' => false,
  524. 'recurrence_id' => 1465430400,
  525. 'is_recurrence_exception' => false,
  526. 'event_hash' => '5c70531aab15c92b52518ae10a2f78a4',
  527. 'alarm_hash' => 'de919af7429d3b5c11e8b9d289b411a6',
  528. 'type' => 'EMAIL',
  529. 'is_relative' => true,
  530. 'notification_date' => 1465429500,
  531. 'is_repeat_based' => false,
  532. 'calendardata' => self::CALENDAR_DATA,
  533. 'displayname' => 'Displayname 123',
  534. 'principaluri' => 'principals/users/user001',
  535. ],
  536. [
  537. 'id' => 2,
  538. 'calendar_id' => 1337,
  539. 'object_id' => 42,
  540. 'uid' => 'wej2z68l9h',
  541. 'is_recurring' => false,
  542. 'recurrence_id' => 1465430400,
  543. 'is_recurrence_exception' => false,
  544. 'event_hash' => '5c70531aab15c92b52518ae10a2f78a4',
  545. 'alarm_hash' => 'ecacbf07d413c3c78d1ac7ad8c469602',
  546. 'type' => 'EMAIL',
  547. 'is_relative' => true,
  548. 'notification_date' => 1465429740,
  549. 'is_repeat_based' => true,
  550. 'calendardata' => self::CALENDAR_DATA_REPEAT,
  551. 'displayname' => 'Displayname 123',
  552. 'principaluri' => 'principals/users/user001',
  553. ],
  554. [
  555. 'id' => 3,
  556. 'calendar_id' => 1337,
  557. 'object_id' => 42,
  558. 'uid' => 'wej2z68l9h',
  559. 'is_recurring' => false,
  560. 'recurrence_id' => 1465430400,
  561. 'is_recurrence_exception' => false,
  562. 'event_hash' => '5c70531aab15c92b52518ae10a2f78a4',
  563. 'alarm_hash' => '35b3eae8e792aa2209f0b4e1a302f105',
  564. 'type' => 'DISPLAY',
  565. 'is_relative' => false,
  566. 'notification_date' => 1465344000,
  567. 'is_repeat_based' => false,
  568. 'calendardata' => self::CALENDAR_DATA,
  569. 'displayname' => 'Displayname 123',
  570. 'principaluri' => 'principals/users/user001',
  571. ],
  572. [
  573. 'id' => 4,
  574. 'calendar_id' => 1337,
  575. 'object_id' => 42,
  576. 'uid' => 'wej2z68l9h',
  577. 'is_recurring' => true,
  578. 'recurrence_id' => 1467244800,
  579. 'is_recurrence_exception' => false,
  580. 'event_hash' => 'fbdb2726bc0f7dfacac1d881c1453e20',
  581. 'alarm_hash' => 'ecacbf07d413c3c78d1ac7ad8c469602',
  582. 'type' => 'EMAIL',
  583. 'is_relative' => true,
  584. 'notification_date' => 1467243900,
  585. 'is_repeat_based' => false,
  586. 'calendardata' => self::CALENDAR_DATA_RECURRING_REPEAT,
  587. 'displayname' => 'Displayname 123',
  588. 'principaluri' => 'principals/users/user001',
  589. ],
  590. [
  591. 'id' => 5,
  592. 'calendar_id' => 1337,
  593. 'object_id' => 42,
  594. 'uid' => 'wej2z68l9h',
  595. 'is_recurring' => true,
  596. 'recurrence_id' => 1467849600,
  597. 'is_recurrence_exception' => false,
  598. 'event_hash' => 'fbdb2726bc0f7dfacac1d881c1453e20',
  599. 'alarm_hash' => '8996992118817f9f311ac5cc56d1cc97',
  600. 'type' => 'EMAIL',
  601. 'is_relative' => true,
  602. 'notification_date' => 1467158400,
  603. 'is_repeat_based' => false,
  604. 'calendardata' => self::CALENDAR_DATA_RECURRING,
  605. 'displayname' => 'Displayname 123',
  606. 'principaluri' => 'principals/users/user001',
  607. ]
  608. ]);
  609. $this->notificationProviderManager->expects($this->exactly(5))
  610. ->method('hasProvider')
  611. ->willReturnMap([
  612. ['EMAIL', true],
  613. ['DISPLAY', true],
  614. ]);
  615. $provider1 = $this->createMock(INotificationProvider::class);
  616. $provider2 = $this->createMock(INotificationProvider::class);
  617. $provider3 = $this->createMock(INotificationProvider::class);
  618. $provider4 = $this->createMock(INotificationProvider::class);
  619. $provider5 = $this->createMock(INotificationProvider::class);
  620. $this->notificationProviderManager->expects($this->exactly(5))
  621. ->method('getProvider')
  622. ->withConsecutive(
  623. ['EMAIL'],
  624. ['EMAIL'],
  625. ['DISPLAY'],
  626. ['EMAIL'],
  627. ['EMAIL'],
  628. )
  629. ->willReturnOnConsecutiveCalls(
  630. $provider1,
  631. $provider2,
  632. $provider3,
  633. $provider4,
  634. $provider5,
  635. );
  636. $user = $this->createMock(IUser::class);
  637. $this->userManager->expects($this->exactly(5))
  638. ->method('get')
  639. ->with('user001')
  640. ->willReturn($user);
  641. $provider1->expects($this->once())
  642. ->method('send')
  643. ->with($this->callback(function ($vevent) {
  644. if ($vevent->DTSTART->getDateTime()->format(DateTime::ATOM) !== '2016-06-09T00:00:00+00:00') {
  645. return false;
  646. }
  647. return true;
  648. }, 'Displayname 123', $user));
  649. $provider2->expects($this->once())
  650. ->method('send')
  651. ->with($this->callback(function ($vevent) {
  652. if ($vevent->DTSTART->getDateTime()->format(DateTime::ATOM) !== '2016-06-09T00:00:00+00:00') {
  653. return false;
  654. }
  655. return true;
  656. }, 'Displayname 123', $user));
  657. $provider3->expects($this->once())
  658. ->method('send')
  659. ->with($this->callback(function ($vevent) {
  660. if ($vevent->DTSTART->getDateTime()->format(DateTime::ATOM) !== '2016-06-09T00:00:00+00:00') {
  661. return false;
  662. }
  663. return true;
  664. }, 'Displayname 123', $user));
  665. $provider4->expects($this->once())
  666. ->method('send')
  667. ->with($this->callback(function ($vevent) {
  668. if ($vevent->DTSTART->getDateTime()->format(DateTime::ATOM) !== '2016-06-30T00:00:00+00:00') {
  669. return false;
  670. }
  671. return true;
  672. }, 'Displayname 123', $user));
  673. $provider5->expects($this->once())
  674. ->method('send')
  675. ->with($this->callback(function ($vevent) {
  676. if ($vevent->DTSTART->getDateTime()->format(DateTime::ATOM) !== '2016-07-07T00:00:00+00:00') {
  677. return false;
  678. }
  679. return true;
  680. }, 'Displayname 123', $user));
  681. $this->backend->expects($this->exactly(5))
  682. ->method('removeReminder')
  683. ->withConsecutive([1], [2], [3], [4], [5]);
  684. $this->backend->expects($this->exactly(6))
  685. ->method('insertReminder')
  686. ->withConsecutive(
  687. [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467848700, false],
  688. [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467848820, true],
  689. [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467848940, true],
  690. [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467849060, true],
  691. [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467849180, true],
  692. [1337, 42, 'wej2z68l9h', true, 1468454400, false, 'fbdb2726bc0f7dfacac1d881c1453e20', '8996992118817f9f311ac5cc56d1cc97', 'EMAIL', true, 1467763200, false],
  693. )
  694. ->willReturn(99);
  695. $this->timeFactory->method('getDateTime')
  696. ->willReturn(DateTime::createFromFormat(DateTime::ATOM, '2016-06-08T00:00:00+00:00'));
  697. $this->reminderService->processReminders();
  698. }
  699. }