month, $this->day, $this->year);
switch ($this->view)
{
case 'week':
$skipback = day_of_MRBS_week($time);
$this->day_start_interval = $this->day - $skipback;
$this->n_days = DAYS_PER_WEEK;
$this->start_dow = $weekstarts;
break;
case 'month':
$this->day_start_interval = 1;
$this->n_days = (int) date('t', $time);
$this->start_dow = (int) date('N', mktime(12, 0, 0, $this->month, 1, $this->year));
break;
default:
trigger_error("Unsupported view '$this->view'", E_USER_WARNING);
break;
}
$this->start_date = (new DateTime())->setTimestamp(get_start_first_slot($this->month, $this->day_start_interval, $this->year));
$this->end_date = (new DateTime())->setTimestamp(get_end_last_slot($this->month, $this->day_start_interval + $this->n_days-1, $this->year));
// Get the data. It's much quicker to do a single SQL query getting all the
// entries for the interval in one go, rather than doing a query for each day.
$entries = get_entries_by_area($this->area_id, $this->start_date, $this->end_date);
// We want to build an array containing all the data we want to show and then spit it out.
$this->map = new Map($this->start_date, $this->end_date, $resolution);
$this->map->addEntries($entries);
}
// TODO: Handle the case where there is more than one booking per slot
public function innerHTML(): string
{
global $row_labels_both_sides, $column_labels_both_ends;
global $view_all_always_go_to_day_view;
// It's theoretically possible to display a transposed table with rooms along the top and days
// down the side. However, it doesn't seem a very useful display and so hasn't yet been implemented.
// The problem is that the results don't look good whether you have the flex direction as 'row' or
// 'column'. If you set it to 'row' the bookings are read from left to right within a day, but from
// top to bottom within the interval (week/month), so you have to read the display by snaking down
// the columns, which is potentially confusing. If you set it to 'column' then the bookings are in
// order reading straight down the column, but the text within the bookings is usually clipped unless
// the booking lasts the whole day. When the days are along the top and the text is clipped you can
// at least see the first few characters which is useful, but when the days are down the side you only
// see the top of the line.
//
// As a result $days_along_top is always true, but is here so that there can be stubs in the code in
// case people want a transposed view in future.
$days_along_top = true;
$rooms = get_rooms($this->area_id);
$n_rooms = count($rooms);
// Check to see whether there are any rooms in the area
if ($n_rooms == 0)
{
// Add an 'empty' data flag so that the JavaScript knows whether this is a real table or not
return "
" . get_vocab("no_rooms_for_area") . " |
";
}
// TABLE HEADER
$thead = 'getSlots($this->month, $this->day_start_interval, $this->year, $this->n_days, true);
if (isset($slots))
{
// Add some data to enable the JavaScript to draw the timeline
$thead .= ' data-slots="' . escape_html(json_encode($slots)) . '"';
$thead .= ' data-timeline-vertical="' . (($days_along_top) ? 'true' : 'false') . '"';
$thead .= ' data-timeline-full="true"';
}
$thead .= ">\n";
if ($days_along_top)
{
$header_inner_rows = $this->multidayHeaderRowsHTML($this->day_start_interval, $this->n_days, $this->start_dow);
}
else
{
// See comment above
trigger_error("Not yet implemented", E_USER_WARNING);
}
$thead .= implode('', $header_inner_rows);
$thead .= "\n";
// Now repeat the header in a footer if required
$tfoot = ($column_labels_both_ends) ? "\n" . implode('',array_reverse($header_inner_rows)) . "\n" : '';
// TABLE BODY LISTING BOOKINGS
$tbody = "\n";
$room_link_vars = [
'view' => $this->view,
'view_all' => 0,
'page_date' => format_iso_date($this->year, $this->month, $this->day),
'area' => $this->area_id
];
if ($days_along_top)
{
// the standard view, with days along the top and rooms down the side
foreach ($rooms as $room)
{
$room_id = $room['id'];
$room_link_vars['room'] = $room_id;
$tbody .= "\n";
$row_label = $this->roomCellHTML($room, $room_link_vars);
$tbody .= $row_label;
for ($j = 0, $date = clone $this->start_date; $j < $this->n_days; $j++, $date->modify('+1 day'))
{
if ($date->isHiddenDay())
{
continue;
}
// Add classes for weekends, holidays, etc.
$classes = $this->getDateClasses($date);
$tbody .= '| $this->view_all,
'page_date' => $date->getISODate(),
'area' => $this->area_id,
'room' => $room['id']
];
// If there is more than one slot per day, then it can be very difficult to pick
// out an individual one, which could be just one pixel wide, so we go to the
// day view first where it's easier to see what you are doing. Otherwise, we go
// direct to edit_entry.php if the slot is free, or view_entry.php if it is not.
// Note: the structure of the cell, with a single link and multiple flex divs,
// only allows us to direct to the booking if there's only one slot per day.
if ($view_all_always_go_to_day_view || (self::getNTimeSlots() > 1))
{
$page = 'index.php';
$vars['view'] = 'day';
}
else
{
$vars['view'] = $this->view;
$this_slot = $this->map->slot($room_id, $j, Calendar::morningSlotsSeconds());
if (empty($this_slot))
{
$page = 'edit_entry.php';
}
else
{
$page = 'view_entry.php';
$vars['id'] = $this_slot[0]['id'];
}
}
$link = "$page?" . http_build_query($vars, '', '&');
$link = multisite($link);
$tbody .= '\n";
$tbody .= $this->flexDivsHTML($room_id, $j, $j);
$tbody .= "\n";
$tbody .= " | \n";
}
if ($row_labels_both_sides)
{
$tbody .= $row_label;
}
$tbody .= "
\n";
}
}
else
{
// See comment above
trigger_error("Not yet implemented", E_USER_WARNING);
}
$tbody .= "\n";
return $thead . $tfoot . $tbody;
}
}