Completed
Push — master ( e1fcb8...b01a52 )
by Brian
26s queued 17s
created

user_invoice()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 5
c 1
b 0
f 0
dl 0
loc 11
rs 10
cc 2
nc 2
nop 1
1
<?php
2
/**
3
 * Contains the invoice notification emails management class.
4
 *
5
 */
6
7
defined( 'ABSPATH' ) || exit;
8
9
/**
10
 * This class handles invoice notificaiton emails.
11
 *
12
 */
13
class GetPaid_Invoice_Notification_Emails {
14
15
	/**
16
	 * The array of invoice email actions.
17
	 *
18
	 * @param array
19
	 */
20
	public $invoice_actions;
21
22
	/**
23
	 * Class constructor
24
	 *
25
	 */
26
	public function __construct() {
27
28
		$this->invoice_actions = apply_filters(
29
			'getpaid_notification_email_invoice_triggers',
30
			array(
31
				'getpaid_new_invoice'                   => 'new_invoice',
32
				'getpaid_invoice_status_wpi-cancelled'  => 'cancelled_invoice',
33
				'getpaid_invoice_status_wpi-failed'     => 'failed_invoice',
34
				'getpaid_invoice_status_wpi-onhold'     => 'onhold_invoice',
35
				'getpaid_invoice_status_wpi-processing' => 'processing_invoice',
36
				'getpaid_invoice_status_publish'        => 'completed_invoice',
37
				'getpaid_invoice_status_wpi-renewal'    => 'completed_invoice',
38
				'getpaid_invoice_status_wpi-refunded'   => 'refunded_invoice',
39
				'getpaid_new_invoice'                   => 'user_invoice',
40
				'getpaid_new_customer_note'             => 'user_note',
41
				'getpaid_daily_maintenance'             => 'overdue',
42
43
			)
44
		);
45
46
		$this->init_hooks();
47
48
	}
49
50
	/**
51
	 * Registers email hooks.
52
	 */
53
	public function init_hooks() {
54
55
		add_filter( 'getpaid_get_email_merge_tags', array( $this, 'invoice_merge_tags' ), 10, 2 );
56
		add_filter( 'getpaid_invoice_email_recipients', array( $this, 'filter_email_recipients' ), 10, 2 );
57
		foreach ( $this->invoice_actions as $hook => $email_type ) {
58
59
			$email = new GetPaid_Notification_Email( $email_type );
60
61
			if ( ! $email->is_active() ) {
62
				continue;
63
			}
64
65
			if ( method_exists( $this, $email_type ) ) {
66
				add_action( $hook, array( $this, $email_type ), 100, 2 );
67
				continue;
68
			}
69
70
			do_action( 'getpaid_invoice_notification_email_register_hook', $email );
71
72
		}
73
74
	}
75
76
	/**
77
	 * Filters invoice merge tags.
78
	 *
79
	 * @param array $merge_tags
80
	 * @param mixed|WPInv_Invoice|WPInv_Subscription $object
81
	 */
82
	public function invoice_merge_tags( $merge_tags, $object ) {
83
84
		if ( is_a( $object, 'WPInv_Invoice' ) ) {
85
			return array_merge(
86
				$merge_tags,
87
				$this->get_invoice_merge_tags( $object )
88
			);
89
		}
90
91
		if ( is_a( $object, 'WPInv_Subscription' ) ) {
92
			return array_merge(
93
				$merge_tags,
94
				$this->get_invoice_merge_tags( $object->get_parent_payment() )
95
			);
96
		}
97
98
		return $merge_tags;
99
100
	}
101
102
	/**
103
	 * Generates invoice merge tags.
104
	 *
105
	 * @param WPInv_Invoice $invoice
106
	 * @return array
107
	 */
108
	public function get_invoice_merge_tags( $invoice ) {
109
110
		// Abort if it does not exist.
111
		if ( ! $invoice->get_id() ) {
112
			return array();
113
		}
114
115
		return array(
116
			'{name}'                => sanitize_text_field( $invoice->get_user_full_name() ),
117
			'{full_name}'           => sanitize_text_field( $invoice->get_user_full_name() ),
118
			'{first_name}'          => sanitize_text_field( $invoice->get_first_name() ),
119
			'{last_name}'           => sanitize_text_field( $invoice->get_last_name() ),
120
			'{email}'               => sanitize_email( $invoice->get_email() ),
121
			'{invoice_number}'      => sanitize_text_field( $invoice->get_number() ),
122
			'{invoice_total}'       => wpinv_price( wpinv_format_amount( $invoice->get_total() ) ),
123
			'{invoice_link}'        => esc_url( $invoice->get_view_url() ),
124
			'{invoice_pay_link}'    => esc_url( $invoice->get_checkout_payment_url() ),
125
			'{invoice_receipt_link}'=> esc_url( $invoice->get_receipt_url() ),
126
			'{invoice_date}'        => date( get_option( 'date_format' ), strtotime( $invoice->get_date_created(), current_time( 'timestamp' ) ) ),
0 ignored issues
show
Bug introduced by
It seems like get_option('date_format') can also be of type false; however, parameter $format of date() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

126
			'{invoice_date}'        => date( /** @scrutinizer ignore-type */ get_option( 'date_format' ), strtotime( $invoice->get_date_created(), current_time( 'timestamp' ) ) ),
Loading history...
127
			'{invoice_due_date}'    => date( get_option( 'date_format' ), strtotime( $invoice->get_due_date(), current_time( 'timestamp' ) ) ),
128
			'{invoice_quote}'       => sanitize_text_field( $invoice->get_type() ),
129
			'{invoice_label}'       => sanitize_text_field( ucfirst( $invoice->get_type() ) ),
130
			'{invoice_description}' => wp_kses_post( $invoice->get_description() ),
131
			'{subscription_name}'   => wp_kses_post( $invoice->get_subscription_name() ),
132
			'{is_was}'              => strtotime( $invoice->get_due_date() ) < current_time( 'timestamp' ) ? __( 'was', 'invoicing' ) : __( 'is', 'invoicing' ),
133
		);
134
135
	}
136
137
	/**
138
	 * Helper function to send an email.
139
	 *
140
	 * @param WPInv_Invoice $invoice
141
	 * @param GetPaid_Notification_Email $email
142
	 * @param string $type
143
	 * @param string|array $recipients
144
	 * @param array $extra_args Extra template args.
145
	 */
146
	public function send_email( $invoice, $email, $type, $recipients, $extra_args = array() ) {
147
148
		do_action( 'getpaid_before_send_invoice_notification', $type, $invoice, $email );
149
150
		$mailer     = new GetPaid_Notification_Email_Sender();
151
		$merge_tags = $email->get_merge_tags();
152
153
		$result = $mailer->send(
154
			apply_filters( 'getpaid_invoice_email_recipients', wpinv_parse_list( $recipients ), $email ),
155
			$email->add_merge_tags( $email->get_subject(), $merge_tags ),
156
			$email->get_content( $merge_tags, $extra_args ),
157
			$email->get_attachments()
158
		);
159
160
		// Maybe send a copy to the admin.
161
		if ( $email->include_admin_bcc() ) {
162
			$mailer->send(
163
				wpinv_get_admin_email(),
164
				$email->add_merge_tags( $email->get_subject() . __( ' - ADMIN BCC COPY', 'invoicing' ), $merge_tags ),
165
				$email->get_content( $merge_tags ),
166
				$email->get_attachments()
167
			);
168
		}
169
170
		if ( ! $result ) {
171
			$invoice->add_note( sprintf( __( 'Failed sending %s notification email.', 'invoicing' ), sanitize_key( $type ) ), false, false, true );
172
		}
173
174
		do_action( 'getpaid_after_send_invoice_notification', $type, $invoice, $email );
175
176
		return $result;
177
	}
178
179
	/**
180
	 * Also send emails to any cc users.
181
	 *
182
	 * @param array $recipients
183
	 * @param GetPaid_Notification_Email $email
184
	 */
185
	public function filter_email_recipients( $recipients, $email ) {
186
187
		if ( ! $email->is_admin_email() ) {
188
			$cc = $email->object->get_email_cc();
0 ignored issues
show
Bug introduced by
The method get_email_cc() does not exist on WPInv_Subscription. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

188
			/** @scrutinizer ignore-call */ 
189
   $cc = $email->object->get_email_cc();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method get_email_cc() does not exist on WPInv_Item. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

188
			/** @scrutinizer ignore-call */ 
189
   $cc = $email->object->get_email_cc();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
189
190
			if ( ! empty( $cc ) ) {
191
				$cc = array_map( 'sanitize_email', wpinv_parse_list( $cc ) );
192
				$recipients = array_filter( array_unique( array_merge( $recipients, $cc ) ) );
193
			}
194
195
		}
196
197
		return $recipients;
198
199
	}
200
201
	/**
202
	 * Sends a new invoice notification.
203
	 *
204
	 * @param WPInv_Invoice $invoice
205
	 */
206
	public function new_invoice( $invoice ) {
207
208
		$email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
209
		$recipient = wpinv_get_admin_email();
210
211
		return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
212
213
	}
214
215
	/**
216
	 * Sends a cancelled invoice notification.
217
	 *
218
	 * @param WPInv_Invoice $invoice
219
	 */
220
	public function cancelled_invoice( $invoice ) {
221
222
		$email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
223
		$recipient = wpinv_get_admin_email();
224
225
		return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
226
227
	}
228
229
	/**
230
	 * Sends a failed invoice notification.
231
	 *
232
	 * @param WPInv_Invoice $invoice
233
	 */
234
	public function failed_invoice( $invoice ) {
235
236
		$email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
237
		$recipient = wpinv_get_admin_email();
238
239
		return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
240
241
	}
242
243
	/**
244
	 * Sends a notification whenever an invoice is put on hold.
245
	 *
246
	 * @param WPInv_Invoice $invoice
247
	 */
248
	public function onhold_invoice( $invoice ) {
249
250
		$email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
251
		$recipient = $invoice->get_email();
252
253
		return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
254
255
	}
256
257
	/**
258
	 * Sends a notification whenever an invoice is marked as processing payment.
259
	 *
260
	 * @param WPInv_Invoice $invoice
261
	 */
262
	public function processing_invoice( $invoice ) {
263
264
		$email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
265
		$recipient = $invoice->get_email();
266
267
		return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
268
269
	}
270
271
	/**
272
	 * Sends a notification whenever an invoice is paid.
273
	 *
274
	 * @param WPInv_Invoice $invoice
275
	 */
276
	public function completed_invoice( $invoice ) {
277
278
		// (Maybe) abort if it is a renewal invoice.
279
		if ( $invoice->is_renewal() && ! wpinv_get_option( 'email_completed_invoice_renewal_active', false ) ) {
280
			return;
281
		}
282
283
		$email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
284
		$recipient = $invoice->get_email();
285
286
		return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
287
288
	}
289
290
	/**
291
	 * Sends a notification whenever an invoice is refunded.
292
	 *
293
	 * @param WPInv_Invoice $invoice
294
	 */
295
	public function refunded_invoice( $invoice ) {
296
297
		$email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
298
		$recipient = $invoice->get_email();
299
300
		return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
301
302
	}
303
304
	/**
305
	 * Notifies a user about new invoices
306
	 *
307
	 * @param WPInv_Invoice $invoice
308
	 */
309
	public function user_invoice( $invoice ) {
310
311
		// Only send this email for invoices created via the admin page.
312
		if ( $this->is_payment_form_invoice( $invoice->get_id() ) ) {
313
			return;
314
		}
315
316
		$email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
317
		$recipient = $invoice->get_email();
318
319
		return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
320
321
	}
322
323
	/**
324
	 * Checks if an invoice is a payment form invoice.
325
	 *
326
	 * @param int $invoice
327
	 * @return bool
328
	 */
329
	public function is_payment_form_invoice( $invoice ) {
330
		return empty( $_GET['getpaid-admin-action'] ) && 'payment_form' == get_post_meta( $invoice, 'wpinv_created_via', true );
331
	}
332
333
	/**
334
	 * Notifies admin about new invoice notes
335
	 *
336
	 * @param WPInv_Invoice $invoice
337
	 * @param string $note
338
	 */
339
	public function user_note( $invoice, $note ) {
340
341
		$email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
342
		$recipient = $invoice->get_email();
343
344
		return $this->send_email( $invoice, $email, __FUNCTION__, $recipient, array( 'customer_note' => $note ) );
345
346
	}
347
348
	/**
349
	 * (Force) Sends overdue notices.
350
	 *
351
	 * @param WPInv_Invoice $invoice
352
	 */
353
	public function force_send_overdue_notice( $invoice ) {
354
		$email = new GetPaid_Notification_Email( 'overdue', $invoice );
355
		return $this->send_email( $invoice, $email, 'overdue', $invoice->get_email() );
356
	}
357
358
	/**
359
	 * Sends overdue notices.
360
	 *
361
	 * @TODO: Create an invoices query class.
362
	 */
363
	public function overdue() {
364
		global $wpdb;
365
366
		$email = new GetPaid_Notification_Email( __FUNCTION__ );
367
368
		// Fetch reminder days.
369
		$reminder_days = array_unique( wp_parse_id_list( $email->get_option( 'days' ) ) );
370
371
		// Abort if non is set.
372
		if ( empty( $reminder_days ) ) {
373
			return;
374
		}
375
376
		// Retrieve date query.
377
		$date_query = $this->get_date_query( $reminder_days );
378
379
		// Invoices table.
380
		$table = $wpdb->prefix . 'getpaid_invoices';
381
382
		// Fetch invoices.
383
		$invoices  = $wpdb->get_col(
384
			"SELECT posts.ID FROM $wpdb->posts as posts
385
			LEFT JOIN $table as invoices ON invoices.post_id = posts.ID
386
			WHERE posts.post_type = 'wpi_invoice' AND posts.post_status = 'wpi-pending' $date_query");
387
388
		foreach ( $invoices as $invoice ) {
389
390
			// Only send this email for invoices created via the admin page.
391
			if ( ! $this->is_payment_form_invoice( $invoice ) ) {
392
				$invoice       = new WPInv_Invoice( $invoice );
393
				$email->object = $invoice;
394
395
				if ( $invoice->needs_payment() ) {
396
					$this->send_email( $invoice, $email, __FUNCTION__, $invoice->get_email() );
397
				}
398
399
			}
400
401
		}
402
403
	}
404
405
	/**
406
	 * Calculates the date query for an invoices query
407
	 *
408
	 * @param array $reminder_days
409
	 * @return string
410
	 */
411
	public function get_date_query( $reminder_days ) {
412
413
		$date_query = array(
414
			'relation'  => 'OR'
415
		);
416
417
		foreach ( $reminder_days as $days ) {
418
			$date = date_parse( date( 'Y-m-d', strtotime( "-$days days", current_time( 'timestamp' ) ) ) );
419
420
			$date_query[] = array(
421
				'year'  => $date['year'],
422
				'month' => $date['month'],
423
				'day'   => $date['day'],
424
			);
425
426
		}
427
428
		$date_query = new WP_Date_Query( $date_query, 'invoices.due_date' );
429
430
		return $date_query->get_sql();
431
432
	}
433
434
}
435