<?php
/*
* ConPortal - Pomona College ITS scheduling appplication
* Copyright (C) 2005-2008 Pomona College & Bucknell University
*
* 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
*/
/*
* Functions in this file:
* cancel_shift
* checkShiftCovered
* checkShiftsOverlap
* checkShowShiftDropButton
* checkShowShiftTakeButton
* checkUserCanDropShift
* checkUserCanTakeShift
* createShift
* copyShifts
* getAllShiftDetails
* getPositionDetails
* getPositions
* getShiftDetails
* getShiftDetailsForArray
* getShiftDetailsHumanReadable
* getShiftForTimeAndPosition
* getShifts
* getShiftsForDateRangeAndUser
* getShiftsForDayAndPosition
* getShiftsForDayAndUser
* getShiftsForShiftTable
* getShiftsForTime
* getShiftsForUser
* getShiftsForUserIncludingDropped
* getShiftStaffingStatus
* internalCancelSplit
* internalDropShift
* internalPermSplit
* internalShiftSplit
* internalTakeShift
* internalTempSplit
* isShiftTimeValid
* perm_drop_shift
* perm_take_shift
* temp_drop_shift
* temp_take_shift
* removeShift
* xlate_shiftdate
*/
// Cancel the given shift on the given day.
function cancel_shift ($shiftPid, $timestamp)
{
// No need to check whether user can drop this shift, since this function
// is only called from a "priveleged" page
// Perform the database mechanics
start_transaction();
internalCancelSplit($shiftPid, $timestamp);
commit_transaction();
}
function checkShiftCovered ($shiftPid)
{
$data = getShiftDetails($shiftPid);
return (isset($data['owner']) && $data['owner'] != 0);
}
/*
* Check if any shifts overlap with the (potential) shift specified
* by the startDate through positionPid parameters.
* Returns one of the following:
* - NULL if no shifts overlap
* - an array of the PIDs of overlapping shifts if any were found.
*
* If $shiftPid is set (i.e. not NULL), then that PID is specifically _excluded_
* from the check. So, if we are checking for overlapping shifts on a shift
* that is already in the database, set $shiftPid to that shifts' PID and we won't
* think that it's overlapping itself!
*
* A shift is defined as 'overlapping' if it occurs on the same date and
* shift 2 starts before shift 1 ends and shift 2 ends after shift 1 starts
*/
function checkShiftsOverlap ($shiftPid, $startDate, $endDate, $startTime, $endTime, $dow, $positionPid)
{
$query = sprintf("select pid from shifts where " .
"day_of_week = '%s' and " .
"position = %d and " .
"start_date <= FROM_UNIXTIME(%d) and end_date >= FROM_UNIXTIME(%d) and " .
"TIME_TO_SEC(start_time) < %d and TIME_TO_SEC(end_time) > %d",
mysql_real_escape_string($dow),
$positionPid,
$endDate, $startDate,
time_part($endTime), time_part($startTime));
if ($shiftPid)
$query .= " and pid != " . intval($shiftPid);
$result = safeQuery($query);
$a = array();
while ($row = mysql_fetch_assoc($result))
//if ($row['pid'] != $shiftPid)
$a[] = $row['pid'];
return $a;
}
/*
* Sam made this function to allow us to check to see if this person
* is working elsewhere at the same time. (Elsewhere means in another
* "position")
*/
function checkShiftsOverlapAnyPosition ($shiftPid, $startDate, $endDate, $startTime, $endTime, $dow)
{
$query = sprintf("select pid from shifts where " .
"day_of_week = '%s' and " .
"start_date <= FROM_UNIXTIME(%d) and end_date >= FROM_UNIXTIME(%d) and " .
"TIME_TO_SEC(start_time) < %d and TIME_TO_SEC(end_time) > %d",
mysql_real_escape_string($dow),
$endDate, $startDate,
time_part($endTime), time_part($startTime));
if ($shiftPid)
$query .= " and pid != " . intval($shiftPid);
$result = safeQuery($query);
$a = array();
while ($row = mysql_fetch_assoc($result))
//if ($row['pid'] != $shiftPid)
$a[] = $row['pid'];
return $a;
}
/*
* Determine whether to show a shift-drop button for this shift.
*/
function checkShowShiftDropButton ($shiftPid, $timestamp)
{
if (checkPerm($_SESSION, "shifts"))
return isShiftTimeValid($shiftPid, $timestamp);
return checkUserCanDropShift($_SESSION['pid'], $shiftPid, $timestamp);
}
/*
* Determine whether to show a shift-take button for this shift.
*/
function checkShowShiftTakeButton ($shiftPid, $timestamp)
{
if (checkPerm($_SESSION, "shifts"))
return isShiftTimeValid($shiftPid, $timestamp);
return checkUserCanTakeShift($_SESSION['pid'], $shiftPid, $timestamp);
}
function checkUserCanDropShift ($userPid, $shiftPid, $timestamp)
{
$shift = getShiftDetails($shiftPid);
// Shift timestamp sanity checks
if (!isShiftTimeValid($shiftPid, $timestamp))
return false;
// Allow users with "shifts" permission to short-circuit the remaining checks
if (checkPerm($_SESSION, "shifts"))
return true;
// Check that the user owns this shift
if (!isset($shift['owner']) or $shift['owner'] != $userPid)
return false;
return true;
}
/*
* Run a number of tests to determine whether the user is allowed to
* take the specified shift (on the specified day).
*/
function checkUserCanTakeShift ($userPid, $shiftPid, $timestamp)
{
$shift = getShiftDetails($shiftPid);
// If the shift is already taken, then this person can't take it
if (isset($shift['owner']))
return false;
// Ensure this timestamp really falls within the shift, on the
// right day of the week, etc (basic sanity checks)
if (!isShiftTimeValid($shiftPid, $timestamp))
return false;
//added by George and modified by sam to make sure people don't take the same hour twice
if(!(notAlreadyTakenTheseHours($userPid, $shiftPid)))
return false;
// Allow users with "shifts" permission to short-circuit the remaining checks
if (checkPerm($_SESSION, "shifts"))
return true;
// Determine if the user who is being staffed has enough time to take this shift
if (!drawCheckRemainingTime($userPid, $shiftPid, $timestamp))
return false;
// If there are no restrictions on the position of this shift (signaled
// by there being no entries in position_group for it), then any users can take it
$position_groups = getGroupsForPosition($shift['position']);
if (count($position_groups) == 0)
return true;
// Otherwise, check that the user is in one of the position groups
$user_groups = getGroupsForUser($_SESSION['pid']);
$user_groups[] = getPrimaryGroupForUser($userPid);
return count(array_intersect($user_groups, $position_groups)) > 0;
}
/*
* Creates a new shift. The start and end dates are inherited from the
* specified shiftgroup if $startDate and $endDate are NULL.
*
* Returns NULL on error or the PID of the newly created shift otherwise.
* owner, dropper, time_taken, and time_dropped are all left as NULL.
*
* Since overlapping shifts are a big NO-NO, this function does include
* checking to ensure that the newly created shift does not overlap with any
* other shift (based on (start|end)_date, (start|end)_time, $dow, and
* $position).
*/
function createShift ($shiftgroupPid, $dow, $positionPid, $startTime, $endTime,
$startDate = NULL, $endDate = NULL)
{
// get the shiftgroup information
$shiftgroup = getShiftgroupDetails($shiftgroupPid);
if (!$shiftgroup)
{
error("Unknown shift group '$shiftgroupPid'");
return NULL;
}
if (!$startDate)
$startDate = $shiftgroup['start_date'];
if (!$endDate)
$endDate = $shiftgroup['end_date'];
// Check for overlapping shifts like we promised in the function desc...
$overlapping = checkShiftsOverlap(NULL, $startDate, $endDate,
$startTime, $endTime, $dow,
$positionPid);
if ($overlapping)
{
// non-NULL indicates that we found some overlapping shifts :-(
error("Found some overlapping shifts: " . implode(", ", $overlapping));
return NULL;
}
// All clear, create the shift!
safeQuery("insert into shifts set " .
"shift_group = %d, " .
"start_date = FROM_UNIXTIME(%d), " .
"end_date = FROM_UNIXTIME(%d), " .
"start_time = SEC_TO_TIME(%d), " .
"end_time = SEC_TO_TIME(%d), " .
"day_of_week = '%s', " .
"position = %d",
$shiftgroupPid,
$startDate, $endDate,
time_part($startTime), time_part($endTime),
mysql_real_escape_string($dow),
$positionPid);
return mysql_insert_id();
}
/*
* Copies the whole set of shifts from a day of the week in one shift group
* to another day of the week in (possibly the same) shiftgroup
*
* Since overlapping shits are a big NO-NO, this function does include checking
* to ensure that no shifts already existed for the shift group and day
* being copied to... YAY!
*
* Ownership information *IS NOT COPIED*
*/
function copyShifts ($fromShiftgroup, $fromDOW, $toShiftgroup, $toDOW)
{
// make sure that no shifts exist on the 'to' day
$result = safeQuery("select pid from shifts where shift_group = %d and day_of_week = '%s'",
$toShiftgroup, mysql_real_escape_string($toDOW));
if (mysql_num_rows($result) > 0)
{
error("Error copying a whole day of shifts: there are already shifts " .
"for shift group $toShiftgroup on $toDOW.");
return false;
}
// get shiftgroup info
$fromSGDetails = getShiftgroupDetails($fromShiftgroup);
$toSGDetails = getShiftgroupDetails($toShiftgroup);
// tell the DB to make the transfer
// NOTE! if we're copying from a shiftgroup that has shift splits and so forth,
// we're at risk of creating overlaps because the start/end dates are all reset
// in the destination. SO, only copy those shifts whose start date is identical
// to the start date of the originating shift group. This should extract only
// one non-overlapping set of shifts.
$result = safeQuery("insert into shifts select " .
"NULL as pid, " .
"%d as shift_group, " .
"FROM_UNIXTIME(%d) as start_date, FROM_UNIXTIME(%d) as end_date, " .
"start_time, end_time, " .
"'%s' as day_of_week, " .
"position, " .
"NULL as owner, NULL as dropper, NULL as time_taken, NULL as time_dropped " .
"from shifts where shift_group = %d and day_of_week = '%s' and start_date = FROM_UNIXTIME(%d)",
$toShiftgroup,
$toSGDetails["start_date"], $toSGDetails["end_date"],
mysql_real_escape_string($toDOW),
$fromShiftgroup,
mysql_real_escape_string($fromDOW),
$fromSGDetails["start_date"]);
return true;
}
function getAllShiftDetails ()
{
return getShiftDetailsForArray(getShifts());
}
function getPositionDetails ($pid)
{
$result = safeQuery("select * from positions where pid = %d", $pid);
return mysql_fetch_assoc($result);
}
/*
* Array of pids of all positions
*/
function getPositions ()
{
$result = safeQuery("select pid from positions order by display_order asc");
$array = array();
while ($row = mysql_fetch_assoc($result))
$array[] = $row['pid'];
return $array;
}
/*
* master shifts query, doing all the necessary translations of date/time values
* all other functions should use this (or getShiftDetailsForArray, below) to
* retrieve shift data. NEVER, NEVER write "select * from shifts"!
*/
function getShiftDetails ($shiftPid)
{
//added ORDER BY stuff for revision 252, 7/11/07
$result = safeQuery("select pid, shift_group, day_of_week, position, owner, dropper, " .
"UNIX_TIMESTAMP(start_date) as start_date, " .
"UNIX_TIMESTAMP(end_date) as end_date, " .
"(UNIX_TIMESTAMP(start_date) + TIME_TO_SEC(start_time)) as start_time, " .
"(UNIX_TIMESTAMP(start_date) + TIME_TO_SEC(end_time)) as end_time, " .
"UNIX_TIMESTAMP(time_taken) as time_taken, " .
"UNIX_TIMESTAMP(time_dropped) as time_dropped " .
"from shifts where pid = %d ORDER BY end_time DESC", $shiftPid);
return mysql_fetch_assoc($result);
}
/*
* getShiftDetailsForArray - returns details for each in an array of shift PIDs.
*/
function getShiftDetailsForArray ($array)
{
$a = array();
foreach ($array as $pid)
$a[] = getShiftDetails($pid);
return $a;
}
/*
* Return shift details in human readable format (e.g. person's name
* instead of user pid, date strings instead of timestamps, etc...)
*/
function getShiftDetailsHumanReadable ($shiftPid)
{
$shiftData = getShiftDetails($shiftPid);
if (!$shiftData)
return NULL;
$shiftgroup = getShiftgroupDetails($shiftData['shift_group']);
$shiftData['shift_group'] = $shiftgroup['name'];
list($shiftData['start_date'], $shiftData['end_date']) =
xlate_shiftdate($shiftData['day_of_week'], $shiftData['start_date'], $shiftData['end_date'], $shiftData['pid']);
$shiftData['start_date'] = date("n/j", $shiftData['start_date']);
$shiftData['end_date'] = date("n/j", $shiftData['end_date']);
$shiftData['start_time'] = date("g:i a", $shiftData['start_time']);
$shiftData['end_time'] = date("g:i a", $shiftData['end_time']);
$shiftData['day_of_week'] = ucfirst($shiftData['day_of_week']);
$position = getPositionDetails($shiftData['position']);
$shiftData['position'] = $position['name'];
if (isset($shiftData['owner']))
$shiftData['owner'] = getNameForUser($shiftData['owner']);
if (isset($shiftData['dropper']))
$shiftData['dropper'] = getNameForUser($shiftData['dropper']);
if (isset($shiftData['time_taken']))
$shiftData['time_taken'] = date("n/j g:ia", $shiftData['time_taken']);
if (isset($shiftData['time_dropped']))
$shiftData['time_dropped'] = date("n/j g:ia", $shiftData['time_dropped']);
return $shiftData;
}
/*
* Returns single PID of shift at a given time for a particular position
*/
function getShiftForTimeAndPosition ($timestamp, $positionPid)
{
$result = safeQuery("select pid from shifts where " .
"day_of_week = '%s' and position = %d and " .
"start_date <= FROM_UNIXTIME(%d) and " .
"end_date >= FROM_UNIXTIME(%d) and " .
"TIME_TO_SEC(start_time) <= %d and " .
"TIME_TO_SEC(end_time) > %d",
strtolower(date('l', $timestamp)), $positionPid,
$timestamp, $timestamp,
time_part($timestamp), time_part($timestamp));
if (mysql_num_rows($result) == 0)
return NULL;
$row = mysql_fetch_assoc($result);
return $row['pid'];
}
/*
* All shift pids
*/
function getShifts ()
{
$result = safeQuery("select pid from shifts");
$array = array();
while ($row = mysql_fetch_assoc($result))
$array[] = $row['pid'];
return $array;
}
/*
* Find the shifts taken by the specified user on the days between
* start_date and end_date (inclusive). Returns array of PIDs.
*
* Does not return temp-dropped shifts.
*/
//Updated by George for Revision 250 on 7/12/07 to add sorting
function getShiftsForDateRangeAndUser ($userPid, $startDate, $endDate)
{
$result = safeQuery("select pid, day_of_week, " .
"UNIX_TIMESTAMP(start_date) as start_date, " .
"UNIX_TIMESTAMP(end_date) as end_date " .
"from shifts where owner = %d and " .
"start_date <= FROM_UNIXTIME(%d) and end_date >= FROM_UNIXTIME(%d) ORDER BY end_time",
$userPid, $endDate, $startDate);
$a = array();
while ($row = mysql_fetch_assoc($result))
{
// Use xlate_shiftdate to get real shift start and end dates, and filter
// based on the same condition as in the query
list($start, $end) = xlate_shiftdate($row['day_of_week'], $row['start_date'], $row['end_date'], $row['pid']);
if ($start <= $endDate and $end >= $startDate)
$a[] = $row['pid'];
}
return $a;
}
/* getShiftsForDayAndPosition ($date, $positionPid)
* retrieves array of PIDs of shifts occuring on the date and
* assigned to the given position
*/
function getShiftsForDayAndPosition ($date, $positionPid)
{
$result = safeQuery("select pid from shifts where " .
"start_date <= FROM_UNIXTIME(%d) and end_date >= FROM_UNIXTIME(%d) " .
"and position = %d and day_of_week = '%s'",
date_part($date), date_part($date), $positionPid,
strtolower(date('l', $date)));
$a = array();
while ($row = mysql_fetch_assoc($result))
$a[] = $row['pid'];
return $a;
}
/* getShiftsForDayAndUser ($userPid, $date)
* retrieves PIDS of shifts worked by that user on that date
*/
function getShiftsForDayAndUser ($userPid, $date)
{
$result = safeQuery("select pid from shifts where " .
"start_date <= FROM_UNIXTIME(%d) and end_date >= FROM_UNIXTIME(%d) " .
"and owner = %d and day_of_week = '%s'",
date_part($date), date_part($date), $userPid,
strtolower(date('l', $date)));
$a = array();
while ($row = mysql_fetch_assoc($result))
$a[] = $row['pid'];
return $a;
}
/* getShiftsForShiftTable ($date)
* retrieves all the data for all shifts occuring on the specified date.
* returned in an array format:
* array(position_pids => array(0,1,... => shiftDetails))
*/
function getShiftsForShiftTable ($date)
{
$positions = getPositions();
$shifts_today = array();
foreach ($positions as $positionPid)
{
$pids = getShiftsForDayAndPosition($date, $positionPid);
$shifts_today[$positionPid] = sortShiftsByTime(getShiftDetailsForArray($pids));
}
return $shifts_today;
}
/*
* Get array of PIDs of all shifts occurring at the specified date/time.
*/
function getShiftsForTime ($timestamp)
{
$result = safeQuery("select pid from shifts where " .
"day_of_week = '%s' and " .
"start_date <= FROM_UNIXTIME(%d) and " .
"end_date >= FROM_UNIXTIME(%d) and " .
"TIME_TO_SEC(start_time) <= %d and " .
"TIME_TO_SEC(end_time) > %d",
strtolower(date('l', $timestamp)),
$timestamp, $timestamp,
time_part($timestamp), time_part($timestamp));
$a = array();
while ($row = mysql_fetch_assoc($result))
$a[] = $row['pid'];
return $a;
}
/*
* Get pids of shifts owned by this user (not including temp-dropped)
*/
function getShiftsForUser ($userPid)
{
$result = safeQuery("select pid from shifts where owner = %d", $userPid);
$a = array();
while ($row = mysql_fetch_assoc($result))
$a[] = $row['pid'];
return $a;
}
/*
* Get pids of shifts owned or previously owned by this user,
* including shifts they dropped that no one has yet picked up.
*/
function getShiftsForUserIncludingDropped ($userPid)
{
$result = safeQuery("select pid from shifts where " .
"owner = %d or (dropper = %d and owner is null)", $userPid, $userPid);
$a = array();
while ($row = mysql_fetch_assoc($result))
$a[] = $row['pid'];
return $a;
}
/*
* Get status of the given shift PID, returns one of the following enums:
*/
define('STATUS_PERM_OPEN', 0);
define('STATUS_PERM_TAKEN', 1);
define('STATUS_TEMP_OPEN', 2);
define('STATUS_TEMP_TAKEN', 3);
function getShiftStaffingStatus ($shiftPid)
{
$shift = getShiftDetails($shiftPid);
if (isset($shift['owner']))
{
// Taken shift; if it occurs only once, consider it a temp shift;
// otherwise, a perm shift.
if ($shift['end_date'] < strtotime("+1 week", $shift['start_date']))
return STATUS_TEMP_TAKEN;
else
return STATUS_PERM_TAKEN;
}
else
{
// Open shift; if it occurs only once AND has a dropper,
// consider it a temp shift; otherwise, a perm shift.
if ($shift['end_date'] < strtotime("+1 week", $shift['start_date']) and isset($shift['dropper']))
return STATUS_TEMP_OPEN;
else
return STATUS_PERM_OPEN;
}
}
/*
* Split the shift into *before this day* and *after this day*, thus
* appearing to cancel it for the given day only. Works properly if the
* given timestamp is in fact the first or last day of the shift.
*/
function internalCancelSplit ($shiftPid, $timestamp)
{
// Create the before, this, and after segments
$newShift = internalTempSplit($shiftPid, $timestamp);
// Now we can be assured that $newShift occurs only once, on
// the day we want to cancel it. So delete it from the DB.
if (!removeShift($newShift))
{
error("internalCancelSplit($shiftPid, $timestamp): Unable to delete shift $newShift: did not exist");
return NULL;
}
return $newShift;
}
/*
* Set owner and time_taken to NULL. Set dropper and time_dropped.
*/
function internalDropShift ($shiftPid, $userPid)
{
safeQuery("update shifts set owner = NULL, time_taken = NULL, " .
"dropper = %d, time_dropped = NOW() where pid = %d",
$userPid, $shiftPid);
}
/*
* Split the shift into *before this day* and *this day and after this day*.
* Works properly if timestamp represents the first date of the shift.
* Returns the PID of the "this day and after" shift.
*/
function internalPermSplit ($shiftPid, $timestamp)
{
$newShift = internalSplitShift($shiftPid, $timestamp);
if (!$newShift)
$newShift = $shiftPid;
return $newShift;
}
/* internalSplitShift(shift PID, date (timestamp))
*
* Take a shift and split it around splitDate. The new shift starts on
* $splitDate and the old shift is shortened to end one day before $splitDate.
*
* Returns NULL if splitDate is the first day of the shift, or the PID of the
* new shift otherwise.
*/
function internalSplitShift ($oldPid, $splitDate)
{
// Check whether this is the first date of the shift
$data = getShiftDetails($oldPid);
if (strtotime("-7 days", date_part($splitDate)) < $data['start_date'])
// If this is the first shift
return NULL;
// Create the new shift (starts at $splitDate, but copies all other fields
// from the original shift)
safeQuery("INSERT INTO shifts (shift_group, start_date, end_date, " .
" start_time, end_time, day_of_week, position, owner, dropper, " .
" time_taken, time_dropped) " .
"SELECT shift_group, FROM_UNIXTIME(%d) as start_date, end_date, start_time, " .
" end_time, day_of_week, position, owner, dropper, time_taken, " .
" time_dropped FROM shifts WHERE pid = %d",
date_part($splitDate), $oldPid);
$newPid = mysql_insert_id();
// Resize the old shift (goes from start_date to $splitDate - 1)
safeQuery("UPDATE shifts SET end_date = (FROM_UNIXTIME(%d) - INTERVAL 1 DAY) " .
"WHERE pid = %d", date_part($splitDate), $oldPid);
return $newPid;
}
/*
* Set the owner of the shift to user and set time_taken.
*/
function internalTakeShift ($shiftPid, $userPid)
{
safeQuery("UPDATE shifts SET owner = %d, time_taken = NOW() " .
"WHERE pid = %d", $userPid, $shiftPid);
}
/*
* Split the shift into *before this day*, *this day*, and *after this day*.
* Works properly if timestamp represents the first day of the shift.
* Returns the PID of the *this day* shift.
*/
function internalTempSplit ($shiftPid, $timestamp)
{
$newShift = internalSplitShift($shiftPid, $timestamp);
if (!$newShift)
$newShift = $shiftPid;
// Check if this is the last day of the shift
$data = getShiftDetails($newShift);
$nextTimestamp = strtotime("+7 days", $timestamp);
if (date_part($nextTimestamp) <= $data['end_date']) {
$temp = internalSplitShift($newShift, $nextTimestamp);
}
return $newShift;
}
/*
* Determine if timestamp is a day on which shift occurs (basic sanity check
* for taking/dropping), and if timestamp is within the agreed upon future
* time limit of 1 month (people can't take/drop shifts further than that
* in advance).
*/
function isShiftTimeValid ($shiftPid, $timestamp)
{
$shift = getShiftDetails($shiftPid);
$start = $shift['start_date'];
$end = $shift['end_date'];
// Within the shift's bounds.
$date = ($start <= $timestamp and $timestamp <= $end);
// Date in the agreed upon time (between today and one month from today)
//NOTE George changed this from 1 month to 2; may change later.
$time = ($timestamp >= date_part(time())) &&
($timestamp < strtotime("+2 month"));
// Correct day-of-week
$dow = (!strcasecmp(date('l', $timestamp), $shift['day_of_week']));
// Timestamp represents midnight
$mid = (time_part($timestamp) == 0);
return ($date && $time && $dow && $mid);
}
function perm_drop_shift ($shiftPid, $timestamp, $userPid, $email_message)
{
// Do checks to ensure that this user can perm-drop this shift
$shift_data = getShiftDetails($shiftPid);
if (!$shift_data)
{
error("Shift $shiftPid does not exist.");
return NULL;
}
if (!checkUserCanDropShift($userPid, $shiftPid, $timestamp))
{
error('You are not allowed to drop this shift.');
return NULL;
}
// Doing this as transaction so that nobody could ever possibly see the
// database in an inconsistent state.
start_transaction();
// Split the shift on today
$newShift = internalPermSplit($shiftPid, $timestamp);
// Update the information of the new shift
$result = internalDropShift($newShift, $userPid);
// commit transaction
commit_transaction();
//check to see if we shouldn't send email
$someRow = getShiftDetails($shiftPid);
if(checkIfShouldSendEmail($someRow['shift_group']))
email_cons_perm_drop($newShift, $shift_data['owner'], $email_message);
return $newShift;
}
function perm_take_shift ($shiftPid, $timestamp, $userPid, $email_message)
{
// Do checks to ensure that this is a valid action
$shift_data = getShiftDetails($shiftPid);
if (!$shift_data)
{
error("Shift $shiftPid does not exist.");
return NULL;
}
if (!checkUserCanTakeShift($userPid, $shiftPid, $timestamp))
{
error('You are not allowed to take this shift.');
return NULL;
}
// Doing this as transaction so that nobody could ever possibly see the
// database in an inconsistent state.
start_transaction();
// Split the shift on this day
$newShift = internalPermSplit($shiftPid, $timestamp);
// Update the information of the new shift
$result = internalTakeShift($newShift, $userPid);
// commit transaction
commit_transaction();
//check to see if we shouldn't send email
$someRow = getShiftDetails($shiftPid);
if(checkIfShouldSendEmail($someRow['shift_group']))
email_cons_perm_take($newShift, $userPid, $email_message);
return $newShift;
}
function temp_drop_shift ($shiftPid, $timestamp, $userPid, $email_message)
{
// Do checks to ensure that this user can temp-drop this shift
$shift_data = getShiftDetails($shiftPid);
if (!$shift_data)
{
error("Shift $shiftPid does not exist.");
return NULL;
}
if (!checkUserCanDropShift($userPid, $shiftPid, $timestamp))
{
error('You are not allowed to drop this shift.');
return NULL;
}
// Doing this as transaction so that nobody could ever possibly see the
// database in an inconsistent state.
start_transaction();
// Split the shift on this day, then, if this day isn't the last day of the
// shift, split this shift on +7 days.
$newShift = internalTempSplit($shiftPid, $timestamp);
// Update the information of the new shift
$result = internalDropShift($newShift, $userPid);
// commit transaction
commit_transaction();
//check to see if we shouldn't send email
$someRow = getShiftDetails($shiftPid);
if(checkIfShouldSendEmail($someRow['shift_group']))
email_cons_temp_drop($newShift, $shift_data['owner'], $email_message);
return;
}
function temp_take_shift ($shiftPid, $timestamp, $userPid, $email_message)
{
// Do checks to ensure that this user can temp-take this shift
$shift_data = getShiftDetails($shiftPid);
if (!$shift_data)
{
error("Shift $shiftPid does not exist.");
return NULL;
}
if (!checkUserCanTakeShift($userPid, $shiftPid, $timestamp))
{
error('You are not allowed to take this shift.');
return NULL;
}
// Doing this as transaction so that nobody could ever possibly see the
// database in an inconsistent state.
start_transaction();
// Splits it on this day and then this day + 7 (so we end
// up with *before this day*, *this day*, and *after this day*)
$newShift = internalTempSplit($shiftPid, $timestamp);
// Update the information of the new shift
$result = internalTakeShift($newShift, $userPid);
// commit transaction
commit_transaction();
//check to see if we shouldn't send email
$someRow = getShiftDetails($shiftPid);
if(checkIfShouldSendEmail($someRow['shift_group']))
email_cons_temp_take($newShift, $userPid, $email_message);
return $newShift;
}
function removeShift ($pid)
{
safeQuery("delete from shifts where pid = %d", $pid);
return (mysql_affected_rows() == 1);
}
/* Given a day_of_week, the start date, and the end date of a shift, return
* the actual start and end date of the shift (i.e. the returned start and end
* dates wiil both fall on the appropriate day of the week.
*
* $start_date and $end_date are timestamps.
*
* DO NOT DO NOT DO NOT DO NOT DO NOT remove the dual strtotime()
* calls (strtotime('12AM', strtotime('stuff...)))!!!!!!!!
*
* Hacking around a bug with the 'this ...' and 'last ...' and
* strtotime() in PHP and Daylight Saving Time:
print date('r', strtotime('last thursday', strtotime("00:00:00 April 3, 2006")));
outputs
Wed, 29 Mar 2006 23:00:00 -0800
*/
function xlate_shiftdate($day_of_week, $start_date, $end_date, $shift_pid = 0)
{
if (strcasecmp(date("l", $start_date), $day_of_week) == 0)
$new_start = $start_date;
else
$new_start = strtotime('12AM', strtotime("12PM this $day_of_week", $start_date));
if (strcasecmp(date("l", $end_date), $day_of_week) == 0)
$new_end = $end_date;
else
$new_end = strtotime('12AM', strtotime("12PM last $day_of_week", $end_date));
if ($new_start > $end_date or $new_end < $start_date)
exit("Xlate exception: this shift never actually occurs " .
"($new_start > $end_date or $new_end < $start_date). Please contact supers immediately. Shift pid is $shift_pid");
return array($new_start, $new_end);
}
?>