dbManager = $dbManager; $this->tenantArchivePath = $tenantArchivePath; } /** * Prepara migrazione completa amministratore */ public function prepareAmministratoreMigration(Amministratore $amministratore): array { try { $migrationId = "migration_admin_{$amministratore->codice_univoco}_" . date('Y-m-d_H-i-s'); $migrationPath = storage_path("app/migrations/{$migrationId}"); if (! is_dir($migrationPath)) { mkdir($migrationPath, 0755, true); } $results = [ 'migration_id' => $migrationId, 'amministratore' => $amministratore->codice_univoco, 'created_at' => date('Y-m-d H:i:s'), 'components' => [], ]; // 1. Backup database amministratore $adminDbBackup = $this->dbManager->backupAmministratoreDatabase($amministratore); if (! $adminDbBackup['success']) { throw new Exception('Errore backup database amministratore: ' . $adminDbBackup['error']); } $results['components']['admin_database'] = $adminDbBackup; // 2. Backup database per ogni stabile $stabiliBackups = []; foreach ($amministratore->stabili as $stabile) { if ($stabile->database_dedicato) { $stabileBackup = $this->dbManager->backupStabileDatabase($stabile); if ($stabileBackup['success']) { $stabiliBackups[$stabile->codice_stabile] = $stabileBackup; } } } $results['components']['stabili_databases'] = $stabiliBackups; // 3. Archivio file sistema $archiveResult = $this->createFileSystemArchive($amministratore, $migrationPath); $results['components']['filesystem_archive'] = $archiveResult; // 4. Metadata e configurazioni $metadataResult = $this->createMigrationMetadata($amministratore, $migrationPath); $results['components']['metadata'] = $metadataResult; // 5. Script di ricostruzione $scriptsResult = $this->createMigrationScripts($amministratore, $migrationPath); $results['components']['scripts'] = $scriptsResult; // 6. Verifica integritΓ  $verificationResult = $this->verifyMigrationIntegrity($migrationPath); $results['components']['verification'] = $verificationResult; // 7. Crea package finale $packageResult = $this->createMigrationPackage($migrationId, $migrationPath); $results['package'] = $packageResult; return [ 'success' => true, 'migration' => $results, ]; } catch (Exception $e) { return [ 'success' => false, 'error' => $e->getMessage(), ]; } } /** * Prepara migrazione singolo stabile */ public function prepareStabileMigration(Stabile $stabile): array { try { $migrationId = "migration_stabile_{$stabile->codice_stabile}_" . date('Y-m-d_H-i-s'); $migrationPath = storage_path("app/migrations/{$migrationId}"); if (! is_dir($migrationPath)) { mkdir($migrationPath, 0755, true); } $results = [ 'migration_id' => $migrationId, 'stabile' => $stabile->codice_stabile, 'amministratore' => $stabile->amministratore->codice_univoco, 'created_at' => date('Y-m-d H:i:s'), 'components' => [], ]; // 1. Backup database stabile if ($stabile->database_dedicato) { $stabileDbBackup = $this->dbManager->backupStabileDatabase($stabile); if (! $stabileDbBackup['success']) { throw new Exception('Errore backup database stabile: ' . $stabileDbBackup['error']); } $results['components']['stabile_database'] = $stabileDbBackup; } // 2. Archivio file stabile $archiveResult = $this->createStabileFileArchive($stabile, $migrationPath); $results['components']['filesystem_archive'] = $archiveResult; // 3. Metadata stabile $metadataResult = $this->createStabileMetadata($stabile, $migrationPath); $results['components']['metadata'] = $metadataResult; // 4. Package finale $packageResult = $this->createMigrationPackage($migrationId, $migrationPath); $results['package'] = $packageResult; return [ 'success' => true, 'migration' => $results, ]; } catch (Exception $e) { return [ 'success' => false, 'error' => $e->getMessage(), ]; } } /** * Crea archivio completo file system amministratore */ private function createFileSystemArchive(Amministratore $amministratore, string $migrationPath): array { try { $sourcePath = $this->tenantArchivePath->amministratoreAbsolutePath($amministratore); $archiveName = "filesystem_admin_{$amministratore->codice_univoco}.zip"; $archivePath = $migrationPath . '/' . $archiveName; if (! is_dir($sourcePath)) { throw new Exception("Cartella amministratore non trovata: {$sourcePath}"); } $zip = new ZipArchive(); if ($zip->open($archivePath, ZipArchive::CREATE) !== true) { throw new Exception('Impossibile creare archivio filesystem'); } $iterator = new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator($sourcePath, \RecursiveDirectoryIterator::SKIP_DOTS) ); foreach ($iterator as $file) { if ($file->isFile()) { $relativePath = str_replace($sourcePath . DIRECTORY_SEPARATOR, '', $file->getPathname()); $zip->addFile($file->getPathname(), $relativePath); } } $zip->close(); return [ 'success' => true, 'archive_name' => $archiveName, 'archive_path' => $archivePath, 'archive_size' => filesize($archivePath), 'files_count' => $zip->numFiles ?? 0, ]; } catch (Exception $e) { return [ 'success' => false, 'error' => $e->getMessage(), ]; } } /** * Crea archivio file singolo stabile */ private function createStabileFileArchive(Stabile $stabile, string $migrationPath): array { try { $sourcePath = $this->tenantArchivePath->stabileAbsolutePath($stabile); $archiveName = "filesystem_stabile_{$stabile->codice_stabile}.zip"; $archivePath = $migrationPath . '/' . $archiveName; if (! is_dir($sourcePath)) { // Crea struttura base se non esiste $this->createStabileFolderStructure($stabile); } $zip = new ZipArchive(); if ($zip->open($archivePath, ZipArchive::CREATE) !== true) { throw new Exception('Impossibile creare archivio filesystem stabile'); } $iterator = new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator($sourcePath, \RecursiveDirectoryIterator::SKIP_DOTS) ); foreach ($iterator as $file) { if ($file->isFile()) { $relativePath = str_replace($sourcePath . DIRECTORY_SEPARATOR, '', $file->getPathname()); $zip->addFile($file->getPathname(), $relativePath); } } $zip->close(); return [ 'success' => true, 'archive_name' => $archiveName, 'archive_path' => $archivePath, 'archive_size' => filesize($archivePath), 'files_count' => $zip->numFiles ?? 0, ]; } catch (Exception $e) { return [ 'success' => false, 'error' => $e->getMessage(), ]; } } /** * Crea metadata completi per migrazione */ private function createMigrationMetadata(Amministratore $amministratore, string $migrationPath): array { try { $metadata = [ 'migration' => [ 'type' => 'amministratore_completo', 'version' => '1.0.0', 'created_at' => date('Y-m-d H:i:s'), 'source_server' => env('APP_URL'), 'netgescon_version' => '2.1.0', ], 'amministratore' => [ 'id' => $amministratore->id, 'codice_univoco' => $amministratore->codice_univoco, 'nome' => $amministratore->nome, 'cognome' => $amministratore->cognome, 'denominazione_studio' => $amministratore->denominazione_studio, 'partita_iva' => $amministratore->partita_iva, 'codice_fiscale_studio' => $amministratore->codice_fiscale_studio, 'email_studio' => $amministratore->email_studio, 'database_principale' => $amministratore->getDatabaseName(), 'created_at' => $amministratore->created_at->toISOString(), ], 'stabili' => [], 'databases' => [ 'principale' => $amministratore->getDatabaseName(), 'stabili' => [], ], 'requirements' => [ 'php_version' => PHP_VERSION, 'laravel_version' => app()->version(), 'mysql_version' => DB::select('SELECT VERSION() as version')[0]->version, 'required_extensions' => [ 'zip', 'pdo_mysql', 'openssl', 'fileinfo', 'mbstring', ], 'min_disk_space_mb' => $this->calculateRequiredSpace($amministratore), ], 'structure' => [ 'folders' => $this->analyzeFolderStructure($amministratore), 'databases' => $this->analyzeDatabaseStructure($amministratore), ], ]; // Aggiungi info per ogni stabile foreach ($amministratore->stabili as $stabile) { $stabileInfo = [ 'id' => $stabile->id, 'codice_stabile' => $stabile->codice_stabile, 'denominazione' => $stabile->denominazione, 'indirizzo' => $stabile->indirizzo . ', ' . $stabile->citta, 'database_dedicato' => $stabile->database_dedicato, 'created_at' => $stabile->created_at->toISOString(), ]; $metadata['stabili'][] = $stabileInfo; if ($stabile->database_dedicato) { $metadata['databases']['stabili'][] = $stabile->database_dedicato; } } $metadataPath = $migrationPath . '/metadata.json'; file_put_contents($metadataPath, json_encode($metadata, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); return [ 'success' => true, 'metadata_file' => $metadataPath, 'stabili_count' => count($metadata['stabili']), 'databases_count' => count($metadata['databases']['stabili']) + 1, ]; } catch (Exception $e) { return [ 'success' => false, 'error' => $e->getMessage(), ]; } } /** * Crea metadata per singolo stabile */ private function createStabileMetadata(Stabile $stabile, string $migrationPath): array { try { $metadata = [ 'migration' => [ 'type' => 'stabile_singolo', 'version' => '1.0.0', 'created_at' => date('Y-m-d H:i:s'), 'source_server' => env('APP_URL'), ], 'stabile' => [ 'id' => $stabile->id, 'codice_stabile' => $stabile->codice_stabile, 'denominazione' => $stabile->denominazione, 'indirizzo' => $stabile->indirizzo, 'cap' => $stabile->cap, 'citta' => $stabile->citta, 'provincia' => $stabile->provincia, 'database_dedicato' => $stabile->database_dedicato, 'created_at' => $stabile->created_at->toISOString(), ], 'amministratore_origine' => [ 'codice_univoco' => $stabile->amministratore->codice_univoco, 'nome_completo' => $stabile->amministratore->nome_completo, 'denominazione_studio' => $stabile->amministratore->denominazione_studio, ], 'requirements' => [ 'target_admin_code' => 'required', 'php_version' => PHP_VERSION, 'mysql_version' => DB::select('SELECT VERSION() as version')[0]->version, ], ]; $metadataPath = $migrationPath . '/stabile_metadata.json'; file_put_contents($metadataPath, json_encode($metadata, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); return [ 'success' => true, 'metadata_file' => $metadataPath, ]; } catch (Exception $e) { return [ 'success' => false, 'error' => $e->getMessage(), ]; } } /** * Crea script di ricostruzione ambiente */ private function createMigrationScripts(Amministratore $amministratore, string $migrationPath): array { try { $scriptsPath = $migrationPath . '/scripts'; if (! is_dir($scriptsPath)) { mkdir($scriptsPath, 0755, true); } // 1. Script restore database $restoreDbScript = $this->createDatabaseRestoreScript($amministratore); file_put_contents($scriptsPath . '/restore_databases.sh', $restoreDbScript); // 2. Script restore filesystem $restoreFsScript = $this->createFilesystemRestoreScript($amministratore); file_put_contents($scriptsPath . '/restore_filesystem.sh', $restoreFsScript); // 3. Script verifica post-migrazione $verifyScript = $this->createVerificationScript($amministratore); file_put_contents($scriptsPath . '/verify_migration.sh', $verifyScript); // 4. Script PHP per ricostruzione record $phpScript = $this->createPhpRestoreScript($amministratore); file_put_contents($scriptsPath . '/restore_records.php', $phpScript); // 5. README istruzioni $readme = $this->createMigrationReadme($amministratore); file_put_contents($scriptsPath . '/README.md', $readme); // Rendi script eseguibili chmod($scriptsPath . '/restore_databases.sh', 0755); chmod($scriptsPath . '/restore_filesystem.sh', 0755); chmod($scriptsPath . '/verify_migration.sh', 0755); return [ 'success' => true, 'scripts_path' => $scriptsPath, 'scripts_created' => 5, ]; } catch (Exception $e) { return [ 'success' => false, 'error' => $e->getMessage(), ]; } } /** * Crea script restore database */ private function createDatabaseRestoreScript(Amministratore $amministratore): string { $script = "#!/bin/bash\n\n"; $script .= "# Script restore database per amministratore {$amministratore->codice_univoco}\n"; $script .= "# Generato automaticamente da NetGescon\n\n"; $script .= "set -e\n\n"; $script .= "# Configurazione\n"; $script .= "ADMIN_CODE=\"{$amministratore->codice_univoco}\"\n"; $script .= "ADMIN_DB=\"netgescon_admin_{$amministratore->codice_univoco}\"\n"; $script .= "MYSQL_USER=\"\${MYSQL_USER:-root}\"\n"; $script .= "MYSQL_PASS=\"\${MYSQL_PASS}\"\n"; $script .= "MYSQL_HOST=\"\${MYSQL_HOST:-localhost}\"\n\n"; $script .= "echo \"πŸš€ Inizio restore database amministratore \$ADMIN_CODE\"\n\n"; $script .= "# Crea database amministratore\n"; $script .= "echo \"πŸ“¦ Creazione database \$ADMIN_DB\"\n"; $script .= "mysql -h\$MYSQL_HOST -u\$MYSQL_USER -p\$MYSQL_PASS -e \"CREATE DATABASE IF NOT EXISTS \\\`\$ADMIN_DB\\\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci\"\n\n"; $script .= "# Restore database amministratore\n"; $script .= "if [ -f \"../database_backups/backup_admin_\${ADMIN_CODE}_*.sql\" ]; then\n"; $script .= " ADMIN_BACKUP=\$(ls ../database_backups/backup_admin_\${ADMIN_CODE}_*.sql | head -1)\n"; $script .= " echo \"πŸ“₯ Restore database amministratore da \$ADMIN_BACKUP\"\n"; $script .= " mysql -h\$MYSQL_HOST -u\$MYSQL_USER -p\$MYSQL_PASS \$ADMIN_DB < \$ADMIN_BACKUP\n"; $script .= " echo \"βœ… Database amministratore ripristinato\"\n"; $script .= "else\n"; $script .= " echo \"❌ Backup database amministratore non trovato\"\n"; $script .= " exit 1\n"; $script .= "fi\n\n"; // Aggiungi restore per ogni stabile foreach ($amministratore->stabili as $stabile) { if ($stabile->database_dedicato) { $script .= "# Restore database stabile {$stabile->codice_stabile}\n"; $script .= "STABILE_DB=\"{$stabile->database_dedicato}\"\n"; $script .= "echo \"πŸ“¦ Creazione database stabile \$STABILE_DB\"\n"; $script .= "mysql -h\$MYSQL_HOST -u\$MYSQL_USER -p\$MYSQL_PASS -e \"CREATE DATABASE IF NOT EXISTS \\\`\$STABILE_DB\\\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci\"\n"; $script .= "if [ -f \"../database_backups/backup_stabile_{$stabile->codice_stabile}_*.sql\" ]; then\n"; $script .= " STABILE_BACKUP=\$(ls ../database_backups/backup_stabile_{$stabile->codice_stabile}_*.sql | head -1)\n"; $script .= " echo \"πŸ“₯ Restore database stabile da \$STABILE_BACKUP\"\n"; $script .= " mysql -h\$MYSQL_HOST -u\$MYSQL_USER -p\$MYSQL_PASS \$STABILE_DB < \$STABILE_BACKUP\n"; $script .= " echo \"βœ… Database stabile {$stabile->codice_stabile} ripristinato\"\n"; $script .= "else\n"; $script .= " echo \"⚠️ Backup database stabile {$stabile->codice_stabile} non trovato\"\n"; $script .= "fi\n\n"; } } $script .= "echo \"πŸŽ‰ Restore database completato!\"\n"; return $script; } /** * Crea script restore filesystem */ private function createFilesystemRestoreScript(Amministratore $amministratore): string { $script = "#!/bin/bash\n\n"; $script .= "# Script restore filesystem per amministratore {$amministratore->codice_univoco}\n\n"; $script .= "set -e\n\n"; $script .= "ADMIN_CODE=\"{$amministratore->codice_univoco}\"\n"; $script .= "TARGET_PATH=\"\${TARGET_PATH:-/var/www/netgescon/storage/app/amministratori}\"\n\n"; $script .= "echo \"πŸš€ Inizio restore filesystem amministratore \$ADMIN_CODE\"\n\n"; $script .= "# Crea directory target\n"; $script .= "mkdir -p \"\$TARGET_PATH/\$ADMIN_CODE\"\n\n"; $script .= "# Estrai archivio filesystem\n"; $script .= "if [ -f \"../filesystem_admin_\${ADMIN_CODE}.zip\" ]; then\n"; $script .= " echo \"πŸ“₯ Estrazione archivio filesystem\"\n"; $script .= " cd \"\$TARGET_PATH/\$ADMIN_CODE\"\n"; $script .= " unzip -q \"../../../migrations/\$(basename \$PWD)/filesystem_admin_\${ADMIN_CODE}.zip\"\n"; $script .= " echo \"βœ… Filesystem ripristinato in \$TARGET_PATH/\$ADMIN_CODE\"\n"; $script .= "else\n"; $script .= " echo \"❌ Archivio filesystem non trovato\"\n"; $script .= " exit 1\n"; $script .= "fi\n\n"; $script .= "# Imposta permessi\n"; $script .= "echo \"πŸ”§ Impostazione permessi\"\n"; $script .= "chown -R www-data:www-data \"\$TARGET_PATH/\$ADMIN_CODE\"\n"; $script .= "find \"\$TARGET_PATH/\$ADMIN_CODE\" -type d -exec chmod 755 {} \\;\n"; $script .= "find \"\$TARGET_PATH/\$ADMIN_CODE\" -type f -exec chmod 644 {} \\;\n\n"; $script .= "echo \"πŸŽ‰ Restore filesystem completato!\"\n"; return $script; } /** * Crea script verifica post-migrazione */ private function createVerificationScript(Amministratore $amministratore): string { $script = "#!/bin/bash\n\n"; $script .= "# Script verifica migrazione per amministratore {$amministratore->codice_univoco}\n\n"; $script .= "ADMIN_CODE=\"{$amministratore->codice_univoco}\"\n"; $script .= "ADMIN_DB=\"netgescon_admin_{$amministratore->codice_univoco}\"\n"; $script .= "MYSQL_USER=\"\${MYSQL_USER:-root}\"\n"; $script .= "MYSQL_PASS=\"\${MYSQL_PASS}\"\n"; $script .= "MYSQL_HOST=\"\${MYSQL_HOST:-localhost}\"\n\n"; $script .= "echo \"πŸ” Verifica migrazione amministratore \$ADMIN_CODE\"\n\n"; $script .= "# Verifica database\n"; $script .= "echo \"πŸ“Š Verifica database...\"\n"; $script .= "DB_EXISTS=\$(mysql -h\$MYSQL_HOST -u\$MYSQL_USER -p\$MYSQL_PASS -e \"SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME='\$ADMIN_DB'\" | grep -v SCHEMA_NAME | wc -l)\n"; $script .= "if [ \$DB_EXISTS -eq 1 ]; then\n"; $script .= " echo \"βœ… Database amministratore presente\"\n"; $script .= " TABLE_COUNT=\$(mysql -h\$MYSQL_HOST -u\$MYSQL_USER -p\$MYSQL_PASS -e \"SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='\$ADMIN_DB'\" | tail -1)\n"; $script .= " echo \"πŸ“‹ Tabelle trovate: \$TABLE_COUNT\"\n"; $script .= "else\n"; $script .= " echo \"❌ Database amministratore mancante\"\n"; $script .= "fi\n\n"; $script .= "# Verifica filesystem\n"; $script .= "echo \"πŸ“ Verifica filesystem...\"\n"; $script .= "ADMIN_PATH=\"/var/www/netgescon/storage/app/amministratori/\$ADMIN_CODE\"\n"; $script .= "if [ -d \"\$ADMIN_PATH\" ]; then\n"; $script .= " echo \"βœ… Cartella amministratore presente\"\n"; $script .= " FILE_COUNT=\$(find \"\$ADMIN_PATH\" -type f | wc -l)\n"; $script .= " echo \"πŸ“„ File trovati: \$FILE_COUNT\"\n"; $script .= "else\n"; $script .= " echo \"❌ Cartella amministratore mancante\"\n"; $script .= "fi\n\n"; $script .= "echo \"🎯 Verifica completata!\"\n"; return $script; } /** * Crea script PHP per restore record */ private function createPhpRestoreScript(Amministratore $amministratore): string { return "codice_univoco} * Da eseguire dopo restore database e filesystem */ require_once __DIR__ . '/../../../../vendor/autoload.php'; use Illuminate\\Support\\Facades\\DB; use App\\Models\\Amministratore; use App\\Models\\User; // Carica configurazione Laravel \$app = require_once __DIR__ . '/../../../../bootstrap/app.php'; \$app->make(Illuminate\\Contracts\\Console\\Kernel::class)->bootstrap(); try { echo \"πŸš€ Inizio restore record amministratore {$amministratore->codice_univoco}\\n\"; // Leggi metadata \$metadata = json_decode(file_get_contents(__DIR__ . '/../metadata.json'), true); \$adminData = \$metadata['amministratore']; // Verifica se amministratore esiste giΓ  \$esistente = Amministratore::where('codice_univoco', '{$amministratore->codice_univoco}')->first(); if (\$esistente) { echo \"⚠️ Amministratore {$amministratore->codice_univoco} giΓ  presente, aggiorno record...\\n\"; \$esistente->update([ 'database_attivo' => \$adminData['database_principale'] ]); \$amministratore = \$esistente; } else { echo \"βž• Creazione nuovo record amministratore...\\n\"; // Crea/trova utente \$user = User::where('email', \$adminData['email_studio'])->first(); if (!\$user) { \$user = User::create([ 'name' => \$adminData['nome'] . ' ' . \$adminData['cognome'], 'email' => \$adminData['email_studio'], 'password' => bcrypt('temp_password_' . uniqid()), 'email_verified_at' => now(), ]); } // Crea amministratore \$amministratore = Amministratore::create([ 'user_id' => \$user->id, 'nome' => \$adminData['nome'], 'cognome' => \$adminData['cognome'], 'denominazione_studio' => \$adminData['denominazione_studio'], 'partita_iva' => \$adminData['partita_iva'], 'codice_fiscale_studio' => \$adminData['codice_fiscale_studio'], 'email_studio' => \$adminData['email_studio'], 'codice_univoco' => '{$amministratore->codice_univoco}', 'database_attivo' => \$adminData['database_principale'] ]); } echo \"βœ… Record amministratore ripristinato (ID: {\$amministratore->id})\\n\"; // Restore stabili foreach (\$metadata['stabili'] as \$stabileData) { \$stabile = \$amministratore->stabili()->where('codice_stabile', \$stabileData['codice_stabile'])->first(); if (!\$stabile) { \$stabile = \$amministratore->stabili()->create([ 'codice_stabile' => \$stabileData['codice_stabile'], 'denominazione' => \$stabileData['denominazione'], 'indirizzo' => 'Da aggiornare', 'cap' => '00000', 'citta' => 'Da aggiornare', 'provincia' => 'XX', 'database_dedicato' => \$stabileData['database_dedicato'] ]); echo \"βž• Stabile {\$stabileData['codice_stabile']} creato\\n\"; } else { \$stabile->update(['database_dedicato' => \$stabileData['database_dedicato']]); echo \"πŸ”„ Stabile {\$stabileData['codice_stabile']} aggiornato\\n\"; } } echo \"πŸŽ‰ Restore record completato!\\n\"; } catch (Exception \$e) { echo \"❌ Errore durante restore: \" . \$e->getMessage() . \"\\n\"; exit(1); } "; } /** * Crea README istruzioni migrazione */ private function createMigrationReadme(Amministratore $amministratore): string { return "# πŸ“¦ Migrazione Amministratore {$amministratore->codice_univoco} ## πŸ“‹ Informazioni Migrazione - **Amministratore**: {$amministratore->nome_completo} - **Studio**: {$amministratore->denominazione_studio} - **Codice**: {$amministratore->codice_univoco} - **Data Migrazione**: " . date('d/m/Y H:i') . " - **Server Origine**: " . env('APP_URL') . " ## 🎯 Contenuto Package - Database amministratore principale - Database dedicati per ogni stabile - Archivio completo filesystem - Script automatici di restore - Metadata e configurazioni ## πŸš€ Procedura di Restore ### 1️⃣ Prerequisiti ```bash # MySQL server attivo # PHP 8.1+ con estensioni: zip, pdo_mysql, openssl # Spazio disco sufficiente (vedere metadata.json) # Accesso directory NetGescon ``` ### 2️⃣ Configurazione Environment ```bash export MYSQL_USER=\"root\" export MYSQL_PASS=\"password\" export MYSQL_HOST=\"localhost\" export TARGET_PATH=\"/var/www/netgescon/storage/app/amministratori\" ``` ### 3️⃣ Esecuzione Restore ```bash # 1. Restore database cd scripts/ chmod +x *.sh ./restore_databases.sh # 2. Restore filesystem ./restore_filesystem.sh # 3. Restore record Laravel php restore_records.php # 4. Verifica migrazione ./verify_migration.sh ``` ## ⚠️ Note Importanti ### πŸ” Sicurezza - Modificare password temporanee dopo restore - Verificare permessi filesystem - Testare connessioni database ### πŸ”„ Post-Migrazione - Aggiornare configurazioni server-specific - Verificare path assoluti - Testare funzionalitΓ  complete - Aggiornare backup automatici ### πŸ†˜ Troubleshooting - Verificare log errori in `/var/log/mysql/` - Controllare permessi `www-data` - Verificare spazio disco disponibile - Consultare `verify_migration.sh` ## πŸ“Š Statistiche Migrazione - **Stabili Inclusi**: " . $amministratore->stabili->count() . " - **Database**: " . ($amministratore->stabili->where('database_dedicato', '!=', null)->count() + 1) . " - **Spazio Richiesto**: Vedere metadata.json --- *Package generato automaticamente da NetGescon v2.1.0* "; } /** * Verifica integritΓ  migrazione */ private function verifyMigrationIntegrity(string $migrationPath): array { try { $checks = [ 'metadata_exists' => file_exists($migrationPath . '/metadata.json'), 'scripts_exists' => is_dir($migrationPath . '/scripts'), 'database_backups' => 0, 'filesystem_archives' => 0, ]; // Conta backup database $files = glob($migrationPath . '/backup_*.sql'); $checks['database_backups'] = count($files); // Conta archivi filesystem $archives = glob($migrationPath . '/filesystem_*.zip'); $checks['filesystem_archives'] = count($archives); $checks['integrity_ok'] = $checks['metadata_exists'] && $checks['scripts_exists'] && $checks['database_backups'] > 0; return [ 'success' => true, 'checks' => $checks, ]; } catch (Exception $e) { return [ 'success' => false, 'error' => $e->getMessage(), ]; } } /** * Crea package finale migrazione */ private function createMigrationPackage(string $migrationId, string $migrationPath): array { try { $packagePath = storage_path("app/migrations/{$migrationId}.zip"); $zip = new ZipArchive(); if ($zip->open($packagePath, ZipArchive::CREATE) !== true) { throw new Exception('Impossibile creare package migrazione'); } $iterator = new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator($migrationPath, \RecursiveDirectoryIterator::SKIP_DOTS) ); foreach ($iterator as $file) { if ($file->isFile()) { $relativePath = str_replace($migrationPath . DIRECTORY_SEPARATOR, '', $file->getPathname()); $zip->addFile($file->getPathname(), $relativePath); } } $zip->close(); // Rimuovi cartella temporanea $this->deleteDirectory($migrationPath); return [ 'success' => true, 'package_path' => $packagePath, 'package_size' => filesize($packagePath), 'download_url' => url('admin/migrations/download/' . basename($packagePath)), ]; } catch (Exception $e) { return [ 'success' => false, 'error' => $e->getMessage(), ]; } } /** * Calcola spazio richiesto */ private function calculateRequiredSpace(Amministratore $amministratore): int { $totalSize = 0; // Dimensione archivio amministratore $adminPath = $this->tenantArchivePath->amministratoreAbsolutePath($amministratore); if (is_dir($adminPath)) { $totalSize += $this->getDirectorySize($adminPath); } // Aggiungi overhead per backup database (stimato) $totalSize += 50 * 1024 * 1024; // 50MB stimati per backup return intval($totalSize / (1024 * 1024)); // Converti in MB } /** * Analizza struttura cartelle */ private function analyzeFolderStructure(Amministratore $amministratore): array { $adminPath = $this->tenantArchivePath->amministratoreAbsolutePath($amministratore); if (! is_dir($adminPath)) { return ['exists' => false]; } return [ 'exists' => true, 'path' => $adminPath, 'size' => $this->getDirectorySize($adminPath), 'files_count' => $this->countFiles($adminPath), 'directories' => $this->listDirectories($adminPath), ]; } /** * Analizza struttura database */ private function analyzeDatabaseStructure(Amministratore $amministratore): array { $structure = [ 'amministratore' => [ 'database' => $amministratore->getDatabaseName(), 'exists' => false, 'tables' => [], ], 'stabili' => [], ]; // Verifica database amministratore try { $tables = DB::select("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ?", [$amministratore->getDatabaseName()]); $structure['amministratore']['exists'] = count($tables) > 0; $structure['amministratore']['tables'] = array_column($tables, 'TABLE_NAME'); } catch (Exception $e) { // Database non esiste } // Verifica database stabili foreach ($amministratore->stabili as $stabile) { if ($stabile->database_dedicato) { $stabileInfo = [ 'codice' => $stabile->codice_stabile, 'database' => $stabile->database_dedicato, 'exists' => false, 'tables' => [], ]; try { $tables = DB::select("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ?", [$stabile->database_dedicato]); $stabileInfo['exists'] = count($tables) > 0; $stabileInfo['tables'] = array_column($tables, 'TABLE_NAME'); } catch (Exception $e) { // Database non esiste } $structure['stabili'][] = $stabileInfo; } } return $structure; } /** * Utilities */ private function getDirectorySize(string $path): int { $size = 0; $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path)); foreach ($iterator as $file) { if ($file->isFile()) { $size += $file->getSize(); } } return $size; } private function countFiles(string $path): int { $count = 0; $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path)); foreach ($iterator as $file) { if ($file->isFile()) { $count++; } } return $count; } private function listDirectories(string $path): array { $directories = []; $iterator = new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator($path), \RecursiveIteratorIterator::SELF_FIRST ); foreach ($iterator as $file) { if ($file->isDir() && ! in_array($file->getFilename(), ['.', '..'])) { $relativePath = str_replace($path . DIRECTORY_SEPARATOR, '', $file->getPathname()); $directories[] = $relativePath; } } return $directories; } private function deleteDirectory(string $path): bool { if (! is_dir($path)) { return false; } $iterator = new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::CHILD_FIRST ); foreach ($iterator as $file) { if ($file->isDir()) { rmdir($file->getPathname()); } else { unlink($file->getPathname()); } } return rmdir($path); } }