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

GridSchedule   B

Complexity

Total Complexity 46

Size/Duplication

Total Lines 281
Duplicated Lines 2.85 %

Coupling/Cohesion

Components 2
Dependencies 9

Importance

Changes 0
Metric Value
dl 8
loc 281
rs 8.72
c 0
b 0
f 0
wmc 46
lcom 2
cbo 9

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A getSimpleHour() 0 16 4
F createSpreadSheet() 8 179 25
A getBuffer() 0 25 3
A shiftSort() 0 4 1
A groupSort() 0 14 5
B shiftTimeSort() 0 21 7

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like GridSchedule often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use GridSchedule, and based on these observations, apply Extract Interface, too.

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