Completed
Push — master ( cf9a3d...3ae770 )
by Théo
24:54 queued 09:56
created

ServiceInstantiator::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 9
rs 9.6666
cc 1
eloc 7
nc 1
nop 3
1
<?php
2
3
/*
4
 * This file is part of the LaravelYaml package.
5
 *
6
 * (c) Théo FIDRY <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Fidry\LaravelYaml\DependencyInjection\Builder\Instantiator;
13
14
use Fidry\LaravelYaml\DependencyInjection\Definition\FactoryInterface;
15
use Fidry\LaravelYaml\DependencyInjection\Definition\Reference;
16
use Fidry\LaravelYaml\DependencyInjection\Definition\ServiceInterface;
17
use Fidry\LaravelYaml\DependencyInjection\Resolver\ParameterResolverInterface;
18
use Fidry\LaravelYaml\DependencyInjection\Resolver\ReferenceResolverInterface;
19
use Illuminate\Contracts\Foundation\Application;
20
21
/**
22
 * @author Théo FIDRY <[email protected]>
23
 */
24
final class ServiceInstantiator
25
{
26
    /**
27
     * @var Application
28
     */
29
    private $application;
30
31
    /**
32
     * @var ParameterResolverInterface
33
     */
34
    private $parameterResolver;
35
36
    /**
37
     * @var ReferenceResolverInterface
38
     */
39
    private $referenceResolver;
40
41
    public function __construct(
42
        ParameterResolverInterface $parameterResolver,
43
        ReferenceResolverInterface $referenceResolver,
44
        Application $application
45
    ) {
46
        $this->parameterResolver = $parameterResolver;
47
        $this->referenceResolver = $referenceResolver;
48
        $this->application = $application;
49
    }
50
51
    /**
52
     * @param ServiceInterface $service
53
     *
54
     * @return object
55
     */
56
    public function create(ServiceInterface $service)
57
    {
58
        if ($service instanceof FactoryInterface) {
59
            return $this->factoryInstantiator($service);
60
        }
61
62
        return $this->constructorInstantiator($service);
63
    }
64
65
    /**
66
     * @param ServiceInterface $service
67
     *
68
     * @return object
69
     */
70
    private function constructorInstantiator(ServiceInterface $service)
71
    {
72
        $constructor = $service->getClass();
73
        $resolvedArguments = $this->resolveArguments($service);
74
75
        return new $constructor(...$resolvedArguments);
76
    }
77
78
    /**
79
     * @param FactoryInterface $service
80
     *
81
     * @return object
82
     */
83
    private function factoryInstantiator(FactoryInterface $service)
84
    {
85
        $factory = [
86
            $this->resolveArgument($service->getFactory()[0]),
87
            $service->getFactory()[1],
88
        ];
89
        $resolvedArguments = $this->resolveArguments($service);
90
91
        return call_user_func_array($factory, $resolvedArguments);
92
    }
93
94
    /**
95
     * @param ServiceInterface $service
96
     *
97
     * @return array
98
     */
99
    private function resolveArguments(ServiceInterface $service)
100
    {
101
        $resolvedArguments = [];
102
        foreach ($service->getArguments() as $argument) {
103
            $resolvedArguments[] = $this->resolveArgument($argument);
104
        }
105
106
        return $resolvedArguments;
107
    }
108
109
    /**
110
     * @param Reference|string $argument
111
     *
112
     * @return mixed
113
     */
114
    private function resolveArgument($argument)
115
    {
116
        if ($argument instanceof Reference) {
117
            return $this->referenceResolver->resolve($argument, $this->application);
118
        }
119
120
        return $this->parameterResolver->resolve($argument);
121
    }
122
}
123