2016-02-03 09:43:45 -05:00
< ? php
2019-12-03 13:57:53 -05:00
2019-08-21 04:35:17 -04:00
declare ( strict_types = 1 );
2019-12-03 13:57:53 -05:00
2016-02-03 09:43:45 -05:00
/**
2024-05-27 11:39:07 -04:00
* SPDX - FileCopyrightText : 2019 Nextcloud GmbH and Nextcloud contributors
* SPDX - FileCopyrightText : 2016 ownCloud , Inc .
* SPDX - License - Identifier : AGPL - 3.0 - only
2016-02-03 09:43:45 -05:00
*/
namespace OCA\DAV\CalDAV ;
use Exception ;
use OCA\DAV\CardDAV\CardDavBackend ;
2016-03-23 09:12:50 -04:00
use OCA\DAV\DAV\GroupPrincipalBackend ;
2017-11-10 19:27:48 -05:00
use OCP\IConfig ;
2018-11-27 12:41:40 -05:00
use OCP\IDBConnection ;
2019-08-21 04:35:17 -04:00
use OCP\IL10N ;
2016-02-03 09:43:45 -05:00
use Sabre\VObject\Component\VCalendar ;
2016-12-07 17:10:11 -05:00
use Sabre\VObject\Component\VCard ;
use Sabre\VObject\DateTimeParser ;
use Sabre\VObject\Document ;
use Sabre\VObject\InvalidDataException ;
use Sabre\VObject\Property\VCard\DateAndOrTime ;
2016-02-03 09:43:45 -05:00
use Sabre\VObject\Reader ;
2019-08-21 04:35:17 -04:00
/**
* Class BirthdayService
*
* @ package OCA\DAV\CalDAV
*/
2016-02-03 09:43:45 -05:00
class BirthdayService {
2020-04-10 10:54:27 -04:00
public const BIRTHDAY_CALENDAR_URI = 'contact_birthdays' ;
2022-10-02 12:21:29 -04:00
public const EXCLUDE_FROM_BIRTHDAY_CALENDAR_PROPERTY_NAME = 'X-NC-EXCLUDE-FROM-BIRTHDAY-CALENDAR' ;
2016-02-03 09:43:45 -05:00
/**
* BirthdayService constructor .
*/
2024-10-18 06:04:22 -04:00
public function __construct (
private CalDavBackend $calDavBackEnd ,
private CardDavBackend $cardDavBackEnd ,
private GroupPrincipalBackend $principalBackend ,
private IConfig $config ,
private IDBConnection $dbConnection ,
private IL10N $l10n ,
) {
2016-02-03 09:43:45 -05:00
}
2019-08-21 04:35:17 -04:00
public function onCardChanged ( int $addressBookId ,
string $cardUri ,
2022-05-05 18:01:08 -04:00
string $cardData ) : void {
2017-11-10 19:27:48 -05:00
if ( ! $this -> isGloballyEnabled ()) {
return ;
}
2016-03-23 09:12:50 -04:00
$targetPrincipals = $this -> getAllAffectedPrincipals ( $addressBookId );
2016-02-03 09:43:45 -05:00
$book = $this -> cardDavBackEnd -> getAddressBookById ( $addressBookId );
2022-07-17 12:36:06 -04:00
if ( $book === null ) {
return ;
}
2016-03-23 07:28:54 -04:00
$targetPrincipals [] = $book [ 'principaluri' ];
2016-09-30 04:29:27 -04:00
$datesToSync = [
2019-08-21 04:35:17 -04:00
[ 'postfix' => '' , 'field' => 'BDAY' ],
[ 'postfix' => '-death' , 'field' => 'DEATHDATE' ],
[ 'postfix' => '-anniversary' , 'field' => 'ANNIVERSARY' ],
2016-09-30 04:29:27 -04:00
];
2019-08-21 04:35:17 -04:00
2016-03-23 07:28:54 -04:00
foreach ( $targetPrincipals as $principalUri ) {
2017-11-10 19:27:48 -05:00
if ( ! $this -> isUserEnabled ( $principalUri )) {
continue ;
}
2022-07-17 08:51:01 -04:00
$reminderOffset = $this -> getReminderOffsetForUser ( $principalUri );
2016-03-23 07:28:54 -04:00
$calendar = $this -> ensureCalendarExists ( $principalUri );
2022-07-17 12:36:06 -04:00
if ( $calendar === null ) {
return ;
}
2016-09-30 04:29:27 -04:00
foreach ( $datesToSync as $type ) {
2022-07-17 08:51:01 -04:00
$this -> updateCalendar ( $cardUri , $cardData , $book , ( int ) $calendar [ 'id' ], $type , $reminderOffset );
2016-02-03 09:43:45 -05:00
}
}
}
2019-08-21 04:35:17 -04:00
public function onCardDeleted ( int $addressBookId ,
2022-05-05 18:01:08 -04:00
string $cardUri ) : void {
2017-11-10 19:27:48 -05:00
if ( ! $this -> isGloballyEnabled ()) {
return ;
}
2016-03-23 09:12:50 -04:00
$targetPrincipals = $this -> getAllAffectedPrincipals ( $addressBookId );
2016-02-03 09:43:45 -05:00
$book = $this -> cardDavBackEnd -> getAddressBookById ( $addressBookId );
2016-03-23 07:28:54 -04:00
$targetPrincipals [] = $book [ 'principaluri' ];
foreach ( $targetPrincipals as $principalUri ) {
2017-11-10 19:27:48 -05:00
if ( ! $this -> isUserEnabled ( $principalUri )) {
continue ;
}
2016-03-23 07:28:54 -04:00
$calendar = $this -> ensureCalendarExists ( $principalUri );
2016-09-30 04:29:27 -04:00
foreach ([ '' , '-death' , '-anniversary' ] as $tag ) {
$objectUri = $book [ 'uri' ] . '-' . $cardUri . $tag . '.ics' ;
2022-02-02 09:19:03 -05:00
$this -> calDavBackEnd -> deleteCalendarObject ( $calendar [ 'id' ], $objectUri , CalDavBackend :: CALENDAR_TYPE_CALENDAR , true );
2016-09-30 04:29:27 -04:00
}
2016-03-23 07:28:54 -04:00
}
2016-02-03 09:43:45 -05:00
}
/**
* @ throws \Sabre\DAV\Exception\BadRequest
*/
2022-05-05 18:01:08 -04:00
public function ensureCalendarExists ( string $principal ) : ? array {
2019-02-16 10:18:58 -05:00
$calendar = $this -> calDavBackEnd -> getCalendarByUri ( $principal , self :: BIRTHDAY_CALENDAR_URI );
if ( ! is_null ( $calendar )) {
return $calendar ;
2016-02-03 09:43:45 -05:00
}
2016-03-16 12:19:14 -04:00
$this -> calDavBackEnd -> createCalendar ( $principal , self :: BIRTHDAY_CALENDAR_URI , [
2021-03-25 05:26:50 -04:00
'{DAV:}displayname' => $this -> l10n -> t ( 'Contact birthdays' ),
2020-01-14 10:48:48 -05:00
'{http://apple.com/ns/ical/}calendar-color' => '#E9D859' ,
2020-10-05 09:12:57 -04:00
'components' => 'VEVENT' ,
2016-03-16 12:19:14 -04:00
]);
2016-02-03 09:43:45 -05:00
2016-03-16 12:19:14 -04:00
return $this -> calDavBackEnd -> getCalendarByUri ( $principal , self :: BIRTHDAY_CALENDAR_URI );
2016-02-03 09:43:45 -05:00
}
/**
2019-08-21 04:35:17 -04:00
* @ param $cardData
* @ param $dateField
* @ param $postfix
2022-07-17 08:51:01 -04:00
* @ param $reminderOffset
2019-08-21 04:35:17 -04:00
* @ return VCalendar | null
* @ throws InvalidDataException
2016-02-03 09:43:45 -05:00
*/
2024-10-18 22:46:25 -04:00
public function buildDateFromContact ( string $cardData ,
string $dateField ,
string $postfix ,
2022-07-17 08:51:01 -04:00
? string $reminderOffset ) : ? VCalendar {
2016-02-03 09:43:45 -05:00
if ( empty ( $cardData )) {
return null ;
}
try {
$doc = Reader :: read ( $cardData );
2016-12-07 17:10:11 -05:00
// We're always converting to vCard 4.0 so we can rely on the
// VCardConverter handling the X-APPLE-OMIT-YEAR property for us.
if ( ! $doc instanceof VCard ) {
return null ;
}
$doc = $doc -> convert ( Document :: VCARD40 );
2016-02-03 09:43:45 -05:00
} catch ( Exception $e ) {
return null ;
}
2022-10-02 12:21:29 -04:00
if ( isset ( $doc -> { self :: EXCLUDE_FROM_BIRTHDAY_CALENDAR_PROPERTY_NAME })) {
2022-10-02 11:41:59 -04:00
return null ;
}
2016-09-30 04:29:27 -04:00
if ( ! isset ( $doc -> { $dateField })) {
2016-02-03 09:43:45 -05:00
return null ;
}
2016-12-07 17:10:11 -05:00
if ( ! isset ( $doc -> FN )) {
return null ;
}
2016-09-30 04:29:27 -04:00
$birthday = $doc -> { $dateField };
2016-02-03 09:43:45 -05:00
if ( ! ( string ) $birthday ) {
return null ;
}
2016-12-07 17:10:11 -05:00
// Skip if the BDAY property is not of the right type.
if ( ! $birthday instanceof DateAndOrTime ) {
return null ;
}
// Skip if we can't parse the BDAY value.
try {
$dateParts = DateTimeParser :: parseVCardDateTime ( $birthday -> getValue ());
} catch ( InvalidDataException $e ) {
return null ;
}
2021-09-30 14:06:49 -04:00
if ( $dateParts [ 'year' ] !== null ) {
$parameters = $birthday -> parameters ();
$omitYear = ( isset ( $parameters [ 'X-APPLE-OMIT-YEAR' ])
&& $parameters [ 'X-APPLE-OMIT-YEAR' ] === $dateParts [ 'year' ]);
// 'X-APPLE-OMIT-YEAR' is not always present, at least iOS 12.4 uses the hard coded date of 1604 (the start of the gregorian calendar) when the year is unknown
if ( $omitYear || ( int ) $dateParts [ 'year' ] === 1604 ) {
$dateParts [ 'year' ] = null ;
}
}
2016-12-07 17:10:11 -05:00
2018-10-14 15:20:04 -04:00
$originalYear = null ;
2021-09-30 14:06:49 -04:00
if ( $dateParts [ 'year' ] !== null ) {
$originalYear = ( int ) $dateParts [ 'year' ];
}
2016-12-07 17:10:11 -05:00
2021-09-30 14:06:49 -04:00
$leapDay = (( int ) $dateParts [ 'month' ] === 2
&& ( int ) $dateParts [ 'date' ] === 29 );
if ( $dateParts [ 'year' ] === null || $originalYear < 1970 ) {
$birthday = ( $leapDay ? '1972-' : '1970-' )
. $dateParts [ 'month' ] . '-' . $dateParts [ 'date' ];
2016-12-07 17:10:11 -05:00
}
2016-02-03 09:43:45 -05:00
try {
2019-09-16 09:47:42 -04:00
if ( $birthday instanceof DateAndOrTime ) {
$date = $birthday -> getDateTime ();
} else {
$date = new \DateTimeImmutable ( $birthday );
}
2016-02-03 09:43:45 -05:00
} catch ( Exception $e ) {
return null ;
}
2019-08-21 04:35:17 -04:00
$summary = $this -> formatTitle ( $dateField , $doc -> FN -> getValue (), $originalYear , $this -> dbConnection -> supports4ByteText ());
2018-11-27 12:41:40 -05:00
2016-02-03 09:43:45 -05:00
$vCal = new VCalendar ();
$vCal -> VERSION = '2.0' ;
2020-03-10 09:13:43 -04:00
$vCal -> PRODID = '-//IDN nextcloud.com//Birthday calendar//EN' ;
2016-02-03 09:43:45 -05:00
$vEvent = $vCal -> createComponent ( 'VEVENT' );
$vEvent -> add ( 'DTSTART' );
$vEvent -> DTSTART -> setDateTime (
$date
);
$vEvent -> DTSTART [ 'VALUE' ] = 'DATE' ;
$vEvent -> add ( 'DTEND' );
2019-09-16 09:47:42 -04:00
$dtEndDate = ( new \DateTime ()) -> setTimestamp ( $date -> getTimeStamp ());
$dtEndDate -> add ( new \DateInterval ( 'P1D' ));
2016-02-03 09:43:45 -05:00
$vEvent -> DTEND -> setDateTime (
2019-09-16 09:47:42 -04:00
$dtEndDate
2016-02-03 09:43:45 -05:00
);
2019-09-16 09:47:42 -04:00
2016-02-03 09:43:45 -05:00
$vEvent -> DTEND [ 'VALUE' ] = 'DATE' ;
2018-01-04 14:15:24 -05:00
$vEvent -> { 'UID' } = $doc -> UID . $postfix ;
2016-02-03 09:43:45 -05:00
$vEvent -> { 'RRULE' } = 'FREQ=YEARLY' ;
2021-09-30 14:06:49 -04:00
if ( $leapDay ) {
/* Sabre\VObject supports BYMONTHDAY only if BYMONTH
* is also set */
$vEvent -> { 'RRULE' } = 'FREQ=YEARLY;BYMONTH=2;BYMONTHDAY=-1' ;
}
2016-11-16 16:06:36 -05:00
$vEvent -> { 'SUMMARY' } = $summary ;
2016-02-03 09:43:45 -05:00
$vEvent -> { 'TRANSP' } = 'TRANSPARENT' ;
2018-10-14 15:20:04 -04:00
$vEvent -> { 'X-NEXTCLOUD-BC-FIELD-TYPE' } = $dateField ;
2021-09-30 14:06:49 -04:00
$vEvent -> { 'X-NEXTCLOUD-BC-UNKNOWN-YEAR' } = $dateParts [ 'year' ] === null ? '1' : '0' ;
2018-10-14 15:20:04 -04:00
if ( $originalYear !== null ) {
$vEvent -> { 'X-NEXTCLOUD-BC-YEAR' } = ( string ) $originalYear ;
}
2022-07-17 08:51:01 -04:00
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 );
}
2016-02-03 09:43:45 -05:00
$vCal -> add ( $vEvent );
return $vCal ;
}
2019-02-16 10:18:58 -05:00
/**
* @ param string $user
*/
2019-08-21 04:35:17 -04:00
public function resetForUser ( string $user ) : void {
2019-02-16 10:18:58 -05:00
$principal = 'principals/users/' . $user ;
$calendar = $this -> calDavBackEnd -> getCalendarByUri ( $principal , self :: BIRTHDAY_CALENDAR_URI );
2022-07-25 09:15:14 -04:00
if ( ! $calendar ) {
return ; // The user's birthday calendar doesn't exist, no need to purge it
}
2019-02-16 10:18:58 -05:00
$calendarObjects = $this -> calDavBackEnd -> getCalendarObjects ( $calendar [ 'id' ], CalDavBackend :: CALENDAR_TYPE_CALENDAR );
foreach ( $calendarObjects as $calendarObject ) {
2022-02-02 09:19:03 -05:00
$this -> calDavBackEnd -> deleteCalendarObject ( $calendar [ 'id' ], $calendarObject [ 'uri' ], CalDavBackend :: CALENDAR_TYPE_CALENDAR , true );
2019-02-16 10:18:58 -05:00
}
}
2016-02-18 08:49:45 -05:00
/**
* @ param string $user
2019-08-21 04:35:17 -04:00
* @ throws \Sabre\DAV\Exception\BadRequest
2016-02-18 08:49:45 -05:00
*/
2019-08-21 04:35:17 -04:00
public function syncUser ( string $user ) : void {
2016-03-16 12:19:14 -04:00
$principal = 'principals/users/' . $user ;
$this -> ensureCalendarExists ( $principal );
$books = $this -> cardDavBackEnd -> getAddressBooksForUser ( $principal );
2016-02-18 08:49:45 -05:00
foreach ( $books as $book ) {
$cards = $this -> cardDavBackEnd -> getCards ( $book [ 'id' ]);
foreach ( $cards as $card ) {
2019-09-16 09:47:42 -04:00
$this -> onCardChanged (( int ) $book [ 'id' ], $card [ 'uri' ], $card [ 'carddata' ]);
2016-02-18 08:49:45 -05:00
}
}
}
/**
* @ param string $existingCalendarData
* @ param VCalendar $newCalendarData
* @ return bool
*/
2019-08-21 04:35:17 -04:00
public function birthdayEvenChanged ( string $existingCalendarData ,
VCalendar $newCalendarData ) : bool {
2016-02-18 08:49:45 -05:00
try {
$existingBirthday = Reader :: read ( $existingCalendarData );
} catch ( Exception $ex ) {
return true ;
}
2019-08-21 04:35:17 -04:00
return (
$newCalendarData -> VEVENT -> DTSTART -> getValue () !== $existingBirthday -> VEVENT -> DTSTART -> getValue ()
2016-02-18 08:49:45 -05:00
|| $newCalendarData -> VEVENT -> SUMMARY -> getValue () !== $existingBirthday -> VEVENT -> SUMMARY -> getValue ()
2019-08-21 04:35:17 -04:00
);
2016-02-18 08:49:45 -05:00
}
2016-03-23 09:12:50 -04:00
/**
2016-04-08 11:11:37 -04:00
* @ param integer $addressBookId
2016-03-23 09:12:50 -04:00
* @ return mixed
*/
2019-08-21 04:35:17 -04:00
protected function getAllAffectedPrincipals ( int $addressBookId ) {
2016-03-23 09:12:50 -04:00
$targetPrincipals = [];
$shares = $this -> cardDavBackEnd -> getShares ( $addressBookId );
foreach ( $shares as $share ) {
if ( $share [ '{http://owncloud.org/ns}group-share' ]) {
$users = $this -> principalBackend -> getGroupMemberSet ( $share [ '{http://owncloud.org/ns}principal' ]);
foreach ( $users as $user ) {
$targetPrincipals [] = $user [ 'uri' ];
}
} else {
$targetPrincipals [] = $share [ '{http://owncloud.org/ns}principal' ];
}
}
return array_values ( array_unique ( $targetPrincipals , SORT_STRING ));
}
2016-09-30 04:29:27 -04:00
/**
* @ param string $cardUri
2019-08-21 04:35:17 -04:00
* @ param string $cardData
2016-09-30 04:29:27 -04:00
* @ param array $book
* @ param int $calendarId
2019-08-21 04:35:17 -04:00
* @ param array $type
2022-07-17 08:51:01 -04:00
* @ param string $reminderOffset
2019-08-21 04:35:17 -04:00
* @ throws InvalidDataException
* @ throws \Sabre\DAV\Exception\BadRequest
2016-09-30 04:29:27 -04:00
*/
2019-08-21 04:35:17 -04:00
private function updateCalendar ( string $cardUri ,
string $cardData ,
array $book ,
int $calendarId ,
2022-07-17 08:51:01 -04:00
array $type ,
2022-07-17 12:36:06 -04:00
? string $reminderOffset ) : void {
2016-09-30 04:29:27 -04:00
$objectUri = $book [ 'uri' ] . '-' . $cardUri . $type [ 'postfix' ] . '.ics' ;
2022-07-17 08:51:01 -04:00
$calendarData = $this -> buildDateFromContact ( $cardData , $type [ 'field' ], $type [ 'postfix' ], $reminderOffset );
2016-09-30 04:29:27 -04:00
$existing = $this -> calDavBackEnd -> getCalendarObject ( $calendarId , $objectUri );
2020-08-11 16:13:55 -04:00
if ( $calendarData === null ) {
if ( $existing !== null ) {
2022-02-02 09:19:03 -05:00
$this -> calDavBackEnd -> deleteCalendarObject ( $calendarId , $objectUri , CalDavBackend :: CALENDAR_TYPE_CALENDAR , true );
2016-09-30 04:29:27 -04:00
}
} else {
2020-08-11 16:13:55 -04:00
if ( $existing === null ) {
// not found by URI, but maybe by UID
// happens when a contact with birthday is moved to a different address book
$calendarInfo = $this -> calDavBackEnd -> getCalendarById ( $calendarId );
$extraData = $this -> calDavBackEnd -> getDenormalizedData ( $calendarData -> serialize ());
if ( $calendarInfo && array_key_exists ( 'principaluri' , $calendarInfo )) {
$existing2path = $this -> calDavBackEnd -> getCalendarObjectByUID ( $calendarInfo [ 'principaluri' ], $extraData [ 'uid' ]);
if ( $existing2path !== null && array_key_exists ( 'uri' , $calendarInfo )) {
// delete the old birthday entry first so that we do not get duplicate UIDs
$existing2objectUri = substr ( $existing2path , strlen ( $calendarInfo [ 'uri' ]) + 1 );
2022-02-02 09:19:03 -05:00
$this -> calDavBackEnd -> deleteCalendarObject ( $calendarId , $existing2objectUri , CalDavBackend :: CALENDAR_TYPE_CALENDAR , true );
2020-08-11 16:13:55 -04:00
}
}
2016-09-30 04:29:27 -04:00
$this -> calDavBackEnd -> createCalendarObject ( $calendarId , $objectUri , $calendarData -> serialize ());
} else {
if ( $this -> birthdayEvenChanged ( $existing [ 'calendardata' ], $calendarData )) {
$this -> calDavBackEnd -> updateCalendarObject ( $calendarId , $objectUri , $calendarData -> serialize ());
}
}
}
}
2017-11-10 19:27:48 -05:00
/**
* checks if the admin opted - out of birthday calendars
*
* @ return bool
*/
2019-08-21 04:35:17 -04:00
private function isGloballyEnabled () : bool {
return $this -> config -> getAppValue ( 'dav' , 'generateBirthdayCalendar' , 'yes' ) === 'yes' ;
2017-11-10 19:27:48 -05:00
}
2022-07-17 08:51:01 -04:00
/**
* Extracts the userId part of a principal
*
* @ param string $userPrincipal
* @ return string | null
*/
private function principalToUserId ( string $userPrincipal ) : ? string {
2023-07-06 21:07:57 -04:00
if ( str_starts_with ( $userPrincipal , 'principals/users/' )) {
2022-07-17 08:51:01 -04:00
return substr ( $userPrincipal , 17 );
}
return null ;
}
2017-11-10 19:27:48 -05:00
/**
2019-08-21 04:35:17 -04:00
* Checks if the user opted - out of birthday calendars
2017-11-10 19:27:48 -05:00
*
2019-08-21 04:35:17 -04:00
* @ param string $userPrincipal The user principal to check for
2017-11-10 19:27:48 -05:00
* @ return bool
*/
2019-08-21 04:35:17 -04:00
private function isUserEnabled ( string $userPrincipal ) : bool {
2022-07-17 08:51:01 -04:00
$userId = $this -> principalToUserId ( $userPrincipal );
if ( $userId !== null ) {
2017-11-10 19:27:48 -05:00
$isEnabled = $this -> config -> getUserValue ( $userId , 'dav' , 'generateBirthdayCalendar' , 'yes' );
return $isEnabled === 'yes' ;
}
// not sure how we got here, just be on the safe side and return true
return true ;
}
2022-07-17 08:51:01 -04:00
/**
* 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' ;
}
2019-08-21 04:35:17 -04:00
/**
* Formats title of Birthday event
*
* @ param string $field Field name like BDAY , ANNIVERSARY , ...
* @ param string $name Name of contact
* @ param int | null $year Year of birth , anniversary , ...
* @ param bool $supports4Byte Whether or not the database supports 4 byte chars
* @ return string The formatted title
*/
private function formatTitle ( string $field ,
string $name ,
2024-03-28 11:13:19 -04:00
? int $year = null ,
2020-10-05 09:12:57 -04:00
bool $supports4Byte = true ) : string {
2019-08-21 04:35:17 -04:00
if ( $supports4Byte ) {
switch ( $field ) {
case 'BDAY' :
return implode ( '' , [
'🎂 ' ,
$name ,
$year ? ( ' (' . $year . ')' ) : '' ,
]);
case 'DEATHDATE' :
return implode ( '' , [
$this -> l10n -> t ( 'Death of %s' , [ $name ]),
$year ? ( ' (' . $year . ')' ) : '' ,
]);
case 'ANNIVERSARY' :
return implode ( '' , [
'💍 ' ,
$name ,
$year ? ( ' (' . $year . ')' ) : '' ,
]);
default :
return '' ;
}
} else {
switch ( $field ) {
case 'BDAY' :
return implode ( '' , [
$name ,
' ' ,
$year ? ( '(*' . $year . ')' ) : '*' ,
]);
case 'DEATHDATE' :
return implode ( '' , [
$this -> l10n -> t ( 'Death of %s' , [ $name ]),
$year ? ( ' (' . $year . ')' ) : '' ,
]);
case 'ANNIVERSARY' :
return implode ( '' , [
$name ,
' ' ,
$year ? ( '(⚭' . $year . ')' ) : '⚭' ,
]);
default :
return '' ;
}
}
}
2016-02-03 09:43:45 -05:00
}