DefaultController   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 90
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 10

Importance

Changes 0
Metric Value
wmc 10
lcom 0
cbo 10
dl 0
loc 90
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
B filters() 0 38 1
A actionIndex() 0 4 1
B actionLogin() 0 23 4
A actionError() 0 13 3
A actionLogout() 0 5 1
1
<?php
2
3
namespace App\Controllers;
4
5
use App\Components\Controller;
6
use App\Components\View;
7
use App\Models\LoginFormModel;
8
use Micro\Base\KernelInjector;
9
use Micro\Form\FormBuilder;
10
use Micro\Web\Html\Html;
11
use Micro\Web\RequestInjector;
12
use Micro\Web\SessionInjector;
13
14
/**
15
 * Class DefaultController
16
 * @package App\Controllers
17
 */
18
class DefaultController extends Controller
19
{
20
    public function filters()
21
    {
22
        return [
23
            [
24
                'class' => '\Micro\Filter\AccessFilter',
25
                'actions' => ['login', 'logout', 'index'],
26
                'rules' => [
27
                    [
28
                        'allow' => false,
29
                        'actions' => ['index'],
30
                        'users' => ['@'],
31
                        'message' => 'Only for not authorized!'
32
                    ],
33
                    [
34
                        'allow' => false,
35
                        'actions' => ['login'],
36
                        'users' => ['@'],
37
                        'message' => 'Not authorized only'
38
                    ],
39
                    [
40
                        'allow' => false,
41
                        'actions' => ['logout'],
42
                        'users' => ['?'],
43
                        'message' => 'Authorized only'
44
                    ]
45
                ]
46
            ],
47
            [
48
                'class' => '\Micro\Filter\CsrfFilter',
49
                'actions' => ['login']
50
            ],
51
            [
52
                'class' => '\Micro\Filter\XssFilter',
53
                'actions' => ['index', 'login', 'logout'],
54
                'clean' => '*'
55
            ]
56
        ];
57
    }
58
59
    public function actionIndex()
60
    {
61
        return new View;
62
    }
63
64
    public function actionLogin()
65
    {
66
        /** @noinspection PhpIncludeInspection */
67
        $form = new FormBuilder(
68
            include (new KernelInjector)->build()->getAppDir() . '/views/default/loginform.php',
69
            new LoginFormModel(),
70
            'POST'
71
        );
72
        $body = (new RequestInjector)->build()->getParsedBody();
73
74
        if (!empty($body['LoginFormModel'])) {
75
            $form->setModelData($body['LoginFormModel']);
76
            /** @noinspection PhpUndefinedMethodInspection */
77
            if ($form->validateModel() && $form->getModel()->logined()) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Micro\Form\IFormModel as the method logined() does only exist in the following implementations of said interface: App\Models\LoginFormModel.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
78
                return $this->redirect('/profile');
79
            }
80
        }
81
82
        $v = new View();
83
        $v->addParameter('form', $form);
84
85
        return $v;
86
    }
87
88
    public function actionError()
89
    {
90
        $result = null;
91
        $body = (new RequestInjector())->build()->getParsedBody();
92
93
        if (!empty($body['error'])) {
94
            $result .= Html::heading(3, $body['error']->getMessage(), ['class' => 'text-danger bg-danger']);
95
        }
96
        $v = new View();
97
        $v->data = $result ?: 'undefined error';
98
99
        return $v;
100
    }
101
102
    public function actionLogout()
103
    {
104
        (new SessionInjector())->build()->destroy();
105
        return $this->redirect('/');
106
    }
107
}
108