// Convert a start time and end time to a plain language description.
// This is similar but different from the way it is done in view_entry.
function describe_span($starts, $ends)
{
global $twentyfourhour_format;
$start_date = utf8_strftime('%A %d %B %Y', $starts);
$start_time = utf8_strftime(hours_minutes_seconds_format(), $starts);
$duration = $ends - $starts;
if ($start_time == "00:00:00" && $duration == 60*60*24)
{
return $start_date . " - " . get_vocab("all_day");
}
toTimeString($duration, $dur_units);
return $start_date . " " . $start_time . " - " . $duration . " " . $dur_units;
}
// Convert a start period and end period to a plain language description.
// This is similar but different from the way it is done in view_entry.
function describe_period_span($starts, $ends)
{
list( $start_period, $start_date) = period_date_string($starts);
list( , $end_date) = period_date_string($ends, -1);
$duration = $ends - $starts;
toPeriodString($start_period, $duration, $dur_units);
return $start_date . " - " . $duration . " " . $dur_units;
}
// this is based on describe_span but it displays the start and end
// date/time of an entry
function start_to_end($starts, $ends)
{
global $twentyfourhour_format;
$start_date = utf8_strftime('%A %d %B %Y', $starts);
$start_time = utf8_strftime(hours_minutes_seconds_format(), $starts);
// this is based on describe_period_span but it displays the start and end
// date/period of an entry
function start_to_end_period($starts, $ends)
{
list( , $start_date) = period_date_string($starts);
list( , $end_date) = period_date_string($ends, -1);
return $start_date . " - " . $end_date;
}
// Report on one entry. See below for columns in $row[].
// $last_area_room remembers the current area/room.
// $last_date remembers the current date.
function reporton(&$row, &$last_area_room, &$last_date, $sortby, $display)
{
global $typel;
global $enable_periods;
// Display Area/Room, but only when it changes:
$area_room = htmlspecialchars($row['area_name']) . " - " . htmlspecialchars($row['room_name']);
$date = utf8_strftime("%d-%b-%Y", $row['start_time']);
// entries to be sorted on area/room
echo "<div class=\"div_report\">\n";
if( $sortby == "r" )
{
if ($area_room != $last_area_room)
{
echo "<h2>". get_vocab("room") . ": " . $area_room . "</h2>\n";
}
if ($date != $last_date || $area_room != $last_area_room)
{
echo "<h3>". get_vocab("date") . ": " . $date . "</h3>\n";
$last_date = $date;
}
// remember current area/room that is being processed.
// this is done here as the if statement above needs the old
// values
if ($area_room != $last_area_room)
{
$last_area_room = $area_room;
}
}
else
// entries to be sorted on start date
{
if ($date != $last_date)
{
echo "<h2>". get_vocab("date") . ": " . $date . "</h2>\n";
}
if ($area_room != $last_area_room || $date != $last_date)
{
echo "<h3>". get_vocab("room") . ": " . $area_room . "</h3>\n";
$last_area_room = $area_room;
}
// remember current date that is being processed.
// this is done here as the if statement above needs the old
// values
if ($date != $last_date)
{
$last_date = $date;
}
}
echo "<div class=\"report_entry_title\">\n";
// Collect summary statistics on one entry. See below for columns in $row[].
// $sumby selects grouping on brief description (d) or created by (c).
// This also builds hash tables of all unique names and rooms. When sorted,
// these will become the column and row headers of the summary table.
function accumulate(&$row, &$count, &$hours, $report_start, $report_end,
&$room_hash, &$name_hash)
{
global $sumby;
// Use brief description or created by as the name:
$name = htmlspecialchars($row[($sumby == "d" ? 'name' : 'create_by')]);
// Area and room separated by break:
$room = htmlspecialchars($row['area_name']) . "<br>" . htmlspecialchars($row['room_name']);
// Accumulate the number of bookings for this room and name:
@$count[$room][$name]++;
// Accumulate hours used, clipped to report range dates:
@$hours[$room][$name] += (min((int)$row['end_time'], $report_end)
- max((int)$row['start_time'], $report_start)) / 3600.0;
$room_hash[$room] = 1;
$name_hash[$name] = 1;
}
function accumulate_periods(&$row, &$count, &$hours, $report_start,
$report_end, &$room_hash, &$name_hash)
{
global $sumby;
global $periods;
$max_periods = count($periods);
// Use brief description or created by as the name:
$name = htmlspecialchars($row[($sumby == "d" ? 'name' : 'create_by')]);
// Area and room separated by break:
$room = htmlspecialchars($row['area_name']) . "<br>" . htmlspecialchars($row['room_name']);
// Accumulate the number of bookings for this room and name:
@$count[$room][$name]++;
// Accumulate hours used, clipped to report range dates:
$dur = (min((int)$row['end_time'], $report_end) - max((int)$row['start_time'], $report_start))/60;
@$hours[$room][$name] += ($dur % $max_periods) + floor( $dur/(24*60) ) * $max_periods;
$room_hash[$room] = 1;
$name_hash[$name] = 1;
}
// Output a table cell containing a count (integer) and hours (float):
// (actually output two cells, so that we can style the counts and hours)
function cell($count, $hours)
{
echo "<td class=\"count\">($count)</td><td>" . sprintf("%.2f", $hours) . "</td>\n";
}
// Output the summary table (a "cross-tab report"). $count and $hours are
// 2-dimensional sparse arrays indexed by [area/room][name].
// $room_hash & $name_hash are arrays with indexes naming unique rooms and names.
function do_summary(&$count, &$hours, &$room_hash, &$name_hash)
{
global $enable_periods;
// Make a sorted array of area/rooms, and of names, to use for column
// and row indexes. Use the rooms and names hashes built by accumulate().
// At PHP4 we could use array_keys().
reset($room_hash);
while (list($room_key) = each($room_hash))
{
$rooms[] = $room_key;
}
ksort($rooms);
reset($name_hash);
while (list($name_key) = each($name_hash))
{
$names[] = $name_key;
}
ksort($names);
$n_rooms = sizeof($rooms);
$n_names = sizeof($names);
# Require authenticated user if private bookings are required
if ($private_override == "private")
{
if (!getAuthorised(1))
{
showAccessDenied($day, $month, $year, $area, "");
exit();
}
}
# Need to know user name and if they are an admin
$user = getUserName();
$is_admin = (isset($user) && authGetUserLevel($user)>=2) ;
//If we dont know the right date then make it up
if (!isset($day) or !isset($month) or !isset($year))
{
$day = date("d");
$month = date("m");
$year = date("Y");
}
if(empty($area))
$area = get_default_area();
// Lower part: Results, if called with parameters:
if (isset($areamatch))
{
// Start and end times are also used to clip the times for summary info.
$report_start = mktime(0, 0, 0, $From_month+0, $From_day+0, $From_year+0);
$report_end = mktime(0, 0, 0, $To_month+0, $To_day+1, $To_year+0);
// SQL result will contain the following columns:
// Col Index Description:
// 1 [0] Entry ID, not displayed -- used for linking to View script.
// 2 [1] Start time as Unix time_t
// 3 [2] End time as Unix time_t
// 4 [3] Entry name or short description, must be HTML escaped
// 5 [4] Entry description, must be HTML escaped
// 6 [5] Type, single char mapped to a string
// 7 [6] Created by (user name or IP addr), must be HTML escaped
// 8 [7] Creation timestamp, converted to Unix time_t by the database
// 9 [8] Area name, must be HTML escaped
// 10 [9] Room name, must be HTML escaped
$sql = "SELECT e.id AS entry_id, e.start_time, e.end_time, e.name, e.description, "
. "e.type, e.create_by, "
. sql_syntax_timestamp_to_unix("e.timestamp") . " AS last_updated"
. ", a.area_name, r.room_name"
. " FROM $tbl_entry e, $tbl_area a, $tbl_room r"
. " WHERE e.room_id = r.id AND r.area_id = a.id"
. " AND e.start_time < $report_end AND e.end_time > $report_start";
if (!empty($areamatch))
{
// sql_syntax_caseless_contains() does the SQL escaping
$sql .= " AND" . sql_syntax_caseless_contains("a.area_name", $areamatch);
}
if (!empty($roommatch))
{
// sql_syntax_caseless_contains() does the SQL escaping
$sql .= " AND" . sql_syntax_caseless_contains("r.room_name", $roommatch);
}
if (!empty($typematch))
{
$sql .= " AND ";
if ( count( $typematch ) > 1 )
{
$or_array = array();
foreach ( $typematch as $type )
{
$or_array[] = "e.type = '".addslashes($type)."'";
}
$sql .= "(". implode( " OR ", $or_array ) .")";
}
else
{
$sql .= "e.type = '".addslashes($typematch[0])."'";
}
}
if (!empty($namematch))
{
// sql_syntax_caseless_contains() does the SQL escaping
$sql .= " AND" . sql_syntax_caseless_contains("e.name", $namematch);
}
if (!empty($descrmatch))
{
// sql_syntax_caseless_contains() does the SQL escaping
$sql .= " AND" . sql_syntax_caseless_contains("e.description", $descrmatch);
}
if (!empty($creatormatch))
{
// sql_syntax_caseless_contains() does the SQL escaping
$sql .= " AND" . sql_syntax_caseless_contains("e.create_by", $creatormatch);
}
# If not overriding as public entries and user isn't and admin...
if (($private_override != "public") && !$is_admin)
{
if (isset($user))
{
if ($private_override == "private")
{
$sql .= " AND e.create_by = '".addslashes($user)."'";
}
else
{
$sql .= " AND (e.create_by = '".addslashes($user)."' OR e.private=0)";
}
}
else
{
# un-authenticated users can only report on
# items which are not marked private
$sql .= " AND e.private=0";
}
}
if ( $sortby == "r" )
{
// Order by Area, Room, Start date/time
$sql .= " ORDER BY 9,10,2";
}
else
{
// Order by Start date/time, Area, Room
$sql .= " ORDER BY 2,9,10";
}