Completed
Push — master ( df6d12...eab9e2 )
by Patrick
01:41 queued 10s
created

DepartmentAPI   A

Complexity

Total Complexity 42

Size/Duplication

Total Lines 231
Duplicated Lines 12.99 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 0
Metric Value
dl 30
loc 231
rs 9.0399
c 0
b 0
f 0
wmc 42
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
A createEntityForDepartment() 17 17 3
A createRoleForDepartment() 0 4 1
A createShiftForDepartment() 0 4 1
A updateRoleForDepartment() 0 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 View Code Duplication
    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
        $ret = $dataTable->create($obj);
140
        return $response->withJson($ret);
141
    }
142
143
    public function createRoleForDepartment($request, $response, $args)
144
    {
145
        return $this->createEntityForDepartment($request, $response, $args, 'roles');
146
    }
147
148
    public function createShiftForDepartment($request, $response, $args)
149
    {
150
        return $this->createEntityForDepartment($request, $response, $args, 'shifts');
151
    }
152
153
    public function updateRoleForDepartment($request, $response, $args)
154
    {
155
        $deptId = $args['dept'];
156
        $roleId = $args['roleName'];
157
        if($this->canEditDept($request, $deptId) === false)
158
        {
159
            return $response->withStatus(401);
160
        }
161
        $dataTable = DataSetFactory::getDataTableByNames('fvs', 'roles');
162
        $filter = new \Data\Filter("departmentID eq '$deptId' and short_name eq '$roleId'");
163
        $entry = $dataTable->read($filter);
164
        if(empty($entry))
165
        {
166
            return $response->withStatus(404);
167
        }
168
        $obj = $request->getParsedBody();
169
        if($obj === null)
170
        {
171
            $request->getBody()->rewind();
172
            $obj = $request->getBody()->getContents();
173
            $tmp = json_decode($obj, true);
174
            if($tmp !== null)
175
            {
176
                $obj = $tmp;
177
            }
178
        }
179
        $ret = $dataTable->update($filter, $obj);
180
        return $response->withJson($ret);
181
    }
182
183
    public function generateShiftSchedule($request, $response, $args)
184
    {
185
        $deptId = $args['dept'];
186
        if($this->canEditDept($request, $deptId) === false)
187
        {
188
            return $response->withStatus(401);
189
        }
190
        $dataTable = DataSetFactory::getDataTableByNames('fvs', 'departments');
191
        $depts = $dataTable->read(new \Data\Filter('departmentID eq '.$deptId));
192
        if(empty($depts))
193
        {
194
            return $response->withStatus(404);
195
        }
196
        $dataTable = DataSetFactory::getDataTableByNames('fvs', 'shifts');
197
        $eventId = $request->getParam('eventID');
198
        $filter = new \Data\Filter('eventID eq '.$eventId.' and departmentID eq '.$deptId);
199
        $shifts = $dataTable->read($filter);
200
        if(empty($shifts))
201
        {
202
            return $response->withStatus(404);
203
        }
204
        switch($request->getParam('type'))
205
        {
206
            case 'simplePDF':
207
               return $this->generateSimplePDFSchedule($depts[0], $shifts, $response);
208
            case 'gridXLSX':
209
               return $this->generateGridSchedule($depts[0], $shifts, $response, 'XLSX');
210
            case 'gridPDF':
211
               return $this->generateGridSchedule($depts[0], $shifts, $response, 'PDF');
212
        }
213
        return $response->withJson($shifts);
214
    }
215
216
    public function generateSimplePDFSchedule($dept, $shifts, $response)
217
    {
218
        $pdf = new \Schedules\SimplePDF($dept, $shifts);
219
        $response = $response->withHeader('Content-Type', 'application/pdf');
220
        $response->getBody()->write($pdf->toPDFBuffer());
221
        return $response;
222
    }
223
224
    public function generateGridSchedule($dept, $shifts, $response, $type)
225
    {
226
        $ss = new \Schedules\GridSchedule($dept, $shifts);
227
        $data = $ss->getBuffer($type);
228
        $response = $response->withHeader('Content-Type', $data['content-type']);
229
        $response = $response->withHeader('Content-Disposition', 'attachment; filename='.$dept['departmentName'].$data['extension']);
230
        $response->getBody()->write($data['buffer']);
231
        return $response;
232
    }
233
}
234
235