User::getAuthKey()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
namespace app\models;
4
5
use Yii;
6
use yii\helpers\ArrayHelper;
7
use yii\web\IdentityInterface;
8
use yii\rbac\Role as BaseRole;
9
use Itstructure\AdminModule\interfaces\AdminMenuInterface;
10
use Itstructure\AdminModule\models\ActiveRecord;
11
use Itstructure\RbacModule\interfaces\RbacIdentityInterface;
12
use Itstructure\MFUploader\behaviors\BehaviorMediafile;
13
use Itstructure\MFUploader\models\Mediafile;
14
use Itstructure\MFUploader\interfaces\UploadModelInterface;
15
use app\traits\ThumbnailTrait;
16
17
/**
18
 * Class User model.
19
 *
20
 * @property int $id
21
 * @property int $order
22
 * @property int $public
23
 * @property int $minOrder
24
 * @property int $maxOrder
25
 * @property string $first_name
26
 * @property string $last_name
27
 * @property string $patronymic
28
 * @property string $login
29
 * @property string $email
30
 * @property string $phone
31
 * @property string  $passwordRepeat Password confirmed.
32
 * @property int|string  $thumbnail Thumbnail(mediafile id or url).
33
 * @property array|null|\yii\db\ActiveRecord|Mediafile $thumbnailModel
34
 * @property Position $position
35
 *
36
 * @package app\models
37
 */
