requireRole('admin')) { return $r; } $logModel = new ActivityLogModel(); $summary = $logModel->getActivitySummary(); $availableActions = $logModel->getAvailableActions(); $action = $this->request->getGet('action'); if (is_array($action)) { $action = array_values(array_filter(array_map('trim', $action))); } else { $action = trim((string) $action); } $role = $this->request->getGet('role'); if (is_array($role)) { $role = array_values(array_filter(array_map('trim', $role))); } else { $role = trim((string) $role); } $filters = [ 'action' => $action, 'role' => $role, 'date_from' => trim((string) $this->request->getGet('date_from')), 'date_to' => trim((string) $this->request->getGet('date_to')), ]; return view('admin/activity_log', [ 'logs' => $logModel->getFilteredLogs($filters), 'filters' => $filters, 'summary' => $summary, 'availableActions' => $availableActions, ]); } public function analytics() { if ($r = $this->requireRole('admin')) { return $r; } $period = $this->request->getGet('period') ?? '7_days'; $days = ($period === '30_days') ? 30 : 7; $dateFrom = date('Y-m-d', strtotime("-$days days")); $db = \Config\Database::connect(); $summary = [ 'total_actions' => $db->table('activity_logs')->where('activity_at >=', $dateFrom)->countAllResults(), 'by_action' => $db->table('activity_logs')->select('action, COUNT(id) as count')->where('activity_at >=', $dateFrom)->groupBy('action')->get()->getResultArray(), 'by_role' => $db->table('activity_logs')->select('activity_user_type as actor_role, COUNT(id) as count')->where('activity_at >=', $dateFrom)->groupBy('activity_user_type')->get()->getResultArray(), ]; $mostActive = $db->table('activity_logs al') ->select("CONCAT(COALESCE(u.first_name, ''), ' ', COALESCE(u.last_name, '')) as name, COUNT(al.id) as count") ->join('users u', 'u.id = al.activity_user_id', 'left') ->where('al.activity_at >=', $dateFrom) ->groupBy('al.activity_user_id') ->orderBy('count', 'DESC') ->limit(10) ->get() ->getResultArray(); $summary['most_active_users'] = $mostActive; $actionLabels = array_column($summary['by_action'], 'action'); $actionCounts = array_column($summary['by_action'], 'count'); $typeLabels = array_column($summary['by_role'], 'actor_role'); $typeCounts = array_column($summary['by_role'], 'count'); $userLabels = array_map(function($user) { return trim((string) $user['name']) ?: 'System'; }, $mostActive); $userCounts = array_column($mostActive, 'count'); $uniqueIPs = $db->table('activity_logs')->select('ip as ip, COUNT(id) as count')->where('activity_at >=', $dateFrom)->where('ip IS NOT NULL')->groupBy('ip')->orderBy('count', 'DESC')->get()->getResultArray(); $criticalActions = $db->table('activity_logs al') ->select("al.activity_at as activity_at, CONCAT(COALESCE(u.first_name, ''), ' ', COALESCE(u.last_name, '')) AS actor_name, u.email AS actor_email, al.action, al.target_user_type as target_user_type, al.target_user_id as target_user_id, al.description") ->join('users u', 'u.id = al.activity_user_id', 'left') ->like('al.action', 'delete') ->orderBy('al.activity_at', 'DESC') ->limit(50) ->get() ->getResultArray(); return view('admin/activity_analytics', [ 'period' => $period, 'summary' => $summary, 'uniqueIPs' => $uniqueIPs, 'criticalActions' => $criticalActions, 'actionLabels' => json_encode($actionLabels), 'actionCounts' => json_encode($actionCounts), 'typeLabels' => json_encode($typeLabels), 'typeCounts' => json_encode($typeCounts), 'userLabels' => json_encode($userLabels), 'userCounts' => json_encode($userCounts) ]); } }