128 lines
3.3 KiB
PHP
128 lines
3.3 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace NeonBlog;
|
|
|
|
final class Config
|
|
{
|
|
/** @var array<string, mixed> */
|
|
private array $data;
|
|
|
|
private string $path;
|
|
|
|
/** @param array<string, mixed> $data */
|
|
private function __construct(string $path, array $data)
|
|
{
|
|
$this->path = $path;
|
|
$this->data = array_replace_recursive(self::defaults(), $data);
|
|
}
|
|
|
|
public static function load(string $path): self
|
|
{
|
|
$data = [];
|
|
if (is_file($path)) {
|
|
$decoded = json_decode((string) file_get_contents($path), true);
|
|
if (is_array($decoded)) {
|
|
$data = $decoded;
|
|
}
|
|
}
|
|
|
|
return new self($path, $data);
|
|
}
|
|
|
|
/** @return mixed */
|
|
public function get(string $key, mixed $default = null): mixed
|
|
{
|
|
$segments = explode('.', $key);
|
|
$value = $this->data;
|
|
foreach ($segments as $segment) {
|
|
if (!is_array($value) || !array_key_exists($segment, $value)) {
|
|
return $default;
|
|
}
|
|
$value = $value[$segment];
|
|
}
|
|
|
|
return $value;
|
|
}
|
|
|
|
public function set(string $key, mixed $value): void
|
|
{
|
|
$segments = explode('.', $key);
|
|
$cursor = &$this->data;
|
|
foreach ($segments as $segment) {
|
|
if (!isset($cursor[$segment]) || !is_array($cursor[$segment])) {
|
|
$cursor[$segment] = [];
|
|
}
|
|
$cursor = &$cursor[$segment];
|
|
}
|
|
$cursor = $value;
|
|
}
|
|
|
|
/** @return array<string, mixed> */
|
|
public function all(): array
|
|
{
|
|
return $this->data;
|
|
}
|
|
|
|
public function save(): void
|
|
{
|
|
$dir = dirname($this->path);
|
|
if (!is_dir($dir)) {
|
|
mkdir($dir, 0775, true);
|
|
}
|
|
|
|
file_put_contents(
|
|
$this->path,
|
|
json_encode($this->data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . PHP_EOL
|
|
);
|
|
}
|
|
|
|
public function baseUrl(): string
|
|
{
|
|
$configured = trim((string) $this->get('base_url', ''));
|
|
if ($configured !== '') {
|
|
return rtrim($configured, '/');
|
|
}
|
|
|
|
if (PHP_SAPI === 'cli') {
|
|
return '';
|
|
}
|
|
|
|
$https = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
|
|
|| (($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https');
|
|
$scheme = $https ? 'https' : 'http';
|
|
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
|
|
|
|
return $scheme . '://' . $host;
|
|
}
|
|
|
|
/** @return array<string, mixed> */
|
|
private static function defaults(): array
|
|
{
|
|
return [
|
|
'site' => [
|
|
'title' => 'Neon Notes',
|
|
'tagline' => 'A fast file-first blog CMS',
|
|
'description' => 'A Markdown blog powered by PHP, SQLite, JSON, and plain files.',
|
|
'author' => 'Editor',
|
|
'language' => 'en',
|
|
],
|
|
'base_url' => '',
|
|
'timezone' => 'UTC',
|
|
'theme' => 'neon',
|
|
'posts_per_page' => 6,
|
|
'comments' => [
|
|
'enabled' => true,
|
|
'moderate' => true,
|
|
'captcha' => true,
|
|
'honeypot_field' => 'website_url',
|
|
],
|
|
'stats' => [
|
|
'enabled' => true,
|
|
'hash_salt' => 'change-me',
|
|
],
|
|
'social' => [],
|
|
];
|
|
}
|
|
}
|