Completed
Push — master ( 2a55a2...8b8a64 )
by Igor
05:27
created

User::addProvider()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 6
ccs 5
cts 5
cp 1
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
crap 1
1
<?php
2
3
namespace app\models;
4
5
use Yii;
6
use yii\base\NotSupportedException;
7
use yii\db\ActiveRecord;
8
use yii\web\IdentityInterface;
9
use yii\behaviors\TimestampBehavior;
10
use app\models\UserProfile;
11
use app\models\UserProvider;
12
use app\models\query\UserQuery;
13
14
/**
15
 * This is the model class for table "user".
16
 *
17
 * @property integer $id
18
 * @property string $username
19
 * @property string $email
20
 * @property string $password
21
 * @property string $password_reset_token
22
 * @property string $email_confirm_token
23
 * @property string $auth_key
24
 * @property string $date_confirm
25
 * @property string $date_create
26
 * @property string $date_update
27
 * @property string $date_login
28
 * @property integer $ip
29
 * @property string $role
30
 * @property integer $status
31
 */
32
class User extends \yii\db\ActiveRecord implements IdentityInterface
33
{
34
    const STATUS_DELETED = 0;
35
    const STATUS_ACTIVE  = 1;
36
    const STATUS_BLOCKED = 2;
37
38
    const ROLE_SUPERUSER = 'SuperUser';
39
40
    /**
41
     * @var string
42
     */
43
    public $passwordNew;
44
45
    /**
46
     * @inheritdoc
47
     */
48 284
    public static function tableName()
49
    {
50 284
        return 'user';
51
    }
52
53
    /**
54
     * @inheritdoc
55
     */
56 26
    public function rules()
57
    {
58
        return [
59 26
            ['username', 'string', 'min' => 3, 'max' => 40],
60
            ['username', 'match', 'pattern' => '/^[a-zA-Z0-9_-]+$/'],
61
            ['username', 'unique'],
62
            ['username', 'default', 'value' => null],
63
64
            ['email', 'email'],
65
            ['email', 'string', 'max' => 255],
66
            ['email', 'unique'],
67
            ['email', 'default', 'value' => null],
68
69
            ['status', 'integer'],
70 26
            ['status', 'default', 'value' => self::STATUS_ACTIVE],
71 26
            ['status', 'in', 'range' => array_keys(self::getStatuses())],
72
        ];
73
    }
74
75
    /**
76
     * @inheritdoc
77
     */
78 118
    public function attributeLabels()
79
    {
80
        return [
81 118
            'id' => Yii::t('app', 'ID'),
82 118
            'username' => Yii::t('app', 'Username'),
83 118
            'email' => Yii::t('app', 'Email'),
84 118
            'password' => Yii::t('app', 'Password'),
85 118
            'date_create' => Yii::t('app', 'Date create'),
86 118
            'date_update' => Yii::t('app', 'Date update'),
87 118
            'date_login' => Yii::t('app', 'Last login'),
88 118
            'ip' => Yii::t('app', 'IP'),
89 118
            'role' => Yii::t('app', 'Role'),
90 118
            'status' => Yii::t('app', 'Status'),
91
92 118
            'passwordNew' => Yii::t('app', 'New password'),
93
        ];
94
    }
95
96
    /**
97
     * @inheritdoc
98
     * @codeCoverageIgnore
99
     */
100
    public function attributeHints()
101
    {
102
        return [
103
            'username' => Yii::t('app.validators', 'Only letters, numbers, symbols _ and -'),
104
            'passwordNew' => Yii::t('app.validators', 'Set a new password')
105
        ];
106
    }
107
108
    /**
109
     * @inheritdoc
110
     */
111 268
    public function behaviors()
112
    {
113
        return [
114
            [
115 268
                'class' => TimestampBehavior::className(),
116 268
                'createdAtAttribute' => 'date_create',
117 268
                'updatedAtAttribute' => 'date_update',
118 268
                'value' => new \yii\db\Expression('NOW()'),
119
            ],
120
        ];
121
    }
122
123
    /**
124
     * @inheritdoc
125
     * @codeCoverageIgnore
126
     */
127
    public function events()
128
    {
129
        return [
130
            ActiveRecord::EVENT_BEFORE_DELETE => 'beforeDelete',
131
        ];
132
    }
133
134 31
    public function transactions()
135
    {
136
        return [
137 31
            'create' => self::OP_ALL,
138 31
            'update' => self::OP_ALL,
139 31
            'delete' => self::OP_ALL,
140
        ];
141
    }
142
143
    /**
144
     * @return \yii\db\ActiveQuery
145
     */
146 31
    public function getProfile()
147
    {
148 31
        return $this->hasOne(UserProfile::className(), ['user_id' => 'id']);
149
    }
150
151
    /**
152
     * @param array $attributes
153
     */
154 18
    public function setProfile($attributes = [])
155
    {
156 18
        return $this->populateRelation('profile', new UserProfile($attributes));
157
    }
158
159
    /**
160
     * @return \yii\db\ActiveQuery
161
     */
162 30
    public function getProviders()
163
    {
164 30
        return $this->hasMany(UserProvider::className(), ['user_id' => 'id']);
165
    }
166
167
    /**
168
     * @param array $attributes
169
     */
170 6
    public function setProviders($attributes = [])
171
    {
172 6
        return $this->populateRelation('providers', [new UserProvider($attributes)]);
173
    }
174
175
    /**
176
     * @return \yii\db\ActiveQuery
177
     */
178 33
    public function getRoles()
179
    {
180 33
        return $this->hasOne(AuthItem::className(), ['name' => 'role']);
181
    }
182
183
    /**
184
     * @inheritdoc
185
     * @return UserQuery
186
     */
187 240
    public static function find()
188
    {
189 240
        return new UserQuery(get_called_class());
190
    }
191
192
    /**
193
     * @inheritdoc
194
     */
195 28
    public function beforeSave($insert)
196
    {
197 28
        if (parent::beforeSave($insert)) {
198 28
            if ($insert) {
199 18
                $this->generateAuthKey();
200 18
                if (!Yii::$app instanceof \yii\console\Application) {
201 18
                    $this->ip = ip2long(Yii::$app->request->getUserIP());
202
                }
203
204 18
                if ($this->profile === null) {
205 8
                    $this->setProfile();
206
                }
207
            }
208
209 28
            if (!empty($this->passwordNew)) {
210 3
                $this->setPassword($this->passwordNew);
211
            }
212
213 28
            return true;
214
        } // @codeCoverageIgnore
215
216
        return false; // @codeCoverageIgnore
217
    }
218
219
    /**
220
     * @inheritdoc
221
     * @property \app\models\UserProfile $profile
222
     * @property \app\models\UserProvider $providers
223
     */
224 28
    public function afterSave($insert, $changedAttributes)
225
    {
226 28
        parent::afterSave($insert, $changedAttributes);
227
228 28
        if ($this->profile !== null) {
229 20
            $this->link('profile', $this->profile);
230
        }
231
232 28
        if ($this->providers !== null && count($this->providers)) {
233 6
            foreach ($this->providers as $provider) {
234 6
                if ($provider) {
235 6
                    $this->link('providers', $provider);
236
                }
237
            }
238
        }
239 28
    }
240
241
    /**
242
     * @inheritdoc
243
     * @param boolean $runValidation
244
     * @param array $attributeNames
245
     * @return boolean
246
     */
247
    public function save($runValidation = true, $attributeNames = null)
248
    {
249 30
        return $this->getDb()->transaction(function () use ($runValidation, $attributeNames) {
250 30
            return parent::save($runValidation, $attributeNames);
251 30
        });
252
    }
253
254
    /**
255
     * Get all statuses
256
     *
257
     * @param string[]
258
     */
259 52
    public static function getStatuses()
260
    {
261
        return [
262 52
            self::STATUS_DELETED => Yii::t('app', 'Deleted'),
263 52
            self::STATUS_BLOCKED => Yii::t('app', 'Locked'),
264 52
            self::STATUS_ACTIVE  => Yii::t('app', 'Active'),
265
        ];
266
    }
267
268
    /**
269
     * Get statuse name
270
     *
271
     * @return string
272
     */
273 35
    public function getStatusName()
274
    {
275 35
        $statuses = self::getStatuses();
276 35
        return isset($statuses[$this->status]) ? $statuses[$this->status] : '';
277
    }
278
279
    /**
280
     * Is it deleted?
281
     *
282
     * @param bool
283
     */
284 2
    public function isDeleted()
285
    {
286 2
        return $this->status == self::STATUS_DELETED;
287
    }
288
289
    /**
290
     * Is it blocked?
291
     *
292
     * @param bool
293
     */
294 2
    public function isBlocked()
295
    {
296 2
        return $this->status == self::STATUS_BLOCKED;
297
    }
298
299
    /**
300
     * Is it active?
301
     *
302
     * @param bool
303
     */
304 174
    public function isActive()
305
    {
306 174
        return $this->status == self::STATUS_ACTIVE;
307
    }
308
309
    /**
310
     * Is it confirmed?
311
     *
312
     * @param bool
313
     */
314 25
    public function isConfirmed()
315
    {
316 25
        return strtotime($this->date_confirm) > 0;
317
    }
318
319
    /**
320
     * Set confirmed
321
     */
322 8
    public function setConfirmed()
323
    {
324 8
        $this->email_confirm_token = null;
325 8
        $this->date_confirm = new \yii\db\Expression('NOW()');
326 8
    }
327
328
    /**
329
     * Get status description
330
     *
331
     * @return string
332
     */
333 12
    public function getStatusDescription()
334
    {
335 12
        if ($this->status == self::STATUS_BLOCKED) {
336 6
            return Yii::t('app', 'Your account has been suspended');
337 6
        } elseif ($this->status == self::STATUS_DELETED) {
338 5
            return Yii::t('app', 'Your account has been deleted');
339
        }
340 1
        return Yii::t('app', 'Your account is activated');
341
    }
342
343
    /**
344
     * Is SuperUser?
345
     *
346
     * @return bool
347
     */
348 151
    public function isSuperUser()
349
    {
350 151
        return $this->role === self::ROLE_SUPERUSER;
351
    }
352
353
    /**
354
     * @inheritdoc
355
     */
356 171
    public function getId()
357
    {
358 171
        return $this->id;
359
    }
360
361
    /**
362
     * @inheritdoc
363
     */
364 2
    public function getAuthKey()
365
    {
366 2
        return $this->auth_key;
367
    }
368
369
    /**
370
     * @inheritdoc
371
     */
372 2
    public function validateAuthKey($authKey)
373
    {
374 2
        return $this->getAuthKey() === $authKey;
375
    }
376
377
    /**
378
     * Generates "remember me" authentication key
379
     */
380 19
    public function generateAuthKey()
381
    {
382 19
        $this->auth_key = Yii::$app->security->generateRandomString();
383 19
    }
384
385
    /**
386
     * Validates password
387
     *
388
     * @param string $password password to validate
389
     * @return boolean if password provided is valid for current user
390
     */
391 28
    public function validatePassword($password)
392
    {
393 28
        if (empty($this->password)) {
394 1
            return false;
395
        }
396
397 28
        return Yii::$app->security->validatePassword($password, $this->password);
398
    }
399
400
    /**
401
     * Generates password hash from password and sets it to the model
402
     *
403
     * @param string $password
404
     */
405 14
    public function setPassword($password)
406
    {
407 14
        $this->password = Yii::$app->security->generatePasswordHash($password);
408 14
    }
409
410
    /**
411
     * Generate new token
412
     */
413 18
    public function generateToken()
414
    {
415 18
        return Yii::$app->security->generateRandomString() . '_' . time();
416
    }
417
418
    /**
419
     * Authorize user
420
     *
421
     * @param bool $rememberMe
422
     * @return bool
423
     */
424 19
    public function authorize($rememberMe = false)
425
    {
426 19
        $this->updateAttributes([
427 19
            'date_login' => new \yii\db\Expression('NOW()'),
428 19
            'ip' => ip2long(Yii::$app->request->getUserIP())
429
        ]);
430
431 19
        return Yii::$app->user->login($this, $rememberMe ? 3600 * 24 * 30 : 0);
432
    }
433
434
    /**
435
     * Finds out if token is valid
436
     *
437
     * @param string $token
438
     * @return boolean
439
     */
440 28
    public static function isTokenValid($token)
441
    {
442 28
        if (empty($token)) {
443 9
            return false;
444
        }
445
446 20
        $expire = Yii::$app->params['user.tokenExpire'];
447 20
        $parts = explode('_', $token);
448 20
        $timestamp = (int) end($parts);
449
450 20
        return $timestamp + $expire >= time();
451
    }
452
453
    /**
454
     * Generates new password reset token
455
     */
456 1
    public function generatePasswordResetToken()
457
    {
458 1
        $this->password_reset_token = self::generateToken();
459 1
    }
460
461
    /**
462
     * Removes password reset token
463
     */
464 2
    public function removePasswordResetToken()
465
    {
466 2
        $this->password_reset_token = null;
467 2
    }
468
469
    /**
470
     * Finds user by password reset token
471
     *
472
     * @param string $token password reset token
473
     * @return app\models\User|null
474
     */
475 10
    public static function findByPasswordResetToken($token)
476
    {
477 10
        if (!static::isTokenValid($token)) {
478 2
            return null;
479
        }
480
481 9
        return static::findOne([
482 9
            'password_reset_token' => $token,
483 9
            'status' => self::STATUS_ACTIVE,
484
        ]);
485
    }
486
487
    /**
488
     * Generates new confirm email token
489
     */
490 17
    public function generateEmailConfirmToken()
491
    {
492 17
        $this->email_confirm_token = self::generateToken();
493 17
        $this->date_confirm = null;
494 17
    }
495
496
    /**
497
     * Finds user by confirm email token
498
     *
499
     * @param string $token confirm email token
500
     * @return app\models\User|null
501
     */
502 4
    public static function findByEmailConfirmToken($token)
503
    {
504 4
        if (!static::isTokenValid($token)) {
505 2
            return null;
506
        }
507
508 2
        return static::findOne([
509 2
            'email_confirm_token' => $token,
510 2
            'status' => self::STATUS_ACTIVE,
511
        ]);
512
    }
513
514
    /**
515
     * @inheritdoc
516
     */
517 158
    public static function findIdentity($id)
518
    {
519 158
        return static::findOne([$id]);
520
    }
521
522
    /**
523
     * @inheritdoc
524
     */
525 1
    public static function findIdentityByAccessToken($token, $type = null)
526
    {
527 1
        throw new NotSupportedException('findIdentityByAccessToken is not implemented.');
528
    }
529
530
    /**
531
     * Finds user by username
532
     *
533
     * @param string $username
534
     * @return app\models\User|null
535
     */
536 164
    public static function findByUsername($username)
537
    {
538 164
        return static::findOne(['username' => $username]);
539
    }
540
541
    /**
542
     * Finds user by email
543
     *
544
     * @param string $email
545
     * @return app\models\User|null
546
     */
547 38
    public static function findByEmail($email)
548
    {
549 38
        return static::findOne(['email' => $email]);
550
    }
551
552
    /**
553
     * @return bool
554
     */
555 3
    public function beforeDelete()
556
    {
557 3
        Yii::$app->authManager->revokeAll($this->id);
558
559 3
        if ($this->profile !== null) {
560 3
            $this->profile->delete();
561
        }
562
563 3
        return true;
564
    }
565
}
566