diff --git a/docs/superpowers/plans/2026-08-04-hostnamen-trennung.md b/docs/superpowers/plans/2026-08-04-hostnamen-trennung.md index f21871c..c1cc719 100644 --- a/docs/superpowers/plans/2026-08-04-hostnamen-trennung.md +++ b/docs/superpowers/plans/2026-08-04-hostnamen-trennung.md @@ -729,6 +729,7 @@ Datei `app/Console/Commands/BindHosts.php`: namespace App\Console\Commands; use App\Services\Env\EnvFileEditor; +use App\Services\Env\InvalidEnvContentException; use Illuminate\Console\Command; /** @@ -821,7 +822,16 @@ class BindHosts extends Command return self::FAILURE; } - $backup = $env->write($this->apply($content, $missing)); + try { + $backup = $env->write($this->apply($content, $missing)); + } catch (InvalidEnvContentException $e) { + // Abgelehnt heißt hier: NICHTS geschrieben, und die Sicherung ist + // erst gar nicht angelegt worden — der Editor prüft vor beidem. + // Der Betreiber soll das als Satz erfahren, nicht als Stapelabzug. + $this->error('Die Datei wurde nicht geschrieben: '.$e->getMessage()); + + return self::FAILURE; + } $this->info('Geschrieben. Die vorherige Fassung liegt unter '.$backup); $this->line('Danach: php artisan config:cache && php artisan route:cache'); @@ -850,6 +860,12 @@ class BindHosts extends Command /** * Vorhandene Zeile ersetzen, sonst anhängen. * + * Zeilenweise und ohne `preg_replace`: der Wert kommt von der Befehlszeile, + * und `preg_replace` deutet `$1`, `\1` und `\\` im ERSATZ als Rückverweise. + * Aus `--site 'www.example.test$1'` würde still `SITE_HOST=www.example.test` + * — und diese Datei hält jedes Geheimnis dieser Installation. Ein leise + * verstümmelter Wert darin ist schlimmer als eine Fehlermeldung. + * * Ersetzen und nicht nur anhängen, weil ein leerer Schlüssel als fehlend * gilt: `APP_HOST=` steht dann schon da, und ein zweites `APP_HOST=…` * darunter wäre eine Datei mit zwei Antworten auf dieselbe Frage. @@ -858,16 +874,25 @@ class BindHosts extends Command */ private function apply(string $content, array $values): string { - foreach ($values as $key => $value) { - $line = $key.'='.$value; - $pattern = '/^'.preg_quote($key, '/').'=.*$/m'; + $lines = preg_split('/\R/', rtrim($content, "\r\n")); - $content = preg_match($pattern, $content) === 1 - ? preg_replace($pattern, $line, $content, 1) - : rtrim($content, "\n")."\n".$line."\n"; + foreach ($values as $key => $value) { + $replaced = false; + + foreach ($lines as $index => $line) { + if (str_starts_with($line, $key.'=')) { + $lines[$index] = $key.'='.$value; + $replaced = true; + break; + } + } + + if (! $replaced) { + $lines[] = $key.'='.$value; + } } - return $content; + return implode("\n", $lines)."\n"; } } ```