request = $request; } public function setResponse(Response $response): void { $this->response = $response; } public function setSession(Session $session): void { $this->session = $session; } public function setDatabase(Database $database): void { $this->database = $database; $this->auditService = new AuditService($database, $session); } protected function render(string $view, array $data = []): string { // Extract data to variables extract($data); // Add common data $user = $this->session->getUser(); $flashMessages = $this->session->getFlashMessages(); $csrfToken = $this->session->getCsrfToken(); $locale = $this->session->getLocale(); // Load language file $lang = $this->loadLanguage($locale); // Start output buffering ob_start(); // Include the view file $viewPath = APP_PATH . '/Views/' . $view . '.php'; if (!file_exists($viewPath)) { throw new \Exception("View not found: {$view}"); } require $viewPath; // Return the buffered content return ob_get_clean(); } protected function renderLayout(string $view, array $data = []): string { $content = $this->render($view, $data); // Add layout wrapper $user = $this->session->getUser(); $flashMessages = $this->session->getFlashMessages(); $csrfToken = $this->session->getCsrfToken(); $locale = $this->session->getLocale(); $lang = $this->loadLanguage($locale); ob_start(); require APP_PATH . '/Views/layouts/main.php'; return ob_get_clean(); } protected function redirect(string $url): Response { return $this->response->redirect($url); } protected function json(array $data, int $statusCode = 200): Response { return $this->response->json($data, $statusCode); } protected function validate(array $rules): array { return $this->request->validate($rules); } protected function flash(string $key, string $message): void { $this->session->flash($key, $message); } protected function getUserId(): ?int { return $this->session->getUserId(); } protected function getUserRole(): ?string { return $this->session->getUserRole(); } protected function isAdmin(): bool { return $this->session->isAdmin(); } protected function isAuditor(): bool { return $this->session->isAuditor(); } protected function isEmployee(): bool { return $this->session->isEmployee(); } protected function hasPermission(string $permission): bool { $role = $this->getUserRole(); switch ($permission) { case 'admin': return $role === 'admin'; case 'auditor': return in_array($role, ['admin', 'auditor']); case 'employee': return in_array($role, ['admin', 'auditor', 'employee']); default: return false; } } protected function paginate(string $sql, array $params = [], int $perPage = 20): array { $page = (int) ($this->request->get('page', 1)); $offset = ($page - 1) * $perPage; // Get total count $countSql = preg_replace('/SELECT .* FROM/', 'SELECT COUNT(*) as total FROM', $sql); $countSql = preg_replace('/ORDER BY .*/', '', $countSql); $countSql = preg_replace('/LIMIT .*/', '', $countSql); $totalResult = $this->database->fetch($countSql, $params); $total = $totalResult['total'] ?? 0; // Get paginated data $dataSql = $sql . " LIMIT {$perPage} OFFSET {$offset}"; $data = $this->database->fetchAll($dataSql, $params); $totalPages = ceil($total / $perPage); return [ 'data' => $data, 'pagination' => [ 'current_page' => $page, 'per_page' => $perPage, 'total' => $total, 'total_pages' => $totalPages, 'has_previous' => $page > 1, 'has_next' => $page < $totalPages, 'previous_page' => $page > 1 ? $page - 1 : null, 'next_page' => $page < $totalPages ? $page + 1 : null, ] ]; } protected function logAudit(string $action, string $table, int $recordId, array $oldValue = null, array $newValue = null): void { $this->auditService->log($action, $table, $recordId, $oldValue, $newValue); } private function loadLanguage(string $locale): array { $langFile = LANG_PATH . '/' . $locale . '.php'; if (file_exists($langFile)) { return require $langFile; } // Fallback to German $langFile = LANG_PATH . '/de.php'; return file_exists($langFile) ? require $langFile : []; } protected function trans(string $key, array $params = []): string { $lang = $this->loadLanguage($this->session->getLocale()); $text = $lang[$key] ?? $key; foreach ($params as $param => $value) { $text = str_replace(':' . $param, $value, $text); } return $text; } protected function formatDate(string $date, string $format = 'd.m.Y'): string { return date($format, strtotime($date)); } protected function formatDateTime(string $date, string $format = 'd.m.Y H:i'): string { return date($format, strtotime($date)); } protected function formatCurrency(float $amount): string { return number_format($amount, 2, ',', '.') . ' €'; } protected function sanitizeInput(string $input): string { return htmlspecialchars(trim($input), ENT_QUOTES, 'UTF-8'); } protected function generateSlug(string $text): string { $text = strtolower($text); $text = preg_replace('/[^a-z0-9\s-]/', '', $text); $text = preg_replace('/[\s-]+/', '-', $text); return trim($text, '-'); } }