Completed
Push — master ( 51f787...8bc09a )
by Alexey
03:06
created

User::getStatusLabelName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace modules\users\models;
4
5
use Yii;
6
use yii\helpers\Html;
7
use yii\helpers\ArrayHelper;
8
use yii\db\ActiveRecord;
9
use yii\web\IdentityInterface;
10
use yii\behaviors\TimestampBehavior;
11
use yii2tech\ar\softdelete\SoftDeleteBehavior;
12
use modules\users\models\query\UserQuery;
13
use modules\users\traits\ModuleTrait;
14
use modules\users\Module;
15
16
/**
17
 * This is the model class for table "{{%user}}".
18
 *
19
 * @property int $id ID
20
 * @property string $username Username
21
 * @property string $email Email
22
 * @property string $auth_key Authorization Key
23
 * @property string $password_hash Hash Password
24
 * @property string $password_reset_token Password Token
25
 * @property string $email_confirm_token Email Confirm Token
26
 * @property int $created_at Created
27
 * @property int $updated_at Updated
28
 * @property int $status Status
29
 *
30
 * @property UserProfile $profile
31
 * @property string $statusLabelName
32
 * @property string $statusName
33
 * @property array $statusesArray
34
 * @property string $labelMailConfirm
35
 */
36
class User extends ActiveRecord implements IdentityInterface
37
{
38
    use ModuleTrait;
39
40
    // Statuses
41
    const STATUS_BLOCKED = 0;
42
    const STATUS_ACTIVE = 1;
43
    const STATUS_WAIT = 2;
44
    const STATUS_DELETED = 3;
45
46
    // Length password
47
    const LENGTH_STRING_PASSWORD_MIN = 2;
48
    const LENGTH_STRING_PASSWORD_MAX = 32;
49
50
    /**
51
     * @var string
52
     */
53
    public $password;
54
55
    /**
56
     * {@inheritdoc}
57
     * @return string
58
     */
59
    public static function tableName()
60
    {
61
        return '{{%user}}';
62
    }
63
64
    /**
65
     * {@inheritdoc}
66
     * @return array
67
     */
68
    public function behaviors()
69
    {
70
        return [
71
            'timestamp' => [
72
                'class' => TimestampBehavior::class,
73
            ],
74
            'softDeleteBehavior' => [
75
                'class' => SoftDeleteBehavior::class,
76
                'softDeleteAttributeValues' => [
77
                    'status' => self::STATUS_DELETED,
78
                ],
79
            ],
80
        ];
81
    }
82
83
    /**
84
     * {@inheritdoc}
85
     * @return array
86
     */
87
    public function rules()
88
    {
89
        return [
90
            ['username', 'required'],
91
            ['username', 'match', 'pattern' => '#^[\w_-]+$#i'],
92
            ['username', 'unique', 'targetClass' => self::class, 'message' => Module::t('module', 'This username is already taken.')],
93
            ['username', 'string', 'min' => 2, 'max' => 255],
94
95
            ['email', 'required'],
96
            ['email', 'email'],
97
            ['email', 'unique', 'targetClass' => self::class, 'message' => Module::t('module', 'This email is already taken.')],
98
            ['email', 'string', 'max' => 255],
99
            [['auth_key'], 'string', 'max' => 32],
100
            [['password_reset_token'], 'unique'],
101
102
            ['status', 'integer'],
103
            ['status', 'default', 'value' => self::STATUS_WAIT],
104
            ['status', 'in', 'range' => array_keys(self::getStatusesArray())],
105
106
            ['password', 'string', 'min' => self::LENGTH_STRING_PASSWORD_MIN, 'max' => self::LENGTH_STRING_PASSWORD_MAX],
107
        ];
108
    }
109
110
    /**
111
     * {@inheritdoc}
112
     * @return array
113
     */
114
    public function attributeLabels()
115
    {
116
        return [
117
            'id' => Module::t('module', 'ID'),
118
            'username' => Module::t('module', 'Username'),
119
            'email' => Module::t('module', 'Email'),
120
            'auth_key' => Module::t('module', 'Auth Key'),
121
            'password_hash' => Module::t('module', 'Hash Password'),
122
            'password_reset_token' => Module::t('module', 'Password Token'),
123
            'email_confirm_token' => Module::t('module', 'Email Confirm Token'),
124
            'created_at' => Module::t('module', 'Created'),
125
            'updated_at' => Module::t('module', 'Updated'),
126
            'status' => Module::t('module', 'Status'),
127
            'userRoleName' => Module::t('module', 'User Role Name'),
128
            'password' => Module::t('module', 'Password'),
129
        ];
130
    }
131
132
    /**
133
     * {@inheritdoc}
134
     * @return \modules\users\models\query\UserQuery the active query used by this AR class.
135
     */
136
    public static function find()
137
    {
138
        return new UserQuery(get_called_class());
139
    }
140
141
    /**
142
     * @return \yii\db\ActiveQuery
143
     */
144
    public function getProfile()
145
    {
146
        return $this->hasOne(UserProfile::class, ['user_id' => 'id']);
147
    }
148
149
    /**
150
     * {@inheritdoc}
151
     * @param int|string $id
152
     * @return User|null|IdentityInterface
153
     */
154
    public static function findIdentity($id)
155
    {
156
        return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);
0 ignored issues
show
Bug Best Practice introduced by
The expression return static::findOne(a...> self::STATUS_ACTIVE)) also could return the type yii\db\BaseActiveRecord which is incompatible with the return type mandated by yii\web\IdentityInterface::findIdentity() of yii\web\IdentityInterface.
Loading history...
157
    }
