Completed
Push — master ( f1f529...6a6be2 )
by Patrick
02:20
created

ShiftAPI::deleteGroup()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 4
nop 2
dl 0
loc 21
rs 9.584
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('/Actions/DeleteGroup', array($this, 'deleteGroup'));
17
        $app->post('/{shift}/Actions/Signup[/]', array($this, 'signup'));
18
        $app->post('/{shift}/Actions/Abandon[/]', array($this, 'abandon'));
19
        $app->post('/{shift}/Actions/Approve[/]', array($this, 'approvePending'));
20
        $app->post('/{shift}/Actions/Disapprove[/]', array($this, 'disapprovePending')); 
21
        $app->post('/{shift}/Actions/StartGroupSignup', array($this, 'startGroupSignup'));
22
        $app->post('/{shift}/Actions/GenerateGroupLink', array($this, 'generateGroupLink'));
23
    }
24
25
    protected function canCreate($request)
26
    {
27
        if($this->isVolunteerAdmin($request))
28
        {
29
            return true;
30
        }
31
        //TODO give access to department lead
32
        return false;
33
    }
34
35
    protected function canUpdate($request, $entity)
36
    {
37
 	if($this->isVolunteerAdmin($request))
38
        {
39
            return true;
40
        }
41
        return $this->isUserDepartmentLead($entity['departmentID'], $this->user);
42
    }
43
44
    protected function canDelete($request, $entity)
45
    {
46
        return $this->canUpdate($request, $entity);
47
    }
48
49
    protected function processEntry($entry, $request)
50
    {
51
        return $this->processShift($entry, $request);
52
    }
53
54
    protected function genUUID()
55
    {
56
        return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
57
            // 32 bits for "time_low"
58
            mt_rand(0, 0xffff), mt_rand(0, 0xffff),
59
60
            // 16 bits for "time_mid"
61
            mt_rand(0, 0xffff),
62
63
            // 16 bits for "time_hi_and_version",
64
            // four most significant bits holds version number 4
65
            mt_rand(0, 0x0fff) | 0x4000,
66
67
            // 16 bits, 8 bits for "clk_seq_hi_res",
68
            // 8 bits for "clk_seq_low",
69
            // two most significant bits holds zero and one for variant DCE1.1
70
            mt_rand(0, 0x3fff) | 0x8000,
71
72
            // 48 bits for "node"
73
            mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
74
        );
75
    }
76
77
    public function createGroup($request, $response)
78
    {
79
        $array = $request->getParsedBody();
80
        $count = count($array);
81
        $entArray = array();
82
        $uuid = $this->genUUID();
83
        $dataTable = $this->getDataTable();
84
        //User must be able to edit all shifts
85
        for($i = 0; $i < $count; $i++)
86
        {
87
            $filter = $this->getFilterForPrimaryKey($array[$i]);
88
            $entity = $dataTable->read($filter);
89
            if($entity === false || !isset($entity[0]))
90
            {
91
                return $response->withStatus(404);
92
            }
93
            $entity = $entity[0];
94
            if(!$this->canUpdate($request, $entity))
95
            {
96
                return $response->withStatus(401);
97
            }
98
            $entity['groupID'] = $uuid;
99
            array_push($entArray, $entity);
100
        }
101
        //If we got here we can update them all
102
        $myRet = true;
103
        $errors = array();
104
        for($i = 0; $i < $count; $i++)
105
        {
106
            $filter = $this->getFilterForPrimaryKey($array[$i]);
107
            $ret = $dataTable->update($filter, $entArray[$i]);
108
            if($ret === false)
109
            {
110
               $myRet = false;
111
               array_push($errors, $array[$i]);
112
            }
113
        }
114
        if($myRet)
115
        {
116
            return $response->withJson($myRet);
117
        }
118
        else
119
        {
120
            return $response->withJson(array('res'=>$myRet, 'errors'=>$errors));
121
        }
122
    }
123
124
    public function newGroup($request, $response)
125
    {
126
        if(!$this->canCreate($request))
127
        {
128
            return $response->withStatus(401);
129
        }
130
        $data = $request->getParsedBody();
131
        $shift = array();
132
        $shift['groupID'] = $this->genUUID();
133
        $shift['departmentID'] = $data['groupDepartmentID'];
134
        $shift['earlyLate'] = $data['groupEarlyLate'];
135
        $shift['enabled'] = $data['groupEnabled'];
136
        $shift['endTime'] = $data['groupEndTime'];
137
        $shift['eventID'] = $data['groupEvent'];
138
        $shift['name'] = $data['groupName'];
139
        $shift['startTime'] = $data['groupStartTime'];
140
        $dataTable = $this->getDataTable();
141
        $ret = true;
142
        foreach($data['roles'] as $role=>$count)
143
        {
144
            $count = intval($count);
145
            for($i = 0; $i < $count; $i++)
146
            {
147
                $shift['roleID'] = $role;
148
                if($dataTable->create($shift) === false)
149
                {
150
                    $ret = false;
151
                }
152
            }
153
        }
154
        return $response->withJSON($ret);
155
    }
156
157
    public function deleteGroup($request, $response)
