modUsers   F
last analyzed

Complexity

Total Complexity 137

Size/Duplication

Total Lines 772
Duplicated Lines 0 %

Test Coverage

Coverage 6.8%

Importance

Changes 26
Bugs 16 Features 1
Metric Value
wmc 137
eloc 400
dl 0
loc 772
ccs 28
cts 412
cp 0.068
rs 2
c 26
b 16
f 1

30 Methods

Rating   Name   Duplication   Size   Complexity  
A setUserGroupsByName() 0 18 5
C testAuth() 0 35 12
A getRememberTime() 0 3 1
A isUnique() 0 9 3
A issetField() 0 6 3
A __construct() 0 4 1
A setAutoLoginCookie() 0 12 4
C AutoLogin() 0 24 12
A loadUserSettings() 0 7 2
B setUserGroups() 0 23 8
B set() 0 32 9
B checkBlock() 0 19 10
B saveQuery() 0 24 7
A editQuery() 0 8 1
A deleteQuery() 0 6 1
A getUserId() 0 9 3
A delete() 0 19 2
A getPassword() 0 3 1
A close() 0 7 1
A authUser() 0 20 4
A SessionHandler() 0 43 5
A logOut() 0 13 3
A isSecure() 0 5 1
A edit() 0 24 5
A findUser() 0 17 6
F save() 0 81 20
A getDocumentGroups() 0 16 2
A setRememberTime() 0 4 1
A getUserGroups() 0 18 3
A create() 0 6 1

How to fix   Complexity   

Complex Class

Complex classes like modUsers 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 modUsers, and based on these observations, apply Extract Interface, too.

1
<?php
2 1
require_once('MODx.php');
3
4
/**
5
 * Class modUsers
6
 */
7
class modUsers extends MODxAPI
0 ignored issues
show
Coding Style introduced by
Class name "modUsers" is not in PascalCase format

Classes in PHP are usually named in CamelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. The whole name starts with a capital letter as well.

Thus the name database provider becomes DatabaseProvider.

