Completed
Push — FVSv2 ( ab906d...c17b7d )
by Patrick
01:58
created

GridSchedule::getSimpleHour()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 4
nop 1
dl 0
loc 16
rs 9.7333
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 createSpreadSheet()
44
    {
45
        $shifts = $this->shifts;
46
        $dept = $this->department;
47
        $ssheat = new Spreadsheet();
48
        $sheat = $ssheat->getActiveSheet();
49
        $sheat->setCellValue('A1', $dept['departmentName']);
50
        $count = count($shifts);
51
        $days = array();
52
        $roles = array();
53
        $roles2 = array();
54
        for($i = 0; $i < $count; $i++)
55
        {
56
            $start = new \DateTime($shifts[$i]['startTime']);
57
            $end = new \DateTime($shifts[$i]['endTime']);
58
            $shifts[$i]['startTime'] = $start;
59
            $shifts[$i]['endTime'] = $end;
60
            $startDateStr = $start->format('l (n/j/Y)');
61
            $endDateStr = $end->format('l (n/j/Y)');
62
            $days[$startDateStr] = 1;
63
            $days[$endDateStr] = 1;
64
            $diff = $start->diff($end);
65
            $shifts[$i]['length'] = $diff->h;
66
            if(!isset($roles[$shifts[$i]['roleID']]))
67
            {
68
                 $roles[$shifts[$i]['roleID']] = $shifts[$i]['length'];
69
                 $roles2[$shifts[$i]['roleID']] = array();
70
            }
71
            else
72
            {
73
                 if($roles[$shifts[$i]['roleID']] < $shifts[$i]['length'])
74
                 {
75
                     $roles[$shifts[$i]['roleID']] = $shifts[$i]['length'];
76
                 }
77
            }
78
            array_push($roles2[$shifts[$i]['roleID']], array('start'=>$start, 'end'=>$end));
79
        }
80
        arsort($roles);
81
        usort($shifts, array($this, 'shiftTimeSort'));
82
        $originalStartTime = $shifts[0]['startTime'];
83
        $str = $shifts[0]['startTime']->format('c');
84
        $start = date_parse($str);
85
        $lastShift = $shifts[$count - 1];
86
        $interval = $lastShift['endTime']->diff($shifts[0]['startTime']);
87
        $hourCount = ($interval->d*24) + $interval->h;
88
        $simpleHours = array();
89
        $militaryHours = array();
90
        $hour = $start['hour'];
91
        for($i = 0; $i < $hourCount; $i++)
92
        {
93
            array_push($simpleHours, $this->getSimpleHour($hour));
94
            array_push($militaryHours, $hour.':00');
95
            $hour++;
96
            if($hour === 24)
97
            {
98
                $hour = 0;
99
            }
100
        }
101
        $sheat->fromArray($simpleHours, null, 'B2');
102
        $sheat->fromArray($militaryHours, null, 'B3');
103
        $mergeCount = 24 - $start['hour'];
104
        if($mergeCount > $hourCount)
105
        {
106
            $mergeCount = $hourCount;
107
        }
108
        $days = array_keys($days);
109
        $cellIndex = 2;
110
        while($mergeCount)
111
        {
112
            $sheat->mergeCellsByColumnAndRow($cellIndex, 1, $cellIndex + $mergeCount - 1, 1);
113
            $sheat->setCellValueByColumnAndRow($cellIndex, 1, array_shift($days));
114
            $cell = $sheat->getCellByColumnAndRow($cellIndex, 1);
115
            $cell->getStyle()->getAlignment()->setHorizontal('center');
116
            $cellIndex += $mergeCount;
117
            $hourCount -= $mergeCount;
118
            $mergeCount = $hourCount;
119
            if($mergeCount > 24)
120
            {
121
                $mergeCount = 24;
122
            }
123
        }
124
        $i = 0;
125
        $rows = array();
126
        foreach($roles as $role=>$hour)
127
        {
128
            $sheat->setCellValueByColumnAndRow(1, 4 + $i, $this->getRoleNameFromID($role));
129
            array_push($rows, $role);
130
            $overlaps = array();
131
            for($j = 0; $j < count($roles2[$role]) - 1; $j++)
132
            {
133
                $currRole = $roles2[$role][$j];
134
                $nextRole = $roles2[$role][$j + 1];
135
                if($currRole['end'] > $nextRole['start'])
136
                {
137
                    $str = $currRole['start']->format('c');
138
                    if(!isset($overlaps[$str]))
139
                    {
140
                        $overlaps[$str] = 0;
141
                    }
142
                    $overlaps[$str]++;
143
                }
144
            }
145
            if(!empty($overlaps))
146
            {
147
                $overlapCount = max(array_values($overlaps));
148
                for($j = 0; $j < $overlapCount + 1; $j++)
149
                {
150
                    $i++;
151
                    $sheat->setCellValueByColumnAndRow(1, 4 + $i, $this->getRoleNameFromID($role));
152
                    if($j > 0)
153
                    {
154
                        array_push($rows, $role);
155
                    }
156
                }
157
            }
158
            else
159
            {
160
                $i++;
161
            }
162
        }
163
        $shift = array_shift($shifts);
164
        while($shift)
165
        {
166
            $i = 1;
167
            $timeDiff = $originalStartTime->diff($shift['startTime']);
168
            $hoursFromStart = ($timeDiff->d*24)+$timeDiff->h;
169
            $firstRow = array_search($shift['roleID'], $rows);
170
            $cell = $sheat->getCellByColumnAndRow($hoursFromStart+2, $firstRow+4);
171
            if($cell->isInMergeRange())
172
            {
173
                while($rows[$firstRow+$i] === $shift['roleID'])
174
                {
175
                    $cell = $sheat->getCellByColumnAndRow($hoursFromStart+2, $firstRow+4+$i);
176
                    if(!$cell->isInMergeRange())
177
                    {
178
                        break;
179
                    }
180
                    $i++;
181
                }
182
                $sheat->mergeCellsByColumnAndRow($hoursFromStart+2, $firstRow+4+$i, $hoursFromStart+1+$shift['length'], $firstRow+4+$i);
183 View Code Duplication
                if(isset($shift['participant']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
184
                {
185
                    $sheat->setCellValueByColumnAndRow($hoursFromStart+2, $firstRow+4+$i, $this->getParticipantDiplayName($shift['participant']));
186
                }
187
            }
188
            else
189
            {
190
                $sheat->mergeCellsByColumnAndRow($hoursFromStart+2, $firstRow+4, $hoursFromStart+1+$shift['length'], $firstRow+4);
191 View Code Duplication
                if(isset($shift['participant']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
192
                {
193
                    $sheat->setCellValueByColumnAndRow($hoursFromStart+2, $firstRow+4, $this->getParticipantDiplayName($shift['participant']));
194
                }
195
            }
196
            $shift = array_shift($shifts);
197
        }
198
        $rowCount = count($rows);
199
        $style = $sheat->getStyleByColumnAndRow(2, 4, 1+count($simpleHours), 3 + $rowCount);
200
        $style->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
201
        $hourCount = count($simpleHours);
202
        for($i = 0; $i < $hourCount; $i++)
203
        {
204
            for($j = 0; $j < $rowCount; $j++)
205
            {
206
                 $cell = $sheat->getCellByColumnAndRow($i+2, $j+4);
207
                 if($cell->isInMergeRange())
208
                 {
209
                      continue;
210
                 }
211
                 else
212
                 {
213
                     $style = $cell->getStyle();
214
                     $style->getBorders()->getAllBorders()->setBorderStyle(false);
215
                     $style->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTGRAY);
216
                 }
217
            }
218
        }
219
        $sheat->getColumnDimension('A')->setAutoSize(true);
220
        return $ssheat;
221
    }
222
223
    public function getBuffer($type)
224
    {
225
        if($type === 'XLSX')
226
        {
227
            $writer = new Xlsx($this->ssheat);
228
            $content = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
229
            $extension = '.xlsx';
230
        }
231
        else if($type === 'PDF')
232
        {
233
            $this->ssheat->getActiveSheet()->getPageSetup()->setOrientation(\PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::ORIENTATION_LANDSCAPE);
234
            $writer = new mpdf($this->ssheat);
235
            $writer->setOrientation(\PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::ORIENTATION_LANDSCAPE);
236
            $content = 'application/pdf';
237
            $extension = '.pdf';
238
        }
239
        else
240
        {
241
            return array('error'=> true, 'msg'=>'Unknown type specified: '.$type);
242
        }
243
        ob_start();
244
        $writer->save('php://output');
245
        $str = ob_get_clean();
246
        return array('content-type'=>$content, 'extension'=>$extension, 'buffer'=>$str); 
247
    }
248
249
    public function shiftSort($a, $b)
250
    {
251
        return strcmp($this->getRoleNameFromID($a['roleID']), $this->getRoleNameFromID($b['roleID']));
252
    }
253
254
    public function groupSort($a, $b)
255
    {
256
        $aArr = explode(' ', $a);
257
        $bArr = explode(' ', $b);
258
        if($aArr[1] === 'PM' && $bArr[1] === 'AM')
259
        {
260
            return 1;
261
        }
262
        else if($aArr[1] === 'AM' && $bArr[1] === 'PM')
263
        {
264
            return -1;
265
        }
266
        return strcmp($a, $b);
267
    }
268
269
    public function shiftTimeSort($a, $b)
270
    {
271
        $interval = $a['startTime']->diff($b['startTime']);
272
        if($interval->invert === 0)
273
        {
274
            if($interval->h || $interval->i)
275
            {
276
                return -1;
277
            }
278
            else
279
            {
280
                return 0;
281
            }
282
        }
283
        else if($interval->invert === 1 && ($interval->h || $interval->days))
284
        {
285
            return 1;
286
        }
287
        print_r($interval);
288
        die();
289
    }
290
}
291