Completed
Push — FVSv2 ( 2b5aa4...5bc7db )
by Patrick
01:39
created

ShiftAPI::disapprovePending()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 4
nop 3
dl 0
loc 26
rs 9.504
c 0
b 0
f 0
1
<?php
2
class ShiftAPI extends VolunteerAPI
3
{
4
    use Processor;
5
6
    public function __construct()
7
    {
8
        parent::__construct('shifts');
9
    }
10
11
    public function setup($app)
12
    {
13
        parent::setup($app);
14
        $app->post('/Actions/CreateGroup', array($this, 'createGroup'));
15
        $app->post('/Actions/NewGroup', array($this, 'newGroup'));
16
        $app->post('/{shift}/Actions/Signup[/]', array($this, 'signup'));
17
        $app->post('/{shift}/Actions/Abandon[/]', array($this, 'abandon'));
18
        $app->post('/{shift}/Actions/Approve[/]', array($this, 'approvePending'));
19
        $app->post('/{shift}/Actions/Disapprove[/]', array($this, 'disapprovePending')); 
20
        $app->post('/{shift}/Actions/StartGroupSignup', array($this, 'startGroupSignup'));
21
        $app->post('/{shift}/Actions/GenerateGroupLink', array($this, 'generateGroupLink'));
22
    }
23
24
    protected function canCreate($request)
25
    {
26
        if($this->isVolunteerAdmin($request))
27
        {
28
            return true;
29
        }
30
        //TODO give access to department lead
31
        return false;
32
    }
33
34
    protected function canUpdate($request, $entity)
35
    {
36
 	if($this->isVolunteerAdmin($request))
37
        {
38
            return true;
39
        }
40
        return $this->isUserDepartmentLead($entity['departmentID'], $this->user);
41
    }
42
43
    protected function canDelete($request, $entity)
44
    {
45
        return $this->canUpdate($request, $entity);
46
    }
47
48
    protected function processEntry($entry, $request)
49
    {
50
        return $this->processShift($entry, $request);
51
    }
52
53
    protected function genUUID()
54
    {
55
        return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
56
            // 32 bits for "time_low"
57
            mt_rand(0, 0xffff), mt_rand(0, 0xffff),
58
59
            // 16 bits for "time_mid"
60
            mt_rand(0, 0xffff),
61
62
            // 16 bits for "time_hi_and_version",
63
            // four most significant bits holds version number 4
64
            mt_rand(0, 0x0fff) | 0x4000,
65
66
            // 16 bits, 8 bits for "clk_seq_hi_res",
67
            // 8 bits for "clk_seq_low",
68
            // two most significant bits holds zero and one for variant DCE1.1
69
            mt_rand(0, 0x3fff) | 0x8000,
70
71
            // 48 bits for "node"
72
            mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
73
        );
74
    }
75
76
    public function createGroup($request, $response)
77
    {
78
        $array = $request->getParsedBody();
79
        $count = count($array);
80
        $entArray = array();
81
        $uuid = $this->genUUID();
82
        $dataTable = $this->getDataTable();
83
        //User must be able to edit all shifts
84
        for($i = 0; $i < $count; $i++)
85
        {
86
            $filter = $this->getFilterForPrimaryKey($array[$i]);
87
            $entity = $dataTable->read($filter);
88
            if($entity === false || !isset($entity[0]))
89
            {
90
                return $response->withStatus(404);
91
            }
92
            $entity = $entity[0];
93
            if(!$this->canUpdate($request, $entity))
94
            {
95
                return $response->withStatus(401);
96
            }
97
            $entity['groupID'] = $uuid;
98
            array_push($entArray, $entity);
99
        }
100
        //If we got here we can update them all
101
        $myRet = true;
102
        $errors = array();
103
        for($i = 0; $i < $count; $i++)
104
        {
105
            $filter = $this->getFilterForPrimaryKey($array[$i]);
106
            $ret = $dataTable->update($filter, $entArray[$i]);
107
            if($ret === false)
108
            {
109
               $myRet = false;
110
               array_push($errors, $array[$i]);
111
            }
112
        }
113
        if($myRet)
114
        {
115
            return $response->withJson($myRet);
116
        }
117
        else
118
        {
119
            return $response->withJson(array('res'=>$myRet, 'errors'=>$errors));
120
        }
121
    }
