Completed
Push — master ( 3b3146...8cb790 )
by Patrick
01:37
created

ParticipantAPI   B

Complexity

Total Complexity 49

Size/Duplication

Total Lines 273
Duplicated Lines 15.38 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 0
Metric Value
dl 42
loc 273
rs 8.48
c 0
b 0
f 0
wmc 49
lcom 1
cbo 9

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A setup() 0 8 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() 18 61 13

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
    }
17
18
    protected function canCreate($request)
19
    {
20
        $this->validateLoggedIn($request);
21
        return true;
22
    }
23
24
    protected function canRead($request)
25
    {
26
        if($this->isVolunteerAdmin($request))
27
        {
28
            return true;
29
        }
30
        //TODO give access to department leads
31
        return true;
32
    }
33
34
    protected function canUpdate($request, $entity)
35
    {
36
 	if($this->isVolunteerAdmin($request))
37
        {
38
            return true;
39
        }       
40
        //TODO give access to department lead
41
        return false;
42
    }
43
44
    protected function canDelete($request, $entity)
45
    {
46
        return $this->canUpdate($request, $entity);
47
    }
48
49
    protected function validateCreate(&$obj, $request)
50
    {
51
        if(isset($obj['uid']))
52
        {
53
            return false;
54
        }
55
        $uid = $this->user->uid;
56
        $dataTable = $this->getDataTable();
57
        $filter = $this->getFilterForPrimaryKey($uid);
58
        $users = $dataTable->read($filter);
59
        if(!empty($users))
60
        {
61
            //User is already created...
62
            return false;
63
        }
64
        $obj['uid'] = $uid;
65
        return true;
66
    }
67
68
    protected function getFilterForPrimaryKey($value)
69
    {
70
        if($value === 'me')
71
        {
72
            $value = $this->user->uid;
73
        }
74
        return parent::getFilterForPrimaryKey($value);
75
    }
76
77
    public function readEntry($request, $response, $args)
78
    {
79
        $this->validateLoggedIn($request);
80
        $uid = $args['name'];
81 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...
82
        {
83
            $uid = $this->user->uid;
84
        }
85
        else if($uid !== $this->user->uid && $this->canRead($request) === false)
86
        {
87
            return $response->withStatus(401);
88
        }
89
        $dataTable = $this->getDataTable();
90
        $odata = $request->getAttribute('odata', new \ODataParams(array()));
91
        $filter = $this->getFilterForPrimaryKey($uid);
92
        $areas = $dataTable->read($filter, $odata->select, $odata->top,
93
                                  $odata->skip, $odata->orderby);
94
        if(empty($areas))
95
        {
96
            return $response->withStatus(404);
97
        }
98
        return $response->withJson($areas[0]);
99
    }
100
101
    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...
102
    {
103
        $this->validateLoggedIn($request);
104
        $uid = $this->user->uid;
105
        $dataTable = DataSetFactory::getDataTableByNames('fvs', 'shifts');
106
        $filter = new \Data\Filter("participant eq '$uid'");
107
        $shifts = $dataTable->read($filter);
108
        $format = $request->getAttribute('format', false);
109
        if($format === false || $format === 'text/calendar')
110
        {
111
            $text = "BEGIN:VCALENDAR\r\n";
112
            $text.= "VERSION:2.0\r\n";
113
            $text.= "PRODID:-//hacksw/handcal//NONSGML v1.0//EN\r\n";
114
            $count = count($shifts);
115
            for($i = 0; $i < $count; $i++)
116
            {
117
                $text.= "BEGIN:VEVENT\r\n";
118
                $text.= "UID:".$this->user->mail."\r\n";
119
                $d = new DateTime($shifts[$i]['startTime']);
120
                $d->setTimezone(new \DateTimeZone('UTC'));
121
                $text.= "DTSTAMP:".$d->format('Ymd\THis\Z')."\r\n";
122
                $text.= "DTSTART:".$d->format('Ymd\THis\Z')."\r\n";
123
                $d = new DateTime($shifts[$i]['endTime']);
124
                $d->setTimezone(new \DateTimeZone('UTC'));
125
                $text.= "DTEND:".$d->format('Ymd\THis\Z')."\r\n";
126
                $text.= "SUMMARY:".$shifts[$i]['roleID'].' '.$shifts[$i]['name']."\r\n";
127
                $text.= "END:VEVENT\r\n";
128
            }
129
            $text.= "END:VCALENDAR\r\n";
130
            $response = $response->withHeader('Content-type', 'text/calendar');
131
            $response = $response->withHeader('Content-Disposition', 'attachment; filename="MyShifts.ics"');
132
            $body = $response->getBody();
133
            $body->write($text);
134
        }
135
        else if($format === 'application/pdf')
136
        {
137
            $pdf = new \Schedules\SimplePDF('My', $shifts);
138
            $response = $response->withHeader('Content-Type', 'application/pdf');
139
            $response->getBody()->write($pdf->toPDFBuffer());
140
        }
141
        else
142
        {
143
            throw new \Exception('Unknown format '.$format);
144
        }
145
        return $response;
146
    }
