authorizeRead('documenti'); $documenti = Documento::with(['user', 'target']) ->orderByDesc('created_at') ->paginate(20); $individui = Individuo::orderBy('cognome')->orderBy('nome')->get(); $gruppi = Gruppo::orderBy('nome')->get(); $eventi = Evento::orderBy('nome_evento')->get(); $mailingLists = \App\Models\MailingList::orderBy('nome')->get(); $tipologie = TipologiaDocumento::attive(); return view('documenti.index', compact('documenti', 'individui', 'gruppi', 'eventi', 'mailingLists', 'tipologie')); } public function create() { $this->authorizeWrite('documenti'); $individui = Individuo::orderBy('cognome')->orderBy('nome')->get(); $gruppi = Gruppo::orderBy('nome')->get(); $eventi = Evento::orderBy('nome_evento')->get(); $tipologie = TipologiaDocumento::attive(); return view('documenti.create', compact('individui', 'gruppi', 'eventi', 'tipologie')); } public function edit($documento) { $this->authorizeWrite('documenti'); $documento = Documento::with('target')->findOrFail($documento); $individui = Individuo::orderBy('cognome')->orderBy('nome')->get(); $gruppi = Gruppo::orderBy('nome')->get(); $eventi = Evento::orderBy('nome_evento')->get(); $mailingLists = \App\Models\MailingList::orderBy('nome')->get(); $tipologie = TipologiaDocumento::attive(); return view('documenti.edit', compact('documento', 'individui', 'gruppi', 'eventi', 'mailingLists', 'tipologie')); } public function options(Request $request) { $tipo = $request->get('tipo'); $options = ''; switch ($tipo) { case 'individuo': $items = Individuo::orderBy('cognome')->orderBy('nome')->get(); foreach ($items as $item) { $options .= ''; } break; case 'gruppo': $items = Gruppo::orderBy('nome')->get(); foreach ($items as $item) { $options .= ''; } break; case 'evento': $items = Evento::orderBy('nome_evento')->get(); foreach ($items as $item) { $options .= ''; } break; case 'mailing': $items = \App\Models\MailingList::orderBy('nome')->get(); foreach ($items as $item) { $options .= ''; } break; } return response($options); } public function update(Request $request, $documento) { $this->authorizeWrite('documenti'); $documento = Documento::findOrFail($documento); $tipologieValidi = TipologiaDocumento::opzioni(); $tipologieRule = 'in:' . implode(',', $tipologieValidi); $data = $request->validate([ 'nome_file' => 'required|string|max:255', 'tipologia' => 'required|' . $tipologieRule, 'visibilita' => 'nullable|string', 'visibilita_target_id' => 'nullable|integer', 'visibilita_target_type' => 'nullable|string', 'note' => 'nullable|string', ]); $data['visibilita'] = $request->contesto_tipo ?: 'pubblico'; if ($request->contesto_tipo) { $typeMap = [ 'individuo' => Individuo::class, 'gruppo' => Gruppo::class, 'evento' => Evento::class, 'mailing' => \App\Models\MailingList::class, ]; $data['visibilita_target_type'] = $typeMap[$request->contesto_tipo] ?? null; } else { $data['visibilita'] = 'pubblico'; $data['visibilita_target_id'] = null; $data['visibilita_target_type'] = null; } $documento->update($data); return redirect('/documenti')->with('success', 'Documento aggiornato.'); } public function store(Request $request) { $this->authorizeWrite('documenti'); $data = $request->validate([ 'nome_file' => 'required|string|max:255', 'tipologia' => 'required|in:avatar,galleria,documento,statuto,altro', 'file' => 'required|file|max:10240', 'visibilita' => 'required|in:pubblico,individuo,gruppo', 'visibilita_target_id' => 'nullable|integer', 'visibilita_target_type' => 'nullable|string', ]); $file = $request->file('file'); $path = $file->store('documenti', 'local'); $visibilitaTargetType = null; if ($data['visibilita'] === 'individuo' && $data['visibilita_target_id']) { $visibilitaTargetType = Individuo::class; } elseif ($data['visibilita'] === 'gruppo' && $data['visibilita_target_id']) { $visibilitaTargetType = Gruppo::class; } Documento::create([ 'nome_file' => $data['nome_file'], 'file_path' => $path, 'tipo' => 'upload', 'tipologia' => $data['tipologia'], 'visibilita' => $data['visibilita'], 'visibilita_target_id' => $data['visibilita_target_id'] ?? null, 'visibilita_target_type' => $visibilitaTargetType, 'mime_type' => $file->getMimeType(), 'dimensione' => $file->getSize(), 'user_id' => auth()->id(), ]); $redirect = $request->_redirect ?? url()->previous(); return redirect($redirect)->with('success', 'Documento caricato.'); } public function download($documento) { $this->authorizeRead('documenti'); $documento = Documento::findOrFail($documento); if (!Storage::disk('local')->exists($documento->file_path)) { abort(404); } $extension = pathinfo($documento->file_path, PATHINFO_EXTENSION); $filename = $extension ? $documento->nome_file . '.' . $extension : $documento->nome_file; return Storage::disk('local')->download( $documento->file_path, $filename, ['Content-Type' => $documento->mime_type] ); } public function preview($documento) { $this->authorizeRead('documenti'); $documento = Documento::findOrFail($documento); if (!Storage::disk('local')->exists($documento->file_path)) { abort(404); } $fullPath = Storage::disk('local')->path($documento->file_path); $mimeType = $documento->mime_type; $previewableMimeTypes = [ 'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml', 'application/pdf', 'text/plain', 'text/html', 'text/csv', ]; if (in_array($mimeType, $previewableMimeTypes)) { return response()->file($fullPath, ['Content-Type' => $mimeType]); } return response()->view('documenti.preview-fallback', [ 'documento' => $documento, ])->header('X-Preview-Fallback', 'true'); } public function destroy($documento) { $this->authorizeDelete('documenti'); $documento = Documento::findOrFail($documento); if (Storage::disk('local')->exists($documento->file_path)) { Storage::disk('local')->delete($documento->file_path); } $documento->delete(); $redirect = request('_redirect', url('/')); return redirect($redirect)->with('success', 'Documento eliminato.'); } public function checkLinks($documento) { $documento = Documento::findOrFail($documento); $links = []; if (in_array($documento->visibilita, ['individuo', 'gruppo', 'evento']) && $documento->visibilita_target_id) { if ($documento->visibilita === 'individuo') { $target = Individuo::find($documento->visibilita_target_id); if ($target) { $links[] = [ 'type' => 'individuo', 'name' => $target->cognome . ' ' . $target->nome, 'url' => '/individui/' . $target->id, ]; } } elseif ($documento->visibilita === 'gruppo') { $target = Gruppo::find($documento->visibilita_target_id); if ($target) { $links[] = [ 'type' => 'gruppo', 'name' => $target->nome, 'url' => '/gruppi/' . $target->id, ]; } } elseif ($documento->visibilita === 'evento') { $target = Evento::find($documento->visibilita_target_id); if ($target) { $links[] = [ 'type' => 'evento', 'name' => $target->nome_evento, 'url' => '/eventi/' . $target->id, ]; } } } if ($documento->tipologia === 'avatar') { $linkedToAvatar = Individuo::whereHas('avatar', function($q) use ($documento) { $q->where('id', $documento->id); })->count(); if ($linkedToAvatar > 0) { $links[] = [ 'type' => 'avatar', 'name' => 'Avatar di ' . $linkedToAvatar . ' individuo(i)', 'url' => null, ]; } } if ($documento->eventi()->count() > 0) { foreach ($documento->eventi as $evento) { $links[] = [ 'type' => 'evento', 'name' => 'Evento: ' . $evento->nome_evento, 'url' => '/eventi/' . $evento->id, ]; } } return response()->json([ 'has_links' => count($links) > 0, 'links' => $links, ]); } public function checkMassLinks(Request $request) { $idsInput = $request->input('ids', ''); $ids = is_array($idsInput) ? $idsInput : (is_string($idsInput) ? explode(',', $idsInput) : []); if (empty($ids)) { return response()->json(['linked_count' => 0, 'links' => []]); } $documenti = Documento::whereIn('id', $ids)->get(); $allLinks = []; $linkedCount = 0; foreach ($documenti as $documento) { $isLinked = false; $linkName = ''; $linkUrl = null; if (in_array($documento->visibilita, ['individuo', 'gruppo', 'evento']) && $documento->visibilita_target_id) { $isLinked = true; $linkName = $documento->nome_file . ' → '; if ($documento->visibilita === 'individuo') { $target = Individuo::find($documento->visibilita_target_id); $linkName .= $target ? $target->cognome . ' ' . $target->nome : 'Individuo #' . $documento->visibilita_target_id; $linkUrl = $target ? '/individui/' . $target->id : null; } elseif ($documento->visibilita === 'gruppo') { $target = Gruppo::find($documento->visibilita_target_id); $linkName .= $target ? $target->nome : 'Gruppo #' . $documento->visibilita_target_id; $linkUrl = $target ? '/gruppi/' . $target->id : null; } elseif ($documento->visibilita === 'evento') { $target = Evento::find($documento->visibilita_target_id); $linkName .= $target ? $target->nome_evento : 'Evento #' . $documento->visibilita_target_id; $linkUrl = $target ? '/eventi/' . $target->id : null; } } if ($documento->tipologia === 'avatar') { $linkedToAvatar = Individuo::whereHas('avatar', function($q) use ($documento) { $q->where('id', $documento->id); })->count(); if ($linkedToAvatar > 0) { $isLinked = true; $allLinks[] = [ 'name' => $documento->nome_file . ' → Avatar di ' . $linkedToAvatar . ' individuo(i)', 'url' => null, ]; $linkedCount++; } } if ($documento->eventi()->count() > 0) { $eventi = $documento->eventi; foreach ($eventi as $evento) { $allLinks[] = [ 'name' => $documento->nome_file . ' → Evento: ' . $evento->nome_evento, 'url' => '/eventi/' . $evento->id, ]; $linkedCount++; } } if ($isLinked && $documento->tipologia !== 'avatar' && $linkName) { $allLinks[] = [ 'name' => $linkName, 'url' => $linkUrl, ]; $linkedCount++; } } return response()->json([ 'linked_count' => $linkedCount, 'links' => $allLinks, ]); } public function massDestroy(Request $request) { $this->authorizeDelete('documenti'); $idsInput = $request->input('ids', ''); $ids = is_array($idsInput) ? $idsInput : (is_string($idsInput) ? explode(',', $idsInput) : []); if (empty($ids)) { return back()->with('error', 'Nessun documento selezionato.'); } $documenti = Documento::whereIn('id', $ids)->get(); foreach ($documenti as $documento) { if (Storage::disk('local')->exists($documento->file_path)) { Storage::disk('local')->delete($documento->file_path); } $documento->delete(); } return back()->with('success', count($ids) . ' documenti eliminati.'); } public function massUpdate(Request $request) { $this->authorizeWrite('documenti'); $idsInput = $request->input('ids', ''); $ids = is_array($idsInput) ? $idsInput : (is_string($idsInput) ? explode(',', $idsInput) : []); if (empty($ids)) { return back()->with('error', 'Nessun documento selezionato.'); } $data = $request->validate([ 'tipologia' => 'nullable|string', 'visibilita' => 'nullable|string', ]); $tipologia = $data['tipologia'] ?? null; $visibilita = $data['visibilita'] ?? null; if (empty($tipologia) && empty($visibilita)) { return back()->with('error', 'Specificare almeno un campo da aggiornare.'); } $updateData = []; if (!empty($tipologia)) { $updateData['tipologia'] = $tipologia; } if (!empty($visibilita)) { $updateData['visibilita'] = $visibilita; $typeMap = [ 'individuo' => Individuo::class, 'gruppo' => Gruppo::class, 'evento' => Evento::class, 'mailing' => \App\Models\MailingList::class, ]; if (isset($typeMap[$visibilita])) { $updateData['visibilita_target_type'] = $typeMap[$visibilita]; } } Documento::whereIn('id', $ids)->update($updateData); return back()->with('success', count($ids) . ' documenti aggiornati.'); } public function massAssociate(Request $request) { $this->authorizeWrite('documenti'); $idsInput = $request->input('ids', ''); $ids = is_array($idsInput) ? $idsInput : (is_string($idsInput) ? explode(',', $idsInput) : []); if (empty($ids)) { return back()->with('error', 'Nessun documento selezionato.'); } $data = $request->validate([ 'target_type' => 'required|in:individuo,gruppo,evento,mailing', 'target_id' => 'required|integer', ]); $targetType = match($data['target_type']) { 'individuo' => Individuo::class, 'gruppo' => Gruppo::class, 'evento' => Evento::class, 'mailing' => \App\Models\MailingList::class, }; Documento::whereIn('id', $ids)->update([ 'visibilita' => $data['target_type'], 'visibilita_target_id' => $data['target_id'], 'visibilita_target_type' => $targetType, ]); return back()->with('success', count($ids) . ' documenti associati.'); } }