Fix missing events on edges of the view time range (when client timezone is different than server tz) (T698)

This commit is contained in:
Aleksander Machniak 2015-08-18 12:39:55 +02:00
parent f98e1d7e14
commit 990712503d
6 changed files with 64 additions and 18 deletions

View file

@ -251,14 +251,16 @@ class kolab_calendar extends kolab_storage_folder_api
public function list_events($start, $end, $search = null, $virtual = 1, $query = array(), $filter_query = null)
{
// convert to DateTime for comparisons
// #5190: make the range a little bit wider
// to workaround possible timezone differences
try {
$start = new DateTime('@'.$start);
$start = new DateTime('@' . ($start - 12 * 3600));
}
catch (Exception $e) {
$start = new DateTime('@0');
}
try {
$end = new DateTime('@'.$end);
$end = new DateTime('@' . ($end + 12 * 3600));
}
catch (Exception $e) {
$end = new DateTime('today +10 years');

View file

@ -50,6 +50,7 @@ class kolab_storage_cache
protected $order_by = null;
protected $limit = null;
protected $error = 0;
protected $server_timezone;
/**
@ -84,6 +85,7 @@ class kolab_storage_cache
$this->enabled = $rcmail->config->get('kolab_cache', false);
$this->folders_table = $this->db->table_name('kolab_folders');
$this->cache_refresh = get_offset_sec($rcmail->config->get('kolab_cache_refresh', '12h'));
$this->server_timezone = new DateTimeZone(date_default_timezone_get());
if ($this->enabled) {
// always read folder cache and lock state from DB master
@ -1145,4 +1147,19 @@ class kolab_storage_cache
}
}
/**
* Converts DateTime or unix timestamp into sql date format
* using server timezone.
*/
protected function _convert_datetime($datetime)
{
if (is_object($datetime)) {
$dt = clone $datetime;
$dt->setTimeZone($this->server_timezone);
return $dt->format(self::DB_DATE_FORMAT);
}
else if ($datetime) {
return date(self::DB_DATE_FORMAT, $datetime);
}
}
}

View file

@ -34,27 +34,27 @@ class kolab_storage_cache_event extends kolab_storage_cache
{
$sql_data = parent::_serialize($object);
$sql_data['dtstart'] = is_object($object['start']) ? $object['start']->format(self::DB_DATE_FORMAT) : date(self::DB_DATE_FORMAT, $object['start']);
$sql_data['dtend'] = is_object($object['end']) ? $object['end']->format(self::DB_DATE_FORMAT) : date(self::DB_DATE_FORMAT, $object['end']);
$sql_data['dtstart'] = $this->_convert_datetime($object['start']);
$sql_data['dtend'] = $this->_convert_datetime($object['end']);
// extend date range for recurring events
if ($object['recurrence'] && $object['_formatobj']) {
$recurrence = new kolab_date_recurrence($object['_formatobj']);
$dtend = $recurrence->end() ?: new DateTime('now +10 years');
$sql_data['dtend'] = $dtend->format(self::DB_DATE_FORMAT);
$sql_data['dtend'] = $this->_convert_datetime($dtend);
}
// extend start/end dates to spawn all exceptions
if (is_array($object['exceptions'])) {
foreach ($object['exceptions'] as $exception) {
if (is_a($exception['start'], 'DateTime')) {
$exstart = $exception['start']->format(self::DB_DATE_FORMAT);
$exstart = $this->_convert_datetime($exception['start']);
if ($exstart < $sql_data['dtstart']) {
$sql_data['dtstart'] = $exstart;
}
}
if (is_a($exception['end'], 'DateTime')) {
$exend = $exception['end']->format(self::DB_DATE_FORMAT);
$exend = $this->_convert_datetime($exception['end']);
if ($exend > $sql_data['dtend']) {
$sql_data['dtend'] = $exend;
}

View file

@ -24,4 +24,19 @@
class kolab_storage_cache_freebusy extends kolab_storage_cache
{
protected $extra_cols = array('dtstart','dtend');
/**
* Helper method to convert the given Kolab object into a dataset to be written to cache
*
* @override
*/
protected function _serialize($object)
{
$sql_data = parent::_serialize($object) + array('dtstart' => null, 'dtend' => null);
$sql_data['dtstart'] = $this->_convert_datetime($object['start']);
$sql_data['dtend'] = $this->_convert_datetime($object['end']);
return $sql_data;
}
}

View file

@ -25,4 +25,18 @@ class kolab_storage_cache_journal extends kolab_storage_cache
{
protected $extra_cols = array('dtstart','dtend');
/**
* Helper method to convert the given Kolab object into a dataset to be written to cache
*
* @override
*/
protected function _serialize($object)
{
$sql_data = parent::_serialize($object) + array('dtstart' => null, 'dtend' => null);
$sql_data['dtstart'] = $this->_convert_datetime($object['start']);
$sql_data['dtend'] = $this->_convert_datetime($object['end']);
return $sql_data;
}
}

View file

@ -32,12 +32,10 @@ class kolab_storage_cache_task extends kolab_storage_cache
*/
protected function _serialize($object)
{
$sql_data = parent::_serialize($object) + array('dtstart' => null, 'dtend' => null);
$sql_data = parent::_serialize($object);
if ($object['start'])
$sql_data['dtstart'] = is_object($object['start']) ? $object['start']->format(self::DB_DATE_FORMAT) : date(self::DB_DATE_FORMAT, $object['start']);
if ($object['due'])
$sql_data['dtend'] = is_object($object['due']) ? $object['due']->format(self::DB_DATE_FORMAT) : date(self::DB_DATE_FORMAT, $object['due']);
$sql_data['dtstart'] = $this->_convert_datetime($object['start']);
$sql_data['dtend'] = $this->_convert_datetime($object['due']);
return $sql_data;
}