StaffHandler   B
last analyzed

Complexity

Total Complexity 46

Size/Duplication

Total Lines 473
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 178
c 0
b 0
f 0
dl 0
loc 473
rs 8.72
wmc 46

20 Methods

Rating   Name   Duplication   Size   Complexity  
A isStaff() 0 5 1
A staffInRole() 0 8 2
A getByUid() 0 18 4
A getRoles() 0 11 2
A removeStaffRoles() 0 6 1
A increaseCallsClosed() 0 12 3
A updateRating() 0 14 3
A updateQuery() 0 26 2
A __construct() 0 5 1
A deleteQuery() 0 5 1
A getByAllDepts() 0 5 1
A getRolesByDept() 0 15 2
A delete() 0 34 6
A getTimeSpent() 0 17 3
A clearRoles() 0 12 2
A addStaff() 0 13 1
A updateResponseTime() 0 14 3
A getStaffByTask() 0 32 4
A addStaffRole() 0 12 2
A insertQuery() 0 26 2

How to fix   Complexity   

Complex Class

Complex classes like StaffHandler 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.

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

1
<?php declare(strict_types=1);
2
3
namespace XoopsModules\Xhelp;
4
5
/*
6
 * You may not change or alter any portion of this comment or credits
7
 * of supporting developers from this source code or any supporting source code
8
 * which is considered copyrighted (c) material of the original comment or credit authors.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
 */
14
15
/**
16
 * @copyright    {@link https://xoops.org/ XOOPS Project}
17
 * @license      {@link https://www.gnu.org/licenses/gpl-2.0.html GNU GPL 2 or later}
18
 * @author       Eric Juden <[email protected]>
19
 * @author       XOOPS Development Team
20
 */
21
22
if (!\defined('XHELP_CLASS_PATH')) {
23
    exit();
24
}
25
26
// require_once XHELP_CLASS_PATH . '/BaseObjectHandler.php';
27
// require_once XHELP_CLASS_PATH . '/NotificationService.php';
28
29
/**
30
 * Staff class
31
 *
32
 * @author  Eric Juden <[email protected]>
33
 */
34
35
// require_once XHELP_CLASS_PATH . '/session.php';
36
37
/**
38
 * StaffHandler class
39
 *
40
 * Staff Handler for Staff class
41
 *
42
 * @author  Eric Juden <[email protected]> &
43
 */
