diff options
Diffstat (limited to 'includes/model/Shifts_model.php')
-rw-r--r-- | includes/model/Shifts_model.php | 280 |
1 files changed, 166 insertions, 114 deletions
diff --git a/includes/model/Shifts_model.php b/includes/model/Shifts_model.php index a827c6b5..2db0a3d3 100644 --- a/includes/model/Shifts_model.php +++ b/includes/model/Shifts_model.php @@ -1,9 +1,83 @@ <?php +use Engelsystem\ShiftsFilter; +use Engelsystem\ShiftSignupState; + +function Shifts_by_room($room) { + $result = sql_select("SELECT * FROM `Shifts` WHERE `RID`=" . sql_escape($room['RID']) . " ORDER BY `start`"); + if ($result === false) { + engelsystem_error("Unable to load shifts."); + } + return $result; +} + +function Shifts_by_ShiftsFilter(ShiftsFilter $shiftsFilter, $user) { + $SQL = "SELECT DISTINCT `Shifts`.*, `ShiftTypes`.`name`, `Room`.`Name` as `room_name`, nat2.`special_needs` > 0 AS 'has_special_needs' + FROM `Shifts` + INNER JOIN `Room` USING (`RID`) + INNER JOIN `ShiftTypes` ON (`ShiftTypes`.`id` = `Shifts`.`shifttype_id`) + LEFT JOIN ( + SELECT COUNT(*) AS special_needs , nat3.`shift_id` + FROM `NeededAngelTypes` AS nat3 + WHERE `shift_id` IS NOT NULL + GROUP BY nat3.`shift_id` + ) AS nat2 ON nat2.`shift_id` = `Shifts`.`SID` + INNER JOIN `NeededAngelTypes` AS nat + ON nat.`count` != 0 + AND nat.`angel_type_id` IN (" . implode(',', $shiftsFilter->getTypes()) . ") + AND ( + (nat2.`special_needs` > 0 AND nat.`shift_id` = `Shifts`.`SID`) + OR + ( + (nat2.`special_needs` = 0 OR nat2.`special_needs` IS NULL) + AND nat.`room_id` = `RID`) + ) + LEFT JOIN ( + SELECT se.`SID`, se.`TID`, COUNT(*) as count + FROM `ShiftEntry` AS se GROUP BY se.`SID`, se.`TID` + ) AS entries ON entries.`SID` = `Shifts`.`SID` AND entries.`TID` = nat.`angel_type_id` + WHERE `Shifts`.`RID` IN (" . implode(',', $shiftsFilter->getRooms()) . ") + AND `start` BETWEEN " . $shiftsFilter->getStartTime() . " AND " . $shiftsFilter->getEndTime(); + + if (count($shiftsFilter->getFilled()) == 1) { + if ($shiftsFilter->getFilled()[0] == ShiftsFilter::FILLED_FREE) { + $SQL .= " + AND ( + nat.`count` > entries.`count` OR entries.`count` IS NULL + OR EXISTS ( + SELECT `SID` + FROM `ShiftEntry` + WHERE `UID` = '" . sql_escape($user['UID']) . "' + AND `ShiftEntry`.`SID` = `Shifts`.`SID` + ) + )"; + } elseif ($_SESSION['user_shifts']['filled'][0] == ShiftsFilter::FILLED_FILLED) { + $SQL .= " + AND ( + nat.`count` <= entries.`count` + OR EXISTS ( + SELECT `SID` + FROM `ShiftEntry` + WHERE `UID` = '" . sql_escape($user['UID']) . "' + AND `ShiftEntry`.`SID` = `Shifts`.`SID` + ) + )"; + } + } + $SQL .= " + ORDER BY `start`"; + + $result = sql_select($SQL); + if ($result === false) { + engelsystem_error("Unable to load shifts by filter."); + } + return $result; +} /** * Check if a shift collides with other shifts (in time). - * @param Shift $shift - * @param array<Shift> $shifts + * + * @param Shift $shift + * @param array<Shift> $shifts */ function Shift_collides($shift, $shifts) { foreach ($shifts as $other_shift) { @@ -17,29 +91,51 @@ function Shift_collides($shift, $shifts) { } /** - * Check if an angel can sign up for given shift. + * Returns the number of needed angels/free shift entries for an angeltype. * - * @param Shift $shift - * @param AngelType $angeltype - * @param array<Shift> $user_shifts + * @param int $shift_id + * ID of the shift to check + * @param int $angeltype_id + * ID of the angeltype that should be checked */ -function Shift_signup_allowed($shift, $angeltype, $user_angeltype = null, $user_shifts = null) { - global $user, $privileges; +function Shift_free_entries($shift_id, $angeltype_id) { + $needed_angeltypes = NeededAngelTypes_by_shift($shift_id); - if ($user_shifts == null) { - $user_shifts = Shifts_by_user($user); - if ($user_shifts === false) { - engelsystem_error('Unable to load users shifts.'); + foreach ($needed_angeltypes as $needed_angeltype) { + if ($needed_angeltype['angel_type_id'] == $angeltype_id) { + return max(0, $needed_angeltype['count'] - $needed_angeltype['taken']); } } - $collides = Shift_collides($shift, $user_shifts); + return 0; +} + +/** + * Check if an angel can sign up for given shift. + * + * @param Shift $shift + * The shift + * @param AngelType $angeltype + * The angeltype to which the user wants to sign up + * @param array<Shift> $user_shifts + * List of the users shifts + */ +function Shift_signup_allowed($user, $shift, $angeltype, $user_angeltype = null, $user_shifts = null) { + global $privileges; - if ($user_angeltype == null) { - $user_angeltype = UserAngelType_by_User_and_AngelType($user, $angeltype); - if ($user_angeltype === false) { - engelsystem_error('Unable to load user angeltype.'); + $free_entries = Shift_free_entries($shift['SID'], $angeltype['id']); + + if (in_array('user_shifts_admin', $privileges)) { + if ($free_entries == 0) { + // User shift admins may join anybody in every shift + return new ShiftSignupState(ShiftSignupState::ADMIN, $free_entries); } + + return new ShiftSignupState(ShiftSignupState::FREE, $free_entries); + } + + if ($user_shifts == null) { + $user_shifts = Shifts_by_user($user); } $signed_up = false; @@ -50,45 +146,37 @@ function Shift_signup_allowed($shift, $angeltype, $user_angeltype = null, $user_ } } - $needed_angeltypes = NeededAngelTypes_by_shift($shift['SID']); - if ($needed_angeltypes === false) { - engelsystem_error('Unable to load needed angel types.'); + if ($signed_up) { + // you cannot join if you already singed up for this shift + return new ShiftSignupState(ShiftSignupState::SIGNED_UP, $free_entries); } - // is the shift still running or alternatively is the user shift admin? - $user_may_join_shift = true; - - // you canot join if shift is full - foreach ($needed_angeltypes as $needed_angeltype) { - if ($needed_angeltype['angel_type_id'] == $angeltype['id']) { - if ($needed_angeltype['taken'] >= $needed_angeltype['count']) { - $user_may_join_shift = false; - } - break; - } + if (time() > $shift['start']) { + // you can only join if the shift is in future + return new ShiftSignupState(ShiftSignupState::SHIFT_ENDED, $free_entries); + } + if ($free_entries == 0) { + // you cannot join if shift is full + return new ShiftSignupState(ShiftSignupState::OCCUPIED, $free_entries); } - // you cannot join if user alread joined a parallel or this shift - $user_may_join_shift &= ! $collides; - - // you cannot join if you already singed up for this shift - $user_may_join_shift &= ! $signed_up; - - // you cannot join if user is not of this angel type - $user_may_join_shift &= $user_angeltype != null; - - // you cannot join if you are not confirmed - if ($angeltype['restricted'] == 1 && $user_angeltype != null) { - $user_may_join_shift &= isset($user_angeltype['confirm_user_id']); + if ($user_angeltype == null) { + $user_angeltype = UserAngelType_by_User_and_AngelType($user, $angeltype); } - // you can only join if the shift is in future - $user_may_join_shift &= time() < $shift['start']; + if ($user_angeltype == null || ($angeltype['restricted'] == 1 && $user_angeltype != null && ! isset($user_angeltype['confirm_user_id']))) { + // you cannot join if user is not of this angel type + // you cannot join if you are not confirmed + return new ShiftSignupState(ShiftSignupState::ANGELTYPE, $free_entries); + } - // User shift admins may join anybody in every shift - $user_may_join_shift |= in_array('user_shifts_admin', $privileges); + if (Shift_collides($shift, $user_shifts)) { + // you cannot join if user alread joined a parallel or this shift + return new ShiftSignupState(ShiftSignupState::COLLIDES, $free_entries); + } - return $user_may_join_shift; + // Hooray, shift is free for you! + return new ShiftSignupState(ShiftSignupState::FREE, $free_entries); } /** @@ -104,7 +192,11 @@ function Shift_delete_by_psid($shift_psid) { function Shift_delete($shift_id) { mail_shift_delete(Shift($shift_id)); - return sql_query("DELETE FROM `Shifts` WHERE `SID`='" . sql_escape($shift_id) . "'"); + $result = sql_query("DELETE FROM `Shifts` WHERE `SID`='" . sql_escape($shift_id) . "'"); + if ($result === false) { + engelsystem_error('Unable to delete shift.'); + } + return $result; } /** @@ -170,7 +262,7 @@ function Shift_create($shift) { * Return users shifts. */ function Shifts_by_user($user) { - return sql_select(" + $result = sql_select(" SELECT `ShiftTypes`.`id` as `shifttype_id`, `ShiftTypes`.`name`, `ShiftEntry`.*, `Shifts`.*, `Room`.* FROM `ShiftEntry` JOIN `Shifts` ON (`ShiftEntry`.`SID` = `Shifts`.`SID`) @@ -179,52 +271,10 @@ function Shifts_by_user($user) { WHERE `UID`='" . sql_escape($user['UID']) . "' ORDER BY `start` "); -} - -/** - * TODO: $_REQUEST is not allowed in model! - * Returns Shift id array - */ -function Shifts_filtered() { - global $_REQUEST; - $filter = ""; - - // filterRoom (Array of integer) - Array of Room IDs (optional, for list request) - if (isset($_REQUEST['filterRoom']) && is_array($_REQUEST['filterRoom'])) { - foreach ($_REQUEST['filterRoom'] as $key => $value) { - $filter .= ", `RID`='" . sql_escape($value) . "' "; - } - } - - // filterTask (Array of integer) - Array if Task (optional, for list request) - if (isset($_REQUEST['filterTask']) && is_array($_REQUEST['filterTask'])) { - foreach ($_REQUEST['filterTask'] as $key => $value) { - // TODO $filter .= ", `RID`=" . sql_escape($value) . " "; - } - } - - // filterOccupancy (integer) - Occupancy state: (optional, for list request) - // 1 occupied, 2 free, 3 occupied and free - if (isset($_REQUEST['filterOccupancy']) && is_array($_REQUEST['filterOccupancy'])) { - foreach ($_REQUEST['filterOccupancy'] as $key => $value) { - // TODO $filter .= ", `RID`=" . sql_escape($value) . " "; - } - } - - // format filter - if ($filter != "") { - $filter = ' WHERE ' . substr($filter, 1); - } - - // real request - $shifts_source = sql_select("SELECT `SID` FROM `Shifts`" . $filter); - if ($shifts_source === false) { - return false; - } - if (count($shifts_source) > 0) { - return $shifts_source; + if ($result === false) { + engelsystem_error('Unable to load users shifts.'); } - return null; + return $result; } /** @@ -242,27 +292,29 @@ function Shift($shift_id) { $shiftsEntry_source = sql_select("SELECT `id`, `TID` , `UID` , `freeloaded` FROM `ShiftEntry` WHERE `SID`='" . sql_escape($shift_id) . "'"); if ($shifts_source === false) { - return false; + engelsystem_error('Unable to load shift.'); } - if (count($shifts_source) > 0) { - $result = $shifts_source[0]; - - $result['ShiftEntry'] = $shiftsEntry_source; - $result['NeedAngels'] = []; - - $temp = NeededAngelTypes_by_shift($shift_id); - foreach ($temp as $e) { - $result['NeedAngels'][] = [ - 'TID' => $e['angel_type_id'], - 'count' => $e['count'], - 'restricted' => $e['restricted'], - 'taken' => $e['taken'] - ]; - } - - return $result; + + if (empty($shifts_source)) { + return null; } - return null; + + $result = $shifts_source[0]; + + $result['ShiftEntry'] = $shiftsEntry_source; + $result['NeedAngels'] = []; + + $temp = NeededAngelTypes_by_shift($shift_id); + foreach ($temp as $e) { + $result['NeedAngels'][] = [ + 'TID' => $e['angel_type_id'], + 'count' => $e['count'], + 'restricted' => $e['restricted'], + 'taken' => $e['taken'] + ]; + } + + return $result; } /** |