RunInTrait   A
last analyzed

Complexity

Total Complexity 42

Size/Duplication

Total Lines 177
Duplicated Lines 0 %

Importance

Changes 6
Bugs 0 Features 3
Metric Value
eloc 82
dl 0
loc 177
rs 9.0399
c 6
b 0
f 3
wmc 42

15 Methods

Rating   Name   Duplication   Size   Complexity  
A before() 0 3 1
A executeAfter() 0 6 2
A beforeGroup() 0 3 1
A getState() 0 12 6
A after() 0 3 1
A beforeAll() 0 5 2
A addInRoutes() 0 14 6
A executeBefore() 0 7 2
A executeState() 0 9 3
A setState() 0 19 4
A afterAll() 0 5 2
A executeRouteAction() 0 19 5
A afterGroup() 0 3 1
A addInRoute() 0 6 2
A executeController() 0 22 4

How to fix   Complexity   

Complex Class

Complex classes like RunInTrait often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use RunInTrait, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types = 1);
4
5
namespace HnrAzevedo\Router;
6
7
trait RunInTrait
8
{
9
    use Helper, 
10
        CheckTrait, 
11
        CurrentTrait;
12
13
    protected array $beforeExcepts = [];
14
    protected array $afterExcepts = [];
15
    protected \Closure $beforeAll;
16
    protected \Closure $afterAll;
17
18
    protected function getState(string $state, bool $except = false)
19
    {
20
        $this->beforeAll = (!isset($this->beforeAll)) ? function () {
21
        } : $this->beforeAll;
22
        $this->afterAll = (!isset($this->afterAll)) ? function () {
23
        } : $this->afterAll;
24
        
25
        if($state === 'before') {
26
            return ($except) ? $this->beforeExcepts : $this->beforeAll;
27
        }
28
29
        return ($except) ? $this->afterExcepts : $this->afterAll;
30
    }
31
32
    protected function setState(string $state, $settable, bool $except = false): bool
33
    {
34
        if($state === 'before') {
35
            if($except) {
36
                $this->beforeExcepts = $settable;
37
                return true;
38
            }
39
40
            $this->beforeAll = $settable;
41
            return true;
42
        }
43
44
        if($except) {
45
            $this->afterExcepts = $settable;
46
            return true;
47
        }
48
            
49
        $this->afterAll = $settable;
50
        return true;
51
    }
52
53
    public static function before($closure): RouterInterface
54
    {
55
        return self::addInRoute('before', $closure);
56
    }
57
58
    public static function after($closure): RouterInterface
59
    {
60
        return self::addInRoute('after', $closure);
61
    }
62
63
    public static function beforeAll($closure, ?array $excepts = null): RouterInterface
64
    {
65
        self::getInstance()->setState('before', (is_array($excepts)) ? $excepts : [], true);
66
        self::getInstance()->setState('before', $closure, false);
67
        return self::getInstance();
68
    }
69
70
    public static function afterAll($closure, ?array $excepts = null): RouterInterface
71
    {
72
        self::getInstance()->setState('after', (is_array($excepts)) ? $excepts : [], true);
73
        self::getInstance()->setState('after', $closure, false);
74
        return self::getInstance();
75
    }
76
77
    public static function beforeGroup($closure, ?array $excepts = null): RouterInterface
78
    {
79
        return self::addInRoutes('before', $closure, $excepts);
80
    }
81
82
    public static function afterGroup($closure, ?array $excepts = null): RouterInterface
83
    {
84
        return self::addInRoutes('after', $closure, $excepts);
85
    }
86
87
    protected function executeRouteAction($action): bool
88
    {
89
        if(is_callable($action)) { 
90
            
91
            $params = [];
92
            $closure = (get_class($action) !== 'Closure') ? $action->getClosure() : $action;
93
            $ReflectionMethod =  new \ReflectionFunction($closure);
94
95
            foreach($ReflectionMethod->getParameters() as $param){
96
                if(!isset($_REQUEST[$param->name])) continue;
97
                $params[$param->name] = $_REQUEST[$param->name];
98
            }
99
            
100
            call_user_func_array($closure, $params);
101
            return true;
102
        }
103
104
        $this->executeController($action);
105
        return true;
106
    }
107
108
    private static function addInRoutes(string $state, $closure, ?array $excepts = null): RouterInterface
109
    {
110
        self::getInstance()->isInPseudGroup();
111
        $excepts = (is_array($excepts)) ? $excepts : [];
112
        $group = self::getInstance()->inSave()['group'];
113
114
        foreach(self::getInstance()->getRoutes() as $r => $route){
115
            if($route['group'] === $group && !in_array($r, $excepts)) {
116
                $route[$state] = (is_null($route[$state])) ? [ $closure ] : array_merge($route[$state], [ $closure ]); 
117
                self::getInstance()->updateRoute($route, $r);
118
            }
119
        }
120
121
        return self::getInstance();
122
    }
123
124
    private static function addInRoute(string $state, $closure): RouterInterface
125
    {
126
        $route = self::getInstance()->inSave();
127
        $route[$state] = (!is_null($route[$state])) ? [ $closure ] : array_merge($route[$state], [ $closure ]);
128
        self::updateRoute($route, array_key_last(self::getInstance()->getRoutes()));
129
        return self::getInstance();
130
    }
131
132
    protected function executeBefore(): void
133
    {
134
        if(!in_array($this->currentName(), (array) $this->getState('before', true))) {
135
            ($this->getState('before', false))();
136
        }
137
138
        $this->executeState('before');
139
    }
140
141
    protected function executeAfter(): void
142
    {
143
        $this->executeState('after');
144
145
        if(!in_array($this->currentName(), (array) $this->getState('after', true))) {
146
            ($this->getState('after', false))();
147
        }
148
    }
149
150
    private function executeState(string $stage): void
151
    {
152
        foreach($this->current()[$stage] as $state){
153
            if(is_callable($state)) {
154
                $state();
155
                continue;
156
            }
157
158
            $this->executeController($state);
159
        }
160
    }
161
162
    private function executeController(string $controllerMeth): void
163
    {
164
        if(count(explode('@', $controllerMeth)) !== 2) {
165
            $path = urldecode(unserialize($this->current()['uri'])->getPath());
166
            throw new \RuntimeException("Misconfigured route action ({$path})");
167
        }
168
169
        $controller = (string) explode('@', $controllerMeth)[0];
170
        $method = (string) explode('@', $controllerMeth)[1];
171
172
        $this->checkControllerMeth($controllerMeth);
173
174
        $params = [];
175
176
        $ReflectionMethod =  new \ReflectionMethod(new $controller(), $method);
177
178
        foreach($ReflectionMethod->getParameters() as $param){
179
            if(!isset($_REQUEST[$param->name])) continue;
180
            $params[$param->name] = $_REQUEST[$param->name];
181
        }
182
183
        call_user_func_array([(new $controller()),$method], $params);
184
    }
185
186
}
187