Files
2026-06-11 12:30:23 +07:00

116 lines
3.7 KiB
PHP

<?php
// core/Controller.php
class Controller {
protected Database $db;
public function __construct() {
$this->db = Database::getInstance();
}
protected function view(string $view, array $data = [], ?string $layout = 'main'): void {
extract($data);
$viewFile = APP_ROOT . '/app/views/' . str_replace('.', '/', $view) . '.php';
if (!file_exists($viewFile)) {
die("View not found: $viewFile");
}
if ($layout) {
$layoutFile = APP_ROOT . '/app/views/layouts/' . $layout . '.php';
if (file_exists($layoutFile)) {
// Capture view content
ob_start();
require $viewFile;
$content = ob_get_clean();
require $layoutFile;
return;
}
}
require $viewFile;
}
protected function json(mixed $data, int $code = 200): void {
http_response_code($code);
header('Content-Type: application/json; charset=utf-8');
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit;
}
protected function redirect(string $url): void {
// Flush session ke disk sebelum redirect agar data tidak hilang
if (session_status() === PHP_SESSION_ACTIVE) {
session_write_close();
}
header("Location: $url");
exit;
}
protected function back(): void {
$referer = $_SERVER['HTTP_REFERER'] ?? APP_URL;
$this->redirect($referer);
}
protected function csrf(): string {
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
return $_SESSION['csrf_token'];
}
protected function verifyCsrf(): bool {
// Pastikan session aktif sebelum membaca token
Auth::init();
$token = $_POST['_token'] ?? $_SERVER['HTTP_X_CSRF_TOKEN'] ?? '';
return hash_equals($_SESSION['csrf_token'] ?? '', $token);
}
protected function input(string $key, mixed $default = null): mixed {
return $_POST[$key] ?? $_GET[$key] ?? $default;
}
protected function sanitize(string $value): string {
return htmlspecialchars(trim($value), ENT_QUOTES, 'UTF-8');
}
protected function flash(string $type, string $message, array $extra = []): void {
$_SESSION['flash'] = ['type' => $type, 'message' => $message] + $extra;
}
protected function getFlash(): ?array {
if (isset($_SESSION['flash'])) {
$flash = $_SESSION['flash'];
unset($_SESSION['flash']);
return $flash;
}
return null;
}
protected function uploadFile(array $file, string $dir = 'uploads'): ?string {
if ($file['error'] !== UPLOAD_ERR_OK) return null;
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
$allow = ['jpg', 'jpeg', 'png', 'webp'];
if (!in_array($ext, $allow)) return null;
$maxSize = 5 * 1024 * 1024; // 5MB
if ($file['size'] > $maxSize) return null;
$filename = uniqid('img_', true) . '.' . $ext;
$destDir = APP_ROOT . '/public/images/' . $dir . '/';
if (!is_dir($destDir)) mkdir($destDir, 0755, true);
if (move_uploaded_file($file['tmp_name'], $destDir . $filename)) {
return $filename;
}
return null;
}
protected function paginate(int $total, int $perPage = 20): array {
$page = max(1, (int)($_GET['page'] ?? 1));
$offset = ($page - 1) * $perPage;
$pages = (int)ceil($total / $perPage);
return compact('page', 'offset', 'perPage', 'pages', 'total');
}
}