__('Read QSL confirmations')]; } /** * GET /api/v2/confirmation * Filtered list of confirmations, newest first. Clubstation members below * officer level only ever see their own QSOs' confirmations - the operator * restriction mirrors the QSO resource, since a confirmation is reached * through the QSO it belongs to. */ public function index() { $this->CI->load->model('logbook_model'); $types = $this->parse_type_list('type', self::CONFIRMATION_TYPES) ?: self::CONFIRMATION_TYPES; $since = $this->parse_date('since'); $qso_since = $this->parse_date('qso_since'); $qso_until = $this->parse_date('qso_until'); $band = $this->normalize_band($this->param('band')); $mode = $this->normalize_mode($this->param('mode')); $callsign = $this->normalize_callsign($this->param('callsign')); $page = $this->pagination(self::DEFAULT_PER_PAGE, self::MAX_PER_PAGE); $station_ids = $this->resolve_station_ids(); // Same club-member rule as Qso_resource::index(): restricted members // only ever see their own operator's QSOs. $operator = $this->is_restricted_club_member() ? (string) $this->operator_callsign() : ''; $filters = [ 'station_ids' => $station_ids, 'types' => $types, 'since' => $since, 'qso_since' => $qso_since, 'qso_until' => $qso_until, 'band' => $band, 'mode' => $mode, 'callsign' => $callsign, 'operator' => $operator, ]; $total = $this->CI->logbook_model->count_confirmations_list($filters); $query = $this->CI->logbook_model->get_confirmations_list( $filters, $page['per_page'], $page['offset'] ); $rows = is_object($query) ? $query->result() : []; $confirmations = array_map([$this, 'format_confirmation'], $rows); $meta = $this->list_meta($page, count($confirmations), $total); $meta['filters'] = [ 'type' => $types, 'since' => $since ?: null, 'qso_since' => $qso_since ?: null, 'qso_until' => $qso_until ?: null, 'band' => $band ?: null, 'mode' => $mode ?: null, 'callsign' => $callsign ?: null, ]; $this->CI->api_v2_response->respond($confirmations, 200, $meta); } /** * Cast a DB row to its public shape. The model already aliases columns to * these names. Core fields are always present; the optional ones are * omitted entirely when empty so the payload carries only what the QSO * actually has (a HF contact has no sat_*, a gridless one no gridsquare). */ protected function format_confirmation($row) { $out = [ 'qso_id' => (int) $row->qso_id, 'callsign' => $row->callsign, 'qso_date' => $row->qso_date, 'mode' => $row->mode, 'band' => $row->band, 'confirmation_date' => $row->confirmation_date, 'type' => $row->type, ]; foreach (['submode', 'gridsquare', 'vucc_grids', 'sat_name', 'sat_mode'] as $opt) { $value = $row->$opt ?? ''; if ($value !== '' && $value !== null) { $out[$opt] = $value; } } return $out; } }