Completed
Push — master ( 89be15...80fd60 )
by Igor
11:15
created

SignupProviderForm   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 150
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Importance

Changes 0
Metric Value
wmc 14
lcom 1
cbo 10
dl 0
loc 150
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A rules() 0 13 1
A attributeLabels() 0 6 1
A makeUploadedFile() 0 14 1
A savePhoto() 0 11 2
A login() 0 5 1
A signup() 0 19 4
A sendEmail() 0 22 3
1
<?php
2
3
namespace app\modules\auth\models\forms;
4
5
use Yii;
6
use yii\base\DynamicModel;
7
use yii\helpers\FileHelper;
8
use yii\web\UploadedFile;
9
use yii\base\{Exception, UserException};
10
use app\models\entity\{User, UserProfile};
11
use app\modules\auth\services\Tokenizer;
12
13
class SignupProviderForm extends \yii\base\Model
14
{
15
    /**
16
     * @var string
17
     */
18
    public $email;
19
    /**
20
     * @var \app\models\entity\User
21
     */
22
    private $user = null;
23
24
    /**
25
     * @param User $user
26
     */
27
    public function __construct($user)
28
    {
29
        $this->user = $user;
0 ignored issues
show
Documentation Bug introduced by
It seems like $user of type object<User> is incompatible with the declared type object<app\models\entity\User> of property $user.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
30
        $this->email = $user->email;
31
    }
32
33
    /**
34
     * @inheritdoc
35
     */
36
    public function rules()
37
    {
38
        return [
39
            ['email', 'filter', 'filter' => 'trim'],
40
            ['email', 'required'],
41
            ['email', 'string', 'max' => 255],
42
            ['email', 'email'],
43
            ['email', 'unique',
44
                'targetClass' => '\app\models\entity\User',
45
                'message' => Yii::t('app.msg', 'This email address has already been taken')
46
            ],
47
        ];
48
    }
49
50
    /**
51
     * @inheritdoc
52
     */
53
    public function attributeLabels()
54
    {
55
        return [
56
            'email' => Yii::t('app', 'Email'),
57
        ];
58
    }
59
60
    /**
61
     * Create manually UploadedFile instance by file path
62
     *
63
     * @param string $path file path
64
     * @return UploadedFile
65
     */
66
    private function makeUploadedFile(string $path): UploadedFile
67
    {
68
        $tmpFile = tempnam(sys_get_temp_dir(), 'app');
69
        file_put_contents($tmpFile, file_get_contents($path));
70
71
        $uploadedFile = new UploadedFile();
72
        $uploadedFile->name = strtok(pathinfo($path, PATHINFO_BASENAME), '?');
73
        $uploadedFile->tempName = $tmpFile;
74
        $uploadedFile->type = FileHelper::getMimeType($tmpFile);
75
        $uploadedFile->size = filesize($tmpFile);
76
        $uploadedFile->error = 0;
77
78
        return $uploadedFile;
79
    }
80
81
    /**
82
     * Save photo
83
     *
84
     * @param \app\models\entity\UserProfile $profile
85
     * @param string $photo
86
     * @return void
87
     */
88
    private function savePhoto(UserProfile $profile, string $photo): void
89
    {
90
        $file = $this->makeUploadedFile($photo);
91
        $model = new DynamicModel(compact('file'));
92
        $model->addRule('file', 'image', $profile->fileRules('photo', true))->validate();
0 ignored issues
show
Documentation Bug introduced by
The method fileRules does not exist on object<app\models\entity\UserProfile>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
93
        if (!$model->hasErrors()) {
94
            $profile->createFile('photo', $file->tempName, $model->file->name);
0 ignored issues
show
Documentation Bug introduced by
The method createFile does not exist on object<app\models\entity\UserProfile>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
95
        } else {
96
            $profile->photo = '';
97
        }
98
    }
99
100
    /**
101
     * Login
102
     */
103
    public function login(): void
104
    {
105
        $this->user->updateDateLogin();
106
        Yii::$app->user->login($this->user, 3600 * 24 * 30);
107
    }
108
109
    /**
110
     * Signs user up
111
     *
112
     * @throws Exception
113
     * @return \app\models\entity\User
114
     */
115
    public function signup(): User
116
    {
117
        $this->user->email = $this->email;
118
119
        $profile = $this->user->profile;
120
        if ($profile->isNewRecord && !empty($profile->photo)) {
121
            $this->savePhoto($profile, $profile->photo);
122
        }
123
124
        $this->user->status = User::STATUS_ACTIVE;
125
126
        if (!$this->user->save()) {
127
            throw new Exception(Yii::t('app.msg', 'An error occurred while saving user'));
128
        }
129
130
        $this->login();
131
132
        return $this->user;
133
    }
134
135
    /**
136
     * Sends an email with a link, for confirm the email
137
     *
138
     * @throws UserException
139
     */
140
    public function sendEmail(): void
141
    {
142
        $tokenizer = new Tokenizer();
143
        if (!$tokenizer->validate($this->user->email_confirm_token)) {
144
            $this->user->setEmailConfirmToken($tokenizer->generate());
145
            $this->user->updateAttributes([
146
                'email_confirm_token' => $this->user->email_confirm_token,
147
                'date_confirm' => $this->user->date_confirm,
148
            ]);
149
        }
150
151
        $sent = Yii::$app->notify->sendMessage(
152
            $this->email,
153
            Yii::t('app', 'Registration'),
154
            'registration',
155
            ['user' => $this->user]
156
        );
157
158
        if (!$sent) {
159
            throw new UserException(Yii::t('app.msg', 'An error occurred while sending a message to activate account'));
160
        }
161
    }
162
}
163