Passed
Push — master ( bfe1a8...0d4335 )
by Alexey
03:39
created

User::find()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 0
1
<?php
2
3
namespace modules\user\models;
4
5
use Yii;
6
use yii\behaviors\TimestampBehavior;
7
use yii\db\ActiveRecord;
8
use yii\web\IdentityInterface;
9
use yii\helpers\Html;
10
use yii\helpers\ArrayHelper;
11
use modules\user\models\query\UserQuery;
12
use modules\user\traits\ModuleTrait;
13
use modules\user\Module;
14
15
/**
16
 * Class User
17
 * @package modules\user\models
18
 *
19
 * This is the model class for table "{{%user}}".
20
 *
21
 * @property int $id ID
22
 * @property string $username Username
23
 * @property string $auth_key Authorization Key
24
 * @property string $password_hash Hash Password
25
 * @property string $password_reset_token Password Token
26
 * @property string $email_confirm_token Email Confirm Token
27
 * @property string $email Email
28
 * @property int|string $status Status
29
 * @property int $last_visit Last Visit
30
 * @property int $created_at Created
31
 * @property int $updated_at Updated
32
 * @property string $first_name First Name
33
 * @property string $last_name Last Name
34
 * @property int $registration_type Type Registration
35
 * @property string statusLabelName Status name in label
36
 * @property array statusesArray Array statuses
37
 * @property string statusName Name status
38
 * @property int|string registrationType Type registered
39
 */
40
class User extends ActiveRecord implements IdentityInterface
41
{
42
    use ModuleTrait;
43
44
    /**
45
     * Length password symbols min
46
     */
47
    const LENGTH_STRING_PASSWORD_MIN = 6;
48
49
    /**
50
     * Length password symbols max
51
     */
52
    const LENGTH_STRING_PASSWORD_MAX = 16;
53
54
    /**
55
     * Users Statuses
56
     */
57
    const STATUS_BLOCKED = 0;
58
    const STATUS_ACTIVE = 1;
59
    const STATUS_WAIT = 2;
60
    const STATUS_DELETED = 3;
61
62
    /**
63
     * Type of registration
64
     */
65
    const TYPE_REGISTRATION_SYSTEM = 0;
66
67
    /**
68
     * @inheritdoc
69
     * @return string
70
     */
71
    public static function tableName()
72
    {
73
        return '{{%user}}';
74
    }
75
76
    /**
77
     * @inheritdoc
78
     * @return array
79
     */
80
    public function behaviors()
81
    {
82
        return [
83
            'timestamp' => [
84
                'class' => TimestampBehavior::class,
85
            ],
86
        ];
87
    }
88
89
    /**
90
     * @inheritdoc
91
     * @return array
92
     */
93
    public function rules()
94
    {
95
        return [
96
            ['username', 'required'],
97
            ['username', 'match', 'pattern' => '#^[\w_-]+$#i'],
98
            ['username', 'unique', 'targetClass' => self::class, 'message' => Module::t('module', 'This username is already taken.')],
99
            ['username', 'string', 'min' => 2, 'max' => 255],
100
101
            ['email', 'required'],
102
            ['email', 'email'],
103
            ['email', 'unique', 'targetClass' => self::class, 'message' => Module::t('module', 'This email is already taken.')],
104
            ['email', 'string', 'max' => 255],
105
106
            ['first_name', 'string', 'max' => 45],
107
            ['last_name', 'string', 'max' => 45],
108
109
            ['registration_type', 'safe'],
110
111
            ['status', 'integer'],
112
            ['status', 'default', 'value' => self::STATUS_WAIT],
113
            ['status', 'in', 'range' => array_keys(self::getStatusesArray())],
114
        ];
115
    }
116
117
    /**
118
     * @inheritdoc
119
     * @return array
120
     */
121
    public function attributeLabels()
122
    {
123
        return [
124
            'id' => 'ID',
125
            'created_at' => Module::t('module', 'Created'),
126
            'updated_at' => Module::t('module', 'Updated'),
127
            'last_visit' => Module::t('module', 'Last Visit'),
128
            'username' => Module::t('module', 'Username'),
129
            'email' => Module::t('module', 'Email'),
130
            'auth_key' => Module::t('module', 'Auth Key'),
131
            'status' => Module::t('module', 'Status'),
132
            'first_name' => Module::t('module', 'First Name'),
133
            'last_name' => Module::t('module', 'Last Name'),
134
            'registration_type' => Module::t('module', 'Registration Type'),
135
        ];
136
    }
137
138
    /**
139
     * @return object|\yii\db\ActiveQuery
140
     * @throws \yii\base\InvalidConfigException
141
     */
142
    public static function find()
143
    {
144
        return Yii::createObject(UserQuery::class, [get_called_class()]);
145
    }
146
147
    /**
148
     * @inheritdoc
149
     * @param int|string $id
150
     * @return IdentityInterface|ActiveRecord
151
     */
152
    public static function findIdentity($id)
153
    {
154
        /** @var IdentityInterface $result */
155
        $result = static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);
156
        return $result;
157
    }
