Completed
Push — master ( 56110f...3f5174 )
by
unknown
05:31
created

modUsers::setUserGroups()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 12
nc 4
nop 2
dl 0
loc 18
rs 8.8571
c 0
b 0
f 0
1
<?php
2
require_once('MODx.php');
3
4
/**
5
 * Class modUsers
6
 */
7
class modUsers extends MODxAPI
8
{
9
    /**
10
     * @var array
11
     */
12
    protected $default_field = array(
13
        'user'      => array(
14
            'username' => null,
15
            'password' => null,
16
            'cachepwd' => null
17
        ),
18
        'attribute' => array(
19
            'fullname'         => null,
20
            'role'             => null,
21
            'email'            => null,
22
            'phone'            => null,
23
            'mobilephone'      => null,
24
            'blocked'          => null,
25
            'blockeduntil'     => null,
26
            'blockedafter'     => null,
27
            'logincount'       => null,
28
            'lastlogin'        => null,
29
            'thislogin'        => null,
30
            'failedlogincount' => null,
31
            'sessionid'        => null,
32
            'dob'              => null,
33
            'gender'           => null,
34
            'country'          => null,
35
            'state'            => null,
36
            'city'             => null,
37
            'street'           => null,
38
            'zip'              => null,
39
            'fax'              => null,
40
            'photo'            => null,
41
            'comment'          => null
42
        ),
43
        'hidden'    => array(
44
            'internalKey'
45
        )
46
    );
47
48
    /**
49
     * @var string
50
     */
51
    protected $givenPassword = '';
52
    protected $groupIds = array();
53
54
    /**
55
     * @param $key
56
     * @return bool
57
     */
58
    public function issetField($key)
59
    {
60
        return (array_key_exists($key, $this->default_field['user']) || array_key_exists($key,
61
                $this->default_field['attribute']) || in_array($key, $this->default_field['hidden']));
62
    }
63
64
    /**
65
     * @param string $data
66
     * @return string|false
67
     */
68
    protected function findUser($data)
69
    {
70
        switch (true) {
71
            case (is_int($data) || ((int)$data > 0 && (string)intval($data) === $data)):
72
                $find = 'attribute.internalKey';
73
                break;
74
            case filter_var($data, FILTER_VALIDATE_EMAIL):
75
                $find = 'attribute.email';
76
                break;
77
            case is_scalar($data):
78
                $find = 'user.username';
79
                break;
80
            default:
81
                $find = false;
82
        }
83
84
        return $find;
85
    }
86
87
    /**
88
     * @param $id
89
     * @return $this
90
     */
91
    public function edit($id)
92
    {
93
        $id = is_scalar($id) ? trim($id) : '';
94
        if ($this->getID() != $id) {
95
            $this->close();
96
            $this->newDoc = false;
97
98
            if (!$find = $this->findUser($id)) {
99
                $this->id = null;
100
            } else {
101
                $result = $this->query("
102
                    SELECT * from {$this->makeTable('web_user_attributes')} as attribute
103
                    LEFT JOIN {$this->makeTable('web_users')} as user ON user.id=attribute.internalKey
104
                    WHERE BINARY {$find}='{$this->escape($id)}'
105
                ");
106
                $this->field = $this->modx->db->getRow($result);
107
108
                $this->id = empty($this->field['internalKey']) ? null : $this->get('internalKey');
109
                $this->store($this->toArray());
110
                unset($this->field['id']);
111
                unset($this->field['internalKey']);
112
            }
113
        }
114
115
        return $this;
116
    }
117
118
    /**
119
     * @param string $key
120
     * @param $value
121
     * @return $this
122
     */
123
    public function set($key, $value)
124
    {
125
        if (is_scalar($value) && is_scalar($key) && !empty($key)) {
126
            switch ($key) {
127
                case 'password':
128
                    $this->givenPassword = $value;
129
                    $value = $this->getPassword($value);
130
                    break;
131
                case 'sessionid':
132
                    session_regenerate_id(false);
133
                    $value = session_id();
134
                    break;
135
            }
136
            $this->field[$key] = $value;
137
        }
138
139
        return $this;
140
    }
141
142
    /**
143
     * @param $pass
144
     * @return string
145
     */
146
    public function getPassword($pass)
147
    {
148
        return md5($pass);
149
    }
150
151
    /**
152
     * @param bool $fire_events
153
     * @param bool $clearCache
154
     * @return bool|int|null|void
155
     */
156
    public function save($fire_events = false, $clearCache = false)
157
    {
158
        if ($this->get('email') == '' || $this->get('username') == '' || $this->get('password') == '') {
159
            $this->log['EmptyPKField'] = 'Email, username or password is empty <pre>' . print_r($this->toArray(),
160
                    true) . '</pre>';
161
162
            return false;
163
        }
164
165
        if (!$this->checkUnique('web_users', 'username')) {
166
            $this->log['UniqueUsername'] = 'username not unique <pre>' . print_r($this->get('username'),
167
                    true) . '</pre>';
168
169
            return false;
170
        }
171
172
        if (!$this->checkUnique('web_user_attributes', 'email', 'internalKey')) {
173
            $this->log['UniqueEmail'] = 'Email not unique <pre>' . print_r($this->get('email'), true) . '</pre>';
174
175
            return false;
176
        }
177
        $this->set('sessionid', '');
178
        $fld = $this->toArray();
179
        foreach ($this->default_field['user'] as $key => $value) {
180
            $tmp = $this->get($key);
181
            if ($this->newDoc && (!is_int($tmp) && $tmp == '')) {
182
                $this->field[$key] = $value;
183
            }
184
            $this->Uset($key, 'user');
185
            unset($fld[$key]);
186
        }
187
        if (!empty($this->set['user'])) {
188
            if ($this->newDoc) {
189
                $SQL = "INSERT into {$this->makeTable('web_users')} SET " . implode(', ', $this->set['user']);
190
            } else {
191
                $SQL = "UPDATE {$this->makeTable('web_users')} SET " . implode(', ',
192
                        $this->set['user']) . " WHERE id = " . $this->id;
193
            }
194
            $this->query($SQL);
195
        }
196
197
        if ($this->newDoc) {
198
            $this->id = $this->modx->db->getInsertId();
199
        }
200
201
        foreach ($this->default_field['attribute'] as $key => $value) {
202
            $tmp = $this->get($key);
203
            if ($this->newDoc && (!is_int($tmp) && $tmp == '')) {
204
                $this->field[$key] = $value;
205
            }
206
            $this->Uset($key, 'attribute');
207
            unset($fld[$key]);
208
        }
209
        if (!empty($this->set['attribute'])) {
210
            if ($this->newDoc) {
211
                $this->set('internalKey', $this->id)->Uset('internalKey', 'attribute');
212
                $SQL = "INSERT into {$this->makeTable('web_user_attributes')} SET " . implode(', ',
213
                        $this->set['attribute']);
214
            } else {
215
                $SQL = "UPDATE {$this->makeTable('web_user_attributes')} SET " . implode(', ',
216
                        $this->set['attribute']) . " WHERE  internalKey = " . $this->getID();
217
            }
218
            $this->query($SQL);
219
        }
220
        unset($fld['id']);
221
        foreach ($fld as $key => $value) {
222
            if ($value == '' || !$this->isChanged($key)) {
223
                continue;
224
            }
225
            $result = $this->query("SELECT `setting_value` FROM {$this->makeTable('web_user_settings')} WHERE `webuser` = '{$this->id}' AND `setting_name` = '{$key}'");
226
            if ($this->modx->db->getRecordCount($result) > 0) {
227
                $this->query("UPDATE {$this->makeTable('web_user_settings')} SET `setting_value` = '{$value}' WHERE `webuser` = '{$this->id}' AND `setting_name` = '{$key}';");
228
            } else {
229
                $this->query("INSERT into {$this->makeTable('web_user_settings')} SET `webuser` = {$this->id},`setting_name` = '{$key}',`setting_value` = '{$value}';");
230
            }
231
        }
232
        if (!$this->newDoc && $this->givenPassword) {
233
            $this->invokeEvent('OnWebChangePassword', array(
234
                'userObj'      => $this,
235
                'userid'       => $this->id,
236
                'user'         => $this->toArray(),
237
                'userpassword' => $this->givenPassword,
238
                'internalKey'  => $this->id,
239
                'username'     => $this->get('username')
240
            ), $fire_events);
241
        }
242
        
243
        if ($this->groupIds) $this->setUserGroups($this->id, $this->groupIds);
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->groupIds of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
244
        
245
        $this->invokeEvent('OnWebSaveUser', array(
246
            'userObj' => $this,
247
            'mode'    => $this->newDoc ? "new" : "upd",
248
            'id'      => $this->id,
249
            'user'    => $this->toArray()
250
        ), $fire_events);
251
252
        if ($clearCache) {
253
            $this->clearCache($fire_events);
254
        }
255
256
        return $this->id;
257
    }
258
259
    /**
260
     * @param $ids
261
     * @param bool $fire_events
262
     * @return bool|null|void
263
     */
264
    public function delete($ids, $fire_events = false)
265
    {
266
        if ($this->edit($ids)) {
267
            $flag = $this->query("
268
          DELETE user,attribute FROM {$this->makeTable('web_user_attributes')} as attribute
269
            LEFT JOIN {$this->makeTable('web_users')} as user ON user.id=attribute.internalKey
270
            WHERE attribute.internalKey='{$this->escape($this->getID())}'");
271
            $this->query("DELETE FROM {$this->makeTable('web_user_settings')} WHERE webuser='{$this->getID()}'");
272
            $this->query("DELETE FROM {$this->makeTable('web_groups')} WHERE webuser='{$this->getID()}'");
273
            $this->invokeEvent('OnWebDeleteUser', array(
274
                'userObj'     => $this,
275
                'userid'      => $this->getID(),
276
                'internalKey' => $this->getID(),
277
                'username'    => $this->get('username'),
278
                'timestamp'   => time()
279
            ), $fire_events);
280
        } else {
281
            $flag = false;
282
        }
283
        $this->close();
284
285
        return $flag;
286
    }
287
288
    /**
289
     * @param int $id
290
     * @param bool $fulltime
291
     * @param string $cookieName
292
     * @param bool $fire_events
293
     * @return bool
294
     */
295
    public function authUser($id = 0, $fulltime = true, $cookieName = 'WebLoginPE', $fire_events = false)
296
    {
297
        $flag = false;
298
        if (null === $this->getID() && $id) {
299
            $this->edit($id);
300
        }
301
        if (null !== $this->getID()) {
302
            $flag = true;
303
            $this->save(false);
304
            $this->SessionHandler('start', $cookieName, $fulltime);
305
            $this->invokeEvent("OnWebLogin", array(
306
                'userObj'      => $this,
307
                'userid'       => $this->getID(),
308
                'username'     => $this->get('username'),
309
                'userpassword' => $this->givenPassword,
310
                'rememberme'   => $fulltime
311
            ), $fire_events);
312
        }
313
314
        return $flag;
315
    }
316
317
    /**
318
     * @param int $id
319
     * @return bool
320
     */
321
    public function checkBlock($id = 0)
322
    {
323
        $tmp = clone $this;
324
        if ($id && $tmp->getID() != $id) {
325
            $tmp->edit($id);
326
        }
327
        $now = time();
328
329
        $b = $tmp->get('blocked');
330
        $bu = $tmp->get('blockeduntil');
331
        $ba = $tmp->get('blockedafter');
332
        $flag = (($b && !$bu && !$ba) || ($bu && $now < $bu) || ($ba && $now > $ba));
333
        unset($tmp);
334
335
        return $flag;
336
    }
337
338
    /**
339
     * @param $id
340
     * @param $password
341
     * @param $blocker
342
     * @param bool $fire_events
343
     * @return bool
344
     */
345
    public function testAuth($id, $password, $blocker, $fire_events = false)
346
    {
347
        $tmp = clone $this;
348
        if ($id && $tmp->getID() != $id) {
349
            $tmp->edit($id);
350
        }
351
352
        $flag = $pluginFlag = false;
353
        if (
354
            (null !== $tmp->getID()) && (!$blocker || ($blocker && !$tmp->checkBlock($id)))
355
        ) {
356
            $eventResult = $this->getInvokeEventResult('OnWebAuthentication', array(
357
                'userObj'       => $this,
358
                'userid'        => $tmp->getID(),
359
                'username'      => $tmp->get('username'),
360
                'userpassword'  => $password,
361
                'savedpassword' => $tmp->get('password')
362
            ), $fire_events);
363
            if (is_array($eventResult)) {
364
                foreach ($eventResult as $result) {
365
                    $pluginFlag = (bool)$result;
366
                }
367
            } else {
368
                $pluginFlag = (bool)$eventResult;
369
            }
370
            if (!$pluginFlag) {
371
                $flag = ($tmp->get('password') == $tmp->getPassword($password));
372
            }
373
        }
374
        unset($tmp);
375
376
        return $flag || $pluginFlag;
377
    }
378
379
    /**
380
     * @param bool $fulltime
381
     * @param string $cookieName
382
     * @return bool
383
     */
384
    public function AutoLogin($fulltime = true, $cookieName = 'WebLoginPE', $fire_events = null)
385
    {
386
        $flag = false;
387
        if (isset($_COOKIE[$cookieName])) {
388
            $cookie = explode('|', $_COOKIE[$cookieName], 3);
389
            if (isset($cookie[0], $cookie[1], $cookie[2]) && strlen($cookie[0]) == 32 && strlen($cookie[1]) == 32) {
390
                $this->close();
391
                $q = $this->modx->db->query("SELECT id FROM " . $this->makeTable('web_users') . " WHERE md5(username)='{$this->escape($cookie[0])}'");
392
                $id = $this->modx->db->getValue($q);
393
                if ($this->edit($id) && null !== $this->getID() && $this->get('password') == $cookie[1] && $this->get('sessionid') == $cookie[2] && $this->testAuth($this->getID(),
394
                        $cookie[1], true)
395
                ) {
396
                    $flag = $this->authUser($this->getID(), $fulltime, $cookieName, $fire_events);
397
398
                }
399
            }
400
        }
401
402
        return $flag;
403
    }
404
405
    /**
406
     * @param string $cookieName
407
     * @param null $fire_events
408
     */
409
    public function logOut($cookieName = 'WebLoginPE', $fire_events = null)
410
    {
411
        if (!$uid = $this->modx->getLoginUserID('web')) {
412
            return;
413
        }
414
        $params = array(
415
            'username'    => $_SESSION['webShortname'],
416
            'internalKey' => $uid,
417
            'userid'      => $uid // Bugfix by TS
418
        );
419
        $this->invokeEvent('OnBeforeWebLogout', $params, $fire_events);
0 ignored issues
show
Documentation introduced by
$fire_events is of type null, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
420
        $this->SessionHandler('destroy', $cookieName ? $cookieName : 'WebLoginPE');
421
        $this->invokeEvent('OnWebLogout', $params, $fire_events);
0 ignored issues
show
Documentation introduced by
$fire_events is of type null, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
422
    }
423
424
    /**
425
     * SessionHandler
426
     * Starts the user session on login success. Destroys session on error or logout.
427
     *
428
     * @param string $directive ('start' or 'destroy')
429
     * @param string $cookieName
430
     * @return modUsers
431
     * @author Raymond Irving
432
     * @author Scotty Delicious
433
     *
434
     * remeber может быть числом в секундах
435
     */
436
    protected function SessionHandler($directive, $cookieName, $remember = true)
437
    {
438
        switch ($directive) {
439
            case 'start':
440
                if ($this->getID()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->getID() of type null|integer is loosely compared to true; this is ambiguous if the integer can be zero. 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...
441
                    $_SESSION['webShortname'] = $this->get('username');
442
                    $_SESSION['webFullname'] = $this->get('fullname');
443
                    $_SESSION['webEmail'] = $this->get('email');
444
                    $_SESSION['webValidated'] = 1;
445
                    $_SESSION['webInternalKey'] = $this->getID();
446
                    $_SESSION['webValid'] = base64_encode($this->get('password'));
447
                    $_SESSION['webUser'] = base64_encode($this->get('username'));
448
                    $_SESSION['webFailedlogins'] = $this->get('failedlogincount');
449
                    $_SESSION['webLastlogin'] = $this->get('lastlogin');
450
                    $_SESSION['webnrlogins'] = $this->get('logincount');
451
                    $_SESSION['webUsrConfigSet'] = array();
452
                    $_SESSION['webUserGroupNames'] = $this->getUserGroups();
453
                    $_SESSION['webDocgroups'] = $this->getDocumentGroups();
454
                    if ($remember) {
455
                        $this->setAutoLoginCookie($cookieName, $remember);
456
                    }
457
                }
458
                break;
459
            case 'destroy':
460
                if (isset($_SESSION['mgrValidated'])) {
461
                    unset($_SESSION['webShortname']);
462
                    unset($_SESSION['webFullname']);
463
                    unset($_SESSION['webEmail']);
464
                    unset($_SESSION['webValidated']);
465
                    unset($_SESSION['webInternalKey']);
466
                    unset($_SESSION['webValid']);
467
                    unset($_SESSION['webUser']);
468
                    unset($_SESSION['webFailedlogins']);
469
                    unset($_SESSION['webLastlogin']);
470
                    unset($_SESSION['webnrlogins']);
471
                    unset($_SESSION['webUsrConfigSet']);
472
                    unset($_SESSION['webUserGroupNames']);
473
                    unset($_SESSION['webDocgroups']);
474
475
                    setcookie($cookieName, '', time() - 60, '/');
476
                } else {
477
                    if (isset($_COOKIE[session_name()])) {
478
                        setcookie(session_name(), '', time() - 60, '/');
479
                    }
480
                    setcookie($cookieName, '', time() - 60, '/');
481
                    session_destroy();
482
                }
483
                break;
484
        }
485
486
        return $this;
487
    }
488
489
    /**
490
     * @return bool
491
     */
492
    public function isSecure()
493
    {
494
        $out = $this->modxConfig('server_protocol') == 'http' ? false : true;
495
496
        return $out;
497
    }
498
499
    /**
500
     * @param $cookieName
501
     * @param bool $remember
502
     * @return $this
503
     */
504
    protected function setAutoLoginCookie($cookieName, $remember = true)
505
    {
506
        if (!empty($cookieName)) {
507
            $secure = $this->isSecure();
508
            $cookieValue = array(md5($this->get('username')), $this->get('password'), $this->get('sessionid'));
509
            $cookieValue = implode('|', $cookieValue);
510
            $cookieExpires = time() + (is_bool($remember) ? (60 * 60 * 24 * 365 * 5) : (int)$remember);
511
            setcookie($cookieName, $cookieValue, $cookieExpires, '/', '', $secure, true);
512
        }
513
514
        return $this;
515
    }
516
517
    /**
518
     * @param int $userID
519
     * @return array
520
     */
521
    public function getDocumentGroups($userID = 0)
522
    {
523
        $out = array();
524
        $user = $this->switchObject($userID);
525
        if (null !== $user->getID()) {
526
            $web_groups = $this->modx->getFullTableName('web_groups');
527
            $webgroup_access = $this->modx->getFullTableName('webgroup_access');
528
529
            $sql = "SELECT `uga`.`documentgroup` FROM {$web_groups} as `ug`
530
                INNER JOIN {$webgroup_access} as `uga` ON `uga`.`webgroup`=`ug`.`webgroup`
531
                WHERE `ug`.`webuser` = " . $user->getID();
532
            $out = $this->modx->db->getColumn('documentgroup', $this->query($sql));
533
534
        }
535
        unset($user);
536
537
        return $out;
538
    }
539
540
    /**
541
     * @param int $userID
542
     * @return array
543
     */
544
    public function getUserGroups($userID = 0)
545
    {
546
        $out = array();
547
        $user = $this->switchObject($userID);
548
        if (null !== $user->getID()) {
549
            $web_groups = $this->makeTable('web_groups');
550
            $webgroup_names = $this->makeTable('webgroup_names');
551
552
            $sql = "SELECT `ugn`.`name` FROM {$web_groups} as `ug`
553
                INNER JOIN {$webgroup_names} as `ugn` ON `ugn`.`id`=`ug`.`webgroup`
554
                WHERE `ug`.`webuser` = " . $user->getID();
555
            $out = $this->modx->db->getColumn('name', $this->query($sql));
556
        }
557
        unset($user);
558
559
        return $out;
560
    }
561
562
    /**
563
     * @param int $userID
564
     * @param array $groupIds
565
     * @return $this
566
     */
567
    public function setUserGroups($userID = 0, $groupIds = array())
568
    {
569
        if (!is_array($groupIds)) return $this;
570
        if ($this->newDoc && $userID == 0) {
571
            $this->groupIds = $groupIds;
572
        } else {
573
            $user = $this->switchObject($userID);
574
            if ($uid = $user->getID()) {
575
                foreach ($groupIds as $gid) {
576
                    $this->query("REPLACE INTO {$this->makeTable('web_groups')} (`webgroup`, `webuser`) VALUES ('{$gid}', '{$uid}')");
577
                }
578
            }
579
            unset($user);
580
            $this->groupIds = array();
581
        }
582
583
        return $this;
584
    }
585
}
586