158
    {
159
        $data = $request->getParsedBody();
160
        $dataTable = $this->getDataTable();
161
        $filter = new \Data\Filter('groupID eq '.$data['groupID']);
162
        $entities = $dataTable->read($filter);
163
        if(empty($entities))
164
        {
165
            return $response->withStatus(404);
166
        }
167
        if(!$this->canUpdate($request, $entities[0]))
168
        {
169
            return $response->withStatus(401);
170
        }
171
        $res = $dataTable->delete($filter);
172
        if($res)
173
        {
174
            return $response->withJSON($res);
175
        }
176
        return $response->withJSON($res, 500);
177
    }
178
179
    public function signup($request, $response, $args)
180
    {
181
        $this->validateLoggedIn($request);
182
        $shiftId = $args['shift'];
183
        $dataTable = $this->getDataTable();
184
        $filter = $this->getFilterForPrimaryKey($shiftId);
185
        $entity = $dataTable->read($filter);
186
        if(empty($entity))
187
        {
188
            return $response->withStatus(404);
189
        }
190
        $entity = $entity[0];
191 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...
192
        {
193
            return $response->withStatus(401);
194
        }
195
        $shift = new \VolunteerShift($shiftId, $entity);
196
        $entity = $this->processShift($entity, $request);
197
        if(isset($entity['overlap']) && $entity['overlap'])
198
        {
199
            $overlaps = $shift->findOverlaps($this->user->uid);
200
            $count = count($overlaps);
201
            $leads = array();
202
            for($i = 0; $i < $count; $i++)
203
            {
204
                $dept = new \VolunteerDepartment($overlaps[$i]->departmentID);
205
                $leads = array_merge($leads, $dept->getLeadEmails());
206
                $overlaps[$i]->status = 'pending';
207
                $tmp = new \Data\Filter('_id eq '.$overlaps[$i]->{'_id'});
208
                $res = $dataTable->update($tmp, $overlaps[$i]);
209
                if($res === false)
210
                {
211
                    return $response->withJSON(array('err'=>'Unable to update overlap with id '.$overlaps[$i]->{'_id'}));
212
                }
213
            }
214
            $dept = new \VolunteerDepartment($entity['departmentID']);
215
            $leads = array_merge($leads, $dept->getLeadEmails());
216
            $leads = array_unique($leads);
217
            $entity['participant'] = $this->user->uid;
218
            $entity['status'] = 'pending';
219
            $profile = new \VolunteerProfile($this->user->uid);
220
            $email = new \Emails\TwoShiftsAtOnceEmail($profile);
221
            $email->addLeads($leads);
222
            $emailProvider = \EmailProvider::getInstance();
223
            if($emailProvider->sendEmail($email) === false)
224
            {
225
                throw new \Exception('Unable to send duplicate email!');
226
            }
227
            return $response->withJSON($dataTable->update($filter, $entity));
228
        }
229 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...
230
        {
231
            $entity['participant'] = $this->user->uid;
232
            $entity['status'] = 'filled';
233
            return $response->withJSON($dataTable->update($filter, $entity));
234
        }
235 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...
236
        {
237
            $entity['participant'] = $this->user->uid;
238
            $entity['status'] = 'filled';
239
            return $response->withJSON($dataTable->update($filter, $entity));
240
        }
241
        print_r($entity); die();
242
    }
243
244
    public function abandon($request, $response, $args)
245
    {
246
        $this->validateLoggedIn($request);
247
        $shiftId = $args['shift'];
248
        $dataTable = $this->getDataTable();
249
        $filter = $this->getFilterForPrimaryKey($shiftId);
250
        $entity = $dataTable->read($filter);
251
        if(empty($entity))
252
        {
253
            return $response->withStatus(404);
254
        }
255
        $entity = $entity[0];
256
        if(!isset($entity['participant']) || $entity['participant'] !== $this->user->uid)
257
        {
258
            return $response->withStatus(401);
259
        }
260
        $entity['participant'] = '';
261
        $entity['status'] = 'unfilled';
262
        return $response->withJSON($dataTable->update($filter, $entity));
263
    }
264
265
    public function approvePending($request, $response, $args)
266
    {
267
        if(!$this->canCreate($request))
268
        {
269
            return $response->withStatus(401);
270
        }
271
        $shiftId = $args['shift'];
272
        $dataTable = $this->getDataTable();
273
        $filter = $this->getFilterForPrimaryKey($shiftId);
274
        $entity = $dataTable->read($filter);
275
        if(empty($entity))
276
        {
277
            return $response->withStatus(404);
278
        }
279
        $entity = $entity[0];
280
        $entity['status'] = 'filled';
281
        return $response->withJSON($dataTable->update($filter, $entity));
282
    }
283
284
    public function disapprovePending($request, $response, $args)
