with('category') ->orderBy('name'); $this->applyTrashed($query, $request->input('trashed')); $this->applySearch($query, $request->input('search')); if ($request->filled('category_id')) { $query->where('category_id', $request->integer('category_id')); } $institutions = $query->paginate($request->integer('per_page') ?: 20); return $this->paginatedCollectionResponse($institutions); } /** * Crea un'istituzione (con upload del logo). */ public function store(StoreInstitutionRequest $request): JsonResponse { $data = $request->validated(); $data['logo'] = $this->storeLogo($request->file('logo')); $institution = Institution::create($data); return $this->createdResponse($institution->load('category')); } /** * Dettaglio (con categoria e link). */ public function show(Institution $institution): JsonResponse { return $this->okResponse($institution->load(['category', 'links'])); } /** * Aggiorna un'istituzione. Logo opzionale: se presente sostituisce il vecchio. */ public function update(UpdateInstitutionRequest $request, Institution $institution): JsonResponse { $data = $request->validated(); if ($request->hasFile('logo')) { $this->deleteLogo($institution->logo); $data['logo'] = $this->storeLogo($request->file('logo')); } else { unset($data['logo']); } $institution->update($data); return $this->updatedResponse($institution->load('category')); } /** * Cestina (soft delete). */ public function destroy(Institution $institution): JsonResponse { $institution->delete(); return $this->deletedResponse(); } /** * Ripristina un'istituzione cestinata. */ public function restore(Institution $institution): JsonResponse { $institution->restore(); return $this->restoredResponse($institution->load('category')); } /** * Elimina definitivamente (rimuove il file logo; i link cadono in cascata DB). */ public function forceDestroy(Institution $institution): JsonResponse { $this->deleteLogo($institution->logo); $institution->forceDelete(); return $this->deletedResponse(); } /** * Salva il file logo sul disco `public` e ne restituisce il path relativo. */ private function storeLogo(UploadedFile $file): string { return $file->store(self::LOGO_DIR, 'public'); } /** * Rimuove un file logo dal disco `public`, se presente. */ private function deleteLogo(?string $path): void { if (filled($path)) { Storage::disk('public')->delete($path); } } /** * Include i soft-deleted: `with` (tutti) o `only` (solo cestinati). * * @param Builder $query */ private function applyTrashed(Builder $query, ?string $trashed): void { match ($trashed) { 'with' => $query->withTrashed(), 'only' => $query->onlyTrashed(), default => null, }; } /** * Ricerca parziale su nome, città e sigla. * * @param Builder $query */ private function applySearch(Builder $query, ?string $search): void { if (blank($search)) { return; } $term = '%'.$search.'%'; $query->where(function (Builder $q) use ($term): void { $q->where('name', 'like', $term) ->orWhere('city', 'like', $term) ->orWhere('abbreviation', 'like', $term); }); } }