Completed
Pull Request — master (#3)
by
unknown
05:51
created

Users::addUserActivity()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 9
rs 9.6666
cc 1
eloc 6
nc 1
nop 3
1
<?php
2
3
/**
4
 * Users module
5
 *
6
 * @author Alexey Krupskiy <[email protected]>
7
 * @link http://inji.ru/
8
 * @copyright 2015 Alexey Krupskiy
9
 * @license https://github.com/injitools/cms-Inji/blob/master/LICENSE
10
 */
11
class Users extends Module
12
{
13
    public $cookiePrefix = '';
14
15
    public function init()
2 ignored issues
show
Coding Style introduced by
init uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
init uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
16
    {
17
        if (!empty($this->config['cookieSplit'])) {
18
            $this->cookiePrefix = \App::$cur->type;
19
        }
20
        \Users\User::$cur = new Users\User(array('group_id' => 1, 'role_id' => 1));
21
        if (!App::$cur->db->connect) {
22
            return;
23
        }
24
        if (isset($_GET['logout'])) {
25
            return $this->logOut();
26
        }
27
        if (filter_input(INPUT_COOKIE, $this->cookiePrefix . '_user_session_hash') && filter_input(INPUT_COOKIE, $this->cookiePrefix . '_user_id')) {
28
            return $this->cuntinueSession(filter_input(INPUT_COOKIE, $this->cookiePrefix . '_user_session_hash'), filter_input(INPUT_COOKIE, $this->cookiePrefix . '_user_id'));
29
        }
30
        if (isset($_POST['autorization']) && trim(filter_input(INPUT_POST, 'user_login')) && trim(filter_input(INPUT_POST, 'user_pass'))) {
31
            unset($_POST['autorization']);
32
            return $this->autorization(trim(filter_input(INPUT_POST, 'user_login')), trim(filter_input(INPUT_POST, 'user_pass')), strpos(filter_input(INPUT_POST, 'user_login'), '@') ? 'mail' : 'login', false);
33
        }
34
        if (isset($_GET['passre']) && filter_input(INPUT_GET, 'user_mail')) {
35
            return $this->passre(trim(filter_input(INPUT_GET, 'user_mail')));
36
        }
37
        if (!empty($_GET['passrecont']) && filter_input(INPUT_GET, 'hash')) {
38
            return $this->passrecont(filter_input(INPUT_GET, 'hash'));
39
        }
40
    }
41
42
    public function logOut($redirect = true)
1 ignored issue
show
Coding Style introduced by
logOut uses the super-global variable $_COOKIE which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
43
    {
44
        if (!empty($_COOKIE[$this->cookiePrefix . "_user_session_hash"]) && !empty($_COOKIE[$this->cookiePrefix . "_user_id"])) {
45
            $session = Users\Session::get([
46
                        ['user_id', $_COOKIE[$this->cookiePrefix . "_user_id"]],
47
                        ['hash', $_COOKIE[$this->cookiePrefix . "_user_session_hash"]]
48
            ]);
49
            if ($session) {
50
                $session->delete();
51
            }
52
        }
53 View Code Duplication
        if (!headers_sent()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
54
            setcookie($this->cookiePrefix . "_user_session_hash", '', 0, "/");
55
            setcookie($this->cookiePrefix . "_user_id", '', 0, "/");
56
        }
57
        if ($redirect) {
58
            Tools::redirect('/', 'Вы вышли из своего профиля', 'success');
59
        }
60
    }
61
62
    public function cuntinueSession($hash, $userId)
63
    {
64
        $session = Users\Session::get([
65
                    ['user_id', $userId],
66
                    ['hash', $hash]
67
        ]);
68
        if ($session && $session->user && $session->user->blocked) {
69 View Code Duplication
            if (!headers_sent()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
70
                setcookie($this->cookiePrefix . "_user_session_hash", '', 0, "/");
71
                setcookie($this->cookiePrefix . "_user_id", '', 0, "/");
72
            }
73
            Msg::add('Ваш аккаунт заблокирован', 'info');
74
            return;
75
        }
76
        if ($session && $session->user && !$session->user->blocked) {
77
            if ($session->user->activation) {
78
                Msg::add('Этот аккаунт ещё не активирован, не все функции могут быть доступны. <br />Если вы не получали письмо с ссылкой для активации, нажмите на - <a href = "/users/resendActivation/' . $session->user->id . '"><b>повторно выслать ссылку активации</b></a>');
79
            }
80
            if (!$session->user->mail) {
81
                Msg::add('У вас не указан E-Mail, не все функции могут быть доступны. <a href = "/users/attachEmail/"><b>Указать E-Mail</b></a>');
82
            }
83
            Users\User::$cur = $session->user;
84
            Users\User::$cur->date_last_active = 'CURRENT_TIMESTAMP';
85
            Users\User::$cur->save();
86 View Code Duplication
        } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
87
            if (!headers_sent()) {
88
                setcookie($this->cookiePrefix . "_user_session_hash", '', 0, "/");
89
                setcookie($this->cookiePrefix . "_user_id", '', 0, "/");
90
            }
91
            Msg::add('Ваша сессия устарела или более недействительна, вам необходимо пройти <a href = "/users/login">авторазиацию</a> заново', 'info');
92
        }
93
    }
94
95
    public function passre($user_mail)
96
    {
97
        $user = $this->get($user_mail, 'mail');
98
        if (!$user) {
99
            Msg::add('Пользователь ' . $user_mail . ' не найден, проверьте првильность ввода e-mail или зарегистрируйтесь', 'danger');
100
            return false;
101
        }
102
        $passre = Users\Passre::get([['user_id', $user->id], ['status', 1]]);
103
        if ($passre) {
104
            $passre->status = 2;
105
            $passre->save();
106
        }
107
        $hash = $user->id . '_' . Tools::randomString(50);
108
        $passre = new Users\Passre(['user_id' => $user->id, 'status' => 1, 'hash' => $hash]);
109
        $passre->save();
110
        Tools::sendMail('noreply@' . INJI_DOMAIN_NAME, $user_mail, 'Восстановление пароля на сайте ' . idn_to_utf8(INJI_DOMAIN_NAME), 'Было запрошено восстановление пароля на сайте ' . idn_to_utf8(INJI_DOMAIN_NAME) . '<br />для продолжения восстановления пароля перейдите по ссылке: <a href = "http://' . idn_to_utf8(INJI_DOMAIN_NAME) . '/?passrecont=1&hash=' . $hash . '">' . idn_to_utf8(INJI_DOMAIN_NAME) . '/?passrecont=1&hash=' . $hash . '</a>');
111
        Tools::redirect('/', 'На указанный почтовый ящик была выслана инструкция по восстановлению пароля', 'success');
112
    }
113
114
    public function passrecont($hash)
115
    {
116
        $passre = Users\Passre::get([['hash', $hash]]);
117
        if ($passre) {
118
            if ($passre->status != 1) {
119
                Tools::redirect('/', 'Этот код восстановление более недействителен', 'danger');
120
            }
121
            $passre->status = 3;
122
            $passre->save();
123
            $pass = Tools::randomString(10);
124
            $user = Users\User::get($passre->user_id);
125
            $user->pass = $this->hashpass($pass);
126
            $user->save();
127
            $this->autorization($user->mail, $user->pass, 'mail');
128
            Tools::sendMail('noreply@' . INJI_DOMAIN_NAME, $user->mail, 'Новый пароль на сайте ' . idn_to_utf8(INJI_DOMAIN_NAME), 'Было запрошено восстановление пароля на сайте ' . idn_to_utf8(INJI_DOMAIN_NAME) . '<br />Ваш новый пароль: ' . $pass);
129
            Tools::redirect('/', 'На указанный почтовый ящик был выслан новый пароль', 'success');
130
        }
131
    }
132
133
    public function autorization($login, $pass, $ltype = 'login', $noMsg = true)
134
    {
135
136
        sleep(3); //simple anti brute
137
138
        $user = $this->get($login, $ltype);
139
        if ($user && $this->verifypass($pass, $user->pass) && !$user->blocked) {
140
            if ($user->activation) {
141
                Msg::add('Этот аккаунт ещё не активирован, не все функции могут быть доступны. <br />Если вы не получали письмо с ссылкой для активации, нажмите на - <a href = "/users/resendActivation/' . $user->id . '"><b>повторно выслать ссылку активации</b></a>');
142
            }
143
            if (!$user->mail) {
144
                Msg::add('У вас не указан E-Mail, не все функции могут быть доступны. <a href = "/users/attachEmail/"><b>Указать E-Mail</b></a>');
145
            }
146
            $this->newSession($user);
147
148
            Users\User::$cur = $user;
149
            Users\User::$cur->date_last_active = 'CURRENT_TIMESTAMP';
150
            Users\User::$cur->save();
151
            if (!$noMsg && !empty($this->config['loginUrl'][$this->app->type])) {
152
                Tools::redirect($this->config['loginUrl'][$this->app->type]);
153
            }
154
            return true;
155
        }
156
        if (!$noMsg) {
157
            if ($user && $user->blocked) {
158
                Msg::add('Вы заблокированы', 'danger');
159
            } elseif ($user) {
160
                Msg::add('Вы ошиблись при наборе пароля или логина, попробуйте ещё раз или воспользуйтесь <a href = "?passre=1&user_mail=' . $user->mail . '">Восстановлением пароля</a>', 'danger');
161
            } else {
162
                Msg::add('Данный почтовый ящик не зарегистрирован в системе', 'danger');
163
            }
164
        }
165
166
        return false;
167
    }
168
169
    public function newSession($user)
1 ignored issue
show
Coding Style introduced by
newSession uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
170
    {
171
        $hash = Tools::randomString(255);
172
173
        $session = new Users\Session([
174
            'user_id' => $user->id,
175
            'agent' => $_SERVER['HTTP_USER_AGENT'],
176
            'ip' => $_SERVER['REMOTE_ADDR']
177
        ]);
178
179
        $session->hash = $hash;
180
        $session->save();
181
182
        if (!headers_sent()) {
183
            setcookie($this->cookiePrefix . "_user_session_hash", $session->hash, time() + 360000, "/");
184
            setcookie($this->cookiePrefix . "_user_id", $session->user_id, time() + 360000, "/");
185
        } else {
186
            Msg::add('Не удалось провести авторизацию. Попробуйте позже', 'info');
187
        }
188
    }
189
190
    /**
191
     * Return user
192
     * 
193
     * @param integer|string $idn
194
     * @param type $ltype
195
     * @return boolean|\User\User
196
     */
197
    public function get($idn, $ltype = 'id')
198
    {
199
        if (!$idn)
200
            return false;
201
202
        if (is_numeric($idn) && $ltype != 'login')
203
            $user = Users\User::get($idn, 'id');
204
        elseif ($ltype == 'login')
205
            $user = Users\User::get($idn, 'login');
206
        else
207
            $user = Users\User::get($idn, 'mail');
208
        if (!$user)
209
            return [];
210
211
        return $user;
212
    }
213
214
    public function registration($data, $autorization = false)
3 ignored issues
show
Coding Style introduced by
registration uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
registration uses the super-global variable $_COOKIE which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
registration uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
215
    {
216
        extract($data);
217
218
        if (empty($user_mail)) {
219
            Msg::add('Вы не ввели E-mail', 'danger');
220
            return false;
221
        }
222
        $user_mail = trim($user_mail);
223
        if (!filter_var($user_mail, FILTER_VALIDATE_EMAIL)) {
224
            Msg::add('Вы ввели не корректный E-mail', 'danger');
225
            return false;
226
        }
227
228
        $user = $this->get($user_mail, 'mail');
229
        if ($user) {
230
            Msg::add('Введенный вами почтовый ящик зарегистрирован в нашей системе, войдите или введите другой почтовый ящик', 'danger');
231
            return false;
232
        }
233
        if (empty($user_login)) {
234
            $user_login = $user_mail;
235
        }
236
        $user_login = trim($user_login);
237
        $user = $this->get($user_login, 'login');
238
        if ($user) {
239
            Msg::add('Введенный вами логин зарегистрирован в нашей системе, войдите или введите другой логин', 'danger');
240
            return false;
241
        }
242
        if (empty($user_name)) {
243
            $user_name = '';
244
        }
245
        if (empty($user_city)) {
246
            $user_city = '';
247
        }
248
        if (empty($user_birthday)) {
249
            $user_birthday = '';
250
        }
251
        if (empty($user_phone)) {
252
            $user_phone = '';
253
        }
254
        $invite_code = (!empty($data['invite_code']) ? $data['invite_code'] : (!empty($_POST['invite_code']) ? $_POST['invite_code'] : ((!empty($_COOKIE['invite_code']) ? $_COOKIE['invite_code'] : ((!empty($_GET['invite_code']) ? $_GET['invite_code'] : ''))))));
255
        if (!empty($invite_code)) {
256
            $invite = Users\User\Invite::get($invite_code, 'code');
257
            if (!$invite) {
258
                Msg::add('Такой код приглашения не найден', 'danger');
259
                return false;
260
            }
261
            if ($invite->limit && !($invite->limit - $invite->count)) {
262
                Msg::add('Лимит приглашений для данного кода исчерпан', 'danger');
263
                return false;
264
            }
265
            $parent_id = $invite->user_id;
266
            $inviter = $parent_id;
267
            $invite->count++;
268
            $invite->save();
269
        }
270
        if (empty($parent_id) && !empty($this->config['defaultPartner'])) {
271
            $parent_id = $this->config['defaultPartner'];
272
        }
273
274
        $pass = Tools::randomString(10);
275
        $user = new Users\User([
276
            'pass' => $this->hashpass($pass),
277
            'mail' => $user_mail,
278
            'login' => htmlspecialchars($user_login),
279
            'role_id' => 2,
280
            'group_id' => 2,
281
            'parent_id' => !empty($parent_id) ? $parent_id : 0
282
        ]);
283
        if (!empty($this->config['needActivation'])) {
284
            $user->activation = Tools::randomString();
285
        }
286
        $user->save();
287
        if (!$user->id) {
288
            Msg::add('Не удалось зарегистрировать', 'danger');
289
            return false;
290
        }
291
        $info = new \Users\User\Info([
292
            'user_id' => $user->id,
293
            'first_name' => htmlspecialchars($user_name),
294
            'city' => htmlspecialchars($user_city),
295
            'bday' => htmlspecialchars($user_birthday),
296
            'phone' => htmlspecialchars($user_phone),
297
        ]);
298
        $info->save();
299
        if (isset($inviter))
300
            $this->AddUserActivity($inviter, 2, "По вашей ссылке зарегистрировался новый партнер, {$info->first_name} {$info->last_name} (id: {$user->id})" );
301
        if ($autorization) {
302
            $this->autorization($user_mail, $pass, 'mail');
303
        }
304
        if (!empty($this->config['needActivation'])) {
305
            $from = 'noreply@' . INJI_DOMAIN_NAME;
306
            $to = $user_mail;
307
            $subject = 'Регистрация на сайте ' . idn_to_utf8(INJI_DOMAIN_NAME);
308
            $text = 'Вы были зарегистрированы на сайте ' . idn_to_utf8(INJI_DOMAIN_NAME) . '<br />для входа используйте ваш почтовый ящик в качестве логина и пароль: ' . $pass;
309
            $text .='<br />';
310
            $text .= '<br />';
311
            $text .= 'Для активации вашего аккаунта перейдите по ссылке <a href = "http://' . INJI_DOMAIN_NAME . '/users/activation/' . $user->id . '/' . $user->activation . '">http://' . idn_to_utf8(INJI_DOMAIN_NAME) . '/users/activation/' . $user->id . '/' . $user->activation . '</a>';
312
            Tools::sendMail($from, $to, $subject, $text);
313
            Msg::add('Вы были зарегистрированы. На указанный почтовый ящик был выслан ваш пароль и ссылка для активации', 'success');
314
        } else {
315
            $from = 'noreply@' . INJI_DOMAIN_NAME;
316
            $to = $user_mail;
317
            $subject = 'Регистрация на сайте ' . idn_to_utf8(INJI_DOMAIN_NAME);
318
            $text = 'Вы были зарегистрированы на сайте ' . idn_to_utf8(INJI_DOMAIN_NAME) . '<br />для входа используйте ваш почтовый ящик в качестве логина и пароль: ' . $pass;
319
            Tools::sendMail($from, $to, $subject, $text);
320
            Msg::add('Вы были зарегистрированы. На указанный почтовый ящик был выслан ваш пароль', 'success');
321
        }
322
        return $user->id;
323
    }
324
325
    public function hashpass($pass)
326
    {
327
        return password_hash($pass, PASSWORD_DEFAULT);
328
    }
329
330
    public function verifypass($pass, $hash)
331
    {
332
        return password_verify($pass, $hash);
333
    }
334
335
    public function getUserPartners($user, $levels = 0)
0 ignored issues
show
Unused Code introduced by
The parameter $levels is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
336
    {
337
        $return = [
338
            'users' => [],
339
            'levels' => [],
340
            'count' => 0,
341
            'lastLevel' => 0
342
        ];
343
        $levels = [];
344
        $userIds = $user->user_id;
345
        for ($i = 1; $i <= $levels || !$levels; $i++) {
346
            if (!$userIds && $levels) {
347
                $levels[$i] = [];
348
                continue;
349
            } elseif (!$userIds && !$levels) {
350
                break;
351
            }
352
            $usersLevel = \Users\User::getList(['where' => [['parent_id', $userIds, 'IN']]]);
353
            $return['users'] += $usersLevel;
354
            $return['levels'][$i] = array_keys($usersLevel);
355
            $userIds = implode(',', $return['levels'][$i]);
356
            $return['lastLevel'] = $i;
357
        }
358
        $return['count'] = count($return['users']);
359
        return $return;
360
    }
361
362
    public function addUserActivity($user_id, $cat_id , $text = '')
363
    {
364
        $ua = new Users\Activity([
365
            'user_id' => $user_id,
366
            'category_id' => $cat_id,
367
            'text' => $text,
368
        ]);
369
        $ua->save();
370
    }
371
372
}