Location: PHPKode > projects > ConPortal > conportal/inc/shifts/display.php
<?php
/*
 *  ConPortal - Pomona College ITS scheduling appplication
 *  Copyright (C) 2005-2006  Pomona College
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of version 2 of the GNU General Public License
 *  as published by the Free Software Foundation.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

//Temporary debug variable for debugging popups.
$DEBUG = FALSE;

/* Cache list of appointments found during the creation of the shift table,
 * so we can output their "details" divs all at the end of the table
 */
$global_appts = array();

/*
 * Displays the shifts for the currently selected day, specified by $_SESSION['shift_timestamp']
 */
function shifts_by_day ()
{
    // Print shift display header
    ?>
	<div id="content">
	<form action="shift_confirm.php" method="post">
        <div id="shifts_by_day_date">
            Shifts for:
            <?= timestamp_to_prettydate($_SESSION['shift_timestamp']) ?>.
        </div>
    <?php
    print_shift_draw_info();
	global $global_appts;
	$global_appts = array();
    shift_table("print_shift_take_drop_info", "shifts");
	echo "</form>\n";
	print_appointment_details();
}

/*
 * Given a shift status (as determined by getShiftStaffingStatus),
 * decide which CSS class to use to draw that shift
 */
function determine_shift_class ($status, $owner)
{
    switch($status) {
        case STATUS_TEMP_TAKEN:
            if ($owner == $_SESSION['pid'])
                $classname = "YourTempShift";
            else
                $classname = "TempTakenShift";
            break;
        case STATUS_TEMP_OPEN:
            $classname = "DroppedShift";
            break;
        case STATUS_PERM_TAKEN:
            if ($owner == $_SESSION['pid'])
                $classname = "YourPermShift";
            else
                $classname = "PermTakenShift";
            break;
        case STATUS_PERM_OPEN:
            $classname = "OpenShift";
            break;
    }
    return $classname;
}

/*
 * Print the legend that occurs at the top and bottom of the shifts table
 */
function print_shifts_legend ()
{
    ?>
    <div class="LegendBar">	
    <div class="Legend">Legend:</div>
    <div class="OpenShift" style="height: inherit; float: left">Open Shift</div>
    <div class="DroppedShift" style="height: inherit; float: left">Dropped Shift</div>
    <div class="PermTakenShift" style="height: inherit; float: left">Perm Taken Shift</div>
    <div class="TempTakenShift" style="height: inherit; float: left">Temp Taken Shift</div>
    <div class="YourPermShift" style="height: inherit; float: left">Your Perm Shift</div>
    <div class="YourTempShift" style="height: inherit; float: left">Your Temp Shift</div>
	<div style="clear:both">
		<input type="submit" value="Submit Changes..." />
		<?php
			if (checkPerm($_SESSION, "shifts"))
				echo "Note: you may select another user on behalf of whom to take shifts on the next page.";
		?>
	</div>
	</div>
    <?php
}

define("ACTION_NOTHING",   0);
define("ACTION_PERM_TAKE", 1);
define("ACTION_TEMP_TAKE", 2);
define("ACTION_PERM_DROP", 3);
define("ACTION_TEMP_DROP", 4);

/*
 * Print the shift take/drop information for a shift
 * This gets passed an associative array containing all the shift data
 */
