ReflectionContainer   A
last analyzed

Complexity

Total Complexity 18

Size/Duplication

Total Lines 91
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 6
Bugs 1 Features 2
Metric Value
wmc 18
eloc 40
dl 0
loc 91
ccs 41
cts 41
cp 1
rs 10
c 6
b 1
f 2

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
B call() 0 33 8
A has() 0 3 1
B get() 0 31 8
1
<?php
2
3
declare(strict_types=1);
4
5
namespace League\Container;
6
7
use League\Container\Argument\{ArgumentResolverInterface, ArgumentResolverTrait};
8
use League\Container\Exception\ContainerException;
9
use League\Container\Exception\NotFoundException;
10
use Psr\Container\ContainerInterface;
11
use ReflectionClass;
12
use ReflectionFunction;
13
use ReflectionMethod;
14
15
class ReflectionContainer implements ArgumentResolverInterface, ContainerInterface
16
{
17
    use ArgumentResolverTrait;
18
    use ContainerAwareTrait;
19
20
    /**
21
     * @var boolean
22
     */
23
    protected $cacheResolutions;
24
25
    /**
26
     * @var array
27
     */
28
    protected $cache = [];
29
30 54
    public function __construct(bool $cacheResolutions = false)
31
    {
32 54
        $this->cacheResolutions = $cacheResolutions;
33
    }
34
35 45
    public function get($id, array $args = [])
36
    {
37 45
        if ($this->cacheResolutions === true && array_key_exists($id, $this->cache)) {
38 6
            return $this->cache[$id];
39
        }
40
41 45
        if (!$this->has($id)) {
42 3
            throw new NotFoundException(
43 3
                sprintf('Alias (%s) is not an existing class and therefore cannot be resolved', $id)
44 3
            );
45
        }
46
47 42
        $reflector = new ReflectionClass($id);
48 42
        $construct = $reflector->getConstructor();
49
50 42
        if ($construct && !$construct->isPublic()) {
51 3
            throw new NotFoundException(
52 3
                sprintf('Alias (%s) has a non-public constructor and therefore cannot be instantiated', $id)
53 3
            );
54
        }
55
56 42
        $resolution = $construct === null
57 30
            ? new $id()
58 27
            : $reflector->newInstanceArgs($this->reflectArguments($construct, $args))
59 42
        ;
60
61 42
        if ($this->cacheResolutions === true) {
62 6
            $this->cache[$id] = $resolution;
63
        }
64
65 42
        return $resolution;
66
    }
67
68 51
    public function has($id): bool
69
    {
70 51
        return class_exists($id);
71
    }
72
73 18
    public function call(callable $callable, array $args = [])
74
    {
75 18
        if (is_string($callable) && strpos($callable, '::') !== false) {
76 3
            $callable = explode('::', $callable);
77
        }
78
79 18
        if (is_array($callable)) {
80 9
            if (is_string($callable[0])) {
0 ignored issues
show
introduced by
The condition is_string($callable[0]) is always true.
Loading history...
81
                // if we have a definition container, try that first, otherwise, reflect
82
                try {
83 3
                    $callable[0] = $this->getContainer()->get($callable[0]);
84 3
                } catch (ContainerException $e) {
85 3
                    $callable[0] = $this->get($callable[0]);
86
                }
87
            }
88
89 9
            $reflection = new ReflectionMethod($callable[0], $callable[1]);
90
91 9
            if ($reflection->isStatic()) {
92 3
                $callable[0] = null;
93
            }
94
95 9
            return $reflection->invokeArgs($callable[0], $this->reflectArguments($reflection, $args));
96
        }
97
98 9
        if (is_object($callable)) {
99 6
            $reflection = new ReflectionMethod($callable, '__invoke');
100 6
            return $reflection->invokeArgs($callable, $this->reflectArguments($reflection, $args));
101
        }
102
103 3
        $reflection = new ReflectionFunction(\Closure::fromCallable($callable));
104
105 3
        return $reflection->invokeArgs($this->reflectArguments($reflection, $args));
106
    }
107
}
108