Backup #626
| ID | 626 |
| Dateipfad | /var/www/dev.campus.systemische-tools.de/src/Framework/Controller.php |
| Version | 5 |
| Typ |
modified |
| Größe | 6.0 KB |
| Hash | ac632b1ad96012b2a42e29d5e779f300ce1774618e8a9e8028edf09559f07b38 |
| Datum | 2025-12-23 04:44:04 |
| Geändert von | claude-code-hook |
| Grund | Claude Code Pre-Hook Backup vor Edit-Operation |
| Datei existiert |
Ja
|
Dateiinhalt
<?php
namespace Framework;
abstract class Controller
{
protected function csrfToken(): string
{
return CsrfService::getToken();
}
protected function csrfField(): string
{
return CsrfService::getTokenField();
}
protected function validateCsrf(): bool
{
$token = $_POST['_csrf_token'] ?? $_SERVER['HTTP_X_CSRF_TOKEN'] ?? null;
return CsrfService::validateToken($token);
}
protected function requireCsrf(): void
{
if (!$this->validateCsrf()) {
http_response_code(403);
if ($this->isJsonRequest()) {
$this->json(['error' => 'CSRF token invalid'], 403);
} else {
echo 'CSRF token invalid';
}
exit;
}
}
private function isJsonRequest(): bool
{
$accept = $_SERVER['HTTP_ACCEPT'] ?? '';
$contentType = $_SERVER['CONTENT_TYPE'] ?? '';
return str_contains($accept, 'application/json') || str_contains($contentType, 'application/json');
}
protected function view(string $name, array $data = []): void
{
$data['csrfField'] = $this->csrfField();
$data['csrfToken'] = $this->csrfToken();
extract($data);
$file = VIEW_PATH . '/' . str_replace('.', '/', $name) . '.php';
if (file_exists($file)) {
require $file;
} else {
throw new \Exception("View not found: {$name}");
}
}
protected function json(mixed $data, int $status = 200): void
{
http_response_code($status);
header('Content-Type: application/json');
echo json_encode($data, JSON_UNESCAPED_UNICODE);
}
protected function redirect(string $url, int $status = 302): never
{
http_response_code($status);
header("Location: {$url}");
exit;
}
/**
* Render a partial template (for HTMX responses).
*
* @param string $name Partial name (e.g., 'chat/message' or 'content/version')
* @param array<string, mixed> $data Data to pass to partial
*/
protected function partial(string $name, array $data = []): void
{
$data['csrfField'] = $this->csrfField();
$data['csrfToken'] = $this->csrfToken();
extract($data);
// Try module-specific partials first, then global partials
$paths = [
VIEW_PATH . '/' . str_replace('.', '/', $name) . '.php',
VIEW_PATH . '/partials/' . str_replace('.', '/', $name) . '.php',
];
foreach ($paths as $file) {
if (file_exists($file)) {
require $file;
return;
}
}
throw new \Exception("Partial not found: {$name}");
}
/**
* Output an HTMX-compatible alert message.
*
* @param string $type Alert type: 'success', 'error', 'warning', 'info'
* @param string $message The message to display
*/
protected function htmxAlert(string $type, string $message): void
{
$escapedMessage = htmlspecialchars($message, ENT_QUOTES, 'UTF-8');
echo "<div class=\"alert {$type}\">{$escapedMessage}</div>";
}
/**
* Output success alert for HTMX.
*/
protected function htmxSuccess(string $message): void
{
$this->htmxAlert('success', $message);
}
/**
* Output error alert for HTMX.
*/
protected function htmxError(string $message): void
{
$this->htmxAlert('error', $message);
}
/**
* HTMX redirect via header.
*/
protected function htmxRedirect(string $url): void
{
header('HX-Redirect: ' . $url);
echo 'OK';
}
/**
* @return array<string, mixed>
*/
protected function getJsonInput(): array
{
$input = file_get_contents('php://input');
if ($input === false || $input === '') {
return [];
}
$decoded = json_decode($input, true);
if (!is_array($decoded)) {
return [];
}
return $decoded;
}
protected function jsonError(string $message, int $status = 500): void
{
$this->json(['success' => false, 'error' => $message], $status);
}
/**
* Return 404 Not Found response and exit.
* Automatically detects JSON requests.
*/
protected function notFound(string $message = 'Nicht gefunden'): never
{
http_response_code(404);
if ($this->isJsonRequest()) {
$this->json(['error' => $message], 404);
} else {
echo "404 - {$message}";
}
exit;
}
/**
* Decode JSON string to array with safe defaults.
*
* @return array<mixed>
*/
protected function decodeJson(?string $json): array
{
if ($json === null || $json === '') {
return [];
}
$decoded = json_decode($json, true);
return is_array($decoded) ? $decoded : [];
}
/**
* Get input value from GET or POST.
*/
protected function getInput(string $key, mixed $default = null): mixed
{
return $_GET[$key] ?? $_POST[$key] ?? $default;
}
/**
* Get trimmed string input.
*/
protected function getString(string $key, string $default = ''): string
{
$value = $this->getInput($key, $default);
return is_string($value) ? trim($value) : $default;
}
/**
* Get integer input.
*/
protected function getInt(string $key, int $default = 0): int
{
return (int) ($this->getInput($key, $default));
}
/**
* Get current page number from request.
*/
protected function getPage(): int
{
return max(1, $this->getInt('page', 1));
}
/**
* Get limit with bounds.
*/
protected function getLimit(int $max = 50, int $default = 10): int
{
return min($max, max(1, $this->getInt('limit', $default)));
}
/**
* Calculate offset from page and limit.
*/
protected function getOffset(int $limit): int
{
return ($this->getPage() - 1) * $limit;
}
}
Vollständig herunterladen
Aktionen
Andere Versionen dieser Datei
| ID |
Version |
Typ |
Größe |
Datum |
| 2095 |
18 |
modified |
8.6 KB |
2025-12-29 00:20 |
| 1887 |
17 |
modified |
8.6 KB |
2025-12-28 01:00 |
| 1883 |
16 |
modified |
8.5 KB |
2025-12-28 01:00 |
| 1793 |
15 |
modified |
8.5 KB |
2025-12-27 14:09 |
| 1775 |
14 |
modified |
8.1 KB |
2025-12-27 14:03 |
| 1774 |
13 |
modified |
8.0 KB |
2025-12-27 14:03 |
| 1676 |
12 |
modified |
7.6 KB |
2025-12-27 11:45 |
| 1669 |
11 |
modified |
7.4 KB |
2025-12-27 11:29 |
| 877 |
10 |
modified |
7.4 KB |
2025-12-23 09:40 |
| 818 |
9 |
modified |
7.3 KB |
2025-12-23 08:09 |
| 640 |
8 |
modified |
6.9 KB |
2025-12-23 04:47 |
| 628 |
7 |
modified |
6.9 KB |
2025-12-23 04:44 |
| 627 |
6 |
modified |
6.9 KB |
2025-12-23 04:44 |
| 626 |
5 |
modified |
6.0 KB |
2025-12-23 04:44 |
| 496 |
4 |
modified |
4.2 KB |
2025-12-22 15:38 |
| 214 |
3 |
modified |
2.3 KB |
2025-12-22 01:41 |
| 89 |
2 |
modified |
2.2 KB |
2025-12-20 19:16 |
| 87 |
1 |
modified |
1.2 KB |
2025-12-20 19:16 |
← Zurück zur Übersicht