function print_shift_take_drop_info ($shift_data)
{
    // Determine which buttons to display
    $status = getShiftStaffingStatus($shift_data['pid']);
    switch($status)
    {
        case STATUS_TEMP_TAKEN:
            $temp_drop_button = checkShowShiftDropButton($shift_data['pid'], $_SESSION['shift_timestamp']);
            $temp_take_button = false;
            $perm_drop_button = false;
            $perm_take_button = false;
            break;
        case STATUS_TEMP_OPEN:
            $temp_drop_button = false;
            $temp_take_button = checkShowShiftTakeButton($shift_data['pid'], $_SESSION['shift_timestamp']);
            $perm_drop_button = false;
            $perm_take_button = false;
            break;
        case STATUS_PERM_TAKEN:
            $temp_drop_button = checkShowShiftDropButton($shift_data['pid'], $_SESSION['shift_timestamp']);
            $temp_take_button = false;
            $perm_drop_button = $temp_drop_button;
            $perm_take_button = false;
            break;
        case STATUS_PERM_OPEN:
            $temp_drop_button = false;
            $temp_take_button = checkShowShiftTakeButton($shift_data['pid'], $_SESSION['shift_timestamp']);
            $perm_drop_button = false;
            $perm_take_button = $temp_take_button;
            break;
    }
	
	// Determine CSS class and open the div
	$classname = determine_shift_class(getShiftStaffingStatus($shift_data['pid']), $shift_data['owner']);
	echo "<div class=\"$classname\">\n";

    // Time
    if($_SESSION['show_times'])
    {
   	 echo date('g:i A', $shift_data['start_time']) . ' - ';
   	 echo date('g:i A', $shift_data['end_time']) . "<br />\n";
    }
    // Date
	
	 $new_dates = xlate_shiftdate($shift_data['day_of_week'],
        $shift_data['start_date'],
        $shift_data['end_date']); 
    if ($new_dates[0] == $new_dates[1])
    {
    	if($_SESSION['show_date_range'])
    	{
        	echo timestamp_to_monthday($new_dates[0]) . "<br />\n";
    	}
        // If the shift is just one day, disable perm take/drop buttons
        $perm_take_button = false;
        $perm_drop_button = false;
    }
    else
    {
    	if($_SESSION['show_date_range'])
    	{
    		echo timestamp_to_monthday($new_dates[0]) . " - " .
             timestamp_to_monthday($new_dates[1]) . "<br />\n";
    	}
    }   

    // Names
    if($_SESSION['show_names'])
    {
    if (isset($shift_data['owner']) and $shift_data['owner'] != 0 )
        echo getNameForUser($shift_data['owner']) . "<br />\n";
    elseif (isset($shift_data["dropper"]) and $shift_data["dropper"] != 0)
    	//allow suppression of the dropped by message if the admins desire
    	//this code is somewhat dirty, potential FIXME someday
    	if((SHOW_PERM_DROPPER && $status==STATUS_PERM_OPEN) || ($status==STATUS_TEMP_OPEN))
    	{
        	echo 'Dropped by: ' . getNameForUser($shift_data["dropper"]) . "<br />\n";
    	}
    	else
    	{
		if($_SESSION['show_shift_open'])
    			echo "Shift open<br />\n";
    	}
    else
	if($_SESSION['show_shift_open'])
        	echo "Shift open<br />\n";
    }
    
    if ($DEBUG)
    {
    	$dbout = "";
    	foreach ($shift_data as $dbkey => $dbval)
		$dbout .= $dbkey . "=>" . $dbval . " -- ";
    	echo "<a href=\"javascript:alert('$dbout');\">DB</a><br />";
    }

	// Combo box of options...display only if "No Action" is not the only option and client wants dropdowns
	// Now hacked for "employees stupidly starting to take their semester shifts a month into the semester" protection
	$the_day = $_SESSION['shift_timestamp'];
	$sg = getShiftgroupDetails(getShiftgroupByDate($the_day));
	//if semester hasn't started yet, and the selected day is further in the future than one week after the start of the semester, and first week only protection is on, display a notice
	if((time() < $sg['start_date']) && (strtotime("+6 days", $sg['start_date']) < $the_day) && $sg['first_week_protection'])
	{
		//defined in strings.php
		echo SHIFTS_FIRST_WEEK_WARNING;
	}
	else if (($perm_take_button or $perm_drop_button or $temp_take_button or $temp_drop_button) && ($_SESSION['show_dropdowns']))
	{
		$name = $shift_data['pid'] . "_" . $_SESSION['shift_timestamp'];
		echo "<select name=\"$name\">\n";
		echo "<option value=\"" . ACTION_NOTHING . "\">No action</option>\n";
		if ($perm_take_button)
			echo "<option value=\"" . ACTION_PERM_TAKE . "\">Perm take</option>\n";
		if ($perm_drop_button)
			echo "<option value=\"" . ACTION_PERM_DROP . "\">Perm drop</option>\n";
		if ($temp_take_button)
			echo "<option value=\"" . ACTION_TEMP_TAKE . "\">Temp take</option>\n";
		if ($temp_drop_button)
			echo "<option value=\"" . ACTION_TEMP_DROP . "\">Temp drop</option>\n";
		echo "</select><br />\n";
	}

    $staffed = (isset($shift_data['owner']) and $shift_data['owner'] != 0);

    // Calculate correct start_time and end_time taking into account $_SESSION['shift_timestamp'] date
    $start_time = date_part($_SESSION['shift_timestamp']) + time_part($shift_data['start_time']);
    $end_time   = date_part($_SESSION['shift_timestamp']) + time_part($shift_data['end_time']);

    // Show appointment info for this shift
    $appointments = getUncancelledAppointmentsForRangeAndPosition($start_time, $end_time, intval($shift_data['position']));
	global $global_appts;
	if(BUCKNELL_OPTIONS == TRUE)
	{
		foreach ($appointments as $apptPid)
		{
			$appt_data = getAppointmentDetails($apptPid);
		?>
		<div class="<?= $staffed ? "Appointment" : "UnstaffedAppointment" ?>">
		<span class="AppointmentDetailsLink"
		onclick="showDetails('details<?= $appt_data['pid'] ?>', this)">Appt <?= $appt_data['status'] ?></span>
		</div>
			<?php
			// Add this appointment to a list of appointments for which we will print out
			// the floating divs later, at the end of the document (so as to be outside
			// the shift-taking-dropping form)
			$global_appts[] = $appt_data;
		}
		// Show appointment creation button, normally only if the shift is staffed and has
		// no other appointments, and the shift starts in the future.  However, for supers
		// and admins, let them create appointments whenever (even in the past!).
		if (($staffed and count($appointments) == 0 and $start_time > mktime()) or 
		checkPerm($_SESSION, "appointments"))
		{
			if($_SESSION['show_create_appointments'] && USE_APPOINTMENT_SYSTEM && checkPerm($_SESSION, "appointments"))
			{
				print_create_appointment($shift_data['pid']);
				echo "<br />";
			}
		}
		if($_SESSION['show_shiftpid'])
		{
			echo "Shift PID: " . $shift_data['pid']	. "<br />";
		}
	}
	// Close out the containing div
	echo "</div>\n";
}

