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
![]() |
|||||
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
|
|||||
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
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
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. ![]() |
|||||
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
The property
created_at does not exist on app\models\User . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||
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
|
|||||
387 | } |
||||
388 | |||||
389 | return $this; |
||||
390 | } |
||||
391 | |||||
392 | /** |
||||
393 | * Validate password. |
||||
394 | * |
||||
395 | * @param string $password. |
||||
396 | * |
||||
397 | * @return bool. |
||||
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
|
|||||
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
|
|||||
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 |