122
123
    public function newGroup($request, $response)
124
    {
125
        if(!$this->canCreate($request))
126
        {
127
            return $response->withStatus(401);
128
        }
129
        $data = $request->getParsedBody();
130
        $shift = array();
131
        $shift['groupID'] = $this->genUUID();
132
        $shift['departmentID'] = $data['groupDepartmentID'];
133
        $shift['earlyLate'] = $data['groupEarlyLate'];
134
        $shift['enabled'] = $data['groupEnabled'];
135
        $shift['endTime'] = $data['groupEndTime'];
136
        $shift['eventID'] = $data['groupEvent'];
137
        $shift['name'] = $data['groupName'];
138
        $shift['startTime'] = $data['groupStartTime'];
139
        $dataTable = $this->getDataTable();
140
        $ret = true;
141
        foreach($data['roles'] as $role=>$count)
142
        {
143
            $count = intval($count);
144
            for($i = 0; $i < $count; $i++)
145
            {
146
                $shift['roleID'] = $role;
147
                if($dataTable->create($shift) === false)
148
                {
149
                    $ret = false;
150
                }
151
            }
152
        }
153
        return $response->withJSON($ret);
154
    }
155
156
    public function signup($request, $response, $args)
157
    {
158
        $this->validateLoggedIn($request);
159
        $shiftId = $args['shift'];
160
        $dataTable = $this->getDataTable();
161
        $filter = $this->getFilterForPrimaryKey($shiftId);
162
        $entity = $dataTable->read($filter);
163
        if(empty($entity))
164
        {
165
            return $response->withStatus(404);
166
        }
167
        $entity = $entity[0];
168 View Code Duplication
        if(isset($entity['participant']) && strlen($entity['participant']) > 0)
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...
169
        {
170
            return $response->withStatus(401);
171
        }
172
        $shift = new \VolunteerShift($shiftId, $entity);
173
        $entity = $this->processShift($entity, $request);
174
        if(isset($entity['overlap']) && $entity['overlap'])
175
        {
176
            $overlaps = $shift->findOverlaps($this->user->uid);
177
            $count = count($overlaps);
178
            $leads = array();
179
            for($i = 0; $i < $count; $i++)
180
            {
181
                $dept = new \VolunteerDepartment($overlaps[$i]->departmentID);
182
                $leads = array_merge($leads, $dept->getLeadEmails());
183
                $overlaps[$i]->status = 'pending';
184
                $tmp = new \Data\Filter('_id eq '.$overlaps[$i]->{'_id'});
185
                $res = $dataTable->update($tmp, $overlaps[$i]);
186
                if($res === false)
187
                {
188
                    return $response->withJSON(array('err'=>'Unable to update overlap with id '.$overlaps[$i]->{'_id'}));
189
                }
190
            }
191
            $dept = new \VolunteerDepartment($entity['departmentID']);
192
            $leads = array_merge($leads, $dept->getLeadEmails());
193
            $leads = array_unique($leads);
194
            $entity['participant'] = $this->user->uid;
195
            $entity['status'] = 'pending';
196
            $profile = new \VolunteerProfile($this->user->uid);
197
            $email = new \Emails\TwoShiftsAtOnceEmail($profile);
198
            $email->addLeads($leads);
199
            $emailProvider = \EmailProvider::getInstance();
200
            if($emailProvider->sendEmail($email) === false)
201
            {
202
                throw new \Exception('Unable to send duplicate email!');
203
            }
204
            return $response->withJSON($dataTable->update($filter, $entity));
205
        }
206 View Code Duplication
        if(isset($entity['available']) && $entity['available'])
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...
207
        {
208
            $entity['participant'] = $this->user->uid;
209
            $entity['status'] = 'filled';
210
            return $response->withJSON($dataTable->update($filter, $entity));
211
        }
212 View Code Duplication
        if(isset($entity['status']) && $entity['status'] === 'groupPending')
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...
213
        {
214
            $entity['participant'] = $this->user->uid;
215
            $entity['status'] = 'filled';
216
            return $response->withJSON($dataTable->update($filter, $entity));
217
        }
218
        print_r($entity); die();
219
    }
