mailer(); do_action( 'apd_email_deposit_received_notification', $order_id ); } /** * Trigger full payment complete email. * * @param int $order_id Order ID. * @param WC_Order $order Order object. */ public function trigger_payment_complete( $order_id, $order ) { if ( 'yes' !== apd_get_option( 'email_payment_complete', 'yes' ) ) { return; } WC()->mailer(); do_action( 'apd_email_payment_complete_notification', $order_id ); } /** * Get editable email template defaults. * * @return array> */ public static function get_email_template_defaults() { return array( 'deposit_received' => array( 'title' => __( 'Deposit Received', 'advanced-partial-payment-or-deposit-for-woocommerce' ), 'description' => __( 'Sent to the customer when their deposit payment is confirmed.', 'advanced-partial-payment-or-deposit-for-woocommerce' ), 'subject' => __( 'Your deposit payment for Order #{order_number}', 'advanced-partial-payment-or-deposit-for-woocommerce' ), 'heading' => __( 'Deposit Payment Received', 'advanced-partial-payment-or-deposit-for-woocommerce' ), 'body' => implode( "\n\n", array( __( 'Hi {customer_first_name},', 'advanced-partial-payment-or-deposit-for-woocommerce' ), __( 'Thank you for your deposit payment for order #{order_number}.', 'advanced-partial-payment-or-deposit-for-woocommerce' ), '[deposit_summary]', __( 'You can pay your remaining balance from your account page or payment link when you are ready.', 'advanced-partial-payment-or-deposit-for-woocommerce' ), ) ), 'button_label' => '', ), 'balance_due' => array( 'title' => __( 'Balance Due Reminder', 'advanced-partial-payment-or-deposit-for-woocommerce' ), 'description' => __( 'Sent as a reminder when a customer has an outstanding balance.', 'advanced-partial-payment-or-deposit-for-woocommerce' ), 'subject' => __( 'Balance payment due for Order #{order_number}', 'advanced-partial-payment-or-deposit-for-woocommerce' ), 'heading' => __( 'Balance Payment Due', 'advanced-partial-payment-or-deposit-for-woocommerce' ), 'body' => implode( "\n\n", array( __( 'Hi {customer_first_name},', 'advanced-partial-payment-or-deposit-for-woocommerce' ), __( 'This is a reminder that you still have an outstanding balance for order #{order_number}.', 'advanced-partial-payment-or-deposit-for-woocommerce' ), '[deposit_summary]', '[pay_balance_button]', ) ), 'button_label' => __( 'Pay Balance Now', 'advanced-partial-payment-or-deposit-for-woocommerce' ), ), 'payment_complete' => array( 'title' => __( 'Payment Complete', 'advanced-partial-payment-or-deposit-for-woocommerce' ), 'description' => __( 'Sent when the customer has paid the full remaining balance.', 'advanced-partial-payment-or-deposit-for-woocommerce' ), 'subject' => __( 'Payment complete for Order #{order_number}', 'advanced-partial-payment-or-deposit-for-woocommerce' ), 'heading' => __( 'Payment Complete', 'advanced-partial-payment-or-deposit-for-woocommerce' ), 'body' => implode( "\n\n", array( __( 'Hi {customer_first_name},', 'advanced-partial-payment-or-deposit-for-woocommerce' ), __( 'Great news! Your order #{order_number} has been fully paid.', 'advanced-partial-payment-or-deposit-for-woocommerce' ), '[deposit_summary]', __( 'Your order is now complete. Thank you for completing your payment.', 'advanced-partial-payment-or-deposit-for-woocommerce' ), ) ), 'button_label' => '', ), ); } /** * Get template config merged with saved settings. * * @param string $template_id Template key. * @return array */ public static function get_email_template_config( $template_id ) { $defaults = self::get_email_template_defaults(); $settings = get_option( 'apd_settings', array() ); $default = $defaults[ $template_id ] ?? array(); $subject = $settings[ 'email_' . $template_id . '_subject' ] ?? ''; $heading = $settings[ 'email_' . $template_id . '_heading' ] ?? ''; $body = $settings[ 'email_' . $template_id . '_body' ] ?? ''; $button = $settings[ 'email_' . $template_id . '_button_label' ] ?? ''; return array( 'title' => $default['title'] ?? '', 'description' => $default['description'] ?? '', 'subject' => '' !== trim( $subject ) ? $subject : ( $default['subject'] ?? '' ), 'heading' => '' !== trim( $heading ) ? $heading : ( $default['heading'] ?? '' ), 'body' => '' !== trim( wp_strip_all_tags( $body ) ) ? $body : ( $default['body'] ?? '' ), 'button_label' => '' !== trim( $button ) ? $button : ( $default['button_label'] ?? '' ), ); } /** * Get placeholder replacements. * * @param WC_Order $order Order object. * @param array|false $deposit_details Deposit details. * @param bool $formatted Whether to format amounts with wc_price(). * @return array */ public static function get_placeholder_values( $order, $deposit_details = false, $formatted = true ) { $first_name = $order ? $order->get_billing_first_name() : ''; $total = $deposit_details ? floatval( $deposit_details['total_amount'] ?? 0 ) : 0; $deposit = $deposit_details ? floatval( $deposit_details['deposit_amount'] ?? 0 ) : 0; $paid = $deposit_details ? floatval( $deposit_details['amount_paid'] ?? 0 ) : 0; $balance = $deposit_details ? floatval( $deposit_details['balance_due'] ?? 0 ) : 0; if ( $formatted ) { $total = wc_price( $total ); $deposit = wc_price( $deposit ); $paid = wc_price( $paid ); $balance = wc_price( $balance ); } else { $total = wc_format_decimal( $total, wc_get_price_decimals() ); $deposit = wc_format_decimal( $deposit, wc_get_price_decimals() ); $paid = wc_format_decimal( $paid, wc_get_price_decimals() ); $balance = wc_format_decimal( $balance, wc_get_price_decimals() ); } return array( '{customer_first_name}' => $first_name, '{order_number}' => $order ? $order->get_order_number() : '', '{order_date}' => $order && $order->get_date_created() ? wc_format_datetime( $order->get_date_created() ) : '', '{total_amount}' => $total, '{deposit_amount}' => $deposit, '{amount_paid}' => $paid, '{balance_due}' => $balance, '{pay_balance_url}' => $order ? $order->get_checkout_payment_url() : '', '{site_title}' => wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ), ); } /** * Render email body content from editable template fields. * * @param string $template_id Template key. * @param WC_Order $order Order object. * @param array|bool $deposit Deposit details. * @param bool $plain_text Whether to render plain text. * @return string */ public static function render_email_body( $template_id, $order, $deposit = false, $plain_text = false ) { $config = self::get_email_template_config( $template_id ); $body = $config['body'] ?? ''; $body = strtr( $body, self::get_placeholder_values( $order, $deposit, ! $plain_text ) ); $body = strtr( $body, array( '[deposit_summary]' => self::render_deposit_summary_block( $template_id, $order, $deposit, $plain_text ), '[pay_balance_button]' => self::render_pay_balance_block( $template_id, $order, $plain_text ), ) ); if ( $plain_text ) { $body = str_replace( array( "\r\n", "\r" ), "\n", $body ); return trim( preg_replace( "/\n{3,}/", "\n\n", wp_strip_all_tags( $body ) ) ); } return wpautop( wp_kses_post( $body ) ); } /** * Render summary block token for the email body. * * @param string $template_id Template key. * @param WC_Order $order Order object. * @param array|bool $deposit Deposit details. * @param bool $plain_text Whether to render plain text. * @return string */ private static function render_deposit_summary_block( $template_id, $order, $deposit, $plain_text = false ) { if ( ! $order ) { return ''; } // Part of the balance, such as a payment plan's next instalment, when that is all // the pay button collects. 0 when the whole balance is due. $due_now = 0; if ( $deposit && 'balance_due' === $template_id ) { $due_now = APD_Order::get_balance_amount_due_now( $order ); $due_now = round( floatval( $deposit['balance_due'] ?? 0 ) - $due_now, wc_get_price_decimals() ) > 0 ? $due_now : 0; } if ( $plain_text ) { $lines = array(); /* translators: %s: order number. */ $lines[] = sprintf( __( 'Order Number: #%s', 'advanced-partial-payment-or-deposit-for-woocommerce' ), $order->get_order_number() ); if ( $deposit ) { if ( 'payment_complete' === $template_id ) { /* translators: %s: formatted total amount paid. */ $lines[] = sprintf( __( 'Total Paid: %s', 'advanced-partial-payment-or-deposit-for-woocommerce' ), wc_price( $deposit['total_amount'] ?? 0 ) ); } elseif ( 'balance_due' === $template_id ) { /* translators: %s: formatted order total. */ $lines[] = sprintf( __( 'Total Amount: %s', 'advanced-partial-payment-or-deposit-for-woocommerce' ), wc_price( $deposit['total_amount'] ?? 0 ) ); /* translators: %s: formatted amount already paid. */ $lines[] = sprintf( __( 'Amount Paid: %s', 'advanced-partial-payment-or-deposit-for-woocommerce' ), wc_price( $deposit['amount_paid'] ?? 0 ) ); /* translators: %s: formatted balance still due. */ $lines[] = sprintf( __( 'Balance Due: %s', 'advanced-partial-payment-or-deposit-for-woocommerce' ), wc_price( $deposit['balance_due'] ?? 0 ) ); if ( $due_now > 0 ) { /* translators: %s: formatted amount the next payment collects. */ $lines[] = sprintf( __( 'Amount Due Now: %s', 'advanced-partial-payment-or-deposit-for-woocommerce' ), wc_price( $due_now ) ); } } else { /* translators: %s: formatted order total. */ $lines[] = sprintf( __( 'Total Amount: %s', 'advanced-partial-payment-or-deposit-for-woocommerce' ), wc_price( $deposit['total_amount'] ?? 0 ) ); /* translators: %s: formatted deposit amount paid. */ $lines[] = sprintf( __( 'Deposit Paid: %s', 'advanced-partial-payment-or-deposit-for-woocommerce' ), wc_price( $deposit['deposit_amount'] ?? 0 ) ); /* translators: %s: formatted balance still due. */ $lines[] = sprintf( __( 'Balance Due: %s', 'advanced-partial-payment-or-deposit-for-woocommerce' ), wc_price( $deposit['balance_due'] ?? 0 ) ); } } return implode( "\n", $lines ); } ob_start(); ?> 0 ) : ?>
#get_order_number() ); ?>
get_checkout_payment_url(); if ( $plain_text ) { /* translators: 1: call to action label, 2: payment URL. */ return sprintf( __( '%1$s: %2$s', 'advanced-partial-payment-or-deposit-for-woocommerce' ), $label, $url ); } return sprintf( '

%2$s

', esc_url( $url ), esc_html( $label ) ); } }