Completed
Push — master ( 30d3de...6bbfea )
by Xu
29:18 queued 23:02
created

User::getIsBlocked()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace yuncms\models;
4
5
use Yii;
6
use yii\db\ActiveRecord;
7
use yii\db\Query;
8
use yii\helpers\ArrayHelper;
9
use yii\helpers\Inflector;
10
use yii\helpers\Url;
11
use yii\web\IdentityInterface;
12
use yii\filters\RateLimitInterface;
13
use yii\behaviors\TimestampBehavior;
14
use creocoder\taggable\TaggableBehavior;
15
use yuncms\helpers\PasswordHelper;
16
17
/**
18
 * This is the model class for table "{{%user}}".
19
 *
20
 * Magic methods:
21
 * @method ActiveRecord getTagValues($asArray = null)
22
 * @method ActiveRecord setTagValues($values)
23
 * @method ActiveRecord addTagValues($values)
24
 * @method ActiveRecord removeTagValues($values)
25
 * @method ActiveRecord removeAllTagValues()
26
 * @method ActiveRecord hasTagValues($values)
27
 *
28
 * Database fields:
29
 * @property integer $id
30
 * @property string $username
31
 * @property string $email
32
 * @property string $mobile
33
 * @property string $nickname
34
 * @property string $auth_key
35
 * @property string $password_hash
36
 * @property string $access_token
37
 * @property integer $avatar
38
 * @property string $unconfirmed_email
39
 * @property string $unconfirmed_mobile
40
 * @property string $registration_ip
41
 * @property integer $flags
42
 * @property integer $email_confirmed_at
43
 * @property integer $mobile_confirmed_at
44
 * @property integer $blocked_at
45
 * @property integer $created_at
46
 * @property integer $updated_at
47
 *
48
 * @property-read boolean $isBlocked 账户是否锁定
49
 * @property-read bool $isMobileConfirmed 是否已经手机激活
50
 * @property-read bool $isEmailConfirmed 是否已经邮箱激活
51
 * @property-read bool $isAvatar 是否有头像
52
 *
53
 * Defined relations:
54
 * @property UserExtra $extra
55
 * @property UserLoginHistory[] $userLoginHistories
56
 * @property UserProfile $profile
57
 * @property UserSocialAccount[] $socialAccounts
58
 * @property Tag[] $tags
59
 * @property UserToken[] $userTokens
60
 *
61
 */
