Completed
Push — FVSv2 ( e85196...534a54 )
by Patrick
01:34
created

GridSchedule::grayOutUnused()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

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