read(); if (trim($content) === '') { $this->error("Keine .env unter {$env->path()}."); return self::FAILURE; } $wanted = [ 'APP_HOST' => (string) ($this->option('app') ?: $this->hostOf($content)), 'SITE_HOST' => (string) $this->option('site'), 'STATUS_HOST' => (string) $this->option('status'), 'FILES_HOST' => (string) $this->option('files'), ]; $missing = []; foreach ($wanted as $key => $value) { if ($value === '' || $this->valueOf($content, $key) !== '') { continue; } $missing[$key] = $value; } if ($missing === []) { $this->info('Nichts nachzutragen — jeder angegebene Hostname steht bereits in der Datei.'); return self::SUCCESS; } $this->line('In '.$env->path().':'); foreach ($missing as $key => $value) { $this->line(" {$key}={$value}"); } // Der Satz, der einen Ausfall verhindert. Ein Hostname wird durch das // Binden zur EINZIGEN Adresse, unter der diese Routen noch antworten — // steht dafür kein DNS-Eintrag und kein Block im Reverse Proxy, ist der // Bereich danach schlicht nicht mehr erreichbar. $this->newLine(); $this->warn('Jeder dieser Namen braucht einen DNS-Eintrag und einen Block im Reverse Proxy.'); $this->warn('Ohne den ist der jeweilige Bereich nach dem Neuladen der Konfiguration nicht mehr erreichbar.'); $this->newLine(); if ($this->option('dry-run')) { $this->info('--dry-run: nichts geschrieben.'); return self::SUCCESS; } if (! $this->option('force') && ! $this->confirm('Diese Namen jetzt binden?')) { $this->line('Nichts geschrieben.'); return self::FAILURE; } $backup = $env->write($this->apply($content, $missing)); $this->info('Geschrieben. Die vorherige Fassung liegt unter '.$backup); $this->line('Danach: php artisan config:cache && php artisan route:cache'); return self::SUCCESS; } /** * Der Wert eines Schlüssels, oder '' wenn er fehlt ODER leer ist. * * Beides zusammen, absichtlich: siehe Klassenkommentar. */ private function valueOf(string $content, string $key): string { return preg_match('/^'.preg_quote($key, '/').'=(.*)$/m', $content, $matches) === 1 ? trim($matches[1]) : ''; } /** Der Hostname aus APP_URL — die Antwort für APP_HOST steht schon in der Datei. */ private function hostOf(string $content): string { return (string) parse_url($this->valueOf($content, 'APP_URL'), PHP_URL_HOST); } /** * Vorhandene Zeile ersetzen, sonst anhängen. * * 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. * * @param array $values */ private function apply(string $content, array $values): string { foreach ($values as $key => $value) { $line = $key.'='.$value; $pattern = '/^'.preg_quote($key, '/').'=.*$/m'; $content = preg_match($pattern, $content) === 1 ? preg_replace($pattern, $line, $content, 1) : rtrim($content, "\n")."\n".$line."\n"; } return $content; } }