diff --git a/api/src/Contacts.php b/api/src/Contacts.php index 6046c41816..c5b96273d1 100755 --- a/api/src/Contacts.php +++ b/api/src/Contacts.php @@ -1022,6 +1022,15 @@ class Contacts extends Contacts\Storage if (!isset($this->tracking)) $this->tracking = new Contacts\Tracking($this); $this->tracking->track($to_write, $old ? $old : null, null, $deleted); } + + // Expire birthday cache for this year and next if birthday changed + if($isUpdate && $old['bday'] !== $to_write['bday'] || !$isUpdate && $to_write['bday']) + { + $year = (int) date('Y',time()); + Cache::unsetInstance(__CLASS__,"birthday-$year-{$to_write['owner']}"); + $year++; + Cache::unsetInstance(__CLASS__,"birthday-$year-{$to_write['owner']}"); + } } return $this->error ? false : $contact['id']; @@ -1676,6 +1685,68 @@ class Contacts extends Contacts\Storage return $calendars; } + /** + * Read the holidays (birthdays) from the given addressbook, either from the + * instance cache, or read them & cache for next time. Cached for HOLIDAY_CACHE_TIME. + * + * @param int $addressbook - Addressbook to search. We cache them separately in the instance. + * @param int $year + */ + public function read_birthdays($addressbook, $year) + { + $birthdays = Cache::getInstance(__CLASS__,"birthday-$year-$addressbook"); + if($birthdays !== null) + { + return $birthdays; + } + + $birthdays = array(); + $filter = array( + 'owner' => (int)$addressbook, + 'n_family' => "!''", + 'bday' => "!''", + ); + $bdays =& $this->search('',array('id','n_family','n_given','n_prefix','n_middle','bday'), + 'contact_bday ASC',$extra_cols='',$wildcard='',$empty=False,$op='AND',$start=false,$filter); + + if ($bdays) + { + // sort by month and day only + usort($bdays, function($a, $b) + { + return (int) $a['bday'] == (int) $b['bday'] ? + strcmp($a['bday'], $b['bday']) : + (int) $a['bday'] - (int) $b['bday']; + }); + foreach($bdays as $pers) + { + if (empty($pers['bday']) || $pers['bday']=='0000-00-00 0' || $pers['bday']=='0000-00-00' || $pers['bday']=='0.0.00') + { + //error_log(__METHOD__.__LINE__.' Skipping entry for invalid birthday:'.array2string($pers)); + continue; + } + list($y,$m,$d) = explode('-',$pers['bday']); + if ($y > $year) + { + // not yet born + continue; + } + $birthdays[sprintf('%04d%02d%02d',$year,$m,$d)][] = array( + 'day' => $d, + 'month' => $m, + 'occurence' => 0, + 'name' => lang('Birthday').' '.($pers['n_given'] ? $pers['n_given'] : $pers['n_prefix']).' '.$pers['n_middle'].' '. + $pers['n_family']. + ($GLOBALS['egw_info']['server']['hide_birthdays'] == 'age' ? ' '.($year - $y): ''). + ($y && in_array($GLOBALS['egw_info']['server']['hide_birthdays'], array('','age')) ? ' ('.$y.')' : ''), + 'birthyear' => $y, // this can be used to identify birthdays from holidays + ); + } + } + Cache::setInstance(__CLASS__,"birthday-$year-$addressbook", $birthdays, 864000 /* 10 days*/); + return $birthdays; + } + /** * Called by delete-account hook, when an account get deleted --> deletes/moves the personal addressbook * diff --git a/calendar/inc/class.calendar_bo.inc.php b/calendar/inc/class.calendar_bo.inc.php index c84c01130a..77eaacc2f6 100644 --- a/calendar/inc/class.calendar_bo.inc.php +++ b/calendar/inc/class.calendar_bo.inc.php @@ -1879,7 +1879,7 @@ class calendar_bo $contacts = new Api\Contacts(); foreach($contacts->get_addressbooks() as $owner => $name) { - $holidays += calendar_holidays::read_addressbook($year, $owner); + $holidays += $contacts->read_birthdays($owner, $year); } } diff --git a/calendar/inc/class.calendar_holidays.inc.php b/calendar/inc/class.calendar_holidays.inc.php index 53fe377ea7..a18e74a282 100644 --- a/calendar/inc/class.calendar_holidays.inc.php +++ b/calendar/inc/class.calendar_holidays.inc.php @@ -35,7 +35,7 @@ class calendar_holidays const URL_FAIL_CACHE_TIME = 300; const EGW_HOLIDAY_URL = 'https://community.egroupware.org/egw'; const HOLIDAY_PATH = '/calendar/setup/ical_holiday_urls.json'; - const HOLIDAY_CACHE_TIME = 864000; // 1 day + const HOLIDAY_CACHE_TIME = 864000; // 10 days /** * Read holidays for given country/url and year @@ -211,70 +211,6 @@ class calendar_holidays return $urls[$country]; } - - /** - * Read the holidays (birthdays) from the given addressbook, either from the - * instance cache, or read them & cache for next time. Cached for HOLIDAY_CACHE_TIME. - * - * @param int $year - * @param int $addressbook - Addressbook to search. We cache them separately in the instance. - */ - public static function read_addressbook($year, $addressbook) - { - $birthdays = Api\Cache::getInstance(__CLASS__,"contacts-$year-$addressbook"); - if($birthdays !== null) - { - return $birthdays; - } - - $birthdays = array(); - $contacts = new Api\Contacts(); - $filter = array( - 'owner' => (int)$addressbook, - 'n_family' => "!''", - 'bday' => "!''", - ); - $bdays =& $contacts->search('',array('id','n_family','n_given','n_prefix','n_middle','bday'), - 'contact_bday ASC',$extra_cols='',$wildcard='',$empty=False,$op='AND',$start=false,$filter); - - if ($bdays) - { - // sort by month and day only - usort($bdays, function($a, $b) - { - return (int) $a['bday'] == (int) $b['bday'] ? - strcmp($a['bday'], $b['bday']) : - (int) $a['bday'] - (int) $b['bday']; - }); - foreach($bdays as $pers) - { - if (empty($pers['bday']) || $pers['bday']=='0000-00-00 0' || $pers['bday']=='0000-00-00' || $pers['bday']=='0.0.00') - { - //error_log(__METHOD__.__LINE__.' Skipping entry for invalid birthday:'.array2string($pers)); - continue; - } - list($y,$m,$d) = explode('-',$pers['bday']); - if ($y > $year) - { - // not yet born - continue; - } - $birthdays[sprintf('%04d%02d%02d',$year,$m,$d)][] = array( - 'day' => $d, - 'month' => $m, - 'occurence' => 0, - 'name' => lang('Birthday').' '.($pers['n_given'] ? $pers['n_given'] : $pers['n_prefix']).' '.$pers['n_middle'].' '. - $pers['n_family']. - ($GLOBALS['egw_info']['server']['hide_birthdays'] == 'age' ? ' '.($year - $y): ''). - ($y && in_array($GLOBALS['egw_info']['server']['hide_birthdays'], array('','age')) ? ' ('.$y.')' : ''), - 'birthyear' => $y, // this can be used to identify birthdays from holidays - ); - } - } - Api\Cache::setInstance(__CLASS__,"contacts-$year-$addressbook", $birthdays, self::HOLIDAY_CACHE_TIME); - return $birthdays; - } - } // some tests when url is called direct