diff --git a/calendar/inc/class.bocalupdate.inc.php b/calendar/inc/class.bocalupdate.inc.php index 619534f26d..961c5f0d31 100644 --- a/calendar/inc/class.bocalupdate.inc.php +++ b/calendar/inc/class.bocalupdate.inc.php @@ -51,7 +51,7 @@ class bocalupdate extends bocal * @var mixed */ var $debug; - + /** * @var string/boolean $log_file filename to enable the login or false for no update-logging */ @@ -65,12 +65,12 @@ class bocalupdate extends bocal if ($this->debug > 0) $this->debug_message('bocalupdate::bocalupdate() started',True); $this->bocal(); // calling the parent constructor - + if ($this->debug > 0) $this->debug_message('bocalupdate::bocalupdate() finished',True); } /** - * updates or creates an event, it (optionaly) checks for conflicts and sends the necessary notifications + * updates or creates an event, it (optionaly) checks for conflicts and sends the necessary notifications * * @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 @@ -81,6 +81,7 @@ class bocalupdate extends bocal */ function update(&$event,$ignore_conflicts=false,$touch_modified=true,$ignore_acl=false) { + //error_log(__METHOD__."(".str_replace(array("\n",' '),'',print_r($event,true)).",$ignore_conflicts,$touch_modified,$ignore_acl)"); if ($this->debug > 1 || $this->debug == 'update') { $this->debug_message('bocalupdate::update(%1,ignore_conflict=%2,touch_modified=%3,ignore_acl=%4)', @@ -90,7 +91,7 @@ class bocalupdate extends bocal // - new events need start, end and title // - updated events cant set start, end or title to empty if (!$event['id'] && (!$event['start'] || !$event['end'] || !$event['title']) || - $event['id'] && (isset($event['start']) && !$event['start'] || isset($event['end']) && !$event['end'] || + $event['id'] && (isset($event['start']) && !$event['start'] || isset($event['end']) && !$event['end'] || isset($event['title']) && !$event['title'])) { return false; @@ -104,7 +105,7 @@ class bocalupdate extends bocal if (!$event['id'] && (!is_array($event['participants']) || !count($event['participants']))) { $event['participants'][$event['owner']] = 'U'; - } + } // set the status of the current user to 'A' = accepted if (isset($event['participants'][$this->user]) && $event['participants'][$this->user] != 'A') { @@ -113,7 +114,7 @@ class bocalupdate extends bocal } // 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'])) && + !$event['id'] && !$this->check_perms(EGW_ACL_EDIT,0,$event['owner'])) && !$this->check_perms(EGW_ACL_ADD,0,$event['owner'])) { // Just update the status, if the user is in the event already @@ -147,7 +148,7 @@ class bocalupdate extends bocal foreach($event['participants'] as $uid => $status) { if ($status[0] == 'R') continue; // ignore rejected participants - + if ($uid < 0) // group, check it's members too { $users += $GLOBALS['egw']->accounts->members($uid,true); @@ -187,7 +188,7 @@ class bocalupdate extends bocal $common_parts = array_intersect($users,array_keys($overlap['participants'])); foreach($common_parts as $n => $uid) { - if ($overlap['participants'][$uid]{0} == 'R') + if ($overlap['participants'][$uid]{0} == 'R') { unset($common_parts[$uid]); continue; @@ -231,7 +232,7 @@ class bocalupdate extends bocal } } unset($possible_quantity_conflicts); - + if (count($conflicts)) { foreach($conflicts as $key => $conflict) @@ -252,7 +253,7 @@ class bocalupdate extends bocal $this->debug_message('bocalupdate::update() %1 conflicts found %2',false,count($conflicts),$conflicts); } return $conflicts; - } + } } // save the event to the database @@ -304,11 +305,11 @@ class bocalupdate extends bocal * * @param array $new_event the updated event * @param array $old_event the event before the update - */ + */ function check4update($new_event,$old_event) { $modified = $added = $deleted = array(); - + //echo "
bocalupdate::check4update() new participants = ".print_r($new_event['participants'],true).", old participants =".print_r($old_event['participants'],true)."
\n"; // Find modified and deleted participants ... @@ -509,7 +510,7 @@ class bocalupdate extends bocal $notify_msg = $this->cal_prefs['notifyAdded']; // use a default } $details = $this->_get_event_details($event,$action,$event_arr,$disinvited); - + // add all group-members to the notification, unless they are already participants foreach($to_notify as $userid => $statusid) { @@ -532,7 +533,7 @@ class bocalupdate extends bocal { $res_info = $this->resource_info($userid); $userid = $res_info['responsible']; - if (!isset($userid)) continue; + if (!isset($userid)) continue; } if ($statusid == 'R' || $GLOBALS['egw']->accounts->get_type($userid) == 'g') @@ -550,11 +551,11 @@ class bocalupdate extends bocal } $GLOBALS['egw']->accounts->get_account_name($userid,$lid,$details['to-firstname'],$details['to-lastname']); $details['to-fullname'] = $GLOBALS['egw']->common->display_fullname('',$details['to-firstname'],$details['to-lastname']); - + $GLOBALS['egw_info']['user']['preferences']['common']['tz_offset'] = $part_prefs['common']['tz_offset']; $GLOBALS['egw_info']['user']['preferences']['common']['timeformat'] = $part_prefs['common']['timeformat']; $GLOBALS['egw_info']['user']['preferences']['common']['dateformat'] = $part_prefs['common']['dateformat']; - + $GLOBALS['egw']->datetime->tz_offset = 3600 * (int) $GLOBALS['egw_info']['user']['preferences']['common']['tz_offset']; // event is in user-time of current user, now we need to calculate the tz-difference to the notified user and take it into account @@ -587,7 +588,7 @@ class bocalupdate extends bocal case 'ical': $ics = ExecMethod2('calendar.boical.exportVCal',$event['id'],'2.0',$method); - if ($method == 'REQUEST') + if ($method == 'REQUEST') { $attachment = array( 'string' => $ics, 'filename' => 'cal.ics', @@ -638,7 +639,7 @@ class bocalupdate extends bocal * Function called via async service, when an alarm is to be send * * @param array $alarm array with keys owner, cal_id, all - * @return boolean + * @return boolean */ function send_alarm($alarm) { @@ -684,6 +685,7 @@ class bocalupdate extends bocal */ function save($event) { + //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']) || !$event['id'] && !$this->check_perms(EGW_ACL_EDIT,0,$event['owner']) && @@ -702,9 +704,6 @@ class bocalupdate extends bocal // we convert here from user-time to timestamps in server-time! if (isset($event[$ts])) $event[$ts] = $event[$ts] ? $this->date2ts($event[$ts],true) : 0; } - // Lock realized with a counter, that is checked and incremented as we save the entry - $check_etag = ($event['etag'] ? $event['etag']:0); - // same with the recur exceptions if (isset($event['recur_exception']) && is_array($event['recur_exception'])) { @@ -721,7 +720,7 @@ class bocalupdate extends bocal $event['alarm'][$id]['time'] = $this->date2ts($alarm['time'],true); } } - if (($cal_id = $this->so->save($event,$set_recurrences,NULL,$check_etag)) && $set_recurrences && $event['recur_type'] != MCAL_RECUR_NONE) + if (($cal_id = $this->so->save($event,$set_recurrences,NULL,$event['etag'])) && $set_recurrences && $event['recur_type'] != MCAL_RECUR_NONE) { $save_event['id'] = $cal_id; $this->set_recurrences($save_event); @@ -730,10 +729,10 @@ class bocalupdate extends bocal return $cal_id; } - + /** * Check if the current user has the necessary ACL rights to change the status of $uid - * + * * For contacts we use edit rights of the owner of the event (aka. edit rights of the event). * * @param int/string $uid account_id or 1-char type-identifer plus id (eg. c15 for addressbook entry #15) @@ -804,19 +803,19 @@ class bocalupdate extends bocal function delete($cal_id,$recur_date=0) { $event = $this->read($cal_id,$recur_date); - + if (!($event = $this->read($cal_id,$recur_date)) || !$this->check_perms(EGW_ACL_DELETE,$event)) { return false; } $this->send_update(MSG_DELETED,$event['participants'],$event); - + if (!$recur_date || $event['recur_type'] == MCAL_RECUR_NONE) { $this->so->delete($cal_id); $GLOBALS['egw']->contenthistory->updateTimeStamp('calendar',$cal_id,'delete',time()); - + // delete all links to the event egw_link::unlink(0,'calendar',$cal_id); } @@ -858,7 +857,7 @@ class bocalupdate extends bocal $link; } $event_arr['link']['data'] = $details['link'] = $link; - + /* this is needed for notification-app * notification-app creates the link individual for * every user, so we must provide a neutral link-style @@ -872,7 +871,7 @@ class bocalupdate extends bocal ); $link_arr['popup'] = '750x400'; $details['link_arr'] = $link_arr; - + $dis = array(); foreach($disinvited as $uid) { @@ -1102,18 +1101,4 @@ class bocalupdate extends bocal return $cat_list; } - - /** - * updates the edit user information for timelocking an event - * - * @param array &$event2update event-array, on return some values might be changed due to set defaults - * this is a wrapper for the socal function - * cal_edit_time is set to current timestamp - * @return the returnvalue of so->save_edit_user (0 (someone else modified the entry), true (saved) or false (could not save))) - */ - function update_edit_user(&$event2update) - { - $event2update['edit_time']=$this->now_su; - return $this->so->save_edit_user($event2update); - } } diff --git a/calendar/inc/class.socal.inc.php b/calendar/inc/class.socal.inc.php index b92d04250c..1b639a3310 100644 --- a/calendar/inc/class.socal.inc.php +++ b/calendar/inc/class.socal.inc.php @@ -68,7 +68,7 @@ class socal /** * internal copy of the global db-object - * + * * @var egw_db */ var $db; @@ -464,12 +464,13 @@ ORDER BY cal_user_type, cal_usre_id * @param array $event * @param boolean &$set_recurrences on return: true if the recurrences need to be written, false otherwise * @param int $change_since=0 time from which on the repetitions should be changed, default 0=all - * @return boolean/int false on error, cal_id otherwise - * @return int $check_etag check etag from GUI, if there is any Change since the last save SB:Lock for etag + * @param int &$etag etag=null etag to check or null, on return new etag + * @return boolean/int false on error, 0 if etag does not match, cal_id otherwise */ - function save($event,&$set_recurrences,$change_since=0,$check_modified=0) + function save($event,&$set_recurrences,$change_since=0,&$etag=null) { //echo "socal::save(,$change_since) event="; _debug_array($event); + error_log(__METHOD__."(".str_replace(array("\n",' '),'',print_r($event,true)).",$set_recurrences,$change_since,$etag)"); $cal_id = (int) $event['id']; unset($event['id']); @@ -486,36 +487,21 @@ ORDER BY cal_user_type, cal_usre_id } if (is_array($event['cal_category'])) $event['cal_category'] = implode(',',$event['cal_category']); - // while saving handle the etag as condition for the update, to check if an entry was saved before this action occured - $check_etag = ($check_modified ? $check_modified : $event['cal_etag']); - if ($cal_id && $check_etag && $check_modified) - { - //$event2update[]= 'cal_etag=cal_etag+1'; - $event2update['cal_etag']= $event['cal_etag']=$check_etag+1; - $event2update['cal_edit_user']= $event['cal_edit_user']=NULL; - $event2update['cal_edit_time']= $event['cal_edit_time']=NULL; - // cal_etag will be set on first save (if not set) - $where = array('cal_id' => $cal_id,'(cal_etag is NULL or cal_etag='.$check_etag.')'); - #if ($check_etag) $where['cal_etag'] = $check_etag; - if (!$this->db->update($this->cal_table,$event2update,$where,__LINE__,__FILE__,'calendar')) - { - //error_log("### socal::write(".print_r($event,true).") where=".print_r($where,true)." returning false"); - return false; // Error - } - //echo $this->db->affected_rows()."##"; - if ($check_etag && $this->db->affected_rows() < 1) - { - //error_log("### socal::write(".print_r($event,true).") where=".print_r($where,true)." returning 0 (nothing updated, eg. condition not met)"); - return 0; // someone else updated the modtime or deleted the entry - } - - } else { - $event['cal_etag']=($check_etag?$check_etag:1); - } - if ($cal_id) { - $this->db->update($this->cal_table,$event,array('cal_id' => $cal_id),__LINE__,__FILE__,'calendar'); + $where = array('cal_id' => $cal_id); + if (!is_null($etag)) $where['cal_etag'] = $etag; + + unset($event['cal_etag']); + $event[] = 'cal_etag=cal_etag+1'; // always update the etag, even if none given to check + + $this->db->update($this->cal_table,$event,$where,__LINE__,__FILE__,'calendar'); + + if (!is_null($etag) && $this->db->affected_rows() < 1) + { + return 0; // wrong etag, someone else updated the entry + } + if (!is_null($etag)) ++$etag; } else { @@ -534,6 +520,7 @@ ORDER BY cal_user_type, cal_usre_id $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'])) { @@ -635,6 +622,10 @@ ORDER BY cal_user_type, cal_usre_id $this->save_alarm($cal_id,$alarm); } } + if (is_null($etag)) + { + $etag = $this->db->select($this->cal_table,'cal_etag',array('cal_id' => $cal_id),__LINE__,__FILE__,false,'','calendar')->fetchSingle(); + } return $cal_id; } @@ -1104,45 +1095,4 @@ ORDER BY cal_user_type, cal_usre_id ),__LINE__,__FILE__,'calendar'); } } - - /** - * Save actually User, who is working on the Calenar Data if there is no user set or the timestamp is "expired" - * - * @param array $event2update - * - * @return (0 (someone else modified the entry), true (saved) or false (could not save))) - */ - function save_edit_user($event2update) - { - $cal_id = (int) $event2update['id']; - //unset($event2update['id']); - - // add colum prefix 'cal_' if there's not already a 'recur_' prefix - foreach($event2update as $col => $val) - { - if ($col{0} != '#' && substr($col,0,6) != 'recur_' && $col != 'alarm') - { - $event2update['cal_'.$col] = $val; - unset($event2update[$col]); - } - } - if ($cal_id && $event2update['cal_edit_user'] && $event2update['cal_edit_time']) - { - $locktime = ($GLOBALS['egw_info']['server']['Lock_Time_Calender'] ? $GLOBALS['egw_info']['server']['Lock_Time_Calender'] : 1); - $lockborder=$event2update['cal_edit_time']-$locktime; - $where = array('cal_id' => $cal_id,'(cal_edit_user is NULL or cal_edit_time<'.$lockborder.')'); - if (!$this->db->update($this->cal_table,$event2update,$where,__LINE__,__FILE__,'calendar')) - { - //error_log("### socal::write(".print_r($event,true).") where=".print_r($where,true)." returning false"); - return false; // Error - } - //echo $this->db->affected_rows()."##"; - if ($this->db->affected_rows() < 1) - { - //error_log("### socal::write(".print_r($event,true).") where=".print_r($where,true)." returning 0 (nothing updated, eg. condition not met)"); - return 0; // someone else updated the modtime or deleted the entry - } - return true; - } - } } diff --git a/calendar/inc/class.uiforms.inc.php b/calendar/inc/class.uiforms.inc.php index be8cc91e98..29b7ca2eff 100644 --- a/calendar/inc/class.uiforms.inc.php +++ b/calendar/inc/class.uiforms.inc.php @@ -38,21 +38,21 @@ class uiforms extends uical * @var bolink */ var $link; - + /** * Standard durations used in edit and freetime search * * @var array */ var $durations = array(); - + /** * Name of the tabs used in edit * * @var string */ var $tabs = 'general|description|participants|recurrence|custom|links|alarms'; - + /** * default timelock for entries, that are opened by another user * @@ -66,20 +66,20 @@ class uiforms extends uical function uiforms() { $this->uical(true); // call the parent's constructor - + $this->link =& $this->bo->link; - + for ($n=15; $n <= 8*60; $n+=($n < 60 ? 15 : ($n < 240 ? 30 : 60))) { $this->durations[$n*60] = sprintf('%d:%02d',$n/60,$n%60); } } - + /** * Create a default event (adding a new event) by evaluating certain _GET vars * * @return array event-array - */ + */ function &default_add_event() { $extra_participants = $_GET['participants'] ? explode(',',$_GET['participants']) : array(); @@ -93,7 +93,7 @@ class uiforms extends uical { $owner = $this->owner; } - if (!$owner || !is_numeric($owner) || $GLOBALS['egw']->accounts->get_type($owner) != 'u' || + if (!$owner || !is_numeric($owner) || $GLOBALS['egw']->accounts->get_type($owner) != 'u' || !$this->bo->check_perms(EGW_ACL_ADD,0,$owner)) { if ($owner) // make an owner who is no user or we have no add-rights a participant @@ -113,7 +113,7 @@ class uiforms extends uical 'minute' => (int) $_GET['minute'], )); //echo "
_GET[date]=$_GET[date], _GET[hour]=$_GET[hour], _GET[minute]=$_GET[minute], this->date=$this->date ==> start=$start=".date('Y-m-d H:i',$start)."
\n"; - + $participant_types['u'] = $participant_types = $participants = array(); foreach($extra_participants as $uid) { @@ -130,7 +130,7 @@ class uiforms extends uical $participants[$uid] = $participant_types[$uid{0}][$id] = ($res_data['new_status'] ? ExecMethod($res_data['new_status'],$id) : 'U'). ((int) $quantity > 1 ? (int)$quantity : ''); // if new_status == 'x', resource is not bookable - if(strpos($participant_types[$uid{0}][$id],'x') !== false) + if(strpos($participant_types[$uid{0}][$id],'x') !== false) { unset($participant_types[$uid{0}][$id]); unset($participants[$uid]); @@ -148,7 +148,7 @@ class uiforms extends uical 'alarm' => array(), ); } - + /** * Process the edited event and evtl. call edit to redisplay it * @@ -182,7 +182,7 @@ class uiforms extends uical { list($id) = each($content['alarm']['delete_alarm']); //echo "delete alarm $id"; _debug_array($content['alarm']['delete_alarm']); - + if ($content['id']) { if ($this->bo->delete_alarm($id)) @@ -192,7 +192,7 @@ class uiforms extends uical } else { - $msg = lang('Permission denied'); + $msg = lang('Permission denied'); } } else @@ -256,7 +256,7 @@ class uiforms extends uical { $status = isset($this->bo->resources[$type]['new_status']) ? ExecMethod($this->bo->resources[$type]['new_status'],$id) : 'U'; $quantity = $content['participants']['quantity'] ? $content['participants']['quantity'] : 1; - if ($uid) $event['participants'][$uid] = $event['participant_types'][$type][$id] = + if ($uid) $event['participants'][$uid] = $event['participant_types'][$type][$id] = $status.((int) $quantity > 1 ? (int)$quantity : ''); break; } @@ -264,7 +264,7 @@ class uiforms extends uical case 'account': foreach(is_array($data) ? $data : explode(',',$data) as $uid) { - if ($uid) $event['participants'][$uid] = $event['participant_types']['u'][$uid] = + if ($uid) $event['participants'][$uid] = $event['participant_types']['u'][$uid] = $uid == $this->bo->user ? 'A' : 'U'; } break; @@ -282,12 +282,12 @@ class uiforms extends uical { if (is_numeric($uid)) { - $id = $uid; + $id = $uid; $type = 'u'; } else { - $id = substr($uid,1); + $id = substr($uid,1); $type = $uid{0}; } if ($data['old_status'] != $status) @@ -307,7 +307,7 @@ class uiforms extends uical } if ($uid && $status != 'G') { - $event['participants'][$uid] = $event['participant_types'][$type][$id] = + $event['participants'][$uid] = $event['participant_types'][$type][$id] = $status.((int) $quantity > 1 ? (int)$quantity : ''); } } @@ -344,7 +344,7 @@ class uiforms extends uical $msg = lang('Event copied - the copy can now be edited'); $event['title'] = lang('Copy of:').' '.$event['title']; break; - + case 'ignore': $ignore_conflicts = true; $button = $event['button_was']; // save or apply @@ -353,15 +353,15 @@ class uiforms extends uical case 'mail': case 'save': case 'apply': - if ($event['id'] && !$this->bo->check_perms(EGW_ACL_EDIT,$event)) - { + if ($event['id'] && !$this->bo->check_perms(EGW_ACL_EDIT,$event)) + { if ($button == 'mail') // just mail without edit-rights is ok { $js = $this->custom_mail($event,false); break; } - $msg = lang('Permission denied'); - break; + $msg = lang('Permission denied'); + break; } if ($event['start'] > $event['end']) { @@ -409,7 +409,7 @@ class uiforms extends uical $event['button_was'] = $button; // remember for ignore return $this->conflicts($event,$conflicts,$preserv); } - elseif ($conflicts ===0) + elseif ($conflicts ===0) { $msg .= ($msg ? ', ' : '') .lang('Error: the entry has been updated since you opened it for editing!').'lock_path=$lock_path, lock_owner=$lock_owner, lock_token=$preserv[lock_token], msg=$msg
\n"; + } $content = array_merge($event,array( 'link_to' => array( 'to_id' => $link_to_id, @@ -710,6 +747,7 @@ class uiforms extends uical 'edit_single' => $preserv['edit_single'], // need to be in content too, as it is used in the template $this->tabs => $preserv[$this->tabs], 'view' => $view, + 'msg' => $msg, )); $content['duration'] = $content['end'] - $content['start']; if (isset($this->durations[$content['duration']])) $content['end'] = ''; @@ -736,9 +774,9 @@ class uiforms extends uical $readonlys[$row.'[quantity]'] = $type == 'u' || !isset($this->bo->resources[$type]['max_quantity']); $readonlys[$row.'[status]'] = $readonlys[$row.'[status_recurrence]'] = !$this->bo->check_status_perms($uid,$event); $readonlys["delete[$uid]"] = !$this->bo->check_perms(EGW_ACL_EDIT,$event); - $content['participants'][$row++]['title'] = $name == 'accounts' ? + $content['participants'][$row++]['title'] = $name == 'accounts' ? $GLOBALS['egw']->common->grab_owner_name($id) : egw_link::title($name,$id); - + // enumerate group-invitations, so people can accept/reject them if ($name == 'accounts' && $GLOBALS['egw']->accounts->get_type($id) == 'g' && ($members = $GLOBALS['egw']->accounts->members($id,true))) @@ -787,7 +825,7 @@ class uiforms extends uical if ($minutes) $label[] = $minutes.' '.lang('Minutes'); $alarm['offset'] = implode(', ',$label); $content['alarm'][] = $alarm; - + $readonlys['delete_alarm['.$id.']'] = !$this->bo->check_perms(EGW_ACL_EDIT,$alarm['all'] ? $event : 0,$alarm['owner']); } } @@ -811,7 +849,7 @@ class uiforms extends uical $readonlys['button[save]'] = $readonlys['button[apply]'] = $readonlys['freetime'] = true; $readonlys['link_to'] = $readonlys['customfields'] = true; $readonlys['duration'] = true; - + if ($event['recur_type'] != MCAL_RECUR_NONE) { $onclick =& $etpl->get_cell_attribute('button[delete]','onclick'); @@ -821,10 +859,6 @@ class uiforms extends uical } else { - if (!is_object($GLOBALS['egw']->js)) - { - $GLOBALS['egw']->js = CreateObject('phpgwapi.javascript'); - } // We hide the enddate if one of our predefined durations fits // the call to set_style_by_class has to be in onload, to make sure the function and the element is already created $GLOBALS['egw']->js->set_onload("set_style_by_class('table','end_hide','visibility','".($content['duration'] && isset($sel_options['duration'][$content['duration']]) ? 'hidden' : 'visible')."');"); @@ -868,7 +902,7 @@ class uiforms extends uical $content['no_add_alarm'] = !count($sel_options['owner']); // no rights to set any alarm if (!$event['id']) { - $etpl->set_cell_attribute('button[new_alarm]','type','checkbox'); + $etpl->set_cell_attribute('button[new_alarm]','type','checkbox'); } if ($preserv['no_popup']) { @@ -878,31 +912,12 @@ class uiforms extends uical //echo "preserv="; _debug_array($preserv); //echo "readonlys="; _debug_array($readonlys); //echo "sel_options="; _debug_array($sel_options); - $GLOBALS['egw_info']['flags']['app_header'] = lang('calendar') . ' - ' . (!$event['id'] ? lang('Add') : ($view ? lang('View') : + $GLOBALS['egw_info']['flags']['app_header'] = lang('calendar') . ' - ' . (!$event['id'] ? lang('Add') : ($view ? lang('View') : ($content['edit_single'] ? lang('Create exception') : ($content['recur_type'] ? lang('Edit series') : lang('Edit'))))); $GLOBALS['egw_info']['flags']['java_script'] .= "\n"; - - $content['cancel_needs_refresh'] = (bool)$_GET['cancel_needs_refresh']; - - // time locking for entries - $locktime = $GLOBALS['egw_info']['server']['Lock_Time_Calender']; - if ($locktime) { - // the warning and the saving of edit_user and time will only be performed, if there is a lock time set - if (($this->bo->now_su>($event['edit_time']+$locktime)) || ($event['edit_time']=='')) - { - //echo "write Lock!!->DB"; - $event2update['id']=$event['id']; - $event2update['edit_user']=$this->user; - $event2update['edit_time']=''; // this is set in bo->update_edit_user - $this->bo->update_edit_user($event2update); - } - else - { - if ($event['edit_user'] && $event['edit_user']!=$this->user) $content['msg'].=" ".lang('This entry is opened by user: ').$GLOBALS['egw']->accounts->id2name($event['edit_user']); - } - } else { - } + $content['cancel_needs_refresh'] = (bool)$_GET['cancel_needs_refresh']; + // non_interactive==true from $_GET calls immediate save action without displaying the edit form if(isset($_GET['non_interactive']) && (bool)$_GET['non_interactive'] === true) { @@ -916,21 +931,41 @@ class uiforms extends uical } } + /** + * Remove (shared) lock via ajax, when edit popup get's closed + * + * @param int $id + * @param string $token + */ + function ajax_unlock($id,$token) + { + $lock_path = egw_vfs::app_entry_lock_path('calendar',$id); + $lock_owner = 'mailto:'.$GLOBALS['egw_info']['user']['account_email']; + + if (($lock = egw_vfs::checkLock($lock_path)) && $lock['owner'] == $lock_owner || $lock['token'] == $token) + { + egw_vfs::unlock($lock_path,$token,false); + } + $response = new xajaxResponse(); + $response->addScript('window.close();'); + return $response->getXML(); + } + /** * displays a sheduling conflict * - * @param array $event + * @param array $event * @param array $conflicts array with conflicting events, the events are not garantied to be readable by the user! * @param array $preserv data to preserv */ function conflicts($event,$conflicts,$preserv) { $etpl =& CreateObject('etemplate.etemplate','calendar.conflicts'); - + foreach($conflicts as $k => $conflict) { $is_readable = $this->bo->check_perms(EGW_ACL_READ,$conflict); - + $conflicts[$k] += array( 'icon_participants' => $is_readable ? (count($conflict['participants']) > 1 ? 'users' : 'single') : 'private', 'tooltip_participants' => $is_readable ? implode(', ',$this->bo->participants($conflict)) : '', @@ -940,7 +975,7 @@ class uiforms extends uical ),true,true)), // show group invitations too 'icon_recur' => $conflict['recur_type'] != MCAL_RECUR_NONE ? 'recur' : '', 'text_recur' => $conflict['recur_type'] != MCAL_RECUR_NONE ? lang('Recurring event') : ' ', - ); + ); } $content = $event + array( 'conflicts' => array_values($conflicts), // conflicts have id-start as key @@ -1018,12 +1053,12 @@ class uiforms extends uical $content['end_time'] = 0; // no end-time limit, as duration would never fit } $content['weekdays'] = MCAL_M_WEEKDAYS; - + $content['search_window'] = 7 * DAY_s; // pick a searchwindow fitting the duration (search for a 10 day slot in a one week window never succeeds) foreach($sel_options['search_window'] as $window => $label) { - if ($window > $content['duration']) + if ($window > $content['duration']) { $content['search_window'] = $window; break; @@ -1032,8 +1067,8 @@ class uiforms extends uical } else { - if (!$content['duration']) $content['duration'] = $content['end'] - $content['start']; - + if (!$content['duration']) $content['duration'] = $content['end'] - $content['start']; + if (is_array($content['freetime']['select'])) { list($selected) = each($content['freetime']['select']); @@ -1059,7 +1094,7 @@ class uiforms extends uical 'exec[end][a]' => date('a',$end), ); } - else + else { $fields_to_set += array( 'exec[start][H]' => (int) date('H',$start), @@ -1081,7 +1116,7 @@ class uiforms extends uical } } } - window.close(); + window.close();