158
159
    /**
160
     * {@inheritdoc}
161
     * @param mixed $token
162
     * @param null $type
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $type is correct as it would always require null to be passed?
Loading history...
163
     * @return User|null|IdentityInterface
164
     */
165
    public static function findIdentityByAccessToken($token, $type = null)
166
    {
167
        return static::findOne(['auth_key' => $token, 'status' => self::STATUS_ACTIVE]);
0 ignored issues
show
Bug Best Practice introduced by
The expression return static::findOne(a...> self::STATUS_ACTIVE)) also could return the type yii\db\BaseActiveRecord which is incompatible with the return type mandated by yii\web\IdentityInterfac...IdentityByAccessToken() of yii\web\IdentityInterface.
Loading history...
168
    }
169
170
    /**
171
     * {@inheritdoc}
172
     * @return int|string
173
     */
174
    public function getId()
175
    {
176
        return $this->id;
177
    }
178
179
    /**
180
     * {@inheritdoc}
181
     * @return string
182
     */
183
    public function getAuthKey()
184
    {
185
        return $this->auth_key;
186
    }
187
188
    /**
189
     * {@inheritdoc}
190
     * @param string $authKey
191
     * @return bool
192
     */
193
    public function validateAuthKey($authKey)
194
    {
195
        return $this->getAuthKey() === $authKey;
196
    }
197
198
    /**
199
     * Generates "remember me" authentication key
200
     */
201
    public function generateAuthKey()
202
    {
203
        $this->auth_key = Yii::$app->security->generateRandomString();
204
    }
205
206
    /**
207
     * Generates email confirmation token
208
     */
209
    public function generateEmailConfirmToken()
210
    {
211
        $this->email_confirm_token = Yii::$app->security->generateRandomString();
212
    }
213
214
    /**
215
     * Finds out if password reset token is valid
216
     *
217
     * @param mixed $token password reset token
218
     * @return boolean
219
     */
220
    public static function isPasswordResetTokenValid($token)
221
    {
222
        if (empty($token)) {
223
            return false;
224
        }
225
        $expire = Module::$passwordResetTokenExpire;
226
        $parts = explode('_', $token);
227
        $timestamp = (int)end($parts);
228
        return $timestamp + $expire >= time();
229
    }
230
231
    /**
232
     * Finds user by password reset token
233
     *
234
     * @param mixed $token password reset token
235
     * @return static|null
236
     */
237
    public static function findByPasswordResetToken($token)
