Issues (42)

app/Schedules/class.GridSchedule.php (1 issue)

Severity
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 getRowForShift($roleID, $rows, $col, $sheat)
101
    {
102
        $i = 1;
103
        $firstRow = array_search($roleID, $rows);
104
        $cell = $sheat->getCellByColumnAndRow($col, $firstRow + 4);
105
        if($cell->isInMergeRange())
106
        {
107
            while($rows[$firstRow + $i] === $roleID)
108
            {
109
                $cell = $sheat->getCellByColumnAndRow($col, $firstRow + 4 + $i);
110
                if(!$cell->isInMergeRange())
111
                {
112
                    break;
113
                }
114
                $i++;
115
            }
116
            return $firstRow + 4 + $i;
117
        }
118
        return $firstRow + 4;
119
    }
120
121
    protected function createSpreadSheet()
122
    {
123
        $shifts = $this->shifts;
124
        $dept = $this->department;
125
        $ssheat = new Spreadsheet();
126
        $sheat = $ssheat->getActiveSheet();
127
        $sheat->setCellValue('A1', $dept['departmentName']);
128
        $count = count($shifts);
129
        $days = array();
130
        $roles = array();
131
        $roles2 = array();
132
        for($i = 0; $i < $count; $i++)
133
        {
134
            $start = new \DateTime($shifts[$i]['startTime']);
135
            $end = new \DateTime($shifts[$i]['endTime']);
136
            $shifts[$i]['startTime'] = $start;
137
            $shifts[$i]['endTime'] = $end;
138
            $startDateStr = $start->format('l (n/j/Y)');
139
            $endDateStr = $end->format('l (n/j/Y)');
140
            $days[$startDateStr] = 1;
141
            $days[$endDateStr] = 1;
142
            $diff = $start->diff($end);
143
            $shifts[$i]['length'] = $diff->h;
144
            if(!isset($roles[$shifts[$i]['roleID']]))
145
            {
146
                $roles[$shifts[$i]['roleID']] = $shifts[$i]['length'];
147
                $roles2[$shifts[$i]['roleID']] = array();
148
            }
149
            else
150
            {
151
                if($roles[$shifts[$i]['roleID']] < $shifts[$i]['length'])
152
                {
153
                    $roles[$shifts[$i]['roleID']] = $shifts[$i]['length'];
154
                }
155
            }
156
            array_push($roles2[$shifts[$i]['roleID']], array('start'=>$start, 'end'=>$end));
157
        }
158
        arsort($roles);
159
        usort($shifts, array($this, 'shiftTimeSort'));
160
        $originalStartTime = $shifts[0]['startTime'];
161
        $str = $shifts[0]['startTime']->format('c');
162
        $start = date_parse($str);
163
        $lastShift = $shifts[$count - 1];
164
        $interval = $lastShift['endTime']->diff($shifts[0]['startTime']);
165
        $hourCount = ($interval->d * 24) + $interval->h;
166
        $tmp = $this->getHoursArrays($start['hour'], $hourCount);
167
        $simpleHours = $tmp[0];
168
        $militaryHours = $tmp[1];
169
        $sheat->fromArray($simpleHours, null, 'B2');
170
        $sheat->fromArray($militaryHours, null, 'B3');
171
        $mergeCount = 24 - $start['hour'];
172
        if($mergeCount > $hourCount)
173
        {
174
            $mergeCount = $hourCount;
175
        }
176
        $days = array_keys($days);
177
        $cellIndex = 2;
178
        while($mergeCount)
179
        {
180
            $sheat->mergeCellsByColumnAndRow($cellIndex, 1, $cellIndex + $mergeCount - 1, 1);
181
            $sheat->setCellValueByColumnAndRow($cellIndex, 1, array_shift($days));
182
            $cell = $sheat->getCellByColumnAndRow($cellIndex, 1);
183
            $cell->getStyle()->getAlignment()->setHorizontal('center');
184
            $cellIndex += $mergeCount;
185
            $hourCount -= $mergeCount;
186
            $mergeCount = $hourCount;
187
            if($mergeCount > 24)
188
            {
189
                $mergeCount = 24;
190
            }
191
        }
192
        $i = 0;
193
        $rows = array();
194
        foreach($roles as $role=>$hour)
195
        {
196
            $sheat->setCellValueByColumnAndRow(1, 4 + $i, $this->getRoleNameFromID($role));
197
            array_push($rows, $role);
198
            $overlaps = array();
199
            for($j = 0; $j < count($roles2[$role]) - 1; $j++)
200
            {
201
                $currRole = $roles2[$role][$j];
202
                $nextRole = $roles2[$role][$j + 1];
203
                if($currRole['end'] > $nextRole['start'])
204
                {
205
                    $str = $currRole['start']->format('c');
206
                    if(!isset($overlaps[$str]))
207
                    {
208
                        $overlaps[$str] = 0;
209
                    }
210
                    $overlaps[$str]++;
211
                }
212
            }
213
            if(!empty($overlaps))
214
            {
215
                $overlapCount = max(array_values($overlaps));
216
                for($j = 0; $j < $overlapCount + 1; $j++)
217
                {
218
                    $i++;
219
                    $sheat->setCellValueByColumnAndRow(1, 4 + $i, $this->getRoleNameFromID($role));
220
                    if($j > 0)
221
                    {
222
                        array_push($rows, $role);
223
                    }
224
                }
225
            }
226
            else
227
            {
228
                $i++;
229
            }
230
        }
231
        $shift = array_shift($shifts);
232
        while($shift)
233
        {
234
            $timeDiff = $originalStartTime->diff($shift['startTime']);
235
            $hoursFromStart = ($timeDiff->d * 24)+$timeDiff->h;
236
            $rowForShift = $this->getRowForShift($shift['roleID'], $rows, $hoursFromStart + 2, $sheat);
237
            $this->createShiftCell($sheat, $hoursFromStart + 2, $rowForShift, $shift);
238
            $shift = array_shift($shifts);
239
        }
240
        $rowCount = count($rows);
241
        $style = $sheat->getStyleByColumnAndRow(2, 4, 1 + count($simpleHours), 3 + $rowCount);
242
        $style->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
243
        $hourCount = count($simpleHours);
244
        $this->grayOutUnused($hourCount, $rowCount, $sheat);
245
        $sheat->getColumnDimension('A')->setAutoSize(true);
246
        return $ssheat;
247
    }