220
221
    public function abandon($request, $response, $args)
222
    {
223
        $this->validateLoggedIn($request);
224
        $shiftId = $args['shift'];
225
        $dataTable = $this->getDataTable();
226
        $filter = $this->getFilterForPrimaryKey($shiftId);
227
        $entity = $dataTable->read($filter);
228
        if(empty($entity))
229
        {
230
            return $response->withStatus(404);
231
        }
232
        $entity = $entity[0];
233
        if(!isset($entity['participant']) || $entity['participant'] !== $this->user->uid)
234
        {
235
            return $response->withStatus(401);
236
        }
237
        $entity['participant'] = '';
238
        $entity['status'] = 'unfilled';
239
        return $response->withJSON($dataTable->update($filter, $entity));
240
    }
241
242
    public function approvePending($request, $response, $args)
243
    {
244
        if(!$this->canCreate($request))
245
        {
246
            return $response->withStatus(401);
247
        }
248
        $shiftId = $args['shift'];
249
        $dataTable = $this->getDataTable();
250
        $filter = $this->getFilterForPrimaryKey($shiftId);
251
        $entity = $dataTable->read($filter);
252
        if(empty($entity))
253
        {
254
            return $response->withStatus(404);
255
        }
256
        $entity = $entity[0];
257
        $entity['status'] = 'filled';
258
        return $response->withJSON($dataTable->update($filter, $entity));
259
    }
260
261
    public function disapprovePending($request, $response, $args)
262
    {
263
        if(!$this->canCreate($request))
264
        {
265
            return $response->withStatus(401);
266
        }
267
        $shiftId = $args['shift'];
268
        $dataTable = $this->getDataTable();
269
        $filter = $this->getFilterForPrimaryKey($shiftId);
270
        $entity = $dataTable->read($filter);
271
        if(empty($entity))
272
        {
273
            return $response->withStatus(404);
274
        }
275
        $entity['participant'] = '';
276
        $entity['status'] = 'unfilled';
277
        $profile = new \VolunteerProfile($this->user->uid);
278
        $email = new \Emails\PendingRejectedEmail($profile);
279
        $email->setShift($entity);
280
        $emailProvider = \EmailProvider::getInstance();
281
        if($emailProvider->sendEmail($email) === false)
282
        {
283
            throw new \Exception('Unable to send duplicate email!');
284
        }
285
        return $response->withJSON($dataTable->update($filter, $entity));
286
    }
287
288
    public function startGroupSignup($request, $response, $args)
289
    {
290
        $this->validateLoggedIn($request);
291
        $shiftId = $args['shift'];
292
        $dataTable = $this->getDataTable();
293
        $filter = $this->getFilterForPrimaryKey($shiftId);
294
        $entity = $dataTable->read($filter);
295
        if(empty($entity))
296
        {
297
            return $response->withStatus(404);
298
        }
299
        $entity = $entity[0];
300 View Code Duplication
        if(isset($entity['participant']) && strlen($entity['participant']) > 0)
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...
301
        {
302
            return $response->withStatus(401);
303
        }
304
        $filter = new \Data\Filter('groupID eq '.$entity['groupID'].' and enabled eq true');
305
        $entities = $dataTable->read($filter);
306
        $count = count($entities);
307
        $dept = new \VolunteerDepartment($entity['departmentID']);
308
        $res = array();
309
        $res['department'] = $dept->departmentName;
0 ignored issues
show
Bug introduced by
The property departmentName does not seem to exist in VolunteerDepartment.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
310
        $res['earlyLate'] = $entity['earlyLate'];
311
        $res['endTime'] = $entity['endTime'];
312
        $res['eventID'] = $entity['eventID'];
313
        $res['name'] = $entity['name'];
314
        $res['startTime'] = $entity['startTime'];
315
        $res['groupID'] = $entity['groupID'];
316
        $res['shifts'] = array();
317
        $roles = array();
318
        for($i = 0; $i < $count; $i++)
319
        {
320 View Code Duplication
            if(isset($entities[$i]['status']) && ($entities[$i]['status'] === 'filled' || $entities[$i]['status'] === 'pending'))
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...
321
            {
322
                continue;
323
            }
324
            if(!isset($roles[$entities[$i]['roleID']]))
325
            {
326
                $roles[$entities[$i]['roleID']] = new \VolunteerRole($entities[$i]['roleID']);
327
            }
328
            $role = $roles[$entities[$i]['roleID']];
329
            $entities[$i]['role'] = $role->display_name;
330
            array_push($res['shifts'], $entities[$i]);
331
        }
332
        return $response->withJSON($res);
333
    }