158
159
    /**
160
     * @inheritdoc
161
     * @param mixed $token
162
     * @param mixed $type
163
     * @return IdentityInterface|ActiveRecord|null
164
     */
165
    public static function findIdentityByAccessToken($token, $type = null)
166
    {
167
        /** @var IdentityInterface $result */
168
        if ($result = static::findOne(['auth_key' => $token, 'status' => self::STATUS_ACTIVE]))
169
            return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result returns the type yii\db\BaseActiveRecord which is incompatible with the return type mandated by yii\web\IdentityInterfac...IdentityByAccessToken() of yii\web\IdentityInterface.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
170
        return null;
171
    }
172
173
    /**
174
     * Finds user by username
175
     *
176
     * @param string $username
177
     * @return static|null|ActiveRecord
178
     */
179
    public static function findByUsername($username)
180
    {
181
        if ($result = static::findOne(['username' => $username, 'status' => self::STATUS_ACTIVE]))
182
            return $result;
183
        return null;
184
    }
185
186
    /**
187
     * Finds user by email
188
     *
189
     * @param string $email
190
     * @return array|null|ActiveRecord
191
     */
192
    public static function findByUsernameEmail($email)
193
    {
194
        if ($result = static::findOne(['email' => $email, 'status' => self::STATUS_ACTIVE]))
195
            return $result;
196
        return null;
197
    }
198
199
    /**
200
     * Finds user by username or email
201
     *
202
     * @param string $string
203
     * @return array|null|ActiveRecord
204
     */
205
    public static function findByUsernameOrEmail($string)
206
    {
207
        if ($result = static::find()
208
            ->where(['or', ['username' => $string], ['email' => $string]])
209
            ->andWhere(['status' => self::STATUS_ACTIVE])
210
            ->one())
211
            return $result;
212
        return null;
213
    }
214
215
    /**
216
     * Generates password hash from password and sets it to the model
217
     *
218
     * @param string $password
219
     * @throws \yii\base\Exception
220
     */
221
    public function setPassword($password)
222
    {
223
        $this->password_hash = Yii::$app->security->generatePasswordHash($password);
224
    }
225
226
    /**
227
     * Generates "remember me" authentication key
228
     */
229
    public function generateAuthKey()
230
    {
231
        $this->auth_key = Yii::$app->security->generateRandomString();
232
    }
233
234
    /**
235
     * Generates new password reset token
236
     */
237
    public function generatePasswordResetToken()
238
    {
239
        $this->password_reset_token = Yii::$app->security->generateRandomString() . '_' . time();
240
    }
241
242
    /**
243
     * Removes password reset token
244
     */
245
    public function removePasswordResetToken()
246
    {
247
        $this->password_reset_token = null;
248
    }
249
250
    /**
251
     * Removes email confirmation token
252
     */
253
    public function removeEmailConfirmToken()
254
    {
255
        $this->email_confirm_token = null;
256
    }
257
258
    /**
259
     * Finds user by password reset token
260
     *
261
     * @param mixed $token password reset token
262
     * @return static|null
263
     */
264
    public static function findByPasswordResetToken($token)
265
    {
266
        if (!static::isPasswordResetTokenValid($token)) {
267
            return null;
268
        }
269
        return static::findOne([
270
            'password_reset_token' => $token,
271
            'status' => self::STATUS_ACTIVE,
272
        ]);
273
    }
274
275
    /**
276
     * @param mixed $email_confirm_token
277
     * @return bool|null|static
278
     */
279
    public static function findByEmailConfirmToken($email_confirm_token)
280
    {
281
        return static::findOne([
282
            'email_confirm_token' => $email_confirm_token,
283
            'status' => self::STATUS_WAIT
284
        ]);
285
    }
286
287
    /**
288
     * Generates email confirmation token
289
     */
290
    public function generateEmailConfirmToken()
291
    {
292
        $this->email_confirm_token = Yii::$app->security->generateRandomString();
293
    }
294
295
    /**
296
     * @return integer
297
     */
298
    public function getId()
299
    {
300
        return $this->id;
301
    }
302
303
    /**
304
     * @return string current user auth key
305
     */
