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 ( 5821a5...6c281c )
by Dangerous
02:20
created

DiMaria::has()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 3
Metric Value
dl 0
loc 4
ccs 1
cts 1
cp 1
rs 10
cc 3
eloc 2
nc 4
nop 1
crap 3
1
<?php
2
namespace DD;
3
4
use DD\DiMaria\Exception\ContainerException;
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
        if (! $this->has($class)) {
102 21
            throw new NotFoundException('Class or alias ' . $class . ' does not exist');
103
        }
104
        while ($preference = $this->preferences[$class] ?? false) {
105
            $class = $preference;
106
        }
107
        $originalClass = $class;
108
        while ($alias = $this->aliases[$class] ?? false) {
109
            $params = $params + $alias['params'];
110 4
            $class = $alias['class'];
111
        }
112 4
        try {
113 4
            $callback = $this->cache[$originalClass] ?? $this->cache[$originalClass] = $this->getCallback($class, $originalClass);
114
            $object = $callback($params);
115
        } catch (\Exception $e) {
116
            throw new ContainerException($e->getMessage(), $e->getCode(), $e);
117
        } catch (\Error $e) {
118
            throw new ContainerException($e->getMessage(), $e->getCode(), $e);
119
        }
120
        if (isset($this->shared[$originalClass])) {
121
            $this->sharedInstance[$originalClass] = $object;
122 58
        }
123
        return $object;
124 58
    }
125 3
126
    protected function getCallback(string $class, string $originalClass): callable
127 58
    {
128 4
        $callback = $this->generateCallback($class);
129
        if (isset($this->injections[$originalClass])) {
130 58
            foreach ($this->injections[$originalClass] as $method => $instance) {
131 58
                $methodInfo = $this->getMethodInfo(new \ReflectionMethod($class, $method));
132 22
                foreach ($instance as $methodParameters) {
133 22
                    $methodParams = $this->getParameters($methodInfo, $methodParameters);
134
                    $callback = function ($params) use ($callback, $method, $methodParams) {
135 58
                        $object = $callback($params);
136 58
                        $object->$method(...$methodParams);
137 56
                        return $object;
138 4
                    };
139
                };
140 56
            }
141
        }
142
        return $callback;
143 58
    }
144
145 58
    protected function generateCallback(string $class): callable
146 58
    {
147 18
        $constructor = (new \ReflectionClass($class))->getConstructor();
148 18
        if (! $constructor || ! $constructor->getNumberOfParameters()) {
149 18
            return function () use ($class) {
150 18
                return new $class;
151
            };
152 18
        }
153 18
        $constructorInfo = $this->getMethodInfo($constructor);
154 18
        $predefinedParams = $this->params[$class] ?? [];
155 18
156
        return function ($params) use ($class, $constructorInfo, $predefinedParams) {
157
            return new $class(...$this->getParameters($constructorInfo, $params + $predefinedParams));
158
        };
159 58
    }
160 58
161
    protected function getMethodInfo(\ReflectionMethod $method): array
162
    {
163 58
        $paramInfo = [];
164
        foreach ($method->getParameters() as $param) {
165 58
            $paramType = $param->hasType() ? $param->getType() : null;
166 58
            $paramType = $paramType ? $paramType->isBuiltin() ? null : $paramType->__toString() : null;
167
            $paramInfo[$param->name] = [
168 29
                'name' => $param->name,
169 29
                'optional' => $param->isOptional(),
170
                'default' => $param->isOptional() ? ($param->isVariadic() ? null : $param->getDefaultValue()) : null,
171 40
                'variadic' => $param->isVariadic(),
172 40
                'type' => $paramType,
173 40
            ];
174 40
        }
175 40
        return $paramInfo;
176
    }
177
178 56
    public function getParameters(array $methodInfo, array $params): array
179
    {
180 56
        $parameters = [];
181 56
        foreach ($methodInfo as $param) {
182 53
            if (isset($params[$param['name']])) {
183 53
                array_push($parameters, ...$this->determineParameter($params[$param['name']], $param['variadic']));
184 53
            } elseif ($param['optional']) {
185 53
                if ($param['variadic']) {
186 53
                    break;
187 53
                }
188 53
                $parameters[] = $param['default'];
189 53
            } elseif ($param['type']) {
190
                $parameters[] = $this->get($param['type']);
191
            } else {
192 56
                throw new ContainerException('Required parameter $' . $param['name'] . ' is missing');
193
            }
194
        }
195 56
        return $parameters;
196
    }
197 56
198 56
    protected function determineParameter($param, bool $isVariadic): array
199 53
    {
200 39
        if (is_array($param)) {
201 29
            if ($isVariadic) {
202 26
                $params = [];
203 4
                foreach ($param as $val) {
204
                    $params[] = isset($val['instanceOf']) ? $this->get($val['instanceOf'], $val['params'] ?? []) : $val;
205 22
                }
206 15
                return $params;
207 13
            }
208
            return isset($param['instanceOf']) ? [$this->get($param['instanceOf'], $param['params'] ?? [])] : [$param];
209 51
        }
210
        return [$param];
211
    }
212
}
213