334
335
    public function generateGroupLink($request, $response, $args)
336
    {
337
        $this->validateLoggedIn($request);
338
        $shiftId = $args['shift'];
339
        $dataTable = $this->getDataTable();
340
        $filter = $this->getFilterForPrimaryKey($shiftId);
341
        $entity = $dataTable->read($filter);
342
        if(empty($entity))
343
        {
344
            return $response->withStatus(404);
345
        }
346
        $entity = $entity[0];
347 View Code Duplication
        if(isset($entity['participant']) && strlen($entity['participant']) > 0)
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...
348
        {
349
            return $response->withStatus(401);
350
        }
351
        $data = $request->getParsedBody();
352
        $myShift = $data['myshift'];
353
        $roles = array();
354
        foreach($data as $key => $value)
355
        {
356
            if(substr($key, 0, 6) === "roles.")
357
            {
358
                $roles[substr($key, 6)] = $value;
359
            }
360
        }
361
        $filter = new \Data\Filter('groupID eq '.$entity['groupID'].' and enabled eq true');
362
        $entities = $dataTable->read($filter);
363
        $count = count($entities);
364
        $uuid = $this->genUUID();
365
        for($i = 0; $i < $count; $i++)
366
        {
367 View Code Duplication
            if(isset($entities[$i]['status']) && ($entities[$i]['status'] === 'filled' || $entities[$i]['status'] === 'pending'))
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...
368
            {
369
                $entities[$i] = false;
370
                continue;
371
            }
372
            if((string)$entities[$i]['_id'] === (string)new \MongoDB\BSON\ObjectId($myShift))
373
            {
374
                $entities[$i]['participant'] = $this->user->uid;
375
                $entities[$i]['status'] = 'filled';
376
                $entities[$i]['signupLink'] = $uuid;
377
            }
378
            else if(isset($roles[$entities[$i]['roleID']]))
379
            {
380
                $entities[$i]['status'] = 'groupPending';
381
                $entities[$i]['signupLink'] = $uuid;
382
                $roles[$entities[$i]['roleID']]--;
383
                if($roles[$entities[$i]['roleID']] === 0)
384
                {
385
                    unset($roles[$entities[$i]['roleID']]);
386
                }
387
            }
388
            else
389
            {
390
                $entities[$i] = false;
391
            }
392
        }
393
        if(count($roles) !== 0)
394
        {
395
            throw new \Exception('Not enough shifts to fullfill requests');
396
        }
397
        for($i = 0; $i < $count; $i++)
398
        {
399
            if($entities[$i] === false)
400
            {
401
                continue;
402
            }
403
            $filter = new \Data\Filter('_id eq '.$entities[$i]['_id']);
404
            $res = $dataTable->update($filter, $entities[$i]);
405
            if($res === false)
406
            {
407
                throw new \Exception('Not able to save shift '.$entities[$i]['_id']);
408
            }
409
        }
410
        return $response->withJSON(array('uuid' => $uuid));
411
    }
412
}
413