get_gateway() !== 'mail-in' ) { return; } $this->send_instructions_email( $order ); } /** * Handle order status changes * * @since 1.0.0 * @param \TEC\Tickets\Commerce\Order $order Order object * @param string $old_status Previous status * @param string $new_status New status * @return void */ public function handle_status_change( $order, $old_status, $new_status ) { // Only for mail-in payment orders if ( $order->get_gateway() !== 'mail-in' ) { return; } // Send confirmation email when payment is completed if ( $new_status === 'completed' ) { $this->send_confirmation_email( $order ); } // Send cancellation email if order is cancelled if ( in_array( $new_status, [ 'denied', 'cancelled', 'refunded' ] ) ) { $this->send_cancellation_email( $order ); } } /** * Schedule cleanup of expired orders * * @since 1.0.0 * @return void */ public function schedule_cleanup() { if ( ! wp_next_scheduled( 'et_mail_in_cleanup_expired_orders' ) ) { wp_schedule_event( time(), 'daily', 'et_mail_in_cleanup_expired_orders' ); } } /** * Cleanup expired mail-in orders * * @since 1.0.0 * @return void */ public function cleanup_expired_orders() { // Only run if auto-cancel is enabled if ( ! tribe_get_option( 'tickets-commerce-mail-in-auto-cancel', false ) ) { return; } $reservation_days = absint( tribe_get_option( 'tickets-commerce-mail-in-reservation-days', 7 ) ); $cutoff_date = date( 'Y-m-d H:i:s', strtotime( "-{$reservation_days} days" ) ); $args = [ 'post_type' => 'tec_tc_order', 'meta_query' => [ [ 'key' => '_tec_tc_gateway', 'value' => 'mail-in', 'compare' => '=' ], [ 'key' => '_mail_in_check_received', 'value' => false, 'compare' => '=' ], [ 'key' => '_mail_in_created_date', 'value' => $cutoff_date, 'compare' => '<', 'type' => 'DATETIME' ] ], 'post_status' => [ 'tec-tc-pending', 'tec-tc-approved' ], 'posts_per_page' => 50, // Process in batches ]; $expired_orders = new \WP_Query( $args ); $order_controller = new Order(); foreach ( $expired_orders->posts as $order_post ) { $order = tribe( 'tickets.commerce.order' )->get_by_id( $order_post->ID ); if ( $order ) { // Cancel the order $order->update_status( 'denied' ); // Add order note $order_controller->add_order_note( $order_post->ID, __( 'Order automatically cancelled due to expired payment deadline.', 'event-tickets-mail-in' ) ); } } } /** * Add custom actions to order admin page * * @since 1.0.0 * @param array $actions Existing actions * @param \TEC\Tickets\Commerce\Order $order Order object * @return array */ public function add_order_actions( $actions, $order ) { // Only for mail-in payment orders if ( $order->get_gateway() !== 'mail-in' ) { return $actions; } $order_controller = new Order(); $details = $order_controller->get_mail_in_details( $order->get_id() ); // Add "Mark Check Received" action if check hasn't been received if ( ! $details['check_received'] && ! $details['check_bounced'] ) { $actions['mark_check_received'] = [ 'label' => __( 'Mark Check Received', 'event-tickets-mail-in' ), 'url' => wp_nonce_url( admin_url( 'admin-post.php?action=mark_check_received&order_id=' . $order->get_id() ), 'et_mail_in_admin' ), 'class' => 'button-secondary', ]; $actions['mark_check_bounced'] = [ 'label' => __( 'Mark Check Bounced', 'event-tickets-mail-in' ), 'url' => wp_nonce_url( admin_url( 'admin-post.php?action=mark_check_bounced&order_id=' . $order->get_id() ), 'et_mail_in_admin' ), 'class' => 'button-secondary', ]; } return $actions; } /** * Get checkout template for mail-in payment * * @since 1.0.0 * @param string $template Template name * @param string $gateway Gateway key * @return string */ public function get_checkout_template( $template, $gateway ) { if ( $gateway === 'mail-in' ) { return 'checkout/mail-in-form'; } return $template; } /** * Send payment instructions email * * @since 1.0.0 * @param \TEC\Tickets\Commerce\Order $order Order object * @return void */ protected function send_instructions_email( $order ) { $purchaser_email = $order->get_purchaser_email(); if ( ! $purchaser_email ) { return; } $subject = sprintf( __( 'Payment Instructions for Order #%s', 'event-tickets-mail-in' ), $order->get_order_number() ); $order_controller = new Order(); $details = $order_controller->get_mail_in_details( $order->get_id() ); $message = $this->get_email_template( 'payment-instructions', [ 'order' => $order, 'details' => $details, ] ); wp_mail( $purchaser_email, $subject, $message, $this->get_email_headers() ); } /** * Send payment confirmation email * * @since 1.0.0 * @param \TEC\Tickets\Commerce\Order $order Order object * @return void */ protected function send_confirmation_email( $order ) { $purchaser_email = $order->get_purchaser_email(); if ( ! $purchaser_email ) { return; } $subject = sprintf( __( 'Payment Confirmed for Order #%s', 'event-tickets-mail-in' ), $order->get_order_number() ); $message = $this->get_email_template( 'payment-confirmation', [ 'order' => $order, ] ); wp_mail( $purchaser_email, $subject, $message, $this->get_email_headers() ); } /** * Send order cancellation email * * @since 1.0.0 * @param \TEC\Tickets\Commerce\Order $order Order object * @return void */ protected function send_cancellation_email( $order ) { $purchaser_email = $order->get_purchaser_email(); if ( ! $purchaser_email ) { return; } $subject = sprintf( __( 'Order Cancelled: #%s', 'event-tickets-mail-in' ), $order->get_order_number() ); $message = $this->get_email_template( 'order-cancelled', [ 'order' => $order, ] ); wp_mail( $purchaser_email, $subject, $message, $this->get_email_headers() ); } /** * Get email template content * * @since 1.0.0 * @param string $template Template name * @param array $args Template arguments * @return string */ protected function get_email_template( $template, $args = [] ) { $template_file = ET_MAIL_IN_PATH . "templates/emails/{$template}.php"; if ( ! file_exists( $template_file ) ) { return $this->get_fallback_email_content( $template, $args ); } ob_start(); extract( $args ); include $template_file; return ob_get_clean(); } /** * Get fallback email content * * @since 1.0.0 * @param string $template Template name * @param array $args Template arguments * @return string */ protected function get_fallback_email_content( $template, $args ) { switch ( $template ) { case 'payment-instructions': return $this->get_instructions_fallback( $args ); case 'payment-confirmation': return $this->get_confirmation_fallback( $args ); case 'order-cancelled': return $this->get_cancellation_fallback( $args ); default: return ''; } } /** * Get payment instructions fallback content * * @since 1.0.0 * @param array $args Template arguments * @return string */ protected function get_instructions_fallback( $args ) { $order = $args['order']; $details = $args['details']; $content = sprintf( __( 'Thank you for your order #%s!', 'event-tickets-mail-in' ), $order->get_order_number() ) . "\n\n"; $content .= $details['instructions'] . "\n\n"; $content .= sprintf( __( 'Mailing Address:\n%s', 'event-tickets-mail-in' ), $details['mailing_address'] ) . "\n\n"; $content .= sprintf( __( 'Make Check Payable To: %s', 'event-tickets-mail-in' ), $details['payable_to'] ) . "\n\n"; $content .= sprintf( __( 'Order Total: %s', 'event-tickets-mail-in' ), $order->get_total_value()->get_formatted() ) . "\n"; return $content; } /** * Get confirmation fallback content * * @since 1.0.0 * @param array $args Template arguments * @return string */ protected function get_confirmation_fallback( $args ) { $order = $args['order']; return sprintf( __( 'Your payment for order #%s has been received and processed. Your tickets are now confirmed!', 'event-tickets-mail-in' ), $order->get_order_number() ); } /** * Get cancellation fallback content * * @since 1.0.0 * @param array $args Template arguments * @return string */ protected function get_cancellation_fallback( $args ) { $order = $args['order']; return sprintf( __( 'Your order #%s has been cancelled. If you believe this is an error, please contact us.', 'event-tickets-mail-in' ), $order->get_order_number() ); } /** * Get email headers * * @since 1.0.0 * @return array */ protected function get_email_headers() { return [ 'Content-Type: text/html; charset=UTF-8', 'From: ' . get_option( 'blogname' ) . ' <' . get_option( 'admin_email' ) . '>', ]; } }