diff options
author | msquare <msquare@notrademark.de> | 2017-06-20 16:50:21 +0200 |
---|---|---|
committer | msquare <msquare@notrademark.de> | 2017-06-20 16:50:21 +0200 |
commit | 56814fa2fdf58b4013f4d57c5ea87619c7122957 (patch) | |
tree | 640945769b7e9626cdf43162c786147f5c962029 /includes/view/ShiftCalendarRenderer.php | |
parent | a5fc5bd0979e8de1fce8a8addd351a6e7bd6aeb8 (diff) | |
parent | cd30017b97afc3c7001fbb9eb14b54dbb980b7b6 (diff) |
Merge branch 'pr/316' into feature-igel-rewrite
Diffstat (limited to 'includes/view/ShiftCalendarRenderer.php')
-rw-r--r-- | includes/view/ShiftCalendarRenderer.php | 532 |
1 files changed, 294 insertions, 238 deletions
diff --git a/includes/view/ShiftCalendarRenderer.php b/includes/view/ShiftCalendarRenderer.php index 8c8e72a4..aad0d643 100644 --- a/includes/view/ShiftCalendarRenderer.php +++ b/includes/view/ShiftCalendarRenderer.php @@ -2,256 +2,312 @@ namespace Engelsystem; -class ShiftCalendarRenderer { - - /** - * 15m * 60s/m = 900s - */ - const SECONDS_PER_ROW = 900; - - /** - * Height of a block in pixel. - * Do not change - corresponds with theme/css - */ - const BLOCK_HEIGHT = 30; - - /** - * Distance between two shifts in pixels - */ - const MARGIN = 5; - - /** - * Seconds added to the start and end time - */ - const TIME_MARGIN = 1800; - - private $lanes; - - private $shiftsFilter; - - private $firstBlockStartTime = null; - - private $lastBlockEndTime = null; - - private $blocksPerSlot = null; - - 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; - } - - /** - * Assigns the shifts to different lanes per room if they collide - * - * @param Shift[] $shifts - * The shifts to assign - * - * @return Returns an array that assigns a room_id to an array of ShiftCalendarLane containing the shifts - */ - private function assignShiftsToLanes($shifts) { - // array that assigns a room id to a list of lanes (per room) - $lanes = []; - - foreach ($shifts as $shift) { - $room_id = $shift['RID']; - $header = Room_name_render([ - 'RID' => $room_id, - 'Name' => $shift['room_name'] - ]); - if (! isset($lanes[$room_id])) { - // initialize room with one lane - $lanes[$room_id] = [ - new ShiftCalendarLane($header, $this->getFirstBlockStartTime(), $this->getBlocksPerSlot()) - ]; - } - // Try to add the shift to the existing lanes for this room - $shift_added = false; - foreach ($lanes[$room_id] as $lane) { - $shift_added = $lane->addShift($shift); - if ($shift_added == true) { - break; - } - } - // If all lanes for this room are busy, create a new lane and add shift to it - if ($shift_added == false) { - $newLane = new ShiftCalendarLane($header, $this->getFirstBlockStartTime(), $this->getBlocksPerSlot()); - if (! $newLane->addShift($shift)) { - engelsystem_error("Unable to add shift to new lane."); +class ShiftCalendarRenderer +{ + /** + * 15m * 60s/m = 900s + */ + const SECONDS_PER_ROW = 900; + + /** + * Height of a block in pixel. + * Do not change - corresponds with theme/css + */ + const BLOCK_HEIGHT = 30; + + /** + * Distance between two shifts in pixels + */ + const MARGIN = 5; + + /** + * Seconds added to the start and end time + */ + const TIME_MARGIN = 1800; + + /** @var array */ + private $lanes; + + /** @var ShiftsFilter */ + private $shiftsFilter; + + /** @var int */ + private $firstBlockStartTime = 0; + + /** @var int */ + private $lastBlockEndTime = 0; + + /** @var int */ + private $blocksPerSlot = null; + + /** @var array[] */ + private $needed_angeltypes = []; + + /** @var array[] */ + private $shift_entries = []; + + /** + * ShiftCalendarRenderer constructor. + * + * @param array[] $shifts + * @param array[] $needed_angeltypes + * @param array[] $shift_entries + * @param ShiftsFilter $shiftsFilter + */ + 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; + } + + /** + * Assigns the shifts to different lanes per room if they collide + * + * @param array[] $shifts The shifts to assign + * + * @return array Returns an array that assigns a room_id to an array of ShiftCalendarLane containing the shifts + */ + private function assignShiftsToLanes($shifts) + { + // array that assigns a room id to a list of lanes (per room) + $lanes = []; + + foreach ($shifts as $shift) { + $room_id = $shift['RID']; + $header = Room_name_render([ + 'RID' => $room_id, + 'Name' => $shift['room_name'] + ]); + if (!isset($lanes[$room_id])) { + // initialize room with one lane + $lanes[$room_id] = [ + new ShiftCalendarLane($header, $this->getFirstBlockStartTime(), $this->getBlocksPerSlot()) + ]; + } + // Try to add the shift to the existing lanes for this room + $shift_added = false; + foreach ($lanes[$room_id] as $lane) { + /** @var ShiftCalendarLane $lane */ + $shift_added = $lane->addShift($shift); + if ($shift_added == true) { + break; + } + } + // If all lanes for this room are busy, create a new lane and add shift to it + if ($shift_added == false) { + $newLane = new ShiftCalendarLane($header, $this->getFirstBlockStartTime(), $this->getBlocksPerSlot()); + if (!$newLane->addShift($shift)) { + engelsystem_error('Unable to add shift to new lane.'); + } + $lanes[$room_id][] = $newLane; + } } - $lanes[$room_id][] = $newLane; - } + + return $lanes; } - - return $lanes; - } - public function getFirstBlockStartTime() { - return $this->firstBlockStartTime; - } + /** + * @return int + */ + public function getFirstBlockStartTime() + { + return $this->firstBlockStartTime; + } - public function getLastBlockEndTime() { - return $this->lastBlockEndTime; - } + /** + * @return int + */ + public function getLastBlockEndTime() + { + return $this->lastBlockEndTime; + } - public function getBlocksPerSlot() { - if ($this->blocksPerSlot == null) { - $this->blocksPerSlot = $this->calcBlocksPerSlot(); + /** + * @return float + */ + public function getBlocksPerSlot() + { + if ($this->blocksPerSlot == null) { + $this->blocksPerSlot = $this->calcBlocksPerSlot(); + } + return $this->blocksPerSlot; + } + + /** + * Renders the whole calendar + * + * @return string the generated html + */ + public function render() + { + if (count($this->lanes) == 0) { + return ''; + } + return div('shift-calendar', [ + $this->renderTimeLane(), + $this->renderShiftLanes() + ]) . $this->renderLegend(); } - return $this->blocksPerSlot; - } - - /** - * Renders the whole calendar - * - * @return the generated html - */ - public function render() { - if (count($this->lanes) == 0) { - return ''; + + /** + * Renders the lanes containing the shifts + * + * @return string + */ + private function renderShiftLanes() + { + $html = ''; + foreach ($this->lanes as $room_lanes) { + foreach ($room_lanes as $lane) { + $html .= $this->renderLane($lane); + } + } + + return $html; } - return div('shift-calendar', [ - $this->renderTimeLane(), - $this->renderShiftLanes() - ]) . $this->renderLegend(); - } - - /** - * Renders the lanes containing the shifts - */ - private function renderShiftLanes() { - $html = ""; - foreach ($this->lanes as $room_lanes) { - foreach ($room_lanes as $lane) { - $html .= $this->renderLane($lane); - } + + /** + * Renders a single lane + * + * @param ShiftCalendarLane $lane The lane to render + * @return string + */ + private function renderLane(ShiftCalendarLane $lane) + { + global $user; + + $shift_renderer = new ShiftCalendarShiftRenderer(); + $html = ''; + $rendered_until = $this->getFirstBlockStartTime(); + + 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, + $this->needed_angeltypes[$shift['SID']], + $this->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; + } + + return div('lane', [ + div('header', $lane->getHeader()), + $html + ]); } - - return $html; - } - - /** - * Renders a single lane - * - * @param ShiftCalendarLane $lane - * The lane to render - */ - private function renderLane(ShiftCalendarLane $lane) { - global $user; - - $shift_renderer = new ShiftCalendarShiftRenderer(); - $html = ""; - $rendered_until = $this->getFirstBlockStartTime(); - - 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, $this->needed_angeltypes[$shift['SID']], $this->shift_entries[$shift['SID']], $user); - $html .= $shift_html; - $rendered_until += $shift_height * ShiftCalendarRenderer::SECONDS_PER_ROW; + + /** + * Renders a tick/block for given time + * + * @param int $time unix timestamp + * @param boolean $label Should time labels be generated? + * @return string rendered tick html + */ + private function renderTick($time, $label = false) + { + if ($time % (24 * 60 * 60) == 23 * 60 * 60) { + if (!$label) { + return div('tick day'); + } + return div('tick day', [ + date('m-d<b\r />H:i', $time) + ]); + } elseif ($time % (60 * 60) == 0) { + if (!$label) { + return div('tick hour'); + } + return div('tick hour', [ + date('m-d<b\r />H:i', $time) + ]); + } + return div('tick'); } - - while ($rendered_until < $this->getLastBlockEndTime()) { - $html .= $this->renderTick($rendered_until); - $rendered_until += ShiftCalendarRenderer::SECONDS_PER_ROW; + + /** + * Renders the left time lane including hour/day ticks + * + * @return string + */ + private function renderTimeLane() + { + $time_slot = [ + div('header', [ + _('Time') + ]) + ]; + for ($block = 0; $block < $this->getBlocksPerSlot(); $block++) { + $thistime = $this->getFirstBlockStartTime() + ($block * ShiftCalendarRenderer::SECONDS_PER_ROW); + $time_slot[] = $this->renderTick($thistime, true); + } + return div('lane time', $time_slot); } - - return div('lane', [ - div('header', $lane->getHeader()), - $html - ]); - } - - /** - * Renders a tick/block for given time - * - * @param int $time - * unix timestamp - * @param boolean $label - * Should time labels be generated? - * @return rendered tick html - */ - private function renderTick($time, $label = false) { - if ($time % (24 * 60 * 60) == 23 * 60 * 60) { - if (! $label) { - return div('tick day'); - } - return div('tick day', [ - date('m-d<b\r />H:i', $time) - ]); - } elseif ($time % (60 * 60) == 0) { - if (! $label) { - return div('tick hour'); - } - return div('tick hour', [ - date('m-d<b\r />H:i', $time) - ]); + + /** + * @param array[] $shifts + * @return int + */ + private function calcFirstBlockStartTime($shifts) + { + $start_time = $this->shiftsFilter->getEndTime(); + foreach ($shifts as $shift) { + if ($shift['start'] < $start_time) { + $start_time = $shift['start']; + } + } + return ShiftCalendarRenderer::SECONDS_PER_ROW * floor(($start_time - ShiftCalendarRenderer::TIME_MARGIN) / ShiftCalendarRenderer::SECONDS_PER_ROW); } - return div('tick'); - } - - /** - * Renders the left time lane including hour/day ticks - */ - private function renderTimeLane() { - $time_slot = [ - div('header', [ - _("Time") - ]) - ]; - for ($block = 0; $block < $this->getBlocksPerSlot(); $block ++) { - $thistime = $this->getFirstBlockStartTime() + ($block * ShiftCalendarRenderer::SECONDS_PER_ROW); - $time_slot[] = $this->renderTick($thistime, true); + + /** + * @param array[] $shifts + * @return int + */ + private function calcLastBlockEndTime($shifts) + { + $end_time = $this->shiftsFilter->getStartTime(); + foreach ($shifts as $shift) { + if ($shift['end'] > $end_time) { + $end_time = $shift['end']; + } + } + return ShiftCalendarRenderer::SECONDS_PER_ROW * ceil(($end_time + ShiftCalendarRenderer::TIME_MARGIN) / ShiftCalendarRenderer::SECONDS_PER_ROW); } - return div('lane time', $time_slot); - } - - private function calcFirstBlockStartTime($shifts) { - $start_time = $this->shiftsFilter->getEndTime(); - foreach ($shifts as $shift) { - if ($shift['start'] < $start_time) { - $start_time = $shift['start']; - } + + /** + * @return int + */ + private function calcBlocksPerSlot() + { + return ceil(($this->getLastBlockEndTime() - $this->getFirstBlockStartTime()) / ShiftCalendarRenderer::SECONDS_PER_ROW); } - return ShiftCalendarRenderer::SECONDS_PER_ROW * floor(($start_time - ShiftCalendarRenderer::TIME_MARGIN) / ShiftCalendarRenderer::SECONDS_PER_ROW); - } - - private function calcLastBlockEndTime($shifts) { - $end_time = $this->shiftsFilter->getStartTime(); - foreach ($shifts as $shift) { - if ($shift['end'] > $end_time) { - $end_time = $shift['end']; - } + + /** + * Renders a legend explaining the shift coloring + * + * @return string + */ + private function renderLegend() + { + return div('legend', [ + label(_('Your shift'), 'primary'), + label(_('Help needed'), 'danger'), + label(_('Other angeltype needed / collides with my shifts'), 'warning'), + label(_('Shift is full'), 'success'), + label(_('Shift running/ended'), 'default') + ]); } - return ShiftCalendarRenderer::SECONDS_PER_ROW * ceil(($end_time + ShiftCalendarRenderer::TIME_MARGIN) / ShiftCalendarRenderer::SECONDS_PER_ROW); - } - - private function calcBlocksPerSlot() { - return ceil(($this->getLastBlockEndTime() - $this->getFirstBlockStartTime()) / ShiftCalendarRenderer::SECONDS_PER_ROW); - } - - /** - * Renders a legend explaining the shift coloring - */ - private function renderLegend() { - return div('legend', [ - label(_('Your shift'), 'primary'), - label(_('Help needed'), 'danger'), - label(_('Other angeltype needed / collides with my shifts'), 'warning'), - label(_('Shift is full'), 'success'), - label(_('Shift running/ended'), 'default') - ]); - } } - -?>
\ No newline at end of file |