248
249
    public function getBuffer($type)
250
    {
251
        if($type === 'XLSX')
252
        {
253
            $writer = new Xlsx($this->ssheat);
254
            $content = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
255
            $extension = '.xlsx';
256
        }
257
        else if($type === 'PDF')
258
        {
259
            $this->ssheat->getActiveSheet()->getPageSetup()->setOrientation(\PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::ORIENTATION_LANDSCAPE);
260
            $writer = new mpdf($this->ssheat);
261
            $writer->setOrientation(\PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::ORIENTATION_LANDSCAPE);
262
            $content = 'application/pdf';
263
            $extension = '.pdf';
264
        }
265
        else
266
        {
267
            return array('error'=> true, 'msg'=>'Unknown type specified: '.$type);
268
        }
269
        ob_start();
270
        $writer->save('php://output');
271
        $str = ob_get_clean();
272
        return array('content-type'=>$content, 'extension'=>$extension, 'buffer'=>$str); 
273
    }
274
275
    public function shiftSort($a, $b)
276
    {
277
        return strcmp($this->getRoleNameFromID($a['roleID']), $this->getRoleNameFromID($b['roleID']));
278
    }
279
280
    public function groupSort($a, $b)
281
    {
282
        $aArr = explode(' ', $a);
283
        $bArr = explode(' ', $b);
284
        if($aArr[1] === 'PM' && $bArr[1] === 'AM')
285
        {
286
            return 1;
287
        }
288
        else if($aArr[1] === 'AM' && $bArr[1] === 'PM')
289
        {
290
            return -1;
291
        }
292
        return strcmp($a, $b);
293
    }
294
295
    public function shiftTimeSort($a, $b)
296
    {
297
        $interval = $a['startTime']->diff($b['startTime']);
298
        if($interval->invert === 0)
299
        {
300
            if($interval->h || $interval->i)
301
            {
302
                return -1;
303
            }
304
            else
305
            {
306
                return 0;
307
            }
308
        }
309
        else if($interval->invert === 1 && ($interval->h || $interval->days))
310
        {
311
            return 1;
312
        }
313
        print_r($interval);
314
        die();
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
315
    }
316
}
317
/* vim: set tabstop=4 shiftwidth=4 expandtab: */
318