Completed
Push — master ( 671ffe...9db278 )
by
unknown
02:15
created

modUsers::editQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 2
dl 0
loc 8
rs 9.4285
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' => '',
15
            'password' => '',
16
            'cachepwd' => ''
17
        ),
18
        'attribute' => array(
19
            'fullname'         => '',
20
            'role'             => '',
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
        ),
45
        'hidden'    => array(
46
            'internalKey'
47
        )
48
    );
49
50
    /**
51
     * @var string
52
     */
53
    protected $givenPassword = '';
54
    protected $groupIds = array();
55
56
    /**
57
     * @param $key
58
     * @return bool
59
     */
60
    public function issetField($key)
61
    {
62
        return (array_key_exists($key, $this->default_field['user']) || array_key_exists($key,
63
                $this->default_field['attribute']) || in_array($key, $this->default_field['hidden']));
64
    }
65
66
    /**
67
     * @param string $data
68
     * @return string|false
69
     */
70
    protected function findUser($data)
71
    {
72
        switch (true) {
73
            case (is_int($data) || ((int)$data > 0 && (string)intval($data) === $data)):
74
                $find = 'attribute.internalKey';
75
                break;
76
            case filter_var($data, FILTER_VALIDATE_EMAIL):
77
                $find = 'attribute.email';
78
                break;
79
            case is_scalar($data):
80
                $find = 'user.username';
81
                break;
82
            default:
83
                $find = false;
84
        }
85
86
        return $find;
87
    }
88
89
    /**
90
     * @param array $data
91
     * @return $this
92
     */
93
    public function create($data = array())
94
    {
95
        parent::create($data);
96
        $this->set('createdon', time());
97
98
        return $this;
99
    }
100
101
    /**
102
     * @param $id
103
     * @return $this
104
     */
105
    public function edit($id)
106
    {
107
        $id = is_scalar($id) ? trim($id) : '';
108
        if ($this->getID() != $id) {
109
            $this->close();
110
            $this->newDoc = false;
111
112
            if (!$find = $this->findUser($id)) {
113
                $this->id = null;
114
            } else {
115
                $this->set('editedon', time());
116
                $this->editQuery($find, $id);
117
                $this->id = empty($this->field['internalKey']) ? null : $this->get('internalKey');
118
                $this->store($this->toArray());
119
                unset($this->field['id']);
120
                unset($this->field['internalKey']);
121
            }
122
        }
123
124
        return $this;
125
    }
126
127
    /**
128
     * @param string $find
129
     * @param string $id
130
     */
