Completed
Push — master ( 8cb790...efb981 )
by Patrick
01:54
created

ParticipantAPI   D

Complexity

Total Complexity 58

Size/Duplication

Total Lines 316
Duplicated Lines 25.32 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 0
Metric Value
dl 80
loc 316
rs 4.5599
c 0
b 0
f 0
wmc 58
lcom 1
cbo 9

14 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A setup() 0 9 1
A canCreate() 0 5 1
A canRead() 0 9 2
A canUpdate() 0 9 2
A canDelete() 0 4 1
A validateCreate() 0 18 3
A getFilterForPrimaryKey() 0 8 2
A readEntry() 8 23 5
B getMyShifts() 0 46 5
B getCerts() 8 27 6
B uploadCert() 8 36 7
C rejectCert() 33 61 13
B acceptCert() 23 41 9

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

1
<?php
2
class ParticipantAPI extends VolunteerAPI
3
{
4
    public function __construct()
5
    {
6
        parent::__construct('participants', 'uid');
7
    }
8
9
    public function setup($app)
10
    {
11
        parent::setup($app);
12
        $app->get('/me/shifts[/]', array($this, 'getMyShifts'));
13
        $app->get('/{uid}/certs[/]', array($this, 'getCerts'));
14
        $app->post('/{uid}/certs/{certId}[/]', array($this, 'uploadCert'));
15
        $app->post('/{uid}/certs/{certId}/Actions/RejectCert', array($this, 'rejectCert'));
16
        $app->post('/{uid}/certs/{certId}/Actions/AcceptCert', array($this, 'acceptCert'));
17
    }
18
19
    protected function canCreate($request)
20
    {
21
        $this->validateLoggedIn($request);
22
        return true;
23
    }
24
25
    protected function canRead($request)
26
    {
27
        if($this->isVolunteerAdmin($request))
28
        {
29
            return true;
30
        }
31
        //TODO give access to department leads
32
        return true;
33
    }
34
35
    protected function canUpdate($request, $entity)
36
    {
37
 	if($this->isVolunteerAdmin($request))
38
        {
39
            return true;
40
        }       
41
        //TODO give access to department lead
42
        return false;
43
    }
44
45
    protected function canDelete($request, $entity)
46
    {
47
        return $this->canUpdate($request, $entity);
48
    }
49
50
    protected function validateCreate(&$obj, $request)
51
    {
52
        if(isset($obj['uid']))
53
        {
54
            return false;
55
        }
56
        $uid = $this->user->uid;
57
        $dataTable = $this->getDataTable();
58
        $filter = $this->getFilterForPrimaryKey($uid);
59
        $users = $dataTable->read($filter);
60
        if(!empty($users))
61
        {
62
            //User is already created...
63
            return false;
64
        }
65
        $obj['uid'] = $uid;
66
        return true;
67
    }
68
69
    protected function getFilterForPrimaryKey($value)
70
    {
71
        if($value === 'me')
72
        {
73
            $value = $this->user->uid;
74
        }
75
        return parent::getFilterForPrimaryKey($value);
76
    }
77
78
    public function readEntry($request, $response, $args)
79
    {
80
        $this->validateLoggedIn($request);
81
        $uid = $args['name'];
82 View Code Duplication
        if($uid === 'me')
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...
83
        {
84
            $uid = $this->user->uid;
85
        }
86
        else if($uid !== $this->user->uid && $this->canRead($request) === false)
87
        {
88
            return $response->withStatus(401);
89
        }
90
        $dataTable = $this->getDataTable();
91
        $odata = $request->getAttribute('odata', new \ODataParams(array()));
92
        $filter = $this->getFilterForPrimaryKey($uid);
93
        $areas = $dataTable->read($filter, $odata->select, $odata->top,
94
                                  $odata->skip, $odata->orderby);
95
        if(empty($areas))
96
        {
97
            return $response->withStatus(404);
98
        }
99
        return $response->withJson($areas[0]);
100
    }
101
102
    public function getMyShifts($request, $response, $args)
0 ignored issues
show
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
103
    {
104
        $this->validateLoggedIn($request);
105
        $uid = $this->user->uid;
106
        $dataTable = DataSetFactory::getDataTableByNames('fvs', 'shifts');
107
        $filter = new \Data\Filter("participant eq '$uid'");
108
        $shifts = $dataTable->read($filter);
109
        $format = $request->getAttribute('format', false);
110
        if($format === false || $format === 'text/calendar')
111
        {
112
            $text = "BEGIN:VCALENDAR\r\n";
113
            $text.= "VERSION:2.0\r\n";
114
            $text.= "PRODID:-//hacksw/handcal//NONSGML v1.0//EN\r\n";
115
            $count = count($shifts);
116
            for($i = 0; $i < $count; $i++)
117
            {
118
                $text.= "BEGIN:VEVENT\r\n";
119
                $text.= "UID:".$this->user->mail."\r\n";
120
                $d = new DateTime($shifts[$i]['startTime']);
121
                $d->setTimezone(new \DateTimeZone('UTC'));
122
                $text.= "DTSTAMP:".$d->format('Ymd\THis\Z')."\r\n";
123
                $text.= "DTSTART:".$d->format('Ymd\THis\Z')."\r\n";
124
                $d = new DateTime($shifts[$i]['endTime']);
125
                $d->setTimezone(new \DateTimeZone('UTC'));
126
                $text.= "DTEND:".$d->format('Ymd\THis\Z')."\r\n";
127
                $text.= "SUMMARY:".$shifts[$i]['roleID'].' '.$shifts[$i]['name']."\r\n";
128
                $text.= "END:VEVENT\r\n";
129
            }
130
            $text.= "END:VCALENDAR\r\n";
131
            $response = $response->withHeader('Content-type', 'text/calendar');
132
            $response = $response->withHeader('Content-Disposition', 'attachment; filename="MyShifts.ics"');
133
            $body = $response->getBody();
134
            $body->write($text);
135
        }
136
        else if($format === 'application/pdf')
137
        {
138
            $pdf = new \Schedules\SimplePDF('My', $shifts);
139
            $response = $response->withHeader('Content-Type', 'application/pdf');
140
            $response->getBody()->write($pdf->toPDFBuffer());
141
        }
142
        else
143
        {
144
            throw new \Exception('Unknown format '.$format);
145
        }
146
        return $response;
147
    }
148
149
    public function getCerts($request, $response, $args)
150
    {
151
        $this->validateLoggedIn($request);
152
        $uid = $args['uid'];
153 View Code Duplication
        if($uid === 'me')
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...
154
        {
155
            $uid = $this->user->uid;
156
        }
157
        else if($uid !== $this->user->uid && $this->canRead($request) === false)
158
        {
159
            return $response->withStatus(401);
160
        }
161
        $dataTable = $this->getDataTable();
162
        $odata = $request->getAttribute('odata', new \ODataParams(array()));
163
        $filter = $this->getFilterForPrimaryKey($uid);
164
        $areas = $dataTable->read($filter, array('certs'), $odata->top,
165
                                  $odata->skip, $odata->orderby);
166
        if(empty($areas))
167
        {
168
            return $response->withStatus(404);
169
        }
170
        if(!isset($areas[0]['certs']))
171
        {
172
            return $response->withJson(array());
173
        }
174
        return $response->withJson($areas[0]['certs']);
175
    }
176
177
    public function uploadCert($request, $response, $args)
178
    {
179
        $this->validateLoggedIn($request);
180
        $uid = $args['uid'];
181 View Code Duplication
        if($uid === 'me')
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...
182
        {
183
            $uid = $this->user->uid;
184
        }
185
        else if($uid !== $this->user->uid && $this->canRead($request) === false)
186
        {
187
            return $response->withStatus(401);
188
        }
189
        $dataTable = $this->getDataTable();
190
        $filter = $this->getFilterForPrimaryKey($uid);
191
        $users = $dataTable->read($filter);
192
        if(empty($users))
193
        {
194
            return $response->withStatus(404);
195
        }
196
        $user = $users[0];
197
        if(!isset($user['certs']))
198
        {
199
             $user['certs'] = array();
200
        }
201
        $files = $request->getUploadedFiles();
202
        $file = $files['file'];
203
        $stream = $file->getStream();
204
        $cert = array('status'=>'pending', 'image'=>base64_encode($stream->getContents()), 'imageType'=>$file->getClientMediaType());
205
        $user['certs'][$args['certId']] = $cert;
206
        $ret = $dataTable->update($filter, $user);
207
        if($ret)
208
        {
209
            return $response->withStatus(200);
210
        }
211
        return $response->withStatus(500);
212
    }
213
214
    public function rejectCert($request, $response, $args)
215
    {
216
        $this->validateLoggedIn($request);
217
        $uid = $args['uid'];
218 View Code Duplication
        if($uid === 'me')
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...
219
        {
220
            $uid = $this->user->uid;
221
        }
222
        else if($uid !== $this->user->uid && $this->canRead($request) === false)
223
        {
224
            return $response->withStatus(401);
225
        }
226
        $dataTable = $this->getDataTable();
227
        $filter = $this->getFilterForPrimaryKey($uid);
228
        $users = $dataTable->read($filter);
229
        if(empty($users))
230
        {
231
            return $response->withStatus(404);
232
        }
233
        $user = $users[0];
234
        $certType = $args['certId'];
235 View Code Duplication
        if(!isset($user['certs']) || !isset($user['certs'][$certType]))
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...
236
        {
237
            return $response->withStatus(404);
238
        }
239
        $obj = $request->getParsedBody();
240 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...
241
        {
242
            $request->getBody()->rewind();
243
            $obj = $request->getBody()->getContents();
244
            $tmp = json_decode($obj, true);
245
            if($tmp !== null)
246
            {
247
                $obj = $tmp;
248
            }
249
        }
250
        $reason = 'Unknown';
251
        switch($obj['reason'])
252
        {
253
            case 'invalid':
254
                $reason = 'the image provided did not seem to show a valid certication of the type selected';
255
                break;
256
            case 'expired':
257
                $reason = 'the image provided was for a certification that had already expired';
258
                break;
259
        }
260
        unset($user['certs'][$certType]);
261
        $ret = $dataTable->update($filter, $user);
262 View Code Duplication
        if($ret)
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...
263
        {
264
            $profile = new \VolunteerProfile(false, $user);
265
            $email = new \Emails\CertificationEmail($profile, 'certifcationRejected', $certType, array('reason'=>$reason));
266
            $emailProvider = \EmailProvider::getInstance();
267
            if($emailProvider->sendEmail($email) === false)
268
            {
269
                throw new \Exception('Unable to send email!');
270
            }
271
            return $response->withStatus(200);
272
        }
273
        return $response->withStatus(500);
274
    }
275
276
    public function acceptCert($request, $response, $args)
277
    {
278
        $this->validateLoggedIn($request);
279
        $uid = $args['uid'];
280 View Code Duplication
        if($uid === 'me')
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...
281
        {
282
            $uid = $this->user->uid;
283
        }
284
        else if($uid !== $this->user->uid && $this->canRead($request) === false)
285
        {
286
            return $response->withStatus(401);
287
        }
288
        $dataTable = $this->getDataTable();
289
        $filter = $this->getFilterForPrimaryKey($uid);
290
        $users = $dataTable->read($filter);
291
        if(empty($users))
292
        {
293
            return $response->withStatus(404);
294
        }
295
        $user = $users[0];
296
        $certType = $args['certId'];
0 ignored issues
show
Unused Code introduced by
$certType is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
297
        $certType = $args['certId'];
298 View Code Duplication
        if(!isset($user['certs']) || !isset($user['certs'][$certType]))
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...
299
        {
300
            return $response->withStatus(404);
301
        }
302
        $user['certs'][$certType]['status'] = 'current';
303
        $ret = $dataTable->update($filter, $user);
304 View Code Duplication
        if($ret)
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...
305
        {
306
            $profile = new \VolunteerProfile(false, $user);
307
            $email = new \Emails\CertificationEmail($profile, 'certifcationAccepted', $certType);
308
            $emailProvider = \EmailProvider::getInstance();
309
            if($emailProvider->sendEmail($email) === false)
310
            {
311
                throw new \Exception('Unable to send email!');
312
            }
313
            return $response->withStatus(200);
314
        }
315
        return $response->withStatus(500);
316
    }
317
}
318