Skip to content

Commit 5084b23

Browse files
Fixed handling multiple occurences of a variable
1 parent ffcaf1d commit 5084b23

File tree

5 files changed

+122
-35
lines changed

5 files changed

+122
-35
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
},
2626
"extra": {
2727
"branch-alias": {
28-
"dev-master": "3.3-dev"
28+
"dev-master": "3.4-dev"
2929
}
3030
}
3131
}

src/Environment/AbstractVariables.php

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
namespace Dotenv\Environment;
44

5+
use Dotenv\Environment\Adapter\ArrayAdapter;
6+
use InvalidArgumentException;
7+
58
/**
69
* This is the abstract variables implementation.
710
*
@@ -16,6 +19,13 @@ abstract class AbstractVariables implements VariablesInterface
1619
*/
1720
private $immutable;
1821

22+
/**
23+
* The record of loaded variables.
24+
*
25+
* @var \Dotenv\Environment\Adapter\ArrayAdapter
26+
*/
27+
private $loaded;
28+
1929
/**
2030
* Create a new environment variables instance.
2131
*
@@ -26,8 +36,104 @@ abstract class AbstractVariables implements VariablesInterface
2636
public function __construct($immutable)
2737
{
2838
$this->immutable = $immutable;
39+
$this->loaded = new ArrayAdapter();
40+
}
41+
42+
/**
43+
* Get an environment variable.
44+
*
45+
* @param string $name
46+
*
47+
* @throws \InvalidArgumentException
48+
*
49+
* @return string|null
50+
*/
51+
public function get($name)
52+
{
53+
if (!is_string($name)) {
54+
throw new InvalidArgumentException('Expected name to be a string.');
55+
}
56+
57+
return $this->getInternal($name);
2958
}
3059

60+
/**
61+
* Get an environment variable.
62+
*
63+
* @param string $name
64+
*
65+
* @return string|null
66+
*/
67+
protected abstract function getInternal($name);
68+
69+
/**
70+
* Set an environment variable.
71+
*
72+
* @param string $name
73+
* @param string|null $value
74+
*
75+
* @throws \InvalidArgumentException
76+
*
77+
* @return void
78+
*/
79+
public function set($name, $value = null)
80+
{
81+
if (!is_string($name)) {
82+
throw new InvalidArgumentException('Expected name to be a string.');
83+
}
84+
85+
// Don't overwrite existing environment variables if we're immutable
86+
// Ruby's dotenv does this with `ENV[key] ||= value`.
87+
if ($this->isImmutable() && $this->get($name) !== null && $this->loaded->get($name)->isEmpty()) {
88+
return;
89+
}
90+
91+
$this->setInternal($name, $value);
92+
$this->loaded->set($name, '');
93+
}
94+
95+
/**
96+
* Set an environment variable.
97+
*
98+
* @param string $name
99+
* @param string|null $value
100+
*
101+
* @return void
102+
*/
103+
protected abstract function setInternal($name, $value = null);
104+
105+
/**
106+
* Clear an environment variable.
107+
*
108+
* @param string $name
109+
*
110+
* @throws \InvalidArgumentException
111+
*
112+
* @return void
113+
*/
114+
public function clear($name)
115+
{
116+
if (!is_string($name)) {
117+
throw new InvalidArgumentException('Expected name to be a string.');
118+
}
119+
120+
// Don't clear anything if we're immutable.
121+
if ($this->isImmutable()) {
122+
return;
123+
}
124+
125+
$this->clearInternal($name);
126+
}
127+
128+
/**
129+
* Clear an environment variable.
130+
*
131+
* @param string $name
132+
*
133+
* @return void
134+
*/
135+
protected abstract function clearInternal($name);
136+
31137
/**
32138
* Determine if the environment is immutable.
33139
*

src/Environment/DotenvVariables.php

Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
namespace Dotenv\Environment;
44

5-
use InvalidArgumentException;
6-
75
/**
86
* The default implementation of the environment variables interface.
97
*/
@@ -37,16 +35,10 @@ public function __construct(array $adapters, $immutable)
3735
*
3836
* @param string $name
3937
*
40-
* @throws \InvalidArgumentException
41-
*
4238
* @return string|null
4339
*/
44-
public function get($name)
40+
protected function getInternal($name)
4541
{
46-
if (!is_string($name)) {
47-
throw new InvalidArgumentException('Expected name to be a string.');
48-
}
49-
5042
foreach ($this->adapters as $adapter) {
5143
$result = $adapter->get($name);
5244
if ($result->isDefined()) {
@@ -61,22 +53,10 @@ public function get($name)
6153
* @param string $name
6254
* @param string|null $value
6355
*
64-
* @throws \InvalidArgumentException
65-
*
6656
* @return void
6757
*/
68-
public function set($name, $value = null)
58+
protected function setInternal($name, $value = null)
6959
{
70-
if (!is_string($name)) {
71-
throw new InvalidArgumentException('Expected name to be a string.');
72-
}
73-
74-
// Don't overwrite existing environment variables if we're immutable
75-
// Ruby's dotenv does this with `ENV[key] ||= value`.
76-
if ($this->isImmutable() && $this->get($name) !== null) {
77-
return;
78-
}
79-
8060
foreach ($this->adapters as $adapter) {
8161
$adapter->set($name, $value);
8262
}
@@ -87,21 +67,10 @@ public function set($name, $value = null)
8767
*
8868
* @param string $name
8969
*
90-
* @throws \InvalidArgumentException
91-
*
9270
* @return void
9371
*/
94-
public function clear($name)
72+
protected function clearInternal($name)
9573
{
96-
if (!is_string($name)) {
97-
throw new InvalidArgumentException('Expected name to be a string.');
98-
}
99-
100-
// Don't clear anything if we're immutable.
101-
if ($this->isImmutable()) {
102-
return;
103-
}
104-
10574
foreach ($this->adapters as $adapter) {
10675
$adapter->clear($name);
10776
}

tests/Dotenv/DotenvTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,14 @@ public function testLargeDotenvLoadsEnvironmentVars()
100100
$this->assertNotEmpty(getenv('LARGE'));
101101
}
102102

103+
public function testMultipleDotenvLoadsEnvironmentVars()
104+
{
105+
$dotenv = Dotenv::create($this->fixturesFolder, 'multiple.env');
106+
$dotenv->load();
107+
$this->assertSame('bar', getenv('MULTI1'));
108+
$this->assertSame('foo', getenv('MULTI2'));
109+
}
110+
103111
public function testExportedDotenvLoadsEnvironmentVars()
104112
{
105113
$dotenv = Dotenv::create($this->fixturesFolder, 'exported.env');

tests/fixtures/env/multiple.env

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
MULTI1=foo
2+
MULTI2=${MULTI1}
3+
MULTI1=bar
4+

0 commit comments

Comments
 (0)