PluginProbe ʕ •ᴥ•ʔ
WooCommerce / 7.6.2
WooCommerce v7.6.2
10.8.1 10.8.0 10.8.0-rc.1 10.8.0-beta.2 10.8.0-beta.1 7.8.0-beta.1 7.8.0-beta.2 7.8.0-rc.1 7.8.0-rc.2 7.8.1 7.8.2 7.8.3 7.8.4 7.9.0 7.9.0-beta.1 7.9.0-beta.2 7.9.0-rc.2 7.9.0-rc.3 7.9.1 7.9.2 8.0.0 8.0.0-beta.1 8.0.0-beta.2 8.0.0-rc.1 8.0.0-rc.2 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.1.0 8.1.0-beta.1 8.1.0-rc.1 8.1.0-rc.2 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 8.2.0-beta.1 8.2.0-rc.1 8.2.0-rc.2 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.3.0 8.3.0-beta.1 8.3.0-rc.1 8.3.0-rc.2 8.3.1 8.3.2 8.3.3 8.3.4 8.4.0 8.4.0-beta.1 8.4.0-rc.1 8.4.1 8.4.2 8.4.3 8.5.0 8.5.0-beta.1 8.5.0-rc.1 8.5.1 8.5.2 8.5.3 8.5.4 8.5.5 8.6.0 8.6.0-beta.1 8.6.0-rc.1 8.6.1 8.6.2 8.6.3 8.6.4 8.7.0 8.7.0-beta.1 8.7.0-beta.2 8.7.0-rc.1 8.7.1 8.7.2 8.7.3 8.8.0 8.8.0-beta.1 8.8.0-rc.1 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.8.6 8.8.7 8.9.0 8.9.0-beta.1 8.9.0-rc.1 8.9.1 8.9.2 8.9.3 8.9.4 8.9.5 9.0.0 9.0.0-beta.1 9.0.0-beta.2 9.0.0-rc.1 9.0.1 9.0.2 9.0.3 9.0.4 9.1.0 9.1.0-beta.1 9.1.0-rc.1 9.1.1 9.1.2 9.1.3 9.1.4 9.1.5 9.1.6 9.2.0 9.2.0-beta.1 9.2.0-rc.1 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.3.0 9.3.0-beta.1 9.3.0-rc.1 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.3.6 9.4.0 9.4.0-beta.1 9.4.0-beta.2 9.4.0-rc.1 9.4.0-rc.2 9.4.0-rc.3 9.4.0-rc.4 9.4.1 9.4.2 9.4.3 9.4.4 9.4.5 9.5.0 9.5.0-beta.1 9.5.0-beta.2 9.5.0-rc.1 9.5.1 9.5.2 9.5.3 9.5.4 9.6.0 9.6.0-beta.1 9.6.0-beta.2 9.6.0-rc.1 9.6.1 9.6.2 9.6.3 9.6.4 9.7.0 9.7.0-beta.1 9.7.0-rc.1 9.7.1 9.7.2 9.7.3 9.8.0 9.8.0-beta.1 9.8.0-rc.1 9.8.1 9.8.2 9.8.3 9.8.4 9.8.5 9.8.6 9.8.7 9.9.0 9.9.0-beta.1 9.9.0-rc.1 9.9.1 9.9.2 9.9.3 9.9.4 9.9.5 9.9.6 9.9.7 3.7.3 7.1.2 3.8.0 7.2.0 3.8.0-beta.1 7.2.0-beta.1 3.8.0-rc.1 7.2.0-beta.2 3.8.0-rc.2 7.2.0-rc.1 3.8.1 7.2.0-rc.2 3.8.2 7.2.1 3.8.3 7.2.2 3.9.0 7.2.3 3.9.0-beta.1 7.2.4 3.9.0-beta.2 7.3.0 3.9.0-rc.1 7.3.0-beta.1 3.9.0-rc.2 7.3.0-beta.2 3.9.0-rc.3 7.3.0-rc.1 3.9.0-rc.4 7.3.0-rc.2 3.9.1 7.3.1 3.9.2 7.4.0 3.9.3 7.4.0-beta.1 3.9.4 7.4.0-beta.2 3.9.5 7.4.0-rc.1 4.0.0 7.4.0-rc.2 4.0.0-beta.1 7.4.1 4.0.0-rc.1 7.4.2 4.0.0-rc.2 7.5.0 4.0.1 7.5.0-beta.1 4.0.2 7.5.0-beta.2 4.0.3 7.5.0-rc.1 4.0.4 7.5.1 4.1.0 7.5.2 4.1.0-beta.1 7.6.0 4.1.0-beta.2 7.6.0-beta.1 4.1.0-rc.1 7.6.0-beta.2 4.1.0-rc.2 7.6.0-rc.1 4.1.1 7.6.0-rc.2 4.1.2 7.6.0-rc.3 4.1.3 7.6.1 4.1.4 7.6.2 4.2.0 7.7.0 4.2.0-RC.1 7.7.0-beta.1 4.2.0-RC.2 7.7.0-beta.2 4.2.0-beta.1 7.7.0-rc.1 4.2.1 7.7.1 4.2.2 7.7.2 4.2.3 7.7.3 4.2.4 7.8.0 4.2.5 4.3.0 4.3.0-beta.1 4.3.0-rc.1 4.3.0-rc.2 4.3.0-rc.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.4.0 4.4.0-beta.1 4.4.0-rc.1 4.4.1 4.4.2 4.4.3 4.4.4 4.5.0 4.5.0-beta.1 4.5.0-rc.1 4.5.0-rc.3 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.6.0-beta.1 4.6.0-rc.1 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.7.0 4.7.0-beta.1 4.7.0-beta.2 4.7.0-rc.1 4.7.1 4.7.1-beta.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.0-beta.1 4.8.0-rc.1 4.8.0-rc.2 4.8.1 4.8.2 4.8.3 4.9.0 4.9.0-beta.1 4.9.0-rc.1 4.9.0-rc.2 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 5.0.0 5.0.0-beta.1 5.0.0-beta.2 5.0.0-rc.1 5.0.0-rc.2 5.0.0-rc.3 5.0.1 5.0.2 5.0.3 5.1.0 5.1.0-beta.1 5.1.0-rc.1 trunk 5.1.1 10.0.0 5.1.2 10.0.0-rc.1 5.1.3 10.0.0-rc.2 5.2.0 10.0.1 5.2.0-beta.1 10.0.2 5.2.0-rc.1 10.0.3 5.2.0-rc.2 10.0.4 5.2.1 10.0.5 5.2.2 10.0.6 5.2.3 10.1.0 5.2.4 10.1.0-rc.1 5.2.5 10.1.0-rc.2 5.3.0 10.1.0-rc.3 5.3.0-beta.1 10.1.0-rc.4 5.3.0-rc.1 10.1.1 5.3.0-rc.2 10.1.2 5.3.1 10.1.3 5.3.2 10.1.4 5.3.3 10.2.0 5.4.0 10.2.0-beta.1 5.4.0-beta.1 10.2.0-beta.2 5.4.0-rc.1 10.2.0-rc.1 5.4.1 10.2.1 5.4.2 10.2.2 5.4.3 10.2.3 5.4.4 10.2.4 5.4.5 10.3.0 5.5.0 10.3.0-beta.1 5.5.0-beta.1 10.3.0-beta.2 5.5.0-rc.1 10.3.0-rc.1 5.5.0-rc.2 10.3.0-rc.2 5.5.1 10.3.1 5.5.2 10.3.2 5.5.3 10.3.3 5.5.4 10.3.4 5.5.5 10.3.5 5.6.0 10.3.6 5.6.0-beta.1 10.3.7 5.6.0-rc.1 10.3.8 5.6.0-rc.2 10.4.0 5.6.1 10.4.0-beta.1 5.6.2 10.4.0-beta.2 5.6.3 10.4.0-rc.1 5.7.0 10.4.1 5.7.0-beta.1 10.4.2 5.7.0-rc.1 10.4.3 5.7.1 10.4.4 5.7.2 10.5.0 5.7.3 10.5.0-beta.1 5.8.0 10.5.0-beta.2 5.8.0-beta.1 10.5.0-rc.1 5.8.0-beta.2 10.5.0-rc.2 5.8.0-rc.1 10.5.0-rc.3 5.8.1 10.5.1 5.8.2 10.5.2 5.9.0 10.5.3 5.9.0-beta.1 10.6.0 5.9.0-rc.1 10.6.0-beta.1 5.9.0-rc.2 10.6.0-beta.2 5.9.1 10.6.0-rc.1 5.9.2 10.6.1 6.0.0 10.6.2 6.0.0-beta.1 10.7.0 6.0.0-rc.1 10.7.0-beta.1 6.0.1 10.7.0-beta.2 6.0.2 10.7.0-rc.1 6.1.0 3.0.0 6.1.0-beta.1 3.0.1 6.1.0-rc.1 3.0.2 6.1.0-rc.2 3.0.3 6.1.1 3.0.4 6.1.2 3.0.5 6.1.3 3.0.6 6.2.0 3.0.7 6.2.0-beta.1 3.0.8 6.2.0-rc.1 3.0.9 6.2.0-rc.2 3.1.0 6.2.1 3.1.1 6.2.2 3.1.2 6.2.3 3.2.0 6.3.0 3.2.1 6.3.0-beta.1 3.2.2 6.3.0-rc.1 3.2.3 6.3.0-rc.2 3.2.4 6.3.1 3.2.5 6.3.2 3.2.6 6.4.0 3.3.0 6.4.0-beta.1 3.3.1 6.4.0-rc.1 3.3.2 6.4.1 3.3.2-rc.1 6.4.2 3.3.3 6.5.0 3.3.4 6.5.0-beta.1 3.3.5 6.5.0-rc.1 3.3.6 6.5.0-rc.2 3.4.0 6.5.1 3.4.0-beta.1 6.5.2 3.4.0-rc.2 6.6.0 3.4.1 6.6.0-beta.1 3.4.2 6.6.0-rc.1 3.4.3 6.6.0-rc.2 3.4.4 6.6.1 3.4.5 6.6.2 3.4.6 6.7.0 3.4.7 6.7.0-beta.1 3.4.8 6.7.0-beta.2 3.5.0 6.7.0-rc.1 3.5.0-beta.1 6.7.1 3.5.0-rc.1 6.8.0 3.5.0-rc.2 6.8.0-beta.1 3.5.1 6.8.0-beta.2 3.5.10 6.8.0-rc.1 3.5.2 6.8.1 3.5.3 6.8.2 3.5.4 6.8.3 3.5.5 6.9.0 3.5.6 6.9.0-beta.1 3.5.7 6.9.0-beta.2 3.5.8 6.9.0-rc.1 3.5.9 6.9.1 3.6.0 6.9.2 3.6.0-beta.1 6.9.3 3.6.0-rc.1 6.9.4 3.6.0-rc.2 6.9.5 3.6.0-rc.3 7.0.0 3.6.1 7.0.0-beta.1 3.6.2 7.0.0-beta.2 3.6.3 7.0.0-beta.3 3.6.4 7.0.0-rc.1 3.6.5 7.0.0-rc.2 3.6.6 7.0.1 3.6.7 7.0.2 3.7.0 7.1.0 3.7.0-beta.1 7.1.0-beta.1 3.7.0-rc.1 7.1.0-beta.2 3.7.0-rc.2 7.1.0-rc.1 3.7.1 7.1.0-rc.2 3.7.2 7.1.1
woocommerce / includes / class-wc-emails.php
woocommerce / includes Last commit date
abstracts 3 years ago admin 3 years ago blocks 5 years ago cli 3 years ago customizer 3 years ago data-stores 3 years ago emails 3 years ago export 3 years ago gateways 3 years ago import 3 years ago integrations 4 years ago interfaces 3 years ago legacy 3 years ago libraries 3 years ago log-handlers 4 years ago payment-tokens 5 years ago queue 4 years ago react-admin 3 years ago rest-api 3 years ago shipping 4 years ago shortcodes 3 years ago theme-support 3 years ago tracks 3 years ago traits 5 years ago walkers 5 years ago wccom-site 5 years ago widgets 3 years ago class-wc-ajax.php 3 years ago class-wc-api.php 4 years ago class-wc-auth.php 4 years ago class-wc-autoloader.php 5 years ago class-wc-background-emailer.php 5 years ago class-wc-background-updater.php 5 years ago class-wc-breadcrumb.php 5 years ago class-wc-cache-helper.php 3 years ago class-wc-cart-fees.php 5 years ago class-wc-cart-session.php 3 years ago class-wc-cart-totals.php 4 years ago class-wc-cart.php 3 years ago class-wc-checkout.php 3 years ago class-wc-cli.php 3 years ago class-wc-comments.php 3 years ago class-wc-countries.php 3 years ago class-wc-coupon.php 3 years ago class-wc-customer-download-log.php 5 years ago class-wc-customer-download.php 4 years ago class-wc-customer.php 4 years ago class-wc-data-exception.php 8 years ago class-wc-data-store.php 3 years ago class-wc-datetime.php 4 years ago class-wc-deprecated-action-hooks.php 8 years ago class-wc-deprecated-filter-hooks.php 3 years ago class-wc-discounts.php 3 years ago class-wc-download-handler.php 3 years ago class-wc-emails.php 3 years ago class-wc-embed.php 5 years ago class-wc-form-handler.php 4 years ago class-wc-frontend-scripts.php 3 years ago class-wc-geo-ip.php 4 years ago class-wc-geolite-integration.php 6 years ago class-wc-geolocation.php 3 years ago class-wc-https.php 4 years ago class-wc-install.php 3 years ago class-wc-integrations.php 5 years ago class-wc-log-levels.php 5 years ago class-wc-logger.php 4 years ago class-wc-meta-data.php 4 years ago class-wc-order-factory.php 3 years ago class-wc-order-item-coupon.php 4 years ago class-wc-order-item-fee.php 4 years ago class-wc-order-item-meta.php 4 years ago class-wc-order-item-product.php 4 years ago class-wc-order-item-shipping.php 4 years ago class-wc-order-item-tax.php 4 years ago class-wc-order-item.php 4 years ago class-wc-order-query.php 4 years ago class-wc-order-refund.php 3 years ago class-wc-order.php 3 years ago class-wc-payment-gateways.php 4 years ago class-wc-payment-tokens.php 3 years ago class-wc-post-data.php 3 years ago class-wc-post-types.php 3 years ago class-wc-privacy-background-process.php 5 years ago class-wc-privacy-erasers.php 4 years ago class-wc-privacy-exporters.php 4 years ago class-wc-privacy.php 4 years ago class-wc-product-attribute.php 4 years ago class-wc-product-download.php 4 years ago class-wc-product-external.php 5 years ago class-wc-product-factory.php 5 years ago class-wc-product-grouped.php 8 years ago class-wc-product-query.php 5 years ago class-wc-product-simple.php 3 years ago class-wc-product-variable.php 4 years ago class-wc-product-variation.php 4 years ago class-wc-query.php 3 years ago class-wc-rate-limiter.php 4 years ago class-wc-regenerate-images-request.php 3 years ago class-wc-regenerate-images.php 3 years ago class-wc-register-wp-admin-settings.php 4 years ago class-wc-rest-authentication.php 5 years ago class-wc-rest-exception.php 5 years ago class-wc-session-handler.php 3 years ago class-wc-shipping-rate.php 3 years ago class-wc-shipping-zone.php 5 years ago class-wc-shipping-zones.php 5 years ago class-wc-shipping.php 4 years ago class-wc-shortcodes.php 5 years ago class-wc-structured-data.php 5 years ago class-wc-tax.php 4 years ago class-wc-template-loader.php 3 years ago class-wc-tracker.php 3 years ago class-wc-validation.php 3 years ago class-wc-webhook.php 3 years ago class-woocommerce.php 3 months ago wc-account-functions.php 3 years ago wc-attribute-functions.php 3 years ago wc-cart-functions.php 3 years ago wc-conditional-functions.php 3 years ago wc-core-functions.php 3 years ago wc-coupon-functions.php 3 years ago wc-deprecated-functions.php 3 years ago wc-formatting-functions.php 3 years ago wc-notice-functions.php 5 years ago wc-order-functions.php 3 years ago wc-order-item-functions.php 3 years ago wc-page-functions.php 5 years ago wc-product-functions.php 3 years ago wc-rest-functions.php 3 years ago wc-stock-functions.php 3 years ago wc-template-functions.php 3 years ago wc-template-hooks.php 5 years ago wc-term-functions.php 3 years ago wc-update-functions.php 3 years ago wc-user-functions.php 3 years ago wc-webhook-functions.php 4 years ago wc-widget-functions.php 5 years ago
class-wc-emails.php
732 lines
1 <?php
2 /**
3 * Transactional Emails Controller
4 *
5 * WooCommerce Emails Class which handles the sending on transactional emails and email templates. This class loads in available emails.
6 *
7 * @package WooCommerce\Classes\Emails
8 * @version 2.3.0
9 */
10
11 use Automattic\Jetpack\Constants;
12
13 defined( 'ABSPATH' ) || exit;
14
15 /**
16 * Emails class.
17 */
18 class WC_Emails {
19
20 /**
21 * Array of email notification classes
22 *
23 * @var WC_Email[]
24 */
25 public $emails = array();
26
27 /**
28 * The single instance of the class
29 *
30 * @var WC_Emails
31 */
32 protected static $_instance = null;
33
34 /**
35 * Background emailer class.
36 *
37 * @var WC_Background_Emailer
38 */
39 protected static $background_emailer = null;
40
41 /**
42 * Main WC_Emails Instance.
43 *
44 * Ensures only one instance of WC_Emails is loaded or can be loaded.
45 *
46 * @since 2.1
47 * @static
48 * @return WC_Emails Main instance
49 */
50 public static function instance() {
51 if ( is_null( self::$_instance ) ) {
52 self::$_instance = new self();
53 }
54 return self::$_instance;
55 }
56
57 /**
58 * Cloning is forbidden.
59 *
60 * @since 2.1
61 */
62 public function __clone() {
63 wc_doing_it_wrong( __FUNCTION__, __( 'Cloning is forbidden.', 'woocommerce' ), '2.1' );
64 }
65
66 /**
67 * Unserializing instances of this class is forbidden.
68 *
69 * @since 2.1
70 */
71 public function __wakeup() {
72 wc_doing_it_wrong( __FUNCTION__, __( 'Unserializing instances of this class is forbidden.', 'woocommerce' ), '2.1' );
73 }
74
75 /**
76 * Hook in all transactional emails.
77 */
78 public static function init_transactional_emails() {
79 $email_actions = apply_filters(
80 'woocommerce_email_actions',
81 array(
82 'woocommerce_low_stock',
83 'woocommerce_no_stock',
84 'woocommerce_product_on_backorder',
85 'woocommerce_order_status_pending_to_processing',
86 'woocommerce_order_status_pending_to_completed',
87 'woocommerce_order_status_processing_to_cancelled',
88 'woocommerce_order_status_pending_to_failed',
89 'woocommerce_order_status_pending_to_on-hold',
90 'woocommerce_order_status_failed_to_processing',
91 'woocommerce_order_status_failed_to_completed',
92 'woocommerce_order_status_failed_to_on-hold',
93 'woocommerce_order_status_cancelled_to_processing',
94 'woocommerce_order_status_cancelled_to_completed',
95 'woocommerce_order_status_cancelled_to_on-hold',
96 'woocommerce_order_status_on-hold_to_processing',
97 'woocommerce_order_status_on-hold_to_cancelled',
98 'woocommerce_order_status_on-hold_to_failed',
99 'woocommerce_order_status_completed',
100 'woocommerce_order_fully_refunded',
101 'woocommerce_order_partially_refunded',
102 'woocommerce_new_customer_note',
103 'woocommerce_created_customer',
104 )
105 );
106
107 if ( apply_filters( 'woocommerce_defer_transactional_emails', false ) ) {
108 self::$background_emailer = new WC_Background_Emailer();
109
110 foreach ( $email_actions as $action ) {
111 add_action( $action, array( __CLASS__, 'queue_transactional_email' ), 10, 10 );
112 }
113 } else {
114 foreach ( $email_actions as $action ) {
115 add_action( $action, array( __CLASS__, 'send_transactional_email' ), 10, 10 );
116 }
117 }
118 }
119
120 /**
121 * Queues transactional email so it's not sent in current request if enabled,
122 * otherwise falls back to send now.
123 *
124 * @param mixed ...$args Optional arguments.
125 */
126 public static function queue_transactional_email( ...$args ) {
127 if ( is_a( self::$background_emailer, 'WC_Background_Emailer' ) ) {
128 self::$background_emailer->push_to_queue(
129 array(
130 'filter' => current_filter(),
131 'args' => func_get_args(),
132 )
133 );
134 } else {
135 self::send_transactional_email( ...$args );
136 }
137 }
138
139 /**
140 * Init the mailer instance and call the notifications for the current filter.
141 *
142 * @internal
143 *
144 * @param string $filter Filter name.
145 * @param array $args Email args (default: []).
146 */
147 public static function send_queued_transactional_email( $filter = '', $args = array() ) {
148 if ( apply_filters( 'woocommerce_allow_send_queued_transactional_email', true, $filter, $args ) ) {
149 self::instance(); // Init self so emails exist.
150
151 // Ensure gateways are loaded in case they need to insert data into the emails.
152 WC()->payment_gateways();
153 WC()->shipping();
154
155 do_action_ref_array( $filter . '_notification', $args );
156 }
157 }
158
159 /**
160 * Init the mailer instance and call the notifications for the current filter.
161 *
162 * @internal
163 *
164 * @param array $args Email args (default: []).
165 */
166 public static function send_transactional_email( $args = array() ) {
167 try {
168 $args = func_get_args();
169 self::instance(); // Init self so emails exist.
170 do_action_ref_array( current_filter() . '_notification', $args );
171 } catch ( Exception $e ) {
172 $error = 'Transactional email triggered fatal error for callback ' . current_filter();
173 $logger = wc_get_logger();
174 $logger->critical(
175 $error . PHP_EOL,
176 array(
177 'source' => 'transactional-emails',
178 )
179 );
180 if ( Constants::is_true( 'WP_DEBUG' ) ) {
181 trigger_error( $error, E_USER_WARNING ); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped, WordPress.PHP.DevelopmentFunctions.error_log_trigger_error
182 }
183 }
184 }
185
186 /**
187 * Constructor for the email class hooks in all emails that can be sent.
188 */
189 public function __construct() {
190 $this->init();
191
192 // Email Header, Footer and content hooks.
193 add_action( 'woocommerce_email_header', array( $this, 'email_header' ) );
194 add_action( 'woocommerce_email_footer', array( $this, 'email_footer' ) );
195 add_action( 'woocommerce_email_order_details', array( $this, 'order_downloads' ), 10, 4 );
196 add_action( 'woocommerce_email_order_details', array( $this, 'order_details' ), 10, 4 );
197 add_action( 'woocommerce_email_order_meta', array( $this, 'order_meta' ), 10, 3 );
198 add_action( 'woocommerce_email_customer_details', array( $this, 'customer_details' ), 10, 3 );
199 add_action( 'woocommerce_email_customer_details', array( $this, 'email_addresses' ), 20, 3 );
200
201 // Hooks for sending emails during store events.
202 add_action( 'woocommerce_low_stock_notification', array( $this, 'low_stock' ) );
203 add_action( 'woocommerce_no_stock_notification', array( $this, 'no_stock' ) );
204 add_action( 'woocommerce_product_on_backorder_notification', array( $this, 'backorder' ) );
205 add_action( 'woocommerce_created_customer_notification', array( $this, 'customer_new_account' ), 10, 3 );
206
207 // Hook for replacing {site_title} in email-footer.
208 add_filter( 'woocommerce_email_footer_text', array( $this, 'replace_placeholders' ) );
209
210 // Let 3rd parties unhook the above via this hook.
211 do_action( 'woocommerce_email', $this );
212 }
213
214 /**
215 * Init email classes.
216 */
217 public function init() {
218 // Include email classes.
219 include_once dirname( __FILE__ ) . '/emails/class-wc-email.php';
220
221 $this->emails['WC_Email_New_Order'] = include __DIR__ . '/emails/class-wc-email-new-order.php';
222 $this->emails['WC_Email_Cancelled_Order'] = include __DIR__ . '/emails/class-wc-email-cancelled-order.php';
223 $this->emails['WC_Email_Failed_Order'] = include __DIR__ . '/emails/class-wc-email-failed-order.php';
224 $this->emails['WC_Email_Customer_On_Hold_Order'] = include __DIR__ . '/emails/class-wc-email-customer-on-hold-order.php';
225 $this->emails['WC_Email_Customer_Processing_Order'] = include __DIR__ . '/emails/class-wc-email-customer-processing-order.php';
226 $this->emails['WC_Email_Customer_Completed_Order'] = include __DIR__ . '/emails/class-wc-email-customer-completed-order.php';
227 $this->emails['WC_Email_Customer_Refunded_Order'] = include __DIR__ . '/emails/class-wc-email-customer-refunded-order.php';
228 $this->emails['WC_Email_Customer_Invoice'] = include __DIR__ . '/emails/class-wc-email-customer-invoice.php';
229 $this->emails['WC_Email_Customer_Note'] = include __DIR__ . '/emails/class-wc-email-customer-note.php';
230 $this->emails['WC_Email_Customer_Reset_Password'] = include __DIR__ . '/emails/class-wc-email-customer-reset-password.php';
231 $this->emails['WC_Email_Customer_New_Account'] = include __DIR__ . '/emails/class-wc-email-customer-new-account.php';
232
233 $this->emails = apply_filters( 'woocommerce_email_classes', $this->emails );
234 }
235
236 /**
237 * Return the email classes - used in admin to load settings.
238 *
239 * @return WC_Email[]
240 */
241 public function get_emails() {
242 return $this->emails;
243 }
244
245 /**
246 * Get from name for email.
247 *
248 * @return string
249 */
250 public function get_from_name() {
251 return wp_specialchars_decode( get_option( 'woocommerce_email_from_name' ), ENT_QUOTES );
252 }
253
254 /**
255 * Get from email address.
256 *
257 * @return string
258 */
259 public function get_from_address() {
260 return sanitize_email( get_option( 'woocommerce_email_from_address' ) );
261 }
262
263 /**
264 * Get the email header.
265 *
266 * @param mixed $email_heading Heading for the email.
267 */
268 public function email_header( $email_heading ) {
269 wc_get_template( 'emails/email-header.php', array( 'email_heading' => $email_heading ) );
270 }
271
272 /**
273 * Get the email footer.
274 */
275 public function email_footer() {
276 wc_get_template( 'emails/email-footer.php' );
277 }
278
279 /**
280 * Replace placeholder text in strings.
281 *
282 * @since 3.7.0
283 * @param string $string Email footer text.
284 * @return string Email footer text with any replacements done.
285 */
286 public function replace_placeholders( $string ) {
287 $domain = wp_parse_url( home_url(), PHP_URL_HOST );
288
289 return str_replace(
290 array(
291 '{site_title}',
292 '{site_address}',
293 '{site_url}',
294 '{woocommerce}',
295 '{WooCommerce}',
296 ),
297 array(
298 $this->get_blogname(),
299 $domain,
300 $domain,
301 '<a href="https://woocommerce.com">WooCommerce</a>',
302 '<a href="https://woocommerce.com">WooCommerce</a>',
303 ),
304 $string
305 );
306 }
307
308 /**
309 * Filter callback to replace {site_title} in email footer
310 *
311 * @since 3.3.0
312 * @deprecated 3.7.0
313 * @param string $string Email footer text.
314 * @return string Email footer text with any replacements done.
315 */
316 public function email_footer_replace_site_title( $string ) {
317 wc_deprecated_function( 'WC_Emails::email_footer_replace_site_title', '3.7.0', 'WC_Emails::replace_placeholders' );
318 return $this->replace_placeholders( $string );
319 }
320
321 /**
322 * Wraps a message in the woocommerce mail template.
323 *
324 * @param string $email_heading Heading text.
325 * @param string $message Email message.
326 * @param bool $plain_text Set true to send as plain text. Default to false.
327 *
328 * @return string
329 */
330 public function wrap_message( $email_heading, $message, $plain_text = false ) {
331 // Buffer.
332 ob_start();
333
334 do_action( 'woocommerce_email_header', $email_heading, null );
335
336 echo wpautop( wptexturize( $message ) ); // WPCS: XSS ok.
337
338 do_action( 'woocommerce_email_footer', null );
339
340 // Get contents.
341 $message = ob_get_clean();
342
343 return $message;
344 }
345
346 /**
347 * Send the email.
348 *
349 * @param mixed $to Receiver.
350 * @param mixed $subject Email subject.
351 * @param mixed $message Message.
352 * @param string $headers Email headers (default: "Content-Type: text/html\r\n").
353 * @param string $attachments Attachments (default: "").
354 * @return bool
355 */
356 public function send( $to, $subject, $message, $headers = "Content-Type: text/html\r\n", $attachments = '' ) {
357 // Send.
358 $email = new WC_Email();
359 return $email->send( $to, $subject, $message, $headers, $attachments );
360 }
361
362 /**
363 * Prepare and send the customer invoice email on demand.
364 *
365 * @param int|WC_Order $order Order instance or ID.
366 */
367 public function customer_invoice( $order ) {
368 $email = $this->emails['WC_Email_Customer_Invoice'];
369
370 if ( ! is_object( $order ) ) {
371 $order = wc_get_order( absint( $order ) );
372 }
373
374 $email->trigger( $order->get_id(), $order );
375 }
376
377 /**
378 * Customer new account welcome email.
379 *
380 * @param int $customer_id Customer ID.
381 * @param array $new_customer_data New customer data.
382 * @param bool $password_generated If password is generated.
383 */
384 public function customer_new_account( $customer_id, $new_customer_data = array(), $password_generated = false ) {
385 if ( ! $customer_id ) {
386 return;
387 }
388
389 $user_pass = ! empty( $new_customer_data['user_pass'] ) ? $new_customer_data['user_pass'] : '';
390
391 $email = $this->emails['WC_Email_Customer_New_Account'];
392 $email->trigger( $customer_id, $user_pass, $password_generated );
393 }
394
395 /**
396 * Show the order details table
397 *
398 * @param WC_Order $order Order instance.
399 * @param bool $sent_to_admin If should sent to admin.
400 * @param bool $plain_text If is plain text email.
401 * @param string $email Email address.
402 */
403 public function order_details( $order, $sent_to_admin = false, $plain_text = false, $email = '' ) {
404 if ( $plain_text ) {
405 wc_get_template(
406 'emails/plain/email-order-details.php',
407 array(
408 'order' => $order,
409 'sent_to_admin' => $sent_to_admin,
410 'plain_text' => $plain_text,
411 'email' => $email,
412 )
413 );
414 } else {
415 wc_get_template(
416 'emails/email-order-details.php',
417 array(
418 'order' => $order,
419 'sent_to_admin' => $sent_to_admin,
420 'plain_text' => $plain_text,
421 'email' => $email,
422 )
423 );
424 }
425 }
426
427 /**
428 * Show order downloads in a table.
429 *
430 * @since 3.2.0
431 * @param WC_Order $order Order instance.
432 * @param bool $sent_to_admin If should sent to admin.
433 * @param bool $plain_text If is plain text email.
434 * @param string $email Email address.
435 */
436 public function order_downloads( $order, $sent_to_admin = false, $plain_text = false, $email = '' ) {
437 $show_downloads = $order->has_downloadable_item() && $order->is_download_permitted() && ! $sent_to_admin && ! is_a( $email, 'WC_Email_Customer_Refunded_Order' );
438
439 if ( ! $show_downloads ) {
440 return;
441 }
442
443 $downloads = $order->get_downloadable_items();
444 $columns = apply_filters(
445 'woocommerce_email_downloads_columns',
446 array(
447 'download-product' => __( 'Product', 'woocommerce' ),
448 'download-expires' => __( 'Expires', 'woocommerce' ),
449 'download-file' => __( 'Download', 'woocommerce' ),
450 )
451 );
452
453 if ( $plain_text ) {
454 wc_get_template(
455 'emails/plain/email-downloads.php',
456 array(
457 'order' => $order,
458 'sent_to_admin' => $sent_to_admin,
459 'plain_text' => $plain_text,
460 'email' => $email,
461 'downloads' => $downloads,
462 'columns' => $columns,
463 )
464 );
465 } else {
466 wc_get_template(
467 'emails/email-downloads.php',
468 array(
469 'order' => $order,
470 'sent_to_admin' => $sent_to_admin,
471 'plain_text' => $plain_text,
472 'email' => $email,
473 'downloads' => $downloads,
474 'columns' => $columns,
475 )
476 );
477 }
478 }
479
480 /**
481 * Add order meta to email templates.
482 *
483 * @param WC_Order $order Order instance.
484 * @param bool $sent_to_admin If should sent to admin.
485 * @param bool $plain_text If is plain text email.
486 */
487 public function order_meta( $order, $sent_to_admin = false, $plain_text = false ) {
488 $fields = apply_filters( 'woocommerce_email_order_meta_fields', array(), $sent_to_admin, $order );
489
490 /**
491 * Deprecated woocommerce_email_order_meta_keys filter.
492 *
493 * @since 2.3.0
494 */
495 $_fields = apply_filters( 'woocommerce_email_order_meta_keys', array(), $sent_to_admin );
496
497 if ( $_fields ) {
498 foreach ( $_fields as $key => $field ) {
499 if ( is_numeric( $key ) ) {
500 $key = $field;
501 }
502
503 $fields[ $key ] = array(
504 'label' => wptexturize( $key ),
505 'value' => wptexturize( $order->get_meta( $field ) ),
506 );
507 }
508 }
509
510 if ( $fields ) {
511
512 if ( $plain_text ) {
513
514 foreach ( $fields as $field ) {
515 if ( isset( $field['label'] ) && isset( $field['value'] ) && $field['value'] ) {
516 echo $field['label'] . ': ' . $field['value'] . "\n"; // WPCS: XSS ok.
517 }
518 }
519 } else {
520
521 foreach ( $fields as $field ) {
522 if ( isset( $field['label'] ) && isset( $field['value'] ) && $field['value'] ) {
523 echo '<p><strong>' . $field['label'] . ':</strong> ' . $field['value'] . '</p>'; // WPCS: XSS ok.
524 }
525 }
526 }
527 }
528 }
529
530 /**
531 * Is customer detail field valid?
532 *
533 * @param array $field Field data to check if is valid.
534 * @return boolean
535 */
536 public function customer_detail_field_is_valid( $field ) {
537 return isset( $field['label'] ) && ! empty( $field['value'] );
538 }
539
540 /**
541 * Allows developers to add additional customer details to templates.
542 *
543 * In versions prior to 3.2 this was used for notes, phone and email but this data has moved.
544 *
545 * @param WC_Order $order Order instance.
546 * @param bool $sent_to_admin If should sent to admin.
547 * @param bool $plain_text If is plain text email.
548 */
549 public function customer_details( $order, $sent_to_admin = false, $plain_text = false ) {
550 if ( ! is_a( $order, 'WC_Order' ) ) {
551 return;
552 }
553
554 $fields = array_filter( apply_filters( 'woocommerce_email_customer_details_fields', array(), $sent_to_admin, $order ), array( $this, 'customer_detail_field_is_valid' ) );
555
556 if ( ! empty( $fields ) ) {
557 if ( $plain_text ) {
558 wc_get_template( 'emails/plain/email-customer-details.php', array( 'fields' => $fields ) );
559 } else {
560 wc_get_template( 'emails/email-customer-details.php', array( 'fields' => $fields ) );
561 }
562 }
563 }
564
565 /**
566 * Get the email addresses.
567 *
568 * @param WC_Order $order Order instance.
569 * @param bool $sent_to_admin If should sent to admin.
570 * @param bool $plain_text If is plain text email.
571 */
572 public function email_addresses( $order, $sent_to_admin = false, $plain_text = false ) {
573 if ( ! is_a( $order, 'WC_Order' ) ) {
574 return;
575 }
576 if ( $plain_text ) {
577 wc_get_template(
578 'emails/plain/email-addresses.php',
579 array(
580 'order' => $order,
581 'sent_to_admin' => $sent_to_admin,
582 )
583 );
584 } else {
585 wc_get_template(
586 'emails/email-addresses.php',
587 array(
588 'order' => $order,
589 'sent_to_admin' => $sent_to_admin,
590 )
591 );
592 }
593 }
594
595 /**
596 * Get blog name formatted for emails.
597 *
598 * @return string
599 */
600 private function get_blogname() {
601 return wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
602 }
603
604 /**
605 * Low stock notification email.
606 *
607 * @param WC_Product $product Product instance.
608 */
609 public function low_stock( $product ) {
610 if ( 'no' === get_option( 'woocommerce_notify_low_stock', 'yes' ) ) {
611 return;
612 }
613
614 /**
615 * Determine if the current product should trigger a low stock notification
616 *
617 * @param int $product_id - The low stock product id
618 *
619 * @since 4.7.0
620 */
621 if ( false === apply_filters( 'woocommerce_should_send_low_stock_notification', true, $product->get_id() ) ) {
622 return;
623 }
624
625 $subject = sprintf( '[%s] %s', $this->get_blogname(), __( 'Product low in stock', 'woocommerce' ) );
626 $message = sprintf(
627 /* translators: 1: product name 2: items in stock */
628 __( '%1$s is low in stock. There are %2$d left.', 'woocommerce' ),
629 html_entity_decode( wp_strip_all_tags( $product->get_formatted_name() ), ENT_QUOTES, get_bloginfo( 'charset' ) ),
630 html_entity_decode( wp_strip_all_tags( $product->get_stock_quantity() ) )
631 );
632
633 wp_mail(
634 apply_filters( 'woocommerce_email_recipient_low_stock', get_option( 'woocommerce_stock_email_recipient' ), $product, null ),
635 apply_filters( 'woocommerce_email_subject_low_stock', $subject, $product, null ),
636 apply_filters( 'woocommerce_email_content_low_stock', $message, $product ),
637 apply_filters( 'woocommerce_email_headers', '', 'low_stock', $product, null ),
638 apply_filters( 'woocommerce_email_attachments', array(), 'low_stock', $product, null )
639 );
640 }
641
642 /**
643 * No stock notification email.
644 *
645 * @param WC_Product $product Product instance.
646 */
647 public function no_stock( $product ) {
648 if ( 'no' === get_option( 'woocommerce_notify_no_stock', 'yes' ) ) {
649 return;
650 }
651
652 /**
653 * Determine if the current product should trigger a no stock notification
654 *
655 * @param int $product_id - The out of stock product id
656 *
657 * @since 4.6.0
658 */
659 if ( false === apply_filters( 'woocommerce_should_send_no_stock_notification', true, $product->get_id() ) ) {
660 return;
661 }
662
663 $subject = sprintf( '[%s] %s', $this->get_blogname(), __( 'Product out of stock', 'woocommerce' ) );
664 /* translators: %s: product name */
665 $message = sprintf( __( '%s is out of stock.', 'woocommerce' ), html_entity_decode( wp_strip_all_tags( $product->get_formatted_name() ), ENT_QUOTES, get_bloginfo( 'charset' ) ) );
666
667 wp_mail(
668 apply_filters( 'woocommerce_email_recipient_no_stock', get_option( 'woocommerce_stock_email_recipient' ), $product, null ),
669 apply_filters( 'woocommerce_email_subject_no_stock', $subject, $product, null ),
670 apply_filters( 'woocommerce_email_content_no_stock', $message, $product ),
671 apply_filters( 'woocommerce_email_headers', '', 'no_stock', $product, null ),
672 apply_filters( 'woocommerce_email_attachments', array(), 'no_stock', $product, null )
673 );
674 }
675
676 /**
677 * Backorder notification email.
678 *
679 * @param array $args Arguments.
680 */
681 public function backorder( $args ) {
682 $args = wp_parse_args(
683 $args,
684 array(
685 'product' => '',
686 'quantity' => '',
687 'order_id' => '',
688 )
689 );
690
691 $order = wc_get_order( $args['order_id'] );
692 if (
693 ! $args['product'] ||
694 ! is_object( $args['product'] ) ||
695 ! $args['quantity'] ||
696 ! $order
697 ) {
698 return;
699 }
700
701 $subject = sprintf( '[%s] %s', $this->get_blogname(), __( 'Product backorder', 'woocommerce' ) );
702 /* translators: 1: product quantity 2: product name 3: order number */
703 $message = sprintf( __( '%1$s units of %2$s have been backordered in order #%3$s.', 'woocommerce' ), $args['quantity'], html_entity_decode( wp_strip_all_tags( $args['product']->get_formatted_name() ), ENT_QUOTES, get_bloginfo( 'charset' ) ), $order->get_order_number() );
704
705 wp_mail(
706 apply_filters( 'woocommerce_email_recipient_backorder', get_option( 'woocommerce_stock_email_recipient' ), $args, null ),
707 apply_filters( 'woocommerce_email_subject_backorder', $subject, $args, null ),
708 apply_filters( 'woocommerce_email_content_backorder', $message, $args ),
709 apply_filters( 'woocommerce_email_headers', '', 'backorder', $args, null ),
710 apply_filters( 'woocommerce_email_attachments', array(), 'backorder', $args, null )
711 );
712 }
713
714 /**
715 * Adds Schema.org markup for order in JSON-LD format.
716 *
717 * @deprecated 3.0.0
718 * @see WC_Structured_Data::generate_order_data()
719 *
720 * @since 2.6.0
721 * @param WC_Order $order Order instance.
722 * @param bool $sent_to_admin If should sent to admin.
723 * @param bool $plain_text If is plain text email.
724 */
725 public function order_schema_markup( $order, $sent_to_admin = false, $plain_text = false ) {
726 wc_deprecated_function( 'WC_Emails::order_schema_markup', '3.0', 'WC_Structured_Data::generate_order_data' );
727
728 WC()->structured_data->generate_order_data( $order, $sent_to_admin, $plain_text );
729 WC()->structured_data->output_structured_data();
730 }
731 }
732