Completed
Push — master ( bb9e46...bac48d )
by Théo
7s
created

BaseParametersResolver::getExpressionLanguage()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 11
ccs 0
cts 0
cp 0
rs 9.4285
cc 3
eloc 6
nc 3
nop 0
crap 12
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\Resolver;
13
14
use Fidry\LaravelYaml\Exception\DependencyInjection\Resolver\ParameterCircularReferenceException;
15
use Fidry\LaravelYaml\Exception\DependencyInjection\Resolver\RuntimeException;
16
use Fidry\LaravelYaml\Exception\Exception;
17
use Fidry\LaravelYaml\Exception\ParameterNotFoundException;
18
use Illuminate\Contracts\Config\Repository as ConfigRepository;
19
use Symfony\Component\ExpressionLanguage\Expression;
20
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
21
22
/**
23
 * @author Théo FIDRY <[email protected]>
24
 */
25
final class BaseParametersResolver implements ParametersResolverInterface
26
{
27
    /**
28
     * @var ConfigRepository
29
     */
30
    private $config;
31
32
    /**
33
     * @var string
34
     */
35
    private $defaultValue;
36
37
    /**
38
     * @var ExpressionLanguage|null
39
     */
40
    private $expressionLanguage;
41
42
    /**
43
     * @var array|null
44 6
     */
45
    private $parameters;
46 6
47 6
    /**
48 6
     * @var array
49
     */
50
    private $resolved = [];
51
52
    public function __construct(ConfigRepository $config)
53
    {
54
        $this->config = $config;
55
        $this->defaultValue = spl_object_hash(new \stdClass());
56
    }
57
58
    /**
59
     * {@inheritdoc}
60
     *
61 6
     * @param array $parameters
62
     *
63 6
     * @return array
64 6
     *
65 6
     * @throws ParameterCircularReferenceException
66 2
     * @throws ParameterNotFoundException
67 1
     * @throws Exception
68
     */
69 2
    public function resolve(array $parameters)
70
    {
71
        $this->parameters = $parameters;
72
        foreach ($this->parameters as $key => $value) {
73
            $value = $this->resolveValue($value, [$key => true]);
74
            $this->resolved[$key] = $value;
75
        }
76
77
        return $this->resolved;
78
    }
79
80 6
    /**
81
     * @param mixed $value
82 6
     * @param array $resolving
83 2
     *
84
     * @return mixed
85
     * @throws ParameterCircularReferenceException
86 6
     * @throws ParameterNotFoundException
87 2
     */
88
    private function resolveValue($value, $resolving = [])
89
    {
90 6
        if (is_bool($value) || is_numeric($value)) {
91 6
            return $value;
92
        }
93
94 2
        if (is_array($value)) {
95
            return $this->resolveArray($value, $resolving);
96
        }
97 2
        
98
        if ($value instanceof Expression) {
99 2
            return $this->getExpressionLanguage()->evaluate($value, array('container' => $this));
100 2
        }
101 2
102 1
        if (is_string($value)) {
103
            return $this->resolveString($value, $resolving);
104 2
        }
105
106
        return $value;
107
    }
108
109 View Code Duplication
    private function resolveArray(array $arrayValue, array $resolving)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
110
    {
111
        $resolvedValue = [];
112
        foreach ($arrayValue as $key => $value) {
113
            $resolvedValue[$key] = $this->resolveValue($value, $resolving);
114
        }
115 6
116
        return $resolvedValue;
117 6
    }
118 2
119 2
    /**
120
     * @param $value
121
     * @param $resolving
122
     *
123
     * @return array|mixed
124 6
     * @throws ParameterCircularReferenceException
125
     * @throws ParameterNotFoundException
126
     */
127 6
    private function resolveString($value, array $resolving)
128 4
    {
129
        if (0 === preg_match('/^%([^%\s]+)%$/', $value, $match)) {
130
            if (false === array_key_exists($value, $resolving)) {
131 4
                return $value;
132 2
            }
133
134
            $key = $value;
135 4
        } else {
136
            $key = $match[1];
137
        }
138
139
        if (array_key_exists($key, $this->parameters)) {
140
            return $this->resolveParameter($key, $resolving);
141
        }
142
143
        if ($this->config->has($key)) {
144
            return $this->config->get($key);
145
        }
146 4
147
        return $this->resolveEnvironmentValue($key);
148 4
    }
149 2
150
    /**
151
     * @param string $key
152 4
     * @param array  $resolving
153 2
     *
154 1
     * @return array|mixed
155 2
     * @throws ParameterCircularReferenceException
156 1
     * @throws ParameterNotFoundException
157 2
     */
158 1
    private function resolveParameter($key, array $resolving)
159 1
    {
160
        if (array_key_exists($key, $this->resolved)) {
161 4
            return $this->resolved[$key];
162 4
        }
163
164 2
        if (array_key_exists($key, $resolving)) {
165
            throw new ParameterCircularReferenceException(
166
                sprintf(
167
                    'Circular reference detected for the parameter "%s" while resolving [%s]',
168
                    $key,
169
                    implode(', ', array_keys($resolving))
170
                )
171
            );
172
        }
173 4
        $resolving[$key] = true;
174
        $this->resolved[$key] = $this->resolveValue($this->parameters[$key], $resolving);
175 4
176 4
        return $this->resolved[$key];
177 4
    }
178 2
179
    /**
180
     * @param string $key
181 2
     *
182
     * @return string|int|bool|null
183
     * @throws ParameterNotFoundException
184
     */
185 View Code Duplication
    private function resolveEnvironmentValue($key)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
186
    {
187
        $environmentKey = strtoupper(str_replace('.', '_', $key));
188
        $value = env($environmentKey, $this->defaultValue);
189
        if ($this->defaultValue !== $value) {
190
            return $value;
191
        }
192
193
        throw new ParameterNotFoundException(sprintf('No parameter "%s" found', $key));
194
    }
195
196
    /**
197
     * @return ExpressionLanguage
198
     * @throws RuntimeException
199
     */
200
    private function getExpressionLanguage()
201
    {
202
        if (null === $this->expressionLanguage) {
203
            if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
204
                throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
205
            }
206
            $this->expressionLanguage = new ExpressionLanguage();
207
        }
208
209
        return $this->expressionLanguage;
210
    }
211
}
212