147
148
    public function getCerts($request, $response, $args)
149
    {
150
        $this->validateLoggedIn($request);
151
        $uid = $args['uid'];
152 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...
153
        {
154
            $uid = $this->user->uid;
155
        }
156
        else if($uid !== $this->user->uid && $this->canRead($request) === false)
157
        {
158
            return $response->withStatus(401);
159
        }
160
        $dataTable = $this->getDataTable();
161
        $odata = $request->getAttribute('odata', new \ODataParams(array()));
162
        $filter = $this->getFilterForPrimaryKey($uid);
163
        $areas = $dataTable->read($filter, array('certs'), $odata->top,
164
                                  $odata->skip, $odata->orderby);
165
        if(empty($areas))
166
        {
167
            return $response->withStatus(404);
168
        }
169
        if(!isset($areas[0]['certs']))
170
        {
171
            return $response->withJson(array());
172
        }
173
        return $response->withJson($areas[0]['certs']);
174
    }
175
176
    public function uploadCert($request, $response, $args)
177
    {
178
        $this->validateLoggedIn($request);
179
        $uid = $args['uid'];
180 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...
181
        {
182
            $uid = $this->user->uid;
183
        }
184
        else if($uid !== $this->user->uid && $this->canRead($request) === false)
185
        {
186
            return $response->withStatus(401);
187
        }
188
        $dataTable = $this->getDataTable();
189
        $filter = $this->getFilterForPrimaryKey($uid);
190
        $users = $dataTable->read($filter);
191
        if(empty($users))
192
        {
193
            return $response->withStatus(404);
194
        }
195
        $user = $users[0];
196
        if(!isset($user['certs']))
197
        {
198
             $user['certs'] = array();
199
        }
200
        $files = $request->getUploadedFiles();
201
        $file = $files['file'];
202
        $stream = $file->getStream();
203
        $cert = array('status'=>'pending', 'image'=>base64_encode($stream->getContents()), 'imageType'=>$file->getClientMediaType());
204
        $user['certs'][$args['certId']] = $cert;
205
        $ret = $dataTable->update($filter, $user);
206
        if($ret)
207
        {
208
            return $response->withStatus(200);
209
        }
210
        return $response->withStatus(500);
211
    }
212
213
    public function rejectCert($request, $response, $args)
214
    {
215
        $this->validateLoggedIn($request);
216
        $uid = $args['uid'];
217 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...
218
        {
219
            $uid = $this->user->uid;
220
        }
221
        else if($uid !== $this->user->uid && $this->canRead($request) === false)
222
        {
223
            return $response->withStatus(401);
224
        }
225
        $dataTable = $this->getDataTable();
226
        $filter = $this->getFilterForPrimaryKey($uid);
227
        $users = $dataTable->read($filter);
228
        if(empty($users))
229
        {
230
            return $response->withStatus(404);
231
        }
232
        $user = $users[0];
233
        $certType = $args['certId'];
234
        if(!isset($user['certs']) || !isset($user['certs'][$certType]))
235
        {
236
            return $response->withStatus(404);
237
        }
238
        $obj = $request->getParsedBody();
239 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...
240
        {
241
            $request->getBody()->rewind();
242
            $obj = $request->getBody()->getContents();
243
            $tmp = json_decode($obj, true);
244
            if($tmp !== null)
245
            {
246
                $obj = $tmp;
247
            }
248
        }
249
        $reason = 'Unknown';
250
        switch($obj['reason'])
251
        {
252
            case 'invalid':
253
                $reason = 'the image provided did not seem to show a valid certication of the type selected';
254
                break;
255
            case 'expired':
256
                $reason = 'the image provided was for a certification that had already expired';
257
                break;
258
        }
259
        unset($user['certs'][$certType]);
260
        $ret = $dataTable->update($filter, $user);
261
        if($ret)
262
        {
263
            $profile = new \VolunteerProfile(false, $user);
264
            $email = new \Emails\CertificationEmail($profile, 'certifcationRejected', $certType, array('reason'=>$reason));
265
            $emailProvider = \EmailProvider::getInstance();
266
            if($emailProvider->sendEmail($email) === false)
267
            {
268
                throw new \Exception('Unable to send email!');
269
            }
270
            return $response->withStatus(200);
271
        }
272
        return $response->withStatus(500);
273
    }
274
}
275