settings_repository = new SettingsRepository(); } /** * Render page. */ public function render(): void { $this->prepare_page(); $notice = $this->handle_submit(); $settings = $this->settings_repository->get_all(); $this->open_page( __( 'Settings', 'inteltele' ) ); $this->render_step_notice(); $this->render_notice( $notice ); echo '
'; wp_nonce_field( 'inteltele_save_settings', 'inteltele_nonce' ); echo ''; $this->render_text_input( 'api_key', __( 'API key', 'inteltele' ), SettingsRepository::mask_api_key( (string) $settings['api_key'] ) ); $this->render_readonly_text( __( 'Balance', 'inteltele' ), $this->format_balance( (string) $settings['balance'] ) ); $this->render_text_input( 'sms_sender', __( 'Alpha-name', 'inteltele' ), (string) $settings['sms_sender'] ); $this->render_text_input( 'viber_sender', __( 'Viber name', 'inteltele' ), (string) $settings['viber_sender'] ); $this->render_manager_phones( is_array( $settings['manager_phones'] ) ? $settings['manager_phones'] : array() ); $this->render_number_input( 'viber_ttl', __( 'Viber + SMS TTL, seconds', 'inteltele' ), (string) $settings['viber_ttl'], 600, 86400 ); $this->render_number_input( 'batch_size', __( 'Bulk campaign batch size', 'inteltele' ), (string) $settings['batch_size'], 1, 200 ); $this->render_webhook_url(); echo ''; echo '

'; echo ' '; echo ''; echo '

'; echo '
'; $this->close_page(); } /** * Handle form submission. * * @return array{type:string,messages:string[]}|null */ private function handle_submit(): ?array { if ( ! $this->is_post_request() ) { return null; } if ( ! current_user_can( 'inteltele_manage' ) ) { return array( 'type' => 'error', 'messages' => array( __( 'You do not have permission to manage IntelTele settings.', 'inteltele' ) ), ); } if ( ! isset( $_POST['inteltele_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['inteltele_nonce'] ) ), 'inteltele_save_settings' ) ) { return array( 'type' => 'error', 'messages' => array( __( 'Security check failed. Please reload the page and try again.', 'inteltele' ) ), ); } $result = $this->settings_repository->sanitize( $_POST, $this->settings_repository->get_all() ); if ( ! empty( $result['errors'] ) ) { return array( 'type' => 'error', 'messages' => $result['errors'], ); } $action = isset( $_POST['inteltele_action'] ) ? sanitize_key( wp_unslash( $_POST['inteltele_action'] ) ) : 'save'; if ( 'check_connection' === $action ) { return $this->handle_connection_check( $result['settings'] ); } if ( ! $this->settings_repository->save( $result['settings'] ) ) { return array( 'type' => 'error', 'messages' => array( __( 'Settings could not be saved. Please try again.', 'inteltele' ) ), ); } return array( 'type' => 'success', 'messages' => array( __( 'Saved.', 'inteltele' ) ), ); } /** * Check API connection and update balance. * * @param array $settings Settings. * @return array{type:string,messages:string[]} */ private function handle_connection_check( array $settings ): array { $client = ClientFactory::create( $settings ); $result = $client->get_balance(); if ( ! $result->is_success() ) { PluginLogger::log( 'error', 'connection_check_failed', $result->get_error(), array( 'http_status' => $result->get_status_code(), 'raw' => $result->get_raw(), ), 'SettingsPage' ); return array( 'type' => 'error', 'messages' => array( __( 'Connection check failed.', 'inteltele' ), $result->get_error(), ), ); } $balance = sanitize_text_field( (string) $result->get( 'balance', '' ) ); $settings['balance'] = $balance; PluginLogger::log( 'info', 'connection_check_success', __( 'API connection checked successfully.', 'inteltele' ), array( 'balance' => $balance, 'http_status' => $result->get_status_code(), ), 'SettingsPage' ); if ( ! $this->settings_repository->save( $settings ) ) { return array( 'type' => 'error', 'messages' => array( __( 'Connection was checked, but settings could not be saved.', 'inteltele' ) ), ); } return array( 'type' => 'success', 'messages' => array( __( 'Connection checked successfully.', 'inteltele' ), sprintf( /* translators: %s: account balance. */ __( 'Balance: %s', 'inteltele' ), '' === $balance ? __( 'not returned by API', 'inteltele' ) : $balance ), ), ); } /** * Render submit notice. * * @param array{type:string,messages:string[]}|null $notice Notice data. */ private function render_notice( ?array $notice ): void { if ( null === $notice ) { return; } $class = 'success' === $notice['type'] ? 'notice-success' : 'notice-error'; echo '
'; foreach ( $notice['messages'] as $message ) { echo '

' . esc_html( $message ) . '

'; } echo '
'; } /** * Render a text input row. * * @param string $name Field name. * @param string $label Field label. * @param string $value Field value. * @param bool $readonly Whether the field is readonly. */ private function render_text_input( string $name, string $label, string $value, bool $readonly = false ): void { echo ''; echo ''; echo ''; echo ''; } /** * Render a number input row. * * @param string $name Field name. * @param string $label Field label. * @param string $value Field value. */ private function render_number_input( string $name, string $label, string $value, int $min, int $max ): void { echo ''; echo ''; echo ''; echo ''; } /** * Render readonly text. * * @param string $label Field label. * @param string $value Field value. */ private function render_readonly_text( string $label, string $value ): void { echo ''; echo '' . esc_html( $label ) . ''; echo '

' . esc_html( $value ) . '

'; echo ''; } /** * Render webhook URL field. */ private function render_webhook_url(): void { $url = DeliveryStatusWebhook::get_url(); echo ''; echo ''; echo ''; echo ' '; echo ''; echo '

' . esc_html__( 'Copy this URL to the IntelTele cabinet for delivery status webhooks.', 'inteltele' ) . '

'; echo ''; echo ''; } /** * Render manager phone fields. */ private function render_manager_phones( array $phones ): void { if ( empty( $phones ) ) { $phones = array( '' ); } echo ''; echo '' . esc_html__( 'Manager phones', 'inteltele' ) . ''; echo ''; echo '
'; foreach ( $phones as $index => $phone ) { if ( $index > 0 ) { echo '
'; } echo ' '; } echo ''; echo '
'; echo '

' . esc_html__( 'Only digits are allowed. Use international format without plus sign.', 'inteltele' ) . '

'; echo ''; echo ''; } /** * Format balance for readonly output. * * @param string $balance Balance. */ private function format_balance( string $balance ): string { return '' === $balance ? __( 'Not checked yet', 'inteltele' ) : $balance; } }