1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* User model for the module yii2-activeuser |
4
|
|
|
* |
5
|
|
|
* @link https://github.com/inblank/yii2-activeuser |
6
|
|
|
* @copyright Copyright (c) 2016 Pavel Aleksandrov <[email protected]> |
7
|
|
|
* @license http://opensource.org/licenses/MIT |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
namespace inblank\activeuser\models; |
11
|
|
|
|
12
|
|
|
use inblank\activeuser\traits\CommonTrait; |
13
|
|
|
use inblank\image\ImageBehavior; |
14
|
|
|
use yii; |
15
|
|
|
use yii\db\ActiveRecord; |
16
|
|
|
use yii\web\IdentityInterface; |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* This is the model class for table "{{%activeuser_users}}" |
20
|
|
|
* |
21
|
|
|
* Table fields: |
22
|
|
|
* @property integer $id user identifier |
23
|
|
|
* @property integer $status user status. STATUS_ACTIVE, STATUS_BLOCKED, STATUS_CONFIRM, STATUS_RESTORE |
24
|
|
|
* @property string $email user email used as login |
25
|
|
|
* @property string $pass_hash hash of user password |
26
|
|
|
* @property string $name real user name |
27
|
|
|
* @property int $gender user gender. User::MALE, User::FEMALE. If empty, not set |
28
|
|
|
* @property string $birth user birth date |
29
|
|
|
* @property string $avatar user avatar filename |
30
|
|
|
* @property string $access_token user access token for use site API |
31
|
|
|
* @property string $auth_key user key for access by `remember me` |
32
|
|
|
* @property string $token token for registration confirm or restore password |
33
|
|
|
* @property int $token_created_at the time when the token was created |
34
|
|
|
* @property string $registered_at user registration date |
35
|
|
|
* |
36
|
|
|
* By getters: |
37
|
|
|
* @property $statusText user status as text |
38
|
|
|
* @property $genderText user gender as text |
39
|
|
|
* |
40
|
|
|
* Relations: |
41
|
|
|
* @property Profile $profile user profile data |
42
|
|
|
* |
43
|
|
|
* @mixin ImageBehavior |
44
|
|
|
*/ |
45
|
|
|
class User extends ActiveRecord implements yii\web\IdentityInterface |
46
|
|
|
{ |
47
|
|
|
use CommonTrait; |
48
|
|
|
|
49
|
|
|
/** Male gender */ |
50
|
|
|
const MALE = 1; |
51
|
|
|
/** Female gender */ |
52
|
|
|
const FEMALE = 2; |
53
|
|
|
|
54
|
|
|
/** Active user status */ |
55
|
|
|
const STATUS_ACTIVE = 1; |
56
|
|
|
/** Blocked user status */ |
57
|
|
|
const STATUS_BLOCKED = 2; |
58
|
|
|
/** User await email confirmation status */ |
59
|
|
|
const STATUS_CONFIRM = 3; |
60
|
|
|
/** User await access restore status */ |
61
|
|
|
const STATUS_RESTORE = 4; |
62
|
|
|
|
63
|
|
|
// TODO where store password between data enter and confirmation email? Password must be send with congratulation email |
64
|
|
|
/** @var string password field on registration on restore */ |
65
|
|
|
public $password; |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* @inheritdoc |
69
|
|
|
*/ |
70
|
16 |
|
public static function tableName() |
71
|
|
|
{ |
72
|
16 |
|
return '{{%activeuser_users}}'; |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* @inheritdoc |
77
|
|
|
* @return UserQuery the active query used by this AR class. |
78
|
|
|
*/ |
79
|
15 |
|
public static function find() |
80
|
|
|
{ |
81
|
15 |
|
$queryClass = self::di('UserQuery'); |
82
|
15 |
|
return new $queryClass(get_called_class()); |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
/** |
86
|
|
|
* Finds an identity by the given ID. |
87
|
|
|
* @param string|integer $id the ID to be looked for |
88
|
|
|
* @return IdentityInterface the identity object that matches the given ID. |
89
|
|
|
* Null should be returned if such an identity cannot be found |
90
|
|
|
* or the identity is not in an active state (disabled, deleted, etc.) |
91
|
|
|
*/ |
92
|
2 |
|
public static function findIdentity($id) |
93
|
|
|
{ |
94
|
2 |
|
return static::findOne($id); |
|
|
|
|
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* Find user by token |
99
|
|
|
* @param string $token for search |
100
|
|
|
* @return null|static |
101
|
|
|
*/ |
102
|
3 |
|
public static function findByToken($token) |
103
|
|
|
{ |
104
|
3 |
|
return empty($token) ? null : static::findOne(['token' => $token]); |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* Finds an identity by the given token. |
109
|
|
|
* @param mixed $token the token to be looked for |
110
|
|
|
* @param mixed $type the type of the token. The value of this parameter depends on the implementation. |
111
|
|
|
* For example, [[\yii\filters\auth\HttpBearerAuth]] will set this parameter to be `yii\filters\auth\HttpBearerAuth`. |
112
|
|
|
* @return IdentityInterface the identity object that matches the given token. |
113
|
|
|
* Null should be returned if such an identity cannot be found |
114
|
|
|
* or the identity is not in an active state (disabled, deleted, etc.) |
115
|
|
|
*/ |
116
|
1 |
|
public static function findIdentityByAccessToken($token, $type = null) |
117
|
|
|
{ |
118
|
1 |
|
if (empty($token)) { |
119
|
1 |
|
return null; |
120
|
|
|
} |
121
|
1 |
|
return static::findOne(['access_token' => $token, 'status' => self::STATUS_ACTIVE]); |
|
|
|
|
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
/** |
125
|
|
|
* Confirm user registration |
126
|
|
|
* @return bool return false if cannot confirm. |
127
|
|
|
* If in errors list has key `error`, that user already confirmed |
128
|
|
|
* If in errors list has key `token`, that confirm token was expired |
129
|
|
|
*/ |
130
|
3 |
|
public function confirm() |
131
|
|
|
{ |
132
|
3 |
|
if ($this->isConfirmed()) { |
133
|
1 |
|
$this->addError('error', Yii::t('activeuser_general', 'User already confirmed')); |
134
|
1 |
|
return false; |
135
|
|
|
} |
136
|
3 |
|
if ($this->isConfirmTokenExpired()) { |
137
|
1 |
|
$this->addError('token', Yii::t('activeuser_general', 'You token was expired')); |
138
|
1 |
|
return false; |
139
|
|
|
} |
140
|
3 |
|
$this->updateAttributes([ |
141
|
3 |
|
'token' => null, |
142
|
3 |
|
'token_created_at' => 0, |
143
|
3 |
|
'status' => self::STATUS_ACTIVE, |
144
|
|
|
]); |
145
|
3 |
|
$this->module->sendMessage('register', [ |
146
|
3 |
|
'user' => $this, |
147
|
|
|
]); |
148
|
3 |
|
return true; |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
/** |
152
|
|
|
* Check that user was confirmed |
153
|
|
|
* @return bool |
154
|
|
|
*/ |
155
|
6 |
|
public function isConfirmed() |
156
|
|
|
{ |
157
|
6 |
|
return $this->status !== self::STATUS_CONFIRM; |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
/** |
161
|
|
|
* Checks that the token was expired |
162
|
|
|
* @param int $timeToExpire time |
163
|
|
|
* @return bool |
164
|
|
|
*/ |
165
|
3 |
|
public function isTokenExpired($timeToExpire) |
166
|
|
|
{ |
167
|
3 |
|
return $this->token_created_at + $timeToExpire < time(); |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
/** |
171
|
|
|
* Checks that the confirmation token was expired |
172
|
|
|
* @return bool |
173
|
|
|
*/ |
174
|
3 |
|
public function isConfirmTokenExpired() |
175
|
|
|
{ |
176
|
3 |
|
return $this->isTokenExpired($this->getModule()->confirmationTime); |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
/** |
180
|
|
|
* Checks that the restore token was expired |
181
|
|
|
* @return bool |
182
|
|
|
*/ |
183
|
1 |
|
public function isRestoreTokenExpired() |
184
|
|
|
{ |
185
|
1 |
|
return $this->isTokenExpired($this->getModule()->restoreTime); |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
/** |
189
|
|
|
* @inheritdoc |
190
|
|
|
*/ |
191
|
11 |
|
public function rules() |
192
|
|
|
{ |
193
|
|
|
// todo check password length |
194
|
|
|
return [ |
195
|
11 |
|
[['email'], 'required'], |
196
|
|
|
['password', 'required', 'when' => function ($model) { |
197
|
11 |
|
return $model->isNewRecord; |
198
|
11 |
|
}], |
199
|
|
|
['email', 'unique'], |
200
|
|
|
['email', 'string', 'max' => 200], |
201
|
|
|
['email', 'email'], |
202
|
|
|
['name', 'string', 'max' => 200], |
203
|
|
|
['name', function () { |
204
|
11 |
|
if (in_array('name', $this->module->registrationFields) && empty($this->name)) { |
205
|
2 |
|
$this->addError('name', Yii::t('activeuser_general', 'Name cannot be blank.')); |
206
|
|
|
} |
207
|
11 |
|
}, 'skipOnEmpty' => false], |
208
|
11 |
|
['status', 'in', 'range' => [ |
209
|
11 |
|
self::STATUS_ACTIVE, |
210
|
11 |
|
self::STATUS_BLOCKED, |
211
|
11 |
|
self::STATUS_CONFIRM, |
212
|
11 |
|
self::STATUS_RESTORE, |
213
|
|
|
]], |
214
|
|
|
['status', 'default', 'value' => function () { |
215
|
9 |
|
return $this->module->enableConfirmation ? self::STATUS_CONFIRM : self::STATUS_ACTIVE; |
216
|
11 |
|
}], |
217
|
11 |
|
['gender', 'in', 'range' => [ |
218
|
11 |
|
0, |
219
|
11 |
|
self::MALE, |
220
|
11 |
|
self::FEMALE, |
221
|
|
|
]], |
222
|
|
|
['birth', 'date', 'format' => 'php:Y-m-d', 'skipOnEmpty' => true,], |
223
|
|
|
['token_created_at', 'integer'], |
224
|
|
|
['registered_at', 'date', 'format' => 'php:Y-m-d H:i:s'], |
225
|
11 |
|
['registered_at', 'default', 'value' => function () { |
226
|
10 |
|
return date('Y-m-d H:i:s'); |
227
|
11 |
|
}], |
228
|
|
|
// rules below for prevent nullable value of attributes |
229
|
|
|
[['name', 'avatar'], 'default', 'value' => ''], |
230
|
|
|
[['gender', 'token_created_at'], 'default', 'value' => 0], |
231
|
|
|
]; |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
/** |
235
|
|
|
* @inheritdoc |
236
|
|
|
*/ |
237
|
1 |
|
public function attributeLabels() |
238
|
|
|
{ |
239
|
|
|
return [ |
240
|
1 |
|
'id' => 'ID', |
241
|
1 |
|
'status' => Yii::t('activeuser_general', 'Status'), |
242
|
1 |
|
'email' => Yii::t('activeuser_general', 'Email'), |
243
|
1 |
|
'password' => Yii::t('activeuser_general', 'Password'), |
244
|
1 |
|
'pass_hash' => Yii::t('activeuser_general', 'Password hash'), |
245
|
1 |
|
'name' => Yii::t('activeuser_general', 'Name'), |
246
|
1 |
|
'gender' => Yii::t('activeuser_general', 'Gender'), |
247
|
1 |
|
'birth' => Yii::t('activeuser_general', 'Birth'), |
248
|
1 |
|
'avatar' => Yii::t('activeuser_general', 'Avatar'), |
249
|
1 |
|
'access_token' => Yii::t('activeuser_general', 'Access token'), |
250
|
1 |
|
'auth_key' => Yii::t('activeuser_general', 'Auth key'), |
251
|
1 |
|
'token' => Yii::t('activeuser_general', 'Token'), |
252
|
1 |
|
'token_created_at' => Yii::t('activeuser_general', 'Token created'), |
253
|
1 |
|
'registered_at' => Yii::t('activeuser_general', 'Registered'), |
254
|
|
|
|
255
|
1 |
|
'statusText' => Yii::t('activeuser_general', 'Status'), |
256
|
1 |
|
'genderText' => Yii::t('activeuser_general', 'Gender'), |
257
|
1 |
|
'imageUrl' => Yii::t('activeuser_general', 'Avatar'), |
258
|
|
|
]; |
259
|
|
|
} |
260
|
|
|
|
261
|
|
|
/** |
262
|
|
|
* Get user profile |
263
|
|
|
* @return yii\db\ActiveQuery |
264
|
|
|
*/ |
265
|
1 |
|
public function getProfile() |
266
|
|
|
{ |
267
|
1 |
|
return $this->hasOne(self::di('Profile'), ['user_id' => 'id']); |
268
|
|
|
} |
269
|
|
|
|
270
|
|
|
/** |
271
|
|
|
* @inheritdoc |
272
|
|
|
*/ |
273
|
11 |
|
public function beforeSave($insert) |
274
|
|
|
{ |
275
|
11 |
|
if (!parent::beforeSave($insert)) { |
276
|
1 |
|
return false; |
277
|
|
|
} |
278
|
10 |
|
if ($this->getIsNewRecord() && !empty($this->password)) { |
279
|
9 |
|
$this->pass_hash = Yii::$app->getSecurity()->generatePasswordHash($this->password); |
280
|
|
|
} |
281
|
10 |
|
return true; |
282
|
|
|
} |
283
|
|
|
|
284
|
|
|
/** |
285
|
|
|
* @inheritdoc |
286
|
|
|
*/ |
287
|
10 |
|
public function afterSave($insert, $changedAttributes) |
288
|
|
|
{ |
289
|
10 |
|
if ($insert) { |
290
|
|
|
// add profile for new user |
291
|
9 |
|
Yii::createObject([ |
292
|
9 |
|
'class' => self::di('Profile'), |
293
|
9 |
|
'user_id' => $this->id, |
294
|
9 |
|
])->save(); |
295
|
|
|
} |
296
|
10 |
|
parent::afterSave($insert, $changedAttributes); |
297
|
10 |
|
} |
298
|
|
|
|
299
|
|
|
/** |
300
|
|
|
* @inheritdoc |
301
|
|
|
*/ |
302
|
11 |
|
public function transactions() |
303
|
|
|
{ |
304
|
|
|
return [ |
305
|
11 |
|
self::SCENARIO_DEFAULT => self::OP_INSERT, |
306
|
|
|
]; |
307
|
|
|
} |
308
|
|
|
|
309
|
|
|
/** |
310
|
|
|
* Returns an ID that can uniquely identify a user identity. |
311
|
|
|
* @return string|integer an ID that uniquely identifies a user identity. |
312
|
|
|
*/ |
313
|
2 |
|
public function getId() |
314
|
|
|
{ |
315
|
2 |
|
return $this->id; |
316
|
|
|
} |
317
|
|
|
|
318
|
|
|
/** |
319
|
|
|
* Validates the given auth key. |
320
|
|
|
* |
321
|
|
|
* This is required if [[User::enableAutoLogin]] is enabled. |
322
|
|
|
* @param string $authKey the given auth key |
323
|
|
|
* @return boolean whether the given auth key is valid. |
324
|
|
|
* @see getAuthKey() |
325
|
|
|
*/ |
326
|
1 |
|
public function validateAuthKey($authKey) |
327
|
|
|
{ |
328
|
1 |
|
$userAuthKey = $this->getAuthKey(); |
329
|
1 |
|
return $this->status === self::STATUS_ACTIVE && !empty($userAuthKey) && $userAuthKey === $authKey; |
330
|
|
|
} |
331
|
|
|
|
332
|
|
|
/** |
333
|
|
|
* Returns a key that can be used to check the validity of a given identity ID. |
334
|
|
|
* |
335
|
|
|
* The key should be unique for each individual user, and should be persistent |
336
|
|
|
* so that it can be used to check the validity of the user identity. |
337
|
|
|
* |
338
|
|
|
* The space of such keys should be big enough to defeat potential identity attacks. |
339
|
|
|
* |
340
|
|
|
* This is required if [[User::enableAutoLogin]] is enabled. |
341
|
|
|
* @return string a key that is used to check the validity of a given identity ID. |
342
|
|
|
* @see validateAuthKey() |
343
|
|
|
*/ |
344
|
1 |
|
public function getAuthKey() |
345
|
|
|
{ |
346
|
1 |
|
return $this->auth_key; |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
/** |
350
|
|
|
* Check active user |
351
|
|
|
* @return bool |
352
|
|
|
*/ |
353
|
2 |
|
public function isActive() |
354
|
|
|
{ |
355
|
2 |
|
return $this->status === self::STATUS_ACTIVE; |
356
|
|
|
} |
357
|
|
|
|
358
|
|
|
/** |
359
|
|
|
* User creation |
360
|
|
|
* For create the user you always must set attributes `email`, `password` and `name` |
361
|
|
|
* @param bool $sendEmail whether to send email about registration |
362
|
|
|
* @return bool |
363
|
|
|
*/ |
364
|
1 |
|
public function create($sendEmail = false) |
365
|
|
|
{ |
366
|
1 |
|
$oldRegisterFields = $this->module->registrationFields; |
367
|
1 |
|
$this->module->registrationFields = ['password', 'name']; |
368
|
1 |
View Code Duplication |
if ($this->getIsNewRecord() == false) { |
|
|
|
|
369
|
1 |
|
throw new \RuntimeException('Calling "' . __CLASS__ . '::' . __METHOD__ . '" on existing user'); |
370
|
|
|
} |
371
|
1 |
|
$generatedPassword = false; |
372
|
1 |
|
if (empty($this->password)) { |
373
|
|
|
// password autogenerate |
374
|
1 |
|
$generatedPassword = true; |
375
|
1 |
|
$this->password = $this->generatePassword(); |
|
|
|
|
376
|
|
|
} |
377
|
1 |
|
$this->status = self::STATUS_ACTIVE; |
378
|
1 |
|
$isCreated = $this->save(); |
379
|
1 |
|
$this->module->registrationFields = $oldRegisterFields; |
380
|
1 |
|
if (!$isCreated) { |
381
|
1 |
|
if ($generatedPassword) { |
382
|
|
|
$this->password = null; |
383
|
|
|
} |
384
|
1 |
|
return false; |
385
|
|
|
} |
386
|
1 |
|
if ($sendEmail) { |
387
|
|
|
// send email with registration congratulation |
388
|
1 |
|
$this->module->sendMessage('register', [ |
389
|
1 |
|
'user' => $this, |
390
|
|
|
]); |
391
|
|
|
} |
392
|
1 |
|
return true; |
393
|
|
|
} |
394
|
|
|
|
395
|
|
|
/** |
396
|
|
|
* User registration |
397
|
|
|
* @return bool |
398
|
|
|
*/ |
399
|
8 |
|
public function register() |
400
|
|
|
{ |
401
|
8 |
View Code Duplication |
if ($this->getIsNewRecord() == false) { |
|
|
|
|
402
|
1 |
|
throw new \RuntimeException('Calling "' . __CLASS__ . '::' . __METHOD__ . '" on existing user'); |
403
|
|
|
} |
404
|
8 |
|
if (!$this->module->enableRegistration) { |
405
|
1 |
|
$this->addError('registration', Yii::t('activeuser_general', 'Registration is not available')); |
406
|
1 |
|
return false; |
407
|
|
|
} |
408
|
8 |
|
if (!in_array('password', $this->module->registrationFields)) { |
409
|
|
|
// password autogenerate |
410
|
6 |
|
$this->password = $this->generatePassword(); |
|
|
|
|
411
|
|
|
} |
412
|
8 |
|
if (!$this->save()) { |
413
|
1 |
|
return false; |
414
|
|
|
} |
415
|
8 |
|
if ($this->module->enableConfirmation) { |
416
|
8 |
|
$this->generateToken(); |
417
|
|
|
// send email with confirm link |
418
|
8 |
|
$this->module->sendMessage('confirm', [ |
419
|
8 |
|
'user' => $this, |
420
|
|
|
]); |
421
|
1 |
|
} elseif ($this->module->enableRegistrationEmail) { |
422
|
|
|
// send email with registration congratulation |
423
|
1 |
|
$this->module->sendMessage('register', [ |
424
|
1 |
|
'user' => $this, |
425
|
|
|
]); |
426
|
|
|
} |
427
|
8 |
|
return true; |
428
|
|
|
} |
429
|
|
|
|
430
|
|
|
/** |
431
|
|
|
* Password generator |
432
|
|
|
* @return mixed |
433
|
|
|
*/ |
434
|
7 |
|
public function generatePassword() |
435
|
|
|
{ |
436
|
7 |
|
return (new \PWGen\PWGen())->generate(); |
437
|
|
|
} |
438
|
|
|
|
439
|
|
|
/** |
440
|
|
|
* Generate special hash |
441
|
|
|
* @return string |
442
|
|
|
*/ |
443
|
8 |
|
public function generateToken() |
444
|
|
|
{ |
445
|
8 |
|
$this->updateAttributes([ |
446
|
8 |
|
'token' => Yii::$app->security->generateRandomString(40), |
447
|
8 |
|
'token_created_at' => time(), |
448
|
|
|
]); |
449
|
8 |
|
return $this->token; |
450
|
|
|
} |
451
|
|
|
|
452
|
|
|
/** |
453
|
|
|
* Start password restore procedure |
454
|
|
|
* @return bool |
455
|
|
|
*/ |
456
|
1 |
|
public function restore() |
457
|
|
|
{ |
458
|
1 |
|
if (!$this->module->enablePasswordRestore) { |
459
|
1 |
|
$this->addError('error', Yii::t('activeuser_general', 'Password restore by email is disabled')); |
460
|
1 |
|
return false; |
461
|
|
|
} |
462
|
1 |
|
if ($this->isBlocked() || !$this->isConfirmed()) { |
463
|
1 |
|
$this->addError('error', Yii::t('activeuser_general', 'You cannot start restore procedure')); |
464
|
1 |
|
return false; |
465
|
|
|
} |
466
|
1 |
|
$this->generateToken(); |
467
|
1 |
|
$this->updateAttributes([ |
468
|
1 |
|
'status' => self::STATUS_RESTORE, |
469
|
|
|
]); |
470
|
1 |
|
$this->module->sendMessage('restore', [ |
471
|
1 |
|
'user' => $this, |
472
|
|
|
]); |
473
|
1 |
|
return true; |
474
|
|
|
} |
475
|
|
|
|
476
|
|
|
/** |
477
|
|
|
* Check blocked user |
478
|
|
|
* @return bool |
479
|
|
|
*/ |
480
|
4 |
|
public function isBlocked() |
481
|
|
|
{ |
482
|
4 |
|
return $this->status === self::STATUS_BLOCKED; |
483
|
|
|
} |
484
|
|
|
|
485
|
|
|
/** |
486
|
|
|
* Block user |
487
|
|
|
* @param bool $sendMail whether to send confirmation email about blocking. |
488
|
|
|
* If null, use global setting Module::$enableBlockingEmail |
489
|
|
|
* @return bool return false if user already blocked or not confirmed |
490
|
|
|
*/ |
491
|
1 |
View Code Duplication |
public function block($sendMail = null) |
|
|
|
|
492
|
|
|
{ |
493
|
1 |
|
if ($this->isBlocked() || !$this->isConfirmed()) { |
494
|
1 |
|
return false; |
495
|
|
|
} |
496
|
1 |
|
if ($sendMail === null) { |
497
|
1 |
|
$sendMail = $this->module->enableBlockingEmail; |
498
|
|
|
} |
499
|
1 |
|
$this->updateAttributes([ |
500
|
1 |
|
'status' => self::STATUS_BLOCKED |
501
|
|
|
]); |
502
|
1 |
|
if ($sendMail) { |
503
|
1 |
|
$this->module->sendMessage('block', [ |
504
|
1 |
|
'user' => $this, |
505
|
|
|
]); |
506
|
|
|
} |
507
|
1 |
|
return true; |
508
|
|
|
} |
509
|
|
|
|
510
|
|
|
/** |
511
|
|
|
* Unblock user |
512
|
|
|
* @param bool $sendMail whether to send confirmation email about unblocking. |
513
|
|
|
* If null, use global setting Module::$enableUnblockingEmail |
514
|
|
|
* @return bool return false if user not blocked |
515
|
|
|
*/ |
516
|
1 |
View Code Duplication |
public function unblock($sendMail = null) |
|
|
|
|
517
|
|
|
{ |
518
|
1 |
|
if (!$this->isBlocked()) { |
519
|
1 |
|
return false; |
520
|
|
|
} |
521
|
1 |
|
if ($sendMail === null) { |
522
|
1 |
|
$sendMail = $this->module->enableBlockingEmail; |
523
|
|
|
} |
524
|
1 |
|
$this->updateAttributes([ |
525
|
1 |
|
'status' => self::STATUS_ACTIVE |
526
|
|
|
]); |
527
|
1 |
|
if ($sendMail) { |
528
|
1 |
|
$this->module->sendMessage('unblock', [ |
529
|
1 |
|
'user' => $this, |
530
|
|
|
]); |
531
|
|
|
} |
532
|
1 |
|
return true; |
533
|
|
|
} |
534
|
|
|
|
535
|
|
|
/** |
536
|
|
|
* Change the user password |
537
|
|
|
* @return bool |
538
|
|
|
*/ |
539
|
1 |
|
public function changePassword() |
540
|
|
|
{ |
541
|
1 |
|
if (!$this->isRestore()) { |
542
|
1 |
|
$this->addError('error', Yii::t('activeuser_general', 'User not request restore procedure')); |
543
|
1 |
|
return false; |
544
|
|
|
} |
545
|
1 |
|
if ($this->isRestoreTokenExpired()) { |
546
|
1 |
|
$this->addError('token', Yii::t('activeuser_general', 'You token was expired')); |
547
|
1 |
|
return false; |
548
|
|
|
} |
549
|
1 |
|
if (empty($this->password) && !$this->module->generatePassOnRestore) { |
550
|
1 |
|
$this->addError('password', Yii::t('activeuser_general', 'Password cannot be blank')); |
551
|
1 |
|
return false; |
552
|
|
|
} |
553
|
1 |
|
$this->status = self::STATUS_ACTIVE; |
554
|
1 |
|
$this->newPassword(); |
555
|
1 |
|
return true; |
556
|
|
|
} |
557
|
|
|
|
558
|
|
|
/** |
559
|
|
|
* Set new password |
560
|
|
|
* @param bool $sendEmail whether to send email about password change |
561
|
|
|
* @throws yii\base\Exception |
562
|
|
|
* @throws yii\base\InvalidConfigException |
563
|
|
|
*/ |
564
|
1 |
|
public function newPassword($sendEmail = null) |
565
|
|
|
{ |
566
|
1 |
|
if (empty($this->password)) { |
567
|
1 |
|
$this->password = $this->generatePassword(); |
|
|
|
|
568
|
|
|
} |
569
|
1 |
|
$this->updateAttributes([ |
570
|
1 |
|
'pass_hash' => Yii::$app->getSecurity()->generatePasswordHash($this->password), |
571
|
|
|
'token' => null, |
572
|
1 |
|
'token_created_at' => 0, |
573
|
1 |
|
'status' => $this->status, |
574
|
|
|
]); |
575
|
1 |
|
if ($sendEmail === null) { |
576
|
1 |
|
$sendEmail = $this->getModule()->enableNewPasswordEmail; |
577
|
|
|
} |
578
|
1 |
|
if ($sendEmail) { |
579
|
1 |
|
$this->module->sendMessage('passchanged', [ |
580
|
1 |
|
'user' => $this, |
581
|
|
|
]); |
582
|
|
|
} |
583
|
1 |
|
} |
584
|
|
|
|
585
|
|
|
/** |
586
|
|
|
* Check that user request restore |
587
|
|
|
* @return bool |
588
|
|
|
*/ |
589
|
2 |
|
public function isRestore() |
590
|
|
|
{ |
591
|
2 |
|
return $this->status === self::STATUS_RESTORE; |
592
|
|
|
} |
593
|
|
|
|
594
|
|
|
/** |
595
|
|
|
* Get user status as text |
596
|
|
|
* @param string $status status value. If not set, get from model |
597
|
|
|
* @return null|string |
598
|
|
|
*/ |
599
|
|
|
public function getStatusText($status = null) |
600
|
|
|
{ |
601
|
|
|
if ($status === null) { |
602
|
|
|
$status = $this->status; |
603
|
|
|
} |
604
|
|
|
$statuses = self::statusesList(); |
605
|
|
|
return empty($statuses[$status]) ? '' : $statuses[$status]; |
606
|
|
|
} |
607
|
|
|
|
608
|
|
|
/** |
609
|
|
|
* Get status list as array |
610
|
|
|
* @return array |
611
|
|
|
*/ |
612
|
|
|
static public function statusesList() |
|
|
|
|
613
|
|
|
{ |
614
|
|
|
return [ |
615
|
|
|
self::STATUS_ACTIVE => Yii::t('activeuser_general', 'Active'), |
616
|
|
|
self::STATUS_BLOCKED => Yii::t('activeuser_general', 'Blocked'), |
617
|
|
|
self::STATUS_CONFIRM => Yii::t('activeuser_general', 'Confirm'), |
618
|
|
|
self::STATUS_RESTORE => Yii::t('activeuser_general', 'Restore'), |
619
|
|
|
]; |
620
|
|
|
} |
621
|
|
|
|
622
|
|
|
/** |
623
|
|
|
* Get user gender as text |
624
|
|
|
* @param int $gender gender value. If not set, get from model |
625
|
|
|
* @return null|string |
626
|
|
|
*/ |
627
|
|
|
public function getGenderText($gender = null) |
628
|
|
|
{ |
629
|
|
|
if ($gender === null) { |
630
|
|
|
$gender = $this->gender; |
631
|
|
|
} |
632
|
|
|
$genders = self::gendersList(); |
633
|
|
|
return empty($genders[$gender]) ? $genders[0] : $genders[$gender]; |
634
|
|
|
} |
635
|
|
|
|
636
|
|
|
/** |
637
|
|
|
* Get gender list as array |
638
|
|
|
* @return array |
639
|
|
|
*/ |
640
|
|
|
static public function gendersList() |
|
|
|
|
641
|
|
|
{ |
642
|
|
|
return [ |
643
|
|
|
0 => Yii::t('activeuser_general', 'None'), |
644
|
|
|
self::MALE => Yii::t('activeuser_general', 'Male'), |
645
|
|
|
self::FEMALE => Yii::t('activeuser_general', 'Female'), |
646
|
|
|
]; |
647
|
|
|
} |
648
|
|
|
|
649
|
|
|
/** |
650
|
|
|
* Resend confirmation message |
651
|
|
|
*/ |
652
|
|
|
public function resend() |
653
|
|
|
{ |
654
|
|
|
if ($this->getModule()->enableConfirmation && !$this->getIsNewRecord() && $this->status === self::STATUS_CONFIRM) { |
655
|
|
|
$this->generateToken(); |
656
|
|
|
$this->getModule()->sendMessage('confirm', [ |
657
|
|
|
'user' => $this, |
658
|
|
|
]); |
659
|
|
|
} |
660
|
|
|
} |
661
|
|
|
|
662
|
|
|
/** |
663
|
|
|
* @inheritdoc |
664
|
|
|
*/ |
665
|
15 |
|
public function behaviors() |
666
|
|
|
{ |
667
|
|
|
return [ |
668
|
|
|
[ |
669
|
15 |
|
'class' => ImageBehavior::className(), |
|
|
|
|
670
|
15 |
|
'imageAttribute' => 'avatar', |
671
|
15 |
|
'imageSize' => 150, |
672
|
15 |
|
'imageResizeStrategy' => ImageBehavior::CROP, |
673
|
|
|
] |
674
|
|
|
]; |
675
|
|
|
} |
676
|
|
|
} |
677
|
|
|
|
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.