CalDavBackendTest.php 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. * @copyright Copyright (c) 2017 Georg Ehrke
  5. *
  6. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  7. * @author dartcafe <github@dartcafe.de>
  8. * @author Georg Ehrke <oc.list@georgehrke.com>
  9. * @author Joas Schilling <coding@schilljs.com>
  10. * @author leith abdulla <online-nextcloud@eleith.com>
  11. * @author Morris Jobke <hey@morrisjobke.de>
  12. * @author Robin Appelman <robin@icewind.nl>
  13. * @author Roeland Jago Douma <roeland@famdouma.nl>
  14. * @author Thomas Citharel <nextcloud@tcit.fr>
  15. * @author Thomas Müller <thomas.mueller@tmit.eu>
  16. *
  17. * @license AGPL-3.0
  18. *
  19. * This code is free software: you can redistribute it and/or modify
  20. * it under the terms of the GNU Affero General Public License, version 3,
  21. * as published by the Free Software Foundation.
  22. *
  23. * This program is distributed in the hope that it will be useful,
  24. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  26. * GNU Affero General Public License for more details.
  27. *
  28. * You should have received a copy of the GNU Affero General Public License, version 3,
  29. * along with this program. If not, see <http://www.gnu.org/licenses/>
  30. *
  31. */
  32. namespace OCA\DAV\Tests\unit\CalDAV;
  33. use DateTime;
  34. use DateTimeZone;
  35. use OCA\DAV\CalDAV\CalDavBackend;
  36. use OCA\DAV\CalDAV\Calendar;
  37. use OCA\DAV\DAV\Sharing\Plugin as SharingPlugin;
  38. use OCA\DAV\Events\CalendarDeletedEvent;
  39. use OCP\IConfig;
  40. use OCP\IL10N;
  41. use Sabre\DAV\Exception\NotFound;
  42. use Sabre\DAV\PropPatch;
  43. use Sabre\DAV\Xml\Property\Href;
  44. use Sabre\DAVACL\IACL;
  45. /**
  46. * Class CalDavBackendTest
  47. *
  48. * @group DB
  49. *
  50. * @package OCA\DAV\Tests\unit\CalDAV
  51. */
  52. class CalDavBackendTest extends AbstractCalDavBackend {
  53. public function testCalendarOperations() {
  54. $calendarId = $this->createTestCalendar();
  55. // update its display name
  56. $patch = new PropPatch([
  57. '{DAV:}displayname' => 'Unit test',
  58. '{urn:ietf:params:xml:ns:caldav}calendar-description' => 'Calendar used for unit testing'
  59. ]);
  60. $this->dispatcher->expects(self::atLeastOnce())
  61. ->method('dispatchTyped');
  62. $this->backend->updateCalendar($calendarId, $patch);
  63. $patch->commit();
  64. $this->assertEquals(1, $this->backend->getCalendarsForUserCount(self::UNIT_TEST_USER));
  65. $calendars = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER);
  66. $this->assertCount(1, $calendars);
  67. $this->assertEquals('Unit test', $calendars[0]['{DAV:}displayname']);
  68. $this->assertEquals('Calendar used for unit testing', $calendars[0]['{urn:ietf:params:xml:ns:caldav}calendar-description']);
  69. $this->assertEquals('User\'s displayname', $calendars[0]['{http://nextcloud.com/ns}owner-displayname']);
  70. // delete the address book
  71. $this->dispatcher->expects(self::atLeastOnce())
  72. ->method('dispatchTyped');
  73. $this->backend->deleteCalendar($calendars[0]['id'], true);
  74. $calendars = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER);
  75. self::assertEmpty($calendars);
  76. }
  77. public function providesSharingData() {
  78. return [
  79. [true, true, true, false, [
  80. [
  81. 'href' => 'principal:' . self::UNIT_TEST_USER1,
  82. 'readOnly' => false
  83. ],
  84. [
  85. 'href' => 'principal:' . self::UNIT_TEST_GROUP,
  86. 'readOnly' => true
  87. ]
  88. ]],
  89. [true, true, true, false, [
  90. [
  91. 'href' => 'principal:' . self::UNIT_TEST_GROUP,
  92. 'readOnly' => true,
  93. ],
  94. [
  95. 'href' => 'principal:' . self::UNIT_TEST_GROUP2,
  96. 'readOnly' => false,
  97. ],
  98. ]],
  99. [true, true, true, true, [
  100. [
  101. 'href' => 'principal:' . self::UNIT_TEST_GROUP,
  102. 'readOnly' => false,
  103. ],
  104. [
  105. 'href' => 'principal:' . self::UNIT_TEST_GROUP2,
  106. 'readOnly' => true,
  107. ],
  108. ]],
  109. [true, false, false, false, [
  110. [
  111. 'href' => 'principal:' . self::UNIT_TEST_USER1,
  112. 'readOnly' => true
  113. ],
  114. ]],
  115. ];
  116. }
  117. /**
  118. * @dataProvider providesSharingData
  119. */
  120. public function testCalendarSharing($userCanRead, $userCanWrite, $groupCanRead, $groupCanWrite, $add) {
  121. /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject $l10n */
  122. $l10n = $this->createMock(IL10N::class);
  123. $l10n
  124. ->expects($this->any())
  125. ->method('t')
  126. ->willReturnCallback(function ($text, $parameters = []) {
  127. return vsprintf($text, $parameters);
  128. });
  129. $logger = $this->createMock(\Psr\Log\LoggerInterface::class);
  130. $config = $this->createMock(IConfig::class);
  131. $this->userManager->expects($this->any())
  132. ->method('userExists')
  133. ->willReturn(true);
  134. $this->groupManager->expects($this->any())
  135. ->method('groupExists')
  136. ->willReturn(true);
  137. $calendarId = $this->createTestCalendar();
  138. $calendars = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER);
  139. $this->assertCount(1, $calendars);
  140. $calendar = new Calendar($this->backend, $calendars[0], $l10n, $config, $logger);
  141. $this->backend->updateShares($calendar, $add, []);
  142. $calendars = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER1);
  143. $this->assertCount(1, $calendars);
  144. $calendar = new Calendar($this->backend, $calendars[0], $l10n, $config, $logger);
  145. $acl = $calendar->getACL();
  146. $this->assertAcl(self::UNIT_TEST_USER, '{DAV:}read', $acl);
  147. $this->assertAcl(self::UNIT_TEST_USER, '{DAV:}write', $acl);
  148. $this->assertAccess($userCanRead, self::UNIT_TEST_USER1, '{DAV:}read', $acl);
  149. $this->assertAccess($userCanWrite, self::UNIT_TEST_USER1, '{DAV:}write', $acl);
  150. $this->assertEquals(self::UNIT_TEST_USER, $calendar->getOwner());
  151. // test acls on the child
  152. $uri = static::getUniqueID('calobj');
  153. $calData = <<<'EOD'
  154. BEGIN:VCALENDAR
  155. VERSION:2.0
  156. PRODID:ownCloud Calendar
  157. BEGIN:VEVENT
  158. CREATED;VALUE=DATE-TIME:20130910T125139Z
  159. UID:47d15e3ec8
  160. LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
  161. DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
  162. SUMMARY:Test Event
  163. DTSTART;VALUE=DATE-TIME:20130912T130000Z
  164. DTEND;VALUE=DATE-TIME:20130912T140000Z
  165. CLASS:PUBLIC
  166. END:VEVENT
  167. END:VCALENDAR
  168. EOD;
  169. $this->dispatcher->expects(self::atLeastOnce())
  170. ->method('dispatchTyped');
  171. $this->backend->createCalendarObject($calendarId, $uri, $calData);
  172. /** @var IACL $child */
  173. $child = $calendar->getChild($uri);
  174. $acl = $child->getACL();
  175. $this->assertAcl(self::UNIT_TEST_USER, '{DAV:}read', $acl);
  176. $this->assertAcl(self::UNIT_TEST_USER, '{DAV:}write', $acl);
  177. $this->assertAccess($userCanRead, self::UNIT_TEST_USER1, '{DAV:}read', $acl);
  178. $this->assertAccess($userCanWrite, self::UNIT_TEST_USER1, '{DAV:}write', $acl);
  179. // delete the calendar
  180. $this->dispatcher->expects(self::once())
  181. ->method('dispatchTyped')
  182. ->with(self::callback(function ($event) {
  183. return $event instanceof CalendarDeletedEvent;
  184. }));
  185. $this->backend->deleteCalendar($calendars[0]['id'], true);
  186. $calendars = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER);
  187. self::assertEmpty($calendars);
  188. }
  189. public function testCalendarObjectsOperations() {
  190. $calendarId = $this->createTestCalendar();
  191. // create a card
  192. $uri = static::getUniqueID('calobj');
  193. $calData = <<<'EOD'
  194. BEGIN:VCALENDAR
  195. VERSION:2.0
  196. PRODID:ownCloud Calendar
  197. BEGIN:VEVENT
  198. CREATED;VALUE=DATE-TIME:20130910T125139Z
  199. UID:47d15e3ec8
  200. LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
  201. DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
  202. SUMMARY:Test Event
  203. DTSTART;VALUE=DATE-TIME:20130912T130000Z
  204. DTEND;VALUE=DATE-TIME:20130912T140000Z
  205. CLASS:PUBLIC
  206. END:VEVENT
  207. END:VCALENDAR
  208. EOD;
  209. $this->dispatcher->expects(self::atLeastOnce())
  210. ->method('dispatchTyped');
  211. $this->backend->createCalendarObject($calendarId, $uri, $calData);
  212. // get all the calendar objects
  213. $calendarObjects = $this->backend->getCalendarObjects($calendarId);
  214. $this->assertCount(1, $calendarObjects);
  215. $this->assertEquals($calendarId, $calendarObjects[0]['calendarid']);
  216. $this->assertArrayHasKey('classification', $calendarObjects[0]);
  217. // get the calendar objects
  218. $calendarObject = $this->backend->getCalendarObject($calendarId, $uri);
  219. $this->assertNotNull($calendarObject);
  220. $this->assertArrayHasKey('id', $calendarObject);
  221. $this->assertArrayHasKey('uri', $calendarObject);
  222. $this->assertArrayHasKey('lastmodified', $calendarObject);
  223. $this->assertArrayHasKey('etag', $calendarObject);
  224. $this->assertArrayHasKey('size', $calendarObject);
  225. $this->assertArrayHasKey('classification', $calendarObject);
  226. $this->assertArrayHasKey('{' . SharingPlugin::NS_NEXTCLOUD . '}deleted-at', $calendarObject);
  227. $this->assertEquals($calData, $calendarObject['calendardata']);
  228. // update the card
  229. $calData = <<<'EOD'
  230. BEGIN:VCALENDAR
  231. VERSION:2.0
  232. PRODID:ownCloud Calendar
  233. BEGIN:VEVENT
  234. CREATED;VALUE=DATE-TIME:20130910T125139Z
  235. UID:47d15e3ec8
  236. LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
  237. DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
  238. SUMMARY:Test Event
  239. DTSTART;VALUE=DATE-TIME:20130912T130000Z
  240. DTEND;VALUE=DATE-TIME:20130912T140000Z
  241. END:VEVENT
  242. END:VCALENDAR
  243. EOD;
  244. $this->dispatcher->expects(self::atLeastOnce())
  245. ->method('dispatchTyped');
  246. $this->backend->updateCalendarObject($calendarId, $uri, $calData);
  247. $calendarObject = $this->backend->getCalendarObject($calendarId, $uri);
  248. $this->assertEquals($calData, $calendarObject['calendardata']);
  249. // delete the card
  250. $this->dispatcher->expects(self::atLeastOnce())
  251. ->method('dispatchTyped');
  252. $this->backend->deleteCalendarObject($calendarId, $uri);
  253. $calendarObjects = $this->backend->getCalendarObjects($calendarId);
  254. $this->assertCount(0, $calendarObjects);
  255. }
  256. public function testMultipleCalendarObjectsWithSameUID() {
  257. $this->expectException(\Sabre\DAV\Exception\BadRequest::class);
  258. $this->expectExceptionMessage('Calendar object with uid already exists in this calendar collection.');
  259. $calendarId = $this->createTestCalendar();
  260. $calData = <<<'EOD'
  261. BEGIN:VCALENDAR
  262. VERSION:2.0
  263. PRODID:ownCloud Calendar
  264. BEGIN:VEVENT
  265. CREATED;VALUE=DATE-TIME:20130910T125139Z
  266. UID:47d15e3ec8-1
  267. LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
  268. DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
  269. SUMMARY:Test Event
  270. DTSTART;VALUE=DATE-TIME:20130912T130000Z
  271. DTEND;VALUE=DATE-TIME:20130912T140000Z
  272. CLASS:PUBLIC
  273. END:VEVENT
  274. END:VCALENDAR
  275. EOD;
  276. $uri0 = static::getUniqueID('event');
  277. $uri1 = static::getUniqueID('event');
  278. $this->backend->createCalendarObject($calendarId, $uri0, $calData);
  279. $this->backend->createCalendarObject($calendarId, $uri1, $calData);
  280. }
  281. public function testMultiCalendarObjects() {
  282. $calendarId = $this->createTestCalendar();
  283. // create an event
  284. $calData = [];
  285. $calData[] = <<<'EOD'
  286. BEGIN:VCALENDAR
  287. VERSION:2.0
  288. PRODID:ownCloud Calendar
  289. BEGIN:VEVENT
  290. CREATED;VALUE=DATE-TIME:20130910T125139Z
  291. UID:47d15e3ec8-1
  292. LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
  293. DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
  294. SUMMARY:Test Event
  295. DTSTART;VALUE=DATE-TIME:20130912T130000Z
  296. DTEND;VALUE=DATE-TIME:20130912T140000Z
  297. CLASS:PUBLIC
  298. END:VEVENT
  299. END:VCALENDAR
  300. EOD;
  301. $calData[] = <<<'EOD'
  302. BEGIN:VCALENDAR
  303. VERSION:2.0
  304. PRODID:ownCloud Calendar
  305. BEGIN:VEVENT
  306. CREATED;VALUE=DATE-TIME:20130910T125139Z
  307. UID:47d15e3ec8-2
  308. LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
  309. DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
  310. SUMMARY:Test Event
  311. DTSTART;VALUE=DATE-TIME:20130912T130000Z
  312. DTEND;VALUE=DATE-TIME:20130912T140000Z
  313. CLASS:PUBLIC
  314. END:VEVENT
  315. END:VCALENDAR
  316. EOD;
  317. $calData[] = <<<'EOD'
  318. BEGIN:VCALENDAR
  319. VERSION:2.0
  320. PRODID:ownCloud Calendar
  321. BEGIN:VEVENT
  322. CREATED;VALUE=DATE-TIME:20130910T125139Z
  323. UID:47d15e3ec8-3
  324. LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
  325. DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
  326. SUMMARY:Test Event
  327. DTSTART;VALUE=DATE-TIME:20130912T130000Z
  328. DTEND;VALUE=DATE-TIME:20130912T140000Z
  329. CLASS:PUBLIC
  330. END:VEVENT
  331. END:VCALENDAR
  332. EOD;
  333. $uri0 = static::getUniqueID('card');
  334. $this->dispatcher->expects(self::atLeastOnce())
  335. ->method('dispatchTyped');
  336. $this->backend->createCalendarObject($calendarId, $uri0, $calData[0]);
  337. $uri1 = static::getUniqueID('card');
  338. $this->dispatcher->expects(self::atLeastOnce())
  339. ->method('dispatchTyped');
  340. $this->backend->createCalendarObject($calendarId, $uri1, $calData[1]);
  341. $uri2 = static::getUniqueID('card');
  342. $this->dispatcher->expects(self::atLeastOnce())
  343. ->method('dispatchTyped');
  344. $this->backend->createCalendarObject($calendarId, $uri2, $calData[2]);
  345. // get all the cards
  346. $calendarObjects = $this->backend->getCalendarObjects($calendarId);
  347. $this->assertCount(3, $calendarObjects);
  348. // get the cards
  349. $calendarObjects = $this->backend->getMultipleCalendarObjects($calendarId, [$uri1, $uri2]);
  350. $this->assertCount(2, $calendarObjects);
  351. foreach ($calendarObjects as $card) {
  352. $this->assertArrayHasKey('id', $card);
  353. $this->assertArrayHasKey('uri', $card);
  354. $this->assertArrayHasKey('lastmodified', $card);
  355. $this->assertArrayHasKey('etag', $card);
  356. $this->assertArrayHasKey('size', $card);
  357. $this->assertArrayHasKey('classification', $card);
  358. }
  359. usort($calendarObjects, function ($a, $b) {
  360. return $a['id'] - $b['id'];
  361. });
  362. $this->assertEquals($calData[1], $calendarObjects[0]['calendardata']);
  363. $this->assertEquals($calData[2], $calendarObjects[1]['calendardata']);
  364. // delete the card
  365. $this->dispatcher->expects(self::atLeastOnce())
  366. ->method('dispatchTyped');
  367. $this->backend->deleteCalendarObject($calendarId, $uri0);
  368. $this->dispatcher->expects(self::atLeastOnce())
  369. ->method('dispatchTyped');
  370. $this->backend->deleteCalendarObject($calendarId, $uri1);
  371. $this->dispatcher->expects(self::atLeastOnce())
  372. ->method('dispatchTyped');
  373. $this->backend->deleteCalendarObject($calendarId, $uri2);
  374. $calendarObjects = $this->backend->getCalendarObjects($calendarId);
  375. $this->assertCount(0, $calendarObjects);
  376. }
  377. /**
  378. * @dataProvider providesCalendarQueryParameters
  379. */
  380. public function testCalendarQuery($expectedEventsInResult, $propFilters, $compFilter) {
  381. $calendarId = $this->createTestCalendar();
  382. $events = [];
  383. $events[0] = $this->createEvent($calendarId, '20130912T130000Z', '20130912T140000Z');
  384. $events[1] = $this->createEvent($calendarId, '20130912T150000Z', '20130912T170000Z');
  385. $events[2] = $this->createEvent($calendarId, '20130912T173000Z', '20130912T220000Z');
  386. $events[3] = $this->createEvent($calendarId, '21130912T130000Z', '22130912T130000Z');
  387. $result = $this->backend->calendarQuery($calendarId, [
  388. 'name' => '',
  389. 'prop-filters' => $propFilters,
  390. 'comp-filters' => $compFilter
  391. ]);
  392. $expectedEventsInResult = array_map(function ($index) use ($events) {
  393. return $events[$index];
  394. }, $expectedEventsInResult);
  395. $this->assertEqualsCanonicalizing($expectedEventsInResult, $result);
  396. }
  397. public function testGetCalendarObjectByUID() {
  398. $calendarId = $this->createTestCalendar();
  399. $uri = static::getUniqueID('calobj');
  400. $calData = <<<'EOD'
  401. BEGIN:VCALENDAR
  402. VERSION:2.0
  403. PRODID:ownCloud Calendar
  404. BEGIN:VEVENT
  405. CREATED;VALUE=DATE-TIME:20130910T125139Z
  406. UID:47d15e3ec8
  407. LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
  408. DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
  409. SUMMARY:Test Event
  410. DTSTART;VALUE=DATE-TIME:20130912T130000Z
  411. DTEND;VALUE=DATE-TIME:20130912T140000Z
  412. CLASS:PUBLIC
  413. END:VEVENT
  414. END:VCALENDAR
  415. EOD;
  416. $this->backend->createCalendarObject($calendarId, $uri, $calData);
  417. $co = $this->backend->getCalendarObjectByUID(self::UNIT_TEST_USER, '47d15e3ec8');
  418. $this->assertNotNull($co);
  419. }
  420. public function providesCalendarQueryParameters() {
  421. return [
  422. 'all' => [[0, 1, 2, 3], [], []],
  423. 'only-todos' => [[], ['name' => 'VTODO'], []],
  424. 'only-events' => [[0, 1, 2, 3], [], [['name' => 'VEVENT', 'is-not-defined' => false, 'comp-filters' => [], 'time-range' => ['start' => null, 'end' => null], 'prop-filters' => []]],],
  425. 'start' => [[1, 2, 3], [], [['name' => 'VEVENT', 'is-not-defined' => false, 'comp-filters' => [], 'time-range' => ['start' => new DateTime('2013-09-12 14:00:00', new DateTimeZone('UTC')), 'end' => null], 'prop-filters' => []]],],
  426. 'end' => [[0], [], [['name' => 'VEVENT', 'is-not-defined' => false, 'comp-filters' => [], 'time-range' => ['start' => null, 'end' => new DateTime('2013-09-12 14:00:00', new DateTimeZone('UTC'))], 'prop-filters' => []]],],
  427. 'future' => [[3], [], [['name' => 'VEVENT', 'is-not-defined' => false, 'comp-filters' => [], 'time-range' => ['start' => new DateTime('2099-09-12 14:00:00', new DateTimeZone('UTC')), 'end' => null], 'prop-filters' => []]],],
  428. ];
  429. }
  430. public function testSyncSupport() {
  431. $calendarId = $this->createTestCalendar();
  432. // fist call without synctoken
  433. $changes = $this->backend->getChangesForCalendar($calendarId, '', 1);
  434. $syncToken = $changes['syncToken'];
  435. // add a change
  436. $event = $this->createEvent($calendarId, '20130912T130000Z', '20130912T140000Z');
  437. // look for changes
  438. $changes = $this->backend->getChangesForCalendar($calendarId, $syncToken, 1);
  439. $this->assertEquals($event, $changes['added'][0]);
  440. }
  441. public function testPublications() {
  442. $this->dispatcher->expects(self::atLeastOnce())
  443. ->method('dispatchTyped');
  444. $this->backend->createCalendar(self::UNIT_TEST_USER, 'Example', []);
  445. $calendarInfo = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER)[0];
  446. /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject $l10n */
  447. $l10n = $this->createMock(IL10N::class);
  448. $config = $this->createMock(IConfig::class);
  449. $logger = $this->createMock(\Psr\Log\LoggerInterface::class);
  450. $calendar = new Calendar($this->backend, $calendarInfo, $l10n, $config, $logger);
  451. $calendar->setPublishStatus(true);
  452. $this->assertNotEquals(false, $calendar->getPublishStatus());
  453. $publicCalendars = $this->backend->getPublicCalendars();
  454. $this->assertCount(1, $publicCalendars);
  455. $this->assertEquals(true, $publicCalendars[0]['{http://owncloud.org/ns}public']);
  456. $this->assertEquals('User\'s displayname', $publicCalendars[0]['{http://nextcloud.com/ns}owner-displayname']);
  457. $publicCalendarURI = $publicCalendars[0]['uri'];
  458. $publicCalendar = $this->backend->getPublicCalendar($publicCalendarURI);
  459. $this->assertEquals(true, $publicCalendar['{http://owncloud.org/ns}public']);
  460. $calendar->setPublishStatus(false);
  461. $this->assertEquals(false, $calendar->getPublishStatus());
  462. $this->expectException(NotFound::class);
  463. $this->backend->getPublicCalendar($publicCalendarURI);
  464. }
  465. public function testSubscriptions() {
  466. $id = $this->backend->createSubscription(self::UNIT_TEST_USER, 'Subscription', [
  467. '{http://calendarserver.org/ns/}source' => new Href('test-source'),
  468. '{http://apple.com/ns/ical/}calendar-color' => '#1C4587',
  469. '{http://calendarserver.org/ns/}subscribed-strip-todos' => ''
  470. ]);
  471. $subscriptions = $this->backend->getSubscriptionsForUser(self::UNIT_TEST_USER);
  472. $this->assertCount(1, $subscriptions);
  473. $this->assertEquals('#1C4587', $subscriptions[0]['{http://apple.com/ns/ical/}calendar-color']);
  474. $this->assertEquals(true, $subscriptions[0]['{http://calendarserver.org/ns/}subscribed-strip-todos']);
  475. $this->assertEquals($id, $subscriptions[0]['id']);
  476. $patch = new PropPatch([
  477. '{DAV:}displayname' => 'Unit test',
  478. '{http://apple.com/ns/ical/}calendar-color' => '#ac0606',
  479. ]);
  480. $this->backend->updateSubscription($id, $patch);
  481. $patch->commit();
  482. $subscriptions = $this->backend->getSubscriptionsForUser(self::UNIT_TEST_USER);
  483. $this->assertCount(1, $subscriptions);
  484. $this->assertEquals($id, $subscriptions[0]['id']);
  485. $this->assertEquals('Unit test', $subscriptions[0]['{DAV:}displayname']);
  486. $this->assertEquals('#ac0606', $subscriptions[0]['{http://apple.com/ns/ical/}calendar-color']);
  487. $this->backend->deleteSubscription($id);
  488. $subscriptions = $this->backend->getSubscriptionsForUser(self::UNIT_TEST_USER);
  489. $this->assertCount(0, $subscriptions);
  490. }
  491. public function providesSchedulingData() {
  492. $data = <<<EOS
  493. BEGIN:VCALENDAR
  494. VERSION:2.0
  495. PRODID:-//Sabre//Sabre VObject 3.5.0//EN
  496. CALSCALE:GREGORIAN
  497. METHOD:REQUEST
  498. BEGIN:VTIMEZONE
  499. TZID:Europe/Warsaw
  500. BEGIN:DAYLIGHT
  501. TZOFFSETFROM:+0100
  502. TZOFFSETTO:+0200
  503. TZNAME:CEST
  504. DTSTART:19700329T020000
  505. RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
  506. END:DAYLIGHT
  507. BEGIN:STANDARD
  508. TZOFFSETFROM:+0200
  509. TZOFFSETTO:+0100
  510. TZNAME:CET
  511. DTSTART:19701025T030000
  512. RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
  513. END:STANDARD
  514. END:VTIMEZONE
  515. BEGIN:VEVENT
  516. CREATED:20170320T131655Z
  517. LAST-MODIFIED:20170320T135019Z
  518. DTSTAMP:20170320T135019Z
  519. UID:7e908a6d-4c4e-48d7-bd62-59ab80fbf1a3
  520. SUMMARY:TEST Z pg_escape_bytea
  521. ORGANIZER;RSVP=TRUE;PARTSTAT=ACCEPTED;ROLE=CHAIR:mailto:k.klimczak@gromar.e
  522. u
  523. ATTENDEE;RSVP=TRUE;CN=Zuzanna Leszek;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICI
  524. PANT:mailto:z.leszek@gromar.eu
  525. ATTENDEE;RSVP=TRUE;CN=Marcin Pisarski;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTIC
  526. IPANT:mailto:m.pisarski@gromar.eu
  527. ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT:mailto:klimcz
  528. ak.k@gmail.com
  529. ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT:mailto:k_klim
  530. czak@tlen.pl
  531. DTSTART;TZID=Europe/Warsaw:20170325T150000
  532. DTEND;TZID=Europe/Warsaw:20170325T160000
  533. TRANSP:OPAQUE
  534. DESCRIPTION:Magiczna treść uzyskana za pomocą magicznego proszku.\n\nę
  535. żźćńłóÓŻŹĆŁĘ€śśśŚŚ\n \,\,))))))))\;\,\n
  536. __))))))))))))))\,\n \\|/ -\\(((((''''((((((((.\n -*-==///
  537. ///(('' . `))))))\,\n /|\\ ))| o \;-. '(((((
  538. \,(\,\n ( `| / ) \;))))'
  539. \,_))^\;(~\n | | | \,))((((_ _____-
  540. -----~~~-. %\,\;(\;(>'\;'~\n o_)\; \; )))(((` ~---
  541. ~ `:: \\ %%~~)(v\;(`('~\n \; ''''````
  542. `: `:::|\\\,__\,%% )\;`'\; ~\n | _
  543. ) / `:|`----' `-'\n ______/\\/~ |
  544. / /\n /~\;\;.____/\;\;' / ___--\
  545. ,-( `\;\;\;/\n / // _\;______\;'------~~~~~ /\;\;/\\ /\n
  546. // | | / \; \\\;\;\,\\\n (<_ | \;
  547. /'\,/-----' _>\n \\_| ||_
  548. //~\;~~~~~~~~~\n `\\_| (\,~~ -Tua Xiong\n
  549. \\~\\\n
  550. ~~\n\n
  551. SEQUENCE:1
  552. X-MOZ-GENERATION:1
  553. END:VEVENT
  554. END:VCALENDAR
  555. EOS;
  556. return [
  557. 'no data' => [''],
  558. 'failing on postgres' => [$data]
  559. ];
  560. }
  561. /**
  562. * @dataProvider providesSchedulingData
  563. * @param $objectData
  564. */
  565. public function testScheduling($objectData) {
  566. $this->backend->createSchedulingObject(self::UNIT_TEST_USER, 'Sample Schedule', $objectData);
  567. $sos = $this->backend->getSchedulingObjects(self::UNIT_TEST_USER);
  568. $this->assertCount(1, $sos);
  569. $so = $this->backend->getSchedulingObject(self::UNIT_TEST_USER, 'Sample Schedule');
  570. $this->assertNotNull($so);
  571. $this->backend->deleteSchedulingObject(self::UNIT_TEST_USER, 'Sample Schedule');
  572. $sos = $this->backend->getSchedulingObjects(self::UNIT_TEST_USER);
  573. $this->assertCount(0, $sos);
  574. }
  575. /**
  576. * @dataProvider providesCalDataForGetDenormalizedData
  577. */
  578. public function testGetDenormalizedData($expected, $key, $calData) {
  579. $actual = $this->backend->getDenormalizedData($calData);
  580. $this->assertEquals($expected, $actual[$key]);
  581. }
  582. public function providesCalDataForGetDenormalizedData() {
  583. return [
  584. 'first occurrence before unix epoch starts' => [0, 'firstOccurence', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:413F269B-B51B-46B1-AFB6-40055C53A4DC\r\nDTSTAMP:20160309T095056Z\r\nDTSTART;VALUE=DATE:16040222\r\nDTEND;VALUE=DATE:16040223\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:SUMMARY\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"],
  585. 'no first occurrence because yearly' => [null, 'firstOccurence', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:413F269B-B51B-46B1-AFB6-40055C53A4DC\r\nDTSTAMP:20160309T095056Z\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:SUMMARY\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"],
  586. 'last occurrence is max when only last VEVENT in group is weekly' => [(new DateTime(CalDavBackend::MAX_DATE))->getTimestamp(), 'lastOccurence', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.3.0//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nDTSTART;TZID=America/Los_Angeles:20200812T103000\r\nDTEND;TZID=America/Los_Angeles:20200812T110000\r\nDTSTAMP:20200927T180638Z\r\nUID:asdfasdfasdf@google.com\r\nRECURRENCE-ID;TZID=America/Los_Angeles:20200811T123000\r\nCREATED:20200626T181848Z\r\nLAST-MODIFIED:20200922T192707Z\r\nSUMMARY:Weekly 1:1\r\nTRANSP:OPAQUE\r\nEND:VEVENT\r\nBEGIN:VEVENT\r\nDTSTART;TZID=America/Los_Angeles:20200728T123000\r\nDTEND;TZID=America/Los_Angeles:20200728T130000\r\nEXDATE;TZID=America/Los_Angeles:20200818T123000\r\nRRULE:FREQ=WEEKLY;BYDAY=TU\r\nDTSTAMP:20200927T180638Z\r\nUID:asdfasdfasdf@google.com\r\nCREATED:20200626T181848Z\r\nDESCRIPTION:Setting up recurring time on our calendars\r\nLAST-MODIFIED:20200922T192707Z\r\nSUMMARY:Weekly 1:1\r\nTRANSP:OPAQUE\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"],
  587. 'first occurrence is found when not first VEVENT in group' => [(new DateTime('2020-09-01T110000', new DateTimeZone("America/Los_Angeles")))->getTimestamp(), 'firstOccurence', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.3.0//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nDTSTART;TZID=America/Los_Angeles:20201013T110000\r\nDTEND;TZID=America/Los_Angeles:20201013T120000\r\nDTSTAMP:20200927T180638Z\r\nUID:asdf0000@google.com\r\nRECURRENCE-ID;TZID=America/Los_Angeles:20201013T110000\r\nCREATED:20160330T034726Z\r\nLAST-MODIFIED:20200925T042014Z\r\nSTATUS:CONFIRMED\r\nTRANSP:OPAQUE\r\nEND:VEVENT\r\nBEGIN:VEVENT\r\nDTSTART;TZID=America/Los_Angeles:20200901T110000\r\nDTEND;TZID=America/Los_Angeles:20200901T120000\r\nRRULE:FREQ=WEEKLY;BYDAY=TU\r\nEXDATE;TZID=America/Los_Angeles:20200922T110000\r\nEXDATE;TZID=America/Los_Angeles:20200915T110000\r\nEXDATE;TZID=America/Los_Angeles:20200908T110000\r\nDTSTAMP:20200927T180638Z\r\nUID:asdf0000@google.com\r\nCREATED:20160330T034726Z\r\nLAST-MODIFIED:20200915T162810Z\r\nSTATUS:CONFIRMED\r\nTRANSP:OPAQUE\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"],
  588. 'CLASS:PRIVATE' => [CalDavBackend::CLASSIFICATION_PRIVATE, 'classification', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//dmfs.org//mimedir.icalendar//EN\r\nBEGIN:VTIMEZONE\r\nTZID:Europe/Berlin\r\nX-LIC-LOCATION:Europe/Berlin\r\nBEGIN:DAYLIGHT\r\nTZOFFSETFROM:+0100\r\nTZOFFSETTO:+0200\r\nTZNAME:CEST\r\nDTSTART:19700329T020000\r\nRRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU\r\nEND:DAYLIGHT\r\nBEGIN:STANDARD\r\nTZOFFSETFROM:+0200\r\nTZOFFSETTO:+0100\r\nTZNAME:CET\r\nDTSTART:19701025T030000\r\nRRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU\r\nEND:STANDARD\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nDTSTART;TZID=Europe/Berlin:20160419T130000\r\nSUMMARY:Test\r\nCLASS:PRIVATE\r\nTRANSP:OPAQUE\r\nSTATUS:CONFIRMED\r\nDTEND;TZID=Europe/Berlin:20160419T140000\r\nLAST-MODIFIED:20160419T074202Z\r\nDTSTAMP:20160419T074202Z\r\nCREATED:20160419T074202Z\r\nUID:2e468c48-7860-492e-bc52-92fa0daeeccf.1461051722310\r\nEND:VEVENT\r\nEND:VCALENDAR"],
  589. 'CLASS:PUBLIC' => [CalDavBackend::CLASSIFICATION_PUBLIC, 'classification', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//dmfs.org//mimedir.icalendar//EN\r\nBEGIN:VTIMEZONE\r\nTZID:Europe/Berlin\r\nX-LIC-LOCATION:Europe/Berlin\r\nBEGIN:DAYLIGHT\r\nTZOFFSETFROM:+0100\r\nTZOFFSETTO:+0200\r\nTZNAME:CEST\r\nDTSTART:19700329T020000\r\nRRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU\r\nEND:DAYLIGHT\r\nBEGIN:STANDARD\r\nTZOFFSETFROM:+0200\r\nTZOFFSETTO:+0100\r\nTZNAME:CET\r\nDTSTART:19701025T030000\r\nRRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU\r\nEND:STANDARD\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nDTSTART;TZID=Europe/Berlin:20160419T130000\r\nSUMMARY:Test\r\nCLASS:PUBLIC\r\nTRANSP:OPAQUE\r\nSTATUS:CONFIRMED\r\nDTEND;TZID=Europe/Berlin:20160419T140000\r\nLAST-MODIFIED:20160419T074202Z\r\nDTSTAMP:20160419T074202Z\r\nCREATED:20160419T074202Z\r\nUID:2e468c48-7860-492e-bc52-92fa0daeeccf.1461051722310\r\nEND:VEVENT\r\nEND:VCALENDAR"],
  590. 'CLASS:CONFIDENTIAL' => [CalDavBackend::CLASSIFICATION_CONFIDENTIAL, 'classification', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//dmfs.org//mimedir.icalendar//EN\r\nBEGIN:VTIMEZONE\r\nTZID:Europe/Berlin\r\nX-LIC-LOCATION:Europe/Berlin\r\nBEGIN:DAYLIGHT\r\nTZOFFSETFROM:+0100\r\nTZOFFSETTO:+0200\r\nTZNAME:CEST\r\nDTSTART:19700329T020000\r\nRRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU\r\nEND:DAYLIGHT\r\nBEGIN:STANDARD\r\nTZOFFSETFROM:+0200\r\nTZOFFSETTO:+0100\r\nTZNAME:CET\r\nDTSTART:19701025T030000\r\nRRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU\r\nEND:STANDARD\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nDTSTART;TZID=Europe/Berlin:20160419T130000\r\nSUMMARY:Test\r\nCLASS:CONFIDENTIAL\r\nTRANSP:OPAQUE\r\nSTATUS:CONFIRMED\r\nDTEND;TZID=Europe/Berlin:20160419T140000\r\nLAST-MODIFIED:20160419T074202Z\r\nDTSTAMP:20160419T074202Z\r\nCREATED:20160419T074202Z\r\nUID:2e468c48-7860-492e-bc52-92fa0daeeccf.1461051722310\r\nEND:VEVENT\r\nEND:VCALENDAR"],
  591. 'no class set -> public' => [CalDavBackend::CLASSIFICATION_PUBLIC, 'classification', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//dmfs.org//mimedir.icalendar//EN\r\nBEGIN:VTIMEZONE\r\nTZID:Europe/Berlin\r\nX-LIC-LOCATION:Europe/Berlin\r\nBEGIN:DAYLIGHT\r\nTZOFFSETFROM:+0100\r\nTZOFFSETTO:+0200\r\nTZNAME:CEST\r\nDTSTART:19700329T020000\r\nRRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU\r\nEND:DAYLIGHT\r\nBEGIN:STANDARD\r\nTZOFFSETFROM:+0200\r\nTZOFFSETTO:+0100\r\nTZNAME:CET\r\nDTSTART:19701025T030000\r\nRRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU\r\nEND:STANDARD\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nDTSTART;TZID=Europe/Berlin:20160419T130000\r\nSUMMARY:Test\r\nTRANSP:OPAQUE\r\nDTEND;TZID=Europe/Berlin:20160419T140000\r\nLAST-MODIFIED:20160419T074202Z\r\nDTSTAMP:20160419T074202Z\r\nCREATED:20160419T074202Z\r\nUID:2e468c48-7860-492e-bc52-92fa0daeeccf.1461051722310\r\nEND:VEVENT\r\nEND:VCALENDAR"],
  592. 'unknown class -> private' => [CalDavBackend::CLASSIFICATION_PRIVATE, 'classification', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//dmfs.org//mimedir.icalendar//EN\r\nBEGIN:VTIMEZONE\r\nTZID:Europe/Berlin\r\nX-LIC-LOCATION:Europe/Berlin\r\nBEGIN:DAYLIGHT\r\nTZOFFSETFROM:+0100\r\nTZOFFSETTO:+0200\r\nTZNAME:CEST\r\nDTSTART:19700329T020000\r\nRRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU\r\nEND:DAYLIGHT\r\nBEGIN:STANDARD\r\nTZOFFSETFROM:+0200\r\nTZOFFSETTO:+0100\r\nTZNAME:CET\r\nDTSTART:19701025T030000\r\nRRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU\r\nEND:STANDARD\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nDTSTART;TZID=Europe/Berlin:20160419T130000\r\nSUMMARY:Test\r\nCLASS:VERTRAULICH\r\nTRANSP:OPAQUE\r\nSTATUS:CONFIRMED\r\nDTEND;TZID=Europe/Berlin:20160419T140000\r\nLAST-MODIFIED:20160419T074202Z\r\nDTSTAMP:20160419T074202Z\r\nCREATED:20160419T074202Z\r\nUID:2e468c48-7860-492e-bc52-92fa0daeeccf.1461051722310\r\nEND:VEVENT\r\nEND:VCALENDAR"],
  593. ];
  594. }
  595. public function testCalendarSearch() {
  596. $calendarId = $this->createTestCalendar();
  597. $uri = static::getUniqueID('calobj');
  598. $calData = <<<EOD
  599. BEGIN:VCALENDAR
  600. VERSION:2.0
  601. PRODID:ownCloud Calendar
  602. BEGIN:VEVENT
  603. CREATED;VALUE=DATE-TIME:20130910T125139Z
  604. UID:47d15e3ec8
  605. LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
  606. DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
  607. SUMMARY:Test Event
  608. DTSTART;VALUE=DATE-TIME:20130912T130000Z
  609. DTEND;VALUE=DATE-TIME:20130912T140000Z
  610. CLASS:PUBLIC
  611. END:VEVENT
  612. END:VCALENDAR
  613. EOD;
  614. $this->backend->createCalendarObject($calendarId, $uri, $calData);
  615. $search1 = $this->backend->calendarSearch(self::UNIT_TEST_USER, [
  616. 'comps' => [
  617. 'VEVENT',
  618. 'VTODO'
  619. ],
  620. 'props' => [
  621. 'SUMMARY',
  622. 'LOCATION'
  623. ],
  624. 'search-term' => 'Test',
  625. ]);
  626. $this->assertEquals(count($search1), 1);
  627. // update the card
  628. $calData = <<<'EOD'
  629. BEGIN:VCALENDAR
  630. VERSION:2.0
  631. PRODID:ownCloud Calendar
  632. BEGIN:VEVENT
  633. CREATED;VALUE=DATE-TIME:20130910T125139Z
  634. UID:47d15e3ec8
  635. LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
  636. DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
  637. SUMMARY:123 Event 🙈
  638. DTSTART;VALUE=DATE-TIME:20130912T130000Z
  639. DTEND;VALUE=DATE-TIME:20130912T140000Z
  640. ATTENDEE;CN=test:mailto:foo@bar.com
  641. END:VEVENT
  642. END:VCALENDAR
  643. EOD;
  644. $this->backend->updateCalendarObject($calendarId, $uri, $calData);
  645. $search2 = $this->backend->calendarSearch(self::UNIT_TEST_USER, [
  646. 'comps' => [
  647. 'VEVENT',
  648. 'VTODO'
  649. ],
  650. 'props' => [
  651. 'SUMMARY',
  652. 'LOCATION'
  653. ],
  654. 'search-term' => 'Test',
  655. ]);
  656. $this->assertEquals(count($search2), 0);
  657. $search3 = $this->backend->calendarSearch(self::UNIT_TEST_USER, [
  658. 'comps' => [
  659. 'VEVENT',
  660. 'VTODO'
  661. ],
  662. 'props' => [
  663. 'SUMMARY',
  664. 'LOCATION'
  665. ],
  666. 'params' => [
  667. [
  668. 'property' => 'ATTENDEE',
  669. 'parameter' => 'CN'
  670. ]
  671. ],
  672. 'search-term' => 'Test',
  673. ]);
  674. $this->assertEquals(count($search3), 1);
  675. // t matches both summary and attendee's CN, but we want unique results
  676. $search4 = $this->backend->calendarSearch(self::UNIT_TEST_USER, [
  677. 'comps' => [
  678. 'VEVENT',
  679. 'VTODO'
  680. ],
  681. 'props' => [
  682. 'SUMMARY',
  683. 'LOCATION'
  684. ],
  685. 'params' => [
  686. [
  687. 'property' => 'ATTENDEE',
  688. 'parameter' => 'CN'
  689. ]
  690. ],
  691. 'search-term' => 't',
  692. ]);
  693. $this->assertEquals(count($search4), 1);
  694. $this->backend->deleteCalendarObject($calendarId, $uri);
  695. $search5 = $this->backend->calendarSearch(self::UNIT_TEST_USER, [
  696. 'comps' => [
  697. 'VEVENT',
  698. 'VTODO'
  699. ],
  700. 'props' => [
  701. 'SUMMARY',
  702. 'LOCATION'
  703. ],
  704. 'params' => [
  705. [
  706. 'property' => 'ATTENDEE',
  707. 'parameter' => 'CN'
  708. ]
  709. ],
  710. 'search-term' => 't',
  711. ]);
  712. $this->assertEquals(count($search5), 0);
  713. }
  714. /**
  715. * @dataProvider searchDataProvider
  716. */
  717. public function testSearch(bool $isShared, array $searchOptions, int $count) {
  718. $calendarId = $this->createTestCalendar();
  719. $uris = [];
  720. $calData = [];
  721. $uris[] = static::getUniqueID('calobj');
  722. $calData[] = <<<EOD
  723. BEGIN:VCALENDAR
  724. VERSION:2.0
  725. PRODID:Nextcloud Calendar
  726. BEGIN:VEVENT
  727. CREATED;VALUE=DATE-TIME:20130910T125139Z
  728. UID:47d15e3ec8-1
  729. LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
  730. DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
  731. SUMMARY:Test Event
  732. DTSTART;VALUE=DATE-TIME:20130912T130000Z
  733. DTEND;VALUE=DATE-TIME:20130912T140000Z
  734. CLASS:PUBLIC
  735. END:VEVENT
  736. END:VCALENDAR
  737. EOD;
  738. $uris[] = static::getUniqueID('calobj');
  739. $calData[] = <<<EOD
  740. BEGIN:VCALENDAR
  741. VERSION:2.0
  742. PRODID:Nextcloud Calendar
  743. BEGIN:VEVENT
  744. CREATED;VALUE=DATE-TIME:20130910T125139Z
  745. UID:47d15e3ec8-2
  746. LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
  747. DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
  748. SUMMARY:123
  749. LOCATION:Test
  750. DTSTART;VALUE=DATE-TIME:20130912T130000Z
  751. DTEND;VALUE=DATE-TIME:20130912T140000Z
  752. CLASS:PUBLIC
  753. END:VEVENT
  754. END:VCALENDAR
  755. EOD;
  756. $uris[] = static::getUniqueID('calobj');
  757. $calData[] = <<<EOD
  758. BEGIN:VCALENDAR
  759. VERSION:2.0
  760. PRODID:Nextcloud Calendar
  761. BEGIN:VEVENT
  762. CREATED;VALUE=DATE-TIME:20130910T125139Z
  763. UID:47d15e3ec8-3
  764. LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
  765. DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
  766. SUMMARY:123
  767. ATTENDEE;CN=test:mailto:foo@bar.com
  768. DTSTART;VALUE=DATE-TIME:20130912T130000Z
  769. DTEND;VALUE=DATE-TIME:20130912T140000Z
  770. CLASS:PRIVATE
  771. END:VEVENT
  772. END:VCALENDAR
  773. EOD;
  774. $uris[] = static::getUniqueID('calobj');
  775. $calData[] = <<<EOD
  776. BEGIN:VCALENDAR
  777. VERSION:2.0
  778. PRODID:Nextcloud Calendar
  779. BEGIN:VEVENT
  780. CREATED;VALUE=DATE-TIME:20130910T125139Z
  781. UID:47d15e3ec8-4
  782. LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
  783. DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
  784. SUMMARY:123
  785. ATTENDEE;CN=foobar:mailto:test@bar.com
  786. DTSTART;VALUE=DATE-TIME:20130912T130000Z
  787. DTEND;VALUE=DATE-TIME:20130912T140000Z
  788. CLASS:CONFIDENTIAL
  789. END:VEVENT
  790. END:VCALENDAR
  791. EOD;
  792. $uriCount = count($uris);
  793. for ($i = 0; $i < $uriCount; $i++) {
  794. $this->backend->createCalendarObject($calendarId,
  795. $uris[$i], $calData[$i]);
  796. }
  797. $calendarInfo = [
  798. 'id' => $calendarId,
  799. 'principaluri' => 'user1',
  800. '{http://owncloud.org/ns}owner-principal' => $isShared ? 'user2' : 'user1',
  801. ];
  802. $result = $this->backend->search($calendarInfo, 'Test',
  803. ['SUMMARY', 'LOCATION', 'ATTENDEE'], $searchOptions, null, null);
  804. $this->assertCount($count, $result);
  805. }
  806. public function searchDataProvider() {
  807. return [
  808. [false, [], 4],
  809. [true, ['timerange' => ['start' => new DateTime('2013-09-12 13:00:00'), 'end' => new DateTime('2013-09-12 14:00:00')]], 2],
  810. [true, ['timerange' => ['start' => new DateTime('2013-09-12 15:00:00'), 'end' => new DateTime('2013-09-12 16:00:00')]], 0],
  811. ];
  812. }
  813. public function testSameUriSameIdForDifferentCalendarTypes() {
  814. $calendarId = $this->createTestCalendar();
  815. $subscriptionId = $this->createTestSubscription();
  816. $uri = static::getUniqueID('calobj');
  817. $calData = <<<EOD
  818. BEGIN:VCALENDAR
  819. VERSION:2.0
  820. PRODID:ownCloud Calendar
  821. BEGIN:VEVENT
  822. CREATED;VALUE=DATE-TIME:20130910T125139Z
  823. UID:47d15e3ec8
  824. LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
  825. DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
  826. SUMMARY:Test Event
  827. DTSTART;VALUE=DATE-TIME:20130912T130000Z
  828. DTEND;VALUE=DATE-TIME:20130912T140000Z
  829. CLASS:PUBLIC
  830. END:VEVENT
  831. END:VCALENDAR
  832. EOD;
  833. $calData2 = <<<EOD
  834. BEGIN:VCALENDAR
  835. VERSION:2.0
  836. PRODID:ownCloud Calendar
  837. BEGIN:VEVENT
  838. CREATED;VALUE=DATE-TIME:20130910T125139Z
  839. UID:47d15e3ec8
  840. LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
  841. DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
  842. SUMMARY:Test Event 123
  843. DTSTART;VALUE=DATE-TIME:20130912T130000Z
  844. DTEND;VALUE=DATE-TIME:20130912T140000Z
  845. CLASS:PUBLIC
  846. END:VEVENT
  847. END:VCALENDAR
  848. EOD;
  849. $this->backend->createCalendarObject($calendarId, $uri, $calData);
  850. $this->backend->createCalendarObject($subscriptionId, $uri, $calData2, CalDavBackend::CALENDAR_TYPE_SUBSCRIPTION);
  851. $this->assertEquals($calData, $this->backend->getCalendarObject($calendarId, $uri, CalDavBackend::CALENDAR_TYPE_CALENDAR)['calendardata']);
  852. $this->assertEquals($calData2, $this->backend->getCalendarObject($subscriptionId, $uri, CalDavBackend::CALENDAR_TYPE_SUBSCRIPTION)['calendardata']);
  853. }
  854. public function testPurgeAllCachedEventsForSubscription() {
  855. $subscriptionId = $this->createTestSubscription();
  856. $uri = static::getUniqueID('calobj');
  857. $calData = <<<EOD
  858. BEGIN:VCALENDAR
  859. VERSION:2.0
  860. PRODID:ownCloud Calendar
  861. BEGIN:VEVENT
  862. CREATED;VALUE=DATE-TIME:20130910T125139Z
  863. UID:47d15e3ec8
  864. LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
  865. DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
  866. SUMMARY:Test Event
  867. DTSTART;VALUE=DATE-TIME:20130912T130000Z
  868. DTEND;VALUE=DATE-TIME:20130912T140000Z
  869. CLASS:PUBLIC
  870. END:VEVENT
  871. END:VCALENDAR
  872. EOD;
  873. $this->backend->createCalendarObject($subscriptionId, $uri, $calData, CalDavBackend::CALENDAR_TYPE_SUBSCRIPTION);
  874. $this->backend->purgeAllCachedEventsForSubscription($subscriptionId);
  875. $this->assertEquals(null, $this->backend->getCalendarObject($subscriptionId, $uri, CalDavBackend::CALENDAR_TYPE_SUBSCRIPTION));
  876. }
  877. public function testCalendarMovement() {
  878. $this->backend->createCalendar(self::UNIT_TEST_USER, 'Example', []);
  879. $this->assertCount(1, $this->backend->getCalendarsForUser(self::UNIT_TEST_USER));
  880. $calendarInfoUser = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER)[0];
  881. $this->backend->moveCalendar('Example', self::UNIT_TEST_USER, self::UNIT_TEST_USER1);
  882. $this->assertCount(0, $this->backend->getCalendarsForUser(self::UNIT_TEST_USER));
  883. $this->assertCount(1, $this->backend->getCalendarsForUser(self::UNIT_TEST_USER1));
  884. $calendarInfoUser1 = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER1)[0];
  885. $this->assertEquals($calendarInfoUser['id'], $calendarInfoUser1['id']);
  886. $this->assertEquals($calendarInfoUser['uri'], $calendarInfoUser1['uri']);
  887. }
  888. public function testSearchPrincipal(): void {
  889. $myPublic = <<<EOD
  890. BEGIN:VCALENDAR
  891. VERSION:2.0
  892. PRODID:-//dmfs.org//mimedir.icalendar//EN
  893. BEGIN:VTIMEZONE
  894. TZID:Europe/Berlin
  895. X-LIC-LOCATION:Europe/Berlin
  896. BEGIN:DAYLIGHT
  897. TZOFFSETFROM:+0100
  898. TZOFFSETTO:+0200
  899. TZNAME:CEST
  900. DTSTART:19700329T020000
  901. RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
  902. END:DAYLIGHT
  903. BEGIN:STANDARD
  904. TZOFFSETFROM:+0200
  905. TZOFFSETTO:+0100
  906. TZNAME:CET
  907. DTSTART:19701025T030000
  908. RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
  909. END:STANDARD
  910. END:VTIMEZONE
  911. BEGIN:VEVENT
  912. DTSTART;TZID=Europe/Berlin:20160419T130000
  913. SUMMARY:My Test (public)
  914. CLASS:PUBLIC
  915. TRANSP:OPAQUE
  916. STATUS:CONFIRMED
  917. DTEND;TZID=Europe/Berlin:20160419T140000
  918. LAST-MODIFIED:20160419T074202Z
  919. DTSTAMP:20160419T074202Z
  920. CREATED:20160419T074202Z
  921. UID:2e468c48-7860-492e-bc52-92fa0daeeccf.1461051722310-1
  922. END:VEVENT
  923. END:VCALENDAR
  924. EOD;
  925. $myPrivate = <<<EOD
  926. BEGIN:VCALENDAR
  927. VERSION:2.0
  928. PRODID:-//dmfs.org//mimedir.icalendar//EN
  929. BEGIN:VTIMEZONE
  930. TZID:Europe/Berlin
  931. X-LIC-LOCATION:Europe/Berlin
  932. BEGIN:DAYLIGHT
  933. TZOFFSETFROM:+0100
  934. TZOFFSETTO:+0200
  935. TZNAME:CEST
  936. DTSTART:19700329T020000
  937. RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
  938. END:DAYLIGHT
  939. BEGIN:STANDARD
  940. TZOFFSETFROM:+0200
  941. TZOFFSETTO:+0100
  942. TZNAME:CET
  943. DTSTART:19701025T030000
  944. RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
  945. END:STANDARD
  946. END:VTIMEZONE
  947. BEGIN:VEVENT
  948. DTSTART;TZID=Europe/Berlin:20160419T130000
  949. SUMMARY:My Test (private)
  950. CLASS:PRIVATE
  951. TRANSP:OPAQUE
  952. STATUS:CONFIRMED
  953. DTEND;TZID=Europe/Berlin:20160419T140000
  954. LAST-MODIFIED:20160419T074202Z
  955. DTSTAMP:20160419T074202Z
  956. CREATED:20160419T074202Z
  957. UID:2e468c48-7860-492e-bc52-92fa0daeeccf.1461051722310-2
  958. END:VEVENT
  959. END:VCALENDAR
  960. EOD;
  961. $myConfidential = <<<EOD
  962. BEGIN:VCALENDAR
  963. VERSION:2.0
  964. PRODID:-//dmfs.org//mimedir.icalendar//EN
  965. BEGIN:VTIMEZONE
  966. TZID:Europe/Berlin
  967. X-LIC-LOCATION:Europe/Berlin
  968. BEGIN:DAYLIGHT
  969. TZOFFSETFROM:+0100
  970. TZOFFSETTO:+0200
  971. TZNAME:CEST
  972. DTSTART:19700329T020000
  973. RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
  974. END:DAYLIGHT
  975. BEGIN:STANDARD
  976. TZOFFSETFROM:+0200
  977. TZOFFSETTO:+0100
  978. TZNAME:CET
  979. DTSTART:19701025T030000
  980. RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
  981. END:STANDARD
  982. END:VTIMEZONE
  983. BEGIN:VEVENT
  984. DTSTART;TZID=Europe/Berlin:20160419T130000
  985. SUMMARY:My Test (confidential)
  986. CLASS:CONFIDENTIAL
  987. TRANSP:OPAQUE
  988. STATUS:CONFIRMED
  989. DTEND;TZID=Europe/Berlin:20160419T140000
  990. LAST-MODIFIED:20160419T074202Z
  991. DTSTAMP:20160419T074202Z
  992. CREATED:20160419T074202Z
  993. UID:2e468c48-7860-492e-bc52-92fa0daeeccf.1461051722310-3
  994. END:VEVENT
  995. END:VCALENDAR
  996. EOD;
  997. $sharerPublic = <<<EOD
  998. BEGIN:VCALENDAR
  999. VERSION:2.0
  1000. PRODID:-//dmfs.org//mimedir.icalendar//EN
  1001. BEGIN:VTIMEZONE
  1002. TZID:Europe/Berlin
  1003. X-LIC-LOCATION:Europe/Berlin
  1004. BEGIN:DAYLIGHT
  1005. TZOFFSETFROM:+0100
  1006. TZOFFSETTO:+0200
  1007. TZNAME:CEST
  1008. DTSTART:19700329T020000
  1009. RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
  1010. END:DAYLIGHT
  1011. BEGIN:STANDARD
  1012. TZOFFSETFROM:+0200
  1013. TZOFFSETTO:+0100
  1014. TZNAME:CET
  1015. DTSTART:19701025T030000
  1016. RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
  1017. END:STANDARD
  1018. END:VTIMEZONE
  1019. BEGIN:VEVENT
  1020. DTSTART;TZID=Europe/Berlin:20160419T130000
  1021. SUMMARY:Sharer Test (public)
  1022. CLASS:PUBLIC
  1023. TRANSP:OPAQUE
  1024. STATUS:CONFIRMED
  1025. DTEND;TZID=Europe/Berlin:20160419T140000
  1026. LAST-MODIFIED:20160419T074202Z
  1027. DTSTAMP:20160419T074202Z
  1028. CREATED:20160419T074202Z
  1029. UID:2e468c48-7860-492e-bc52-92fa0daeeccf.1461051722310-4
  1030. END:VEVENT
  1031. END:VCALENDAR
  1032. EOD;
  1033. $sharerPrivate = <<<EOD
  1034. BEGIN:VCALENDAR
  1035. VERSION:2.0
  1036. PRODID:-//dmfs.org//mimedir.icalendar//EN
  1037. BEGIN:VTIMEZONE
  1038. TZID:Europe/Berlin
  1039. X-LIC-LOCATION:Europe/Berlin
  1040. BEGIN:DAYLIGHT
  1041. TZOFFSETFROM:+0100
  1042. TZOFFSETTO:+0200
  1043. TZNAME:CEST
  1044. DTSTART:19700329T020000
  1045. RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
  1046. END:DAYLIGHT
  1047. BEGIN:STANDARD
  1048. TZOFFSETFROM:+0200
  1049. TZOFFSETTO:+0100
  1050. TZNAME:CET
  1051. DTSTART:19701025T030000
  1052. RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
  1053. END:STANDARD
  1054. END:VTIMEZONE
  1055. BEGIN:VEVENT
  1056. DTSTART;TZID=Europe/Berlin:20160419T130000
  1057. SUMMARY:Sharer Test (private)
  1058. CLASS:PRIVATE
  1059. TRANSP:OPAQUE
  1060. STATUS:CONFIRMED
  1061. DTEND;TZID=Europe/Berlin:20160419T140000
  1062. LAST-MODIFIED:20160419T074202Z
  1063. DTSTAMP:20160419T074202Z
  1064. CREATED:20160419T074202Z
  1065. UID:2e468c48-7860-492e-bc52-92fa0daeeccf.1461051722310-5
  1066. END:VEVENT
  1067. END:VCALENDAR
  1068. EOD;
  1069. $sharerConfidential = <<<EOD
  1070. BEGIN:VCALENDAR
  1071. VERSION:2.0
  1072. PRODID:-//dmfs.org//mimedir.icalendar//EN
  1073. BEGIN:VTIMEZONE
  1074. TZID:Europe/Berlin
  1075. X-LIC-LOCATION:Europe/Berlin
  1076. BEGIN:DAYLIGHT
  1077. TZOFFSETFROM:+0100
  1078. TZOFFSETTO:+0200
  1079. TZNAME:CEST
  1080. DTSTART:19700329T020000
  1081. RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
  1082. END:DAYLIGHT
  1083. BEGIN:STANDARD
  1084. TZOFFSETFROM:+0200
  1085. TZOFFSETTO:+0100
  1086. TZNAME:CET
  1087. DTSTART:19701025T030000
  1088. RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
  1089. END:STANDARD
  1090. END:VTIMEZONE
  1091. BEGIN:VEVENT
  1092. DTSTART;TZID=Europe/Berlin:20160419T130000
  1093. SUMMARY:Sharer Test (confidential)
  1094. CLASS:CONFIDENTIAL
  1095. TRANSP:OPAQUE
  1096. STATUS:CONFIRMED
  1097. DTEND;TZID=Europe/Berlin:20160419T140000
  1098. LAST-MODIFIED:20160419T074202Z
  1099. DTSTAMP:20160419T074202Z
  1100. CREATED:20160419T074202Z
  1101. UID:2e468c48-7860-492e-bc52-92fa0daeeccf.1461051722310-6
  1102. END:VEVENT
  1103. END:VCALENDAR
  1104. EOD;
  1105. $l10n = $this->createMock(IL10N::class);
  1106. $l10n
  1107. ->expects($this->any())
  1108. ->method('t')
  1109. ->willReturnCallback(function ($text, $parameters = []) {
  1110. return vsprintf($text, $parameters);
  1111. });
  1112. $config = $this->createMock(IConfig::class);
  1113. $this->userManager->expects($this->any())
  1114. ->method('userExists')
  1115. ->willReturn(true);
  1116. $this->groupManager->expects($this->any())
  1117. ->method('groupExists')
  1118. ->willReturn(true);
  1119. $me = self::UNIT_TEST_USER;
  1120. $sharer = self::UNIT_TEST_USER1;
  1121. $this->backend->createCalendar($me, 'calendar-uri-me', []);
  1122. $this->backend->createCalendar($sharer, 'calendar-uri-sharer', []);
  1123. $myCalendars = $this->backend->getCalendarsForUser($me);
  1124. $this->assertCount(1, $myCalendars);
  1125. $sharerCalendars = $this->backend->getCalendarsForUser($sharer);
  1126. $this->assertCount(1, $sharerCalendars);
  1127. $logger = $this->createMock(\Psr\Log\LoggerInterface::class);
  1128. $sharerCalendar = new Calendar($this->backend, $sharerCalendars[0], $l10n, $config, $logger);
  1129. $this->backend->updateShares($sharerCalendar, [
  1130. [
  1131. 'href' => 'principal:' . $me,
  1132. 'readOnly' => false,
  1133. ],
  1134. ], []);
  1135. $this->assertCount(2, $this->backend->getCalendarsForUser($me));
  1136. $this->backend->createCalendarObject($myCalendars[0]['id'], 'event0.ics', $myPublic);
  1137. $this->backend->createCalendarObject($myCalendars[0]['id'], 'event1.ics', $myPrivate);
  1138. $this->backend->createCalendarObject($myCalendars[0]['id'], 'event2.ics', $myConfidential);
  1139. $this->backend->createCalendarObject($sharerCalendars[0]['id'], 'event3.ics', $sharerPublic);
  1140. $this->backend->createCalendarObject($sharerCalendars[0]['id'], 'event4.ics', $sharerPrivate);
  1141. $this->backend->createCalendarObject($sharerCalendars[0]['id'], 'event5.ics', $sharerConfidential);
  1142. $mySearchResults = $this->backend->searchPrincipalUri($me, 'Test', ['VEVENT'], ['SUMMARY'], []);
  1143. $sharerSearchResults = $this->backend->searchPrincipalUri($sharer, 'Test', ['VEVENT'], ['SUMMARY'], []);
  1144. $this->assertCount(4, $mySearchResults);
  1145. $this->assertCount(3, $sharerSearchResults);
  1146. $this->assertEquals($myPublic, $mySearchResults[0]['calendardata']);
  1147. $this->assertEquals($myPrivate, $mySearchResults[1]['calendardata']);
  1148. $this->assertEquals($myConfidential, $mySearchResults[2]['calendardata']);
  1149. $this->assertEquals($sharerPublic, $mySearchResults[3]['calendardata']);
  1150. $this->assertEquals($sharerPublic, $sharerSearchResults[0]['calendardata']);
  1151. $this->assertEquals($sharerPrivate, $sharerSearchResults[1]['calendardata']);
  1152. $this->assertEquals($sharerConfidential, $sharerSearchResults[2]['calendardata']);
  1153. }
  1154. /**
  1155. * @throws \OCP\DB\Exception
  1156. * @throws \Sabre\DAV\Exception\BadRequest
  1157. */
  1158. public function testPruneOutdatedSyncTokens(): void {
  1159. $calendarId = $this->createTestCalendar();
  1160. $uri = static::getUniqueID('calobj');
  1161. $calData = <<<EOD
  1162. BEGIN:VCALENDAR
  1163. VERSION:2.0
  1164. PRODID:Nextcloud Calendar
  1165. BEGIN:VEVENT
  1166. CREATED;VALUE=DATE-TIME:20130910T125139Z
  1167. UID:47d15e3ec8
  1168. LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
  1169. DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
  1170. SUMMARY:Test Event
  1171. DTSTART;VALUE=DATE-TIME:20130912T130000Z
  1172. DTEND;VALUE=DATE-TIME:20130912T140000Z
  1173. CLASS:PUBLIC
  1174. END:VEVENT
  1175. END:VCALENDAR
  1176. EOD;
  1177. $this->backend->createCalendarObject($calendarId, $uri, $calData);
  1178. // update the card
  1179. $calData = <<<'EOD'
  1180. BEGIN:VCALENDAR
  1181. VERSION:2.0
  1182. PRODID:Nextcloud Calendar
  1183. BEGIN:VEVENT
  1184. CREATED;VALUE=DATE-TIME:20130910T125139Z
  1185. UID:47d15e3ec8
  1186. LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
  1187. DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
  1188. SUMMARY:123 Event 🙈
  1189. DTSTART;VALUE=DATE-TIME:20130912T130000Z
  1190. DTEND;VALUE=DATE-TIME:20130912T140000Z
  1191. ATTENDEE;CN=test:mailto:foo@bar.com
  1192. END:VEVENT
  1193. END:VCALENDAR
  1194. EOD;
  1195. $this->backend->updateCalendarObject($calendarId, $uri, $calData);
  1196. $deleted = $this->backend->pruneOutdatedSyncTokens(0);
  1197. // At least one from the object creation and one from the object update
  1198. $this->assertGreaterThanOrEqual(2, $deleted);
  1199. $changes = $this->backend->getChangesForCalendar($calendarId, '5', 1);
  1200. $this->assertEmpty($changes['added']);
  1201. $this->assertEmpty($changes['modified']);
  1202. $this->assertEmpty($changes['deleted']);
  1203. }
  1204. }