validate([ 'sqlDump' => ['required', 'file', 'max:256000'], ]); $file = $request->file('sqlDump'); $ext = strtolower($file->getClientOriginalExtension()); if (! in_array($ext, ['sql', 'txt'])) { return back()->withErrors(['sqlDump' => 'Il file deve essere .sql o .txt']); } $content = file_get_contents($file->getRealPath()); if (! $content) { return back()->withErrors(['sqlDump' => 'File vuoto o non leggibile.']); } $exchange = app(XmlExchange::class); $dataset = $exchange->legacySqlToDatasetPublic($content); $xml = $exchange->datasetToXmlPublic($dataset, 'legacy-sql-conversion'); return response()->streamDownload(function () use ($xml) { echo $xml; }, 'termanager-conversion.xml', ['Content-Type' => 'application/xml; charset=UTF-8']); } public function importXml(Request $request) { $request->validate([ 'xmlImport' => ['required', 'file', 'max:256000'], ]); $file = $request->file('xmlImport'); $ext = strtolower($file->getClientOriginalExtension()); if (! in_array($ext, ['xml', 'txt'])) { return back()->withErrors(['xmlImport' => 'Il file deve essere .xml o .txt']); } $content = file_get_contents($file->getRealPath()); if (! $content) { return back()->withErrors(['xmlImport' => 'File vuoto o non leggibile.']); } // L'import svuota e riscrive le tabelle: non puo' girare insieme a un // ripristino (che fa lo stesso), a un azzeramento, a un backup che le sta // fotografando o a un import PDF che sta aggiornando i territori. Il // ripristino chiama importXmlFromContent() per conto suo, gia' dentro il // proprio posto: per questo il blocco sta qui, sulla porta d'ingresso, e // non dentro l'import. $stato = app(BackupOperationState::class); $operationId = (string) Str::uuid(); $inCorso = $stato->occupa($operationId, BackupOperationState::TIPO_IMPORT_XML, 'Import XML', self::TTL_POSTO_IMPORT_XML); if ($inCorso !== null) { return back()->withErrors(['xmlImport' => $stato->messaggioOccupato($inCorso) . ' Nessun dato è stato modificato.']); } $stato->markRunning($operationId); try { $exchange = new XmlExchange(); $fileDiPrima = XmlExchange::fileDeiTerritori(); $result = $exchange->importXmlFromContent($content); if (! isset($result['error'])) { $result['stats']['file_rimossi'] = XmlExchange::eliminaFileNonPiuUsati($fileDiPrima); } } catch (\Throwable $e) { $stato->markFailed($operationId, $e->getMessage()); throw $e; } if (isset($result['error'])) { $stato->markFailed($operationId, $result['error']); return back()->withErrors(['xmlImport' => $result['error']]); } $stato->markCompleted($operationId); $stats = $result['stats']; $issues = $result['issues']; $message = 'Import XML completato con successo.'; if (($stats['duplicate_territori'] ?? 0) > 0 || ($stats['assegnazioni_saltate'] ?? 0) > 0) { $message .= ' Territori duplicati saltati: ' . $stats['duplicate_territori'] . '. Assegnazioni saltate: ' . $stats['assegnazioni_saltate'] . '.'; } if (($stats['file_rimossi'] ?? 0) > 0) { $message .= ' Eliminati ' . $stats['file_rimossi'] . ' file (PDF e miniature) dei territori sostituiti, che i dati importati non usano più.'; } return redirect()->route('xml.exchange') ->with('success', $message) ->with('importStats', $stats) ->with('importIssues', $issues); } }