Completed
Push — FVSv2 ( c17b7d...6cb237 )
by Patrick
01:37
created

GridSchedule::createSpreadSheet()   F

Complexity

Conditions 22
Paths 8568

Size

Total Lines 163

Duplication

Lines 8
Ratio 4.91 %

Importance

Changes 0
Metric Value
cc 22
nc 8568
nop 0
dl 8
loc 163
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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