Skip to content

Commit 8207bf9

Browse files
Minor preg refactoring and added more nesting tests (#315)
1 parent 46fa940 commit 8207bf9

File tree

5 files changed

+58
-28
lines changed

5 files changed

+58
-28
lines changed

src/Loader.php

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Dotenv\Environment\FactoryInterface;
66
use Dotenv\Exception\InvalidPathException;
7+
use Dotenv\Regex\Regex;
78
use PhpOption\Option;
89

910
/**
@@ -170,29 +171,21 @@ private function processEntries(array $entries)
170171
*/
171172
private function resolveNestedVariables($value = null)
172173
{
173-
if ($value === null || strpos($value, '$') === false) {
174-
return $value;
175-
}
176-
177-
return preg_replace_callback(
178-
'/\${([a-zA-Z0-9_.]+)}/',
179-
[$this, 'nestedVariableResolver'],
180-
$value
181-
);
182-
}
183-
184-
/**
185-
* Resolve the matched variable to its value, if possible.
186-
*
187-
* @param string[] $matches
188-
*
189-
* @return string
190-
*/
191-
private function nestedVariableResolver(array $matches)
192-
{
193-
$nested = $this->getEnvironmentVariable($matches[1]);
194-
195-
return $nested === null ? $matches[0] : $nested;
174+
return Option::fromValue($value)
175+
->filter(function ($str) {
176+
return strpos($str, '$') !== false;
177+
})
178+
->flatMap(function ($str) {
179+
return Regex::replaceCallback(
180+
'/\${([a-zA-Z0-9_.]+)}/',
181+
function (array $matches) {
182+
return Option::fromValue($this->getEnvironmentVariable($matches[1]))
183+
->getOrElse($matches[0]);
184+
},
185+
$str
186+
)->success();
187+
})
188+
->getOrElse($value);
196189
}
197190

198191
/**

src/Parser.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ private static function processQuotedValue($value)
155155
$quote
156156
);
157157

158-
return Regex::pregReplace($pattern, '$1', $value)
158+
return Regex::replace($pattern, '$1', $value)
159159
->mapSuccess(function ($str) use ($quote) {
160160
return str_replace('\\\\', '\\', str_replace("\\$quote", $quote, $str));
161161
})

src/Regex/Regex.php

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,48 @@
77
class Regex
88
{
99
/**
10-
* Perform a preg replace, failing with an exception.
10+
* Perform a preg replace, wrapping up the result.
1111
*
1212
* @param string $pattern
13-
* @param string $repalcement
13+
* @param string $replacement
1414
* @param string $subject
1515
*
1616
* @return \Dotenv\Regex\Result
1717
*/
18-
public static function pregReplace($pattern, $replacement, $subject)
18+
public static function replace($pattern, $replacement, $subject)
1919
{
20-
$result = (string) @preg_replace($pattern, $replacement, $subject);
20+
return self::pregAndWrap(function ($subject) use ($pattern, $replacement) {
21+
return preg_replace($pattern, $replacement, $subject);
22+
}, $subject);
23+
}
24+
25+
/**
26+
* Perform a preg replace callback, wrapping up the result.
27+
*
28+
* @param string $pattern
29+
* @param callable $callback
30+
* @param string $subject
31+
*
32+
* @return \Dotenv\Regex\Result
33+
*/
34+
public static function replaceCallback($pattern, callable $callback, $subject)
35+
{
36+
return self::pregAndWrap(function ($subject) use ($pattern, $callback) {
37+
return preg_replace_callback($pattern, $callback, $subject);
38+
}, $subject);
39+
}
40+
41+
/**
42+
* Perform a preg operation, wrapping up the result.
43+
*
44+
* @param callable $operation
45+
* @param string $subject
46+
*
47+
* @return \Dotenv\Regex\Result
48+
*/
49+
private static function pregAndWrap(callable $operation, $subject)
50+
{
51+
$result = (string) @$operation($subject);
2152

2253
if (($e = preg_last_error()) !== PREG_NO_ERROR) {
2354
return Error::create(self::lookupError($e));

tests/Dotenv/DotenvTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ public function testDotenvNestedEnvironmentVars()
151151
$this->assertSame('$NVAR1 {NVAR2}', $_ENV['NVAR5']); // not resolved
152152
$this->assertSame('Special Value', $_ENV['N.VAR6']); // new '.' (dot) in var name
153153
$this->assertSame('Special Value', $_ENV['NVAR7']); // nested '.' (dot) variable
154+
$this->assertSame('', $_ENV['NVAR8']);
155+
$this->assertSame('', $_ENV['NVAR9']); // nested variable is empty string
156+
$this->assertSame('${NVAR888}', $_ENV['NVAR10']); // nested variable is not set
154157
}
155158

156159
/**

tests/fixtures/env/nested.env

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@ NVAR4="${NVAR1} ${NVAR2}"
55
NVAR5="$NVAR1 {NVAR2}"
66
N.VAR6="Special Value"
77
NVAR7="${N.VAR6}"
8+
NVAR8=""
9+
NVAR9="${NVAR8}"
10+
NVAR10="${NVAR888}"

0 commit comments

Comments
 (0)