with(['causer.profile']) ->when($tableQuery['search'] !== '', function (Builder $query) use ($tableQuery): void { $search = $tableQuery['search']; $query->where(function (Builder $query) use ($search): void { $query->where('description', 'like', "%{$search}%") ->orWhere('event', 'like', "%{$search}%") ->orWhereHasMorph( 'causer', [User::class], fn (Builder $query) => $query ->where('username', 'like', "%{$search}%") ->orWhereHas('profile', fn (Builder $query) => $query->where('full_name', 'like', "%{$search}%")), ); }); }) ->when($event !== '', fn (Builder $query) => $query->where('event', $event)) ->when($subjectType !== '', fn (Builder $query) => $query->where('subject_type', $subjectType)); $this->applySorting($query, $tableQuery['sort'], $tableQuery['direction']); return $query ->paginate(10) ->withQueryString() ->through(fn (Activity $activity) => $this->present($activity)); } /** * @return array{ * id: int, * description: string, * event: string|null, * event_label: string, * subject_type: string|null, * subject_label: string, * subject_id: int|null, * causer_name: string, * created_at: string|null, * created_at_formatted: string|null, * changes: list * } */ private function present(Activity $activity): array { return [ 'id' => $activity->id, 'description' => $activity->description, 'event' => $activity->event, 'event_label' => ActivityEventLabel::labelFor($activity->event), 'subject_type' => $activity->subject_type, 'subject_label' => ModelLabel::for($activity->subject_type), 'subject_id' => $activity->subject_id, 'causer_name' => $this->resolveCauserName($activity->causer), 'created_at' => $activity->created_at?->toIso8601String(), 'created_at_formatted' => $activity->created_at?->translatedFormat('l, d F Y H:i'), 'changes' => $this->formatChanges($activity->attribute_changes), ]; } private function resolveCauserName(?Model $causer): string { if (! $causer instanceof User) { return '-'; } return $causer->profile?->full_name ?? $causer->username ?? '-'; } /** * @return list */ private function formatChanges(?Collection $changes): array { if ($changes === null || $changes->isEmpty()) { return []; } $attributes = $changes->get('attributes', []); $old = $changes->get('old', []); if (! is_array($attributes)) { return []; } $formatted = []; foreach ($attributes as $field => $newValue) { $formatted[] = [ 'field' => (string) $field, 'old' => is_array($old) ? ($old[$field] ?? null) : null, 'new' => $newValue, ]; } return $formatted; } private function applySorting(Builder $query, string $sort, string $direction): void { if (in_array($sort, ['created_at', 'description', 'event'], true)) { $query->orderBy($sort, $direction); return; } $query->latest(); } }