285
    {
286
        if(!$this->canCreate($request))
287
        {
288
            return $response->withStatus(401);
289
        }
290
        $shiftId = $args['shift'];
291
        $dataTable = $this->getDataTable();
292
        $filter = $this->getFilterForPrimaryKey($shiftId);
293
        $entity = $dataTable->read($filter);
294
        if(empty($entity))
295
        {
296
            return $response->withStatus(404);
297
        }
298
        $entity['participant'] = '';
299
        $entity['status'] = 'unfilled';
300
        $profile = new \VolunteerProfile($this->user->uid);
301
        $email = new \Emails\PendingRejectedEmail($profile);
302
        $email->setShift($entity);
303
        $emailProvider = \EmailProvider::getInstance();
304
        if($emailProvider->sendEmail($email) === false)
305
        {
306
            throw new \Exception('Unable to send duplicate email!');
307
        }
308
        return $response->withJSON($dataTable->update($filter, $entity));
309
    }
310
311
    public function startGroupSignup($request, $response, $args)
312
    {
313
        $this->validateLoggedIn($request);
314
        $shiftId = $args['shift'];
315
        $dataTable = $this->getDataTable();
316
        $filter = $this->getFilterForPrimaryKey($shiftId);
317
        $entity = $dataTable->read($filter);
318
        if(empty($entity))
319
        {
320
            return $response->withStatus(404);
321
        }
322
        $entity = $entity[0];
323 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...
324
        {
325
            return $response->withStatus(401);
326
        }
327
        $filter = new \Data\Filter('groupID eq '.$entity['groupID'].' and enabled eq true');
328
        $entities = $dataTable->read($filter);
329
        $count = count($entities);
330
        $dept = new \VolunteerDepartment($entity['departmentID']);
331
        $res = array();
332
        $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...
333
        $res['earlyLate'] = $entity['earlyLate'];
334
        $res['endTime'] = $entity['endTime'];
335
        $res['eventID'] = $entity['eventID'];
336
        $res['name'] = $entity['name'];
337
        $res['startTime'] = $entity['startTime'];
338
        $res['groupID'] = $entity['groupID'];
339
        $res['shifts'] = array();
340
        $roles = array();
341
        for($i = 0; $i < $count; $i++)
342
        {
343 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...
344
            {
345
                continue;
346
            }
347
            if(!isset($roles[$entities[$i]['roleID']]))
348
            {
349
                $roles[$entities[$i]['roleID']] = new \VolunteerRole($entities[$i]['roleID']);
350
            }
351
            $role = $roles[$entities[$i]['roleID']];
352
            $entities[$i]['role'] = $role->display_name;
353
            array_push($res['shifts'], $entities[$i]);
354
        }
355
        return $response->withJSON($res);
356
    }
357
358
    public function generateGroupLink($request, $response, $args)
359
    {
360
        $this->validateLoggedIn($request);
361
        $shiftId = $args['shift'];
362
        $dataTable = $this->getDataTable();
363
        $filter = $this->getFilterForPrimaryKey($shiftId);
364
        $entity = $dataTable->read($filter);
365
        if(empty($entity))
366
        {
367
            return $response->withStatus(404);
368
        }
369
        $entity = $entity[0];
370 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...
371
        {
372
            return $response->withStatus(401);
373
        }
374
        $data = $request->getParsedBody();
375
        $myShift = $data['myshift'];
376
        $roles = array();
377
        foreach($data as $key => $value)
378
        {
379
            if(substr($key, 0, 6) === "roles.")
380
            {
381
                $roles[substr($key, 6)] = $value;
382
            }
383
        }
384
        $filter = new \Data\Filter('groupID eq '.$entity['groupID'].' and enabled eq true');
385
        $entities = $dataTable->read($filter);
386
        $count = count($entities);
387
        $uuid = $this->genUUID();
388
        for($i = 0; $i < $count; $i++)
389
        {
390 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...
391
            {
392
                $entities[$i] = false;
393
                continue;
394
            }
395
            if((string)$entities[$i]['_id'] === (string)new \MongoDB\BSON\ObjectId($myShift))
396
            {
397
                $entities[$i]['participant'] = $this->user->uid;
398
                $entities[$i]['status'] = 'filled';
399
                $entities[$i]['signupLink'] = $uuid;
400
            }
401
            else if(isset($roles[$entities[$i]['roleID']]))
402
            {
403
                $entities[$i]['status'] = 'groupPending';
404
                $entities[$i]['signupLink'] = $uuid;
405
                $roles[$entities[$i]['roleID']]--;
406
                if($roles[$entities[$i]['roleID']] === 0)
407
                {
408
                    unset($roles[$entities[$i]['roleID']]);
409
                }
410
            }
411
            else
412
            {
413
                $entities[$i] = false;
414
            }
415
        }
416
        if(count($roles) !== 0)
417
        {
418
            throw new \Exception('Not enough shifts to fullfill requests');
419
        }
420
        for($i = 0; $i < $count; $i++)
421
        {
422
            if($entities[$i] === false)
423
            {
424
                continue;
425
            }
426
            $filter = new \Data\Filter('_id eq '.$entities[$i]['_id']);
427
            $res = $dataTable->update($filter, $entities[$i]);
428
            if($res === false)
429
            {
430
                throw new \Exception('Not able to save shift '.$entities[$i]['_id']);
431
            }
432
        }
433
        return $response->withJSON(array('uuid' => $uuid));
434
    }
435
}
436