Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnna <anna@nextcloud.com>2022-07-26 21:59:33 +0300
committerGitHub <noreply@github.com>2022-07-26 21:59:33 +0300
commit5671abd168b58348859acf068c25313992dfaa0b (patch)
treecf92d2a525fc3d9f7d2822431e5e168149c3d15f
parent072a0c6227819bbee32e8499b616c01884478388 (diff)
parent9eb276b20b051c31b349671600961c60d94ad175 (diff)
Merge pull request #33251 from cneukom/feature/birthday-calendar-reminder-settings
Birthday Calendar Reminder Setting
-rw-r--r--apps/dav/lib/CalDAV/BirthdayService.php71
-rw-r--r--apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php69
2 files changed, 99 insertions, 41 deletions
diff --git a/apps/dav/lib/CalDAV/BirthdayService.php b/apps/dav/lib/CalDAV/BirthdayService.php
index 6e60f9d932e..be6b0911538 100644
--- a/apps/dav/lib/CalDAV/BirthdayService.php
+++ b/apps/dav/lib/CalDAV/BirthdayService.php
@@ -14,6 +14,7 @@ declare(strict_types=1);
* @author Sven Strickroth <email@cs-ware.de>
* @author Thomas MΓΌller <thomas.mueller@tmit.eu>
* @author Valdnet <47037905+Valdnet@users.noreply.github.com>
+ * @author CΓ©dric Neukom <github@webguy.ch>
*
* @license AGPL-3.0
*
@@ -86,6 +87,9 @@ class BirthdayService {
$targetPrincipals = $this->getAllAffectedPrincipals($addressBookId);
$book = $this->cardDavBackEnd->getAddressBookById($addressBookId);
+ if ($book === null) {
+ return;
+ }
$targetPrincipals[] = $book['principaluri'];
$datesToSync = [
['postfix' => '', 'field' => 'BDAY'],
@@ -98,9 +102,14 @@ class BirthdayService {
continue;
}
+ $reminderOffset = $this->getReminderOffsetForUser($principalUri);
+
$calendar = $this->ensureCalendarExists($principalUri);
+ if ($calendar === null) {
+ return;
+ }
foreach ($datesToSync as $type) {
- $this->updateCalendar($cardUri, $cardData, $book, (int) $calendar['id'], $type);
+ $this->updateCalendar($cardUri, $cardData, $book, (int) $calendar['id'], $type, $reminderOffset);
}
}
}
@@ -148,12 +157,14 @@ class BirthdayService {
* @param $cardData
* @param $dateField
* @param $postfix
+ * @param $reminderOffset
* @return VCalendar|null
* @throws InvalidDataException
*/
- public function buildDateFromContact(string $cardData,
- string $dateField,
- string $postfix):?VCalendar {
+ public function buildDateFromContact(string $cardData,
+ string $dateField,
+ string $postfix,
+ ?string $reminderOffset):?VCalendar {
if (empty($cardData)) {
return null;
}
@@ -258,11 +269,13 @@ class BirthdayService {
if ($originalYear !== null) {
$vEvent->{'X-NEXTCLOUD-BC-YEAR'} = (string) $originalYear;
}
- $alarm = $vCal->createComponent('VALARM');
- $alarm->add($vCal->createProperty('TRIGGER', '-PT0M', ['VALUE' => 'DURATION']));
- $alarm->add($vCal->createProperty('ACTION', 'DISPLAY'));
- $alarm->add($vCal->createProperty('DESCRIPTION', $vEvent->{'SUMMARY'}));
- $vEvent->add($alarm);
+ if ($reminderOffset) {
+ $alarm = $vCal->createComponent('VALARM');
+ $alarm->add($vCal->createProperty('TRIGGER', $reminderOffset, ['VALUE' => 'DURATION']));
+ $alarm->add($vCal->createProperty('ACTION', 'DISPLAY'));
+ $alarm->add($vCal->createProperty('DESCRIPTION', $vEvent->{'SUMMARY'}));
+ $vEvent->add($alarm);
+ }
$vCal->add($vEvent);
return $vCal;
}
@@ -344,6 +357,7 @@ class BirthdayService {
* @param array $book
* @param int $calendarId
* @param array $type
+ * @param string $reminderOffset
* @throws InvalidDataException
* @throws \Sabre\DAV\Exception\BadRequest
*/
@@ -351,9 +365,10 @@ class BirthdayService {
string $cardData,
array $book,
int $calendarId,
- array $type):void {
+ array $type,
+ ?string $reminderOffset):void {
$objectUri = $book['uri'] . '-' . $cardUri . $type['postfix'] . '.ics';
- $calendarData = $this->buildDateFromContact($cardData, $type['field'], $type['postfix']);
+ $calendarData = $this->buildDateFromContact($cardData, $type['field'], $type['postfix'], $reminderOffset);
$existing = $this->calDavBackEnd->getCalendarObject($calendarId, $objectUri);
if ($calendarData === null) {
if ($existing !== null) {
@@ -394,14 +409,27 @@ class BirthdayService {
}
/**
+ * Extracts the userId part of a principal
+ *
+ * @param string $userPrincipal
+ * @return string|null
+ */
+ private function principalToUserId(string $userPrincipal):?string {
+ if (substr($userPrincipal, 0, 17) === 'principals/users/') {
+ return substr($userPrincipal, 17);
+ }
+ return null;
+ }
+
+ /**
* Checks if the user opted-out of birthday calendars
*
* @param string $userPrincipal The user principal to check for
* @return bool
*/
private function isUserEnabled(string $userPrincipal):bool {
- if (strpos($userPrincipal, 'principals/users/') === 0) {
- $userId = substr($userPrincipal, 17);
+ $userId = $this->principalToUserId($userPrincipal);
+ if ($userId !== null) {
$isEnabled = $this->config->getUserValue($userId, 'dav', 'generateBirthdayCalendar', 'yes');
return $isEnabled === 'yes';
}
@@ -411,6 +439,23 @@ class BirthdayService {
}
/**
+ * Get the reminder offset value for a user. This is a duration string (e.g.
+ * PT9H) or null if no reminder is wanted.
+ *
+ * @param string $userPrincipal
+ * @return string|null
+ */
+ private function getReminderOffsetForUser(string $userPrincipal):?string {
+ $userId = $this->principalToUserId($userPrincipal);
+ if ($userId !== null) {
+ return $this->config->getUserValue($userId, 'dav', 'birthdayCalendarReminderOffset', 'PT9H') ?: null;
+ }
+
+ // not sure how we got here, just be on the safe side and return the default value
+ return 'PT9H';
+ }
+
+ /**
* Formats title of Birthday event
*
* @param string $field Field name like BDAY, ANNIVERSARY, ...
diff --git a/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php b/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php
index bb45c88b10d..188b82843cd 100644
--- a/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php
+++ b/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php
@@ -34,6 +34,7 @@ use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IL10N;
use Sabre\VObject\Component\VCalendar;
+use Sabre\VObject\Property\ICalendar\Duration;
use Sabre\VObject\Reader;
use Test\TestCase;
@@ -82,11 +83,12 @@ class BirthdayServiceTest extends TestCase {
* @param string $expectedFieldType
* @param string $expectedUnknownYear
* @param string $expectedOriginalYear
+ * @param string|null $expectedReminder
* @param string | null $data
*/
- public function testBuildBirthdayFromContact($expectedSummary, $expectedDTStart, $expectedFieldType, $expectedUnknownYear, $expectedOriginalYear, $data, $fieldType, $prefix, $supports4Bytes) {
+ public function testBuildBirthdayFromContact($expectedSummary, $expectedDTStart, $expectedFieldType, $expectedUnknownYear, $expectedOriginalYear, $expectedReminder, $data, $fieldType, $prefix, $supports4Bytes, $configuredReminder) {
$this->dbConnection->method('supports4ByteText')->willReturn($supports4Bytes);
- $cal = $this->service->buildDateFromContact($data, $fieldType, $prefix);
+ $cal = $this->service->buildDateFromContact($data, $fieldType, $prefix, $configuredReminder);
if ($expectedSummary === null) {
$this->assertNull($cal);
@@ -104,6 +106,11 @@ class BirthdayServiceTest extends TestCase {
$this->assertEquals($expectedOriginalYear, $cal->VEVENT->{'X-NEXTCLOUD-BC-YEAR'}->getValue());
}
+ if ($expectedReminder) {
+ $this->assertEquals($expectedReminder, $cal->VEVENT->VALARM->TRIGGER->getValue());
+ $this->assertEquals('DURATION', $cal->VEVENT->VALARM->TRIGGER->getValueType());
+ }
+
$this->assertEquals('TRANSPARENT', $cal->VEVENT->TRANSP->getValue());
}
}
@@ -227,10 +234,13 @@ class BirthdayServiceTest extends TestCase {
->with('dav', 'generateBirthdayCalendar', 'yes')
->willReturn('yes');
- $this->config->expects($this->once())
+ $this->config->expects($this->exactly(2))
->method('getUserValue')
- ->with('user01', 'dav', 'generateBirthdayCalendar', 'yes')
- ->willReturn('yes');
+ ->withConsecutive(
+ ['user01', 'dav', 'generateBirthdayCalendar', 'yes'],
+ ['user01', 'dav', 'birthdayCalendarReminderOffset', 'PT9H'],
+ )
+ ->willReturnOnConsecutiveCalls('yes', 'PT9H');
$this->cardDav->expects($this->once())->method('getAddressBookById')
->with(666)
@@ -402,29 +412,32 @@ class BirthdayServiceTest extends TestCase {
public function providesVCards() {
return [
- // $expectedSummary, $expectedDTStart, $expectedFieldType, $expectedUnknownYear, $expectedOriginalYear, $data, $fieldType, $prefix, $supports4Byte
- [null, null, null, null, null, 'yasfewf', '', '', true],
- [null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nEND:VCARD\r\n", 'BDAY', '', true],
- [null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:\r\nEND:VCARD\r\n", 'BDAY', '', true],
- [null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:someday\r\nEND:VCARD\r\n", 'BDAY', '', true],
- ['πŸŽ‚ 12345 (1900)', '19700101', 'BDAY', '0', '1900', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19000101\r\nEND:VCARD\r\n", 'BDAY', '', true],
- ['πŸŽ‚ 12345 (1900)', '19701231', 'BDAY', '0', '1900', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', true],
- ['Death of 12345 (1900)', '19701231', 'DEATHDATE', '0', '1900', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nDEATHDATE:19001231\r\nEND:VCARD\r\n", 'DEATHDATE', '-death', true],
- ['Death of 12345 (1900)', '19701231', 'DEATHDATE', '0', '1900', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nDEATHDATE:19001231\r\nEND:VCARD\r\n", 'DEATHDATE', '-death', false],
- ['πŸ’ 12345 (1900)', '19701231', 'ANNIVERSARY', '0', '1900', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nANNIVERSARY:19001231\r\nEND:VCARD\r\n", 'ANNIVERSARY', '-anniversary', true],
- ['12345 (⚭1900)', '19701231', 'ANNIVERSARY', '0', '1900', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nANNIVERSARY:19001231\r\nEND:VCARD\r\n", 'ANNIVERSARY', '-anniversary', false],
- ['πŸŽ‚ 12345', '19701231', 'BDAY', '1', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:--1231\r\nEND:VCARD\r\n", 'BDAY', '', true],
- ['πŸŽ‚ 12345', '19701231', 'BDAY', '1', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY;X-APPLE-OMIT-YEAR=1604:16041231\r\nEND:VCARD\r\n", 'BDAY', '', true],
- [null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:;VALUE=text:circa 1800\r\nEND:VCARD\r\n", 'BDAY', '', true],
- [null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nN:12345;;;;\r\nBDAY:20031231\r\nEND:VCARD\r\n", 'BDAY', '', true],
- ['πŸŽ‚ 12345 (900)', '19701231', 'BDAY', '0', '900', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:09001231\r\nEND:VCARD\r\n", 'BDAY', '', true],
- ['12345 (*1900)', '19700101', 'BDAY', '0', '1900', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19000101\r\nEND:VCARD\r\n", 'BDAY', '', false],
- ['12345 (*1900)', '19701231', 'BDAY', '0', '1900', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', false],
- ['12345 *', '19701231', 'BDAY', '1', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:--1231\r\nEND:VCARD\r\n", 'BDAY', '', false],
- ['12345 *', '19701231', 'BDAY', '1', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY;X-APPLE-OMIT-YEAR=1604:16041231\r\nEND:VCARD\r\n", 'BDAY', '', false],
- [null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:;VALUE=text:circa 1800\r\nEND:VCARD\r\n", 'BDAY', '', false],
- [null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nN:12345;;;;\r\nBDAY:20031231\r\nEND:VCARD\r\n", 'BDAY', '', false],
- ['12345 (*900)', '19701231', 'BDAY', '0', '900', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:09001231\r\nEND:VCARD\r\n", 'BDAY', '', false],
+ // $expectedSummary, $expectedDTStart, $expectedFieldType, $expectedUnknownYear, $expectedOriginalYear, $expectedReminder, $data, $fieldType, $prefix, $supports4Byte, $configuredReminder
+ [null, null, null, null, null, null, 'yasfewf', '', '', true, null],
+ [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
+ [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
+ [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:someday\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
+ ['πŸŽ‚ 12345 (1900)', '19700101', 'BDAY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19000101\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
+ ['πŸŽ‚ 12345 (1900)', '19701231', 'BDAY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
+ ['Death of 12345 (1900)', '19701231', 'DEATHDATE', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nDEATHDATE:19001231\r\nEND:VCARD\r\n", 'DEATHDATE', '-death', true, null],
+ ['Death of 12345 (1900)', '19701231', 'DEATHDATE', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nDEATHDATE:19001231\r\nEND:VCARD\r\n", 'DEATHDATE', '-death', false, null],
+ ['πŸ’ 12345 (1900)', '19701231', 'ANNIVERSARY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nANNIVERSARY:19001231\r\nEND:VCARD\r\n", 'ANNIVERSARY', '-anniversary', true, null],
+ ['12345 (⚭1900)', '19701231', 'ANNIVERSARY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nANNIVERSARY:19001231\r\nEND:VCARD\r\n", 'ANNIVERSARY', '-anniversary', false, null],
+ ['πŸŽ‚ 12345', '19701231', 'BDAY', '1', null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:--1231\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
+ ['πŸŽ‚ 12345', '19701231', 'BDAY', '1', null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY;X-APPLE-OMIT-YEAR=1604:16041231\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
+ [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:;VALUE=text:circa 1800\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
+ [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nN:12345;;;;\r\nBDAY:20031231\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
+ ['πŸŽ‚ 12345 (900)', '19701231', 'BDAY', '0', '900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:09001231\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
+ ['12345 (*1900)', '19700101', 'BDAY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19000101\r\nEND:VCARD\r\n", 'BDAY', '', false, null],
+ ['12345 (*1900)', '19701231', 'BDAY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', false, null],
+ ['12345 *', '19701231', 'BDAY', '1', null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:--1231\r\nEND:VCARD\r\n", 'BDAY', '', false, null],
+ ['12345 *', '19701231', 'BDAY', '1', null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY;X-APPLE-OMIT-YEAR=1604:16041231\r\nEND:VCARD\r\n", 'BDAY', '', false, null],
+ [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:;VALUE=text:circa 1800\r\nEND:VCARD\r\n", 'BDAY', '', false, null],
+ [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nN:12345;;;;\r\nBDAY:20031231\r\nEND:VCARD\r\n", 'BDAY', '', false, null],
+ ['12345 (*900)', '19701231', 'BDAY', '0', '900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:09001231\r\nEND:VCARD\r\n", 'BDAY', '', false, null],
+ ['12345 (*1900)', '19701231', 'BDAY', '0', '1900', 'PT9H', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', false, 'PT9H'],
+ ['12345 (*1900)', '19701231', 'BDAY', '0', '1900', '-PT15H', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', false, '-PT15H'],
+ ['12345 (*1900)', '19701231', 'BDAY', '0', '1900', '-P6DT15H', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', false, '-P6DT15H'],
];
}
}