function print_appointment_details ()
{
	global $global_appts;
	foreach ($global_appts as $appt_data)
	{
		?>
			<div class="AppointmentDetails" id="details<?= $appt_data['pid'] ?>">
				<img class="CloseIcon" src="<?= BASE_URL ?>images/close.gif"
					alt="Close" onclick="hideDetails('details<?= $appt_data['pid'] ?>')"/>
				<?= date('g:ia', $appt_data['start_time']) ?>: <?= $appt_data['description'] ?><br />
				Case: <?= $appt_data['ticket_number'] ?><br />
				<?php print_update($appt_data['pid'], $appt_data['status']); ?>
			</div><br />
		<?php
	}
}

//  Has some leftover code from when day selection was a dropdown
//  Low priority FIXME
function print_copy_shifts_form()
{
    // pre-generate the list of the days of the week
    $d = array('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
               'Saturday', 'Sunday');
    $days = '';
    foreach ($d as $day)
        $days .= "<option value='$day'>$day</option>\n";
	// pre-generate list of shiftgroups
	$shiftgroupPids = getShiftgroups();
	$shiftgroups = "";
	foreach ($shiftgroupPids as $pid)
	{
		$info = getShiftgroupDetails($pid);
		$shiftgroups .= "<option value=\"$pid\">{$info['name']}</option>\n";
	}
?>
<form action='redirects/copy_shifts.php' method='post'><div>
    Copy from <select name='copy_day_orig'><?= $days ?></select>
	in shift group <select name='copy_sg_orig'><?= $shiftgroups ?></select>
    to <select name='copy_day_dest'><?= $days ?></select>
    in shift group <select name='copy_sg_dest'><?= $shiftgroups ?></select>
    <br /><input type="submit" value="Submit" />
    </div>
</form>
<?
}

