User   A
last analyzed

Complexity

Total Complexity 36

Size/Duplication

Total Lines 337
Duplicated Lines 0 %

Importance

Changes 22
Bugs 5 Features 0
Metric Value
wmc 36
eloc 121
c 22
b 5
f 0
dl 0
loc 337
rs 9.52

22 Methods

Rating   Name   Duplication   Size   Complexity  
A behaviors() 0 10 1
A generatePasswordResetToken() 0 3 1
A findByUsernameEmail() 0 3 1
A removeEmailConfirmToken() 0 3 1
A sendConfirmEmail() 0 10 1
A getProfile() 0 3 1
A afterSave() 0 9 2
A validatePassword() 0 3 1
A findByUsernameOrEmail() 0 6 1
A rules() 0 35 1
A beforeSave() 0 12 4
A setPassword() 0 3 1
A isSuperAdmin() 0 11 4
A getLabelMailConfirm() 0 8 2
A removePasswordResetToken() 0 3 1
A isDeleted() 0 3 1
A findByEmailConfirmToken() 0 5 1
A setStatus() 0 13 3
A find() 0 3 1
A attributeLabels() 0 15 1
A beforeDelete() 0 11 3
A getUserFullName() 0 8 3
1
<?php
2
3
namespace modules\users\models;
4
5
use Yii;
6
use yii\base\Exception;
7
use yii\db\ActiveQuery;
8
use yii\db\StaleObjectException;
9
use yii\helpers\Html;
10
use yii\db\ActiveRecord;
11
use yii\behaviors\TimestampBehavior;
12
use yii2tech\ar\softdelete\SoftDeleteBehavior;
13
use modules\rbac\models\Role;
14
use modules\users\models\query\UserQuery;
15
use modules\users\traits\ModuleTrait;
16
use modules\users\Module;
17
use Throwable;
18
19
/**
20
 * This is the model class for table "{{%user}}".
21
 *
22
 * @property int|string $id ID
23
 * @property string $username Username
24
 * @property string $email Email
25
 * @property string $auth_key Authorization Key
26
 * @property string $password_hash Hash Password
27
 * @property string $password_reset_token Password Token
28
 * @property string $email_confirm_token Email Confirm Token
29
 * @property int $created_at Created
30
 * @property int $updated_at Updated
31
 * @property int|string $status Status
32
 *
33
 * @property UserProfile $profile
34
 * @property string $statusLabelName
35
 * @property string $statusName
36
 * @property array $statusesArray
37
 * @property string $labelMailConfirm
38
 * @property-read string $userFullName
39
 * @property string $newPassword
40
 *
41
 * @method touch() TimestampBehavior
42
 */
