Completed
Push — master ( 77319b...ee05cf )
by Théo
7s
created

ServicesBuilder::getParameterResolver()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.2559
Metric Value
dl 0
loc 10
ccs 3
cts 5
cp 0.6
rs 9.4285
cc 2
eloc 5
nc 2
nop 1
crap 2.2559
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;
13
14
use Fidry\LaravelYaml\DependencyInjection\Definition\Reference;
15
use Fidry\LaravelYaml\DependencyInjection\Definition\Service;
16
use Fidry\LaravelYaml\DependencyInjection\Resolver\BaseReferenceResolver;
17
use Fidry\LaravelYaml\DependencyInjection\Resolver\BuiltParameterResolver;
18
use Fidry\LaravelYaml\DependencyInjection\Resolver\ParameterResolverInterface;
19
use Fidry\LaravelYaml\DependencyInjection\Resolver\ReferenceResolverInterface;
20
use Fidry\LaravelYaml\Exception\DependencyInjection\Exception;
21
use Fidry\LaravelYaml\Exception\DependencyInjection\Resolver\Exception as ResolverException;
22
use Fidry\LaravelYaml\Exception\ServiceNotFoundException;
23
use Illuminate\Contracts\Config\Repository as ConfigRepository;
24
use Illuminate\Contracts\Container\BindingResolutionException;
25
use Illuminate\Contracts\Foundation\Application;
26
27
/**
28
 * @author Théo FIDRY <[email protected]>
29
 */
30
final class ServicesBuilder implements BuilderInterface
31
{
32
    /**
33
     * @var array
34
     */
35
    private $parameters;
36
37
    /**
38
     * @var ReferenceResolverInterface
39
     */
40
    private $referenceResolver;
41
42
    /**
43
     * @var Service[]
44
     */
45
    private $services;
46
47
    /**
48
     * @var ParameterResolverInterface|null
49
     */
50
    private $parameterResolver;
51
52
    /**
53
     * @param Service[]                       $services
54
     * @param array                           $parameters
55
     * @param ParameterResolverInterface|null $parameterResolver
56
     * @param ReferenceResolverInterface|null $referenceResolver
57
     */
58 24
    public function __construct(
59
        array $services,
60
        array $parameters,
61
        ParameterResolverInterface $parameterResolver = null,
62
        ReferenceResolverInterface $referenceResolver = null
63
    ) {
64 24
        $this->services = $services;
65 24
        $this->parameters = $parameters;
66 24
        $this->parameterResolver = $parameterResolver;
67 24
        $this->referenceResolver = (null === $referenceResolver) ? new BaseReferenceResolver() : $referenceResolver;
68 24
    }
69
70 24
    public function build(Application $application)
71
    {
72
73
        try {
74 24
            $parameterResolver = $this->getParameterResolver($application);
75 24
            foreach ($this->services as $service) {
76 21
                $this->buildService($service, $parameterResolver, $application);
77 10
            }
78
79 15
            return $this->parameters;
80 9
        } catch (BindingResolutionException $exception) {
81 3
            throw new Exception(sprintf('Could not load "%s" class', ConfigRepository::class), 0, $exception);
82 6
        } catch (ResolverException $exception) {
83 3
            throw new Exception('Could not resolve the parameters', 0, $exception);
84 3
        } catch (\Exception $exception) {
85 3
            throw new Exception('Could not build the parameters', 0, $exception);
86
        }
87
    }
88
89
    /**
90
     * @param Application $application
91
     *
92
     * @return ParameterResolverInterface
93
     */
94 24
    private function getParameterResolver(Application $application)
95
    {
96 24
        if (null === $this->parameterResolver) {
97
            $config = $application->make(ConfigRepository::class);
98
99
            return new BuiltParameterResolver($this->parameters, $config);
100
        }
101
102 24
        return $this->parameterResolver;
103
    }
104
105 21
    private function buildService(
106
        Service $service,
107
        ParameterResolverInterface $parameterResolver,
108
        Application $application
109
    ) {
110 21
        $instance = $this->getInstance($service, $parameterResolver, $application);
111
112 15
        $application->instance($service->getName(), $instance);
113 15
        $application->bind($service->getClass(), $service->getName());
114 12
        $this->bindAutowiringTypes($service, $application);
115 12
        $this->tagService($service, $application);
116 12
    }
117
118
    /**
119
     * @param Service                    $service
120
     * @param ParameterResolverInterface $parameterResolver
121
     * @param Application                $application
122
     *
123
     * @return object
124
     */
125 21
    private function getInstance(
126
        Service $service,
127
        ParameterResolverInterface $parameterResolver,
128
        Application $application
129
    ) {
130 21
        $constructor = $service->getClass();
131 21
        $resolvedArguments = $this->resolveArguments($service, $parameterResolver, $application);
132
133 15
        return new $constructor(...$resolvedArguments);
134
    }
135
136
    /**
137
     * @param Service                    $service
138
     * @param ParameterResolverInterface $parameterResolver
139
     * @param Application                $application
140
     *
141
     * @return array
142
     * @throws ServiceNotFoundException
143
     */
144 21
    private function resolveArguments(
145
        Service $service,
146
        ParameterResolverInterface $parameterResolver,
147
        Application $application
148
    ) {
149 21
        $resolvedArguments = [];
150 21
        foreach ($service->getArguments() as $argument) {
151 9
            if ($argument instanceof Reference) {
152 3
                $resolvedArguments[] = $this->referenceResolver->resolve($argument, $application);
153
154 3
                continue;
155
            }
156
157 9
            $resolvedArguments[] = $parameterResolver->resolve($argument);
158 10
        }
159
160 15
        return $resolvedArguments;
161
    }
162
163 12
    private function bindAutowiringTypes(Service $service, Application $application)
164
    {
165 12
        foreach ($service->getAutowiringTypes() as $binding) {
166 3
            $application->bind($binding, $service->getName());
167 8
        }
168 12
    }
169
170 12
    private function tagService(Service $service, Application $application)
171
    {
172 12
        if (count($service->getTags()) === 0) {
173 9
            return;
174
        }
175
176 3
        $application->tag($service->getName(), array_keys($service->getTags()));
177 3
    }
178
}
179