From 46528fe1d888ae09d125c2ae8ac1952f1d7f29f6 Mon Sep 17 00:00:00 2001 From: msquare Date: Tue, 27 Dec 2016 23:02:05 +0100 Subject: shift view performance improvements --- includes/controller/rooms_controller.php | 4 +- includes/controller/shift_entries_controller.php | 5 +- includes/controller/shifts_controller.php | 8 +- includes/model/Shifts_model.php | 181 ++++++++++++++--------- includes/model/UserAngelTypes_model.php | 7 +- includes/mysqli_provider.php | 3 + includes/pages/user_shifts.php | 17 +-- includes/view/ShiftCalendarRenderer.php | 26 +++- includes/view/ShiftCalendarShiftRenderer.php | 45 +++--- includes/view/Shifts_view.php | 5 +- 10 files changed, 189 insertions(+), 112 deletions(-) diff --git a/includes/controller/rooms_controller.php b/includes/controller/rooms_controller.php index 0e8560d5..7a4f543b 100644 --- a/includes/controller/rooms_controller.php +++ b/includes/controller/rooms_controller.php @@ -44,10 +44,12 @@ function room_controller() { $shiftsFilterRenderer->enableDaySelection($days); $shifts = Shifts_by_ShiftsFilter($shiftsFilter, $user); + $needed_angeltypes = NeededAngeltypes_by_ShiftsFilter($shiftsFilter, $user); + $shift_entries = ShiftEntries_by_ShiftsFilter($shiftsFilter, $user); return [ $room['Name'], - Room_view($room, $shiftsFilterRenderer, new ShiftCalendarRenderer($shifts, $shiftsFilter)) + Room_view($room, $shiftsFilterRenderer, new ShiftCalendarRenderer($shifts, $needed_angeltypes, $shift_entries, $shiftsFilter)) ]; } diff --git a/includes/controller/shift_entries_controller.php b/includes/controller/shift_entries_controller.php index 32c94a6b..d0a12288 100644 --- a/includes/controller/shift_entries_controller.php +++ b/includes/controller/shift_entries_controller.php @@ -48,7 +48,10 @@ function shift_entry_add_controller() { $user_id = $user['UID']; } - $shift_signup_allowed = Shift_signup_allowed(User($user_id), $shift, $type); + $needed_angeltype = NeededAngeltype_by_Shift_and_Angeltype($shift, $type); + $shift_entries = ShiftEntries_by_shift_and_angeltype($shift['SID'], $type['id']); + + $shift_signup_allowed = Shift_signup_allowed(User($user_id), $shift, $type, null, null, $needed_angeltype, $shift_entries); if (! $shift_signup_allowed->isSignupAllowed()) { error(_("You are not allowed to sign up for this shift. Maybe shift is full or already running.")); redirect(shift_link($shift)); diff --git a/includes/controller/shifts_controller.php b/includes/controller/shifts_controller.php index 1e04c5a8..9ac8a766 100644 --- a/includes/controller/shifts_controller.php +++ b/includes/controller/shifts_controller.php @@ -202,13 +202,17 @@ function shift_controller() { $user_shifts = Shifts_by_user($user); $shift_signup_state = new ShiftSignupState(ShiftSignupState::OCCUPIED, 0); - foreach ($angeltypes as $angeltype) { - $angeltype_signup_state = Shift_signup_allowed($user, $shift, $angeltype, null, $user_shifts); + foreach ($angeltypes as &$angeltype) { + $needed_angeltype = NeededAngeltype_by_Shift_and_Angeltype($shift, $angeltype); + $shift_entries = ShiftEntries_by_shift_and_angeltype($shift['SID'], $angeltype['id']); + + $angeltype_signup_state = Shift_signup_allowed($user, $shift, $angeltype, null, $user_shifts, $needed_angeltype, $shift_entries); if ($shift_signup_state == null) { $shift_signup_state = $angeltype_signup_state; } else { $shift_signup_state->combineWith($angeltype_signup_state); } + $angeltype['shift_signup_state'] = $angeltype_signup_state; } return [ diff --git a/includes/model/Shifts_model.php b/includes/model/Shifts_model.php index e45c54ac..5565ba92 100644 --- a/includes/model/Shifts_model.php +++ b/includes/model/Shifts_model.php @@ -11,7 +11,7 @@ function Shifts_by_room($room) { } function Shifts_by_ShiftsFilter(ShiftsFilter $shiftsFilter, $user) { - $SQL="SELECT `Shifts`.*, `ShiftTypes`.`name`, `Room`.`Name` as `room_name` + $SQL = "SELECT `Shifts`.*, `ShiftTypes`.`name`, `Room`.`Name` as `room_name` FROM `Shifts` JOIN `Room` USING (`RID`) JOIN `ShiftTypes` ON `ShiftTypes`.`id` = `Shifts`.`shifttype_id` @@ -19,49 +19,49 @@ function Shifts_by_ShiftsFilter(ShiftsFilter $shiftsFilter, $user) { AND `start` BETWEEN " . $shiftsFilter->getStartTime() . " AND " . $shiftsFilter->getEndTime() . " ORDER BY `Shifts`.`start`"; /** - $SQL = "SELECT DISTINCT `Shifts`.*, `ShiftTypes`.`name`, `Room`.`Name` as `room_name` - 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 - )"; - } elseif ($_SESSION['user_shifts']['filled'][0] == ShiftsFilter::FILLED_FILLED) { - $SQL .= " - AND ( - nat.`count` <= entries.`count` - )"; - } - } - $SQL .= " - ORDER BY `start`"; - */ + * $SQL = "SELECT DISTINCT `Shifts`.*, `ShiftTypes`.`name`, `Room`.`Name` as `room_name` + * 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 + * )"; + * } elseif ($_SESSION['user_shifts']['filled'][0] == ShiftsFilter::FILLED_FILLED) { + * $SQL .= " + * AND ( + * nat.`count` <= entries.`count` + * )"; + * } + * } + * $SQL .= " + * ORDER BY `start`"; + */ $result = sql_select($SQL); if ($result === false) { engelsystem_error("Unable to load shifts by filter."); @@ -69,6 +69,56 @@ function Shifts_by_ShiftsFilter(ShiftsFilter $shiftsFilter, $user) { return $result; } +function NeededAngeltypes_by_ShiftsFilter(ShiftsFilter $shiftsFilter, $user) { + $SQL = "SELECT `NeededAngelTypes`.*, `AngelTypes`.`id`, `AngelTypes`.`name`, `AngelTypes`.`restricted`, `AngelTypes`.`no_self_signup` + FROM `Shifts` + JOIN `NeededAngelTypes` ON `NeededAngelTypes`.`shift_id`=`Shifts`.`SID` + JOIN `AngelTypes` ON `AngelTypes`.`id`= `NeededAngelTypes`.`angel_type_id` + WHERE `Shifts`.`RID` IN (" . implode(',', $shiftsFilter->getRooms()) . ") + AND `start` BETWEEN " . $shiftsFilter->getStartTime() . " AND " . $shiftsFilter->getEndTime() . " + ORDER BY `Shifts`.`start`"; + // FIXME: Use needed angeltypes on rooms! + $result = sql_select($SQL); + if ($result === false) { + engelsystem_error("Unable to load needed angeltypes by filter."); + } + return $result; +} + +function NeededAngeltype_by_Shift_and_Angeltype($shift, $angeltype) { + $SQL = "SELECT `NeededAngelTypes`.*, `AngelTypes`.`id`, `AngelTypes`.`name`, `AngelTypes`.`restricted`, `AngelTypes`.`no_self_signup` + FROM `Shifts` + JOIN `NeededAngelTypes` ON `NeededAngelTypes`.`shift_id`=`Shifts`.`SID` + JOIN `AngelTypes` ON `AngelTypes`.`id`= `NeededAngelTypes`.`angel_type_id` + WHERE `Shifts`.`SID`=" . sql_escape($shift['SID']) . " + AND `AngelTypes`.`id`=" . sql_escape($angeltype['id']) . " + ORDER BY `Shifts`.`start`"; + // FIXME: Use needed angeltypes on rooms! + $result = sql_select($SQL); + if ($result === false) { + engelsystem_error("Unable to load needed angeltypes by filter."); + } + if (count($result) == 0) { + return null; + } + return $result[0]; +} + +function ShiftEntries_by_ShiftsFilter(ShiftsFilter $shiftsFilter, $user) { + $SQL = "SELECT `User`.`Nick`, `User`.`email`, `User`.`email_shiftinfo`, `User`.`Sprache`, `User`.`Gekommen`, `ShiftEntry`.`UID`, `ShiftEntry`.`TID`, `ShiftEntry`.`SID`, `ShiftEntry`.`Comment`, `ShiftEntry`.`freeloaded` + FROM `Shifts` + JOIN `ShiftEntry` ON `ShiftEntry`.`SID`=`Shifts`.`SID` + JOIN `User` ON `ShiftEntry`.`UID`=`User`.`UID` + WHERE `Shifts`.`RID` IN (" . implode(',', $shiftsFilter->getRooms()) . ") + AND `start` BETWEEN " . $shiftsFilter->getStartTime() . " AND " . $shiftsFilter->getEndTime() . " + ORDER BY `Shifts`.`start`"; + $result = sql_select($SQL); + if ($result === false) { + engelsystem_error("Unable to load shift entries by filter."); + } + return $result; +} + /** * Check if a shift collides with other shifts (in time). * @@ -88,22 +138,15 @@ function Shift_collides($shift, $shifts) { /** * Returns the number of needed angels/free shift entries for an angeltype. - * - * @param int $shift_id - * ID of the shift to check - * @param int $angeltype_id - * ID of the angeltype that should be checked */ -function Shift_free_entries($shift_id, $angeltype_id) { - $needed_angeltypes = NeededAngelTypes_by_shift($shift_id); - - foreach ($needed_angeltypes as $needed_angeltype) { - if ($needed_angeltype['angel_type_id'] == $angeltype_id) { - return max(0, $needed_angeltype['count'] - $needed_angeltype['taken']); +function Shift_free_entries($needed_angeltype, $shift_entries) { + $taken = 0; + foreach ($shift_entries as $shift_entry) { + if ($shift_entry['freeloaded'] == 0) { + $taken ++; } } - - return 0; + return max(0, $needed_angeltype['count'] - $taken); } /** @@ -118,10 +161,10 @@ function Shift_free_entries($shift_id, $angeltype_id) { * @param boolean $angeltype_supporter * True, if the user has angeltype supporter rights for the angeltype, which enables him to sign somebody up for the shift. */ -function Shift_signup_allowed_angel($user, $shift, $angeltype, $user_angeltype, $user_shifts, $angeltype_supporter = false) { - $free_entries = Shift_free_entries($shift['SID'], $angeltype['id']); +function Shift_signup_allowed_angel($user, $shift, $angeltype, $user_angeltype, $user_shifts, $needed_angeltype, $shift_entries) { + $free_entries = Shift_free_entries($needed_angeltype, $shift_entries); - if($user['Gekommen'] == 0) { + if ($user['Gekommen'] == 0) { return new ShiftSignupState(ShiftSignupState::SHIFT_ENDED, $free_entries); } @@ -155,7 +198,7 @@ function Shift_signup_allowed_angel($user, $shift, $angeltype, $user_angeltype, $user_angeltype = UserAngelType_by_User_and_AngelType($user, $angeltype); } - if ($user_angeltype == null || ($angeltype['no_self_signup'] == 1 && $user_angeltype != null && $angeltype_supporter === false) || ($angeltype['restricted'] == 1 && $user_angeltype != null && ! isset($user_angeltype['confirm_user_id']))) { + if ($user_angeltype == null || ($angeltype['no_self_signup'] == 1 && $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 // you cannot join if angeltype has no self signup @@ -175,8 +218,8 @@ function Shift_signup_allowed_angel($user, $shift, $angeltype, $user_angeltype, /** * Check if an angeltype supporter can sign up a user to a shift. */ -function Shift_signup_allowed_angeltype_supporter($shift, $angeltype) { - $free_entries = Shift_free_entries($shift['SID'], $angeltype['id']); +function Shift_signup_allowed_angeltype_supporter($shift, $angeltype, $needed_angeltype, $shift_entries) { + $free_entries = Shift_free_entries($needed_angeltype, $shift_entries); if ($free_entries == 0) { return new ShiftSignupState(ShiftSignupState::OCCUPIED, $free_entries); } @@ -192,8 +235,8 @@ function Shift_signup_allowed_angeltype_supporter($shift, $angeltype) { * @param AngelType $angeltype * The angeltype to which the user wants to sign up */ -function Shift_signup_allowed_admin($shift, $angeltype) { - $free_entries = Shift_free_entries($shift['SID'], $angeltype['id']); +function Shift_signup_allowed_admin($shift, $angeltype, $needed_angeltype, $shift_entries) { + $free_entries = Shift_free_entries($needed_angeltype, $shift_entries); if ($free_entries == 0) { // User shift admins may join anybody in every shift return new ShiftSignupState(ShiftSignupState::ADMIN, $free_entries); @@ -212,18 +255,18 @@ function Shift_signup_allowed_admin($shift, $angeltype) { * @param array $user_shifts * List of the users shifts */ -function Shift_signup_allowed($signup_user, $shift, $angeltype, $user_angeltype = null, $user_shifts = null) { +function Shift_signup_allowed($signup_user, $shift, $angeltype, $user_angeltype = null, $user_shifts = null, $needed_angeltype, $shift_entries) { global $user, $privileges; if (in_array('user_shifts_admin', $privileges)) { - return Shift_signup_allowed_admin($shift, $angeltype); + return Shift_signup_allowed_admin($shift, $angeltype, $needed_angeltype, $shift_entries); } if (in_array('shiftentry_edit_angeltype_supporter', $privileges) && User_is_AngelType_supporter($user, $angeltype)) { - return Shift_signup_allowed_angeltype_supporter($shift, $angeltype); + return Shift_signup_allowed_angeltype_supporter($shift, $angeltype, $needed_angeltype, $shift_entries); } - return Shift_signup_allowed_angel($signup_user, $shift, $angeltype, $user_angeltype, $user_shifts, false); + return Shift_signup_allowed_angel($signup_user, $shift, $angeltype, $user_angeltype, $user_shifts, $needed_angeltype, $shift_entries); } /** diff --git a/includes/model/UserAngelTypes_model.php b/includes/model/UserAngelTypes_model.php index 92b35321..11366cdf 100644 --- a/includes/model/UserAngelTypes_model.php +++ b/includes/model/UserAngelTypes_model.php @@ -73,14 +73,17 @@ function User_unconfirmed_AngelTypes($user) { * @param User $user * @param AngelType $angeltype */ -function User_is_AngelType_supporter($user, $angeltype) { +function User_is_AngelType_supporter(&$user, $angeltype) { + if(!isset($user['privileges'])) { + $user['privileges'] = privileges_for_user($user['UID']); + } return (sql_num_query(" SELECT `id` FROM `UserAngelTypes` WHERE `user_id`='" . sql_escape($user['UID']) . "' AND `angeltype_id`='" . sql_escape($angeltype['id']) . "' AND `supporter`=TRUE - LIMIT 1") > 0) || in_array('admin_user_angeltypes', privileges_for_user($user['UID'])); + LIMIT 1") > 0) || in_array('admin_user_angeltypes', $user['privileges']); } /** diff --git a/includes/mysqli_provider.php b/includes/mysqli_provider.php index 8c6463f4..b77f6815 100644 --- a/includes/mysqli_provider.php +++ b/includes/mysqli_provider.php @@ -131,6 +131,9 @@ function sql_select_db($db_name) { function sql_select($query) { global $sql_connection, $query_count; +// echo $query . ";\n"; +// echo debug_string_backtrace() . "\n"; + $result = $sql_connection->query($query); if ($result) { $data = []; diff --git a/includes/pages/user_shifts.php b/includes/pages/user_shifts.php index 5703ea8b..6b942804 100644 --- a/includes/pages/user_shifts.php +++ b/includes/pages/user_shifts.php @@ -130,19 +130,8 @@ function view_user_shifts() { $shiftsFilter = $_SESSION['ShiftsFilter']; $shifts = Shifts_by_ShiftsFilter($shiftsFilter, $user); - - $ownshifts_source = sql_select(" - SELECT `ShiftTypes`.`name`, `Shifts`.* - FROM `Shifts` - INNER JOIN `ShiftTypes` ON (`ShiftTypes`.`id` = `Shifts`.`shifttype_id`) - INNER JOIN `ShiftEntry` ON (`Shifts`.`SID` = `ShiftEntry`.`SID` AND `ShiftEntry`.`UID` = '" . sql_escape($user['UID']) . "') - WHERE `Shifts`.`RID` IN (" . implode(',', $shiftsFilter->getRooms()) . ") - AND `start` BETWEEN " . $shiftsFilter->getStartTime() . " AND " . $shiftsFilter->getEndTime()); - $ownshifts = []; - foreach ($ownshifts_source as $ownshift) { - $ownshifts[$ownshift['SID']] = $ownshift; - } - unset($ownshifts_source); + $needed_angeltypes = NeededAngeltypes_by_ShiftsFilter($shiftsFilter, $user); + $shift_entries = ShiftEntries_by_ShiftsFilter($shiftsFilter, $user); if ($user['api_key'] == "") { User_reset_api_key($user, false); @@ -163,7 +152,7 @@ function view_user_shifts() { $end_day = date("Y-m-d", $shiftsFilter->getEndTime()); $end_time = date("H:i", $shiftsFilter->getEndTime()); - $shiftCalendarRenderer = new ShiftCalendarRenderer($shifts, $shiftsFilter); + $shiftCalendarRenderer = new ShiftCalendarRenderer($shifts, $needed_angeltypes, $shift_entries, $shiftsFilter); return page([ div('col-md-12', [ msg(), diff --git a/includes/view/ShiftCalendarRenderer.php b/includes/view/ShiftCalendarRenderer.php index 7f39d64e..d8d31bd0 100644 --- a/includes/view/ShiftCalendarRenderer.php +++ b/includes/view/ShiftCalendarRenderer.php @@ -35,11 +35,17 @@ class ShiftCalendarRenderer { private $blocksPerSlot = null; - public function __construct($shifts, ShiftsFilter $shiftsFilter) { + private $needed_angeltypes = null; + + private $shift_entries = null; + + public function __construct($shifts, $needed_angeltypes, $shift_entries, ShiftsFilter $shiftsFilter) { $this->shiftsFilter = $shiftsFilter; $this->firstBlockStartTime = $this->calcFirstBlockStartTime($shifts); $this->lastBlockEndTime = $this->calcLastBlockEndTime($shifts); $this->lanes = $this->assignShiftsToLanes($shifts); + $this->needed_angeltypes = $needed_angeltypes; + $this->shift_entries = $shift_entries; } /** @@ -127,6 +133,7 @@ class ShiftCalendarRenderer { $html .= $this->renderLane($lane); } } + return $html; } @@ -142,16 +149,31 @@ class ShiftCalendarRenderer { $shift_renderer = new ShiftCalendarShiftRenderer(); $html = ""; $rendered_until = $this->getFirstBlockStartTime(); + + $needed_angeltypes = []; + $shift_entries = []; + foreach ($lane->getShifts() as $shift) { + $needed_angeltypes[$shift['SID']] = []; + $shift_entries[$shift['SID']] = []; + } + foreach ($this->needed_angeltypes as $needed_angeltype) { + $needed_angeltypes[$needed_angeltype['shift_id']][] = $needed_angeltype; + } + foreach ($this->shift_entries as $shift_entry) { + $shift_entries[$shift_entry['SID']][] = $shift_entry; + } + foreach ($lane->getShifts() as $shift) { while ($rendered_until + ShiftCalendarRenderer::SECONDS_PER_ROW <= $shift['start']) { $html .= $this->renderTick($rendered_until); $rendered_until += ShiftCalendarRenderer::SECONDS_PER_ROW; } - list($shift_height, $shift_html) = $shift_renderer->render($shift, $user); + list($shift_height, $shift_html) = $shift_renderer->render($shift, $needed_angeltypes[$shift['SID']], $shift_entries[$shift['SID']], $user); $html .= $shift_html; $rendered_until += $shift_height * ShiftCalendarRenderer::SECONDS_PER_ROW; } + while ($rendered_until < $this->getLastBlockEndTime()) { $html .= $this->renderTick($rendered_until); $rendered_until += ShiftCalendarRenderer::SECONDS_PER_ROW; diff --git a/includes/view/ShiftCalendarShiftRenderer.php b/includes/view/ShiftCalendarShiftRenderer.php index e3ceb47f..2a345692 100644 --- a/includes/view/ShiftCalendarShiftRenderer.php +++ b/includes/view/ShiftCalendarShiftRenderer.php @@ -15,19 +15,19 @@ class ShiftCalendarShiftRenderer { * @param User $user * The user who is viewing the shift calendar */ - public function render($shift, $user) { + public function render($shift, $needed_angeltypes, $shift_entries, $user) { $info_text = ""; if ($shift['title'] != '') { $info_text = glyph('info-sign') . $shift['title'] . '
'; } - list($shift_signup_state, $shifts_row) = $this->renderShiftNeededAngeltypes($shift, $user); + list($shift_signup_state, $shifts_row) = $this->renderShiftNeededAngeltypes($shift, $needed_angeltypes, $shift_entries, $user); $class = $this->classForSignupState($shift_signup_state); $blocks = ceil(($shift["end"] - $shift["start"]) / ShiftCalendarRenderer::SECONDS_PER_ROW); $blocks = max(1, $blocks); return [ $blocks, - '' . div('shift panel panel-' . $class . '" style="height: ' . ($blocks * ShiftCalendarRenderer::BLOCK_HEIGHT - ShiftCalendarRenderer::MARGIN) . 'px"', [ + div('shift panel panel-' . $class . '" style="height: ' . ($blocks * ShiftCalendarRenderer::BLOCK_HEIGHT - ShiftCalendarRenderer::MARGIN) . 'px"', [ $this->renderShiftHead($shift), div('panel-body', [ $info_text, @@ -38,7 +38,7 @@ class ShiftCalendarShiftRenderer { ]), $shifts_row, div('shift-spacer') - ]) . '' + ]) ]; } @@ -63,27 +63,36 @@ class ShiftCalendarShiftRenderer { } } - private function renderShiftNeededAngeltypes($shift, $user) { + private function renderShiftNeededAngeltypes($shift, $needed_angeltypes, $shift_entries, $user) { global $privileges; + $shift_entries_filtered = []; + foreach ($needed_angeltypes as $needed_angeltype) { + $shift_entries_filtered[$needed_angeltype['id']] = []; + } + foreach ($shift_entries as $shift_entry) { + $shift_entries_filtered[$shift_entry['TID']][] = $shift_entry; + } + $html = ""; $shift_signup_state = null; - $angeltypes = NeededAngelTypes_by_shift($shift['SID']); - foreach ($angeltypes as $angeltype) { - list($angeltype_signup_state, $angeltype_html) = $this->renderShiftNeededAngeltype($shift, $angeltype, $user); - if ($shift_signup_state == null) { - $shift_signup_state = $angeltype_signup_state; - } else { - $shift_signup_state->combineWith($angeltype_signup_state); + foreach ($needed_angeltypes as $angeltype) { + if ($angeltype['count'] > 0 || count($shift_entries_filtered[$angeltype['id']]) > 0) { + list($angeltype_signup_state, $angeltype_html) = $this->renderShiftNeededAngeltype($shift, $shift_entries_filtered[$angeltype['id']], $angeltype, $user); + if ($shift_signup_state == null) { + $shift_signup_state = $angeltype_signup_state; + } else { + $shift_signup_state->combineWith($angeltype_signup_state); + } + $html .= $angeltype_html; } - $html .= $angeltype_html; } if ($shift_signup_state == null) { $shift_signup_state = new ShiftSignupState(ShiftSignupState::SHIFT_ENDED, 0); } if (in_array('user_shifts_admin', $privileges)) { - $html .= '
  • ' . button(page_link_to('user_shifts') . '&shift_id=' . $shift['SID'] . '&type_id=' . $angeltype['id'], _("Add more angels"), 'btn-xs') . '
  • '; + $html .= '
  • ' . button(page_link_to('user_shifts') . '&shift_id=' . $shift['SID'], _("Add more angels"), 'btn-xs') . '
  • '; } if ($html != '') { return [ @@ -107,13 +116,13 @@ class ShiftCalendarShiftRenderer { * @param User $user * The user who is viewing the shift calendar */ - private function renderShiftNeededAngeltype($shift, $angeltype, $user) { + private function renderShiftNeededAngeltype($shift, $shift_entries, $angeltype, $user) { $entry_list = []; - foreach ($angeltype['shift_entries'] as $entry) { + foreach ($shift_entries as $entry) { $style = $entry['freeloaded'] ? " text-decoration: line-through;" : ''; $entry_list[] = "" . User_Nick_render($entry) . ""; } - $shift_signup_state = Shift_signup_allowed($user, $shift, $angeltype); + $shift_signup_state = Shift_signup_allowed($user, $shift, $angeltype, null, null, $angeltype, $shift_entries); $inner_text = sprintf(ngettext("%d helper needed", "%d helpers needed", $shift_signup_state->getFreeEntries()), $shift_signup_state->getFreeEntries()); switch ($shift_signup_state->getState()) { case ShiftSignupState::ADMIN: @@ -174,7 +183,7 @@ class ShiftCalendarShiftRenderer { button(page_link_to('user_shifts') . '&delete_shift=' . $shift['SID'], glyph('trash'), 'btn-xs') ]) . ''; } - $shift_heading = date('H:i', $shift['start']) . ' ‐ ' . date('H:i', $shift['end']) . ' — ' . ShiftType($shift['shifttype_id'])['name']; + $shift_heading = date('H:i', $shift['start']) . ' ‐ ' . date('H:i', $shift['end']) . ' — ' . $shift['name']; return div('panel-heading', [ '' . $shift_heading . '', $header_buttons diff --git a/includes/view/Shifts_view.php b/includes/view/Shifts_view.php index bd4f19c3..c2c0912e 100644 --- a/includes/view/Shifts_view.php +++ b/includes/view/Shifts_view.php @@ -14,13 +14,12 @@ function Shift_editor_info_render($shift) { function Shift_signup_button_render($shift, $angeltype, $user_angeltype = null, $user_shifts = null) { global $user; - + if ($user_angeltype == null) { $user_angeltype = UserAngelType_by_User_and_AngelType($user, $angeltype); } - $shift_signup_state = Shift_signup_allowed($user, $shift, $angeltype, $user_angeltype, $user_shifts); - if ($shift_signup_state->isSignupAllowed()) { + if ($angeltype['shift_signup_state']->isSignupAllowed()) { return button(page_link_to('user_shifts') . '&shift_id=' . $shift['SID'] . '&type_id=' . $angeltype['id'], _('Sign up')); } elseif ($user_angeltype == null) { return button(page_link_to('angeltypes') . '&action=view&angeltype_id=' . $angeltype['id'], sprintf(_('Become %s'), $angeltype['name'])); -- cgit v1.2.3-54-g00ecf