306
    public function getAuthKey()
307
    {
308
        return $this->auth_key;
309
    }
310
311
    /**
312
     * @param string|mixed $authKey
313
     * @return bool if auth key is valid for current user
314
     */
315
    public function validateAuthKey($authKey)
316
    {
317
        return $this->getAuthKey() === $authKey;
318
    }
319
320
    /**
321
     * Validates password
322
     *
323
     * @param string $password password to validate
324
     * @return bool if password provided is valid for current user
325
     */
326
    public function validatePassword($password)
327
    {
328
        return Yii::$app->security->validatePassword($password, $this->password_hash);
329
    }
330
331
    /**
332
     * Type of registration
333
     * How the user is created
334
     * If the system registration type is registered by itself,
335
     * if it is created from the admin area,
336
     * then the login type that created the account
337
     *
338
     * @return mixed|string
339
     */
340
    public function getRegistrationType()
341
    {
342
        if ($this->registration_type > 0) {
343
            if (($model = User::findOne($this->registration_type)) !== null) {
344
                return $model->username;
345
            }
346
        }
347
        return $this->getRegistrationTypeName();
348
    }
349
350
    /**
351
     * Returns the registration type string
352
     * @return mixed
353
     */
354
    public function getRegistrationTypeName()
355
    {
356
        return ArrayHelper::getValue(self::getRegistrationTypesArray(), $this->registration_type);
357
    }
358
359
    /**
360
     * Returns an array of log types
361
     * @return array
362
     */
363
    public static function getRegistrationTypesArray()
364
    {
365
        return [
366
            self::TYPE_REGISTRATION_SYSTEM => Module::t('module', 'System'),
367
        ];
368
    }
369
370
    /**
371
     * Actions before saving
372
     *
373
     * @param bool $insert
374
     * @return bool
375
     */
376
    public function beforeSave($insert)
377
    {
378
        if (parent::beforeSave($insert)) {
379
            if ($insert) {
380
                $this->generateAuthKey();
381
            }
382
            return true;
383
        }
384
        return false;
385
    }
386
387
    /**
388
     * @return array
389
     */
390
    public static function getStatusesArray()
391
    {
392
        return [
393
            self::STATUS_BLOCKED => Module::t('module', 'Blocked'),
394
            self::STATUS_ACTIVE => Module::t('module', 'Active'),
395
            self::STATUS_WAIT => Module::t('module', 'Wait'),
396
            self::STATUS_DELETED => Module::t('module', 'Deleted'),
397
        ];
398
    }
399
400
    /**
401
     * Set Status
402
     * @return int|string
403
     */
404
    public function setStatus()
405
    {
406
        switch ($this->status) {
407
            case self::STATUS_ACTIVE:
408
                $this->status = self::STATUS_BLOCKED;
409
                break;
410
            case self::STATUS_DELETED:
411
                $this->status = self::STATUS_WAIT;
412
                break;
413
            default:
414
                $this->status = self::STATUS_ACTIVE;
415
        }
416
        return $this->status;
417
    }
418
419
    /**
420
     * @return mixed
421
     */
422
    public function getStatusName()
423
    {
424
        return ArrayHelper::getValue(self::getStatusesArray(), $this->status);
425
    }
426
427
    /**
428
     * Return <span class="label label-success">Active</span>
429
     * @return string
430
     */
431
    public function getStatusLabelName()
432
    {
433
        $name = ArrayHelper::getValue(self::getLabelsArray(), $this->status);
434
        return Html::tag('span', $this->getStatusName(), ['class' => 'label label-' . $name]);
435
    }
436
437
    /**
438
     * @return array
439
     */
440
    public static function getLabelsArray()
441
    {
442
        return [
443
            self::STATUS_BLOCKED => 'default',
444
            self::STATUS_ACTIVE => 'success',
445
            self::STATUS_WAIT => 'warning',
446
            self::STATUS_DELETED => 'danger',
447
        ];
448
    }
449
450
    /**
451
     * @return bool
452
     */
453
    public function isDeleted()
454
    {
455
        return $this->status === self::STATUS_DELETED;
456
    }
457
458
    /**
459
     * Finds out if password reset token is valid
460
     *
461
     * @param mixed $token password reset token
462
     * @return boolean
463
     */
464
    public static function isPasswordResetTokenValid($token)
465
    {
466
        if (empty($token)) {
467
            return false;
468
        }
469
        $expire = Yii::$app->params['user.passwordResetTokenExpire'];
470
        $parts = explode('_', $token);
471
        $timestamp = (int)end($parts);
472
        return $timestamp + $expire >= time();
473
    }
474
}
475