Completed
Push — FVSv2 ( e6ffd8...1cdbcb )
by Patrick
01:32
created

GridSchedule::createShiftCell()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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