Completed
Push — master ( 63632c...9f438b )
by Patrick
01:51
created

DepartmentAPI   B

Complexity

Total Complexity 48

Size/Duplication

Total Lines 241
Duplicated Lines 13.69 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 0
Metric Value
dl 33
loc 241
rs 8.5599
c 0
b 0
f 0
wmc 48
lcom 1
cbo 8

15 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A setup() 0 10 1
A canEditDept() 0 12 3
A canUpdate() 0 4 1
A canDelete() 0 8 2
A processEntry() 0 18 6
A getRolesForDepartment() 0 23 4
A getShiftsForDepartment() 13 31 5
B createEntityForDepartment() 10 27 9
A createRoleForDepartment() 0 4 1
A createShiftForDepartment() 0 4 1
A updateRoleForDepartment() 10 29 5
B generateShiftSchedule() 0 32 7
A generateSimplePDFSchedule() 0 7 1
A generateGridSchedule() 0 9 1

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 DepartmentAPI 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 DepartmentAPI, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
class DepartmentAPI extends VolunteerAPI
4
{
5
    use Processor;
6
7
    public function __construct()
8
    {
9
        parent::__construct('departments', 'departmentID');
10
    }
11
12
    public function setup($app)
13
    {
14
        parent::setup($app);
15
        $app->get('/{dept}/roles[/]', array($this, 'getRolesForDepartment'));
16
        $app->post('/{dept}/roles[/]', array($this, 'createRoleForDepartment'));
17
        $app->patch('/{dept}/roles/{roleName}[/]', array($this, 'updateRoleForDepartment'));
18
        $app->get('/{dept}/shifts[/]', array($this, 'getShiftsForDepartment'));
19
        $app->post('/{dept}/shifts[/]', array($this, 'createShiftForDepartment'));
20
        $app->get('/{dept}/shifts/Actions/GenerateShiftSchedule', array($this, 'generateShiftSchedule'));
21
    }
22
23
    protected function canEditDept($request, $deptId, $dept = null)
24
    {
25
        if($this->isVolunteerAdmin($request))
26
        {
27
            return true;
28
        }
29
        if($dept !== null)
30
        {
31
            return $this->isUserDepartmentLead2($dept, $this->user);
32
        }
33
        return $this->isUserDepartmentLead($deptId, $this->user);
34
    }
35
36
    protected function canUpdate($request, $entity)
37
    {
38
        return $this->canEditDept($request, false);
39
    }
40
41
    protected function canDelete($request, $entity)
42
    {
43
        if($this->isVolunteerAdmin($request))
44
        {
45
            return true;
46
        }
47
        return false;
48
    }
49
50
    protected function processEntry($entry, $request)
51
    {
52
        $entry['available'] = true;
53
        $entry['isAdmin'] = $this->canEditDept($request, null, $entry);
54
        if(isset($entry['public']) && $entry['public'] === false)
55
        {
56
            if(!$this->isUserDepartmentLead2($entry, $this->user))
57
            {
58
                $entry['available'] = false;
59
                $entry['why'] = 'Not lead of department';
60
            }
61
            if(!$entry['available'] && !$entry['isAdmin'])
62
            {
63
                return null;
64
            }
65
        }
66
        return $entry;
67
    }
68
69
    public function getRolesForDepartment($request, $response, $args)
70
    {
71
        $deptId = $args['dept'];
72
        if($this->canEditDept($request, $deptId) === false)
73
        {
74
            return $response->withStatus(401);
75
        }
76
        $dataTable = DataSetFactory::getDataTableByNames('fvs', 'roles');
77
        $filter = new \Data\Filter("departmentID eq '$deptId'");
78
        $odata = $request->getAttribute('odata', new \ODataParams(array()));
79
        $roles = $dataTable->read($filter, $odata->select, $odata->top,
80
                                  $odata->skip, $odata->orderby);
81
        if($roles === false)
82
        {
83
            $roles = array();
84
        }
85
        $count = count($roles);
86
        for($i = 0; $i < $count; $i++)
87
        {
88
            $roles[$i] = $this->processRole($roles[$i], $request);
89
        }
90
        return $response->withJson($roles);
91
    }
92
93
    public function getShiftsForDepartment($request, $response, $args)
94
    {
95
        $deptId = $args['dept'];
96
        if($this->canEditDept($request, $deptId) === false)
97
        {
98
            return $response->withStatus(401);
99
        }
100
        $dataTable = DataSetFactory::getDataTableByNames('fvs', 'shifts');
101
        $filter = new \Data\Filter("departmentID eq '$deptId'");
102
        $odata = $request->getAttribute('odata', new \ODataParams(array()));
103 View Code Duplication
        if($odata->filter !== false)
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...
104
        {
105
            $clause = $odata->filter->getClause('departmentID');
106
            if($clause !== null)
107
            {
108
                return $response->withStatus(409);
109
            }
110
            else
111
            {
112
                $filter->appendChild('and');
113
                $filter->appendChild($odata->filter);
114
            }
115
        }
116
        $shifts = $dataTable->read($filter, $odata->select, $odata->top,
117
                                  $odata->skip, $odata->orderby);
118
        if($shifts === false)
119
        {
120
            $shifts = array();
121
        }
122
        return $response->withJson($shifts);
123
    }
124
125
    protected function createEntityForDepartment($request, $response, $args, $table)
126
    {
127
        $deptId = $args['dept'];
128
        if($this->canEditDept($request, $deptId) === false)
129
        {
130
            return $response->withStatus(401);
131
        }
132
        $dataTable = DataSetFactory::getDataTableByNames('fvs', $table);
133
        $obj = $request->getParsedBody();
134
        if($obj === null)
135
        {
136
            $obj = json_decode($request->getBody()->getContents(), true);
137
        }
138
        $obj['departmentID'] = $deptId;
139 View Code Duplication
        if($table === 'shifts')
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...
140
        {
141
            if(isset($obj['unbounded']) && $obj['unbounded'])
142
            {
143
                if(!isset($obj['minShifts']) || $obj['minShifts'] === 0 || $obj['minShifts'] === '')
144
                {
145
                    $obj['minShifts'] = '1';
146
                }
147
            }
148
        }
149
        $ret = $dataTable->create($obj);
150
        return $response->withJson($ret);
151
    }
152
153
    public function createRoleForDepartment($request, $response, $args)
154
    {
155
        return $this->createEntityForDepartment($request, $response, $args, 'roles');
156
    }
157
158
    public function createShiftForDepartment($request, $response, $args)
159
    {
160
        return $this->createEntityForDepartment($request, $response, $args, 'shifts');
161
    }
162
163
    public function updateRoleForDepartment($request, $response, $args)
164
    {
165
        $deptId = $args['dept'];
166
        $roleId = $args['roleName'];
167
        if($this->canEditDept($request, $deptId) === false)
168
        {
169
            return $response->withStatus(401);
170
        }
171
        $dataTable = DataSetFactory::getDataTableByNames('fvs', 'roles');
172
        $filter = new \Data\Filter("departmentID eq '$deptId' and short_name eq '$roleId'");
173
        $entry = $dataTable->read($filter);
174
        if(empty($entry))
175
        {
176
            return $response->withStatus(404);
177
        }
178
        $obj = $request->getParsedBody();
179 View Code Duplication
        if($obj === null)
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...
180
        {
181
            $request->getBody()->rewind();
182
            $obj = $request->getBody()->getContents();
183
            $tmp = json_decode($obj, true);
184
            if($tmp !== null)
185
            {
186
                $obj = $tmp;
187
            }
188
        }
189
        $ret = $dataTable->update($filter, $obj);
190
        return $response->withJson($ret);
191
    }
192
193
    public function generateShiftSchedule($request, $response, $args)
194
    {
195
        $deptId = $args['dept'];
196
        if($this->canEditDept($request, $deptId) === false)
197
        {
198
            return $response->withStatus(401);
199
        }
200
        $dataTable = DataSetFactory::getDataTableByNames('fvs', 'departments');
201
        $depts = $dataTable->read(new \Data\Filter('departmentID eq '.$deptId));
202
        if(empty($depts))
203
        {
204
            return $response->withStatus(404);
205
        }
206
        $dataTable = DataSetFactory::getDataTableByNames('fvs', 'shifts');
207
        $eventId = $request->getParam('eventID');
208
        $filter = new \Data\Filter('eventID eq '.$eventId.' and departmentID eq '.$deptId);
209
        $shifts = $dataTable->read($filter);
210
        if(empty($shifts))
211
        {
212
            return $response->withStatus(404);
213
        }
214
        switch($request->getParam('type'))
215
        {
216
            case 'simplePDF':
217
               return $this->generateSimplePDFSchedule($depts[0], $shifts, $response);
218
            case 'gridXLSX':
219
               return $this->generateGridSchedule($depts[0], $shifts, $response, 'XLSX');
220
            case 'gridPDF':
221
               return $this->generateGridSchedule($depts[0], $shifts, $response, 'PDF');
222
        }
223
        return $response->withJson($shifts);
224
    }
225
226
    public function generateSimplePDFSchedule($dept, $shifts, $response)
227
    {
228
        $pdf = new \Schedules\SimplePDF($dept, $shifts);
229
        $response = $response->withHeader('Content-Type', 'application/pdf');
230
        $response->getBody()->write($pdf->toPDFBuffer());
231
        return $response;
232
    }
233
234
    public function generateGridSchedule($dept, $shifts, $response, $type)
235
    {
236
        $ss = new \Schedules\GridSchedule($dept, $shifts);
237
        $data = $ss->getBuffer($type);
238
        $response = $response->withHeader('Content-Type', $data['content-type']);
239
        $response = $response->withHeader('Content-Disposition', 'attachment; filename='.$dept['departmentName'].$data['extension']);
240
        $response->getBody()->write($data['buffer']);
241
        return $response;
242
    }
243
}
244
245