log_repository = new MessageLogRepository(); $this->settings_repository = new SettingsRepository(); } /** * Sync SMS and Viber statuses. * * @return array{sms:int,viber:int} */ public function sync(): array { return array( 'sms' => $this->sync_channel( 'sms' ), 'viber' => $this->sync_channel( 'viber' ), ); } /** * Sync one channel. * * @param string $channel Channel. */ private function sync_channel( string $channel ): int { $logs = $this->log_repository->get_sync_candidates( $channel, 50 ); if ( empty( $logs ) ) { PluginLogger::log( 'info', 'status_sync_skipped', __( 'No delivery status sync candidates found.', 'inteltele' ), array( 'channel' => $channel ), 'StatusSync' ); return 0; } $settings = $this->settings_repository->get_all(); $client = ClientFactory::create( $settings ); $message_ids = array(); $by_id = array(); foreach ( $logs as $log ) { $message_id = (string) $log->api_message_id; if ( '' === $message_id ) { continue; } $message_ids[] = $message_id; $by_id[ $message_id ] = $log; } if ( empty( $message_ids ) ) { PluginLogger::log( 'warning', 'status_sync_no_message_ids', __( 'Status sync candidates do not have API message IDs.', 'inteltele' ), array( 'channel' => $channel, 'count' => count( $logs ), ), 'StatusSync' ); return 0; } $result = 'viber' === $channel ? $client->get_viber_statuses( $message_ids ) : $client->get_sms_statuses( $message_ids ); if ( ! $result->is_success() ) { PluginLogger::log( 'error', 'status_sync_failed', $result->get_error(), array( 'channel' => $channel, 'message_ids' => $message_ids, 'http_status' => $result->get_status_code(), 'api_response' => $result->get_raw(), ), 'StatusSync' ); return 0; } $statuses = $this->normalize_status_response( $result->get( 'statuses', array() ) ); $updated = 0; foreach ( $statuses as $message_id => $items ) { if ( ! isset( $by_id[ $message_id ] ) || empty( $items ) ) { continue; } $latest = end( $items ); if ( ! is_array( $latest ) || empty( $latest['status'] ) ) { continue; } $api_status = (string) $latest['status']; $date = isset( $latest['date'] ) ? (string) $latest['date'] : ''; if ( $this->log_repository->update_delivery_status( (int) $by_id[ $message_id ]->id, $api_status, StatusMapper::to_internal( $api_status ), $date ) ) { $updated++; } } PluginLogger::log( 'info', 'status_sync_completed', __( 'Delivery status sync completed.', 'inteltele' ), array( 'channel' => $channel, 'checked' => count( $message_ids ), 'updated' => $updated, ), 'StatusSync' ); return $updated; } /** * Normalize API status response. * * @param mixed $raw Raw statuses. * @return array>> */ private function normalize_status_response( $raw ): array { $result = array(); if ( ! is_array( $raw ) ) { return $result; } foreach ( $raw as $key => $value ) { if ( is_string( $key ) && is_array( $value ) ) { $result[ $key ] = $value; continue; } if ( is_array( $value ) ) { foreach ( $value as $message_id => $items ) { if ( is_string( $message_id ) && is_array( $items ) ) { $result[ $message_id ] = $items; } } } } return $result; } }