1
|
|
|
<?php |
2
|
|
|
namespace Consolidation\Config\Util; |
3
|
|
|
|
4
|
|
|
use Consolidation\Config\Config; |
5
|
|
|
use Consolidation\Config\ConfigInterface; |
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* Provides configuration objects with an 'interpolate' method |
9
|
|
|
* that may be used to inject config values into tokens embedded |
10
|
|
|
* in strings.. |
11
|
|
|
*/ |
12
|
|
|
class Interpolator |
13
|
|
|
{ |
14
|
|
|
/** |
15
|
|
|
* interpolate replaces tokens in a string with the correspnding |
16
|
|
|
* value from this config object. Tokens are surrounded by double |
17
|
|
|
* curley braces, e.g. "{{key}}". |
18
|
|
|
* |
19
|
|
|
* Example: |
20
|
|
|
* If the message is 'Hello, {{user.name}}', then the key user.name |
21
|
|
|
* is fetched from the config object, and the token {{user.name}} is |
22
|
|
|
* replaced with the result. |
23
|
|
|
* |
24
|
|
|
* @param string $message Message containing tokens to be replaced |
25
|
|
|
* @param string|bool $default The value to substitute for tokens that |
26
|
|
|
* are not found in the configuration. If `false`, then missing |
27
|
|
|
* tokens are not replaced. |
28
|
|
|
* @return string |
29
|
|
|
*/ |
30
|
|
|
public function interpolate($data, $message, $default = '') |
31
|
|
|
{ |
32
|
|
|
$replacements = $this->replacements($data, $message, $default); |
|
|
|
|
33
|
|
|
return strtr($message, $replacements); |
34
|
|
|
} |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* @inheritdoc |
38
|
|
|
*/ |
39
|
|
|
public function mustInterpolate($data, $message) |
40
|
|
|
{ |
41
|
|
|
$result = $this->interpolate($data, $message, false); |
42
|
|
|
$tokens = $this->findTokens($result); |
43
|
|
|
if (!empty($tokens)) { |
44
|
|
|
throw new \Exception('The following required keys were not found in configuration: ' . implode(',', $tokens)); |
45
|
|
|
} |
46
|
|
|
return $result; |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* findTokens finds all of the tokens in the provided message |
51
|
|
|
* |
52
|
|
|
* @param string $message String with tokens |
53
|
|
|
* @return string[] map of token to key, e.g. {{key}} => key |
54
|
|
|
*/ |
55
|
|
|
public function findTokens($message) |
56
|
|
|
{ |
57
|
|
|
if (!preg_match_all('#{{([a-zA-Z0-9._-]+)}}#', $message, $matches, PREG_SET_ORDER)) { |
58
|
|
|
return []; |
59
|
|
|
} |
60
|
|
|
$tokens = []; |
61
|
|
|
foreach ($matches as $matchSet) { |
62
|
|
|
list($sourceText, $key) = $matchSet; |
63
|
|
|
$tokens[$sourceText] = $key; |
64
|
|
|
} |
65
|
|
|
return $tokens; |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* Replacements looks up all of the replacements in the configuration |
70
|
|
|
* object, given the token keys from the provided message. Keys that |
71
|
|
|
* do not exist in the configuration are replaced with the default value. |
72
|
|
|
*/ |
73
|
|
|
public function replacements($data, $message, $default = '') |
74
|
|
|
{ |
75
|
|
|
$tokens = $this->findTokens($message); |
76
|
|
|
|
77
|
|
|
$replacements = []; |
78
|
|
|
foreach ($tokens as $sourceText => $key) { |
79
|
|
|
$replacementText = $this->get($data, $key, $default); |
80
|
|
|
if ($replacementText !== false) { |
81
|
|
|
$replacements[$sourceText] = $replacementText; |
82
|
|
|
} |
83
|
|
|
} |
84
|
|
|
return $replacements; |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
protected function get($data, $key, $default) |
88
|
|
|
{ |
89
|
|
|
if (is_array($data)) { |
90
|
|
|
return array_key_exists($key, $data) ? $data[$key] : $default; |
91
|
|
|
} |
92
|
|
|
if ($data instanceof ConfigInterface) { |
93
|
|
|
return $data->get($key, $default); |
94
|
|
|
} |
95
|
|
|
throw new \Exception('Bad data type provided to Interpolator'); |
96
|
|
|
} |
97
|
|
|
} |
98
|
|
|
|
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.