UserValidate   A
last analyzed

Complexity

Total Complexity 34

Size/Duplication

Total Lines 387
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 141
dl 0
loc 387
c 0
b 0
f 0
rs 9.68
wmc 34

17 Methods

Rating   Name   Duplication   Size   Complexity  
B rules() 0 94 3
A getRoles() 0 4 1
B save() 0 26 7
A setUserModel() 0 3 1
A setAuthManager() 0 3 1
A validateRoles() 0 8 2
A __get() 0 13 3
A attributeLabels() 0 17 1
A getUserModel() 0 3 1
A scenarios() 0 6 1
A getId() 0 3 1
A getAuthManager() 0 3 1
A attributes() 0 17 1
A setRoles() 0 3 1
A assignRoles() 0 20 5
A __set() 0 8 2
A init() 0 4 2
1
<?php
2
3
namespace app\models;
4
5
use Yii;
6
use yii\db\ActiveRecordInterface;
7
use yii\web\IdentityInterface;
8
use yii\rbac\ManagerInterface;
9
use yii\base\{Model, InvalidConfigException};
10
use Itstructure\AdminModule\interfaces\ModelInterface;
11
use Itstructure\MFUploader\interfaces\UploadModelInterface;
12
13
/**
14
 * Class for validation user fields.
15
 *
16
 * @property bool $changeRoles
17
 * @property string[] $roles
18
 * @property IdentityInterface|ActiveRecordInterface  $userModel
19
 * @property ManagerInterface  $authManager
20
 * @property string  $first_name
21
 * @property string  $last_name
22
 * @property string  $patronymic
23
 * @property string  $login
24
 * @property string  $email
25
 * @property string  $phone
26
 * @property integer  $status
27
 * @property integer  $public
28
 * @property integer  $position_id
29
 * @property string  $about
30
 * @property string  $password
31
 * @property string  $passwordRepeat
32
 *
33
 * @package app\models
34
 */
