From 5cd90d41162d4d33d397c7c42e86a38168ec87ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Fri, 30 Sep 2016 10:29:27 +0200 Subject: [PATCH] [9.2] Sync deathdate and anniversary to birthday calendar (#25655) * Sync deathdate and anniversary to birthday calendar (which should be renamed maybe) * Sync deathdate and anniversary to birthday calendar (which should be renamed maybe) Signed-off-by: Roeland Jago Douma --- apps/dav/lib/CalDAV/BirthdayService.php | 65 ++++++++++++------- .../unit/CardDAV/BirthdayServiceTest.php | 55 ++++++++++------ 2 files changed, 77 insertions(+), 43 deletions(-) diff --git a/apps/dav/lib/CalDAV/BirthdayService.php b/apps/dav/lib/CalDAV/BirthdayService.php index 71f4940a2c..bf26aec537 100644 --- a/apps/dav/lib/CalDAV/BirthdayService.php +++ b/apps/dav/lib/CalDAV/BirthdayService.php @@ -62,28 +62,19 @@ class BirthdayService { * @param string $cardData */ public function onCardChanged($addressBookId, $cardUri, $cardData) { - $targetPrincipals = $this->getAllAffectedPrincipals($addressBookId); $book = $this->cardDavBackEnd->getAddressBookById($addressBookId); $targetPrincipals[] = $book['principaluri']; + $datesToSync = [ + ['postfix' => '', 'field' => 'BDAY', 'symbol' => '*'], + ['postfix' => '-death', 'field' => 'DEATHDATE', 'symbol' => "†"], + ['postfix' => '-anniversary', 'field' => 'ANNIVERSARY', 'symbol' => "⚭"], + ]; foreach ($targetPrincipals as $principalUri) { $calendar = $this->ensureCalendarExists($principalUri); - $objectUri = $book['uri'] . '-' . $cardUri. '.ics'; - $calendarData = $this->buildBirthdayFromContact($cardData); - $existing = $this->calDavBackEnd->getCalendarObject($calendar['id'], $objectUri); - if (is_null($calendarData)) { - if (!is_null($existing)) { - $this->calDavBackEnd->deleteCalendarObject($calendar['id'], $objectUri); - } - } else { - if (is_null($existing)) { - $this->calDavBackEnd->createCalendarObject($calendar['id'], $objectUri, $calendarData->serialize()); - } else { - if ($this->birthdayEvenChanged($existing['calendardata'], $calendarData)) { - $this->calDavBackEnd->updateCalendarObject($calendar['id'], $objectUri, $calendarData->serialize()); - } - } + foreach ($datesToSync as $type) { + $this->updateCalendar($cardUri, $cardData, $book, $calendar['id'], $type); } } } @@ -98,8 +89,10 @@ class BirthdayService { $targetPrincipals[] = $book['principaluri']; foreach ($targetPrincipals as $principalUri) { $calendar = $this->ensureCalendarExists($principalUri); - $objectUri = $book['uri'] . '-' . $cardUri . '.ics'; - $this->calDavBackEnd->deleteCalendarObject($calendar['id'], $objectUri); + foreach (['', '-death', '-anniversary'] as $tag) { + $objectUri = $book['uri'] . '-' . $cardUri . $tag .'.ics'; + $this->calDavBackEnd->deleteCalendarObject($calendar['id'], $objectUri); + } } } @@ -124,9 +117,11 @@ class BirthdayService { /** * @param string $cardData + * @param string $dateField + * @param string $summarySymbol * @return null|VCalendar */ - public function buildBirthdayFromContact($cardData) { + public function buildDateFromContact($cardData, $dateField, $summarySymbol) { if (empty($cardData)) { return null; } @@ -136,10 +131,10 @@ class BirthdayService { return null; } - if (!isset($doc->BDAY)) { + if (!isset($doc->{$dateField})) { return null; } - $birthday = $doc->BDAY; + $birthday = $doc->{$dateField}; if (!(string)$birthday) { return null; } @@ -168,7 +163,7 @@ class BirthdayService { $vEvent->DTEND['VALUE'] = 'DATE'; $vEvent->{'UID'} = $doc->UID; $vEvent->{'RRULE'} = 'FREQ=YEARLY'; - $vEvent->{'SUMMARY'} = $title . ' (*' . $date->format('Y') . ')'; + $vEvent->{'SUMMARY'} = $title . ' (' . $summarySymbol . $date->format('Y') . ')'; $vEvent->{'TRANSP'} = 'TRANSPARENT'; $alarm = $vCal->createComponent('VALARM'); $alarm->add($vCal->createProperty('TRIGGER', '-PT0M', ['VALUE' => 'DURATION'])); @@ -233,4 +228,30 @@ class BirthdayService { return array_values(array_unique($targetPrincipals, SORT_STRING)); } + /** + * @param string $cardUri + * @param string $cardData + * @param array $book + * @param int $calendarId + * @param string $type + */ + private function updateCalendar($cardUri, $cardData, $book, $calendarId, $type) { + $objectUri = $book['uri'] . '-' . $cardUri . $type['postfix'] . '.ics'; + $calendarData = $this->buildDateFromContact($cardData, $type['field'], $type['symbol']); + $existing = $this->calDavBackEnd->getCalendarObject($calendarId, $objectUri); + if (is_null($calendarData)) { + if (!is_null($existing)) { + $this->calDavBackEnd->deleteCalendarObject($calendarId, $objectUri); + } + } else { + if (is_null($existing)) { + $this->calDavBackEnd->createCalendarObject($calendarId, $objectUri, $calendarData->serialize()); + } else { + if ($this->birthdayEvenChanged($existing['calendardata'], $calendarData)) { + $this->calDavBackEnd->updateCalendarObject($calendarId, $objectUri, $calendarData->serialize()); + } + } + } + } + } diff --git a/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php b/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php index 7c772184fe..40a6330ddb 100644 --- a/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php +++ b/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php @@ -41,16 +41,16 @@ class BirthdayServiceTest extends TestCase { /** @var CardDavBackend | \PHPUnit_Framework_MockObject_MockObject */ private $cardDav; /** @var GroupPrincipalBackend | \PHPUnit_Framework_MockObject_MockObject */ - private $groupPrincialBackend; + private $groupPrincipalBackend; public function setUp() { parent::setUp(); - $this->calDav = $this->getMockBuilder('OCA\DAV\CalDAV\CalDavBackend')->disableOriginalConstructor()->getMock(); - $this->cardDav = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend')->disableOriginalConstructor()->getMock(); - $this->groupPrincialBackend = $this->getMockBuilder('OCA\DAV\DAV\GroupPrincipalBackend')->disableOriginalConstructor()->getMock(); + $this->calDav = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock(); + $this->cardDav = $this->getMockBuilder(CardDavBackend::class)->disableOriginalConstructor()->getMock(); + $this->groupPrincipalBackend = $this->getMockBuilder(GroupPrincipalBackend::class)->disableOriginalConstructor()->getMock(); - $this->service = new BirthdayService($this->calDav, $this->cardDav, $this->groupPrincialBackend); + $this->service = new BirthdayService($this->calDav, $this->cardDav, $this->groupPrincipalBackend); } /** @@ -59,7 +59,7 @@ class BirthdayServiceTest extends TestCase { * @param string | null $data */ public function testBuildBirthdayFromContact($nullExpected, $data) { - $cal = $this->service->buildBirthdayFromContact($data); + $cal = $this->service->buildDateFromContact($data, 'BDAY', '*'); if ($nullExpected) { $this->assertNull($cal); } else { @@ -83,7 +83,9 @@ class BirthdayServiceTest extends TestCase { ->willReturn([ 'id' => 1234 ]); - $this->calDav->expects($this->once())->method('deleteCalendarObject')->with(1234, 'default-gump.vcf.ics'); + $this->calDav->expects($this->at(1))->method('deleteCalendarObject')->with(1234, 'default-gump.vcf.ics'); + $this->calDav->expects($this->at(2))->method('deleteCalendarObject')->with(1234, 'default-gump.vcf-death.ics'); + $this->calDav->expects($this->at(3))->method('deleteCalendarObject')->with(1234, 'default-gump.vcf-anniversary.ics'); $this->cardDav->expects($this->once())->method('getShares')->willReturn([]); $this->service->onCardDeleted(666, 'gump.vcf'); @@ -107,26 +109,37 @@ class BirthdayServiceTest extends TestCase { $this->cardDav->expects($this->once())->method('getShares')->willReturn([]); /** @var BirthdayService | \PHPUnit_Framework_MockObject_MockObject $service */ - $service = $this->getMockBuilder('\OCA\DAV\CalDAV\BirthdayService') - ->setMethods(['buildBirthdayFromContact', 'birthdayEvenChanged']) - ->setConstructorArgs([$this->calDav, $this->cardDav, $this->groupPrincialBackend]) + $service = $this->getMockBuilder(BirthdayService::class) + ->setMethods(['buildDateFromContact', 'birthdayEvenChanged']) + ->setConstructorArgs([$this->calDav, $this->cardDav, $this->groupPrincipalBackend]) ->getMock(); if ($expectedOp === 'delete') { - $this->calDav->expects($this->once())->method('getCalendarObject')->willReturn(''); - $service->expects($this->once())->method('buildBirthdayFromContact')->willReturn(null); - $this->calDav->expects($this->once())->method('deleteCalendarObject')->with(1234, 'default-gump.vcf.ics'); + $this->calDav->expects($this->exactly(3))->method('getCalendarObject')->willReturn(''); + $service->expects($this->exactly(3))->method('buildDateFromContact')->willReturn(null); + $this->calDav->expects($this->exactly(3))->method('deleteCalendarObject')->withConsecutive( + [1234, 'default-gump.vcf.ics'], + [1234, 'default-gump.vcf-death.ics'], + [1234, 'default-gump.vcf-anniversary.ics'] + ); } if ($expectedOp === 'create') { - $service->expects($this->once())->method('buildBirthdayFromContact')->willReturn(new VCalendar()); - $this->calDav->expects($this->once())->method('createCalendarObject')->with(1234, 'default-gump.vcf.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nCALSCALE:GREGORIAN\r\nEND:VCALENDAR\r\n"); + $service->expects($this->exactly(3))->method('buildDateFromContact')->willReturn(new VCalendar()); + $this->calDav->expects($this->exactly(3))->method('createCalendarObject')->withConsecutive( + [1234, 'default-gump.vcf.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nCALSCALE:GREGORIAN\r\nEND:VCALENDAR\r\n"], + [1234, 'default-gump.vcf-death.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nCALSCALE:GREGORIAN\r\nEND:VCALENDAR\r\n"], + [1234, 'default-gump.vcf-anniversary.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nCALSCALE:GREGORIAN\r\nEND:VCALENDAR\r\n"] + ); } if ($expectedOp === 'update') { - $service->expects($this->once())->method('buildBirthdayFromContact')->willReturn(new VCalendar()); - $service->expects($this->once())->method('birthdayEvenChanged')->willReturn(true); - $this->calDav->expects($this->once())->method('getCalendarObject')->willReturn([ - 'calendardata' => '']); - $this->calDav->expects($this->once())->method('updateCalendarObject')->with(1234, 'default-gump.vcf.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nCALSCALE:GREGORIAN\r\nEND:VCALENDAR\r\n"); + $service->expects($this->exactly(3))->method('buildDateFromContact')->willReturn(new VCalendar()); + $service->expects($this->exactly(3))->method('birthdayEvenChanged')->willReturn(true); + $this->calDav->expects($this->exactly(3))->method('getCalendarObject')->willReturn(['calendardata' => '']); + $this->calDav->expects($this->exactly(3))->method('updateCalendarObject')->withConsecutive( + [1234, 'default-gump.vcf.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nCALSCALE:GREGORIAN\r\nEND:VCALENDAR\r\n"], + [1234, 'default-gump.vcf-death.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nCALSCALE:GREGORIAN\r\nEND:VCALENDAR\r\n"], + [1234, 'default-gump.vcf-anniversary.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nCALSCALE:GREGORIAN\r\nEND:VCALENDAR\r\n"] + ); } $service->onCardChanged(666, 'gump.vcf', ''); @@ -162,7 +175,7 @@ class BirthdayServiceTest extends TestCase { '{http://owncloud.org/ns}principal' => 'principals/groups/users' ], ]); - $this->groupPrincialBackend->expects($this->once())->method('getGroupMemberSet') + $this->groupPrincipalBackend->expects($this->once())->method('getGroupMemberSet') ->willReturn([ [ 'uri' => 'principals/users/user01',