Page MenuHomePhorge

No OneTemporary

Size
33 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/kolab_sync_data_tasks.php b/lib/kolab_sync_data_tasks.php
index d30a6cf..eb66358 100644
--- a/lib/kolab_sync_data_tasks.php
+++ b/lib/kolab_sync_data_tasks.php
@@ -1,298 +1,332 @@
<?php
/**
+--------------------------------------------------------------------------+
| Kolab Sync (ActiveSync for Kolab) |
| |
| Copyright (C) 2011-2012, Kolab Systems AG <contact@kolabsys.com> |
| |
| This program is free software: you can redistribute it and/or modify |
| it under the terms of the GNU Affero General Public License as published |
| by the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public License |
| along with this program. If not, see <http://www.gnu.org/licenses/> |
+--------------------------------------------------------------------------+
| Author: Aleksander Machniak <machniak@kolabsys.com> |
+--------------------------------------------------------------------------+
*/
/**
* Tasks data class for Syncroton
*/
class kolab_sync_data_tasks extends kolab_sync_data
{
/**
* Mapping from ActiveSync Calendar namespace fields
*/
protected $mapping = array(
'body' => 'description',
'categories' => 'categories',
//'complete' => 'complete', // handled separately
'dateCompleted' => 'changed',
'dueDate' => 'due',
'importance' => 'priority',
//'recurrence' => 'recurrence',
//'reminderSet' => 'reminderset',
//'reminderTime' => 'remindertime',
'sensitivity' => 'sensitivity',
'startDate' => 'start',
'subject' => 'title',
'utcDueDate' => 'due',
'utcStartDate' => 'start',
);
/**
* Sensitivity values
*/
const SENSITIVITY_NORMAL = 0;
const SENSITIVITY_PERSONAL = 1;
const SENSITIVITY_PRIVATE = 2;
const SENSITIVITY_CONFIDENTIAL = 3;
/**
* mapping of sensitivity
*
* @var array
*/
protected $sensitivityMap = array(
'public' => self::SENSITIVITY_PERSONAL,
'private' => self::SENSITIVITY_PRIVATE,
'confidential' => self::SENSITIVITY_CONFIDENTIAL,
);
/**
* Kolab object type
*
* @var string
*/
protected $modelName = 'task';
/**
* Type of the default folder
*
* @var int
*/
protected $defaultFolderType = Syncroton_Command_FolderSync::FOLDERTYPE_TASK;
/**
* Default container for new entries
*
* @var string
*/
protected $defaultFolder = 'Tasks';
/**
* Type of user created folders
*
* @var int
*/
protected $folderType = Syncroton_Command_FolderSync::FOLDERTYPE_TASK_USER_CREATED;
/**
* Enable mapping Activesync categories into Kolab tags (relations)
*/
protected $tag_categories = true;
/**
* Appends contact data to xml element
*
* @param Syncroton_Model_SyncCollection $collection Collection data
* @param string $serverId Local entry identifier
* @param boolean $as_array Return entry as an array
*
* @return array|Syncroton_Model_Task|array Task object
*/
public function getEntry(Syncroton_Model_SyncCollection $collection, $serverId, $as_array = false)
{
$task = is_array($serverId) ? $serverId : $this->getObject($collection->collectionId, $serverId);
// $config = $this->getFolderConfig($task['_mailbox']);
$result = array();
// Completion status (required)
$result['complete'] = intval($task['status'] == 'COMPLETED' || $task['complete'] == 100);
// Calendar namespace fields
foreach ($this->mapping as $key => $name) {
$value = $this->getKolabDataItem($task, $name);
switch ($name) {
case 'due':
case 'start':
if (preg_match('/^UTC/i', $key)) {
$value = self::date_from_kolab($value);
}
break;
case 'changed':
$value = $result['complete'] ? self::date_from_kolab($value) : null;
break;
case 'description':
$value = $this->body_from_kolab($value, $collection);
break;
case 'sensitivity':
$value = intval($this->sensitivityMap[$value]);
break;
case 'priority':
$value = $this->prio_to_importance($value);
break;
}
if (empty($value) || is_array($value)) {
continue;
}
$result[$key] = $value;
}
// convert kolab tags into categories
$result['categories'] = $this->getKolabTags($task['uid'], $result['categories']);
// Recurrence
$this->recurrence_from_kolab($collection, $task, $result, 'Task');
return $as_array ? $result : new Syncroton_Model_Task($result);
}
+
+
+ /**
+ * Apply a timezone matching the utc offset.
+ */
+ private static function applyTimezone($value, $utcValue)
+ {
+ $tzc = kolab_sync_timezone_converter::getInstance();
+ $tz = $tzc->getOffsetTimezone($value, $utcValue);
+ if ($tz) {
+ //Setting the timezone will change the time, so we set it on the utc variant instead to end up with the same time in the new timezone.
+ $value = $utcValue;
+ $value->setTimezone($tz);
+ }
+ return $value;
+ }
+
/**
* convert contact from xml to libkolab array
*
* @param Syncroton_Model_IEntry $data Contact to convert
* @param string $folderid Folder identifier
* @param array $entry Existing entry
*
* @return array
*/
public function toKolab(Syncroton_Model_IEntry $data, $folderid, $entry = null)
{
$task = !empty($entry) ? $entry : array();
$foldername = isset($task['_mailbox']) ? $task['_mailbox'] : $this->getFolderName($folderid);
// $config = $this->getFolderConfig($foldername);
$task['allday'] = 0;
// Calendar namespace fields
foreach ($this->mapping as $key => $name) {
$value = $data->$key;
switch ($name) {
+
+ case 'due':
+ case 'start':
+ // We expect to always get regular and utc variants, so we only need to take one into account.
+ if ($key == 'utcStartDate' || $key == 'utcDueDate') {
+ continue 2;
+ }
+ if ($value) {
+ if ($name =='due' && $data->utcDueDate) {
+ $value = static::applyTimezone($value, $data->utcDueDate);
+ }
+ if ($name =='start' && $data->utcStartDate) {
+ $value = static::applyTimezone($value, $data->utcStartDate);
+ }
+ }
+ break;
+
case 'sensitivity':
$map = array_flip($this->sensitivityMap);
$value = $map[$value];
break;
case 'description':
$value = $this->getBody($value, Syncroton_Model_EmailBody::TYPE_PLAINTEXT);
// If description isn't specified keep old description
if ($value === null) {
continue 2;
}
break;
case 'priority':
$value = $this->importance_to_prio($value);
break;
}
$this->setKolabDataItem($task, $name, $value);
}
if (!empty($data->complete)) {
$task['status'] = 'COMPLETED';
$task['complete'] = 100;
}
else if (isset($data->complete) && ($task['status'] == 'COMPLETED' || $task['complete'] == 100)) {
$task['status'] = '';
$task['complete'] = 0;
}
// recurrence
$task['recurrence'] = $this->recurrence_to_kolab($data, $folderid, null);
return $task;
}
/**
* Returns filter query array according to specified ActiveSync FilterType
*
* @param int $filter_type Filter type
*
* @param array Filter query
*/
protected function filter($filter_type = 0)
{
$filter = array(array('type', '=', $this->modelName));
if ($filter_type == Syncroton_Command_Sync::FILTER_INCOMPLETE) {
$filter[] = array('tags', '!~', 'x-complete');
}
return $filter;
}
/**
* Convert Kolab priority into ActiveSync importance value
*/
protected function prio_to_importance($value)
{
// ActiveSync has only 3 levels of importance:
// 0 - Low, 1 - Normal, 2 - High
// but Kolab uses ten levels:
// 0 - unknown and 1-9 where 1 is the highest
// Use mapping from http://msdn.microsoft.com/en-us/library/ee159635.aspx
if ($value === null) {
return;
}
switch ($value) {
case 1:
case 2:
case 3:
case 4:
return 2;
case 5:
return 1;
case 6:
case 7:
case 8:
case 9:
return 0;
}
return;
}
/**
* Convert ActiveSync importance into Kolab priority value
*/
protected function importance_to_prio($value)
{
// Use mapping from http://msdn.microsoft.com/en-us/library/ee159635.aspx
if ($value === null) {
return;
}
switch ($value) {
case 0:
return 9;
case 1:
return 5;
case 2:
return 1;
}
return;
}
}
diff --git a/lib/kolab_sync_timezone_converter.php b/lib/kolab_sync_timezone_converter.php
index 5d8d5c7..fe2e9d7 100644
--- a/lib/kolab_sync_timezone_converter.php
+++ b/lib/kolab_sync_timezone_converter.php
@@ -1,610 +1,647 @@
<?php
/**
+--------------------------------------------------------------------------+
| Kolab Sync (ActiveSync for Kolab) |
| |
| Copyright (C) 2011-2017, Kolab Systems AG <contact@kolabsys.com> |
| Copyright (C) 2008-2012, Metaways Infosystems GmbH |
| |
| This program is free software: you can redistribute it and/or modify |
| it under the terms of the GNU Affero General Public License as published |
| by the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public License |
| along with this program. If not, see <http://www.gnu.org/licenses/> |
+--------------------------------------------------------------------------+
| Author: Aleksander Machniak <machniak@kolabsys.com> |
| Author: Jonas Fischer <j.fischer@metaways.de> |
+--------------------------------------------------------------------------+
*/
/**
* Activesync timezone converter
*/
class kolab_sync_timezone_converter
{
/**
* holds the instance of the singleton
*
* @var kolab_sync_timezone_onverter
*/
private static $_instance = NULL;
protected $_startDate = array();
/**
* If set then the timezone guessing results will be cached.
* This is strongly recommended for performance reasons.
*
* @var rcube_cache
*/
protected $cache = null;
/**
* array of offsets known by ActiceSync clients, but unknown by php
* @var array
*/
protected $_knownTimezones = array(
'0AIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==' => array(
'Pacific/Kwajalein' => 'MHT'
)
);
/**
* don't use the constructor. Use the singleton.
*
* @param $_logger
*/
private function __construct()
{
}
/**
* don't clone. Use the singleton.
*/
private function __clone()
{
}
/**
* the singleton pattern
*
* @return kolab_sync_timezone_converter
*/
public static function getInstance()
{
if (self::$_instance === NULL) {
self::$_instance = new kolab_sync_timezone_converter();
}
return self::$_instance;
}
+
+ /**
+ * Returns a timezone with an offset matching the time difference
+ * of $dt from $referenceDt.
+ *
+ * If set and matching the offset, kolab_format::$timezone is preferred.
+ *
+ * @param DateTime $dt The date time value for which we
+ * calculate the offset.
+ * @param DateTime $referenceDt The reference value, for instance in UTC.
+ *
+ * @return DateTimeZone|null
+ */
+ public function getOffsetTimezone($dt, $referenceDt)
+ {
+ $interval = $referenceDt->diff($dt);
+ $tz = new DateTimeZone($interval->format('%R%H%I')); //e.g. +0200
+ $utcOffset = $tz->getOffset($dt);
+
+ //Prefer the configured timezone if it matches the offset.
+ if (kolab_format::$timezone) {
+ if (kolab_format::$timezone->getOffset($dt) == $utcOffset) {
+ return kolab_format::$timezone;
+ }
+ }
+
+ //Look for any timezone with a matching offset.
+ foreach (DateTimeZone::listIdentifiers() as $timezoneIdentifier) {
+ $timezone = new DateTimeZone($timezoneIdentifier);
+ if ($timezone->getOffset($dt) == $utcOffset) {
+ return $timezone;
+ }
+ }
+ return null;
+ }
+
+
/**
* Returns a list of timezones that match to the {@param $_offsets}
*
* If {@see $_expectedTimezone} is set then the method will terminate as soon
* as the expected timezone has matched and the expected timezone will be the
* first entry to the returned array.
*
* @param string|array $_offsets
*
* @return array
*/
public function getListOfTimezones($_offsets)
{
if (is_string($_offsets) && isset($this->_knownTimezones[$_offsets])) {
$timezones = $this->_knownTimezones[$_offsets];
}
else {
if (is_string($_offsets)) {
// unpack timezone info to array
$_offsets = $this->_unpackTimezoneInfo($_offsets);
}
if (!$this->_validateOffsets($_offsets)) {
return array();
}
$this->_setDefaultStartDateIfEmpty($_offsets);
$cacheId = $this->_getCacheId('timezones', $_offsets);
$timezones = $this->_loadFromCache($cacheId);
if (!is_array($timezones)) {
$timezones = array();
foreach (DateTimeZone::listIdentifiers() as $timezoneIdentifier) {
$timezone = new DateTimeZone($timezoneIdentifier);
if (false !== ($matchingTransition = $this->_checkTimezone($timezone, $_offsets))) {
$timezones[$timezoneIdentifier] = $matchingTransition['abbr'];
}
}
$this->_saveInCache($timezones, $cacheId);
}
}
return $timezones;
}
/**
* Returns PHP timezone that matches to the {@param $_offsets}
*
* If {@see $_expectedTimezone} is set then the method will return this timezone if it matches.
*
* @param string|array $_offsets Activesync timezone definition
* @param string $_expectedTomezone Expected timezone name
*
* @return string Expected timezone name
*/
public function getTimezone($_offsets, $_expectedTimezone = null)
{
$timezones = $this->getListOfTimezones($_offsets);
if ($_expectedTimezone && isset($timezones[$_expectedTimezone])) {
return $_expectedTimezone;
}
else {
return key($timezones);
}
}
/**
* Return packed string for given {@param $_timezone}
*
* @param string $_timezone Timezone identifier
* @param string|int $_startDate Start date
*
* @return string Packed timezone offsets
*/
public function encodeTimezone($_timezone, $_startDate = null)
{
foreach ($this->_knownTimezones as $packedString => $knownTimezone) {
if (array_key_exists($_timezone, $knownTimezone)) {
return $packedString;
}
}
$offsets = $this->getOffsetsForTimezone($_timezone, $_startDate);
return $this->_packTimezoneInfo($offsets);
}
/**
* Get offsets for given timezone
*
* @param string $_timezone Timezone identifier
* @param string|int $_startDate Start date
*
* @return array Timezone offsets
*/
public function getOffsetsForTimezone($_timezone, $_startDate = null)
{
$this->_setStartDate($_startDate);
$cacheId = $this->_getCacheId('offsets', array($_timezone));
if (false === ($offsets = $this->_loadFromCache($cacheId))) {
$offsets = $this->_getOffsetsTemplate();
try {
$timezone = new DateTimeZone($_timezone);
}
catch (Exception $e) {
return null;
}
list($standardTransition, $daylightTransition) = $this->_getTransitionsForTimezoneAndYear($timezone, $this->_startDate['year']);
if ($standardTransition) {
$offsets['bias'] = $standardTransition['offset']/60*-1;
if ($daylightTransition) {
$offsets = $this->_generateOffsetsForTransition($offsets, $standardTransition, 'standard', $timezone);
$offsets = $this->_generateOffsetsForTransition($offsets, $daylightTransition, 'daylight', $timezone);
//@todo how do we get the standardBias (is usually 0)?
//$offsets['standardBias'] = ...
$offsets['daylightBias'] = ($daylightTransition['offset'] - $standardTransition['offset'])/60*-1;
$offsets['standardHour'] -= $offsets['daylightBias'] / 60;
$offsets['daylightHour'] += $offsets['daylightBias'] / 60;
}
}
$this->_saveInCache($offsets, $cacheId);
}
return $offsets;
}
/**
* Get offsets for timezone transition
*
* @param array $_offsets Timezone offsets
* @param array $_transition Timezone transition information
* @param string $_type Transition type: 'standard' or 'daylight'
* @param DateTimeZone $_timezone Timezone of the transition
*
* @return array
*/
protected function _generateOffsetsForTransition(array $_offsets, array $_transition, $_type, $_timezone)
{
$transitionDate = new DateTime($_transition['time'], $_timezone);
if ($_transition['offset']) {
$transitionDate->modify($_transition['offset'] . ' seconds');
}
$_offsets[$_type . 'Month'] = (int) $transitionDate->format('n');
$_offsets[$_type . 'DayOfWeek'] = (int) $transitionDate->format('w');
$_offsets[$_type . 'Minute'] = (int) $transitionDate->format('i');
$_offsets[$_type . 'Hour'] = (int) $transitionDate->format('G');
for ($i=5; $i>0; $i--) {
if ($this->_isNthOcurrenceOfWeekdayInMonth($transitionDate, $i)) {
$_offsets[$_type . 'Day'] = $i;
break;
};
}
return $_offsets;
}
/**
* Test if the weekday of the given {@param $_timestamp} is the {@param $_occurence}th occurence of this weekday within its month.
*
* @param DateTime $_datetime
* @param int $_occurence [1 to 5, where 5 indicates the final occurrence during the month if that day of the week does not occur 5 times]
*
* @return bool
*/
protected function _isNthOcurrenceOfWeekdayInMonth($_datetime, $_occurence)
{
if ($_occurence <= 1) {
return true;
}
$orig = $_datetime->format('n');
if ($_occurence == 5) {
$modified = clone($_datetime);
$modified->modify('1 week');
$mod = $modified->format('n');
// modified date is a next month
return $mod > $orig || ($mod == 1 && $orig == 12);
}
$modified = clone($_datetime);
$modified->modify(sprintf('-%d weeks', $_occurence - 1));
$mod = $modified->format('n');
if ($mod != $orig) {
return false;
}
$modified = clone($_datetime);
$modified->modify(sprintf('-%d weeks', $_occurence));
$mod = $modified->format('n');
// modified month is earlier than original
return $mod < $orig || ($mod == 12 && $orig == 1);
}
/**
* Check if the given {@param $_standardTransition} and {@param $_daylightTransition}
* match to the object property {@see $_offsets}
*
* @param array $standardTransition
* @param array $daylightTransition
*
* @return bool
*/
protected function _checkTransition($_standardTransition, $_daylightTransition, $_offsets, $tz)
{
if (empty($_standardTransition) || empty($_offsets)) {
return false;
}
$standardOffset = ($_offsets['bias'] + $_offsets['standardBias']) * 60 * -1;
// check each condition in a single if statement and break the chain when one condition is not met - for performance reasons
if ($standardOffset == $_standardTransition['offset'] ) {
if (empty($_offsets['daylightMonth']) && (empty($_daylightTransition) || empty($_daylightTransition['isdst']))) {
// No DST
return true;
}
$daylightOffset = ($_offsets['bias'] + $_offsets['daylightBias']) * 60 * -1;
// the milestone is sending a positive value for daylightBias while it should send a negative value
$daylightOffsetMilestone = ($_offsets['bias'] + ($_offsets['daylightBias'] * -1) ) * 60 * -1;
if ($daylightOffset == $_daylightTransition['offset'] || $daylightOffsetMilestone == $_daylightTransition['offset']) {
$standardDate = new DateTime($_standardTransition['time'], $tz);
$daylightDate = new DateTime($_daylightTransition['time'], $tz);
if ($standardDate->format('n') == $_offsets['standardMonth'] &&
$daylightDate->format('n') == $_offsets['daylightMonth'] &&
$standardDate->format('w') == $_offsets['standardDayOfWeek'] &&
$daylightDate->format('w') == $_offsets['daylightDayOfWeek']
) {
return $this->_isNthOcurrenceOfWeekdayInMonth($daylightDate, $_offsets['daylightDay']) &&
$this->_isNthOcurrenceOfWeekdayInMonth($standardDate, $_offsets['standardDay']);
}
}
}
return false;
}
/**
* decode timezone info from activesync
*
* @param string $_packedTimezoneInfo the packed timezone info
* @return array
*/
protected function _unpackTimezoneInfo($_packedTimezoneInfo)
{
$timezoneUnpackString = 'lbias/a64standardName/vstandardYear/vstandardMonth/vstandardDayOfWeek/vstandardDay/vstandardHour/vstandardMinute/vstandardSecond/vstandardMilliseconds/lstandardBias/a64daylightName/vdaylightYear/vdaylightMonth/vdaylightDayOfWeek/vdaylightDay/vdaylightHour/vdaylightMinute/vdaylightSecond/vdaylightMilliseconds/ldaylightBias';
$timezoneInfo = unpack($timezoneUnpackString, base64_decode($_packedTimezoneInfo));
return $timezoneInfo;
}
/**
* encode timezone info to activesync
*
* @param array $_timezoneInfo
* @return string
*/
protected function _packTimezoneInfo($_timezoneInfo)
{
if (!is_array($_timezoneInfo)) {
return null;
}
$packed = pack(
"la64vvvvvvvvla64vvvvvvvvl",
$_timezoneInfo['bias'],
$_timezoneInfo['standardName'],
$_timezoneInfo['standardYear'],
$_timezoneInfo['standardMonth'],
$_timezoneInfo['standardDayOfWeek'],
$_timezoneInfo['standardDay'],
$_timezoneInfo['standardHour'],
$_timezoneInfo['standardMinute'],
$_timezoneInfo['standardSecond'],
$_timezoneInfo['standardMilliseconds'],
$_timezoneInfo['standardBias'],
$_timezoneInfo['daylightName'],
$_timezoneInfo['daylightYear'],
$_timezoneInfo['daylightMonth'],
$_timezoneInfo['daylightDayOfWeek'],
$_timezoneInfo['daylightDay'],
$_timezoneInfo['daylightHour'],
$_timezoneInfo['daylightMinute'],
$_timezoneInfo['daylightSecond'],
$_timezoneInfo['daylightMilliseconds'],
$_timezoneInfo['daylightBias']
);
return base64_encode($packed);
}
/**
* Returns complete offsets array with all fields empty
*
* Used e.g. when reverse-generating ActiveSync Timezone Offset Information
* based on a given Timezone, {@see getOffsetsForTimezone}
*
* @return unknown_type
*/
protected function _getOffsetsTemplate()
{
return array(
'bias' => 0,
'standardName' => '',
'standardYear' => 0,
'standardMonth' => 0,
'standardDayOfWeek' => 0,
'standardDay' => 0,
'standardHour' => 0,
'standardMinute' => 0,
'standardSecond' => 0,
'standardMilliseconds' => 0,
'standardBias' => 0,
'daylightName' => '',
'daylightYear' => 0,
'daylightMonth' => 0,
'daylightDayOfWeek' => 0,
'daylightDay' => 0,
'daylightHour' => 0,
'daylightMinute' => 0,
'daylightSecond' => 0,
'daylightMilliseconds' => 0,
'daylightBias' => 0
);
}
/**
* Validate and set offsets
*
* @param array $value
*
* @return bool Validation result
*/
protected function _validateOffsets($value)
{
// validate $value
if ((!empty($value['standardMonth']) || !empty($value['standardDay']) || !empty($value['daylightMonth']) || !empty($value['daylightDay'])) &&
(empty($value['standardMonth']) || empty($value['standardDay']) || empty($value['daylightMonth']) || empty($value['daylightDay']))
) {
// It is not possible not set standard offsets without setting daylight offsets and vice versa
return false;
}
return true;
}
/**
* Parse and set object property {@see $_startDate}
*
* @param string|int $_startDate
* @return void
*/
protected function _setStartDate($_startDate)
{
if (empty($_startDate)) {
$this->_setDefaultStartDateIfEmpty();
return;
}
$startDateParsed = array();
if (is_string($_startDate)) {
$startDateParsed['string'] = $_startDate;
$startDateParsed['ts'] = strtotime($_startDate);
}
else if (is_int($_startDate)) {
$startDateParsed['ts'] = $_startDate;
$startDateParsed['string'] = strftime('%F', $_startDate);
}
else {
$this->_setDefaultStartDateIfEmpty();
return;
}
$startDateParsed['object'] = new DateTime($startDateParsed['string']);
$startDateParsed = array_merge($startDateParsed, getdate($startDateParsed['ts']));
$this->_startDate = $startDateParsed;
}
/**
* Set default value for object property {@see $_startdate} if it is not set yet.
* Tries to guess the correct startDate depending on object property {@see $_offsets} and
* falls back to current date.
*
* @param array $_offsets [offsets may be avaluated for a given start year]
* @return void
*/
protected function _setDefaultStartDateIfEmpty($_offsets = null)
{
if (!empty($this->_startDate)) {
return;
}
if (!empty($_offsets['standardYear'])) {
$this->_setStartDate($_offsets['standardYear'].'-01-01');
}
else {
$this->_setStartDate(time());
}
}
/**
* Check if the given {@param $_timezone} matches the {@see $_offsets}
* and also evaluate the daylight saving time transitions for this timezone if necessary.
*
* @param DateTimeZone $timezone
* @param array $offsets
*
* @return array|bool
*/
protected function _checkTimezone(DateTimeZone $timezone, $offsets)
{
list($standardTransition, $daylightTransition) = $this->_getTransitionsForTimezoneAndYear($timezone, $this->_startDate['year']);
if ($this->_checkTransition($standardTransition, $daylightTransition, $offsets, $timezone)) {
return $standardTransition;
}
return false;
}
/**
* Returns the standard and daylight transitions for the given {@param $_timezone}
* and {@param $_year}.
*
* @param DateTimeZone $_timezone
* @param int $_year
*
* @return array
*/
protected function _getTransitionsForTimezoneAndYear(DateTimeZone $_timezone, $_year)
{
$standardTransition = null;
$daylightTransition = null;
$start = mktime(0, 0, 0, 12, 1, $_year - 1);
$end = mktime(24, 0, 0, 12, 31, $_year);
$transitions = $_timezone->getTransitions($start, $end);
if ($transitions === false) {
return array();
}
foreach ($transitions as $index => $transition) {
if (strftime('%Y', $transition['ts']) == $_year) {
if (isset($transitions[$index+1]) && strftime('%Y', $transitions[$index]['ts']) == strftime('%Y', $transitions[$index+1]['ts'])) {
$daylightTransition = $transition['isdst'] ? $transition : $transitions[$index+1];
$standardTransition = $transition['isdst'] ? $transitions[$index+1] : $transition;
}
else {
$daylightTransition = $transition['isdst'] ? $transition : null;
$standardTransition = $transition['isdst'] ? null : $transition;
}
break;
}
else if ($index == count($transitions) -1) {
$standardTransition = $transition;
}
}
return array($standardTransition, $daylightTransition);
}
protected function _getCacheId($_prefix, $_offsets)
{
return $_prefix . md5(serialize($_offsets));
}
protected function _loadFromCache($key)
{
if ($cache = $this->getCache) {
return $cache->get($key);
}
return false;
}
protected function _saveInCache($value, $key)
{
if ($cache = $this->getCache) {
$cache->set($key, $value);
}
}
/**
* Getter for the cache engine object
*/
protected function getCache()
{
if ($this->cache === null) {
$rcube = rcube::get_instance();
$cache = $rcube->get_cache_shared('activesync');
$this->cache = $cache ? $cache : false;
}
return $this->cache;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Aug 17, 12:00 PM (19 h, 38 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1261440
Default Alt Text
(33 KB)

Event Timeline