Files
gtsit/app/Support/helpers.php
2026-08-10 21:19:10 +09:00

135 lines
3.6 KiB
PHP

<?php
declare(strict_types=1);
function config(string $key, mixed $default = null): mixed
{
static $configs = [];
[$file, $path] = array_pad(explode('.', $key, 2), 2, null);
if (!array_key_exists($file, $configs)) {
$configFile = dirname(__DIR__, 2) . '/config/' . $file . '.php';
$configs[$file] = is_file($configFile) ? require $configFile : [];
}
$value = $configs[$file];
if ($path === null) {
return $value;
}
foreach (explode('.', $path) as $segment) {
if (!is_array($value) || !array_key_exists($segment, $value)) {
return $default;
}
$value = $value[$segment];
}
return $value;
}
function e(mixed $value): string
{
return htmlspecialchars((string) $value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
function url(string $path = ''): string
{
$basePath = (string) config('app.base_path', '');
$path = '/' . ltrim($path, '/');
return ($basePath !== '' ? $basePath : '') . $path;
}
function asset(string $path): string
{
return url('assets/' . ltrim($path, '/'));
}
function csrf_token(): string
{
if (empty($_SESSION['_csrf'])) {
$_SESSION['_csrf'] = bin2hex(random_bytes(32));
}
return $_SESSION['_csrf'];
}
function csrf_field(): string
{
return '<input type="hidden" name="_csrf" value="' . e(csrf_token()) . '">';
}
function verify_csrf(): void
{
$submitted = $_POST['_csrf'] ?? '';
if (!is_string($submitted) || !hash_equals(csrf_token(), $submitted)) {
http_response_code(403);
render('errors/419', ['title' => '요청을 다시 확인해 주세요']);
exit;
}
}
function redirect(string $path, int $status = 302): never
{
header('Location: ' . url($path), true, $status);
exit;
}
function render(string $view, array $data = [], string $layout = 'layouts/site'): void
{
$viewFile = dirname(__DIR__) . '/Views/' . $view . '.php';
$layoutFile = dirname(__DIR__) . '/Views/' . $layout . '.php';
if (!is_file($viewFile) || !is_file($layoutFile)) {
throw new RuntimeException('View not found.');
}
extract($data, EXTR_SKIP);
ob_start();
require $viewFile;
$content = (string) ob_get_clean();
ob_start();
require $layoutFile;
$html = (string) ob_get_clean();
$basePath = (string) config('app.base_path', '');
if ($basePath !== '') {
$html = (string) preg_replace_callback(
'/\b(href|src|action)="(\/(?!\/)[^"]*)"/',
static function (array $matches) use ($basePath): string {
$path = $matches[2];
if ($path === $basePath || str_starts_with($path, $basePath . '/')) return $matches[0];
return $matches[1] . '="' . $basePath . $path . '"';
},
$html
);
}
echo $html;
}
function old(string $key, string $default = ''): string
{
return e($_POST[$key] ?? $default);
}
function is_active_path(string $path): bool
{
$current = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH) ?: '/';
$basePath = (string) config('app.base_path', '');
if ($basePath !== '' && ($current === $basePath || str_starts_with($current, $basePath . '/'))) {
$current = substr($current, strlen($basePath)) ?: '/';
}
return $path === '/' ? $current === '/' : str_starts_with($current, $path);
}
function site_setting(string $key, mixed $default = ''): mixed
{
static $settings = null;
if ($settings === null) {
try {
$settings = (new \App\Repositories\SiteSettingRepository())->all();
} catch (\Throwable) {
$settings = [];
}
}
return $settings[$key] ?? $default;
}