186 lines
5.0 KiB
PHP
186 lines
5.0 KiB
PHP
<?php
|
|
|
|
namespace App\Installer\EnvFiles;
|
|
|
|
use App\Environment;
|
|
use App\Utilities\Strings;
|
|
use Dotenv\Dotenv;
|
|
use Dotenv\Exception\ExceptionInterface;
|
|
use http\Exception\InvalidArgumentException;
|
|
|
|
abstract class AbstractEnvFile implements \ArrayAccess
|
|
{
|
|
final public function __construct(
|
|
protected string $path,
|
|
protected array $data = []
|
|
) {
|
|
}
|
|
|
|
public function getPath(): string
|
|
{
|
|
return $this->path;
|
|
}
|
|
|
|
public function getBasename(): string
|
|
{
|
|
return basename($this->path);
|
|
}
|
|
|
|
public function setFromDefaults(): void
|
|
{
|
|
$currentVars = array_filter($this->data);
|
|
|
|
$defaults = [];
|
|
foreach (static::getConfiguration() as $key => $keyInfo) {
|
|
if (isset($keyInfo['default'])) {
|
|
$defaults[$key] = $keyInfo['default'] ?? null;
|
|
}
|
|
}
|
|
|
|
$this->data = array_merge($defaults, $currentVars);
|
|
}
|
|
|
|
public function offsetExists($offset): bool
|
|
{
|
|
return isset($this->data[$offset]);
|
|
}
|
|
|
|
public function offsetGet($offset): mixed
|
|
{
|
|
return $this->data[$offset];
|
|
}
|
|
|
|
public function offsetSet($offset, $value): void
|
|
{
|
|
$this->data[$offset] = $value;
|
|
}
|
|
|
|
public function offsetUnset($offset): void
|
|
{
|
|
unset($this->data[$offset]);
|
|
}
|
|
|
|
public function writeToFile(): string
|
|
{
|
|
$values = array_filter($this->data);
|
|
|
|
$envFile = [
|
|
'# ' . __('This file was automatically generated by AzuraCast.'),
|
|
'# ' . __('You can modify it as necessary. To apply changes, restart the Docker containers.'),
|
|
'# ' . __('Remove the leading "#" symbol from lines to uncomment them.'),
|
|
'',
|
|
];
|
|
|
|
foreach (static::getConfiguration() as $key => $keyInfo) {
|
|
$envFile[] = '# ' . ($keyInfo['name'] ?? $key);
|
|
|
|
if (!empty($keyInfo['description'])) {
|
|
$desc = Strings::mbWordwrap($keyInfo['description']);
|
|
|
|
foreach (explode("\n", $desc) as $descPart) {
|
|
$envFile[] = '# ' . $descPart;
|
|
}
|
|
}
|
|
|
|
if (!empty($keyInfo['options'])) {
|
|
$options = array_map(
|
|
fn($val) => $this->getEnvValue($val),
|
|
$keyInfo['options'],
|
|
);
|
|
|
|
$envFile[] = '# ' . __('Valid options: %s', implode(', ', $options));
|
|
}
|
|
|
|
if (isset($values[$key])) {
|
|
$value = $this->getEnvValue($values[$key]);
|
|
unset($values[$key]);
|
|
} else {
|
|
$value = null;
|
|
}
|
|
|
|
if (!empty($keyInfo['default'])) {
|
|
$default = $this->getEnvValue($keyInfo['default']);
|
|
$envFile[] = '# ' . __('Default: %s', $default);
|
|
} else {
|
|
$default = '';
|
|
}
|
|
|
|
if ((null === $value || $default === $value) && Environment::LANG !== $key) {
|
|
$value ??= $default;
|
|
$envFile[] = '# ' . $key . '=' . $value;
|
|
} else {
|
|
$envFile[] = $key . '=' . $value;
|
|
}
|
|
|
|
$envFile[] = '';
|
|
}
|
|
|
|
// Add in other environment vars that were missed or previously present.
|
|
if (!empty($values)) {
|
|
$envFile[] = '# ' . __('Additional Environment Variables');
|
|
|
|
foreach ($values as $key => $value) {
|
|
$envFile[] = $key . '=' . $this->getEnvValue($value);
|
|
}
|
|
}
|
|
|
|
$envFileStr = implode("\n", $envFile);
|
|
file_put_contents($this->path, $envFileStr);
|
|
|
|
return $envFileStr;
|
|
}
|
|
|
|
protected function getEnvValue(
|
|
mixed $value
|
|
): string {
|
|
if (is_null($value)) {
|
|
return '';
|
|
}
|
|
if (is_bool($value)) {
|
|
return $value ? 'true' : 'false';
|
|
}
|
|
if (is_int($value)) {
|
|
return (string)$value;
|
|
}
|
|
if (is_array($value)) {
|
|
return implode(',', $value);
|
|
}
|
|
|
|
if (str_contains($value, ' ')) {
|
|
$value = '"' . $value . '"';
|
|
}
|
|
|
|
return $value;
|
|
}
|
|
|
|
/**
|
|
* @return mixed[]
|
|
*/
|
|
abstract public static function getConfiguration(): array;
|
|
|
|
abstract public static function buildPathFromBase(string $baseDir): string;
|
|
|
|
public static function fromEnvFile(string $path): static
|
|
{
|
|
$data = [];
|
|
if (is_file($path)) {
|
|
$fileContents = file_get_contents($path);
|
|
if (!empty($fileContents)) {
|
|
try {
|
|
$data = Dotenv::parse($fileContents);
|
|
} catch (ExceptionInterface $e) {
|
|
throw new InvalidArgumentException(
|
|
sprintf(
|
|
'Encountered an error parsing %s: "%s". Resetting to default configuration.',
|
|
basename($path),
|
|
$e->getMessage()
|
|
)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
return new static($path, $data);
|
|
}
|
|
}
|