image_path || ! Storage::disk('public')->exists($mappa->image_path)) { throw new RuntimeException('Prima di generare il PDF va generata l\'immagine della piantina.'); } $immagine = Storage::disk('public')->path($mappa->image_path); $dimensioni = getimagesize($immagine); if ($dimensioni === false) { throw new RuntimeException('L\'immagine della piantina non è leggibile: rigenerala.'); } [$imgPxW, $imgPxH] = $dimensioni; $pdf = new Fpdi(); $pdf->setSourceFile(resource_path('pdf/S-12_I.pdf')); $template = $pdf->importPage(1); $misure = $pdf->getTemplateSize($template); $w = $misure['width']; $h = $misure['height']; $pdf->AddPage($misure['orientation'], [$w, $h]); $pdf->useTemplate($template); // Intestazione: i valori si appoggiano sulle righe punteggiate del // modulo. Posizioni in proporzione alla pagina, tarate sull'S-12. $pdf->SetFont('Helvetica', 'B', 10); $pdf->SetTextColor(0, 0, 0); // Tarato sull'S-12 reale: i valori si appoggiano alle righe // punteggiate senza coprire le etichette "Località" e "Terr. N.". $headerY = $h * 0.112; $pdf->SetXY($w * 0.155, $headerY); $pdf->Cell($w * 0.48, 5, $this->latin($this->area->localita()), 0, 0, 'L'); $pdf->SetXY($w * 0.875, $headerY); $pdf->Cell($w * 0.10, 5, $this->latin($territorio->numero), 0, 0, 'C'); // Piantina nello spazio centrale, adattata mantenendo le proporzioni: // sotto l'intestazione, sopra la dicitura "(Incollate qui sopra...)". $boxX = $w * 0.045; $boxY = $h * 0.175; $boxW = $w * 0.91; $boxH = $h * 0.565; $scala = min($boxW / $imgPxW, $boxH / $imgPxH); $imgW = $imgPxW * $scala; $imgH = $imgPxH * $scala; $pdf->Image( $immagine, $boxX + ($boxW - $imgW) / 2, $boxY + ($boxH - $imgH) / 2, $imgW, $imgH, 'PNG' ); // Pagina 2: i confini scritti. $pdf->AddPage($misure['orientation'], [$w, $h]); $pdf->SetFont('Helvetica', 'B', 13); $pdf->SetXY($w * 0.045, $h * 0.06); $pdf->Cell($w * 0.91, 7, $this->latin('Confini del territorio N. ' . $territorio->numero), 0, 2, 'C'); $pdf->SetFont('Helvetica', '', 11); $pdf->SetXY($w * 0.045, $h * 0.16); $confini = trim((string) $territorio->confini); $pdf->MultiCell( $w * 0.91, 6, $this->latin($confini !== '' ? $confini : 'Confini non ancora descritti.') ); return $pdf->Output('S'); } /** * Genera il PDF e lo rende quello ufficiale del territorio, archiviando * l'eventuale PDF precedente nello storico versioni. */ public function sostituisci(Territorio $territorio, TerritorioMappa $mappa, string $origine = 'piantine'): void { $binario = $this->genera($territorio, $mappa); $disk = Storage::disk('public'); $this->archiviaCorrente($territorio, $origine); $nuovoPath = 'territori-pdf/piantina-' . $territorio->id . '-' . now()->format('Ymd-His') . '.pdf'; $disk->put($nuovoPath, $binario); $territorio->update([ 'pdf_path' => $nuovoPath, 'thumbnail_path' => $this->thumbnails->generate($nuovoPath), ]); activity() ->causedBy(auth()->user()) ->performedOn($territorio) ->log('piantina_pdf_sostituito'); } /** * Rimette in vigore una versione archiviata; il PDF attuale finisce a sua * volta nello storico, quindi il ripristino è sempre reversibile. */ public function ripristina(TerritorioPdfVersione $versione): void { $disk = Storage::disk('public'); $territorio = $versione->territorio; if (! $territorio) { throw new RuntimeException('La versione non appartiene più a nessun territorio.'); } if (! $disk->exists($versione->pdf_path)) { throw new RuntimeException('Il file di questa versione non esiste più sul disco.'); } $this->archiviaCorrente($territorio, 'ripristino'); $nuovoPath = 'territori-pdf/ripristino-' . $territorio->id . '-' . now()->format('Ymd-His') . '.pdf'; $disk->move($versione->pdf_path, $nuovoPath); $territorio->update([ 'pdf_path' => $nuovoPath, 'thumbnail_path' => $this->thumbnails->generate($nuovoPath), ]); $versione->delete(); activity() ->causedBy(auth()->user()) ->performedOn($territorio) ->log('piantina_pdf_ripristinato'); } /** * Sposta il PDF attuale del territorio (se esiste) nello storico. */ private function archiviaCorrente(Territorio $territorio, string $origine): void { $disk = Storage::disk('public'); if (! $territorio->pdf_path || ! $disk->exists($territorio->pdf_path)) { return; } $versionePath = 'territori-pdf-versioni/territorio-' . $territorio->id . '-' . now()->format('Ymd-His') . '-' . substr(uniqid(), -5) . '.pdf'; $disk->makeDirectory('territori-pdf-versioni'); $disk->move($territorio->pdf_path, $versionePath); TerritorioPdfVersione::create([ 'territorio_id' => $territorio->id, 'pdf_path' => $versionePath, 'thumbnail_path' => $territorio->thumbnail_path, 'origine' => $origine, 'sostituito_il' => now(), ]); } /** FPDF ragiona in windows-1252: gli accenti UTF-8 vanno convertiti. */ private function latin(string $testo): string { $convertito = @iconv('UTF-8', 'windows-1252//TRANSLIT', $testo); return $convertito !== false ? $convertito : $testo; } }