/* display the form that allows someone to create a new shift */
function print_create_shift_form()
{
    // pre-generate the list of the days of the week
    // FIXME - This code is no longer used, thanks to Meredith-style checkboxes.  I'm leaving it in
    // for posterity's sake, or in case someone wants to go back to the day dropdowns...
    $d = array('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
               'Saturday', 'Sunday');
    $days = '';
    foreach ($d as $day)
        $days .= "<option value='$day'>$day</option>\n";
	?>
		<form action='redirects/create_shifts.php' method='post'>
		<p>Create a new shift:</p>
		<table>
			<tr><td>Shift Group:</td>
				<td><select name='shift_group'>
						<?
							$pids = getShiftgroups();
							foreach ($pids as $pid)
							{
								$tmp = getShiftgroupDetails($pid);
								echo "<option value='$pid'>".$tmp['name']."</option>\n";
							}
						?>
					</select>
				</td>
			</tr>
			<tr><td>Starting time (Earliest is midnight, 00:00 AM):</td>
				<td>
					<input type='text' name='start_hour' maxlength='2'
						style='width:1.5em' />:<input type='text' name='start_min' 
						maxlength='2' style='width:1.5em' />
				<select name='start_AMPM'> <option value='AM' selected='selected'>AM</option><option value='PM'>PM</option></select>

				</td>
			</tr>
			<tr><td>Ending time (Latest is 11:59 PM):</td>
				<td><input type='text' name='end_hour' maxlength='2'
						style='width:1.5em' />:<input type='text' name='end_min'
						maxlength='2' style='width:1.5em' />
				<select name='end_AMPM'> <option value='AM' selected='selected'>AM</option><option value='PM'>PM</option></select>
				
				</td>
			</tr>

<!--		The former drop-down box, replaced with Meredith-style checkboxes!	
			<tr><td>Day of week:</td><td><select name='day'><?= $days ?></select></td></tr>  -->

			<tr><td>Select the day(s) of the week for this shift:</td>
<td><input type="checkbox" name="dayList[]" value="Monday" /> Monday
</td></tr>
<tr><td></td><td><input type="checkbox" name="dayList[]" value="Tuesday" /> Tuesday</td></tr>
<tr><td></td><td><input type="checkbox" name="dayList[]" value="Wednesday" /> Wednesday</td></tr>
<tr><td></td><td><input type="checkbox" name="dayList[]" value="Thursday" /> Thursday</td></tr>
<tr><td></td><td><input type="checkbox" name="dayList[]" value="Friday" /> Friday</td></tr>
<tr><td></td><td><input type="checkbox" name="dayList[]" value="Saturday" /> Saturday</td></tr>
<tr><td></td><td><input type="checkbox" name="dayList[]" value="Sunday" /> Sunday</td></tr>

</p>

<tr><td width="50%"><strong>Mult-shift creation checkbox</strong> - in the time range specified, create multiple 
shifts using the default interval of <? 
	echo EZ_INTERVAL_HOURS . " hour(s) and " . EZ_INTERVAL_MINUTES . " minute(s) long";
	if(BLACKOUT_EXISTS)
	{
		echo " with a blackout period ranging from " . BLACKOUT_START_HOURS . 
			":" . BLACKOUT_START_MINUTES . " to " . BLACKOUT_END_HOURS . 
			":" . BLACKOUT_END_MINUTES .".  ";
	}
?>These values are set by your <a href="edit_prefs.php">preferences</a>. If you want blocks of time longer or shorter than the default interval, or during the blackout period, don't check this box!  Or at least, not until you've changed those in the preferences...</td><td><input type="checkbox" name="multi_shift"></td></tr>
			
			<tr><td>Start date:</td>
				<td>
					<input type="radio" name="startdate_custom" value="0" checked />
						Inherit from shiftgroup
					<input type="radio" name="startdate_custom" value="1" />
						Custom:
					<select name="start_month"><?php print_month_options(date('n')) ?></select>
					<select name="start_day">  <?php print_day_options(date('j'))   ?></select>
					<select name="start_year"> <?php print_year_options(date('Y'))  ?></select>
				</td>
			</tr>
			<tr><td>End date:</td>
				<td>
					<input type="radio" name="enddate_custom" value="0" checked />
						Inherit from shiftgroup
					<input type="radio" name="enddate_custom" value="1" />
						Custom:
					<select name="end_month"><?php print_month_options(date('n')) ?></select>
					<select name="end_day">  <?php print_day_options(date('j'))   ?></select>
					<select name="end_year"> <?php print_year_options(date('Y'))  ?></select>
				</td>
			</tr>
			<tr><td>Position:</td>
				<td><select name='position'>
						<?
							$pids = getPositions();
							foreach ($pids as $pid)
							{
								$tmp = getPositionDetails($pid);
								echo "<option value='$pid'>".$tmp['name']."</option>\n";
							}
						?>
					</select>
				</td>
			</tr>
		</table>
		<p><input type="submit" value="Submit" /></p>
		</form>
	<?
}

