199 lines
6.8 KiB
PHP
199 lines
6.8 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Piantine;
|
|
|
|
use App\Models\Territorio;
|
|
use App\Models\TerritorioMappa;
|
|
use App\Models\TerritorioPdfVersione;
|
|
use App\Services\TerritorioThumbnailService;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use RuntimeException;
|
|
use setasign\Fpdi\Fpdi;
|
|
|
|
/**
|
|
* Compone il PDF del territorio sul modulo ufficiale S-12 e lo sostituisce
|
|
* nel gestionale conservando la versione precedente.
|
|
*
|
|
* Pagina 1: il modulo S-12 originale (resources/pdf/S-12_I.pdf) importato
|
|
* com'è, con Località, numero e piantina sovrapposti negli spazi previsti.
|
|
* Pagina 2: i confini scritti (campo `confini` del territorio).
|
|
*/
|
|
class PiantinaPdfService
|
|
{
|
|
public function __construct(
|
|
private PiantineArea $area,
|
|
private TerritorioThumbnailService $thumbnails,
|
|
) {
|
|
}
|
|
|
|
/** Il PDF completo, come stringa binaria. */
|
|
public function genera(Territorio $territorio, TerritorioMappa $mappa): string
|
|
{
|
|
if (! $mappa->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;
|
|
}
|
|
}
|