38
class User extends ActiveRecord implements RbacIdentityInterface, AdminMenuInterface
39
{
40
    use ThumbnailTrait;
0 ignored issues
show
Bug introduced by
The trait app\traits\ThumbnailTrait requires the property $alt which is not provided by app\models\User.
Loading history...
41
42
    /**
43
     * Password confirmed.
44
     *
45
     * @var string
46
     */
47
    public $passwordRepeat;
48
49
    /**
50
     * Thumbnail(mediafile id or url).
51
     *
52
     * @var int|string
53
     */
54
    public $thumbnail;
55
56
    /**
57
     * @inheritdoc
58
     */
59
    public static function tableName()
60
    {
61
        return 'users';
62
    }
63
64
    /**
65
     * @inheritdoc
66
     */
67
    public function rules()
68
    {
69
        return [
70
            [
71
                [
72
                    'created_at',
73
                    'updated_at',
74
                ],
75
                'safe',
76
            ],
77
            [
78
                [
79
                    'first_name',
80
                    'login',
81
                    'email',
82
                ],
83
                'required',
84
            ],
85
            [
86
                [
87
                    'status',
88
                    'public',
89
                    'order',
90
                    'position_id',
91
                ],
92
                'integer',
93
            ],
94
            [
95
                [
96
                    'first_name',
97
                    'last_name',
98
                    'patronymic',
99
                    'login',
100
                    'email',
101
                    'phone',
102
                    'hashedPassword',
103
                ],
104
                'string',
105
                'max' => 255,
106
            ],
107
            [
108
                [
109
                    'about',
110
                ],
111
                'string',
112
            ],
113
            [
114
                'login',
115
                'unique',
116
            ],
117
            [
118
                'email',
119
                'unique',
120
            ],
121
            [
122
                'email',
123
                'email',
124
            ],
125
            [
126
                UploadModelInterface::FILE_TYPE_THUMB,
127
                function($attribute) {
128
                    if (!is_numeric($this->{$attribute}) && !is_string($this->{$attribute})) {
129
                        $this->addError($attribute, 'Tumbnail content must be a numeric or string.');
130
                    }
131
                },
132
                'skipOnError' => false,
133
            ],
134
            [
135
                [
136
                    'position_id'
137
                ],
138
                'exist',
139
                'skipOnError' => true,
140
                'targetClass' => Position::class,
141
                'targetAttribute' => ['position_id' => 'id']
142
            ],
143
        ];
144
    }
145
146
    /**
147
     * @inheritdoc
148
     */
149
    public function behaviors()
150
    {
151
        return ArrayHelper::merge(parent::behaviors(), [
152
            'mediafile' => [
153
                'class' => BehaviorMediafile::class,
154
                'name' => static::tableName(),
155
                'attributes' => [
156
                    UploadModelInterface::FILE_TYPE_THUMB,
157
                ],
158
            ],
159
        ]);
160
    }
161
162
    /**
163
     * @return array
164
     */
165
    public function attributes()
166
    {
167
        return ArrayHelper::merge(parent::attributes(), [
168
            UploadModelInterface::FILE_TYPE_THUMB,
169
        ]);
170
    }
171
172
    /**
173
     * @inheritdoc
174
     */
175
    public function attributeLabels()
176
    {
177
        return [
178
            'id' => 'ID',
179
            'first_name' => Yii::t('users', 'First Name'),
180
            'login' => Yii::t('users', 'Login'),
181
            'email' => Yii::t('users', 'Email'),
182
            'password' => Yii::t('users', 'Password'),
183
            'passwordRepeat' => Yii::t('users', 'Password confirm'),
184
            'created_at' => Yii::t('app', 'Created date'),
185
            'updated_at' => Yii::t('app', 'Updated date'),
186
            UploadModelInterface::FILE_TYPE_THUMB => Yii::t('users', 'Avatar'),
187
        ];
188
    }
189
190
    /**
191
     * @return \yii\db\ActiveQuery|Position
192
     */
193
    public function getPosition()
194
    {
195
        return $this->hasOne(Position::class, [
196
            'id' => 'position_id'
197
        ]);
198
    }
199
200
    /**
201
     * @return array|\yii\db\ActiveRecord[]
202
     */
203
    public static function getPublicUsers()
204
    {
205
        return static::find()
206
            ->where([
207
                'public' => 1
208
            ])->orderBy([
209
                'order' => SORT_ASC
210
            ])->all();
211
    }
212
213
    /**
214
     * Find user by login.
215
     *
216
     * @param string $login
217
     *
218
     * @return User|null
219
     */
220
    public static function findByLogin($login)
221
    {
222
        return static::findOne([
223
            'login' => $login,
224
        ]);
225
    }
226
227
    /**
228
     * Finds an identity by the given ID.
229
     *
230
     * @param string|int $id the ID to be looked for
231
     *
232
     * @return IdentityInterface the identity object that matches the given ID.
233
     * Null should be returned if such an identity cannot be found
234
     * or the identity is not in an active state (disabled, deleted, etc.)
235
     */
236
    public static function findIdentity($id)
237
    {
238
        return static::findOne($id);
0 ignored issues
show
Bug Best Practice introduced by
The expression return static::findOne($id) returns the type yii\db\ActiveRecord which is incompatible with the documented return type yii\web\IdentityInterface.
Loading history...
239
    }
240
241
    /**
242
     * Finds an identity by the given token.
243
     *
244
     * @param mixed $token the token to be looked for
245
     *
246
     * @param mixed $type  the type of the token. The value of this parameter depends on the
247
     *                     implementation. For example, [[\yii\filters\auth\HttpBearerAuth]] will
248
     *                     set this parameter to be `yii\filters\auth\HttpBearerAuth`.
249
     *
250
     * @return IdentityInterface the identity object that matches the given token.
251
     * Null should be returned if such an identity cannot be found
252
     * or the identity is not in an active state (disabled, deleted, etc.)
253
     */
254
    public static function findIdentityByAccessToken($token, $type = null)
255
    {
256
        return null;
257
    }
258
259
    /**
260
     * Returns an ID that can uniquely identify a user identity.
261
     *
262
     * @return string|int an ID that uniquely identifies a user identity.
263
     */
264
    public function getId()
265
    {
266
        return $this->id;
267
    }
268
269
    /**
270
     * Returns a key that can be used to check the validity of a given identity ID.
271
     *
272
     * The key should be unique for each individual user, and should be persistent
273
     * so that it can be used to check the validity of the user identity.
274
     *
275
     * The space of such keys should be big enough to defeat potential identity attacks.
276
     *
277
     * This is required if [[User::enableAutoLogin]] is enabled.
278
     *
279
     * @return string a key that is used to check the validity of a given identity ID.
280
     *
281
     * @see validateAuthKey()
282
     */
283
    public function getAuthKey()
284
    {
285
        return '';
286
    }
287
288
    /**
289
     * Validates the given auth key.
290
     *
291
     * This is required if [[User::enableAutoLogin]] is enabled.
292
     *
293
     * @param string $authKey the given auth key
294
     *
295
     * @return bool whether the given auth key is valid.
296
     *
297
     * @see getAuthKey()
298
     */
299
    public function validateAuthKey($authKey)
300
    {
301
        return true;
302
    }
303
304
    /**
305
     * Return user's full name.
306
     *
307
     * @return string
308
     */
309
    public function getFullName(): string
310
    {
311
        return $this->first_name . ' ' . $this->last_name;
312
    }
313
314
    /**
315
     * Return user's name.
316
     *
317
     * @return string
318
     */
319
    public function getUserName(): string
320
    {
321
        return $this->first_name;
322
    }
323
324
    /**
325
     * Return role name of user, e.g. "Admin" or "Web Developer"
326
     *
327
     * @return string
328
     */
329
    public function getRoleName(): string
330
    {
331
        return implode(', ', array_keys($this->getRoles()));
332
    }
333
334
    /**
335
     * List of profile assigned roles.
336
     *
337
     * @return BaseRole[]
338
     */
339
    public function getRoles()
340
    {
341
        return Yii::$app->authManager->getRolesByUser($this->getId());
0 ignored issues
show
Bug introduced by
The method getRolesByUser() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

341
        return Yii::$app->authManager->/** @scrutinizer ignore-call */ getRolesByUser($this->getId());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
342
    }
343
344
    /**
345
     * Return the date when user was registered (sign-up).
346
     *
347
     * @return \DateTime
348
     */
349
    public function getRegisterDate()
350
    {
351
        return new \DateTime($this->created_at);
0 ignored issues
show
Bug Best Practice introduced by
The property created_at does not exist on app\models\User. Since you implemented __get, consider adding a @property annotation.
Loading history...
352
    }
353
354
    /**
355
     * Does the user have an avatar.
356
     *
357
     * @return boolean
358
     */
359
    public function hasAvatar(): bool
360
    {
361
        return $this->getThumbnailModel() !== null;
362
    }
363
364
    /**
365
     * Return a link to avatar image.
366
     *
367
     * @return string
368
     */
369
    public function getAvatar(): string
370
    {
371
        $defaultThumbUrl = $this->getDefaultThumbUrl();
372
373
        return empty($defaultThumbUrl) ? '' : $defaultThumbUrl;
374
    }
375
376
    /**
377
     * Set hashed password.
378
     *
379
     * @param string $password.
380
     *
381
     * @return $this
382
     */
383
    public function setPassword($password)
384
    {
385
        if (!empty($password)) {
386
            $this->hashedPassword = $this->generateHash($password);
0 ignored issues
show
Bug Best Practice introduced by
The property hashedPassword does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
387
        }
388
389
        return $this;
390
    }
391
392
    /**
393
     * Validate password.
394
     *
395
     * @param string $password.
396
     *
397
     * @return bool.
0 ignored issues
show
Documentation Bug introduced by
The doc comment bool. at position 0 could not be parsed: Unknown type name 'bool.' at position 0 in bool..
Loading history...
398
     */
399
    public function validatePassword($password)
400
    {
401
        return Yii::$app->getSecurity()
402
            ->validatePassword($password, $this->hashedPassword);
403
    }
404
405
    /**
406
     * @return int
407
     */
408
    public function getMinOrder(): int
409
    {
410
        $result = static::find()
411
            ->select('order')
412
            ->orderBy('order ASC')
413
            ->one();
414
415
        return $result == null ? 1 : $result->order;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result == null ? 1 : $result->order could return the type null which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
416
    }
417
418
    /**
419
     * @return int
420
     */
421
    public function getMaxOrder(): int
422
    {
423
        $result = static::find()
424
            ->select('order')
425
            ->orderBy('order DESC')
426
            ->one();
427
428
        return $result == null ? 1 : $result->order;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result == null ? 1 : $result->order could return the type null which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
429
    }
430
431
    /**
432
     * @param int $order
433
     */
434
    public function moveOrder(int $order): void
435
    {
436
        if ($order == $this->order){
437
            return;
438
        }
439
440
        /* @var static $future */
441
        $future = static::find()
442
            ->where([
443
                'order' => $order
444
            ])
445
            ->one();
446
        $future->detachBehavior('mediafile');
447
        $future->order = $order > $this->order ? $order-1 : $order+1;
448
        $future->save();
449
450
        $this->detachBehavior('mediafile');
451
        $this->order = $order;
452
        $this->save();
453
    }
454
455
    /**
456
     * @param bool $insert
457
     *
458
     * @return bool
459
     */
460
    public function beforeSave($insert)
461
    {
462
        if ($this->isNewRecord){
463
            $this->order = $this->maxOrder == null ? 1 : $this->maxOrder + 1;
464
        }
465
466
        return parent::beforeSave($insert);
467
    }
468
469
    /**
470
     * Generate hash by password.
471
     *
472
     * @param string $password.
473
     *
474
     * @return string
475
     */
476
    private function generateHash($password)
477
    {
478
        return Yii::$app->getSecurity()
479
            ->generatePasswordHash($password);
480
    }
481
}
482