1. The name of an email template; 2. Email address; 3. User-agent that requested the action. esc_html__( 'Email template "%1$s" sent to %2$s, via %3$s.', 'woocommerce' ), esc_html( $template->get_title() ), esc_html( $order->get_billing_email() ), $user_agent ? $user_agent : 'REST API' ); $messages = array_filter( $messages ); foreach ( $messages as $message ) { $order->add_order_note( $message, false, true ); } return array( 'message' => implode( ' ', $messages ), ); } /** * Handle the POST /orders/{id}/actions/send_order_details. * * @param WP_REST_Request $request The received request. * @return array|WP_Error Request response or an error. */ protected function send_order_details( WP_REST_Request $request ) { $order = wc_get_order( $request->get_param( 'id' ) ); $email = $request->get_param( 'email' ); $force = wp_validate_boolean( $request->get_param( 'force_email_update' ) ); $messages = array(); if ( $email ) { $message = $this->maybe_update_billing_email( $order, $email, $force ); if ( is_wp_error( $message ) ) { return $message; } $messages[] = $message; } if ( ! is_email( $order->get_billing_email() ) ) { return new WP_Error( 'woocommerce_rest_missing_email', __( 'Order does not have an email address.', 'woocommerce' ), array( 'status' => 400 ) ); } // phpcs:disable WooCommerce.Commenting.CommentHooks.MissingSinceComment /** This action is documented in includes/admin/meta-boxes/class-wc-meta-box-order-actions.php */ do_action( 'woocommerce_before_resend_order_emails', $order, 'customer_invoice' ); WC()->payment_gateways(); WC()->shipping(); WC()->mailer()->customer_invoice( $order ); $user_agent = esc_html( $request->get_header( 'User-Agent' ) ); $messages[] = sprintf( // translators: %1$s is the customer email, %2$s is the user agent that requested the action. esc_html__( 'Order details sent to %1$s, via %2$s.', 'woocommerce' ), esc_html( $order->get_billing_email() ), $user_agent ? $user_agent : 'REST API' ); $messages = array_filter( $messages ); foreach ( $messages as $message ) { $order->add_order_note( $message, false, true ); } // phpcs:disable WooCommerce.Commenting.CommentHooks.MissingSinceComment /** This action is documented in includes/admin/meta-boxes/class-wc-meta-box-order-actions.php */ do_action( 'woocommerce_after_resend_order_email', $order, 'customer_invoice' ); return array( 'message' => implode( ' ', $messages ), ); } /** * Update the billing email of an order when certain conditions are met. * * If the order does not already have a billing email, it will be updated. If it does have one, but `$force` is set * to `true`, it will be updated. Otherwise this will return an error. This can also return an error if the given * email address is not valid. * * @param WC_Order $order The order to update. * @param string $email The email address to maybe add to the order. * @param bool $force Optional. True to update the order even if it already has a billing email. Default false. * * @return string|WP_Error A message upon success, otherwise an error. */ private function maybe_update_billing_email( WC_Order $order, string $email, ?bool $force = false ) { $existing_email = $order->get_billing_email( 'edit' ); if ( $existing_email === $email ) { return ''; } if ( $existing_email && true !== $force ) { return new WP_Error( 'woocommerce_rest_order_billing_email_exists', __( 'Order already has a billing email.', 'woocommerce' ), array( 'status' => 400 ) ); } try { $order->set_billing_email( $email ); $order->save(); } catch ( WC_Data_Exception $e ) { return new WP_Error( $e->getErrorCode(), $e->getMessage() ); } return sprintf( // translators: %s is an email address. __( 'Billing email updated to %s.', 'woocommerce' ), esc_html( $email ) ); } /** * Check if a given order has any partial refunds. * * Based on heuristics in the `wc_create_refund()` function. * * @param WC_Order $order An order object. * * @return bool */ private function order_is_partially_refunded( WC_Order $order ): bool { $remaining_amount = $order->get_remaining_refund_amount(); $remaining_items = $order->get_remaining_refund_items(); $refunds = $order->get_refunds(); $last_refund = reset( $refunds ); // phpcs:disable WooCommerce.Commenting.CommentHooks.MissingSinceComment /** This filter is documented in includes/wc-order-functions.php */ $partially_refunded = apply_filters( 'woocommerce_order_is_partially_refunded', count( $refunds ) > 0 && ( $remaining_amount > 0 || ( $order->has_free_item() && $remaining_items > 0 ) ), $order->get_id(), $last_refund ? $last_refund->get_id() : 0 ); return (bool) $partially_refunded; } }