Loading history...
8
{
9
    /**
10
     * @var array
11
     */
12
    protected $default_field = array(
13
        'user'      => array(
14
            'username' => '',
15
            'password' => '',
16
            'cachepwd' => ''
17
        ),
18
        'attribute' => array(
19
            'fullname'         => '',
20
            'role'             => 0,
21
            'email'            => '',
22
            'phone'            => '',
23
            'mobilephone'      => '',
24
            'blocked'          => 0,
25
            'blockeduntil'     => 0,
26
            'blockedafter'     => 0,
27
            'logincount'       => 0,
28
            'lastlogin'        => 0,
29
            'thislogin'        => 0,
30
            'failedlogincount' => 0,
31
            'sessionid'        => '',
32
            'dob'              => 0,
33
            'gender'           => 0,
34
            'country'          => '',
35
            'state'            => '',
36
            'city'             => '',
37
            'street'           => '',
38
            'zip'              => '',
39
            'fax'              => '',
40
            'photo'            => '',
41
            'comment'          => '',
42
            'createdon'        => 0,
43
            'editedon'         => 0,
44
            'verified'         => 0
45
        ),
46
        'hidden'    => array(
47
            'internalKey'
48
        )
49
    );
50
51
    /**
52
     * @var string
53
     */
54
    protected $givenPassword = '';
55
    protected $groups = [];
56
    protected $groupIds = [];
57
    protected $userIdCache = array(
58
        'attribute.internalKey' => '',
59
        'attribute.email' => '',
60
        'user.username' => ''
61
    );
62
63
    /**
64
     * @var integer
65
     */
66
    private $rememberTime;
67
68
    /**
69
     * MODxAPI constructor.
70
     * @param DocumentParser $modx
71
     * @param bool $debug
72 10
     * @throws Exception
73
     */
74 10
    public function __construct(DocumentParser $modx, $debug = false)
75 10
    {
76 10
        $this->setRememberTime(60 * 60 * 24 * 365 * 5);
77
        parent::__construct($modx, $debug);
78
    }
79
80
    /**
81
     * @param $val
82 10
     * @return $this
83
     */
84 10
    protected function setRememberTime($val)
85 10
    {
86
        $this->rememberTime = (int)$val;
87
        return $this;
88
    }
89
90
    /**
91
     * @return integer
92
     */
93
    public function getRememberTime()
94
    {
95
        return $this->rememberTime;
96
    }
97
98
    /**
99
     * @param $key
100
     * @return bool
101
     */
102
    public function issetField($key)
103
    {
104
        return (array_key_exists($key, $this->default_field['user']) || array_key_exists(
105
            $key,
106
            $this->default_field['attribute']
107
        ) || in_array($key, $this->default_field['hidden']));
108
    }
109
110
    /**
111
     * @param string $data
112
     * @return string|false
113
     */
114
    protected function findUser($data)
115
    {
116
        switch (true) {
117
            case (is_int($data) || ((int)$data > 0 && (string)intval($data) === $data)):
118
                $find = 'attribute.internalKey';
119
                break;
120
            case filter_var($data, FILTER_VALIDATE_EMAIL):
121
                $find = 'attribute.email';
122
                break;
123
            case is_scalar($data):
124
                $find = 'user.username';
125
                break;
126
            default:
127
                $find = false;
128
        }
129
130
        return $find;
131
    }
132
133
    /**
134
     * @param array $data
135
     * @return $this
136
     */
137
    public function create($data = array())
138
    {
139
        parent::create($data);
140
        $this->set('createdon', time());
141
142
        return $this;
143
    }
144
145
    /**
146
     *
147
     */
148
    public function close()
149
    {
150
        parent::close();
151
        $this->userIdCache = array(
152
            'attribute.internalKey' => '',
153
            'attribute.email' => '',
154
            'user.username' => ''
155
        );
156
    }
157
158
    /**
159
     * @param $id
160
     * @return mixed
161
     */
162
    protected function getUserId($id) {
163
        $find = $this->findUser($id);
164
        if ($find && ! empty($this->userIdCache[$find])) {
165
            $id = $this->userIdCache[$find];
166
        } else {
167
            $id = null;
168
        }
169
170
        return $id;
171
    }
172
173
    /**
174
     * @param $id
175
     * @return $this
176
     */
177
    public function edit($id)
178
    {
179
        $id = is_scalar($id) ? trim($id) : '';
180
        if ($this->getUserId($id) != $id) {
181
            $this->close();
182
            $this->newDoc = false;
183
184
            if (! $find = $this->findUser($id)) {
185
                $this->id = null;
186
            } else {
187
                $this->set('editedon', time());
188
                $this->editQuery($find, $id);
189
                $this->id = empty($this->field['internalKey']) ? null : $this->get('internalKey');
190
                $this->userIdCache['attribute.internalKey'] = $this->getID();
191
                $this->userIdCache['attribute.email'] = $this->get('email');
192
                $this->userIdCache['user.username'] = $this->get('username');
193
                $this->loadUserSettings();
194
                $this->store($this->toArray());
195
                unset($this->field['id']);
196
                unset($this->field['internalKey']);
197
            }
198
        }
199
200
        return $this;
201
    }
202
203
    protected function loadUserSettings()
204
    {
205
        $webUser = $this->getID();
206
207
        if (!empty($webUser)) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after NOT operator; 0 found
Loading history...
208
            $settings = $this->modx->db->makeArray($this->modx->db->select('*', $this->makeTable('web_user_settings'), "webuser = {$webUser}"));
209
            $this->fromArray(array_column($settings, 'setting_value', 'setting_name'));
210
        }
211
    }
212
213
    /**
214
     * @param string $find
215
     * @param string $id
216
     */
217
    protected function editQuery($find, $id)
