446 lines
13 KiB
PHP
446 lines
13 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\SuperAdmin;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Log;
|
|
use ZipArchive;
|
|
use Carbon\Carbon;
|
|
|
|
class ArchiviSistemaController extends Controller
|
|
{
|
|
/**
|
|
* Mostra la dashboard di gestione archivi di sistema
|
|
*/
|
|
public function index()
|
|
{
|
|
// Statistiche archivi
|
|
$stats = [
|
|
'comuni_count' => DB::table('comuni_italiani')->count(),
|
|
'last_import' => DB::table('import_logs')
|
|
->where('tipo', 'comuni_italiani')
|
|
->latest()
|
|
->value('created_at'),
|
|
'storage_size' => $this->getArchiveStorageSize(),
|
|
'available_archives' => $this->getAvailableArchives()
|
|
];
|
|
|
|
return view('superadmin.archivi.index', compact('stats'));
|
|
}
|
|
|
|
/**
|
|
* Gestione archivio comuni italiani
|
|
*/
|
|
public function comuniItaliani(Request $request)
|
|
{
|
|
$query = DB::table('comuni_italiani');
|
|
|
|
// Filtri di ricerca
|
|
if ($request->filled('search_nome')) {
|
|
$query->where('denominazione', 'like', '%' . $request->search_nome . '%');
|
|
}
|
|
|
|
if ($request->filled('search_provincia')) {
|
|
$query->where('provincia_codice', 'like', '%' . $request->search_provincia . '%');
|
|
}
|
|
|
|
if ($request->filled('search_regione')) {
|
|
$query->where('regione_denominazione', 'like', '%' . $request->search_regione . '%');
|
|
}
|
|
|
|
if ($request->filled('search_cap')) {
|
|
$query->where('cap', 'like', '%' . $request->search_cap . '%');
|
|
}
|
|
|
|
// Export CSV
|
|
if ($request->get('export') === 'csv') {
|
|
return $this->exportComuniCSV($query);
|
|
}
|
|
|
|
$comuni = $query->orderBy('denominazione')->paginate(50);
|
|
|
|
return view('superadmin.archivi.comuni', compact('comuni'));
|
|
}
|
|
|
|
/**
|
|
* Export comuni in formato CSV
|
|
*/
|
|
private function exportComuniCSV($query)
|
|
{
|
|
$comuni = $query->get();
|
|
|
|
$filename = 'comuni_italiani_' . date('Y-m-d_H-i') . '.csv';
|
|
|
|
$headers = [
|
|
'Content-Type' => 'text/csv',
|
|
'Content-Disposition' => "attachment; filename=\"{$filename}\"",
|
|
];
|
|
|
|
$callback = function() use ($comuni) {
|
|
$file = fopen('php://output', 'w');
|
|
|
|
// Header CSV
|
|
fputcsv($file, [
|
|
'Codice ISTAT',
|
|
'Denominazione',
|
|
'Denominazione Straniera',
|
|
'Codice Catastale',
|
|
'CAP',
|
|
'Provincia Codice',
|
|
'Provincia Denominazione',
|
|
'Regione Codice',
|
|
'Regione Denominazione'
|
|
], ';');
|
|
|
|
// Dati
|
|
foreach ($comuni as $comune) {
|
|
fputcsv($file, [
|
|
$comune->codice_istat,
|
|
$comune->denominazione,
|
|
$comune->denominazione_straniera,
|
|
$comune->codice_catastale,
|
|
$comune->cap,
|
|
$comune->provincia_codice,
|
|
$comune->provincia_denominazione,
|
|
$comune->regione_codice,
|
|
$comune->regione_denominazione
|
|
], ';');
|
|
}
|
|
|
|
fclose($file);
|
|
};
|
|
|
|
return response()->stream($callback, 200, $headers);
|
|
}
|
|
|
|
/**
|
|
* Import ZIP con dati JSON
|
|
*/
|
|
public function importZip(Request $request)
|
|
{
|
|
$request->validate([
|
|
'zip_file' => 'required|file|mimes:zip|max:51200', // 50MB max
|
|
'tipo_archivio' => 'required|string|in:comuni_italiani,province,regioni'
|
|
]);
|
|
|
|
try {
|
|
$zipFile = $request->file('zip_file');
|
|
$tipoArchivio = $request->input('tipo_archivio');
|
|
|
|
// Salva il file ZIP temporaneamente
|
|
$zipPath = $zipFile->storeAs('temp', 'import_' . time() . '.zip');
|
|
$fullZipPath = storage_path('app/' . $zipPath);
|
|
|
|
// Estrai e processa il ZIP
|
|
$result = $this->processZipImport($fullZipPath, $tipoArchivio);
|
|
|
|
// Cancella il file ZIP dopo l'importazione
|
|
Storage::delete($zipPath);
|
|
|
|
// Log dell'operazione
|
|
DB::table('import_logs')->insert([
|
|
'tipo' => $tipoArchivio,
|
|
'file_originale' => $zipFile->getClientOriginalName(),
|
|
'records_importati' => $result['imported'],
|
|
'errori' => $result['errors'],
|
|
'user_id' => auth()->id(),
|
|
'created_at' => Carbon::now(),
|
|
'updated_at' => Carbon::now()
|
|
]);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => "Importazione completata. {$result['imported']} record importati.",
|
|
'data' => $result
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
Log::error('Errore import ZIP: ' . $e->getMessage());
|
|
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Errore durante l\'importazione: ' . $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Processa il file ZIP e importa i dati
|
|
*/
|
|
private function processZipImport($zipPath, $tipo)
|
|
{
|
|
$zip = new ZipArchive;
|
|
$imported = 0;
|
|
$errors = [];
|
|
|
|
if ($zip->open($zipPath) === TRUE) {
|
|
// Estrai in una cartella temporanea
|
|
$extractPath = storage_path('app/temp/extract_' . time());
|
|
$zip->extractTo($extractPath);
|
|
$zip->close();
|
|
|
|
// Cerca file JSON nella cartella estratta
|
|
$jsonFiles = glob($extractPath . '/*.json');
|
|
|
|
foreach ($jsonFiles as $jsonFile) {
|
|
$jsonData = json_decode(file_get_contents($jsonFile), true);
|
|
|
|
if ($jsonData) {
|
|
$result = $this->importJsonData($jsonData, $tipo);
|
|
$imported += $result['imported'];
|
|
$errors = array_merge($errors, $result['errors']);
|
|
}
|
|
}
|
|
|
|
// Pulisci la cartella estratta
|
|
$this->deleteDirectory($extractPath);
|
|
} else {
|
|
throw new \Exception('Impossibile aprire il file ZIP');
|
|
}
|
|
|
|
return [
|
|
'imported' => $imported,
|
|
'errors' => $errors
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Importa i dati JSON nel database
|
|
*/
|
|
private function importJsonData($data, $tipo)
|
|
{
|
|
$imported = 0;
|
|
$errors = [];
|
|
|
|
DB::beginTransaction();
|
|
|
|
try {
|
|
switch ($tipo) {
|
|
case 'comuni_italiani':
|
|
$imported = $this->importComuniItaliani($data);
|
|
break;
|
|
|
|
case 'province':
|
|
$imported = $this->importProvince($data);
|
|
break;
|
|
|
|
case 'regioni':
|
|
$imported = $this->importRegioni($data);
|
|
break;
|
|
|
|
default:
|
|
throw new \Exception("Tipo archivio non supportato: {$tipo}");
|
|
}
|
|
|
|
DB::commit();
|
|
|
|
} catch (\Exception $e) {
|
|
DB::rollBack();
|
|
$errors[] = $e->getMessage();
|
|
}
|
|
|
|
return [
|
|
'imported' => $imported,
|
|
'errors' => $errors
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Importa i comuni italiani
|
|
*/
|
|
private function importComuniItaliani($data)
|
|
{
|
|
// Se necessario, svuota la tabella esistente
|
|
DB::table('comuni_italiani')->truncate();
|
|
|
|
$imported = 0;
|
|
$chunk = [];
|
|
|
|
foreach ($data as $record) {
|
|
$chunk[] = [
|
|
'codice_istat' => $record['codice_istat'] ?? null,
|
|
'denominazione' => $record['denominazione'] ?? null,
|
|
'denominazione_straniera' => $record['denominazione_straniera'] ?? null,
|
|
'codice_catastale' => $record['codice_catastale'] ?? null,
|
|
'cap' => $record['cap'] ?? null,
|
|
'provincia_codice' => $record['provincia_codice'] ?? null,
|
|
'provincia_denominazione' => $record['provincia_denominazione'] ?? null,
|
|
'regione_codice' => $record['regione_codice'] ?? null,
|
|
'regione_denominazione' => $record['regione_denominazione'] ?? null,
|
|
'created_at' => Carbon::now(),
|
|
'updated_at' => Carbon::now()
|
|
];
|
|
|
|
// Inserisci a blocchi di 500 record
|
|
if (count($chunk) >= 500) {
|
|
DB::table('comuni_italiani')->insert($chunk);
|
|
$imported += count($chunk);
|
|
$chunk = [];
|
|
}
|
|
}
|
|
|
|
// Inserisci il resto
|
|
if (!empty($chunk)) {
|
|
DB::table('comuni_italiani')->insert($chunk);
|
|
$imported += count($chunk);
|
|
}
|
|
|
|
return $imported;
|
|
}
|
|
|
|
/**
|
|
* Importa le province
|
|
*/
|
|
private function importProvince($data)
|
|
{
|
|
DB::table('province')->truncate();
|
|
|
|
$imported = 0;
|
|
foreach ($data as $record) {
|
|
DB::table('province')->insert([
|
|
'codice' => $record['codice'] ?? null,
|
|
'denominazione' => $record['denominazione'] ?? null,
|
|
'sigla' => $record['sigla'] ?? null,
|
|
'regione_codice' => $record['regione_codice'] ?? null,
|
|
'created_at' => Carbon::now(),
|
|
'updated_at' => Carbon::now()
|
|
]);
|
|
$imported++;
|
|
}
|
|
|
|
return $imported;
|
|
}
|
|
|
|
/**
|
|
* Importa le regioni
|
|
*/
|
|
private function importRegioni($data)
|
|
{
|
|
DB::table('regioni')->truncate();
|
|
|
|
$imported = 0;
|
|
foreach ($data as $record) {
|
|
DB::table('regioni')->insert([
|
|
'codice' => $record['codice'] ?? null,
|
|
'denominazione' => $record['denominazione'] ?? null,
|
|
'created_at' => Carbon::now(),
|
|
'updated_at' => Carbon::now()
|
|
]);
|
|
$imported++;
|
|
}
|
|
|
|
return $imported;
|
|
}
|
|
|
|
/**
|
|
* Calcola la dimensione dello storage archivi
|
|
*/
|
|
private function getArchiveStorageSize()
|
|
{
|
|
$size = 0;
|
|
$directories = ['archives', 'temp'];
|
|
|
|
foreach ($directories as $dir) {
|
|
$path = storage_path("app/{$dir}");
|
|
if (is_dir($path)) {
|
|
$size += $this->getDirectorySize($path);
|
|
}
|
|
}
|
|
|
|
return $this->formatBytes($size);
|
|
}
|
|
|
|
/**
|
|
* Ottiene gli archivi disponibili
|
|
*/
|
|
private function getAvailableArchives()
|
|
{
|
|
return [
|
|
'comuni_italiani' => [
|
|
'nome' => 'Comuni Italiani',
|
|
'descrizione' => 'Archivio completo dei comuni italiani con codici ISTAT',
|
|
'ultima_sincronizzazione' => DB::table('import_logs')
|
|
->where('tipo', 'comuni_italiani')
|
|
->latest()
|
|
->value('created_at')
|
|
],
|
|
'province' => [
|
|
'nome' => 'Province Italiane',
|
|
'descrizione' => 'Elenco delle province italiane',
|
|
'ultima_sincronizzazione' => null
|
|
],
|
|
'regioni' => [
|
|
'nome' => 'Regioni Italiane',
|
|
'descrizione' => 'Elenco delle regioni italiane',
|
|
'ultima_sincronizzazione' => null
|
|
]
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Cancella ricorsivamente una directory
|
|
*/
|
|
private function deleteDirectory($dir)
|
|
{
|
|
if (!is_dir($dir)) return;
|
|
|
|
$files = array_diff(scandir($dir), ['.', '..']);
|
|
|
|
foreach ($files as $file) {
|
|
$path = $dir . DIRECTORY_SEPARATOR . $file;
|
|
is_dir($path) ? $this->deleteDirectory($path) : unlink($path);
|
|
}
|
|
|
|
rmdir($dir);
|
|
}
|
|
|
|
/**
|
|
* Calcola la dimensione di una directory
|
|
*/
|
|
private function getDirectorySize($path)
|
|
{
|
|
$size = 0;
|
|
|
|
if (is_dir($path)) {
|
|
$iterator = new \RecursiveIteratorIterator(
|
|
new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS)
|
|
);
|
|
|
|
foreach ($iterator as $file) {
|
|
$size += $file->getSize();
|
|
}
|
|
}
|
|
|
|
return $size;
|
|
}
|
|
|
|
/**
|
|
* Formatta i byte in formato leggibile
|
|
*/
|
|
private function formatBytes($size, $precision = 2)
|
|
{
|
|
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
|
|
for ($i = 0; $size > 1024 && $i < count($units) - 1; $i++) {
|
|
$size /= 1024;
|
|
}
|
|
|
|
return round($size, $precision) . ' ' . $units[$i];
|
|
}
|
|
|
|
/**
|
|
* Sincronizzazione futura con ISTAT
|
|
*/
|
|
public function sincronizzaIstat()
|
|
{
|
|
// Placeholder per sincronizzazione automatica con ISTAT
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Sincronizzazione automatica con ISTAT in sviluppo'
|
|
]);
|
|
}
|
|
}
|