// Displays the shift cancelling form, using shift_table
function print_cancel_shift_form ()
{
    // Display shifts menu (i.e. the calendar)    
    menu('shifts');
    shift_table("print_cancel_shift_button", "none");
}

// Called by shift_table for each shift, passed an associative array of the
// shift's data
function print_cancel_shift_button ($shift_data)
{
	echo "<div class=\"OpenShift\">\n";

    // Print shift time
    echo date('g:i', $shift_data['start_time']) . ' - ';
    echo date('g:i', $shift_data['end_time']) . "<br />\n";

    // Print shift dates
    $new_dates = xlate_shiftdate($shift_data['day_of_week'],
        $shift_data['start_date'],
        $shift_data['end_date']);
    if ($new_dates[0] == $new_dates[1])
        echo timestamp_to_monthday($new_dates[0]) . "<br />\n";
    else
        echo timestamp_to_monthday($new_dates[0]) . " - " . timestamp_to_monthday($new_dates[1]) . "<br />\n";
        
    // Print cancel form
    ?>
        <form action="redirects/cancel_shifts.php" method="post"><div>
            <input type="hidden" name="pid" value="<?= $shift_data['pid'] ?>" />
            <input type="hidden" name="timestamp" value="<?= $_SESSION['shift_timestamp'] ?>" />
            <input type="submit" value="Cancel on <?= timestamp_to_monthday($_SESSION['shift_timestamp']) ?>" />
        </div></form>
	</div>
    <?
}

function print_all_shift_histories($start, $end)
{
    $users = sortUsersByName(getAllUserDetails());
    foreach ($users as $user) {
        print "<h2 class='center' style='margin-top: 1em'>".$user['name']."</h2>\n";
        print_shift_history($user['pid'], $start, $end);
    }
}

function print_shift_history($pid, $start, $end)
{
	$shifts = getShiftDetailsForArray(getShiftsForDateRangeAndUser($pid, $start, $end));

    if (count($shifts) == 0) {
        print "<div class='center'>None</div>\n";
        return;
    }

    // Pre-sort the shifts by day-of-week
    $shifts_dow = array();
    foreach ($shifts as $shift) {
        $shifts_dow[strtolower($shift['day_of_week'])][] = $shift;
    }

	//var_dump($shifts);
	
    $rows = array();
    for ($i = $start; $i <= $end; $i = strtotime("+1 day", $i)) {
        $dow = strtolower(date('l', $i));

        // The user may not work some days of the week...
        if (!isset($shifts_dow[$dow]))
            continue;
			
		//added to help track consecutive shifts
			$prevStartTime = 0;
			$latestEndTime = 0;

        foreach ($shifts_dow[$dow] as $shift) {
	
            if ($shift['start_date'] <= $i and $i <= $shift['end_date'])
			{
			// FIXME : this was broken on 2/25/08, when I changed the shift 
			// listing in getShiftsForDateRangeAndUser from DESC to ASC (default)
			// cosmetic, not serious, flaw.

				/* if this shift is immediately before the previous one...
				 Converting to date because occasionally we run into an issue where
				the database compares an hour on one day with the same hour on
				another, and since they have different timestamps, the check fails.  
				Converting it to just the time resolves this */
				if(date("g:ia",$prevStartTime) == date("g:ia",$shift['end_time']))
				{
					//remove the element we just added
					$rows = array_slice($rows,0,(count($rows)-1));
					
					//re-add the row, using the latest end time but the current start
					$rows[] = "
					<tr><td>".date("D, M d", $i)."</td>
        <td>".date("g:ia", $shift['start_time'])."</td>
        <td>".date("g:ia", $latestEndTime)."</td></tr>";
		
					//update start time
					$prevStartTime=$shift['start_time'];
					} 
				//else not part of a consecutive shift	
				else
				{
					
                $rows[] = "
		<tr><td>".date("D, M d", $i)."</td>
        <td>".date("g:ia", $shift['start_time'])."</td>
        <td>".date("g:ia", $shift['end_time'])."</td></tr>";
				$prevStartTime=$shift['start_time'];
				$latestEndTime=$shift['end_time'];
				}
            }
        }
    }

?>
<table class='shift_history'>
    <tr><th>Date</th><th>Starts</th><th>Ends</th></tr>
<?
    foreach ($rows as $row)
        echo $row;
?>
</table>
<?
}

