- new blog cms
This commit is contained in:
+127
@@ -0,0 +1,127 @@
|
||||
<?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' => [],
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user