forked from extern/egroupware
- merged SyncML-1.2 branch with trunk:
svn merge -r 26935:HEAD ^/branches/SyncML-1.2/calendar . - with the exception of class.calendar_uiforms.inc.php, as it was not updated with the latest changes from trunk and I'm not sure about the changes --> needs further discussion, sorry :-( svn revert inc/class.calendar_uiforms.inc.php
This commit is contained in:
parent
036b2cd14e
commit
cb0fc5db82
@ -5,6 +5,7 @@
|
||||
* @link http://www.egroupware.org
|
||||
* @package calendar
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @author Joerg Lehrke <jlehrke@noc.de>
|
||||
* @copyright (c) 2004-8 by RalfBecker-At-outdoor-training.de
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @version $Id$
|
||||
@ -134,6 +135,7 @@ class calendar_bo
|
||||
*/
|
||||
protected static $cached_event = array();
|
||||
protected static $cached_event_date_format = false;
|
||||
protected static $cached_event_date = 0;
|
||||
/**
|
||||
* @var array $cached_holidays holidays plus birthdays (gets cached in the session for performance reasons)
|
||||
*/
|
||||
@ -570,9 +572,17 @@ class calendar_bo
|
||||
|
||||
$events = array();
|
||||
$this->insert_all_repetitions($event,$start,$this->date2ts($this->config['horizont'],true),$events,null);
|
||||
|
||||
$days = $this->so->get_recurrence_exceptions($event);
|
||||
$days = is_array($days) ? $days : array();
|
||||
//error_log('set_recurrences: days' . print_r($days, true) );
|
||||
foreach($events as $event)
|
||||
{
|
||||
//error_log('set_recurrences: start = ' . $event['start'] );
|
||||
if (in_array($event['start'], $days))
|
||||
{
|
||||
// we don't change the stati of recurrence exceptions
|
||||
$event['participants'] = array();
|
||||
}
|
||||
$this->so->recurrence($event['id'],$this->date2ts($event['start'],true),$this->date2ts($event['end'],true),$event['participants']);
|
||||
}
|
||||
}
|
||||
@ -657,8 +667,8 @@ class calendar_bo
|
||||
if ($ignore_acl || is_array($ids) || ($return = $this->check_perms(EGW_ACL_READ,$ids,0,$date_format,$date)))
|
||||
{
|
||||
if (is_array($ids) || !isset(self::$cached_event['id']) || self::$cached_event['id'] != $ids ||
|
||||
self::$cached_event_date_format != $date_format ||
|
||||
self::$cached_event['recur_type'] != MCAL_RECUR_NONE && !is_null($date) && (!$date || self::$cached_event['start'] < $date))
|
||||
self::$cached_event_date_format != $date_format ||
|
||||
self::$cached_event['recur_type'] != MCAL_RECUR_NONE && !is_null($date) && self::$cached_event_date != $date || (!$date || self::$cached_event['start'] < $date))
|
||||
{
|
||||
$events = $this->so->read($ids,$date ? $this->date2ts($date,true) : 0);
|
||||
|
||||
@ -674,6 +684,7 @@ class calendar_bo
|
||||
{
|
||||
self::$cached_event = array_shift($events);
|
||||
self::$cached_event_date_format = $date_format;
|
||||
self::$cached_event_date = $date;
|
||||
$return =& self::$cached_event;
|
||||
}
|
||||
}
|
||||
@ -753,6 +764,8 @@ class calendar_bo
|
||||
{
|
||||
$search_date_ymd = (int)$this->date2string($ts);
|
||||
|
||||
//error_log('insert_all_repetitions search_date = ' . $search_date_ymd . ' => ' . print_r($recur_exceptions, true));
|
||||
|
||||
$have_exception = !is_null($recur_exceptions) && isset($recur_exceptions[$search_date_ymd]);
|
||||
|
||||
if (!$have_exception) // no execption by an edited event => check the deleted ones
|
||||
@ -928,7 +941,7 @@ class calendar_bo
|
||||
{
|
||||
if (is_numeric($uid))
|
||||
{
|
||||
$info = array(
|
||||
$info = array(
|
||||
'res_id' => $uid,
|
||||
'email' => $GLOBALS['egw']->accounts->id2name($uid,'account_email'),
|
||||
'name' => trim($GLOBALS['egw']->accounts->id2name($uid,'account_firstname'). ' ' .
|
||||
@ -1840,4 +1853,20 @@ class calendar_bo
|
||||
$GLOBALS['egw_info']['server']['webserver_url'].'/calendar/freebusy.php?user='.urlencode($user).
|
||||
($pw ? '&password='.urlencode($pw) : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the event is the whole day
|
||||
*
|
||||
* @param event
|
||||
* @return boolean true for whole day events
|
||||
*/
|
||||
function isWholeDay($event)
|
||||
{
|
||||
// check if the event is the whole day
|
||||
$start = $this->date2array($event['start']);
|
||||
$end = $this->date2array($event['end']);
|
||||
$result = (!$start['hour'] && !$start['minute']
|
||||
&& $end['hour'] == 23 && $end['minute'] == 59);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
* @link http://www.egroupware.org
|
||||
* @package calendar
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @author Joerg Lehrke <jlehrke@noc.de>
|
||||
* @copyright (c) 2005-8 by RalfBecker-At-outdoor-training.de
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @version $Id$
|
||||
@ -73,7 +74,7 @@ class calendar_boupdate extends calendar_bo
|
||||
* @param array &$event event-array, on return some values might be changed due to set defaults
|
||||
* @param boolean $ignore_conflicts=false just ignore conflicts or do a conflict check and return the conflicting events
|
||||
* @param boolean $touch_modified=true touch modificatin time and set modifing user, default true=yes
|
||||
* @param boolean $ignore_acl=flase should we ignore the acl
|
||||
* @param boolean $ignore_acl=false should we ignore the acl
|
||||
* @return mixed on success: int $cal_id > 0, on error false or array with conflicting events (only if $check_conflicts)
|
||||
* Please note: the events are not garantied to be readable by the user (no read grant or private)!
|
||||
*/
|
||||
@ -256,7 +257,7 @@ class calendar_boupdate extends calendar_bo
|
||||
//echo "saving $event[id]="; _debug_array($event);
|
||||
$event2save = $event;
|
||||
|
||||
if (!($cal_id = $this->save($event)))
|
||||
if (!($cal_id = $this->save($event, $ignore_acl)))
|
||||
{
|
||||
return $cal_id;
|
||||
}
|
||||
@ -572,7 +573,7 @@ class calendar_boupdate extends calendar_bo
|
||||
break;
|
||||
|
||||
case 'ical':
|
||||
$ics = ExecMethod2('calendar.calendar_ical.exportVCal',$event['id'],'2.0',$method,false);
|
||||
$ics = ExecMethod2('calendar.calendar_ical.exportVCal',$event['id'],'2.0',$method);
|
||||
if ($method == 'REQUEST')
|
||||
{
|
||||
$attachment = array( 'string' => $ics,
|
||||
@ -666,15 +667,16 @@ class calendar_boupdate extends calendar_bo
|
||||
* This methode converts from user to server time and handles the insertion of users and dates of repeating events
|
||||
*
|
||||
* @param array $event
|
||||
* @param boolean $ignore_acl=false should we ignore the acl
|
||||
* @return int/boolean $cal_id > 0 or false on error (eg. permission denied)
|
||||
*/
|
||||
function save($event)
|
||||
function save($event, $ignore_acl=false)
|
||||
{
|
||||
//error_log(__METHOD__."(".str_replace(array("\n",' '),'',print_r($event,true)).",$etag)");
|
||||
// check if user has the permission to update / create the event
|
||||
if ($event['id'] && !$this->check_perms(EGW_ACL_EDIT,$event['id']) ||
|
||||
if (!$ignore_acl && ($event['id'] && !$this->check_perms(EGW_ACL_EDIT,$event['id']) ||
|
||||
!$event['id'] && !$this->check_perms(EGW_ACL_EDIT,0,$event['owner']) &&
|
||||
!$this->check_perms(EGW_ACL_ADD,0,$event['owner']))
|
||||
!$this->check_perms(EGW_ACL_ADD,0,$event['owner'])))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -705,10 +707,11 @@ class calendar_boupdate extends calendar_bo
|
||||
$event['alarm'][$id]['time'] = $this->date2ts($alarm['time'],true);
|
||||
}
|
||||
}
|
||||
if (($cal_id = $this->so->save($event,$set_recurrences,NULL,$event['etag'])) && $set_recurrences && $event['recur_type'] != MCAL_RECUR_NONE)
|
||||
$set_recurrences = false;
|
||||
if (($cal_id = $this->so->save($event,$set_recurrences,0,$event['etag'])) && $set_recurrences && $event['recur_type'] != MCAL_RECUR_NONE)
|
||||
{
|
||||
$save_event['id'] = $cal_id;
|
||||
$this->set_recurrences($save_event);
|
||||
$this->set_recurrences($save_event, 0);
|
||||
}
|
||||
$GLOBALS['egw']->contenthistory->updateTimeStamp('calendar',$cal_id,$event['id'] ? 'modify' : 'add',time());
|
||||
|
||||
@ -749,13 +752,14 @@ class calendar_boupdate extends calendar_bo
|
||||
* @param string/int $uid account_id or 1-char type-identifer plus id (eg. c15 for addressbook entry #15)
|
||||
* @param int/char $status numeric status (defines) or 1-char code: 'R', 'U', 'T' or 'A'
|
||||
* @param int $recur_date=0 date to change, or 0 = all since now
|
||||
* @param boolean $ignore_acl=false do not check the permisions for the $uid, if true
|
||||
* @return int number of changed recurrences
|
||||
*/
|
||||
function set_status($event,$uid,$status,$recur_date=0)
|
||||
function set_status($event,$uid,$status,$recur_date=0, $ignore_acl=false)
|
||||
{
|
||||
$cal_id = is_array($event) ? $event['id'] : $event;
|
||||
//echo "<p>bocalupdate::set_status($cal_id,$uid,$status,$recur_date)</p>\n";
|
||||
if (!$cal_id || !$this->check_status_perms($uid,$event))
|
||||
if (!$cal_id || (!$ignore_acl && !$this->check_status_perms($uid,$event)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -1006,7 +1010,9 @@ class calendar_boupdate extends calendar_bo
|
||||
}
|
||||
$alarm['time'] = $this->date2ts($alarm['time'],true); // user to server-time
|
||||
|
||||
return $this->so->save_alarm($cal_id,$alarm);
|
||||
$GLOBALS['egw']->contenthistory->updateTimeStamp('calendar',$cal_id, 'modify', time());
|
||||
|
||||
return $this->so->save_alarm($cal_id,$alarm, $this->now_su);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1023,7 +1029,10 @@ class calendar_boupdate extends calendar_bo
|
||||
{
|
||||
return false; // no rights to delete the alarm
|
||||
}
|
||||
return $this->so->delete_alarm($id);
|
||||
|
||||
$GLOBALS['egw']->contenthistory->updateTimeStamp('calendar',$cal_id, 'modify', time());
|
||||
|
||||
return $this->so->delete_alarm($id, $this->now_su);
|
||||
}
|
||||
|
||||
var $categories;
|
||||
@ -1046,7 +1055,7 @@ class calendar_boupdate extends calendar_bo
|
||||
{
|
||||
$cat_name = substr($cat_name, 2);
|
||||
}
|
||||
$cat_id = $this->categories->add(array('name' => $cat_name,'descr' => $cat_name));
|
||||
$cat_id = $this->categories->add(array('name' => $cat_name, 'descr' => $cat_name, 'access' => 'private'));
|
||||
}
|
||||
|
||||
if ($cat_id)
|
||||
@ -1086,4 +1095,95 @@ class calendar_boupdate extends calendar_bo
|
||||
|
||||
return $cat_list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find a matching db entry
|
||||
*
|
||||
* @param array $event the vCalendar data we try to find
|
||||
* @param boolean $relax=false if asked to relax, we only match against some key fields
|
||||
* @return the calendar_id of the matching entry or false (if none matches)
|
||||
*/
|
||||
function find_event($event, $relax=false)
|
||||
{
|
||||
if ($event['uid'] && ($uidmatch = $this->read($event['uid'])))
|
||||
{
|
||||
if ($event['reference']
|
||||
&& ($egw_event = $this->read($uidmatch['id'], $event['reference'])))
|
||||
{
|
||||
// Do we work with a "status only" exception here?
|
||||
$match = true;
|
||||
foreach (array('start','end','title','description','priority',
|
||||
'location','public','non_blocking') as $name)
|
||||
{
|
||||
if (isset($event[$name])
|
||||
&& $event[$name] != $egw_event[$name])
|
||||
{
|
||||
$match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($match)
|
||||
{
|
||||
//return ($uidmatch['id'] . ':' . $event['reference']);
|
||||
foreach ($event['participants'] as $attendee => $status)
|
||||
{
|
||||
if (!isset($egw_event['participants'][$attendee])
|
||||
|| $egw_event['participants'][$attendee] != $status)
|
||||
{
|
||||
$match = false;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
unset($egw_event['participants'][$attendee]);
|
||||
}
|
||||
}
|
||||
if ($match && !empty($egw_event['participants'])) $match = false;
|
||||
}
|
||||
if ($match) return ($uidmatch['id'] . ':' . $event['reference']);
|
||||
|
||||
return false; // We need to create a new "status only" exception
|
||||
}
|
||||
else
|
||||
{
|
||||
return $uidmatch['id'];
|
||||
}
|
||||
}
|
||||
|
||||
if ($event['id'] && ($found = $this->read($event['id'])))
|
||||
{
|
||||
// We only do a simple consistency check
|
||||
if ($found['title'] == $event['title']
|
||||
&& $found['start'] == $event['start']
|
||||
&& $found['end'] == $event['end'])
|
||||
{
|
||||
return $found['id'];
|
||||
}
|
||||
}
|
||||
unset($event['id']);
|
||||
|
||||
$query = array(
|
||||
'cal_start='.$event['start'],
|
||||
'cal_end='.$event['end'],
|
||||
);
|
||||
|
||||
#foreach(array('title','location','priority','public','non_blocking','category') as $name) {
|
||||
foreach (array('title','location','public','non_blocking','category') as $name)
|
||||
{
|
||||
if (!empty($event[$name])) $query['cal_'.$name] = $event[$name];
|
||||
}
|
||||
|
||||
if($foundEvents = parent::search(array(
|
||||
//'user' => $this->user,
|
||||
'query' => $query,
|
||||
)))
|
||||
{
|
||||
if(is_array($foundEvents))
|
||||
{
|
||||
$event = array_shift($foundEvents);
|
||||
return $event['id'];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,7 @@
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @author Lars Kneschke <lkneschke@egroupware.org>
|
||||
* @author Joerg Lehrke <jlehrke@noc.de>
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package calendar
|
||||
* @subpackage export
|
||||
@ -21,6 +22,7 @@ class calendar_sif extends calendar_boupdate
|
||||
'Start' => 'start',
|
||||
'End' => 'end',
|
||||
'AllDayEvent' => 'alldayevent',
|
||||
'Attendees' => '',
|
||||
'BillingInformation' => '',
|
||||
'Body' => 'description',
|
||||
'BusyStatus' => '',
|
||||
@ -33,6 +35,11 @@ class calendar_sif extends calendar_boupdate
|
||||
'Mileage' => '',
|
||||
'ReminderMinutesBeforeStart' => 'reminderstart',
|
||||
'ReminderSet' => 'reminderset',
|
||||
'ReminderSoundFile' => '',
|
||||
'ReminderOptions' => '',
|
||||
'ReminderInterval' => '',
|
||||
'ReminderRepeatCount' => '',
|
||||
'Exceptions' => '',
|
||||
'ReplyTime' => '',
|
||||
'Sensitivity' => 'public',
|
||||
'Subject' => 'title',
|
||||
@ -51,6 +58,11 @@ class calendar_sif extends calendar_boupdate
|
||||
// the calendar event array
|
||||
var $event;
|
||||
|
||||
// device specific settings
|
||||
var $productName = 'mozilla plugin';
|
||||
var $productSoftwareVersion = '0.3';
|
||||
var $uidExtension = false;
|
||||
|
||||
// constants for recurence type
|
||||
const olRecursDaily = 0;
|
||||
const olRecursWeekly = 1;
|
||||
@ -68,6 +80,10 @@ class calendar_sif extends calendar_boupdate
|
||||
const olFriday = 32;
|
||||
const olSaturday = 64;
|
||||
|
||||
// standard headers
|
||||
const xml_decl = '<?xml version="1.0" encoding="UTF-8"?>';
|
||||
const SIF_decl = '<SIFVersion>1.1</SIFVersion>';
|
||||
|
||||
function startElement($_parser, $_tag, $_attributes) {
|
||||
}
|
||||
|
||||
@ -87,14 +103,13 @@ class calendar_sif extends calendar_boupdate
|
||||
$vcal = new Horde_iCalendar;
|
||||
$finalEvent = array();
|
||||
$sysCharSet = $GLOBALS['egw']->translation->charset();
|
||||
$sifData = base64_decode($_sifdata);
|
||||
#error_log($sifData);
|
||||
|
||||
$tmpfname = tempnam('/tmp/sync/contents','sife_');
|
||||
#$tmpfname = tempnam('/tmp/sync/contents','sife_');
|
||||
|
||||
$handle = fopen($tmpfname, "w");
|
||||
fwrite($handle, $sifData);
|
||||
fclose($handle);
|
||||
#$handle = fopen($tmpfname, "w");
|
||||
#fwrite($handle, $sifData);
|
||||
#fclose($handle);
|
||||
|
||||
$this->xml_parser = xml_parser_create('UTF-8');
|
||||
xml_set_object($this->xml_parser, $this);
|
||||
@ -111,11 +126,13 @@ class calendar_sif extends calendar_boupdate
|
||||
#error_log(print_r($this->event, true));
|
||||
|
||||
foreach($this->event as $key => $value) {
|
||||
$value = preg_replace('/<\!\[CDATA\[(.+)\]\]>/Usim', '$1', $value);
|
||||
$value = $GLOBALS['egw']->translation->convert($value, 'utf-8', $sysCharSet);
|
||||
#error_log("$key => $value");
|
||||
switch($key) {
|
||||
case 'alldayevent':
|
||||
if($value == 1) {
|
||||
$finalEvent['whole_day'] = true;
|
||||
$startParts = explode('-',$this->event['start']);
|
||||
$finalEvent['start'] = mktime(0, 0, 0, $startParts[1], $startParts[2], $startParts[0]);
|
||||
$endParts = explode('-',$this->event['end']);
|
||||
@ -191,6 +208,11 @@ class calendar_sif extends calendar_boupdate
|
||||
// do nothing, get's handled in isrecuring clause
|
||||
break;
|
||||
|
||||
case 'description':
|
||||
if (preg_match('/\s*\[UID:(.+)?\]/Usm', $value, $matches)) {
|
||||
$finalEvent['uid'] = $matches[1];
|
||||
}
|
||||
|
||||
default:
|
||||
$finalEvent[$key] = $value;
|
||||
break;
|
||||
@ -205,69 +227,32 @@ class calendar_sif extends calendar_boupdate
|
||||
return $finalEvent;
|
||||
}
|
||||
|
||||
function search($_sifdata, $contentID=null) {
|
||||
if(!$event = $this->siftoegw($_sifdata)) {
|
||||
return false;
|
||||
}
|
||||
function search($_sifdata, $contentID=null, $relax=false)
|
||||
{
|
||||
$result = false;
|
||||
|
||||
$query = array(
|
||||
'cal_start='.$this->date2ts($event['start'],true), // true = Server-time
|
||||
'cal_end='.$this->date2ts($event['end'],true),
|
||||
);
|
||||
|
||||
if ($contentID) {
|
||||
$query[] = 'egw_cal.cal_id='.(int)$contentID;
|
||||
}
|
||||
|
||||
#foreach(array('title','location','priority','public','non_blocking') as $name) {
|
||||
foreach(array('title','location','public','non_blocking') as $name) {
|
||||
if (isset($event[$name])) $query['cal_'.$name] = $event[$name];
|
||||
}
|
||||
|
||||
if($foundEvents = parent::search(array(
|
||||
'user' => $this->user,
|
||||
'query' => $query,
|
||||
))) {
|
||||
if(is_array($foundEvents)) {
|
||||
$event = array_shift($foundEvents);
|
||||
return $event['id'];
|
||||
if($event = $this->siftoegw($_sifdata))
|
||||
{
|
||||
if ($contentID) {
|
||||
$event['id'] = $contentID;
|
||||
}
|
||||
$result = $this->find_event($event, $relax);
|
||||
}
|
||||
return false;
|
||||
|
||||
$search['start'] = $event['start'];
|
||||
$search['end'] = $event['end'];
|
||||
|
||||
unset($event['description']);
|
||||
unset($event['start']);
|
||||
unset($event['end']);
|
||||
|
||||
foreach($event as $key => $value) {
|
||||
if (substr($key,0,6) != 'recur_' && substr($key,0,5) != 'alarm') {
|
||||
$search['query']['cal_'.$key] = $value;
|
||||
} else {
|
||||
#$search['query'][$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if($foundEvents = parent::search($search)) {
|
||||
if(is_array($foundEvents)) {
|
||||
$event = array_shift($foundEvents);
|
||||
return $event['id'];
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int contact id
|
||||
* @param string $_vcard the vcard
|
||||
* @param int $_abID the internal addressbook id
|
||||
* @param boolean $merge=false merge data with existing entry
|
||||
* @desc import a vard into addressbook
|
||||
*/
|
||||
function addSIF($_sifdata, $_calID)
|
||||
function addSIF($_sifdata, $_calID, $merge=false)
|
||||
{
|
||||
$state = &$_SESSION['SyncML.state'];
|
||||
$deviceInfo = $state->getClientDeviceInfo();
|
||||
|
||||
$calID = false;
|
||||
|
||||
#error_log('ABID: '.$_abID);
|
||||
@ -282,10 +267,16 @@ class calendar_sif extends calendar_boupdate
|
||||
unset($event['alarm']);
|
||||
}
|
||||
|
||||
if($_calID > 0)
|
||||
{
|
||||
if($_calID > 0) {
|
||||
// update entry
|
||||
$event['id'] = $_calID;
|
||||
} else {
|
||||
if (isset($event['whole_day']) && $event['whole_day']
|
||||
&& isset ($deviceInfo) && is_array($deviceInfo)
|
||||
&& isset($deviceInfo['nonBlockingAllday'])
|
||||
&& $deviceInfo['nonBlockingAllday']) {
|
||||
$event['non_blocking'] = '1';
|
||||
}
|
||||
}
|
||||
|
||||
if($eventID = $this->update($event, TRUE)) {
|
||||
@ -308,14 +299,15 @@ class calendar_sif extends calendar_boupdate
|
||||
}
|
||||
|
||||
/**
|
||||
* return a vcard
|
||||
* return a sife
|
||||
*
|
||||
* @param int $_id the id of the contact
|
||||
* @param int $_vcardProfile profile id for mapping from vcard values to egw addressbook
|
||||
* @param int $_id the id of the event
|
||||
* @return string containing the vcard
|
||||
*/
|
||||
function getSIF($_id)
|
||||
{
|
||||
$sysCharSet = $GLOBALS['egw']->translation->charset();
|
||||
|
||||
$fields = array_unique(array_values($this->sifMapping));
|
||||
sort($fields);
|
||||
|
||||
@ -323,11 +315,17 @@ class calendar_sif extends calendar_boupdate
|
||||
#error_log("FOUND EVENT: ". print_r($event, true));
|
||||
|
||||
if($event = $this->read($_id,null,false,'server')) {
|
||||
$sysCharSet = $GLOBALS['egw']->translation->charset();
|
||||
$vcal = new Horde_iCalendar;
|
||||
|
||||
if ($this->uidExtension) {
|
||||
if (!preg_match('/\[UID:.+\]/m', $event['description'])) {
|
||||
$event['description'] .= "\n[UID:" . $event['uid'] . "]";
|
||||
}
|
||||
}
|
||||
|
||||
$vcal = &new Horde_iCalendar('1.0');
|
||||
|
||||
|
||||
$sifEvent = '<appointment>';
|
||||
$sifEvent = self::xml_decl . "\n<appointment>" . self::SIF_decl;
|
||||
|
||||
foreach($this->sifMapping as $sifField => $egwField)
|
||||
{
|
||||
@ -340,14 +338,6 @@ class calendar_sif extends calendar_boupdate
|
||||
|
||||
switch($sifField)
|
||||
{
|
||||
case 'Categories':
|
||||
if(!empty($value)) {
|
||||
$value = implode('; ', $this->get_categories(explode(',',$value)));
|
||||
$value = $GLOBALS['egw']->translation->convert($value, $sysCharSet, 'utf-8');
|
||||
}
|
||||
$sifEvent .= "<$sifField>$value</$sifField>";
|
||||
break;
|
||||
|
||||
case 'Importance':
|
||||
$value = $value-1;
|
||||
$sifEvent .= "<$sifField>$value</$sifField>";
|
||||
@ -437,6 +427,48 @@ class calendar_sif extends calendar_boupdate
|
||||
$sifEvent .= '<Occurrences>'. $occurrences .'</Occurrences>';
|
||||
}
|
||||
break;
|
||||
case MCAL_RECUR_MONTHLY_MDAY:
|
||||
$eventInterval = ($event['recur_interval'] > 1 ? $event['recur_interval'] : 1);
|
||||
$recurStartDate = mktime(0,0,0,date('m',$event['start']), date('d', $event['start']), date('Y', $event['start']));
|
||||
|
||||
$sifEvent .= "<$sifField>1</$sifField>";
|
||||
$sifEvent .= '<RecurrenceType>'. self::olRecursMonthly .'</RecurrenceType>';
|
||||
$sifEvent .= '<Interval>'. $eventInterval .'</Interval>';
|
||||
$sifEvent .= '<PatternStartDate>'. $vcal->_exportDateTime($recurStartDate) .'</PatternStartDate>';
|
||||
if($event['recur_enddate'] == 0) {
|
||||
$sifEvent .= '<NoEndDate>1</NoEndDate>';
|
||||
} else {
|
||||
$recurEndDate = mktime(24, 0, 0, date('m',$event['recur_enddate']), date('d', $event['recur_enddate']), date('Y', $event['recur_enddate']));
|
||||
|
||||
$sifEvent .= '<NoEndDate>0</NoEndDate>';
|
||||
$sifEvent .= '<PatternEndDate>'. $vcal->_exportDateTime($recurEndDate) .'</PatternEndDate>';
|
||||
}
|
||||
break;
|
||||
case MCAL_RECUR_MONTHLY_WDAY:
|
||||
$weekMaskMap = array('Sun' => self::olSunday, 'Mon' => self::olMonday, 'Tue' => self::olTuesday,
|
||||
'Wed' => self::olWednesday, 'Thu' => self::olThursday, 'Fri' => self::olFriday,
|
||||
'Sat' => self::olSaturday);
|
||||
$eventInterval = ($event['recur_interval'] > 1 ? $event['recur_interval'] : 1);
|
||||
$recurStartDate = mktime(0,0,0,date('m',$event['start']), date('d', $event['start']), date('Y', $event['start']));
|
||||
|
||||
$sifEvent .= "<$sifField>1</$sifField>";
|
||||
$sifEvent .= '<RecurrenceType>'. self::olRecursMonthNth .'</RecurrenceType>';
|
||||
$sifEvent .= '<Interval>'. $eventInterval .'</Interval>';
|
||||
$sifEvent .= '<PatternStartDate>'. $vcal->_exportDateTime($recurStartDate) .'</PatternStartDate>';
|
||||
$sifEvent .= '<Instance>' . (1 + (int) ((date('d',$event['start'])-1) / 7)) . '</Instance>';
|
||||
if($event['recur_enddate'] == 0) {
|
||||
$sifEvent .= '<NoEndDate>1</NoEndDate>';
|
||||
$sifEvent .= '<DayOfWeekMask>' . $weekMaskMap[date('D',$event['start'])] . '</DayOfWeekMask>';
|
||||
} else {
|
||||
$recurEndDate = mktime(24, 0, 0, date('m',$event['recur_enddate']), date('d', $event['recur_enddate']), date('Y', $event['recur_enddate']));
|
||||
|
||||
$sifEvent .= '<NoEndDate>0</NoEndDate>';
|
||||
$sifEvent .= '<PatternEndDate>'. $vcal->_exportDateTime($recurEndDate) .'</PatternEndDate>';
|
||||
$sifEvent .= '<DayOfWeekMask>' . $weekMaskMap[date('D',$event['start'])] . '</DayOfWeekMask>';
|
||||
}
|
||||
break;
|
||||
case MCAL_RECUR_YEARLY:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -456,9 +488,10 @@ class calendar_sif extends calendar_boupdate
|
||||
break;
|
||||
|
||||
case 'Start':
|
||||
if($event['end'] - $event['start'] == 86399 && date('Y-m-d', $event['end']) == date('Y-m-d', $event['start'])) {
|
||||
if ($this->isWholeDay($event)) {
|
||||
$value = date('Y-m-d', $event['start']);
|
||||
$sifEvent .= "<Start>$value</Start>";
|
||||
$vaule = date('Y-m-d', $event['end']);
|
||||
$sifEvent .= "<End>$value</End>";
|
||||
$sifEvent .= "<AllDayEvent>1</AllDayEvent>";
|
||||
} else {
|
||||
@ -487,14 +520,23 @@ class calendar_sif extends calendar_boupdate
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Categories':
|
||||
if(!empty($value)) {
|
||||
$value = implode('; ', $this->get_categories(explode(',',$value)));
|
||||
$value = $GLOBALS['egw']->translation->convert($value, $sysCharSet, 'utf-8');
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
$value = @htmlspecialchars($value, ENT_QUOTES, 'utf-8');
|
||||
$sifEvent .= "<$sifField>$value</$sifField>";
|
||||
break;
|
||||
}
|
||||
}
|
||||
$sifEvent .= '</appointment>';
|
||||
|
||||
return base64_encode($sifEvent);
|
||||
return $sifEvent;
|
||||
}
|
||||
|
||||
if($this->xmlrpc)
|
||||
@ -504,4 +546,31 @@ class calendar_sif extends calendar_boupdate
|
||||
return False;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the supported fields
|
||||
*
|
||||
* Currently we only store name and version, manucfacturer is always Funambol
|
||||
*
|
||||
* @param string $_productName
|
||||
* @param string $_productSoftwareVersion
|
||||
*/
|
||||
function setSupportedFields($_productName='', $_productSoftwareVersion='')
|
||||
{
|
||||
$state = &$_SESSION['SyncML.state'];
|
||||
$deviceInfo = $state->getClientDeviceInfo();
|
||||
|
||||
if(isset($deviceInfo) && is_array($deviceInfo)) {
|
||||
if(isset($deviceInfo['uidExtension']) &&
|
||||
$deviceInfo['uidExtension']){
|
||||
$this->uidExtension = true;
|
||||
}
|
||||
}
|
||||
// store product name and version, to be able to use it elsewhere
|
||||
if ($_productName) {
|
||||
$this->productName = strtolower($_productName);
|
||||
if (preg_match('/^[^\d]*(\d+\.?\d*)[\.|\d]*$/', $_productSoftwareVersion, $matches)) {
|
||||
$this->productSoftwareVersion = $matches[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,8 @@
|
||||
* @link http://www.egroupware.org
|
||||
* @package calendar
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2005-9 by RalfBecker-At-outdoor-training.de
|
||||
* @author Joerg Lehrke <jlehrke@noc.de>
|
||||
* @copyright (c) 2005-8 by RalfBecker-At-outdoor-training.de
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @version $Id$
|
||||
*/
|
||||
@ -105,12 +106,18 @@ class calendar_so
|
||||
*
|
||||
* All times (start, end and modified) are returned as timesstamps in servertime!
|
||||
*
|
||||
* @param int|array/string $ids id or array of id's of the entries to read, or string with a single uid
|
||||
* @param int|array|string $ids id or array of id's of the entries to read, or string with a single uid
|
||||
* @param int $recur_date=0 if set read the next recurrance at or after the timestamp, default 0 = read the initital one
|
||||
* @return array|boolean array with id => data pairs or false if entry not found
|
||||
*/
|
||||
function read($ids,$recur_date=0)
|
||||
{
|
||||
if (isset($GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length'])) {
|
||||
$minimum_uid_length = $GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length'];
|
||||
} else {
|
||||
$minimum_uid_length = 8;
|
||||
}
|
||||
|
||||
//echo "<p>socal::read(".print_r($ids,true).",$recur_date)<br />\n".function_backtrace()."<p>\n";
|
||||
|
||||
$table_def = $this->db->get_table_definitions('calendar',$this->cal_table);
|
||||
@ -131,7 +138,9 @@ class calendar_so
|
||||
}
|
||||
else
|
||||
{
|
||||
// We only what the parents to match
|
||||
$where['cal_uid'] = $ids;
|
||||
$where['cal_reference'] = 0;
|
||||
}
|
||||
if ((int) $recur_date)
|
||||
{
|
||||
@ -153,6 +162,15 @@ class calendar_so
|
||||
}
|
||||
if (!$events) return false;
|
||||
|
||||
foreach ($events as $event) {
|
||||
if (!isset($event['uid']) || strlen($event['uid']) < $minimum_uid_length) {
|
||||
// event (without uid), not strong enough uid => create new uid
|
||||
$event['uid'] = $GLOBALS['egw']->common->generate_uid('calendar',$event['id']);
|
||||
$this->db->update($this->cal_table, array('cal_uid' => $event['uid']),
|
||||
array('cal_id' => $event['id']),__LINE__,__FILE__,'calendar');
|
||||
}
|
||||
}
|
||||
|
||||
// check if we have a real recurance, if not set $recur_date=0
|
||||
if (is_array($ids) || $events[(int)$ids]['recur_type'] == MCAL_RECUR_NONE)
|
||||
{
|
||||
@ -222,7 +240,7 @@ class calendar_so
|
||||
$sql = '';
|
||||
if ($cat_id)
|
||||
{
|
||||
if (!is_array($cat_ids) && !@$GLOBALS['egw_info']['user']['preferences']['common']['cats_no_subs'])
|
||||
if (!is_array($cat_id) && !@$GLOBALS['egw_info']['user']['preferences']['common']['cats_no_subs'])
|
||||
{
|
||||
$cats = $GLOBALS['egw']->categories->return_all_children($cat_id);
|
||||
}
|
||||
@ -260,12 +278,11 @@ class calendar_so
|
||||
* @param string|array $_cols=null what to select, default "$this->repeats_table.*,$this->cal_table.*,cal_start,cal_end,cal_recur_date"
|
||||
* if specified an iterator for the rows is returned
|
||||
* @param string $append='' SQL to append to the query before $order, eg. for a GROUP BY clause
|
||||
* @return array|boolean|iterator of cal_id => event pairs, or false if error in the parameters, or iterator if !is_null($_cols)
|
||||
* @return array of cal_ids, or false if error in the parameters
|
||||
*
|
||||
* ToDo: search custom-fields too
|
||||
*/
|
||||
function &search($start,$end,$users,$cat_id=0,$filter='',$query='',$offset=False,$num_rows=0,$order = 'cal_start',$show_rejected=true,
|
||||
$_cols=null,$append='')
|
||||
function &search($start,$end,$users,$cat_id=0,$filter='',$query='',$offset=False,$num_rows=0,$order='cal_start',$show_rejected=true,$_cols=null,$append='')
|
||||
{
|
||||
//echo '<p>'.__METHOD__.'('.($start ? date('Y-m-d H:i',$start) : '').','.($end ? date('Y-m-d H:i',$end) : '').','.array2string($users).','.array2string($cat_id).",'$filter',".array2string($query).",$offset,$num_rows,$order,$show_rejected,".array2string($_cols).",$append)</p>\n";
|
||||
|
||||
@ -344,6 +361,7 @@ class calendar_so
|
||||
|
||||
$selects[0]['cols'] = $selects[1]['cols'] = $select['cols']; // restore the original cols
|
||||
}
|
||||
// error_log("calendar_so_search:\n" . print_r($selects, true));
|
||||
$rs = $this->db->union($selects,__LINE__,__FILE__,$order,$offset,$num_rows);
|
||||
}
|
||||
else // MsSQL oder MySQL 3.23
|
||||
@ -487,6 +505,12 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
*/
|
||||
function save($event,&$set_recurrences,$change_since=0,&$etag=null)
|
||||
{
|
||||
if (isset($GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length'])) {
|
||||
$minimum_uid_length = $GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length'];
|
||||
} else {
|
||||
$minimum_uid_length = 8;
|
||||
}
|
||||
|
||||
//echo "<p>socal::save(,$change_since) event="; _debug_array($event);
|
||||
//error_log(__METHOD__."(".str_replace(array("\n",' '),'',print_r($event,true)).",$set_recurrences,$change_since,$etag)");
|
||||
|
||||
@ -520,9 +544,17 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
return 0; // wrong etag, someone else updated the entry
|
||||
}
|
||||
if (!is_null($etag)) ++$etag;
|
||||
// events need to have at least one participant, default to the owner
|
||||
if (!isset($event['cal_participants'])) {
|
||||
$event['cal_participants'] = array($event['cal_owner'] => 'A');
|
||||
}
|
||||
if (!isset($event['cal_participants'][$event['cal_owner']])) {
|
||||
$event['cal_participants'][$event['cal_owner']] = 'A';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// new event
|
||||
if (!$event['cal_owner']) $event['cal_owner'] = $GLOBALS['egw_info']['user']['account_id'];
|
||||
|
||||
if (!$event['cal_id'] && !isset($event['cal_uid'])) $event['cal_uid'] = ''; // uid is NOT NULL!
|
||||
@ -532,45 +564,54 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// new event (without uid), not strong enough uid or new created referencing event => create new uid
|
||||
if (strlen($event['cal_uid']) < 20 || is_numeric($event['cal_uid']) ||
|
||||
$event['cal_reference'] && strpos($event['cal_uid'],'cal-'.$event['calreference'].'-') !== false)
|
||||
{
|
||||
$event['cal_uid'] = $GLOBALS['egw']->common->generate_uid('calendar',$cal_id);
|
||||
$this->db->update($this->cal_table,array('cal_uid' => $event['cal_uid']),array('cal_id' => $cal_id),__LINE__,__FILE__,'calendar');
|
||||
}
|
||||
$etag = 0;
|
||||
// new events need to have at least one participant, default to the owner
|
||||
if (!isset($event['cal_participants']))
|
||||
{
|
||||
if (!isset($event['cal_participants'])) {
|
||||
$event['cal_participants'] = array($event['cal_owner'] => 'A');
|
||||
}
|
||||
if (!isset($event['cal_participants'][$event['cal_owner']])) {
|
||||
$event['cal_participants'][$event['cal_owner']] = 'A';
|
||||
}
|
||||
}
|
||||
if (!isset($event['cal_uid']) || strlen($event['cal_uid']) < $minimum_uid_length
|
||||
|| ($event['cal_reference'] && strpos($event['cal_uid'],
|
||||
'cal-'.$event['calreference'].'-') !== false)) {
|
||||
// event (without uid), not strong enough uid
|
||||
// or new created referencing event => create new uid
|
||||
$event['cal_uid'] = $GLOBALS['egw']->common->generate_uid('calendar',$cal_id);
|
||||
$this->db->update($this->cal_table, array('cal_uid' => $event['cal_uid']),
|
||||
array('cal_id' => $event['cal_id']),__LINE__,__FILE__,'calendar');
|
||||
}
|
||||
// write information about recuring event, if recur_type is present in the array
|
||||
if (isset($event['recur_type']))
|
||||
{
|
||||
// save the original start
|
||||
$min = (int) $this->db->select($this->dates_table,'MIN(cal_start)',array('cal_id'=>$cal_id),__LINE__,__FILE__,false,'','calendar')->fetchSingle();
|
||||
|
||||
if (isset($event['recur_exception']) && is_array($event['recur_exception']) && count($event['recur_exception']))
|
||||
{
|
||||
// delete execeptions from the user and dates table, it could be the first time
|
||||
// delete the execeptions from the user and dates table, it could be the first time
|
||||
$this->db->delete($this->user_table,array('cal_id' => $cal_id,'cal_recur_date' => $event['recur_exception']),__LINE__,__FILE__,'calendar');
|
||||
$this->db->delete($this->dates_table,array('cal_id' => $cal_id,'cal_start' => $event['recur_exception']),__LINE__,__FILE__,'calendar');
|
||||
|
||||
$event['recur_exception'] = implode(',',$event['recur_exception']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$event['recur_exception'] = null;
|
||||
$event['recur_exception'] = array();
|
||||
}
|
||||
if (!$set_recurrences)
|
||||
{
|
||||
// check if the recure-information changed
|
||||
// check if the recurrence-information changed
|
||||
$old_recur = $this->db->select($this->repeats_table,'*',array('cal_id' => $cal_id),__LINE__,__FILE__,false,'','calendar')->fetch();
|
||||
$old_exceptions = $old_recur['recur_exception'] ? explode(',',$old_recur['recur_exception']) : array();
|
||||
$exceptions = $event['recur_exception'] ? explode(',',$event['recur_exception']) : array();
|
||||
$set_recurrences = $event['recur_type'] != $old_recur['recur_type'] || $event['recur_data'] != $old_recur['recur_data'] ||
|
||||
$event['recur_interval'] != $old_recur['recur_interval'] || $event['recur_enddate'] != $old_recur['recur_enddate'] ||
|
||||
count(array_diff($old_exceptions,$exceptions)); // exception deleted or added
|
||||
$set_recurrences = (isset($event['cal_start']) && (int)$min != (int) $event['cal_start']) ||
|
||||
$event['recur_type'] != $old_recur['recur_type'] || $event['recur_data'] != $old_recur['recur_data'] ||
|
||||
(int)$event['recur_interval'] != (int)$old_recur['recur_interval'] || $event['recur_enddate'] != $old_recur['recur_enddate'] ||
|
||||
count(array_diff($old_exceptions,$event['recur_exception'])); // exception deleted or added
|
||||
$max = (int) $this->db->select($this->dates_table,'MAX(cal_start)',array('cal_id'=>$cal_id),__LINE__,__FILE__,false,'','calendar')->fetchSingle();
|
||||
} else {
|
||||
$max = 0;
|
||||
}
|
||||
$event['recur_exception'] = empty($event['recur_exception']) ? null : implode(',',$event['recur_exception']);
|
||||
unset($event[0]); // unset the 'etag=etag+1', as it's not in the repeats table
|
||||
if($event['recur_type'] != MCAL_RECUR_NONE)
|
||||
{
|
||||
@ -582,17 +623,21 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
}
|
||||
if ($set_recurrences)
|
||||
{
|
||||
if ((int)$min != (int)$event['cal_start'])
|
||||
{
|
||||
// We need to reset all recurrences
|
||||
$max = -1;
|
||||
}
|
||||
// delete all, but the lowest dates record
|
||||
$min = (int) $this->db->select($this->dates_table,'MIN(cal_start)',array('cal_id'=>$cal_id),__LINE__,__FILE__,false,'','calendar')->fetchColumn();
|
||||
|
||||
$this->db->delete($this->dates_table,array(
|
||||
'cal_id' => $cal_id,
|
||||
'cal_start > '.(int)$min,
|
||||
),__LINE__,__FILE__,'calendar');
|
||||
// delete all user-records, with recur-date != 0
|
||||
|
||||
// delete all user-records, with recur-date > old enddate
|
||||
$this->db->delete($this->user_table,array(
|
||||
'cal_id' => $cal_id,
|
||||
'cal_recur_date != 0',
|
||||
'cal_recur_date > '.(int)$max,
|
||||
),__LINE__,__FILE__,'calendar');
|
||||
}
|
||||
}
|
||||
@ -647,10 +692,10 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
}
|
||||
|
||||
//pgoerzen: don't add an alarm if it is before the current date.
|
||||
if ($event['recur_type'] && ($tmp_event = $this->read($eventID, time() + $alarm['offset'])))
|
||||
/*if ($event['recur_type'] && ($tmp_event = $this->read($eventID, time() + $alarm['offset'])))
|
||||
{
|
||||
$alarm['time'] = $tmp_event['cal_start'] - $alarm['offset'];
|
||||
}
|
||||
} */
|
||||
|
||||
$this->save_alarm($cal_id,$alarm);
|
||||
}
|
||||
@ -708,7 +753,7 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
{
|
||||
// move the recur-date of the participants
|
||||
$this->db->query("UPDATE $this->user_table SET cal_recur_date=cal_recur_date+$move_start WHERE $where AND cal_recur_date ".
|
||||
((int)$change_since ? '>= '.(int)$change_since : '!= 0'),__LINE__,__FILE__);
|
||||
((int)$change_since ? '>= '.(int)$change_since : '!= 0') + " ORDER BY cal_recur_date DESC",__LINE__,__FILE__);
|
||||
}
|
||||
if ($move_start || $move_end)
|
||||
{
|
||||
@ -762,7 +807,6 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
* @param int $cal_id
|
||||
* @param array $participants id => status pairs
|
||||
* @param int|boolean $change_since=0 false=new entry, > 0 time from which on the repetitions should be changed, default 0=all
|
||||
* @param int $recur_date=0 time of which repetitions should be updated, default 0=all
|
||||
* @return int|boolean number of updated recurrences or false on error
|
||||
*/
|
||||
function participants($cal_id,$participants,$change_since=0)
|
||||
@ -786,6 +830,7 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
if ($change_since !== false) // existing entries only
|
||||
{
|
||||
// delete not longer set participants
|
||||
$where[0] = 'cal_recur_date=0';
|
||||
$deleted = array();
|
||||
foreach($this->db->select($this->user_table,'DISTINCT cal_user_type,cal_user_id,cal_quantity',$where,
|
||||
__LINE__,__FILE__,false,'','calendar') as $row)
|
||||
@ -795,11 +840,15 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
{
|
||||
$deleted[$row['cal_user_type']][] = $row['cal_user_id'];
|
||||
}
|
||||
elseif($row['cal_quantity'] == (substr($participants[$uid],1) ? substr($participants[$uid],1) : 1))
|
||||
elseif((($row['cal_user_type'] == 'r') &&
|
||||
// quantity of resource unchanged
|
||||
($row['cal_quantity'] == (substr($participants[$uid],1) ? substr($participants[$uid],1) : 1))) ||
|
||||
($row['cal_status'] == $participants[$uid]))
|
||||
{
|
||||
unset($participants[$uid]); // we dont touch them
|
||||
unset($participants[$uid]); // we don't touch them
|
||||
}
|
||||
}
|
||||
unset($where[0]);
|
||||
|
||||
if (count($deleted))
|
||||
{
|
||||
@ -815,21 +864,32 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
$this->db->delete($this->user_table,$where + array('('.implode(' OR ',$to_or).')'),__LINE__,__FILE__,'calendar');
|
||||
}
|
||||
}
|
||||
if (count($participants)) // these are NEW participants now
|
||||
if (count($participants)) // these are ALL participants now - we exclude the existing ones later
|
||||
{
|
||||
// find all recurrences, as they all need the new parts to be added
|
||||
$recurrences = array();
|
||||
$existing_participants = array();
|
||||
|
||||
if ($change_since !== false) // existing entries only
|
||||
{
|
||||
foreach($this->db->select($this->user_table,'DISTINCT cal_recur_date',$where,__LINE__,__FILE__,false,'','calendar') as $row)
|
||||
{
|
||||
$recurrences[] = $row['cal_recur_date'];
|
||||
}
|
||||
|
||||
// existing participants must not be updated
|
||||
foreach($this->db->select($this->user_table,'DISTINCT cal_user_type,cal_user_id',$where,__LINE__,__FILE__,false,'','calendar') as $row)
|
||||
{
|
||||
$existing_participants[] = $this->combine_user($row['cal_user_type'],$row['cal_user_id']);
|
||||
}
|
||||
}
|
||||
if (!count($recurrences)) $recurrences[] = 0; // insert the default one
|
||||
|
||||
foreach($participants as $uid => $status)
|
||||
{
|
||||
if (in_array($uid,$existing_participants)) continue; // don't update existing participants
|
||||
|
||||
$id = null;
|
||||
$this->split_user($uid,$type,$id);
|
||||
foreach($recurrences as $recur_date)
|
||||
{
|
||||
@ -854,7 +914,7 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
* @param int $cal_id
|
||||
* @param char $user_type 'u' regular user, 'r' resource, 'c' contact
|
||||
* @param int $user_id
|
||||
* @param int|string $status numeric status (defines) or 1-char code: 'R', 'U', 'T' or 'A'
|
||||
* @param int|char $status numeric status (defines) or 1-char code: 'R', 'U', 'T' or 'A'
|
||||
* @param int $recur_date=0 date to change, or 0 = all since now
|
||||
* @return int number of changed recurrences
|
||||
*/
|
||||
@ -897,7 +957,7 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
),$where,__LINE__,__FILE__,'calendar');
|
||||
}
|
||||
$ret = $this->db->affected_rows();
|
||||
error_log(__METHOD__."($cal_id,$user_type,$user_id,$status,$recur_date) = $ret");
|
||||
//error_log(__METHOD__."($cal_id,$user_type,$user_id,$status,$recur_date) = $ret");
|
||||
return $this->db->affected_rows();
|
||||
}
|
||||
|
||||
@ -923,6 +983,8 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
{
|
||||
if ($status == 'G') continue; // dont save group-invitations
|
||||
|
||||
$type = '';
|
||||
$id = null;
|
||||
$this->split_user($uid,$type,$id);
|
||||
$this->db->insert($this->user_table,array(
|
||||
'cal_status' => $status !== true ? $status[0] : 'U',
|
||||
@ -1024,9 +1086,10 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
*
|
||||
* @param int $cal_id Id of the calendar-entry
|
||||
* @param array $alarm array with fields: text, owner, enabled, ..
|
||||
* @param timestamp $now_su=0 timestamp for modification of related event
|
||||
* @return string id of the alarm
|
||||
*/
|
||||
function save_alarm($cal_id,$alarm)
|
||||
function save_alarm($cal_id, $alarm, $now_su = 0)
|
||||
{
|
||||
//echo "<p>save_alarm(cal_id=$cal_id, alarm="; print_r($alarm); echo ")</p>\n";
|
||||
if (!($id = $alarm['id']))
|
||||
@ -1050,6 +1113,13 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
{
|
||||
return False;
|
||||
}
|
||||
|
||||
// update the modification information of the related event
|
||||
$datetime = $GLOBALS['egw']->datetime;
|
||||
$now = ($now_su ? $now_su : time() + $datetime->this->tz_offset);
|
||||
$modifier = $GLOBALS['egw_info']['user']['account_id'];
|
||||
$this->db->update($this->cal_table, array('cal_modified' => $now, 'cal_modifier' => $modifier),
|
||||
array('cal_id' => $cal_id), __LINE__, __FILE__, 'calendar');
|
||||
return $id;
|
||||
}
|
||||
|
||||
@ -1074,10 +1144,20 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
* delete one alarms identified by its id
|
||||
*
|
||||
* @param string $id alarm-id is a string of 'cal:'.$cal_id.':'.$alarm_nr, it is used as the job-id too
|
||||
* @param timestamp $now_su=0 timestamp for modification of related event
|
||||
* @return int number of alarms deleted
|
||||
*/
|
||||
function delete_alarm($id)
|
||||
function delete_alarm($id, $now_su = 0)
|
||||
{
|
||||
// update the modification information of the related event
|
||||
list(,$cal_id) = explode(':',$id);
|
||||
if ($cal_id) {
|
||||
$datetime = $GLOBALS['egw']->datetime;
|
||||
$now = ($now_su ? $now_su : time() + $datetime->this->tz_offset);
|
||||
$modifier = $GLOBALS['egw_info']['user']['account_id'];
|
||||
$this->db->update($this->cal_table, array('cal_modified' => $now, 'cal_modifier' => $modifier),
|
||||
array('cal_id' => $cal_id), __LINE__, __FILE__, 'calendar');
|
||||
}
|
||||
return $this->async->cancel_timer($id);
|
||||
}
|
||||
|
||||
@ -1087,7 +1167,7 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
* @param array|int $old_user integer old user or array with keys 'account_id' and 'new_owner' as the deleteaccount hook uses it
|
||||
* @param int $new_user=null
|
||||
*/
|
||||
function deleteaccount($data)
|
||||
function deleteaccount($old_user, $newuser=null)
|
||||
{
|
||||
if (is_array($old_user))
|
||||
{
|
||||
@ -1096,6 +1176,8 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
}
|
||||
if (!(int)$new_user)
|
||||
{
|
||||
$user_type = '';
|
||||
$user_id = null;
|
||||
$this->split_user($old_user,$user_type,$user_id);
|
||||
|
||||
if ($user_type == 'u') // only accounts can be owners of events
|
||||
@ -1144,4 +1226,134 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
),__LINE__,__FILE__,'calendar');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get stati of all recurrences of an event for a specific participant
|
||||
*
|
||||
* @param int $cal_id
|
||||
* @param int $uid participant uid
|
||||
* @return array recur_date => status pairs (index 0 => main status)
|
||||
*/
|
||||
function get_recurrences($cal_id, $uid)
|
||||
{
|
||||
$user_type = $user_id = null;
|
||||
$this->split_user($uid, $user_type, $user_id);
|
||||
$participant_status = array();
|
||||
$where = array('cal_id' => $cal_id);
|
||||
foreach($this->db->select($this->user_table,'DISTINCT cal_recur_date',$where,__LINE__,__FILE__,false,'','calendar') as $row)
|
||||
{
|
||||
// inititalize the array
|
||||
$participant_status[$row['cal_recur_date']] = null;
|
||||
}
|
||||
$where = array(
|
||||
'cal_id' => $cal_id,
|
||||
'cal_user_type' => $user_type ? $user_type : 'u',
|
||||
'cal_user_id' => $user_id,
|
||||
);
|
||||
foreach ($this->db->select($this->user_table,'cal_recur_date,cal_status',$where,
|
||||
__LINE__,__FILE__,false,'','calendar') as $row)
|
||||
{
|
||||
$participant_status[$row['cal_recur_date']] = $row['cal_status'];
|
||||
}
|
||||
return $participant_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all participants of an event
|
||||
*
|
||||
* @param int $cal_id
|
||||
* @param int $recur_date=0 gives participants of this recurrence, default 0=all
|
||||
*
|
||||
* @return array participants
|
||||
*/
|
||||
function get_participants($cal_id, $recur_date=0)
|
||||
{
|
||||
$participants = array();
|
||||
$where = array('cal_id' => $cal_id);
|
||||
if ($recur_date)
|
||||
{
|
||||
$where['cal_recur_date'] = $recur_date;
|
||||
}
|
||||
|
||||
foreach ($this->db->select($this->user_table,'DISTINCT cal_user_type,cal_user_id', $where,
|
||||
__LINE__,__FILE__,false,'','calendar') as $row)
|
||||
{
|
||||
$uid = $this->combine_user($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]['id'] = $row['cal_user_id'];
|
||||
$participants[$id]['uid'] = $uid;
|
||||
}
|
||||
return $participants;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all releated events
|
||||
*
|
||||
* @param int $uid UID of the series
|
||||
*
|
||||
* @return array of event exception ids for all events which share $uid
|
||||
*/
|
||||
function get_related($uid)
|
||||
{
|
||||
$where = array(
|
||||
'cal_uid' => $uid,
|
||||
);
|
||||
$related = array();
|
||||
foreach ($this->db->select($this->cal_table,'cal_id,cal_reference',$where,
|
||||
__LINE__,__FILE__,false,'','calendar') as $row)
|
||||
{
|
||||
if ($row['cal_reference'])
|
||||
{
|
||||
// not the series entry itself
|
||||
$related[$row['cal_id']] = $row['cal_reference'];
|
||||
}
|
||||
}
|
||||
return $related;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the exception days of a given recurring event caused by
|
||||
* irregular participant stati
|
||||
*
|
||||
* @param array $event Recurring Event.
|
||||
*
|
||||
* @return array Array of exception days (false for non-recurring events).
|
||||
*/
|
||||
function get_recurrence_exceptions(&$event)
|
||||
{
|
||||
$cal_id = (int) $event['id'];
|
||||
if (!$cal_id || $event['recur_type'] == MCAL_RECUR_NONE) return false;
|
||||
|
||||
$days = array();
|
||||
|
||||
$participants = $this->get_participants($event['id'], 0);
|
||||
|
||||
// Check if the stati for all participants are identical for all recurrences
|
||||
foreach ($participants as $uid => $attendee)
|
||||
{
|
||||
switch ($attendee['type'])
|
||||
{
|
||||
case 'u': // account
|
||||
case 'c': // contact
|
||||
case 'e': // email address
|
||||
$recurrences = $this->get_recurrences($event['id'], $uid);
|
||||
foreach ($recurrences as $recur_date => $recur_status)
|
||||
{
|
||||
if ($recur_date && $recur_status != $recurrences[0])
|
||||
{
|
||||
// Every distinct status results in an exception
|
||||
$days[] = $recur_date;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: // We don't handle the rest
|
||||
break;
|
||||
}
|
||||
}
|
||||
$days = array_unique($days);
|
||||
sort($days);
|
||||
return $days;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user