Reworked some of the QRZ code for downloading
这个提交包含在:
父节点
b1a68d6c61
当前提交
0416d8446f
共有 2 个文件被更改,包括 314 次插入 和 79 次删除
|
|
@ -195,89 +195,237 @@ class Qrz extends CI_Controller {
|
|||
// Query the logbook to determine when the last LoTW confirmation was
|
||||
$qrz_last_date = null;
|
||||
}
|
||||
$this->download($this->session->userdata('user_id'),$qrz_last_date,true);
|
||||
$this->download($this->session->userdata('user_id'),true);
|
||||
} // end function
|
||||
|
||||
function download($user_id_to_load = null, $lastqrz = null, $show_views = false) {
|
||||
function download($user_id_to_load = null, $show_views = false) { // Remove $lastqrz parameter
|
||||
$this->load->model('user_model');
|
||||
$this->load->model('logbook_model');
|
||||
|
||||
|
||||
$api_keys = $this->logbook_model->get_qrz_apikeys();
|
||||
$total_processed_count = 0; // Initialize total count here
|
||||
$data = []; // Initialize data array
|
||||
|
||||
if ($api_keys) {
|
||||
foreach ($api_keys as $station) {
|
||||
if ((($user_id_to_load != null) && ($user_id_to_load != $station->user_id))) { // Skip User if we're called with a specific user_id
|
||||
continue;
|
||||
}
|
||||
if ($lastqrz == null) {
|
||||
$lastqrz = $this->logbook_model->qrz_last_qsl_date($station->user_id);
|
||||
}
|
||||
|
||||
// Remove the block checking for $lastqrz == null and fetching the date
|
||||
$qrz_api_key = $station->qrzapikey;
|
||||
$result=($this->mass_download_qsos($qrz_api_key, $lastqrz));
|
||||
if (isset($result['tableheaders'])) {
|
||||
$data['tableheaders']=$result['tableheaders'];
|
||||
if (isset($data['table'])) {
|
||||
$data['table'].=$result['table'];
|
||||
} else {
|
||||
$data['table']=$result['table'];
|
||||
$result = $this->mass_download_qsos($qrz_api_key); // mass_download_qsos returns ['table_data' => ..., 'processed_count' => ...] or ['status' => 'error', 'message' => ...]
|
||||
|
||||
|
||||
if ($result !== false && isset($result['processed_count'])) {
|
||||
$total_processed_count += $result['processed_count']; // Accumulate count
|
||||
$table_data = $result['table_data'];
|
||||
|
||||
if (isset($table_data['tableheaders'])) {
|
||||
// Ensure headers are set only once
|
||||
if (!isset($data['tableheaders'])) {
|
||||
$data['tableheaders'] = $table_data['tableheaders'];
|
||||
}
|
||||
if (isset($table_data['table']) && $table_data['table'] != '') {
|
||||
if (isset($data['table'])) {
|
||||
$data['table'] .= $table_data['table'];
|
||||
} else {
|
||||
$data['table'] = $table_data['table'];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (is_array($result) && isset($result['status']) && $result['status'] === 'error') {
|
||||
// Handle specific error structure returned by mass_download_qsos
|
||||
log_message('error', "Error during QRZ download for user_id: " . $station->user_id . ". Message: " . $result['message']);
|
||||
// Optionally echo error to user if $show_views is true, or add to $data['error']
|
||||
if ($show_views) {
|
||||
$data['errors'][] = "Error for user ID " . $station->user_id . ": " . $result['message'];
|
||||
}
|
||||
} else {
|
||||
// Catch-all for unexpected return values (like the old boolean false or other issues)
|
||||
log_message('error', "Unexpected error or empty result returned from mass_download_qsos for API key associated with user_id: " . $station->user_id);
|
||||
if ($show_views) {
|
||||
$data['errors'][] = "Unexpected error during download for user ID " . $station->user_id . ". Check system logs.";
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo "No station profiles with a QRZ API Key found.";
|
||||
log_message('error', "No station profiles with a QRZ API Key found.");
|
||||
// If no keys, we can exit early if showing views, or just let it fall through if not.
|
||||
if ($show_views) {
|
||||
$data['page_title'] = "QRZ ADIF Information";
|
||||
$data['error'] = "No station profiles with a QRZ API Key found.";
|
||||
$this->load->view('interface_assets/header', $data);
|
||||
$this->load->view('qrz/analysis', $data); // Assuming view can show $error
|
||||
$this->load->view('interface_assets/footer');
|
||||
return; // Stop further processing
|
||||
} else {
|
||||
return ''; // Return empty if not showing views and no keys found
|
||||
}
|
||||
}
|
||||
|
||||
$this->load->model('user_model');
|
||||
if ($this->user_model->authorize(2)) { // Only Output results if authorized User
|
||||
if(isset($data['tableheaders'])) {
|
||||
if ($data['table'] != '') {
|
||||
$data['table'].='</table>';
|
||||
}
|
||||
if($show_views == TRUE) {
|
||||
$data['page_title'] = "QRZ ADIF Information";
|
||||
$this->load->view('interface_assets/header', $data);
|
||||
$this->load->view('qrz/analysis');
|
||||
// Pass potential errors to the view
|
||||
if (isset($data['errors'])) {
|
||||
$view_data['errors'] = $data['errors'];
|
||||
}
|
||||
|
||||
$has_matches_to_display = (isset($data['tableheaders']) && isset($data['table']) && $data['table'] != '');
|
||||
$message = "Downloaded and processed " . $total_processed_count . " QSOs from QRZ.";
|
||||
|
||||
if ($has_matches_to_display) {
|
||||
$message .= " Matching QSOs found and updated.";
|
||||
if ($show_views == TRUE) {
|
||||
$view_data['tableheaders'] = $data['tableheaders'];
|
||||
$view_data['table'] = $data['table'] . '</table>';
|
||||
$view_data['page_title'] = "QRZ ADIF Information";
|
||||
$this->load->view('interface_assets/header', $view_data);
|
||||
$this->load->view('qrz/analysis', $view_data); // Pass $view_data containing table headers, rows, and errors
|
||||
$this->load->view('interface_assets/footer');
|
||||
} else {
|
||||
echo $message; // Echo message when not showing views but matches were found
|
||||
// Optionally echo errors if any occurred
|
||||
if (isset($data['errors'])) {
|
||||
echo " Errors encountered: " . implode("; ", $data['errors']);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
} else {
|
||||
echo "Downloaded QRZ report contains no matches.";
|
||||
// No matches found in the logbook
|
||||
$message .= " No matching QSOs found in your logbook to update.";
|
||||
if ($show_views == TRUE) {
|
||||
$view_data['page_title'] = "QRZ ADIF Information";
|
||||
$view_data['info_message'] = $message; // Pass the info message to the view
|
||||
// Errors are already in $view_data if they exist
|
||||
$this->load->view('interface_assets/header', $view_data);
|
||||
$this->load->view('qrz/analysis', $view_data); // Load view, assuming it checks for $info_message and $errors
|
||||
$this->load->view('interface_assets/footer');
|
||||
} else {
|
||||
echo $message; // Echo message when not showing views and no matches found
|
||||
// Optionally echo errors if any occurred
|
||||
if (isset($data['errors'])) {
|
||||
echo " Errors encountered: " . implode("; ", $data['errors']);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
} // End authorize check
|
||||
}
|
||||
|
||||
function mass_download_qsos($qrz_api_key = '', $lastqrz = '1900-01-01', $trusted = false) {
|
||||
function mass_download_qsos($qrz_api_key = '', $trusted = false) { // Remove $lastqrz parameter
|
||||
$config['upload_path'] = './uploads/';
|
||||
$file = $config['upload_path'] . 'qrzcom_download_report.adi';
|
||||
if (file_exists($file) && ! is_writable($file)) {
|
||||
$result = "Temporary download file ".$file." is not writable. Aborting!";
|
||||
return false;
|
||||
// This part is fine - checks local file writability
|
||||
$error_message = "Temporary download file ".$file." is not writable. Aborting!";
|
||||
// Return the structured error array here too for consistency
|
||||
return ['status' => 'error', 'message' => $error_message];
|
||||
}
|
||||
$url = 'http://logbook.qrz.com/api';
|
||||
$url = 'http://logbook.qrz.com/api'; // Correct URL
|
||||
|
||||
$post_data['KEY'] = $qrz_api_key;
|
||||
$post_data['ACTION'] = 'FETCH';
|
||||
$post_data['OPTION'] = 'MODSINCE:'.$lastqrz.';STATUS:CONFIRMED;TYPE:ADIF';
|
||||
$post_data['KEY'] = $qrz_api_key; // Correct parameter
|
||||
$post_data['ACTION'] = 'FETCH'; // Correct parameter
|
||||
$post_data['OPTION'] = 'BAND:80m,TYPE:ADIF'; // Correct parameter for fetching all confirmed in ADIF
|
||||
|
||||
$ch = curl_init( $url );
|
||||
curl_setopt( $ch, CURLOPT_POST, true);
|
||||
curl_setopt( $ch, CURLOPT_POSTFIELDS, $post_data);
|
||||
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_setopt( $ch, CURLOPT_HEADER, 0);
|
||||
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt( $ch, CURLOPT_POST, true); // Correct method
|
||||
curl_setopt( $ch, CURLOPT_POSTFIELDS, $post_data); // Correct data
|
||||
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1); // Okay
|
||||
curl_setopt( $ch, CURLOPT_HEADER, 0); // Correct - don't need response headers
|
||||
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true); // Correct - get response as string
|
||||
|
||||
$content = htmlspecialchars_decode(curl_exec($ch));
|
||||
file_put_contents($file, $content);
|
||||
if (strlen(file_get_contents($file, false, null, 0, 100))!=100) {
|
||||
$result = "QRZ downloading failed, either due to it being down or incorrect logins.";
|
||||
return "false";
|
||||
$content = curl_exec($ch); // Get raw content
|
||||
$curl_error = curl_error($ch); // Check for cURL errors
|
||||
curl_close($ch);
|
||||
|
||||
// Find the start of the ADIF data after "ADIF="
|
||||
$adif_start_pos = strpos($content, 'ADIF=');
|
||||
if ($adif_start_pos !== false) {
|
||||
// Extract the content starting after "ADIF="
|
||||
$content = substr($content, $adif_start_pos + 5);
|
||||
} else {
|
||||
// If "ADIF=" is not found, check for potential errors before assuming it's just ADIF
|
||||
if (strpos($content, 'STATUS=FAIL') !== false || strpos($content, 'STATUS=AUTH') !== false) {
|
||||
// Handle API errors even if ADIF= is missing
|
||||
$reason = $content;
|
||||
if (preg_match('/REASON=([^&]+)/', $content, $matches)) {
|
||||
$reason = urldecode($matches[1]); // Decode URL encoded reason
|
||||
}
|
||||
$error_message = "QRZ API Error: " . $reason;
|
||||
log_message('error', $error_message . ' API Key used: ' . $qrz_api_key . ' Raw Response: ' . $content);
|
||||
return ['status' => 'error', 'message' => $error_message];
|
||||
}
|
||||
// If no error status and no ADIF=, maybe it's just ADIF? Or an unknown error.
|
||||
// Log a warning if content seems unusual but doesn't match known error patterns.
|
||||
if (trim($content) === '' || strlen(trim($content)) < 10) { // Arbitrary small length check
|
||||
log_message('error', 'QRZ download: Received unexpected content without ADIF= prefix or known error status. Content: ' . $content);
|
||||
// Decide if this should be treated as an error or empty ADIF
|
||||
// For now, let's treat it as potentially empty/invalid ADIF and let loadFromFile handle it.
|
||||
}
|
||||
}
|
||||
|
||||
// Also remove the trailing metadata like &RESULT=OK&COUNT=... or just &COUNT=...
|
||||
$result_pos = strpos($content, '&RESULT=');
|
||||
$count_pos = strpos($content, '&COUNT=');
|
||||
|
||||
$truncate_pos = false;
|
||||
|
||||
if ($result_pos !== false && $count_pos !== false) {
|
||||
// Both found, take the earlier one
|
||||
$truncate_pos = min($result_pos, $count_pos);
|
||||
} elseif ($result_pos !== false) {
|
||||
// Only RESULT found
|
||||
$truncate_pos = $result_pos;
|
||||
} elseif ($count_pos !== false) {
|
||||
// Only COUNT found
|
||||
$truncate_pos = $count_pos;
|
||||
}
|
||||
|
||||
if ($truncate_pos !== false) {
|
||||
$content = substr($content, 0, $truncate_pos);
|
||||
}
|
||||
|
||||
if ($curl_error) { // Check for cURL level errors first
|
||||
$error_message = "QRZ download cURL error: " . $curl_error;
|
||||
log_message('error', $error_message . ' API Key used: ' . $qrz_api_key);
|
||||
return ['status' => 'error', 'message' => $error_message];
|
||||
}
|
||||
|
||||
if ($content === false || $content === '') { // Check if curl_exec failed or returned empty
|
||||
$error_message = "QRZ download failed: No content received from QRZ.com.";
|
||||
log_message('error', $error_message . ' API Key used: ' . $qrz_api_key);
|
||||
return ['status' => 'error', 'message' => $error_message];
|
||||
}
|
||||
|
||||
// Check for QRZ API specific error messages
|
||||
if (strpos($content, 'STATUS=FAIL') !== false || strpos($content, 'STATUS=AUTH') !== false) {
|
||||
// Extract reason if possible, otherwise use full content
|
||||
$reason = $content;
|
||||
if (preg_match('/REASON=([^&]+)/', $content, $matches)) {
|
||||
$reason = urldecode($matches[1]); // Decode URL encoded reason
|
||||
}
|
||||
$error_message = "QRZ API Error: " . $reason;
|
||||
log_message('error', $error_message . ' API Key used: ' . $qrz_api_key . ' Raw Response: ' . $content);
|
||||
return ['status' => 'error', 'message' => $error_message];
|
||||
}
|
||||
|
||||
$content = html_entity_decode($content, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
|
||||
// Save the potentially valid content
|
||||
if (file_put_contents($file, $content) === false) {
|
||||
$error_message = "Failed to write downloaded QRZ data to temporary file: " . $file;
|
||||
log_message('error', $error_message);
|
||||
return ['status' => 'error', 'message' => $error_message];
|
||||
} else {
|
||||
// echo "Downloaded QRZ data to temporary file: " . $file;
|
||||
}
|
||||
|
||||
// Proceed to load from the file
|
||||
ini_set('memory_limit', '-1');
|
||||
$result = $this->loadFromFile($file);
|
||||
$result = $this->loadFromFile($file); // loadFromFile returns ['table_data' => ..., 'processed_count' => ...]
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
|
@ -302,9 +450,17 @@ class Qrz extends CI_Controller {
|
|||
|
||||
$this->load->library('adif_parser');
|
||||
|
||||
$this->adif_parser->load_from_file($filepath);
|
||||
// Load the data from the file into the parser object
|
||||
$this->adif_parser->load_from_file($filepath); // <-- ADD THIS LINE
|
||||
|
||||
// Now initialize the parser with the loaded data
|
||||
if (!$this->adif_parser->initialize()) { // Check return value of initialize
|
||||
// Handle initialization error (e.g., log it, return error structure)
|
||||
log_message('error', 'ADIF Parser initialization failed for file: ' . $filepath);
|
||||
// Return an error structure consistent with mass_download_qsos
|
||||
return ['status' => 'error', 'message' => 'ADIF Parser initialization failed. Check logs.'];
|
||||
}
|
||||
|
||||
$this->adif_parser->initialize();
|
||||
$tableheaders = "<table width=\"100%\">";
|
||||
$tableheaders .= "<tr class=\"titles\">";
|
||||
$tableheaders .= "<td>Station Callsign</td>";
|
||||
|
|
@ -317,53 +473,51 @@ class Qrz extends CI_Controller {
|
|||
$tableheaders .= "</tr>";
|
||||
|
||||
$table = "";
|
||||
while($record = $this->adif_parser->get_record()) {
|
||||
$batch_data = [];
|
||||
$batch_size = 500; // Process 500 records at a time
|
||||
$record_count = 0; // Initialize record counter
|
||||
while ($record = $this->adif_parser->get_record()) {
|
||||
$record_count++; // Increment counter for each record read
|
||||
if ((!(isset($record['app_qrzlog_qsldate']))) || (!(isset($record['qso_date'])))) {
|
||||
continue;
|
||||
}
|
||||
$time_on = date('Y-m-d', strtotime($record['qso_date'])) ." ".date('H:i', strtotime($record['time_on']));
|
||||
|
||||
$qsl_date = date('Y-m-d', strtotime($record['app_qrzlog_qsldate']));
|
||||
|
||||
if (isset($record['time_off'])) {
|
||||
$time_off = date('Y-m-d', strtotime($record['qso_date'])) ." ".date('H:i', strtotime($record['time_off']));
|
||||
} else {
|
||||
$time_off = date('Y-m-d', strtotime($record['qso_date'])) ." ".date('H:i', strtotime($record['time_on']));
|
||||
}
|
||||
|
||||
// If we have a positive match from LoTW, record it in the DB according to the user's preferences
|
||||
if ($record['app_qrzlog_status'] == "C") {
|
||||
$record['qsl_rcvd'] = $config['qrz_rcvd_mark'];
|
||||
$qsl_rcvd = ''; // Default empty
|
||||
if (isset($record['app_qrzlog_status']) && $record['app_qrzlog_status'] == "C") {
|
||||
$qsl_rcvd = $config['qrz_rcvd_mark'];
|
||||
}
|
||||
|
||||
$record['call']=str_replace("_","/",$record['call']);
|
||||
$record['station_callsign']=str_replace("_","/",$record['station_callsign']);
|
||||
$status = $this->logbook_model->import_check($time_on, $record['call'], $record['band'], $record['mode'], $record['station_callsign']);
|
||||
$call = str_replace("_","/",$record['call']);
|
||||
$station_callsign = str_replace("_","/",$record['station_callsign']);
|
||||
$band = $record['band'] ?? ''; // Ensure band exists
|
||||
$mode = $record['mode'] ?? ''; // Ensure mode exists
|
||||
|
||||
if($status[0] == "Found") {
|
||||
$qrz_status = $this->logbook_model->qrz_update($time_on, $record['call'], $record['band'], $qsl_date, $record['qsl_rcvd'],$record['station_callsign']);
|
||||
// Add record data to batch
|
||||
$batch_data[] = [
|
||||
'time_on' => $time_on,
|
||||
'call' => $call,
|
||||
'band' => $band,
|
||||
'mode' => $mode,
|
||||
'station_callsign' => $station_callsign,
|
||||
'qsl_date' => $qsl_date,
|
||||
'qsl_rcvd' => $qsl_rcvd
|
||||
];
|
||||
|
||||
$table .= "<tr>";
|
||||
$table .= "<td>".$record['station_callsign']."</td>";
|
||||
$table .= "<td>".$time_on."</td>";
|
||||
$table .= "<td>".$record['call']."</td>";
|
||||
$table .= "<td>".$record['mode']."</td>";
|
||||
$table .= "<td>".$record['qsl_rcvd']."</td>";
|
||||
$table .= "<td>".$qsl_date."</td>";
|
||||
$table .= "<td>QSO Record: ".$status[0]."</td>";
|
||||
$table .= "</tr>";
|
||||
} else {
|
||||
$table .= "<tr>";
|
||||
$table .= "<td>".$record['station_callsign']."</td>";
|
||||
$table .= "<td>".$time_on."</td>";
|
||||
$table .= "<td>".$record['call']."</td>";
|
||||
$table .= "<td>".$record['mode']."</td>";
|
||||
$table .= "<td>".$record['qsl_rcvd']."</td>";
|
||||
$table .= "<td>QSO Record: ".$status[0]."</td>";
|
||||
$table .= "</tr>";
|
||||
// If batch size reached, process it
|
||||
if (count($batch_data) >= $batch_size) {
|
||||
$table .= $this->logbook_model->process_qrz_batch($batch_data);
|
||||
$batch_data = []; // Reset batch
|
||||
}
|
||||
}
|
||||
|
||||
// Process any remaining records in the last batch
|
||||
if (!empty($batch_data)) {
|
||||
$table .= $this->logbook_model->process_qrz_batch($batch_data);
|
||||
}
|
||||
|
||||
if ($table != "") {
|
||||
$data['tableheaders'] = $tableheaders;
|
||||
$data['table'] = $table;
|
||||
|
|
@ -372,8 +526,7 @@ class Qrz extends CI_Controller {
|
|||
}
|
||||
|
||||
unlink($filepath);
|
||||
return $data;
|
||||
|
||||
// Return both table data and the count of processed records
|
||||
return ['table_data' => $data, 'processed_count' => $record_count];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4244,6 +4244,7 @@ class Logbook_model extends CI_Model
|
|||
# try: $a looks like a call (.\d[A-Z]) and $b doesn't (.\d), they are
|
||||
# swapped. This still does not properly handle calls like DJ1YFK/KH7K where
|
||||
# only the OP's experience says that it's DJ1YFK on KH7K.
|
||||
|
||||
if (!$c && $a && $b) { # $a and $b exist, no $c
|
||||
if (preg_match($lidadditions, $b)) { # check if $b is a lid-addition
|
||||
$b = $a;
|
||||
|
|
@ -4864,6 +4865,87 @@ class Logbook_model extends CI_Model
|
|||
return $row->oldest_qso_date;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a batch of QRZ ADIF records for efficient database updates.
|
||||
*
|
||||
* @param array $batch_data Array of records from the ADIF file.
|
||||
* @return string HTML table rows for the processed batch.
|
||||
*/
|
||||
public function process_qrz_batch($batch_data) {
|
||||
$table = "";
|
||||
$update_batch_data = [];
|
||||
$this->load->model('Stations');
|
||||
|
||||
if (empty($batch_data)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Step 1: Build WHERE clause for fetching potential matches
|
||||
$this->db->select($this->config->item('table_name').'.COL_PRIMARY_KEY, '.$this->config->item('table_name').'.COL_CALL, '.$this->config->item('table_name').'.COL_TIME_ON, '.$this->config->item('table_name').'.COL_BAND, '.$this->config->item('table_name').'.COL_MODE, '.$this->config->item('table_name').'.COL_STATION_CALLSIGN');
|
||||
$this->db->from($this->config->item('table_name'));
|
||||
$this->db->group_start(); // Start grouping OR conditions
|
||||
foreach ($batch_data as $record) {
|
||||
$this->db->or_group_start(); // Start group for this record's AND conditions
|
||||
$this->db->where($this->config->item('table_name').'.COL_CALL', $record['call']);
|
||||
$this->db->where($this->config->item('table_name').'.COL_TIME_ON', $record['time_on']);
|
||||
$this->db->where($this->config->item('table_name').'.COL_BAND', $record['band']);
|
||||
// Optional: Add mode check if necessary, but it might reduce matches if modes differ slightly (e.g., SSB vs USB)
|
||||
// $this->db->where($this->config->item('table_name').'.COL_MODE', $record['mode']);
|
||||
$this->db->where($this->config->item('table_name').'.COL_STATION_CALLSIGN', $record['station_callsign']);
|
||||
$this->db->group_end(); // End group for this record's AND conditions
|
||||
}
|
||||
$this->db->group_end(); // End grouping OR conditions
|
||||
|
||||
// Step 2: Fetch Matches
|
||||
$query = $this->db->get();
|
||||
$db_results = $query->result_array();
|
||||
|
||||
// Index DB results for faster lookup
|
||||
$indexed_results = [];
|
||||
foreach ($db_results as $row) {
|
||||
$key = $row['COL_CALL'] . '|' . $row['COL_TIME_ON'] . '|' . $row['COL_BAND'] . '|' . $row['COL_STATION_CALLSIGN'];
|
||||
$indexed_results[$key] = $row['COL_PRIMARY_KEY'];
|
||||
}
|
||||
|
||||
// Step 3 & 4: Prepare Batch Update and Build Table Rows
|
||||
foreach ($batch_data as $record) {
|
||||
$match_key = $record['call'] . '|' . $record['time_on'] . '|' . $record['band'] . '|' . $record['station_callsign'];
|
||||
$log_status = '<span class="badge text-bg-danger">Not Found</span>';
|
||||
$primary_key = null;
|
||||
|
||||
if (isset($indexed_results[$match_key])) {
|
||||
$primary_key = $indexed_results[$match_key];
|
||||
$log_status = '<span class="badge text-bg-success">Confirmed</span>';
|
||||
|
||||
// Prepare data for batch update
|
||||
$update_batch_data[] = [
|
||||
'COL_PRIMARY_KEY' => $primary_key,
|
||||
'COL_QRZCOM_QSO_DOWNLOAD_DATE' => $record['qsl_date'],
|
||||
'COL_QRZCOM_QSO_UPLOAD_STATUS' => $record['qsl_rcvd'] // Should be 'Y' if confirmed
|
||||
];
|
||||
}
|
||||
|
||||
// Build table row
|
||||
$table .= "<tr>";
|
||||
$table .= "<td>" . $record['station_callsign'] . "</td>";
|
||||
$table .= "<td>" . $record['time_on'] . "</td>";
|
||||
$table .= "<td>" . $record['call'] . "</td>";
|
||||
$table .= "<td>" . $record['mode'] . "</td>";
|
||||
$table .= "<td>" . $record['qsl_date'] . "</td>";
|
||||
$table .= "<td>" . ($record['qsl_rcvd'] == 'Y' ? '<span class="badge text-bg-success">Yes</span>' : '<span class="badge text-bg-danger">No</span>') . "</td>";
|
||||
$table .= "<td>" . $log_status . "</td>";
|
||||
$table .= "</tr>";
|
||||
}
|
||||
|
||||
// Step 5: Execute Batch Update
|
||||
if (!empty($update_batch_data)) {
|
||||
$this->db->update_batch($this->config->item('table_name'), $update_batch_data, 'COL_PRIMARY_KEY');
|
||||
}
|
||||
|
||||
// Step 6: Return Table HTML
|
||||
return $table;
|
||||
}
|
||||
}
|
||||
|
||||
function validateADIFDate($date, $format = 'Ymd')
|
||||
|
|
|
|||
正在加载…
在新工单中引用