diff --git a/calendar/inc/class.calendar_boupdate.inc.php b/calendar/inc/class.calendar_boupdate.inc.php index f2b19720fe..dd5f4ad0e8 100644 --- a/calendar/inc/class.calendar_boupdate.inc.php +++ b/calendar/inc/class.calendar_boupdate.inc.php @@ -104,33 +104,33 @@ class calendar_boupdate extends calendar_bo // set owner as participant if none is given if (!is_array($event['participants']) || !count($event['participants'])) { - $event['participants'] = array($event['owner'] => 'U'); + $status = $event['owner'] == $this->user ? 'A' : 'U'; + $status = calendar_so::combine_status($status, 1, 'CHAIR'); + $event['participants'] = array($event['owner'] => $status); } - // set the status of the current user to 'A' = accepted - if (isset($event['participants'][$this->user]) && $event['participants'][$this->user][0] != 'A') - { - $event['participants'][$this->user][0] = 'A'; - } - } + $new_event = true; + } else $new_event = false; + // check if user has the permission to update / create the event - if (!$ignore_acl && ($event['id'] && !$this->check_perms(EGW_ACL_EDIT,$event['id']) || - !$event['id'] && !$this->check_perms(EGW_ACL_EDIT,0,$event['owner'])) && + if (!$ignore_acl && (!$new_event && !$this->check_perms(EGW_ACL_EDIT,$event['id']) || + $new_event && !$this->check_perms(EGW_ACL_EDIT,0,$event['owner'])) && !$this->check_perms(EGW_ACL_ADD,0,$event['owner'])) { return false; } - if (!($new_event = !(int)$event['id'])) + if ($new_event) + { + $event['created'] = $this->now_su; + $event['creator'] = $GLOBALS['egw_info']['user']['account_id']; + } + else { $old_event = $this->read((int)$event['id'],null,$ignore_acl); // if no participants are set, set them from the old event, as we might need them to update recuring events if (!isset($event['participants'])) $event['participants'] = $old_event['participants']; //echo "old $event[id]="; _debug_array($old_event); } - else - { - $event['created'] = $this->now_su; - $event['creator'] = $GLOBALS['egw_info']['user']['account_id']; - } + // do we need to check, if user is allowed to invite the invited participants if ($this->require_acl_invite && ($removed = $this->remove_no_acl_invite($event,$old_event))) { @@ -336,7 +336,7 @@ class calendar_boupdate extends calendar_bo public function check_acl_invite($uid) { if (!is_numeric($uid)) return true; // nothing implemented for resources so far - + if (!$this->require_acl_invite) { $ret = true; // no grant required @@ -846,7 +846,8 @@ class calendar_boupdate extends calendar_bo { return false; } - if (($Ok = $this->so->set_status($cal_id,is_numeric($uid)?'u':$uid[0],is_numeric($uid)?$uid:substr($uid,1),$status,$recur_date ? $this->date2ts($recur_date,true) : 0))) + calendar_so::split_status($status, $quantity, $role); + if (($Ok = $this->so->set_status($cal_id,is_numeric($uid)?'u':$uid[0],is_numeric($uid)?$uid:substr($uid,1),$status,$recur_date ? $this->date2ts($recur_date,true) : 0,$role))) { if ($updateTS) $GLOBALS['egw']->contenthistory->updateTimeStamp('calendar',$cal_id,'modify',time()); diff --git a/calendar/inc/class.calendar_ical.inc.php b/calendar/inc/class.calendar_ical.inc.php index f4b9a8c527..9971079594 100644 --- a/calendar/inc/class.calendar_ical.inc.php +++ b/calendar/inc/class.calendar_ical.inc.php @@ -164,8 +164,8 @@ class calendar_ical extends calendar_boupdate 'LOCATION' => 'location', 'DTSTART' => 'start', 'DTEND' => 'end', - 'ORGANIZER' => 'owner', 'ATTENDEE' => 'participants', + 'ORGANIZER' => 'owner', 'RRULE' => 'recur_type', 'EXDATE' => 'recur_exception', 'PRIORITY' => 'priority', @@ -194,6 +194,9 @@ class calendar_ical extends calendar_boupdate $vtimezones_added = array(); foreach($events as $event) { + $mailtoOrganizer = false; + $organizerCN = false; + if (strpos($this->productName, 'palmos') !== false) { $date_format = 'ts'; @@ -303,11 +306,17 @@ class calendar_ical extends calendar_boupdate foreach ((array)$event['participants'] as $uid => $status) { if (!($info = $this->resource_info($uid))) continue; - if ($uid == $event['owner']) continue; // Organizer + $mailtoParticipant = $info['email'] ? 'MAILTO:'.$info['email'] : ''; + $participantCN = '"' . ($info['cn'] ? $info['cn'] : $info['name']) . '"'; + calendar_so::split_status($status, $quantity, $role); + if ($role == 'CHAIR' && $uid != $this->user) + { + $mailtoOrganizer = $mailtoParticipant; + $organizerCN = $participantCN; + if ($status == 'U') continue; // saved ORGANIZER + } // RB: MAILTO href contains only the email-address, NO cn! - $attributes['ATTENDEE'][] = $info['email'] ? 'MAILTO:'.$info['email'] : ''; - // ROLE={CHAIR|REQ-PARTICIPANT|OPT-PARTICIPANT|NON-PARTICIPANT|X-*} - calendar_so::split_status($status,$quantity,$role); + $attributes['ATTENDEE'][] = $mailtoParticipant; // RSVP={TRUE|FALSE} // resonse expected, not set in eGW => status=U $rsvp = $status == 'U' ? 'TRUE' : 'FALSE'; // PARTSTAT={NEEDS-ACTION|ACCEPTED|DECLINED|TENTATIVE|DELEGATED|COMPLETED|IN-PROGRESS} everything from delegated is NOT used by eGW atm. @@ -330,8 +339,9 @@ class calendar_ical extends calendar_boupdate $cutype = 'UNKNOWN'; break; }; + // ROLE={CHAIR|REQ-PARTICIPANT|OPT-PARTICIPANT|NON-PARTICIPANT|X-*} $parameters['ATTENDEE'][] = array( - 'CN' => '"'.($info['cn'] ? $info['cn'] : $info['name']).'"', + 'CN' => $participantCN, 'ROLE' => $role, 'PARTSTAT' => $status, 'CUTYPE' => $cutype, @@ -345,13 +355,21 @@ class calendar_ical extends calendar_boupdate $attributes['CLASS'] = $event['public'] ? 'PUBLIC' : 'CONFIDENTIAL'; break; - case 'ORGANIZER': // according to iCalendar standard, ORGANIZER not used for events in the own calendar - if ($event['owner'] != $this->user || $this->productManufacturer != 'groupdav') + case 'ORGANIZER': + // according to iCalendar standard, ORGANIZER not used for events in the own calendar + if (!$organizerCN && + ($event['owner'] != $this->user + || $this->productManufacturer != 'groupdav')) { $mailtoOrganizer = $GLOBALS['egw']->accounts->id2name($event['owner'],'account_email'); - $attributes['ORGANIZER'] = $mailtoOrganizer ? 'MAILTO:'.$mailtoOrganizer : ''; - $parameters['ORGANIZER']['CN'] = '"'.trim($GLOBALS['egw']->accounts->id2name($event['owner'],'account_firstname').' '. - $GLOBALS['egw']->accounts->id2name($event['owner'],'account_lastname')).'"'; + $mailtoOrganizer = $mailtoOrganizer ? 'MAILTO:'.$mailtoOrganizer : ''; + $organizerCN = '"' . trim($GLOBALS['egw']->accounts->id2name($event['owner'],'account_firstname') + . ' ' . $GLOBALS['egw']->accounts->id2name($event['owner'],'account_lastname')) . '"'; + } + if ($organizerCN) + { + $attributes['ORGANIZER'] = $mailtoOrganizer; + $parameters['ORGANIZER']['CN'] = $organizerCN; } break; @@ -734,12 +752,12 @@ class calendar_ical extends calendar_boupdate $event['owner'] = $this->user; } - // add ourself to new events as participant - if (!isset($this->supportedFields['participants']) - ||!isset($event['participants'][$this->user])) - { - $event['participants'][$this->user] = 'A'; - } + if (!is_array($event['participants']) || !count($event['participants'])) + { + $status = $event['owner'] == $this->user ? 'A' : 'U'; + $status = calendar_so::combine_status($status, 1, 'CHAIR'); + $event['participants'] = array($event['owner'] => $status); + } } // common adjustments for existing events @@ -1034,8 +1052,7 @@ class calendar_ical extends calendar_boupdate if ($this->log) { - $egw_event = $this->read($event['id']); - error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n".array2string($egw_event)."\n",3,$this->logfile); + error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n".array2string($event_info['stored_event'])."\n",3,$this->logfile); } } @@ -1439,7 +1456,6 @@ class calendar_ical extends calendar_boupdate } $isDate = false; - $hasOrganizer = false; $event = array(); $alarms = array(); $vcardData = array( @@ -1813,7 +1829,7 @@ class calendar_ical extends calendar_boupdate } else { - $status = 0; + $status = 'U'; } $cn = ''; if (preg_match('/MAILTO:([@.a-z0-9_-]+)|MAILTO:"?([.a-z0-9_ -]*)"?[ ]*<([@.a-z0-9_-]*)>/i', @@ -1862,21 +1878,31 @@ class calendar_ical extends calendar_boupdate } //elseif (//$attributes['params']['CUTYPE'] == 'GROUP' - elseif (preg_match('/(.*) Group/', $searcharray['n_fn'], $matches) - && $status && $status != 'U') + elseif (preg_match('/(.*) Group/', $searcharray['n_fn'], $matches)) { if (($uid = $GLOBALS['egw']->accounts->name2id($matches[1], 'account_lid', 'g'))) { //Horde::logMessage("vevent2egw: group participant $uid", - // __FILE__, __LINE__, PEAR_LOG_DEBUG); - $members = $GLOBALS['egw']->accounts->members($uid, true); - if (in_array($this->user, $members)) + // __FILE__, __LINE__, PEAR_LOG_DEBUG); + if ($status == 'U') { - //Horde::logMessage("vevent2egw: set status to " . $status, - // __FILE__, __LINE__, PEAR_LOG_DEBUG); - $event['participants'][$this->user] = $status; + + } + else + { + // User tries to reply to the group invitiation + $members = $GLOBALS['egw']->accounts->members($uid, true); + if (in_array($this->user, $members)) + { + //Horde::logMessage("vevent2egw: set status to " . $status, + // __FILE__, __LINE__, PEAR_LOG_DEBUG); + $event['participants'][$this->user] = + calendar_so::combine_status($status); + } + continue; } } + else continue; // can not find this group } elseif ($attributes['value'] == 'Unknown') { @@ -1906,22 +1932,26 @@ class calendar_ical extends calendar_boupdate switch($attributes['name']) { case 'ATTENDEE': - if ($status) + if (!isset($attributes['params']['ROLE']) && + isset($event['owner']) && $event['owner'] == $uid) { - $event['participants'][$uid] = $status; - } - else - { - $event['participants'][$uid] = ($uid == $event['owner'] ? 'A' : 'U'); - } - if (!isset($attributes['params']['ROLE']) || $attributes['params']['ROLE'] != 'ORGANIZER') - { - // add quantity and role - $event['participants'][$uid] = calendar_so::combine_status($status,$attributes['params']['X-EGROUPWARE-QUANTITY'],$attributes['params']['ROLE']); - break; + $attributes['params']['ROLE'] = 'CHAIR'; } + // add quantity and role + $event['participants'][$uid] = + calendar_so::combine_status($status, + $attributes['params']['X-EGROUPWARE-QUANTITY'], + $attributes['params']['ROLE']); + break; + case 'ORGANIZER': - $hasOrganizer = true; + if (isset($event['participants'][$uid])) + { + $status = $event['participants'][$uid]; + calendar_so::split_status($status, $quantity, $role); + $event['participants'][$uid] = + calendar_so::combine_status($status, $quantity, 'CHAIR'); + } if (is_numeric($uid)) { $event['owner'] = $uid; @@ -1929,9 +1959,13 @@ class calendar_ical extends calendar_boupdate else { $event['owner'] = $this->user; + if (!isset($event['participants'][$uid])) + { + // save the ORGANIZER as event CHAIR + $event['participants'][$uid] = + calendar_so::combine_status('U', 1, 'CHAIR'); + } } - // RalfBecker: this is not allways true, owner can choose to NOT participate in EGroupware - $event['participants'][$uid] = 'A'; break; } break; @@ -1944,13 +1978,6 @@ class calendar_ical extends calendar_boupdate } } - if (!$hasOrganizer && $this->productManufacturer == 'groupdav' - && !isset($event['participants'][$this->user])) - { - // according to iCalendar standard, ORGANIZER not used for events in the own calendar - $event['participants'][$this->user] = 'A'; - } - // check if the entry is a birthday // this field is only set from NOKIA clients $agendaEntryType = $component->getAttribute('X-EPOCAGENDAENTRYTYPE'); diff --git a/calendar/inc/class.calendar_so.inc.php b/calendar/inc/class.calendar_so.inc.php index 8f30ec5bee..069112ab02 100644 --- a/calendar/inc/class.calendar_so.inc.php +++ b/calendar/inc/class.calendar_so.inc.php @@ -908,6 +908,10 @@ ORDER BY cal_user_type, cal_usre_id if ($matches[2]) $role = $matches[2]; $status = $status[0]; } + elseif ($status === true) + { + $status = 'U'; + } } /** @@ -1076,7 +1080,7 @@ ORDER BY cal_user_type, cal_usre_id else { $set = array('cal_status' => $status); - if (!is_null($role)) $set['cal_role'] = $role; + if (!is_null($role) && $role != 'REQ-PARTICIPANT') $set['cal_role'] = $role; $this->db->insert($this->user_table,$set,$where,__LINE__,__FILE__,'calendar'); } $ret = $this->db->affected_rows(); @@ -1109,9 +1113,11 @@ ORDER BY cal_user_type, cal_usre_id $type = ''; $id = null; $this->split_user($uid,$type,$id); + $this->split_status($status,$quantity,$role); $this->db->insert($this->user_table,array( - 'cal_status' => $status !== true ? $status[0] : 'U', - 'cal_quantity' => substr($status,1) ? substr($status,1) : 1, + 'cal_status' => $status, + 'cal_quantity' => $quantity, + 'cal_role' => $role ),array( 'cal_id' => $cal_id, 'cal_recur_date' => $start, diff --git a/calendar/inc/class.calendar_uiforms.inc.php b/calendar/inc/class.calendar_uiforms.inc.php index 0b2258933d..4b043059ba 100644 --- a/calendar/inc/class.calendar_uiforms.inc.php +++ b/calendar/inc/class.calendar_uiforms.inc.php @@ -141,7 +141,7 @@ class calendar_uiforms extends calendar_ui } if (!$participants) // if all participants got removed, include current user { - $participants[$this->user] = $participant_types['u'][$this->user] = calendar_so::combine_status('A','CHAIR'); + $participants[$this->user] = $participant_types['u'][$this->user] = calendar_so::combine_status('A',1,'CHAIR'); } return array( 'participant_types' => $participant_types, @@ -351,7 +351,8 @@ class calendar_uiforms extends calendar_ui if ($data['old_status'] != $status && !(!$data['old_status'] && $status == 'G')) { //echo "

$uid: status changed '$data[old_status]' --> '$status<'/p>\n"; - if ($this->bo->set_status($event['id'],$uid,$status,isset($content['edit_single']) ? $content['participants']['status_date'] : 0)) + $new_status = calendar_so::combine_status($status, $quantity, $role); + if ($this->bo->set_status($event['id'],$uid,$new_status,isset($content['edit_single']) ? $content['participants']['status_date'] : 0)) { // refreshing the calendar-view with the changed participant-status if($event['recur_type'] != MCAL_RECUR_NONE)