From b111419c1bb1ca54e2abfe002c7a66127b1da5e9 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Wed, 23 Nov 2005 14:21:20 +0000 Subject: [PATCH] fixed handling of groups: - groups can now be selected as participants again - groups need to have calendar run-rights, to be selectable in the calendar (as it was in 1.0) - groups will NOT be enumerated as users anymore --> new or removed members are taken into account as participants - error messages: if no participant selected or startdate behind enddate (no more automatic swapping) - pushing the version to 1.2 --- calendar/inc/class.bocal.inc.php | 57 +++++++++++++- calendar/inc/class.bocalupdate.inc.php | 25 ++++-- calendar/inc/class.socal.inc.php | 31 ++++++-- calendar/inc/class.uical.inc.php | 46 +++-------- calendar/inc/class.uiforms.inc.php | 103 +++++++++++++++++-------- calendar/inc/class.uiviews.inc.php | 1 + calendar/setup/etemplates.inc.php | 4 +- calendar/setup/phpgw_de.lang | 2 + calendar/setup/phpgw_en.lang | 2 + calendar/setup/setup.inc.php | 3 +- calendar/setup/tables_current.inc.php | 1 - calendar/setup/tables_update.inc.php | 54 ++++++++++++- 12 files changed, 241 insertions(+), 88 deletions(-) diff --git a/calendar/inc/class.bocal.inc.php b/calendar/inc/class.bocal.inc.php index 96decb1b28..5d5c24fe7d 100644 --- a/calendar/inc/class.bocal.inc.php +++ b/calendar/inc/class.bocal.inc.php @@ -194,6 +194,34 @@ class bocal unset($config); } + /** + * Add group-members as participants with status 'G' + * + * @param array $event event-array + * @return int number of added participants + */ + function enum_groups(&$event) + { + $added = 0; + foreach($event['participants'] as $uid => $status) + { + if (is_numeric($uid) && $GLOBALS['egw']->accounts->get_type($uid) == 'g' && + ($members = $GLOBALS['egw']->accounts->member($uid))) + { + foreach($members as $member) + { + $member = $member['account_id']; + if (!isset($event['participants'][$member])) + { + $event['participants'][$member] = 'G'; + ++$added; + } + } + } + } + return $added; + } + /** * Searches / lists calendar entries, including repeating ones * @@ -217,6 +245,7 @@ class bocal * order column-names plus optional DESC|ASC separted by comma * show_rejected if set rejected invitation are shown only when true, otherwise it depends on the cal-pref or a running query * ignore_acl if set and true no check_perms for a general EGW_ACL_READ grants is performed + * enum_groups boolean if set and true, group-members will be added as participants with status 'G' * @return array of events or array with YYYYMMDD strings / array of events pairs (depending on $daywise param) */ function &search($params) @@ -236,6 +265,8 @@ class bocal $users = array(); foreach($params['users'] as $user) { + if (in_array($user,$users)) continue; // already added + if ($params['ignore_acl'] || $this->check_perms(EGW_ACL_READ,0,$user)) { $users[] = $user; @@ -257,6 +288,20 @@ class bocal } } } + else // for users we have to include all the memberships, to get the group-events + { + $memberships = $GLOBALS['egw']->accounts->membership($user); + if (is_array($memberships)) + { + foreach($memberships as $group) + { + if (!in_array($group['account_id'],$users)) + { + $users[] = $group['account_id']; + } + } + } + } } } // if we have no grants from the given user(s), we directly return no events / an empty array, @@ -291,6 +336,10 @@ class bocal foreach($events as $id => $event) { + if ($params['enum_groups'] && $this->enum_groups($event)) + { + $events[$id] = $event; + } if (!$this->check_perms(EGW_ACL_READ,$event)) { $this->clear_private_infos($events[$id],$users); @@ -1225,16 +1274,18 @@ class bocal /** * Converts participants array of an event into array of (readable) participant-names with status * - * @param $event array of an event - * @param $long_status boolean should the long/verbose status or only the one letter shortcut be used + * @param array $event event-data + * @param boolean $long_status=false should the long/verbose status or only the one letter shortcut be used * @return array with id / names with status pairs */ - function participants($event,$long_status=False,$use_type=false) + function participants($event,$long_status=False) { //_debug_array($event); $names = array(); foreach($event['participants'] as $id => $status) { + if ($status == 'G') continue; // dont show group-invitation + $status = $this->verbose_status[$status]; if (!$long_status) diff --git a/calendar/inc/class.bocalupdate.inc.php b/calendar/inc/class.bocalupdate.inc.php index 62a72a5af0..2c2b7c44e0 100644 --- a/calendar/inc/class.bocalupdate.inc.php +++ b/calendar/inc/class.bocalupdate.inc.php @@ -386,9 +386,10 @@ class bocalupdate extends bocal * @param int $msg_type type of the notification: MSG_ADDED, MSG_MODIFIED, MSG_ACCEPTED, ... * @param array $to_notify numerical user-ids as keys (!) (value is not used) * @param array $old_event Event before the change - * @param array $new_event Event after the change + * @param array $new_event=null Event after the change + * @param int $user=0 User who started the notify, default current user */ - function send_update($msg_type,$to_notify,$old_event,$new_event=False,$user=False) + function send_update($msg_type,$to_notify,$old_event,$new_event=null,$user=0) { if (!is_array($to_notify)) { @@ -490,12 +491,26 @@ class bocalupdate extends bocal } $send = &$GLOBALS['egw']->send; + // add all group-members to the notification, unless they are already participants + foreach($to_notify as $userid => $statusid) + { + if (is_numeric($userid) && $GLOBALS['egw']->accounts->get_type($userid) == 'g' && + ($members = $GLOBALS['egw']->accounts->member($userid))) + { + foreach($members as $member) + { + $member = $member['account_id']; + if (!isset($to_notify[$member])) + { + $to_notify[$member] = 'G'; // Group-invitation + } + } + } + } foreach($to_notify as $userid => $statusid) { if (!is_numeric($userid)) continue; // eg. a resource, ToDo notify the responsible of the resource - $userid = (int)$userid; - if ($statusid == 'R' || $GLOBALS['egw']->accounts->get_type($userid) == 'g') { continue; // dont notify rejected participants or groups @@ -702,7 +717,7 @@ class bocalupdate extends bocal $this->send_update($status2msg[$status],$event['participants'],$event); } } - return Ok; + return $Ok; } /** diff --git a/calendar/inc/class.socal.inc.php b/calendar/inc/class.socal.inc.php index 14b0848748..beb9dc5db4 100644 --- a/calendar/inc/class.socal.inc.php +++ b/calendar/inc/class.socal.inc.php @@ -265,7 +265,7 @@ class socal * @param int/array $users user-id or array of user-id's, !$users means all entries regardless of users * @param int $cat_id=0 mixed category-id or array of cat-id's, default 0 = all * Please note: only a single cat-id, will include all sub-cats (if the common-pref 'cats_no_subs' is False) - * @param string $filter='' string space delimited filter-names, atm. 'all' or 'private' + * @param string $filter='' string space delimited filter-names, NOT used atm. * @param string $query='' pattern so search for, if unset or empty all matching entries are returned (no search) * Please Note: a search never returns repeating events more then once AND does not honor start+end date !!! * @param int/bool $offset=False offset for a limited query or False (default) @@ -707,6 +707,14 @@ ORDER BY cal_user_type, cal_usre_id { //echo "

socal::participants($cal_id,".print_r($participants,true).",$change_since)

\n"; + // remove group-invitations, they are NOT stored in the db + foreach($participants as $uid => $status) + { + if ($status == 'G') + { + unset($participants[$uid]); + } + } $where = array('cal_id' => $cal_id); if ((int) $change_since) @@ -716,14 +724,13 @@ ORDER BY cal_user_type, cal_usre_id if ($change_since !== false) // existing entries only { // delete not longer set participants - $parts = $deleted = array(); + $deleted = array(); $this->db->select($this->user_table,'DISTINCT cal_user_type,cal_user_id,cal_quantity',$where,__LINE__,__FILE__); while (($row = $this->db->row(true))) { $uid = $this->combine_user($row['cal_user_type'],$row['cal_user_id']); - if (!isset($participants[$uid])) + if (!isset($participants[$uid])) // delete group-invitations { - $parts[] = $uid; $deleted[$row['cal_user_type']][] = $row['cal_user_id']; } elseif($row['cal_quantity'] == (substr($participants[$uid],1) ? substr($participants[$uid],1) : 1)) @@ -801,7 +808,7 @@ ORDER BY cal_user_type, cal_usre_id if (!(int)$cal_id || !(int)$user_id) return false; if (is_numeric($status)) $status = $status_code_short[$status]; - + $where = array( 'cal_id' => $cal_id, 'cal_user_type' => $user_type ? $user_type : 'u', @@ -815,8 +822,16 @@ ORDER BY cal_user_type, cal_usre_id { $where[] = '(cal_recur_date=0 OR cal_recur_date >= '.time().')'; } - $this->db->update($this->user_table,array('cal_status' => $status),$where,__LINE__,__FILE__); - + if ($status == 'G') // remove group invitations, as we dont store them in the db + { + $this->db->delete($this->user_table,$where,__LINE__,__FILE__); + } + else + { + $this->db->insert($this->user_table,array( + 'cal_status' => $status, + ),$where,__LINE__,__FILE__); + } return $this->db->affected_rows(); } @@ -840,6 +855,8 @@ ORDER BY cal_user_type, cal_usre_id foreach($participants as $uid => $status) { + if ($status == 'G') continue; // dont save group-invitations + $this->split_user($uid,$type,$id); $this->db->insert($this->user_table,array( 'cal_status' => $status !== true ? $status{0} : 'U', diff --git a/calendar/inc/class.uical.inc.php b/calendar/inc/class.uical.inc.php index cd56886de8..433becdff9 100644 --- a/calendar/inc/class.uical.inc.php +++ b/calendar/inc/class.uical.inc.php @@ -72,7 +72,7 @@ class uical */ var $cat_id; /** - * @var int $filter session-state: selected filter + * @var int $filter session-state: selected filter, NOT used at the moment (was all or private) */ var $filter; /** @@ -158,7 +158,7 @@ class uical * - cat_id: the selected category * - owner: the owner of the displayed calendar * - save_owner: the overriden owner of the planner - * - filter: the used filter: no filter / all or only privat + * - filter: the used filter: no filter / all or only privat, NOT used atm. * - sortby: category or user of planner * - view: the actual view, where dialogs should return to or which they refresh * @param set_states array to manualy set / change one of the states, default NULL = use $_REQUEST @@ -235,12 +235,7 @@ class uical $this->view = $states['view'] = $func; } $this->view_menuaction = $this->view == 'listview' ? 'calendar.uilist.listview' : 'calendar.uiviews.'.$this->view; - // deal with group-owners - if (substr($this->owner,0,2) == 'g_' || $GLOBALS['egw']->accounts->get_type($this->owner) == 'g') - { - $this->set_owner_to_group($this->owner); - $states['owner'] = $this->owner; - } + $states['multiple'] = $this->multiple = $_GET['multiple'] || count(explode(',',$this->owner)) > 1; if ($this->debug > 0 || $this->debug == 'menage_states') $this->bo->debug_message('uical::manage_states(%1) session was %2, states now %3, is_group=%4, g_owner=%5',True,$set_states,$states_session,$states,$this->is_group,$this->g_owner); @@ -248,32 +243,6 @@ class uical $GLOBALS['egw']->session->appsession('session_data','calendar',$states); } - /** - * Sets a group as owner (of the events to show) - * - * It set $this->is_group and $this->g_owner - array with user-id's of the group-members who gave read-grants - * @param group-id or 'g_'+group-id - */ - function set_owner_to_group($owner) - { - $this->owner = (int) (substr($owner,0,2) == 'g_' ? substr($owner,2) : $owner); - $this->is_group = True; - $this->g_owner = Array(); - $members = $GLOBALS['egw']->accounts->member($this->owner); - if (is_array($members)) - { - foreach($members as $user) - { - // use only members which gave the user a read-grant - if ($this->bo->check_perms(EGW_ACL_READ,0,$user['account_id'])) - { - $this->g_owner[] = $user['account_id']; - } - } - } - if ($this->debug > 2 || $this->debug == 'set_owner_to_group') $this->bo->debug_message('uical::set_owner_to_group(%1): owner=%2, g_owner=%3',True,$owner,$this->owner,$this->g_owner); - } - /** * gets the icons displayed for a given event * @@ -295,7 +264,9 @@ class uical { $icons[] = $this->html->image('calendar','recur',lang('recurring event')); } - $icons[] = $this->html->image('calendar',count($event['participants']) > 1 ? 'users' : 'single'); + list($first_part) = each($event['participants']); + $icons[] = $this->html->image('calendar',count($event['participants']) > 1 || + $GLOBALS['egw']->accounts->get_type($first_part) == 'g' ? 'users' : 'single'); } if($event['public'] == 0) { @@ -537,13 +508,14 @@ class uical $file[$n]['text']; // Filter all or private +/* NOT used at the moment if(is_numeric($this->owner) && $this->bo->check_perms(EGW_ACL_PRIVATE,0,$this->owner)) { $file[] = $this->_select_box('Filter','filter', ''."\n". ''."\n"); } - +*/ // Calendarselection: User or Group if(count($this->bo->grants) > 0 && (!isset($GLOBALS['egw_info']['server']['deny_user_grants_access']) || !$GLOBALS['egw_info']['server']['deny_user_grants_access'])) @@ -576,7 +548,7 @@ function load_cal(url,id) { } ". - $this->accountsel->selection('owner','uical_select_owner',$accounts,'calendar+',$this->multiple ? 3 : 1,False, + $this->accountsel->selection('owner','uical_select_owner',$accounts,'calendar+',$this->multiple ? 4 : 1,False, ' style="width: '.($this->multiple && $this->common_prefs['account_selection']=='selectbox' ? 185 : 165).'px;"'. ' title="'.lang('select a %1',lang('user')).'" onchange="load_cal(\''. $GLOBALS['egw']->link('/index.php',array( diff --git a/calendar/inc/class.uiforms.inc.php b/calendar/inc/class.uiforms.inc.php index 82eb45698b..b05eab13ee 100644 --- a/calendar/inc/class.uiforms.inc.php +++ b/calendar/inc/class.uiforms.inc.php @@ -66,10 +66,23 @@ class uiforms extends uical */ function &default_add_event() { + $extra_participants = $_GET['participants'] ? explode(',',$_GET['participants']) : array(); + $owner = (int) (isset($_GET['owner']) ? $_GET['owner'] : $this->owner); - if (!$owner || !$this->bo->check_perms(EGW_ACL_ADD,0,$owner)) $owner = $this->user; + 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 + { + $extra_participants[] = $owner; + } + $owner = $this->user; + } //echo "

this->owner=$this->owner, _GET[owner]=$_GET[owner], user=$this->user => owner=$owner

\n"; + // by default include the owner as participant (the user can remove him) + $extra_participants[] = $owner; + $start = $this->bo->date2ts(array( 'full' => isset($_GET['date']) && (int) $_GET['date'] ? (int) $_GET['date'] : $this->date, 'hour' => (int) (isset($_GET['hour']) && (int) $_GET['hour'] ? $_GET['hour'] : $this->bo->cal_prefs['workdaystarts']), @@ -77,28 +90,26 @@ class uiforms extends uical )); //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 = array('u' => array($owner => $owner == $this->user ? 'A' : 'U')); - $participants = array($owner => $owner == $this->user ? 'A' : 'U'); - if ($_GET['participants']) + $participant_types['u'] = $participant_types = $participants = array(); + foreach($extra_participants as $uid) { - foreach(explode(',',$_GET['participants']) as $uid) + if (isset($participants[$uid])) continue; // already included + + if (is_numeric($uid)) { - if (is_numeric($uid)) + $participants[$uid] = $participant_types['u'][$uid] = $uid == $this->user ? 'A' : 'U'; + } + elseif (is_array($this->bo->resources[$uid{0}])) + { + $res_data = $this->bo->resources[$uid{0}]; + list($id,$quantity) = explode(':',substr($uid,1)); + $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(strstr($participant_types[$uid{0}][$id],'x')) { - $participants[$uid] = $participant_types['u'][$uid] = $uid == $this->user ? 'A' : 'U'; - } - elseif (is_array($this->bo->resources[$uid{0}])) - { - $res_data = $this->bo->resources[$uid{0}]; - list($id,$quantity) = explode(':',substr($uid,1)); - $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(strstr($participant_types[$uid{0}][$id],'x')) - { - unset($participant_types[$uid{0}][$id]); - unset($participants[$uid]); - } + unset($participant_types[$uid{0}][$id]); + unset($participants[$uid]); } } } @@ -209,11 +220,6 @@ class uiforms extends uical // ToDo: move this logic into bocal } } - if ($event['start'] > $event['end']) // end need to be after start, otherwise swap them - { - $event['start'] = $content['end']; - $event['end'] = $content['start']; - } if ($content['whole_day']) { $event['start'] = $this->bo->date2array($event['start']); @@ -314,6 +320,18 @@ class uiforms extends uical $msg = lang('Permission denied'); break; } + if ($event['start'] > $event['end']) + { + $msg = lang('Error: Starttime has to be before the endtime !!!'); + $button = ''; + break; + } + if (!$event['participants']) + { + $msg = lang('Error: no participants selected !!!'); + $button = ''; + break; + } if ($content['edit_single']) // we edited a single event from a series { $event['reference'] = $event['id']; @@ -516,6 +534,11 @@ class uiforms extends uical { $etpl =& CreateObject('etemplate.etemplate','calendar.edit'); + $sel_options = array( + 'recur_type' => &$this->bo->recur_types, + 'accounts_status' => $this->bo->verbose_status, + 'owner' => array(), + ); if (!is_array($event)) { $preserv = array( @@ -581,8 +604,29 @@ class uiforms extends uical if ($view) { - $content['participants'][$name][$name.'_status'] = $participants; - foreach($participants as $id => $status) + $stati =& $content['participants'][$name][$name.'_status']; + $stati = $participants; + // enumerate group-invitations, so people can accept/reject them + if ($name == 'accounts') + { + foreach($participants as $id => $status) + { + if ($GLOBALS['egw']->accounts->get_type($id) == 'g' && + ($members = $GLOBALS['egw']->accounts->member($id))) + { + $sel_options['accounts_status']['G'] = lang('Select one'); + foreach($members as $member) + { + if (!isset($stati[$member['account_id']]) && $this->bo->check_perms(EGW_ACL_EDIT,0,$member['account_id'])) + { + $stati[$member['account_id']] = 'G'; // status for invitation via membership in group + $content['participants'][$name][] = $member['account_id']; + } + } + } + } + } + foreach($stati as $id => $status) { $readonlys[$name.'_status['.$id.']'] = !$this->bo->check_perms(EGW_ACL_EDIT,0,($type != 'u' ? $type : '').$id); } @@ -657,11 +701,6 @@ class uiforms extends uical { $readonlys['button[delete_series]'] = !$view || $event['recur_type'] == MCAL_RECUR_NONE; } - $sel_options = array( - 'recur_type' => &$this->bo->recur_types, - 'accounts_status' => &$this->bo->verbose_status, - 'owner' => array(), - ); if ($event['id'] || $this->bo->check_perms(EGW_ACL_EDIT,$event)) // new event or edit rights to the event ==> allow to add alarm for all users { $sel_options['owner'][0] = lang('All participants'); diff --git a/calendar/inc/class.uiviews.inc.php b/calendar/inc/class.uiviews.inc.php index 8be2ce1a00..cb79a58771 100644 --- a/calendar/inc/class.uiviews.inc.php +++ b/calendar/inc/class.uiviews.inc.php @@ -192,6 +192,7 @@ class uiviews extends uical $search_params['daywise'] = false; $search_params['start'] = $this->first; $search_params['end'] = $this->last; + $search_params['enum_groups'] = $this->sortby == 'user'; $events = $this->bo->search($search_params); if ($this->debug > 0) $this->bo->debug_message('uiviews::planner() date=%1: first=%2, last=%3',False,$this->date,$this->bo->date2string($this->first),$this->bo->date2string($this->last)); diff --git a/calendar/setup/etemplates.inc.php b/calendar/setup/etemplates.inc.php index c53c3f5c43..f29c2ccaa3 100644 --- a/calendar/setup/etemplates.inc.php +++ b/calendar/setup/etemplates.inc.php @@ -1,5 +1,5 @@ 'calendar.edit.participants','template' => '','l $templ_data[] = array('name' => 'calendar.edit.participants','template' => '','lang' => '','group' => '0','version' => '1.0.1.002','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:5:{s:2:"c1";s:7:"row,top";s:1:"A";s:2:"95";s:2:"h1";s:6:",@view";s:2:"h2";s:7:",!@view";s:2:"c2";s:4:",top";}i:1;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"size";s:15:",,,participants";s:5:"label";s:12:"Participants";}s:1:"B";a:3:{s:4:"type";s:14:"select-account";s:4:"size";s:2:"14";s:4:"name";s:22:"participants[accounts]";}s:1:"C";a:3:{s:4:"type";s:5:"label";s:5:"label";s:9:"Resources";s:5:"align";s:5:"right";}s:1:"D";a:3:{s:4:"type";s:16:"resources_select";s:4:"size";s:2:"14";s:4:"name";s:23:"participants[resources]";}}i:2;a:4:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:12:"Participants";}s:1:"B";a:6:{s:4:"type";s:4:"grid";s:4:"data";a:2:{i:0;a:0:{}i:1;a:2:{s:1:"A";a:3:{s:4:"type";s:14:"select-account";s:4:"name";s:6:"${row}";s:8:"readonly";s:1:"1";}s:1:"B";a:5:{s:4:"type";s:6:"select";s:4:"name";s:26:"accounts_status[$row_cont]";s:8:"onchange";s:1:"1";s:4:"help";s:30:"Accept or reject an invitation";s:7:"no_lang";s:1:"1";}}}s:4:"rows";i:1;s:4:"cols";i:2;s:4:"name";s:22:"participants[accounts]";s:7:"options";a:0:{}}s:1:"C";a:3:{s:4:"type";s:5:"label";s:5:"label";s:9:"Resources";s:5:"align";s:5:"right";}s:1:"D";a:6:{s:4:"type";s:4:"grid";s:4:"data";a:2:{i:0;a:1:{s:2:"h1";s:19:",!@resources_status";}i:1;a:2:{s:1:"A";a:4:{s:4:"type";s:16:"resources_select";s:4:"name";s:6:"${row}";s:8:"readonly";s:1:"1";s:7:"no_lang";s:1:"1";}s:1:"B";a:5:{s:4:"type";s:6:"select";s:4:"name";s:27:"resources_status[$row_cont]";s:8:"onchange";s:1:"1";s:4:"help";s:30:"Accept or reject an invitation";s:7:"no_lang";s:1:"1";}}}s:4:"rows";i:1;s:4:"cols";i:2;s:4:"name";s:23:"participants[resources]";s:7:"options";a:0:{}}}}s:4:"rows";i:2;s:4:"cols";i:4;s:4:"size";s:23:"100%,200,,row_on,,,auto";s:7:"options";a:4:{i:3;s:6:"row_on";i:0;s:4:"100%";i:1;s:3:"200";i:6;s:4:"auto";}}}','size' => '100%,200,,row_on,,,auto','style' => '','modified' => '1129665796',); +$templ_data[] = array('name' => 'calendar.edit.participants','template' => '','lang' => '','group' => '0','version' => '1.0.1.003','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:5:{s:2:"c1";s:7:"row,top";s:1:"A";s:2:"95";s:2:"h1";s:6:",@view";s:2:"h2";s:7:",!@view";s:2:"c2";s:4:",top";}i:1;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"size";s:15:",,,participants";s:5:"label";s:12:"Participants";}s:1:"B";a:3:{s:4:"type";s:14:"select-account";s:4:"size";s:12:"14,calendar+";s:4:"name";s:22:"participants[accounts]";}s:1:"C";a:3:{s:4:"type";s:5:"label";s:5:"label";s:9:"Resources";s:5:"align";s:5:"right";}s:1:"D";a:3:{s:4:"type";s:16:"resources_select";s:4:"size";s:2:"14";s:4:"name";s:23:"participants[resources]";}}i:2;a:4:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:12:"Participants";}s:1:"B";a:6:{s:4:"type";s:4:"grid";s:4:"data";a:2:{i:0;a:0:{}i:1;a:2:{s:1:"A";a:3:{s:4:"type";s:14:"select-account";s:4:"name";s:6:"${row}";s:8:"readonly";s:1:"1";}s:1:"B";a:5:{s:4:"type";s:6:"select";s:4:"name";s:26:"accounts_status[$row_cont]";s:8:"onchange";s:1:"1";s:4:"help";s:30:"Accept or reject an invitation";s:7:"no_lang";s:1:"1";}}}s:4:"rows";i:1;s:4:"cols";i:2;s:4:"name";s:22:"participants[accounts]";s:7:"options";a:0:{}}s:1:"C";a:3:{s:4:"type";s:5:"label";s:5:"label";s:9:"Resources";s:5:"align";s:5:"right";}s:1:"D";a:6:{s:4:"type";s:4:"grid";s:4:"data";a:2:{i:0;a:1:{s:2:"h1";s:19:",!@resources_status";}i:1;a:2:{s:1:"A";a:4:{s:4:"type";s:16:"resources_select";s:4:"name";s:6:"${row}";s:8:"readonly";s:1:"1";s:7:"no_lang";s:1:"1";}s:1:"B";a:5:{s:4:"type";s:6:"select";s:4:"name";s:27:"resources_status[$row_cont]";s:8:"onchange";s:1:"1";s:4:"help";s:30:"Accept or reject an invitation";s:7:"no_lang";s:1:"1";}}}s:4:"rows";i:1;s:4:"cols";i:2;s:4:"name";s:23:"participants[resources]";s:7:"options";a:0:{}}}}s:4:"rows";i:2;s:4:"cols";i:4;s:4:"size";s:23:"100%,200,,row_on,,,auto";s:7:"options";a:4:{i:3;s:6:"row_on";i:0;s:4:"100%";i:1;s:3:"200";i:6;s:4:"auto";}}}','size' => '100%,200,,row_on,,,auto','style' => '','modified' => '1129665796',); + $templ_data[] = array('name' => 'calendar.edit.recurrence','template' => '','lang' => '','group' => '0','version' => '','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:2:{i:0;a:2:{s:2:"c1";s:3:"row";s:1:"A";s:2:"95";}i:1;a:1:{s:1:"A";a:1:{s:4:"type";s:5:"label";}}}s:4:"rows";i:1;s:4:"cols";i:1;s:4:"size";s:8:"100%,200";s:7:"options";a:2:{i:0;s:4:"100%";i:1;s:3:"200";}}}','size' => '100%,200','style' => '','modified' => '1118737412',); $templ_data[] = array('name' => 'calendar.edit.recurrence','template' => '','lang' => '','group' => '0','version' => '1.0.1.001','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:5:{i:0;a:6:{s:2:"c1";s:2:"th";s:1:"A";s:2:"95";s:2:"c2";s:3:"row";s:2:"c3";s:3:"row";s:2:"c4";s:3:"row";s:1:"D";s:3:"50%";}i:1;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"span";s:3:"all";s:5:"label";s:27:"Repeating Event Information";}s:1:"B";a:2:{s:4:"type";s:5:"label";s:5:"label";s:16:"be back soon ;-)";}s:1:"C";a:1:{s:4:"type";s:5:"label";}s:1:"D";a:1:{s:4:"type";s:5:"label";}}i:2;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"size";s:13:",,,recur_type";s:5:"label";s:11:"Repeat type";}s:1:"B";a:2:{s:4:"type";s:6:"select";s:4:"name";s:10:"recur_type";}s:1:"C";a:3:{s:4:"type";s:5:"label";s:4:"size";s:17:",,,recur_interval";s:5:"label";s:8:"Interval";}s:1:"D";a:4:{s:4:"type";s:13:"select-number";s:4:"name";s:14:"recur_interval";s:4:"help";s:53:"repeating interval, eg. 2 to repeat every second week";s:4:"size";s:9:"None,2,10";}}i:3;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"size";s:16:",,,recur_enddate";s:5:"label";s:8:"End date";}s:1:"B";a:3:{s:4:"type";s:4:"date";s:4:"name";s:13:"recur_enddate";s:4:"help";s:57:"repeat the event until which date (empty means unlimited)";}s:1:"C";a:1:{s:4:"type";s:5:"label";}s:1:"D";a:1:{s:4:"type";s:5:"label";}}i:4;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"size";s:13:",,,recur_data";s:5:"label";s:11:"Repeat days";}s:1:"B";a:4:{s:4:"type";s:10:"select-dow";s:4:"size";s:3:"5,1";s:4:"name";s:10:"recur_data";s:4:"help";s:44:"Days of the week for a weekly repeated event";}s:1:"C";a:1:{s:4:"type";s:5:"label";}s:1:"D";a:1:{s:4:"type";s:5:"label";}}}s:4:"rows";i:4;s:4:"cols";i:4;s:4:"size";s:8:"100%,200";s:7:"options";a:2:{i:0;s:4:"100%";i:1;s:3:"200";}}}','size' => '100%,200','style' => '','modified' => '1118737412',); diff --git a/calendar/setup/phpgw_de.lang b/calendar/setup/phpgw_de.lang index e2b260551f..8e9df24379 100644 --- a/calendar/setup/phpgw_de.lang +++ b/calendar/setup/phpgw_de.lang @@ -88,7 +88,9 @@ enddate of the export calendar de Enddatum des Exports ends calendar de endet error adding the alarm calendar de Fehler beim Zufügen des Alarms error: importing the ical calendar de Fehler: beim Importieren des iCal +error: no participants selected !!! calendar de Fehler: keine Teilnehmer ausgewählt !!! error: saving the event !!! calendar de Fehler: beim Speichern des Termins !!! +error: starttime has to be before the endtime !!! calendar de Fehler: Startzeit muß vor Endzeit liegen !!! event copied - the copy can now be edited calendar de Termin kopiert - die Kopie kann jetzt bearbeitet werden event deleted calendar de Termin gelöscht event details follow calendar de Details zum Termin folgen diff --git a/calendar/setup/phpgw_en.lang b/calendar/setup/phpgw_en.lang index 8950fa2925..a22c2397f2 100644 --- a/calendar/setup/phpgw_en.lang +++ b/calendar/setup/phpgw_en.lang @@ -88,7 +88,9 @@ enddate of the export calendar en Enddate of the export ends calendar en ends error adding the alarm calendar en Error adding the alarm error: importing the ical calendar en Error: importing the iCal +error: no participants selected !!! calendar en Error: no participants selected !!! error: saving the event !!! calendar en Error: saving the event !!! +error: starttime has to be before the endtime !!! calendar en Error: Starttime has to be before the endtime !!! event copied - the copy can now be edited calendar en Event copied - the copy can now be edited event deleted calendar en Event deleted event details follow calendar en Event Details follow diff --git a/calendar/setup/setup.inc.php b/calendar/setup/setup.inc.php index 24fafbe070..47862ac7f0 100755 --- a/calendar/setup/setup.inc.php +++ b/calendar/setup/setup.inc.php @@ -12,7 +12,7 @@ /* $Id$ */ $setup_info['calendar']['name'] = 'calendar'; - $setup_info['calendar']['version'] = '1.0.1.009'; + $setup_info['calendar']['version'] = '1.2'; $setup_info['calendar']['app_order'] = 3; $setup_info['calendar']['enable'] = 1; @@ -67,3 +67,4 @@ + diff --git a/calendar/setup/tables_current.inc.php b/calendar/setup/tables_current.inc.php index f82652583f..1fd9d83c8d 100644 --- a/calendar/setup/tables_current.inc.php +++ b/calendar/setup/tables_current.inc.php @@ -18,7 +18,6 @@ 'cal_uid' => array('type' => 'varchar','precision' => '255','nullable' => False), 'cal_owner' => array('type' => 'int','precision' => '4','nullable' => False), 'cal_category' => array('type' => 'varchar','precision' => '30'), - 'cal_groups' => array('type' => 'varchar','precision' => '255'), 'cal_modified' => array('type' => 'int','precision' => '8'), 'cal_priority' => array('type' => 'int','precision' => '2','nullable' => False,'default' => '2'), 'cal_public' => array('type' => 'int','precision' => '2','nullable' => False,'default' => '1'), diff --git a/calendar/setup/tables_update.inc.php b/calendar/setup/tables_update.inc.php index 622d149183..8b5cc35499 100644 --- a/calendar/setup/tables_update.inc.php +++ b/calendar/setup/tables_update.inc.php @@ -38,7 +38,6 @@ $GLOBALS['egw_setup']->oProc->AlterColumn($table, $field, array('type' => 'int', 'precision' => 4, 'nullable' => false, 'default' => 0)); } - $test[] = '0.9.3pre1'; function calendar_upgrade0_9_3pre1() { @@ -47,66 +46,77 @@ $GLOBALS['setup_info']['calendar']['currentver'] = '0.9.3pre2'; return $GLOBALS['setup_info']['calendar']['currentver']; } + $test[] = "0.9.3pre2"; function calendar_upgrade0_9_3pre2() { $GLOBALS['setup_info']['calendar']['currentver'] = '0.9.3pre3'; return $GLOBALS['setup_info']['calendar']['currentver']; } + $test[] = "0.9.3pre3"; function calendar_upgrade0_9_3pre3() { $GLOBALS['setup_info']['calendar']['currentver'] = '0.9.3pre4'; return $GLOBALS['setup_info']['calendar']['currentver']; } + $test[] = "0.9.3pre4"; function calendar_upgrade0_9_3pre4() { $GLOBALS['setup_info']['calendar']['currentver'] = '0.9.3pre5'; return $GLOBALS['setup_info']['calendar']['currentver']; } + $test[] = "0.9.3pre5"; function calendar_upgrade0_9_3pre5() { $GLOBALS['setup_info']['calendar']['currentver'] = '0.9.3pre6'; return $GLOBALS['setup_info']['calendar']['currentver']; } + $test[] = "0.9.3pre6"; function calendar_upgrade0_9_3pre6() { $GLOBALS['setup_info']['calendar']['currentver'] = '0.9.3pre7'; return $GLOBALS['setup_info']['calendar']['currentver']; } + $test[] = "0.9.3pre7"; function calendar_upgrade0_9_3pre7() { $GLOBALS['setup_info']['calendar']['currentver'] = '0.9.3pre8'; return $GLOBALS['setup_info']['calendar']['currentver']; } + $test[] = "0.9.3pre8"; function calendar_upgrade0_9_3pre8() { $GLOBALS['setup_info']['calendar']['currentver'] = '0.9.3pre9'; return $GLOBALS['setup_info']['calendar']['currentver']; } + $test[] = "0.9.3pre9"; function calendar_upgrade0_9_3pre9() { $GLOBALS['setup_info']['calendar']['currentver'] = '0.9.3pre10'; return $GLOBALS['setup_info']['calendar']['currentver']; } + $test[] = "0.9.3pre10"; function calendar_upgrade0_9_3pre10() { $GLOBALS['setup_info']['calendar']['currentver'] = '0.9.3'; return $GLOBALS['setup_info']['calendar']['currentver']; } + $test[] = "0.9.3"; function calendar_upgrade0_9_3() { $GLOBALS['setup_info']['calendar']['currentver'] = '0.9.4pre1'; return $GLOBALS['setup_info']['calendar']['currentver']; } + $test[] = "0.9.4pre1"; function calendar_upgrade0_9_4pre1() { @@ -1446,4 +1456,46 @@ $GLOBALS['setup_info']['calendar']['currentver'] = '1.0.1.009'; return $GLOBALS['setup_info']['calendar']['currentver']; } + + + $test[] = '1.0.1.009'; + function calendar_upgrade1_0_1_009() + { + $db2 = clone($GLOBALS['egw_setup']->db); + $add_groups = array(); + $GLOBALS['egw_setup']->db->select('egw_cal','DISTINCT egw_cal.cal_id,cal_groups,cal_recur_date',"cal_groups != ''",__LINE__,__FILE__, + False,'','calendar',0,',egw_cal_user WHERE egw_cal.cal_id=egw_cal_user.cal_id'); + while(($row = $GLOBALS['egw_setup']->db->row(true))) + { + $row['cal_user_type'] = 'u'; + foreach(explode(',',$row['cal_groups']) as $group) + { + $row['cal_user_id'] = $group; + $db2->insert('egw_cal_user',array('cal_status' => 'U'),$row,__LINE__,__FILE__,'calendar'); + } + } + $GLOBALS['egw_setup']->oProc->DropColumn('egw_cal',array( + 'fd' => array( + 'cal_id' => array('type' => 'auto','nullable' => False), + 'cal_uid' => array('type' => 'varchar','precision' => '255','nullable' => False), + 'cal_owner' => array('type' => 'int','precision' => '4','nullable' => False), + 'cal_category' => array('type' => 'varchar','precision' => '30'), + 'cal_modified' => array('type' => 'int','precision' => '8'), + 'cal_priority' => array('type' => 'int','precision' => '2','nullable' => False,'default' => '2'), + 'cal_public' => array('type' => 'int','precision' => '2','nullable' => False,'default' => '1'), + 'cal_title' => array('type' => 'varchar','precision' => '255','nullable' => False,'default' => '1'), + 'cal_description' => array('type' => 'text'), + 'cal_location' => array('type' => 'varchar','precision' => '255'), + 'cal_reference' => array('type' => 'int','precision' => '4','nullable' => False,'default' => '0'), + 'cal_modifier' => array('type' => 'int','precision' => '4'), + 'cal_non_blocking' => array('type' => 'int','precision' => '2','default' => '0') + ), + 'pk' => array('cal_id'), + 'fk' => array(), + 'ix' => array(), + 'uc' => array() + ),'cal_groups'); + + return $GLOBALS['setup_info']['calendar']['currentver'] = '1.2'; + } ?>