Completed
Push — master ( 97da99...845621 )
by Andy
03:23
created

Resolver   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 137
Duplicated Lines 0 %

Test Coverage

Coverage 97.78%

Importance

Changes 0
Metric Value
eloc 47
dl 0
loc 137
ccs 44
cts 45
cp 0.9778
rs 10
c 0
b 0
f 0
wmc 23

7 Methods

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