Completed
Push — FVSv2 ( 78f5f9...0e95d7 )
by Patrick
01:35
created

GridSchedule::getBuffer()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

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