// Next events
function overview_next_events()
{
global $mybb, $settings, $db, $templates, $theme, $lang, $trow;
$trow = alt_trow();
$table_heading = $lang->overview_next_events;
$column1_heading = $lang->overview_event;
$column2_heading = $lang->overview_author;
if($mybb->usergroup['canviewcalendar'] == 1)
{
// Permissions
$query = $db->query("SELECT cid
FROM ".TABLE_PREFIX."calendarpermissions
WHERE gid = '".intval($mybb->user['usergroup'])."'
AND canviewcalendar = '0';");
$cids = $sep = "";
if($db->num_rows($query) != 0)
{
while($groups = $db->fetch_array($query))
{
$cids .= $sep.$groups['cid'];
$sep = ",";
}
$cids = "AND e.cid NOT IN ({$cids})";
}
// TODO: Instead of substracting 24 hours, align to the users timezone boundary.
$today = TIME_NOW - 60*60*24;
// Decide whether we can include private events or not.
if(intval($settings['overview_cache']) > 0)
{
$private = "e.private='0'";
}
else
{
$private = "(e.private='0' OR e.uid='".intval($mybb->user['uid'])."')";
}
// Fetch data; Raphael: we need more from the db for repeated events
$query = $db->query("SELECT e.eid, e.name, e.starttime, e.endtime, e.uid, e.repeats, u.username, u.usergroup, u.displaygroup
FROM ".TABLE_PREFIX."events e
LEFT JOIN ".TABLE_PREFIX."users u ON (e.uid=u.uid)
WHERE e.visible = '1' AND {$private} AND (e.starttime > '{$today}' OR e.endtime > '{$today}') {$cids}
ORDER BY starttime ASC
LIMIT 0,{$settings['overview_max']};");
/* NEW DATE CHECKING MECHANISM by Raphael */
$event_dates = array();
while( $events = $db->fetch_array($query) ){
$repeat_data = unserialize($events['repeats']);
//Check, if repeated event
if( isset($repeat_data) ){
//Create timestamps of this events for the next starts
//Get the starttime for the loop, set to today, if in the past
if( $events['starttime'] < TIME_NOW )
$starttime = mktime(0,0,0,date('m'),date('d'),date('Y'));
else
$starttime = strtotime( date("Y-m-d", $events['starttime']) ); //Truncate -> without time
//Optimized date-generation strategy based on repeat-type
$elements_added = 0; //Control Variable for performance optimized breakpoint
//"Truncate" starttime; get only d.m.Y without time for easy checking
$truncated_starttime = strtotime( date("Y-m-d", $events['starttime']) );
$time_of_starttime = $events['starttime'] - $truncated_starttime;
switch($repeat_data['repeats']){
//No Repeat / DB-Relict
case "0":
array_push($event_dates, array( $events['starttime'] => $events ) );
break;
//Daily repeated event on x days
case "1":
if( !isset($repeat_data['days']) )
$days = 1;
else
$days = $repeat_data['days'];
//Divider for Rule
$divider = $days * (60*60*24);
for( $i = $starttime; $i <= $events['endtime']; $i = $i + (60*60*24) ){
//Check, if current timestamp meet requirements of repeatment rule
//Rule = day_difference is multiple of $days
if( ( $i - $truncated_starttime ) % ($divider) == 0){
//Add Event to list with time for exact sorting
$event_date_time = $i + $time_of_starttime;
array_push($event_dates, array( $event_date_time => $events ) );
$elements_added++;
if( $elements_added == $settings['overview_max']){
break;//break loop, if enough dates
}
}
}
break;
//Weekly repeated event on Workdays (Mo-Fr)
case "2":
//Go through daily
for( $i = $starttime; $i <= $events['endtime']; $i = $i + (60*60*24) ){
//Check, if current timestamp meet requirements of repeatment rule
//Rule = each workday
$number_of_day = date("w", $i);
if( $number_of_day > 0 && $number_of_day < 6 ){
//Add Event to list with time for exact sorting
$event_date_time = $i + $time_of_starttime;
array_push($event_dates, array( $event_date_time => $events ) );
$elements_added++;
if( $elements_added == $settings['overview_max']){
break;//break loop, if enough dates
}
}
}
break;
//Weekly repeated event on x weeks per y days
case "3":
$days = $repeat_data['days']; //Array date("w")
$weeks = $repeat_data['weeks'];
//Multipler for Rule
$multipler = (60*60*24*7);
$kw_startevent = date("W", $truncated_starttime);
//If event_startime is not in $days, but in future, add it
if( !in_array( date("w", $truncated_starttime), $days) && $truncated_starttime >= $starttime ){
//Add Event to list with time for exact sorting
array_push($event_dates, array( $events['starttime'] => $events ) );
$elements_added++;
}
//First loop: Each week
for( $w = $starttime; $w <= $events['endtime']; $w = $w + $multipler ){
//If current week is multiple from start_week + weeks
if( (date("W", $w) - $kw_startevent) % $weeks != 0 )
continue;
//Calc weekbeginning
$weekday = date("N", $w);
if( $weekday != 0 ){
$subtractor = ($weekday -1) * 60*60*24;
} else
$subtractor = 0;
if( ($w - $subtractor) < $starttime ){
$weekbeginning = $w;
} else {
$weekbeginning = $w - $subtractor;
}
$weekend = $w + (7 - $weekday) * 24*60*60;
//Second loop: Days
for( $i = $weekbeginning; $i <= $weekend; $i = $i + (60*60*24) ){
//Check, if current timestamp meet requirements of repeatment rule
//Rule = day is in $days
if( in_array( date("w", $i) , $days) ){
//Add Event to list with time for exact sorting
$event_date_time = $i + $time_of_starttime;
array_push($event_dates, array( $event_date_time => $events ) );
$elements_added++;
if( $elements_added == $settings['overview_max']){
break;//break day loop, if enough dates
}
}
}
if( $elements_added == $settings['overview_max']){
break;//break weekloop, if enough dates
}
}
break;
//Monthly repeated , 2 Suboptions
case "4":
$day = $repeat_data['day'];
$month = $repeat_data['months'];
$occurance = $repeat_data['occurance'];
$weekday = $repeat_data['weekday'];
$event_month_start = date("m", $truncated_starttime);
$counter = 0;
$correction = 0;
//Option 1 - Repeat on day x of month y
if( isset($repeat_data['day']) ){
//Go through monthly
for( $i = $starttime; $i <= $events['endtime']; $i = mktime(0,0,0,date("m",$i)+$month,1,date("Y",$i)) ){
//Check, if current timestamp meet requirements of repeatment rule
//Rule = each day x of month y
$event_date_time = mktime(0,0,0,date("m",$i) - $correction, $day, date("Y",$i), false) + $time_of_starttime;
//Correction for bigger starttime in month than first date-day of beginning
if( $truncated_starttime > $event_date_time )
$correction = $month - 1;
if( $event_date_time >= $starttime && $event_date_time < $events['endtime'] ){
//Add Event to list with time for exact sorting
array_push($event_dates, array( $event_date_time => $events ) );
$elements_added++;
if( $elements_added == $settings['overview_max']){
break;//break loop, if enough dates
}
}
}
} else {
//Option 2 - Repeat on x-th y-day of z months
//Go through monthly
for( $i = $starttime; $i <= $events['endtime']; $i = mktime(0,0,0,date("m",$i)+$month,1,date("Y",$i)) ){
//Check, if current timestamp meet requirements of repeatment rule
//Rule = each day x of month y
//Calc day of month
if( $occurance != "last" ){
$first_weekday_of_month = date("N", mktime(0,0,0,date("m",$i) - $correction,1,date("Y",$i)) );
$day_part = 7 - $first_weekday_of_month + $weekday;
if( $day_part >= 7 )
$day_part -= 7;
$day = $day_part + (($occurance - 1) *7) + 1;
} else {
//MyBB "last of month" Core Calendar has bugs. (E.G. last of month = first of next month); We do it the right way.
$temp_occurance = 5;
$first_weekday_of_month = date("N", mktime(0,0,0,date("m",$i) - $correction,1,date("Y",$i)) );
$last_weekday_of_month_date = date("d", mktime(0,0,0,date("m",$i)+1 - $correction,0,date("Y",$i)) );
$day_part = 7 - $first_weekday_of_month + $weekday;
if( $day_part >= 7 )
$day_part -= 7;
$day = $day_part + (($temp_occurance - 1) *7) + 1;
//If calulated day bigger then last_weekday, reduce occurance to 4
if( $day > $last_weekday_of_month_date)
$day = $day_part + ((4 - 1) *7) + 1;
}
$event_date_time = mktime(0,0,0,date("m",$i) - $correction, $day, date("Y",$i), false) + $time_of_starttime;
//Correction for bigger starttime in month than first date-day of beginning
if( $truncated_starttime > $event_date_time )
$correction = $month - 1;
if( $event_date_time >= $starttime && $event_date_time < $events['endtime'] ){
//Add Event to list with time for exact sorting
array_push($event_dates, array( $event_date_time => $events ) );
$elements_added++;
if( $elements_added == $settings['overview_max']){
break;//break loop, if enough dates
}
}
}
}
break;
//Yearly repeated event on x date of y years
case "5":
$year = $repeat_data['years'];
$month = $repeat_data['month'];
$day = $repeat_data['day'];
$occurance = $repeat_data['occurance'];
$weekday = $repeat_data['weekday'];
$correction = 0;
//Go through yearly
//Option 1 repeat on day x of month y all z years
if( !isset($repeat_data['occurance']) ){
for( $i = $starttime; $i <= $events['endtime']; $i = mktime(0,0,0,date("m",$i),1,date("Y",$i)+$year) ){
//Check, if current timestamp meet requirements of repeatment rule
//Rule = each day x of month y in year z
$event_date_time = mktime(0,0,0,$month, $day, date("Y",$i) - $correction, false) + $time_of_starttime;
//Correction for bigger starttime in month than first date-day of beginning
if( $truncated_starttime > $event_date_time )
$correction = $year - 1;
if( $event_date_time >= $starttime && $event_date_time < $events['endtime'] ){
//Add Event to list with time for exact sorting
array_push($event_dates, array( $event_date_time => $events ) );
$elements_added++;
if( $elements_added == $settings['overview_max']){
break;//break loop, if enough dates
}
}
}
} else {
//Option 2: repeat on a-th occurance of b-day each c-month every d years
//Go through yearly
for( $i = $starttime; $i <= $events['endtime']; $i = mktime(0,0,0,$month,1,date("Y",$i)+$year) ){
//Check, if current timestamp meet requirements of repeatment rule
//Rule
//Calc day of month
if( $occurance != "last" ){
$first_weekday_of_month = date("N", mktime(0,0,0,$month,1,date("Y",$i)- $correction) );
$day_part = 7 - $first_weekday_of_month + $weekday;
if( $day_part >= 7 )
$day_part -= 7;
$day = $day_part + (($occurance - 1) *7) + 1;
} else {
//MyBB "last of month" Core Calendar has bugs. (E.G. last of month = first of next month); We do it the right way.
$temp_occurance = 5;
$first_weekday_of_month = date("N", mktime(0,0,0,$month,1,date("Y",$i) - $correction) );
$last_weekday_of_month_date = date("d", mktime(0,0,0,$month+1,0,date("Y",$i) - $correction) );
$day_part = 7 - $first_weekday_of_month + $weekday;
if( $day_part >= 7 )
$day_part -= 7;
$day = $day_part + (($temp_occurance - 1) *7) + 1;
//If calulated day bigger then last_weekday, reduce occurance to 4
if( $day > $last_weekday_of_month_date)
$day = $day_part + ((4 - 1) *7) + 1;
}
$event_date_time = mktime(0,0,0,date("m",$i), $day, date("Y",$i) - $correction, false) + $time_of_starttime;
//Correction for bigger starttime in month than first date-day of beginning
if( $truncated_starttime > $event_date_time )
$correction = $year - 1;
if( $event_date_time >= $starttime && $event_date_time < $events['endtime'] ){
//Add Event to list with time for exact sorting
array_push($event_dates, array( $event_date_time => $events ) );
$elements_added++;
if( $elements_added == $settings['overview_max']){
break;//break loop, if enough dates
}
}
}
}
break;
}
} else {
//Non repeated Events
array_push($event_dates, array( $events['starttime'] => $events ) );
}
}
//Sort by time asc
usort($event_dates, "sortArrayByDate");
// Print data
foreach( $event_dates as $key => $event ){
if($key == $settings['overview_max'])
break; //Display only as much as needed
$starttime = key($event);
$events = $event[$starttime];
$events['name'] = my_date($settings['dateformat'], $starttime).": ".$events['name'];
$val1 = overview_parsesubject($events['name'], 0, 0, 0, 0, $events['eid'], 0);
$val2 = overview_parseuser($events['uid'], $events['username'], $events['usergroup'], $events['displaygroup']);
eval("\$table_content .= \"".$templates->get("overview_2_columns_row")."\";");
}
}
eval("\$output = \"".$templates->get("overview_2_columns")."\";");
return $output;
}
//Helper for Events
function sortArrayByDate( $a, $b ){
if( key($a) < key($b) )
return -1;
elseif ( key($a) == key($b) )
return 0;
elseif ( key($a) > key($b) )
return 1;
}