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
345 lines
14 KiB
4 years ago
|
<?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;
|
||
|
}
|