Skip to content

Instantly share code, notes, and snippets.

@craigrodway
Last active March 21, 2019 22:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save craigrodway/9950e3214eb1845571c2714d289b38d0 to your computer and use it in GitHub Desktop.
Save craigrodway/9950e3214eb1845571c2714d289b38d0 to your computer and use it in GitHub Desktop.
classroombookings duplicate fix
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Bookings extends MY_Controller
{
public function __construct()
{
parent::__construct();
$this->require_logged_in();
$this->load->model(array(
'crud_model',
'rooms_model',
'periods_model',
'weeks_model',
'users_model',
'holidays_model',
'bookings_model',
));
$this->school = array(
'users' => $this->users_model->Get(NULL, NULL, NULL),
'days_list' => $this->periods_model->days,
);
}
private function _store_query($data = array())
{
$_SESSION['query'] = $data;
}
private function _get_query()
{
if (array_key_exists('query', $_SESSION))
{
return $_SESSION['query'];
}
return array();
}
function index()
{
$query = $this->input->get();
// $this->session->set_userdata('uri', $this->uri->uri_string());
if ( ! isset($query['date']) ) {
$query['date'] = date("Y-m-d");
/*if( $this->session->userdata('chosen_date') ){
#echo "session: {$this->session->userdata('chosen_date')}<br />";
$this->school['chosen_date'] = $this->session->userdata('chosen_date');
}*/
// Day number of the chosen date
$day_num = date('w', strtotime($query['date']));
#$this->school['chosen_date'] = $chosen_date;
#$this->session->set_userdata('chosen_date', $this->school['chosen_date']);
}
$room_of_user = $this->rooms_model->GetByUser($this->userauth->user->user_id);
if ( ! isset($query['room'])) {
if ( ! empty($room_of_user)) {
$query['room'] = $room_of_user->room_id;
} else {
$query['room'] = NULL;
}
}
if ( ! isset($query['direction'])) {
$query['direction'] = 'forward';
}
$this->_store_query($query);
#$this->school['room'] = $uri['room'];
$body['html'] = $this->bookings_model->html(array(
'school' => $this->school,
'query' => $query,
));
/*$body['html'] = $this->M_bookings->htmltable(
$this->school_id,
'day',
'periods',
$chosen_date,
$this->school
);*/
$this->data['title'] = 'Bookings';
$this->data['showtitle'] = '';
$this->data['body'] = $this->session->flashdata('saved');
$this->data['body'] .= $body['html'];
return $this->render();
}
/**
* This function takes the date that was POSTed and loads the view()
*/
function load()
{
$style = $this->bookings_model->BookingStyle();
#$chosen_date = $this->input->post('chosen_date');
$this->load->library('form_validation');
$this->form_validation->set_rules('chosen_date', 'Date', 'max_length[10]|callback_valid_date');
$this->form_validation->set_rules('room_id', 'Room', 'integer');
$this->form_validation->set_rules('direction', 'Diretion', '');
if ($this->form_validation->run() == FALSE) {
show_error("Sorry, the requested details cannot be loaded.");
}
// $query = $this->_get_query();
$query = array(
'direction' => $this->input->post('direction'),
'date' => $this->input->post('chosen_date'),
);
switch ($style['display']) {
case 'day':
// Display type is one day at a time - all rooms/periods
if ($this->input->post('chosen_date')) {
$datearr = explode('/', $this->input->post('chosen_date'));
if (count($datearr) != 3) {
show_error('Invalid date chosen');
}
$query['date'] = date("Y-m-d", mktime(0, 0, 0, $datearr[1], $datearr[0], $datearr[2]));
} else {
show_error('No date chosen');
}
break;
case 'room':
if ($this->input->post('room_id')) {
$query['room'] = $this->input->post('room_id');
} else {
show_error('No day selected');
}
break;
}
$uri = 'bookings/index?' . http_build_query($query);
redirect($uri);
}
function book()
{
$query = $this->input->get();
$this->data['title'] = 'Book a room';
$this->data['showtitle'] = $this->data['title'];
// Either no URI, or all URI info specified
$this->data['hidden'] = new StdClass();
if (isset($query['period']) && isset($query['room']) && isset($query['date'])) {
// Create booking data
$booking = new StdClass();
$booking->booking_id = NULL;
$booking->period_id = $query['period'];
$booking->room_id = $query['room'];
$booking->date = $query['date'];
$booking->notes = '';
$booking->user_id = $this->userauth->user->user_id;
if ($this->userauth->is_level(ADMINISTRATOR)) {
$booking->day_num = isset($query['day']) ? $query['day'] : NULL;
$booking->week_id = isset($query['week']) ? $query['week'] : NULL;
}
$this->data['booking'] = $booking;
$this->data['hidden'] = (array) $booking;
}
// Lookups we need if an admin user
if ($this->userauth->is_level(ADMINISTRATOR)) {
$this->data['days'] = $this->periods_model->days;
$this->data['rooms'] = $this->rooms_model->Get();
$this->data['periods'] = $this->periods_model->Get();
$this->data['weeks'] = $this->weeks_model->Get();
$this->data['users'] = $this->school['users'];
}
$query = $this->_get_query();
$this->data['query_string'] = http_build_query($query);
$this->data['cancel_uri'] = 'bookings?' . http_build_query($query);
$this->data['body'] = $this->load->view('bookings/bookings_book', $this->data, TRUE);
// If we have a date and the user is a teacher, do some extra checks
//
if (isset($query['date']) && $this->userauth->is_level(TEACHER)) {
// Check that the date selected is not in the past
//
$today = strtotime(date("Y-m-d"));
$thedate = strtotime($query['date']);
if ($thedate < $today) {
$this->data['body'] = msgbox('error', 'You cannot make a booking in the past.');
}
// Now see if user is allowed to book in advance
//
$bia = (int) setting('bia');
if ($bia > 0) {
$date_forward = strtotime("+{$bia} days", $today);
if ($thedate > $date_forward) {
$this->data['body'] = msgbox('error', sprintf('You can only book %d days in advance.', $bia));
}
}
}
return $this->render();
}
/**
* Process a form action from the bookings table
*
*/
public function action()
{
if ($this->input->post('cancel')) {
return $this->process_cancel();
}
if ($this->input->post('recurring')) {
return $this->process_recurring();
}
}
private function process_recurring()
{
$bookings = array();
foreach ($this->input->post('recurring') as $booking) {
list($uri, $params) = explode('?', $booking);
parse_str($params, $data);
$bookings[] = $data;
}
$errcount = 0;
foreach ($bookings as $booking) {
$booking_data = array(
'user_id' => $this->input->post('user_id'),
'period_id' => $booking['period'],
'room_id' => $booking['room'],
'notes' => $this->input->post('notes'),
'week_id' => $booking['week'],
'day_num' => $booking['day_num'],
);
if ( ! $this->bookings_model->Add($booking_data)) {
$errcount++;
}
}
if ($errcount > 0) {
$flashmsg = msgbox('error', 'One or more bookings could not be made.');
} else {
$flashmsg = msgbox('info', 'The bookings were created successfully.');
}
$this->session->set_userdata('notes', $booking_data['notes']);
// Go back to index
$this->session->set_flashdata('saved', $flashmsg);
$query = $this->_get_query();
$uri = 'bookings/index?' . http_build_query($query);
redirect($uri);
}
private function process_cancel()
{
$id = $this->input->post('cancel');
$booking = $this->bookings_model->Get($id);
$user_id = $this->userauth->user->user_id;
$room = $this->rooms_model->Get($booking->room_id);
$query = $this->_get_query();
$uri = 'bookings/index?' . http_build_query($query);
$can_delete = ( ($this->userauth->is_level(ADMINISTRATOR))
OR ($user_id == $booking->user_id)
OR ( ($user_id == $room->user_id) && ($booking->date != NULL) )
);
if ( ! $can_delete) {
$this->session->set_flashdata('saved', msgbox('error', "You do not have the correct privileges to cancel this booking."));
return redirect($uri);
}
if ($this->bookings_model->Cancel($id)){
$msg = msgbox('info', 'The booking has been cancelled.');
} else {
$msg = msgbox('error', 'An error occured cancelling the booking.');
}
$this->session->set_flashdata('saved', $msg);
redirect($uri);
}
function edit($booking_id)
{
$booking = $this->bookings_model->Get($booking_id);
$query = $this->_get_query();
$uri = 'bookings?' . http_build_query($query);
$can_edit = ( $this->userauth->is_level(ADMINISTRATOR) OR ($this->userauth->user->user_id == $booking->user_id));
if ( ! $can_edit) {
$this->session->set_flashdata('saved', msgbox('error', "You do not have the correct privileges to cancel this booking."));
return redirect($uri);
}
$this->data['title'] = 'Edit booking';
$this->data['showtitle'] = $this->data['title'];
$this->data['cancel_uri'] = 'bookings?' . http_build_query($query);
// Lookups we need if an admin user
if ($this->userauth->is_level(ADMINISTRATOR)) {
$this->data['days'] = $this->periods_model->days;
$this->data['rooms'] = $this->rooms_model->Get();
$this->data['periods'] = $this->periods_model->Get();
$this->data['weeks'] = $this->weeks_model->Get();
$this->data['users'] = $this->school['users'];
}
$this->data['booking'] = $booking;
$this->data['hidden'] = (array) $booking;
$this->data['body'] = $this->load->view('bookings/bookings_book', $this->data, TRUE);
return $this->render();
}
function save()
{
// Get ID from form
$booking_id = $this->input->post('booking_id');
$this->load->library('form_validation');
$this->form_validation->set_rules('booking_id', 'Booking ID', 'integer');
$this->form_validation->set_rules('date', 'Date', 'max_length[10]');
$this->form_validation->set_rules('use', 'Notes', 'max_length[100]');
$this->form_validation->set_rules('period_id', 'Period', 'integer');
$this->form_validation->set_rules('user_id', 'User', 'integer');
$this->form_validation->set_rules('room_id', 'Room', 'integer');
$this->form_validation->set_rules('week_id', 'Week', 'integer');
$this->form_validation->set_rules('day_num', 'Day of week', 'integer');
if ( ! $this->input->post('day_num')) {
$this->form_validation->set_rules('date', 'Date', 'max_length[10]|callback_valid_date');
}
if ($this->form_validation->run() == FALSE) {
return (empty($booking_id) ? $this->book() : $this->edit($booking_id));
}
$booking_data = array(
'user_id' => $this->input->post('user_id'),
'period_id' => $this->input->post('period_id'),
'room_id' => $this->input->post('room_id'),
'notes' => $this->input->post('notes'),
'booking_id' => $this->input->post('booking_id'),
);
// Determine if this booking is recurring or static.
if ($this->input->post('date')) {
$date_arr = explode('/', $this->input->post('date'));
$booking_data['date'] = date("Y-m-d", mktime(0, 0, 0, $date_arr[1], $date_arr[0], $date_arr[2]));
$booking_data['day_num'] = NULL;
$booking_data['week_id'] = NULL;
}
if ($this->input->post('recurring') && $this->input->post('week_id') && $this->input->post('day_num')) {
$booking_data['date'] = NULL;
$booking_data['day_num'] = $this->input->post('day_num');
$booking_data['week_id'] = $this->input->post('week_id');
}
if ($this->_check_unique_booking($booking_data)) {
$this->_persist_booking($booking_id, $booking_data);
} else {
$flashmsg = msgbox('exclamation', "There is already a booking for that date, period and room.");
$this->data['notice'] = $flashmsg;
// $this->session->set_flashdata('saved', $flashmsg);
return (empty($booking_id) ? $this->book() : $this->edit($booking_id));
}
$query = $this->_get_query();
$uri = 'bookings/index?' . http_build_query($query);
redirect($uri);
}
public function valid_date($date)
{
if (strpos($date, '/') !== FALSE) {
$datearr = explode('/', $date);
$valid = checkdate($datearr[1], $datearr[0], $datearr[2]);
} elseif (strpos($date, '-') !== FALSE) {
$datearr = explode('-', $date);
$valid = checkdate($datearr[1], $datearr[2], $datearr[0]);
} else {
$this->form_validation->set_message('valid_date', 'Invalid date');
return FALSE;
}
if ($valid) {
return TRUE;
}
$this->form_validation->set_message('valid_date', 'Invalid date');
return FALSE;
}
private function _check_unique_booking($data)
{
$bookings = $this->bookings_model->GetUnique(array(
'date' => $data['date'],
'period_id' => $data['period_id'],
'room_id' => $data['room_id'],
'booking_id' => $data['booking_id'],
'week_id' => $data['week_id'],
));
return count($bookings) == 0;
}
private function _persist_booking($booking_id = NULL, $booking_data = array())
{
if (empty($booking_id)) {
unset($booking_data['booking_id']);
$booking_id = $this->bookings_model->Add($booking_data);
if ($booking_id) {
$flashmsg = msgbox('info', "The booking has been made.");
} else {
$line = sprintf($this->lang->line('crbs_action_dberror'), 'adding');
$flashmsg = msgbox('error', $line);
}
} else {
if ($this->bookings_model->Edit($booking_id, $booking_data)) {
$flashmsg = msgbox('info', "The booking has been updated.");
} else {
$line = sprintf($this->lang->line('crbs_action_dberror'), 'editing');
$flashmsg = msgbox('error', $line);
}
}
$this->session->set_flashdata('saved', $flashmsg);
}
}
<?php
class Bookings_model extends CI_Model
{
var $table_headings = '';
var $table_rows = array();
public function __construct()
{
parent::__construct();
}
function Get($booking_id)
{
$this->db->from('bookings');
$this->db->where('booking_id', $booking_id);
$query = $this->db->get();
if ($query->num_rows() == 1) {
return $query->row();
} else {
return FALSE;
}
}
function GetByDate($date = NULL)
{
if ($date == NULL) {
$date = date("Y-m-d");
}
$day_num = date('w', strtotime($date));
$query_str = "SELECT * FROM bookings WHERE (`date`='$date' OR day_num=$day_num)";
$query = $this->db->query($query_str);
$result = $query->result_array();
return $result;
}
function GetUnique($params = array())
{
$defaults = array(
'booking_id' => NULL,
'date' => NULL,
'period_id' => 0,
'room_id' => 0,
'week_id' => 0,
);
$data = array_merge($defaults, $params);
if (empty($data['date'])) {
$data['date'] = date("Y-m-d");
}
if (empty($data['week_id'])) {
$week = $this->WeekObj(strtotime($data['date']));
$week_id = ($week ? $week->week_id : 0);
} else {
$week_id = $data['week_id'];
}
$day_num = date('w', strtotime($data['date']));
$sql = "SELECT *
FROM bookings
WHERE (`date` = ? OR (day_num = ? AND week_id = ?) )
AND period_id = ?
AND room_id = ?";
if ( ! empty($data['booking_id'])) {
$sql .= " AND booking_id != " . $this->db->escape($data['booking_id']);
}
$query = $this->db->query($sql, array(
$data['date'],
$day_num,
$week_id,
$data['period_id'],
$data['room_id'],
));
// echo $this->db->last_query();
return $query->result_array();
}
function TableAddColumn($td)
{
$this->table_headings .= $td;
}
function TableAddRow($data)
{
$this->table_rows[] = $data;
}
function Table()
{
$table = '<tr>' . $this->table_headings . '</tr>';
/* foreach($this->table_rows as $row){
$table .= '<tr>' . $row . '</tr>';
} */
return $table;
}
function BookingCell($data, $key, $rooms, $users, $room_id, $url, $booking_date_ymd = '', $holidays = array())
{
// Check if there is a booking
if(isset($data[$key])){
// There's a booking for this ID, set var
$booking = $data[$key];
if($booking->date == NULL){
// If no date set, then it's a static/timetable/recurring booking
$cell['class'] = 'static';
$cell['body']= '';
} else {
// Date is set, it's a once off staff booking
$cell['class'] = 'staff';
$cell['body'] = '';
}
// Username info
if(isset($users[$booking->user_id])){
$username = $users[$booking->user_id]->username;
$displayname = trim($users[$booking->user_id]->displayname);
if(strlen($displayname) < 2){ $displayname = $username; }
$cell['body'] .= '<strong>'.html_escape($displayname).'</strong>';
$user = 1;
}
// Any notes?
if($booking->notes){
if(isset($user)){ $cell['body'] .= '<br />'; }
$notes = html_escape($booking->notes);
$cell['body'] .= '<span title="'.$notes.'">'.character_limiter($notes, 15).'</span>';
}
// Edit if admin?
if($this->userauth->is_level(ADMINISTRATOR)){
$edit_url = site_url('bookings/edit/'.$booking->booking_id);
$src = base_url('assets/images/ui/edit.gif');
$cell['body'] .= '<br /><a class="booking-action" href="'.$edit_url.'" title="Edit this booking">';
// $cell['body'] .= '<img alt="edit" src="' . $src . '" width="16" height="16" alt="Book" title="Edit" hspace="4" align="absmiddle" >';
$cell['body'] .= ' edit </a>';
$edit = 1;
}
// Cancel if user is an Admin, Room owner, or Booking owner
$user_id = $this->userauth->user->user_id;
if(
($this->userauth->is_level(ADMINISTRATOR)) OR
($user_id == $booking->user_id) OR
( ($user_id == $rooms[$room_id]->user_id) && ($booking->date != NULL) )
){
$cancel_msg = 'Are you sure you want to cancel this booking?';
if($user_id != $booking->user_id){
$cancel_msg = 'Are you sure you want to cancel this booking?\n\n(**) Please take caution, it is not your own.';
}
$cancel_url = site_url('bookings/cancel/'.$booking->booking_id);
if(!isset($edit)){ $cell['body'] .= '<br />'; }
$src = base_url('assets/images/ui/delete.gif');
$cell['body'] .= '<button class="button-empty booking-action" type="submit" name="cancel" value="' . $booking->booking_id . '" onclick="if(!confirm(\''.$cancel_msg.'\')){return false;}">';
$cell['body'] .= 'cancel';
// $cell['body'] .= '<img alt="cancel" src="' . $src . '">';
$cell['body'] .= '</button>';
// $cell['body'] .= '<a onclick="if(!confirm(\''.$cancel_msg.'\')){return false;}" href="'.$cancel_url.'" title="Cancel this booking"><img src="' . base_url('assets/images/ui/delete.gif') . '" width="16" height="16" alt="Cancel" title="Cancel this booking" hspace="8" /></a>';
}
}
elseif (isset($holidays[$booking_date_ymd]))
{
$cell['class'] = 'holiday';
$cell['body'] = $holidays[$booking_date_ymd][0]->name;
}
else
{
// No bookings
$book_url = site_url($url); //site_url('bookings/book/'.$url);
$cell['class'] = 'free';
$cell['body'] = '<a href="'.$book_url.'"><img src="' . base_url('assets/images/ui/accept.gif') . '" width="16" height="16" alt="Book" title="Book" hspace="4" align="absmiddle" />Book</a>';
if($this->userauth->is_level(ADMINISTRATOR)){
$cell['body'] .= '<input type="checkbox" name="recurring[]" value="'.$url.'" />';
}
}
#$cell['width'] =
#return sprintf('<td class="%s" valign="middle" align="center">%s</td>', $cell['class'], $cell['body']);
return $this->load->view('bookings/table/bookingcell', $cell, True);
}
function html($params = array())
{
$defaults = array(
'school' => array(), // data loaded in controller (users, days)
'query' => array(), // input for where the user is/what should be loaded
);
$data = array_merge($defaults, $params);
extract($data);
// Format the date to Ymd
if ( ! isset($query['date'])) {
$date = time();
$date_ymd = date("Y-m-d", $date);
} else {
$date = strtotime($query['date']);
$date_ymd = date("Y-m-d", $date);
}
// Today's weekday number
$day_num = date('w', $date);
$day_num = ($day_num == 0 ? 7 : $day_num);
// Get info on the current week
$this_week = $this->WeekObj($date);
// Init HTML + Jscript variable
$html = '';
// Put users into array with their ID as the key
foreach ($school['users'] as $user) {
$users[$user->user_id] = $user;
}
// Get rooms
$rooms = $this->Rooms();
if ($rooms == FALSE) {
$html .= msgbox('error', 'There are no rooms available. Please contact your administrator.');
return $html;
}
// Find out which columns to display and which view type we use
$style = $this->BookingStyle();
if ( ! $style OR (empty($style['cols']) OR empty($style['display']) ) ) {
$html = msgbox('error', 'No booking style has been configured. Please contact your administrator.');
return $html;
}
$cols = $style['cols'];
$display = $style['display'];
// Select a default room if none given (first room)
if ( ! isset($query['room'])) {
$room_c = current($rooms);
$query['room'] = $room_c->room_id;
}
// Load the appropriate select box depending on view style
switch ($display) {
case 'room':
$html .= $this->load->view('bookings/select_room', array(
'rooms' => $rooms,
'room_id' => $query['room'],
'chosen_date' => $date_ymd,
), TRUE);
break;
case 'day':
$html .= $this->load->view('bookings/select_date', array(
'chosen_date' => $date,
), TRUE);
break;
default:
$html .= msgbox('error', 'Application error: No display type set.');
return $html;
break;
}
$weekdates = array();
$week_bar = array();
// Change the week bar depending on view type
switch ($display) {
case 'room':
$week_bar['back_date'] = date("Y-m-d", strtotime("last Week", $date));
$week_bar['back_text'] = '&larr; Previous week';
$week_bar['back_link'] = 'bookings?' . http_build_query(array(
'date' => $week_bar['back_date'],
'room' => $query['room'],
'direction' => 'back',
));
$week_bar['next_date'] = date("Y-m-d", strtotime("next Week", $date));
$week_bar['next_text'] = 'Next week &rarr;';
$week_bar['next_link'] = 'bookings?' . http_build_query(array(
'date' => $week_bar['next_date'],
'room' => $query['room'],
'direction' => 'next',
));
break;
case 'day':
$week_bar['back_date'] = date("Y-m-d", strtotime("yesterday", $date));
$week_bar['back_link'] = 'bookings?' . http_build_query(array(
'date' => $week_bar['back_date'],
'direction' => 'back',
));
$week_bar['next_date'] = date("Y-m-d", strtotime("tomorrow", $date));
$week_bar['next_link'] = 'bookings?' . http_build_query(array(
'date' => $week_bar['next_date'],
'direction' => 'next',
));
if (date("Y-m-d") == date("Y-m-d", $date)) {
$week_bar['back_text'] = '&larr; Yesterday';
$week_bar['next_text'] = 'Tomorrow &rarr; ';
} else {
$week_bar['back_text'] = '&larr; Back';
$week_bar['next_text'] = 'Next &rarr; ';
}
$week_bar['longdate'] = date("l jS F Y", $date);
break;
}
// Do we have any info on this week name?
if ($this_week) {
// Yes, so alter the week nav bar with the details of the week
$week_bar['week_name'] = $this_week->name;
// Get dates for each weekday
if ($display == 'room') {
$this_date = strtotime("-1 day", strtotime($this_week->date));
foreach ($school['days_list'] as $d_day_num => $d_day_name) {
$weekdates[$d_day_num] = date("Y-m-d", strtotime("+1 day", $this_date));
$this_date = strtotime("+1 day", $this_date);
}
$week_bar['longdate'] = 'Week commencing '.date("l jS F Y", strtotime($this_week->date));
}
$week_bar['style'] = sprintf('padding:6px 3px;font-weight:bold;background:#%s;color:#%s', $this_week->bgcol, $this_week->fgcol);
$html .= $this->load->view('bookings/week_bar', $week_bar, TRUE);
} else {
// No week - change the properties to indicate no week available
$week_bar['longdate'] = 'Week of '.date("l jS F Y", $date);;
$week_bar['week_name'] = 'None';
$week_bar['style'] = sprintf('padding:6px 3px;font-weight:bold;background:#%s;color:#%s', 'dddddd', '000');
$html .= $this->load->view('bookings/week_bar', $week_bar, TRUE);
// Notify user no timetable week is available
$html .= msgbox('error', 'No timetable week has been configured for this selection.');
// Flag error to stop output before table
$err = TRUE;
}
// Holidays
//
// Initialse sql to null here, so we can if it *isn't* later.
// If it's not null, then we have SQL for holidays
$sql = NULL;
// See if our selected date is in a holiday
if ($display === 'day')
{
// If we are day at a time, it is easy!
// = get me any holidays where this day is anywhere in it
$sql = "SELECT *
FROM holidays
WHERE date_start <= '{$date_ymd}'
AND date_end >= '{$date_ymd}' ";
}
else
{
if ($this_week) {
// If we are room/week at a time, little bit more complex
$week_start = date('Y-m-d', strtotime($this_week->date));
$week_end = date('Y-m-d', strtotime('+' . count($school['days_list']) . ' days', strtotime($this_week->date)));
$sql = "SELECT *
FROM holidays
WHERE
/* Starts before this week, ends this week */
(date_start <= '$week_start' AND date_end <= '$week_end')
/* Starts this week, ends this week */
OR (date_start >= '$week_start' AND date_end <= '$week_end')
/* Starts this week, ends after this week */
OR (date_start >= '$week_start' AND date_end >= '$week_end')
";
}
}
$holidays = array();
$holiday_dates = array();
$holiday_interval = new DateInterval('P1D');
if (isset($sql)) {
$holiday_query = $this->db->query($sql);
$holidays = $holiday_query->result();
}
// Organise our holidays by date
foreach ($holidays as $holiday)
{
// Get all dates between date_start & date_end
$start_dt = new DateTime($holiday->date_start);
$end_dt = new DateTime($holiday->date_end);
$end_dt->modify('+1 day');
$range = new DatePeriod($start_dt, $holiday_interval, $end_dt);
foreach ($range as $date)
{
$holiday_ymd = $date->format('Y-m-d');
$holiday_dates[ $holiday_ymd ][] = $holiday;
}
}
if ($display === 'day' && isset($holiday_dates[$date_ymd])) {
// The date selected IS in a holiday - give them a nice message saying so.
$holiday = $holiday_dates[ $date_ymd ][0];
$msg = sprintf(
'The date you selected is during a holiday priod (%s, %s - %s).',
$holiday->name,
date("d/m/Y", strtotime($holiday->date_start)),
date("d/m/Y", strtotime($holiday->date_end))
);
$html .= msgbox('exclamation', $msg);
// Let them choose the date afterwards/before
// If navigating a day at a time, then just go one day.
// If navigating one room at a time, move by one week
if ($display === 'day') {
$next_date = date("Y-m-d", strtotime("+1 day", strtotime($holiday->date_end)));
$prev_date = date("Y-m-d", strtotime("-1 day", strtotime($holiday->date_start)));
} elseif ($display === 'room') {
$next_date = date("Y-m-d", strtotime("+1 week", strtotime($holiday->date_end)));
$prev_date = date("Y-m-d", strtotime("-1 week", strtotime($holiday->date_start)));
}
if ( ! isset($query['direction'])) {
$query['direction'] = 'forward';
}
switch ($query['direction']) {
case 'forward':
$query['date'] = $next_date;
$uri = 'bookings?' . http_build_query($query);
$link = anchor($uri, "Click here to view immediately after the holiday.");
$html .= "<p><strong>{$link}</strong></p>";
break;
case 'back':
$query['date'] = $prev_date;
$uri = 'bookings?' . http_build_query($query);
$link = anchor($uri, "Click here to view immediately before the holiday.");
$html .= "<p><strong>{$link}</strong></p>";
break;
}
$err = TRUE;
}
// Get periods
if ($style['display'] == 'day') {
$periods = $this->periods_model->GetBookable($day_num);
} else {
$periods = $this->periods_model->GetBookable();
}
if (empty($periods)) {
$html .= msgbox('error', 'There are no periods configured or available for this day.');
$err = TRUE;
}
if (isset($err) && $err == TRUE) {
return $html;
}
$count = array(
'periods' => count($periods),
'rooms' => count($rooms),
'days' => count($school['days_list']),
);
$col_width = sprintf('%s%%', round(100/($count[$cols]+1)));
// Open form
$html .= form_open('bookings/action', array(
'name' => 'bookings',
));
$html .= form_hidden('room_id', $query['room']);
// Here goes, start table
$html .= '<table border="0" bordercolor="#ffffff" cellpadding="2" cellspacing="2" class="bookings" width="100%">';
// COLUMNS !!
$html .= '<tr><td>&nbsp;</td>';
switch ($cols) {
case 'periods':
foreach ($periods as $period) {
$period->width = $col_width;
$html .= $this->load->view('bookings/table/cols_periods', $period, TRUE);
}
break;
case 'days':
foreach ($school['days_list'] as $dayofweek) {
$day['width'] = $col_width;
$day['name'] = $dayofweek;
$html .= $this->load->view('bookings/table/headings/days', $day, TRUE);
}
break;
case 'rooms':
foreach ($rooms as $room) {
$room->width = $col_width;
$html .= $this->load->view('bookings/table/cols_rooms', $room, TRUE);
}
break;
} // End switch for cols
$bookings = array();
// Here we go!
switch ($display) {
case 'room':
// ONE ROOM AT A TIME - COLS ARE PERIODS OR DAY NAMES...
switch ($cols) {
case 'periods':
/*
[P1] [P2] [P3] ...
[Mo]
[Tu]
....
*/
// Columns are periods, so each row is a day name
foreach ($school['days_list'] as $day_num => $day_name) {
// Get booking
// TODO: Need to get date("Y-m-d") of THIS weekday (Mon, Tue, Wed) for this week
$bookings = array();
$sql = "SELECT * FROM bookings
WHERE room_id = ?
AND ((day_num = ? AND week_id = ?) OR `date` = ?) ";
$bookings_query = $this->db->query($sql, array(
$query['room'],
$day_num,
$this_week->week_id,
$weekdates[$day_num],
));
if ($bookings_query->num_rows() > 0) {
$result = $bookings_query->result();
foreach ($result as $row) {
$bookings[$row->period_id] = $row;
}
}
$bookings_query->free_result();
$booking_date_ymd = $weekdates[$day_num];
// Start row
$html .= '<tr>';
// First cell
$day['width'] = $col_width;
$day['name'] = $day_name;
$day['date'] = $booking_date_ymd;
$html .= $this->load->view('bookings/table/rowinfo/days', $day, TRUE);
// Now all the other ones to fill in periods
foreach ($periods as $period) {
// URL
$book_url_query = array(
'period' => $period->period_id,
'room' => $query['room'],
'day_num' => $day_num,
'week' => $this_week->week_id,
'date' => $booking_date_ymd,
);
$url = 'bookings/book?' . http_build_query($book_url_query);
// This period is bookable on this day?
$key = "day_{$day_num}";
if ($period->{$key} == '1') {
// Bookable
$html .= $this->BookingCell($bookings, $period->period_id, $rooms, $users, $query['room'], $url, $booking_date_ymd, $holiday_dates);
} else {
// Period not bookable on this day, do not show or allow any bookings
$html .= '<td align="center">&nbsp;</td>';
}
} // Done looping periods (cols)
// This day row is finished
$html .= '</tr>';
}
break; // End $display 'room' $cols 'periods'
case 'days':
/*
[Mo] [Tu] [We] ...
[P1]
[P2]
....
*/
// Columns are days, so each row is a period
foreach ($periods as $period) {
// Get bookings
$bookings = array();
$sql = "SELECT * FROM bookings
WHERE room_id = ?
AND period_id = ?
AND ( week_id = ? OR (`date` >= ? AND `date` <= ?) )";
#."AND ((day_num=$day_num AND week_id=$this_week->week_id) OR date='$date_ymd') ";
$bookings_query = $this->db->query($sql, array(
$query['room'],
$period->period_id,
$this_week->week_id,
$weekdates[1],
$weekdates[7],
));
$results = $bookings_query->result();
if ($bookings_query->num_rows() > 0) {
foreach ($results as $row) {
if ( ! empty($row->date)) {
// Static booking on date
$this_daynum = date('w', strtotime($row->date));
$bookings[$this_daynum] = $row;
} else {
// Recurring booking
$bookings[$row->day_num] = $row;
}
}
}
$bookings_query->free_result();
// Start row
$html .= '<tr>';
// First cell, info
$period->width = $col_width;
$html .= $this->load->view('bookings/table/rows_periods', $period, TRUE);
foreach ($school['days_list'] as $day_num => $day_name) {
$booking_date_ymd = $weekdates[$day_num];
// URL
$book_url_query = array(
'period' => $period->period_id,
'room' => $query['room'],
'day_num' => $day_num,
'week' => $this_week->week_id,
'date' => $booking_date_ymd,
);
$url = 'bookings/book?' . http_build_query($book_url_query);
// $url = 'period/%s/room/%s/day/%s/week/%s/date/%s';
// $url = sprintf($url, $period->period_id, $room_id, $day_num, $this_week->week_id, $booking_date_ymd);
// Is this period bookable on this day?
$key = "day_{$day_num}";
if ($period->{$key} == '1') {
// Bookable
$html .= $this->BookingCell($bookings, $day_num, $rooms, $users, $query['room'], $url, $booking_date_ymd, $holiday_dates);
} else {
// Period not bookable on this day, do not show or allow any bookings
$html .= '<td align="center">&nbsp;</td>';
}
}
// This period row is finished
$html .= '</tr>';
}
break; // End $display 'room' $cols 'days'
}
break;
case 'day':
// ONE DAY AT A TIME - COLS ARE DAY NAMES OR ROOMS
switch ($cols) {
case 'periods':
/*
[P1] [P2] [P3] ...
[R1]
[R2]
....
*/
// Columns are periods, so each row is a room
foreach ($rooms as $room) {
$bookings = array();
// See if there are any bookings for any period this room.
// A booking will either have a date (teacher booking), or a day_num and week_id (static/timetabled)
$sql = "SELECT *
FROM bookings
WHERE room_id = ?
AND ((day_num = ? AND week_id = ?) OR `date` = ?)";
$bookings_query = $this->db->query($sql, array(
$room->room_id,
$day_num,
$this_week->week_id,
$date_ymd,
));
if ($bookings_query->num_rows() > 0){
$result = $bookings_query->result();
foreach ($result as $row) {
$bookings[$row->period_id] = $row;
}
}
$bookings_query->free_result();
// Start row
$html .= '<tr>';
$room->width = $col_width;
$html .= $this->load->view('bookings/table/rows_rooms', $room, TRUE);
foreach ($periods as $period) {
// URL
$book_url_query = array(
'period' => $period->period_id,
'room' => $room->room_id,
'day_num' => $day_num,
'week' => $this_week->week_id,
'date' => $date_ymd,
);
$url = 'bookings/book?' . http_build_query($book_url_query);
$key = "day_{$day_num}";
if ($period->{$key} == '1') {
// Bookable
$html .= $this->BookingCell($bookings, $period->period_id, $rooms, $users, $room->room_id, $url, $date_ymd, $holiday_dates);
} else {
// Period not bookable on this day, do not show or allow any bookings
$html .= '<td align="center">&nbsp;</td>';
}
}
// End row
$html .= '</tr>';
}
break; // End $display 'day' $cols 'periods'
case 'rooms':
/*
[R1] [R2] [R3] ...
[P1]
[P2]
*/
// Columns are rooms, so each row is a period
foreach ($periods as $period) {
$bookings = array();
// See if there are any bookings for any period this room.
// A booking will either have a date (teacher booking), or a day_num and week_id (static/timetabled)
$sql = "SELECT * FROM bookings
WHERE period_id = ?
AND ((day_num = ? AND week_id = ?) OR `date` = ?) ";
$bookings_query = $this->db->query($sql, array(
$period->period_id,
$day_num,
$this_week->week_id,
$date_ymd,
));
if ($bookings_query->num_rows() > 0) {
$result = $bookings_query->result();
foreach ($result as $row){
$bookings[$row->room_id] = $row;
}
}
$bookings_query->free_result();
// Start period row
$html .= '<tr>';
// First cell, info
$period->width = $col_width;
$html .= $this->load->view('bookings/table/rows_periods', $period, TRUE);
foreach ($rooms as $room) {
// URL
$book_url_query = array(
'period' => $period->period_id,
'room' => $room->room_id,
'day_num' => $day_num,
'week' => $this_week->week_id,
'date' => $date_ymd,
);
$url = 'bookings/book?' . http_build_query($book_url_query);
// $url = 'period/%s/room/%s/day/%s/week/%s/date/%s';
// $url = sprintf($url, $period->period_id, $room->room_id, $day_num, $this_week->week_id, $date_ymd);
// Bookable on this day?
$key = "day_{$day_num}";
if ($period->{$key} == '1') {
// Bookable
$html .= $this->BookingCell($bookings, $room->room_id, $rooms, $users, $room->room_id, $url, $date_ymd, $holiday_dates);
} else {
// Period not bookable on this day, do not show or allow any bookings
$html .= '<td align="center">&nbsp;</td>';
}
}
// End period row
$html .= '</tr>';
}
break; // End $display 'day' $cols 'rooms'
}
break;
}
$html .= $this->Table();
// Finish table
$html .= '</table>';
// Visual key
$html .= $this->load->view('bookings/key', NULL, TRUE);
// Show link to making a booking for admins
if ($this->userauth->is_level(ADMINISTRATOR)) {
$html .= $this->load->view('bookings/make_recurring', array('users' => $school['users']), TRUE);
}
$html .= form_close();
// Finaly return the HTML variable so the controller can then pass it to the view.
return $html;
}
public function Cancel($booking_id)
{
$sql = "DELETE FROM bookings
WHERE booking_id = ?
LIMIT 1";
$query = $this->db->query($sql, array($booking_id));
return ($query && $this->db->affected_rows() == 1);
}
function BookingStyle()
{
$out = array(
'cols' => setting('d_columns'),
'display' => setting('displaytype'),
);
if (empty($out['cols']) || empty($out['display'])) {
return FALSE;
}
return $out;
}
/**
* Get rooms and their users
*
*/
function Rooms()
{
$sql = "SELECT rooms.*, users.user_id, users.username, users.displayname
FROM rooms
LEFT JOIN users ON users.user_id=rooms.user_id
WHERE rooms.bookable=1
ORDER BY name asc";
$query = $this->db->query($sql);
if ($query->num_rows() > 0) {
$result = $query->result();
// Put all room data into an array where the key is the room_id
foreach ($result as $room) {
$rooms[$room->room_id] = $room;
}
return $rooms;
}
return FALSE;
}
/**
* Returns an object containing the week information for a given date
*
*/
public function WeekObj($date)
{
// First find the monday date of the week that $date is in
if (date("w", $date) == 1) {
$nextdate = date("Y-m-d", $date);
} else {
$nextdate = date("Y-m-d", strtotime("last Monday", $date));
}
// Get week info that this date falls into
$sql = "SELECT * FROM weeks, weekdates
WHERE weeks.week_id = weekdates.week_id
AND weekdates.date = '$nextdate'
LIMIT 1";
$query = $this->db->query($sql);
if ($query->num_rows() == 1) {
$row = $query->row();
} else {
$row = false;
}
return $row;
}
/**
* Add a booking
*
*/
function Add($data = array())
{
// Run query to insert blank row
$this->db->insert('bookings', array('booking_id' => NULL));
// Get id of inserted record
$booking_id = $this->db->insert_id();
// Now call the edit function to update the actual data for this new row now we have the ID
return $this->Edit($booking_id, $data);
}
function Edit($booking_id, $data)
{
$this->db->where('booking_id', $booking_id);
$result = $this->db->update('bookings', $data);
// Return bool on success
if ($result) {
return $booking_id;
} else {
return false;
}
}
function ByRoomOwner($user_id = 0)
{
$maxdate = date("Y-m-d", strtotime("+14 days", Now()));
$today = date("Y-m-d");
$sql = "SELECT rooms.*, bookings.*, users.username, users.displayname, users.user_id, periods.name as periodname
FROM bookings
JOIN rooms ON rooms.room_id=bookings.room_id
JOIN users ON users.user_id=bookings.user_id
JOIN periods ON periods.period_id=bookings.period_id
WHERE rooms.user_id='$user_id' AND bookings.cancelled=0
AND bookings.date IS NOT NULL
AND bookings.date <= '$maxdate'
AND bookings.date >= '$today'
ORDER BY bookings.date, rooms.name ";
$query = $this->db->query($sql);
if ($query->num_rows() > 0) {
// We have some bookings
return $query->result();
}
return FALSE;
}
function ByUser($user_id)
{
$maxdate = date("Y-m-d", strtotime("+14 days", Now()));
$today = date("Y-m-d");
// All current bookings for this user between today and 2 weeks' time
$sql = "SELECT rooms.*, bookings.*, periods.name as periodname, periods.time_start, periods.time_end
FROM bookings
JOIN rooms ON rooms.room_id=bookings.room_id
JOIN periods ON periods.period_id=bookings.period_id
WHERE bookings.user_id='$user_id' AND bookings.cancelled=0
AND bookings.date IS NOT NULL
AND bookings.date <= '$maxdate'
AND bookings.date >= '$today'
ORDER BY bookings.date asc, periods.time_start asc";
$query = $this->db->query($sql);
if ($query->num_rows() > 0) {
return $query->result();
} else {
return false;
}
}
function TotalNum($user_id = 0)
{
$today = date("Y-m-d");
// All bookings by user, EVER!
$sql = "SELECT * FROM bookings WHERE user_id='$user_id'";
$query = $this->db->query($sql);
$total['all'] = $query->num_rows();
// All bookings by user, for this academic year, up to and including today
$sql = "SELECT * FROM bookings
JOIN academicyears ON bookings.date >= academicyears.date_start
WHERE user_id='$user_id' ";
$query = $this->db->query($sql);
$total['yeartodate'] = $query->num_rows();
// All bookings up to and including today
$sql = "SELECT * FROM bookings WHERE user_id='$user_id' AND date <= '$today'";
$query = $this->db->query($sql);
$total['todate'] = $query->num_rows();
// All "active" bookings (today onwards)
$sql = "SELECT * FROM bookings WHERE user_id='$user_id' AND date >= '$today'";
$query = $this->db->query($sql);
$total['active'] = $query->num_rows();
return $total;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment