validate([ 'q' => ['nullable', 'string', 'max:100'], 'page' => ['nullable', 'integer', 'min:1'], 'per_page' => ['nullable', 'integer', 'min:1', 'max:100'], ]); $today = today()->toDateString(); $query = InvestmentLegalSource::query() ->where('validation_status', 'validated') ->whereDate('valid_from', '<=', $today) ->where(fn ($query) => $query->whereNull('valid_until')->orWhereDate('valid_until', '>=', $today)); if (! empty($filters['q'])) { $term = '%'.addcslashes($filters['q'], '%_\\').'%'; $query->where(fn ($query) => $query ->whereRaw('title ILIKE ?', [$term]) ->orWhereRaw('diploma ILIKE ?', [$term]) ->orWhereRaw('article ILIKE ?', [$term]) ->orWhereRaw('competent_entity ILIKE ?', [$term])); } $page = $query->orderBy('title')->orderBy('id')->paginate($filters['per_page'] ?? 25)->withQueryString(); $data = collect($page->items())->map(fn (InvestmentLegalSource $source): array => [ 'id' => $source->id, 'title' => $source->title, 'url' => $source->url, 'diploma' => $source->diploma, 'article' => $source->article, 'competent_entity' => $source->competent_entity, 'validation_status' => $source->validation_status, 'version_no' => (int) $source->version_no, 'valid_from' => $source->valid_from, 'valid_until' => $source->valid_until, 'validator_id' => $source->validator_id === null ? null : (int) $source->validator_id, 'validated_at' => $source->validated_at, ])->values(); $body = [ 'data' => $data, 'meta' => [ 'current_page' => $page->currentPage(), 'per_page' => $page->perPage(), 'total' => $page->total(), ], ]; $etag = 'W/"legal-sources-'.hash('sha256', json_encode([ 'filters' => $filters, 'data' => $data, 'total' => $page->total(), ], JSON_THROW_ON_ERROR)).'"'; return response()->json($body) ->header('ETag', $etag) ->header('Cache-Control', 'public, max-age=300'); } }