GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( aaffd4...08de09 )
by Dangerous
02:14
created

DiMaria::setPreference()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1
Metric Value
dl 0
loc 5
ccs 3
cts 3
cp 1
rs 9.4285
cc 1
eloc 3
nc 1
nop 2
crap 1
1
<?php
2
namespace DD;
3
4
/**
5
 * DiMaria Dependency injector
6
 */
7
class DiMaria
8
{
9
    protected $preferences = [];
10
    protected $aliases = [];
11
    protected $cache = [];
12
    protected $injections = [];
13
    protected $params = [];
14
    protected $shared = [];
15
    protected $sharedInstance = [];
16
17
    /**
18
     * Set multiple di rules at once.
19
     * @param array $rules a multi-dimensional array of rules to set
20
     * @return self
21
     */
22 3
    public function setRules(array $rules): self
23
    {
24 3
        $rules['preferences'] = $rules['preferences'] ?? [];
25 3
        $rules['aliases'] = $rules['aliases'] ?? [];
26 3
        $rules['params'] = $rules['params'] ?? [];
27 3
        $rules['shared'] = $rules['shared'] ?? [];
28 3
        $rules['injections'] = $rules['injections'] ?? [];
29
30 3
        foreach ($rules['preferences'] as $interface => $class) {
31 1
            $this->setPreference($interface, $class);
32
        }
33 3
        foreach ($rules['aliases'] as $alias => $aliasConfig) {
34 1
            $this->setAlias($alias, ...$aliasConfig);
35
        };
36 3
        foreach ($rules['params'] as $instance => $params) {
37 1
            $this->setParams($instance, $params);
38
        }
39 3
        foreach ($rules['shared'] as $instance => $isShared) {
40 1
            if ($isShared) {
41 1
                $this->setShared($instance);
42
            }
43
        };
44 3
        foreach ($rules['injections'] as $instance => $config) {
45 1
            foreach ($config as $params) {
46 1
                $this->setInjection($instance, ...$params);
47
            }
48
        }
49 3
        return $this;
50
    }
51
52
    /**
53
     * Set a preferred implementation of a class/interface
54
     * @param string $alias     the name of the alias
55
     * @param string $className the name of the class/interface
56
     * @return self
57
     */
58 4
    public function setPreference(string $alias, string $className): self
59
    {
60 4
        $this->preferences[$alias] = $className;
61 4
        return $this;
62
    }
63
64
    /**
65
     * Alias a class/interface/alias to a string.
66
     * @param string $alias     the name of the alias
67
     * @param string $className the name of the class
68
     * @param array  $params    a key/value array of parameter names and values
69
     * @return self
70
     */
71 23
    public function setAlias(string $alias, string $className, array $params = []): self
72
    {
73 23
        $this->aliases[$alias] = [
74 23
            'className' => $className,
75 23
            'params' => $params
76
        ];
77 23
        return $this;
78
    }
79
80
    /**
81
     * Set rule to call a method after constructing a class
82
     * @param string $className the name of the class
83
     * @param string $method    the name of the method
84
     * @param array  $params    a key/value array of parameter names and values
85
     * @return self
86
     */
87 19
    public function setInjection(string $className, string $method, array $params = []): self
88
    {
89 19
        $this->injections[$className][$method][] = $params;
90 19
        return $this;
91
    }
92
93
    /**
94
     * Set parameters of a class
95
     * @param string $className the name of the class
96
     * @param array  $params    a key/value array of parameter names and values
97
     * @return self
98
     */
99 21
    public function setParams(string $className, array $params): self
100
    {
101 21
        $this->params[$className] = $params + ($this->params[$className] ?? []);
102 21
        return $this;
103
    }
104
105
    /**
106
     * Mark a class/alias as shared
107
     * @param string $className the name of class/alias
108
     * @return self
109
     */
110 4
    public function setShared(string $className): self
111
    {
112 4
        $this->shared[$className] = true;
113 4
        return $this;
114
    }
115
116
    /**
117
     * Get an instance of a class
118
     * @param  string $className the name of class/alias to create
119
     * @param  array $params     a key/value array of parameter names and values
120
     * @return mixed             an instance of the class requested
121
     */
122 58
    public function get(string $className, array $params = [])
123
    {
124 58
        if (isset($this->shared[$className]) && isset($this->sharedInstance[$className])) {
125 3
            return $this->sharedInstance[$className];
126
        }
127 58
        while ($preference = $this->preferences[$className] ?? false) {
128 4
            $className = $preference;
129
        }
130 58
        $originalClassName = $className;
131 58
        while ($alias = $this->aliases[$className] ?? false) {
132 22
            $params = $params + $alias['params'];
133 22
            $className = $alias['className'];
134
        }
135 58
        $callback = $this->cache[$originalClassName] ?? $this->getCallback($className, $originalClassName);
136 58
        $object = $callback($params);
137 56
        if (isset($this->shared[$originalClassName])) {
138 4
            $this->sharedInstance[$originalClassName] = $object;
139
        }
140 56
        return $object;
141
    }
142
143 58
    protected function getCallback(string $className, string $originalClassName): callable
144
    {
145 58
        $callback = $this->generateCallback($className);
146 58
        if (isset($this->injections[$originalClassName])) {
147 18
            foreach ($this->injections[$originalClassName] as $method => $instance) {
148 18
                $methodInfo = $this->getMethodInfo(new \ReflectionMethod($className, $method));
149 18
                foreach ($instance as $methodParameters) {
150 18
                    $methodParams = $this->getParameters($methodInfo, $methodParameters);
151
                    $callback = function ($params) use ($callback, $method, $methodParams) {
152 18
                        $object = $callback($params);
153 18
                        $object->$method(...$methodParams);
154 18
                        return $object;
155 18
                    };
156
                };
157
            }
158
        }
159 58
        $this->cache[$originalClassName] = $callback;
160 58
        return $callback;
161
    }
162
163 58
    protected function generateCallback(string $className): callable
164
    {
165 58
        $constructor = (new \ReflectionClass($className))->getConstructor();
166 58
        if (! $constructor || ! $constructor->getNumberOfParameters()) {
167
            return function () use ($className) {
168 29
                return new $className;
169 29
            };
170
        }
171 40
        $constructorInfo = $this->getMethodInfo($constructor);
172 40
        $predefinedParams = $this->params[$className] ?? [];
173 40
        return function ($params) use ($className, $constructorInfo, $predefinedParams) {
174 40
            return new $className(...$this->getParameters($constructorInfo, $params + $predefinedParams));
175 40
        };
176
    }
177
178 56
    protected function getMethodInfo(\ReflectionMethod $method): array
179
    {
180 56
        $paramInfo = [];
181 56
        foreach ($method->getParameters() as $param) {
182 53
            $paramType = $param->hasType() ? $param->getType() : null;
183 53
            $paramType = $paramType ? $paramType->isBuiltin() ? null : $paramType->__toString() : null;
184 53
            $paramInfo[$param->name] = [
185 53
                'name' => $param->name,
186 53
                'optional' => $param->isOptional(),
187 53
                'default' => $param->isOptional() ? ($param->isVariadic() ? null : $param->getDefaultValue()) : null,
188 53
                'variadic' => $param->isVariadic(),
189 53
                'type' => $paramType,
190
            ];
191
        }
192 56
        return $paramInfo;
193
    }
194
195 56
    protected function getParameters(array $methodInfo, array $params): array
196
    {
197 56
        $parameters = [];
198 56
        foreach ($methodInfo as $param) {
199 53
            if (isset($params[$param['name']])) {
200 39
                array_push($parameters, ...$this->determineParameter($params[$param['name']], $param['variadic']));
201 29
            } elseif ($param['optional']) {
202 26
                if ($param['variadic']) {
203 4
                    break;
204
                }
205 22
                $parameters[] = $param['default'];
206 15
            } elseif ($param['type']) {
207 13
                $parameters[] = $this->get($param['type']);
208
            } else {
209 51
                throw new \Exception('Required parameter $' . $param['name'] . ' is missing');
210
            }
211
        }
212 54
        return $parameters;
213
    }
214
215 39
    protected function determineParameter($param, bool $isVariadic): array
216
    {
217 39
        if (is_array($param)) {
218 15
            if ($isVariadic) {
219 7
                $params = [];
220 7
                foreach ($param as $a) {
221 7
                    $params[] = isset($a['instanceOf']) ? $this->get($a['instanceOf']) : $a;
222
                }
223 7
                return $params;
224
            }
225 8
            return isset($param['instanceOf']) ? [$this->get($param['instanceOf'])] : [$param];
226
        }
227 33
        return [$param];
228
    }
229
}
230