44
class StaffHandler extends BaseObjectHandler
45
{
46
    /**
47
     * Name of child class
48
     *
49
     * @var string
50
     */
51
    public $classname = Staff::class;
52
    /**
53
     * DB table name
54
     *
55
     * @var string
56
     */
57
    public $dbtable = 'xhelp_staff';
58
59
    private const TABLE = 'xhelp_staff';
60
    private const ENTITY = Staff::class;
61
    private const ENTITYNAME = 'Staff';
62
    private const KEYNAME = 'id';
63
    private const IDENTIFIER = 'uid';
64
65
    /**
66
     * Constructor
67
     *
68
     * @param \XoopsMySQLDatabase|null $db reference to a xoopsDB object
69
     */
70
    public function __construct(\XoopsMySQLDatabase $db = null)
71
    {
72
        $this->init($db);
73
        $this->helper = Helper::getInstance();
74
        parent::__construct($db, static::TABLE, static::ENTITY, static::KEYNAME, static::IDENTIFIER);
75
    }
76
77
    /**
78
     * retrieve a staff object from the database
79
     * @param int $uid user id
80
     * @return bool|Staff
81
     */
82
    public function &getByUid(int $uid)
83
    {
84
        $ret = false;
85
        $uid = $uid;
86
        if ($uid > 0) {
87
            $sql = $this->selectQuery(new \Criteria('uid', (string)$uid));
88
            if (!$result = $this->db->query($sql)) {
89
                return $ret;
90
            }
91
            $arr = $this->db->fetchArray($result);
92
            if ($arr) {
93
                $ret = new $this->classname($arr);
94
95
                return $ret;
96
            }
97
        }
98
99
        return $ret;
100
    }
101
102
    /**
103
     * Add user to a new role
104
     *
105
     * @param int $uid    user id
106
     * @param int $roleid role id
107
     * @param int $deptid department id
108
     *
109
     * @return bool true if success, FALSE if failure
110
     */
111
    public function addStaffRole(int $uid, int $roleid, int $deptid): bool
112
    {
113
        $staffRoleHandler = $this->helper->getHandler('StaffRole');
114
        $role             = $staffRoleHandler->create();
115
        $role->setVar('uid', $uid);
116
        $role->setVar('roleid', $roleid);
117
        $role->setVar('deptid', $deptid);
118
        if (!$staffRoleHandler->insert($role)) {
119
            return false;
120
        }
121
122
        return true;
123
    }
124
125
    /**
126
     * Retrive all roles of the current staff member
127
     *
128
     * @param int  $uid
129
     * @param bool $id_as_key
130
     * @return array|bool StaffRoles or FALSE if failure
131
     */
132
    public function getRoles(int $uid, bool $id_as_key = false)
133
    {
134
        $uid = $uid;
135
        /** @var \XoopsModules\Xhelp\StaffRoleHandler $staffRoleHandler */
136
        $staffRoleHandler = $this->helper->getHandler('StaffRole');
137
138
        if (!$roles = $staffRoleHandler->getObjectsByStaff($uid, $id_as_key)) {
139
            return false;
140
        }
141
142
        return $roles;
143
    }
144
145
    /**
146
     * @return bool
147
     */
148
    public function clearRoles(): bool
149
    {
150
        $session = Session::getInstance();
151
152
        $myRoles = $session->get('xhelp_hasRights');
153
        if ($myRoles) {
154
            $session->del('xhelp_hasRights');
155
156
            return true;
157
        }
158
159
        return false;
160
    }
161
162
    /**
163
     * Retrieve all of the roles of current department for staff member
164
     *
165
     * @param int  $uid
166
     * @param int  $deptid
167
     * @param bool $id_as_key
168
     * @return array|bool array of StaffRoles or FALSE if failure
169
     */
170
    public function getRolesByDept(int $uid, int $deptid, bool $id_as_key = false)
171
    {
172
        $ret              = false;
173
        $uid              = $uid;
174
        $deptid           = $deptid;
175
        $staffRoleHandler = $this->helper->getHandler('StaffRole');
176
177
        $criteria = new \CriteriaCompo(new \Criteria('uid', (string)$uid));
178
        $criteria->add(new \Criteria('deptid', (string)$deptid));
179
180
        if (!$roles = $staffRoleHandler->getObjects($criteria, $id_as_key)) {
181
            return $ret;
182
        }
183
184
        return $roles;
185
    }
186
187
    /**
188
     * Remove user from a role
189
     *
190
     * @param int $uid user id
191
     * @return true if success, FALSE if failure
192
     * @internal param int $roleid role id
193
     * @internal param int $deptid department id
194
     */
195
    public function removeStaffRoles(int $uid): bool
196
    {
197
        $staffRoleHandler = $this->helper->getHandler('StaffRole');
198
        $criteria         = new \Criteria('uid', (string)$uid);
199
200
        return $staffRoleHandler->deleteAll($criteria);
201
    }
202
203
    /**
204
     * Check if a user is in a particular role
205
     *
206
     * @param int $uid    user id
207
     * @param int $roleid role id
208
     *
209
     * @return bool true on success, FALSE on failure
210
     */
211
    public function staffInRole(int $uid, int $roleid): bool
212
    {
213
        $staffRoleHandler = $this->helper->getHandler('StaffRole');
214
        if (!$inRole = $staffRoleHandler->staffInRole($uid, $roleid)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $inRole is dead and can be removed.
Loading history...
215
            return false;
216
        }
217
218
        return true;
219
    }
220
221
    /**
222
     * Retrieve amount of time spent by staff member
223
     * @param int $uid user id
224
     * @return int
225
     */
226
    public function &getTimeSpent(int $uid = 0): int
227
    {
228
        $responseHandler = $this->helper->getHandler('Response');
229
        if (0 == !$uid) {
230
            $uid       = $uid;
231
            $criteria  = new \Criteria('uid', (string)$uid);
232
            $responses = $responseHandler->getObjects($criteria);
233
        } else {
234
            $responses = $responseHandler->getObjects();
235
        }
236
        $timeSpent = 0;
237
        foreach ($responses as $response) {
238
            $newTime   = $response->getVar('timeSpent');
239
            $timeSpent += $newTime;
240
        }
241
242
        return $timeSpent;
243
    }
244
245
    /**
246
     * @return array
247
     */
248
    public function &getByAllDepts(): array
249
    {
250
        $ret = $this->getObjects(new \Criteria('allDepartments', '1'), true);
251
252
        return $ret;
253
    }
254
255
    /**
256
     * creates new staff member
257
     *
258
     * @param int    $uid
259
     * @param string $email
260
     * @return bool
261
     */
262
    public function addStaff(int $uid, string $email) //, $allDepts = 0
263
    : bool
264
    {
265
        $notify = new NotificationService();
266
        /** @var \XoopsModules\Xhelp\Staff $staff */
267
        $staff = $this->create();
268
        $staff->setVar('uid', $uid);
269
        $staff->setVar('email', $email);
270
        $numNotify = $notify->getNumDeptNotifications();
271
        $staff->setVar('notify', (2 ** $numNotify) - 1);
272
        $staff->setVar('permTimestamp', \time());
273
274
        return $this->insert($staff);
275
    }
276
277
    /**
278
     * checks to see if the user is a staff member
279
     *
280
     * @param int $uid User ID to look for
281
     * @return bool TRUE if user is a staff member, false if not
282
     */
283
    public function isStaff(int $uid): bool
284
    {
285
        $count = $this->getCount(new \Criteria('uid', (string)$uid));
286
287
        return ($count > 0);
288
    }
289
290
    /**
291
     * @param \XoopsObject $object
292
     * @return string
293
     */
294
    public function insertQuery(\XoopsObject $object): string
295
    {
296
        //TODO mb replace with individual variables
297
        // Copy all object vars into local variables
298
        foreach ($object->cleanVars as $k => $v) {
299
            ${$k} = $v;
300
        }
301
302
        $sql = \sprintf(
303
            'INSERT INTO `%s` (id, uid, email, responseTime, numReviews, callsClosed, attachSig, rating, allDepartments, ticketsResponded, notify, permTimestamp) VALUES (%u, %u, %s, %u, %u, %u, %u, %u, %u, %u, %u, %u)',
304
            $this->db->prefix($this->dbtable),
305
            $id,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $id seems to be never defined.
Loading history...
306
            $uid,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $uid seems to be never defined.
Loading history...
307
            $this->db->quoteString($email),
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $email seems to be never defined.
Loading history...
308
            $responseTime,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $responseTime seems to be never defined.
Loading history...
309
            $numReviews,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $numReviews seems to be never defined.
Loading history...
310
            $callsClosed,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $callsClosed seems to be never defined.
Loading history...
311
            $attachSig,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $attachSig seems to be never defined.
Loading history...
312
            $rating,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $rating seems to be never defined.
Loading history...
313
            $allDepartments,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $allDepartments seems to be never defined.
Loading history...
314
            $ticketsResponded,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $ticketsResponded seems to be never defined.
Loading history...
315
            $notify,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $notify seems to be never defined.
Loading history...
316
            $permTimestamp
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $permTimestamp seems to be never defined.
Loading history...
317
        );
318
319
        return $sql;
320
    }
321
322
    /**
323
     * @param \XoopsObject $object
324
     * @return string
325
     */
326
    public function updateQuery(\XoopsObject $object): string
327
    {
328
        //TODO mb replace with individual variables
329
        // Copy all object vars into local variables
330
        foreach ($object->cleanVars as $k => $v) {
331
            ${$k} = $v;
332
        }
333
334
        $sql = \sprintf(
335
            'UPDATE `%s` SET uid = %u, email = %s, responseTime = %u, numReviews = %u, callsClosed = %u, attachSig = %u, rating = %u, allDepartments = %u, ticketsResponded = %u, notify = %u, permTimestamp = %u WHERE id = %u',
336
            $this->db->prefix($this->dbtable),
337
            $uid,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $uid seems to be never defined.
Loading history...
338
            $this->db->quoteString($email),
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $email seems to be never defined.
Loading history...
339
            $responseTime,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $responseTime seems to be never defined.
Loading history...
340
            $numReviews,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $numReviews seems to be never defined.
Loading history...
341
            $callsClosed,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $callsClosed seems to be never defined.
Loading history...
342
            $attachSig,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $attachSig seems to be never defined.
Loading history...
343
            $rating,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $rating seems to be never defined.
Loading history...
344
            $allDepartments,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $allDepartments seems to be never defined.
Loading history...
345
            $ticketsResponded,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $ticketsResponded seems to be never defined.
Loading history...
346
            $notify,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $notify seems to be never defined.
Loading history...
347
            $permTimestamp,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $permTimestamp seems to be never defined.
Loading history...
348
            $id
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $id seems to be never defined.
Loading history...
349
        );
350
351
        return $sql;
352
    }
353
354
    /**
355
     * @param \XoopsObject $object
356
     * @return string
357
     */
358
    public function deleteQuery(\XoopsObject $object): string
359
    {
360
        $sql = \sprintf('DELETE FROM `%s` WHERE id = %u', $this->db->prefix($this->dbtable), $object->getVar('id'));
0 ignored issues
show
Bug introduced by
It seems like $object->getVar('id') can also be of type array and array; however, parameter $values of sprintf() does only seem to accept double|integer|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

360
        $sql = \sprintf('DELETE FROM `%s` WHERE id = %u', $this->db->prefix($this->dbtable), /** @scrutinizer ignore-type */ $object->getVar('id'));
Loading history...
361
362
        return $sql;
363
    }
364
365
    /**
366
     * delete a staff member from the database
367
     *
368
     * @param \XoopsObject $object    reference to the {@link Staff}
369
     *                                obj to delete
370
     * @param bool         $force
371
     * @return bool FALSE if failed.
372
     */
373
    public function delete(\XoopsObject $object, $force = false): bool
374
    {
375
        if (0 != \strcasecmp($this->classname, \get_class($object))) {
376
            return false;
377
        }
378
379
        // Clear Department Membership
380
        /** @var \XoopsModules\Xhelp\MembershipHandler $membershipHandler */
381
        $membershipHandler = $this->helper->getHandler('Membership');
382
        if (!$membershipHandler->clearStaffMembership($object->getVar('uid'))) {
383
            return false;
384
        }
385
386
        // Remove ticket lists
387
        $ticketListHandler = $this->helper->getHandler('TicketList');
388
        $criteria          = new \Criteria('uid', $object->getVar('uid'));
0 ignored issues
show
Bug introduced by
It seems like $object->getVar('uid') can also be of type array and array; however, parameter $value of Criteria::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

388
        $criteria          = new \Criteria('uid', /** @scrutinizer ignore-type */ $object->getVar('uid'));
Loading history...
389
        if (!$ticketListHandler->deleteAll($criteria)) {
390
            return false;
391
        }
392
393
        // Remove saved searches
394
        $savedSearchHandler = $this->helper->getHandler('SavedSearch');
395
        if (!$savedSearchHandler->deleteAll($criteria)) {   // use existing crit object
396
            return false;
397
        }
398
399
        // Clear permission roles
400
        if (!$this->removeStaffRoles($object->getVar('uid'))) {
401
            return false;
402
        }
403
404
        $ret = parent::delete($object, $force);
405
406
        return $ret;
407
    }
408
409
    /**
410
     * Adjust the # of calls closed for the given user by the given offset
411
     *
412
     * @param int $uid    User ID to modify
413
     * @param int $offset Number of tickets to add to current call count (Negative for decrementing)
414
     * @return bool FALSE if query failed
415
     */
416
    public function increaseCallsClosed(int $uid, int $offset = 1): bool
417
    {
418
        if ($offset < 0) {
419
            $sql = \sprintf('UPDATE `%s` SET callsClosed = callsClosed - %u WHERE uid = %u', $this->db->prefix($this->dbtable), \abs($offset), $uid);
420
        } else {
421
            $sql = \sprintf('UPDATE `%s` SET callsClosed = callsClosed + %u WHERE uid = %u', $this->db->prefix($this->dbtable), $offset, $uid);
422
        }
423
        if (!$result = $this->db->query($sql)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
424
            return false;
425
        }
426
427
        return true;
428
    }
429
430
    /**
431
     * Adjust the responseTime for the specified staff member
432
     *
433
     * @param int $uid          User ID to modify
434
     * @param int $responseTime If $ticketCount is specified, the total # of response seconds, otherwise the number of seconds to add
435
     * @param int $ticketCount  If = 0, increments 'responseTime' and 'ticketsResponded' otherwise, total # of tickets
436
     * @return bool FALSE if query failed
437
     */
438
    public function updateResponseTime(int $uid, int $responseTime, int $ticketCount = 0): bool
439
    {
440
        if (0 == $ticketCount) {
441
            //Incrementing responseTime
442
            $sql = \sprintf('UPDATE `%s` SET responseTime = responseTime + %u, ticketsResponded = ticketsResponded + 1 WHERE uid = %u', $this->db->prefix($this->dbtable), $responseTime, $uid);
443
        } else {
444
            //Setting responseTime, ticketsResponded
445
            $sql = \sprintf('UPDATE `%s` SET responseTime = %u, ticketsResponded = %u WHERE uid = %u', $this->db->prefix($this->dbtable), $responseTime, $ticketCount, $uid);
446
        }
447
        if (!$result = $this->db->query($sql)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
448
            return false;
449
        }
450
451
        return true;
452
    }
453
454
    /**
455
     * Adjust the rating for the specified staff member
456
     *
457
     * @param int $uid        Staff ID to modify
458
     * @param int $rating     If $numReviews is specified, the total # of rating points, otherwise the number of rating points to add
459
     * @param int $numReviews If = 0, increments 'rating' and 'numReviews', otherwise total # of reviews
460
     * @return bool FALSE if query failed
461
     */
462
    public function updateRating(int $uid, int $rating, int $numReviews = 0): bool
463
    {
464
        if (0 == $numReviews) {
465
            //Add New Review
466
            $sql = \sprintf('UPDATE `%s` SET rating = rating + %u, numReviews = numReviews + 1 WHERE uid = %u', $this->db->prefix($this->dbtable), $rating, $uid);
467
        } else {
468
            //Set rating, numReviews to supplied values
469
            $sql = \sprintf('UPDATE `%s` SET rating = %u, numReviews = %u WHERE uid = %u', $this->db->prefix($this->dbtable), $rating, $numReviews, $uid);
470
        }
471
        if (!$result = $this->db->query($sql)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
472
            return false;
473
        }
474
475
        return true;
476
    }
477
478
    /**
479
     * Retrieve array of all staff with permission for current task
480
     * @param int  $task
481
     * @param int  $deptid
482
     * @param bool $id_as_key
483
     * @return array
484
     */
485
    public function getStaffByTask(int $task, int $deptid = 0, bool $id_as_key = false): array
486
    {
487
        $task = $task;
488
        if (null !== $deptid) {
0 ignored issues
show
introduced by
The condition null !== $deptid is always true.
Loading history...
489
            $deptid = $deptid;
490
        }
491
492
        // Get roles with $task value set
493
        $roleHandler = $this->helper->getHandler('Role');
494
        $roles       = $roleHandler->getRolesByTask($task);
495
        $aRoles      = [];
496
        foreach ($roles as $role) {
497
            $aRoles[$role->getVar('id')] = '';
498
        }
499
500
        // Get staff roles by dept
501
        $staffRoleHandler = $this->helper->getHandler('StaffRole');
502
        $criteria         = new \CriteriaCompo(new \Criteria('deptid', (string)$deptid));
503
        $criteria->add(new \Criteria('roleid', '(' . \implode(',', \array_keys($aRoles)) . ')', 'IN'));
504
        unset($aRoles);
505
506
        $staffRoles = $staffRoleHandler->getObjects($criteria);
507
        $aStaffID   = [];
508
        foreach ($staffRoles as $sRole) {
509
            $aStaffID[$sRole->getVar('uid')] = '';
510
        }
511
512
        // Get staff objects
513
        $criteria     = new \Criteria('uid', '(' . \implode(',', \array_keys($aStaffID)) . ')', 'IN');
514
        $staffHandler = $this->helper->getHandler('Staff');
515
516
        return $staffHandler->getObjects($criteria, $id_as_key);
517
    }
518
}
519