/*
 * Function: shift_table ($info_func, $legend)
 *
 * info_func: The name of a function that expects to be passed an array of
 *            shift data function taking one parameter.
 *            It's responsible for printing whatever information should be
 *            displayed in the shift box.
 *
 * legend:    A string, either "none", "shifts", or "appointments".
 *            Controls what function to call to print out the legend:
 *            shift_table calls the function "print_{$legend}_legend."
 */
function shift_table($info_func, $legend = "none")
{
    // constants
    define('HALF_HOUR', 30 * 60);          // 1800 seconds = 1/2 hour
    define('SIZE_FACTOR', 4.5 * $_SESSION['scaling_factor']); //vertical scaling factor
    define('TIME_SCALE', SIZE_FACTOR / HALF_HOUR); // ratio of ems to seconds inital value 4.5
    define('SMALL_DIFF', 5 * 60);          // between shifts, spaces smaller
                                           // than this many seconds are not
                                           // displayed
    define('DISPLAY_STOP',(BLACKOUT_START_HOURS * 3600) + (BLACKOUT_START_MINUTES * 60) + HALF_HOUR);
    define('DISPLAY_RESTART',(BLACKOUT_END_HOURS *3600) + (BLACKOUT_END_MINUTES * 60) - HALF_HOUR);

    // Retrieve shifts for today
    $shift_sets = getShiftsForShiftTable($_SESSION['shift_timestamp']);
	/*echo "<pre>";
	var_dump($shift_sets);
	echo "</pre>";*/

    $start_time = earliest_shift_start_time($shift_sets);
    $end_time = latest_shift_end_time($shift_sets);
    if ($start_time >= $end_time) {
        echo "There are no shifts for today.\n";
        return;
    }

?>
<div id="shifts_by_day">
<?
    // Display the legend =D
    call_user_func("print_{$legend}_legend");
?>
    <div style='clear:both'></div>
    <table>
<?php print_positions($shift_sets) ?>
        <tr>
            <td class="time">
<?php
    // Print out the list of times, at half-hour intervals
    // FIXME: should we round down and up to the next half-hour?
    // if the first shift of the day started at 9:05 for some
    // reason, this would make the display weird...
    
	//George has hacked this so as to remove the blackout period from being displayed.  
	//Display up to a half hour after after the start of the blackout period, and start
	//again a half hour before it begins again.  
	if(BLACKOUT_EXISTS)
	{
		for ($i = $start_time; $i < $end_time; $i += HALF_HOUR)
		{
			if($i <= DISPLAY_STOP || $i >= DISPLAY_RESTART)
			{	
				echo "<div class=\"time\" style=\"height:" . SIZE_FACTOR . "em;\">" . date('g:i', date_part(time()) + $i) . "</div>\n";
			}
		}
	}
	else  //no blackout, perform the original behavior
	{
		for ($i = $start_time; $i < $end_time; $i += HALF_HOUR)
		{
			echo "<div class=\"time\" style=\"height:" . SIZE_FACTOR . "em;\">" . date('g:i', date_part(time()) + $i) . "</div>\n";
		//echo '<div class="time">' . date('g:i', date_part(time()) + $i) . "</div>\n";
		}
	}

?>
            </td>
<?php
    // Loop through positions
    foreach ($shift_sets as $shifts)
	{
        if (!count($shifts))
            continue;
    
	    echo "<td>\n";
        $current_time = $start_time;

        foreach ($shifts as $i => $shift) {
            $diff   = time_part($shift['start_time']) - $current_time;
            $length = $shift['end_time'] - $shift['start_time'];

            // Check that this shift is in the correct shift group
            if ($shift['shift_group'] != $_SESSION['shift_shiftgroup'])
                echo "<b>Error: Shift {$shift['pid']} returned, ".
                     "but is not in shiftgroup ".
                     "{$_SESSION['shift_shiftgroup']}</b><br>";

            /*
             * Check to see if there's space between the current time and the
             * start time of the next shift. If so, output a div.NoShift
             */
            if ($diff < 0) {
                echo "<b>Error: Overlapping shifts! Displayed times may " .
                     "not be correct</b>\n";
            } else if ($diff <= SMALL_DIFF) {
                /*
                 * This porridge is too small!
                 *
                 * If the diff is too small, IE would render the element too
                 * big. So we won't display a NoShift block, but we need to
                 * then compensate in the length of the next block (to assure
                 * consistency).
                 */
                $length += $diff;
            } else {
                // This porridge is just right!

		/* George sez: Not so fast, Goldilocks!  I want to skip displaying empty
		blocks in the blackout zone.  Commenting out original code...

                echo "<div class='NoShift' style='height: ".
                     ($diff * TIME_SCALE) . "em'></div>\n";     */
		
		/* George sez: First, shame on me for taking 2 hours to figure this out initially!
		Anyway, the blank spaces are a variable hight based on time until the next 
		shift, so subtracting DISPLAY_STOP from DISPLAY_RESTART and adding a half hour
		gives the corrected height.  
		
		I also check to see if the start time is earlier than the start of the blackout 
		don't want to perform the shift if we're not worried about the blackout gap
		 		
		*/
		if($start_time>DISPLAY_STOP)
		{
			$adjusted_diff = $diff;
		}
		else
		{
			//compute the correct time, and add a half hour so things line up...
			$adjusted_diff = $diff-(DISPLAY_RESTART - DISPLAY_STOP)+HALF_HOUR;
		}

		echo "<div class='NoShift' style='height: ".
                     ($adjusted_diff * TIME_SCALE) . "em'></div>\n";  
		
                $current_time += $diff;
            }
            $current_time += $length;

            /*
             * Output the outer div that sets the shift's height. We give this
             * div an overflow:hidden style unless it has a space after it or
             * or it's the last in its column. this is a hack to get the
             * heights to display correctly in IE.  (oh IE, how i loathe thee!)
             */
            if (($i == count($shifts) - 1) ||
                ($shifts[$i+1]['start_time'] - $shift['end_time'] > SMALL_DIFF))
                $overflow = '';
            else
                $overflow = 'overflow: hidden';

            // !!!TEMP: no overflow at all (why is this again?)
			$overflow = '';
			
?>
<div style='height: <?= $length * TIME_SCALE ?>em; <?= $overflow ?>'>
<? call_user_func($info_func, $shift) ?>
</div>
<?
        }
        echo "</td>\n";
    }
?>
        </tr>
<?php print_positions($shift_sets) ?>
    </table>

<?
    call_user_func("print_{$legend}_legend")
?>
  </div>
<?php
}

