SingUp::verifyEmail()   B
last analyzed

Complexity

Conditions 9
Paths 97

Size

Total Lines 102
Code Lines 50

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 50
dl 0
loc 102
rs 7.5353
c 0
b 0
f 0
cc 9
nc 97
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Auth\Controller;
4
5
use Auth\Model\User;
6
use Auth\Model\UserTbl;
7
use Drone\Db\TableGateway\EntityAdapter;
8
use Drone\Debug\Catcher;
0 ignored issues
show
Bug introduced by
The type Drone\Debug\Catcher 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...
9
use Drone\Dom\Element\Form;
10
use Drone\Mvc\AbstractionController;
11
use Drone\Network\Http;
12
use Drone\Pear\Mail;
13
use Drone\Validator\FormValidator;
14
use Zend\Crypt\Password\Bcrypt;
15
16
class SingUp extends AbstractionController
17
{
18
    use \Drone\Error\ErrorTrait;
19
20
    /**
21
     * @var UsersEntity
0 ignored issues
show
Bug introduced by
The type Auth\Controller\UsersEntity 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...
22
     */
23
    private $userAdapter;
24
25
    /**
26
     * @return UsersEntity
27
     */
28
    private function getUserAdapter()
29
    {
30
        if (!is_null($this->userAdapter))
31
            return $this->userAdapter;
32
33
        $this->userAdapter = new EntityAdapter(new UserTbl(new User()));
0 ignored issues
show
Documentation Bug introduced by
It seems like new Drone\Db\TableGatewa...new Auth\Model\User())) of type Drone\Db\TableGateway\EntityAdapter is incompatible with the declared type Auth\Controller\UsersEntity of property $userAdapter.

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...
34
35
        return $this->userAdapter;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->userAdapter returns the type Drone\Db\TableGateway\EntityAdapter which is incompatible with the documented return type Auth\Controller\UsersEntity.
Loading history...
36
    }
37
38
    /**
39
     * Checks user session and redirect to other module if exists any active session
40
     *
41
     * @return null
42
     */
43
    private function checkSession()
44
    {
45
        $config = include 'module/Auth/config/user.config.php';
46
        $method = $config["authentication"]["method"];
47
        $key    = $config["authentication"]["key"];
48
49
        $global_config = include 'config/global.config.php';
50
51
        /** URL TO REDIRECT:
52
         *
53
         * By default if there isn't a session active, it will be redirected to the module in the user config file ($config["redirect"]).
54
         * If a last URI requested exists, it will be redirecto to it.
55
         *
56
         * Other modules must have the following line of code inside init method to ensure last uri redirection.
57
         * $_SESSION["last_uri_" . $global_config["project"]["id"]] = $_SERVER["REQUEST_URI"];
58
         * It should be an unique session id for the app to prevent bad redirections with other projects.
59
         */
60
        if (array_key_exists("last_uri_" . $global_config["project"]["id"], $_SESSION) || !empty($_SESSION["last_uri_" . $global_config["project"]["id"]]))
61
            $location = $_SESSION["last_uri_" . $global_config["project"]["id"]];
62
        else
63
            $location = $this->getBasePath() . "/public/" . $config["redirect"];
64
65
        switch ($method)
66
        {
67
            case '_COOKIE':
68
69
                if (array_key_exists($key, $_COOKIE) || !empty($_COOKIE[$key]))
70
                    header("location: " . $location);
71
72
                break;
73
74
            case '_SESSION':
75
76
                if (array_key_exists($key, $_SESSION) || !empty($_SESSION[$key]))
77
                    header("location: " . $location);
78
79
                break;
80
        }
81
    }
82
83
    /**
84
     * Shows register form
85
     *
86
     * @return array
87
     */
88
    public function index()
89
    {
90
        # STANDARD VALIDATIONS [check method]
91
        if (!$this->isGet())
92
        {
93
            $http = new Http();
94
            $http->writeStatus($http::HTTP_METHOD_NOT_ALLOWED);
95
96
            die('Error ' . $http::HTTP_METHOD_NOT_ALLOWED .' (' . $http->getStatusText($http::HTTP_METHOD_NOT_ALLOWED) . ')!!');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
97
        }
98
99
        $this->checkSession();
100
101
        return [];
102
    }
103
104
    /**
105
     * Does register process
106
     *
107
     * @return array
108
     */
