*/ private $event_sent_phones = array(); /** * Constructor. */ public function __construct() { $this->settings_repository = new SettingsRepository(); $this->template_repository = new TemplateRepository(); $this->template_renderer = new TemplateRenderer(); $this->sender = new MessageSender(); $this->duplicate_guard = new DuplicateGuard(); } /** * Register hooks. */ public function register_hooks(): void { add_action( 'woocommerce_order_status_changed', array( $this, 'handle_status_changed' ), 20, 4 ); } /** * Handle WooCommerce status change. * * @param int $order_id Order ID. * @param string $from From status without wc- prefix. * @param string $to To status without wc- prefix. * @param mixed $order Order object. */ public function handle_status_changed( int $order_id, string $from, string $to, $order ): void { if ( ! $order || ! is_object( $order ) ) { return; } $status_key = 'wc-' . $to; $enabled = $this->settings_repository->get_wc_statuses(); $this->event_sent_phones = array(); if ( in_array( $status_key, $enabled['customer'], true ) ) { $this->send_to_customer( $order_id, $status_key, $order ); } if ( in_array( $status_key, $enabled['admin'], true ) ) { $this->send_to_managers( $order_id, $status_key, $order ); } } /** * Send customer notification. * * @param int $order_id Order ID. * @param string $status_key Status key. * @param mixed $order Order. */ private function send_to_customer( int $order_id, string $status_key, $order ): void { $phone = $this->normalize_phone( $this->call_order_getter( $order, 'get_billing_phone' ) ); if ( '' === $phone ) { $this->log_error( __( 'Customer phone is empty. Order status message was not sent.', 'inteltele' ) ); return; } $name = trim( $this->call_order_getter( $order, 'get_billing_first_name' ) . ' ' . $this->call_order_getter( $order, 'get_billing_last_name' ) ); $this->send_by_templates( 'customer', $order_id, $status_key, $order, $phone, $name ); } /** * Send manager notifications. * * @param int $order_id Order ID. * @param string $status_key Status key. * @param mixed $order Order. */ private function send_to_managers( int $order_id, string $status_key, $order ): void { $settings = $this->settings_repository->get_all(); $phones = isset( $settings['manager_phones'] ) && is_array( $settings['manager_phones'] ) ? $settings['manager_phones'] : array(); foreach ( $phones as $phone ) { $phone = $this->normalize_phone( (string) $phone ); if ( '' === $phone ) { continue; } $this->send_by_templates( 'admin', $order_id, $status_key, $order, $phone, __( 'Administrator', 'inteltele' ) ); } } /** * Send the active saved template for a recipient type/status. * * @param string $recipient_type Recipient type. * @param int $order_id Order ID. * @param string $status_key Status key. * @param mixed $order Order. * @param string $phone Phone. * @param string $recipient_name Recipient name. */ private function send_by_templates( string $recipient_type, int $order_id, string $status_key, $order, string $phone, string $recipient_name ): void { if ( isset( $this->event_sent_phones[ $phone ] ) ) { return; } $scheme = $this->settings_repository->get_wc_template_scheme( $recipient_type, $status_key ); $template = $this->template_repository->get( $recipient_type, $status_key, $scheme ); if ( ! $template || empty( $template->message ) ) { return; } $message = $this->template_renderer->render( (string) $template->message, $order ); $duplicate_key = DuplicateGuard::build_key( $order_id, $status_key, $phone, $scheme, (string) $template->message ); if ( $this->duplicate_guard->already_sent( $duplicate_key ) ) { return; } $this->sender->send_order_status( $message, $phone, $scheme, array( 'order_id' => $order_id, 'recipient_name' => $recipient_name, 'recipient_role' => $recipient_type, 'duplicate_key' => $duplicate_key, ) ); $this->event_sent_phones[ $phone ] = true; } /** * Normalize phone number. * * @param string $phone Phone. */ private function normalize_phone( string $phone ): string { return (string) preg_replace( '/\D+/', '', $phone ); } /** * Call order getter safely. * * @param mixed $order Order. * @param string $method Method. */ private function call_order_getter( $order, string $method ): string { if ( ! is_object( $order ) || ! method_exists( $order, $method ) ) { return ''; } $value = $order->{$method}(); return is_scalar( $value ) ? (string) $value : ''; } /** * Log error. * * @param string $message Message. */ private function log_error( string $message ): void { if ( function_exists( 'wc_get_logger' ) ) { wc_get_logger()->warning( $message, array( 'source' => 'inteltele', ) ); return; } error_log( 'IntelTele: ' . $message ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log } }