room_reservation module as it exists on rooms.library.upei.ca. rooms.lib.. seemed like a clean module from drupal.org. Due to covid we have had to make some changes, I am tracking them here (pp).
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

345 lines
14 KiB

<?php
/**
* @file
* Calendar controller functionality.
*/
/**
* Display the reservation calendar.
*
* @param int $selected_month
* (optional) The month of the day selected by the user.
* @param int $selected_day
* (optional) The day of the month selected by the user.
*
* @return string
* The page display formatted as HTML.
*/
function room_reservations($selected_month = NULL, $selected_day = NULL) {
// likely no need for this as not used anywhere else; but maybe for external modules
global $yyyymmdd;
// dates are now keyed by Cat ID; but we only need anyone of these to build calendar but make sure its the one which starts earliest
$datesbycat = _room_reservations_dates($selected_month, $selected_day);
$categories = _room_reservations_categories();
// allow other modules to alter the categories
drupal_alter('room_reservations_categories', $categories);
// if no Categories left; we should not bother with the rest of this
if (!count($categories)) {
drupal_set_message(t('There are no configured Room Categories. Please contact the System Administrator'), 'warning');
drupal_goto();
}
$earliest = _room_reservations_earliest_category($categories);
$dates = $datesbycat[$earliest];
// Determine which day has been selected by the user. If the user has entered a url that specifies a day outside of the
// allowable reservation window, then set the current day as the selected day.
$yyyymmdd = $dates[0]['yyyymmdd'];
foreach ($dates as $day) {
if ($day['selected']) {
$yyyymmdd = $day['yyyymmdd'];
}
}
if ($yyyymmdd == $dates[0]['yyyymmdd']) {
$dates[0]['selected'] = TRUE;
$dates[0]['today'] = TRUE;
}
// a bit hacky; but we need to store what the calendar is using for its date so we can use this in theme functions later
//$_SESSION['reservations_current_day'] = $yyyymmdd;
// If the day being displayed is today, only display time slots that are later than the current time minus two hours.
$today_displayed = FALSE;
foreach ($dates as $day) {
if (($day['selected']) && $day['today']) {
$today_displayed = TRUE;
}
}
if ($today_displayed) {
$hours = _room_reservations_hours('limited');
}
else {
$hours = _room_reservations_hours();
}
$_room_reservations_building_hours = _room_reservations_facility_hours();
$display_hours = _room_reservations_hours();
// Determine the open hours (display version) for the date selected by the user.
$building_hours_day = $_room_reservations_building_hours[$yyyymmdd];
$building_hours_display = $building_hours_day['display'];
// For each time slot, determine if the rooms are open or closed.
$building_hours_day = $_room_reservations_building_hours[$yyyymmdd];
$int_first_shift_open = intval($building_hours_day['first_shift_open']);
$int_first_shift_close = intval($building_hours_day['first_shift_close']);
$int_second_shift_open = intval($building_hours_day['second_shift_open']);
$int_second_shift_close = intval($building_hours_day['second_shift_close']);
$open_24 = $building_hours_day['open_24_hours'];
$x = 0;
$buffer = variable_get('room_reservations_before_after_hours', 3) * 100;
foreach ($hours as $time_slot) {
$int_time_slot_time = intval($time_slot['time']);
if ($building_hours_day['open_24_hours']) {
$time_slot['open'] = TRUE;
}
elseif ((($int_time_slot_time >= $int_first_shift_open) && ($int_time_slot_time < $int_first_shift_close)) ||
(($int_time_slot_time >= $int_second_shift_open) && ($int_time_slot_time < $int_second_shift_close))) {
$time_slot['open'] = TRUE;
}
else {
$time_slot['open'] = FALSE;
}
// if not open ALL day let's limit display to start just before first open shift (or 2nd if only one used)
// this assume you must have 1st shift defined and possible 2nd (i.e. can't define only 2nd shift)
if (!$open_24 && $buffer != 300) {
if ($int_first_shift_open < 9999 && ($hours[$x]['time'] < $int_first_shift_open - $buffer)) {
unset($hours[$x]);
}
else {
$hours[$x] = $time_slot;
}
// and do the same for closing
if (isset($hours[$x])) {
if ($int_second_shift_close < 9999) {
if ($hours[$x]['time'] >= $int_second_shift_close + $buffer) {
unset($hours[$x]);
}
}
elseif ($int_first_shift_close < 9999) {
if ($hours[$x]['time'] >= $int_first_shift_close + $buffer) {
unset($hours[$x]);
}
}
}
}
else {
$hours[$x] = $time_slot;
}
$x++;
}
$all_hours = _room_reservations_hours();
$times = _room_reservations_times();
$rooms = _room_reservations_rooms();
// Initialize the $reservations array.
$reservations = array();
foreach ($rooms as $room) {
$room_name = $room['name'];
foreach ($hours as $time_slot) {
$time = $time_slot['time'];
$reservations[$room['nid']][$time] = array(
'time' => $time,
'display' => $time_slot['display'],
'class' => $time_slot['class'],
'id' => '',
'booked' => FALSE,
'start' => FALSE,
'end' => FALSE,
'user' => '',
'name' => '',
);
}
}
$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'room_reservations_reservation')
->fieldCondition('reservation_date', 'value', $yyyymmdd . '%', 'like')
->fieldOrderBy('reservation_time', 'value', 'DESC')
// EFQ respects access so if user does not have access to view a reservation (most likely due to some access module then we will not return a
// reservation for this slot; this means it will not block this slot from being bookable - which is likely worse than being able to
// see the booking title (especially since we have a method to block the title if user really doesn't want anyone to see it)
// so, let's load the reservations as user 1 to make sure we get them all
->addMetaData('account', user_load(1));
$result = $query->execute();
if (isset($result['node'])) {
$result_nids = array_keys($result['node']);
$results = entity_load('node', $result_nids);
foreach ($results as $data) {
$id = $data->nid;
$time = $data->reservation_time[LANGUAGE_NONE][0]['value'];;
$rid = $data->reservation_room[LANGUAGE_NONE][0]['target_id'];
$name = $data->title;
$user_name = $data->name;
$reservations[$rid][$time]['booked'] = TRUE;
$reservations[$rid][$time]['class'] .= ' booked';
$reservations[$rid][$time]['name'] = $name;
$reservations[$rid][$time]['user_name'] = $user_name;
$reservations[$rid][$time]['id'] = $id;
$reservations[$rid][$time]['series_id'] = isset($data->reservation_series_id[LANGUAGE_NONE][0]['value']) ? $data->reservation_series_id[LANGUAGE_NONE][0]['value'] : '';
$reservations[$rid][$time]['user'] = $data->uid;
$reservations[$rid][$time]['blocked'] = isset($data->reservation_block_title[LANGUAGE_NONE][0]['value']) ? $data->reservation_block_title[LANGUAGE_NONE][0]['value'] : 0;
// add rest of slots as booked for the length of this reservation
$length = $data->reservation_length[LANGUAGE_NONE][0]['value'];;
$time_slots = $length / 30;
$reservations[$rid][$time]['slots'] = $time_slots;
$remainder = $length % 30;
if ($remainder > 1) {
$time_slots++;
}
$key = array_search($time, $times);
$x = 2;
while ($x <= $time_slots) {
$key++;
$next_time = $times[$key];
$reservations[$rid][$next_time]['booked'] = TRUE;
if(isset($reservations[$rid][$next_time]['class'])) {
$reservations[$rid][$next_time]['class'] = $reservations[$rid][$next_time]['class'] . ' booked';
}
//$reservations[$rid][$next_time]['class'] .= ' booked';
//$reservations[$rid][$next_time]['class'] = $reservations[$rid][$next_time]['class'] . ' booked';
$x++;
// unclear how we handle wrapping a reservation to the next day; but reservation time slots can't go passed midnight; i.e. slot 47
if ($key == 47) {
break;
}
}
// add in pre/post buffer for setup/takedown (rev 7.x-1.3+)
// - if the slot is part of buffer we add "setup" to class
// - if we don't have admin rights; we also mark it as booked so no one can book in these slots
$category = $categories[$rooms[$rid]['reservations_room_category'][LANGUAGE_NONE][0]['target_id']];
$preslots = $category['prebuffer'] / 30;
$postslots = $category['postbuffer'] / 30;
$startkey = array_search($reservations[$rid][$time]['time'], $times);
$endkey = $startkey + $time_slots;
$k = $startkey - $preslots;
while ($k < $startkey) {
if (!$reservations[$rid][$times[$k]]['booked']) {
$reservations[$rid][$times[$k]]['class'] .= ' setup';
}
$reservations[$rid][$times[$k]]['booked'] = user_access('book over buffer') ? $reservations[$rid][$times[$k]]['booked'] : true;
$k++;
}
$k = $endkey;
while ($k < $endkey + $postslots) {
if (!$reservations[$rid][$times[$k]]['booked']) {
$reservations[$rid][$times[$k]]['class'] .= ' setup';
}
$reservations[$rid][$times[$k]]['booked'] = user_access('book over buffer') ? $reservations[$rid][$times[$k]]['booked'] : true;
$k++;
}
}
}
// Get any room_reservation records for the previous day that might carry over into the selected day.
// Continue to update the $reservation array with that information.
$previous_day = date('Y-m-d', strtotime("$yyyymmdd -1 days"));
$max_length = user_access('create room reservations extended length') ? variable_get('room_reservations_max_length_extended', 120) : variable_get('room_reservations_max_length_standard', 120);
$lhours = _room_reservations_hours();
$rhours = array_reverse($lhours);
$slots = ($max_length / 30) - 1;
$late_times = array();
$search_times = array(
'9999',
'9999',
'9999',
'9999',
'9999',
'9999',
'9999',
);
for ($j = 0; $j < $slots; $j++) {
$hour = $rhours[$j];
$late_times[] = $hour['time'];
$search_times[$j] = $hour['time'];
}
$late_times = array_reverse($late_times);
$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'room_reservations_reservation')
->fieldCondition('reservation_date', 'value', $previous_day . '%', 'like')
->fieldCondition('reservation_time', 'value', $search_times, 'in')
->fieldOrderBy('reservation_time', 'value', 'DESC')
// EFQ respects access so let's load the reservations as user 1 to make sure we get them all
->addMetaData('account', user_load(1));
$result = $query->execute();
if (isset($result['node'])) {
$result_nids = array_keys($result['node']);
$results = entity_load('node', $result_nids);
foreach ($results as $data) {
$id = $data->nid;
$time = $data->reservation_time[LANGUAGE_NONE][0]['value'];
$rid = $data->reservation_room[LANGUAGE_NONE][0]['target_id'];
$length = $data->reservation_length[LANGUAGE_NONE][0]['value'];
//$room_name = $data->room;
$name = $data->title;
$user_name = $data->name;
$time_slots = $length / 30;
$remainder = $length % 30;
if ($remainder > 1) {
$time_slots++;
}
for ($j = 0; $j < (($max_length / 30) - 1); $j++) {
if ($late_times[$j] == $time) {
$carry_over_time_slots = ($time_slots + $j - (($max_length / 30) - 1));
break;
}
}
if ($carry_over_time_slots > 0) {
$reservations[$rid]['0000']['booked'] = TRUE;
$reservations[$rid]['0000']['name'] = $name;
$reservations[$rid]['0000']['user_name'] = $user_name;
$reservations[$rid]['0000']['id'] = $id;
$carry_over_time_slots--;
}
while ($carry_over_time_slots > 0) {
$next_time = $times[$carry_over_time_slots];
$reservations[$rid][$next_time]['booked'] = TRUE;
$carry_over_time_slots--;
}
}
}
$user_reservations = _room_reservations_user_reservations();
$output = '';
$output .= theme('room_reservations', array(
'dates' => $dates,
'categories' => $categories,
'reservations' => $reservations,
'hours' => $hours,
'building_hours' => $_room_reservations_building_hours,
'building_hours_display' => $building_hours_display,
'rooms' => $rooms,
'user_reservations' => $user_reservations));
return $output;
}
function _room_reservations_earliest_category($categories) {
$earliest = 1000;
foreach ($categories as $cat) {
if ($cat['advmin'] < $earliest) {
$earliest = $cat['advmin'];
$result = $cat['nid'];
}
}
return $result;
}
function _room_reservations_get_dates() {
// dates are now keyed by Cat ID; but we only need anyone of these to build calendar but make sure its the one which starts earliest
$datesbycat = _room_reservations_dates($selected_month, $selected_day);
$categories = _room_reservations_categories();
$earliest = _room_reservations_earlist_category($categories);
$dates = $datesbycat[$earliest];
// Determine which day has been selected by the user. If the user has entered a url that specifies a day outside of the
// allowable reservation window, then set the current day as the selected day.
$yyyymmdd = $dates[0]['yyyymmdd'];
foreach ($dates as $day) {
if ($day['selected']) {
$yyyymmdd = $day['yyyymmdd'];
}
}
if ($yyyymmdd == $dates[0]['yyyymmdd']) {
$dates[0]['selected'] = TRUE;
$dates[0]['today'] = TRUE;
}
return $dates;
}