Optimized SyncML memory footprint; fixes various filter issues

This commit is contained in:
Jörg Lehrke 2009-11-29 14:03:45 +00:00
parent 7c67b5bd59
commit a0e1a238dd
3 changed files with 78 additions and 40 deletions

View File

@ -86,6 +86,13 @@ class calendar_ical extends calendar_boupdate
*/ */
var $uidExtension = false; var $uidExtension = false;
/**
* user preference: calendar to synchronize with
*
* @var int
*/
var $calendarOwner = 0;
/** /**
* Original timezone * Original timezone
* *
@ -942,6 +949,7 @@ class calendar_ical extends calendar_boupdate
unset($event_to_store); unset($event_to_store);
$event['reference'] = $event_info['master_event']['id']; $event['reference'] = $event_info['master_event']['id'];
$event['category'] = $event_info['master_event']['category']; $event['category'] = $event_info['master_event']['category'];
$event['owner'] = $event_info['master_event']['owner'];
} }
$event_to_store = $event; // prevent $event from being changed by update method $event_to_store = $event; // prevent $event from being changed by update method
@ -1160,6 +1168,14 @@ class calendar_ical extends calendar_boupdate
{ {
$this->tzid = $deviceInfo['tzid']; $this->tzid = $deviceInfo['tzid'];
} }
if (isset($GLOBALS['egw_info']['user']['preferences']['syncml']['calendar_owner']))
{
$owner = $GLOBALS['egw_info']['user']['preferences']['syncml']['calendar_owner'];
if (0 < (int)$owner && $this->check_perms(EGW_ACL_EDIT,0,$owner))
{
$this->calendarOwner = $owner;
}
}
if (!isset($this->productManufacturer) || if (!isset($this->productManufacturer) ||
$this->productManufacturer == '' || $this->productManufacturer == '' ||
$this->productManufacturer == 'file') $this->productManufacturer == 'file')
@ -1549,7 +1565,7 @@ class calendar_ical extends calendar_boupdate
$recurence = $attributes['value']; $recurence = $attributes['value'];
$type = preg_match('/FREQ=([^;: ]+)/i',$recurence,$matches) ? $matches[1] : $recurence[0]; $type = preg_match('/FREQ=([^;: ]+)/i',$recurence,$matches) ? $matches[1] : $recurence[0];
// vCard 2.0 values for all types // vCard 2.0 values for all types
if (preg_match('/UNTIL=([0-9T]+)/',$recurence,$matches)) if (preg_match('/UNTIL=([0-9TZ]+)/',$recurence,$matches))
{ {
$vcardData['recur_enddate'] = $this->vCalendar->_parseDateTime($matches[1]); $vcardData['recur_enddate'] = $this->vCalendar->_parseDateTime($matches[1]);
} }
@ -1886,11 +1902,7 @@ class calendar_ical extends calendar_boupdate
{ {
//Horde::logMessage("vevent2egw: group participant $uid", //Horde::logMessage("vevent2egw: group participant $uid",
// __FILE__, __LINE__, PEAR_LOG_DEBUG); // __FILE__, __LINE__, PEAR_LOG_DEBUG);
if ($status == 'U') if ($status != 'U')
{
}
else
{ {
// User tries to reply to the group invitiation // User tries to reply to the group invitiation
$members = $GLOBALS['egw']->accounts->members($uid, true); $members = $GLOBALS['egw']->accounts->members($uid, true);
@ -1904,7 +1916,7 @@ class calendar_ical extends calendar_boupdate
continue; continue;
} }
} }
else continue; // can not find this group else continue; // can't find this group
} }
elseif ($attributes['value'] == 'Unknown') elseif ($attributes['value'] == 'Unknown')
{ {
@ -1954,12 +1966,14 @@ class calendar_ical extends calendar_boupdate
$event['participants'][$uid] = $event['participants'][$uid] =
calendar_so::combine_status($status, $quantity, 'CHAIR'); calendar_so::combine_status($status, $quantity, 'CHAIR');
} }
if (is_numeric($uid)) if (is_numeric($uid) && ($uid == $this->calendarOwner || !$this->calendarOwner))
{ {
// we can store the ORGANIZER as event owner
$event['owner'] = $uid; $event['owner'] = $uid;
} }
else else
{ {
// we must insert a CHAIR participant to keep the ORGANIZER
$event['owner'] = $this->user; $event['owner'] = $this->user;
if (!isset($event['participants'][$uid])) if (!isset($event['participants'][$uid]))
{ {
@ -1968,7 +1982,6 @@ class calendar_ical extends calendar_boupdate
calendar_so::combine_status('U', 1, 'CHAIR'); calendar_so::combine_status('U', 1, 'CHAIR');
} }
} }
break;
} }
break; break;
case 'CREATED': // will be written direct to the event case 'CREATED': // will be written direct to the event
@ -2048,6 +2061,7 @@ class calendar_ical extends calendar_boupdate
break; break;
} }
} }
if ($this->calendarOwner) $event['owner'] = $this->calendarOwner;
//Horde::logMessage("vevent2egw:\n" . print_r($event, true), //Horde::logMessage("vevent2egw:\n" . print_r($event, true),
// __FILE__, __LINE__, PEAR_LOG_DEBUG); // __FILE__, __LINE__, PEAR_LOG_DEBUG);
return $event; return $event;
@ -2239,8 +2253,8 @@ class calendar_ical extends calendar_boupdate
$recurrence_event['start'] = $event['recurrence']; $recurrence_event['start'] = $event['recurrence'];
$recurrence_event['end'] = $event['recurrence'] + ($master_event['end'] - $master_event['start']); $recurrence_event['end'] = $event['recurrence'] + ($master_event['end'] - $master_event['start']);
// check for changed data // check for changed data
foreach (array('start','end','uid','owner','title','description', foreach (array('start','end','uid','title','location',
'location','priority','public','special','non_blocking') as $key) 'priority','public','special','non_blocking') as $key)
{ {
if (!empty($event[$key]) && $recurrence_event[$key] != $event[$key]) if (!empty($event[$key]) && $recurrence_event[$key] != $event[$key])
{ {

View File

@ -935,6 +935,8 @@ ORDER BY cal_user_type, cal_usre_id
*/ */
function participants($cal_id,$participants,$change_since=0,$add_only=false) function participants($cal_id,$participants,$change_since=0,$add_only=false)
{ {
$recurrences = array();
// remove group-invitations, they are NOT stored in the db // remove group-invitations, they are NOT stored in the db
foreach($participants as $uid => $status) foreach($participants as $uid => $status)
{ {
@ -950,8 +952,15 @@ ORDER BY cal_user_type, cal_usre_id
$where[0] = '(cal_recur_date=0 OR cal_recur_date >= '.(int)$change_since.')'; $where[0] = '(cal_recur_date=0 OR cal_recur_date >= '.(int)$change_since.')';
} }
if ($change_since !== false) // update existing entries if ($change_since !== false)
{ {
// find all existing recurrences
foreach($this->db->select($this->user_table,'DISTINCT cal_recur_date',$where,__LINE__,__FILE__,false,'','calendar') as $row)
{
$recurrences[] = $row['cal_recur_date'];
}
// update existing entries
$existing_entries = $this->db->select($this->user_table,'DISTINCT cal_user_type,cal_user_id',$where,__LINE__,__FILE__,false,'','calendar'); $existing_entries = $this->db->select($this->user_table,'DISTINCT cal_user_type,cal_user_id',$where,__LINE__,__FILE__,false,'','calendar');
// create a full list of participants which already exist in the db // create a full list of participants which already exist in the db
@ -999,16 +1008,7 @@ ORDER BY cal_user_type, cal_usre_id
if (count($participants)) // participants which need to be added if (count($participants)) // participants which need to be added
{ {
// find all recurrences, as they all need the new parts to be added if (!count($recurrences)) $recurrences[] = 0; // insert the default recurrence
$recurrences = array();
if ($change_since !== false) // existing entries
{
foreach($this->db->select($this->user_table,'DISTINCT cal_recur_date',$where,__LINE__,__FILE__,false,'','calendar') as $row)
{
$recurrences[] = $row['cal_recur_date'];
}
}
if (!count($recurrences)) $recurrences[] = 0; // insert the default one
// update participants // update participants
foreach($participants as $uid => $status) foreach($participants as $uid => $status)
@ -1315,7 +1315,7 @@ ORDER BY cal_user_type, cal_usre_id
{ {
$user_type = ''; $user_type = '';
$user_id = null; $user_id = null;
$this->split_user($old_user,$user_type,$user_id); self::split_user($old_user,$user_type,$user_id);
if ($user_type == 'u') // only accounts can be owners of events if ($user_type == 'u') // only accounts can be owners of events
{ {
@ -1369,14 +1369,24 @@ ORDER BY cal_user_type, cal_usre_id
* *
* @param int $cal_id * @param int $cal_id
* @param int $uid participant uid * @param int $uid participant uid
* @param int $start=0 if != 0: startdate of the search/list (servertime)
* @param int $end=0 if != 0: enddate of the search/list (servertime)
*
* @return array recur_date => status pairs (index 0 => main status) * @return array recur_date => status pairs (index 0 => main status)
*/ */
function get_recurrences($cal_id, $uid) function get_recurrences($cal_id, $uid, $start=0, $end=0)
{ {
$user_type = $user_id = null; $user_type = $user_id = null;
$this->split_user($uid, $user_type, $user_id); self::split_user($uid, $user_type, $user_id);
$participant_status = array(); $participant_status = array();
$where = array('cal_id' => $cal_id); $where = array('cal_id' => $cal_id);
if ($start != 0 && $end == 0) $where[] = '(cal_recur_date = 0 OR cal_recur_date >= ' . (int)$start . ')';
if ($start == 0 && $end != 0) $where[] = '(cal_recur_date = 0 OR cal_recur_date =< ' . (int)$end . ')';
if ($start != 0 && $end != 0)
{
$where[] = '(cal_recur_date = 0 OR (cal_recur_date >= ' . (int)$start .
' AND cal_recur_date <= ' . (int)$end . '))';
}
foreach($this->db->select($this->user_table,'DISTINCT cal_recur_date',$where,__LINE__,__FILE__,false,'','calendar') as $row) foreach($this->db->select($this->user_table,'DISTINCT cal_recur_date',$where,__LINE__,__FILE__,false,'','calendar') as $row)
{ {
// inititalize the array // inititalize the array
@ -1387,6 +1397,13 @@ ORDER BY cal_user_type, cal_usre_id
'cal_user_type' => $user_type ? $user_type : 'u', 'cal_user_type' => $user_type ? $user_type : 'u',
'cal_user_id' => $user_id, 'cal_user_id' => $user_id,
); );
if ($start != 0 && $end == 0) $where[] = '(cal_recur_date = 0 OR cal_recur_date >= ' . (int)$start . ')';
if ($start == 0 && $end != 0) $where[] = '(cal_recur_date = 0 OR cal_recur_date =< ' . (int)$end . ')';
if ($start != 0 && $end != 0)
{
$where[] = '(cal_recur_date = 0 OR (cal_recur_date >= ' . (int)$start .
' AND cal_recur_date <= ' . (int)$end . '))';
}
foreach ($this->db->select($this->user_table,'cal_recur_date,cal_status,cal_quantity,cal_role',$where, foreach ($this->db->select($this->user_table,'cal_recur_date,cal_status,cal_quantity,cal_role',$where,
__LINE__,__FILE__,false,'','calendar') as $row) __LINE__,__FILE__,false,'','calendar') as $row)
{ {
@ -1416,7 +1433,7 @@ ORDER BY cal_user_type, cal_usre_id
foreach ($this->db->select($this->user_table,'DISTINCT cal_user_type,cal_user_id', $where, foreach ($this->db->select($this->user_table,'DISTINCT cal_user_type,cal_user_id', $where,
__LINE__,__FILE__,false,'','calendar') as $row) __LINE__,__FILE__,false,'','calendar') as $row)
{ {
$uid = $this->combine_user($row['cal_user_type'], $row['cal_user_id']); $uid = self::combine_user($row['cal_user_type'], $row['cal_user_id']);
$id = $row['cal_user_type'] . $row['cal_user_id']; $id = $row['cal_user_type'] . $row['cal_user_id'];
$participants[$id]['type'] = $row['cal_user_type']; $participants[$id]['type'] = $row['cal_user_type'];
$participants[$id]['id'] = $row['cal_user_id']; $participants[$id]['id'] = $row['cal_user_id'];
@ -1456,10 +1473,12 @@ ORDER BY cal_user_type, cal_usre_id
* *
* @param array $event Recurring Event. * @param array $event Recurring Event.
* @param string tz_id=null timezone for exports (null for event's timezone) * @param string tz_id=null timezone for exports (null for event's timezone)
* @param int $start=0 if != 0: startdate of the search/list (servertime)
* @param int $end=0 if != 0: enddate of the search/list (servertime)
* *
* @return array Array of exception days (false for non-recurring events). * @return array Array of exception days (false for non-recurring events).
*/ */
function get_recurrence_exceptions(&$event, $tz_id=null) function get_recurrence_exceptions(&$event, $tz_id=null, $start=0, $end=0)
{ {
$cal_id = (int) $event['id']; $cal_id = (int) $event['id'];
if (!$cal_id || $event['recur_type'] == MCAL_RECUR_NONE) return false; if (!$cal_id || $event['recur_type'] == MCAL_RECUR_NONE) return false;
@ -1489,7 +1508,7 @@ ORDER BY cal_user_type, cal_usre_id
case 'u': // account case 'u': // account
case 'c': // contact case 'c': // contact
case 'e': // email address case 'e': // email address
$recurrences = $this->get_recurrences($event['id'], $uid); $recurrences = $this->get_recurrences($event['id'], $uid, $start, $end);
foreach ($recurrences as $recur_date => $recur_status) foreach ($recurrences as $recur_date => $recur_status)
{ {
if ($recur_date) if ($recur_date)

View File

@ -423,15 +423,28 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
'type' => $syncType, 'type' => $syncType,
'filter' => $this->_filterExpression 'filter' => $this->_filterExpression
))); )));
$state->mergeChangedItems($syncType, $registry->call($hordeType . '/listBy', array (
$changedItems =& $registry->call($hordeType . '/listBy', array (
'action' => 'modify', 'action' => 'modify',
'timestamp' => $refts, 'timestamp' => $refts,
'type' => $syncType, 'type' => $syncType,
'filter' => $this->_filterExpression 'filter' => $this->_filterExpression
))); ));
$addedItems =& $registry->call($hordeType . '/listBy', array (
'action' => 'add',
'timestamp' => $refts,
'type' => $syncType,
'filter' => $this->_filterExpression
));
// added items may show up as changed, too
$changedItems = array_diff($changedItems, $addedItems);
$state->mergeChangedItems($syncType, $changedItems);
$state->mergeAddedItems($syncType, $addedItems);
Horde :: logMessage("SyncML: reading deleted items from database for $hordeType",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$state->setDeletedItems($syncType, $registry->call($hordeType . '/listBy', array ( $state->setDeletedItems($syncType, $registry->call($hordeType . '/listBy', array (
'action' => 'delete', 'action' => 'delete',
'timestamp' => $refts, 'timestamp' => $refts,
@ -439,8 +452,6 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
'filter' => $this->_filterExpression 'filter' => $this->_filterExpression
))); )));
Horde :: logMessage("SyncML: reading added items from database for $hordeType",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
/* The items, which now match the filter criteria are show here, too /* The items, which now match the filter criteria are show here, too
$delta_add = count($registry->call($hordeType . '/listBy', array ( $delta_add = count($registry->call($hordeType . '/listBy', array (
'action' => 'add', 'action' => 'add',
@ -449,12 +460,6 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
'filter' => $this->_filterExpression 'filter' => $this->_filterExpression
))); )));
*/ */
$state->mergeAddedItems($syncType, $registry->call($hordeType . '/listBy', array (
'action' => 'add',
'timestamp' => $refts,
'type' => $syncType,
'filter' => $this->_filterExpression
)));
$this->_syncDataLoaded = TRUE; $this->_syncDataLoaded = TRUE;