mrbs_sql.inc (mrbs-1.9.4) | : | mrbs_sql.inc (mrbs-1.10.0) | ||
---|---|---|---|---|
skipping to change at line 59 | skipping to change at line 59 | |||
function mrbsCheckFree(array $booking, $ignore, $repignore) | function mrbsCheckFree(array $booking, $ignore, $repignore) | |||
{ | { | |||
global $enable_periods, $periods, $twentyfourhour_format; | global $enable_periods, $periods, $twentyfourhour_format; | |||
global $strftime_format, $is_private_field; | global $strftime_format, $is_private_field; | |||
$room_id = $booking['room_id']; | $room_id = $booking['room_id']; | |||
get_area_settings(get_area($room_id)); | get_area_settings(get_area($room_id)); | |||
// Select any meetings which overlap for this room: | // Select any meetings which overlap for this room: | |||
$sql = "SELECT E.id, name, start_time, create_by, status, room_name | $sql = "SELECT E.id, name, start_time, end_time, create_by, status, room_name | |||
FROM " . _tbl('entry') . " E, " . _tbl('room') . " R | FROM " . _tbl('entry') . " E, " . _tbl('room') . " R | |||
WHERE E.room_id=R.id | WHERE E.room_id=R.id | |||
AND start_time < ? | AND start_time < ? | |||
AND end_time > ? | AND end_time > ? | |||
AND E.room_id = ?"; | AND E.room_id = ?"; | |||
$sql_params = array($booking['end_time'], | $sql_params = array($booking['end_time'], | |||
$booking['start_time'], | $booking['start_time'], | |||
$room_id); | $room_id); | |||
skipping to change at line 97 | skipping to change at line 97 | |||
} | } | |||
// Get the room's area ID for linking to day, week, and month views: | // Get the room's area ID for linking to day, week, and month views: | |||
$area = mrbsGetRoomArea($room_id); | $area = mrbsGetRoomArea($room_id); | |||
// Build an listing all the conflicts: | // Build an listing all the conflicts: | |||
$err = array(); | $err = array(); | |||
while (false !== ($row = $res->next_row_keyed())) | while (false !== ($row = $res->next_row_keyed())) | |||
{ | { | |||
unpack_status($row); | unpack_status($row); | |||
$starts = getdate($row['start_time']); | $start_date = getdate($row['start_time']); | |||
$end_date = getdate($row['end_time']); | ||||
$different_dates = ( $start_date['year'] != $end_date['year'] || | ||||
$start_date['yday'] != $end_date['yday']); | ||||
if ($enable_periods) | if ($enable_periods) | |||
{ | { | |||
$p_num =$starts['minutes']; | $p_num = $start_date['minutes']; | |||
$startstr = utf8_strftime($strftime_format['date'] . ", ", | // The number of periods might have been reduced since the booking was mad | |||
$row['start_time']) . htmlspecialchars($periods[ | e | |||
$p_num]); | $p_end_num = min(count($periods), $end_date['minutes']) - 1; | |||
if ($different_dates) | ||||
{ | ||||
$timestr = $periods[$p_num] . ", " . | ||||
utf8_strftime($strftime_format['date'], $row['start_time']) . | ||||
" - " . | ||||
$periods[$p_end_num] . ", " . | ||||
utf8_strftime($strftime_format['date'], $row['end_time']); | ||||
} | ||||
else | ||||
{ | ||||
$timestr = $periods[$p_num]; | ||||
if ($p_num != $p_end_num) | ||||
{ | ||||
$timestr .= " - " . $periods[$p_end_num]; | ||||
} | ||||
$timestr .= ", " . utf8_strftime($strftime_format['date'], $row['start_t | ||||
ime']); | ||||
} | ||||
} | } | |||
else | else | |||
{ | { | |||
$startstr = utf8_strftime(($twentyfourhour_format) ? $strftime_format['dat | if ($different_dates) | |||
etime24'] : $strftime_format['datetime12'], | { | |||
$row['start_time']); | $date_format = ($twentyfourhour_format) ? $strftime_format['datetime24'] | |||
: $strftime_format['datetime12']; | ||||
} | ||||
else | ||||
{ | ||||
$date_format = ($twentyfourhour_format) ? $strftime_format['time24'] : $ | ||||
strftime_format['time12']; | ||||
} | ||||
$timestr = utf8_strftime($date_format, $row['start_time']) . " - " . | ||||
utf8_strftime($date_format, $row['end_time']); | ||||
if (!$different_dates) | ||||
{ | ||||
$timestr .= ", " . utf8_strftime($strftime_format['date'], $row['start_t | ||||
ime']); | ||||
} | ||||
} | } | |||
if (is_private_event($row['private']) && | if (is_private_event($row['private']) && | |||
$is_private_field['entry.name'] && | $is_private_field['entry.name'] && | |||
!getWritable($row['create_by'], $room_id)) | !getWritable($row['create_by'], $room_id)) | |||
{ | { | |||
$row['name'] = get_vocab("unavailable"); | $row['name'] = get_vocab("unavailable"); | |||
} | } | |||
// enclose the viewday etc. links in a span to make it easier for JavaScript to strip them out | // enclose the viewday etc. links in a span to make it easier for JavaScript to strip them out | |||
$vars = array('year' => $starts['year'], | $vars = array('year' => $start_date['year'], | |||
'month' => $starts['mon'], | 'month' => $start_date['mon'], | |||
'day' => $starts['mday'], | 'day' => $start_date['mday'], | |||
'area' => $area, | 'area' => $area, | |||
'room' => $room_id); | 'room' => $room_id); | |||
$query = http_build_query($vars, '', '&'); | $query = http_build_query($vars, '', '&'); | |||
$err[] = '<a href="' . htmlspecialchars(multisite('view_entry.php?id=' . $ro w['id'])) . '">' . | $err[] = '<a href="' . htmlspecialchars(multisite('view_entry.php?id=' . $ro w['id'])) . '">' . | |||
htmlspecialchars($row['name']) . '</a>' . | htmlspecialchars($row['name']) . '</a>' . | |||
' (' . $startstr . ', ' . htmlspecialchars($row['room_name']) . ') ' . | ' (' . htmlspecialchars($timestr) . ', ' . htmlspecialchars($row['r oom_name']) . ') ' . | |||
'<span>(' . | '<span>(' . | |||
'<a href="' . htmlspecialchars(multisite("index.php?view=day&$query ")) . '">' . get_vocab('viewday') . '</a> | ' . | '<a href="' . htmlspecialchars(multisite("index.php?view=day&$query ")) . '">' . get_vocab('viewday') . '</a> | ' . | |||
'<a href="' . htmlspecialchars(multisite("index.php?view=week&$quer y")) . '">' . get_vocab('viewweek') . '</a> | ' . | '<a href="' . htmlspecialchars(multisite("index.php?view=week&$quer y")) . '">' . get_vocab('viewweek') . '</a> | ' . | |||
'<a href="' . htmlspecialchars(multisite("index.php?view=month&$que ry")) . '">' . get_vocab('viewmonth') . '</a>' . | '<a href="' . htmlspecialchars(multisite("index.php?view=month&$que ry")) . '">' . get_vocab('viewmonth') . '</a>' . | |||
')</span>'; | ')</span>'; | |||
} | } | |||
return $err; | return $err; | |||
} | } | |||
skipping to change at line 608 | skipping to change at line 639 | |||
$violations[] = $tmp; | $violations[] = $tmp; | |||
} | } | |||
} | } | |||
} | } | |||
$result[$violation_status] = $violations; | $result[$violation_status] = $violations; | |||
return $result; | return $result; | |||
} | } | |||
function get_entry_by_id($id) | function get_entry_by_id(int $id) : ?array | |||
{ | { | |||
if (!isset($id)) | if (!isset($id)) | |||
{ | { | |||
return null; | return null; | |||
} | } | |||
$sql = "SELECT * | $sql = "SELECT * | |||
FROM " . _tbl('entry') . " | FROM " . _tbl('entry') . " | |||
WHERE id=? | WHERE id=? | |||
LIMIT 1"; | LIMIT 1"; | |||
skipping to change at line 821 | skipping to change at line 852 | |||
* orphaned rows in the repeat table. | * orphaned rows in the repeat table. | |||
* | * | |||
* $id - The entry to delete | * $id - The entry to delete | |||
* $series - If set, delete the series, except user modified entries | * $series - If set, delete the series, except user modified entries | |||
* $all - If set, include user modified entries in the series delete | * $all - If set, include user modified entries in the series delete | |||
* | * | |||
* Returns FALSE if an error occurred, otherwise an array of start_times that | * Returns FALSE if an error occurred, otherwise an array of start_times that | |||
* have been deleted. | * have been deleted. | |||
* | * | |||
*/ | */ | |||
function mrbsDelEntry($id, $series, $all) | function mrbsDelEntry($id, $series, bool $all) | |||
{ | { | |||
$start_times = array(); | $start_times = array(); | |||
// Get the repeat_id and room_id for this entry | // Get the repeat_id and room_id for this entry | |||
$sql = "SELECT repeat_id, room_id | $sql = "SELECT repeat_id, room_id | |||
FROM " . _tbl('entry') . " | FROM " . _tbl('entry') . " | |||
WHERE id=? | WHERE id=? | |||
LIMIT 1"; | LIMIT 1"; | |||
$res = db()->query($sql, array($id)); | $res = db()->query($sql, array($id)); | |||
if ($res->count() <= 0) | if ($res->count() <= 0) | |||
skipping to change at line 910 | skipping to change at line 941 | |||
* | * | |||
* $table - The table in which to create the entry | * $table - The table in which to create the entry | |||
* $data - An array containing the row data for the entry | * $data - An array containing the row data for the entry | |||
* | * | |||
* Returns: | * Returns: | |||
* 0 - An error occurred while inserting the entry | * 0 - An error occurred while inserting the entry | |||
* non-zero - The entry's ID | * non-zero - The entry's ID | |||
*/ | */ | |||
function mrbsCreateEntry($table, $data) | function mrbsCreateEntry($table, $data) | |||
{ | { | |||
global $standard_fields, $db_tbl_prefix; | global $standard_fields; | |||
$sql_col = array(); | $sql_col = array(); | |||
$sql_val = array(); | $sql_val = array(); | |||
$table_no_prefix = utf8_substr($table, utf8_strlen($db_tbl_prefix)); // strip the prefix off the table name | ||||
$table_short_name = get_table_short_name($table); | ||||
$fields = db()->field_info($table); | $fields = db()->field_info($table); | |||
$sql_params = array(); | $sql_params = array(); | |||
// Pack the status fields into the bit map | // Pack the status fields into the bit map | |||
pack_status($data); | pack_status($data); | |||
foreach ($fields as $field) | foreach ($fields as $field) | |||
{ | { | |||
$key = $field['name']; | $key = $field['name']; | |||
skipping to change at line 1018 | skipping to change at line 1049 | |||
if (!empty($data[$key])) | if (!empty($data[$key])) | |||
{ | { | |||
$sql_col[] = $key; | $sql_col[] = $key; | |||
$sql_val[] = '?'; | $sql_val[] = '?'; | |||
$sql_params[] = $data[$key]; | $sql_params[] = $data[$key]; | |||
} | } | |||
break; | break; | |||
default: | default: | |||
// custom fields | // custom fields | |||
if (!in_array($key, $standard_fields[$table_no_prefix])) | if (!in_array($key, $standard_fields[$table_short_name])) | |||
{ | { | |||
$sql_col[] = $key; | $sql_col[] = $key; | |||
// Depending on the nature of the custom field the treatment will va ry | // Depending on the nature of the custom field the treatment will va ry | |||
switch ($field['nature']) | switch ($field['nature']) | |||
{ | { | |||
case 'integer': | case 'integer': | |||
if (!isset($data[$key]) || ($data[$key] === '')) | if (!isset($data[$key]) || ($data[$key] === '')) | |||
{ | { | |||
// Try and set it to NULL when we can because there will be ca ses when we | // Try and set it to NULL when we can because there will be ca ses when we | |||
skipping to change at line 1592 | skipping to change at line 1623 | |||
FROM " . _tbl('entry') . " E | FROM " . _tbl('entry') . " E | |||
LEFT JOIN " . _tbl('participants') . " P ON E.id=P.entry_id | LEFT JOIN " . _tbl('participants') . " P ON E.id=P.entry_id | |||
WHERE E.repeat_id=:repeat_id | WHERE E.repeat_id=:repeat_id | |||
LIMIT 1"; | LIMIT 1"; | |||
$sql_params = array(':repeat_id' => $repeat_id); | $sql_params = array(':repeat_id' => $repeat_id); | |||
return (db()->query1($sql, $sql_params) > 0); | return (db()->query1($sql, $sql_params) > 0); | |||
} | } | |||
// Determines whether any entries allow registration | ||||
function registration_somewhere() : bool | ||||
{ | ||||
$sql = "SELECT COUNT(*) | ||||
FROM " . _tbl('entry') . " | ||||
WHERE allow_registration=1 | ||||
LIMIT 1"; | ||||
return (db()->query1($sql) > 0); | ||||
} | ||||
// get_booking_info($id, $series) | // get_booking_info($id, $series) | |||
// | // | |||
// Gets all the details for a booking with $id, which is in the | // Gets all the details for a booking with $id, which is in the | |||
// repeat table if $series is set, otherwise in the entry table. | // repeat table if $series is set, otherwise in the entry table. | |||
// Returns the results in an array with keys the same as the table | // Returns the results in an array with keys the same as the table | |||
// field names. In the event of an error stops with a fatal error, | // field names. In the event of an error stops with a fatal error, | |||
// unless $silent is TRUE, when it returns FALSE. | // unless $silent is TRUE, when it returns FALSE. | |||
function get_booking_info($id, $series, $silent=FALSE) | function get_booking_info($id, $series, $silent=FALSE) | |||
{ | { | |||
skipping to change at line 1731 | skipping to change at line 1772 | |||
if ($silent) | if ($silent) | |||
{ | { | |||
return FALSE; | return FALSE; | |||
} | } | |||
else | else | |||
{ | { | |||
fatal_error(($series ? get_vocab("invalid_series_id") : get_vocab("invalid _entry_id"))); | fatal_error(($series ? get_vocab("invalid_series_id") : get_vocab("invalid _entry_id"))); | |||
} | } | |||
} | } | |||
// Turn the last_updated column into an int (PostgreSQL will return a float) | ||||
$row['last_updated'] = intval($row['last_updated']); | ||||
// Now get the duration. | // Now get the duration. | |||
// Don't translate the units at this stage. We'll translate them later. | // Don't translate the units at this stage. We'll translate them later. | |||
$d = get_duration($row['start_time'], $row['end_time'], $row['enable_periods'] , $row['area_id'], false); | $d = get_duration($row['start_time'], $row['end_time'], $row['enable_periods'] , $row['area_id'], false); | |||
$row['duration'] = $d['duration']; | $row['duration'] = $d['duration']; | |||
$row['dur_units'] = $d['dur_units']; | $row['dur_units'] = $d['dur_units']; | |||
// Translate the status field into a set of booleans | // Translate the status field into a set of booleans | |||
unpack_status($row); | unpack_status($row); | |||
// Get some extra information | // Get some extra information | |||
skipping to change at line 2211 | skipping to change at line 2255 | |||
return true; | return true; | |||
} | } | |||
// Makes bookings | // Makes bookings | |||
// $bookings an array of bookings | // $bookings an array of bookings | |||
// $id the id of the current booking when editing an existing entry | // $id the id of the current booking when editing an existing entry | |||
function mrbsMakeBookings(array $bookings, $id=NULL, $just_check=FALSE, $skip=FA LSE, $original_room_id=NULL, $send_mail=FALSE, $edit_type='') | function mrbsMakeBookings(array $bookings, $id=NULL, $just_check=FALSE, $skip=FA LSE, $original_room_id=NULL, $send_mail=FALSE, $edit_type='') | |||
{ | { | |||
global $max_rep_entrys, $enable_periods, $resolution, $mail_settings; | global $max_rep_entrys, $enable_periods, $resolution, $mail_settings; | |||
global $prevent_simultaneous_bookings; | global $prevent_simultaneous_bookings, $auth; | |||
// All the data, except for the status and room id, will be common | // All the data, except for the status and room id, will be common | |||
// across the bookings | // across the bookings | |||
$common = $bookings[0]; | $common = $bookings[0]; | |||
// Work out the duration in seconds, but adjust it for DST changes so that | // Work out the duration in seconds, but adjust it for DST changes so that | |||
// the user will still see, for example, "24 hours" when a booking goes from | // the user will still see, for example, "24 hours" when a booking goes from | |||
// 1200 one day to 1200 the next, crossing a DST boundary. | // 1200 one day to 1200 the next, crossing a DST boundary. | |||
$duration_seconds = $common['end_time'] - $common['start_time']; | $duration_seconds = $common['end_time'] - $common['start_time']; | |||
$duration_seconds -= cross_dst($common['start_time'], $common['end_time']); | $duration_seconds -= cross_dst($common['start_time'], $common['end_time']); | |||
// Now get the duration, which will be needed for email notifications | // Now get the duration, which will be needed for email notifications | |||
skipping to change at line 2276 | skipping to change at line 2320 | |||
} | } | |||
// Validate the booking for (a) conflicting bookings and (b) conformance to po licy rules | // Validate the booking for (a) conflicting bookings and (b) conformance to po licy rules | |||
$valid_booking = true; | $valid_booking = true; | |||
$conflicts = array(); // Holds a list of all the conflic ts | $conflicts = array(); // Holds a list of all the conflic ts | |||
$violations = array('notices' => array(), // Holds an array of the policy ru les that have been broken | $violations = array('notices' => array(), // Holds an array of the policy ru les that have been broken | |||
'errors' => array()); // classified by 'notices' and 'er rors' | 'errors' => array()); // classified by 'notices' and 'er rors' | |||
$skip_lists = array(); // Holds a 2D array of bookings to skip past. Index ed | $skip_lists = array(); // Holds a 2D array of bookings to skip past. Index ed | |||
// by room id and start time | // by room id and start time | |||
// Do the simple check for simultaneous bookings: if there is more than one bo | // Do the simple check for simultaneous bookings and or selection of multiple | |||
oking | rooms: if | |||
// then this is going to result in a simultaneous booking. The only question | // there is more than one booking then this is going to result in a simultaneo | |||
is whether | us booking. | |||
// this a notice or an error. If the user is an ordinary user in more than on | // The only question is whether this a notice or an error. If the user is an | |||
e of | ordinary user | |||
// the rooms, then it's an error, otherwise a notice. | // in more than one of the rooms, then it's an error, otherwise a notice. | |||
// The policy check later on will check whether the booking is at the same tim e as | // The policy check later on will check whether the booking is at the same tim e as | |||
// any other bookings made by this user. | // any other bookings made by this user. | |||
if ($prevent_simultaneous_bookings && (count($bookings) > 1)) | if (($prevent_simultaneous_bookings || $auth['only_admin_can_select_multiroom' | |||
]) | ||||
&& (count($bookings) > 1)) | ||||
{ | { | |||
$violation_status = 'notices'; | $violation_status = 'notices'; | |||
$non_admin_rooms = 0; | $non_admin_rooms = 0; | |||
foreach($bookings as $booking) | foreach($bookings as $booking) | |||
{ | { | |||
if (!is_book_admin($booking['room_id'])) | if (!is_book_admin($booking['room_id'])) | |||
{ | { | |||
$non_admin_rooms++; | $non_admin_rooms++; | |||
if ($non_admin_rooms > 1) | if ($non_admin_rooms > 1) | |||
{ | { | |||
$violation_status = 'errors'; | $violation_status = 'errors'; | |||
$valid_booking = false; | $valid_booking = false; | |||
break; | break; | |||
} | } | |||
} | } | |||
} | } | |||
$violations[$violation_status][] = get_vocab('no_simultaneous_bookings'); | if ($prevent_simultaneous_bookings) | |||
{ | ||||
$violations[$violation_status][] = get_vocab('no_simultaneous_bookings'); | ||||
} | ||||
if ($auth['only_admin_can_select_multiroom']) | ||||
{ | ||||
$violations[$violation_status][] = get_vocab('multiroom_not_allowed'); | ||||
} | ||||
} | } | |||
// Check for any schedule conflicts in each room we're going to try and | // Check for any schedule conflicts in each room we're going to try and | |||
// book in; also check that the booking conforms to the policy | // book in; also check that the booking conforms to the policy | |||
foreach ($bookings as $booking) | foreach ($bookings as $booking) | |||
{ | { | |||
$skip_lists[$booking['room_id']] = array(); | $skip_lists[$booking['room_id']] = array(); | |||
if ($booking['rep_type'] != REP_NONE && !empty($reps)) | if ($booking['rep_type'] != REP_NONE && !empty($reps)) | |||
{ | { | |||
if(count($reps) < $max_rep_entrys) | if(count($reps) < $max_rep_entrys) | |||
skipping to change at line 2418 | skipping to change at line 2470 | |||
if (isset($id)) | if (isset($id)) | |||
{ | { | |||
if ($edit_type == "series") | if ($edit_type == "series") | |||
{ | { | |||
$old_bookings = get_bookings_in_series($repeat_id); | $old_bookings = get_bookings_in_series($repeat_id); | |||
} | } | |||
else | else | |||
{ | { | |||
$old_bookings = array(); | $old_bookings = array(); | |||
$old_bookings[] = get_entry_by_id($id); | $old_booking = get_entry_by_id($id); | |||
if (isset($old_booking)) | ||||
{ | ||||
$old_bookings[] = $old_booking; | ||||
} | ||||
} | } | |||
foreach ($old_bookings as $old_booking) | foreach ($old_bookings as $old_booking) | |||
{ | { | |||
$violations_this_booking = mrbsCheckPolicy($old_booking, FALSE, FALSE, TRU E); | $violations_this_booking = mrbsCheckPolicy($old_booking, FALSE, FALSE, TRU E); | |||
foreach (array('notices', 'errors') as $key) | foreach (array('notices', 'errors') as $key) | |||
{ | { | |||
$violations[$key] = array_merge($violations[$key], $violations_this_book ing[$key]); | $violations[$key] = array_merge($violations[$key], $violations_this_book ing[$key]); | |||
} | } | |||
if (!empty($violations_this_booking['errors'])) | if (!empty($violations_this_booking['errors'])) | |||
skipping to change at line 2597 | skipping to change at line 2653 | |||
} | } | |||
} | } | |||
} // end foreach $bookings | } // end foreach $bookings | |||
$result['new_details'] = $new_details; | $result['new_details'] = $new_details; | |||
$result['slots'] = intval(($common['end_time'] - $common['start_time'])/$resol ution); | $result['slots'] = intval(($common['end_time'] - $common['start_time'])/$resol ution); | |||
return $result; | return $result; | |||
} | } | |||
function get_bookings_in_series($repeat_id) | function get_bookings_in_series(?int $repeat_id) : array | |||
{ | { | |||
$bookings = array(); | $bookings = array(); | |||
$sql = "SELECT id | if (isset($repeat_id)) | |||
{ | ||||
$sql = "SELECT id | ||||
FROM " . _tbl('entry') . " | FROM " . _tbl('entry') . " | |||
WHERE repeat_id = ?"; | WHERE repeat_id = ?"; | |||
$res = db()->query_array($sql, array($repeat_id)); | $res = db()->query_array($sql, array($repeat_id)); | |||
foreach ($res as $id) | foreach ($res as $id) | |||
{ | { | |||
$bookings[] = get_entry_by_id($id); | $booking = get_entry_by_id($id); | |||
if (isset($booking)) | ||||
{ | ||||
$bookings[] = $booking; | ||||
} | ||||
} | ||||
} | } | |||
return $bookings; | return $bookings; | |||
} | } | |||
End of changes. 23 change blocks. | ||||
35 lines changed or deleted | 103 lines changed or added |