Skip to content

Commit 6a9494d

Browse files
Merge pull request #395 from vlucas/refactor
[4.1] Refactor to use stores
2 parents a6bd169 + 7738fec commit 6a9494d

File tree

9 files changed

+298
-122
lines changed

9 files changed

+298
-122
lines changed

UPGRADING.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Upgrading Guide
22

3+
## V4.0 to V4.1
4+
5+
There are no breaking changes in this release, but the `Dotenv\Dotenv` constructor now expects either an array of file paths as the third parameter, or an instance of `Dotenv\Store\StoreInterface`. Passing an array is deprecated, and will be removed in V5.
6+
37
## V3 to V4
48

59
V4 has again changed the way you initialize the `Dotenv` class. If you want immutable loading of environment variables, then replace `Dotenv::create` with `Dotenv::createImmutable`, and if you want mutable loading, replace `Dotenv::create` with `Dotenv::createMutable` and `->overload()` with `->load()`. The `overload` method has been removed in faviour of specifying mutability at object construction.

src/Dotenv.php

Lines changed: 20 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@
33
namespace Dotenv;
44

55
use Dotenv\Exception\InvalidPathException;
6-
use Dotenv\File\Paths;
7-
use Dotenv\File\Reader;
86
use Dotenv\Loader\Loader;
97
use Dotenv\Loader\LoaderInterface;
108
use Dotenv\Repository\RepositoryBuilder;
119
use Dotenv\Repository\RepositoryInterface;
12-
use PhpOption\Option;
10+
use Dotenv\Store\StoreBuilder;
1311

1412
class Dotenv
1513
{
@@ -28,35 +26,26 @@ class Dotenv
2826
protected $repository;
2927

3028
/**
31-
* The file paths.
29+
* The store instance.
3230
*
33-
* @var string[]
31+
* @var \Dotenv\Store\StoreInterface
3432
*/
35-
protected $filePaths;
36-
37-
/**
38-
* Should file loading short circuit?
39-
*
40-
* @var bool
41-
*/
42-
protected $shortCircuit;
33+
protected $store;
4334

4435
/**
4536
* Create a new dotenv instance.
4637
*
4738
* @param \Dotenv\Loader\LoaderInterface $loader
4839
* @param \Dotenv\Repository\RepositoryInterface $repository
49-
* @param string[] $filePaths
50-
* @param bool $shortCircuit
40+
* @param \Dotenv\Store\StoreInterface|string[] $store
5141
*
5242
* @return void
5343
*/
54-
public function __construct(LoaderInterface $loader, RepositoryInterface $repository, array $filePaths, $shortCircuit = true)
44+
public function __construct(LoaderInterface $loader, RepositoryInterface $repository, $store)
5545
{
5646
$this->loader = $loader;
5747
$this->repository = $repository;
58-
$this->filePaths = $filePaths;
59-
$this->shortCircuit = $shortCircuit;
48+
$this->store = is_array($store) ? new Store($store, true) : $store;
6049
}
6150

6251
/**
@@ -71,9 +60,13 @@ public function __construct(LoaderInterface $loader, RepositoryInterface $reposi
7160
*/
7261
public static function create(RepositoryInterface $repository, $paths, $names = null, $shortCircuit = true)
7362
{
74-
$files = Paths::filePaths((array) $paths, (array) ($names ?: '.env'));
63+
$builder = StoreBuilder::create()->withPaths((array) $paths)->withNames((array) ($names ?: '.env'));
64+
65+
if ($shortCircuit) {
66+
$builder = $builder->shortCircuit();
67+
}
7568

76-
return new self(new Loader(), $repository, $files, $shortCircuit);
69+
return new self(new Loader(), $repository, $builder->make());
7770
}
7871

7972
/**
@@ -117,15 +110,7 @@ public static function createImmutable($paths, $names = null, $shortCircuit = tr
117110
*/
118111
public function load()
119112
{
120-
if ($this->filePaths === []) {
121-
throw new InvalidPathException('At least one environment file path must be provided.');
122-
}
123-
124-
return $this->tryLoad()->getOrCall(function () {
125-
throw new InvalidPathException(
126-
sprintf('Unable to read any of the environment file(s) at [%s].', implode(', ', $this->filePaths))
127-
);
128-
});
113+
return $this->loader->load($this->repository, $this->store->read());
129114
}
130115

131116
/**
@@ -137,7 +122,12 @@ public function load()
137122
*/
138123
public function safeLoad()
139124
{
140-
return $this->tryLoad()->getOrElse([]);
125+
try {
126+
return $this->load();
127+
} catch (InvalidPathException $e) {
128+
// suppressing exception
129+
return [];
130+
}
141131
}
142132

143133
/**
@@ -163,36 +153,4 @@ public function ifPresent($variables)
163153
{
164154
return new Validator($this->repository, (array) $variables, false);
165155
}
166-
167-
/**
168-
* Read and load environment file(s), returning an option.
169-
*
170-
* @throws \Dotenv\Exception\InvalidFileException
171-
*
172-
* @return \PhpOption\Option
173-
*/
174-
private function tryLoad()
175-
{
176-
return self::aggregate(Reader::read($this->filePaths, $this->shortCircuit))->map(function ($content) {
177-
return $this->loader->load($this->repository, $content);
178-
});
179-
}
180-
181-
/**
182-
* Aggregate the given raw file contents.
183-
*
184-
* @param array<string,string> $contents
185-
*
186-
* @return \PhpOption\Option
187-
*/
188-
private static function aggregate(array $contents)
189-
{
190-
$output = '';
191-
192-
foreach ($contents as $content) {
193-
$output .= $content."\n";
194-
}
195-
196-
return Option::fromValue($output, '');
197-
}
198156
}

