Files
server-manager/src/Core/View.php
2026-06-06 17:58:34 -04:00

135 lines
3.6 KiB
PHP
Executable File

<?php
declare(strict_types=1);
namespace ServerManager\Core;
class View
{
private string $viewsPath;
private string $layout = 'main';
private array $data = [];
private Security $security;
public function __construct(Security $security)
{
$this->viewsPath = dirname(__DIR__, 2) . '/views/';
$this->security = $security;
}
public function setLayout(string $layout): self
{
$this->layout = $layout;
return $this;
}
public function assign(string $key, mixed $value): self
{
$this->data[$key] = $value;
return $this;
}
public function assignMultiple(array $data): self
{
$this->data = array_merge($this->data, $data);
return $this;
}
public function render(string $view, array $data = []): string
{
$data = array_merge($this->data, $data);
$content = $this->renderView($view, $data);
if ($this->layout !== null) {
$data['content'] = $content;
$content = $this->renderView('layouts/' . $this->layout, $data);
}
return $content;
}
public function renderView(string $view, array $data = []): string
{
$viewFile = $this->viewsPath . str_replace('.', '/', $view) . '.php';
if (!file_exists($viewFile)) {
throw new \RuntimeException("View not found: {$view}");
}
extract($data, EXTR_SKIP);
ob_start();
include $viewFile;
return ob_get_clean();
}
public function renderPartial(string $partial, array $data = []): string
{
return $this->renderView('partials/' . $partial, $data);
}
public function display(string $view, array $data = []): void
{
echo $this->render($view, $data);
}
public function escape(string $value): string
{
return $this->security->purify($value);
}
public function csrfToken(): string
{
return $this->security->generateCSRFToken();
}
public function csrfField(): string
{
$token = $this->csrfToken();
return '<input type="hidden" name="_csrf_token" value="' . $this->escape($token) . '">';
}
public function redirect(string $url, int $statusCode = 302): never
{
http_response_code($statusCode);
header("Location: {$url}");
exit;
}
public function json(mixed $data, int $statusCode = 200): never
{
http_response_code($statusCode);
header('Content-Type: application/json; charset=utf-8');
echo json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
exit;
}
public function error(int $statusCode, string $message = ''): never
{
http_response_code($statusCode);
if (str_starts_with($_SERVER['HTTP_ACCEPT'] ?? '', 'application/json')) {
$this->json(['error' => true, 'message' => $message ?: $this->getStatusMessage($statusCode)], $statusCode);
}
$this->display("errors.{$statusCode}", [
'code' => $statusCode,
'message' => $message ?: $this->getStatusMessage($statusCode),
]);
exit;
}
private function getStatusMessage(int $code): string
{
return match($code) {
400 => 'Bad Request',
401 => 'Unauthorized',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
429 => 'Too Many Requests',
500 => 'Internal Server Error',
503 => 'Service Unavailable',
default => 'Error',
};
}
}