109
    public function attemp()
110
    {
111
        # data to send
112
        $data = [];
113
114
        # environment settings
115
        $post = $this->getPost();           # catch $_POST
116
        $this->setTerminal(true);           # set terminal
117
118
        # TRY-CATCH-BLOCK
119
        try {
120
121
            # STANDARD VALIDATIONS [check method]
122
            if (!$this->isPost())
123
            {
124
                $http = new Http();
125
                $http->writeStatus($http::HTTP_METHOD_NOT_ALLOWED);
126
127
                die('Error ' . $http::HTTP_METHOD_NOT_ALLOWED .' (' . $http->getStatusText($http::HTTP_METHOD_NOT_ALLOWED) . ')!!');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
128
            }
129
130
            # STANDARD VALIDATIONS [check needed arguments]
131
            $needles = ['username', 'email', 'password', 'password_confirm'];
132
133
            array_walk($needles, function(&$item) use ($post) {
134
                if (!array_key_exists($item, $post))
135
                {
136
                    $http = new Http();
137
                    $http->writeStatus($http::HTTP_BAD_REQUEST);
138
139
                    die('Error ' . $http::HTTP_BAD_REQUEST .' (' . $http->getStatusText($http::HTTP_BAD_REQUEST) . ')!!');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
140
                }
141
            });
142
143
            $this->checkSession();
144
145
            if ($post["password"] !== $post["password_confirm"])
146
                throw new \Drone\Exception\Exception("The password fields are different!", 300);
147
148
            $components = [
149
                "attributes" => [
150
                    "username" => [
151
                        "required"  => true,
152
                        "type"      => "text",
153
                        "minlength" => 4,
154
                        "maxlength" => 20
155
                    ],
156
                    "email" => [
157
                        "required"  => true,
158
                        "type"      => "text",
159
                        "minlength" => 4,
160
                        "maxlength" => 50
161
                    ],
162
                    "password" => [
163
                        "required"  => true,
164
                        "type"      => "text",
165
                        "minlength" => 4,
166
                        "maxlength" => 20
167
                    ],
168
                    "password_confirm" => [
169
                        "required"  => true,
170
                        "type"      => "text",
171
                        "minlength" => 4,
172
                        "maxlength" => 20
173
                    ]
174
                ],
175
            ];
176
177
            $options = [
178
                "username" => [
179
                    "label"      => "Username",
180
                    "validators" => [
181
                        "Alnum"  => ["allowWhiteSpace" => false]
182
                    ]
183
                ],
184
                "email" => [
185
                    "label"      => "Email"
186
                ],
187
                "password" => [
188
                    "label"      => "Password"
189
                ],
190
                "password_confirm" => [
191
                    "label"      => "Password confirmation"
192
                ]
193
            ];
194
195
            $form = new Form($components);
196
            $form->fill($post);
197
198
            $validator = new FormValidator($form, $options);
199
            $validator->validate();
200
201
            $data["validator"] = $validator;
202
203
            # STANDARD VALIDATIONS [check argument constraints]
204
            if (!$validator->isValid())
205
            {
206
                $data["messages"] = $validator->getMessages();
207
                throw new \Drone\Exception\Exception("Form validation errors!", 300);
208
            }
209
210
            $config = include 'module/Auth/config/user.config.php';
211
            $username_str = $config["authentication"]["gateway"]["credentials"]["username"];
212
            $password_str = $config["authentication"]["gateway"]["credentials"]["password"];
213
            $state_field  = $config["authentication"]["gateway"]["table_info"]["columns"]["state_field"];
214
            $id_field     = $config["authentication"]["gateway"]["table_info"]["columns"]["id_field"];
215
            $email_field  = $config["authentication"]["gateway"]["table_info"]["columns"]["email_field"];
216
217
            $pending_state = $config["authentication"]["gateway"]["table_info"]["column_values"]["state_field"]["pending_email"];
218
            $active_state  = $config["authentication"]["gateway"]["table_info"]["column_values"]["state_field"]["user_active"];
219
220
            $rowset = $this->getUserAdapter()->select([
221
                $username_str => $post["username"]
222
            ]);
223
224
            if (count($rowset))
225
                throw new \Drone\Exception\Exception("This username already exists!", 300);
226
227
            $bcrypt = new Bcrypt();
228
            $securePass = $bcrypt->create($post["password"]);
229
230
            $t = base64_encode(time() . uniqid());
231
            $token = substr($t, 0, 30);
232
233
            $this->getUserAdapter()->getTableGateway()->getDriver()->getDb()->beginTransaction();
234
235
            $data["mail"] = ($config["mail"]["checking"]["enabled"] == "Y") ? true : false;
236
237
            $user = new User();
238
239
            $user->exchangeArray([
240
                $id_field     => $this->getUserAdapter()->getTableGateway()->getNextId(),
241
                $state_field  => $data["mail"] ? $pending_state : $active_state,
242
                $username_str => $post["username"],
243
                $email_field  => $post["email"],
244
                "TOKEN"       => $token,
245
                $password_str => $securePass
246
            ]);
247
248
            $this->getUserAdapter()->insert($user);
249
250
            $link = $_SERVER["REQUEST_SCHEME"] .'://'. $_SERVER["HTTP_HOST"] . $this->getBasePath() . "/public/Auth/SingUp/verifyEmail/user/" . $post["username"] . "/token/" . $token;
251
252
            if ($data["mail"])
253
            {
254
                $from = $config["mail"]["checking"]["from"];
255
                $host = $config["mail"]["host"];
256
257
                $mail = new Mail();
258
                $mail->setHost($host);
259
                $subject = $this->translator->translate("Email checking") . "!";
0 ignored issues
show
Bug Best Practice introduced by
The property translator does not exist on Auth\Controller\SingUp. Did you maybe forget to declare it?
Loading history...
260
                $body = $this->translator->translate("Your account has been registered") . "!." .
261
                        $this->translator->translate("Please click on the following link to confirm your account") .
262
                            "<br /><br /><a href='$link'>$link</a>.";
263
264
                $success = $mail->send($from, $post["email"], $subject, $body);
265
266
                if (!$success)
267
                {
268
                    $errors = array_values($mail->getErrors());
269
                    $err = array_shift($errors);
270
                    $this->getUserAdapter()->getTableGateway()->getDriver()->getDb()->rollback();
271
                    throw new \Exception($err);
272
                }
273
            }
274
275
            $this->getUserAdapter()->getTableGateway()->getDriver()->getDb()->endTransaction();
276
277
            $data["username"] = $post["username"];
278
            $data["email"] = $post["email"];
279
280
            # SUCCESS-MESSAGE
281
            $data["process"] = "success";
282
        }
283
        catch (\Drone\Exception\Exception $e)
284
        {
285
            # ERROR-MESSAGE
286
            $data["process"] = "warning";
287
            $data["message"] = $e->getMessage();
288
        }
289
        catch (\Exception $e)
290
        {
291
            $file = str_replace('\\', '', __CLASS__);
292
            $storage = new \Drone\Exception\Storage("cache/$file.json");
293
294
            # stores the error code
295
            if (($errorCode = $storage->store($e)) === false)
0 ignored issues
show
introduced by
The condition $errorCode = $storage->store($e) === false is always true.
Loading history...
296
            {
297
                $errors = $storage->getErrors();
298
299
                # if error storing is not possible, handle it (internal app error)
300
                $this->handleErrors($errors, __METHOD__);
301
            }
302
303
            # errors retrived by the use of ErrorTrait
304
            if (count($this->getErrors()))
305
                $this->handleErrors($this->getErrors(), __METHOD__);
306
307
            $data["code"]    = $errorCode;
308
            $data["message"] = $e->getMessage();
309
310
            $config = include 'config/application.config.php';
311
            $data["dev_mode"] = $config["environment"]["dev_mode"];
312
313
            # redirect view
314
            $this->setMethod('error');
315
316
            return $data;
317
        }
318
319
        return $data;
320
    }