43
class User extends BaseUser
44
{
45
    use ModuleTrait;
46
47
    // Length password
48
    const LENGTH_STRING_PASSWORD_MIN = 2;
49
    const LENGTH_STRING_PASSWORD_MAX = 32;
50
51
    const SCENARIO_ADMIN_CREATE = 'adminCreate';
52
53
    /**
54
     * @var string
55
     */
56
    public $password;
57
58
    /**
59
     * {@inheritdoc}
60
     * @return array
61
     */
62
    public function behaviors()
63
    {
64
        return [
65
            'timestamp' => [
66
                'class' => TimestampBehavior::class
67
            ],
68
            'softDeleteBehavior' => [
69
                'class' => SoftDeleteBehavior::class,
70
                'softDeleteAttributeValues' => [
71
                    'status' => self::STATUS_DELETED
72
                ]
73
            ]
74
        ];
75
    }
76
77
    /**
78
     * {@inheritdoc}
79
     * @return array
80
     */
81
    public function rules()
82
    {
83
        return [
84
            ['username', 'required'],
85
            ['username', 'match', 'pattern' => '#^[\w_-]+$#i'],
86
            [
87
                'username',
88
                'unique',
89
                'targetClass' => self::class,
90
                'message' => Module::translate('module', 'This username is already taken.')
91
            ],
92
            ['username', 'string', 'min' => 2, 'max' => 255],
93
94
            ['email', 'required'],
95
            ['email', 'email'],
96
            [
97
                'email',
98
                'unique',
99
                'targetClass' => self::class,
100
                'message' => Module::translate('module', 'This email is already taken.')
101
            ],
102
            ['email', 'string', 'max' => 255],
103
            [['auth_key'], 'string', 'max' => 32],
104
            [['email_confirm_token', 'password_reset_token', 'auth_key'], 'unique'],
105
106
            ['status', 'integer'],
107
            ['status', 'default', 'value' => self::STATUS_WAIT],
108
            ['status', 'in', 'range' => array_keys(self::getStatusesArray())],
109
110
            [['password'], 'required', 'on' => self::SCENARIO_ADMIN_CREATE],
111
            [
112
                'password',
113
                'string',
114
                'min' => self::LENGTH_STRING_PASSWORD_MIN,
115
                'max' => self::LENGTH_STRING_PASSWORD_MAX
116
            ]
117
        ];
118
    }
119
120
    /**
121
     * {@inheritdoc}
122
     * @return array
123
     */
124
    public function attributeLabels()
125
    {
126
        return [
127
            'id' => Module::translate('module', 'ID'),
128
            'username' => Module::translate('module', 'Username'),
129
            'email' => Module::translate('module', 'Email'),
130
            'auth_key' => Module::translate('module', 'Auth Key'),
131
            'password_hash' => Module::translate('module', 'Hash Password'),
132
            'password_reset_token' => Module::translate('module', 'Password Token'),
133
            'email_confirm_token' => Module::translate('module', 'Email Confirm Token'),
134
            'created_at' => Module::translate('module', 'Created'),
135
            'updated_at' => Module::translate('module', 'Updated'),
136
            'status' => Module::translate('module', 'Status'),
137
            'userRoleName' => Module::translate('module', 'User Role Name'),
138
            'password' => Module::translate('module', 'Password')
139
        ];
140
    }
141
142
    /**
143
     * {@inheritdoc}
144
     * @return UserQuery the active query used by this AR class.
145
     */
146
    public static function find()
147
    {
148
        return new UserQuery(static::class);
149
    }
150
151
    /**
152
     * @return ActiveQuery
153
     */
154
    public function getProfile()
155
    {
156
        return $this->hasOne(UserProfile::class, ['user_id' => 'id']);
157
    }
158
159
    /**
160
     * Generates password hash from password and sets it to the model
161
     *
162
     * @param string $password
163
     * @throws Exception
164
     */
165
    public function setPassword($password)
166
    {
167
        $this->password_hash = Yii::$app->security->generatePasswordHash($password);
168
    }
169
170
    /**
171
     * Removes password reset token
172
     */
173
    public function removePasswordResetToken()
174
    {
175
        $this->password_reset_token = null;
176
    }
177
178
    /**
179
     * Generates new password reset token
180
     * @throws Exception
181
     */
182
    public function generatePasswordResetToken()
183
    {
184
        $this->password_reset_token = Yii::$app->security->generateRandomString() . '_' . time();
185
    }
186
187
    /**
188
     * Validates password
189
     *
190
     * @param string $password password to validate
191
     * @return bool if password provided is valid for current user
192
     */
193
    public function validatePassword($password)
194
    {
195
        return Yii::$app->security->validatePassword($password, $this->password_hash);
196
    }
197
198
    /**
199
     * Finds user by email
200
     *
201
     * @param string $email
202
     * @return array|null|ActiveRecord
203
     */
204
    public static function findByUsernameEmail($email)
205
    {
206
        return static::findOne(['email' => $email, 'status' => self::STATUS_ACTIVE]);
207
    }
208
209
    /**
210
     * Finds user by username or email
211
     *
212
     * @param string $string
213
     * @return array|null|ActiveRecord
214
     */
215
    public static function findByUsernameOrEmail($string)
216
    {
217
        return static::find()
218
            ->where(['or', ['username' => $string], ['email' => $string]])
219
            ->andWhere(['status' => self::STATUS_ACTIVE])
220
            ->one();
221
    }
222
223
    /**
224
     * @param mixed $email_confirm_token
225
     * @return bool|null|static
226
     */
227
    public static function findByEmailConfirmToken($email_confirm_token)
228
    {
229
        return static::findOne([
230
            'email_confirm_token' => $email_confirm_token,
231
            'status' => self::STATUS_WAIT
232
        ]);
233
    }
234
235
    /**
236
     * Removes email confirmation token
237
     */
238
    public function removeEmailConfirmToken()
239
    {
240
        $this->email_confirm_token = null;
241
    }
242
243
    /**
244
     * @param string $name
245
     * @return string
246
     */
247
    public function getLabelMailConfirm($name = 'default')
248
    {
249
        if ($this->status === self::STATUS_WAIT) {
250
            return Html::tag('span', Html::tag('span', '', [
251
                'class' => 'glyphicon glyphicon-envelope'
252
            ]), ['class' => 'label label-' . $name]);
253
        }
254
        return '';
255
    }
256
257
    /**
258
     * @return bool
259
     */
260
    public function sendConfirmEmail()
261
    {
262
        return Yii::$app->mailer->compose([
263
            'html' => '@modules/users/mail/emailConfirm-html',
264
            'text' => '@modules/users/mail/emailConfirm-text'
265
        ], ['user' => $this])
266
            ->setFrom([Yii::$app->params['supportEmail'] => Yii::$app->name])
267
            ->setTo($this->email)
268
            ->setSubject(Module::translate('module', 'Account activation!') . ' ' . Yii::$app->name)
269
            ->send();
270
    }
271
272
    /**
273
     * Set Status
274
     * @return int|string
275
     */
276
    public function setStatus()
277
    {
278
        switch ($this->status) {
279
            case self::STATUS_ACTIVE:
280
                $this->status = self::STATUS_BLOCKED;
281
                break;
282
            case self::STATUS_DELETED:
283
                $this->status = self::STATUS_WAIT;
284
                break;
285
            default:
286
                $this->status = self::STATUS_ACTIVE;
287
        }
288
        return $this->status;
289
    }
290
291
    /**
292
     * @return string
293
     */
294
    public function getUserFullName()
295
    {
296
        $fullName = Module::translate('module', 'Guest');
297
        if (!Yii::$app->user->isGuest) {
298
            $fullName = $this->profile->first_name . ' ' . $this->profile->last_name;
299
            $fullName = ($fullName !== ' ') ? $fullName : $this->username;
300
        }
301
        return Html::encode(trim($fullName));
302
    }
303
304
    /**
305
     * @param int|string $id
306
     * @return bool
307
     */
308
    public function isSuperAdmin($id = '')
309
    {
310
        $id = $id ?: $this->id;
311
        $authManager = Yii::$app->authManager;
312
        $roles = $authManager->getRolesByUser($id);
313
        foreach ($roles as $role) {
314
            if ($role->name === Role::ROLE_SUPER_ADMIN) {
315
                return true;
316
            }
317
        }
318
        return false;
319
    }
320
321
    /**
322
     * @return bool
323
     */
324
    public function isDeleted()
325
    {
326
        return $this->status === self::STATUS_DELETED;
327
    }
328
329
    /**
330
     * @param bool $insert
331
     * @return bool
332
     * @throws Exception
333
     */
334
    public function beforeSave($insert)
335
    {
336
        if (parent::beforeSave($insert)) {
337
            if ($insert) {
338
                $this->generateAuthKey();
339
            }
340
            if (!empty($this->newPassword)) {
341
                $this->setPassword($this->newPassword);
342
            }
343
            return true;
344
        }
345
        return false;
346
    }
347
348
    /**
349
     * @param bool $insert
350
     * @param array $changedAttributes
351
     */
352
    public function afterSave($insert, $changedAttributes)
353
    {
354
        parent::afterSave($insert, $changedAttributes);
355
        if ($insert) {
356
            $profile = new UserProfile([
357
                'user_id' => $this->id,
358
                'email_gravatar' => $this->email
359
            ]);
360
            $profile->save();
361
        }
362
    }
363
364
    /**
365
     * @return bool
366
     * @throws Throwable
367
     * @throws StaleObjectException
368
     */
369
    public function beforeDelete()
370
    {
371
        if ($this->isDeleted()) {
372
            $this->profile->delete();
373
            // Отвязываем от ролей
374
            $authManager = Yii::$app->getAuthManager();
375
            if ($authManager->getRolesByUser($this->id)) {
376
                $authManager->revokeAll($this->id);
377
            }
378
        }
379
        return parent::beforeDelete();
380
    }
381
}
382