238
    {
239
        if (!static::isPasswordResetTokenValid($token)) {
240
            return null;
241
        }
242
        return static::findOne([
243
            'password_reset_token' => $token,
244
            'status' => self::STATUS_ACTIVE,
245
        ]);
246
    }
247
248
    /**
249
     * Generates password hash from password and sets it to the model
250
     *
251
     * @param string $password
252
     * @throws \yii\base\Exception
253
     */
254
    public function setPassword($password)
255
    {
256
        $this->password_hash = Yii::$app->security->generatePasswordHash($password);
257
    }
258
259
    /**
260
     * Removes password reset token
261
     */
262
    public function removePasswordResetToken()
263
    {
264
        $this->password_reset_token = null;
265
    }
266
267
    /**
268
     * Generates new password reset token
269
     */
270
    public function generatePasswordResetToken()
271
    {
272
        $this->password_reset_token = Yii::$app->security->generateRandomString() . '_' . time();
273
    }
274
275
    /**
276
     * Validates password
277
     *
278
     * @param string $password password to validate
279
     * @return bool if password provided is valid for current user
280
     */
281
    public function validatePassword($password)
282
    {
283
        return Yii::$app->security->validatePassword($password, $this->password_hash);
284
    }
285
286
    /**
287
     * Finds user by email
288
     *
289
     * @param string $email
290
     * @return array|null|ActiveRecord
291
     */
292
    public static function findByUsernameEmail($email)
293
    {
294
        return static::findOne(['email' => $email, 'status' => self::STATUS_ACTIVE]);
295
    }
296
297
    /**
298
     * Finds user by username or email
299
     *
300
     * @param string $string
301
     * @return array|null|ActiveRecord
302
     */
303
    public static function findByUsernameOrEmail($string)
304
    {
305
        return static::find()
306
            ->where(['or', ['username' => $string], ['email' => $string]])
307
            ->andWhere(['status' => self::STATUS_ACTIVE])
308
            ->one();
309
    }
310
311
    /**
312
     * @param mixed $email_confirm_token
313
     * @return bool|null|static
314
     */
315
    public static function findByEmailConfirmToken($email_confirm_token)
316
    {
317
        return static::findOne([
318
            'email_confirm_token' => $email_confirm_token,
319
            'status' => self::STATUS_WAIT
320
        ]);
321
    }
322
323
    /**
324
     * Removes email confirmation token
325
     */
326
    public function removeEmailConfirmToken()
327
    {
328
        $this->email_confirm_token = null;
329
    }
330
331
    /**
332
     * @return array
333
     */
334
    public static function getStatusesArray()
335
    {
336
        return [
337
            self::STATUS_BLOCKED => Module::t('module', 'Blocked'),
338
            self::STATUS_ACTIVE => Module::t('module', 'Active'),
339
            self::STATUS_WAIT => Module::t('module', 'Wait'),
340
            self::STATUS_DELETED => Module::t('module', 'Deleted'),
341
        ];
342
    }
343
344
    /**
345
     * @return array
346
     */
347
    public static function getLabelsArray()
348
    {
349
        return [
350
            self::STATUS_BLOCKED => 'default',
351
            self::STATUS_ACTIVE => 'success',
352
            self::STATUS_WAIT => 'warning',
353
            self::STATUS_DELETED => 'danger',
354
        ];
355
    }
356
357
    /**
358
     * @return mixed
359
     */
360
    public function getStatusName()
361
    {
362
        return ArrayHelper::getValue(self::getStatusesArray(), $this->status);
363
    }
364
365
    /**
366
     * Return <span class="label label-success">Active</span>
367
     * @return string
368
     */
369
    public function getStatusLabelName()
370
    {
371
        $name = ArrayHelper::getValue(self::getLabelsArray(), $this->status);
372
        return Html::tag('span', $this->getStatusName(), ['class' => 'label label-' . $name]);
373
    }
374
375
    /**
376
     * @param string $name
377
     * @return string
378
     */
379
    public function getLabelMailConfirm($name = 'default')
