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 ( 6c281c...502620 )
by Dangerous
02:13
created

DiMaria::get()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 4
Metric Value
dl 0
loc 11
ccs 3
cts 3
cp 1
rs 9.2
cc 4
eloc 7
nc 3
nop 2
crap 4
1
<?php
2
namespace DD;
3
4
use DD\DiMaria\Exception\DiMariaException;
5
use DD\DiMaria\Exception\NotFoundException;
6
use Interop\Container\ContainerInterface;
7
8
/**
9
 * DiMaria Dependency injector
10
 */
11
class DiMaria implements ContainerInterface
12
{
13
    protected $preferences = [];
14
    protected $aliases = [];
15
    protected $cache = [];
16
    protected $injections = [];
17
    protected $params = [];
18
    protected $shared = [];
19
    protected $sharedInstance = [];
20
21
    /**
22 3
     * Set a preferred implementation of a class/interface
23
     * @param string $alias  the name of the alias
24 3
     * @param string $class  the name of the class/interface
25 3
     * @return self
26 3
     */
27 3
    public function setPreference(string $alias, string $class): self
28 3
    {
29
        $this->preferences[$alias] = $class;
30 3
        return $this;
31 1
    }
32
33 3
    /**
34 1
     * Alias a class/interface/alias to a string.
35
     * @param string $alias   the name of the alias
36 3
     * @param string $class   the name of the class
37 1
     * @param array  $params  a key/value array of parameter names and values
38
     * @return self
39 3
     */
40 1
    public function setAlias(string $alias, string $class, array $params = []): self
41 1
    {
42
        $this->aliases[$alias] = [
43
            'class' => $class,
44 3
            'params' => $params
45 1
        ];
46 1
        return $this;
47
    }
48
49 3
    /**
50
     * Set rule to call a method after constructing a class
51
     * @param string $class the name of the class
52
     * @param string $method    the name of the method
53
     * @param array  $params    a key/value array of parameter names and values
54
     * @return self
55
     */
56
    public function setInjection(string $class, string $method, array $params = []): self
57
    {
58 4
        $this->injections[$class][$method][] = $params;
59
        return $this;
60 4
    }
61 4
62
    /**
63
     * Set parameters of a class
64
     * @param string $class the name of the class
65
     * @param array  $params    a key/value array of parameter names and values
66
     * @return self
67
     */
68
    public function setParams(string $class, array $params): self
69
    {
70
        $this->params[$class] = $params + ($this->params[$class] ?? []);
71 23
        return $this;
72
    }
73 23
74 23
    /**
75 23
     * Mark a class/alias as shared
76
     * @param string $class the name of class/alias
77 23
     * @return self
78
     */
79
    public function setShared(string $class): self
80
    {
81
        $this->shared[$class] = true;
82
        return $this;
83
    }
84
85
    public function has($class): bool
86
    {
87 19
        return class_exists($class) ?: isset($this->aliases[$class]) ?: isset($this->preferences[$class]);
88
    }
89 19
90 19
    /**
91
     * Get an instance of a class
92
     * @param  string $class  the name of class/alias to create
93
     * @param  array $params  a key/value array of parameter names and values
94
     * @return mixed          an instance of the class requested
95
     */
96
    public function get($class, array $params = [])
97
    {
98
        if (isset($this->shared[$class]) && isset($this->sharedInstance[$class])) {
99 21
            return $this->sharedInstance[$class];
100
        }
101 21
        $object = $this->newInstance($class, $params);
102 21
        if (isset($this->shared[$originalClass])) {
103
            $this->sharedInstance[$originalClass] = $object;
0 ignored issues
show
Bug introduced by
The variable $originalClass does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
104
        }
105
        return $object;
106
    }
107
108
    /**
109
     * Get a new instance of a class
110 4
     * @param  string $class  the name of class/alias to create
111
     * @param  array $params  a key/value array of parameter names and values
112 4
     * @return mixed          an instance of the class requested
113 4
     */
114
    public function newInstance(string $class, array $params = [])
115
    {
116
        if (! $this->has($class)) {
117
            throw new NotFoundException('Class or alias ' . $class . ' does not exist');
118
        }
119
        while ($preference = $this->preferences[$class] ?? false) {
120
            $class = $preference;
121
        }
122 58
        $originalClass = $class;
123
        while ($alias = $this->aliases[$class] ?? false) {
124 58
            $params = $params + $alias['params'];
125 3
            $class = $alias['class'];
126
        }
127 58
        try {
128 4
            $callback = $this->cache[$originalClass] ?? $this->cache[$originalClass] = $this->getCallback($class, $originalClass);
129
            return $callback($params);
130 58
        } catch (\Exception $e) {
131 58
            throw new ContainerException($e->getMessage(), $e->getCode(), $e);
132 22
        } catch (\Error $e) {
133 22
            throw new ContainerException($e->getMessage(), $e->getCode(), $e);
134
        }
135 58
    }
136 58
137 56
    protected function getCallback(string $class, string $originalClass): callable
138 4
    {
139
        $callback = $this->generateCallback($class);
140 56
        if (isset($this->injections[$originalClass])) {
141
            foreach ($this->injections[$originalClass] as $method => $instance) {
142
                $methodInfo = $this->getMethodInfo(new \ReflectionMethod($class, $method));
143 58
                foreach ($instance as $methodParameters) {
144
                    $methodParams = $this->getParameters($methodInfo, $methodParameters);
145 58
                    $callback = function ($params) use ($callback, $method, $methodParams) {
146 58
                        $object = $callback($params);
147 18
                        $object->$method(...$methodParams);
148 18
                        return $object;
149 18
                    };
150 18
                };
151
            }
152 18
        }
153 18
        return $callback;
154 18
    }
155 18
156
    protected function generateCallback(string $class): callable
157
    {
158
        $constructor = (new \ReflectionClass($class))->getConstructor();
159 58
        if (! $constructor || ! $constructor->getNumberOfParameters()) {
160 58
            return function () use ($class) {
161
                return new $class;
162
            };
163 58
        }
164
        $constructorInfo = $this->getMethodInfo($constructor);
165 58
        $predefinedParams = $this->params[$class] ?? [];
166 58
167
        return function ($params) use ($class, $constructorInfo, $predefinedParams) {
168 29
            return new $class(...$this->getParameters($constructorInfo, $params + $predefinedParams));
169 29
        };
170
    }
171 40
172 40
    protected function getMethodInfo(\ReflectionMethod $method): array
173 40
    {
174 40
        $paramInfo = [];
175 40
        foreach ($method->getParameters() as $param) {
176
            $paramType = $param->hasType() ? $param->getType() : null;
177
            $paramType = $paramType ? $paramType->isBuiltin() ? null : $paramType->__toString() : null;
178 56
            $paramInfo[$param->name] = [
179
                'name' => $param->name,
180 56
                'optional' => $param->isOptional(),
181 56
                'default' => $param->isOptional() ? ($param->isVariadic() ? null : $param->getDefaultValue()) : null,
182 53
                'variadic' => $param->isVariadic(),
183 53
                'type' => $paramType,
184 53
            ];
185 53
        }
186 53
        return $paramInfo;
187 53
    }
188 53
189 53
    public function getParameters(array $methodInfo, array $params): array
190
    {
191
        $parameters = [];
192 56
        foreach ($methodInfo as $param) {
193
            if (isset($params[$param['name']])) {
194
                array_push($parameters, ...$this->determineParameter($params[$param['name']], $param['variadic']));
195 56
            } elseif ($param['optional']) {
196
                if ($param['variadic']) {
197 56
                    break;
198 56
                }
199 53
                $parameters[] = $param['default'];
200 39
            } elseif ($param['type']) {
201 29
                $parameters[] = $this->get($param['type']);
202 26
            } else {
203 4
                throw new ContainerException('Required parameter $' . $param['name'] . ' is missing');
204
            }
205 22
        }
206 15
        return $parameters;
207 13
    }
208
209 51
    protected function determineParameter($param, bool $isVariadic): array
210
    {
211
        if (is_array($param)) {
212 54
            if ($isVariadic) {
213
                $params = [];
214
                foreach ($param as $val) {
215 39
                    $params[] = isset($val['instanceOf']) ? $this->get($val['instanceOf'], $val['params'] ?? []) : $val;
216
                }
217 39
                return $params;
218 15
            }
219 7
            return isset($param['instanceOf']) ? [$this->get($param['instanceOf'], $param['params'] ?? [])] : [$param];
220 7
        }
221 7
        return [$param];
222
    }
223
}
224