Resolver::inject()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 9
ccs 4
cts 4
cp 1
crap 2
rs 10
1
<?php
2
3
namespace Palmtree\Container;
4
5
use Palmtree\Container\Exception\ParameterNotFoundException;
6
use Palmtree\Container\Exception\ServiceNotFoundException;
7
use Palmtree\Container\Exception\ServiceNotPublicException;
8
9
class Resolver
10
{
11
    /** Regex for single parameters e.g '%my.parameter%' */
12
    private const PATTERN_PARAMETER = '/^%([^%\s]+)%$/';
13
    /** Regex for multiple parameters in a string */
14
    private const PATTERN_MULTI_PARAMETER = '/%%|%([^%\s]+)%/';
15
    /** @var Container */
16
    private $container;
17
    /** @var array */
18
    private $containerServices;
19
    /** @var array */
20
    private $envCache = [];
21
22 27
    public function __construct(Container $container, array &$containerServices)
23
    {
24 27
        $this->container         = $container;
25 27
        $this->containerServices = &$containerServices;
26 27
    }
27
28 27
    public function resolveArgs(array $args): array
29
    {
30 27
        foreach ($args as $key => &$arg) {
31 25
            if (\is_array($arg)) {
32 24
                $arg = $this->resolveArgs($arg);
33
            } else {
34 25
                $arg = $this->resolveArg($arg);
35
            }
36
        }
37
38 27
        return $args;
39
    }
40
41
    /**
42
     * @param mixed $arg
43
     *
44
     * @return mixed
45
     *
46
     * @throws ServiceNotFoundException
47
     * @throws ParameterNotFoundException
48
     */
49 26
    public function resolveArg($arg)
50
    {
51 26
        if (!\is_string($arg) || $arg === '') {
52 23
            return $arg;
53
        }
54
55 26
        if ($arg[0] === '@') {
56 23
            return $this->inject(substr($arg, 1));
57
        }
58
59 26
        return $this->resolveParameter($arg);
60
    }
61
62
    /**
63
     * @return mixed
64
     *
65
     * @throws ServiceNotFoundException
66
     */
67 23
    private function inject(string $key)
68
    {
69
        try {
70 23
            $this->container->get($key);
71 23
        } catch (ServiceNotPublicException $e) {
72
            // Ensures the service is created. Private services are allowed to be injected.
73
        }
74
75 23
        return $this->containerServices[$key];
76
    }
77
78
    /**
79
     * @param string $arg
80
     *
81
     * @return mixed
82
     *
83
     * @throws ParameterNotFoundException
84
     */
85 26
    private function resolveParameter($arg)
86
    {
87
        // Resolve a single parameter value e.g %my_param%
88
        // Used for non-string values (boolean, integer etc)
89 26
        if (preg_match(self::PATTERN_PARAMETER, $arg, $matches)) {
90 23
            $envKey = $this->getEnvParameterKey($matches[1]);
91
92 23
            if ($envKey !== null) {
93 23
                return $this->getEnv($envKey);
94
            }
95
96 23
            $constKey = $this->getConstParameterKey($matches[1]);
97
98 23
            if ($constKey !== null) {
99 23
                return \constant($constKey);
100
            }
101
102 23
            return $this->container->getParameter($matches[1]);
103
        }
104
105
        // Resolve multiple parameters in a string e.g /%parent_dir%/somewhere/%child_dir%
106
        return preg_replace_callback(self::PATTERN_MULTI_PARAMETER, function ($matches) {
107
            // Skip %% to allow escaping percent signs
108 23
            if (!isset($matches[1])) {
109 23
                return '%';
110
            }
111
112 23
            if ($envKey = $this->getEnvParameterKey($matches[1])) {
113 23
                return $this->getEnv($envKey);
114
            }
115
116 23
            if ($constKey = $this->getConstParameterKey($matches[1])) {
117
                return \constant($constKey);
118
            }
119
120 23
            return $this->container->getParameter($matches[1]);
121 26
        }, $arg);
122
    }
123
124 23
    private function getEnvParameterKey(string $value): ?string
125
    {
126 23
        if (strpos($value, 'env(') === 0 && substr($value, -1) === ')' && $value !== 'env()') {
127 23
            return substr($value, 4, -1);
128
        }
129
130 23
        return null;
131
    }
132
133 23
    private function getConstParameterKey(string $value): ?string
134
    {
135 23
        if (strpos($value, 'constant(') === 0 && substr($value, -1) === ')' && $value !== 'constant()') {
136 23
            return substr($value, 9, -1);
137
        }
138
139 23
        return null;
140
    }
141
142
    /**
143
     * @return string|bool
144
     */
145 23
    private function getEnv(string $key)
146
    {
147 23
        if (isset($this->envCache[$key]) || \array_key_exists($key, $this->envCache)) {
148 23
            return $this->envCache[$key];
149
        }
150
151 23
        if (!$envVar = getenv($key)) {
152
            try {
153 22
                $envVar = $this->resolveArg($this->container->getParameter("env($key)"));
154
            } catch (ParameterNotFoundException $exception) {
155
                // do nothing
156
            }
157
        }
158
159 23
        $this->envCache[$key] = $envVar;
160
161 23
        return $this->envCache[$key];
162
    }
163
}
164