35
class UserValidate extends Model implements ModelInterface
36
{
37
    /**
38
     * Allow to change roles.
39
     *
40
     * @var bool
41
     */
42
    public $changeRoles = true;
43
44
    /**
45
     * Current profile (user) model.
46
     *
47
     * @var IdentityInterface|ActiveRecordInterface
48
     */
49
    private $userModel;
50
51
    /**
52
     * Auth manager.
53
     *
54
     * @var ManagerInterface
55
     */
56
    private $authManager;
57
58
    /**
59
     * Initialize.
60
     */
61
    public function init()
62
    {
63
        if (null === $this->authManager) {
64
            throw new InvalidConfigException('The authManager is not defined.');
65
        }
66
    }
67
68
    /**
69
     * @inheritdoc
70
     */
71
    public function rules()
72
    {
73
        return [
74
            [
75
                [
76
                    'first_name',
77
                    'login',
78
                    'email',
79
                ],
80
                'required',
81
            ],
82
            [
83
                [
84
                    'password',
85
                    'passwordRepeat',
86
                ],
87
                'required',
88
                'on' => self::SCENARIO_CREATE,
89
            ],
90
            [
91
                [
92
                    'first_name',
93
                    'last_name',
94
                    'patronymic',
95
                    'login',
96
                    'email',
97
                    'phone',
98
                    'password',
99
                    'passwordRepeat',
100
                ],
101
                'string',
102
                'max' => 255,
103
            ],
104
            [
105
                [
106
                    'about',
107
                ],
108
                'string',
109
            ],
110
            [
111
                [
112
                    'status',
113
                    'public',
114
                    'position_id',
115
                ],
116
                'integer',
117
            ],
118
            [
119
                'login',
120
                'unique',
121
                'skipOnError'     => true,
122
                'targetClass'     => \Yii::$app->user->identityClass,
123
                'targetAttribute' => ['login' => 'login'],
124
                'filter' => $this->getScenario() == self::SCENARIO_UPDATE ? 'id != '.$this->id : ''
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on app\models\UserValidate. Since you implemented __get, consider adding a @property annotation.
Loading history...
125
            ],
126
            [
127
                'email',
128
                'unique',
129
                'skipOnError'     => true,
130
                'targetClass'     => \Yii::$app->user->identityClass,
131
                'targetAttribute' => ['email' => 'email'],
132
                'filter' => $this->getScenario() == self::SCENARIO_UPDATE ? 'id != '.$this->id : ''
133
            ],
134
            [
135
                'password',
136
                'compare',
137
                'compareAttribute' => 'passwordRepeat',
138
            ],
139
            [
140
                'passwordRepeat',
141
                'compare',
142
                'compareAttribute' => 'password',
143
            ],
144
            [
145
                'roles',
146
                'required',
147
            ],
148
            [
149
                'roles',
150
                'validateRoles',
151
            ],
152
            [
153
                UploadModelInterface::FILE_TYPE_THUMB,
154
                'integer',
155
                'skipOnError' => false,
156
            ],
157
            [
158
                [
159
                    'position_id'
160
                ],
161
                'exist',
162
                'skipOnError' => true,
163
                'targetClass' => Position::class,
164
                'targetAttribute' => ['position_id' => 'id']
165
            ],
166
        ];
167
    }
168
169
    /**
170
     * Scenarios.
171
     *
172
     * @return array
173
     */
174
    public function scenarios()
175
    {
176
        return [
177
            self::SCENARIO_CREATE => $this->attributes(),
178
            self::SCENARIO_UPDATE => $this->attributes(),
179
            self::SCENARIO_DEFAULT => $this->attributes(),
180
        ];
181
    }
182
183
    /**
184
     * List if attributes.
185
     *
186
     * @return array
187
     */
188
    public function attributes()
189
    {
190
        return [
191
            'first_name',
192
            'last_name',
193
            'patronymic',
194
            'position_id',
195
            'login',
196
            'email',
197
            'phone',
198
            'status',
199
            'public',
200
            'about',
201
            'password',
202
            'passwordRepeat',
203
            'roles',
204
            UploadModelInterface::FILE_TYPE_THUMB,
205
        ];
206
    }
207
208
    /**
209
     * List if attribute labels.
210
     *
211
     * @inheritdoc
212
     */
213
    public function attributeLabels()
214
    {
215
        return [
216
            'first_name' => Yii::t('users', 'First Name'),
217
            'last_name' => Yii::t('users', 'Last Name'),
218
            'patronymic' => Yii::t('users', 'Patronymic'),
219
            'position_id' => Yii::t('users', 'Position'),
220
            'login' => Yii::t('users', 'Login'),
221
            'email' => Yii::t('users', 'Email'),
222
            'phone' => Yii::t('users', 'Phone'),
223
            'status' => Yii::t('users', 'Status'),
224
            'public' => Yii::t('users', 'Publicity'),
225
            'about' => Yii::t('users', 'About'),
226
            'password' => Yii::t('users', 'Password'),
227
            'passwordRepeat' => Yii::t('users', 'Password confirm'),
228
            'roles' => Yii::t('users', 'Roles'),
229
            UploadModelInterface::FILE_TYPE_THUMB => Yii::t('users', 'Avatar')
230
        ];
231
    }
232
233
    /**
234
     * Get field value.
235
     *
236
     * @param string $name field name.
237
     *
238
     * @return mixed
239
     */
240
    public function __get($name)
241
    {
242
        $getter = 'get' . $name;
243
244
        if (method_exists($this, $getter)) {
245
            return $this->$getter();
246
        }
247
248
        if ($this->userModel->getIsNewRecord()) {
0 ignored issues
show
Bug introduced by
The method getIsNewRecord() does not exist on yii\web\IdentityInterface. It seems like you code against a sub-type of yii\web\IdentityInterface such as Itstructure\RbacModule\i...s\RbacIdentityInterface. ( Ignorable by Annotation )

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

248
        if ($this->userModel->/** @scrutinizer ignore-call */ getIsNewRecord()) {
Loading history...
249
            return $this->{$name} ?? '';
250
        }
251
252
        return $this->userModel->{$name} ?? '';
253
    }
254
255
    /**
256
     * Set field value.
257
     *
258
     * @param string $name  name of field.
259
     * @param mixed  $value value to be stored in field.
260
     *
261
     * @return void
262
     */
263
    public function __set($name, $value)
264
    {
265
        $setter = 'set' . $name;
266
267
        if (method_exists($this, $setter)) {
268
            $this->$setter($value);
269
        } else {
270
            $this->{$name} = $value;
271
        }
272
    }
273
274
    /**
275
     * Set new roles values.
276
     *
277
     * @param mixed $roles
278
     */
279
    public function setRoles($roles)
280
    {
281
        $this->roles = $roles;
282
    }
283
284
    /**
285
     * List of profile assigned roles.
286
     *
287
     * @return string[]
288
     */
289
    public function getRoles()
290
    {
291
        $roles = $this->authManager->getRolesByUser($this->userModel->getId());
292
        return array_keys($roles);
293
    }
294
295
    /**
296
     * Set user model.
297
     *
298
     * @param IdentityInterface $model.
299
     *
300
     * @throws InvalidConfigException
301
     *
302
     * @return void
303
     */
304
    public function setUserModel(IdentityInterface $model): void
305
    {
306
        $this->userModel = $model;
307
    }
308
309
    /**
310
     * Returns user model.
311
     *
312
     * @return IdentityInterface
313
     */
314
    public function getUserModel(): IdentityInterface
315
    {
316
        return $this->userModel;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->userModel could return the type yii\db\ActiveRecordInterface which is incompatible with the type-hinted return yii\web\IdentityInterface. Consider adding an additional type-check to rule them out.
Loading history...
317
    }
318
319
    /**
320
     * Set auth manager.
321
     *
322
     * @param ManagerInterface $authManager
323
     */
324
    public function setAuthManager(ManagerInterface $authManager): void
325
    {
326
        $this->authManager = $authManager;
327
    }
328
329
    /**
330
     * Get auth manager.
331
     *
332
     * @return ManagerInterface
333
     */
334
    public function getAuthManager(): ManagerInterface
335
    {
336
        return $this->authManager;
337
    }
338
339
    /**
340
     * Validate roles data format.
341
     *
342
     * @param $attribute
343
     *
344
     * @return bool
345
     */
346
    public function validateRoles($attribute): bool
347
    {
348
        if (!is_array($this->roles)) {
0 ignored issues
show
introduced by
The condition is_array($this->roles) is always true.
Loading history...
349
            $this->addError($attribute, 'Incorrect roles data format.');
350
            return false;
351
        }
352
353
        return true;
354
    }
355
356
    /**
357
     * Save user data.
358
     *
359
     * @return bool
360
     */
361
    public function save(): bool
362
    {
363
        if ($this->userModel->getIsNewRecord()) {
364
            $this->setScenario(self::SCENARIO_CREATE);
365
        } else {
366
            $this->setScenario(self::SCENARIO_UPDATE);
367
        }
368
369
        if (!$this->validate()) {
370
            return false;
371
        }
372
373
        foreach ($this->attributes() as $attribute) {
374
375
            if (null !== $this->{$attribute} && 'roles' !== $attribute) {
376
                $this->userModel->{$attribute} = $this->{$attribute};
377
            }
378
        }
379
380
        if (!$this->userModel->save()) {
0 ignored issues
show
Bug introduced by
The method save() does not exist on yii\web\IdentityInterface. It seems like you code against a sub-type of yii\web\IdentityInterface such as Itstructure\RbacModule\i...s\RbacIdentityInterface. ( Ignorable by Annotation )

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

380
        if (!$this->userModel->/** @scrutinizer ignore-call */ save()) {
Loading history...
381
            return false;
382
        }
383
384
        $this->assignRoles();
385
386
        return true;
387
    }
388
389
    /**
390
     * Returns current model id.
391
     *
392
     * @return int
393
     */
394
    public function getId(): int
395
    {
396
        return $this->userModel->getId();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->userModel->getId() could return the type string which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
397
    }
398
399
    /**
400
     * Assign roles.
401
     */
402
    private function assignRoles()
403
    {
404
        if (!$this->changeRoles) {
405
            return;
406
        }
407
408
        if (!$this->userModel->getIsNewRecord()) {
409
            $this->authManager->revokeAll(
410
                $this->userModel->getId()
411
            );
412
        }
413
414
        foreach ($this->roles as $role) {
415
            $roleObject = $this->authManager->getRole($role);
416
417
            if (null === $roleObject) {
418
                continue;
419
            }
420
421
            $this->authManager->assign($roleObject, $this->userModel->getId());
422
        }
423
    }
424
}
425