380
    {
381
        if ($this->status === self::STATUS_WAIT) {
382
            return Html::tag('span', Html::tag('span', '', [
383
                'class' => 'glyphicon glyphicon-envelope',
384
            ]), ['class' => 'label label-' . $name]);
385
        }
386
        return '';
387
    }
388
389
    /**
390
     * @return bool
391
     */
392
    public function sendConfirmEmail()
393
    {
394
        return Yii::$app->mailer->compose([
395
            'html' => '@modules/users/mail/emailConfirm-html',
396
            'text' => '@modules/users/mail/emailConfirm-text'
397
        ], ['user' => $this])
398
            ->setFrom([Yii::$app->params['supportEmail'] => Yii::$app->name])
399
            ->setTo($this->email)
400
            ->setSubject(Module::t('module', 'Account activation!') . ' ' . Yii::$app->name)
401
            ->send();
402
    }
403
404
    /**
405
     * Set Status
406
     * @return int|string
407
     */
408
    public function setStatus()
409
    {
410
        switch ($this->status) {
411
            case self::STATUS_ACTIVE:
412
                $this->status = self::STATUS_BLOCKED;
413
                break;
414
            case self::STATUS_DELETED:
415
                $this->status = self::STATUS_WAIT;
416
                break;
417
            default:
418
                $this->status = self::STATUS_ACTIVE;
419
        }
420
        return $this->status;
421
    }
422
423
    /**
424
     * @return string
425
     */
426
    public function getUserFullName()
427
    {
428
        $fullName = Module::t('module', 'Guest');
429
        if (!Yii::$app->user->isGuest) {
430
            $fullName = $this->profile->first_name . ' ' . $this->profile->last_name;
431
            $fullName = ($fullName != ' ') ? $fullName : $this->username;
432
        }
433
        return Html::encode(trim($fullName));
434
    }
435
436
    /**
437
     * @param integer|string $id
438
     * @return bool
439
     */
440
    public function isSuperAdmin($id = '')
441
    {
442
        $id = $id ? $id : $this->id;
443
        $authManager = Yii::$app->authManager;
444
        $roles = $authManager->getRolesByUser($id);
445
        foreach ($roles as $role) {
446
            if ($role->name == \modules\rbac\models\Role::ROLE_SUPER_ADMIN)
447
                return true;
448
        }
449
        return false;
450
    }
451
452
    /**
453
     * @return bool
454
     */
455
    public function isDeleted()
456
    {
457
        return $this->status === self::STATUS_DELETED;
458
    }
459
460
    /**
461
     * @param bool $insert
462
     * @return bool
463
     * @throws \yii\base\Exception
464
     */
465
    public function beforeSave($insert)
466
    {
467
        if (parent::beforeSave($insert)) {
468
            if ($insert) {
469
                $this->generateAuthKey();
470
            }
471
            if (!empty($this->newPassword)) {
0 ignored issues
show
Bug Best Practice introduced by
The property newPassword does not exist on modules\users\models\User. Since you implemented __get, consider adding a @property annotation.
Loading history...
472
                $this->setPassword($this->newPassword);
473
            }
474
            return true;
475
        }
476
        return false;
477
    }
478
479
    /**
480
     * @param bool $insert
481
     * @param array $changedAttributes
482
     */
483
    public function afterSave($insert, $changedAttributes)
484
    {
485
        if ($insert) {
486
            $profile = new UserProfile([
487
                'user_id' => $this->id,
488
                'email_gravatar' => $this->email
489
            ]);
490
            $profile->save();
491
        }
492
        parent::afterSave($insert, $changedAttributes);
493
    }
494
495
    /**
496
     * @return bool
497
     * @throws \Throwable
498
     * @throws \yii\db\StaleObjectException
499
     */
500
    public function beforeDelete()
501
    {
502
        if ($this->isDeleted()) {
503
            $this->profile->delete();
504
            // Отвязываем от ролей
505
            $authManager = Yii::$app->getAuthManager();
506
            if ($authManager->getRolesByUser($this->id)) {
507
                $authManager->revokeAll($this->id);
508
            }
509
        }
510
        return parent::beforeDelete();
511
    }
512
}
513