218
    {
219 10
        $result = $this->query("
220
            SELECT * from {$this->makeTable('web_user_attributes')} as attribute
221 10
            LEFT JOIN {$this->makeTable('web_users')} as user ON user.id=attribute.internalKey
222
            WHERE {$find}='{$this->escape($id)}'
223 10
        ");
224
        $this->field = $this->modx->db->getRow($result);
225
    }
226
227 10
    /**
228
     * @param string $key
229
     * @param $value
230
     * @return $this
231
     */
232
    public function set($key, $value)
0 ignored issues
show
Coding Style introduced by
Function's nesting level (4) exceeds 3; consider refactoring the function
Loading history...
233
    {
234
        if (is_scalar($value) && is_scalar($key) && ! empty($key)) {
235
            switch ($key) {
236 10
                case 'password':
237 10
                    $this->givenPassword = $value;
238
                    $value = $this->getPassword($value);
239
                    break;
240
                case 'sessionid':
241 10
                    //short bug fix when authoring a web user if the manager is logged in
242 10
                    $oldSessionId  =  session_id();
243
                    session_regenerate_id(false);
244 10
                    $value = session_id();
245
                    if ($mid = $this->modx->getLoginUserID('mgr')) {
0 ignored issues
show
Unused Code introduced by
The call to DocumentParser::getLoginUserID() has too many arguments starting with 'mgr'. ( Ignorable by Annotation )

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

245
                    if ($mid = $this->modx->/** @scrutinizer ignore-call */ getLoginUserID('mgr')) {

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
246
                        //short bug fix when authoring a web user if the manager is logged in
247
                        $this->modx->db->delete($this->makeTable('active_users'),"`internalKey`={$mid} and `sid` != '{$oldSessionId}'  " );
248
                        $this->modx->db->delete($this->makeTable('active_user_sessions'),"`internalKey`={$mid} and `sid` != '{$oldSessionId}'  " );
249
250
                        $this->modx->db->query("UPDATE {$this->makeTable('active_user_locks')} SET `sid`='{$value}' WHERE `internalKey`={$mid}");
251
                        $this->modx->db->query("UPDATE {$this->makeTable('active_user_sessions')} SET `sid`='{$value}' WHERE `internalKey`={$mid}");
252
                        $this->modx->db->query("UPDATE {$this->makeTable('active_users')} SET `sid`='{$value}' WHERE `internalKey`={$mid}");
253
                    }
254
                    break;
255
                case 'editedon':
256
                case 'createdon':
257
                    $value = $this->getTime($value);
258
                    break;
259
            }
260
            $this->field[$key] = $value;
261
        }
262
263
        return $this;
264
    }
265
266
    /**
267
     * @param $pass
268
     * @return string
269
     */
270
    public function getPassword($pass)
271
    {
272
        return md5($pass);
273
    }
274
275
    /**
276
     * @param bool $fire_events
277
     * @param bool $clearCache
278
     * @return bool|int|null|void
279
     */
280
    public function save($fire_events = false, $clearCache = false)
281
    {
282
        if ($this->get('email') == '' || $this->get('username') == '' || $this->get('password') == '') {
283
            $this->log['EmptyPKField'] = 'Email, username or password is empty <pre>' . print_r(
0 ignored issues
show
Bug introduced by
Are you sure print_r($this->toArray(), true) of type string|true can be used in concatenation? ( Ignorable by Annotation )

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

283
            $this->log['EmptyPKField'] = 'Email, username or password is empty <pre>' . /** @scrutinizer ignore-type */ print_r(
Loading history...
284
                $this->toArray(),
285
                true
286
            ) . '</pre>';
287
288
            return false;
289
        }
290
291
        if ($this->isChanged('username') && ! $this->isUnique('username')) {
292
            $this->log['UniqueUsername'] = 'username not unique <pre>' . print_r(
0 ignored issues
show
Bug introduced by
Are you sure print_r($this->get('username'), true) of type string|true can be used in concatenation? ( Ignorable by Annotation )

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

292
            $this->log['UniqueUsername'] = 'username not unique <pre>' . /** @scrutinizer ignore-type */ print_r(
Loading history...
293
                $this->get('username'),
294
                true
295
            ) . '</pre>';
296
297
            return false;
298
        }
299
300
        if ($this->isChanged('email') && ! $this->isUnique('email')) {
301
            $this->log['UniqueEmail'] = 'Email not unique <pre>' . print_r($this->get('email'), true) . '</pre>';
0 ignored issues
show
Bug introduced by
Are you sure print_r($this->get('email'), true) of type string|true can be used in concatenation? ( Ignorable by Annotation )

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

301
            $this->log['UniqueEmail'] = 'Email not unique <pre>' . /** @scrutinizer ignore-type */ print_r($this->get('email'), true) . '</pre>';
Loading history...
302
303
            return false;
304
        }
305
        $this->set('sessionid', '');
306
        $fld = $this->toArray();
307
        foreach ($this->default_field['user'] as $key => $value) {
308
            $tmp = $this->get($key);
309
            if ($this->newDoc && (!is_int($tmp) && $tmp == '')) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after NOT operator; 0 found
Loading history...
310
                $this->field[$key] = $value;
311
            }
312
            $this->Uset($key, 'user');
313
            unset($fld[$key]);
314
        }
315
        if (! empty($this->set['user'])) {
316
            if ($this->newDoc) {
317
                $SQL = "INSERT into {$this->makeTable('web_users')} SET " . implode(', ', $this->set['user']);
318
            } else {
319
                $SQL = "UPDATE {$this->makeTable('web_users')} SET " . implode(
320
                    ', ',
321
                    $this->set['user']
322
                ) . " WHERE id = " . $this->id;
323
            }
324
            $this->query($SQL);
325
        }
326
327
        if ($this->newDoc) {
328
            $this->id = $this->modx->db->getInsertId();
329
        }
330
331
        $this->saveQuery($fld);
332
        unset($fld['id']);
333
334
        if (! $this->newDoc && $this->givenPassword) {
335
            $this->invokeEvent('OnWebChangePassword', array(
336
                'userObj'      => $this,
337
                'userid'       => $this->id,
338
                'user'         => $this->toArray(),
339
                'userpassword' => $this->givenPassword,
340
                'internalKey'  => $this->id,
341
                'username'     => $this->get('username')
342
            ), $fire_events);
343
        }
344
345
        if (! empty($this->groupIds)) {
346
            $this->setUserGroups($this->id, $this->groupIds);
347
        }
348
349
        $this->invokeEvent('OnWebSaveUser', array(
350
            'userObj' => $this,
351
            'mode'    => $this->newDoc ? "new" : "upd",
352
            'id'      => $this->id,
353
            'user'    => $this->toArray()
354
        ), $fire_events);
355
356
        if ($clearCache) {
357
            $this->clearCache($fire_events);
358
        }
359
360
        return $this->id;
361
    }
362
    
363
    /**
364
     * @param $field
365
     * @return bool
366
     */
367
    public function isUnique($field) {
368
        $out = false;
369
        if (isset($this->default_field['user'][$field])) {
370
            $out = $this->checkUnique('web_users', $field);
371
        } elseif(isset($this->default_field['attribute'][$field])) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after ELSEIF keyword; 0 found
Loading history...
372
            $out = $this->checkUnique('web_user_attributes', $field, 'internalKey');
373
        }
374
375
        return $out;
376
    }
377
378
    /**
379
     * @param  array  $fld
380
     */
381
    protected function saveQuery(array &$fld)
382
    {
383
        foreach ($this->default_field['attribute'] as $key => $value) {
384
            $tmp = $this->get($key);
385
            if ($this->newDoc && (!is_int($tmp) && $tmp == '')) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after NOT operator; 0 found
Loading history...
386
                $this->field[$key] = $value;
387
            }
388
            $this->Uset($key, 'attribute');
389
            unset($fld[$key]);
390
        }
391
        if (! empty($this->set['attribute'])) {
392
            if ($this->newDoc) {
393
                $this->set('internalKey', $this->id)->Uset('internalKey', 'attribute');
394
                $SQL = "INSERT into {$this->makeTable('web_user_attributes')} SET " . implode(
395
                    ', ',
396
                    $this->set['attribute']
397
                );
398
            } else {
399
                $SQL = "UPDATE {$this->makeTable('web_user_attributes')} SET " . implode(
400
                    ', ',
401
                    $this->set['attribute']
402
                ) . " WHERE  internalKey = " . $this->getID();
403
            }
404
            $this->query($SQL);
405
        }
406
    }
407
408
    /**
409
     * @param $ids
410
     * @param bool $fire_events
411
     * @return bool|null|void
412
     */
413
    public function delete($ids, $fire_events = false)
414
    {
415
        if ($this->edit($ids)) {
416
            $flag = $this->deleteQuery();
417
            $this->query("DELETE FROM {$this->makeTable('web_user_settings')} WHERE webuser='{$this->getID()}'");
418
            $this->query("DELETE FROM {$this->makeTable('web_groups')} WHERE webuser='{$this->getID()}'");
419
            $this->invokeEvent('OnWebDeleteUser', array(
420
                'userObj'     => $this,
421
                'userid'      => $this->getID(),
422
                'internalKey' => $this->getID(),
423
                'username'    => $this->get('username'),
424
                'timestamp'   => time()
425
            ), $fire_events);
426
        } else {
427
            $flag = false;
428
        }
429
        $this->close();
430
431
        return $flag;
432
    }
433
434
    /**
435
     * @return mixed
436
     */
437
    protected function deleteQuery()
438
    {
439
        return $this->query("
440
          DELETE user,attribute FROM {$this->makeTable('web_user_attributes')} as attribute
441
            LEFT JOIN {$this->makeTable('web_users')} as user ON user.id=attribute.internalKey
442
            WHERE attribute.internalKey='{$this->escape($this->getID())}'");
443
    }
444
445
    /**
446
     * @param int $id
447
     * @param bool|integer $fulltime
448
     * @param string $cookieName
449
     * @param bool $fire_events
450
     * @return bool
451
     */
452
    public function authUser($id = 0, $fulltime = true, $cookieName = 'WebLoginPE', $fire_events = false)
453
    {
454
        $flag = false;
455 10
        if (null === $this->getID() && $id) {
456
            $this->edit($id);
457 10
        }
458 10
        if (null !== $this->getID()) {
459 10
            $flag = true;
460
            $this->save(false);
461
            $this->SessionHandler('start', $cookieName, $fulltime);
462 10
            $this->invokeEvent("OnWebLogin", array(
463
                'userObj'      => $this,
464
                'userid'       => $this->getID(),
465 10
                'username'     => $this->get('username'),
466
                'userpassword' => $this->givenPassword,
467 10
                'rememberme'   => $fulltime
468 10
            ), $fire_events);
469 10
        }
470 10
471 10
        return $flag;
472
    }
473 10
474
    /**
475
     * @param int $id
476
     * @return bool
477
     */
478
    public function checkBlock($id = 0)
479
    {
480
        if ($this->getID()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->getID() of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
481
            $tmp = clone $this;
482
        } else {
483
            $tmp = $this;
484
        }
485
        if ($id && $tmp->getUserId($id) != $id) {
486
            $tmp->edit($id);
487
        }
488
        $now = time();
489
490
        $b = $tmp->get('blocked');
491
        $bu = $tmp->get('blockeduntil');
492
        $ba = $tmp->get('blockedafter');
493
        $flag = (($b && ! $bu && ! $ba) || ($bu && $now < $bu) || ($ba && $now > $ba));
494
        unset($tmp);
495
496
        return $flag;
497
    }
498
499
    /**
500
     * @param $id
501
     * @param $password
502
     * @param $blocker
503
     * @param bool $fire_events
504
     * @return bool
505
     */
506
    public function testAuth($id, $password, $blocker, $fire_events = false)
507
    {
508
        if ($this->getID()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->getID() of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
509
            $tmp = clone $this;
510
        } else {
511
            $tmp = $this;
512
        }
513
        if ($id && $tmp->getUserId($id) != $id) {
514
            $tmp->edit($id);
515
        }
516
517
        $flag = $pluginFlag = false;
518
        if ((null !== $tmp->getID()) && (! $blocker || ($blocker && ! $tmp->checkBlock($id)))
519
        ) {
520
            $eventResult = $this->getInvokeEventResult('OnWebAuthentication', array(
521
                'userObj'       => $this,
522
                'userid'        => $tmp->getID(),
523
                'username'      => $tmp->get('username'),
524
                'userpassword'  => $password,
525
                'savedpassword' => $tmp->get('password')
526
            ), $fire_events);
527
            if (is_array($eventResult)) {
528
                foreach ($eventResult as $result) {
529
                    $pluginFlag = (bool)$result;
530
                }
531
            } else {
532
                $pluginFlag = (bool)$eventResult;
533
            }
534
            if (! $pluginFlag) {
535
                $flag = ($tmp->get('password') == $tmp->getPassword($password));
536
            }
537
        }
538
        unset($tmp);
539
540
        return $flag || $pluginFlag;
541
    }
542
543
    /**
544
     * @param bool|integer $fulltime
545
     * @param string $cookieName
546
     * @return bool
547
     */
548
    public function AutoLogin($fulltime = true, $cookieName = 'WebLoginPE', $fire_events = null)
0 ignored issues
show
Coding Style introduced by
Method name "modUsers::AutoLogin" is not in camel caps format
Loading history...
Coding Style introduced by
This method is not in camel caps format.

This check looks for method names that are not written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection seeker becomes databaseConnectionSeeker.

Loading history...
549
    {
550
        $flag = false;
551
        if (isset($_COOKIE[$cookieName])) {
552
            $cookie = explode('|', $_COOKIE[$cookieName], 4);
553
            if (isset($cookie[0], $cookie[1], $cookie[2]) && strlen($cookie[0]) == 32 && strlen($cookie[1]) == 32) {
554
                if (! $fulltime && isset($cookie[4])) {
555
                    $fulltime = (int)$cookie[4];
556
                }
557
                $this->close();
558
                $q = $this->modx->db->query("SELECT id FROM " . $this->makeTable('web_users') . " WHERE md5(username)='{$this->escape($cookie[0])}'");
559
                $id = $this->modx->db->getValue($q);
560
                if ($this->edit($id)
561
                    && null !== $this->getID()
562
                    && $this->get('password') == $cookie[1]
563
                    && $this->get('sessionid') == $cookie[2]
564
                    && ! $this->checkBlock($this->getID())
565
                ) {
566
                    $flag = $this->authUser($this->getID(), $fulltime, $cookieName, $fire_events);
567
                }
568
            }
569
        }
570
571
        return $flag;
572
    }
573
574
    /**
575
     * @param string $cookieName
576
     * @param bool $fire_events
577
     */
578
    public function logOut($cookieName = 'WebLoginPE', $fire_events = false)
579
    {
580
        if (! $uid = $this->modx->getLoginUserID('web')) {
0 ignored issues
show
Unused Code introduced by
The call to DocumentParser::getLoginUserID() has too many arguments starting with 'web'. ( Ignorable by Annotation )

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

580
        if (! $uid = $this->modx->/** @scrutinizer ignore-call */ getLoginUserID('web')) {

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
581
            return;
582
        }
583
        $params = array(
584
            'username'    => $_SESSION['webShortname'],
585
            'internalKey' => $uid,
586
            'userid'      => $uid // Bugfix by TS
587
        );
588
        $this->invokeEvent('OnBeforeWebLogout', $params, $fire_events);
589
        $this->SessionHandler('destroy', $cookieName ? $cookieName : 'WebLoginPE');
590
        $this->invokeEvent('OnWebLogout', $params, $fire_events);
591
    }
592
593
    /**
594
     * SessionHandler
595
     * Starts the user session on login success. Destroys session on error or logout.
596
     *
597
     * @param string $directive ('start' or 'destroy')
598
     * @param string $cookieName
599
     * @param bool|integer $remember
600
     * @return modUsers
601
     * @author Raymond Irving
602
     * @author Scotty Delicious
603
     *
604
     * remeber может быть числом в секундах
605
     */
606
    protected function SessionHandler($directive, $cookieName, $remember = true)
0 ignored issues
show
Coding Style introduced by
Function's nesting level (4) exceeds 3; consider refactoring the function
Loading history...
Coding Style introduced by
Method name "modUsers::SessionHandler" is not in camel caps format
Loading history...
Coding Style introduced by
This method is not in camel caps format.

This check looks for method names that are not written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection seeker becomes databaseConnectionSeeker.

Loading history...
607
    {
608
        switch ($directive) {
609
            case 'start':
610
                if ($this->getID() !== null) {
611
                    $_SESSION['webShortname'] = $this->get('username');
612
                    $_SESSION['webFullname'] = $this->get('fullname');
613
                    $_SESSION['webEmail'] = $this->get('email');
614
                    $_SESSION['webValidated'] = 1;
615
                    $_SESSION['webInternalKey'] = $this->getID();
616
                    $_SESSION['webValid'] = base64_encode($this->get('password'));
617
                    $_SESSION['webUser'] = base64_encode($this->get('username'));
618
                    $_SESSION['webFailedlogins'] = $this->get('failedlogincount');
619
                    $_SESSION['webLastlogin'] = $this->get('lastlogin');
620
                    $_SESSION['webnrlogins'] = $this->get('logincount');
621
                    $_SESSION['webUsrConfigSet'] = array();
622
                    $_SESSION['webUserGroupNames'] = $this->getUserGroups();
623
                    $_SESSION['webDocgroups'] = $this->getDocumentGroups();
624
                    if (! empty($remember)) {
625
                        $this->setAutoLoginCookie($cookieName, $remember);
626
                    }
627
                }
628
                break;
629
            case 'destroy':
630
                unset($_SESSION['webShortname']);
631
                unset($_SESSION['webFullname']);
632
                unset($_SESSION['webEmail']);
633
                unset($_SESSION['webValidated']);
634
                unset($_SESSION['webInternalKey']);
635
                unset($_SESSION['webValid']);
636
                unset($_SESSION['webUser']);
637
                unset($_SESSION['webFailedlogins']);
638
                unset($_SESSION['webLastlogin']);
639
                unset($_SESSION['webnrlogins']);
640
                unset($_SESSION['webUsrConfigSet']);
641
                unset($_SESSION['webUserGroupNames']);
642
                unset($_SESSION['webDocgroups']);
643
644
                setcookie($cookieName, '', time() - 60, MODX_BASE_URL);
645
                break;
646
        }
647
648
        return $this;
649
    }
650
651
    /**
652
     * @return bool
653
     */
654
    public function isSecure()
655
    {
656
        $out = strpos(MODX_SITE_URL, 'https') === 0;
657
658
        return $out;
659
    }
660
661
    /**
662
     * @param $cookieName
663
     * @param bool|integer $remember
664
     * @return $this
665
     */
666
    public function setAutoLoginCookie($cookieName, $remember = true)
667
    {
668
        if (! empty($cookieName) && $this->getID() !== null) {
669
            $secure = $this->isSecure();
670
            $remember = is_bool($remember) ? $this->getRememberTime() : (int)$remember;
671
            $cookieValue = array(md5($this->get('username')), $this->get('password'), $this->get('sessionid'), $remember);
672
            $cookieValue = implode('|', $cookieValue);
673
            $cookieExpires = time() + $remember;
674
            setcookie($cookieName, $cookieValue, $cookieExpires, MODX_BASE_URL, '', $secure, true);
675
        }
676
677
        return $this;
678
    }
679
680
    /**
681
     * @param int $userID
682
     * @return array
683
     */
684
    public function getDocumentGroups($userID = 0)
685
    {
686
        $out = array();
687
        $user = $this->switchObject($userID);
688
        if (null !== $user->getID()) {
689
            $web_groups = $this->modx->getFullTableName('web_groups');
690
            $webgroup_access = $this->modx->getFullTableName('webgroup_access');
691
692
            $sql = "SELECT `uga`.`documentgroup` FROM {$web_groups} as `ug`
693
                INNER JOIN {$webgroup_access} as `uga` ON `uga`.`webgroup`=`ug`.`webgroup`
694
                WHERE `ug`.`webuser` = " . $user->getID();
695
            $out = $this->modx->db->getColumn('documentgroup', $this->query($sql));
696
        }
697
        unset($user);
698
699
        return $out;
700
    }
701
702
    /**
703
     * @param int $userID
704
     * @return array
705
     */
706
    public function getUserGroups($userID = 0)
707
    {
708
        $out = array();
709
        $user = $this->switchObject($userID);
710
        if (null !== $user->getID()) {
711
            $web_groups = $this->makeTable('web_groups');
712
            $webgroup_names = $this->makeTable('webgroup_names');
713
714
            $rs = $this->query("SELECT `ug`.`webgroup`, `ugn`.`name` FROM {$web_groups} as `ug`
715
                INNER JOIN {$webgroup_names} as `ugn` ON `ugn`.`id`=`ug`.`webgroup`
716
                WHERE `ug`.`webuser` = " . $user->getID());
717
            while ($row = $this->modx->db->getRow($rs)) {
718
                $out[$row['webgroup']] = $row['name'];
719
            }
720
        }
721
        unset($user);
722
723
        return $out;
724
    }
725
    
726
    /**
727
     * @param  int  $userID
728
     * @param  array  $groupNames
729
     * @return $this
730
     */
731
    public function setUserGroupsByName($userID = 0, $groupNames = array()) 
732
    {
733
        if (!is_array($groupNames)) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after NOT operator; 0 found
Loading history...
introduced by
The condition is_array($groupNames) is always true.
Loading history...
734
            return $this;
735
        }
736
        
737
        if (empty($this->groups)) {
738
            $q = $this->query("SELECT `id`,`name` FROM {$this->makeTable('webgroup_names')}");
739
            while ($row = $this->modx->db->getRow($q)) {
740
                $this->groups[$row['name']] = $row['id'];
741
            }
742
        }
743
        $groupIds = [];
744
        foreach ($groupNames as $group) {
745
            $groupIds[] = $this->groups[$group];
746
        }
747
        
748
        return $this->setUserGroups($userID, $groupIds);
749
    }
750
751
    /**
752
     * @param int $userID
753
     * @param array $groupIds
754
     * @return $this
755
     */
756
    public function setUserGroups($userID = 0, $groupIds = array())
757
    {
758
        if (!is_array($groupIds)) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after NOT operator; 0 found
Loading history...
introduced by
The condition is_array($groupIds) is always true.
Loading history...
759
            return $this;
760
        }
761
        if ($this->newDoc && $userID == 0) {
762
            $this->groupIds = $groupIds;
763
        } else {
764
            $user = $this->switchObject($userID);
765
            if ($uid = $user->getID()) {
766
                foreach ($groupIds as $gid) {
767
                    $this->query("REPLACE INTO {$this->makeTable('web_groups')} (`webgroup`, `webuser`) VALUES ('{$gid}', '{$uid}')");
768
                }
769
                if (! $this->newDoc) {
770
                    $groupIds = empty($groupIds) ? '0' : implode(',', $groupIds);
771
                    $this->query("DELETE FROM {$this->makeTable('web_groups')} WHERE `webuser`={$uid} AND `webgroup` NOT IN ({$groupIds})");
772
                }
773
            }
774
            unset($user);
775
            $this->groupIds = array();
776
        }
777
778
        return $this;
779
    }
780
}
781