131
    protected function editQuery($find, $id) {
132
        $result = $this->query("
133
            SELECT * from {$this->makeTable('web_user_attributes')} as attribute
134
            LEFT JOIN {$this->makeTable('web_users')} as user ON user.id=attribute.internalKey
135
            WHERE BINARY {$find}='{$this->escape($id)}'
136
        ");
137
        $this->field = $this->modx->db->getRow($result);
138
    }
139
140
    /**
141
     * @param string $key
142
     * @param $value
143
     * @return $this
144
     */
145
    public function set($key, $value)
146
    {
147
        if (is_scalar($value) && is_scalar($key) && !empty($key)) {
148
            switch ($key) {
149
                case 'password':
150
                    $this->givenPassword = $value;
151
                    $value = $this->getPassword($value);
152
                    break;
153
                case 'sessionid':
154
                    session_regenerate_id(false);
155
                    $value = session_id();
156
                    if ($mid = $this->modx->getLoginUserID('mgr')) {
157
                        $this->modx->db->query("UPDATE {$this->makeTable('active_user_locks')} SET `sid`='{$value}' WHERE `internalKey`={$mid}");
158
                        $this->modx->db->query("UPDATE {$this->makeTable('active_user_sessions')} SET `sid`='{$value}' WHERE `internalKey`={$mid}");
159
                        $this->modx->db->query("UPDATE {$this->makeTable('active_users')} SET `sid`='{$value}' WHERE `internalKey`={$mid}");
160
                    }
161
                    break;
162
                case 'editedon':
163
                case 'createdon':
164
                    $value = $this->getTime($value);
165
                    break;
166
            }
167
            $this->field[$key] = $value;
168
        }
169
170
        return $this;
171
    }
172
173
    /**
174
     * @param $pass
175
     * @return string
176
     */
177
    public function getPassword($pass)
178
    {
179
        return md5($pass);
180
    }
181
182
    /**
183
     * @param bool $fire_events
184
     * @param bool $clearCache
185
     * @return bool|int|null|void
186
     */
187
    public function save($fire_events = false, $clearCache = false)
188
    {
189
        if ($this->get('email') == '' || $this->get('username') == '' || $this->get('password') == '') {
190
            $this->log['EmptyPKField'] = 'Email, username or password is empty <pre>' . print_r($this->toArray(),
191
                    true) . '</pre>';
192
193
            return false;
194
        }
195
196
        if (!$this->checkUnique('web_users', 'username')) {
197
            $this->log['UniqueUsername'] = 'username not unique <pre>' . print_r($this->get('username'),
198
                    true) . '</pre>';
199
200
            return false;
201
        }
202
203
        if (!$this->checkUnique('web_user_attributes', 'email', 'internalKey')) {
204
            $this->log['UniqueEmail'] = 'Email not unique <pre>' . print_r($this->get('email'), true) . '</pre>';
205
206
            return false;
207
        }
208
        $this->set('sessionid', '');
209
        $fld = $this->toArray();
210
        foreach ($this->default_field['user'] as $key => $value) {
211
            $tmp = $this->get($key);
212
            if ($this->newDoc && (!is_int($tmp) && $tmp == '')) {
213
                $this->field[$key] = $value;
214
            }
215
            $this->Uset($key, 'user');
216
            unset($fld[$key]);
217
        }
218
        if (!empty($this->set['user'])) {
219
            if ($this->newDoc) {
220
                $SQL = "INSERT into {$this->makeTable('web_users')} SET " . implode(', ', $this->set['user']);
221
            } else {
222
                $SQL = "UPDATE {$this->makeTable('web_users')} SET " . implode(', ',
223
                        $this->set['user']) . " WHERE id = " . $this->id;
224
            }
225
            $this->query($SQL);
226
        }
227
228
        if ($this->newDoc) {
229
            $this->id = $this->modx->db->getInsertId();
230
        }
231
232
        $this->saveQuery($fld);
233
        unset($fld['id']);
234
235
        foreach ($fld as $key => $value) {
236
            if ($value == '' || !$this->isChanged($key)) {
237
                continue;
238
            }
239
            $result = $this->query("SELECT `setting_value` FROM {$this->makeTable('web_user_settings')} WHERE `webuser` = '{$this->id}' AND `setting_name` = '{$key}'");
240
            if ($this->modx->db->getRecordCount($result) > 0) {
241
                $this->query("UPDATE {$this->makeTable('web_user_settings')} SET `setting_value` = '{$value}' WHERE `webuser` = '{$this->id}' AND `setting_name` = '{$key}';");
242
            } else {
243
                $this->query("INSERT into {$this->makeTable('web_user_settings')} SET `webuser` = {$this->id},`setting_name` = '{$key}',`setting_value` = '{$value}';");
244
            }
245
        }
246
        if (!$this->newDoc && $this->givenPassword) {
247
            $this->invokeEvent('OnWebChangePassword', array(
248
                'userObj'      => $this,
249
                'userid'       => $this->id,
250
                'user'         => $this->toArray(),
251
                'userpassword' => $this->givenPassword,
252
                'internalKey'  => $this->id,
253
                'username'     => $this->get('username')
254
            ), $fire_events);
255
        }
256
        
257
        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...
258
        
259
        $this->invokeEvent('OnWebSaveUser', array(
260
            'userObj' => $this,
261
            'mode'    => $this->newDoc ? "new" : "upd",
262
            'id'      => $this->id,
263
            'user'    => $this->toArray()
264
        ), $fire_events);
265
266
        if ($clearCache) {
267
            $this->clearCache($fire_events);
268
        }
269
270
        return $this->id;
271
    }
272
273
    /**
274
     * @param  array  $fld 
275
     */
276
    protected function saveQuery(array &$fld) {
277
        foreach ($this->default_field['attribute'] as $key => $value) {
278
            $tmp = $this->get($key);
279
            if ($this->newDoc && (!is_int($tmp) && $tmp == '')) {
280
                $this->field[$key] = $value;
281
            }
282
            $this->Uset($key, 'attribute');
283
            unset($fld[$key]);
284
        }
285
        if (!empty($this->set['attribute'])) {
286
            if ($this->newDoc) {
287
                $this->set('internalKey', $this->id)->Uset('internalKey', 'attribute');
288
                $SQL = "INSERT into {$this->makeTable('web_user_attributes')} SET " . implode(', ',
289
                        $this->set['attribute']);
290
            } else {
291
                $SQL = "UPDATE {$this->makeTable('web_user_attributes')} SET " . implode(', ',
292
                        $this->set['attribute']) . " WHERE  internalKey = " . $this->getID();
293
            }
294
            $this->query($SQL);
295
        }
296
    }
297
298
    /**
299
     * @param $ids
300
     * @param bool $fire_events
301
     * @return bool|null|void
302
     */
303
    public function delete($ids, $fire_events = false)
304
    {
305
        if ($this->edit($ids)) {
306
            $flag = $this->deleteQuery();
307
            $this->query("DELETE FROM {$this->makeTable('web_user_settings')} WHERE webuser='{$this->getID()}'");
308
            $this->query("DELETE FROM {$this->makeTable('web_groups')} WHERE webuser='{$this->getID()}'");
309
            $this->invokeEvent('OnWebDeleteUser', array(
310
                'userObj'     => $this,
311
                'userid'      => $this->getID(),
312
                'internalKey' => $this->getID(),
313
                'username'    => $this->get('username'),
314
                'timestamp'   => time()
315
            ), $fire_events);
316
        } else {
317
            $flag = false;
318
        }
319
        $this->close();
320
321
        return $flag;
322
    }
323
324
    protected function deleteQuery() {
325
        return $this->query("
326
          DELETE user,attribute FROM {$this->makeTable('web_user_attributes')} as attribute
327
            LEFT JOIN {$this->makeTable('web_users')} as user ON user.id=attribute.internalKey
328
            WHERE attribute.internalKey='{$this->escape($this->getID())}'");
329
    }
330
331
    /**
332
     * @param int $id
333
     * @param bool $fulltime
334
     * @param string $cookieName
335
     * @param bool $fire_events
336
     * @return bool
337
     */
338
    public function authUser($id = 0, $fulltime = true, $cookieName = 'WebLoginPE', $fire_events = false)
339
    {
340
        $flag = false;
341
        if (null === $this->getID() && $id) {
342
            $this->edit($id);
343
        }
344
        if (null !== $this->getID()) {
345
            $flag = true;
346
            $this->save(false);
347
            $this->SessionHandler('start', $cookieName, $fulltime);
348
            $this->invokeEvent("OnWebLogin", array(
349
                'userObj'      => $this,
350
                'userid'       => $this->getID(),
351
                'username'     => $this->get('username'),
352
                'userpassword' => $this->givenPassword,
353
                'rememberme'   => $fulltime
354
            ), $fire_events);
355
        }
356
357
        return $flag;
358
    }
359
360
    /**
361
     * @param int $id
362
     * @return bool
363
     */
364
    public function checkBlock($id = 0)
365
    {
366
        $tmp = clone $this;
367
        if ($id && $tmp->getID() != $id) {
368
            $tmp->edit($id);
369
        }
370
        $now = time();
371
372
        $b = $tmp->get('blocked');
373
        $bu = $tmp->get('blockeduntil');
374
        $ba = $tmp->get('blockedafter');
375
        $flag = (($b && !$bu && !$ba) || ($bu && $now < $bu) || ($ba && $now > $ba));
376
        unset($tmp);
377
378
        return $flag;
379
    }
380
381
    /**
382
     * @param $id
383
     * @param $password
384
     * @param $blocker
385
     * @param bool $fire_events
386
     * @return bool
387
     */
388
    public function testAuth($id, $password, $blocker, $fire_events = false)
389
    {
390
        $tmp = clone $this;
391
        if ($id && $tmp->getID() != $id) {
392
            $tmp->edit($id);
393
        }
394
395
        $flag = $pluginFlag = false;
396
        if (
397
            (null !== $tmp->getID()) && (!$blocker || ($blocker && !$tmp->checkBlock($id)))
398
        ) {
399
            $eventResult = $this->getInvokeEventResult('OnWebAuthentication', array(
400
                'userObj'       => $this,
401
                'userid'        => $tmp->getID(),
402
                'username'      => $tmp->get('username'),
403
                'userpassword'  => $password,
404
                'savedpassword' => $tmp->get('password')
405
            ), $fire_events);
406
            if (is_array($eventResult)) {
407
                foreach ($eventResult as $result) {
408
                    $pluginFlag = (bool)$result;
409
                }
410
            } else {
411
                $pluginFlag = (bool)$eventResult;
412
            }
413
            if (!$pluginFlag) {
414
                $flag = ($tmp->get('password') == $tmp->getPassword($password));
415
            }
416
        }
417
        unset($tmp);
418
419
        return $flag || $pluginFlag;
420
    }
421
422
    /**
423
     * @param bool $fulltime
424
     * @param string $cookieName
425
     * @return bool
426
     */
427
    public function AutoLogin($fulltime = true, $cookieName = 'WebLoginPE', $fire_events = null)
428
    {
429
        $flag = false;
430
        if (isset($_COOKIE[$cookieName])) {
431
            $cookie = explode('|', $_COOKIE[$cookieName], 4);
432
            if (isset($cookie[0], $cookie[1], $cookie[2]) && strlen($cookie[0]) == 32 && strlen($cookie[1]) == 32) {
433
                if (!$fulltime && isset($cookie[4])) {
434
                    $fulltime = (int)$cookie[4];
435
                }
436
                $this->close();
437
                $q = $this->modx->db->query("SELECT id FROM " . $this->makeTable('web_users') . " WHERE md5(username)='{$this->escape($cookie[0])}'");
438
                $id = $this->modx->db->getValue($q);
439
                if (
440
                    $this->edit($id) 
441
                    && null !== $this->getID() 
442
                    && $this->get('password') == $cookie[1] 
443
                    && $this->get('sessionid') == $cookie[2] 
444
                    && !$this->checkBlock($this->getID())
445
                ) {
446
                    $flag = $this->authUser($this->getID(), $fulltime, $cookieName, $fire_events);
0 ignored issues
show
Bug introduced by
It seems like $fulltime defined by (int) $cookie[4] on line 434 can also be of type integer; however, modUsers::authUser() does only seem to accept boolean, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
447
448
                }
449
            }
450
        }
451
452
        return $flag;
453
    }
454
455
    /**
456
     * @param string $cookieName
457
     * @param null $fire_events
458
     */
459
    public function logOut($cookieName = 'WebLoginPE', $fire_events = null)
460
    {
461
        if (!$uid = $this->modx->getLoginUserID('web')) {
462
            return;
463
        }
464
        $params = array(
465
            'username'    => $_SESSION['webShortname'],
466
            'internalKey' => $uid,
467
            'userid'      => $uid // Bugfix by TS
468
        );
469
        $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...
470
        $this->SessionHandler('destroy', $cookieName ? $cookieName : 'WebLoginPE');
471
        $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...
472
    }
473
474
    /**
475
     * SessionHandler
476
     * Starts the user session on login success. Destroys session on error or logout.
477
     *
478
     * @param string $directive ('start' or 'destroy')
479
     * @param string $cookieName
480
     * @return modUsers
481
     * @author Raymond Irving
482
     * @author Scotty Delicious
483
     *
484
     * remeber может быть числом в секундах
485
     */
486
    protected function SessionHandler($directive, $cookieName, $remember = true)
487
    {
488
        switch ($directive) {
489
            case 'start':
490
                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...
491
                    $_SESSION['webShortname'] = $this->get('username');
492
                    $_SESSION['webFullname'] = $this->get('fullname');
493
                    $_SESSION['webEmail'] = $this->get('email');
494
                    $_SESSION['webValidated'] = 1;
495
                    $_SESSION['webInternalKey'] = $this->getID();
496
                    $_SESSION['webValid'] = base64_encode($this->get('password'));
497
                    $_SESSION['webUser'] = base64_encode($this->get('username'));
498
                    $_SESSION['webFailedlogins'] = $this->get('failedlogincount');
499
                    $_SESSION['webLastlogin'] = $this->get('lastlogin');
500
                    $_SESSION['webnrlogins'] = $this->get('logincount');
501
                    $_SESSION['webUsrConfigSet'] = array();
502
                    $_SESSION['webUserGroupNames'] = $this->getUserGroups();
503
                    $_SESSION['webDocgroups'] = $this->getDocumentGroups();
504
                    if ($remember) {
505
                        $this->setAutoLoginCookie($cookieName, $remember);
506
                    }
507
                }
508
                break;
509
            case 'destroy':
510
                if (isset($_SESSION['mgrValidated'])) {
511
                    unset($_SESSION['webShortname']);
512
                    unset($_SESSION['webFullname']);
513
                    unset($_SESSION['webEmail']);
514
                    unset($_SESSION['webValidated']);
515
                    unset($_SESSION['webInternalKey']);
516
                    unset($_SESSION['webValid']);
517
                    unset($_SESSION['webUser']);
518
                    unset($_SESSION['webFailedlogins']);
519
                    unset($_SESSION['webLastlogin']);
520
                    unset($_SESSION['webnrlogins']);
521
                    unset($_SESSION['webUsrConfigSet']);
522
                    unset($_SESSION['webUserGroupNames']);
523
                    unset($_SESSION['webDocgroups']);
524
525
                    setcookie($cookieName, '', time() - 60, MODX_BASE_URL);
526
                } else {
527
                    if (isset($_COOKIE[session_name()])) {
528
                        setcookie(session_name(), '', time() - 60, MODX_BASE_URL);
529
                    }
530
                    setcookie($cookieName, '', time() - 60, MODX_BASE_URL);
531
                    session_destroy();
532
                }
533
                break;
534
        }
535
536
        return $this;
537
    }
538
539
    /**
540
     * @return bool
541
     */
542
    public function isSecure()
543
    {
544
        $out = $this->modxConfig('server_protocol') == 'http' ? false : true;
545
546
        return $out;
547
    }
548
549
    /**
550
     * @param $cookieName
551
     * @param bool $remember
552
     * @return $this
553
     */
554
    public function setAutoLoginCookie($cookieName, $remember = true)
555
    {
556
        if (!empty($cookieName) && $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...
557
            $secure = $this->isSecure();
558
            $remember = is_bool($remember) ? (60 * 60 * 24 * 365 * 5) : (int)$remember;
559
            $cookieValue = array(md5($this->get('username')), $this->get('password'), $this->get('sessionid'), $remember);
560
            $cookieValue = implode('|', $cookieValue);
561
            $cookieExpires = time() + $remember;
562
            setcookie($cookieName, $cookieValue, $cookieExpires, MODX_BASE_URL, '', $secure, true);
563
        }
564
565
        return $this;
566
    }
567
568
    /**
569
     * @param int $userID
570
     * @return array
571
     */
572
    public function getDocumentGroups($userID = 0)
573
    {
574
        $out = array();
575
        $user = $this->switchObject($userID);
576
        if (null !== $user->getID()) {
577
            $web_groups = $this->modx->getFullTableName('web_groups');
578
            $webgroup_access = $this->modx->getFullTableName('webgroup_access');
579
580
            $sql = "SELECT `uga`.`documentgroup` FROM {$web_groups} as `ug`
581
                INNER JOIN {$webgroup_access} as `uga` ON `uga`.`webgroup`=`ug`.`webgroup`
582
                WHERE `ug`.`webuser` = " . $user->getID();
583
            $out = $this->modx->db->getColumn('documentgroup', $this->query($sql));
584
585
        }
586
        unset($user);
587
588
        return $out;
589
    }
590
591
    /**
592
     * @param int $userID
593
     * @return array
594
     */
595
    public function getUserGroups($userID = 0)
596
    {
597
        $out = array();
598
        $user = $this->switchObject($userID);
599
        if (null !== $user->getID()) {
600
            $web_groups = $this->makeTable('web_groups');
601
            $webgroup_names = $this->makeTable('webgroup_names');
602
603
            $rs = $this->query("SELECT `ug`.`webgroup`, `ugn`.`name` FROM {$web_groups} as `ug`
604
                INNER JOIN {$webgroup_names} as `ugn` ON `ugn`.`id`=`ug`.`webgroup`
605
                WHERE `ug`.`webuser` = " . $user->getID());
606
            while ($row = $this->modx->db->getRow($rs)) {
607
                $out[$row['webgroup']] = $row['name'];
608
            }
609
        }
610
        unset($user);
611
612
        return $out;
613
    }
614
615
    /**
616
     * @param int $userID
617
     * @param array $groupIds
618
     * @return $this
619
     */
620
    public function setUserGroups($userID = 0, $groupIds = array())
621
    {
622
        if (!is_array($groupIds)) return $this;
623
        if ($this->newDoc && $userID == 0) {
624
            $this->groupIds = $groupIds;
625
        } else {
626
            $user = $this->switchObject($userID);
627
            if ($uid = $user->getID()) {
628
                foreach ($groupIds as $gid) {
629
                    $this->query("REPLACE INTO {$this->makeTable('web_groups')} (`webgroup`, `webuser`) VALUES ('{$gid}', '{$uid}')");
630
                }
631
                if (!$this->newDoc) {
632
                    $groupIds = empty($groupIds) ? '0' : implode(',', $groupIds);
633
                    $this->query("DELETE FROM {$this->makeTable('web_groups')} WHERE `webuser`={$uid} AND `webgroup` NOT IN ({$groupIds})");
634
                }
635
            }
636
            unset($user);
637
            $this->groupIds = array();
638
        }
639
640
        return $this;
641
    }
642
}
643