2004-10-08 00:11:18 +02:00
< ? php
2007-03-09 12:39:47 +01:00
/**
2011-04-07 09:28:46 +02:00
* EGroupware - Calendar ' s forms of the UserInterface
2007-03-09 12:39:47 +01:00
*
* @ link http :// www . egroupware . org
* @ package calendar
* @ author Ralf Becker < RalfBecker - AT - outdoor - training . de >
2015-06-25 22:35:24 +02:00
* @ copyright ( c ) 2004 - 15 by RalfBecker - At - outdoor - training . de
2007-03-09 12:39:47 +01:00
* @ license http :// opensource . org / licenses / gpl - license . php GPL - GNU General Public License
* @ version $Id $
*/
2004-10-08 00:11:18 +02:00
/**
2005-11-09 00:15:14 +01:00
* calendar UserInterface forms : view and edit events , freetime search
*
* The new UI , BO and SO classes have a strikt definition , in which time - zone they operate :
* UI only operates in user - time , so there have to be no conversation at all !!!
* BO ' s functions take and return user - time only ( ! ), they convert internaly everything to servertime , because
* SO operates only on server - time
*
* The state of the UI elements is managed in the uical class , which all UI classes extend .
*
* All permanent debug messages of the calendar - code should done via the debug - message method of the bocal class ! ! !
2004-10-08 00:11:18 +02:00
*/
2008-06-07 19:45:33 +02:00
class calendar_uiforms extends calendar_ui
2004-10-08 00:11:18 +02:00
{
var $public_functions = array (
'freetimesearch' => True ,
2005-11-09 00:15:14 +01:00
'edit' => true ,
2010-02-05 04:34:17 +01:00
'process_edit' => true ,
2005-11-09 00:15:14 +01:00
'export' => true ,
'import' => true ,
2009-12-03 19:24:19 +01:00
'cat_acl' => true ,
2011-05-27 22:32:46 +02:00
'meeting' => true ,
2015-04-15 17:55:18 +02:00
'mail_import' => true ,
2004-10-08 00:11:18 +02:00
);
2008-05-08 00:12:25 +02:00
2006-06-03 01:36:43 +02:00
/**
* Standard durations used in edit and freetime search
*
* @ var array
*/
var $durations = array ();
2008-05-08 00:12:25 +02:00
2008-01-15 09:21:25 +01:00
/**
2009-10-18 14:59:12 +02:00
* default locking time for entries , that are opened by another user
2008-01-15 09:21:25 +01:00
*
2009-10-18 14:59:12 +02:00
* @ var locktime in seconds
2008-01-15 09:21:25 +01:00
*/
var $locktime_default = 1 ;
2004-10-08 00:11:18 +02:00
/**
* Constructor
*/
2008-06-07 19:45:33 +02:00
function __construct ()
2004-10-08 00:11:18 +02:00
{
2008-06-07 19:45:33 +02:00
parent :: __construct ( true ); // call the parent's constructor
2008-05-08 00:12:25 +02:00
2012-12-03 19:05:04 +01:00
for ( $n = 15 ; $n <= 16 * 60 ; $n += ( $n < 60 ? 15 : ( $n < 240 ? 30 : ( $n < 600 ? 60 : 120 ))))
2006-06-03 01:36:43 +02:00
{
$this -> durations [ $n * 60 ] = sprintf ( '%d:%02d' , $n / 60 , $n % 60 );
}
2005-11-09 00:15:14 +01:00
}
2008-05-08 00:12:25 +02:00
2005-11-09 00:15:14 +01:00
/**
* Create a default event ( adding a new event ) by evaluating certain _GET vars
*
* @ return array event - array
2008-05-08 00:12:25 +02:00
*/
2005-11-09 00:15:14 +01:00
function & default_add_event ()
{
2005-11-23 15:21:20 +01:00
$extra_participants = $_GET [ 'participants' ] ? explode ( ',' , $_GET [ 'participants' ]) : array ();
2014-09-03 18:22:05 +02:00
// if participant is a contact, add its link title as title
foreach ( $extra_participants as $uid )
{
if ( $uid [ 0 ] == 'c' )
{
$title = egw_link :: title ( 'addressbook' , substr ( $uid , 1 ));
break ;
}
}
2006-03-03 19:56:01 +01:00
if ( isset ( $_GET [ 'owner' ]))
{
$owner = $_GET [ 'owner' ];
}
// dont set the planner start group as owner/participants if called from planner
elseif ( $this -> view != 'planner' || $this -> owner != $this -> cal_prefs [ 'planner_start_with_group' ])
{
$owner = $this -> owner ;
}
2008-11-12 10:22:45 +01:00
2008-05-08 00:12:25 +02:00
if ( ! $owner || ! is_numeric ( $owner ) || $GLOBALS [ 'egw' ] -> accounts -> get_type ( $owner ) != 'u' ||
2005-11-23 15:21:20 +01:00
! $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
{
2008-11-12 10:22:45 +01:00
// if we come from ressources we don't need any users selected in calendar
if ( ! isset ( $_GET [ 'participants' ]) || $_GET [ 'participants' ][ 0 ] != 'r' )
2008-10-25 08:43:15 +02:00
{
2008-11-12 10:22:45 +01:00
foreach ( explode ( ',' , $owner ) as $uid )
{
// only add users or a single ressource, not all ressources displayed by a category
if ( is_numeric ( $uid ) || $owner == $uid )
{
$extra_participants [] = $uid ;
}
}
2008-10-25 08:43:15 +02:00
}
2005-11-23 15:21:20 +01:00
}
$owner = $this -> user ;
}
2006-03-03 19:56:01 +01:00
//echo "<p>this->owner=$this->owner, _GET[owner]=$_GET[owner], user=$this->user => owner=$owner, extra_participants=".implode(',',$extra_participants)."</p>\n";
2005-11-09 00:15:14 +01:00
2005-11-23 15:21:20 +01:00
// by default include the owner as participant (the user can remove him)
$extra_participants [] = $owner ;
2005-11-09 00:15:14 +01:00
$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' ]),
'minute' => ( int ) $_GET [ 'minute' ],
));
//echo "<p>_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)."</p>\n";
2008-05-08 00:12:25 +02:00
2005-11-23 15:21:20 +01:00
$participant_types [ 'u' ] = $participant_types = $participants = array ();
foreach ( $extra_participants as $uid )
2005-11-09 00:15:14 +01:00
{
2005-11-23 15:21:20 +01:00
if ( isset ( $participants [ $uid ])) continue ; // already included
2009-11-19 19:56:04 +01:00
if ( ! $this -> bo -> check_acl_invite ( $uid )) continue ; // no right to invite --> ignored
2005-11-23 15:21:20 +01:00
if ( is_numeric ( $uid ))
2005-11-09 00:15:14 +01:00
{
2009-10-13 11:00:01 +02:00
$participants [ $uid ] = $participant_types [ 'u' ][ $uid ] =
2009-11-27 09:04:29 +01:00
calendar_so :: combine_status ( $uid == $this -> user ? 'A' : 'U' , 1 ,
( $uid == $this -> user || ( $uid == $owner && $this -> bo -> check_perms ( EGW_ACL_ADD , 0 , $owner ))) ? 'CHAIR' : 'REQ-PARTICIPANT' );
2005-11-23 15:21:20 +01:00
}
2008-05-08 17:02:35 +02:00
elseif ( is_array ( $this -> bo -> resources [ $uid [ 0 ]]))
2005-11-23 15:21:20 +01:00
{
2011-02-15 12:34:36 +01:00
// if contact is a user, use the user instead (as the GUI)
if ( $uid [ 0 ] == 'c' && ( $account_id = $GLOBALS [ 'egw' ] -> accounts -> name2id ( substr ( $uid , 1 ), 'person_id' )))
{
$uid = $account_id ;
$participants [ $uid ] = $participant_types [ 'u' ][ $uid ] =
calendar_so :: combine_status ( $uid == $this -> user ? 'A' : 'U' , 1 ,
( $uid == $this -> user || ( $uid == $owner && $this -> bo -> check_perms ( EGW_ACL_ADD , 0 , $owner ))) ? 'CHAIR' : 'REQ-PARTICIPANT' );
continue ;
}
2008-05-08 17:02:35 +02:00
$res_data = $this -> bo -> resources [ $uid [ 0 ]];
2005-11-23 15:21:20 +01:00
list ( $id , $quantity ) = explode ( ':' , substr ( $uid , 1 ));
2009-10-12 21:16:42 +02:00
if (( $status = $res_data [ 'new_status' ] ? ExecMethod ( $res_data [ 'new_status' ], $id ) : 'U' ))
2005-11-09 00:15:14 +01:00
{
2009-10-13 11:00:01 +02:00
$participants [ $uid ] = $participant_types [ $uid [ 0 ]][ $id ] =
calendar_so :: combine_status ( $status , $quantity , 'REQ-PARTICIPANT' );
2005-11-09 00:15:14 +01:00
}
}
}
2009-11-19 19:56:04 +01:00
if ( ! $participants ) // if all participants got removed, include current user
{
2009-11-26 19:36:19 +01:00
$participants [ $this -> user ] = $participant_types [ 'u' ][ $this -> user ] = calendar_so :: combine_status ( 'A' , 1 , 'CHAIR' );
2009-11-19 19:56:04 +01:00
}
2014-06-06 13:59:20 +02:00
$alarms = array ();
// if default alarm set in prefs --> add it
// we assume here that user does NOT have a whole-day but no regular default-alarm, no whole-day!
if (( string ) $this -> cal_prefs [ 'default-alarm' ] !== '' )
{
$offset = 60 * $this -> cal_prefs [ 'default-alarm' ];
$alarms [ 1 ] = array (
'default' => 1 ,
'offset' => $offset ,
'time' => $start - $offset ,
'all' => false ,
'owner' => $owner ,
'id' => 1 ,
);
}
2005-11-09 00:15:14 +01:00
return array (
'participant_types' => $participant_types ,
'participants' => $participants ,
'owner' => $owner ,
'start' => $start ,
'end' => $start + ( int ) $this -> bo -> cal_prefs [ 'defaultlength' ] * 60 ,
2009-11-04 08:56:00 +01:00
'tzid' => $this -> bo -> common_prefs [ 'tz' ],
2005-11-09 00:15:14 +01:00
'priority' => 2 , // normal
'public' => $this -> cal_prefs [ 'default_private' ] ? 0 : 1 ,
2014-06-06 13:59:20 +02:00
'alarm' => $alarms ,
2014-05-23 10:16:22 +02:00
'recur_exception' => array (),
2014-09-03 18:22:05 +02:00
'title' => $title ? $title : '' ,
2005-11-09 00:15:14 +01:00
);
}
2014-06-06 13:59:20 +02:00
2005-11-09 00:15:14 +01:00
/**
* Process the edited event and evtl . call edit to redisplay it
*
* @ param array $content posted eTemplate content
2010-11-11 14:29:37 +01:00
* @ ToDo add conflict check / available quantity of resources when adding participants
2005-11-09 00:15:14 +01:00
*/
function process_edit ( $content )
{
2010-02-05 04:34:17 +01:00
if ( ! is_array ( $content )) // redirect from etemplate, if POST empty
{
return $this -> edit ( null , null , strip_tags ( $_GET [ 'msg' ]));
}
2014-06-05 13:03:12 +02:00
// clear notification errors
notifications :: errors ( true );
2010-05-12 13:15:45 +02:00
$messages = null ;
$msg_permission_denied_added = false ;
2005-11-09 00:15:14 +01:00
list ( $button ) = @ each ( $content [ 'button' ]);
2006-12-22 20:51:56 +01:00
if ( ! $button && $content [ 'action' ]) $button = $content [ 'action' ]; // action selectbox
unset ( $content [ 'button' ]); unset ( $content [ 'action' ]);
2005-11-09 00:15:14 +01:00
2006-12-22 20:51:56 +01:00
$view = $content [ 'view' ];
if ( $button == 'ical' )
2005-11-09 00:15:14 +01:00
{
$msg = $this -> export ( $content [ 'id' ], true );
}
// delete a recur-exception
if ( $content [ 'recur_exception' ][ 'delete_exception' ])
{
list ( $date ) = each ( $content [ 'recur_exception' ][ 'delete_exception' ]);
2015-02-06 10:47:50 +01:00
// eT2 converts time to
if ( ! is_numeric ( $date )) $date = egw_time :: to ( str_replace ( 'Z' , '' , $date ), 'ts' );
2005-11-09 00:15:14 +01:00
unset ( $content [ 'recur_exception' ][ 'delete_exception' ]);
if (( $key = array_search ( $date , $content [ 'recur_exception' ])) !== false )
{
2010-05-19 19:41:46 +02:00
// propagate the exception to a single event
$recur_exceptions = $this -> bo -> so -> get_related ( $content [ 'uid' ]);
foreach ( $recur_exceptions as $id )
{
if ( ! ( $exception = $this -> bo -> read ( $id )) ||
$exception [ 'recurrence' ] != $content [ 'recur_exception' ][ $key ]) continue ;
$exception [ 'uid' ] = common :: generate_uid ( 'calendar' , $id );
$exception [ 'reference' ] = $exception [ 'recurrence' ] = 0 ;
2014-05-27 17:02:56 +02:00
$this -> bo -> update ( $exception , true , true , false , true , $messages , $content [ 'no_notifications' ]);
2010-05-19 19:41:46 +02:00
break ;
}
2005-11-09 00:15:14 +01:00
unset ( $content [ 'recur_exception' ][ $key ]);
$content [ 'recur_exception' ] = array_values ( $content [ 'recur_exception' ]);
}
}
// delete an alarm
if ( $content [ 'alarm' ][ 'delete_alarm' ])
{
list ( $id ) = each ( $content [ 'alarm' ][ 'delete_alarm' ]);
//echo "delete alarm $id"; _debug_array($content['alarm']['delete_alarm']);
2008-05-08 00:12:25 +02:00
2005-11-09 00:15:14 +01:00
if ( $content [ 'id' ])
{
if ( $this -> bo -> delete_alarm ( $id ))
{
$msg = lang ( 'Alarm deleted' );
unset ( $content [ 'alarm' ][ $id ]);
}
else
{
2008-05-08 00:12:25 +02:00
$msg = lang ( 'Permission denied' );
2005-11-09 00:15:14 +01:00
}
}
else
{
unset ( $content [ 'alarm' ][ $id ]);
}
}
2006-06-03 01:36:43 +02:00
if ( $content [ 'duration' ])
{
$content [ 'end' ] = $content [ 'start' ] + $content [ 'duration' ];
}
2014-06-06 13:59:20 +02:00
// fix default alarm for a new (whole day) event, to be according to default-alarm(-wholeday) pref
if ( $content [ 'alarm' ][ 1 ][ 'default' ])
2014-06-05 18:07:59 +02:00
{
2014-06-06 13:59:20 +02:00
$def_alarm = $this -> cal_prefs [ 'default-alarm' . ( $content [ 'whole_day' ] ? '-wholeday' : '' )];
if (( string ) $def_alarm === '' )
{
unset ( $content [ 'alarm' ][ 1 ]); // '' = no alarm on whole day --> delete it
}
else
{
$content [ 'alarm' ][ 1 ][ 'offset' ] = $offset = 60 * $def_alarm ;
$content [ 'start' ][ 1 ][ 'offset' ] = $this -> bo -> date2ts ( $content [ 'start' ]) - $offset ;
}
2014-06-05 18:07:59 +02:00
}
2014-06-06 13:59:20 +02:00
2005-11-09 00:15:14 +01:00
$event = $content ;
unset ( $event [ 'new_alarm' ]);
unset ( $event [ 'alarm' ][ 'delete_alarm' ]);
2006-09-28 06:32:38 +02:00
unset ( $event [ 'duration' ]);
2005-11-09 00:15:14 +01:00
2013-02-21 17:29:13 +01:00
if ( in_array ( $button , array ( 'ignore' , 'freetime' , 'reedit' , 'confirm_edit_series' )))
2006-03-07 21:30:29 +01:00
{
// no conversation necessary, event is already in the right format
}
2010-06-16 12:41:45 +02:00
else
2005-11-09 00:15:14 +01:00
{
2010-06-16 12:41:45 +02:00
// convert content => event
2005-11-09 00:15:14 +01:00
if ( $content [ 'whole_day' ])
{
$event [ 'start' ] = $this -> bo -> date2array ( $event [ 'start' ]);
$event [ 'start' ][ 'hour' ] = $event [ 'start' ][ 'minute' ] = 0 ; unset ( $event [ 'start' ][ 'raw' ]);
$event [ 'start' ] = $this -> bo -> date2ts ( $event [ 'start' ]);
$event [ 'end' ] = $this -> bo -> date2array ( $event [ 'end' ]);
$event [ 'end' ][ 'hour' ] = 23 ; $event [ 'end' ][ 'minute' ] = $event [ 'end' ][ 'second' ] = 59 ; unset ( $event [ 'end' ][ 'raw' ]);
$event [ 'end' ] = $this -> bo -> date2ts ( $event [ 'end' ]);
}
2010-02-24 16:05:00 +01:00
// some checks for recurrences, if you give a date, make it a weekly repeating event and visa versa
2005-11-09 00:15:14 +01:00
if ( $event [ 'recur_type' ] == MCAL_RECUR_NONE && $event [ 'recur_data' ]) $event [ 'recur_type' ] = MCAL_RECUR_WEEKLY ;
if ( $event [ 'recur_type' ] == MCAL_RECUR_WEEKLY && ! $event [ 'recur_data' ])
{
$event [ 'recur_data' ] = 1 << ( int ) date ( 'w' , $event [ 'start' ]);
}
2010-11-11 14:29:37 +01:00
if ( isset ( $content [ 'participants' ]))
2005-11-09 00:15:14 +01:00
{
2010-11-11 14:29:37 +01:00
2010-06-16 12:41:45 +02:00
$event [ 'participants' ] = $event [ 'participant_types' ] = array ();
2010-11-11 14:29:37 +01:00
2010-06-16 12:41:45 +02:00
foreach ( $content [ 'participants' ] as $key => $data )
2005-11-09 00:15:14 +01:00
{
2010-06-16 12:41:45 +02:00
switch ( $key )
{
case 'delete' : // handled in default
case 'quantity' : // handled in new_resource
case 'role' : // handled in add, account or resource
case 'cal_resources' :
case 'status_date' :
break ;
2010-11-11 14:29:37 +01:00
2010-06-16 12:41:45 +02:00
case 'add' :
// email or rfc822 addresse (eg. "Ralf Becker <ralf@domain.com>") in the search field
2014-05-27 17:02:56 +02:00
$matches = array ();
2014-09-22 18:53:53 +02:00
if (( $email = $content [ 'participants' ][ 'resource' ][ 'search' ]) &&
2010-06-16 12:41:45 +02:00
( preg_match ( '/^(.*<)?([a-z0-9_.-]+@[a-z0-9_.-]{5,})>?$/i' , $email , $matches )))
{
$status = calendar_so :: combine_status ( 'U' , $content [ 'participants' ][ 'quantity' ], $content [ 'participants' ][ 'role' ]);
// check if email belongs to account or contact --> prefer them over just emails (if we are allowed to invite him)
if (( $data = $GLOBALS [ 'egw' ] -> accounts -> name2id ( $matches [ 2 ], 'account_email' )) && $this -> bo -> check_acl_invite ( $data ))
{
$event [ 'participants' ][ $data ] = $event [ 'participant_types' ][ 'u' ][ $data ] = $status ;
}
elseif (( list ( $data ) = ExecMethod2 ( 'addressbook.addressbook_bo.search' , array (
'email' => $matches [ 2 ],
'email_home' => $matches [ 2 ],
), true , '' , '' , '' , false , 'OR' )))
{
$event [ 'participants' ][ 'c' . $data [ 'id' ]] = $event [ 'participant_types' ][ 'c' ][ $data [ 'id' ]] = $status ;
}
else
{
$event [ 'participants' ][ 'e' . $email ] = $event [ 'participant_types' ][ 'e' ][ $email ] = $status ;
}
}
elseif ( ! $content [ 'participants' ][ 'account' ] && ! $content [ 'participants' ][ 'resource' ])
2008-05-08 17:02:35 +02:00
{
2010-06-16 12:41:45 +02:00
$msg = lang ( 'You need to select an account, contact or resource first!' );
2008-05-08 17:02:35 +02:00
}
2010-06-16 12:41:45 +02:00
break ;
2010-11-11 14:29:37 +01:00
2010-06-16 12:41:45 +02:00
case 'resource' :
2011-08-11 09:41:18 +02:00
if ( is_array ( $data )) // if $data['current'] is NOT set --> $app==''
2008-05-08 17:02:35 +02:00
{
2010-06-16 12:41:45 +02:00
list ( $app , $id ) = explode ( ':' , $data [ 'current' ]);
2013-02-08 15:07:39 +01:00
if ( ! $app && ! $id )
{
$app = $data [ 'app' ];
$id = $data [ 'id' ];
}
2008-05-08 17:02:35 +02:00
}
else
{
2010-06-16 12:41:45 +02:00
list ( $app , $id ) = explode ( ':' , $data );
2008-05-08 17:02:35 +02:00
}
2014-05-27 17:02:56 +02:00
foreach ( $this -> bo -> resources as $type => $data )
{
if ( $data [ 'app' ] == $app ) break ;
2014-05-28 12:03:57 +02:00
}
2010-06-16 12:41:45 +02:00
$uid = $this -> bo -> resources [ $type ][ 'app' ] == $app ? $type . $id : false ;
2011-09-07 16:47:51 +02:00
if ( $app == 'home-accounts' )
{
$data = $id ;
}
2010-06-16 12:41:45 +02:00
// check if new entry is no account (or contact entry of an account)
2011-09-07 16:47:51 +02:00
elseif ( $app != 'addressbook' || ! ( $data = $GLOBALS [ 'egw' ] -> accounts -> name2id ( $id , 'person_id' )) || ! $this -> bo -> check_acl_invite ( $data ))
2009-07-02 13:26:52 +02:00
{
2010-06-16 12:41:45 +02:00
if ( $uid && $id )
2009-10-12 21:16:42 +02:00
{
2010-06-16 12:41:45 +02:00
$status = isset ( $this -> bo -> resources [ $type ][ 'new_status' ]) ? ExecMethod ( $this -> bo -> resources [ $type ][ 'new_status' ], $id ) : 'U' ;
if ( $status )
{
2010-11-11 14:29:37 +01:00
$res_info = $this -> bo -> resource_info ( $uid );
// todo check real availability = maximum - already booked quantity
if ( isset ( $res_info [ 'useable' ]) && $content [ 'participants' ][ 'quantity' ] > $res_info [ 'useable' ])
{
$msg .= lang ( 'Maximum available quantity of %1 exceeded!' , $res_info [ 'useable' ]);
foreach ( array ( 'quantity' , 'resource' , 'role' ) as $n )
{
$event [ 'participants' ][ $n ] = $content [ 'participants' ][ $n ];
}
}
else
{
$event [ 'participants' ][ $uid ] = $event [ 'participant_types' ][ $type ][ $id ] =
calendar_so :: combine_status ( $status , $content [ 'participants' ][ 'quantity' ], $content [ 'participants' ][ 'role' ]);
}
2010-06-16 12:41:45 +02:00
}
elseif ( ! $msg_permission_denied_added )
{
$msg .= lang ( 'Permission denied!' );
$msg_permission_denied_added = true ;
}
2009-10-12 21:16:42 +02:00
}
2014-09-03 18:22:05 +02:00
// if participant is a contact and no title yet, add its link title as title
if ( $app == 'addressbook' && empty ( $event [ 'title' ]))
{
$event [ 'title' ] = egw_link :: title ( $app , substr ( $uid , 1 ));
}
2010-06-16 12:41:45 +02:00
break ;
2009-07-02 13:26:52 +02:00
}
2010-06-16 12:41:45 +02:00
// fall-through for accounts entered as contact
case 'account' :
foreach ( is_array ( $data ) ? $data : explode ( ',' , $data ) as $uid )
{
2010-11-11 14:29:37 +01:00
if ( $uid && $this -> bo -> check_acl_invite ( $uid ))
{
$event [ 'participants' ][ $uid ] = $event [ 'participant_types' ][ 'u' ][ $uid ] =
calendar_so :: combine_status ( $uid == $this -> bo -> user ? 'A' : 'U' , 1 , $content [ 'participants' ][ 'role' ]);
}
elseif ( $uid && ! $msg_permission_denied_added )
{
$msg .= lang ( 'Permission denied!' );
$msg_permission_denied_added = true ;
}
2010-06-16 12:41:45 +02:00
}
break ;
2010-11-11 14:29:37 +01:00
2010-06-16 12:41:45 +02:00
default : // existing participant row
2012-10-23 17:09:41 +02:00
if ( ! is_array ( $data )) continue ; // widgets in participant tab, above participant list
2010-06-16 12:41:45 +02:00
foreach ( array ( 'uid' , 'status' , 'quantity' , 'role' ) as $name )
{
2010-11-11 14:29:37 +01:00
$$name = $data [ $name ];
2010-06-16 12:41:45 +02:00
}
2010-11-11 14:29:37 +01:00
if ( $content [ 'participants' ][ 'delete' ][ $uid ] || $content [ 'participants' ][ 'delete' ][ md5 ( $uid )])
2005-11-09 00:15:14 +01:00
{
2010-11-11 14:29:37 +01:00
$uid = false ; // entry has been deleted
2006-12-22 20:51:56 +01:00
}
2011-06-21 08:46:51 +02:00
elseif ( $uid )
2006-12-22 20:51:56 +01:00
{
2010-11-11 14:29:37 +01:00
if ( is_numeric ( $uid ))
2006-12-22 20:51:56 +01:00
{
2010-11-11 14:29:37 +01:00
$id = $uid ;
$type = 'u' ;
}
else
{
$id = substr ( $uid , 1 );
$type = $uid [ 0 ];
}
if ( $data [ 'old_status' ] != $status && ! ( ! $data [ 'old_status' ] && $status == 'G' ))
{
//echo "<p>$uid: status changed '$data[old_status]' --> '$status<'/p>\n";
2015-06-25 22:35:24 +02:00
$quantity = $role = null ;
2010-11-11 14:29:37 +01:00
$new_status = calendar_so :: combine_status ( $status , $quantity , $role );
2011-03-09 18:26:20 +01:00
if ( $this -> bo -> set_status ( $event [ 'id' ], $uid , $new_status , isset ( $content [ 'edit_single' ]) ? $content [ 'participants' ][ 'status_date' ] : 0 , false , true , $content [ 'no_notifications' ]))
2009-08-17 16:38:18 +02:00
{
2010-11-11 14:29:37 +01:00
// refreshing the calendar-view with the changed participant-status
if ( $event [ 'recur_type' ] != MCAL_RECUR_NONE )
2009-08-17 22:05:46 +02:00
{
2010-11-11 14:29:37 +01:00
$msg = lang ( 'Status for all future scheduled days changed' );
2009-08-17 22:05:46 +02:00
}
else
{
2010-11-11 14:29:37 +01:00
if ( isset ( $content [ 'edit_single' ]))
{
$msg = lang ( 'Status for this particular day changed' );
// prevent accidentally creating a real exception afterwards
$view = true ;
$hide_delete = true ;
}
else
{
$msg = lang ( 'Status changed' );
2014-11-28 10:48:57 +01:00
//Refresh the event in the main window after changing status
egw_framework :: refresh_opener ( $msg , 'calendar' , $event [ 'id' ]);
2010-11-11 14:29:37 +01:00
}
}
if ( ! $content [ 'no_popup' ])
{
2013-10-31 15:51:19 +01:00
//we are handling refreshing for status changes on client side
2009-08-17 22:05:46 +02:00
}
2013-08-15 16:56:34 +02:00
if ( $status == 'R' && $event [ 'alarm' ])
{
// remove from bo->set_status deleted alarms of rejected users from UI too
foreach ( $event [ 'alarm' ] as $alarm_id => $alarm )
{
if (( string ) $alarm [ 'owner' ] === ( string ) $uid )
{
unset ( $event [ 'alarm' ][ $alarm_id ]);
}
}
}
2006-12-22 20:51:56 +01:00
}
}
2010-11-11 14:29:37 +01:00
if ( $uid && $status != 'G' )
{
$event [ 'participants' ][ $uid ] = $event [ 'participant_types' ][ $type ][ $id ] =
calendar_so :: combine_status ( $status , $quantity , $role );
}
2005-11-09 00:15:14 +01:00
}
2010-11-11 14:29:37 +01:00
break ;
2010-06-16 12:41:45 +02:00
}
2005-11-09 00:15:14 +01:00
}
}
}
$preserv = array (
2009-08-17 22:05:46 +02:00
'view' => $view ,
'hide_delete' => $hide_delete ,
'edit_single' => $content [ 'edit_single' ],
'reference' => $content [ 'reference' ],
'recurrence' => $content [ 'recurrence' ],
'actual_date' => $content [ 'actual_date' ],
'no_popup' => $content [ 'no_popup' ],
2010-08-16 09:13:47 +02:00
'tabs' => $content [ 'tabs' ],
2009-11-25 21:16:41 +01:00
'template' => $content [ 'template' ],
2005-11-09 00:15:14 +01:00
);
2008-01-15 09:21:25 +01:00
$noerror = true ;
2010-11-11 14:29:37 +01:00
2010-06-08 11:52:48 +02:00
//error_log(__METHOD__.$button.'#'.array2string($content['edit_single']).'#');
2010-11-11 14:29:37 +01:00
2014-01-23 18:15:49 +01:00
$ignore_conflicts = $status_reset_to_unknown = false ;
2010-11-11 14:29:37 +01:00
2010-06-09 20:00:11 +02:00
switch (( string ) $button )
{
case 'ignore' :
$ignore_conflicts = true ;
$button = $event [ 'button_was' ]; // save or apply
unset ( $event [ 'button_was' ]);
break ;
2014-01-30 11:12:08 +01:00
2010-06-09 20:00:11 +02:00
}
2010-11-11 14:29:37 +01:00
2006-12-22 20:51:56 +01:00
switch (( string ) $button )
2005-11-09 00:15:14 +01:00
{
2005-11-23 22:39:37 +01:00
case 'exception' : // create an exception in a recuring event
2008-02-07 03:38:55 +01:00
$msg = $this -> _create_exception ( $event , $preserv );
2005-11-23 22:39:37 +01:00
break ;
2005-11-09 00:15:14 +01:00
case 'copy' : // create new event with copied content, some content need to be unset to make a "new" event
unset ( $event [ 'id' ]);
unset ( $event [ 'uid' ]);
unset ( $event [ 'reference' ]);
2015-07-16 13:18:54 +02:00
unset ( $preserv [ 'reference' ]);
2009-07-23 18:14:22 +02:00
unset ( $event [ 'recurrence' ]);
2015-07-16 13:18:54 +02:00
unset ( $preserv [ 'recurrence' ]);
2005-11-09 00:15:14 +01:00
unset ( $event [ 'recur_exception' ]);
unset ( $event [ 'edit_single' ]); // in case it has been set
unset ( $event [ 'modified' ]);
unset ( $event [ 'modifier' ]);
2011-04-07 09:28:46 +02:00
unset ( $event [ 'caldav_name' ]);
2005-11-09 00:15:14 +01:00
$event [ 'owner' ] = ! ( int ) $this -> owner || ! $this -> bo -> check_perms ( EGW_ACL_ADD , 0 , $this -> owner ) ? $this -> user : $this -> owner ;
2010-04-30 18:00:03 +02:00
// Clear participant stati
2010-06-16 12:41:45 +02:00
foreach ( $event [ 'participant_types' ] as $type => & $participants )
{
2010-04-30 18:00:03 +02:00
foreach ( $participants as $id => & $response )
{
if ( $type == 'u' && $id == $event [ 'owner' ]) continue ;
2013-02-21 16:21:19 +01:00
calendar_so :: split_status ( $response , $quantity , $role );
2012-05-15 13:20:07 +02:00
// if resource defines callback for status of new status (eg. Resources app acknowledges direct booking acl), call it
$status = isset ( $this -> bo -> resources [ $type ][ 'new_status' ]) ? ExecMethod ( $this -> bo -> resources [ $type ][ 'new_status' ], $id ) : 'U' ;
$response = calendar_so :: combine_status ( $status , $quantity , $role );
2010-04-30 18:00:03 +02:00
}
}
2012-10-23 20:35:48 +02:00
// Copy alarms
2013-06-21 11:58:55 +02:00
if ( is_array ( $event [ 'alarm' ]))
2012-10-23 20:35:48 +02:00
{
2013-06-21 11:58:55 +02:00
foreach ( $event [ 'alarm' ] as $n => & $alarm )
{
unset ( $alarm [ 'id' ]);
unset ( $alarm [ 'cal_id' ]);
}
2012-10-23 20:35:48 +02:00
}
2012-10-22 18:15:06 +02:00
// Get links to be copied
// With no ID, $content['link_to']['to_id'] is used
$content [ 'link_to' ][ 'to_id' ] = array ( 'to_app' => 'calendar' , 'to_id' => 0 );
2015-06-25 22:35:24 +02:00
foreach ( egw_link :: get_links ( 'calendar' , $content [ 'id' ]) as $link )
2012-10-22 18:15:06 +02:00
{
if ( $link [ 'app' ] != egw_link :: VFS_APPNAME )
{
egw_link :: link ( 'calendar' , $content [ 'link_to' ][ 'to_id' ], $link [ 'app' ], $link [ 'id' ], $link [ 'remark' ]);
}
elseif ( $link [ 'app' ] == egw_link :: VFS_APPNAME )
{
egw_link :: link ( 'calendar' , $content [ 'link_to' ][ 'to_id' ], egw_link :: VFS_APPNAME , array (
'tmp_name' => egw_link :: vfs_path ( $link [ 'app2' ], $link [ 'id2' ]) . '/' . $link [ 'id' ],
'name' => $link [ 'id' ],
), $link [ 'remark' ]);
}
}
unset ( $link );
2005-11-09 00:15:14 +01:00
$preserv [ 'view' ] = $preserv [ 'edit_single' ] = false ;
$msg = lang ( 'Event copied - the copy can now be edited' );
$event [ 'title' ] = lang ( 'Copy of:' ) . ' ' . $event [ 'title' ];
break ;
2008-05-08 00:12:25 +02:00
2006-12-22 20:51:56 +01:00
case 'mail' :
2011-12-16 10:55:57 +01:00
case 'sendrequest' :
2005-11-09 00:15:14 +01:00
case 'save' :
2008-12-18 15:47:21 +01:00
case 'print' :
2005-11-09 00:15:14 +01:00
case 'apply' :
2013-05-10 12:54:36 +02:00
case 'infolog' :
2008-05-08 00:12:25 +02:00
if ( $event [ 'id' ] && ! $this -> bo -> check_perms ( EGW_ACL_EDIT , $event ))
{
2008-12-18 15:47:21 +01:00
$msg = lang ( 'Permission denied' );
2009-10-01 21:16:38 +02:00
$button = '' ;
2008-12-18 15:47:21 +01:00
break ;
}
2005-11-23 15:21:20 +01:00
if ( $event [ 'start' ] > $event [ 'end' ])
{
$msg = lang ( 'Error: Starttime has to be before the endtime !!!' );
$button = '' ;
break ;
}
2009-10-01 21:16:38 +02:00
if ( $event [ 'recur_type' ] != MCAL_RECUR_NONE && $event [ 'recur_enddate' ] && $event [ 'start' ] > $event [ 'recur_enddate' ])
{
$msg = lang ( 'repetition' ) . ': ' . lang ( 'Error: Starttime has to be before the endtime !!!' );
$button = '' ;
break ;
}
2012-10-22 17:47:06 +02:00
if ( $event [ 'recur_type' ] != MCAL_RECUR_NONE && $event [ 'end' ] - $event [ 'start' ] > calendar_rrule :: recurrence_interval ( $event [ 'recur_type' ], $event [ 'recur_interval' ]))
{
$msg = lang ( 'Error: Duration of event longer then recurrence interval!' );
$button = '' ;
break ;
}
2005-11-23 15:21:20 +01:00
if ( ! $event [ 'participants' ])
{
$msg = lang ( 'Error: no participants selected !!!' );
$button = '' ;
break ;
}
2008-10-10 12:24:31 +02:00
// if private event with ressource reservation is forbidden
if ( ! $event [ 'public' ] && $GLOBALS [ 'egw_info' ][ 'server' ][ 'no_ressources_private' ])
{
2015-06-25 22:35:24 +02:00
foreach ( array_keys ( $event [ 'participants' ]) as $uid )
2008-10-10 12:24:31 +02:00
{
if ( $uid [ 0 ] == 'r' ) //ressource detection
{
$msg = lang ( 'Error: ressources reservation in private events is not allowed!!!' );
$button = '' ;
break 2 ; //break foreach and case
}
}
}
2005-11-09 00:15:14 +01:00
if ( $content [ 'edit_single' ]) // we edited a single event from a series
{
$event [ 'reference' ] = $event [ 'id' ];
2009-07-23 18:14:22 +02:00
$event [ 'recurrence' ] = $content [ 'edit_single' ];
2005-11-09 00:15:14 +01:00
unset ( $event [ 'id' ]);
2011-03-09 18:26:20 +01:00
$conflicts = $this -> bo -> update ( $event , $ignore_conflicts , true , false , true , $messages , $content [ 'no_notifications' ]);
2005-11-09 00:15:14 +01:00
if ( ! is_array ( $conflicts ) && $conflicts )
{
// now we need to add the original start as recur-execption to the series
$recur_event = $this -> bo -> read ( $event [ 'reference' ]);
$recur_event [ 'recur_exception' ][] = $content [ 'edit_single' ];
2015-06-25 22:35:24 +02:00
// check if we need to move the alarms, because they are next on that exception
foreach ( $recur_event [ 'alarm' ] as $id => $alarm )
{
if ( $alarm [ 'time' ] == $content [ 'edit_single' ] - $alarm [ 'offset' ])
{
$rrule = calendar_rrule :: event2rrule ( $recur_event , true );
foreach ( $rrule as $time )
{
if ( $content [ 'edit_single' ] < $time -> format ( 'ts' ))
{
$alarm [ 'time' ] = $time -> format ( 'ts' ) - $alarm [ 'offset' ];
$this -> bo -> save_alarm ( $event [ 'reference' ], $alarm );
break ;
}
}
}
}
2005-11-23 22:39:37 +01:00
unset ( $recur_event [ 'start' ]); unset ( $recur_event [ 'end' ]); // no update necessary
2011-11-11 13:46:34 +01:00
unset ( $recur_event [ 'alarm' ]); // unsetting alarms too, as they cant be updated without start!
2005-11-09 00:15:14 +01:00
$this -> bo -> update ( $recur_event , true ); // no conflict check here
unset ( $recur_event );
unset ( $event [ 'edit_single' ]); // if we further edit it, it's just a single event
2005-11-23 22:39:37 +01:00
unset ( $preserv [ 'edit_single' ]);
2005-11-09 00:15:14 +01:00
}
else // conflict or error, we need to reset everything to the state befor we tried to save it
{
$event [ 'id' ] = $event [ 'reference' ];
2015-01-20 14:49:18 +01:00
$event [ 'reference' ] = $event [ 'recurrence' ] = 0 ;
2005-11-09 00:15:14 +01:00
$event [ 'uid' ] = $content [ 'uid' ];
}
}
else // we edited a non-reccuring event or the whole series
{
2011-11-10 19:39:08 +01:00
if (( $old_event = $this -> bo -> read ( $event [ 'id' ])))
2010-06-09 20:00:11 +02:00
{
2010-06-23 16:47:34 +02:00
if ( $event [ 'recur_type' ] != MCAL_RECUR_NONE )
2010-06-09 20:00:11 +02:00
{
2010-06-23 16:47:34 +02:00
// we edit a existing series event
if ( $event [ 'start' ] != $old_event [ 'start' ] ||
$event [ 'whole_day' ] != $old_event [ 'whole_day' ])
2010-06-09 20:00:11 +02:00
{
2010-06-23 16:47:34 +02:00
if ( ! ( $next_occurrence = $this -> bo -> read ( $event [ 'id' ], $this -> bo -> now_su + 1 , true )))
{
$msg = lang ( " Error: You can't shift a series from the past! " );
$noerror = false ;
break ;
}
2011-11-10 19:39:08 +01:00
// splitting of series confirmed or first event clicked (no confirmation necessary)
2014-04-14 18:10:57 +02:00
$orig_event = $event ;
2010-11-11 14:29:37 +01:00
2014-04-14 18:10:57 +02:00
// calculate offset against old series start or clicked recurrance,
// depending on which is smaller
$offset = $event [ 'start' ] - $old_event [ 'start' ];
if ( abs ( $offset ) > abs ( $off2 = $event [ 'start' ] - $event [ 'actual_date' ]))
{
$offset = $off2 ;
}
// base start-date of new series on actual / clicked date
$actual_date = $event [ 'actual_date' ];
$event [ 'start' ] = $actual_date + $offset ;
if ( $content [ 'duration' ])
{
$event [ 'end' ] = $event [ 'start' ] + $content [ 'duration' ];
}
elseif ( $event [ 'end' ] < $event [ 'start' ])
{
$event [ 'end' ] = $event [ 'start' ] + $event [ 'end' ] - $actual_date ;
}
//echo "<p>".__LINE__.": event[start]=$event[start]=".egw_time::to($event['start']).", duration=$content[duration], event[end]=$event[end]=".egw_time::to($event['end']).", offset=$offset</p>\n";
$event [ 'participants' ] = $old_event [ 'participants' ];
foreach ( $old_event [ 'recur_exception' ] as $key => $exdate )
{
if ( $exdate > $actual_date )
2011-11-10 19:39:08 +01:00
{
2014-04-14 18:10:57 +02:00
unset ( $old_event [ 'recur_exception' ][ $key ]);
$event [ 'recur_exception' ][ $key ] += $offset ;
2011-11-10 19:39:08 +01:00
}
2014-04-14 18:10:57 +02:00
else
2011-11-10 19:39:08 +01:00
{
2014-04-14 18:10:57 +02:00
unset ( $event [ 'recur_exception' ][ $key ]);
2011-11-10 19:39:08 +01:00
}
2014-04-14 18:10:57 +02:00
}
$old_alarms = $old_event [ 'alarm' ];
if ( $old_event [ 'start' ] < $actual_date )
{
unset ( $orig_event );
// copy event by unsetting the id(s)
unset ( $event [ 'id' ]);
unset ( $event [ 'uid' ]);
unset ( $event [ 'caldav_name' ]);
// set enddate of existing event
$rriter = calendar_rrule :: event2rrule ( $old_event , true );
$rriter -> rewind ();
$last = $rriter -> current ();
do
2010-06-09 20:00:11 +02:00
{
2014-04-14 18:10:57 +02:00
$rriter -> next_no_exception ();
$occurrence = $rriter -> current ();
2010-06-09 20:00:11 +02:00
}
2014-04-14 18:10:57 +02:00
while ( $rriter -> valid () &&
egw_time :: to ( $occurrence , 'ts' ) < $actual_date &&
( $last = $occurrence ));
$last -> setTime ( 0 , 0 , 0 );
$old_event [ 'recur_enddate' ] = egw_time :: to ( $last , 'ts' );
if ( ! $this -> bo -> update ( $old_event , true , true , false , true , $dummy = null , $content [ 'no_notifications' ]))
2010-06-09 20:00:11 +02:00
{
2014-04-14 18:10:57 +02:00
$msg .= ( $msg ? ', ' : '' ) . lang ( 'Error: the entry has been updated since you opened it for editing!' ) . '<br />' .
lang ( 'Copy your changes to the clipboard, %1reload the entry%2 and merge them.' , '<a href="' .
htmlspecialchars ( egw :: link ( '/index.php' , array (
'menuaction' => 'calendar.calendar_uiforms.edit' ,
'cal_id' => $content [ 'id' ],
))) . '">' , '</a>' );
$noerror = false ;
$event = $orig_event ;
break ;
2010-06-09 20:00:11 +02:00
}
2014-04-14 18:10:57 +02:00
$event [ 'alarm' ] = array ();
2010-06-09 20:00:11 +02:00
}
}
}
else
{
2010-06-23 16:47:34 +02:00
if ( $old_event [ 'start' ] != $event [ 'start' ] ||
$old_event [ 'end' ] != $event [ 'end' ] ||
$event [ 'whole_day' ] != $old_event [ 'whole_day' ])
{
2010-11-02 12:00:41 +01:00
$sameday = ( date ( 'Ymd' , $old_event [ 'start' ]) == date ( 'Ymd' , $event [ 'start' ]));
foreach (( array ) $event [ 'participants' ] as $uid => $status )
2010-06-23 16:47:34 +02:00
{
2015-06-25 22:35:24 +02:00
$q = $r = null ;
2010-11-02 12:00:41 +01:00
calendar_so :: split_status ( $status , $q , $r );
if ( $uid [ 0 ] != 'c' && $uid [ 0 ] != 'e' && $uid != $this -> bo -> user && $status != 'U' )
{
$preferences = CreateObject ( 'phpgwapi.preferences' , $uid );
$part_prefs = $preferences -> read_repository ();
switch ( $part_prefs [ 'calendar' ][ 'reset_stati' ])
2010-06-23 16:47:34 +02:00
{
2010-11-02 12:00:41 +01:00
case 'no' :
break ;
case 'startday' :
if ( $sameday ) break ;
default :
2010-11-11 14:29:37 +01:00
$status_reset_to_unknown = true ;
2010-06-23 16:47:34 +02:00
$event [ 'participants' ][ $uid ] = calendar_so :: combine_status ( 'U' , $q , $r );
// todo: report reset status to user
}
2010-11-02 12:00:41 +01:00
}
2010-06-23 16:47:34 +02:00
}
}
2010-06-09 20:00:11 +02:00
}
}
2011-03-09 18:26:20 +01:00
$conflicts = $this -> bo -> update ( $event , $ignore_conflicts , true , false , true , $messages , $content [ 'no_notifications' ]);
2005-11-09 00:15:14 +01:00
unset ( $event [ 'ignore' ]);
}
if ( is_array ( $conflicts ))
{
$event [ 'button_was' ] = $button ; // remember for ignore
return $this -> conflicts ( $event , $conflicts , $preserv );
}
2009-12-03 19:24:19 +01:00
// check if there are messages from update, eg. removed participants or categories because of missing rights
if ( $messages )
{
$msg .= ( $msg ? ', ' : '' ) . implode ( ', ' , $messages );
}
if ( $conflicts === 0 )
2008-01-15 09:21:25 +01:00
{
$msg .= ( $msg ? ', ' : '' ) . lang ( 'Error: the entry has been updated since you opened it for editing!' ) . '<br />' .
lang ( 'Copy your changes to the clipboard, %1reload the entry%2 and merge them.' , '<a href="' .
2009-11-25 21:16:41 +01:00
htmlspecialchars ( egw :: link ( '/index.php' , array (
2008-06-07 19:45:33 +02:00
'menuaction' => 'calendar.calendar_uiforms.edit' ,
2009-12-03 19:24:19 +01:00
'cal_id' => $content [ 'id' ],
))) . '">' , '</a>' );
2010-06-09 20:00:11 +02:00
$noerror = false ;
2008-01-15 09:21:25 +01:00
}
2009-07-23 18:14:22 +02:00
elseif ( $conflicts > 0 )
2005-11-09 00:15:14 +01:00
{
2014-01-30 11:12:08 +01:00
// series moved by splitting in two --> move alarms and exceptions
if ( $old_event && $old_event [ 'id' ] != $event [ 'id' ])
{
2013-08-15 12:38:45 +02:00
foreach (( array ) $old_alarms as $alarm )
2010-06-09 20:00:11 +02:00
{
2011-11-10 19:39:08 +01:00
// check if alarms still needed in old event, if not delete it
$event_time = $alarm [ 'time' ] + $alarm [ 'offset' ];
if ( $event_time >= $actual_date )
2010-06-11 09:32:10 +02:00
{
$this -> bo -> delete_alarm ( $alarm [ 'id' ]);
}
2010-06-09 20:00:11 +02:00
$alarm [ 'time' ] += $offset ;
unset ( $alarm [ 'id' ]);
2011-11-10 19:39:08 +01:00
// if alarm would be in the past (eg. event moved back) --> move to next possible recurrence
if ( $alarm [ 'time' ] < $this -> bo -> now_su )
{
if (( $next_occurrence = $this -> bo -> read ( $event [ 'id' ], $this -> bo -> now_su + $alarm [ 'offset' ], true )))
{
$alarm [ 'time' ] = $next_occurrence [ 'start' ] - $alarm [ 'offset' ];
}
else
{
$alarm = false ; // no (further) recurence found --> ignore alarm
}
}
// alarm is currently on a previous recurrence --> set for first recurrence of new series
elseif ( $event_time < $event [ 'start' ])
2010-06-09 20:00:11 +02:00
{
2011-11-10 19:39:08 +01:00
$alarm [ 'time' ] = $event [ 'start' ] - $alarm [ 'offset' ];
}
if ( $alarm )
{
$alarm [ 'id' ] = $this -> bo -> save_alarm ( $event [ 'id' ], $alarm );
$event [ 'alarm' ][ $alarm [ 'id' ]] = $alarm ;
2010-06-09 20:00:11 +02:00
}
}
// attach all future exceptions to the new series
$events =& $this -> bo -> search ( array (
'query' => array ( 'cal_uid' => $old_event [ 'uid' ]),
'filter' => 'owner' , // return all possible entries
'daywise' => false ,
'date_format' => 'ts' ,
));
foreach (( array ) $events as $exception )
{
2011-11-10 19:39:08 +01:00
if ( $exception [ 'recurrence' ] > $actual_date )
2010-06-09 20:00:11 +02:00
{
$exception [ 'recurrence' ] += $offset ;
$exception [ 'reference' ] = $event [ 'id' ];
$exception [ 'uid' ] = $event [ 'uid' ];
2011-11-10 19:39:08 +01:00
$this -> bo -> update ( $exception , true , true , true , true , $msg = null , $content [ 'no_notifications' ]);
2010-06-09 20:00:11 +02:00
}
}
2014-01-30 11:12:08 +01:00
}
2010-11-11 14:29:37 +01:00
2010-06-23 16:47:34 +02:00
$message = lang ( 'Event saved' );
if ( $status_reset_to_unknown )
{
foreach (( array ) $event [ 'participants' ] as $uid => $status )
{
if ( $uid [ 0 ] != 'c' && $uid [ 0 ] != 'e' && $uid != $this -> bo -> user )
{
calendar_so :: split_status ( $status , $q , $r );
$status = calendar_so :: combine_status ( 'U' , $q , $r );
2010-06-24 18:21:23 +02:00
$this -> bo -> set_status ( $event [ 'id' ], $uid , $status , 0 , true );
2010-06-23 16:47:34 +02:00
}
}
$message .= lang ( ', stati of participants reset' );
}
2010-11-11 14:29:37 +01:00
2015-07-01 01:34:38 +02:00
$response = egw_json_response :: get ();
if ( $response )
{
// Directly update stored data. If event is still visible, it will
// be notified & update itself.
2015-07-22 01:45:38 +02:00
if ( ! $old_event )
{
// For new events, make sure we have the whole event, not just form data
$event = $this -> bo -> read ( $event [ 'id' ]);
}
2015-07-01 01:34:38 +02:00
$this -> to_client ( $event );
$response -> call ( 'egw.dataStoreUID' , 'calendar::' . $event [ 'id' ], $event );
}
2010-06-23 16:47:34 +02:00
$msg = $message . ( $msg ? ', ' . $msg : '' );
2014-05-23 10:16:22 +02:00
egw_framework :: refresh_opener ( $msg , 'calendar' , $event [ 'id' ]);
2005-11-09 00:15:14 +01:00
// writing links for new entry, existing ones are handled by the widget itself
2008-05-08 00:12:25 +02:00
if ( ! $content [ 'id' ] && is_array ( $content [ 'link_to' ][ 'to_id' ]))
2005-11-09 00:15:14 +01:00
{
2008-03-26 13:23:26 +01:00
egw_link :: link ( 'calendar' , $event [ 'id' ], $content [ 'link_to' ][ 'to_id' ]);
2005-11-09 00:15:14 +01:00
}
}
else
{
$msg = lang ( 'Error: saving the event !!!' );
}
break ;
2008-05-08 00:12:25 +02:00
2007-01-15 23:58:32 +01:00
case 'cancel' :
if ( $content [ 'cancel_needs_refresh' ])
{
2013-10-31 15:51:19 +01:00
egw_framework :: refresh_opener ( $msg , 'calendar' );
2007-01-15 23:58:32 +01:00
}
break ;
2010-05-20 11:19:15 +02:00
case 'delete' : // delete of regular event
case 'delete_keep_exceptions' : // series and user selected to keep the exceptions
case 'delete_exceptions' : // series and user selected to delete the exceptions too
2015-06-25 22:35:24 +02:00
$exceptions_kept = null ;
2015-07-16 12:05:18 +02:00
if ( $this -> bo -> delete ( $event [ 'id' ], ( int ) $content [ 'edit_single' ], false , $event [ 'no_notifications' ],
2012-10-22 15:15:40 +02:00
$button == 'delete_exceptions' , $exceptions_kept ))
2005-11-09 00:15:14 +01:00
{
2010-06-08 18:36:55 +02:00
if ( $event [ 'recur_type' ] != MCAL_RECUR_NONE && $content [ 'reference' ] == 0 && ! $content [ 'edit_single' ])
2010-01-22 20:49:37 +01:00
{
2010-05-12 13:15:45 +02:00
$msg = lang ( 'Series deleted' );
2012-10-22 15:15:40 +02:00
if ( $exceptions_kept ) $msg .= lang ( ', exceptions preserved' );
2010-05-12 13:15:45 +02:00
}
else
{
$msg = lang ( 'Event deleted' );
2010-01-22 20:49:37 +01:00
}
2013-10-31 15:51:19 +01:00
2005-11-09 00:15:14 +01:00
}
break ;
2008-05-08 00:12:25 +02:00
2005-11-09 00:15:14 +01:00
case 'freetime' :
// the "click" has to be in onload, to make sure the button is already created
2013-10-31 15:51:19 +01:00
$event [ 'button_was' ] = $button ;
2005-11-09 00:15:14 +01:00
break ;
2008-05-08 00:12:25 +02:00
2005-11-09 00:15:14 +01:00
case 'add_alarm' :
2014-12-09 23:35:36 +01:00
$time = $content [ 'start' ];
2014-05-27 17:02:56 +02:00
$offset = $time - $content [ 'new_alarm' ][ 'date' ];
2010-06-08 18:36:55 +02:00
if ( $event [ 'recur_type' ] != MCAL_RECUR_NONE &&
2010-06-09 20:00:11 +02:00
( $next_occurrence = $this -> bo -> read ( $event [ 'id' ], $this -> bo -> now_su + $offset , true )) &&
2010-06-08 18:36:55 +02:00
$time < $next_occurrence [ 'start' ])
{
2014-12-09 23:35:36 +01:00
$content [ 'new_alarm' ][ 'date' ] = $next_occurrence [ 'start' ] - $offset ;
2010-06-08 18:36:55 +02:00
}
2005-11-09 00:15:14 +01:00
if ( $this -> bo -> check_perms ( EGW_ACL_EDIT , ! $content [ 'new_alarm' ][ 'owner' ] ? $event : 0 , $content [ 'new_alarm' ][ 'owner' ]))
{
$alarm = array (
'offset' => $offset ,
2014-05-27 17:02:56 +02:00
'time' => $content [ 'new_alarm' ][ 'date' ],
2005-11-09 00:15:14 +01:00
'all' => ! $content [ 'new_alarm' ][ 'owner' ],
'owner' => $content [ 'new_alarm' ][ 'owner' ] ? $content [ 'new_alarm' ][ 'owner' ] : $this -> user ,
);
if ( $alarm [ 'time' ] < $this -> bo -> now_su )
{
$msg = lang ( " Can't add alarms in the past !!! " );
}
elseif ( $event [ 'id' ]) // save the alarm immediatly
{
2010-06-09 20:00:11 +02:00
if (( $alarm_id = $this -> bo -> save_alarm ( $event [ 'id' ], $alarm )))
2005-11-09 00:15:14 +01:00
{
$alarm [ 'id' ] = $alarm_id ;
$event [ 'alarm' ][ $alarm_id ] = $alarm ;
2008-05-08 00:12:25 +02:00
2005-11-09 00:15:14 +01:00
$msg = lang ( 'Alarm added' );
2013-10-31 15:51:19 +01:00
egw_framework :: refresh_opener ( $msg , 'calendar' , $event [ 'id' ], 'update' );
2005-11-09 00:15:14 +01:00
}
else
{
$msg = lang ( 'Error adding the alarm' );
}
}
else
{
2015-06-25 22:35:24 +02:00
for ( $alarm [ 'id' ] = 1 ; isset ( $event [ 'alarm' ][ $alarm [ 'id' ]]); $alarm [ 'id' ] ++ ) {} // get a temporary non-conflicting, numeric id
2005-11-09 00:15:14 +01:00
$event [ 'alarm' ][ $alarm [ 'id' ]] = $alarm ;
}
}
else
{
$msg = lang ( 'Permission denied' );
}
break ;
}
2014-06-05 13:03:12 +02:00
// add notification-errors, if we have some
if (( $notification_errors = notifications :: errors ( true )))
{
$msg .= ( $msg ? " \n " : '' ) . implode ( " \n " , $notification_errors );
}
2010-05-20 11:19:15 +02:00
if ( in_array ( $button , array ( 'cancel' , 'save' , 'delete' , 'delete_exceptions' , 'delete_keep_exceptions' )) && $noerror )
2005-11-09 00:15:14 +01:00
{
2008-05-08 00:12:25 +02:00
if ( $content [ 'lock_token' ]) // remove an existing lock
{
egw_vfs :: unlock ( egw_vfs :: app_entry_lock_path ( 'calendar' , $content [ 'id' ]), $content [ 'lock_token' ], false );
}
2005-11-09 00:15:14 +01:00
if ( $content [ 'no_popup' ])
{
2010-06-10 19:24:22 +02:00
egw :: redirect_link ( '/index.php' , array (
'menuaction' => 'calendar.calendar_uiviews.index' ,
2005-11-09 00:15:14 +01:00
'msg' => $msg ,
));
}
2015-06-25 22:35:24 +02:00
if ( in_array ( $button , array ( 'delete_exceptions' , 'delete_keep_exceptions' )) || $content [ 'recur_type' ] && $button == 'delete' )
2014-06-17 09:48:59 +02:00
{
egw_framework :: refresh_opener ( $msg , 'calendar' );
}
else
{
2015-07-22 01:45:38 +02:00
egw_framework :: refresh_opener ( $msg , 'calendar' , $event [ 'id' ], $button == 'save' ? ( $content [ 'id' ] ? 'update' : 'add' ) : 'delete' );
2014-09-03 18:22:05 +02:00
}
2013-10-31 15:51:19 +01:00
egw_framework :: window_close ();
2009-10-12 21:16:42 +02:00
common :: egw_exit ();
2005-11-09 00:15:14 +01:00
}
2011-03-09 18:26:20 +01:00
unset ( $event [ 'no_notifications' ]);
2013-10-31 15:51:19 +01:00
return $this -> edit ( $event , $preserv , $msg , $event [ 'id' ] ? $event [ 'id' ] : $content [ 'link_to' ][ 'to_id' ]);
2005-11-09 00:15:14 +01:00
}
2008-05-08 00:12:25 +02:00
2008-02-07 03:38:55 +01:00
/**
* Create an exception from the clicked event
2008-05-08 00:12:25 +02:00
*
2008-02-07 03:38:55 +01:00
* It ' s not stored to the DB unless the user saves it !
*
* @ param array & $event
* @ param array & $preserv
* @ return string message that exception was created
*/
function _create_exception ( & $event , & $preserv )
{
2012-10-22 19:03:02 +02:00
// In some cases where the user makes the first day an exception, actual_date may be missing
2015-06-10 23:51:28 +02:00
$preserv [ 'actual_date' ] = $preserv [ 'actual_date' ] ? $preserv [ 'actual_date' ] : $event [ 'start' ];
2012-10-22 19:03:02 +02:00
2008-02-07 03:38:55 +01:00
$event [ 'end' ] += $preserv [ 'actual_date' ] - $event [ 'start' ];
2009-07-23 18:14:22 +02:00
$event [ 'reference' ] = $preserv [ 'reference' ] = $event [ 'id' ];
2009-08-07 11:26:11 +02:00
$event [ 'recurrence' ] = $preserv [ 'recurrence' ] = $preserv [ 'actual_date' ];
2008-02-07 03:38:55 +01:00
$event [ 'start' ] = $preserv [ 'edit_single' ] = $preserv [ 'actual_date' ];
$event [ 'recur_type' ] = MCAL_RECUR_NONE ;
foreach ( array ( 'recur_enddate' , 'recur_interval' , 'recur_exception' , 'recur_data' ) as $name )
{
unset ( $event [ $name ]);
}
2015-06-25 22:35:24 +02:00
// add all alarms as new alarms to execption
2015-07-16 14:51:13 +02:00
$event [ 'alarm' ] = array_values (( array ) $event [ 'alarm' ]);
2015-06-25 22:35:24 +02:00
foreach ( $event [ 'alarm' ] as & $alarm )
{
unset ( $alarm [ 'uid' ], $alarm [ 'id' ], $alarm [ 'time' ]);
}
2009-07-22 17:38:58 +02:00
if ( $this -> bo -> check_perms ( EGW_ACL_EDIT , $event ))
{
2009-08-17 23:15:40 +02:00
return lang ( 'Save event as exception - Delete single occurrence - Edit status or alarms for this particular day' );
2009-07-22 17:38:58 +02:00
}
2009-08-17 23:15:40 +02:00
return lang ( 'Edit status or alarms for this particular day' );
2008-02-07 03:38:55 +01:00
}
2005-11-09 00:15:14 +01:00
/**
2014-03-20 17:10:52 +01:00
* return javascript to open mail compose window with preset content to mail all participants
2005-11-09 00:15:14 +01:00
*
* @ param array $event
* @ param boolean $added
* @ return string javascript window . open command
*/
2013-10-31 15:51:19 +01:00
function ajax_custom_mail ( $event , $added , $asrequest = false )
2005-11-09 00:15:14 +01:00
{
$to = array ();
2008-05-08 17:02:35 +02:00
2005-11-09 00:15:14 +01:00
foreach ( $event [ 'participants' ] as $uid => $status )
{
2014-04-22 15:51:32 +02:00
//error_log(__METHOD__.__LINE__.' '.$uid.':'.array2string($status));
if ( empty ( $status )) continue ;
2009-03-05 16:18:40 +01:00
$toadd = '' ;
2014-03-20 17:10:52 +01:00
if (( isset ( $status [ 'status' ]) && $status [ 'status' ] == 'R' ) || ( isset ( $status [ 'uid' ]) && $status [ 'uid' ] == $this -> user )) continue ;
2008-05-08 00:12:25 +02:00
2014-03-20 17:10:52 +01:00
if ( isset ( $status [ 'uid' ]) && is_numeric ( $status [ 'uid' ]) && $GLOBALS [ 'egw' ] -> accounts -> get_type ( $status [ 'uid' ]) == 'u' )
2005-11-09 00:15:14 +01:00
{
2014-01-29 09:32:01 +01:00
if ( ! ( $email = $GLOBALS [ 'egw' ] -> accounts -> id2name ( $status [ 'uid' ], 'account_email' ))) continue ;
2007-12-11 08:13:08 +01:00
2015-06-25 22:35:24 +02:00
$lid = $firstname = $lastname = null ;
2014-01-29 09:32:01 +01:00
$GLOBALS [ 'egw' ] -> accounts -> get_account_name ( $status [ 'uid' ], $lid , $firstname , $lastname );
2008-05-08 00:12:25 +02:00
2009-03-05 16:18:40 +01:00
$toadd = $firstname . ' ' . $lastname . ' <' . $email . '>' ;
if ( ! in_array ( $toadd , $to )) $to [] = $toadd ;
2014-04-22 15:51:32 +02:00
//error_log(__METHOD__.__LINE__.array2string($to));
2007-12-11 08:13:08 +01:00
}
elseif ( $uid < 0 )
{
foreach ( $GLOBALS [ 'egw' ] -> accounts -> members ( $uid , true ) as $uid )
{
if ( ! ( $email = $GLOBALS [ 'egw' ] -> accounts -> id2name ( $uid , 'account_email' ))) continue ;
$GLOBALS [ 'egw' ] -> accounts -> get_account_name ( $uid , $lid , $firstname , $lastname );
2008-05-08 00:12:25 +02:00
2009-03-05 16:18:40 +01:00
$toadd = $firstname . ' ' . $lastname . ' <' . $email . '>' ;
2009-03-05 16:52:57 +01:00
// dont add groupmembers if they already rejected the event, or are the current user
if ( ! in_array ( $toadd , $to ) && ( $event [ 'participants' ][ $uid ] !== 'R' && $uid != $this -> user )) $to [] = $toadd ;
2014-04-22 15:51:32 +02:00
//error_log(__METHOD__.__LINE__.array2string($to));
2007-12-11 08:13:08 +01:00
}
2005-11-09 00:15:14 +01:00
}
2014-04-22 15:51:32 +02:00
elseif ( ! empty ( $status [ 'uid' ]) && ! is_numeric ( substr ( $status [ 'uid' ], 0 , 1 )) && ( $info = $this -> bo -> resource_info ( $status [ 'uid' ])))
2006-12-22 20:51:56 +01:00
{
2008-05-08 17:02:35 +02:00
$to [] = $info [ 'email' ];
2014-04-22 15:51:32 +02:00
//error_log(__METHOD__.__LINE__.array2string($to));
}
elseif ( ! is_numeric ( substr ( $uid , 0 , 1 )) && ( $info = $this -> bo -> resource_info ( $uid )))
{
$to [] = $info [ 'email' ];
//error_log(__METHOD__.__LINE__.array2string($to));
2006-12-22 20:51:56 +01:00
}
2005-11-09 00:15:14 +01:00
}
list ( $subject , $body ) = $this -> bo -> get_update_message ( $event , $added ? MSG_ADDED : MSG_MODIFIED ); // update-message is in TZ of the user
2014-03-20 17:10:52 +01:00
//error_log(__METHOD__.print_r($event,true));
2008-06-12 09:33:44 +02:00
$boical = new calendar_ical ();
2012-03-12 13:45:54 +01:00
// we need to pass $event[id] so iCal class reads event again,
// as event is in user TZ, but iCal class expects server TZ!
2014-02-05 16:15:00 +01:00
$ics = $boical -> exportVCal ( array ( $event [ 'id' ]), '2.0' , 'REQUEST' , false );
2005-11-09 00:15:14 +01:00
$ics_file = tempnam ( $GLOBALS [ 'egw_info' ][ 'server' ][ 'temp_dir' ], 'ics' );
if (( $f = fopen ( $ics_file , 'w' )))
{
fwrite ( $f , $ics );
fclose ( $f );
}
2014-04-22 15:51:32 +02:00
//error_log(__METHOD__.__LINE__.array2string($to));
2005-11-09 00:15:14 +01:00
$vars = array (
2013-10-31 15:51:19 +01:00
'menuaction' => 'mail.mail_compose.compose' ,
2010-12-09 12:57:14 +01:00
'mimeType' => 'plain' , // force type to plain as thunderbird seems to try to be smart while parsing html messages with ics attachments
2007-05-16 09:30:58 +02:00
'preset[to]' => $to ,
2005-11-09 00:15:14 +01:00
'preset[subject]' => $subject ,
'preset[body]' => $body ,
'preset[name]' => 'event.ics' ,
'preset[file]' => $ics_file ,
2014-02-05 16:15:00 +01:00
'preset[type]' => 'text/calendar' . ( $asrequest ? '; method=REQUEST' : '' ),
2005-11-09 00:15:14 +01:00
'preset[size]' => filesize ( $ics_file ),
);
2011-12-16 10:55:57 +01:00
if ( $asrequest ) $vars [ 'preset[msg]' ] = lang ( 'You attempt to mail a meetingrequest to the recipients above. Depending on the client this mail is opened with, the recipient may or may not see the mailbody below, but only see the meeting request attached.' );
2013-10-31 15:51:19 +01:00
$response = egw_json_response :: get ();
$response -> call ( 'app.calendar.custom_mail' , $vars );
2013-05-10 12:54:36 +02:00
}
2012-11-13 12:23:29 +01:00
/**
* Get title of a uid / calendar participant
*
* @ param int | string $uid
* @ return string
*/
public function get_title ( $uid )
{
if ( is_numeric ( $uid ))
{
return common :: grab_owner_name ( $uid );
}
elseif (( $info = $this -> bo -> resource_info ( $uid )))
{
2014-03-13 11:20:17 +01:00
if ( $uid [ 0 ] == 'e' && $info [ 'name' ] && $info [ 'name' ] != $info [ 'email' ])
{
return $info [ 'name' ] . ' <' . $info [ 'email' ] . '>' ;
}
2012-11-13 12:23:29 +01:00
return $info [ 'name' ] ? $info [ 'name' ] : $info [ 'email' ];
}
return '#' . $uid ;
}
/**
* Compare two uid by there title
*
* @ param int | string $uid1
* @ param int | string $uid2
* @ return int see strnatcasecmp
*/
public function uid_title_cmp ( $uid1 , $uid2 )
{
return strnatcasecmp ( $this -> get_title ( $uid1 ), $this -> get_title ( $uid2 ));
}
2008-12-18 15:47:21 +01:00
2005-11-09 00:15:14 +01:00
/**
* Edit a calendar event
*
2014-05-27 17:02:56 +02:00
* @ param array $event Event to edit , if not $_GET [ 'cal_id' ] contains the event - id
* @ param array $preserv following keys :
2005-11-09 00:15:14 +01:00
* view boolean view - mode , if no edit - access we automatic fallback to view - mode
2009-08-17 22:05:46 +02:00
* hide_delete boolean hide delete button
2005-11-09 00:15:14 +01:00
* no_popup boolean use a popup or not
* edit_single int timestamp of single event edited , unset / null otherwise
2014-11-25 11:42:27 +01:00
* @ param string $msg = '' msg to display
* @ param mixed $link_to_id = '' from or for the link - widget
2015-09-16 13:36:51 +02:00
* @ param string $msg_type = null default automatic detect , if it contains " error "
2005-11-09 00:15:14 +01:00
*/
2015-09-16 13:36:51 +02:00
function edit ( $event = null , $preserv = null , $msg = '' , $link_to_id = '' , $msg_type = null )
2005-11-09 00:15:14 +01:00
{
2005-11-23 15:21:20 +01:00
$sel_options = array (
2006-12-22 20:51:56 +01:00
'recur_type' => & $this -> bo -> recur_types ,
'status' => $this -> bo -> verbose_status ,
'duration' => $this -> durations ,
2009-10-12 21:16:42 +02:00
'role' => $this -> bo -> roles ,
2014-06-05 18:07:59 +02:00
'new_alarm[options]' => $this -> bo -> alarms + array ( 0 => lang ( 'Custom' )),
2006-12-22 20:51:56 +01:00
'action' => array (
'copy' => array ( 'label' => 'Copy' , 'title' => 'Copy this event' ),
'ical' => array ( 'label' => 'Export' , 'title' => 'Download this event as iCal' ),
2008-12-18 15:47:21 +01:00
'print' => array ( 'label' => 'Print' , 'title' => 'Print this event' ),
2013-05-10 12:54:36 +02:00
'infolog' => array ( 'label' => 'InfoLog' , 'title' => 'Create an InfoLog from this event' ),
'mail' => array ( 'label' => 'Mail all participants' , 'title' => 'Compose a mail to all participants after the event is saved' ),
'sendrequest' => array ( 'label' => 'Meetingrequest to all participants' , 'title' => 'Send meetingrequest to all participants after the event is saved' ),
2006-12-22 20:51:56 +01:00
),
2005-11-23 15:21:20 +01:00
);
2006-12-22 20:51:56 +01:00
unset ( $sel_options [ 'status' ][ 'G' ]);
2005-11-09 00:15:14 +01:00
if ( ! is_array ( $event ))
{
$preserv = array (
'no_popup' => isset ( $_GET [ 'no_popup' ]),
2009-11-25 21:16:41 +01:00
'template' => isset ( $_GET [ 'template' ]) ? $_GET [ 'template' ] : ( isset ( $_REQUEST [ 'print' ]) ? 'calendar.print' : 'calendar.edit' ),
2005-11-09 00:15:14 +01:00
);
$cal_id = ( int ) $_GET [ 'cal_id' ];
2012-10-16 00:37:24 +02:00
if ( $_GET [ 'action' ])
{
$event = $this -> bo -> read ( $cal_id );
$event [ 'action' ] = $_GET [ 'action' ];
unset ( $event [ 'participants' ]);
return $this -> process_edit ( $event );
}
2015-03-25 19:35:31 +01:00
// vfs url
if ( ! empty ( $_GET [ 'ical_url' ]) && parse_url ( $_GET [ 'ical_url' ], PHP_URL_SCHEME ) == 'vfs' )
2015-03-24 10:43:38 +01:00
{
2015-03-25 19:35:31 +01:00
$_GET [ 'ical_vfs' ] = parse_url ( $_GET [ 'ical_url' ], PHP_URL_PATH );
2015-03-24 10:43:38 +01:00
}
2015-03-25 19:35:31 +01:00
// vfs path
if ( ! empty ( $_GET [ 'ical_vfs' ]) &&
( ! egw_vfs :: file_exists ( $_GET [ 'ical_vfs' ]) || ! ( $_GET [ 'ical' ] = file_get_contents ( egw_vfs :: PREFIX . $_GET [ 'ical_vfs' ]))))
2015-03-24 10:43:38 +01:00
{
2015-03-25 19:35:31 +01:00
//error_log(__METHOD__."() Error: importing the iCal: vfs file not found '$_GET[ical_vfs]'!");
$msg = lang ( 'Error: importing the iCal' ) . ': ' . lang ( 'VFS file not found' ) . ': ' . $_GET [ 'ical_vfs' ];
$event =& $this -> default_add_event ();
}
if ( ! empty ( $_GET [ 'ical_data' ]) &&
! ( $_GET [ 'ical' ] = egw_link :: get_data ( $_GET [ 'ical_data' ])))
{
//error_log(__METHOD__."() Error: importing the iCal: data not found '$_GET[ical_data]'!");
$msg = lang ( 'Error: importing the iCal' ) . ': ' . lang ( 'Data not found' ) . ': ' . $_GET [ 'ical_data' ];
$event =& $this -> default_add_event ();
2015-03-24 10:43:38 +01:00
}
if ( ! empty ( $_GET [ 'ical' ]))
2011-05-26 20:28:41 +02:00
{
$ical = new calendar_ical ();
2015-09-16 13:36:51 +02:00
if ( ! ( $events = $ical -> icaltoegw ( $_GET [ 'ical' ], '' , 'utf-8' )))
2011-05-26 20:28:41 +02:00
{
error_log ( __METHOD__ . " (' $_GET[ical] ') error parsing iCal! " );
$msg = lang ( 'Error: importing the iCal' );
$event =& $this -> default_add_event ();
}
else
{
2015-09-16 13:36:51 +02:00
if ( count ( $events ) > 1 )
{
$msg = lang ( '%1 events in iCal file, only first one imported and displayed!' , count ( $events ));
$msg_type = 'notice' ; // no not hide automatic
}
2012-03-22 15:02:06 +01:00
// as icaltoegw returns timestamps in server-time, we have to convert them here to user-time
$this -> bo -> db2data ( $events , 'ts' );
2011-05-26 20:28:41 +02:00
$event = array_shift ( $events );
2011-05-26 20:40:35 +02:00
if (( $existing_event = $this -> bo -> read ( $event [ 'uid' ])))
2011-05-26 20:28:41 +02:00
{
2011-05-26 20:40:35 +02:00
$event = $existing_event ;
}
else
{
$event [ 'participant_types' ] = array ();
foreach ( $event [ 'participants' ] as $uid => $status )
{
2015-06-25 22:35:24 +02:00
$user_type = $user_id = null ;
2011-05-26 20:40:35 +02:00
calendar_so :: split_user ( $uid , $user_type , $user_id );
$event [ 'participant_types' ][ $user_type ][ $user_id ] = $status ;
}
2011-05-26 20:28:41 +02:00
}
//error_log(__METHOD__."(...) parsed as ".array2string($event));
}
unset ( $ical );
2012-03-08 19:43:40 +01:00
}
elseif ( ! $cal_id || $cal_id && ! ( $event = $this -> bo -> read ( $cal_id )))
{
if ( $cal_id )
{
if ( ! $preserv [ 'no_popup' ])
{
2013-10-31 15:51:19 +01:00
egw_framework :: window_close ( lang ( 'Permission denied' ));
2012-03-08 19:43:40 +01:00
}
else
{
2013-11-11 15:02:08 +01:00
$GLOBALS [ 'egw' ] -> framework -> render ( '<p class="message" align="center">' . lang ( 'Permission denied' ) . " </p> \n " , null , true );
2012-03-08 19:43:40 +01:00
common :: egw_exit ();
}
}
$event =& $this -> default_add_event ();
2011-05-26 20:28:41 +02:00
}
2006-12-22 20:51:56 +01:00
else
{
$preserv [ 'actual_date' ] = $event [ 'start' ]; // remember the date clicked
2010-06-08 18:36:55 +02:00
if ( $event [ 'recur_type' ] != MCAL_RECUR_NONE )
2006-12-22 20:51:56 +01:00
{
2010-05-03 09:52:10 +02:00
if ( empty ( $event [ 'whole_day' ]))
2008-02-07 03:38:55 +01:00
{
2010-05-03 09:52:10 +02:00
$date = $_GET [ 'date' ];
2008-02-07 03:38:55 +01:00
}
2009-08-17 16:38:18 +02:00
else
{
2015-06-25 22:35:24 +02:00
$date = $this -> bo -> so -> startOfDay ( new egw_time ( $_GET [ 'date' ], egw_time :: $user_timezone ));
2010-05-03 09:52:10 +02:00
$date -> setUser ();
2009-08-17 16:38:18 +02:00
}
2010-05-03 09:52:10 +02:00
$event = $this -> bo -> read ( $cal_id , $date , true );
$preserv [ 'actual_date' ] = $event [ 'start' ]; // remember the date clicked
2010-06-08 18:36:55 +02:00
if ( $_GET [ 'exception' ])
{
$msg = $this -> _create_exception ( $event , $preserv );
}
else
{
$event = $this -> bo -> read ( $cal_id , null , true );
}
2006-12-22 20:51:56 +01:00
}
}
2007-01-15 23:58:32 +01:00
// set new start and end if given by $_GET
if ( isset ( $_GET [ 'start' ])) { $event [ 'start' ] = $_GET [ 'start' ]; }
if ( isset ( $_GET [ 'end' ])) { $event [ 'end' ] = $_GET [ 'end' ]; }
2005-11-09 00:15:14 +01:00
// check if the event is the whole day
$start = $this -> bo -> date2array ( $event [ 'start' ]);
$end = $this -> bo -> date2array ( $event [ 'end' ]);
$event [ 'whole_day' ] = ! $start [ 'hour' ] && ! $start [ 'minute' ] && $end [ 'hour' ] == 23 && $end [ 'minute' ] == 59 ;
$link_to_id = $event [ 'id' ];
2015-05-04 14:19:33 +02:00
if ( ! $event [ 'id' ] && isset ( $_REQUEST [ 'link_app' ]) && isset ( $_REQUEST [ 'link_id' ]))
2005-11-09 00:15:14 +01:00
{
2011-12-12 22:51:12 +01:00
$link_ids = is_array ( $_REQUEST [ 'link_id' ]) ? $_REQUEST [ 'link_id' ] : array ( $_REQUEST [ 'link_id' ]);
foreach ( is_array ( $_REQUEST [ 'link_app' ]) ? $_REQUEST [ 'link_app' ] : array ( $_REQUEST [ 'link_app' ]) as $n => $link_app )
{
$link_id = $link_ids [ $n ];
if ( ! preg_match ( '/^[a-z_0-9-]+:[:a-z_0-9-]+$/i' , $link_app . ':' . $link_id )) // guard against XSS
{
continue ;
}
2012-02-22 13:31:00 +01:00
if ( ! $n )
2011-12-12 22:51:12 +01:00
{
2012-02-22 13:31:00 +01:00
$event [ 'title' ] = egw_link :: title ( $link_app , $link_id );
// ask first linked app via "calendar_set" hook, for further data to set, incl. links
if (( $set = $GLOBALS [ 'egw' ] -> hooks -> single ( $event + array ( 'location' => 'calendar_set' , 'entry_id' => $link_id ), $link_app )))
{
foreach (( array ) $set [ 'link_app' ] as $i => $l_app )
2011-12-12 22:51:12 +01:00
{
2015-06-25 22:35:24 +02:00
if (( $l_id = $set [ 'link_id' ][ $i ])) egw_link :: link ( 'calendar' , $event [ 'link_to' ][ 'to_id' ], $l_app , $l_id );
2011-12-12 22:51:12 +01:00
}
2012-02-22 13:31:00 +01:00
unset ( $set [ 'link_app' ]);
unset ( $set [ 'link_id' ]);
2011-12-12 22:51:12 +01:00
2012-02-22 13:31:00 +01:00
$event = array_merge ( $event , $set );
}
2011-12-12 22:51:12 +01:00
}
egw_link :: link ( 'calendar' , $link_to_id , $link_app , $link_id );
}
2005-11-09 00:15:14 +01:00
}
}
2014-06-05 13:03:12 +02:00
2013-10-31 15:51:19 +01:00
$etpl = new etemplate_new ();
2009-11-25 21:16:41 +01:00
if ( ! $etpl -> read ( $preserv [ 'template' ]))
{
$etpl -> read ( $preserv [ 'template' ] = 'calendar.edit' );
}
2005-11-09 00:15:14 +01:00
$view = $preserv [ 'view' ] = $preserv [ 'view' ] || $event [ 'id' ] && ! $this -> bo -> check_perms ( EGW_ACL_EDIT , $event );
//echo "view=$view, event="; _debug_array($event);
2008-05-08 00:12:25 +02:00
// shared locking of entries to edit
if ( ! $view && ( $locktime = $GLOBALS [ 'egw_info' ][ 'server' ][ 'Lock_Time_Calender' ]) && $event [ 'id' ])
{
$lock_path = egw_vfs :: app_entry_lock_path ( 'calendar' , $event [ 'id' ]);
$lock_owner = 'mailto:' . $GLOBALS [ 'egw_info' ][ 'user' ][ 'account_email' ];
2015-06-25 22:35:24 +02:00
if (( $preserv [ 'lock_token' ] = $event [ 'lock_token' ])) // already locked --> refresh the lock
2008-05-08 00:12:25 +02:00
{
egw_vfs :: lock ( $lock_path , $preserv [ 'lock_token' ], $locktime , $lock_owner , $scope = 'shared' , $type = 'write' , true , false );
}
if (( $lock = egw_vfs :: checkLock ( $lock_path )) && $lock [ 'owner' ] != $lock_owner )
{
$msg .= ' ' . lang ( 'This entry is currently opened by %1!' ,
(( $lock_uid = $GLOBALS [ 'egw' ] -> accounts -> name2id ( substr ( $lock [ 'owner' ], 7 ), 'account_email' )) ?
2009-10-12 21:16:42 +02:00
common :: grab_owner_name ( $lock_uid ) : $lock [ 'owner' ]));
2008-05-08 00:12:25 +02:00
}
elseif ( $lock )
{
$preserv [ 'lock_token' ] = $lock [ 'token' ];
}
elseif ( egw_vfs :: lock ( $lock_path , $preserv [ 'lock_token' ], $locktime , $lock_owner , $scope = 'shared' , $type = 'write' , false , false ))
{
2013-10-31 15:51:19 +01:00
//We handle AJAX_REQUEST in client-side for unlocking the locked entry, in case of closing the entry by X button or close button
2008-05-08 00:12:25 +02:00
}
else
{
$msg .= ' ' . lang ( " Can't aquire lock! " ); // eg. an exclusive lock via CalDAV ...
$view = true ;
}
}
2005-11-09 00:15:14 +01:00
$content = array_merge ( $event , array (
'link_to' => array (
'to_id' => $link_to_id ,
'to_app' => 'calendar' ,
),
'edit_single' => $preserv [ 'edit_single' ], // need to be in content too, as it is used in the template
2010-08-16 09:13:47 +02:00
'tabs' => $preserv [ 'tabs' ],
2005-11-09 00:15:14 +01:00
'view' => $view ,
2011-04-08 16:21:23 +02:00
'query_delete_exceptions' => ( int )( $event [ 'recur_type' ] && $event [ 'recur_exception' ]),
2005-11-09 00:15:14 +01:00
));
2015-09-16 13:36:51 +02:00
egw_framework :: message ( $msg , $msg_type );
2006-06-03 01:36:43 +02:00
$content [ 'duration' ] = $content [ 'end' ] - $content [ 'start' ];
if ( isset ( $this -> durations [ $content [ 'duration' ]])) $content [ 'end' ] = '' ;
2014-02-06 19:16:40 +01:00
$row = 3 ;
2006-12-22 20:51:56 +01:00
$readonlys = $content [ 'participants' ] = $preserv [ 'participants' ] = array ();
2010-11-11 14:29:37 +01:00
// preserve some ui elements, if set eg. under error-conditions
foreach ( array ( 'quantity' , 'resource' , 'role' ) as $n )
{
if ( isset ( $event [ 'participants' ][ $n ])) $content [ 'participants' ][ $n ] = $event [ 'participants' ][ $n ];
}
2005-11-09 00:15:14 +01:00
foreach ( $event [ 'participant_types' ] as $type => $participants )
{
$name = 'accounts' ;
if ( isset ( $this -> bo -> resources [ $type ]))
{
$name = $this -> bo -> resources [ $type ][ 'app' ];
}
2012-11-13 12:23:29 +01:00
// sort participants (in there group/app) by title
uksort ( $participants , array ( $this , 'uid_title_cmp' ));
2005-11-09 00:15:14 +01:00
foreach ( $participants as $id => $status )
{
2006-12-22 20:51:56 +01:00
$uid = $type == 'u' ? $id : $type . $id ;
2015-06-25 22:35:24 +02:00
$quantity = $role = null ;
2009-10-12 21:16:42 +02:00
calendar_so :: split_status ( $status , $quantity , $role );
2006-12-22 20:51:56 +01:00
$preserv [ 'participants' ][ $row ] = $content [ 'participants' ][ $row ] = array (
'app' => $name == 'accounts' ? ( $GLOBALS [ 'egw' ] -> accounts -> get_type ( $id ) == 'g' ? 'Group' : 'User' ) : $name ,
'uid' => $uid ,
2009-10-12 21:16:42 +02:00
'status' => $status ,
'old_status' => $status ,
'quantity' => $quantity > 1 || $uid [ 0 ] == 'r' ? $quantity : '' , // only display quantity for resources or if > 1
'role' => $role ,
2006-12-22 20:51:56 +01:00
);
2009-10-12 21:16:42 +02:00
// replace iCal roles with a nicer label and remove regular REQ-PARTICIPANT
if ( isset ( $this -> bo -> roles [ $role ]))
{
2009-10-12 23:26:11 +02:00
$content [ 'participants' ][ $row ][ 'role_label' ] = lang ( $this -> bo -> roles [ $role ]);
2009-10-12 21:16:42 +02:00
}
// allow third party apps to use categories for roles
elseif ( substr ( $role , 0 , 6 ) == 'X-CAT-' )
{
2009-10-12 23:26:11 +02:00
$content [ 'participants' ][ $row ][ 'role_label' ] = $GLOBALS [ 'egw' ] -> categories -> id2name ( substr ( $role , 6 ));
2009-10-12 21:16:42 +02:00
}
else
{
2009-10-12 23:26:11 +02:00
$content [ 'participants' ][ $row ][ 'role_label' ] = lang ( str_replace ( 'X-' , '' , $role ));
2009-10-12 21:16:42 +02:00
}
2010-04-16 12:19:29 +02:00
$content [ 'participants' ][ $row ][ 'delete_id' ] = strpbrk ( $uid , '"\'<>' ) !== false ? md5 ( $uid ) : $uid ;
2009-10-12 21:16:42 +02:00
//echo "<p>$uid ($quantity): $role --> {$content['participants'][$row]['role']}</p>\n";
2014-02-10 23:01:01 +01:00
2014-11-18 16:04:13 +01:00
if (( $no_status = ! $this -> bo -> check_status_perms ( $uid , $event )) || $view )
$readonlys [ 'participants' ][ $row ][ 'status' ] = $no_status ;
2014-11-17 14:30:12 +01:00
if ( $preserv [ 'hide_delete' ] || ! $this -> bo -> check_perms ( EGW_ACL_EDIT , $event ))
$readonlys [ 'participants' ][ 'delete' ][ $uid ] = true ;
2008-05-08 17:02:35 +02:00
// todo: make the participants available as links with email as title
2012-11-13 12:23:29 +01:00
$content [ 'participants' ][ $row ++ ][ 'title' ] = $this -> get_title ( $uid );
2005-11-23 15:21:20 +01:00
// enumerate group-invitations, so people can accept/reject them
2006-12-22 20:51:56 +01:00
if ( $name == 'accounts' && $GLOBALS [ 'egw' ] -> accounts -> get_type ( $id ) == 'g' &&
( $members = $GLOBALS [ 'egw' ] -> accounts -> members ( $id , true )))
2005-11-23 15:21:20 +01:00
{
2006-12-22 20:51:56 +01:00
$sel_options [ 'status' ][ 'G' ] = lang ( 'Select one' );
2012-11-13 12:23:29 +01:00
// sort members by title
usort ( $members , array ( $this , 'uid_title_cmp' ));
2006-12-22 20:51:56 +01:00
foreach ( $members as $member )
2005-11-23 15:21:20 +01:00
{
2009-06-18 15:21:05 +02:00
if ( ! isset ( $participants [ $member ]) && $this -> bo -> check_perms ( EGW_ACL_READ , 0 , $member ))
2005-11-23 15:21:20 +01:00
{
2009-06-18 15:21:05 +02:00
$preserv [ 'participants' ][ $row ] = $content [ 'participants' ][ $row ] = array (
'app' => 'Group invitation' ,
'uid' => $member ,
'status' => 'G' ,
);
2014-02-10 23:01:01 +01:00
$readonlys [ 'participants' ][ $row ][ 'quantity' ] = $readonlys [ 'participants' ][ 'delete' ][ $member ] = true ;
2009-08-17 16:38:18 +02:00
// read access is enough to invite participants, but you need edit rights to change status
2014-11-25 11:41:06 +01:00
$readonlys [ 'participants' ][ $row ][ 'status' ] = ! $this -> bo -> check_perms ( EGW_ACL_EDIT , 0 , $member );
2009-10-12 21:16:42 +02:00
$content [ 'participants' ][ $row ++ ][ 'title' ] = common :: grab_owner_name ( $member );
2005-11-23 15:21:20 +01:00
}
}
}
2005-11-09 00:15:14 +01:00
}
2006-12-22 20:51:56 +01:00
// resouces / apps we shedule, atm. resources and addressbook
$content [ 'participants' ][ 'cal_resources' ] = '' ;
2008-10-10 12:24:31 +02:00
foreach ( $this -> bo -> resources as $data )
{
2014-10-01 14:54:12 +02:00
if ( $data [ 'app' ] == 'email' ) continue ; // make no sense, as we cant search for email
2008-10-10 12:24:31 +02:00
$content [ 'participants' ][ 'cal_resources' ] .= ',' . $data [ 'app' ];
}
// adding extra content for the resource link-entry widget to
// * select resources or addressbook as a default selection on the app selectbox based on prefs
2015-03-12 16:23:15 +01:00
$content [ 'participants' ][ 'resource' ][ 'app' ] = $this -> cal_prefs [ 'defaultresource_sel' ];
2008-10-10 12:24:31 +02:00
// * get informations from the event on the ajax callback
2015-03-12 16:23:15 +01:00
if ( in_array ( $content [ 'participants' ][ 'resource' ][ 'app' ], array ( 'resources_conflict' , 'resources_without_conflict' )))
2008-10-10 12:24:31 +02:00
{
// fix real app string
2015-03-12 16:23:15 +01:00
$content [ 'participants' ][ 'resource' ][ 'app' ] = 'resources' ;
2008-10-10 12:24:31 +02:00
}
2015-02-06 10:47:50 +01:00
// check if current pref. is an allowed application for the user
2015-03-12 16:23:15 +01:00
if ( ! isset ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'apps' ][ $content [ 'participants' ][ 'resource' ][ 'app' ]]))
2015-02-06 10:47:50 +01:00
{
2015-03-12 16:23:15 +01:00
$content [ 'participants' ][ 'resource' ][ 'app' ] = 'home-accounts' ;
2015-02-06 10:47:50 +01:00
}
2005-11-09 00:15:14 +01:00
}
2006-12-22 20:51:56 +01:00
$content [ 'participants' ][ 'status_date' ] = $preserv [ 'actual_date' ];
2015-06-25 22:35:24 +02:00
$preserved = array_merge ( $preserv , $content );
2014-05-28 17:04:06 +02:00
$event [ 'new_alarm' ][ 'options' ] = $content [ 'new_alarm' ][ 'options' ];
2005-11-09 00:15:14 +01:00
if ( $event [ 'alarm' ])
{
// makes keys of the alarm-array starting with 1
$content [ 'alarm' ] = array ( false );
2015-06-25 22:35:24 +02:00
foreach ( array_values ( $event [ 'alarm' ]) as $id => $alarm )
2005-11-09 00:15:14 +01:00
{
2015-06-25 22:35:24 +02:00
if ( ! $alarm [ 'all' ] && ! $this -> bo -> check_perms ( EGW_ACL_READ , 0 , $alarm [ 'owner' ]))
2005-11-09 00:15:14 +01:00
{
2015-06-25 22:35:24 +02:00
continue ; // no read rights to the calendar of the alarm-owner, dont show the alarm
2005-11-09 00:15:14 +01:00
}
2015-06-25 22:35:24 +02:00
$alarm [ 'all' ] = ( int ) $alarm [ 'all' ];
$after = false ;
if ( $alarm [ 'offset' ] < 0 )
{
$after = true ;
$alarm [ 'offset' ] = - 1 * $alarm [ 'offset' ];
}
$days = ( int ) ( $alarm [ 'offset' ] / DAY_s );
$hours = ( int ) (( $alarm [ 'offset' ] % DAY_s ) / HOUR_s );
$minutes = ( int ) (( $alarm [ 'offset' ] % HOUR_s ) / 60 );
$label = array ();
if ( $days ) $label [] = $days . ' ' . lang ( 'days' );
if ( $hours ) $label [] = $hours . ' ' . lang ( 'hours' );
if ( $minutes ) $label [] = $minutes . ' ' . lang ( 'Minutes' );
$alarm [ 'offset' ] = implode ( ', ' , $label ) . ' ' . ( $after ? lang ( 'after' ) : lang ( 'before' ));
$content [ 'alarm' ][] = $alarm ;
$readonlys [ 'alarm[delete_alarm][' . $alarm [ 'id' ] . ']' ] = ! $this -> bo -> check_perms ( EGW_ACL_EDIT , $alarm [ 'all' ] ? $event : 0 , $alarm [ 'owner' ]);
2005-11-09 00:15:14 +01:00
}
2009-11-04 10:41:19 +01:00
if ( count ( $content [ 'alarm' ]) == 1 )
{
$content [ 'alarm' ] = false ; // no alarms added to content array
}
2005-11-09 00:15:14 +01:00
}
else
{
$content [ 'alarm' ] = false ;
}
2012-11-14 17:25:21 +01:00
$content [ 'msg' ] = $msg ;
2005-11-09 00:15:14 +01:00
if ( $view )
{
2011-08-01 17:57:23 +02:00
$readonlys [ '__ALL__' ] = true ; // making everything readonly, but widgets set explicitly to false
2014-10-01 16:08:31 +02:00
$readonlys [ 'button[cancel]' ] = $readonlys [ 'action' ] =
2011-08-01 17:57:23 +02:00
$readonlys [ 'before_after' ] = $readonlys [ 'button[add_alarm]' ] = $readonlys [ 'new_alarm[owner]' ] =
2014-09-23 15:49:22 +02:00
$readonlys [ 'new_alarm[options]' ] = $readonlys [ 'new_alarm[date]' ] = false ;
2008-05-08 00:12:25 +02:00
2006-12-22 20:51:56 +01:00
$content [ 'participants' ][ 'no_add' ] = true ;
2009-11-25 21:16:41 +01:00
2015-07-22 16:44:19 +02:00
if ( ! $event [ 'whole_day' ])
{
$etpl -> setElementAttribute ( 'whole_day' , 'disabled' , true );
}
2009-11-26 09:28:06 +01:00
// respect category permissions
if ( ! empty ( $event [ 'category' ]))
{
$content [ 'category' ] = $this -> categories -> check_list ( EGW_ACL_READ , $event [ 'category' ]);
}
2005-11-09 00:15:14 +01:00
}
else
{
2010-06-09 20:00:11 +02:00
$readonlys [ 'recur_exception' ] = true ;
2010-02-24 16:05:00 +01:00
2010-01-23 11:40:44 +01:00
if ( $event [ 'recur_type' ] != MCAL_RECUR_NONE )
{
2010-06-09 20:00:11 +02:00
$readonlys [ 'recur_exception' ] = ! count ( $content [ 'recur_exception' ]); // otherwise we get a delete button
2013-10-31 15:51:19 +01:00
//$onclick =& $etpl->get_cell_attribute('button[delete]','onclick');
//$onclick = str_replace('Delete this event','Delete this series of recuring events',$onclick);
2010-01-23 11:40:44 +01:00
}
2010-01-23 13:43:35 +01:00
elseif ( $event [ 'reference' ] != 0 )
{
$readonlys [ 'recur_type' ] = $readonlys [ 'recur_enddate' ] = true ;
$readonlys [ 'recur_interval' ] = $readonlys [ 'recur_data' ] = true ;
}
2005-11-09 00:15:14 +01:00
}
// disabling the custom fields tab, if there are none
2010-08-16 09:13:47 +02:00
$readonlys [ 'tabs' ] = array (
2014-07-09 11:35:22 +02:00
'custom' => ! count ( $this -> bo -> customfields ),
2006-08-22 18:50:45 +02:00
'participants' => $this -> accountsel -> account_selection == 'none' ,
2014-02-05 12:14:44 +01:00
'history' => ! $event [ 'id' ],
2005-11-09 00:15:14 +01:00
);
2014-03-20 17:10:52 +01:00
if ( ! isset ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'apps' ][ 'mail' ])) // no mail without mail-app
2006-12-22 20:51:56 +01:00
{
unset ( $sel_options [ 'action' ][ 'mail' ]);
2011-12-16 10:55:57 +01:00
unset ( $sel_options [ 'action' ][ 'sendmeetingrequest' ]);
2006-12-22 20:51:56 +01:00
}
if ( ! $event [ 'id' ]) // no ical export for new (not saved) events
2005-11-09 00:15:14 +01:00
{
2006-12-22 20:51:56 +01:00
$readonlys [ 'action' ] = true ;
2005-11-09 00:15:14 +01:00
}
2012-10-22 19:03:02 +02:00
if ( ! ( $readonlys [ 'button[exception]' ] = ! $this -> bo -> check_perms ( EGW_ACL_EDIT , $event ) || $event [ 'recur_type' ] == MCAL_RECUR_NONE || ( $event [ 'recur_enddate' ] && $event [ 'start' ] > $event [ 'recur_enddate' ])))
2005-11-09 00:15:14 +01:00
{
2015-06-25 22:35:24 +02:00
$content [ 'exception_label' ] = $this -> bo -> long_date ( max ( $preserved [ 'actual_date' ], $event [ 'start' ]));
2005-11-09 00:15:14 +01:00
}
2015-06-25 22:35:24 +02:00
$readonlys [ 'button[delete]' ] = ! $event [ 'id' ] || $preserved [ 'hide_delete' ] || ! $this -> bo -> check_perms ( EGW_ACL_DELETE , $event );
2005-11-23 22:39:37 +01:00
2007-05-07 11:35:05 +02:00
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
2005-11-09 00:15:14 +01:00
{
$sel_options [ 'owner' ][ 0 ] = lang ( 'All participants' );
}
2007-05-07 11:35:05 +02:00
if ( isset ( $event [ 'participant_types' ][ 'u' ][ $this -> user ]))
{
$sel_options [ 'owner' ][ $this -> user ] = $this -> bo -> participant_name ( $this -> user );
}
2005-11-09 00:15:14 +01:00
foreach (( array ) $event [ 'participant_types' ][ 'u' ] as $uid => $status )
{
2007-05-07 11:35:05 +02:00
if ( $uid != $this -> user && $status != 'R' && $this -> bo -> check_perms ( EGW_ACL_EDIT , 0 , $uid ))
2005-11-09 00:15:14 +01:00
{
$sel_options [ 'owner' ][ $uid ] = $this -> bo -> participant_name ( $uid );
}
}
$content [ 'no_add_alarm' ] = ! count ( $sel_options [ 'owner' ]); // no rights to set any alarm
if ( ! $event [ 'id' ])
{
2008-05-08 00:12:25 +02:00
$etpl -> set_cell_attribute ( 'button[new_alarm]' , 'type' , 'checkbox' );
2005-11-09 00:15:14 +01:00
}
2015-06-25 22:35:24 +02:00
if ( $preserved [ 'no_popup' ])
2005-11-09 00:15:14 +01:00
{
$etpl -> set_cell_attribute ( 'button[cancel]' , 'onclick' , '' );
}
2010-02-12 21:18:45 +01:00
2010-06-28 13:38:28 +02:00
// Allow admins to restore deleted events
2011-04-27 18:53:06 +02:00
if ( $GLOBALS [ 'egw_info' ][ 'server' ][ 'calendar_delete_history' ] && $event [ 'deleted' ] )
2010-06-28 13:38:28 +02:00
{
2015-06-25 22:35:24 +02:00
$content [ 'deleted' ] = $preserved [ 'deleted' ] = null ;
2010-09-09 11:11:57 +02:00
$etpl -> set_cell_attribute ( 'button[save]' , 'label' , 'Recover' );
2010-06-28 13:38:28 +02:00
$etpl -> set_cell_attribute ( 'button[apply]' , 'disabled' , true );
}
2011-03-21 17:57:11 +01:00
// Allow users to prevent notifications?
2011-04-27 18:53:06 +02:00
$etpl -> set_cell_attribute ( 'no_notifications' , 'disabled' , ! $GLOBALS [ 'egw_info' ][ 'server' ][ 'calendar_allow_no_notification' ]);
2010-06-28 13:38:28 +02:00
2010-02-12 21:18:45 +01:00
// Setup history tab
$this -> setup_history ( $content , $sel_options );
2005-11-09 00:15:14 +01:00
//echo "content="; _debug_array($content);
2015-06-25 22:35:24 +02:00
//echo "preserv="; _debug_array($preserved);
2005-11-09 00:15:14 +01:00
//echo "readonlys="; _debug_array($readonlys);
//echo "sel_options="; _debug_array($sel_options);
2009-07-22 17:38:58 +02:00
$GLOBALS [ 'egw_info' ][ 'flags' ][ 'app_header' ] = lang ( 'calendar' ) . ' - '
. ( ! $event [ 'id' ] ? lang ( 'Add' )
: ( $view ? ( $content [ 'edit_single' ] ? lang ( 'View exception' ) : ( $content [ 'recur_type' ] ? lang ( 'View series' ) : lang ( 'View' )))
: ( $content [ 'edit_single' ] ? lang ( 'Create exception' ) : ( $content [ 'recur_type' ] ? lang ( 'Edit series' ) : lang ( 'Edit' )))));
2010-04-16 15:24:58 +02:00
2007-01-15 23:58:32 +01:00
$content [ 'cancel_needs_refresh' ] = ( bool ) $_GET [ 'cancel_needs_refresh' ];
2008-01-17 16:39:22 +01:00
2015-06-25 22:35:24 +02:00
if ( ! empty ( $preserved [ 'lock_token' ])) $content [ 'lock_token' ] = $preserved [ 'lock_token' ];
2013-10-31 15:51:19 +01:00
2007-01-15 23:58:32 +01:00
// non_interactive==true from $_GET calls immediate save action without displaying the edit form
if ( isset ( $_GET [ 'non_interactive' ]) && ( bool ) $_GET [ 'non_interactive' ] === true )
{
unset ( $_GET [ 'non_interactive' ]); // prevent process_exec <--> edit loops
$content [ 'button' ][ 'save' ] = true ;
2015-06-25 22:35:24 +02:00
$this -> process_edit ( array_merge ( $content , $preserved ));
2007-01-15 23:58:32 +01:00
}
else
{
2015-06-25 22:35:24 +02:00
$etpl -> exec ( 'calendar.calendar_uiforms.process_edit' , $content , $sel_options , $readonlys , $preserved , $preserved [ 'no_popup' ] ? 0 : 2 );
2007-01-15 23:58:32 +01:00
}
2005-11-09 00:15:14 +01:00
}
2008-05-08 00:12:25 +02:00
/**
* 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 );
}
}
2011-05-27 22:32:46 +02:00
/**
2013-02-01 13:22:56 +01:00
* Display for FMail an iCal meeting request and allow to accept , tentative or reject it or a reply and allow to apply it
2011-05-27 22:32:46 +02:00
*
* @ todo Handle situation when user is NOT invited , but eg . can view that mail ...
2015-05-04 14:19:33 +02:00
* @ param array $event = null ; special usage if $event is array ( 'event' => null , 'msg' => '' , 'useSession' => true ) we
2013-06-03 11:57:00 +02:00
* are called by new mail - app ; and we intend to use the stuff passed on by session
2015-05-04 14:19:33 +02:00
* @ param string $msg = null
2011-05-27 22:32:46 +02:00
*/
2014-06-05 13:03:12 +02:00
function meeting ( array $event = null , $msg = null )
2011-05-27 22:32:46 +02:00
{
$user = $GLOBALS [ 'egw_info' ][ 'user' ][ 'account_id' ];
2013-02-01 13:22:56 +01:00
$readonlys [ 'button[apply]' ] = true ;
2013-06-03 11:57:00 +02:00
$_usesession =! is_array ( $event );
//special usage if $event is array('event'=>null,'msg'=>'','useSession'=>true) we
//are called by new mail-app; and we intend to use the stuff passed on by session
if ( $event == array ( 'event' => null , 'msg' => '' , 'useSession' => true ))
{
$event = null ; // set to null
$_usesession = true ; // trigger session read
}
2011-05-27 22:32:46 +02:00
if ( ! is_array ( $event ))
{
2011-05-31 12:12:39 +02:00
$ical_charset = 'utf-8' ;
$ical_string = $_GET [ 'ical' ];
2013-06-03 11:57:00 +02:00
if ( $ical_string == 'session' || $_usesession )
2011-05-31 12:12:39 +02:00
{
$session_data = egw_cache :: getSession ( 'calendar' , 'ical' );
$ical_string = $session_data [ 'attachment' ];
$ical_charset = $session_data [ 'charset' ];
2012-06-06 09:39:57 +02:00
$ical_method = $session_data [ 'method' ];
2013-02-01 13:22:56 +01:00
$ical_sender = $session_data [ 'sender' ];
2011-05-31 12:12:39 +02:00
unset ( $session_data );
}
2011-05-27 22:32:46 +02:00
$ical = new calendar_ical ();
2011-05-31 12:12:39 +02:00
if ( ! ( $events = $ical -> icaltoegw ( $ical_string , '' , $ical_charset )) || count ( $events ) != 1 )
2011-05-27 22:32:46 +02:00
{
error_log ( __METHOD__ . " (' $_GET[ical] ') error parsing iCal! " );
$GLOBALS [ 'egw' ] -> framework -> render ( html :: fieldset ( '<pre>' . htmlspecialchars ( $ical_string ) . '</pre>' ,
lang ( 'Error: importing the iCal' )));
return ;
}
$event = array_shift ( $events );
2014-03-13 15:09:41 +01:00
// convert event from servertime returned by calendar_ical to user-time
$this -> bo -> server2usertime ( $event );
2011-05-27 22:32:46 +02:00
if (( $existing_event = $this -> bo -> read ( $event [ 'uid' ])) && ! $existing_event [ 'deleted' ])
{
2013-02-01 13:22:56 +01:00
switch ( strtolower ( $ical_method ))
2011-05-27 22:32:46 +02:00
{
2013-02-01 13:22:56 +01:00
case 'reply' :
if ( $ical_sender && ( $event [ 'ical_sender_uid' ] = groupdav_principals :: url2uid ( 'mailto:' . $ical_sender )) &&
isset ( $existing_event [ 'participants' ][ $event [ 'ical_sender_uid' ]]) &&
$this -> bo -> check_status_perms ( $event [ 'ical_sender_uid' ], $existing_event ))
{
2013-02-01 17:54:51 +01:00
$event [ 'ical_sender_status' ] = $event [ 'participants' ][ $event [ 'ical_sender_uid' ]];
2015-06-25 22:35:24 +02:00
$quantity = $role = null ;
2013-02-01 17:54:51 +01:00
calendar_so :: split_status ( $event [ 'ical_sender_status' ], $quantity , $role );
2013-02-01 13:22:56 +01:00
$existing_status = $existing_event [ 'participants' ][ $event [ 'ical_sender_uid' ]];
calendar_so :: split_status ( $existing_status , $quantity , $role );
2013-02-01 17:54:51 +01:00
if ( $existing_status != $event [ 'ical_sender_status' ])
2013-02-01 13:22:56 +01:00
{
$readonlys [ 'button[apply]' ] = false ;
}
else
{
$msg = lang ( 'Status already applied' );
}
}
break ;
case 'request' :
$status = $existing_event [ 'participants' ][ $user ];
calendar_so :: split_status ( $status , $quantity , $role );
if ( strtolower ( $ical_method ) == 'response' && isset ( $existing_event [ 'participants' ][ $user ]) &&
$status != 'U' && isset ( $this -> bo -> verbose_status [ $status ]))
{
$msg = lang ( 'You already replied to this invitation with' ) . ': ' . lang ( $this -> bo -> verbose_status [ $status ]);
}
else
{
$msg = lang ( 'Using already existing event on server.' );
}
2011-05-27 22:32:46 +02:00
break ;
}
2013-02-01 13:22:56 +01:00
$event [ 'id' ] = $existing_event [ 'id' ];
2011-05-27 22:32:46 +02:00
}
2015-07-16 11:34:55 +02:00
else // event not in calendar
{
$readonlys [ 'button[cancel]' ] = true ; // no way to remove a canceled event not in calendar
}
2013-02-01 13:22:56 +01:00
$event [ 'participant_types' ] = array ();
foreach ( $event [ 'participants' ] as $uid => $status )
2011-05-27 22:32:46 +02:00
{
2015-06-25 22:35:24 +02:00
$user_type = $user_id = null ;
2013-02-01 13:22:56 +01:00
calendar_so :: split_user ( $uid , $user_type , $user_id );
$event [ 'participants' ][ $uid ] = $event [ 'participant_types' ][ $user_type ][ $user_id ] =
$status && $status !== 'X' ? $status : 'U' ; // X --> no status given --> U = unknown
2011-05-27 22:32:46 +02:00
}
//error_log(__METHOD__."(...) parsed as ".array2string($event));
$event [ 'recure' ] = $this -> bo -> recure2string ( $event );
$event [ 'all_participants' ] = implode ( " , \n " , $this -> bo -> participants ( $event , true ));
2012-06-12 18:18:17 +02:00
$user_and_memberships = $GLOBALS [ 'egw' ] -> accounts -> memberships ( $user , true );
$user_and_memberships [] = $user ;
if ( ! array_intersect ( array_keys ( $event [ 'participants' ]), $user_and_memberships ))
2011-05-27 22:32:46 +02:00
{
$msg .= ( $msg ? " \n " : '' ) . lang ( 'You are not invited to that event!' );
if ( $event [ 'id' ])
{
2015-07-16 11:34:55 +02:00
$readonlys [ 'button[accept]' ] = $readonlys [ 'button[tentativ]' ] =
$readonlys [ 'button[reject]' ] = $readonlys [ 'button[cancel]' ] = true ;
2011-05-27 22:32:46 +02:00
}
}
2012-03-12 09:52:40 +01:00
// ignore events in the past (for recurring events check enddate!)
if ( $this -> bo -> date2ts ( $event [ 'start' ]) < $this -> bo -> now_su &&
( ! $event [ 'recur_type' ] || $event [ 'recur_enddate' ] && $event [ 'recur_enddate' ] < $this -> bo -> now_su ))
2011-05-27 22:32:46 +02:00
{
$msg = lang ( 'Requested meeting is in the past!' );
2015-07-16 11:34:55 +02:00
$readonlys [ 'button[accept]' ] = $readonlys [ 'button[tentativ]' ] =
$readonlys [ 'button[reject]' ] = $readonlys [ 'button[cancel]' ] = true ;
2011-05-27 22:32:46 +02:00
}
}
else
{
//_debug_array($event);
list ( $button ) = each ( $event [ 'button' ]);
unset ( $event [ 'button' ]);
2014-06-05 13:03:12 +02:00
// clear notification errors
notifications :: errors ( true );
2011-05-27 22:32:46 +02:00
switch ( $button )
{
case 'reject' :
if ( ! $event [ 'id' ])
{
// send reply to organizer
$this -> bo -> send_update ( MSG_REJECTED , array ( 'e' . $event [ 'organizer' ] => 'DCHAIR' ), $event );
break ; // no need to store rejected event
}
// fall-through
case 'accept' :
case 'tentativ' :
$status = strtoupper ( $button [ 0 ]); // A, R or T
if ( ! $event [ 'id' ])
{
2012-04-24 16:37:32 +02:00
// if organizer is a EGroupware user, but we have no rights to organizers calendar
if ( isset ( $event [ 'owner' ]) && ! $this -> bo -> check_perms ( EGW_ACL_ADD , 0 , $event [ 'owner' ]))
{
// --> make organize a participant with role chair and current user the owner
$event [ 'participant_types' ][ 'u' ] = $event [ 'participants' ][ $event [ 'owner' ]] =
calendar_so :: combine_status ( 'A' , 1 , 'CHAIR' );
$event [ 'owner' ] = $this -> user ;
}
2011-05-27 22:32:46 +02:00
// store event without notifications!
if (( $event [ 'id' ] = $this -> bo -> update ( $event , $ignore_conflicts = true , true , false , true , $msg , true )))
{
2012-04-24 16:37:32 +02:00
$msg [] = lang ( 'Event saved' );
2011-05-27 22:32:46 +02:00
}
else
{
2012-04-24 16:37:32 +02:00
$msg [] = lang ( 'Error saving the event!' );
2011-05-27 22:32:46 +02:00
break ;
}
}
// set status and send notification / meeting response
2013-02-01 13:22:56 +01:00
if ( $this -> bo -> set_status ( $event [ 'id' ], $user , $status ))
2011-05-27 22:32:46 +02:00
{
if ( ! $msg ) $msg = lang ( 'Status changed' );
}
break ;
2013-02-01 13:22:56 +01:00
case 'apply' :
// set status and send notification / meeting response
2013-02-01 17:54:51 +01:00
if ( $this -> bo -> set_status ( $event [ 'id' ], $event [ 'ical_sender_uid' ], $event [ 'ical_sender_status' ]))
2013-02-01 13:22:56 +01:00
{
$msg = lang ( 'Status changed' );
}
break ;
2015-07-16 11:34:55 +02:00
case 'cancel' :
if ( $event [ 'id' ] && $this -> bo -> set_status ( $event [ 'id' ], $user , 'R' ))
{
$msg = lang ( 'Status changed' );
}
break ;
2011-05-27 22:32:46 +02:00
}
2014-06-05 13:03:12 +02:00
// add notification-errors, if we have some
$msg = array_merge (( array ) $msg , notifications :: errors ( true ));
2011-05-27 22:32:46 +02:00
}
2012-04-24 16:37:32 +02:00
$event [ 'msg' ] = implode ( " \n " ,( array ) $msg );
2011-05-27 22:32:46 +02:00
$readonlys [ 'button[edit]' ] = ! $event [ 'id' ];
2012-06-06 09:39:57 +02:00
$event [ 'ics_method' ] = $readonlys [ 'ics_method' ] = strtolower ( $ical_method );
2015-07-16 11:34:55 +02:00
switch ( strtolower ( $ical_method ))
{
case 'reply' :
$event [ 'ics_method_label' ] = lang ( 'Reply to meeting request' );
break ;
case 'cancel' :
$event [ 'ics_method_label' ] = lang ( 'Meeting canceled' );
break ;
case 'request' :
default :
$event [ 'ics_method_label' ] = lang ( 'Meeting request' );
break ;
}
2013-10-31 15:51:19 +01:00
$tpl = new etemplate_new ( 'calendar.meeting' );
2015-05-04 14:19:33 +02:00
$tpl -> exec ( 'calendar.calendar_uiforms.meeting' , $event , array (), $readonlys , $event , 2 );
2011-05-27 22:32:46 +02:00
}
2005-11-09 00:15:14 +01:00
/**
2013-10-31 15:51:19 +01:00
* displays a scheduling conflict
2005-11-09 00:15:14 +01:00
*
2008-05-08 00:12:25 +02:00
* @ param array $event
2005-11-09 00:15:14 +01:00
* @ 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 )
{
2013-10-31 15:51:19 +01:00
$etpl = CreateObject ( 'etemplate.etemplate_new' , 'calendar.conflicts' );
2014-02-12 11:26:34 +01:00
$allConflicts = array ();
2008-05-08 00:12:25 +02:00
2005-11-09 00:15:14 +01:00
foreach ( $conflicts as $k => $conflict )
{
$is_readable = $this -> bo -> check_perms ( EGW_ACL_READ , $conflict );
2008-05-08 00:12:25 +02:00
2005-11-09 00:15:14 +01:00
$conflicts [ $k ] += array (
'icon_participants' => $is_readable ? ( count ( $conflict [ 'participants' ]) > 1 ? 'users' : 'single' ) : 'private' ,
'tooltip_participants' => $is_readable ? implode ( ', ' , $this -> bo -> participants ( $conflict )) : '' ,
'time' => $this -> bo -> long_date ( $conflict [ 'start' ], $conflict [ 'end' ], true ),
'conflicting_participants' => implode ( " , \n " , $this -> bo -> participants ( array (
2014-02-12 12:59:32 +01:00
'participants' => array_intersect_key (( array ) $conflict [ 'participants' ], $event [ 'participants' ]),
2006-03-16 19:03:43 +01:00
), true , true )), // show group invitations too
2005-11-09 00:15:14 +01:00
'icon_recur' => $conflict [ 'recur_type' ] != MCAL_RECUR_NONE ? 'recur' : '' ,
'text_recur' => $conflict [ 'recur_type' ] != MCAL_RECUR_NONE ? lang ( 'Recurring event' ) : ' ' ,
2008-05-08 00:12:25 +02:00
);
2014-02-12 12:59:32 +01:00
$allConflicts += array_intersect_key (( array ) $conflict [ 'participants' ], $event [ 'participants' ]);
}
2005-11-09 00:15:14 +01:00
$content = $event + array (
'conflicts' => array_values ( $conflicts ), // conflicts have id-start as key
);
$GLOBALS [ 'egw_info' ][ 'flags' ][ 'app_header' ] = lang ( 'calendar' ) . ' - ' . lang ( 'Scheduling conflict' );
2014-01-28 17:26:18 +01:00
$resources_config = config :: read ( 'resources' );
$readonlys = array ();
2014-02-19 18:48:25 +01:00
2014-02-12 11:26:34 +01:00
foreach ( array_keys ( $allConflicts ) as $pId )
2014-01-28 17:26:18 +01:00
{
2014-02-12 11:26:34 +01:00
if ( substr ( $pId , 0 , 1 ) == 'r' && $resources_config ) // resources Allow ignore conflicts
2014-01-28 17:26:18 +01:00
{
2014-01-30 11:12:08 +01:00
2014-02-12 11:26:34 +01:00
switch ( $resources_config [ 'ignoreconflicts' ])
{
case 'no' :
$readonlys [ 'button[ignore]' ] = true ;
break ;
case 'allusers' :
$readonlys [ 'button[ignore]' ] = false ;
break ;
default :
if ( ! $this -> bo -> check_status_perms ( $pId , $event ))
{
$readonlys [ 'button[ignore]' ] = true ;
break ;
}
}
2014-01-28 17:26:18 +01:00
}
}
$etpl -> exec ( 'calendar.calendar_uiforms.process_edit' , $content , array (), $readonlys , array_merge ( $event , $preserv ), $preserv [ 'no_popup' ] ? 0 : 2 );
2010-06-09 20:00:11 +02:00
}
2010-11-11 14:29:37 +01:00
2009-04-29 16:17:46 +02:00
/**
* Callback for freetimesearch button in edit
*
* It stores the data of the submitted form in the session under 'freetimesearch_args_' . $edit_content [ 'id' ],
* for later retrival of the freetimesearch method , called by the returned window . open () command .
*
* @ param array $edit_content
* @ return string with xajaxResponse
*/
function ajax_freetimesearch ( array $edit_content )
{
2013-10-31 15:51:19 +01:00
$response = egw_json_response :: get ();
2009-04-29 16:31:58 +02:00
//$response->addAlert(__METHOD__.'('.array2string($edit_content).')');
2009-04-29 16:17:46 +02:00
2014-09-04 15:03:48 +02:00
// convert start/end date-time values to timestamps
foreach ( array ( 'start' , 'end' ) as $name )
{
if ( ! empty ( $edit_content [ $name ]))
{
$date = new egw_time ( $edit_content [ $name ]);
$edit_content [ $name ] = $date -> format ( 'ts' );
}
}
2009-04-29 16:17:46 +02:00
if ( $edit_content [ 'duration' ])
{
$edit_content [ 'end' ] = $edit_content [ 'start' ] + $edit_content [ 'duration' ];
}
if ( $edit_content [ 'whole_day' ])
{
$arr = $this -> bo -> date2array ( $edit_content [ 'start' ]);
$arr [ 'hour' ] = $arr [ 'minute' ] = $arr [ 'second' ] = 0 ; unset ( $arr [ 'raw' ]);
$edit_content [ 'start' ] = $this -> bo -> date2ts ( $arr );
2015-06-25 22:35:24 +02:00
$earr = $this -> bo -> date2array ( $edit_content [ 'end' ]);
$earr [ 'hour' ] = 23 ; $earr [ 'minute' ] = $earr [ 'second' ] = 59 ; unset ( $earr [ 'raw' ]);
$edit_content [ 'end' ] = $this -> bo -> date2ts ( $earr );
2009-04-29 16:17:46 +02:00
}
$content = array (
'start' => $edit_content [ 'start' ],
'duration' => $edit_content [ 'end' ] - $edit_content [ 'start' ],
'end' => $edit_content [ 'end' ],
'cal_id' => $edit_content [ 'id' ],
'recur_type' => $edit_content [ 'recur_type' ],
'participants' => array (),
);
foreach ( $edit_content [ 'participants' ] as $key => $data )
{
2010-04-16 12:19:29 +02:00
if ( is_numeric ( $key ) && ! $edit_content [ 'participants' ][ 'delete' ][ $data [ 'uid' ]] &&
! $edit_content [ 'participants' ][ 'delete' ][ md5 ( $data [ 'uid' ])])
2009-04-29 16:17:46 +02:00
{
$content [ 'participants' ][] = $data [ 'uid' ];
}
elseif ( $key == 'account' && ! is_array ( $data ) && $data )
{
$content [ 'participants' ][] = $data ;
}
}
// default search parameters
$content [ 'start_time' ] = $edit_content [ 'whole_day' ] ? 0 : $this -> cal_prefs [ 'workdaystarts' ];
$content [ 'end_time' ] = $this -> cal_prefs [ 'workdayends' ];
if ( $this -> cal_prefs [ 'workdayends' ] * HOUR_s < $this -> cal_prefs [ 'workdaystarts' ] * HOUR_s + $content [ 'duration' ])
{
$content [ 'end_time' ] = 0 ; // no end-time limit, as duration would never fit
}
$content [ 'weekdays' ] = MCAL_M_WEEKDAYS ;
$content [ 'search_window' ] = 7 * DAY_s ;
// store content in session
2009-04-29 16:31:58 +02:00
egw_cache :: setSession ( 'calendar' , 'freetimesearch_args_' . ( int ) $edit_content [ 'id' ], $content );
2009-04-29 16:17:46 +02:00
//menuaction=calendar.calendar_uiforms.freetimesearch&values2url('start,end,duration,participants,recur_type,whole_day'),ft_search,700,500
2013-10-31 15:51:19 +01:00
$link = 'calendar.calendar_uiforms.freetimesearch&cal_id=' . $edit_content [ 'id' ];
2009-04-29 16:17:46 +02:00
2013-10-31 15:51:19 +01:00
$response -> call ( 'app.calendar.freetime_search_popup' , $link );
//$response->addScriptCall('egw_openWindowCentered2',$link,'ft_search',700,500);
2009-04-29 16:17:46 +02:00
}
2004-10-08 00:11:18 +02:00
/**
* Freetime search
*
* As the function is called in a popup via javascript , parametes get initialy transfered via the url
2005-11-09 00:15:14 +01:00
* @ param array $content = null array with parameters or false ( default ) to use the get - params
* @ param string start [ str ] start - date
* @ param string start [ hour ] start - hour
* @ param string start [ min ] start - minutes
* @ param string end [ str ] end - date
* @ param string end [ hour ] end - hour
* @ param string end [ min ] end - minutes
* @ param string participants ':' delimited string of user - id ' s
2004-10-08 00:11:18 +02:00
*/
2005-11-09 00:15:14 +01:00
function freetimesearch ( $content = null )
2004-10-08 00:11:18 +02:00
{
2013-10-31 15:51:19 +01:00
$etpl = new etemplate_new ( 'calendar.freetimesearch' );
2004-12-12 13:31:41 +01:00
$sel_options [ 'search_window' ] = array (
7 * DAY_s => lang ( 'one week' ),
14 * DAY_s => lang ( 'two weeks' ),
31 * DAY_s => lang ( 'one month' ),
92 * DAY_s => lang ( 'three month' ),
365 * DAY_s => lang ( 'one year' ),
);
2004-10-08 00:11:18 +02:00
if ( ! is_array ( $content ))
{
2009-04-29 16:17:46 +02:00
// get content from session (and delete it immediatly)
$content = egw_cache :: getSession ( 'calendar' , 'freetimesearch_args_' . ( int ) $_GET [ 'cal_id' ]);
egw_cache :: unsetSession ( 'calendar' , 'freetimesearch_args_' . ( int ) $_GET [ 'cal_id' ]);
2013-10-31 15:51:19 +01:00
//Since the start_time and end_time from calendar_user_preferences are numbers, not timestamp, in order to show them on date-timeonly
//widget we need to convert them from numbers to timestamps, only for the first time when we have template without content
$sTime = $content [ 'start_time' ];
$eTime = $content [ 'end_time' ];
$content [ 'start_time' ] = strtotime ((( strlen ( $content [ 'start_time' ]) < 2 ) ? ( " 0 " . $content [ 'start_time' ]) : $content [ 'start_time' ]) . " :00 " );
$content [ 'end_time' ] = strtotime ((( strlen ( $content [ 'end_time' ]) < 2 ) ? ( " 0 " . $content [ 'end_time' ]) : $content [ 'end_time' ]) . " :00 " );
2008-05-08 00:12:25 +02:00
2004-12-12 13:31:41 +01:00
// pick a searchwindow fitting the duration (search for a 10 day slot in a one week window never succeeds)
2015-06-25 22:35:24 +02:00
foreach ( array_keys ( $sel_options [ 'search_window' ]) as $window )
2004-12-12 13:31:41 +01:00
{
2008-05-08 00:12:25 +02:00
if ( $window > $content [ 'duration' ])
2004-12-12 13:31:41 +01:00
{
$content [ 'search_window' ] = $window ;
break ;
}
}
2004-10-08 00:11:18 +02:00
}
else
{
2008-05-08 00:12:25 +02:00
if ( ! $content [ 'duration' ]) $content [ 'duration' ] = $content [ 'end' ] - $content [ 'start' ];
2013-10-31 15:51:19 +01:00
$weekds = 0 ;
2015-05-04 14:19:33 +02:00
foreach ( $content [ 'weekdays' ] as & $wdays )
2013-10-31 15:51:19 +01:00
{
$weekds = $weekds + $wdays ;
2004-10-08 00:11:18 +02:00
}
2013-10-31 15:51:19 +01:00
//split_freetime_daywise function expects to get start_time and end_time values as string numbers, only "hour", therefore, since the date-timeonly widget returns
//always timestamp, we need to convert them to only "hour" string numbers.
$sTime = date ( 'H' , $content [ 'start_time' ]);
$eTime = date ( 'H' , $content [ 'end_time' ]);
2004-10-08 18:04:50 +02:00
}
2013-10-31 15:51:19 +01:00
2004-10-08 18:04:50 +02:00
if ( $content [ 'recur_type' ])
{
$content [ 'msg' ] .= lang ( 'Only the initial date of that recuring event is checked!' );
}
2004-12-12 13:31:41 +01:00
$content [ 'freetime' ] = $this -> freetime ( $content [ 'participants' ], $content [ 'start' ], $content [ 'start' ] + $content [ 'search_window' ], $content [ 'duration' ], $content [ 'cal_id' ]);
2013-10-31 15:51:19 +01:00
$content [ 'freetime' ] = $this -> split_freetime_daywise ( $content [ 'freetime' ], $content [ 'duration' ],( is_array ( $content [ 'weekdays' ]) ? $weekds : $content [ 'weekdays' ]), $sTime , $eTime , $sel_options );
2004-10-08 00:11:18 +02:00
2005-11-09 00:15:14 +01:00
$GLOBALS [ 'egw_info' ][ 'flags' ][ 'app_header' ] = lang ( 'calendar' ) . ' - ' . lang ( 'freetime search' );
2008-05-08 00:12:25 +02:00
2006-06-03 01:36:43 +02:00
$sel_options [ 'duration' ] = $this -> durations ;
if ( $content [ 'duration' ] && isset ( $sel_options [ 'duration' ][ $content [ 'duration' ]])) $content [ 'end' ] = '' ;
2004-10-08 00:11:18 +02:00
2013-10-31 15:51:19 +01:00
$etpl -> exec ( 'calendar.calendar_uiforms.freetimesearch' , $content , $sel_options , NULL , array (
2004-10-08 00:11:18 +02:00
'participants' => $content [ 'participants' ],
2004-10-08 18:04:50 +02:00
'cal_id' => $content [ 'cal_id' ],
'recur_type' => $content [ 'recur_type' ],
2008-05-08 00:12:25 +02:00
), 2 );
2004-10-08 00:11:18 +02:00
}
2008-05-08 00:12:25 +02:00
2004-10-08 00:11:18 +02:00
/**
* calculate the freetime of given $participants in a certain time - span
*
2005-11-09 00:15:14 +01:00
* @ param array $participants user - id ' s
* @ param int $start start - time timestamp in user - time
* @ param int $end end - time timestamp in user - time
* @ param int $duration min . duration in sec , default 1
* @ param int $cal_id own id for existing events , to exclude them from being busy - time , default 0
2004-10-08 00:11:18 +02:00
* @ return array of free time - slots : array with start and end values
*/
2004-10-08 18:04:50 +02:00
function freetime ( $participants , $start , $end , $duration = 1 , $cal_id = 0 )
2004-10-08 00:11:18 +02:00
{
2015-07-16 14:09:19 +02:00
if ( $this -> debug > 2 ) $this -> bo -> debug_message ( __METHOD__ . '(participants=%1, start=%2, end=%3, duration=%4, cal_id=%5)' , true , $participants , $start , $end , $duration , $cal_id );
2004-12-12 13:31:41 +01:00
2004-10-08 00:11:18 +02:00
$busy = $this -> bo -> search ( array (
'start' => $start ,
'end' => $end ,
'users' => $participants ,
2006-03-16 19:03:43 +01:00
'ignore_acl' => true , // otherwise we get only events readable by the user
2004-10-08 00:11:18 +02:00
));
$busy [] = array ( // add end-of-search-date as event, to cope with empty search and get freetime til that date
2005-11-09 00:15:14 +01:00
'start' => $end ,
'end' => $end ,
2008-05-08 00:12:25 +02:00
);
2004-10-08 00:11:18 +02:00
$ft_start = $start ;
$freetime = array ();
$n = 0 ;
foreach ( $busy as $event )
{
2004-10-08 18:04:50 +02:00
if (( int ) $cal_id && $event [ 'id' ] == ( int ) $cal_id ) continue ; // ignore our own event
2006-03-08 11:23:44 +01:00
if ( $event [ 'non_blocking' ]) continue ; // ignore non_blocking events
2015-07-16 14:09:19 +02:00
// check if from all wanted participants at least one has a not rejected status in found event
$non_rejected_found = false ;
foreach ( $participants as $uid )
{
if ( $event [ 'participants' ][ $uid ] == 'R' ) continue ;
if ( isset ( $event [ 'participants' ][ $uid ]) ||
$uid > 0 && array_intersect ( array_keys (( array ) $event [ 'participants' ]),
$GLOBALS [ 'egw' ] -> accounts -> memberships ( $uid , true )))
{
$non_rejected_found = true ;
break ;
}
}
if ( ! $non_rejected_found ) continue ;
2004-10-08 00:11:18 +02:00
if ( $this -> debug )
{
echo " <p>ft_start= " . date ( 'D d.m.Y H:i' , $ft_start ) . " <br> \n " ;
echo " event[title]= $event[title] <br> \n " ;
2008-10-10 12:24:31 +02:00
echo " event[start]= " . date ( 'D d.m.Y H:i' , $event [ 'start' ]) . " <br> \n " ;
echo " event[end]= " . date ( 'D d.m.Y H:i' , $event [ 'end' ]) . " <br> \n " ;
2004-10-08 00:11:18 +02:00
}
// $events ends before our actual position ==> ignore it
2005-11-09 00:15:14 +01:00
if ( $event [ 'end' ] < $ft_start )
2004-10-08 00:11:18 +02:00
{
//echo "==> event ends before ft_start ==> continue<br>\n";
continue ;
}
// $events starts before our actual position ==> set start to it's end and go to next event
2005-11-09 00:15:14 +01:00
if ( $event [ 'start' ] < $ft_start )
2004-10-08 00:11:18 +02:00
{
//echo "==> event starts before ft_start ==> set ft_start to it's end & continue<br>\n";
2005-11-09 00:15:14 +01:00
$ft_start = $event [ 'end' ];
2004-10-08 00:11:18 +02:00
continue ;
}
2005-11-09 00:15:14 +01:00
$ft_end = $event [ 'start' ];
2004-10-08 00:11:18 +02:00
// only show slots equal or bigger to min_length
if ( $ft_end - $ft_start >= $duration )
{
$freetime [ ++ $n ] = array (
'start' => $ft_start ,
'end' => $ft_end ,
);
2004-12-12 13:31:41 +01:00
if ( $this -> debug > 1 ) echo " <p>freetime: " . date ( 'D d.m.Y H:i' , $ft_start ) . " - " . date ( 'D d.m.Y H:i' , $ft_end ) . " </p> \n " ;
2008-05-08 00:12:25 +02:00
}
2005-11-09 00:15:14 +01:00
$ft_start = $event [ 'end' ];
2004-10-08 00:11:18 +02:00
}
2004-12-12 13:31:41 +01:00
if ( $this -> debug > 0 ) $this -> bo -> debug_message ( 'uiforms::freetime(participants=%1, start=%2, end=%3, duration=%4, cal_id=%5) freetime=%6' , true , $participants , $start , $end , $duration , $cal_id , $freetime );
2008-05-08 00:12:25 +02:00
2004-10-08 00:11:18 +02:00
return $freetime ;
}
2008-05-08 00:12:25 +02:00
2004-10-08 00:11:18 +02:00
/**
* split the freetime in daywise slot , taking into account weekdays , start - and stop - times
*
2004-12-12 13:31:41 +01:00
* If the duration is bigger then the difference of start - and end_time , the end_time is ignored
*
2005-11-09 00:15:14 +01:00
* @ param array $freetime free time - slots : array with start and end values
* @ param int $duration min . duration in sec
* @ param int $weekdays allowed weekdays , bitfield of MCAL_M_ ...
2015-06-25 22:35:24 +02:00
* @ param int $_start_time minimum start - hour 0 - 23
* @ param int $_end_time maximum end - hour 0 - 23 , or 0 for none
2005-11-09 00:15:14 +01:00
* @ param array $sel_options on return options for start - time selectbox
2004-10-08 00:11:18 +02:00
* @ return array of free time - slots : array with start and end values
*/
2015-06-25 22:35:24 +02:00
function split_freetime_daywise ( $freetime , $duration , $weekdays , $_start_time , $_end_time , & $sel_options )
2004-10-08 00:11:18 +02:00
{
2015-06-25 22:35:24 +02:00
if ( $this -> debug > 1 ) $this -> bo -> debug_message ( 'uiforms::split_freetime_daywise(freetime=%1, duration=%2, start_time=%3, end_time=%4)' , true , $freetime , $duration , $_start_time , $_end_time );
2008-05-08 00:12:25 +02:00
2004-12-12 13:31:41 +01:00
$freetime_daywise = array ();
if ( ! is_array ( $sel_options )) $sel_options = array ();
2004-10-08 00:11:18 +02:00
$time_format = $this -> common_prefs [ 'timeformat' ] == 12 ? 'h:i a' : 'H:i' ;
2008-05-08 00:12:25 +02:00
2015-06-25 22:35:24 +02:00
$start_time = ( int ) $_start_time ; // ignore leading zeros
$end_time = ( int ) $_end_time ;
2004-10-08 00:11:18 +02:00
2004-12-12 13:31:41 +01:00
// ignore the end_time, if duration would never fit
2008-05-08 00:12:25 +02:00
if (( $end_time - $start_time ) * HOUR_s < $duration )
2004-12-12 13:31:41 +01:00
{
2008-05-08 00:12:25 +02:00
$end_time = 0 ;
2004-12-12 13:31:41 +01:00
if ( $this -> debug > 1 ) $this -> bo -> debug_message ( 'uiforms::split_freetime_daywise(, duration=%2, start_time=%3,..) end_time set to 0, it never fits durationn otherwise' , true , $duration , $start_time );
}
2004-10-08 00:11:18 +02:00
$n = 0 ;
foreach ( $freetime as $ft )
{
2015-06-25 22:35:24 +02:00
$adaybegin = $this -> bo -> date2array ( $ft [ 'start' ]);
$adaybegin [ 'hour' ] = $adaybegin [ 'minute' ] = $adaybegin [ 'second' ] = 0 ;
unset ( $adaybegin [ 'raw' ]);
$daybegin = $this -> bo -> date2ts ( $adaybegin );
2008-05-08 00:12:25 +02:00
2004-10-08 00:11:18 +02:00
for ( $t = $daybegin ; $t < $ft [ 'end' ]; $t += DAY_s , $daybegin += DAY_s )
{
$dow = date ( 'w' , $daybegin + DAY_s / 2 ); // 0=Sun, .., 6=Sat
$mcal_dow = pow ( 2 , $dow );
if ( ! ( $weekdays & $mcal_dow ))
{
2004-12-12 13:31:41 +01:00
//echo "wrong day of week $dow<br>\n";
2004-10-08 00:11:18 +02:00
continue ; // wrong day of week
}
$start = $t < $ft [ 'start' ] ? $ft [ 'start' ] : $t ;
2008-05-08 00:12:25 +02:00
2004-10-08 00:11:18 +02:00
if ( $start - $daybegin < $start_time * HOUR_s ) // start earlier then start_time
{
$start = $daybegin + $start_time * HOUR_s ;
}
// if end_time given use it, else the original slot's end
$end = $end_time ? $daybegin + $end_time * HOUR_s : $ft [ 'end' ];
if ( $end > $ft [ 'end' ]) $end = $ft [ 'end' ];
// slot to small for duration
if ( $end - $start < $duration )
{
2004-12-12 13:31:41 +01:00
//echo "slot to small for duration=$duration<br>\n";
2004-10-08 00:11:18 +02:00
continue ;
}
$freetime_daywise [ ++ $n ] = array (
'start' => $start ,
'end' => $end ,
);
$times = array ();
2004-12-12 13:31:41 +01:00
for ( $s = $start ; $s + $duration <= $end && $s < $daybegin + DAY_s ; $s += 60 * $this -> cal_prefs [ 'interval' ])
2004-10-08 00:11:18 +02:00
{
$e = $s + $duration ;
$end_date = $e - $daybegin > DAY_s ? lang ( date ( 'l' , $e )) . ' ' . date ( $this -> common_prefs [ 'dateformat' ], $e ) . ' ' : '' ;
$times [ $s ] = date ( $time_format , $s ) . ' - ' . $end_date . date ( $time_format , $e );
}
2013-10-31 15:51:19 +01:00
$sel_options [ $n . 'start' ] = $times ;
2004-10-08 00:11:18 +02:00
}
}
return $freetime_daywise ;
}
2008-05-08 00:12:25 +02:00
2005-11-09 00:15:14 +01:00
/**
* Export events as vCalendar version 2.0 files ( iCal )
*
2014-05-27 17:02:56 +02:00
* @ param int | array $content numeric cal_id or submitted content from etempalte :: exec
* @ param boolean $return_error should an error - msg be returned or a regular page with it generated ( default )
2005-11-09 00:15:14 +01:00
* @ return string error - msg if $return_error
*/
function export ( $content = 0 , $return_error = false )
{
2009-02-25 11:55:38 +01:00
$boical = new calendar_ical ();
#error_log(__METHOD__.print_r($content,true));
2005-11-09 00:15:14 +01:00
if ( is_numeric ( $cal_id = $content ? $content : $_REQUEST [ 'cal_id' ]))
{
2009-02-25 11:55:38 +01:00
if ( ! ( $ical =& $boical -> exportVCal ( array ( $cal_id ), '2.0' , 'PUBLISH' , false )))
2005-11-09 00:15:14 +01:00
{
$msg = lang ( 'Permission denied' );
2008-05-08 00:12:25 +02:00
2005-11-09 00:15:14 +01:00
if ( $return_error ) return $msg ;
}
else
{
2009-10-12 21:16:42 +02:00
html :: content_header ( 'event.ics' , 'text/calendar' , bytes ( $ical ));
2005-11-09 00:15:14 +01:00
echo $ical ;
2009-10-12 21:16:42 +02:00
common :: egw_exit ();
2005-11-09 00:15:14 +01:00
}
}
if ( is_array ( $content ))
{
$events =& $this -> bo -> search ( array (
'start' => $content [ 'start' ],
'end' => $content [ 'end' ],
'enum_recuring' => false ,
'daywise' => false ,
'owner' => $this -> owner ,
'date_format' => 'server' , // timestamp in server time for boical class
));
if ( ! $events )
{
$msg = lang ( 'No events found' );
}
else
{
2009-02-25 11:55:38 +01:00
$ical =& $boical -> exportVCal ( $events , '2.0' , 'PUBLISH' , false );
2009-10-12 21:16:42 +02:00
html :: content_header ( $content [ 'file' ] ? $content [ 'file' ] : 'event.ics' , 'text/calendar' , bytes ( $ical ));
2005-11-09 00:15:14 +01:00
echo $ical ;
2009-10-12 21:16:42 +02:00
common :: egw_exit ();
2005-11-09 00:15:14 +01:00
}
}
if ( ! is_array ( $content ))
{
$content = array (
'start' => $this -> bo -> date2ts ( $_REQUEST [ 'start' ] ? $_REQUEST [ 'start' ] : $this -> date ),
'end' => $this -> bo -> date2ts ( $_REQUEST [ 'end' ] ? $_REQUEST [ 'end' ] : $this -> date ),
'file' => 'event.ics' ,
'version' => '2.0' ,
);
}
$content [ 'msg' ] = $msg ;
2008-05-08 00:12:25 +02:00
2005-11-09 00:15:14 +01:00
$GLOBALS [ 'egw_info' ][ 'flags' ][ 'app_header' ] = lang ( 'calendar' ) . ' - ' . lang ( 'iCal Export' );
2013-10-31 15:51:19 +01:00
$etpl = new etemplate_new ( 'calendar.export' );
2008-06-07 19:45:33 +02:00
$etpl -> exec ( 'calendar.calendar_uiforms.export' , $content );
2005-11-09 00:15:14 +01:00
}
2008-05-08 00:12:25 +02:00
2005-11-09 00:15:14 +01:00
/**
* Import events as vCalendar version 2.0 files ( iCal )
*
2014-05-27 17:02:56 +02:00
* @ param array $content submitted content from etempalte :: exec
2005-11-09 00:15:14 +01:00
*/
function import ( $content = null )
{
if ( is_array ( $content ))
{
if ( is_array ( $content [ 'ical_file' ]) && is_uploaded_file ( $content [ 'ical_file' ][ 'tmp_name' ]))
{
2010-04-14 12:19:41 +02:00
@ set_time_limit ( 0 ); // try switching execution time limit off
$start = microtime ( true );
$calendar_ical = new calendar_ical ;
2010-05-21 08:18:52 +02:00
$calendar_ical -> setSupportedFields ( 'file' , '' );
2010-04-14 12:19:41 +02:00
if ( ! $calendar_ical -> importVCal ( $f = fopen ( $content [ 'ical_file' ][ 'tmp_name' ], 'r' )))
2005-11-09 00:15:14 +01:00
{
$msg = lang ( 'Error: importing the iCal' );
}
else
{
2010-04-14 12:19:41 +02:00
$msg = lang ( 'iCal successful imported' ) . ' ' . lang ( '(%1 events in %2 seconds)' ,
$calendar_ical -> events_imported , number_format ( microtime ( true ) - $start , 1 ));
2005-11-09 00:15:14 +01:00
}
2010-04-14 12:19:41 +02:00
if ( $f ) fclose ( $f );
2005-11-09 00:15:14 +01:00
}
else
{
$msg = lang ( 'You need to select an iCal file first' );
}
}
$GLOBALS [ 'egw_info' ][ 'flags' ][ 'app_header' ] = lang ( 'calendar' ) . ' - ' . lang ( 'iCal Import' );
2013-10-31 15:51:19 +01:00
$etpl = new etemplate_new ( 'calendar.import' );
2008-05-08 00:12:25 +02:00
2015-06-25 22:35:24 +02:00
$etpl -> exec ( 'calendar.calendar_uiforms.import' , array (
'msg' => $msg ,
));
2005-11-09 00:15:14 +01:00
}
2009-12-03 19:24:19 +01:00
/**
* Edit category ACL ( admin only )
*
2015-06-25 22:35:24 +02:00
* @ param array $_content
2009-12-03 19:24:19 +01:00
*/
2015-06-25 22:35:24 +02:00
function cat_acl ( array $_content = null )
2009-12-03 19:24:19 +01:00
{
if ( ! $GLOBALS [ 'egw_info' ][ 'user' ][ 'apps' ][ 'admin' ])
{
throw new egw_exception_no_permission_admin ();
}
2015-06-25 22:35:24 +02:00
if ( $_content )
2009-12-03 19:24:19 +01:00
{
2015-06-25 22:35:24 +02:00
list ( $button ) = each ( $_content [ 'button' ]);
unset ( $_content [ 'button' ]);
2009-12-03 19:24:19 +01:00
if ( $button != 'cancel' ) // store changed acl
{
2015-06-25 22:35:24 +02:00
foreach ( $_content as $data )
2009-12-03 19:24:19 +01:00
{
if ( ! ( $cat_id = $data [ 'cat_id' ])) continue ;
foreach ( array_merge (( array ) $data [ 'add' ],( array ) $data [ 'status' ], array_keys (( array ) $data [ 'old' ])) as $account_id )
{
$rights = 0 ;
if ( in_array ( $account_id ,( array ) $data [ 'add' ])) $rights |= calendar_boupdate :: CAT_ACL_ADD ;
if ( in_array ( $account_id ,( array ) $data [ 'status' ])) $rights |= calendar_boupdate :: CAT_ACL_STATUS ;
if ( $account_id ) $this -> bo -> set_cat_rights ( $cat_id , $account_id , $rights );
}
}
}
if ( $button != 'apply' ) // end dialog
{
2014-09-22 17:25:23 +02:00
egw :: redirect_link ( '/index.php' , array (
'menuaction' => 'admin.admin_ui.index' ,
'ajax' => 'true'
), 'admin' );
2009-12-03 19:24:19 +01:00
}
}
2014-07-15 17:18:06 +02:00
$content = $preserv = array ();
2009-12-03 19:24:19 +01:00
$n = 1 ;
foreach ( $this -> bo -> get_cat_rights () as $Lcat_id => $data )
{
2014-07-03 11:10:11 +02:00
$cat_id = substr ( $Lcat_id , 1 );
2009-12-03 19:24:19 +01:00
$row = array (
'cat_id' => $cat_id ,
'add' => array (),
'status' => array (),
);
foreach ( $data as $account_id => $rights )
{
if ( $rights & calendar_boupdate :: CAT_ACL_ADD ) $row [ 'add' ][] = $account_id ;
if ( $rights & calendar_boupdate :: CAT_ACL_STATUS ) $row [ 'status' ][] = $account_id ;
}
2014-07-15 17:18:06 +02:00
$content [ $n ] = $row ;
$preserv [ $n ] = array (
2009-12-03 19:24:19 +01:00
'cat_id' => $cat_id ,
'old' => $data ,
);
$readonlys [ $n . '[cat_id]' ] = true ;
++ $n ;
}
// add empty row for new entries
2014-07-15 17:18:06 +02:00
$content [] = array ( 'cat_id' => '' );
2009-12-03 19:24:19 +01:00
$GLOBALS [ 'egw_info' ][ 'flags' ][ 'app_header' ] = lang ( 'Calendar' ) . ' - ' . lang ( 'Category ACL' );
2013-10-31 15:51:19 +01:00
$tmp = new etemplate_new ( 'calendar.cat_acl' );
2015-08-12 18:37:02 +02:00
$GLOBALS [ 'egw_info' ][ 'flags' ][ 'nonavbar' ] = 1 ;
2009-12-03 19:24:19 +01:00
$tmp -> exec ( 'calendar.calendar_uiforms.cat_acl' , $content , null , $readonlys , $preserv );
}
2010-02-12 21:18:45 +01:00
/**
* Set up the required fields to get the history tab
*/
2011-04-08 16:21:23 +02:00
public function setup_history ( & $content , & $sel_options )
{
2010-02-12 21:18:45 +01:00
$status = 'history_status' ;
$content [ 'history' ] = array (
'id' => $content [ 'id' ],
'app' => 'calendar' ,
2011-08-04 16:00:15 +02:00
'status-widgets' => array (
'owner' => 'select-account' ,
'creator' => 'select-account' ,
'category' => 'select-cat' ,
'non_blocking' => array ( '' => lang ( 'No' ), 1 => lang ( 'Yes' )),
'public' => array ( '' => lang ( 'No' ), 1 => lang ( 'Yes' )),
2010-02-24 16:05:00 +01:00
2011-08-04 16:00:15 +02:00
'start' => 'date-time' ,
'end' => 'date-time' ,
2015-05-26 20:34:03 +02:00
'deleted' => 'date-time' ,
2011-08-04 16:00:15 +02:00
'tz_id' => 'select-timezone' ,
2010-02-12 21:18:45 +01:00
// Participants
'participants' => array (
'select-account' ,
$sel_options [ 'status' ],
$sel_options [ 'role' ]
),
'participants-c' => array (
'link:addressbook' ,
$sel_options [ 'status' ],
'label' ,
$sel_options [ 'role' ]
),
2011-08-04 16:00:15 +02:00
'participants-r' => array (
'link:resources' ,
$sel_options [ 'status' ],
'label' ,
$sel_options [ 'role' ]
),
2010-02-12 21:18:45 +01:00
),
);
// Get participants for only this one, if it's recurring. The date is on the end of the value.
2011-08-04 16:00:15 +02:00
if ( $content [ 'recur_type' ] || $content [ 'recurrence' ])
{
2010-02-12 21:18:45 +01:00
$content [ 'history' ][ 'filter' ] = array (
' ( history_status NOT LIKE \ ' participants % \ ' OR ( history_status LIKE \ ' participants % \ ' AND (
2010-02-24 16:05:00 +01:00
history_new_value LIKE \ '%' . bo_tracking :: ONE2N_SEPERATOR . $content [ 'recurrence' ] . ' \ ' OR
2010-02-12 21:18:45 +01:00
history_old_value LIKE \ '%' . bo_tracking :: ONE2N_SEPERATOR . $content [ 'recurrence' ] . '\')))'
);
}
2010-02-24 16:05:00 +01:00
2010-02-12 21:18:45 +01:00
// Translate labels
$tracking = new calendar_tracking ();
2011-08-04 16:00:15 +02:00
foreach ( $tracking -> field2label as $field => $label )
{
2010-02-12 21:18:45 +01:00
$sel_options [ $status ][ $field ] = lang ( $label );
}
2011-04-20 08:22:29 +02:00
// custom fields are now "understood" directly by historylog widget
2010-02-12 21:18:45 +01:00
}
2014-02-19 18:48:25 +01:00
/**
* moves an event to another date / time
*
2015-07-16 11:34:55 +02:00
* @ param string $_eventId id of the event which has to be moved
2014-02-19 18:48:25 +01:00
* @ param string $calendarOwner the owner of the calendar the event is in
* @ param string $targetDateTime the datetime where the event should be moved to , format : YYYYMMDD
2015-08-05 23:24:07 +02:00
* @ param string | string [] $targetOwner the owner of the target calendar
2014-02-19 18:48:25 +01:00
* @ param string $durationT the duration to support resizable calendar event
* @ return string XML response if no error occurs
*/
2015-07-16 11:34:55 +02:00
function ajax_moveEvent ( $_eventId , $calendarOwner , $targetDateTime , $targetOwner , $durationT = null )
2014-02-19 18:48:25 +01:00
{
// we do not allow dragging into another users calendar ATM
2015-07-22 01:45:38 +02:00
if ( $targetOwner < 0 )
{
2015-08-04 16:26:00 +02:00
$targetOwner = array ( $targetOwner );
2015-07-22 01:45:38 +02:00
}
2015-08-05 23:24:07 +02:00
if ( $targetOwner == 0 || is_array ( $targetOwner ) && $targetOwner [ 0 ] == 0 )
{
$targetOwner = $calendarOwner ;
}
2015-07-22 01:45:38 +02:00
if ( $calendarOwner !== $targetOwner && ! is_array ( $targetOwner ))
2014-02-19 18:48:25 +01:00
{
return false ;
}
2015-07-22 01:45:38 +02:00
// But you may be viewing multiple users, or a group calendar and
// dragging your event
if ( is_array ( $targetOwner ) && ! in_array ( $calendarOwner , $targetOwner ))
{
$return = true ;
foreach ( $targetOwner as $owner )
{
if ( $owner < 0 && in_array ( $calendarOwner , $GLOBALS [ 'egw' ] -> accounts -> members ( $owner , true )))
{
$return = false ;
break ;
}
}
if ( $return ) return ;
}
2015-07-16 11:34:55 +02:00
list ( $eventId , $date ) = explode ( ':' , $_eventId );
2014-02-19 18:48:25 +01:00
$old_event = $event = $this -> bo -> read ( $eventId );
if ( ! $durationT )
{
$duration = $event [ 'end' ] - $event [ 'start' ];
}
else
{
$duration = $durationT ;
}
2015-06-10 23:51:28 +02:00
// If we have a recuring event for a particular day, make an exception
if ( $event [ 'recur_type' ] != MCAL_RECUR_NONE && $date )
{
2015-07-16 11:34:55 +02:00
$d = new egw_time ( $date , egw_time :: $user_timezone );
2015-06-10 23:51:28 +02:00
if ( ! empty ( $event [ 'whole_day' ]))
{
2015-07-16 11:34:55 +02:00
$d =& $this -> bo -> so -> startOfDay ( $d );
$d -> setUser ();
2015-06-10 23:51:28 +02:00
}
2015-07-16 11:34:55 +02:00
$event = $this -> bo -> read ( $eventId , $d , true );
$preserv [ 'actual_date' ] = $d ; // remember the date clicked
2015-06-10 23:51:28 +02:00
// For DnD, always create an exception
$this -> _create_exception ( $event , $preserv );
unset ( $event [ 'id' ]);
2015-07-16 11:34:55 +02:00
$date = $d -> format ( 'ts' );
2015-06-10 23:51:28 +02:00
}
2014-02-19 18:48:25 +01:00
$event [ 'start' ] = $this -> bo -> date2ts ( $targetDateTime );
$event [ 'end' ] = $event [ 'start' ] + $duration ;
$status_reset_to_unknown = false ;
$sameday = ( date ( 'Ymd' , $old_event [ 'start' ]) == date ( 'Ymd' , $event [ 'start' ]));
foreach (( array ) $event [ 'participants' ] as $uid => $status )
{
2015-06-25 22:35:24 +02:00
$q = $r = null ;
2014-02-19 18:48:25 +01:00
calendar_so :: split_status ( $status , $q , $r );
if ( $uid [ 0 ] != 'c' && $uid [ 0 ] != 'e' && $uid != $this -> bo -> user && $status != 'U' )
{
$preferences = CreateObject ( 'phpgwapi.preferences' , $uid );
$part_prefs = $preferences -> read_repository ();
switch ( $part_prefs [ 'calendar' ][ 'reset_stati' ])
{
case 'no' :
break ;
case 'startday' :
if ( $sameday ) break ;
default :
$status_reset_to_unknown = true ;
$event [ 'participants' ][ $uid ] = calendar_so :: combine_status ( 'U' , $q , $r );
// todo: report reset status to user
}
}
}
2015-07-22 01:45:38 +02:00
$message = false ;
$conflicts = $this -> bo -> update ( $event , false , true , false , true , $message );
2014-02-19 18:48:25 +01:00
$response = egw_json_response :: get ();
2015-07-22 01:45:38 +02:00
if ( ! is_array ( $conflicts ) && $conflicts )
2014-02-19 18:48:25 +01:00
{
2015-06-10 23:51:28 +02:00
// Directly update stored data. If event is still visible, it will
// be notified & update itself.
$this -> to_client ( $event );
$response -> call ( 'egw.dataStoreUID' , 'calendar::' . $event [ 'id' ] . ( $date ? ':' . $date : '' ), $event );
2015-07-22 01:45:38 +02:00
if ( ! $sameday )
{
$response -> call ( 'egw.refresh' , '' , 'calendar' , $event [ 'id' ], 'update' );
}
2014-02-19 18:48:25 +01:00
}
2015-07-22 01:45:38 +02:00
else if ( $conflicts )
2014-02-19 18:48:25 +01:00
{
$response -> call (
'egw_openWindowCentered2' ,
$GLOBALS [ 'egw_info' ][ 'server' ][ 'webserver_url' ] . ' / index . php ? menuaction = calendar . calendar_uiforms . edit
& cal_id = '.$event[' id ' ]
. '&start=' . $event [ 'start' ]
. '&end=' . $event [ 'end' ]
. '&non_interactive=true'
. '&cancel_needs_refresh=true' ,
'' , 750 , 410 );
}
2015-07-22 01:45:38 +02:00
else if ( $message )
{
$response -> call ( 'egw.message' , implode ( '<br />' , $message ));
}
2014-02-19 18:48:25 +01:00
if ( $status_reset_to_unknown )
{
foreach (( array ) $event [ 'participants' ] as $uid => $status )
{
if ( $uid [ 0 ] != 'c' && $uid [ 0 ] != 'e' && $uid != $this -> bo -> user )
{
calendar_so :: split_status ( $status , $q , $r );
$status = calendar_so :: combine_status ( 'U' , $q , $r );
$this -> bo -> set_status ( $event [ 'id' ], $uid , $status , 0 , true );
}
}
}
}
2015-05-26 20:34:03 +02:00
2015-07-01 00:26:59 +02:00
/**
* Change the status via ajax
2015-07-16 11:34:55 +02:00
* @ param string $_eventId
* @ param integer $uid
2015-07-01 00:26:59 +02:00
* @ param string $status
*/
2015-07-16 11:34:55 +02:00
function ajax_status ( $_eventId , $uid , $status )
2015-07-01 00:26:59 +02:00
{
2015-07-16 11:34:55 +02:00
list ( $eventId , $date ) = explode ( ':' , $_eventId );
$event = $this -> bo -> read ( $eventId );
2015-07-01 00:26:59 +02:00
// If we have a recuring event for a particular day, make an exception
if ( $event [ 'recur_type' ] != MCAL_RECUR_NONE && $date )
{
2015-07-16 11:34:55 +02:00
$d = new egw_time ( $date , egw_time :: $user_timezone );
2015-07-01 00:26:59 +02:00
if ( ! empty ( $event [ 'whole_day' ]))
{
2015-07-16 11:34:55 +02:00
$d =& $this -> bo -> so -> startOfDay ( $date );
$d -> setUser ();
2015-07-01 00:26:59 +02:00
}
2015-07-16 11:34:55 +02:00
$event = $this -> bo -> read ( $eventId , $d , true );
$preserv [ 'actual_date' ] = $d ; // remember the date clicked
2015-07-01 00:26:59 +02:00
// For DnD, always create an exception
$this -> _create_exception ( $event , $preserv );
unset ( $event [ 'id' ]);
2015-07-16 11:34:55 +02:00
$date = $d -> format ( 'ts' );
2015-07-01 00:26:59 +02:00
}
if ( $event [ 'participants' ][ $uid ])
{
$q = $r = null ;
calendar_so :: split_status ( $event [ 'participants' ][ $uid ], $q , $r );
$event [ 'participants' ][ $uid ] = $status = calendar_so :: combine_status ( $status , $q , $r );
$this -> bo -> set_status ( $event [ 'id' ], $uid , $status , 0 , true );
}
$conflicts = $this -> bo -> update ( $event );
$response = egw_json_response :: get ();
if ( ! is_array ( $conflicts ))
{
// Directly update stored data. If event is still visible, it will
// be notified & update itself.
$this -> to_client ( $event );
$response -> call ( 'egw.dataStoreUID' , 'calendar::' . $event [ 'id' ] . ( $date ? ':' . $date : '' ), $event );
}
else
{
$response -> call (
'egw_openWindowCentered2' ,
$GLOBALS [ 'egw_info' ][ 'server' ][ 'webserver_url' ] . ' / index . php ? menuaction = calendar . calendar_uiforms . edit
& cal_id = '.$event[' id ' ]
. '&start=' . $event [ 'start' ]
. '&end=' . $event [ 'end' ]
. '&non_interactive=true'
. '&cancel_needs_refresh=true' ,
'' , 750 , 410 );
}
}
2015-07-16 11:34:55 +02:00
2015-07-15 18:29:10 +02:00
/**
* Deletes an event
*/
public function ajax_delete ( $eventId )
{
list ( $eventId , $date ) = explode ( ':' , $eventId );
$event = $this -> bo -> read ( $eventId );
$response = egw_json_response :: get ();
if ( $this -> bo -> delete ( $event [ 'id' ], ( int ) $date ))
{
if ( $event [ 'recur_type' ] != MCAL_RECUR_NONE && ! $date )
{
$msg = lang ( 'Series deleted' );
}
else
{
$msg = lang ( 'Event deleted' );
}
$response -> apply ( 'egw.refresh' , Array ( $msg , 'calendar' , $eventId , 'delete' ));
}
else
{
$response -> apply ( 'egw.message' , lang ( 'Error' ), 'error' );
}
}
2015-07-16 12:05:18 +02:00
2015-04-15 13:23:59 +02:00
/**
* imports a mail as Calendar
*
2015-04-15 17:55:18 +02:00
* @ param array $mailContent = null mail content
2015-04-15 13:23:59 +02:00
* @ return array
*/
2015-04-15 17:55:18 +02:00
function mail_import ( array $mailContent = null )
2015-04-15 13:23:59 +02:00
{
2015-04-15 17:55:18 +02:00
// It would get called from compose as a popup with egw_data
if ( ! is_array ( $mailContent ) && ( $_GET [ 'egw_data' ]))
{
// get raw mail data
egw_link :: get_data ( $_GET [ 'egw_data' ]);
return false ;
}
2015-05-26 20:34:03 +02:00
2015-04-15 13:23:59 +02:00
if ( is_array ( $mailContent ))
{
2015-04-23 15:47:12 +02:00
// Addressbook
$AB = new addressbook_bo ();
$accounts = array ( 0 => $GLOBALS [ 'egw_info' ][ 'user' ][ 'account_id' ]);
2015-05-26 20:34:03 +02:00
2015-04-15 13:23:59 +02:00
$participants [ 0 ] = array (
'uid' => $GLOBALS [ 'egw_info' ][ 'user' ][ 'account_id' ],
'delete_id' => $GLOBALS [ 'egw_info' ][ 'user' ][ 'account_id' ],
'status' => 'A' ,
'old_status' => 'A' ,
'app' => 'User' ,
'role' => 'REQ-PARTICIPANT'
);
foreach ( $mailContent [ 'addresses' ] as $address )
{
2015-04-23 15:47:12 +02:00
// Get available contacts from the email
2015-05-04 14:19:33 +02:00
$contacts = $AB -> search ( array (
2015-04-23 15:47:12 +02:00
'email' => $address [ 'email' ],
'email_home' => $address [ 'email' ]
), 'contact_id,contact_email,contact_email_home,egw_addressbook.account_id as account_id' , '' , '' , '' , false , 'OR' , false , array ( 'owner' => 0 ), '' , false );
2015-05-04 14:19:33 +02:00
if ( is_array ( $contacts ))
2015-04-23 15:47:12 +02:00
{
2015-05-04 14:19:33 +02:00
foreach ( $contacts as $account )
2015-04-23 15:47:12 +02:00
{
$accounts [] = $account [ 'account_id' ];
}
}
else
{
$participants [] = array (
'app' => 'email' ,
'uid' => 'e' . $address [ 'email' ],
'status' => 'U' ,
'old_status' => 'U'
);
}
2015-04-15 13:23:59 +02:00
}
2015-04-23 15:47:12 +02:00
$participants = array_merge ( $participants , array (
" account " => $accounts ,
" role " => " REQ-PARTICIPANT " ,
" add " => " pressed "
));
2015-05-26 20:34:03 +02:00
2015-04-15 13:23:59 +02:00
// Prepare calendar event draft
$event = array (
'title' => $mailContent [ 'subject' ],
'description' => $mailContent [ 'message' ],
'participants' => $participants ,
'link_to' => array (
'to_app' => 'calendar' ,
'to_id' => 0 ,
),
2015-05-04 14:19:33 +02:00
'start' => $mailContent [ 'date' ],
'duration' => 60 * $this -> cal_prefs [ 'interval' ]
2015-04-15 13:23:59 +02:00
);
2015-05-26 20:34:03 +02:00
2015-04-15 13:23:59 +02:00
if ( is_array ( $mailContent [ 'attachments' ]))
{
foreach ( $mailContent [ 'attachments' ] as $attachment )
{
if ( $attachment [ 'egw_data' ])
{
egw_link :: link ( 'calendar' , $event [ 'link_to' ][ 'to_id' ], egw_link :: DATA_APPNAME , $attachment );
}
2015-08-27 12:12:55 +02:00
else if ( is_readable ( $attachment [ 'tmp_name' ]) ||
( egw_vfs :: is_readable ( $attachment [ 'tmp_name' ]) && parse_url ( $attachment [ 'tmp_name' ], PHP_URL_SCHEME ) === 'vfs' ))
2015-04-17 11:39:22 +02:00
{
egw_link :: link ( 'calendar' , $event [ 'link_to' ][ 'to_id' ], 'file' , $attachment );
}
2015-04-15 13:23:59 +02:00
}
}
}
else
{
egw_framework :: window_close ( lang ( 'No content found to show up as calendar entry.' ));
}
2015-05-26 20:34:03 +02:00
2015-04-15 13:23:59 +02:00
return $this -> process_edit ( $event );
}
2004-10-08 00:11:18 +02:00
}