2004-08-01 17:36:04 +02:00
< ? php
2007-03-09 12:39:47 +01:00
/**
* eGroupWare - Calendar ' s buisness - object - access only
*
* @ link http :// www . egroupware . org
* @ package calendar
* @ author Ralf Becker < RalfBecker - AT - outdoor - training . de >
* @ copyright ( c ) 2004 - 7 by RalfBecker - At - outdoor - training . de
* @ license http :// opensource . org / licenses / gpl - license . php GPL - GNU General Public License
2008-05-08 17:02:35 +02:00
* @ version $Id $
2007-03-09 12:39:47 +01:00
*/
2004-08-01 17:36:04 +02:00
2005-11-09 00:15:14 +01:00
require_once ( EGW_INCLUDE_ROOT . '/calendar/inc/class.socal.inc.php' );
if ( ! defined ( 'ACL_TYPE_IDENTIFER' )) // used to mark ACL-values for the debug_message methode
{
define ( 'ACL_TYPE_IDENTIFER' , '***ACL***' );
}
define ( 'HOUR_s' , 60 * 60 );
define ( 'DAY_s' , 24 * HOUR_s );
define ( 'WEEK_s' , 7 * DAY_s );
2007-06-19 19:04:58 +02:00
/**
* Gives read access to the calendar , but all events the user is not participating are private !
* Used be the addressbook .
*/
define ( 'EGW_ACL_READ_FOR_PARTICIPANTS' , EGW_ACL_CUSTOM_1 );
2008-03-21 21:30:19 +01:00
require_once ( EGW_INCLUDE_ROOT . '/calendar/inc/class.socal.inc.php' );
2004-08-01 17:36:04 +02:00
/**
2005-11-09 00:15:14 +01:00
* Class to access all calendar data
2004-08-01 17:36:04 +02:00
*
2005-11-09 00:15:14 +01:00
* For updating calendar data look at the bocalupdate class , which extends this class .
2004-08-01 17:36:04 +02:00
*
* 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
2005-11-09 00:15:14 +01:00
* SO operates only in server - time
2004-08-01 17:36:04 +02:00
*
* As this BO class deals with dates / times of several types and timezone , each variable should have a postfix
* appended , telling with type it is : _s = seconds , _su = secs in user - time , _ss = secs in server - time , _h = hours
*
* All new BO code ( should be true for eGW in general ) NEVER use any $_REQUEST ( $_POST or $_GET ) vars itself .
2005-11-09 00:15:14 +01:00
* Nor does it store the state of any UI - elements ( eg . cat - id selectbox ) . All this is the task of the UI class ( es ) !!!
2004-08-01 17:36:04 +02:00
*
2005-11-09 00:15:14 +01:00
* All permanent debug messages of the calendar - code should done via the debug - message method of this class ! ! !
2004-08-01 17:36:04 +02:00
*/
class bocal
{
/**
* @ var int $debug name of method to debug or level of debug - messages :
* False = Off as higher as more messages you get ; - )
* 1 = function - calls incl . parameters to general functions like search , read , write , delete
* 2 = function - calls to exported helper - functions like check_perms
* 4 = function - calls to exported conversation - functions like date2ts , date2array , ...
* 5 = function - calls to private functions
*/
2004-11-07 15:38:00 +01:00
var $debug = false ;
2004-08-01 17:36:04 +02:00
/**
* @ var int $tz_offset_s offset in secconds between user and server - time ,
* it need to be add to a server - time to get the user - time or substracted from a user - time to get the server - time
*/
var $tz_offset_s ;
/**
* @ var int $now_su timestamp of actual user - time
*/
var $now_su ;
/**
* @ var array $cal_prefs calendar - specific prefs
*/
var $cal_prefs ;
/**
* @ var array $common_prefs common preferences
*/
var $common_prefs ;
/**
* @ var int $user nummerical id of the current user - id
*/
var $user = 0 ;
/**
* @ var array $grants grants of the current user , array with user - id / ored - ACL - rights pairs
*/
var $grants = array ();
/**
* @ var array $verbose_status translated 1 - char status values to a verbose name , run through lang () by the constructor
*/
var $verbose_status = array (
'A' => 'Accepted' ,
'R' => 'Rejected' ,
'T' => 'Tentative' ,
'U' => 'No Response' ,
2006-03-16 19:03:43 +01:00
'G' => 'Group invitation' ,
2004-08-01 17:36:04 +02:00
);
2005-11-09 00:15:14 +01:00
/**
* @ var array recur_types translates MCAL recur - types to verbose labels
*/
var $recur_types = Array (
MCAL_RECUR_NONE => 'None' ,
MCAL_RECUR_DAILY => 'Daily' ,
MCAL_RECUR_WEEKLY => 'Weekly' ,
MCAL_RECUR_MONTHLY_WDAY => 'Monthly (by day)' ,
MCAL_RECUR_MONTHLY_MDAY => 'Monthly (by date)' ,
MCAL_RECUR_YEARLY => 'Yearly'
);
/**
* @ var array recur_days translates MCAL recur - days to verbose labels
*/
var $recur_days = array (
MCAL_M_MONDAY => 'Monday' ,
MCAL_M_TUESDAY => 'Tuesday' ,
MCAL_M_WEDNESDAY => 'Wednesday' ,
MCAL_M_THURSDAY => 'Thursday' ,
MCAL_M_FRIDAY => 'Friday' ,
MCAL_M_SATURDAY => 'Saturday' ,
MCAL_M_SUNDAY => 'Sunday' ,
);
/**
* @ var array $resources registered scheduling resources of the calendar ( gets chached in the session for performance reasons )
*/
var $resources ;
/**
* @ var array $cached_event here we do some caching to read single events only once
*/
2008-05-10 22:10:45 +02:00
protected static $cached_event = array ();
protected static $cached_event_date_format = false ;
2005-11-09 00:15:14 +01:00
/**
* @ var array $cached_holidays holidays plus birthdays ( gets cached in the session for performance reasons )
*/
var $cached_holidays ;
2006-12-22 20:51:56 +01:00
/**
* Instance of the socal class
*
* @ var socal
*/
var $so ;
/**
* Instance of the datetime class
*
* @ var egw_datetime
*/
var $datetime ;
2004-08-01 17:36:04 +02:00
/**
* Constructor
*/
function bocal ()
{
if ( $this -> debug > 0 ) $this -> debug_message ( 'bocal::bocal() started' , True , $param );
2008-05-08 17:02:35 +02:00
2008-03-21 21:30:19 +01:00
$this -> so = new socal ();
2008-03-22 10:23:14 +01:00
$this -> datetime = $GLOBALS [ 'egw' ] -> datetime ;
2004-08-01 17:36:04 +02:00
2005-11-09 00:15:14 +01:00
$this -> common_prefs =& $GLOBALS [ 'egw_info' ][ 'user' ][ 'preferences' ][ 'common' ];
$this -> cal_prefs =& $GLOBALS [ 'egw_info' ][ 'user' ][ 'preferences' ][ 'calendar' ];
2004-08-01 17:36:04 +02:00
$this -> tz_offset_s = $this -> datetime -> tz_offset ;
$this -> now_su = time () + $this -> tz_offset_s ;
2005-11-09 00:15:14 +01:00
$this -> user = $GLOBALS [ 'egw_info' ][ 'user' ][ 'account_id' ];
2004-08-01 17:36:04 +02:00
2005-11-09 00:15:14 +01:00
$this -> grants = $GLOBALS [ 'egw' ] -> acl -> get_grants ( 'calendar' );
2004-08-01 17:36:04 +02:00
2006-12-13 08:28:20 +01:00
foreach ( $this -> verbose_status as $status => $text )
{
$this -> verbose_status [ $status ] = lang ( $text );
}
2005-11-09 00:15:14 +01:00
if ( ! is_array ( $this -> resources = $GLOBALS [ 'egw' ] -> session -> appsession ( 'resources' , 'calendar' )))
{
$this -> resources = array ();
foreach ( $GLOBALS [ 'egw' ] -> hooks -> process ( 'calendar_resources' ) as $app => $data )
{
if ( $data && $data [ 'type' ])
{
$this -> resources [ $data [ 'type' ]] = $data + array ( 'app' => $app );
}
}
2008-05-08 17:02:35 +02:00
$this -> resources [ 'e' ] = array (
'type' => 'e' ,
'info' => 'bocal::email_info' ,
'app' => 'email' ,
);
2005-11-09 00:15:14 +01:00
$GLOBALS [ 'egw' ] -> session -> appsession ( 'resources' , 'calendar' , $this -> resources );
2008-05-08 17:02:35 +02:00
}
2005-11-09 00:15:14 +01:00
//echo "registered resources="; _debug_array($this->resources);
2008-03-21 21:30:19 +01:00
$this -> config = config :: read ( 'calendar' );
2004-08-01 17:36:04 +02:00
}
2008-05-08 17:02:35 +02:00
/**
* returns info about email addresses as participants
*
* @ param int / array $ids single contact - id or array of id ' s
* @ return array
*/
static function email_info ( $ids )
{
if ( ! $ids ) return null ;
$data = array ();
foreach ( ! is_array ( $ids ) ? array ( $ids ) : $ids as $id )
{
$email = $id ;
$name = '' ;
if ( preg_match ( '/^(.*) *<([a-z0-9_.@-]{8,})>$/i' , $email , $matches ))
{
$name = $matches [ 1 ];
$email = $matches [ 2 ];
}
$data [] = array (
'res_id' => $id ,
'email' => $email ,
'rights' => EGW_ACL_READ_FOR_PARTICIPANTS ,
'name' => $name ,
);
}
//echo "<p>email_info(".print_r($ids,true).")="; _debug_array($data);
return $data ;
}
2005-11-23 15:21:20 +01:00
/**
* Add group - members as participants with status 'G'
*
* @ param array $event event - array
* @ return int number of added participants
*/
function enum_groups ( & $event )
{
$added = 0 ;
foreach ( $event [ 'participants' ] as $uid => $status )
{
if ( is_numeric ( $uid ) && $GLOBALS [ 'egw' ] -> accounts -> get_type ( $uid ) == 'g' &&
( $members = $GLOBALS [ 'egw' ] -> accounts -> member ( $uid )))
{
foreach ( $members as $member )
{
$member = $member [ 'account_id' ];
if ( ! isset ( $event [ 'participants' ][ $member ]))
{
$event [ 'participants' ][ $member ] = 'G' ;
++ $added ;
}
}
}
}
return $added ;
}
2004-08-01 17:36:04 +02:00
/**
* Searches / lists calendar entries , including repeating ones
*
* @ param params array with the following keys
* start date startdate of the search / list , defaults to today
* end date enddate of the search / list , defaults to start + one day
* users mixed integer user - id or array of user - id ' s to use , defaults to the current user
* cat_id mixed category - id or array of cat - id ' s , defaults to all if unset , 0 or False
* Please note : only a single cat - id , will include all sub - cats ( if the common - pref 'cats_no_subs' is False )
2006-11-02 22:33:00 +01:00
* filter string filter - name , atm . 'all' or 'hideprivate'
2004-08-01 17:36:04 +02:00
* query string pattern so search for , if unset or empty all matching entries are returned ( no search )
* Please Note : a search never returns repeating events more then once AND does not honor start + end date !!!
* dayswise boolean on True it returns an array with YYYYMMDD strings as keys and an array with events
* ( events spanning multiple days are returned each day again ( ! )) otherwise it returns one array with
* the events ( default ), not honored in a search ==> always returns an array of events !
2005-11-09 00:15:14 +01:00
* date_format string date - formats : 'ts' = timestamp ( default ), 'array' = array , or string with format for date
* offset boolean / int false ( default ) to return all entries or integer offset to return only a limited result
* enum_recuring boolean if true or not set ( default ) or daywise is set , each recurence of a recuring events is returned ,
* otherwise the original recuring event ( with the first start - + enddate ) is returned
* num_rows int number of entries to return , default or if 0 , max_entries from the prefs
* order column - names plus optional DESC | ASC separted by comma
* show_rejected if set rejected invitation are shown only when true , otherwise it depends on the cal - pref or a running query
* ignore_acl if set and true no check_perms for a general EGW_ACL_READ grants is performed
2005-11-23 15:21:20 +01:00
* enum_groups boolean if set and true , group - members will be added as participants with status 'G'
2008-05-08 17:02:35 +02:00
* @ return array of events or array with YYYYMMDD strings / array of events pairs ( depending on $daywise param )
2006-03-05 11:26:03 +01:00
* or false if there are no read - grants from _any_ of the requested users
2004-08-01 17:36:04 +02:00
*/
2005-11-09 00:15:14 +01:00
function & search ( $params )
2004-08-01 17:36:04 +02:00
{
$params_in = $params ;
2008-05-08 17:02:35 +02:00
if ( ! isset ( $params [ 'users' ]) || ! $params [ 'users' ] ||
2006-10-11 20:52:39 +02:00
count ( $params [ 'users' ]) == 1 && isset ( $params [ 'users' ][ 0 ]) && ! $params [ 'users' ][ 0 ]) // null or '' casted to an array
2004-08-01 17:36:04 +02:00
{
2005-11-09 00:15:14 +01:00
// for a search use all account you have read grants from
$params [ 'users' ] = $params [ 'query' ] ? array_keys ( $this -> grants ) : $this -> user ;
2004-08-01 17:36:04 +02:00
}
if ( ! is_array ( $params [ 'users' ]))
{
2006-10-11 20:52:39 +02:00
$params [ 'users' ] = $params [ 'users' ] ? array ( $params [ 'users' ]) : array ();
2004-08-01 17:36:04 +02:00
}
// only query calendars of users, we have READ-grants from
$users = array ();
foreach ( $params [ 'users' ] as $user )
{
2007-06-19 19:04:58 +02:00
if ( $params [ 'ignore_acl' ] || $this -> check_perms ( EGW_ACL_READ | EGW_ACL_READ_FOR_PARTICIPANTS , 0 , $user ))
2004-08-01 17:36:04 +02:00
{
2006-10-11 20:52:39 +02:00
if ( $user && ! in_array ( $user , $users )) // already added?
2005-12-02 17:43:23 +01:00
{
$users [] = $user ;
}
2005-11-24 12:21:29 +01:00
}
elseif ( $GLOBALS [ 'egw' ] -> accounts -> get_type ( $user ) != 'g' )
{
continue ; // for non-groups (eg. users), we stop here if we have no read-rights
}
2006-03-05 11:26:03 +01:00
// the further code is only for real users
if ( ! is_numeric ( $user )) continue ;
2005-11-24 12:21:29 +01:00
// for groups we have to include the members
if ( $GLOBALS [ 'egw' ] -> accounts -> get_type ( $user ) == 'g' )
{
$members = $GLOBALS [ 'egw' ] -> accounts -> member ( $user );
if ( is_array ( $members ))
2005-11-09 00:15:14 +01:00
{
2005-11-24 12:21:29 +01:00
foreach ( $members as $member )
2005-11-09 00:15:14 +01:00
{
2005-11-24 12:21:29 +01:00
// use only members which gave the user a read-grant
2008-05-08 17:02:35 +02:00
if ( ! in_array ( $member [ 'account_id' ], $users ) &&
2005-11-24 12:21:29 +01:00
( $params [ 'ignore_acl' ] || $this -> check_perms ( EGW_ACL_READ , 0 , $member [ 'account_id' ])))
2005-11-09 00:15:14 +01:00
{
2005-11-24 12:21:29 +01:00
$users [] = $member [ 'account_id' ];
2005-11-09 00:15:14 +01:00
}
}
}
2005-11-24 12:21:29 +01:00
}
else // for users we have to include all the memberships, to get the group-events
{
$memberships = $GLOBALS [ 'egw' ] -> accounts -> membership ( $user );
if ( is_array ( $memberships ))
2005-11-23 15:21:20 +01:00
{
2005-11-24 12:21:29 +01:00
foreach ( $memberships as $group )
2005-11-23 15:21:20 +01:00
{
2005-11-24 12:21:29 +01:00
if ( ! in_array ( $group [ 'account_id' ], $users ))
2005-11-23 15:21:20 +01:00
{
2005-11-24 12:21:29 +01:00
$users [] = $group [ 'account_id' ];
2005-11-23 15:21:20 +01:00
}
}
}
2004-08-01 17:36:04 +02:00
}
}
2008-05-08 17:02:35 +02:00
// if we have no grants from the given user(s), we directly return no events / an empty array,
2005-11-09 00:15:14 +01:00
// as calling the so-layer without users would give the events of all users (!)
if ( ! count ( $users ))
{
2006-03-05 11:26:03 +01:00
return false ;
2005-11-09 00:15:14 +01:00
}
if ( isset ( $params [ 'start' ])) $start = $this -> date2ts ( $params [ 'start' ]);
if ( isset ( $params [ 'end' ]))
{
$end = $this -> date2ts ( $params [ 'end' ]);
$this -> check_move_horizont ( $end );
}
2004-08-01 17:36:04 +02:00
$daywise = ! isset ( $params [ 'daywise' ]) ? False : !! $params [ 'daywise' ];
2005-11-09 00:15:14 +01:00
$enum_recuring = $daywise || ! isset ( $params [ 'enum_recuring' ]) || !! $params [ 'enum_recuring' ];
2004-08-01 17:36:04 +02:00
$cat_id = isset ( $params [ 'cat_id' ]) ? $params [ 'cat_id' ] : 0 ;
$filter = isset ( $params [ 'filter' ]) ? $params [ 'filter' ] : 'all' ;
2005-11-09 00:15:14 +01:00
$offset = isset ( $params [ 'offset' ]) && $params [ 'offset' ] !== false ? ( int ) $params [ 'offset' ] : false ;
$show_rejected = isset ( $params [ 'show_rejected' ]) ? $params [ 'show_rejected' ] : $this -> cal_prefs [ 'show_rejected' ] || $params [ 'query' ];
2004-08-01 17:36:04 +02:00
if ( $this -> debug && ( $this -> debug > 1 || $this -> debug == 'search' ))
{
2005-11-09 00:15:14 +01:00
$this -> debug_message ( 'bocal::search(%1) start=%2, end=%3, daywise=%4, cat_id=%5, filter=%6, query=%7, offset=%8, num_rows=%9, order=%10, show_rejected=%11)' ,
True , $params , $start , $end , $daywise , $cat_id , $filter , $params [ 'query' ], $offset ,( int ) $params [ 'num_rows' ], $params [ 'order' ], $show_rejected );
2004-08-01 17:36:04 +02:00
}
2005-11-09 00:15:14 +01:00
// date2ts(,true) converts to server time, db2data converts again to user-time
$events =& $this -> so -> search ( isset ( $start ) ? $this -> date2ts ( $start , true ) : null , isset ( $end ) ? $this -> date2ts ( $end , true ) : null ,
$users , $cat_id , $filter , $params [ 'query' ], $offset ,( int ) $params [ 'num_rows' ], $params [ 'order' ], $show_rejected );
$this -> total = $this -> so -> total ;
$this -> db2data ( $events , isset ( $params [ 'date_format' ]) ? $params [ 'date_format' ] : 'ts' );
2008-05-08 17:02:35 +02:00
2006-12-29 09:45:36 +01:00
// socal::search() returns rejected group-invitations, as only the user not also the group is rejected
// as we cant remove them efficiantly in SQL, we kick them out here, but only if just one user is displayed
$remove_rejected_by_user = ! $show_rejected && count ( $params [ 'users' ]) == 1 ? $params [ 'users' ][ 0 ] : false ;
//echo "<p align=right>remove_rejected_by_user=$remove_rejected_by_user, show_rejected=$show_rejected, params[users]=".print_r($param['users'])."</p>\n";
2005-11-09 00:15:14 +01:00
foreach ( $events as $id => $event )
2004-08-01 17:36:04 +02:00
{
2006-12-29 09:45:36 +01:00
if ( $remove_rejected_by_user && $event [ 'participants' ][ $remove_rejected_by_user ] == 'R' )
{
unset ( $events [ $id ]); // remove the rejected event
2007-10-09 10:00:42 +02:00
$this -> total -- ;
2006-12-29 09:45:36 +01:00
continue ;
}
2005-11-23 15:21:20 +01:00
if ( $params [ 'enum_groups' ] && $this -> enum_groups ( $event ))
{
$events [ $id ] = $event ;
}
2006-11-02 22:33:00 +01:00
if ( ! $this -> check_perms ( EGW_ACL_READ , $event ) || ( ! $event [ 'public' ] && $filter == 'hideprivate' ))
2004-08-01 17:36:04 +02:00
{
2007-02-21 23:00:48 +01:00
if ( $params [ 'query' ])
{
unset ( $events [ $id ]);
$this -> total -- ;
continue ;
}
else
{
$this -> clear_private_infos ( $events [ $id ], $users );
}
2004-08-01 17:36:04 +02:00
}
}
2005-11-09 00:15:14 +01:00
if ( $daywise )
2004-08-01 17:36:04 +02:00
{
2005-11-09 00:15:14 +01:00
if ( $this -> debug && ( $this -> debug > 2 || $this -> debug == 'search' ))
{
$this -> debug_message ( 'socalendar::search daywise sorting from %1 to %2 of %3' , False , $start , $end , $events );
}
// create empty entries for each day in the reported time
for ( $ts = $start ; $ts <= $end ; $ts += DAY_s )
{
$daysEvents [ $this -> date2string ( $ts )] = array ();
}
foreach ( $events as $k => $event )
{
$e_start = max ( $this -> date2ts ( $event [ 'start' ]), $start );
// $event['end']['raw']-1 to allow events to end on a full hour/day without the need to enter it as minute=59
$e_end = min ( $this -> date2ts ( $event [ 'end' ]) - 1 , $end );
2004-08-01 17:36:04 +02:00
2005-11-09 00:15:14 +01:00
// add event to each day in the reported time
for ( $ts = $e_start ; $ts <= $e_end ; $ts += DAY_s )
{
$daysEvents [ $ymd = $this -> date2string ( $ts )][] =& $events [ $k ];
}
if ( $ymd != ( $last = $this -> date2string ( $e_end )))
{
$daysEvents [ $last ][] =& $events [ $k ];
2008-05-08 17:02:35 +02:00
}
2005-11-09 00:15:14 +01:00
}
$events =& $daysEvents ;
if ( $this -> debug && ( $this -> debug > 2 || $this -> debug == 'search' ))
2004-08-01 17:36:04 +02:00
{
2005-11-09 00:15:14 +01:00
$this -> debug_message ( 'socalendar::search daywise events=%1' , False , $events );
2004-08-01 17:36:04 +02:00
}
}
2005-11-09 00:15:14 +01:00
elseif ( ! $enum_recuring )
2004-08-01 17:36:04 +02:00
{
2005-11-09 00:15:14 +01:00
$recur_ids = array ();
foreach ( $events as $k => $event )
2004-08-01 17:36:04 +02:00
{
2005-11-09 00:15:14 +01:00
if ( $event [ 'recur_type' ] != MCAL_RECUR_NONE )
2004-08-01 17:36:04 +02:00
{
2005-11-09 00:15:14 +01:00
if ( ! in_array ( $event [ 'id' ], $recur_ids ))
2004-08-01 17:36:04 +02:00
{
2005-11-09 00:15:14 +01:00
$recur_ids [] = $event [ 'id' ];
2004-08-01 17:36:04 +02:00
}
2005-11-09 00:15:14 +01:00
unset ( $events [ $k ]);
2004-08-01 17:36:04 +02:00
}
}
2005-11-09 00:15:14 +01:00
if ( count ( $recur_ids ))
2005-02-10 01:13:37 +01:00
{
2005-12-02 10:46:03 +01:00
$events = array_merge ( $this -> read ( $recur_ids , null , false , $params [ 'date_format' ]), $events );
2005-02-10 01:13:37 +01:00
}
2005-11-09 00:15:14 +01:00
}
if ( $this -> debug && ( $this -> debug > 0 || $this -> debug == 'search' ))
{
$this -> debug_message ( 'bocal::search(%1)=%2' , True , $params , $events );
}
return $events ;
}
2008-05-08 17:02:35 +02:00
2005-11-09 00:15:14 +01:00
/**
* Clears all non - private info from a privat event
*
* That function only returns the infos allowed to be viewed by people without EGW_ACL_PRIVATE grants
*
* @ param array & $event
* @ param array $allowed_participants ids of the allowed participants , eg . the ones the search is over or eg . the owner of the calendar
*/
function clear_private_infos ( & $event , $allowed_participants = array ())
{
$event = array (
'id' => $event [ 'id' ],
'start' => $event [ 'start' ],
'end' => $event [ 'end' ],
'title' => lang ( 'private' ),
'participants' => array_intersect_key ( $event [ 'participants' ], array_flip ( $allowed_participants )),
'public' => 0 ,
2006-03-08 11:23:44 +01:00
'category' => $event [ 'category' ], // category is visible anyway, eg. by using planner by cat
'non_blocking' => $event [ 'non_blocking' ],
2005-11-09 00:15:14 +01:00
);
}
2008-05-08 17:02:35 +02:00
2005-11-09 00:15:14 +01:00
/**
* check and evtl . move the horizont ( maximum date for unlimited recuring events ) to a new date
*
* @ internal automaticaly called by search
* @ param mixed $new_horizont time to set the horizont to ( user - time )
*/
function check_move_horizont ( $new_horizont )
{
if (( int ) $this -> debug >= 2 || $this -> debug == 'check_move_horizont' )
{
$this -> debug_message ( 'bocal::check_move_horizont(%1) horizont=%2' , true , $new_horizont , $this -> config [ 'horizont' ]);
}
$new_horizont = $this -> date2ts ( $new_horizont , true ); // now we are in server-time, where this function operates
2008-05-08 17:02:35 +02:00
2007-12-20 20:53:06 +01:00
if ( $new_horizont > time () + 1000 * DAY_s ) // some user tries to "look" more then 1000 days in the future
{
if ( $this -> debug == 'check_move_horizont' ) $this -> debug_message ( 'bocal::check_move_horizont(%1) horizont=%2 new horizont more then 1000 days from now --> ignoring it' , true , $new_horizont , $this -> config [ 'horizont' ]);
return ;
}
2005-11-09 00:15:14 +01:00
if ( $new_horizont <= $this -> config [ 'horizont' ]) // no move necessary
{
if ( $this -> debug == 'check_move_horizont' ) $this -> debug_message ( 'bocal::check_move_horizont(%1) horizont=%2 is bigger ==> nothing to do' , true , $new_horizont , $this -> config [ 'horizont' ]);
return ;
2004-08-01 17:36:04 +02:00
}
2005-11-09 00:15:14 +01:00
if ( $new_horizont < time () + 31 * DAY_s )
2004-08-01 17:36:04 +02:00
{
2005-11-09 00:15:14 +01:00
$new_horizont = time () + 31 * DAY_s ;
2004-08-01 17:36:04 +02:00
}
2005-11-09 00:15:14 +01:00
$old_horizont = $this -> config [ 'horizont' ];
$this -> config [ 'horizont' ] = $new_horizont ;
// create further recurances for all recuring and not yet (at the old horizont) ended events
if (( $recuring = $this -> so -> unfinished_recuring ( $old_horizont )))
2004-08-01 17:36:04 +02:00
{
2005-11-09 00:15:14 +01:00
foreach ( $this -> read ( array_keys ( $recuring )) as $cal_id => $event )
2004-08-01 17:36:04 +02:00
{
2005-11-09 00:15:14 +01:00
if ( $this -> debug == 'check_move_horizont' )
{
$this -> debug_message ( 'bocal::check_move_horizont(%1): calling set_recurrences(%2,%3)' , true , $new_horizont , $event , $old_horizont );
}
// insert everything behind max(cal_start), which can be less then $old_horizont because of bugs in the past
$this -> set_recurrences ( $event , $recuring [ $cal_id ] + 1 + $this -> tz_offset_s ); // set_recurences operates in user-time!
2004-08-01 17:36:04 +02:00
}
2005-11-09 00:15:14 +01:00
}
// update the horizont
$config =& CreateObject ( 'phpgwapi.config' , 'calendar' );
$config -> save_value ( 'horizont' , $this -> config [ 'horizont' ], 'calendar' );
2008-05-08 17:02:35 +02:00
2005-11-09 00:15:14 +01:00
if ( $this -> debug == 'check_move_horizont' ) $this -> debug_message ( 'bocal::check_move_horizont(%1) new horizont=%2, exiting' , true , $new_horizont , $this -> config [ 'horizont' ]);
}
/**
* set all recurances for an event til the defined horizont $this -> config [ 'horizont' ]
*
* @ param array $event
* @ param mixed $start = 0 minimum start - time for new recurances or ! $start = since the start of the event
*/
function set_recurrences ( $event , $start = 0 )
{
if ( $this -> debug && (( int ) $this -> debug >= 2 || $this -> debug == 'set_recurrences' || $this -> debug == 'check_move_horizont' ))
{
$this -> debug_message ( 'bocal::set_recurrences(%1,%2)' , true , $event , $start );
}
2006-03-09 22:40:35 +01:00
// check if the caller gave the participants and if not read them from the DB
if ( ! isset ( $event [ 'participants' ]))
{
list (, $event_read ) = each ( $this -> so -> read ( $event [ 'id' ]));
$event [ 'participants' ] = $event_read [ 'participants' ];
}
2005-11-09 00:15:14 +01:00
if ( ! $start ) $start = $event [ 'start' ];
2008-05-08 17:02:35 +02:00
2005-11-09 00:15:14 +01:00
$events = array ();
$this -> insert_all_repetitions ( $event , $start , $this -> date2ts ( $this -> config [ 'horizont' ], true ), $events , null );
foreach ( $events as $event )
{
$this -> so -> recurrence ( $event [ 'id' ], $this -> date2ts ( $event [ 'start' ], true ), $this -> date2ts ( $event [ 'end' ], true ), $event [ 'participants' ]);
}
}
2008-05-08 17:02:35 +02:00
2005-11-09 00:15:14 +01:00
/**
* convert data read from the db , eg . convert server to user - time
*
* @ param array & $events array of event - arrays ( reference )
* @ param $date_format = 'ts' date - formats : 'ts' = timestamp , 'server' = timestamp in server - time , 'array' = array or string with date - format
*/
function db2data ( & $events , $date_format = 'ts' )
{
if ( ! is_array ( $events )) echo " <p>bocal::db2data( \$ events, $date_format ) \$ events is no array<br /> \n " . function_backtrace () . " </p> \n " ;
foreach ( $events as $id => $event )
{
// we convert here from the server-time timestamps to user-time and (optional) to a different date-format!
foreach ( array ( 'start' , 'end' , 'modified' , 'recur_enddate' ) as $ts )
2004-08-01 17:36:04 +02:00
{
2005-11-09 00:15:14 +01:00
if ( empty ( $event [ $ts ])) continue ;
$events [ $id ][ $ts ] = $this -> date2usertime ( $event [ $ts ], $date_format );
2004-08-01 17:36:04 +02:00
}
2005-11-09 00:15:14 +01:00
// same with the recur exceptions
if ( isset ( $event [ 'recur_exception' ]) && is_array ( $event [ 'recur_exception' ]))
2004-08-01 17:36:04 +02:00
{
2005-11-09 00:15:14 +01:00
foreach ( $event [ 'recur_exception' ] as $n => $date )
2004-08-01 17:36:04 +02:00
{
2005-11-09 00:15:14 +01:00
$events [ $id ][ 'recur_exception' ][ $n ] = $this -> date2usertime ( $date , $date_format );
2004-08-01 17:36:04 +02:00
}
}
2005-11-09 00:15:14 +01:00
// same with the alarms
if ( isset ( $event [ 'alarm' ]) && is_array ( $event [ 'alarm' ]))
2004-08-01 17:36:04 +02:00
{
2005-11-09 00:15:14 +01:00
foreach ( $event [ 'alarm' ] as $n => $alarm )
{
$events [ $id ][ 'alarm' ][ $n ][ 'time' ] = $this -> date2usertime ( $alarm [ 'time' ], $date_format );
}
2004-08-01 17:36:04 +02:00
}
}
2005-11-09 00:15:14 +01:00
}
2008-05-08 17:02:35 +02:00
2005-11-09 00:15:14 +01:00
/**
* convert a date from server to user - time
*
* @ param int $date timestamp in server - time
* @ param $date_format = 'ts' date - formats : 'ts' = timestamp , 'server' = timestamp in server - time , 'array' = array or string with date - format
*/
function date2usertime ( $ts , $date_format = 'ts' )
{
if ( empty ( $ts )) return $ts ;
2008-05-08 17:02:35 +02:00
2005-11-09 00:15:14 +01:00
switch ( $date_format )
2004-08-01 17:36:04 +02:00
{
2005-11-09 00:15:14 +01:00
case 'ts' :
return $ts + $this -> tz_offset_s ;
case 'server' :
return $ts ;
case 'array' :
return $this -> date2array (( int ) $ts , true );
case 'string' :
return $this -> date2string ( $ts , true );
2004-08-01 17:36:04 +02:00
}
2005-11-09 00:15:14 +01:00
return $this -> date2string ( $ts , true , $date_format );
2004-08-01 17:36:04 +02:00
}
/**
* Reads a calendar - entry
*
2005-11-09 00:15:14 +01:00
* @ param int / array / string $ids id or array of id ' s of the entries to read , or string with a single uid
* @ param mixed $date = null date to specify a single event of a series
* @ param boolean $ignore_acl should we ignore the acl , default False for a single id , true for multiple id ' s
* @ param string $date_format = 'ts' date - formats : 'ts' = timestamp , 'server' = timestamp in servertime , 'array' = array , or string with date - format
2006-06-24 18:04:06 +02:00
* @ return boolean / array event or array of id => event pairs , false if the acl - check went wrong , null if $ids not found
2004-08-01 17:36:04 +02:00
*/
2005-11-09 00:15:14 +01:00
function read ( $ids , $date = null , $ignore_acl = False , $date_format = 'ts' )
2004-08-01 17:36:04 +02:00
{
2005-11-09 00:15:14 +01:00
if ( $date ) $date = $this -> date2ts ( $date );
2004-08-01 17:36:04 +02:00
2006-12-22 20:51:56 +01:00
if ( $ignore_acl || is_array ( $ids ) || ( $return = $this -> check_perms ( EGW_ACL_READ , $ids , 0 , $date_format , $date )))
2004-08-01 17:36:04 +02:00
{
2008-05-10 22:10:45 +02:00
if ( is_array ( $ids ) || ! isset ( self :: $cached_event [ 'id' ]) || self :: $cached_event [ 'id' ] != $ids ||
self :: $cached_event_date_format != $date_format ||
self :: $cached_event [ 'recur_type' ] != MCAL_RECUR_NONE && ! is_null ( $date ) && ( ! $date || self :: $cached_event [ 'start' ] < $date ))
2004-08-01 17:36:04 +02:00
{
2005-11-09 00:15:14 +01:00
$events = $this -> so -> read ( $ids , $date ? $this -> date2ts ( $date , true ) : 0 );
2006-12-22 20:51:56 +01:00
2005-11-09 00:15:14 +01:00
if ( $events )
2004-08-01 17:36:04 +02:00
{
2005-11-09 00:15:14 +01:00
$this -> db2data ( $events , $date_format );
2008-05-08 17:02:35 +02:00
2005-11-09 00:15:14 +01:00
if ( is_array ( $ids ))
2004-11-07 15:38:00 +01:00
{
2005-11-09 00:15:14 +01:00
$return =& $events ;
}
else
{
2008-05-10 22:10:45 +02:00
self :: $cached_event = array_shift ( $events );
self :: $cached_event_date_format = $date_format ;
$return =& self :: $cached_event ;
2004-11-07 15:38:00 +01:00
}
2004-08-01 17:36:04 +02:00
}
2005-11-09 00:15:14 +01:00
}
else
{
2008-05-10 22:10:45 +02:00
$return =& self :: $cached_event ;
2004-08-01 17:36:04 +02:00
}
}
if ( $this -> debug && ( $this -> debug > 1 || $this -> debug == 'read' ))
{
2005-11-09 00:15:14 +01:00
$this -> debug_message ( 'bocal::read(%1,%2,%3,%4)=%5' , True , $ids , $date , $ignore_acl , $date_format , $return );
2004-08-01 17:36:04 +02:00
}
2005-11-09 00:15:14 +01:00
return $return ;
2004-08-01 17:36:04 +02:00
}
/**
* Inserts all repetions of $event in the timespan between $start and $end into $events
*
* As events can have recur - exceptions , only those event - date not having one , should get inserted .
* The caller supplies an array with the already inserted exceptions .
*
* The new entries are just appended to $entries , so $events is no longer sorted by startdate !!!
* Unlike the old code the start - and end - date of the events should be adapted here !!!
*
* TODO : This code is mainly copied from bocalendar and need to be rewritten for the changed algorithm :
* We insert now all repetions of one event in one go . It should be possible to calculate the time - difference
* of the used recur - type and add all events in one simple for - loop . Daylightsaving changes need to be taken into Account .
*
* @ param $event array repeating event whos repetions should be inserted
2005-11-09 00:15:14 +01:00
* @ param $start mixed start - date
* @ param $end mixed end - date
2004-08-01 17:36:04 +02:00
* @ param $events array where the repetions get inserted
2004-09-08 12:13:33 +02:00
* @ param $recur_exceptions array with date ( in Ymd ) as key ( and True as values )
2004-08-01 17:36:04 +02:00
*/
function insert_all_repetitions ( $event , $start , $end , & $events , $recur_exceptions )
{
2005-11-09 00:15:14 +01:00
if (( int ) $this -> debug >= 3 || $this -> debug == 'set_recurrences' || $this -> debug == 'check_move_horizont' || $this -> debug == 'insert_all_repitions' )
{
$this -> debug_message ( 'bocal::insert_all_repitions(%1,%2,%3,&$event,%4)' , true , $event , $start , $end , $recur_exceptions );
}
2004-08-01 17:36:04 +02:00
$start_in = $start ; $end_in = $end ;
2008-05-08 17:02:35 +02:00
2005-11-09 00:15:14 +01:00
$start = $this -> date2ts ( $start );
$end = $this -> date2ts ( $end );
$event_start_ts = $this -> date2ts ( $event [ 'start' ]);
$event_end_ts = $this -> date2ts ( $event [ 'end' ]);
2004-08-01 17:36:04 +02:00
2005-11-09 00:15:14 +01:00
if ( $this -> debug && (( int ) $this -> debug > 3 || $this -> debug == 'insert_all_repetions' || $this -> debug == 'check_move_horizont' || $this -> debug == 'insert_all_repitions' ))
2004-08-01 17:36:04 +02:00
{
$this -> debug_message ( 'bocal::insert_all_repetions(%1,start=%2,end=%3,,%4) starting...' , True , $event , $start_in , $end_in , $recur_exceptions );
}
$id = $event [ 'id' ];
2005-11-09 00:15:14 +01:00
$event_start_arr = $this -> date2array ( $event [ 'start' ]);
2008-05-08 17:02:35 +02:00
// to be able to calculate the repetitions as difference to the start-date,
2005-02-09 21:32:48 +01:00
// both need to be calculated without daylight saving: mktime(,,,,,,0)
2005-11-09 00:15:14 +01:00
$event_start_daybegin_ts = adodb_mktime ( 0 , 0 , 0 , $event_start_arr [ 'month' ], $event_start_arr [ 'day' ], $event_start_arr [ 'year' ], 0 );
2004-08-01 17:36:04 +02:00
if ( $event [ 'recur_enddate' ])
{
$recur_end_ymd = $this -> date2string ( $event [ 'recur_enddate' ]);
}
else
{
2005-11-09 00:15:14 +01:00
$recur_end_ymd = $this -> date2string ( adodb_mktime ( 0 , 0 , 0 , 1 , 1 , 5 + adodb_date ( 'Y' ))); // go max. 5 years from now
2004-08-01 17:36:04 +02:00
}
// We only need to compute the intersection between our reported time-span and the live-time of the event
// To catch all multiday repeated events (eg. second days), we need to start the length of the even earlier
// then our original report-starttime
2005-11-09 00:15:14 +01:00
$event_length = $event_end_ts - $event_start_ts ;
$start_ts = max ( $event_start_ts , $start - $event_length );
2004-08-01 17:36:04 +02:00
// we need to add 26*60*60-1 to the recur_enddate as its hour+minute are 0
2005-11-09 00:15:14 +01:00
$end_ts = $event [ 'recur_enddate' ] ? min ( $this -> date2ts ( $event [ 'recur_enddate' ]) + DAY_s - 1 , $end ) : $end ;
2004-08-01 17:36:04 +02:00
for ( $ts = $start_ts ; $ts < $end_ts ; $ts += DAY_s )
{
$search_date_ymd = ( int ) $this -> date2string ( $ts );
$have_exception = ! is_null ( $recur_exceptions ) && isset ( $recur_exceptions [ $search_date_ymd ]);
2008-05-08 17:02:35 +02:00
2005-02-10 01:13:37 +01:00
if ( ! $have_exception ) // no execption by an edited event => check the deleted ones
{
2005-11-09 00:15:14 +01:00
foreach (( array ) $event [ 'recur_exception' ] as $exception_ts )
2005-02-10 01:13:37 +01:00
{
2006-08-21 12:47:35 +02:00
if (( $have_exception = $search_date_ymd == ( int ) $this -> date2string ( $exception_ts ))) break ;
2005-02-10 01:13:37 +01:00
}
}
2005-11-09 00:15:14 +01:00
if ( $this -> debug && (( int ) $this -> debug > 3 || $this -> debug == 'insert_all_repetions' || $this -> debug == 'check_move_horizont' || $this -> debug == 'insert_all_repitions' ))
2004-08-01 17:36:04 +02:00
{
2005-02-10 01:13:37 +01:00
$this -> debug_message ( 'bocal::insert_all_repetions(...,%1) checking recur_exceptions[%2] and event[recur_exceptions]=%3 ==> %4' , False ,
$recur_exceptions , $search_date_ymd , $event [ 'recur_exception' ], $have_exception );
2004-08-01 17:36:04 +02:00
}
if ( $have_exception )
{
continue ; // we already have an exception for that date
}
2005-11-09 00:15:14 +01:00
$search_date_year = adodb_date ( 'Y' , $ts );
$search_date_month = adodb_date ( 'm' , $ts );
$search_date_day = adodb_date ( 'd' , $ts );
$search_date_dow = adodb_date ( 'w' , $ts );
2008-05-08 17:02:35 +02:00
// to be able to calculate the repetitions as difference to the start-date,
2005-02-09 21:32:48 +01:00
// both need to be calculated without daylight saving: mktime(,,,,,,0)
2005-11-09 00:15:14 +01:00
$search_beg_day = adodb_mktime ( 0 , 0 , 0 , $search_date_month , $search_date_day , $search_date_year , 0 );
2004-08-01 17:36:04 +02:00
2005-11-09 00:15:14 +01:00
if ( $search_date_ymd == $event_start_arr [ 'full' ]) // first occurence
2004-08-01 17:36:04 +02:00
{
$this -> add_adjusted_event ( $events , $event , $search_date_ymd );
continue ;
}
2007-04-11 11:52:06 +02:00
$freq = $event [ 'recur_interval' ] ? $event [ 'recur_interval' ] : 1 ;
2004-08-01 17:36:04 +02:00
$type = $event [ 'recur_type' ];
switch ( $type )
{
case MCAL_RECUR_DAILY :
if ( $this -> debug > 4 )
{
echo '<!-- check_repeating_events - MCAL_RECUR_DAILY - ' . $id . ' -->' . " \n " ;
}
2005-11-09 00:15:14 +01:00
if ( $freq == 1 && $event [ 'recur_enddate' ] && $search_date_ymd <= $recur_end_ymd )
2004-08-01 17:36:04 +02:00
{
$this -> add_adjusted_event ( $events , $event , $search_date_ymd );
}
elseif ( floor (( $search_beg_day - $event_start_daybegin_ts ) / DAY_s ) % $freq )
{
continue ;
}
else
{
$this -> add_adjusted_event ( $events , $event , $search_date_ymd );
}
break ;
case MCAL_RECUR_WEEKLY :
2007-04-27 12:04:33 +02:00
// we use round(,1) to deal with changing daylight saving
if ( floor ( round (( $search_beg_day - $event_start_daybegin_ts ) / WEEK_s , 1 )) % $freq )
2004-08-01 17:36:04 +02:00
{
continue ;
}
$check = 0 ;
switch ( $search_date_dow )
{
case 0 :
$check = MCAL_M_SUNDAY ;
break ;
case 1 :
$check = MCAL_M_MONDAY ;
break ;
case 2 :
$check = MCAL_M_TUESDAY ;
break ;
case 3 :
$check = MCAL_M_WEDNESDAY ;
break ;
case 4 :
$check = MCAL_M_THURSDAY ;
break ;
case 5 :
$check = MCAL_M_FRIDAY ;
break ;
case 6 :
$check = MCAL_M_SATURDAY ;
break ;
}
if ( $event [ 'recur_data' ] & $check )
{
$this -> add_adjusted_event ( $events , $event , $search_date_ymd );
}
break ;
case MCAL_RECUR_MONTHLY_WDAY :
2005-11-09 00:15:14 +01:00
if ((( $search_date_year - $event_start_arr [ 'year' ]) * 12 + $search_date_month - $event_start_arr [ 'month' ]) % $freq )
2004-08-01 17:36:04 +02:00
{
continue ;
}
2005-11-09 00:15:14 +01:00
if (( $GLOBALS [ 'egw' ] -> datetime -> day_of_week ( $event_start_arr [ 'year' ], $event_start_arr [ 'month' ], $event_start_arr [ 'day' ]) == $GLOBALS [ 'egw' ] -> datetime -> day_of_week ( $search_date_year , $search_date_month , $search_date_day )) &&
( ceil ( $event_start_arr [ 'day' ] / 7 ) == ceil ( $search_date_day / 7 )))
2004-08-01 17:36:04 +02:00
{
$this -> add_adjusted_event ( $events , $event , $search_date_ymd );
}
break ;
case MCAL_RECUR_MONTHLY_MDAY :
2005-11-09 00:15:14 +01:00
if ((( $search_date_year - $event_start_arr [ 'year' ]) * 12 + $search_date_month - $event_start_arr [ 'month' ]) % $freq )
2004-08-01 17:36:04 +02:00
{
continue ;
}
2005-11-09 00:15:14 +01:00
if ( $search_date_day == $event_start_arr [ 'day' ])
2004-08-01 17:36:04 +02:00
{
$this -> add_adjusted_event ( $events , $event , $search_date_ymd );
}
break ;
case MCAL_RECUR_YEARLY :
2005-11-09 00:15:14 +01:00
if (( $search_date_year - $event_start_arr [ 'year' ]) % $freq )
2004-08-01 17:36:04 +02:00
{
continue ;
}
2005-11-09 00:15:14 +01:00
if ( adodb_date ( 'dm' , $ts ) == adodb_date ( 'dm' , $event_start_daybegin_ts ))
2004-08-01 17:36:04 +02:00
{
$this -> add_adjusted_event ( $events , $event , $search_date_ymd );
}
break ;
} // switch(recur-type)
} // for($date = ...)
2005-11-09 00:15:14 +01:00
if ( $this -> debug && (( int ) $this -> debug > 2 || $this -> debug == 'insert_all_repetions' || $this -> debug == 'check_move_horizont' || $this -> debug == 'insert_all_repitions' ))
2004-08-01 17:36:04 +02:00
{
$this -> debug_message ( 'bocal::insert_all_repetions(%1,start=%2,end=%3,events,exections=%4) events=%5' , True , $event , $start_in , $end_in , $recur_exceptions , $events );
}
}
/**
* Adds one repetion of $event for $date_ymd to the $events array , after adjusting its start - and end - time
*
* @ param $events array in which the event gets inserted
2004-09-08 12:13:33 +02:00
* @ param $event array event to insert , it has start - and end - date of the first recurrence , not of $date_ymd
2004-08-01 17:36:04 +02:00
* @ param $date_ymd int / string of the date of the event
*/
function add_adjusted_event ( & $events , $event , $date_ymd )
{
$event_in = $event ;
// calculate the new start- and end-time
2005-11-09 00:15:14 +01:00
$length_s = $this -> date2ts ( $event [ 'end' ]) - $this -> date2ts ( $event [ 'start' ]);
$event_start_arr = $this -> date2array ( $event [ 'start' ]);
2004-08-01 17:36:04 +02:00
$date_arr = $this -> date2array (( string ) $date_ymd );
2005-11-09 00:15:14 +01:00
$date_arr [ 'hour' ] = $event_start_arr [ 'hour' ];
$date_arr [ 'minute' ] = $event_start_arr [ 'minute' ];
$date_arr [ 'second' ] = $event_start_arr [ 'second' ];
2004-08-01 17:36:04 +02:00
unset ( $date_arr [ 'raw' ]); // else date2ts would use it
2005-11-09 00:15:14 +01:00
$event [ 'start' ] = $this -> date2ts ( $date_arr );
$event [ 'end' ] = $event [ 'start' ] + $length_s ;
2004-08-01 17:36:04 +02:00
$events [] = $event ;
if ( $this -> debug && ( $this -> debug > 2 || $this -> debug == 'add_adjust_event' ))
{
$this -> debug_message ( 'bocal::add_adjust_event(,%1,%2) as %3' , True , $event_in , $date_ymd , $event );
}
}
2006-03-05 11:26:03 +01:00
/**
* Fetch information about a resource
*
* We do some caching here , as the resource itself might not do it .
*
* @ param string $uid string with one - letter resource - type and numerical resource - id , eg . " r19 "
* @ return array / boolean array with keys res_id , cat_id , name , useable ( name definied by max_quantity in $this -> resources ), rights , responsible or false if $uid is not found
*/
function resource_info ( $uid )
{
static $res_info_cache = array ();
2008-05-08 17:02:35 +02:00
2006-03-05 11:26:03 +01:00
if ( ! isset ( $res_info_cache [ $uid ]))
{
2008-05-08 17:02:35 +02:00
if ( is_numeric ( $uid ))
{
$info = array (
'res_id' => $uid ,
'email' => $GLOBALS [ 'egw' ] -> accounts -> id2name ( $uid , 'account_email' ),
'name' => trim ( $GLOBALS [ 'egw' ] -> accounts -> id2name ( $uid , 'account_firstname' ) . ' ' .
$GLOBALS [ 'egw' ] -> accounts -> id2name ( $uid , 'account_lastname' )),
'type' => $GLOBALS [ 'egw' ] -> accounts -> get_type ( $uid ),
);
}
else
{
list ( $info ) = $this -> resources [ $uid [ 0 ]][ 'info' ] ? ExecMethod ( $this -> resources [ $uid [ 0 ]][ 'info' ], substr ( $uid , 1 )) : false ;
if ( $info )
{
$info [ 'type' ] = $uid [ 0 ];
if ( ! $info [ 'email' ] && $info [ 'responsible' ])
{
$info [ 'email' ] = $GLOBALS [ 'egw' ] -> accounts -> id2name ( $info [ 'responsible' ], 'account_email' );
}
}
}
$res_info_cache [ $uid ] = $info ;
2006-03-05 11:26:03 +01:00
}
if ( $this -> debug && ( $this -> debug > 2 || $this -> debug == 'resource_info' ))
{
$this -> debug_message ( 'bocal::resource_info(%1) = %2' , True , $uid , $res_info_cache [ $uid ]);
}
return $res_info_cache [ $uid ];
}
2004-08-01 17:36:04 +02:00
/**
* Checks if the current user has the necessary ACL rights
*
* The check is performed on an event or generally on the cal of an other user
*
* Note : Participating in an event is considered as haveing read - access on that event ,
* even if you have no general read - grant from that user .
*
2005-11-09 00:15:14 +01:00
* @ param int $needed necessary ACL right : EGW_ACL_ { READ | EDIT | DELETE }
* @ param mixed $event event as array or the event - id or 0 for a general check
* @ param int $other uid to check ( if event == 0 ) or 0 to check against $this -> user
2006-12-22 20:51:56 +01:00
* @ param string $date_format = 'ts' date - format used for reading : 'ts' = timestamp , 'array' = array , 'string' = iso8601 string for xmlrpc
* @ param mixed $date_to_read = null date used for reading , internal param for the caching
2006-06-24 18:04:06 +02:00
* @ return boolean true permission granted , false for permission denied or null if event not found
2004-08-01 17:36:04 +02:00
*/
2006-12-22 20:51:56 +01:00
function check_perms ( $needed , $event = 0 , $other = 0 , $date_format = 'ts' , $date_to_read = null )
2004-08-01 17:36:04 +02:00
{
$event_in = $event ;
2005-11-09 00:15:14 +01:00
if ( $other && ! is_numeric ( $other ))
{
2006-03-05 11:26:03 +01:00
$resource = $this -> resource_info ( $other );
2005-11-09 00:15:14 +01:00
2006-03-05 11:26:03 +01:00
return $needed & $resource [ 'rights' ];
2005-11-09 00:15:14 +01:00
}
2004-08-01 17:36:04 +02:00
if ( is_int ( $event ) && $event == 0 )
{
2005-11-24 20:50:52 +01:00
$owner = $other ? $other : $this -> user ;
2004-08-01 17:36:04 +02:00
}
else
{
if ( ! is_array ( $event ))
{
2006-12-22 20:51:56 +01:00
$event = $this -> read ( $event , $date_to_read , True , $date_format ); // = no ACL check !!!
2004-08-01 17:36:04 +02:00
}
if ( ! is_array ( $event ))
{
if ( $this -> xmlrpc )
{
$GLOBALS [ 'server' ] -> xmlrpc_error ( $GLOBALS [ 'xmlrpcerr' ][ 'not_exist' ], $GLOBALS [ 'xmlrpcstr' ][ 'not_exist' ]);
}
2006-06-24 18:04:06 +02:00
return null ; // event not found
2004-08-01 17:36:04 +02:00
}
$owner = $event [ 'owner' ];
$private = ! $event [ 'public' ];
}
2005-11-09 00:15:14 +01:00
$user = $GLOBALS [ 'egw_info' ][ 'user' ][ 'account_id' ];
2004-08-01 17:36:04 +02:00
$grants = $this -> grants [ $owner ];
2008-05-08 17:02:35 +02:00
2005-11-09 00:15:14 +01:00
if ( is_array ( $event ) && $needed == EGW_ACL_READ )
2004-08-01 17:36:04 +02:00
{
// Check if the $user is one of the participants or has a read-grant from one of them
2004-09-08 14:20:56 +02:00
// in that case he has an implicite READ grant for that event
2004-08-01 17:36:04 +02:00
//
foreach ( $event [ 'participants' ] as $uid => $accept )
{
2008-05-08 17:02:35 +02:00
if ( $uid == $user || $uid < 0 && in_array ( $user , $GLOBALS [ 'egw' ] -> accounts -> members ( $uid , true )))
2004-08-01 17:36:04 +02:00
{
2004-09-08 14:20:56 +02:00
// if we are a participant, we have an implicite READ and PRIVAT grant
2005-11-09 00:15:14 +01:00
$grants |= EGW_ACL_READ | EGW_ACL_PRIVATE ;
2004-08-01 17:36:04 +02:00
break ;
}
2005-11-09 00:15:14 +01:00
elseif ( $this -> grants [ $uid ] & EGW_ACL_READ )
2004-09-08 14:20:56 +02:00
{
// if we have a READ grant from a participant, we dont give an implicit privat grant too
2005-11-09 00:15:14 +01:00
$grants |= EGW_ACL_READ ;
2008-05-08 17:02:35 +02:00
// we cant break here, as we might be a participant too, and would miss the privat grant
2005-11-09 00:15:14 +01:00
}
elseif ( ! is_numeric ( $uid ))
{
// if we have a resource as participant
2006-03-05 11:26:03 +01:00
$resource = $this -> resource_info ( $uid );
$grants |= $resource [ 'rights' ];
2008-05-08 17:02:35 +02:00
}
2004-08-01 17:36:04 +02:00
}
}
2005-11-09 00:15:14 +01:00
if ( $GLOBALS [ 'egw' ] -> accounts -> get_type ( $owner ) == 'g' && $needed == EGW_ACL_ADD )
2004-08-01 17:36:04 +02:00
{
$access = False ; // a group can't be the owner of an event
}
else
{
2005-11-09 00:15:14 +01:00
$access = $user == $owner || $grants & $needed && ( ! $private || $grants & EGW_ACL_PRIVATE );
2004-08-01 17:36:04 +02:00
}
if ( $this -> debug && ( $this -> debug > 2 || $this -> debug == 'check_perms' ))
{
$this -> debug_message ( 'bocal::check_perms(%1,%2,%3)=%4' , True , ACL_TYPE_IDENTIFER . $needed , $event , $other , $access );
}
return $access ;
}
/**
* Converts several date - types to a timestamp and optionaly converts user - to server - time
*
* @ param $date mixed date to convert , should be one of the following types
2005-11-09 00:15:14 +01:00
* string ( ! ) in form YYYYMMDD or iso8601 YYYY - MM - DDThh : mm : ss or YYYYMMDDThhmmss
2004-08-01 17:36:04 +02:00
* int already a timestamp
* array with keys 'second' , 'minute' , 'hour' , 'day' or 'mday' ( depricated ! ), 'month' and 'year'
* @ param $user2server_time boolean conversation between user - and server - time default False == Off
*/
function date2ts ( $date , $user2server = False )
{
$date_in = $date ;
2004-11-07 15:38:00 +01:00
2004-08-01 17:36:04 +02:00
switch ( gettype ( $date ))
{
case 'string' : // YYYYMMDD or iso8601 YYYY-MM-DDThh:mm:ss string
2004-11-07 15:38:00 +01:00
if ( is_numeric ( $date ) && $date > 21000000 )
{
$date = ( int ) $date ; // this is already as timestamp
break ;
}
2005-11-09 00:15:14 +01:00
// ToDo: evaluate evtl. added timezone
// removing all non-nummerical chars, gives YYYYMMDDhhmmss, independent of the iso8601 format
$date = str_replace ( array ( '-' , ':' , 'T' , 'Z' , ' ' ), '' , $date );
$date = array (
'year' => ( int ) substr ( $date , 0 , 4 ),
'month' => ( int ) substr ( $date , 4 , 2 ),
'day' => ( int ) substr ( $date , 6 , 2 ),
'hour' => ( int ) substr ( $date , 8 , 2 ),
'minute' => ( int ) substr ( $date , 10 , 2 ),
'second' => ( int ) substr ( $date , 12 , 2 ),
);
2004-08-01 17:36:04 +02:00
// fall-through
2005-11-09 00:15:14 +01:00
case 'array' : // day, month and year keys
2004-08-01 17:36:04 +02:00
if ( isset ( $date [ 'raw' ]) && $date [ 'raw' ]) // we already have a timestamp
{
$date = $date [ 'raw' ];
break ;
}
2005-11-09 00:15:14 +01:00
if ( ! isset ( $date [ 'year' ]) && isset ( $date [ 'full' ]))
2004-08-01 17:36:04 +02:00
{
2005-11-09 00:15:14 +01:00
$date [ 'year' ] = ( int ) substr ( $date [ 'full' ], 0 , 4 );
$date [ 'month' ] = ( int ) substr ( $date [ 'full' ], 4 , 2 );
$date [ 'day' ] = ( int ) substr ( $date [ 'full' ], 6 , 2 );
2004-08-01 17:36:04 +02:00
}
2006-01-16 09:27:21 +01:00
$date = adodb_mktime (( int ) $date [ 'hour' ],( int ) $date [ 'minute' ],( int ) $date [ 'second' ],( int ) $date [ 'month' ],
( int ) ( isset ( $date [ 'day' ]) ? $date [ 'day' ] : $date [ 'mday' ]),( int ) $date [ 'year' ]);
2004-08-01 17:36:04 +02:00
break ;
case 'integer' : // already a timestamp
break ;
default : // eg. boolean, means now in user-time (!)
2005-05-10 15:38:58 +02:00
$date = $this -> now_su ;
2004-08-01 17:36:04 +02:00
break ;
}
if ( $user2server )
{
$date -= $this -> tz_offset_s ;
}
if ( $this -> debug && ( $this -> debug > 3 || $this -> debug == 'date2ts' ))
{
$this -> debug_message ( 'bocal::date2ts(%1,user2server=%2)=%3)' , False , $date_in , $user2server , $date );
}
return $date ;
}
/**
* Converts a date to an array and optionaly converts server - to user - time
*
* @ param $date mixed date to convert
* @ param $server2user_time boolean conversation between user - and server - time default False == Off
2004-10-08 00:11:18 +02:00
* @ return array with keys 'second' , 'minute' , 'hour' , 'day' , 'month' , 'year' , 'raw' ( timestamp ) and 'full' ( Ymd - string )
2004-08-01 17:36:04 +02:00
*/
function date2array ( $date , $server2user = False )
{
$date_called = $date ;
if ( ! is_array ( $date ) || count ( $date ) < 8 || $server2user ) // do we need a conversation
{
2004-11-07 15:38:00 +01:00
if ( ! is_int ( $date ))
{
$date = $this -> date2ts ( $date );
}
2004-08-01 17:36:04 +02:00
if ( $server2user )
{
$date += $this -> tz_offset_s ;
}
$arr = array ();
foreach ( array ( 'second' => 's' , 'minute' => 'i' , 'hour' => 'H' , 'day' => 'd' , 'month' => 'm' , 'year' => 'Y' , 'full' => 'Ymd' ) as $key => $frmt )
{
2005-11-09 00:15:14 +01:00
$arr [ $key ] = ( int ) adodb_date ( $frmt , $date );
2004-08-01 17:36:04 +02:00
}
$arr [ 'raw' ] = $date ;
}
if ( $this -> debug && ( $this -> debug > 3 || $this -> debug == 'date2array' ))
{
$this -> debug_message ( 'bocal::date2array(%1,server2user=%2)=%3)' , False , $date_called , $server2user , $arr );
}
return $arr ;
}
/**
* Converts a date as timestamp or array to a date - string and optionaly converts server - to user - time
*
2005-11-09 00:15:14 +01:00
* @ param mixed $date integer timestamp or array with ( 'year' , 'month' , .. , 'second' ) to convert
* @ param boolean $server2user_time conversation between user - and server - time default False == Off , not used if $format ends with \Z
* @ param string $format = 'Ymd' format of the date to return , eg . 'Y-m-d\TH:i:sO' ( 2005 - 11 - 01 T15 : 30 : 00 + 0100 )
* @ return string date formatted according to $format
2004-08-01 17:36:04 +02:00
*/
2005-11-09 00:15:14 +01:00
function date2string ( $date , $server2user = False , $format = 'Ymd' )
2004-08-01 17:36:04 +02:00
{
$date_in = $date ;
2005-11-09 00:15:14 +01:00
if ( ! $format ) $format = 'Ymd' ;
if ( is_array ( $date ) && isset ( $date [ 'full' ]) && ! $server2user && $format == 'Ymd' )
2004-08-01 17:36:04 +02:00
{
$date = $date [ 'full' ];
}
else
{
$date = $this -> date2ts ( $date , False );
2008-05-08 17:02:35 +02:00
2005-11-09 00:15:14 +01:00
// if timezone is requested, we dont need to convert to user-time
if (( $tz_used = substr ( $format , - 1 )) == 'O' || $tz_used == 'Z' ) $server2user = false ;
2008-05-08 17:02:35 +02:00
2005-11-09 00:15:14 +01:00
if ( $server2user && substr ( $format , - 1 ) )
2004-08-01 17:36:04 +02:00
{
$date += $this -> tz_offset_s ;
}
2005-11-09 00:15:14 +01:00
if ( substr ( $format , - 2 ) == '\\Z' ) // GMT aka. Zulu time
{
$date = adodb_gmdate ( $format , $date );
}
else
{
$date = adodb_date ( $format , $date );
}
2004-08-01 17:36:04 +02:00
}
if ( $this -> debug && ( $this -> debug > 3 || $this -> debug == 'date2string' ))
{
2005-11-09 00:15:14 +01:00
$this -> debug_message ( 'bocal::date2string(%1,server2user=%2,format=%3)=%4)' , False , $date_in , $server2user , $format , $date );
2004-08-01 17:36:04 +02:00
}
return $date ;
}
2005-11-09 00:15:14 +01:00
/**
* Formats a date given as timestamp or array
*
* @ param mixed $date integer timestamp or array with ( 'year' , 'month' , .. , 'second' ) to convert
2006-08-25 10:17:40 +02:00
* @ param string / boolean $format = '' default common_prefs [ dateformat ], common_prefs [ timeformat ], false = time only , true = date only
2005-11-09 00:15:14 +01:00
* @ return string the formated date ( incl . time )
*/
function format_date ( $date , $format = '' )
{
2006-08-25 10:17:40 +02:00
$timeformat = $this -> common_prefs [ 'timeformat' ] != '12' ? 'H:i' : 'h:i a' ;
if ( $format === '' ) // date+time wanted
2005-11-09 00:15:14 +01:00
{
2006-08-25 10:17:40 +02:00
$format = $this -> common_prefs [ 'dateformat' ] . ', ' . $timeformat ;
}
elseif ( $format === false ) // time wanted
{
$format = $timeformat ;
}
elseif ( $format === true )
{
$format = $this -> common_prefs [ 'dateformat' ];
2005-11-09 00:15:14 +01:00
}
return adodb_date ( $format , $this -> date2ts ( $date , False ));
}
2004-08-01 17:36:04 +02:00
/**
* Gives out a debug - message with certain parameters
*
* All permanent debug - messages in the calendar should be done by this function !!!
* ( In future they may be logged or sent as xmlrpc - faults back . )
*
* Permanent debug - message need to make sure NOT to give secret information like passwords !!!
*
* This function do NOT honor the setting of the debug variable , you may use it like
* if ( $this -> debug > N ) $this -> debug_message ( 'Error ;-)' );
*
* The parameters get formated depending on their type . ACL - values need a ACL_TYPE_IDENTIFER prefix .
*
* @ param $msg string message with parameters / variables like lang (), eg . '%1'
* @ param $backtrace include a function - backtrace , default True = On
* should only be set to False = Off , if your code ensures a call with backtrace = On was made before !!!
* @ param $param mixed a variable number of parameters , to be inserted in $msg
* arrays get serialized with print_r () !
*/
function debug_message ( $msg , $backtrace = True )
{
static $acl2string = array (
2005-11-09 00:15:14 +01:00
0 => 'ACL-UNKNOWN' ,
EGW_ACL_READ => 'ACL_READ' ,
EGW_ACL_ADD => 'ACL_ADD' ,
2006-12-22 20:51:56 +01:00
EGW_ACL_EDIT => 'ACL_EDIT' ,
2005-11-09 00:15:14 +01:00
EGW_ACL_DELETE => 'ACL_DELETE' ,
EGW_ACL_PRIVATE => 'ACL_PRIVATE' ,
2004-08-01 17:36:04 +02:00
);
for ( $i = 2 ; $i < func_num_args (); ++ $i )
{
$param = func_get_arg ( $i );
if ( is_null ( $param ))
{
$param = 'NULL' ;
}
else
{
switch ( gettype ( $param ))
{
case 'string' :
if ( substr ( $param , 0 , strlen ( ACL_TYPE_IDENTIFER )) == ACL_TYPE_IDENTIFER )
{
$param = ( int ) substr ( $param , strlen ( ACL_TYPE_IDENTIFER ));
2006-12-22 20:51:56 +01:00
$param = ( isset ( $acl2string [ $param ]) ? $acl2string [ $param ] : $acl2string [ 0 ]) . " ( $param ) " ;
2004-08-01 17:36:04 +02:00
}
else
{
$param = " ' $param ' " ;
}
break ;
case 'array' :
case 'object' :
list (, $content ) = @ each ( $param );
$do_pre = is_array ( $param ) ? count ( $param ) > 6 || is_array ( $content ) && count ( $content ) : True ;
$param = ( $do_pre ? '<pre>' : '' ) . print_r ( $param , True ) . ( $do_pre ? '</pre>' : '' );
break ;
case 'boolean' :
$param = $param ? 'True' : 'False' ;
break ;
2004-12-12 13:24:24 +01:00
case 'integer' :
2005-11-09 00:15:14 +01:00
if ( $param >= mktime ( 0 , 0 , 0 , 1 , 1 , 2000 )) $param = adodb_date ( 'Y-m-d H:i:s' , $param ) . " ( $param ) " ;
2004-12-12 13:24:24 +01:00
break ;
2004-08-01 17:36:04 +02:00
}
}
$msg = str_replace ( '%' . ( $i - 1 ), $param , $msg );
}
2004-12-12 13:24:24 +01:00
echo '<p>' . $msg . " <br> \n " . ( $backtrace ? 'Backtrace: ' . function_backtrace ( 1 ) . " </p> \n " : '' ) . str_repeat ( ' ' , 4096 );
2004-08-01 17:36:04 +02:00
}
/**
2005-11-09 00:15:14 +01:00
* Formats one or two dates ( range ) as long date ( full monthname ), optionaly with a time
2004-08-01 17:36:04 +02:00
*
2005-11-09 00:15:14 +01:00
* @ param mixed $first first date
2006-06-20 21:55:06 +02:00
* @ param mixed $last = 0 last date if != 0 ( default )
* @ param boolean $display_time = false should a time be displayed too
* @ param boolean $display_day = false should a day - name prefix the date , eg . monday June 20 , 2006
2004-08-01 17:36:04 +02:00
* @ return string with formated date
*/
2006-06-20 21:55:06 +02:00
function long_date ( $first , $last = 0 , $display_time = false , $display_day = false )
2004-08-01 17:36:04 +02:00
{
$first = $this -> date2array ( $first );
if ( $last )
{
$last = $this -> date2array ( $last );
}
$datefmt = $this -> common_prefs [ 'dateformat' ];
2005-11-09 00:15:14 +01:00
$timefmt = $this -> common_prefs [ 'timeformat' ] == 12 ? 'h:i a' : 'H:i' ;
2004-08-01 17:36:04 +02:00
$month_before_day = strtolower ( $datefmt [ 0 ]) == 'm' ||
strtolower ( $datefmt [ 2 ]) == 'm' && $datefmt [ 4 ] == 'd' ;
2006-06-20 21:55:06 +02:00
if ( $display_day )
{
2008-05-08 17:02:35 +02:00
$range = lang ( adodb_date ( 'l' , $first [ 'raw' ])) . ( $this -> common_prefs [ 'dateformat' ][ 0 ] != 'd' ? ' ' : ', ' );
2006-06-20 21:55:06 +02:00
}
2004-08-01 17:36:04 +02:00
for ( $i = 0 ; $i < 5 ; $i += 2 )
{
switch ( $datefmt [ $i ])
{
case 'd' :
$range .= $first [ 'day' ] . ( $datefmt [ 1 ] == '.' ? '.' : '' );
if ( $first [ 'month' ] != $last [ 'month' ] || $first [ 'year' ] != $last [ 'year' ])
{
if ( ! $month_before_day )
{
$range .= ' ' . lang ( strftime ( '%B' , $first [ 'raw' ]));
}
if ( $first [ 'year' ] != $last [ 'year' ] && $datefmt [ 0 ] != 'Y' )
{
$range .= ( $datefmt [ 0 ] != 'd' ? ', ' : ' ' ) . $first [ 'year' ];
}
2005-11-09 00:15:14 +01:00
if ( $display_time )
{
$range .= ' ' . adodb_date ( $timefmt , $first [ 'raw' ]);
}
2004-08-01 17:36:04 +02:00
if ( ! $last )
{
return $range ;
}
$range .= ' - ' ;
if ( $first [ 'year' ] != $last [ 'year' ] && $datefmt [ 0 ] == 'Y' )
{
$range .= $last [ 'year' ] . ', ' ;
}
if ( $month_before_day )
{
$range .= lang ( strftime ( '%B' , $last [ 'raw' ]));
}
}
else
{
2005-11-09 00:15:14 +01:00
if ( $display_time )
{
$range .= ' ' . adodb_date ( $timefmt , $first [ 'raw' ]);
}
2004-08-01 17:36:04 +02:00
$range .= ' - ' ;
}
$range .= ' ' . $last [ 'day' ] . ( $datefmt [ 1 ] == '.' ? '.' : '' );
break ;
case 'm' :
case 'M' :
$range .= ' ' . lang ( strftime ( '%B' , $month_before_day ? $first [ 'raw' ] : $last [ 'raw' ])) . ' ' ;
break ;
case 'Y' :
2006-06-20 21:55:06 +02:00
if ( $datefmt [ 0 ] != 'm' )
{
$range .= ' ' . ( $datefmt [ 0 ] == 'Y' ? $first [ 'year' ] . ( $datefmt [ 2 ] == 'd' ? ', ' : ' ' ) : $last [ 'year' ] . ' ' );
}
2004-08-01 17:36:04 +02:00
break ;
}
}
2005-11-09 00:15:14 +01:00
if ( $display_time && $last )
{
$range .= ' ' . adodb_date ( $timefmt , $last [ 'raw' ]);
}
2006-06-20 21:55:06 +02:00
if ( $datefmt [ 4 ] == 'Y' && $datefmt [ 0 ] == 'm' )
{
$range .= ', ' . $last [ 'year' ];
}
2004-08-01 17:36:04 +02:00
return $range ;
}
2008-05-08 17:02:35 +02:00
2006-06-20 21:55:06 +02:00
/**
* Displays a timespan , eg . $both ? " 10:00 - 13:00: 3h " ( 10 : 00 am - 1 pm : 3 h ) : " 10:00 3h " ( 10 : 00 am 3 h )
*
* @ param int $start_m start time in minutes since 0 h
* @ param int $end_m end time in minutes since 0 h
* @ param boolean $both = false display the end - time too , duration is always displayed
*/
function timespan ( $start_m , $end_m , $both = false )
{
$duration = $end_m - $start_m ;
if ( $end_m == 24 * 60 - 1 ) ++ $duration ;
$duration = floor ( $duration / 60 ) . lang ( 'h' ) . ( $duration % 60 ? $duration % 60 : '' );
$timespan = $t = $GLOBALS [ 'egw' ] -> common -> formattime ( sprintf ( '%02d' , $start_m / 60 ), sprintf ( '%02d' , $start_m % 60 ));
2008-05-08 17:02:35 +02:00
2006-06-20 21:55:06 +02:00
if ( $both ) // end-time too
{
$timespan .= ' - ' . $GLOBALS [ 'egw' ] -> common -> formattime ( sprintf ( '%02d' , $end_m / 60 ), sprintf ( '%02d' , $end_m % 60 ));
// dont double am/pm if they are the same in both times
if ( $this -> common_prefs [ 'timeformat' ] == 12 && substr ( $timespan , - 2 ) == substr ( $t , - 2 ))
{
$timespan = str_replace ( $t , substr ( $t , 0 , - 3 ), $timespan );
}
$timespan .= ':' ;
}
return $timespan . ' ' . $duration ;
}
2004-08-01 17:36:04 +02:00
2005-11-09 00:15:14 +01:00
/**
* Converts a participant into a ( readable ) user - or resource - name
*
* @ param $id string / int id of user or resource
* @ return string with name
*/
function participant_name ( $id , $use_type = false )
{
static $id2lid = array ();
2008-05-08 17:02:35 +02:00
2006-03-05 11:26:03 +01:00
if ( $use_type && $use_type != 'u' ) $id = $use_type . $id ;
2005-11-09 00:15:14 +01:00
if ( ! isset ( $id2lid [ $id ]))
{
2006-03-05 11:26:03 +01:00
if ( ! is_numeric ( $id ))
2005-11-09 00:15:14 +01:00
{
2008-05-08 17:02:35 +02:00
$id2lid [ $id ] = '#' . $id ;
if (( $info = $this -> resource_info ( $id )))
{
$id2lid [ $id ] = $info [ 'name' ] ? $info [ 'name' ] : $info [ 'email' ];
}
2005-11-09 00:15:14 +01:00
}
else
{
$id2lid [ $id ] = $GLOBALS [ 'egw' ] -> common -> grab_owner_name ( $id );
}
}
return $id2lid [ $id ];
}
2004-08-01 17:36:04 +02:00
/**
* Converts participants array of an event into array of ( readable ) participant - names with status
*
2005-11-23 15:21:20 +01:00
* @ param array $event event - data
2006-12-13 08:28:20 +01:00
* @ param boolean $long_status = false should the long / verbose status or an icon be use
2006-03-16 19:03:43 +01:00
* @ param boolean $show_group_invitation = false show group - invitations ( status == 'G' ) or not ( default )
2004-08-01 17:36:04 +02:00
* @ return array with id / names with status pairs
*/
2006-12-13 08:28:20 +01:00
function participants ( $event , $long_status = false , $show_group_invitation = false )
2004-08-01 17:36:04 +02:00
{
2006-12-13 08:28:20 +01:00
//_debug_array($event);
$names = array ();
2005-11-09 00:15:14 +01:00
foreach ( $event [ 'participants' ] as $id => $status )
2004-08-01 17:36:04 +02:00
{
2006-03-16 19:03:43 +01:00
if ( $status == 'G' && ! $show_group_invitation ) continue ; // dont show group-invitation
2005-11-23 15:21:20 +01:00
2006-12-13 08:28:20 +01:00
if ( ! $long_status )
2006-12-06 14:56:17 +01:00
{
2006-12-13 08:28:20 +01:00
switch ( $status )
{
case 'A' : // accepted
2008-03-25 16:38:52 +01:00
$status = html :: image ( 'calendar' , 'agt_action_success' , $this -> verbose_status [ $status ]);
2006-12-13 08:28:20 +01:00
break ;
case 'R' : // rejected
2008-03-25 16:38:52 +01:00
$status = html :: image ( 'calendar' , 'agt_action_fail' , $this -> verbose_status [ $status ]);
2006-12-13 08:28:20 +01:00
break ;
case 'T' : // tentative
2008-03-25 16:38:52 +01:00
$status = html :: image ( 'calendar' , 'tentative' , $this -> verbose_status [ $status ]);
2006-12-13 08:28:20 +01:00
break ;
case 'U' : // no response = unknown
2008-03-25 16:38:52 +01:00
$status = html :: image ( 'calendar' , 'cnr-pending' , $this -> verbose_status [ $status ]);
2006-12-13 08:28:20 +01:00
break ;
case 'G' : // group invitation
// Todo: Image, seems not to be used
2006-12-13 09:26:57 +01:00
$status = '(' . $this -> verbose_status [ $status ] . ')' ;
2006-12-13 08:28:20 +01:00
break ;
}
2006-12-06 14:56:17 +01:00
}
2006-12-13 08:28:20 +01:00
else
2004-08-01 17:36:04 +02:00
{
2006-12-13 09:26:57 +01:00
$status = '(' . $this -> verbose_status [ $status ] . ')' ;
2004-08-01 17:36:04 +02:00
}
2006-12-06 14:56:17 +01:00
$names [ $id ] = $this -> participant_name ( $id ) . ' ' . $status ;
2004-08-01 17:36:04 +02:00
}
return $names ;
}
/**
* Converts category string of an event into array of ( readable ) category - names
*
* @ param $category string cat - id ( multiple id ' s commaseparated )
* @ param $color int color of the category , if multiple cats , the color of the last one with color is returned
* @ return array with id / names
*/
function categories ( $category , & $color )
{
static $id2cat = array ();
$cats = array ();
$color = 0 ;
2005-11-09 00:15:14 +01:00
if ( ! is_object ( $this -> cats ))
2004-08-01 17:36:04 +02:00
{
2005-11-09 00:15:14 +01:00
$this -> cats =& CreateObject ( 'phpgwapi.categories' , '' , 'calendar' );
2004-08-01 17:36:04 +02:00
}
foreach ( explode ( ',' , $category ) as $cat_id )
{
if ( ! $cat_id ) continue ;
if ( ! isset ( $id2cat [ $cat_id ]))
{
2005-11-09 00:15:14 +01:00
list ( $id2cat [ $cat_id ]) = $this -> cats -> return_single ( $cat_id );
2004-08-01 17:36:04 +02:00
$id2cat [ $cat_id ][ 'data' ] = unserialize ( $id2cat [ $cat_id ][ 'data' ]);
}
$cat = $id2cat [ $cat_id ];
if ( $cat [ 'data' ][ 'color' ] || preg_match ( '/(#[0-9A-Fa-f]{6})/' , $cat [ 'description' ], $parts ))
{
$color = $cat [ 'data' ][ 'color' ] ? $cat [ 'data' ][ 'color' ] : $parts [ 1 ];
}
$cats [ $cat_id ] = stripslashes ( $cat [ 'name' ]);
}
return $cats ;
}
/* This is called only by list_cals(). It was moved here to remove fatal error in php5 beta4 */
function _list_cals_add ( $id , & $users , & $groups )
{
2005-11-09 00:15:14 +01:00
$name = $GLOBALS [ 'egw' ] -> common -> grab_owner_name ( $id );
if (( $type = $GLOBALS [ 'egw' ] -> accounts -> get_type ( $id )) == 'g' )
2004-08-01 17:36:04 +02:00
{
$arr = & $groups ;
}
else
{
$arr = & $users ;
}
$arr [ $name ] = Array (
'grantor' => $id ,
'value' => ( $type == 'g' ? 'g_' : '' ) . $id ,
'name' => $name
);
}
/**
* generate list of user - / group - calendars for the selectbox in the header
* @ return alphabeticaly sorted array with groups first and then users
*/
function list_cals ()
{
$users = $groups = array ();
foreach ( $this -> grants as $id => $rights )
{
$this -> _list_cals_add ( $id , $users , $groups );
}
2005-11-09 00:15:14 +01:00
if ( $memberships = $GLOBALS [ 'egw' ] -> accounts -> membership ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'account_id' ]))
2004-08-01 17:36:04 +02:00
{
foreach ( $memberships as $group_info )
{
$this -> _list_cals_add ( $group_info [ 'account_id' ], $users , $groups );
2005-11-09 00:15:14 +01:00
if ( $account_perms = $GLOBALS [ 'egw' ] -> acl -> get_ids_for_location ( $group_info [ 'account_id' ], EGW_ACL_READ , 'calendar' ))
2004-08-01 17:36:04 +02:00
{
foreach ( $account_perms as $id )
{
$this -> _list_cals_add ( $id , $users , $groups );
}
}
}
}
uksort ( $users , 'strnatcasecmp' );
uksort ( $groups , 'strnatcasecmp' );
return $users + $groups ; // users first and then groups, both alphabeticaly
}
2008-05-08 17:02:35 +02:00
2005-12-02 16:34:45 +01:00
/**
* Convert the recure - information of an event , into a human readable string
*
* @ param array $event
2008-05-08 17:02:35 +02:00
* @ return string
2005-12-02 16:34:45 +01:00
*/
function recure2string ( $event )
{
$str = '' ;
// Repeated Events
if ( $event [ 'recur_type' ] != MCAL_RECUR_NONE )
{
$str = lang ( $this -> recur_types [ $event [ 'recur_type' ]]);
$str_extra = array ();
if ( $event [ 'recur_enddate' ])
{
$str_extra [] = lang ( 'ends' ) . ': ' . lang ( $this -> format_date ( $event [ 'recur_enddate' ], 'l' )) . ', ' . $this -> long_date ( $event [ 'recur_enddate' ]) . ' ' ;
}
// only weekly uses the recur-data (days) !!!
if ( $event [ 'recur_type' ] == MCAL_RECUR_WEEKLY )
{
$repeat_days = array ();
foreach ( $this -> recur_days as $mcal_mask => $dayname )
{
if ( $event [ 'recur_data' ] & $mcal_mask )
{
$repeat_days [] = lang ( $dayname );
}
}
if ( count ( $repeat_days ))
{
$str_extra [] = lang ( 'days repeated' ) . ': ' . implode ( ', ' , $repeat_days );
}
}
2007-04-11 11:52:06 +02:00
if ( $event [ 'recur_interval' ] > 1 )
2005-12-02 16:34:45 +01:00
{
$str_extra [] = lang ( 'Interval' ) . ': ' . $event [ 'recur_interval' ];
}
if ( count ( $str_extra ))
{
$str .= ' (' . implode ( ', ' , $str_extra ) . ')' ;
}
}
return $str ;
}
2004-08-01 17:36:04 +02:00
/**
* Read the holidays for a given $year
*
2005-11-09 00:15:14 +01:00
* The holidays get cached in the session ( performance ), so changes in holidays or birthdays do NOT affect a current session !!!
*
* @ param integer $year = 0 year , defaults to 0 = current year
2004-08-01 17:36:04 +02:00
* @ return array indexed with Ymd of array of holidays . A holiday is an array with the following fields :
2005-11-09 00:15:14 +01:00
* index : numerical unique id
2004-08-01 17:36:04 +02:00
* locale : string , 2 - char short for the nation
* name : string
* day : numerical day in month
* month : numerical month
2005-11-09 00:15:14 +01:00
* occurence : numerical year or 0 for every year
2004-08-01 17:36:04 +02:00
* dow : day of week , 0 = sunday , .. , 6 = saturday
* observande_rule : boolean
*/
function read_holidays ( $year = 0 )
{
2005-11-09 00:15:14 +01:00
if ( ! $year ) $year = ( int ) date ( 'Y' , $this -> now_su );
if ( ! $this -> cached_holidays ) // try reading the holidays from the session
{
$this -> cached_holidays = $GLOBALS [ 'egw' ] -> session -> appsession ( 'holidays' , 'calendar' );
}
2004-08-01 17:36:04 +02:00
if ( ! isset ( $this -> cached_holidays [ $year ]))
{
if ( ! is_object ( $this -> holidays ))
{
2005-11-09 00:15:14 +01:00
$this -> holidays =& CreateObject ( 'calendar.boholiday' );
2004-08-01 17:36:04 +02:00
}
$this -> holidays -> prepare_read_holidays ( $year );
$this -> cached_holidays [ $year ] = $this -> holidays -> read_holiday ();
2008-05-08 17:02:35 +02:00
2005-11-09 00:15:14 +01:00
// search for birthdays
2008-01-17 06:58:10 +01:00
if ( $GLOBALS [ 'egw_info' ][ 'server' ][ 'hide_birthdays' ] != 'yes' )
2005-11-09 00:15:14 +01:00
{
2008-01-17 06:58:10 +01:00
$contacts =& CreateObject ( 'phpgwapi.contacts' );
$bdays =& $contacts -> read ( 0 , 0 , array ( 'id' , 'n_family' , 'n_given' , 'n_prefix' , 'n_middle' , 'bday' ), '' , " bday=!'',n_family=!'' " , 'ASC' , 'bday' );
if ( $bdays )
2005-11-09 00:15:14 +01:00
{
2008-01-17 06:58:10 +01:00
// sort by month and day only
usort ( $bdays , create_function ( '$a,$b' , 'return (int) $a[\'bday\'] == (int) $b[\'bday\'] ? strcmp($a[\'bday\'],$b[\'bday\']) : (int) $a[\'bday\'] - (int) $b[\'bday\'];' ));
foreach ( $bdays as $pers )
{
list ( $m , $d , $y ) = explode ( '/' , $pers [ 'bday' ]);
if ( $y > $year ) continue ; // not yet born
$this -> cached_holidays [ $year ][ sprintf ( '%04d%02d%02d' , $year , $m , $d )][] = array (
'day' => $d ,
'month' => $m ,
'occurence' => 0 ,
'name' => lang ( 'Birthday' ) . ' ' . ( $pers [ 'n_given' ] ? $pers [ 'n_given' ] : $pers [ 'n_prefix' ]) . ' ' . $pers [ 'n_middle' ] . ' ' .
$pers [ 'n_family' ] . ( $y && ! $GLOBALS [ 'egw_info' ][ 'server' ][ 'hide_birthdays' ] ? ' (' . $y . ')' : '' ),
'birthyear' => $y , // this can be used to identify birthdays from holidays
);
}
2005-11-09 00:15:14 +01:00
}
}
2008-05-08 17:02:35 +02:00
// store holidays and birthdays in the session
2005-11-09 00:15:14 +01:00
$this -> cached_holidays = $GLOBALS [ 'egw' ] -> session -> appsession ( 'holidays' , 'calendar' , $this -> cached_holidays );
}
if (( int ) $this -> debug >= 2 || $this -> debug == 'read_holidays' )
{
$this -> debug_message ( 'bocal::read_holidays(%1)=%2' , true , $year , $this -> cached_holidays [ $year ]);
2004-08-01 17:36:04 +02:00
}
return $this -> cached_holidays [ $year ];
}
2008-05-08 17:02:35 +02:00
2005-11-09 00:15:14 +01:00
/**
* get title for an event identified by $event
2008-05-08 17:02:35 +02:00
*
2005-11-09 00:15:14 +01:00
* Is called as hook to participate in the linking
*
* @ param int / array $entry int cal_id or array with event
2006-06-24 18:04:06 +02:00
* @ param string / boolean string with title , null if not found or false if not read perms
2005-11-09 00:15:14 +01:00
*/
function link_title ( $event )
{
if ( ! is_array ( $event ) && ( int ) $event > 0 )
{
$event = $this -> read ( $event );
}
if ( ! is_array ( $event ))
{
2006-06-24 18:04:06 +02:00
return $event ;
2005-11-09 00:15:14 +01:00
}
return $this -> format_date ( $event [ 'start' ]) . ': ' . $event [ 'title' ];
}
/**
* query calendar for events matching $pattern
*
* Is called as hook to participate in the linking
*
* @ param string $pattern pattern to search
* @ return array with pm_id - title pairs of the matching entries
*/
function link_query ( $pattern )
{
$result = array ();
foreach (( array ) $this -> search ( array ( 'query' => $pattern )) as $event )
{
$result [ $event [ 'id' ]] = $this -> link_title ( $event );
}
return $result ;
}
2008-05-08 17:02:35 +02:00
2005-11-09 00:15:14 +01:00
/**
2005-11-12 18:57:18 +01:00
* Hook called by link - class to include calendar in the appregistry of the linkage
2005-11-09 00:15:14 +01:00
*
* @ param array / string $location location and other parameters ( not used )
* @ return array with method - names
*/
function search_link ( $location )
{
return array (
'query' => 'calendar.bocal.link_query' ,
'title' => 'calendar.bocal.link_title' ,
'view' => array (
2006-12-22 20:51:56 +01:00
'menuaction' => 'calendar.uiforms.edit' ,
2005-11-09 00:15:14 +01:00
),
2005-11-10 15:56:06 +01:00
'view_id' => 'cal_id' ,
'view_popup' => '750x400' ,
'add' => array (
2005-11-09 00:15:14 +01:00
'menuaction' => 'calendar.uiforms.edit' ,
),
'add_app' => 'link_app' ,
2008-05-08 17:02:35 +02:00
'add_id' => 'link_id' ,
2005-11-10 15:56:06 +01:00
'add_popup' => '750x400' ,
2005-11-09 00:15:14 +01:00
);
}
/**
* sets the default prefs , if they are not already set ( on a per pref . basis )
*
* It sets a flag in the app - session - data to be called only once per session
*/
function check_set_default_prefs ()
{
2006-04-05 16:38:07 +02:00
if ( $this -> cal_prefs [ 'interval' ] && ( $set = $GLOBALS [ 'egw' ] -> session -> appsession ( 'default_prefs_set' , 'calendar' )))
2005-11-09 00:15:14 +01:00
{
return ;
}
$GLOBALS [ 'egw' ] -> session -> appsession ( 'default_prefs_set' , 'calendar' , 'set' );
$default_prefs =& $GLOBALS [ 'egw' ] -> preferences -> default [ 'calendar' ];
2006-08-25 10:17:40 +02:00
if ( ! ( $planner_start_with_group = $GLOBALS [ 'egw' ] -> accounts -> name2id ( 'Default' )))
{
$planner_start_with_group = '0' ;
}
2005-11-09 00:15:14 +01:00
$subject = lang ( 'Calendar Event' ) . ' - $$action$$: $$startdate$$ $$title$$' . " \n " ;
$defaults = array (
'defaultcalendar' => 'week' ,
'mainscreen_showevents' => '0' ,
'summary' => 'no' ,
'receive_updates' => 'no' ,
'update_format' => 'extended' ,
'notifyAdded' => $subject . lang ( 'You have a meeting scheduled for %1' , '$$startdate$$' ),
'notifyCanceled' => $subject . lang ( 'Your meeting scheduled for %1 has been canceled' , '$$startdate$$' ),
'notifyModified' => $subject . lang ( 'Your meeting that had been scheduled for %1 has been rescheduled to %2' , '$$olddate$$' , '$$startdate$$' ),
'notifyDisinvited' => $subject . lang ( 'You have been disinvited from the meeting at %1' , '$$startdate$$' ),
'notifyResponse' => $subject . lang ( 'On %1 %2 %3 your meeting request for %4' , '$$date$$' , '$$fullname$$' , '$$action$$' , '$$startdate$$' ),
'notifyAlarm' => lang ( 'Alarm for %1 at %2 in %3' , '$$title$$' , '$$startdate$$' , '$$location$$' ) . " \n " . lang ( 'Here is your requested alarm.' ),
'show_rejected' => '0' ,
'display_status' => '1' ,
'weekdaystarts' => 'Monday' ,
'workdaystarts' => '9' ,
'workdayends' => '17' ,
'interval' => '30' ,
'defaultlength' => '60' ,
2006-08-25 10:17:40 +02:00
'planner_start_with_group' => $planner_start_with_group ,
2005-11-09 00:15:14 +01:00
'defaultfilter' => 'all' ,
'default_private' => '0' ,
);
foreach ( $defaults as $var => $default )
{
2006-08-25 10:17:40 +02:00
if ( ! isset ( $default_prefs [ $var ]) || ( string ) $default_prefs [ $var ] == '' )
2005-11-09 00:15:14 +01:00
{
$GLOBALS [ 'egw' ] -> preferences -> add ( 'calendar' , $var , $default , 'default' );
$this -> cal_prefs [ $var ] = $default ;
$need_save = True ;
}
}
if ( $need_save )
{
$GLOBALS [ 'egw' ] -> preferences -> save_repository ( False , 'default' );
}
}
2008-05-08 17:02:35 +02:00
2006-07-15 01:24:56 +02:00
/**
* Get the freebusy URL of a user
*
* @ param int / string $user account_id or account_lid
* @ param string $pw = null password
*/
function freebusy_url ( $user , $pw = null )
{
if ( is_numeric ( $user )) $user = $GLOBALS [ 'egw' ] -> accounts -> id2name ( $user );
2008-05-08 17:02:35 +02:00
return ( ! $GLOBALS [ 'egw_info' ][ 'server' ][ 'webserver_url' ] || $GLOBALS [ 'egw_info' ][ 'server' ][ 'webserver_url' ][ 0 ] == '/' ?
2006-07-15 01:24:56 +02:00
( $_SERVER [ 'HTTPS' ] ? 'https://' : 'http://' ) . $_SERVER [ 'HTTP_HOST' ] : '' ) .
$GLOBALS [ 'egw_info' ][ 'server' ][ 'webserver_url' ] . '/calendar/freebusy.php?user=' . urlencode ( $user ) .
( $pw ? '&password=' . urlencode ( $pw ) : '' );
}
2005-11-09 00:15:14 +01:00
}
if ( ! function_exists ( 'array_intersect_key' )) // php5.1 function
{
function array_intersect_key ( $array1 , $array2 )
{
$intersection = $keys = array ();
foreach ( func_get_args () as $arr )
{
2005-11-11 22:51:00 +01:00
$keys [] = array_keys (( array ) $arr );
2005-11-09 00:15:14 +01:00
}
foreach ( call_user_func_array ( 'array_intersect' , $keys ) as $key )
{
$intersection [ $key ] = $array1 [ $key ];
}
return $intersection ;
}
2004-08-01 17:36:04 +02:00
}