62
class User extends ActiveRecord implements IdentityInterface, RateLimitInterface
63
{
64
    //事件定义
65
    const BEFORE_CREATE = 'beforeCreate';
66
    const AFTER_CREATE = 'afterCreate';
67
    const BEFORE_REGISTER = 'beforeRegister';
68
    const AFTER_REGISTER = 'afterRegister';
69
70
    //场景定义
71
    const SCENARIO_CREATE = 'create';//后台或控制台创建用户
72
    const SCENARIO_UPDATE = 'update';//后台或控制台修改用户
73
    const SCENARIO_REGISTER = 'basic_create';//邮箱注册
74
    const SCENARIO_EMAIL_REGISTER = 'email_create';//邮箱注册
75
    const SCENARIO_MOBILE_REGISTER = 'mobile_create';//手机号注册
76
    const SCENARIO_SETTINGS = 'settings';//更新
77
    const SCENARIO_CONNECT = 'connect';//账户链接或自动注册新用户
78
    const SCENARIO_PASSWORD = 'password';
79
80
    // following constants are used on secured email changing process
81
    const OLD_EMAIL_CONFIRMED = 0b1;
82
    const NEW_EMAIL_CONFIRMED = 0b10;
83
84
    //头像
85
    const AVATAR_BIG = 'big';
86
    const AVATAR_MIDDLE = 'middle';
87
    const AVATAR_SMALL = 'small';
88
89
    /**
90
     * @var string Plain password. Used for model validation.
91
     */
92
    public $password;
93
94
    /**
95
     * @var UserProfile|null
0 ignored issues
show
Bug introduced by
The type yuncms\models\UserProfile was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
96
     */
97
    private $_profile;
98
99
    /** @var  UserExtra|null */
0 ignored issues
show
Bug introduced by
The type yuncms\models\UserExtra was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
100
    private $_extra;
101
102
    /**
103
     * @var string Default username regexp
104
     */
105
    public static $usernameRegexp = '/^[-a-zA-Z0-9_]+$/u';
106
107
    /**
108
     * @var string Default nickname regexp
109
     */
110
    public static $nicknameRegexp = '/^[-a-zA-Z0-9_\x{4e00}-\x{9fa5}\.@]+$/u';
111
112
    /**
113
     * @var string Default mobile regexp
114
     */
115
    public static $mobileRegexp = '/^1[34578]{1}[\d]{9}$|^166[\d]{8}$|^19[89]{1}[\d]{8}$/';
116
117
    /**
118
     * @inheritdoc
119
     */
120
    public static function tableName()
121
    {
122
        return '{{%user}}';
123
    }
124
125
    /**
126
     * 定义行为
127
     * @return array
128
     */
129
    public function behaviors()
130
    {
131
        return [
132
            'timestamp' => TimestampBehavior::class,
133
            'taggable' => [
134
                'class' => TaggableBehavior::class,
135
                'tagValuesAsArray' => true,
136
                'tagRelation' => 'tags',
137
                'tagValueAttribute' => 'id',
138
                'tagFrequencyAttribute' => 'frequency',
139
            ],
140
        ];
141
    }
142
143
    /**
144
     * @inheritdoc
145
     */
146
    public function scenarios()
147
    {
148
        $scenarios = parent::scenarios();
149
        return ArrayHelper::merge($scenarios, [
150
            static::SCENARIO_CREATE => ['nickname', 'email', 'password'],
151
            static::SCENARIO_UPDATE => ['nickname', 'email', 'password'],
152
            static::SCENARIO_REGISTER => ['nickname', 'password'],
153
            static::SCENARIO_EMAIL_REGISTER => ['nickname', 'email', 'password'],
154
            static::SCENARIO_MOBILE_REGISTER => ['mobile', 'password'],
155
            static::SCENARIO_SETTINGS => ['username', 'email', 'password'],
156
            static::SCENARIO_CONNECT => ['nickname', 'email', 'password'],//链接账户密码可以为空邮箱可以为空
157
            static::SCENARIO_PASSWORD => ['password'],//只修改密码
158
        ]);
159
    }
160
161
    /**
162
     * @inheritdoc
163
     */
164
    public function rules()
165
    {
166
        return [
167
            // username rules
168
            'usernameMatch' => ['username', 'match', 'pattern' => static::$usernameRegexp],
169
            'usernameLength' => ['username', 'string', 'min' => 3, 'max' => 50],
170
            'usernameUnique' => ['username', 'unique', 'message' => Yii::t('yuncms', 'This username has already been taken')],
171
            'usernameTrim' => ['username', 'trim'],
172
173
            // nickname rules
174
            'nicknameRequired' => ['nickname', 'required', 'on' => [self::SCENARIO_EMAIL_REGISTER, self::SCENARIO_CONNECT]],
175
            'nicknameMatch' => ['nickname', 'match', 'pattern' => static::$nicknameRegexp],
176
            'nicknameLength' => ['nickname', 'string', 'min' => 3, 'max' => 255],
177
            'nicknameUnique' => ['nickname', 'unique', 'message' => Yii::t('yuncms', 'This nickname has already been taken')],
178
            'nicknameTrim' => ['nickname', 'trim'],
179
180
            // email rules
181
            'emailRequired' => ['email', 'required', 'on' => [self::SCENARIO_EMAIL_REGISTER]],
182
            'emailPattern' => ['email', 'email', 'checkDNS' => true],
183
            'emailLength' => ['email', 'string', 'max' => 255],
184
            'emailUnique' => ['email', 'unique', 'message' => Yii::t('yuncms', 'This email address has already been taken')],
185
            'emailTrim' => ['email', 'trim'],
186
            'emailDefault' => ['email', 'default', 'value' => null],
187
188
            //mobile rules
189
            'mobileRequired' => ['mobile', 'required', 'on' => [self::SCENARIO_MOBILE_REGISTER]],
190
            'mobilePattern' => ['mobile', 'match', 'pattern' => static::$mobileRegexp],
191
            'mobileLength' => ['mobile', 'string', 'max' => 11],
192
            'mobileUnique' => ['mobile', 'unique', 'message' => Yii::t('yuncms', 'This phone has already been taken')],
193
            'mobileDefault' => ['mobile', 'default', 'value' => null],
194
195
            // password rules
196
            'passwordRequired' => ['password', 'required', 'on' => [self::SCENARIO_EMAIL_REGISTER, self::SCENARIO_MOBILE_REGISTER]],
197
            'passwordLength' => ['password', 'string', 'min' => 6],
198
199
            // tags rules
200
            'tags' => ['tagValues', 'safe'],
201
202
203
            [['flags', 'email_confirmed_at', 'mobile_confirmed_at', 'blocked_at'], 'integer'],
204
            [['registration_ip'], 'string', 'max' => 255],
205
            [['mobile', 'unconfirmed_mobile'], 'string', 'max' => 11],
206
            [['access_token'], 'string', 'max' => 100],
207
            [['unconfirmed_email'], 'string', 'max' => 150],
208
        ];
209
    }
210
211
    /**
212
     * @inheritdoc
213
     */
214
    public function attributeLabels()
215
    {
216
        return [
217
            'id' => Yii::t('yuncms', 'ID'),
218
            'username' => Yii::t('yuncms', 'Username'),
219
            'email' => Yii::t('yuncms', 'Email'),
220
            'mobile' => Yii::t('yuncms', 'Mobile'),
221
            'nickname' => Yii::t('yuncms', 'Nickname'),
222
            'auth_key' => Yii::t('yuncms', 'Auth Key'),
223
            'password_hash' => Yii::t('yuncms', 'Password Hash'),
224
            'access_token' => Yii::t('yuncms', 'Access Token'),
225
            'avatar' => Yii::t('yuncms', 'Avatar'),
226
            'unconfirmed_email' => Yii::t('yuncms', 'Unconfirmed Email'),
227
            'unconfirmed_mobile' => Yii::t('yuncms', 'Unconfirmed Mobile'),
228
            'registration_ip' => Yii::t('yuncms', 'Registration Ip'),
229
            'flags' => Yii::t('yuncms', 'Flags'),
230
            'email_confirmed_at' => Yii::t('yuncms', 'Email Confirmed At'),
231
            'mobile_confirmed_at' => Yii::t('yuncms', 'Mobile Confirmed At'),
232
            'blocked_at' => Yii::t('yuncms', 'Blocked At'),
233
            'created_at' => Yii::t('yuncms', 'Created At'),
234
            'updated_at' => Yii::t('yuncms', 'Updated At'),
235
        ];
236
    }
237
238
    /**
239
     * @return \yii\db\ActiveQuery
240
     */
241
    public function getExtra()
242
    {
243
        return $this->hasOne(UserExtra::class, ['user_id' => 'id']);
244
    }
245
246
    /**
247
     * @return \yii\db\ActiveQuery
248
     */
249
    public function getLoginHistories()
250
    {
251
        return $this->hasMany(UserLoginHistory::class, ['user_id' => 'id']);
0 ignored issues
show
Bug introduced by
The type yuncms\models\UserLoginHistory was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
252
    }
253
254
    /**
255
     * @return \yii\db\ActiveQuery
256
     */
257
    public function getProfile()
258
    {
259
        return $this->hasOne(UserProfile::class, ['user_id' => 'id']);
260
    }
261
262
    /**
263
     * 返回所有已经连接的社交媒体账户
264
     * @return UserSocialAccount[] Connected accounts ($provider => $account)
265
     */
266
    public function getSocialAccounts()
267
    {
268
        $connected = [];
269
        /** @var UserSocialAccount[] $accounts */
270
        $accounts = $this->hasMany(UserSocialAccount::class, ['user_id' => 'id'])->all();
0 ignored issues
show
Bug introduced by
The type yuncms\models\UserSocialAccount was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
271
        /**
272
         * @var UserSocialAccount $account
273
         */
274
        foreach ($accounts as $account) {
275
            $connected[$account->provider] = $account;
276
        }
277
278
        return $connected;
279
    }
280
281
    /**
282
     * @return \yii\db\ActiveQuery
283
     */
284
    public function getTags()
285
    {
286
        return $this->hasMany(Tag::class, ['id' => 'tag_id'])->viaTable('{{%user_tag}}', ['user_id' => 'id']);
0 ignored issues
show
Bug introduced by
The type yuncms\models\Tag was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
287
    }
288
289
    /**
290
     * @return \yii\db\ActiveQuery
291
     */
292
    public function getTokens()
293
    {
294
        return $this->hasMany(UserToken::class, ['user_id' => 'id']);
0 ignored issues
show
Bug introduced by
The type yuncms\models\UserToken was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
295
    }
296
297
    /**
298
     * 获取头像Url
299
     * @param string $size
300
     * @return string
301
     */
302
    public function getAvatar($size = self::AVATAR_MIDDLE)
303
    {
304
        $size = in_array($size, [self::AVATAR_BIG, self::AVATAR_MIDDLE, self::AVATAR_SMALL]) ? $size : self::AVATAR_BIG;
305
        if ($this->getIsAvatar()) {
306
            $avatarFileName = "_avatar_{$size}.jpg";
307
            return $this->getAvatarUrl($this->id) . $avatarFileName . '?_t=' . $this->updated_at;
0 ignored issues
show
Bug introduced by
The method getAvatarUrl() does not exist on yuncms\models\User. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

307
            return $this->/** @scrutinizer ignore-call */ getAvatarUrl($this->id) . $avatarFileName . '?_t=' . $this->updated_at;
Loading history...
308
        } else {
309
            $avatarUrl = "/img/no_avatar_{$size}.gif";
310
            if (Yii::getAlias('@webroot', false)) {
311
                $baseUrl = UserAsset::register(Yii::$app->view)->baseUrl;
0 ignored issues
show
Bug introduced by
The type yuncms\models\UserAsset was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
312
                return Url::to($baseUrl . $avatarUrl, true);
313
            } else {
314
                return '';
315
            }
316
        }
317
    }
318
319
    /**
320
     * 设置用户资料
321
     * @param UserProfile $profile
322
     */
323
    public function setProfile(UserProfile $profile)
324
    {
325
        $this->_profile = $profile;
326
    }
327
328
    /**
329
     * 设置用户延伸资料
330
     * @param UserExtra $extra
331
     */
332
    public function setExtra($extra)
333
    {
334
        $this->_extra = $extra;
335
    }
336
337
    /**
338
     * 设置Email已经验证
339
     * @return bool
340
     */
341
    public function setEmailConfirm()
342
    {
343
        return (bool)$this->updateAttributes(['email_confirmed_at' => time()]);
344
    }
345
346
    /**
347
     * 设置手机号已经验证
348
     * @return bool
349
     */
350
    public function setMobileConfirm()
351
    {
352
        return (bool)$this->updateAttributes(['mobile_confirmed_at' => time()]);
353
    }
354
355
    /**
356
     * @inheritdoc
357
     * @return UserQuery the active query used by this AR class.
358
     */
359
    public static function find()
360
    {
361
        return new UserQuery(get_called_class());
362
    }
363
364
    /**
365
     * 通过登陆邮箱或手机号获取用户
366
     * @param string $emailOrMobile
367
     * @return User|null
368
     */
369
    public static function findByEmailOrMobile($emailOrMobile)
370
    {
371
        if (filter_var($emailOrMobile, FILTER_VALIDATE_EMAIL)) {
372
            return static::findByEmail($emailOrMobile);
373
        } else if (preg_match(self::$mobileRegexp, $emailOrMobile)) {
374
            return static::findByMobile($emailOrMobile);
375
        }
376
        return null;
377
    }
378
379
    /**
380
     * 通过邮箱获取用户
381
     * @param string $email 邮箱
382
     * @return null|static
383
     */
384
    public static function findByEmail($email)
385
    {
386
        return static::findOne(['email' => $email]);
387
    }
388
389
    /**
390
     * 通过手机号获取用户
391
     * @param string $mobile
392
     * @return static
393
     */
394
    public static function findByMobile($mobile)
395
    {
396
        return static::findOne(['mobile' => $mobile]);
397
    }
398
399
    /**
400
     * 通过用户名获取用户
401
     * @param string $username 用户标识
402
     * @return null|static
403
     */
404
    public static function findModelByUsername($username)
405
    {
406
        return static::findOne(['username' => $username]);
407
    }
408
409
    /**
410
     * @inheritdoc
411
     */
412
    public static function findIdentityByAccessToken($token, $type = null)
413
    {
414
        return static::findOne(['access_token' => $token]);
0 ignored issues
show
Bug Best Practice introduced by
The expression return static::findOne(a...cess_token' => $token)) 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...
415
    }
416
417
    /**
418
     * @inheritdoc
419
     */
420
    public function getId()
421
    {
422
        return $this->getPrimaryKey();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getPrimaryKey() also could return the type array|array<mixed,null|mixed> which is incompatible with the return type mandated by yii\web\IdentityInterface::getId() of integer|string.
Loading history...
423
    }
424
425
    /**
426
     * @inheritdoc
427
     */
428
    public static function findIdentity($id)
429
    {
430
        return static::findOne($id);
0 ignored issues
show
Bug Best Practice introduced by
The expression return static::findOne($id) 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...
431
    }
432
433
    /**
434
     * 获取auth_key
435
     * @inheritdoc
436
     */
437
    public function getAuthKey()
438
    {
439
        return $this->auth_key;
440
    }
441
442
    /**
443
     * 验证密码
444
     *
445
     * @param string $password password to validate
446
     * @return boolean if password provided is valid for current user
447
     */
448
    public function validatePassword($password)
449
    {
450
        return PasswordHelper::validate($password, $this->password_hash);
451
    }
452
453
    /**
454
     * 验证AuthKey
455
     * @param string $authKey
456
     * @return boolean
457
     */
458
    public function validateAuthKey($authKey)
459
    {
460
        return $this->getAuthKey() === $authKey;
461
    }
462
463
    /**
464
     * 创建 "记住我" 身份验证Key
465
     * @return void
466
     * @throws \yii\base\Exception
467
     */
468
    public function generateAuthKey()
469
    {
470
        $this->auth_key = Yii::$app->security->generateRandomString();
471
    }
472
473
    /**
474
     * 创建 "记住我" 身份验证Key
475
     * @return void
476
     * @throws \yii\base\Exception
477
     */
478
    public function generateAccessToken()
479
    {
480
        $this->access_token = Yii::$app->security->generateRandomString();
481
    }
482
483
    /**
484
     * 随机生成一个用户名
485
     */
486
    public function generateUsername()
487
    {
488
        if ($this->email) {
489
            $this->username = explode('@', $this->email)[0];
490
            if ($this->validate(['username'])) {
491
                return $this->username;
492
            }
493
        } else if ($this->nickname) {
494
            $this->username = Inflector::slug($this->nickname, '');
495
            if ($this->validate(['username'])) {
496
                return $this->username;
497
            }
498
        }
499
        // generate name like "user1", "user2", etc...
500
        while (!$this->validate(['username'])) {
501
            $row = (new Query())->from('{{%user}}')->select('MAX(id) as id')->one();
502
            $this->username = 'user' . ++$row['id'];
503
        }
504
        return $this->username;
505
    }
506
507
    /**
508
     * 重置密码
509
     *
510
     * @param string $password
511
     *
512
     * @return boolean
513
     * @throws \yii\base\Exception
514
     */
515
    public function resetPassword($password)
516
    {
517
        return (bool)$this->updateAttributes(['password_hash' => PasswordHelper::hash($password)]);
518
    }
519
520
    /**
521
     * 锁定用户
522
     * @return boolean
523
     * @throws \yii\base\Exception
524
     */
525
    public function block()
526
    {
527
        return (bool)$this->updateAttributes(['blocked_at' => time(), 'auth_key' => Yii::$app->security->generateRandomString()]);
528
    }
529
530
    /**
531
     * 解除用户锁定
532
     * @return boolean
533
     */
534
    public function unblock()
535
    {
536
        return (bool)$this->updateAttributes(['blocked_at' => null]);
537
    }
538
539
    /**
540
     * 返回用户是否已经锁定
541
     * @return boolean Whether the user is blocked or not.
542
     */
543
    public function getIsBlocked()
544
    {
545
        return $this->blocked_at != null;
546
    }
547
548
    /**
549
     * 返回用户是否有头像
550
     * @return boolean Whether the user is blocked or not.
551
     */
552
    public function getIsAvatar()
553
    {
554
        return $this->avatar != 0;
555
    }
556
557
    /**
558
     * 返回用户邮箱是否已经激活
559
     * @return boolean Whether the user is confirmed or not.
560
     */
561
    public function getIsEmailConfirmed()
562
    {
563
        return $this->email_confirmed_at != null;
564
    }
565
566
    /**
567
     * 返回用户手机是否已经激活
568
     * @return boolean Whether the user is confirmed or not.
569
     */
570
    public function getIsMobileConfirmed()
571
    {
572
        return $this->mobile_confirmed_at != null;
573
    }
574
575
    /**
576
     * 此方法用于注册新用户帐户。 如果 enableConfirmation 设置为true,则此方法
577
     * 将生成新的确认令牌,并使用邮件发送给用户。
578
     *
579
     * @return boolean
580
     */
581
    public function register()
582
    {
583
        if ($this->getIsNewRecord() == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
584
            throw new \RuntimeException('Calling "' . __CLASS__ . '::' . __METHOD__ . '" on existing user');
585
        }
586
        $this->password = Yii::$app->settings->get('user.enableGeneratingPassword') ? PasswordHelper::generate(8) : $this->password;
587
        if ($this->scenario == self::SCENARIO_EMAIL_REGISTER) {
588
            $this->email_confirmed_at = Yii::$app->settings->get('user.enableConfirmation') ? null : time();
589
        }
590
        $this->trigger(self::BEFORE_REGISTER);
591
        if (!$this->save()) {
592
            return false;
593
        }
594
        if (Yii::$app->settings->get('user.enableConfirmation') && !empty($this->email)) {
595
            /** @var UserToken $token */
596
            $token = new UserToken(['type' => UserToken::TYPE_CONFIRMATION]);
597
            $token->link('user', $this);
598
            $this->sendMessage($this->email, Yii::t('user', 'Welcome to {0}', Yii::$app->name), 'welcome', ['user' => $this, 'token' => isset($token) ? $token : null, 'module' => $this->module, 'showPassword' => false]);
0 ignored issues
show
Bug introduced by
The method sendMessage() does not exist on yuncms\models\User. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

598
            $this->/** @scrutinizer ignore-call */ 
599
                   sendMessage($this->email, Yii::t('user', 'Welcome to {0}', Yii::$app->name), 'welcome', ['user' => $this, 'token' => isset($token) ? $token : null, 'module' => $this->module, 'showPassword' => false]);
Loading history...
Bug Best Practice introduced by
The property module does not exist on yuncms\models\User. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug introduced by
Yii::app->name of type string is incompatible with the type array expected by parameter $params of yii\BaseYii::t(). ( Ignorable by Annotation )

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

598
            $this->sendMessage($this->email, Yii::t('user', 'Welcome to {0}', /** @scrutinizer ignore-type */ Yii::$app->name), 'welcome', ['user' => $this, 'token' => isset($token) ? $token : null, 'module' => $this->module, 'showPassword' => false]);
Loading history...
599
        } else {
600
            Yii::$app->user->login($this, Yii::$app->settings->get('user.rememberFor'));
601
        }
602
        $this->trigger(self::AFTER_REGISTER);
603
        return true;
604
    }
605
606
    /**
607
     * 创建新用户帐户。 如果用户不提供密码,则会生成密码。
608
     *
609
     * @return boolean
610
     */
611
    public function create()
612
    {
613
        if ($this->getIsNewRecord() == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
614
            throw new \RuntimeException('Calling "' . __CLASS__ . '::' . __METHOD__ . '" on existing user');
615
        }
616
        $this->password = $this->password == null ? PasswordHelper::generate(8) : $this->password;
617
        $this->trigger(self::BEFORE_CREATE);
618
        if (!$this->save()) {
619
            return false;
620
        }
621
        $this->trigger(self::AFTER_CREATE);
622
        return true;
623
    }
624
625
//    public function afterFind()
626
//    {
627
//        parent::afterFind();
628
//        // ...custom code here...
629
//    }
630
631
    /**
632
     * @inheritdoc
633
     */
634
    public function beforeSave($insert)
635
    {
636
        if (!parent::beforeSave($insert)) {
637
            return false;
638
        }
639
        if ($insert) {
640
            $this->generateAccessToken();
641
            $this->generateAuthKey();
642
        }
643
        if(!empty($this->username)){
644
            $this->username = $this->generateUsername();
645
        }
646
        if (!empty($this->password)) {
647
            $this->password_hash = PasswordHelper::hash($this->password);
648
        }
649
        return true;
650
    }
651
652
    /**
653
     * @inheritdoc
654
     */
655
    public function afterSave($insert, $changedAttributes)
656
    {
657
        parent::afterSave($insert, $changedAttributes);
658
        if ($insert) {
659
            if ($this->_profile == null) {
660
                $this->_profile = new UserProfile();
661
            }
662
            $this->_profile->link('user', $this);
663
664
            if ($this->_extra == null) {
665
                $this->_extra = new UserExtra();
666
            }
667
            $this->_extra->link('user', $this);
668
        }
669
    }
670
671
    /**
672
     * @inheritdoc
673
     */
674
//    public function beforeDelete()
675
//    {
676
//        if (!parent::beforeDelete()) {
677
//            return false;
678
//        }
679
//        // ...custom code here...
680
//        return true;
681
//    }
682
683
    /**
684
     * @inheritdoc
685
     */
686
//    public function afterDelete()
687
//    {
688
//        parent::afterDelete();
689
//
690
//        // ...custom code here...
691
//    }
692
693
    /**
694
     * Returns the maximum number of allowed requests and the window size.
695
     * @param \yii\web\Request $request the current request
696
     * @param \yii\base\Action $action the action to be executed
697
     * @return array an array of two elements. The first element is the maximum number of allowed requests,
698
     * and the second element is the size of the window in seconds.
699
     */
700
    public function getRateLimit($request, $action)
701
    {
702
        $rateLimit = Yii::$app->settings->get('user.requestRateLimit', 60);
703
        return [$rateLimit, 60];
704
    }
705
706
    /**
707
     * Loads the number of allowed requests and the corresponding timestamp from a persistent storage.
708
     * @param \yii\web\Request $request the current request
709
     * @param \yii\base\Action $action the action to be executed
710
     * @return array an array of two elements. The first element is the number of allowed requests,
711
     * and the second element is the corresponding UNIX timestamp.
712
     */
713
    public function loadAllowance($request, $action)
714
    {
715
        $allowance = Yii::$app->cache->GET($action->controller->id . ':' . $action->id . ':' . $this->id . '_allowance');
716
        $allowanceUpdatedAt = Yii::$app->cache->GET($action->controller->id . ':' . $action->id . ':' . $this->id . '_allowance_update_at');
717
        if ($allowance && $allowanceUpdatedAt) {
718
            return [$allowance, $allowanceUpdatedAt];
719
        } else {
720
            return [Yii::$app->settings->get('user.requestRateLimit', 60), time()];
721
        }
722
    }
723
724
    /**
725
     * Saves the number of allowed requests and the corresponding timestamp to a persistent storage.
726
     * @param \yii\web\Request $request the current request
727
     * @param \yii\base\Action $action the action to be executed
728
     * @param int $allowance the number of allowed requests remaining.
729
     * @param int $timestamp the current timestamp.
730
     */
731
    public function saveAllowance($request, $action, $allowance, $timestamp)
732
    {
733
        Yii::$app->cache->set($action->controller->id . ':' . $action->id . ':' . $this->id . '_allowance', $allowance, 60);
734
        Yii::$app->cache->set($action->controller->id . ':' . $action->id . ':' . $this->id . '_allowance_update_at', $timestamp, 60);
735
    }
736
}
737