diff --git a/.gitignore b/.gitignore index ceb3329c9..9c2f2c8db 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ /application/config/database.php /application/config/config.php +/application/config/managed.php +/application/config/managed.sample.php /application/logs/*.php /uploads/*.adi /uploads/*.ADI diff --git a/application/config/migration.php b/application/config/migration.php index c0deb3066..82146ae21 100644 --- a/application/config/migration.php +++ b/application/config/migration.php @@ -22,7 +22,7 @@ | */ -$config['migration_version'] = 236; +$config['migration_version'] = 238; /* |-------------------------------------------------------------------------- diff --git a/application/controllers/Award.php b/application/controllers/Award.php new file mode 100644 index 000000000..a10c4aec0 --- /dev/null +++ b/application/controllers/Award.php @@ -0,0 +1,61 @@ +load->helper(array('form', 'url')); + + $this->load->model('user_model'); + if(!$this->user_model->authorize(2)) { $this->session->set_flashdata('notice', 'You\'re not allowed to do that!'); redirect('dashboard'); } + } + + public function index() + { + $this->load->model('awards_model'); + + $data['user_awards'] = $this->awards_model->get_user_awards(); + + // Render Page + $data['page_title'] = "Award Settings"; + $this->load->view('interface_assets/header', $data); + $this->load->view('awards/settings'); + $this->load->view('interface_assets/footer'); + } + + public function saveAward() { + // Get the award type and value from POST + $award_type = $this->security->xss_clean($this->input->post('award_type')); + $award_value = $this->security->xss_clean($this->input->post('award_value')); + + $this->load->model('awards_model'); + $result = $this->awards_model->save_single_award($award_type, $award_value); + + header('Content-Type: application/json'); + echo json_encode(array('message' => 'OK')); + return; + } + + public function activateall() { + $this->load->model('awards_model'); + $this->awards_model->activateall(); + + header('Content-Type: application/json'); + echo json_encode(array('message' => 'OK')); + return; + } + + public function deactivateall() { + $this->load->model('awards_model'); + $this->awards_model->deactivateall(); + + header('Content-Type: application/json'); + echo json_encode(array('message' => 'OK')); + return; + } +} diff --git a/application/controllers/Options.php b/application/controllers/Options.php index 67bfa2a3c..c6905794d 100644 --- a/application/controllers/Options.php +++ b/application/controllers/Options.php @@ -13,6 +13,9 @@ function __construct() $this->load->model('user_model'); if(!$this->user_model->authorize(99)) { $this->session->set_flashdata('notice', 'You\'re not allowed to do that!'); redirect('dashboard'); } + + // Note: Managed deployments may hide specific subsections (e.g. registration) + // but should still allow access to the Options area in general. // Load language files $this->lang->load(array( @@ -59,6 +62,43 @@ function appearance() { $this->load->view('interface_assets/footer'); } + // Registration options + function registration() { + + $data['page_title'] = $this->lang->line('options_cloudlog_options'); + $data['sub_heading'] = $this->lang->line('options_registration'); + + // If open registration is managed-disabled, keep page hidden + if ($this->config->item('disable_open_registration')) { + $this->session->set_flashdata('notice', 'This setting is managed and cannot be changed.'); + redirect('options'); + } + + $this->load->view('interface_assets/header', $data); + $this->load->view('options/registration'); + $this->load->view('interface_assets/footer'); + } + + function registration_save() { + $data['page_title'] = $this->lang->line('options_cloudlog_options'); + $data['sub_heading'] = $this->lang->line('options_registration'); + + if ($this->config->item('disable_open_registration')) { + $this->session->set_flashdata('notice', 'This setting is managed and cannot be changed.'); + redirect('/options'); + return; + } + + // Save the open registration option + $open_registration = $this->input->post('open_registration'); + $update = $this->optionslib->update('open_registration', $open_registration, 'yes'); + if ($update == TRUE) { + $this->session->set_flashdata('success', $this->lang->line('options_registration_settings_saved')); + } + + redirect('/options/registration'); + } + // Handles saving the appreance options to the options system. function appearance_save() { @@ -234,6 +274,7 @@ function email() { $data['page_title'] = $this->lang->line('options_cloudlog_options'); $data['sub_heading'] = $this->lang->line('options_email'); + $data['is_managed'] = ($this->config->item('managed_service') || $this->config->item('managed_email_protocol')) ? true : false; $this->load->view('interface_assets/header', $data); $this->load->view('options/email'); @@ -242,6 +283,11 @@ function email() { // Handles saving the radio options to the options system. function email_save() { + // Check if email is managed - if so, redirect with message + if ($this->config->item('managed_service') || $this->config->item('managed_email_protocol')) { + $this->session->set_flashdata('notice', 'Email settings are centrally managed and cannot be changed here.'); + redirect('options'); + } // Get Language Options diff --git a/application/controllers/Qrz.php b/application/controllers/Qrz.php index 23fe17bee..121cb299d 100644 --- a/application/controllers/Qrz.php +++ b/application/controllers/Qrz.php @@ -212,13 +212,7 @@ public function import_qrz() { $this->load->model('logbook_model'); - $customDate = $this->input->post('from'); - if ($customDate != NULL) { - $qrz_last_date = date($customDate); - } else { - // Query the logbook to determine when the last LoTW confirmation was - $qrz_last_date = null; - } + // Download all QRZ data regardless of date selection $this->download($this->session->userdata('user_id'),true); } // end function diff --git a/application/controllers/Update.php b/application/controllers/Update.php index 16c27ad2b..26428219f 100644 --- a/application/controllers/Update.php +++ b/application/controllers/Update.php @@ -389,9 +389,10 @@ public function lotw_users() { // Only truncate table AFTER we've validated the remote file $this->db->query("TRUNCATE TABLE lotw_users"); - $i = 0; + $i = 0; // raw rows read $batch_count = 0; - $lotwdata = array(); + // Use a map to deduplicate by callsign and keep the latest timestamp + $lotw_map = array(); $batch_size = 500; // Smaller batch size for better performance and memory usage // Skip CSV header row @@ -403,36 +404,42 @@ public function lotw_users() { $callsign = strtoupper($data[0]); // Validate callsign format (basic check) if (preg_match('/^[A-Z0-9\/]+$/', $callsign)) { - $lotwdata[] = array( - 'callsign' => $callsign, - 'lastupload' => $data[1] . ' ' . $data[2] - ); $i++; - - // Insert batch when we reach batch_size - if (count($lotwdata) >= $batch_size) { - if (!$this->db->insert_batch('lotw_users', $lotwdata)) { - echo "FAILED: Database error during batch insert"; - log_message('error', 'Database error during LoTW batch insert'); - fclose($handle); - return; - } - $batch_count++; - $lotwdata = array(); // Reset array + // Compose timestamp string and compare; keep the latest per callsign + $ts = $data[1] . ' ' . $data[2]; + // If we haven't seen this callsign, or this row is newer, store it + if (!isset($lotw_map[$callsign]) || strtotime($ts) > strtotime($lotw_map[$callsign])) { + $lotw_map[$callsign] = $ts; } } } } fclose($handle); - // Insert any remaining records in final batch - if (!empty($lotwdata)) { - if (!$this->db->insert_batch('lotw_users', $lotwdata)) { - echo "FAILED: Database error during final batch insert"; - log_message('error', 'Database error during LoTW final batch insert'); - return; + // Insert deduplicated records in batches + if (!empty($lotw_map)) { + $lotwdata = array(); + foreach ($lotw_map as $cs => $lu) { + $lotwdata[] = array('callsign' => $cs, 'lastupload' => $lu); + if (count($lotwdata) >= $batch_size) { + if (!$this->db->insert_batch('lotw_users', $lotwdata)) { + echo "FAILED: Database error during batch insert"; + log_message('error', 'Database error during LoTW batch insert while inserting deduped map'); + return; + } + $batch_count++; + $lotwdata = array(); + } + } + // Final batch + if (!empty($lotwdata)) { + if (!$this->db->insert_batch('lotw_users', $lotwdata)) { + echo "FAILED: Database error during final batch insert"; + log_message('error', 'Database error during LoTW final batch insert while inserting deduped map'); + return; + } + $batch_count++; } - $batch_count++; } // Verify we actually imported data @@ -454,7 +461,8 @@ public function lotw_users() { $endtime = $mtime; $totaltime = ($endtime - $starttime); echo "This page was created in ".$totaltime." seconds
"; - echo "Records inserted: " . $i . "
"; + echo "Records read: " . $i . "
"; + echo "Unique callsigns inserted: " . $final_count . "
"; } public function lotw_check() { diff --git a/application/controllers/User.php b/application/controllers/User.php index 534e3b8be..e0b7805f8 100644 --- a/application/controllers/User.php +++ b/application/controllers/User.php @@ -1095,6 +1095,177 @@ function login() } } + // Public signup (open registration) + public function signup() + { + // Gate: open registration must be enabled + if ($this->config->item('disable_open_registration') || $this->optionslib->get_option('open_registration') != 'true') { + $this->session->set_flashdata('notice', 'Registration is currently disabled.'); + redirect('user/login'); + return; + } + + $this->load->helper(array('form', 'url')); + $this->load->model('user_model'); + $this->load->library('form_validation'); + + // Validation rules + $this->form_validation->set_rules('user_name', 'Username', 'required'); + $this->form_validation->set_rules('user_email', 'E-mail', 'required|valid_email'); + $this->form_validation->set_rules('user_password', 'Password', 'required'); + $this->form_validation->set_rules('user_password_confirm', 'Password Confirmation', 'required|matches[user_password]'); + $this->form_validation->set_rules('user_firstname', 'First name', 'required'); + $this->form_validation->set_rules('user_lastname', 'Last name', 'required'); + $this->form_validation->set_rules('user_callsign', 'Callsign', 'required'); + $this->form_validation->set_rules('user_locator', 'Locator', 'callback_check_locator'); + $this->form_validation->set_rules('user_timezone', 'Timezone', 'required'); + + // Timezones for select + $data['timezones'] = $this->user_model->timezones(); + $data['page_title'] = 'Sign Up'; + + if ($this->form_validation->run() == FALSE) { + // Show form + $this->load->view('interface_assets/mini_header', $data); + $this->load->view('user/signup', $data); + $this->load->view('interface_assets/footer'); + return; + } + + // Defaults for new users + $user_type = 3; // operator (per config auth_level) + $measurement = 'M'; + $user_date_format = 'd/m/y'; + $user_stylesheet = $this->optionslib->get_option('option_theme') ?: 'default'; + $user_qth_lookup = 0; + $user_sota_lookup = 0; + $user_wwff_lookup = 0; + $user_pota_lookup = 0; + $user_show_notes = 0; + $user_column1 = ''; + $user_column2 = ''; + $user_column3 = ''; + $user_column4 = ''; + $user_column5 = ''; + $user_show_profile_image = 0; + $user_previous_qsl_type = ''; + $user_amsat_status_upload = ''; + $user_mastodon_url = ''; + $user_default_band = ''; + $user_default_confirmation = ''; + $user_qso_end_times = 0; + $user_quicklog = 0; + $user_quicklog_enter = 1; // 1 = search, 0 = log + $language = 'english'; + $user_hamsat_key = ''; + $user_hamsat_workable_only = ''; + $callbook_type = ''; + $callbook_username = ''; + $callbook_password = ''; + + // Attempt to create user + switch ($this->user_model->add( + $this->input->post('user_name', true), + $this->input->post('user_password', true), + $this->input->post('user_email', true), + $user_type, + $this->input->post('user_firstname', true), + $this->input->post('user_lastname', true), + $this->input->post('user_callsign', true), + $this->input->post('user_locator', true), + $this->input->post('user_timezone', true), + $measurement, + $user_date_format, + $user_stylesheet, + $user_qth_lookup, + $user_sota_lookup, + $user_wwff_lookup, + $user_pota_lookup, + $user_show_notes, + $user_column1, + $user_column2, + $user_column3, + $user_column4, + $user_column5, + $user_show_profile_image, + $user_previous_qsl_type, + $user_amsat_status_upload, + $user_mastodon_url, + $user_default_band, + $user_default_confirmation, + $user_qso_end_times, + $user_quicklog, + $user_quicklog_enter, + $language, + $user_hamsat_key, + $user_hamsat_workable_only, + $callbook_type, + $callbook_username, + $callbook_password + )) { + case EUSERNAMEEXISTS: + $data['username_error'] = 'Username ' . $this->input->post('user_name', true) . ' already in use!'; + break; + case EEMAILEXISTS: + $data['email_error'] = 'E-mail address ' . $this->input->post('user_email', true) . ' already in use!'; + break; + case EPASSWORDINVALID: + $data['password_error'] = 'Invalid password!'; + break; + case OK: + // Send a welcome email (without password) if email is configured + if ($this->optionslib->get_option('emailProtocol') != '') { + // Fetch newly created user by username + $new_user_q = $this->user_model->get($this->input->post('user_name', true)); + if ($new_user_q && $new_user_q->num_rows() > 0) { + $u = $new_user_q->row(); + + $this->load->library('email'); + if ($this->optionslib->get_option('emailProtocol') == "smtp") { + $config = Array( + 'protocol' => $this->optionslib->get_option('emailProtocol'), + 'smtp_crypto' => $this->optionslib->get_option('smtpEncryption'), + 'smtp_host' => $this->optionslib->get_option('smtpHost'), + 'smtp_port' => $this->optionslib->get_option('smtpPort'), + 'smtp_user' => $this->optionslib->get_option('smtpUsername'), + 'smtp_pass' => $this->optionslib->get_option('smtpPassword'), + 'crlf' => "\r\n", + 'newline' => "\r\n" + ); + $this->email->initialize($config); + } + + $email_data = array( + 'username' => $u->user_name, + 'user_firstname' => $u->user_firstname, + 'user_lastname' => $u->user_lastname, + 'callsign' => $u->user_callsign, + 'email' => $u->user_email, + 'base_url' => base_url(), + ); + $message = $this->load->view('email/welcome_reminder.php', $email_data, TRUE); + + $this->email->from($this->optionslib->get_option('emailAddress'), $this->optionslib->get_option('emailSenderName')); + $this->email->to($u->user_email); + $this->email->subject('Welcome to Cloudlog'); + $this->email->message($message); + if (!$this->email->send()) { + log_message('error', 'Failed to send signup welcome email to ' . $u->user_email . '. Error: ' . $this->email->print_debugger()); + } + } + } + + $this->session->set_flashdata('success', 'Account created. You can now log in.'); + redirect('user/login'); + return; + } + + // If we get here, something went wrong; re-render form with errors + $this->load->view('interface_assets/mini_header', $data); + $this->load->view('user/signup', $data); + $this->load->view('interface_assets/footer'); + } + function logout() { $this->load->model('user_model'); diff --git a/application/language/bulgarian/awards_lang.php b/application/language/bulgarian/awards_lang.php index 23dfe8e4c..13407e637 100644 --- a/application/language/bulgarian/awards_lang.php +++ b/application/language/bulgarian/awards_lang.php @@ -2,6 +2,7 @@ defined('BASEPATH') OR exit('No direct script access allowed'); +$lang['awards_menu_settings'] = "Award Settings"; $lang['awards_info_button'] = "Award Info"; $lang['awards_show_worked'] = "Show worked"; $lang['awards_show_confirmed'] = "Show confirmed"; diff --git a/application/language/chinese_simplified/awards_lang.php b/application/language/chinese_simplified/awards_lang.php index 77222622b..9ebf749fb 100644 --- a/application/language/chinese_simplified/awards_lang.php +++ b/application/language/chinese_simplified/awards_lang.php @@ -2,7 +2,8 @@ defined('BASEPATH') OR exit('No direct script access allowed'); -$lang['awards_info_button'] = "奖状详情"; +$lang['awards_menu_settings'] = "奖项设置"; +$lang['awards_info_button'] = "奖项信息"; $lang['awards_show_worked'] = "显示已通联"; $lang['awards_show_confirmed'] = "显示已确认"; $lang['awards_show_not_worked'] = "显示未通联"; diff --git a/application/language/czech/awards_lang.php b/application/language/czech/awards_lang.php index b77ede943..130a0a872 100644 --- a/application/language/czech/awards_lang.php +++ b/application/language/czech/awards_lang.php @@ -2,6 +2,7 @@ defined('BASEPATH') OR exit('No direct script access allowed'); +$lang['awards_menu_settings'] = "Award Settings"; $lang['awards_info_button'] = "Award Info"; $lang['awards_show_worked'] = "Show worked"; $lang['awards_show_confirmed'] = "Show confirmed"; diff --git a/application/language/dutch/awards_lang.php b/application/language/dutch/awards_lang.php index 6115045cf..d20b0e8df 100644 --- a/application/language/dutch/awards_lang.php +++ b/application/language/dutch/awards_lang.php @@ -2,7 +2,8 @@ defined('BASEPATH') OR exit('No direct script access allowed'); -$lang['awards_info_button'] = "Award Info"; +$lang['awards_menu_settings'] = "Award-instellingen"; +$lang['awards_info_button'] = "Award informatie"; $lang['awards_show_worked'] = "Show worked"; $lang['awards_show_confirmed'] = "Show confirmed"; $lang['awards_show_not_worked'] = "Show not worked"; diff --git a/application/language/english/awards_lang.php b/application/language/english/awards_lang.php index 23dfe8e4c..13407e637 100644 --- a/application/language/english/awards_lang.php +++ b/application/language/english/awards_lang.php @@ -2,6 +2,7 @@ defined('BASEPATH') OR exit('No direct script access allowed'); +$lang['awards_menu_settings'] = "Award Settings"; $lang['awards_info_button'] = "Award Info"; $lang['awards_show_worked'] = "Show worked"; $lang['awards_show_confirmed'] = "Show confirmed"; diff --git a/application/language/english/options_lang.php b/application/language/english/options_lang.php index 2ba13d251..c1519d514 100644 --- a/application/language/english/options_lang.php +++ b/application/language/english/options_lang.php @@ -103,6 +103,12 @@ $lang['options_save'] = 'Save'; $lang['options_appearance_settings_saved'] = 'Appearance settings have been saved successfully.'; +// Registration +$lang['options_registration'] = 'Registration'; +$lang['options_open_registration'] = 'Open Registration'; +$lang['options_open_registration_hint'] = 'Allow users to self-register via a public signup page.'; +$lang['options_registration_settings_saved'] = 'Registration settings have been saved successfully.'; + // Bands $lang['options_bands'] = "Bands"; diff --git a/application/language/finnish/awards_lang.php b/application/language/finnish/awards_lang.php index 05c6071be..c9e14cdbc 100644 --- a/application/language/finnish/awards_lang.php +++ b/application/language/finnish/awards_lang.php @@ -2,6 +2,7 @@ defined('BASEPATH') OR exit('No direct script access allowed'); +$lang['awards_menu_settings'] = "Award Settings"; $lang['awards_info_button'] = "Award Info"; $lang['awards_show_worked'] = "Show worked"; $lang['awards_show_confirmed'] = "Show confirmed"; diff --git a/application/language/french/awards_lang.php b/application/language/french/awards_lang.php index 9faef5f7f..2827d5017 100644 --- a/application/language/french/awards_lang.php +++ b/application/language/french/awards_lang.php @@ -2,6 +2,7 @@ defined('BASEPATH') OR exit('No direct script access allowed'); +$lang['awards_menu_settings'] = "Paramètres des diplômes"; $lang['awards_info_button'] = "Informations complémentaires"; $lang['awards_show_worked'] = "Voir les \"réalisés\""; $lang['awards_show_confirmed'] = "Voir les \"confirmés\""; diff --git a/application/language/german/awards_lang.php b/application/language/german/awards_lang.php index 4368e4da9..140418a49 100644 --- a/application/language/german/awards_lang.php +++ b/application/language/german/awards_lang.php @@ -2,6 +2,7 @@ defined('BASEPATH') OR exit('Direkter Skriptzugriff nicht erlaubt'); +$lang['awards_menu_settings'] = "Diplom-Einstellungen"; $lang['awards_info_button'] = "Diplom Info"; $lang['awards_show_worked'] = "Zeige gearbeitete"; $lang['awards_show_confirmed'] = "Zeige bestätigte"; diff --git a/application/language/greek/awards_lang.php b/application/language/greek/awards_lang.php index 23dfe8e4c..13407e637 100644 --- a/application/language/greek/awards_lang.php +++ b/application/language/greek/awards_lang.php @@ -2,6 +2,7 @@ defined('BASEPATH') OR exit('No direct script access allowed'); +$lang['awards_menu_settings'] = "Award Settings"; $lang['awards_info_button'] = "Award Info"; $lang['awards_show_worked'] = "Show worked"; $lang['awards_show_confirmed'] = "Show confirmed"; diff --git a/application/language/italian/awards_lang.php b/application/language/italian/awards_lang.php index 04a250898..8167650ac 100644 --- a/application/language/italian/awards_lang.php +++ b/application/language/italian/awards_lang.php @@ -2,6 +2,7 @@ defined('BASEPATH') OR exit('Non è consentito l\'accesso diretto allo script'); +$lang['awards_menu_settings'] = "Impostazioni premi"; $lang['awards_info_button'] = "Informazioni sull'Award"; $lang['awards_show_worked'] = "Mostra lavorati"; $lang['awards_show_confirmed'] = "Mostra confermati"; diff --git a/application/language/polish/awards_lang.php b/application/language/polish/awards_lang.php index 26339b643..21728ae4d 100644 --- a/application/language/polish/awards_lang.php +++ b/application/language/polish/awards_lang.php @@ -2,6 +2,7 @@ defined('BASEPATH') OR exit('Brak bezpośredniego dostępu do skryptu'); +$lang['awards_menu_settings'] = "Ustawienia nagród"; $lang['awards_info_button'] = "Informacje o nagrodzie"; $lang['awards_show_worked'] = "Pokaż wykonane"; $lang['awards_show_confirmed'] = "Pokaż potwierdzone"; diff --git a/application/language/portuguese/awards_lang.php b/application/language/portuguese/awards_lang.php index 8e37ad9e0..39134bbe8 100644 --- a/application/language/portuguese/awards_lang.php +++ b/application/language/portuguese/awards_lang.php @@ -1,6 +1,7 @@ load->config('managed', FALSE, TRUE); + // Force Migration to run on every page load $CI->load->library('Migration'); $CI->migration->current(); @@ -45,6 +48,28 @@ function __construct() function get_option($option_name) { // Make Codeigniter functions available to library $CI =& get_instance(); + + // Check for managed email configuration overrides + $email_settings_map = array( + 'emailProtocol' => 'managed_email_protocol', + 'smtpEncryption' => 'managed_email_smtp_encryption', + 'emailAddress' => 'managed_email_address', + 'emailSenderName' => 'managed_email_sender_name', + 'smtpHost' => 'managed_email_smtp_host', + 'smtpPort' => 'managed_email_smtp_port', + 'smtpUsername' => 'managed_email_smtp_username', + 'smtpPassword' => 'managed_email_smtp_password' + ); + + // If this is an email setting and managed email is configured, return managed value + if (array_key_exists($option_name, $email_settings_map)) { + $managed_key = $email_settings_map[$option_name]; + $managed_value = $CI->config->item($managed_key); + if ($managed_value !== NULL && $managed_value !== FALSE) { + return $managed_value; + } + } + if (strpos($option_name, 'option_') !== false) { if(!$CI->config->item($option_name)) { //Load the options model diff --git a/application/migrations/237_add_awardxuser.php b/application/migrations/237_add_awardxuser.php new file mode 100644 index 000000000..61555ea46 --- /dev/null +++ b/application/migrations/237_add_awardxuser.php @@ -0,0 +1,161 @@ +db->table_exists('awardxuser')) { + $this->dbforge->add_field(array( + 'id' => array( + 'type' => 'INT', + 'constraint' => 20, + 'unsigned' => TRUE, + 'auto_increment' => TRUE, + 'unique' => TRUE + ), + + 'userid' => array( + 'type' => 'INT', + 'constraint' => 20, + 'unsigned' => TRUE, + 'auto_increment' => FALSE + ), + + 'cq' => array( + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 1 + ), + + 'dok' => array( + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 1 + ), + + 'dxcc' => array( + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 1 + ), + + 'ffma' => array( + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 1 + ), + + 'iota' => array( + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 1 + ), + + 'gridmaster_dl' => array( + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 1 + ), + + 'gridmaster_lx' => array( + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 1 + ), + + 'gridmaster_ja' => array( + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 1 + ), + + 'gridmaster_us' => array( + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 1 + ), + + 'gridmaster_uk' => array( + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 1 + ), + + 'gmdxsummer' => array( + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 1 + ), + + 'pota' => array( + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 1 + ), + + 'sig' => array( + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 1 + ), + + 'sota' => array( + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 1 + ), + + 'uscounties' => array( + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 1 + ), + + 'vucc' => array( + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 1 + ), + + 'wab' => array( + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 1 + ), + + 'waja' => array( + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 1 + ), + + 'was' => array( + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 1 + ), + + 'wwff' => array( + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 1 + ), + )); + + $this->dbforge->add_key('id', TRUE); + $this->dbforge->add_key('userid'); + + $this->dbforge->create_table('awardxuser'); + + // Insert default records for all existing users (all awards enabled by default) + $this->db->query("INSERT INTO awardxuser (userid, cq, dok, dxcc, ffma, iota, gridmaster_dl, gridmaster_lx, gridmaster_ja, gridmaster_us, gridmaster_uk, gmdxsummer, pota, sig, sota, uscounties, vucc, wab, waja, was, wwff) + SELECT user_id, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 FROM users;"); + } + } + + public function down() + { + $this->dbforge->drop_table('awardxuser'); + } +} diff --git a/application/migrations/238_tag_2_8_2.php b/application/migrations/238_tag_2_8_2.php new file mode 100644 index 000000000..6cd5568ff --- /dev/null +++ b/application/migrations/238_tag_2_8_2.php @@ -0,0 +1,30 @@ +db->where('option_name', 'version'); + $this->db->update('options', array('option_value' => '2.8.2')); + + // Trigger Version Info Dialog + $this->db->where('option_type', 'version_dialog'); + $this->db->where('option_name', 'confirmed'); + $this->db->update('user_options', array('option_value' => 'false')); + + } + + public function down() + { + $this->db->where('option_name', 'version'); + $this->db->update('options', array('option_value' => '2.8.1')); + } +} \ No newline at end of file diff --git a/application/models/Awards_model.php b/application/models/Awards_model.php new file mode 100644 index 000000000..72c1bbb46 --- /dev/null +++ b/application/models/Awards_model.php @@ -0,0 +1,180 @@ +db->from('awardxuser'); + $this->db->where('userid', $this->session->userdata('user_id')); + $result = $this->db->get(); + + if ($result->num_rows() > 0) { + return $result->row(); + } + + // If no preferences exist, create default ones + $this->create_default_awards(); + return $this->get_user_awards(); + } + + /** + * Create default award preferences for current user + */ + function create_default_awards() { + $data = array( + 'userid' => $this->session->userdata('user_id'), + 'cq' => 1, + 'dok' => 1, + 'dxcc' => 1, + 'ffma' => 1, + 'iota' => 1, + 'gridmaster_dl' => 1, + 'gridmaster_lx' => 1, + 'gridmaster_ja' => 1, + 'gridmaster_us' => 1, + 'gridmaster_uk' => 1, + 'gmdxsummer' => 1, + 'pota' => 1, + 'sig' => 1, + 'sota' => 1, + 'uscounties' => 1, + 'vucc' => 1, + 'wab' => 1, + 'waja' => 1, + 'was' => 1, + 'wwff' => 1, + ); + + $this->db->insert('awardxuser', $data); + } + + /** + * Save a single award preference for current user + * @param string $award_type The award type (e.g., 'cq', 'dxcc', 'pota') + * @param mixed $value The value (true/false or 1/0) + */ + function save_single_award($award_type, $value) { + // Validate award type to prevent SQL injection + $valid_awards = array( + 'cq', 'dok', 'dxcc', 'ffma', 'iota', + 'gridmaster_dl', 'gridmaster_lx', 'gridmaster_ja', 'gridmaster_us', 'gridmaster_uk', + 'gmdxsummer', 'pota', 'sig', 'sota', 'uscounties', 'vucc', 'wab', 'waja', 'was', 'wwff' + ); + + if (!in_array($award_type, $valid_awards)) { + return false; + } + + $data = array( + $award_type => ($value == "true" || $value == "1" || $value === true) ? '1' : '0' + ); + + $this->db->where('userid', $this->session->userdata('user_id')); + $this->db->update('awardxuser', $data); + + return true; + } + + /** + * Save award preferences for current user + * @param array $awards Array of award settings + */ + function save_awards($awards) { + $data = array( + 'cq' => $awards['cq'] == "true" ? '1' : '0', + 'dok' => $awards['dok'] == "true" ? '1' : '0', + 'dxcc' => $awards['dxcc'] == "true" ? '1' : '0', + 'ffma' => $awards['ffma'] == "true" ? '1' : '0', + 'iota' => $awards['iota'] == "true" ? '1' : '0', + 'gridmaster_dl' => $awards['gridmaster_dl'] == "true" ? '1' : '0', + 'gridmaster_lx' => $awards['gridmaster_lx'] == "true" ? '1' : '0', + 'gridmaster_ja' => $awards['gridmaster_ja'] == "true" ? '1' : '0', + 'gridmaster_us' => $awards['gridmaster_us'] == "true" ? '1' : '0', + 'gridmaster_uk' => $awards['gridmaster_uk'] == "true" ? '1' : '0', + 'gmdxsummer' => $awards['gmdxsummer'] == "true" ? '1' : '0', + 'pota' => $awards['pota'] == "true" ? '1' : '0', + 'sig' => $awards['sig'] == "true" ? '1' : '0', + 'sota' => $awards['sota'] == "true" ? '1' : '0', + 'uscounties' => $awards['uscounties'] == "true" ? '1' : '0', + 'vucc' => $awards['vucc'] == "true" ? '1' : '0', + 'wab' => $awards['wab'] == "true" ? '1' : '0', + 'waja' => $awards['waja'] == "true" ? '1' : '0', + 'was' => $awards['was'] == "true" ? '1' : '0', + 'wwff' => $awards['wwff'] == "true" ? '1' : '0', + ); + + $this->db->where('userid', $this->session->userdata('user_id')); + $this->db->update('awardxuser', $data); + + return true; + } + + /** + * Activate all awards for current user + */ + function activateall() { + $data = array( + 'cq' => 1, + 'dok' => 1, + 'dxcc' => 1, + 'ffma' => 1, + 'iota' => 1, + 'gridmaster_dl' => 1, + 'gridmaster_lx' => 1, + 'gridmaster_ja' => 1, + 'gridmaster_us' => 1, + 'gridmaster_uk' => 1, + 'gmdxsummer' => 1, + 'pota' => 1, + 'sig' => 1, + 'sota' => 1, + 'uscounties' => 1, + 'vucc' => 1, + 'wab' => 1, + 'waja' => 1, + 'was' => 1, + 'wwff' => 1, + ); + + $this->db->where('userid', $this->session->userdata('user_id')); + $this->db->update('awardxuser', $data); + + return true; + } + + /** + * Deactivate all awards for current user + */ + function deactivateall() { + $data = array( + 'cq' => 0, + 'dok' => 0, + 'dxcc' => 0, + 'ffma' => 0, + 'iota' => 0, + 'gridmaster_dl' => 0, + 'gridmaster_lx' => 0, + 'gridmaster_ja' => 0, + 'gridmaster_us' => 0, + 'gridmaster_uk' => 0, + 'gmdxsummer' => 0, + 'pota' => 0, + 'sig' => 0, + 'sota' => 0, + 'uscounties' => 0, + 'vucc' => 0, + 'wab' => 0, + 'waja' => 0, + 'was' => 0, + 'wwff' => 0, + ); + + $this->db->where('userid', $this->session->userdata('user_id')); + $this->db->update('awardxuser', $data); + + return true; + } +} diff --git a/application/models/Distances_model.php b/application/models/Distances_model.php index d2e26e001..17a8514d7 100644 --- a/application/models/Distances_model.php +++ b/application/models/Distances_model.php @@ -254,7 +254,11 @@ public function qso_details($distance, $band, $sat, $mode, $power, $propag){ $this->db->join('station_profile', 'station_profile.station_id = '.$this->config->item('table_name').'.station_id'); $this->db->join('dxcc_entities', 'dxcc_entities.adif = '.$this->config->item('table_name').'.COL_DXCC', 'left outer'); - $this->db->join('lotw_users', 'lotw_users.callsign = '.$this->config->item('table_name').'.col_call', 'left outer'); + $this->db->join('( + SELECT callsign, MAX(lastupload) AS lastupload + FROM lotw_users + GROUP BY callsign + ) lotw', 'lotw.callsign = '.$this->config->item('table_name').'.col_call', 'left', false); $this->db->where('COL_DISTANCE >=', $distarray[0]); $this->db->where('COL_DISTANCE <=', $distarray[1]); $this->db->where('LENGTH(col_gridsquare) >', 0); diff --git a/application/models/Logbook_model.php b/application/models/Logbook_model.php index bfdd2f920..897b958fe 100755 --- a/application/models/Logbook_model.php +++ b/application/models/Logbook_model.php @@ -404,7 +404,11 @@ public function qso_details($searchphrase, $band, $mode, $type, $qsl, $searchmod $this->db->join('station_profile', 'station_profile.station_id = ' . $this->config->item('table_name') . '.station_id'); $this->db->join('dxcc_entities', 'dxcc_entities.adif = ' . $this->config->item('table_name') . '.COL_DXCC', 'left outer'); - $this->db->join('lotw_users', 'lotw_users.callsign = ' . $this->config->item('table_name') . '.col_call', 'left outer'); + $this->db->join('( + SELECT callsign, MAX(lastupload) AS lastupload + FROM lotw_users + GROUP BY callsign + ) lotw', 'lotw.callsign = ' . $this->config->item('table_name') . '.col_call', 'left', false); switch ($type) { case 'DXCC': $this->db->where('COL_COUNTRY', $searchphrase); @@ -547,7 +551,7 @@ public function activated_grids_qso_details($searchphrase, $band, $mode) $sql .= 'INNER JOIN ' . $this->config->item('table_name') . ' qsos ON qsos.COL_PRIMARY_KEY = FilteredIDs.COL_PRIMARY_KEY '; $sql .= 'JOIN `station_profile` ON station_profile.station_id = qsos.station_id '; $sql .= 'LEFT OUTER JOIN `dxcc_entities` ON dxcc_entities.adif = qsos.COL_DXCC '; - $sql .= 'LEFT OUTER JOIN `lotw_users` ON lotw_users.callsign = qsos.COL_CALL '; + $sql .= 'LEFT OUTER JOIN (SELECT callsign, MAX(lastupload) AS lastupload FROM lotw_users GROUP BY callsign) lotw ON lotw.callsign = qsos.COL_CALL '; $sql .= 'ORDER BY qsos.COL_TIME_ON DESC'; return $this->db->query($sql); @@ -597,7 +601,11 @@ public function activator_details($call, $band, $leogeo) $this->db->join('station_profile', 'station_profile.station_id = ' . $this->config->item('table_name') . '.station_id'); $this->db->join('dxcc_entities', 'dxcc_entities.adif = ' . $this->config->item('table_name') . '.COL_DXCC', 'left outer'); - $this->db->join('lotw_users', 'lotw_users.callsign = ' . $this->config->item('table_name') . '.col_call', 'left outer'); + $this->db->join('( + SELECT callsign, MAX(lastupload) AS lastupload + FROM lotw_users + GROUP BY callsign + ) lotw', 'lotw.callsign = ' . $this->config->item('table_name') . '.col_call', 'left', false); $this->db->where('COL_CALL', $call); if ($band != 'All') { if ($band == 'SAT') { @@ -1819,7 +1827,7 @@ function get_qsos($num, $offset, $StationLocationsArray = null) $location_list = "'" . implode("','", $logbooks_locations_array) . "'"; // Use optimized subquery approach for better performance - $sql = "SELECT qsos.*, station_profile.*, dxcc_entities.*, lotw_users.callsign, lotw_users.lastupload + $sql = "SELECT qsos.*, station_profile.*, dxcc_entities.*, lotw.callsign, lotw.lastupload FROM ( SELECT DISTINCT COL_PRIMARY_KEY, COL_TIME_ON FROM " . $this->config->item('table_name') . " qsos_inner @@ -1831,7 +1839,11 @@ function get_qsos($num, $offset, $StationLocationsArray = null) INNER JOIN " . $this->config->item('table_name') . " qsos ON qsos.COL_PRIMARY_KEY = FilteredIDs.COL_PRIMARY_KEY INNER JOIN station_profile ON qsos.station_id = station_profile.station_id LEFT JOIN dxcc_entities ON qsos.col_dxcc = dxcc_entities.adif - LEFT OUTER JOIN lotw_users ON qsos.col_call = lotw_users.callsign + LEFT OUTER JOIN ( + SELECT callsign, MAX(lastupload) AS lastupload + FROM lotw_users + GROUP BY callsign + ) AS lotw ON qsos.col_call = lotw.callsign ORDER BY qsos.COL_TIME_ON DESC, qsos.COL_PRIMARY_KEY DESC"; return $this->db->query($sql); @@ -1840,13 +1852,17 @@ function get_qsos($num, $offset, $StationLocationsArray = null) function get_qso($id, $trusted = false) { if ($trusted || ($this->logbook_model->check_qso_is_accessible($id))) { - $this->db->select($this->config->item('table_name') . '.*, station_profile.*, dxcc_entities.*, coalesce(dxcc_entities_2.name, "- NONE -") as station_country, dxcc_entities_2.end as station_end, eQSL_images.image_file as eqsl_image_file, lotw_users.callsign as lotwuser, lotw_users.lastupload'); + $this->db->select($this->config->item('table_name') . '.*, station_profile.*, dxcc_entities.*, coalesce(dxcc_entities_2.name, "- NONE -") as station_country, dxcc_entities_2.end as station_end, eQSL_images.image_file as eqsl_image_file, lotw.callsign as lotwuser, lotw.lastupload'); $this->db->from($this->config->item('table_name')); $this->db->join('dxcc_entities', $this->config->item('table_name') . '.col_dxcc = dxcc_entities.adif', 'left'); $this->db->join('station_profile', 'station_profile.station_id = ' . $this->config->item('table_name') . '.station_id', 'left'); $this->db->join('dxcc_entities as dxcc_entities_2', 'station_profile.station_dxcc = dxcc_entities_2.adif', 'left outer'); $this->db->join('eQSL_images', $this->config->item('table_name') . '.COL_PRIMARY_KEY = eQSL_images.qso_id', 'left outer'); - $this->db->join('lotw_users', $this->config->item('table_name') . '.COL_CALL = lotw_users.callsign', 'left outer'); + $this->db->join('( + SELECT callsign, MAX(lastupload) AS lastupload + FROM lotw_users + GROUP BY callsign + ) lotw', $this->config->item('table_name') . '.COL_CALL = lotw.callsign', 'left', false); $this->db->where('COL_PRIMARY_KEY', $id); return $this->db->get(); @@ -4976,7 +4992,11 @@ function county_qso_details($state, $county) $logbooks_locations_array = $CI->logbooks_model->list_logbook_relationships($this->session->userdata('active_station_logbook')); $this->db->join('station_profile', 'station_profile.station_id = ' . $this->config->item('table_name') . '.station_id'); - $this->db->join('lotw_users', 'lotw_users.callsign = ' . $this->config->item('table_name') . '.col_call', 'left outer'); + $this->db->join('( + SELECT callsign, MAX(lastupload) AS lastupload + FROM lotw_users + GROUP BY callsign + ) lotw', 'lotw.callsign = ' . $this->config->item('table_name') . '.col_call', 'left', false); $this->db->where_in($this->config->item('table_name') . '.station_id', $logbooks_locations_array); $this->db->where('COL_STATE', $state); $this->db->where('COL_CNTY', $county); @@ -4992,7 +5012,11 @@ function wab_qso_details($wab) $logbooks_locations_array = $CI->logbooks_model->list_logbook_relationships($this->session->userdata('active_station_logbook')); $this->db->join('station_profile', 'station_profile.station_id = ' . $this->config->item('table_name') . '.station_id'); - $this->db->join('lotw_users', 'lotw_users.callsign = ' . $this->config->item('table_name') . '.col_call', 'left outer'); + $this->db->join('( + SELECT callsign, MAX(lastupload) AS lastupload + FROM lotw_users + GROUP BY callsign + ) lotw', 'lotw.callsign = ' . $this->config->item('table_name') . '.col_call', 'left', false); $this->db->where_in($this->config->item('table_name') . '.station_id', $logbooks_locations_array); $this->db->where('COL_SIG', "WAB"); $this->db->where('COL_SIG_INFO', $wab); diff --git a/application/models/Logbookadvanced_model.php b/application/models/Logbookadvanced_model.php index 1b830e00a..feae66d71 100644 --- a/application/models/Logbookadvanced_model.php +++ b/application/models/Logbookadvanced_model.php @@ -220,7 +220,7 @@ public function searchDb($searchCriteria) { } $sql = " - SELECT qsos.*, station_profile.*, dxcc_entities.*, lotw_users.callsign, lotw_users.lastupload, x.qslcount + SELECT qsos.*, station_profile.*, dxcc_entities.*, lotw.callsign, lotw.lastupload, x.qslcount FROM ( SELECT qsos_inner.COL_PRIMARY_KEY FROM " . $this->config->item('table_name') . " qsos_inner @@ -233,7 +233,11 @@ public function searchDb($searchCriteria) { INNER JOIN " . $this->config->item('table_name') . " qsos ON qsos.COL_PRIMARY_KEY = FilteredIDs.COL_PRIMARY_KEY INNER JOIN station_profile ON qsos.station_id = station_profile.station_id LEFT OUTER JOIN dxcc_entities ON qsos.col_dxcc = dxcc_entities.adif - LEFT OUTER JOIN lotw_users ON qsos.col_call = lotw_users.callsign + LEFT OUTER JOIN ( + SELECT callsign, MAX(lastupload) AS lastupload + FROM lotw_users + GROUP BY callsign + ) AS lotw ON qsos.col_call = lotw.callsign LEFT OUTER JOIN ( select count(*) as qslcount, qsoid from qsl_images @@ -276,13 +280,17 @@ public function getQsosForAdif($ids, $user_id, $sortorder = null) : object { $order = $this->getSortorder($sortorder); - $sql = " - SELECT qsos.*, d2.*, lotw_users.*, station_profile.*, x.qslcount, dxcc_entities.name AS station_country + $sql = " + SELECT qsos.*, d2.*, lotw.*, station_profile.*, x.qslcount, dxcc_entities.name AS station_country FROM " . $this->config->item('table_name') . " qsos INNER JOIN station_profile ON qsos.station_id = station_profile.station_id LEFT OUTER JOIN dxcc_entities ON qsos.COL_MY_DXCC = dxcc_entities.adif LEFT OUTER JOIN dxcc_entities d2 ON qsos.COL_DXCC = d2.adif - LEFT OUTER JOIN lotw_users ON qsos.col_call=lotw_users.callsign + LEFT OUTER JOIN ( + SELECT callsign, MAX(lastupload) AS lastupload + FROM lotw_users + GROUP BY callsign + ) AS lotw ON qsos.col_call = lotw.callsign LEFT OUTER JOIN ( select count(*) as qslcount, qsoid from qsl_images diff --git a/application/models/User_model.php b/application/models/User_model.php index 4aa8c1969..71cc1d7db 100644 --- a/application/models/User_model.php +++ b/application/models/User_model.php @@ -173,28 +173,28 @@ function add($username, $password, $email, $type, $firstname, $lastname, $callsi 'user_lastname' => xss_clean($lastname), 'user_callsign' => strtoupper(xss_clean($callsign)), 'user_locator' => xss_clean($locator), - 'user_timezone' => xss_clean($timezone), + 'user_timezone' => (int)$timezone, 'user_measurement_base' => xss_clean($measurement), 'user_date_format' => xss_clean($user_date_format), 'user_stylesheet' => xss_clean($user_stylesheet), - 'user_qth_lookup' => xss_clean($user_qth_lookup), - 'user_sota_lookup' => xss_clean($user_sota_lookup), - 'user_wwff_lookup' => xss_clean($user_wwff_lookup), - 'user_pota_lookup' => xss_clean($user_pota_lookup), - 'user_show_notes' => xss_clean($user_show_notes), + 'user_qth_lookup' => (int)$user_qth_lookup, + 'user_sota_lookup' => (int)$user_sota_lookup, + 'user_wwff_lookup' => (int)$user_wwff_lookup, + 'user_pota_lookup' => (int)$user_pota_lookup, + 'user_show_notes' => (int)$user_show_notes, 'user_column1' => xss_clean($user_column1), 'user_column2' => xss_clean($user_column2), 'user_column3' => xss_clean($user_column3), 'user_column4' => xss_clean($user_column4), 'user_column5' => xss_clean($user_column5), - 'user_show_profile_image' => xss_clean($user_show_profile_image), - 'user_previous_qsl_type' => xss_clean($user_previous_qsl_type), - 'user_amsat_status_upload' => xss_clean($user_amsat_status_upload), + 'user_show_profile_image' => (int)$user_show_profile_image, + 'user_previous_qsl_type' => (int)$user_previous_qsl_type, + 'user_amsat_status_upload' => (int)$user_amsat_status_upload, 'user_mastodon_url' => xss_clean($user_mastodon_url), 'user_default_band' => xss_clean($user_default_band), 'user_default_confirmation' => xss_clean($user_default_confirmation), - 'user_qso_end_times' => xss_clean($user_qso_end_times), - 'user_quicklog' => xss_clean($user_quicklog), + 'user_qso_end_times' => (int)$user_qso_end_times, + 'user_quicklog' => (int)$user_quicklog, 'user_quicklog_enter' => xss_clean($user_quicklog_enter), 'language' => xss_clean($language), 'user_eqsl_qth_nickname' => "", @@ -214,6 +214,7 @@ function add($username, $password, $email, $type, $firstname, $lastname, $callsi $this->db->insert($this->config->item('auth_table'), $data); $insert_id = $this->db->insert_id(); $this->db->query("insert into bandxuser (bandid, userid, active, cq, dok, dxcc, iota, pota, sig, sota, uscounties, was, wwff, vucc) select bands.id, " . $insert_id . ", 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 from bands;"); + $this->db->query("insert into awardxuser (userid, cq, dok, dxcc, ffma, iota, gridmaster_dl, gridmaster_lx, gridmaster_ja, gridmaster_us, gridmaster_uk, gmdxsummer, pota, sig, sota, uscounties, vucc, wab, waja, was, wwff) values (" . $insert_id . ", 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);"); $this->db->query("insert into paper_types (user_id,paper_name,metric,width,orientation,height) SELECT ".$insert_id.", paper_name, metric, width, orientation,height FROM paper_types where user_id = -1;"); $this->db->query("insert into user_options (user_id, option_type, option_name, option_key, option_value) values (" . $insert_id . ", 'hamsat','hamsat_key','api','".xss_clean($user_hamsat_key)."');"); $this->db->query("insert into user_options (user_id, option_type, option_name, option_key, option_value) values (" . $insert_id . ", 'hamsat','hamsat_key','workable','".xss_clean($user_hamsat_workable_only)."');"); @@ -268,8 +269,8 @@ function edit($fields) { 'user_column4' => xss_clean($fields['user_column4']), 'user_column5' => xss_clean($fields['user_column5']), 'user_show_profile_image' => xss_clean($fields['user_show_profile_image']), - 'user_previous_qsl_type' => xss_clean($fields['user_previous_qsl_type']), - 'user_amsat_status_upload' => xss_clean($fields['user_amsat_status_upload']), + 'user_previous_qsl_type' => (int)$fields['user_previous_qsl_type'], + 'user_amsat_status_upload' => (int)$fields['user_amsat_status_upload'], 'user_mastodon_url' => xss_clean($fields['user_mastodon_url']), 'user_default_band' => xss_clean($fields['user_default_band']), 'user_default_confirmation' => (isset($fields['user_default_confirmation_qsl']) ? 'Q' : '').(isset($fields['user_default_confirmation_lotw']) ? 'L' : '').(isset($fields['user_default_confirmation_eqsl']) ? 'E' : '').(isset($fields['user_default_confirmation_qrz']) ? 'Z' : ''), diff --git a/application/views/awards/settings.php b/application/views/awards/settings.php new file mode 100644 index 000000000..832655915 --- /dev/null +++ b/application/views/awards/settings.php @@ -0,0 +1,239 @@ +
+ +
+ session->flashdata('message')) { ?> + +
+

session->flashdata('message'); ?>

+
+ + + + +

Award Settings

+ + +
+
+
Award Preferences
+
+
+ + +

+ Using this list you can control which awards are shown in the Awards menu. +

+

+ Active awards will be shown in the menu, while inactive awards will be hidden. +

+
+
+ + +
+
+
+
Awards Configuration
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Show in MenuAward NameDescription
+ cq == 1) echo 'checked'; ?>> + CQ MagazineCQ Magazine DX Awards
+ dok == 1) echo 'checked'; ?>> + DOKDiplom Ortsverbände Kennung (German Districts)
+ dxcc == 1) echo 'checked'; ?>> + DXCCDX Century Club
+ ffma == 1) echo 'checked'; ?>> + FFMAFred Fish Memorial Award
+ iota == 1) echo 'checked'; ?>> + IOTAIslands On The Air
Gridmaster Awards
+ gridmaster_dl == 1) echo 'checked'; ?>> + Gridmaster DLGerman Gridmaster Award
+ gridmaster_lx == 1) echo 'checked'; ?>> + Gridmaster LXLuxembourg Gridmaster Award
+ gridmaster_ja == 1) echo 'checked'; ?>> + Gridmaster JAJapanese Gridmaster Award
+ gridmaster_us == 1) echo 'checked'; ?>> + Gridmaster USUnited States Gridmaster Award
+ gridmaster_uk == 1) echo 'checked'; ?>> + Gridmaster UKUnited Kingdom Gridmaster Award
+ gmdxsummer == 1) echo 'checked'; ?>> + GMDX Summer ChallengeGMDX Summer Challenge Award
+ pota == 1) echo 'checked'; ?>> + POTAParks on the Air
+ sig == 1) echo 'checked'; ?>> + SIGSpecial Interest Group
+ sota == 1) echo 'checked'; ?>> + SOTASummits on the Air
+ uscounties == 1) echo 'checked'; ?>> + US CountiesUnited States Counties Award
+ vucc == 1) echo 'checked'; ?>> + VUCCVHF/UHF Century Club
+ wab == 1) echo 'checked'; ?>> + WABWorked All Britain
+ waja == 1) echo 'checked'; ?>> + WAJAWorked All Japan
+ was == 1) echo 'checked'; ?>> + WASWorked All States
+ wwff == 1) echo 'checked'; ?>> + WWFFWorld Wide Flora and Fauna
+
+
+

+ + +

+
+
+ +
diff --git a/application/views/interface_assets/footer.php b/application/views/interface_assets/footer.php index a3f794cd6..4f9fc5de1 100644 --- a/application/views/interface_assets/footer.php +++ b/application/views/interface_assets/footer.php @@ -3187,6 +3187,10 @@ function displayActivatorsContacts(call, band, leogeo) { +uri->segment(1) == "award") { ?> + + + uri->segment(1) == "accumulated") { ?> diff --git a/application/views/interface_assets/header.php b/application/views/interface_assets/header.php index 2dde290d7..05b2ee5da 100644 --- a/application/views/interface_assets/header.php +++ b/application/views/interface_assets/header.php @@ -144,53 +144,101 @@ - -