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; } }