From bd3d4256e6bdcc43ab7485e34549da737afae90c Mon Sep 17 00:00:00 2001 From: int2001 Date: Fri, 5 Dec 2025 06:39:44 +0000 Subject: [PATCH] Chunked also for custom_export --- application/controllers/Adif.php | 49 ++++++++++++++++++++++++++++---- application/models/Adif_data.php | 45 +++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 5 deletions(-) diff --git a/application/controllers/Adif.php b/application/controllers/Adif.php index e3dafd313..91528a274 100644 --- a/application/controllers/Adif.php +++ b/application/controllers/Adif.php @@ -176,10 +176,15 @@ class adif extends CI_Controller { // Set memory limit to unlimited to allow heavy usage ini_set('memory_limit', '-1'); + set_time_limit(300); $this->load->model('adif_data'); + $this->load->library('AdifHelper'); + // Get parameters $station_id = $this->security->xss_clean($this->input->post('station_profile')); + $from = $this->input->post('from'); + $to = $this->input->post('to'); // Used for exporting QSOs not previously exported to LoTW if ($this->input->post('exportLotw') == 1) { @@ -194,16 +199,50 @@ class adif extends CI_Controller { $onlyop=null; } - $data['qsos'] = $this->adif_data->export_custom($this->input->post('from'), $this->input->post('to'), $station_id, $exportLotw, $onlyop); + // Set headers for direct download + $filename = $this->session->userdata('user_callsign').'-'.date('Ymd-Hi').'.adi'; + header('Content-Type: text/plain; charset=utf-8'); + header('Content-Disposition: attachment; filename="'.$filename.'"'); - $this->load->view('adif/data/exportall', $data); + // Output ADIF header // No chance to use exportall-view any longer, because of chunking logic + echo "Wavelog ADIF export\n"; + echo "3.1.6\n"; + echo "config->item('app_name')).">".$this->config->item('app_name')."\r\n"; + echo "optionslib->get_option('version')).">".$this->optionslib->get_option('version')."\r\n"; + echo "\n\n"; + // Collect QSO IDs for LoTW marking (since we can't access all at once) + $qso_ids_for_lotw = []; - if ((clubaccess_check(9)) && ($this->input->post('markLotw') == 1)) { // Only allow marking if clubofficer or regular user! - foreach ($data['qsos']->result() as $qso) { - $this->adif_data->mark_lotw_sent($qso->COL_PRIMARY_KEY); + // Stream QSOs in 5K chunks + $offset = 0; + $chunk_size = 5000; + + do { + $qsos = $this->adif_data->export_custom_chunked($from, $to, $station_id, $exportLotw, $onlyop, $offset, $chunk_size); + + if ($qsos && $qsos->num_rows() > 0) { + foreach ($qsos->result() as $qso) { + echo $this->adifhelper->getAdifLine($qso); + // Collect IDs for LoTW marking + $qso_ids_for_lotw[] = $qso->COL_PRIMARY_KEY; + } + // Free memory + $qsos->free_result(); + } + + $offset += $chunk_size; + } while ($qsos && $qsos->num_rows() > 0); + + // Handle LoTW marking after export + if ((clubaccess_check(9)) && ($this->input->post('markLotw') == 1) && !empty($qso_ids_for_lotw)) { + foreach ($qso_ids_for_lotw as $qso_id) { + $this->adif_data->mark_lotw_sent($qso_id); } } + + // Stop execution + exit; } public function mark_lotw() { diff --git a/application/models/Adif_data.php b/application/models/Adif_data.php index ba0ad0de6..e54ef1a16 100644 --- a/application/models/Adif_data.php +++ b/application/models/Adif_data.php @@ -281,6 +281,51 @@ class adif_data extends CI_Model { return $this->db->get(); } + function export_custom_chunked($from, $to, $station_id, $exportLotw = false, $onlyop = null, $offset = 0, $limit = 5000) { + // Copy export_custom logic but add chunking for station_id > 0 + $this->load->model('Stations'); + if ($station_id == 0) { + // Use existing chunked export_all for all stations + return $this->export_all_chunked(null, $from, $to, $exportLotw, $onlyop, $offset, $limit); + } + + // Check station access + if (!$this->Stations->check_station_is_accessible($station_id)) { + return; + } + + // Build query identical to export_custom but add LIMIT/OFFSET + $this->db->select(''.$this->config->item('table_name').'.*, station_profile.*, dxcc_entities.name as station_country'); + $this->db->from($this->config->item('table_name')); + $this->db->where($this->config->item('table_name').'.station_id', $station_id); + + // Apply same filters as export_custom + if ($from) { + $this->db->where("date(".$this->config->item('table_name').".COL_TIME_ON) >= ", $from); + } + if ($to) { + $this->db->where("date(".$this->config->item('table_name').".COL_TIME_ON) <= ",$to); + } + if ($onlyop) { + $this->db->where("upper(".$this->config->item('table_name').".col_operator)",$onlyop); + } + if ($exportLotw) { + $this->db->group_start(); + $this->db->where($this->config->item('table_name').".COL_LOTW_QSL_SENT != 'Y'"); + $this->db->or_where($this->config->item('table_name').".COL_LOTW_QSL_SENT", NULL); + $this->db->group_end(); + } + + $this->db->order_by($this->config->item('table_name').".COL_TIME_ON", "ASC"); + $this->db->join('station_profile', 'station_profile.station_id = '.$this->config->item('table_name').'.station_id'); + $this->db->join('dxcc_entities', 'station_profile.station_dxcc = dxcc_entities.adif', 'left outer'); + + // Add chunking + $this->db->limit($limit, $offset); + + return $this->db->get(); + } + }