Passed
Push — main ( 8b738d...e342ba )
by Sammy
01:20
created

ReflectionFactory::makeWithContructorArgs()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 9
c 0
b 0
f 0
dl 0
loc 16
rs 9.9666
cc 2
nc 2
nop 3
1
<?php
2
3
namespace HexMakina\LeMarchand;
4
5
class ReflectionFactory
6
{
7
    private static $instance_cache = [];
8
9
    public static function make($class, $construction_args = [], $container)
10
    {
11
        try {
12
            $rc = new \ReflectionClass($class);
13
            $instance = null;
14
15
            if (!is_null($constructor = $rc->getConstructor())) {
16
                $instance = self::makeWithContructorArgs($rc, $construction_args, $container);
17
            } else {
18
                $instance = $rc->newInstanceArgs();
19
            }
20
21
            if ($rc->hasMethod('set_container')) {
22
                $instance->set_container($container);
23
            }
24
25
            self::setCacheFor($class, $instance);
26
27
            return $instance;
28
        } catch (\ReflectionException $e) {
29
            throw new ContainerException($e->getMessage());
30
        }
31
    }
32
33
    public static function hasCacheFor($class)
34
    {
35
        return isset(self::$instance_cache[$class]);
36
    }
37
38
    public static function getCacheFor($class)
39
    {
40
        return self::$instance_cache[$class];
41
    }
42
43
    public static function setCacheFor($class, $instance)
44
    {
45
        self::$instance_cache[$class] = $instance;
46
    }
47
48
    private static function makeWithContructorArgs(\ReflectionClass $rc, $construction_args, $container)
49
    {
50
        $constructor = $rc->getConstructor();
51
        $construction_args = self::getConstructorParameters($constructor, $construction_args, $container);
52
53
        $instance = null;
54
        if ($constructor->isPrivate()) { // singleton ?
55
          // first argument is the static instance-making method
56
            $singleton_method = $rc->getMethod(array_shift($construction_args));
57
            // invoke the method with remaining constructor args
58
            $instance = $container->resolved($rc->getName(), $singleton_method->invoke(null, $construction_args));
59
        } else {
60
            $instance = $rc->newInstanceArgs($construction_args);
61
        }
62
63
        return $instance;
64
    }
65
66
    private static function getConstructorParameters(\ReflectionMethod $constructor, $construction_args = [], $container)
67
    {
68
        if (empty($construction_args)) {
69
            foreach ($constructor->getParameters() as $param) {
70
                if ($param->getType()) {
71
                    $construction_args [] = $container->get($param->getType()->getName());
0 ignored issues
show
Bug introduced by
The method getName() does not exist on ReflectionType. It seems like you code against a sub-type of ReflectionType such as ReflectionNamedType. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

71
                    $construction_args [] = $container->get($param->getType()->/** @scrutinizer ignore-call */ getName());
Loading history...
72
                } else {
73
                    $setting = 'settings.Constructor.' . $constructor->class . '.' . $param->getName();
74
                    $construction_args [] = $container->getSettings($setting);
75
                }
76
            }
77
        }
78
        return $construction_args;
79
    }
80
}
81