This is a calendar to layout an array of events/classes (from an API) in calendar format:
Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday time event | event | event | event | event | event | event time event | event | event | event | event | event | event time event | event | event | event | event | event | event time event | event | event | event | event | event | event time event | event | event | event | event | event | event time event | event | event | event | event | event | event
This is the function the array of events is fed to:
<?php
function sortClassesByTimeThenDay($mz_classes = array()) {
$mz_classesByTime = array();
// Add top level value to each class to store day of week
for($i=0;$i<count($mz_classes);$i++)
{
$mz_classes[$i]['day_num'] = '';
}
foreach($mz_classes as &$class)
{
/* Create a new array with a key for each time
and corresponsing value an array of class details
for classes at that time. */
$classTime = date_i18n("G.i", strtotime($class['StartDateTime'])); // for numerical sorting
$display_time = (date_i18n("g:i a", strtotime($class['StartDateTime'])));
$classDay = date_i18n("l", strtotime($class['StartDateTime'])); // Weekday name
$class['day_num'] = date_i18n("N", strtotime($class['StartDateTime'])); // Weekday num 1-7
if(!empty($mz_classesByTime[$classTime])) {
$mz_classesByTime[$classTime]['classes'] = array_merge($mz_classesByTime[$classTime]['classes'], array($class));
} else {
$mz_classesByTime[$classTime] = array('display_time' => $display_time,
'classes' => array($class));
}
}
/* Timeslot keys in new array are not time-sequenced so do so*/
ksort($mz_classesByTime);
foreach($mz_classesByTime as $scheduleTime => &$mz_classes)
{
/*
$mz_classes is an array of all classes for given time
Take each of the class arrays and order it by days 1-7
*/
usort($mz_classes['classes'], function($a, $b) {
if(date_i18n("N", strtotime($a['StartDateTime'])) == date_i18n("N", strtotime($b['StartDateTime']))) {
return 0;
}
return $a['StartDateTime'] < $b['StartDateTime'] ? -1 : 1;
});
$mz_classes['classes'] = week_of_timeslot($mz_classes['classes'], 'day_num');
}
return $mz_classesByTime;
}
function week_of_timeslot($array, $indicator){
/*
Make a clean array with seven corresponding slots and populate
based on indicator (day) for each class. There may be more than
one event for each day and empty arrays will represent empty time slots.
*/
$seven_days = array_combine(range(1, 7), array(array(), array(), array(),
array(), array(), array(), array()));
foreach($seven_days as $key => $value){
foreach ($array as $class) {
if ($class[$indicator] == $key){
array_push($seven_days[$key], $class);
}
}
}
return $seven_days;
}
?>
And using HTML Table Class, the calendar is displayed:
<?php
$mz_days = sortClassesByTimeThenDay($mz_days);
$tbl = new HTML_Table('', 'mz-schedule-filter');
$tbl->addTSection('thead');
$tbl->addRow();
// arguments: cell content, class, type (default is 'data' for td, pass 'header' for th)
// can include associative array of optional additional attributes
$tbl->addCell('', '', 'header');
$tbl->addCell('Monday', '', 'header');
$tbl->addCell('Tuesday', '', 'header');
$tbl->addCell('Wednesday', '', 'header');
$tbl->addCell('Thursday', '', 'header');
$tbl->addCell('Friday', '', 'header');
$tbl->addCell('Saturday', '', 'header');
$tbl->addCell('Sunday', '', 'header');
$tbl->addTSection('tbody');
foreach($mz_days as $classDate => $mz_classes)
{
$tbl->addRow();
$tbl->addCell($time_of_day, 'hidden', 'data');
$tbl->addCell($mz_classes['display_time']);
foreach($mz_classes['classes'] as $key => $classes)
{
if(empty($classes)){
$class_details = '';
}else{
$class_details = '';
$class_separator = (count($classes) > 1) ? '<hr/>' : '';
foreach($classes as $class){
$className = $class['ClassDescription']['Name'];
}
}
}
$tbl->addCell($class_details, 'mz_description_holder');
}//end foreach mz_classes
}//end foreach mz_days
$return .= $tbl->display();
?>
I'd like input on styling, comments, syntax, and I'm especially interested in ways to reduce the number of loops being run in sortClassesByTimeThenDay()
.
It seems like maybe array_map
could be used to insert the ordered events into the seven day matrix/array or possibly usort
and week_of_timeslot
could be combined, but not sure how. At the moment I'm basking in the miracle that I made it work at all.