PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / trunk
WCPOS – Point of Sale (POS) plugin for WooCommerce vtrunk
1.10.13 1.10.14 1.10.12 1.10.11 1.10.10 1.10.9 1.10.8 untagged-3d9b7ccddc54df87c672 1.10.7 1.10.6 1.10.5 1.10.3 1.10.4 1.10.2 1.10.1 1.10.0 1.9.17 1.9.15 1.9.16 1.9.14 1.9.13 1.9.12 1.9.11 1.9.10 1.9.9 All 158 releases
woocommerce-pos / includes / Emails.php

Emails.php in WCPOS – Point of Sale (POS) plugin for WooCommerce trunk, at includes/Emails.php

274 lines 8.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WCPOS Emails Class
4 * Handles email management for POS orders.
5 *
6 * @author Paul Kilmurray <paul@kilbot.com>
7 *
8 * @see http://wcpos.com
9 * @package WCPOS\WooCommercePOS
10 */
11
12 namespace WCPOS\WooCommercePOS;
13
14 use WC_Email;
15 use WC_Order;
16 use WCPOS\WooCommercePOS\Services\Settings;
17
18 /**
19 * Emails Class
20 * - manages email sending for POS orders.
21 */
22 class Emails {
23 /**
24 * Constructor.
25 */
26 public function __construct() {
27 // Get filterable email arrays - allow users to customize which emails are affected.
28 $admin_emails = apply_filters(
29 'woocommerce_pos_admin_emails',
30 array(
31 'cancelled_order',
32 'failed_order',
33 )
34 );
35
36 $customer_emails = apply_filters(
37 'woocommerce_pos_customer_emails',
38 array(
39 'customer_failed_order',
40 'customer_on_hold_order',
41 'customer_processing_order',
42 'customer_completed_order',
43 'customer_refunded_order',
44 )
45 );
46
47 // Hook into email enabled filters - this is the main control mechanism.
48 foreach ( $admin_emails as $email_id ) {
49 add_filter( "woocommerce_email_enabled_{$email_id}", array( $this, 'manage_admin_emails' ), 999, 3 );
50 }
51 foreach ( $customer_emails as $email_id ) {
52 add_filter( "woocommerce_email_enabled_{$email_id}", array( $this, 'manage_customer_emails' ), 999, 3 );
53 }
54
55 // Control new_order recipients (admin + cashier) via the recipient filter.
56 add_filter( 'woocommerce_email_recipient_new_order', array( $this, 'filter_new_order_recipients' ), 10, 3 );
57
58 // Manually trigger new_order email for POS status changes.
59 // WooCommerce doesn't automatically trigger new_order for pos-open/pos-partial transitions.
60 add_action( 'woocommerce_order_status_pos-open_to_completed', array( $this, 'trigger_new_order_email' ), 10, 2 );
61 add_action( 'woocommerce_order_status_pos-open_to_processing', array( $this, 'trigger_new_order_email' ), 10, 2 );
62 add_action( 'woocommerce_order_status_pos-open_to_on-hold', array( $this, 'trigger_new_order_email' ), 10, 2 );
63 add_action( 'woocommerce_order_status_pos-partial_to_completed', array( $this, 'trigger_new_order_email' ), 10, 2 );
64 add_action( 'woocommerce_order_status_pos-partial_to_processing', array( $this, 'trigger_new_order_email' ), 10, 2 );
65 add_action( 'woocommerce_order_status_pos-partial_to_on-hold', array( $this, 'trigger_new_order_email' ), 10, 2 );
66 }
67
68 /**
69 * Manage admin email sending for POS orders.
70 * Handles cancelled_order and failed_order via the enabled filter.
71 * Note: new_order is handled separately via filter_new_order_recipients.
72 *
73 * @param bool $enabled Whether the email is enabled.
74 * @param null|WC_Order $order The order object.
75 * @param mixed|WC_Email $email_class The email class.
76 *
77 * @return bool Whether the email should be sent.
78 */
79 public function manage_admin_emails( $enabled, $order, $email_class ) {
80 if ( ! woocommerce_pos_is_pos_order( $order ) ) {
81 return $enabled;
82 }
83
84 $email_id = $email_class instanceof WC_Email ? $email_class->id : 'unknown';
85 $settings = Settings::instance()->admin_emails();
86
87 // Master toggle off = all disabled.
88 if ( empty( $settings['enabled'] ) ) {
89 $is_enabled = false;
90 } else {
91 // Individual toggle (default true if key not set).
92 $is_enabled = $settings[ $email_id ] ?? true;
93 }
94
95 /**
96 * Filters whether a specific admin email is enabled for a POS order.
97 *
98 * @since 1.4.12
99 *
100 * @param bool $is_enabled Whether the email is enabled.
101 * @param string $email_id The WooCommerce email ID.
102 * @param WC_Order $order The order object.
103 * @param WC_Email $email_class The email class instance.
104 */
105 return apply_filters( 'woocommerce_pos_admin_email_enabled', $is_enabled, $email_id, $order, $email_class );
106 }
107
108 /**
109 * Manage customer email sending for POS orders.
110 *
111 * @param bool $enabled Whether the email is enabled.
112 * @param null|WC_Order $order The order object.
113 * @param mixed|WC_Email $email_class The email class.
114 *
115 * @return bool Whether the email should be sent.
116 */
117 public function manage_customer_emails( $enabled, $order, $email_class ) {
118 if ( ! woocommerce_pos_is_pos_order( $order ) ) {
119 return $enabled;
120 }
121
122 $email_id = $email_class instanceof WC_Email ? $email_class->id : 'unknown';
123 $settings = Settings::instance()->customer_emails();
124
125 // Master toggle off = all disabled.
126 if ( empty( $settings['enabled'] ) ) {
127 $is_enabled = false;
128 } else {
129 // Individual toggle (default true if key not set).
130 $is_enabled = $settings[ $email_id ] ?? true;
131 }
132
133 /**
134 * Filters whether a specific customer email is enabled for a POS order.
135 *
136 * @since 1.4.12
137 *
138 * @param bool $is_enabled Whether the email is enabled.
139 * @param string $email_id The WooCommerce email ID.
140 * @param WC_Order $order The order object.
141 * @param WC_Email $email_class The email class instance.
142 */
143 return apply_filters( 'woocommerce_pos_customer_email_enabled', $is_enabled, $email_id, $order, $email_class );
144 }
145
146 /**
147 * Filter new_order email recipients for POS orders.
148 *
149 * Builds the recipient list based on admin and cashier email settings.
150 * Uses the recipient filter (not the enabled filter) so that admin and
151 * cashier toggles can work independently.
152 *
153 * @param string $recipient Comma-separated recipient emails.
154 * @param null|WC_Order $order The order object.
155 * @param null|WC_Email $email The email class instance.
156 *
157 * @return string Filtered comma-separated recipient emails.
158 */
159 public function filter_new_order_recipients( $recipient, $order = null, $email = null ) {
160 if ( ! $order instanceof WC_Order || ! woocommerce_pos_is_pos_order( $order ) ) {
161 return $recipient;
162 }
163
164 $admin_settings = Settings::instance()->admin_emails();
165 $cashier_settings = Settings::instance()->cashier_emails();
166
167 $admin_wants_new_order = ! empty( $admin_settings['enabled'] )
168 && ( $admin_settings['new_order'] ?? true );
169
170 // If admin doesn't want new_order, clear the default recipient list.
171 if ( ! $admin_wants_new_order ) {
172 $recipient = '';
173 }
174
175 // Check if cashier should receive the email.
176 $cashier_wants_new_order = ! empty( $cashier_settings['enabled'] )
177 && ( $cashier_settings['new_order'] ?? true );
178
179 if ( $cashier_wants_new_order ) {
180 $cashier_email = $this->get_cashier_email( $order );
181
182 if ( $cashier_email ) {
183 // Dedup: don't add if already in the recipient list.
184 $existing = array_map( 'trim', explode( ',', $recipient ) );
185 $existing = array_filter( $existing );
186
187 if ( ! \in_array( $cashier_email, $existing, true ) ) {
188 $existing[] = $cashier_email;
189 }
190
191 $recipient = implode( ', ', $existing );
192 }
193 }
194
195 return $recipient;
196 }
197
198 /**
199 * Manually trigger new_order admin email for POS orders.
200 *
201 * This is needed because WooCommerce doesn't automatically trigger new_order
202 * for pos-open/pos-partial status transitions.
203 *
204 * @param int $order_id Order ID.
205 * @param WC_Order $order Order object.
206 */
207 public function trigger_new_order_email( $order_id, $order = null ): void {
208 if ( ! $order ) {
209 $order = wc_get_order( $order_id );
210 }
211
212 if ( ! woocommerce_pos_is_pos_order( $order ) ) {
213 return;
214 }
215
216 // Check if anyone wants the new_order email.
217 $admin_settings = Settings::instance()->admin_emails();
218 $cashier_settings = Settings::instance()->cashier_emails();
219
220 $admin_wants = ! empty( $admin_settings['enabled'] )
221 && ( $admin_settings['new_order'] ?? true );
222 $cashier_wants = ! empty( $cashier_settings['enabled'] )
223 && ( $cashier_settings['new_order'] ?? true );
224
225 if ( ! $admin_wants && ! $cashier_wants ) {
226 return;
227 }
228
229 // Get the new_order email by ID, not class name.
230 $mailer = WC()->mailer();
231 $emails = $mailer->get_emails();
232
233 foreach ( $emails as $email ) {
234 if ( 'new_order' === $email->id ) {
235 // Temporarily enable the email to ensure it sends.
236 $original_enabled = $email->enabled;
237 $email->enabled = 'yes';
238
239 // Trigger the email.
240 // @phpstan-ignore-next-line.
241 $email->trigger( $order_id, $order );
242
243 // Restore original state.
244 $email->enabled = $original_enabled;
245
246 break;
247 }
248 }
249 }
250
251 /**
252 * Get the cashier's email address from the order.
253 *
254 * @param WC_Order $order The order object.
255 *
256 * @return string The cashier email address, or empty string if not found.
257 */
258 private function get_cashier_email( WC_Order $order ): string {
259 $cashier_id = $order->get_meta( '_pos_user' );
260
261 if ( empty( $cashier_id ) ) {
262 return '';
263 }
264
265 $user = get_user_by( 'id', $cashier_id );
266
267 if ( ! $user || empty( $user->user_email ) ) {
268 return '';
269 }
270
271 return $user->user_email;
272 }
273 }
274