Passed
Push — master ( 9bf8dd...ef014d )
by Korotkov
07:46 queued 10s
created

Rudra   A

Complexity

Total Complexity 40

Size/Duplication

Total Lines 165
Duplicated Lines 0 %

Importance

Changes 7
Bugs 0 Features 2
Metric Value
eloc 60
c 7
b 0
f 2
dl 0
loc 165
rs 9.2
wmc 40

16 Methods

Rating   Name   Duplication   Size   Complexity  
A run() 0 7 2
A request() 0 3 1
A mergeData() 0 3 1
A set() 0 15 4
A response() 0 3 1
A config() 0 5 2
A new() 0 12 3
A has() 0 3 1
A binding() 0 5 2
A session() 0 3 1
A iOc() 0 12 3
B getParamsIoC() 0 32 9
A cookie() 0 3 1
A get() 0 11 5
A services() 0 5 2
A setObject() 0 3 2

How to fix   Complexity   

Complex Class

Complex classes like Rudra 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 Rudra, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * @author    : Jagepard <[email protected]">
7
 * @license   https://mit-license.org/ MIT
8
 */
9
10
namespace Rudra\Container;
11
12
use Rudra\Container\Traits\{InstantiationsTrait};
13
use Rudra\Container\Interfaces\{RequestInterface, RudraInterface, ContainerInterface, ResponseInterface};
14
15
class Rudra implements RudraInterface, ContainerInterface
16
{
17
    use InstantiationsTrait;
18
19
    public static ?RudraInterface $rudra = null;
20
    private array $data = [];
21
22
    public function binding(array $contracts = []): ContainerInterface
23
    {
24
        if (!$this->has("binding")) $this->set(["binding", new Container($contracts)]);
25
26
        return $this->get("binding");
27
    }
28
29
    public function services(array $services = []): ContainerInterface
30
    {
31
        if (!$this->has("services")) $this->set(["services", new Container($services)]);
32
33
        return $this->get("services");
34
    }
35
    
36
    public function config(array $config = []): ContainerInterface
37
    {
38
        if (!$this->has("config")) $this->set(["config", new Container($config)]);
39
40
        return $this->get("config");
41
    }
42
43
    public function request(): RequestInterface
44
    {
45
        return $this->containerize(Request::class);
46
    }
47
48
    public function response(): ResponseInterface
49
    {
50
        return $this->containerize(Response::class);
51
    }
52
53
    public function cookie(): Cookie
54
    {
55
        return $this->containerize(Cookie::class);
56
    }
57
58
    public function session(): Session
59
    {
60
        return $this->containerize(Session::class);
61
    }
62
63
    /*
64
     | Creates an object without adding to the container
65
     */
66
    public function new($object, $params = null)
67
    {
68
        $reflection = new \ReflectionClass($object);
69
        $constructor = $reflection->getConstructor();
70
71
        if ($constructor && $constructor->getNumberOfParameters()) {
72
            $paramsIoC = $this->getParamsIoC($constructor, $params);
73
74
            return $reflection->newInstanceArgs($paramsIoC);
75
        }
76
77
        return new $object();
78
    }
79
80
    public static function run(): RudraInterface
81
    {
82
        if (!static::$rudra instanceof static) {
83
            static::$rudra = new static();
84
        }
85
86
        return static::$rudra;
0 ignored issues
show
Bug Best Practice introduced by
The expression return static::rudra could return the type null which is incompatible with the type-hinted return Rudra\Container\Interfaces\RudraInterface. Consider adding an additional type-check to rule them out.
Loading history...
87
    }
88
89
    public function get(string $key = null)
90
    {
91
        if (isset($key) && !$this->has($key)) {
92
            if (!$this->services()->has($key)) {
93
                throw new \InvalidArgumentException("Service '$key' is not installed");
94
            }
95
96
            $this->set([$key, $this->services()->get($key)]);
97
        }
98
99
        return empty($key) ? $this->data : $this->data[$key];
100
    }
101
102
    public function set(array $data): void
103
    {
104
        list($key, $object) = $data;
105
106
        if (is_array($object)) {
107
            if (array_key_exists(1, $object) && !is_object($object[0])) {
108
                $this->iOc($key, $object[0], $object[1]);
109
                return;
110
            }
111
112
            $this->setObject($object[0], $key);
113
            return;
114
        }
115
116
        $this->setObject($object, $key);
117
    }
118
119
    public function has(string $key): bool
120
    {
121
        return array_key_exists($key, $this->data);
122
    }
123
124
    private function setObject($object, $key): void
125
    {
126
        (is_object($object)) ? $this->mergeData($key, $object) : $this->iOc($key, $object);
127
    }
128
129
    private function mergeData(string $key, $object)
130
    {
131
        $this->data = array_merge([$key => $object], $this->data);
132
    }
133
134
    private function iOc(string $key, $object, $params = null): void
135
    {
136
        $reflection = new \ReflectionClass($object);
137
        $constructor = $reflection->getConstructor();
138
139
        if ($constructor && $constructor->getNumberOfParameters()) {
140
            $paramsIoC = $this->getParamsIoC($constructor, $params);
141
            $this->mergeData($key, $reflection->newInstanceArgs($paramsIoC));
142
            return;
143
        }
144
145
        $this->mergeData($key, new $object());
146
    }
147
148
    private function getParamsIoC(\ReflectionMethod $constructor, $params): array
149
    {
150
        $i = 0;
151
        $paramsIoC = [];
152
        $params = (is_array($params) && array_key_exists(0, $params)) ? $params : [$params];
153
154
        foreach ($constructor->getParameters() as $value) {
155
            /*
156
             | If in the constructor expects the implementation of interface,
157
             | so that the container automatically created the necessary object and substituted as an argument,
158
             | we need to bind the interface with the implementation.
159
             */
160
            if (isset($value->getClass()->name) && $this->binding()->has($value->getClass()->name)) {
161
                $className = $this->binding()->get($value->getClass()->name);
162
                $paramsIoC[] = (is_object($className)) ? $className : new $className;
163
                continue;
164
            }
165
166
            /*
167
             | If the class constructor contains arguments with default values,
168
             | then if no arguments are passed,
169
             | values will be added by default by container
170
             */
171
            if ($value->isDefaultValueAvailable() && !isset($params[$i])) {
172
                $paramsIoC[] = $value->getDefaultValue();
173
                continue;
174
            }
175
176
            $paramsIoC[] = $params[$i++];
177
        }
178
179
        return $paramsIoC;
180
    }
181
}
182