Passed
Push — main ( 432d45...7922c5 )
by Sammy
01:40
created

Factory::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
eloc 1
c 1
b 1
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 1
1
<?php
2
3
namespace HexMakina\LeMarchand;
4
5
use Psr\Container\ContainerInterface;
6
7
class Factory
8
{
9
    private static $instance_cache = [];
10
11
    private $container = null;
12
13
    public function __construct(ContainerInterface $container)
14
    {
15
        $this->container = $container;
16
    }
17
18
    public function serve($class, $construction_args = null)
19
    {
20
        return $this->stock($class)
21
            ?? $this->build($class, $construction_args)
22
            ?? null;
23
    }
24
25
    public function stock($class, $instance = null)
26
    {
27
        if(!is_null($instance))
28
          self::$instance_cache[$class] = $instance;
29
30
        return self::$instance_cache[$class] ?? null;
31
    }
32
33
    public function build($class, $construction_args = null)
34
    {
35
      try {
36
          $reflection = new \ReflectionClass($class);
37
          $constructor = $reflection->getConstructor();
38
39
          $instance = null;
40
41
          if(is_null($constructor))
42
              $instance = $reflection->newInstanceArgs();
43
          else{
44
45
              if (empty($construction_args)) {
46
                  $construction_args = $this->getConstructorParameters($constructor);
47
              }
48
49
              $instance = $constructor->isPrivate()
50
                        ? $this->buildSingleton($reflection, $construction_args)
51
                        : $reflection->newInstanceArgs($construction_args);
52
          }
53
54
          $this->stock($class, $instance);
55
56
          return $instance;
57
58
      } catch (\ReflectionException $e) {
59
          throw new ContainerException($e->getMessage());
60
      }
61
    }
62
63
64
    private function getConstructorParameters(\ReflectionMethod $constructor)
65
    {
66
        $ret = [];
67
68
        foreach ($constructor->getParameters() as $param) {
69
70
            $id = $param->getType()
71
                  ? $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
                  ? $param->getType()->/** @scrutinizer ignore-call */ getName()
Loading history...
72
                  : 'settings.Constructor.' . $constructor->class . '.' . $param->getName();
73
74
            $ret []= $this->container->get($id);
75
76
        }
77
        return $ret;
78
    }
79
80
    private function buildSingleton(\ReflectionClass $rc, $construction_args)
81
    {
82
      // first argument is the instantiation method
83
      $singleton_method = $rc->getMethod(array_shift($construction_args));
84
85
      // second are the invocation args
86
      $construction_args = array_shift($construction_args);
87
88
      // invoke the method with args
89
      $singleton = $singleton_method->invoke(null, $construction_args);
90
91
      return $singleton;
92
    }
93
}
94