Completed
Pull Request — 2.x (#216)
by Akihito
09:22
created

FactoryCode::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
c 0
b 0
f 0
rs 9.8666
cc 1
nc 1
nop 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Ray\Compiler;
6
7
use PhpParser\Node;
8
use PhpParser\Node\Expr;
9
use PhpParser\NodeAbstract;
10
use Ray\Di\Argument;
11
use Ray\Di\Container;
12
use Ray\Di\InjectorInterface;
13
use Ray\Di\Instance;
14
use Ray\Di\Name;
15
use Ray\Di\SetterMethod;
16
17
final class FactoryCode
18
{
19
    /**
20
     * @var Container
21
     */
22
    private $container;
23
24
    /**
25
     * @var Normalizer
26
     */
27
    private $normalizer;
28
29
    /**
30
     * @var null|InjectorInterface
31
     */
32
    private $injector;
33
34
    /**
35
     * @var NodeFactory
36
     */
37
    private $nodeFactory;
38
39
    /**
40
     * @var FunctionCode
41
     */
42
    private $functionCompiler;
43
44
    public function __construct(
45
        Container $container,
46
        Normalizer $normalizer,
47
        DependencyCode $compiler,
48
        InjectorInterface $injector = null
49
    ) {
50
        $this->container = $container;
51
        $this->normalizer = $normalizer;
52
        $this->injector = $injector;
53
        $this->nodeFactory = new NodeFactory($normalizer, $this, $injector);
54
        $this->functionCompiler = new FunctionCode($container, new PrivateProperty, $compiler);
55
    }
56
57
    /**
58
     * @param array<Argument>     $arguments
59
     * @param array<SetterMethod> $setterMethods
60
     *
61
     * @return array<Expr>
62
     */
63
    public function getFactoryCode(string $class, array $arguments, array $setterMethods, string $postConstruct) : array
64
    {
65
        $node = [];
66
        $instance = new Expr\Variable('instance');
67
        // constructor injection
68
        $constructorInjection = $this->getConstructorInjection($class, $arguments);
69
        $node[] = new Expr\Assign($instance, $constructorInjection);
70
        $setters = $this->nodeFactory->getSetterInjection($instance, $setterMethods);
71
        foreach ($setters as $setter) {
72
            $node[] = $setter;
73
        }
74
        if ($postConstruct) {
75
            $node[] = $this->nodeFactory->getPostConstruct($instance, $postConstruct);
76
        }
77
78
        return $node;
79
    }
80
81
    /**
82
     * Return method argument code
83
     *
84
     * @return Expr|Expr\FuncCall
85
     */
86
    public function getArgStmt(Argument $argument) : NodeAbstract
87
    {
88
        $dependencyIndex = (string) $argument;
89
        if ($dependencyIndex === 'Ray\Di\InjectionPointInterface-' . Name::ANY) {
90
            return $this->getInjectionPoint();
91
        }
92
        $hasDependency = isset($this->container->getContainer()[$dependencyIndex]);
93
        if (! $hasDependency) {
94
            return $this->nodeFactory->getNode($argument);
95
        }
96
        $dependency = $this->container->getContainer()[$dependencyIndex];
97
        if ($dependency instanceof Instance) {
98
            return ($this->normalizer)($dependency->value);
99
        }
100
101
        return ($this->functionCompiler)($argument, $dependency);
102
    }
103
104
    /**
105
     * @param array<Argument> $arguments
106
     */
107
    private function getConstructorInjection(string $class, array $arguments = []) : Expr\New_
108
    {
109
        $args = [];
110
        foreach ($arguments as $argument) {
111
            //            $argument = $argument->isDefaultAvailable() ? $argument->getDefaultValue() : $argument;
112
            $args[] = $this->getArgStmt($argument);
113
        }
114
        /** @var array<Node\Arg> $args */
115
        return new Expr\New_(new Node\Name\FullyQualified($class), $args);
116
    }
117
118
    /**
119
     * Return "$injection_point()"
120
     */
121
    private function getInjectionPoint() : Expr
122
    {
123
        return new Expr\FuncCall(new Expr\Variable('injection_point'));
124
    }
125
}
126