Changeset View
Changeset View
Standalone View
Standalone View
plugins/calendar/drivers/calendar_driver.php
Show First 20 Lines • Show All 626 Lines • ▼ Show 20 Lines | public function load_birthday_events($start, $end, $search = null, $modifiedsince = null) | ||||
$year2 = $end->format('Y'); | $year2 = $end->format('Y'); | ||||
$events = array(); | $events = array(); | ||||
$search = mb_strtolower($search); | $search = mb_strtolower($search); | ||||
$rcmail = rcmail::get_instance(); | $rcmail = rcmail::get_instance(); | ||||
$cache = $rcmail->get_cache('calendar.birthdays', 'db', 3600); | $cache = $rcmail->get_cache('calendar.birthdays', 'db', 3600); | ||||
$cache->expunge(); | $cache->expunge(); | ||||
$alarm_type = $rcmail->config->get('calendar_birthdays_alarm_type', ''); | $alarm_type = $rcmail->config->get('calendar_birthdays_alarm_type', ''); | ||||
$alarm_offset = $rcmail->config->get('calendar_birthdays_alarm_offset', '-1D'); | $alarm_offset = $rcmail->config->get('calendar_birthdays_alarm_offset', '-1D'); | ||||
$alarms = $alarm_type ? $alarm_offset . ':' . $alarm_type : null; | $alarms = $alarm_type ? $alarm_offset . ':' . $alarm_type : null; | ||||
// let the user select the address books to consider in prefs | // let the user select the address books to consider in prefs | ||||
$selected_sources = $rcmail->config->get('calendar_birthday_adressbooks'); | $selected_sources = $rcmail->config->get('calendar_birthday_adressbooks'); | ||||
$sources = $selected_sources ?: array_keys($rcmail->get_address_sources(false, true)); | $sources = $selected_sources ?: array_keys($rcmail->get_address_sources(false, true)); | ||||
foreach ($sources as $source) { | foreach ($sources as $source) { | ||||
$abook = $rcmail->get_address_book($source); | $abook = $rcmail->get_address_book($source); | ||||
// skip LDAP address books unless selected by the user | // skip LDAP address books unless selected by the user | ||||
if (!$abook || ($abook instanceof rcube_ldap && empty($selected_sources))) { | if (!$abook || ($abook instanceof rcube_ldap && empty($selected_sources))) { | ||||
continue; | continue; | ||||
} | } | ||||
$abook->set_pagesize(10000); | $abook->set_pagesize(10000); | ||||
// check for cached results | // check for cached results | ||||
$cache_records = array(); | $cache_records = array(); | ||||
$cached = $cache->get($source); | $cached = $cache->get($source); | ||||
// iterate over (cached) contacts | // iterate over (cached) contacts | ||||
foreach (($cached ?: $abook->search('*', '', 2, true, true, array('birthday'))) as $contact) { | foreach (($cached ?: $abook->search('*', '', 2, true, true, array('birthday'))) as $contact) { | ||||
if (is_array($contact) && !empty($contact['birthday'])) { | $event = self::parse_contact($contact, $source); | ||||
try { | |||||
if (is_array($contact['birthday'])) | |||||
$contact['birthday'] = reset($contact['birthday']); | |||||
$bday = $contact['birthday'] instanceof DateTime ? $contact['birthday'] : | if (empty($event)) { | ||||
new DateTime($contact['birthday'], new DateTimezone('UTC')); | |||||
$birthyear = $bday->format('Y'); | |||||
} | |||||
catch (Exception $e) { | |||||
rcube::raise_error(array( | |||||
'code' => 600, 'type' => 'php', | |||||
'file' => __FILE__, 'line' => __LINE__, | |||||
'message' => 'BIRTHDAY PARSE ERROR: ' . $e), | |||||
true, false); | |||||
continue; | continue; | ||||
} | } | ||||
$display_name = rcube_addressbook::compose_display_name($contact); | |||||
$event_title = $rcmail->gettext(array('name' => 'birthdayeventtitle', 'vars' => array('name' => $display_name)), 'calendar'); | |||||
// add stripped record to cache | // add stripped record to cache | ||||
if (empty($cached)) { | if (empty($cached)) { | ||||
$cache_records[] = array( | $cache_records[] = array( | ||||
'ID' => $contact['ID'], | 'ID' => $contact['ID'], | ||||
'name' => $display_name, | 'name' => $event['_displayname'], | ||||
'birthday' => $bday->format('Y-m-d'), | 'birthday' => $event['start']->format('Y-m-d'), | ||||
); | ); | ||||
} | } | ||||
// filter by search term (only name is involved here) | // filter by search term (only name is involved here) | ||||
if (!empty($search) && strpos(mb_strtolower($event_title), $search) === false) { | if (!empty($search) && strpos(mb_strtolower($event['title']), $search) === false) { | ||||
continue; | continue; | ||||
} | } | ||||
$bday = clone $event['start']; | |||||
$byear = $bday->format('Y'); | |||||
// quick-and-dirty recurrence computation: just replace the year | // quick-and-dirty recurrence computation: just replace the year | ||||
$bday->setDate($year, $bday->format('n'), $bday->format('j')); | $bday->setDate($year, $bday->format('n'), $bday->format('j')); | ||||
$bday->setTime(12, 0, 0); | $bday->setTime(12, 0, 0); | ||||
$this_year = $year; | $this_year = $year; | ||||
// date range reaches over multiple years: use end year if not in range | // date range reaches over multiple years: use end year if not in range | ||||
if (($bday > $end || $bday < $start) && $year2 != $year) { | if (($bday > $end || $bday < $start) && $year2 != $year) { | ||||
$bday->setDate($year2, $bday->format('n'), $bday->format('j')); | $bday->setDate($year2, $bday->format('n'), $bday->format('j')); | ||||
$this_year = $year2; | $this_year = $year2; | ||||
} | } | ||||
// birthday is within requested range | // birthday is within requested range | ||||
if ($bday <= $end && $bday >= $start) { | if ($bday <= $end && $bday >= $start) { | ||||
$age = $this_year - $birthyear; | unset($event['_displayname']); | ||||
$uid = rcube_ldap::dn_encode('bday:' . $source . ':' . $contact['ID'] . ':' . $this_year); | $event['alarms'] = $alarms; | ||||
$event = array( | |||||
'id' => $uid, | // if this is not the first occurence modify event details | ||||
'uid' => $uid, | // but not when this is "all birthdays feed" request | ||||
'calendar' => self::BIRTHDAY_CALENDAR_ID, | if ($year2 - $year < 10 && ($age = ($this_year - $byear))) { | ||||
'title' => $event_title, | $event['description'] = $rcmail->gettext(array('name' => 'birthdayage', 'vars' => array('age' => $age)), 'calendar'); | ||||
'description' => $rcmail->gettext(array('name' => 'birthdayage', 'vars' => array('age' => $age)), 'calendar'), | $event['start'] = $bday; | ||||
// Add more contact information to description block? | |||||
'allday' => true, | |||||
'start' => $bday, | |||||
'alarms' => $alarms, | |||||
); | |||||
$event['end'] = clone $bday; | $event['end'] = clone $bday; | ||||
$event['end']->add(new DateInterval('PT1H')); | unset($event['recurrence']); | ||||
} | |||||
// add the main instance | |||||
$events[] = $event; | $events[] = $event; | ||||
} | } | ||||
} | } | ||||
} | |||||
// store collected contacts in cache | // store collected contacts in cache | ||||
if (empty($cached)) { | if (empty($cached)) { | ||||
$cache->write($source, $cache_records); | $cache->write($source, $cache_records); | ||||
} | } | ||||
} | } | ||||
return $events; | return $events; | ||||
} | } | ||||
/** | /** | ||||
* Get a single birthday calendar event | * Get a single birthday calendar event | ||||
*/ | */ | ||||
public function get_birthday_event($id) | public function get_birthday_event($id) | ||||
{ | { | ||||
// decode $id | // decode $id | ||||
list(,$source,$contact_id,$year) = explode(':', rcube_ldap::dn_decode($id)); | list(,$source,$contact_id,$year) = explode(':', rcube_ldap::dn_decode($id)); | ||||
$rcmail = rcmail::get_instance(); | $rcmail = rcmail::get_instance(); | ||||
if ($source && $contact_id && ($abook = $rcmail->get_address_book($source))) { | if ($source && $contact_id && ($abook = $rcmail->get_address_book($source))) { | ||||
$contact = $abook->get_record($contact_id, true); | if ($contact = $abook->get_record($contact_id, true)) { | ||||
return self::parse_contact($contact, $source); | |||||
} | |||||
} | |||||
} | |||||
if (is_array($contact) && !empty($contact['birthday'])) { | /** | ||||
try { | * Parse contact and create an event for its birthday | ||||
if (is_array($contact['birthday'])) | * | ||||
* @param array $contact Contact data | |||||
* @param string $source Addressbook source ID | |||||
* | |||||
* @return array Birthday event data | |||||
*/ | |||||
public static function parse_contact($contact, $source) | |||||
{ | |||||
if (!is_array($contact)) { | |||||
return; | |||||
} | |||||
if (is_array($contact['birthday'])) { | |||||
$contact['birthday'] = reset($contact['birthday']); | $contact['birthday'] = reset($contact['birthday']); | ||||
} | |||||
$bday = $contact['birthday'] instanceof DateTime ? $contact['birthday'] : | if (empty($contact['birthday'])) { | ||||
new DateTime($contact['birthday'], new DateTimezone('UTC')); | return; | ||||
$birthyear = $bday->format('Y'); | } | ||||
try { | |||||
$bday = $contact['birthday']; | |||||
if (!$bday instanceof DateTime) { | |||||
$bday = new DateTime($bday, new DateTimezone('UTC')); | |||||
} | |||||
$bday->_dateonly = true; | |||||
} | } | ||||
catch (Exception $e) { | catch (Exception $e) { | ||||
rcube::raise_error(array( | rcube::raise_error(array( | ||||
'code' => 600, 'type' => 'php', | 'code' => 600, 'type' => 'php', | ||||
'file' => __FILE__, 'line' => __LINE__, | 'file' => __FILE__, 'line' => __LINE__, | ||||
'message' => 'BIRTHDAY PARSE ERROR: ' . $e), | 'message' => 'BIRTHDAY PARSE ERROR: ' . $e->getMessage()), | ||||
true, false); | true, false); | ||||
return; | |||||
return null; | |||||
} | } | ||||
$rcmail = rcmail::get_instance(); | |||||
$birthyear = $bday->format('Y'); | |||||
$display_name = rcube_addressbook::compose_display_name($contact); | $display_name = rcube_addressbook::compose_display_name($contact); | ||||
$event_title = $rcmail->gettext(array('name' => 'birthdayeventtitle', 'vars' => array('name' => $display_name)), 'calendar'); | $label = array('name' => 'birthdayeventtitle', 'vars' => array('name' => $display_name)); | ||||
$event_title = $rcmail->gettext($label, 'calendar'); | |||||
$uid = rcube_ldap::dn_encode('bday:' . $source . ':' . $contact['ID'] . ':' . $birthyear); | $uid = rcube_ldap::dn_encode('bday:' . $source . ':' . $contact['ID'] . ':' . $birthyear); | ||||
$event = array( | $event = array( | ||||
'id' => $uid, | 'id' => $uid, | ||||
'uid' => $uid, | 'uid' => $uid, | ||||
'calendar' => self::BIRTHDAY_CALENDAR_ID, | 'calendar' => self::BIRTHDAY_CALENDAR_ID, | ||||
'title' => $event_title, | 'title' => $event_title, | ||||
'description' => '', | 'description' => '', | ||||
'allday' => true, | 'allday' => true, | ||||
'start' => $bday, | 'start' => $bday, | ||||
'end' => clone $bday, | |||||
'recurrence' => array('FREQ' => 'YEARLY', 'INTERVAL' => 1), | 'recurrence' => array('FREQ' => 'YEARLY', 'INTERVAL' => 1), | ||||
'free_busy' => 'free', | 'free_busy' => 'free', | ||||
'_displayname' => $display_name, | |||||
); | ); | ||||
$event['end'] = clone $bday; | |||||
$event['end']->add(new DateInterval('PT1H')); | |||||
return $event; | return $event; | ||||
} | } | ||||
} | |||||
return null; | |||||
} | |||||
/** | /** | ||||
* Store alarm dismissal for birtual birthay events | * Store alarm dismissal for birtual birthay events | ||||
* | * | ||||
* @param string Event identifier | * @param string Event identifier | ||||
* @param integer Suspend the alarm for this number of seconds | * @param integer Suspend the alarm for this number of seconds | ||||
*/ | */ | ||||
public function dismiss_birthday_alarm($event_id, $snooze = 0) | public function dismiss_birthday_alarm($event_id, $snooze = 0) | ||||
Show All 24 Lines |