src/File/Paths.php renamed to src/Store/File/Paths.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
<?php
22

3-
namespace Dotenv\File;
4-
5-
use PhpOption\Option;
3+
namespace Dotenv\Store\File;
64

75
class Paths
86
{

src/File/Reader.php renamed to src/Store/File/Reader.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace Dotenv\File;
3+
namespace Dotenv\Store\File;
44

55
use PhpOption\Option;
66

src/Store/FileStore.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
namespace Dotenv\Store;
4+
5+
use Dotenv\Exception\InvalidPathException;
6+
use Dotenv\Store\File\Reader;
7+
8+
class FileStore implements StoreInterface
9+
{
10+
/**
11+
* The file paths.
12+
*
13+
* @var string[]
14+
*/
15+
protected $filePaths;
16+
17+
/**
18+
* Should file loading short circuit?
19+
*
20+
* @var bool
21+
*/
22+
protected $shortCircuit;
23+
24+
/**
25+
* Create a new file store instance.
26+
*
27+
* @param string[] $filePaths
28+
* @param bool $shortCircuit
29+
*
30+
* @return void
31+
*/
32+
public function __construct(array $filePaths, $shortCircuit)
33+
{
34+
$this->filePaths = $filePaths;
35+
$this->shortCircuit = $shortCircuit;
36+
}
37+
38+
/**
39+
* Read the content of the environment file(s).
40+
*
41+
* @throws \Dotenv\Exception\InvalidPathException
42+
*
43+
* @return string
44+
*/
45+
public function read()
46+
{
47+
if ($this->filePaths === []) {
48+
throw new InvalidPathException('At least one environment file path must be provided.');
49+
}
50+
51+
$contents = Reader::read($this->filePaths, $this->shortCircuit);
52+
53+
if ($contents) {
54+
return implode("\n", $contents);
55+
}
56+
57+
throw new InvalidPathException(
58+
sprintf('Unable to read any of the environment file(s) at [%s].', implode(', ', $this->filePaths))
59+
);
60+
}
61+
}

src/Store/StoreBuilder.php

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?php
2+
3+
namespace Dotenv\Store;
4+
5+
use Dotenv\Store\File\Paths;
6+
7+
class StoreBuilder
8+
{
9+
/**
10+
* The paths to search within.
11+
*
12+
* @var string[]
13+
*/
14+
private $paths;
15+
16+
/**
17+
* The file names to search for.
18+
*
19+
* @var string[]
20+
*/
21+
private $names;
22+
23+
/**
24+
* Should file loading short circuit?
25+
*
26+
* @var bool
27+
*/
28+
protected $shortCircuit;
29+
30+
/**
31+
* Create a new store builder instance.
32+
*
33+
* @param string[] $paths
34+
* @param string[] $names
35+
* @param bool $shortCircuit
36+
*
37+
* @return void
38+
*/
39+
private function __construct(array $paths = [], array $names = [], $shortCircuit = false)
40+
{
41+
$this->paths = $paths;
42+
$this->names = $names;
43+
$this->shortCircuit = $shortCircuit;
44+
}
45+
46+
/**
47+
* Create a new store builder instance.
48+
*
49+
* @return \Dotenv\Store\StoreBuilder
50+
*/
51+
public static function create()
52+
{
53+
return new self();
54+
}
55+
56+
/**
57+
* Creates a store builder with the given paths.
58+
*
59+
* @param string[] $paths
60+
*
61+
* @return \Dotenv\Repository\RepositoryBuilder
62+
*/
63+
public function withPaths(array $paths)
64+
{
65+
return new self($paths, $this->names, $this->shortCircuit);
66+
}
67+
68+
/**
69+
* Creates a store builder with the given names.
70+
*
71+
* @param string[] $names
72+
*
73+
* @return \Dotenv\Store\StoreBuilder
74+
*/
75+
public function withNames(array $names)
76+
{
77+
return new self($this->paths, $names, $this->shortCircuit);
78+
}
79+
80+
/**
81+
* Creates a store builder with short circuit mode enabled.
82+
*
83+
* @return \Dotenv\Store\StoreBuilder
84+
*/
85+
public function shortCircuit()
86+
{
87+
return new self($this->paths, $this->names, true);
88+
}
89+
90+
/**
91+
* Creates a new store instance.
92+
*
93+
* @return \Dotenv\Store\StoreInterface
94+
*/
95+
public function make()
96+
{
97+
return new FileStore(
98+
Paths::filePaths($this->paths, $this->names),
99+
$this->shortCircuit
100+
);
101+
}
102+
}

src/Store/StoreInterface.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace Dotenv\Store;
4+
5+
interface StoreInterface
6+
{
7+
/**
8+
* Read the content of the environment file(s).
9+
*
10+
* @throws \Dotenv\Exception\InvalidPathException
11+
*
12+
* @return string
13+
*/
14+
public function read();
15+
}

0 commit comments

Comments
 (0)