Completed
Push — FVSv2 ( 6cb237...94c8ac )
by Patrick
01:20
created

GridSchedule::shiftTimeSort()   B

Complexity

Conditions 7
Paths 4

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
nc 4
nop 2
dl 0
loc 21
rs 8.6506
c 0
b 0
f 0
1
<?php
2
namespace Schedules;
3
4
use PhpOffice\PhpSpreadsheet\Spreadsheet;
5
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
6
use PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf;
7
8
require_once('../../api/v1/class.Processor.php');
9
10
class GridSchedule
11
{
12
    use ShiftSchedule;
13
    use \Processor;
14
15
    protected $department;
16
    protected $shifts;
17
    protected $ssheat;
18
19
    public function __construct($department, $shifts)
20
    {
21
        $this->department = $department;
22
        $this->shifts = $shifts;
23
        $this->ssheat = $this->createSpreadSheet();
24
    }
25
26
    protected function getSimpleHour($hour)
27
    {
28
        if($hour < 12)
29
        {
30
            if($hour === 0)
31
            {
32
                return '12a';
33
            }
34
            return $hour.'a';
35
        }
36
        if($hour === 12)
37
        {
38
            return $hour.'p';
39
        }
40
        return ($hour - 12).'p';
41
    }
42
43
    protected function grayOutUnused($hourCount, $rowCount, $sheat)
44
    {
45
        for($i = 0; $i < $hourCount; $i++)
46
        {
47
            for($j = 0; $j < $rowCount; $j++)
48
            {
49
                 $cell = $sheat->getCellByColumnAndRow($i+2, $j+4);
50
                 if($cell->isInMergeRange())
51
                 {
52
                      continue;
53
                 }
54
                 else
55
                 {
56
                     $style = $cell->getStyle();
57
                     $style->getBorders()->getAllBorders()->setBorderStyle(false);
58
                     $style->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTGRAY);
59
                 }
60
            }
61
        }
62
    }
63
64
    protected function setShiftNameInCell($sheat, $col, $row, $shift)
65
    {
66
        if(isset($shift['participant']))
67
        {
68
            $sheat->setCellValueByColumnAndRow($col, $row, $this->getParticipantDiplayName($shift['participant']));
69
        }
70
    }
71
72
    protected function createSpreadSheet()