// Intentionally a NOOP
function print_none_legend()
{

}

/*
 * shift_table helper functions
 */

// Takes: the shifts array returned by getShiftsForShiftTable
function print_positions ($shift_sets)
{
    ?>
        <tr class="shiftHeader">
            <td class="time">&nbsp;</td> <!-- Time column -->
            <?php
            // Print out the column headers
            foreach ($shift_sets as $pid => $shifts)
				if (count($shifts) > 0)
				{
					$position = getPositionDetails($pid);
	                echo "<td>" . $position['name'] . "</td>\n";
				}
            ?>
        </tr>
    <?php
}

/*
 * Given an array of arrays containing shifts, determine when the earliest
 * starting time is of the shifts.
 */
function earliest_shift_start_time ($shift_sets)
{
    $earliest = 60*60*24;
    foreach ($shift_sets as $shift_set)
        foreach ($shift_set as $shift)
            if (time_part($shift['start_time']) < $earliest)
                $earliest = time_part($shift['start_time']);

    return $earliest;
}

/*
 * Given an array of arrays containing shifts, determine when the latest
 * ending time of the shifts is.
 */
function latest_shift_end_time ($shift_sets)
{
    $latest = 0;
    foreach ($shift_sets as $shift_set)
        foreach ($shift_set as $shift)
            if ($latest < time_part($shift['end_time']))
                $latest = time_part($shift['end_time']);

    return $latest;
}
?>
Return current item: ConPortal