Skip to content

Commit 4a2d747

Browse files
authored
Merge pull request #9 from MaplePHP/develop
Rebuilt Env class
2 parents b40beb8 + b0d898d commit 4a2d747

File tree

1 file changed

+152
-140
lines changed

1 file changed

+152
-140
lines changed

src/Env.php

Lines changed: 152 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -8,143 +8,155 @@
88

99
class Env
1010
{
11-
private $fileData = [];
12-
private $data = [];
13-
private $set = [];
14-
private $drop = [];
15-
16-
public function __construct(?string $file = null)
17-
{
18-
if ($file !== null && is_file($file)) {
19-
$this->loadEnvFile($file);
20-
}
21-
}
22-
23-
public function loadEnvFile(string $file): void
24-
{
25-
$this->fileData = parse_ini_file($file);
26-
}
27-
28-
public function hasEnv(string $key): ?string
29-
{
30-
$key = $this->formatKey($key);
31-
return (isset($this->fileData[$key])) ? $key : null;
32-
}
33-
34-
public function set(string $key, string $value): string
35-
{
36-
if ($keyB = $this->hasEnv($key)) {
37-
$this->fileData[$keyB] = $value;
38-
} else {
39-
$key = $this->formatKey($key);
40-
$this->set[$key] = $value;
41-
}
42-
return "{$key}={$value}";
43-
}
44-
45-
public function get(string $key): string
46-
{
47-
$key = $this->formatKey($key);
48-
return ($this->fileData[$key] ?? "");
49-
}
50-
51-
public function drop(string $key): void
52-
{
53-
$key = $this->formatKey($key);
54-
$this->drop[$key] = $key;
55-
}
56-
57-
public function formatKey($key)
58-
{
59-
return Format\Str::value($key)->clearBreaks()->trim()->normalizeAccents()
60-
->normalizeSeparators()->replaceSpaces("-")->toUpper()->get();
61-
}
62-
63-
public function generateOutput(array $fromArr = ["data", "fileData", "set"])
64-
{
65-
$out = "";
66-
67-
$data = [];
68-
$validData = ["data", "fileData", "set"];
69-
foreach ($validData as $d) {
70-
if (in_array($d, $fromArr)) {
71-
$data += $this->{$d};
72-
}
73-
}
74-
75-
$length = count($data);
76-
foreach ($data as $key => $val) {
77-
if (empty($this->drop[$key])) {
78-
$key = $this->formatKey($key);
79-
$val = trim($val);
80-
if (!is_numeric($val) && ($val !== "true" || $val !== false)) {
81-
$val = "'{$val}'";
82-
}
83-
$out .= "{$key}={$val}";
84-
if ($length > 1) {
85-
$out .= "\n";
86-
}
87-
}
88-
}
89-
return $out;
90-
}
91-
92-
public function putenv($key, $value): self
93-
{
94-
$this->data[$key] = $value;
95-
return $this;
96-
}
97-
98-
public function putenvArray(array $array): self
99-
{
100-
foreach ($array as $prefix => $val) {
101-
$prefix = strtoupper($prefix);
102-
if (is_array($val)) {
103-
foreach ($val as $k1 => $v1) {
104-
foreach ($v1 as $k2 => $v2) {
105-
$newKey = strtoupper("{$k1}_{$k2}");
106-
if (!isset($this->fileData[$newKey])) {
107-
$this->data[$newKey] = $v2;
108-
}
109-
}
110-
}
111-
} else {
112-
$this->data[$prefix] = $val;
113-
}
114-
}
115-
$this->data = array_merge($this->data, $array);
116-
return $this;
117-
}
118-
119-
private function put(array $data, bool $overwrite = false)
120-
{
121-
foreach ($data as $key => $value) {
122-
/*
123-
if (!$overwrite && getenv($key) !== false) {
124-
throw new InvalidArgumentException("The Environmental variable \"{$key}\" already exists. " .
125-
"It's recommended to make every variable unique.", 1);
126-
}
127-
*/
128-
$_ENV[$key] = $value;
129-
if (is_array($value)) {
130-
$value = json_encode($value);
131-
}
132-
putenv("{$key}={$value}");
133-
}
134-
}
135-
136-
public function execute(bool $overwrite = false): void
137-
{
138-
if ($this->fileData) {
139-
$this->put($this->fileData, $overwrite);
140-
}
141-
if ($this->data) {
142-
$this->put($this->data, $overwrite);
143-
}
144-
}
145-
146-
public function getData()
147-
{
148-
return $this->data + $this->fileData + $this->set;
149-
}
150-
}
11+
private static array $registry = []; // Static registry, survives reloads correctly
12+
private array $fileData = [];
13+
private array $data = [];
14+
private array $set = [];
15+
private array $drop = [];
16+
17+
public function __construct(?string $file = null)
18+
{
19+
if ($file !== null && is_file($file)) {
20+
$this->loadEnvFile($file);
21+
}
22+
}
23+
24+
public function loadEnvFile(string $file): void
25+
{
26+
if (!is_file($file)) {
27+
throw new \RuntimeException("Environment file not found: $file");
28+
}
29+
30+
$lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
31+
$cleaned = array_filter($lines, fn($line) => !str_starts_with(trim($line), '#'));
32+
$data = parse_ini_string(implode("\n", $cleaned), false, INI_SCANNER_RAW);
33+
34+
if ($data === false) {
35+
throw new \RuntimeException(
36+
"Failed to parse .env file: $file\n" .
37+
"Hint: wrap values containing special characters (;, |, $) in double quotes."
38+
);
39+
}
40+
41+
$this->fileData = $data;
42+
}
43+
44+
public function hasEnv(string $key): ?string
45+
{
46+
$key = $this->formatKey($key);
47+
return isset($this->fileData[$key]) ? $key : null;
48+
}
49+
50+
public function set(string $key, string $value): string
51+
{
52+
if ($keyB = $this->hasEnv($key)) {
53+
$this->fileData[$keyB] = $value;
54+
} else {
55+
$key = $this->formatKey($key);
56+
$this->set[$key] = $value;
57+
}
58+
return "{$key}={$value}";
59+
}
60+
61+
public function get(string $key): string
62+
{
63+
$key = $this->formatKey($key);
64+
return self::$registry[$key] ?? "";
65+
}
66+
67+
public function drop(string $key): void
68+
{
69+
$key = $this->formatKey($key);
70+
$this->drop[$key] = $key;
71+
}
72+
73+
public function formatKey(string $key): string
74+
{
75+
return Format\Str::value($key)->clearBreaks()->trim()->normalizeAccents()
76+
->normalizeSeparators()->replaceSpaces("-")->toUpper()->get();
77+
}
78+
79+
public function generateOutput(array $fromArr = ["data", "fileData", "set"]): string
80+
{
81+
$out = "";
82+
$data = [];
83+
$validData = ["data", "fileData", "set"];
84+
85+
foreach ($validData as $d) {
86+
if (in_array($d, $fromArr)) {
87+
$data += $this->{$d};
88+
}
89+
}
90+
91+
$length = count($data);
92+
foreach ($data as $key => $val) {
93+
if (empty($this->drop[$key])) {
94+
$key = $this->formatKey($key);
95+
$val = trim($val);
96+
if (!is_numeric($val) && ($val !== "true" && $val !== "false")) {
97+
$val = "'{$val}'";
98+
}
99+
$out .= "{$key}={$val}";
100+
if ($length > 1) {
101+
$out .= "\n";
102+
}
103+
}
104+
}
105+
return $out;
106+
}
107+
108+
public function putenv(string $key, string $value): self
109+
{
110+
$this->data[$key] = $value;
111+
return $this;
112+
}
113+
114+
public function putenvArray(array $array): self
115+
{
116+
foreach ($array as $prefix => $val) {
117+
$prefix = strtoupper($prefix);
118+
if (is_array($val)) {
119+
foreach ($val as $k1 => $v1) {
120+
foreach ($v1 as $k2 => $v2) {
121+
$newKey = strtoupper("{$k1}_{$k2}");
122+
if (!isset($this->fileData[$newKey])) {
123+
$this->data[$newKey] = $v2;
124+
}
125+
}
126+
}
127+
} else {
128+
$this->data[$prefix] = $val;
129+
}
130+
}
131+
$this->data = array_merge($this->data, $array);
132+
return $this;
133+
}
134+
135+
public function execute(bool $overwrite = false): void
136+
{
137+
$merged = $this->getData();
138+
139+
// Fully replace the registry on every execute — no bleed-through
140+
self::$registry = [];
141+
142+
foreach ($merged as $key => $value) {
143+
if (isset($this->drop[$key])) {
144+
continue;
145+
}
146+
if (!$overwrite && isset(self::$registry[$key])) {
147+
continue;
148+
}
149+
self::$registry[$key] = $value;
150+
}
151+
}
152+
153+
public static function getFromRegistry(string $key): mixed
154+
{
155+
return self::$registry[$key] ?? null;
156+
}
157+
158+
public function getData(): array
159+
{
160+
return $this->data + $this->fileData + $this->set;
161+
}
162+
}

0 commit comments

Comments
 (0)