register_hooks(); $menu->register_hooks(); } if ( class_exists( 'WooCommerce' ) ) { $status_listener = new WooCommerceStatusListener(); $status_listener->register_hooks(); add_filter( 'woocommerce_checkout_fields', array( __CLASS__, 'add_checkout_phone_notice' ) ); } add_filter( 'cron_schedules', array( __CLASS__, 'add_cron_schedules' ) ); add_action( 'inteltele_sync_statuses', array( __CLASS__, 'sync_statuses' ) ); add_action( 'inteltele_process_fallbacks', array( __CLASS__, 'process_fallbacks' ) ); add_action( 'inteltele_process_campaigns', array( __CLASS__, 'process_campaigns' ) ); add_action( 'rest_api_init', array( __CLASS__, 'register_rest_routes' ) ); add_action( 'init', array( __CLASS__, 'ensure_recurring_events' ) ); } /** * Add cron schedules. * * @param array> $schedules Schedules. * @return array> */ public static function add_cron_schedules( array $schedules ): array { $schedules['five_minutes'] = array( 'interval' => 300, 'display' => __( 'Every five minutes', 'inteltele' ), ); return $schedules; } /** * Sync statuses from cron. */ public static function sync_statuses(): void { $sync = new StatusSync(); $sync->sync(); } /** * Process fallbacks from cron. */ public static function process_fallbacks(): void { $processor = new ViberFallbackProcessor(); $processor->process(); } /** * Process pending bulk campaigns from cron. */ public static function process_campaigns(): void { $processor = new CampaignProcessor(); $processor->process_pending_campaigns(); } /** * Register REST routes. */ public static function register_rest_routes(): void { register_rest_route( 'inteltele/v1', '/delivery-status', array( 'methods' => 'POST', 'callback' => array( __CLASS__, 'handle_delivery_status_webhook' ), 'permission_callback' => array( DeliveryStatusWebhook::class, 'authorize' ), ) ); } /** * Handle delivery status webhook. * * @param \WP_REST_Request $request REST request. */ public static function handle_delivery_status_webhook( \WP_REST_Request $request ): \WP_REST_Response { $handler = new DeliveryStatusWebhook(); $payload = $request->get_json_params(); if ( null === $payload ) { $payload = $request->get_body_params(); } $query_params = $request->get_query_params(); unset( $query_params['inteltele_token'] ); $result = $handler->handle( $payload ); $logger = new WebhookLogRepository(); $logger->insert( array( 'route' => $request->get_route(), 'method' => $request->get_method(), 'remote_addr' => isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '', 'content_type' => $request->get_content_type()['value'] ?? '', 'headers' => self::get_safe_webhook_headers( $request ), 'query_params' => $query_params, 'payload' => $payload, 'raw_body' => $request->get_body(), 'result' => $result, 'status' => empty( $result['errors'] ) ? 'processed' : 'processed_with_errors', ) ); return new \WP_REST_Response( array( 'success' => true, 'result' => $result, ), 200 ); } /** * Get request headers with sensitive values redacted. * * @param \WP_REST_Request $request REST request. * @return array */ private static function get_safe_webhook_headers( \WP_REST_Request $request ): array { $headers = $request->get_headers(); foreach ( array( 'authorization', 'cookie', 'x_api_key', 'x-api-key', 'x_inteltele_token', 'x-inteltele-token' ) as $key ) { if ( isset( $headers[ $key ] ) ) { $headers[ $key ] = array( '[redacted]' ); } } return $headers; } /** * Ensure recurring events exist for already activated installs. */ public static function ensure_recurring_events(): void { foreach ( array( 'inteltele_sync_statuses', 'inteltele_process_fallbacks', 'inteltele_process_campaigns' ) as $hook ) { if ( ! wp_next_scheduled( $hook ) ) { wp_schedule_event( time() + 300, 'five_minutes', $hook ); } } } /** * Add consent/help text near WooCommerce checkout phone field. * * @param array $fields Checkout fields. * @return array */ public static function add_checkout_phone_notice( array $fields ): array { if ( isset( $fields['billing']['billing_phone'] ) && is_array( $fields['billing']['billing_phone'] ) ) { $fields['billing']['billing_phone']['description'] = __( 'By leaving your phone number, you agree to receive SMS and Viber messages about your order.', 'inteltele' ); } return $fields; } /** * Seed default WooCommerce message templates. */ public static function seed_default_templates(): void { if ( ! current_user_can( 'inteltele_manage' ) ) { return; } $repository = new TemplateRepository(); $repository->seed_defaults( get_current_user_id() ); } /** * Declare WooCommerce HPOS compatibility. */ public static function declare_hpos_compatibility(): void { if ( ! class_exists( '\Automattic\WooCommerce\Utilities\FeaturesUtil' ) ) { return; } \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', INTELTELE_FILE, true ); } }