false, 'message' => '']; try { if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_POST['iddatadb'])) { throw new Exception('Richiesta non valida'); } $iddatadb = intval($_POST['iddatadb']); $idclient = isset($_POST['idclient']) ? (is_numeric($_POST['idclient']) ? intval($_POST['idclient']) : null) : null; $db = DBHandlerSelect::getInstance(); $pdo = $db->getConnection(); // ---------------- FIXED FIELDS (template_fixed_mapping) ---------------- // 1) Recupera templateid dalla riga datadb (serve per sapere quali fixed_field_key sono permessi) $stmtTpl = $pdo->prepare("SELECT templateid FROM datadb WHERE iddatadb = ?"); $stmtTpl->execute([$iddatadb]); $tplRow = $stmtTpl->fetch(PDO::FETCH_ASSOC); $templateId = isset($tplRow['templateid']) ? (int)$tplRow['templateid'] : 0; if ($templateId <= 0) { throw new Exception("Template non trovato per iddatadb=$iddatadb"); } // 2) Recupera elenco fixed fields visibili per quel template $fxStmt = $pdo->prepare(" SELECT fixed_field_key, data_type, is_required, default_value FROM template_fixed_mapping WHERE template_id = ? AND is_visible_import = 1 "); $fxStmt->execute([$templateId]); $fixedList = $fxStmt->fetchAll(PDO::FETCH_ASSOC); // 3) Crea whitelist: key => metadata $fixedWhitelist = []; foreach ($fixedList as $fx) { $k = (string)$fx['fixed_field_key']; // sicurezza: nome colonna ammesso solo se "safe" (no spazi, no caratteri strani) if (!preg_match('/^[a-zA-Z0-9_]+$/', $k)) { continue; } $fixedWhitelist[$k] = [ 'data_type' => (string)$fx['data_type'], // INT | DATE 'is_required' => (int)$fx['is_required'], 'default_value' => $fx['default_value'] ?? null ]; } $data = $_POST; $details = []; // 1. Estrarre i dettagli da POST foreach ($data as $key => $value) { if (preg_match('/^details(\d+)field_value$/', $key, $matches)) { $id = $matches[1]; $details[$id] = $value; } } // 2. Recupera i valori esistenti da import_data_details $stmt = $pdo->prepare("SELECT mapping_id, field_value FROM import_data_details WHERE id = ?"); $stmt->execute([$iddatadb]); $currentValues = []; while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { $currentValues[$row['mapping_id']] = $row['field_value']; } // 3. Confronta i valori nuovi con quelli esistenti $changed = []; foreach ($details as $id => $newValue) { $oldValue = $currentValues[$id] ?? null; if ($oldValue !== $newValue) { $changed[$id] = [ 'old' => $oldValue, 'new' => $newValue ]; } } // 4. Aggiorna i dettagli se ci sono modifiche if (!empty($changed)) { $updateStmt = $pdo->prepare(" UPDATE import_data_details SET field_value = :newValue WHERE id = :iddatadb AND mapping_id = :mappingId "); foreach ($changed as $mappingId => $values) { $updateStmt->execute([ ':newValue' => $values['new'], ':iddatadb' => $iddatadb, ':mappingId' => $mappingId ]); } } // 5. Aggiorna datadb: idclient + FIXED FIELDS (whitelisted) $setParts = []; $params = []; // 5a) idclient (se presente) if (isset($idclient)) { $setParts[] = "idclient = ?"; $params[] = $idclient; } // 5b) fixed fields dal POST (solo quelli presenti nella whitelist del template) foreach ($fixedWhitelist as $col => $meta) { if (!array_key_exists($col, $_POST)) { continue; // non inviato dal form } $val = $_POST[$col]; // Normalizzazione per tipo if ($meta['data_type'] === 'DATE') { $val = trim((string)$val); $val = ($val === '') ? null : $val; // atteso formato Y-m-d } else { // INT $val = trim((string)$val); $val = ($val === '') ? null : (int)$val; } $setParts[] = "`$col` = ?"; $params[] = $val; } // esegui update solo se c'รจ qualcosa da aggiornare if (!empty($setParts)) { $params[] = $iddatadb; $sqlUpd = "UPDATE datadb SET " . implode(", ", $setParts) . " WHERE iddatadb = ?"; $updStmt = $pdo->prepare($sqlUpd); $updStmt->execute($params); } // Messaggio risposta (mantengo la tua logica ma includo fixed) if (!empty($setParts) && !empty($changed)) { $response['message'] = "Updated details and datadb fields successfully"; } elseif (!empty($setParts)) { $response['message'] = "Updated datadb fields successfully"; } elseif (!empty($changed)) { $response['message'] = "Updated details successfully"; } else { $response['message'] = "No changes found"; } $response['success'] = true; $response['changed'] = $changed; // Debug / optional } catch (Exception $e) { $response['success'] = false; $response['message'] = $e->getMessage(); error_log("Errore in save_edited_row.php: " . $e->getMessage()); } echo json_encode($response); exit;