321
322
    /**
323
     * Does email checking
324
     *
325
     * @return array
326
     */
327
    public function verifyEmail()
328
    {
329
        # data to send
330
        $data = [];
331
332
        # TRY-CATCH-BLOCK
333
        try {
334
335
            # STANDARD VALIDATIONS [check method]
336
            if (!$this->isGet())
337
            {
338
                $http = new Http();
339
                $http->writeStatus($http::HTTP_METHOD_NOT_ALLOWED);
340
341
                die('Error ' . $http::HTTP_METHOD_NOT_ALLOWED .' (' . $http->getStatusText($http::HTTP_METHOD_NOT_ALLOWED) . ')!!');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
342
            }
343
344
            # STANDARD VALIDATIONS [check needed arguments]
345
            $needles = ['token', 'user'];
346
347
            array_walk($needles, function($item) {
348
                if (!array_key_exists($item, $_GET))
349
                {
350
                    $http = new Http();
351
                    $http->writeStatus($http::HTTP_BAD_REQUEST);
352
353
                    die('Error ' . $http::HTTP_BAD_REQUEST .' (' . $http->getStatusText($http::HTTP_BAD_REQUEST) . ')!!');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
354
                }
355
            });
356
357
            $config = include 'module/Auth/config/user.config.php';
358
            $username_str = $config["authentication"]["gateway"]["credentials"]["username"];
359
            $state_field  = $config["authentication"]["gateway"]["table_info"]["columns"]["state_field"];
360
361
            $pending_state = $config["authentication"]["gateway"]["table_info"]["column_values"]["state_field"]["pending_email"];
362
            $active_state  = $config["authentication"]["gateway"]["table_info"]["column_values"]["state_field"]["user_active"];
363
364
            # catch arguments
365
            $token = $_GET["token"];
366
            $user  = $_GET["user"];
367
368
            $row = $this->getUserAdapter()->select([
369
                $username_str => $user,
370
                "TOKEN"       => $token
371
            ]);
372
373
            if (!count($row))
374
                throw new \Drone\Exception\Exception("Token has expired or username does not exists!.");
375
376
            $user = array_shift($row);
377
378
            if ($user->{$state_field} <> $pending_state)
379
                throw new \Drone\Exception\Exception("This email address had verified before!.", 300);
380
381
            $user->exchangeArray([
382
                $state_field => $active_state
383
            ]);
384
385
            $this->getUserAdapter()->update($user, [
386
                $username_str => $user->{$username_str}
387
            ]);
388
389
            # SUCCESS-MESSAGE
390
            $data["process"] = "success";
391
        }
392
        catch (\Drone\Exception\Exception $e)
393
        {
394
            # ERROR-MESSAGE
395
            $data["process"] = "warning";
396
            $data["message"] = $e->getMessage();
397
        }
398
        catch (\Exception $e)
399
        {
400
            $file = str_replace('\\', '', __CLASS__);
401
            $storage = new \Drone\Exception\Storage("cache/$file.json");
402
403
            # stores the error code
404
            if (($errorCode = $storage->store($e)) === false)
0 ignored issues
show
introduced by
The condition $errorCode = $storage->store($e) === false is always true.
Loading history...
405
            {
406
                $errors = $storage->getErrors();
407
408
                # if error storing is not possible, handle it (internal app error)
409
                $this->handleErrors($errors, __METHOD__);
410
            }
411
412
            # errors retrived by the use of ErrorTrait
413
            if (count($this->getErrors()))
414
                $this->handleErrors($this->getErrors(), __METHOD__);
415
416
            $data["code"]    = $errorCode;
417
            $data["message"] = $e->getMessage();
418
419
            $config = include 'config/application.config.php';
420
            $data["dev_mode"] = $config["environment"]["dev_mode"];
421
422
            # redirect view
423
            $this->setMethod('error');
424
425
            return $data;
426
        }
427
428
        return $data;
429
    }
430
431
    private function handleErrors(Array $errors, $method)
432
    {
433
        if (count($errors))
434
        {
435
            $errorInformation = "";
436
437
            foreach ($errors as $errno => $error)
438
            {
439
                $errorInformation .=
440
                    "<strong style='color: #a94442'>".
441
                        $method
442
                            . "</strong>: <span style='color: #e24f4c'>{$error}</span> \n<br />";
443
            }
444
445
            $hd = @fopen('cache/errors.txt', "a");
446
447
            if (!$hd || !@fwrite($hd, $errorInformation))
0 ignored issues
show
introduced by
$hd is of type false|resource, thus it always evaluated to false.
Loading history...
448
            {
449
                # error storing are not mandatory!
450
            }
451
            else
452
                @fclose($hd);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for fclose(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

452
                /** @scrutinizer ignore-unhandled */ @fclose($hd);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
453
454
            $config = include 'config/application.config.php';
455
            $dev = $config["environment"]["dev_mode"];
456
457
            if ($dev)
458
                echo $errorInformation;
459
        }
460
    }
461
}