73
    {
74
        $shifts = $this->shifts;
75
        $dept = $this->department;
76
        $ssheat = new Spreadsheet();
77
        $sheat = $ssheat->getActiveSheet();
78
        $sheat->setCellValue('A1', $dept['departmentName']);
79
        $count = count($shifts);
80
        $days = array();
81
        $roles = array();
82
        $roles2 = array();
83
        for($i = 0; $i < $count; $i++)
84
        {
85
            $start = new \DateTime($shifts[$i]['startTime']);
86
            $end = new \DateTime($shifts[$i]['endTime']);
87
            $shifts[$i]['startTime'] = $start;
88
            $shifts[$i]['endTime'] = $end;
89
            $startDateStr = $start->format('l (n/j/Y)');
90
            $endDateStr = $end->format('l (n/j/Y)');
91
            $days[$startDateStr] = 1;
92
            $days[$endDateStr] = 1;
93
            $diff = $start->diff($end);
94
            $shifts[$i]['length'] = $diff->h;
95
            if(!isset($roles[$shifts[$i]['roleID']]))
96
            {
97
                 $roles[$shifts[$i]['roleID']] = $shifts[$i]['length'];
98
                 $roles2[$shifts[$i]['roleID']] = array();
99
            }
100
            else
101
            {
102
                 if($roles[$shifts[$i]['roleID']] < $shifts[$i]['length'])
103
                 {
104
                     $roles[$shifts[$i]['roleID']] = $shifts[$i]['length'];
105
                 }
106
            }
107
            array_push($roles2[$shifts[$i]['roleID']], array('start'=>$start, 'end'=>$end));
108
        }
109
        arsort($roles);
110
        usort($shifts, array($this, 'shiftTimeSort'));
111
        $originalStartTime = $shifts[0]['startTime'];
112
        $str = $shifts[0]['startTime']->format('c');
113
        $start = date_parse($str);
114
        $lastShift = $shifts[$count - 1];
115
        $interval = $lastShift['endTime']->diff($shifts[0]['startTime']);
116
        $hourCount = ($interval->d*24) + $interval->h;
117
        $simpleHours = array();
118
        $militaryHours = array();
119
        $hour = $start['hour'];
120
        for($i = 0; $i < $hourCount; $i++)
121
        {
122
            array_push($simpleHours, $this->getSimpleHour($hour));
123
            array_push($militaryHours, $hour.':00');
124
            $hour++;
125
            if($hour === 24)
126
            {
127
                $hour = 0;
128
            }
129
        }
130
        $sheat->fromArray($simpleHours, null, 'B2');
131
        $sheat->fromArray($militaryHours, null, 'B3');
132
        $mergeCount = 24 - $start['hour'];
133
        if($mergeCount > $hourCount)
134
        {
135
            $mergeCount = $hourCount;
136
        }
137
        $days = array_keys($days);
138
        $cellIndex = 2;
139
        while($mergeCount)
140
        {
141
            $sheat->mergeCellsByColumnAndRow($cellIndex, 1, $cellIndex + $mergeCount - 1, 1);
142
            $sheat->setCellValueByColumnAndRow($cellIndex, 1, array_shift($days));
143
            $cell = $sheat->getCellByColumnAndRow($cellIndex, 1);
144
            $cell->getStyle()->getAlignment()->setHorizontal('center');
145
            $cellIndex += $mergeCount;
146
            $hourCount -= $mergeCount;
147
            $mergeCount = $hourCount;
148
            if($mergeCount > 24)
149
            {
150
                $mergeCount = 24;
151
            }
152
        }
153
        $i = 0;
154
        $rows = array();
155
        foreach($roles as $role=>$hour)
156
        {
157
            $sheat->setCellValueByColumnAndRow(1, 4 + $i, $this->getRoleNameFromID($role));
158
            array_push($rows, $role);
159
            $overlaps = array();
160
            for($j = 0; $j < count($roles2[$role]) - 1; $j++)
161
            {
162
                $currRole = $roles2[$role][$j];
163
                $nextRole = $roles2[$role][$j + 1];
164
                if($currRole['end'] > $nextRole['start'])
165
                {
166
                    $str = $currRole['start']->format('c');
167
                    if(!isset($overlaps[$str]))
168
                    {
169
                        $overlaps[$str] = 0;
170
                    }
171
                    $overlaps[$str]++;
172
                }
173
            }
174
            if(!empty($overlaps))
175
            {
176
                $overlapCount = max(array_values($overlaps));
177
                for($j = 0; $j < $overlapCount + 1; $j++)
178
                {
179
                    $i++;
180
                    $sheat->setCellValueByColumnAndRow(1, 4 + $i, $this->getRoleNameFromID($role));
181
                    if($j > 0)
182
                    {
183
                        array_push($rows, $role);
184
                    }
185
                }
186
            }
187
            else
188
            {
189
                $i++;
190
            }
191
        }
192
        $shift = array_shift($shifts);
193
        while($shift)
194
        {
195
            $i = 1;
196
            $timeDiff = $originalStartTime->diff($shift['startTime']);
197
            $hoursFromStart = ($timeDiff->d*24)+$timeDiff->h;
198
            $firstRow = array_search($shift['roleID'], $rows);
199
            $cell = $sheat->getCellByColumnAndRow($hoursFromStart+2, $firstRow+4);
200
            if($cell->isInMergeRange())
201
            {
202
                while($rows[$firstRow+$i] === $shift['roleID'])
203
                {
204
                    $cell = $sheat->getCellByColumnAndRow($hoursFromStart+2, $firstRow+4+$i);
205
                    if(!$cell->isInMergeRange())
206
                    {
207
                        break;
208
                    }
209
                    $i++;
210
                }
211
                $sheat->mergeCellsByColumnAndRow($hoursFromStart+2, $firstRow+4+$i, $hoursFromStart+1+$shift['length'], $firstRow+4+$i);
212
                $this->setShiftNameInCell($sheat, $hoursFromStart+2, $firstRow+4+$i, $shift);
213
            }
214
            else
215
            {
216
                $sheat->mergeCellsByColumnAndRow($hoursFromStart+2, $firstRow+4, $hoursFromStart+1+$shift['length'], $firstRow+4);
217
                $this->setShiftNameInCell($sheat, $hoursFromStart+2, $firstRow+4, $shift);
218
            }
219
            $shift = array_shift($shifts);
220
        }
221
        $rowCount = count($rows);
222
        $style = $sheat->getStyleByColumnAndRow(2, 4, 1+count($simpleHours), 3 + $rowCount);
223
        $style->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
224
        $hourCount = count($simpleHours);
225
        $this->grayOutUnused($hourCount, $rowCount, $sheat);
226
        $sheat->getColumnDimension('A')->setAutoSize(true);
227
        return $ssheat;
228
    }
229
230
    public function getBuffer($type)
231
    {
232
        if($type === 'XLSX')
233
        {
234
            $writer = new Xlsx($this->ssheat);
235
            $content = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
236
            $extension = '.xlsx';
237
        }
238
        else if($type === 'PDF')
239
        {
240
            $this->ssheat->getActiveSheet()->getPageSetup()->setOrientation(\PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::ORIENTATION_LANDSCAPE);
241
            $writer = new mpdf($this->ssheat);
242
            $writer->setOrientation(\PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::ORIENTATION_LANDSCAPE);
243
            $content = 'application/pdf';
244
            $extension = '.pdf';
245
        }
246
        else
247
        {
248
            return array('error'=> true, 'msg'=>'Unknown type specified: '.$type);
249
        }
250
        ob_start();
251
        $writer->save('php://output');
252
        $str = ob_get_clean();
253
        return array('content-type'=>$content, 'extension'=>$extension, 'buffer'=>$str); 
254
    }
255
256
    public function shiftSort($a, $b)
257
    {
258
        return strcmp($this->getRoleNameFromID($a['roleID']), $this->getRoleNameFromID($b['roleID']));
259
    }
260
261
    public function groupSort($a, $b)
262
    {
263
        $aArr = explode(' ', $a);
264
        $bArr = explode(' ', $b);
265
        if($aArr[1] === 'PM' && $bArr[1] === 'AM')
266
        {
267
            return 1;
268
        }
269
        else if($aArr[1] === 'AM' && $bArr[1] === 'PM')
270
        {
271
            return -1;
272
        }
273
        return strcmp($a, $b);
274
    }
275
276
    public function shiftTimeSort($a, $b)
277
    {
278
        $interval = $a['startTime']->diff($b['startTime']);
279
        if($interval->invert === 0)
280
        {
281
            if($interval->h || $interval->i)
282
            {
283
                return -1;
284
            }
285
            else
286
            {
287
                return 0;
288
            }
289
        }
290
        else if($interval->invert === 1 && ($interval->h || $interval->days))
291
        {
292
            return 1;
293
        }
294
        print_r($interval);
295
        die();
296
    }
297
}
298