Introduces a new `station_profile.clublogcron` flag (migration 276) and wires it into station create/edit save flows so users can explicitly enable locations for `/clublog/upload`. Clublog station selection now only includes enabled locations (with fallback to `clublogrealtime` if the new column is not present), and the dashboard shows a warning when Clublog credentials exist but no station is enabled. It also tightens Clublog upload-status query grouping and fixes `Clublog::uploadall` return flow so upload results are returned consistently.
Adds migration 275 to convert eQSL password columns to TEXT and encrypt existing user/mapping passwords with an `enc:` prefix. Updates eQSL controller/model flows to decrypt on read, encrypt on create/update, and keep plaintext backward compatibility for legacy rows. User profile updates now avoid reusing stored ciphertext when no new password is submitted, and mapping updates report a clear error if secure password storage fails.
Updates the migration target to 273 and adds a new migration to tag Cloudlog as 2.8.16. The migration sets `options.version` to `2.8.16` and resets `user_options` version dialog confirmation so users see the version info dialog; the down migration restores the version value to `2.8.15`.
Bumps the configured migration target to 272 and adds migration `272_tag_2_8_15`. The new migration updates the app version in `options` to `2.8.15` and resets `user_options` version dialog confirmation so users see release info. The `down()` method rolls the version value back to `2.8.14`.
Update migration_version to 271 and add Migration_tag_2_8_14. The new migration sets options.version to 2.8.14 and resets user_options (version_dialog/confirmed) to 'false' to trigger the version info dialog for users. The down() method reverts options.version back to 2.8.13.
Introduce an experimental browser-based remote audio feature: bump migration version to 270 and add a migration to add a remote_operation flag to the users table. Add server-side support to User and QSO controllers/models to read/save the remote_operation option (stored via user_options_model) and expose isRemoteOperationEnabled to views and session updates. Add UI: a Remote Operation card on the QSO page, a modal component for detailed settings, a toggle in the user edit page, and conditional loading of assets/js/remote-operation.js. Add a large client-side implementation (assets/js/remote-operation.js) implementing WebRTC signalling, device selection, level meters and diagnostics. Minor session/session-update and helper changes to keep UI state in sync.
Bump migration version to 269, add TEVEL2-1..TEVEL2-9 entries to the Lotw satellite mapping, and add migration 269_set_tevel2_series_to_notsent. The migration sets COL_LOTW_QSL_SENT = 'N' for TEVEL2-1 through TEVEL2-9 so their QSOs are marked not-sent to LoTW; down() is intentionally empty since previous per-QSO sent state cannot be safely restored.
Introduce a plugin framework and management UI: adds Plugin Manager controller, Plugin_awards controller, Plugin_manager and Cloudlog_hooks libraries, Plugins_model, migration (268) to create the plugins table, and views for plugin manager and award pages. Integrates hooks into Logbook_model (qso.filter.before_save, qso.action.after_save, qso.action.after_edit), updates header to show award plugin entries and a Plugin Manager menu link, and bumps migration_version to 268. Also adds .gitignore rules, plugin index placeholder, docs and example plugin packages. The Plugin Manager supports uploading/installing ZIP packages, safe extraction, manifest validation, enable/disable/delete actions, and CSRF protection.
Increment migration_version to 267 and add Migration_tag_2_8_13. The new migration updates the 'options' table to set version = '2.8.13' and resets user_options (version_dialog confirmed) to 'false' to trigger the version info dialog; the down() method reverts the version to '2.8.12'.
Add migration (application/migrations/266_tag_2_8_12.php) to update the stored application version to 2.8.12. The up() method sets options.version to '2.8.12' and resets user_options where option_type='version_dialog' and option_name='confirmed' to 'false' to trigger the version info dialog. The down() method reverts the options.version back to '2.8.11'.
Bump migration version to 265 and add a migration (265_add_station_time_on_index) that creates idx_station_time_on on (station_id, COL_TIME_ON) for faster time-based queries. Introduce lazy QSO loading: controller now sets defer_qso_list and uses a new POST endpoint get_filtered_qsos to fetch filtered QSO lists and summaries; also updated cache keys/render version and added per-entry cache deletion. Note model: add include_qso_list flag, memoize QSO summaries/lists and station IDs, replace DATE(COL_TIME_ON) filters with half-open datetime ranges (start inclusive, end exclusive) via helper methods to improve index use and performance. View: update public_index to render QSO list containers with data attributes, add JS to fetch and render QSO rows on demand, and support highlight DX updates. Overall changes optimize QSO queries and enable deferred loading to reduce initial page load and DB cost.
Bump migration_version to 264 and add Migration_tag_2_8_11. The new migration updates the 'options' table to set version = '2.8.11' and resets users' 'version_dialog' confirmed flag to 'false' to trigger the version info dialog. The down() method reverts the stored version back to '2.8.10'.
Bump migration_version to 263 and add Migration_notes_utf8mb4_columns. The new migration converts the notes table to use utf8mb4 with utf8mb4_unicode_ci to support emoji and other 4-byte characters; down() reverts the table back to utf8 with utf8_general_ci.
Bump migration version to 262 and add Migration_tag_2_8_10 which updates the stored app version to 2.8.10 and forces the version info dialog by resetting the user option. The migration includes a down() to revert the version to 2.8.9. Also update L.Terminator.js to generate three longitude-shifted polygon copies (offsets -360, 0, +360) so the night/day terminator overlay tiles correctly across world copies when the map is zoomed out.
Introduce a new Call History feature: adds Callhistory controller, Callhistory_model, migration (create callhistory_files table) and view for uploading/managing call history files. Implements CSV/TXT upload handling, storage per-user, activation/priority controls, checksum, and server-side lookup that scans active files for matching callsigns. Integrates UI: header menu link, contesting and QSO views show call history results inline, and JavaScript to perform lookups and render results with copy-to-SIG functionality. Also updates .gitignore to exclude uploaded callhistory directory and bumps migration_version to 261.
Add support for comma-separated POTA references across the app: bump migration version to 259 and add migration 260 to expand COL_MY_POTA_REF and station_pota to VARCHAR(255). Introduce Pota::split_refs and collect_refs_from_rows to normalize and aggregate multiple refs; refactor Pota counts to compute unique refs per band/mode. Normalize station_pota when saving in Stations and Logbook_model (uses normalize_pota_refs), and adjust POTA search to match refs inside comma-separated values. Update views to render multiple POTA links and hashtags, and add Selectize-based autocomplete for station POTA input on create/edit forms. Also minor change to user_owns_station query (removed user_id where clause).
Bump migration_version to 258 and add Migration_tag_2_8_9. The migration sets the stored app version to 2.8.9, resets users' 'version_dialog' confirmed flag to false to trigger the version info dialog, and includes a down() to revert the stored version to 2.8.8.
Introduce a reactions feature for public station diary entries. Adds a migration to create station_diary_reactions with indexes and a unique (diary_id, visitor_hash) constraint; bumps migration version to 257 and registers a new route for /entry/:id/react. Controller: implements visitor token/hash creation, a react() endpoint to accept POSTed reactions (like, love, fire), increments/updates reactions, invalidates cache and returns totals and visitor reaction. Model: new methods to get totals, fetch visitor reaction and save/update reactions. View: UI, styles and client-side JS for reaction buttons, counts, and copy/share enhancements; integrates totals and visitor state into the single-entry view.
Introduce Public Station Diary feature and QSO filtering support.
- Add migrations: 255 adds public_station_diary_enabled option (default enabled), 256 adds qso_date_start, qso_date_end, qso_satellite_only columns to notes.
- Bump migration version to 256.
- Add controller actions (Options::public_diary, public_diary_save) and new options view to manage the public diary setting; add sidebar link.
- Extend Note model to persist QSO filter fields and provide new methods to fetch QSO lists/summaries for date ranges and satellite-only filtering; wire filter usage into summary generation.
- Update notes add/edit views to include QSO Summary Filters (date range + satellite-only).
- Add translations for the new options keys across multiple language files.
- Update public station diary listing view styling/path and minor content cleanup; other views updated to support feature.
- Remove obsolete cache files (.htaccess, index.html).
These changes enable admins to toggle a public station diary and let note authors control which QSOs are included in summaries via date ranges and SAT-only filtering.
Introduce public Station Diary functionality: add global config flag, routes, controller, model changes, views and DB migrations. New migrations (252-254) add is_public/include_qso_summary, diary_images table and logbook_id on notes. Notes model updated to handle public flags, diary images, qso summaries, caching (per-user cache version), and helper methods for listing/counting public diary entries. New Stationdiary controller serves paginated public pages and RSS feed with caching. Notes controller updated to handle image uploads, attach images to diary entries, and provide an AJAX endpoint to delete images. Views updated to support public visibility options, logbook selector, image upload UI and Quill editor assets; routes and migration version bumped accordingly. Includes file upload example added to uploads/diary.
Adds migration 251_add_ft2_submode.php which inserts a new 'FT2' submode under mode 'MFSK' into the adif_modes table (qrgmode='DATA', active=1) if it doesn't already exist, and provides a down() to remove it. Also bumps application migration_version to 251. Note: FT2 is not part of the ADIF spec yet.
Bump migration version to 250 and add Migration_tag_2_8_8. The new migration sets the stored app version to 2.8.8 and resets the user's version_dialog confirmation (option_value = 'false') to trigger the version info dialog. The down() method rolls the version back to 2.8.7.
Add per-user/logbook file caching for dashboard statistics (15min TTL) and update Dashboard controller to use cached qso, countries, VUCC and QSL queries. Introduce clear_dashboard_cache() in Logbook_model and call it on QSO create/update/delete to invalidate affected users' cache entries. Add migration (249) to create composite indexes (idx_dxcc_stats, idx_vucc_gridsquare, idx_vucc_grids) to improve dashboard query performance, and bump migration_version to 249. Also include generated cache files under application/cache for current stats.
Replace malformed code with a proper existence check for the 'idx_confirmation_match' index, drop the index with ALTER TABLE if present, and re-enable db_debug. This fixes a syntax/logic error in the migration so the LOTW/QRZ/eQSL confirmation match index is removed safely during migration.
Delete the conditional block that dropped the `idx_gridsquare_prefix` index from the table. Add `$this->db->db_debug = true;` and close out the migration method/class. This prevents the migration from removing the gridsquare prefix index and ensures DB debug mode is restored after the migration.
Add batch processing for eQSL imports/exports and introduce performance indexes. Bump migration_version to 248 and add Migration_add_eqsl_performance_indexes to create idx_eqsl_qslrdate and idx_eqsl_confirmation_match indexes to speed up eQSL queries and batch matching. Modify Eqsl controller to collect successful uploads and perform a single batch mark-as-sent update. Update EqslImporter to queue confirmations and run a single batch update at the end. Implement eqsl_update_batch() and eqsl_mark_sent_batch() in Eqslmethods_model to perform efficient batch DB operations and logging, reducing per-record queries for large eQSL operations.
Replace the specific idx_lotw_confirmation_match index with a generic idx_confirmation_match and update related comments and local variable names. Comments now note the index benefits both LOTW and QRZ processing (import_check, lotw_update_batch, process_qrz_batch). The composite index columns remain (COL_TIME_ON, COL_CALL, COL_BAND, COL_STATION_CALLSIGN); existence checks and add/drop statements were adjusted to use the new name.
Bump migration version to 247 and add a migration that creates performance indexes for LoTW workflows (idx_lotw_qslrdate, idx_lotw_qsos_to_upload, idx_lotw_confirmation_match) to speed common queries. Refactor Lotw controller to collect records in memory, build rows for rendering, and perform a single batch confirmation update via a new Logbook_model::lotw_update_batch() method instead of many individual updates. Implement lotw_update_batch() to look up matching QSOs, perform update_batch() calls, and separately update gridsquares/distances using the Qra library. Simplify LotwCert::toggle_archive_certificate() to toggle archived state with a single UPDATE and return the resulting status.
Bump migration version and add a new migration (246) to create/drop a 4-char prefix index on COL_GRIDSQUARE to speed LIKE queries; migration 245 now also drops the prefix index if present. Add Stations::user_owns_station and use it in Logbookadvanced_model to avoid N+1 station lookups. Add caching to Logbooks_model::list_logbook_relationships to prevent redundant queries. Optimize Oqrs_model queries to select only needed columns for several methods. Add Stats::getUniqueCallsignsConsolidated to combine multiple unique-callsign groupings into a single set of queries for better performance. Database debug toggles added where appropriate.
Improve query performance and memory usage by adding a migration to create several indexes and converting various upload/reporting flows to batched processing. Changes include:
- Add migration 245 to create indexes: idx_mode, idx_sat_name, idx_continent, idx_qsl_stats (composite), idx_hrdlog_upload, idx_qrz_upload to speed common queries.
- Bump migration version to 245 in config.
- Hrdlog and Qrz controllers: switch to fetching QSOs in LIMIT/OFFSET batches, process updates in chunks, add logging for batch progress, and use break 2 to stop outer loops on invalid API keys to avoid continuing work.
- Logbook_model:
- get_hrdlog_qsos and get_qrz_qsos now accept limit/offset and use ORDER BY/LIMIT/OFFSET for batching.
- Replaced a subquery with a JOIN for grid-based filtering to improve performance.
- get_modes rewritten to use query builder (distinct/select/order_by).
- Bulk DXCC updates use update_batch instead of per-row queries.
- calls_without_station_id limited to 500 results to avoid UI hangs.
Overall goal: prevent memory exhaustion with large datasets and improve database query performance.
Bump migration version to 244 and add migration 244_tag_2_8_7. The new migration updates options.version to 2.8.7 and resets user_options.version_dialog.confirmed to false to trigger the version info dialog; the down() method reverts options.version to 2.8.6.
Added migration 243 to tag Cloudlog as version 2.8.6 and updated the migration version in config. Improved SOTA awards table to display a message outside the table when no results are found. Modified the SOTA index page to trigger filter refresh on 'Apply' and adjusted DataTables language options for empty states.
Introduces a migration to add a created_at timestamp to the notes table. Updates the Note model and Notes controller to support filtering notes by creation date, and enhances the notes view to include date filter fields and display the created date for each note. Migration version is incremented to 242.
Introduces migration 241 to update the application version to 2.8.5 and trigger the version info dialog for users. Updates the migration version in the configuration accordingly.
Introduces migration 240 to update the application version to 2.8.4 and trigger the version info dialog for users. Updates migration configuration to reflect the new version.
Introduces migration 239 to update the application version to 2.8.3 and trigger the version info dialog for users. Updates the migration version in the configuration to 239.
Introduces migration 238 to update the application version to 2.8.2 and trigger the version info dialog for users. Updates the migration version in the configuration to 238.
Introduces migration 235 to update the application version to 2.8.0 and trigger the version info dialog for users. Updates migration configuration to use the new migration version.
Introduces logbook sharing with read, write, and admin permission levels via a new station_logbooks_permissions table and related migration. Updates controllers, models, and views to support managing collaborators, restricts sensitive actions to owners/admins, and adds UI for sharing management. Also adds user lookup by callsign and improves logbook/station location access logic.
Introduces migration 233 to update the application version to 2.7.8 and trigger the version info dialog for users. Updates the migration configuration to use the new migration version.
Update migration to use array definitions for new user ClubLog fields instead of raw SQL strings. This improves compatibility and clarity when adding columns to the 'users' table.
Introduces migration 232 to update the application version to 2.7.7 and trigger the version info dialog for users. Updates migration configuration to use the new migration version.
Migration now checks if 'user_clublog_name', 'user_clublog_password', and 'user_clublog_callsign' fields exist before adding them to the 'users' table, preventing errors if fields are already present.