Completed
Push — master ( 3e5347...9f2a0a )
by Agel_Nash
03:13
created

modUsers::setUserGroups()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 6
nc 2
nop 2
dl 0
loc 9
rs 9.2
c 0
b 0
f 0
1
<?php
2
require_once('MODx.php');
3
4
class modUsers extends MODxAPI
5
{
6
7
    protected $default_field = array(
8
        'user' => array(
9
            'username' => null,
10
            'password' => null,
11
            'cachepwd' => null
12
        ),
13
        'attribute' => array(
14
            'fullname' => null,
15
            'role' => null,
16
            'email' => null,
17
            'phone' => null,
18
            'mobilephone' => null,
19
            'blocked' => null,
20
            'blockeduntil' => null,
21
            'blockedafter' => null,
22
            'logincount' => null,
23
            'lastlogin' => null,
24
            'thislogin' => null,
25
            'failedlogincount' => null,
26
            'sessionid' => null,
27
            'dob' => null,
28
            'gender' => null,
29
            'country' => null,
30
            'state' => null,
31
	    'city' => null,
32
            'zip' => null,
33
            'fax' => null,
34
            'photo' => null,
35
            'comment' => null
36
        ),
37
        'hidden' => array(
38
            'internalKey'
39
        )
40
    );
41
42
    protected $givenPassword = '';
43
44
    public function issetField($key)
45
    {
46
        return (array_key_exists($key, $this->default_field['user']) || array_key_exists($key, $this->default_field['attribute']) || in_array($key, $this->default_field['hidden']));
47
    }
48
49
    /**
50
     * @param $data
51
     * @return bool|string
52
     */
53 View Code Duplication
    protected function findUser($data)
54
    {
55
        switch (true) {
56
            case (is_int($data) || ((int)$data > 0 && (string)intval($data) === $data)):
57
                $find = 'attribute.internalKey';
58
                break;
59
            case filter_var($data, FILTER_VALIDATE_EMAIL):
60
                $find = 'attribute.email';
61
                break;
62
            case is_scalar($data):
63
                $find = 'user.username';
64
                break;
65
            default:
66
                $find = false;
67
        }
68
        return $find;
69
    }
70
71
    /**
72
     * @param $id
73
     * @return $this
74
     */
75
    public function edit($id)
76
    {
77
        $id = is_scalar($id) ? trim($id) : '';
78
        if ($this->getID() != $id) {
79
            $this->close();
80
            $this->newDoc = false;
81
82
            if (!$find = $this->findUser($id)) {
83
                $this->id = null;
84
            }else {
85
                $result = $this->query("
86
                    SELECT * from {$this->makeTable('web_user_attributes')} as attribute
87
                    LEFT JOIN {$this->makeTable('web_users')} as user ON user.id=attribute.internalKey
88
                    WHERE BINARY {$find}='{$this->escape($id)}'
89
                ");
90
                $this->field = $this->modx->db->getRow($result);
91
92
                $this->id = empty($this->field['internalKey']) ? null : $this->get('internalKey');
93
                unset($this->field['id']);
94
                unset($this->field['internalKey']);
95
            }
96
        }
97
        return $this;
98
    }
99
100
    /**
101
     * @param $key
102
     * @param $value
103
     * @return $this
104
     */
105
    public function set($key, $value)
106
    {
107
        if (is_scalar($value) && is_scalar($key) && !empty($key)) {
108
            switch ($key) {
109
                case 'password':
110
                    $this->givenPassword = $value;
111
                    $value = $this->getPassword($value);
112
                    break;
113
            }
114
            $this->field[$key] = $value;
115
        }
116
        return $this;
117
    }
118
119
    /**
120
     * @param $pass
121
     * @return string
122
     */
123
    public function getPassword($pass)
124
    {
125
        return md5($pass);
126
    }
127
128
    /**
129
     * @param null $fire_events
130
     * @param bool $clearCache
131
     * @return bool|int|null|void
132
     */
133
    public function save($fire_events = null, $clearCache = false)
134
    {
135
        if ($this->get('email') == '' || $this->get('username') == '' || $this->get('password') == '') {
136
            $this->log['EmptyPKField'] = 'Email, username or password is empty <pre>' . print_r($this->toArray(), true) . '</pre>';
137
            return false;
138
        }
139
140
        if (!$this->checkUnique('web_users', 'username')) {
141
            $this->log['UniqueUsername'] = 'username not unique <pre>' . print_r($this->get('username'), true) . '</pre>';
142
            return false;
143
        }
144
145
        if (!$this->checkUnique('web_user_attributes', 'email', 'internalKey')) {
146
            $this->log['UniqueEmail'] = 'Email not unique <pre>' . print_r($this->get('email'), true) . '</pre>';
147
            return false;
148
        }
149
150
        /*$this->invokeEvent('OnBeforeDocFormSave',array (
151
            "mode" => $this->newDoc ? "new" : "upd",
152
            "id" => $this->id ? $this->id : ''
153
        ),$fire_events);*/
154
155
        $fld = $this->toArray();
156 View Code Duplication
        foreach ($this->default_field['user'] as $key => $value) {
157
            $tmp = $this->get($key);
158
            if ($this->newDoc && ( !is_int($tmp) && $tmp=='')) {
159
                if($tmp == $value){
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
160
                    //take default value from global config
161
                }
162
                $this->field[$key] = $value;
163
            }
164
            $this->Uset($key, 'user');
165
            unset($fld[$key]);
166
        }
167
        if (!empty($this->set['user'])) {
168 View Code Duplication
            if ($this->newDoc) {
169
                $SQL = "INSERT into {$this->makeTable('web_users')} SET " . implode(', ', $this->set['user']);
170
            } else {
171
                $SQL = "UPDATE {$this->makeTable('web_users')} SET " . implode(', ', $this->set['user']) . " WHERE id = " . $this->id;
172
            }
173
            $this->query($SQL);
174
        }
175
176
        if ($this->newDoc) {
177
            $this->id = $this->modx->db->getInsertId();
178
        }
179
180 View Code Duplication
        foreach ($this->default_field['attribute'] as $key => $value) {
181
            $tmp = $this->get($key);
182
            if ($this->newDoc && ( !is_int($tmp) && $tmp=='')) {
183
                if($tmp == $value){
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
184
                    //take default value from global config
185
                }
186
                $this->field[$key] = $value;
187
            }
188
            $this->Uset($key, 'attribute');
189
            unset($fld[$key]);
190
        }
191
        if (!empty($this->set['attribute'])) {
192
            if ($this->newDoc) {
193
                $this->set('internalKey', $this->id)->Uset('internalKey', 'attribute');
194
                $SQL = "INSERT into {$this->makeTable('web_user_attributes')} SET " . implode(', ', $this->set['attribute']);
195
            } else {
196
                $SQL = "UPDATE {$this->makeTable('web_user_attributes')} SET " . implode(', ', $this->set['attribute']) . " WHERE  internalKey = " . $this->getID();
197
            }
198
            $this->query($SQL);
199
        }
200
201
        foreach ($fld as $key => $value) {
202
            if ($value == '') continue;
203
            $result = $this->query("SELECT `setting_value` FROM {$this->makeTable('web_user_settings')} WHERE `webuser` = '{$this->id}' AND `setting_name` = '{$key}'");
204
            if ($this->modx->db->getRecordCount($result) > 0) {
205
                $this->query("UPDATE {$this->makeTable('web_user_settings')} SET `setting_value` = '{$value}' WHERE `webuser` = '{$this->id}' AND `setting_name` = '{$key}';");
206
            } else {
207
                $this->query("INSERT into {$this->makeTable('web_user_settings')} SET `webuser` = {$this->id},`setting_name` = '{$key}',`setting_value` = '{$value}';");
208
            }
209
        }
210
        if (!$this->newDoc && $this->givenPassword) {
211
            $this->invokeEvent('OnWebChangePassword',array(
212
                'userObj'       => $this,
213
                'userid'        => $this->id,
214
			    'user'	        => $this->toArray(),
215
			    'userpassword'	=> $this->givenPassword,
216
                'internalKey'   => $this->id,
217
                'username'      => $this->get('username')
218
            ),$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...
219
        }
220
        $this->invokeEvent('OnWebSaveUser',array (
221
            'userObj'   => $this,
222
            'mode'      => $this->newDoc ? "new" : "upd",
223
            'id'        => $this->id,
224
            'user'      => $this->toArray()
225
        ),$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...
226
227
        if ($clearCache) {
228
            $this->clearCache($fire_events);
229
        }
230
        return $this->id;
231
    }
232
233
    public function delete($ids, $fire_events = null)
234
    {
235
        if ($this->edit($ids)) {
236
            $flag = $this->query("
237
          DELETE user,attribute FROM {$this->makeTable('web_user_attributes')} as attribute
238
            LEFT JOIN {$this->makeTable('web_users')} as user ON user.id=attribute.internalKey
239
            WHERE attribute.internalKey='{$this->escape($this->getID())}'");
240
            $this->query("DELETE FROM {$this->makeTable('web_user_settings')} WHERE webuser='{$this->getID()}'");
241
            $this->query("DELETE FROM {$this->makeTable('web_groups')} WHERE webuser='{$this->getID()}'");
242
            $this->invokeEvent('OnWebDeleteUser', array(
243
                'userObj'       => $this,
244
                'userid'        => $this->getID(),
245
                'internalKey'   => $this->getID(),
246
                'username'      => $this->get('username'),
247
                'timestamp'     => time()
248
            ), $fire_events);
249
        } else {
250
            $flag = false;
251
        }
252
        $this->close();
253
        return $flag;
254
    }
255
256
    /**
257
     * @param int $id
258
     * @param bool $fulltime
259
     * @param string $cookieName
260
     * @param null $fire_events
261
     * @return bool
262
     */
263
    public function authUser($id = 0, $fulltime = true, $cookieName = 'WebLoginPE', $fire_events = null)
264
    {
265
        $flag = false;
266
        if (!$this->getID() && $id) $this->edit($id);
267
        if ($this->getID()) {
268
            //$this->logOut($cookieName);
269
            $flag = true;
270
            $this->SessionHandler('start', $cookieName, $fulltime);
271
            $this->invokeEvent("OnWebLogin", array(
272
                'userObj'       => $this,
273
                'userid'        => $this->getID(),
274
                'username'      => $this->get('username'),
275
                'userpassword'  => $this->givenPassword,
276
                'rememberme'    => $fulltime
277
            ),$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...
278
        }
279
        return $flag;
280
    }
281
282
    /**
283
     * @param int $id
284
     * @return bool
285
     */
286
    public function checkBlock($id = 0)
287
    {
288
        $tmp = clone $this;
289
        if ($id && $tmp->getID() != $id) {
290
            $tmp->edit($id);
291
        }
292
        $now = time();
293
294
        $b = $tmp->get('blocked');
295
        $bu = $tmp->get('blockeduntil');
296
        $ba = $tmp->get('blockedafter');
297
        $flag = (($b && !$bu && !$ba) || ($bu && $now < $bu) || ($ba && $now > $ba));
298
        unset($tmp);
299
        return $flag;
300
    }
301
302
    /**
303
     * @param $id
304
     * @param $password
305
     * @param $blocker
306
     * @param null $fire_events
307
     * @return bool
308
     */
309
    public function testAuth($id, $password, $blocker, $fire_events = null)
310
    {
311
        $tmp = clone $this;
312
        if ($id && $tmp->getID() != $id) {
313
            $tmp->edit($id);
314
        }
315
316
        $flag = $pluginFlag = false;
317
        if (
318
            ($tmp->getID()) && (!$blocker || ($blocker && !$tmp->checkBlock($id)))
319
        ) {
320
            $eventResult = $this->getInvokeEventResult('OnWebAuthentication',array(
321
                'userObj'       => $this,
322
                'userid'        => $tmp->getID(),
323
                'username'      => $tmp->get('username'),
324
                'userpassword'  => $password,
325
                'savedpassword' => $tmp->get('password')
326
            ),$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...
327
            if (is_array($eventResult)) {
328
                foreach ($eventResult as $result) {
329
                    $pluginFlag = (bool)$result;
330
                }
331
            } else {
332
                $pluginFlag = (bool)$eventResult;
333
            }
334
            if (!$pluginFlag) {
335
                $flag = ($tmp->get('password') == $tmp->getPassword($password));
336
            } 
337
        }
338
        unset($tmp);
339
        return $flag || $pluginFlag;
340
    }
341
342
    /**
343
     * @param bool $fulltime
344
     * @param string $cookieName
345
     * @return bool
346
     */
347
    public function AutoLogin($fulltime = true, $cookieName = 'WebLoginPE', $fire_events = null)
348
    {
349
        $flag = false;
350
        if (isset($_COOKIE[$cookieName])) {
351
            $cookie = explode('|', $_COOKIE[$cookieName], 2);
352
            if (isset($cookie[0], $cookie[1]) && strlen($cookie[0]) == 32 && strlen($cookie[1]) == 32) {
353
                $this->close();
354
                $q = $this->modx->db->query("SELECT id FROM " . $this->makeTable('web_users') . " WHERE md5(username)='{$this->escape($cookie[0])}'");
355
                $id = $this->modx->db->getValue($q);
356
                if ($this->edit($id) && $this->getID() && $this->get('password') == $cookie[1] && $this->testAuth($this->getID(), $cookie[1], true)) {
357
                    $flag = $this->authUser($this->getID(), $fulltime, $cookieName, $fire_events);
358
359
                }
360
            }
361
        }
362
        return $flag;
363
    }
364
365
    /**
366
     * @param string $cookieName
367
     * @param null $fire_events
368
     */
369
    public function logOut($cookieName = 'WebLoginPE', $fire_events = null)
370
    {
371
        if (!$uid = $this->modx->getLoginUserID('web')) return;
372
        $params = array(
373
            'username'      => $_SESSION['webShortname'],
374
            'internalKey'   => $uid,
375
            'userid'        => $uid // Bugfix by TS
376
        );
377
        $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...
378
        $this->SessionHandler('destroy', $cookieName ? $cookieName : 'WebLoginPE');
379
        $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...
380
    }
381
382
    /**
383
     * SessionHandler
384
     * Starts the user session on login success. Destroys session on error or logout.
385
     *
386
     * @param string $directive ('start' or 'destroy')
387
     * @return void
388
     * @author Raymond Irving
389
     * @author Scotty Delicious
390
     *
391
     * remeber может быть числом в секундах
392
     */
393
    protected function SessionHandler($directive, $cookieName, $remember = true)
394
    {
395
        switch ($directive) {
396
            case 'start':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
397
            {
398
                if ($this->getID()) {
399
                    $_SESSION['webShortname'] = $this->get('username');
400
                    $_SESSION['webFullname'] = $this->get('fullname');
401
                    $_SESSION['webEmail'] = $this->get('email');
402
                    $_SESSION['webValidated'] = 1;
403
                    $_SESSION['webInternalKey'] = $this->getID();
404
                    $_SESSION['webValid'] = base64_encode($this->get('password'));
405
                    $_SESSION['webUser'] = base64_encode($this->get('username'));
406
                    $_SESSION['webFailedlogins'] = $this->get('failedlogincount');
407
                    $_SESSION['webLastlogin'] = $this->get('lastlogin');
408
                    $_SESSION['webnrlogins'] = $this->get('logincount');
409
                    $_SESSION['webUsrConfigSet'] = array();
410
                    $_SESSION['webUserGroupNames'] = $this->getUserGroups();
411
                    $_SESSION['webDocgroups'] = $this->getDocumentGroups();
412
                    if ($remember) {
413
                        $cookieValue = md5($this->get('username')) . '|' . $this->get('password');
414
                        $cookieExpires = time() + (is_bool($remember) ? (60 * 60 * 24 * 365 * 5) : (int)$remember);
415
                        setcookie($cookieName, $cookieValue, $cookieExpires, '/');
416
                    }
417
                }
418
                break;
419
            }
420
            case 'destroy':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
421
            {
422
                if (isset($_SESSION['mgrValidated'])) {
423
                    unset($_SESSION['webShortname']);
424
                    unset($_SESSION['webFullname']);
425
                    unset($_SESSION['webEmail']);
426
                    unset($_SESSION['webValidated']);
427
                    unset($_SESSION['webInternalKey']);
428
                    unset($_SESSION['webValid']);
429
                    unset($_SESSION['webUser']);
430
                    unset($_SESSION['webFailedlogins']);
431
                    unset($_SESSION['webLastlogin']);
432
                    unset($_SESSION['webnrlogins']);
433
                    unset($_SESSION['webUsrConfigSet']);
434
                    unset($_SESSION['webUserGroupNames']);
435
                    unset($_SESSION['webDocgroups']);
436
437
                    setcookie($cookieName, '', time() - 60, '/');
438
                } else {
439
                    if (isset($_COOKIE[session_name()])) {
440
                        setcookie(session_name(), '', time() - 60, '/');
441
                    }
442
                    setcookie($cookieName, '', time() - 60, '/');
443
                    session_destroy();
444
                }
445
                break;
446
            }
447
        }
448
        return $this;
449
    }
450
451
    /**
452
     * @param int $userID
453
     * @return array
454
     */
455 View Code Duplication
    public function getDocumentGroups($userID = 0){
456
        $out = array();
457
        $user = $this->switchObject($userID);
458
        if($user->getID()){
459
            $web_groups = $this->modx->getFullTableName('web_groups');
460
            $webgroup_access = $this->modx->getFullTableName('webgroup_access');
461
462
            $sql = "SELECT `uga`.`documentgroup` FROM {$web_groups} as `ug`
463
                INNER JOIN {$webgroup_access} as `uga` ON `uga`.`webgroup`=`ug`.`webgroup`
464
                WHERE `ug`.`webuser` = ".$user->getID();
465
            $out = $this->modx->db->getColumn('documentgroup',$this->query($sql));
466
467
        }
468
        unset($user);
469
        return $out;
470
    }
471
472
    /**
473
     * @param int $userID
474
     * @return array
475
     */
476 View Code Duplication
    public function getUserGroups($userID = 0){
477
        $out = array();
478
        $user = $this->switchObject($userID);
479
        if($user->getID()){
480
            $web_groups = $this->makeTable('web_groups');
481
            $webgroup_names = $this->makeTable('webgroup_names');
482
483
            $sql = "SELECT `ugn`.`name` FROM {$web_groups} as `ug`
484
                INNER JOIN {$webgroup_names} as `ugn` ON `ugn`.`id`=`ug`.`webgroup`
485
                WHERE `ug`.`webuser` = ".$user->getID();
486
            $out = $this->modx->db->getColumn('name',$this->query($sql));
487
        }
488
        unset($user);
489
        return $out;
490
    }
491
492
    public function setUserGroups($userID = 0, $groupIds = array()) {
493
        $user = $this->switchObject($userID);
494
        if(($uid = $user->getID()) && is_array($groupIds)) {
495
            foreach ($groupIds as $gid) {
496
                $this->query("REPLACE INTO {$this->makeTable('web_groups')} (`webgroup`, `webuser`) VALUES ('{$gid}', '{$uid}')");
497
            }
498
        }
499
        return $this;
500
    }
501
}
502