Completed
Push — issues/611 ( cbcc9a...382813 )
by Ravinder
18:21
created

Give_Email_Notification   B

Complexity

Total Complexity 50

Size/Duplication

Total Lines 610
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 4

Importance

Changes 0
Metric Value
dl 0
loc 610
rs 8.5765
c 0
b 0
f 0
wmc 50
lcom 2
cbo 4

27 Methods

Rating   Name   Duplication   Size   Complexity  
A init() 0 3 1
A get_instance() 0 8 3
A load() 0 10 3
A setup_filters() 0 23 3
A add_section() 0 5 1
A hide_section() 0 5 1
A add_setting_fields() 0 7 2
A get_setting_fields() 0 3 1
A add_metabox_setting_field() 0 10 1
A get_extra_setting_fields() 0 3 1
A get_recipient() 0 14 3
A get_recipient_group_name() 0 3 1
A get_notification_status() 0 9 1
A get_email_subject() 0 10 1
A get_email_message() 0 10 1
A get_email_message_field_description() 0 13 2
A get_emails_tags_list_html() 0 19 3
C get_allowed_email_tags() 0 27 8
A get_default_email_subject() 0 3 1
A get_default_email_message() 0 3 1
A get_preview_email_recipient() 0 15 1
A get_email_attachments() 0 8 1
A get_email_type() 0 3 1
A send_preview_email() 0 10 1
B send_email_notification() 0 29 2
B preview_email_template_tags() 0 60 4
A setup_email_data() 0 2 1

How to fix   Complexity   

Complex Class

Complex classes like Give_Email_Notification often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Give_Email_Notification, and based on these observations, apply Extract Interface, too.

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 27 and the first side effect is on line 16.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * Email Notification
4
 *
5
 * This class handles all email notification settings.
6
 *
7
 * @package     Give
8
 * @subpackage  Classes/Emails
9
 * @copyright   Copyright (c) 2016, WordImpress
10
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
11
 * @since       2.0
12
 */
13
14
// Exit if access directly.
15
if ( ! defined( 'ABSPATH' ) ) {
16
	exit;
17
}
18
19
if ( ! class_exists( 'Give_Email_Notification' ) ) :
20
21
	/**
22
	 * Give_Email_Notification
23
	 *
24
	 * @abstract
25
	 * @since       2.0
26
	 */
27
	abstract class Give_Email_Notification {
28
		/**
29
		 * Array of instances
30
		 *
31
		 * @since  2.0
32
		 * @access private
33
		 * @var array
34
		 */
35
		private static $singleton = array();
36
37
38
		/**
39
		 * Array of notification settings.
40
		 *
41
		 * @since  2.0
42
		 * @access public
43
		 * @var array
44
		 */
45
		public $config = array(
46
			'id'                           => '',
47
			'label'                        => '',
48
			'description'                  => '',
49
			'has_recipient_field'          => false,
50
			'notification_status'          => 'disabled',
51
			'notification_status_editable' => true,
52
			'has_preview'                  => true,
53
			'has_preview_header'           => true,
54
			'preview_email_tags_values'    => array(),
55
			'email_tag_context'            => 'all',
56
			'form_metabox_setting'         => true,
57
		);
58
59
		/**
60
		 * @var     string $recipient_email Donor email.
61
		 * @access  protected
62
		 * @since   2.0
63
		 */
64
		protected $recipient_email = '';
65
66
		/**
67
		 * @var     string $recipient_group_name Categories single or group of recipient.
68
		 * @access  protected
69
		 * @since   2.0
70
		 */
71
		protected $recipient_group_name = '';
72
73
		/**
74
		 * Setup email notification.
75
		 *
76
		 * @since 2.0
77
		 */
78
		public function init() {
79
80
		}
81
82
83
		/**
84
		 * Get instance.
85
		 *
86
		 * @since  2.0
87
		 * @access public
88
		 * @return Give_Email_Notification
89
		 */
90
		public static function get_instance() {
91
			$class = get_called_class();
92
			if ( ! array_key_exists( $class, self::$singleton ) || is_null( self::$singleton[ $class ] ) ) {
93
				self::$singleton[ $class ] = new $class();
94
			}
95
96
			return self::$singleton[ $class ];
97
		}
98
99
		/**
100
		 * Setup action and filters.
101
		 *
102
		 * @access  public
103
		 * @since   2.0
104
		 *
105
		 * @param array $config
106
		 */
107
		public function load( $config ) {
108
			// Set notification configuration.
109
			$this->config = wp_parse_args( $config, $this->config );
110
111
			// Set email preview header status.
112
			$this->config['has_preview_header'] = $this->config['has_preview'] && $this->config['has_preview_header'] ? true : false;
113
114
			// setup filters.
115
			$this->setup_filters();
116
		}
117
118
119
		/**
120
		 * Setup filters.
121
		 *
122
		 * @since  2.0
123
		 * @access public
124
		 */
125
		private function setup_filters() {
126
			// Apply filter only for current email notification section.
127
			if ( give_get_current_setting_section() === $this->config['id'] ) {
128
				// Initialize email context for email notification.
129
				$this->config['email_tag_context'] = apply_filters(
130
					"give_{$this->config['id']}_email_tag_context",
131
					$this->config['email_tag_context'],
132
					$this
133
				);
134
			}
135
136
			// Setup setting fields.
137
			add_filter( 'give_get_settings_emails', array( $this, 'add_setting_fields' ), 10, 2 );
138
139
			if ( $this->config['form_metabox_setting'] ) {
140
				add_filter(
141
					'give_email_notification_options_metabox_fields',
142
					array( $this, 'add_metabox_setting_field' ),
143
					10,
144
					2
145
				);
146
			}
147
		}
148
149
		/**
150
		 * Add sections.
151
		 *
152
		 * @since 2.0
153
		 *
154
		 * @param array $sections
155
		 *
156
		 * @return array
157
		 */
158
		public function add_section( $sections ) {
159
			$sections[ $this->config['id'] ] = $this->config['label'];
160
161
			return $sections;
162
		}
163
164
		/**
165
		 * Add sections.
166
		 *
167
		 * @since 2.0
168
		 *
169
		 * @param bool $hide_section
170
		 *
171
		 * @return bool
172
		 */
173
		public function hide_section( $hide_section ) {
0 ignored issues
show
Unused Code introduced by
The parameter $hide_section is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
174
			$hide_section = true;
175
176
			return $hide_section;
177
		}
178
179
		/**
180
		 * Register email settings.
181
		 *
182
		 * @since  2.0
183
		 * @access public
184
		 *
185
		 * @param   array $settings
186
		 *
187
		 * @return  array
188
		 */
189
		public function add_setting_fields( $settings ) {
190
			if ( $this->config['id'] === give_get_current_setting_section() ) {
191
				$settings = $this->get_setting_fields();
192
			}
193
194
			return $settings;
195
		}
196
197
198
		/**
199
		 * Get setting fields
200
		 *
201
		 * @since  2.0
202
		 * @access public
203
		 *
204
		 * @param int $form_id
205
		 *
206
		 * @return array
207
		 */
208
		public function get_setting_fields( $form_id = 0 ) {
209
			return Give_Email_Setting_Field::get_setting_fields( $this, $form_id );
210
		}
211
212
213
		/**
214
		 * Register email settings to form metabox.
215
		 *
216
		 * @since  2.0
217
		 * @access public
218
		 *
219
		 * @param array $settings
220
		 * @param int   $post_id
221
		 *
222
		 * @return array
223
		 */
224
		public function add_metabox_setting_field( $settings, $post_id ) {
225
226
			$settings[] = array(
227
				'id'     => $this->config['id'],
228
				'title'  => $this->config['label'],
229
				'fields' => $this->get_setting_fields( $post_id ),
230
			);
231
232
			return $settings;
233
		}
234
235
236
		/**
237
		 * Get extra setting field.
238
		 *
239
		 * @since  2.0
240
		 * @access public
241
		 *
242
		 * @param int $form_id
243
		 *
244
		 * @return array
245
		 */
246
		public function get_extra_setting_fields( $form_id = 0 ) {
0 ignored issues
show
Unused Code introduced by
The parameter $form_id is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
247
			return array();
248
		}
249
250
251
		/**
252
		 * Get recipient(s).
253
		 *
254
		 * Note: in case of admin notification this fx will return array of emails otherwise empty string or email of donor.
255
		 *
256
		 * @since  2.0
257
		 * @access public
258
		 * @return string|array
259
		 */
260
		public function get_recipient() {
261
			$recipient = $this->recipient_email;
262
263
			if ( ! $recipient && $this->config['has_recipient_field'] ) {
264
				$recipient = give_get_option( "{$this->config['id']}_recipient" );
265
			}
266
267
			/**
268
			 * Filter the recipients
269
			 *
270
			 * @since 2.0
271
			 */
272
			return apply_filters( "give_{$this->config['id']}_get_recipients", give_check_variable( $recipient, 'empty', Give()->emails->get_from_address() ), $this );
273
		}
274
275
		/**
276
		 * Get recipient(s) group name.
277
		 * *
278
		 *
279
		 * @since  2.0
280
		 * @access public
281
		 * @return string|array
282
		 */
283
		public function get_recipient_group_name() {
284
			return $this->recipient_group_name;
285
		}
286
287
		/**
288
		 * Get notification status.
289
		 *
290
		 * @since  2.0
291
		 * @access public
292
		 * @return bool
293
		 */
294
		public function get_notification_status() {
295
296
			/**
297
			 * Filter the notification status.
298
			 *
299
			 * @since 1.8
300
			 */
301
			return apply_filters( "give_{$this->config['id']}_get_notification_status", give_get_option( "{$this->config['id']}_notification", $this->config['notification_status'] ), $this );
302
		}
303
304
		/**
305
		 * Get email subject.
306
		 *
307
		 * @since  2.0
308
		 * @access public
309
		 * @return string
310
		 */
311
		function get_email_subject() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
312
			$subject = wp_strip_all_tags( give_get_option( "{$this->config['id']}_email_subject", $this->get_default_email_subject() ) );
313
314
			/**
315
			 * Filter the subject.
316
			 *
317
			 * @since 2.0
318
			 */
319
			return apply_filters( "give_{$this->config['id']}_get_email_subject", $subject, $this );
320
		}
321
322
		/**
323
		 * Get email message.
324
		 *
325
		 * @since  2.0
326
		 * @access public
327
		 * @return string
328
		 */
329
		public function get_email_message() {
330
			$message = give_get_option( "{$this->config['id']}_email_message", $this->get_default_email_message() );
331
332
			/**
333
			 * Filter the message.
334
			 *
335
			 * @since 2.0
336
			 */
337
			return apply_filters( "give_{$this->config['id']}_get_email_message", $message, $this );
338
		}
339
340
341
		/**
342
		 * Get email message field description
343
		 *
344
		 * @since 2.0
345
		 * @acess public
346
		 * @return string
347
		 */
348
		public function get_email_message_field_description() {
349
			$desc = esc_html__( 'Enter the email message.', 'give' );
350
351
			if ( $email_tag_list = $this->get_emails_tags_list_html() ) {
352
				$desc = sprintf(
353
					esc_html__( 'Enter the email that is sent to users after completing a successful donation. HTML is accepted. Available template tags: %s', 'give' ),
354
					$email_tag_list
355
				);
356
357
			}
358
359
			return $desc;
360
		}
361
362
		/**
363
		 * Get a formatted HTML list of all available email tags
364
		 *
365
		 * @since 1.0
366
		 *
367
		 * @return string
368
		 */
369
		function get_emails_tags_list_html() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
370
371
			// Get all email tags.
372
			$email_tags = $this->get_allowed_email_tags();
373
374
			ob_start();
375
			if ( count( $email_tags ) > 0 ) : ?>
376
				<div class="give-email-tags-wrap">
377
					<?php foreach ( $email_tags as $email_tag ) : ?>
378
						<span class="give_<?php echo $email_tag['tag']; ?>_tag">
379
					<code>{<?php echo $email_tag['tag']; ?>}</code> - <?php echo $email_tag['description']; ?>
380
				</span>
381
					<?php endforeach; ?>
382
				</div>
383
			<?php endif;
384
385
			// Return the list.
386
			return ob_get_clean();
387
		}
388
389
390
		/**
391
		 * Get allowed email tags for current email notification.
392
		 *
393
		 * @since  2.0
394
		 * @access private
395
		 * @return array
396
		 */
397
		private function get_allowed_email_tags() {
398
			// Get all email tags.
399
			$email_tags = Give()->email_tags->get_tags();
400
401
			// Skip if all email template tags context setup exit.
402
			if ( $this->config['email_tag_context'] && 'all' !== $this->config['email_tag_context'] ) {
403
				if ( is_array( $this->config['email_tag_context'] ) ) {
404
					foreach ( $email_tags as $index => $email_tag ) {
405
						if ( in_array( $email_tag['context'], $this->config['email_tag_context'] ) ) {
406
							continue;
407
						}
408
409
						unset( $email_tags[ $index ] );
410
					}
411
				} else {
412
					foreach ( $email_tags as $index => $email_tag ) {
413
						if ( $this->config['email_tag_context'] === $email_tag['context'] ) {
414
							continue;
415
						}
416
417
						unset( $email_tags[ $index ] );
418
					}
419
				}
420
			}
421
422
			return $email_tags;
423
		}
424
425
		/**
426
		 * Get default email subject.
427
		 *
428
		 * @since  2.0
429
		 * @access public
430
		 * @return string
431
		 */
432
		function get_default_email_subject() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
433
			return apply_filters( "give_{$this->config['id']}give_get_default_email_subject", '', $this );
434
		}
435
436
		/**
437
		 * Get default email message.
438
		 *
439
		 * @since  2.0
440
		 * @access public
441
		 *
442
		 * @return string
443
		 */
444
		function get_default_email_message() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
445
			return apply_filters( "give_{$this->config['id']}give_get_default_email_message", '', $this );
446
		}
447
448
449
		/**
450
		 * Get preview email recipients.
451
		 *
452
		 * @since  2.0
453
		 * @access public
454
		 * @return array|string
455
		 */
456
		public function get_preview_email_recipient() {
457
			$recipients = $this->get_recipient();
458
459
			/**
460
			 * Filter the preview email recipients.
461
			 *
462
			 * @since 2.0
463
			 *
464
			 * @param string|array            $recipients List of recipients.
465
			 * @param Give_Email_Notification $this
466
			 */
467
			$recipients = apply_filters( 'give_get_preview_email_recipient', $recipients, $this );
468
469
			return $recipients;
470
		}
471
472
		/**
473
		 * Get the recipient attachments.
474
		 *
475
		 * @since  2.0
476
		 * @access public
477
		 * @return array
478
		 */
479
		public function get_email_attachments() {
480
			/**
481
			 * Filter the attachment.
482
			 *
483
			 * @since 2.0
484
			 */
485
			return apply_filters( "give_{$this->config['id']}_get_email_attachments", array(), $this );
486
		}
487
488
489
		/**
490
		 * Get email content type
491
		 *
492
		 * @since  2.0
493
		 * @access public
494
		 * @return string
495
		 */
496
		public function get_email_type() {
497
			return Give()->emails->get_content_type();
498
		}
499
500
501
		/**
502
		 * Send preview email.
503
		 *
504
		 * @since  2.0
505
		 * @access public
506
		 */
507
		public function send_preview_email() {
508
			// setup email data.
509
			$this->setup_email_data();
510
511
			$attachments = $this->get_email_attachments();
512
			$message     = $this->preview_email_template_tags( $this->get_email_message() );
513
			$subject     = $this->preview_email_template_tags( $this->get_email_subject() );
514
515
			Give()->emails->send( $this->get_preview_email_recipient(), $subject, $message, $attachments );
516
		}
517
518
		/**
519
		 * Send email notification
520
		 *
521
		 * @since  2.0
522
		 * @access public
523
		 *
524
		 * @param array $email_tag_args Arguments which helps to decode email template tags.
525
		 *
526
		 * @return bool
527
		 */
528
		public function send_email_notification( $email_tag_args = array() ) {
529
			// Do not send email if notification is disable.
530
			if ( ! give_is_setting_enabled( $this->get_notification_status() ) ) {
531
				return false;
532
			}
533
534
			/**
535
			 * Fire action after before email send.
536
			 *
537
			 * @since 2.0
538
			 */
539
			do_action( "give_{$this->config['id']}_email_send_before", $this );
540
541
			$attachments = $this->get_email_attachments();
542
			$message     = give_do_email_tags( $this->get_email_message(), $email_tag_args );
543
			$subject     = give_do_email_tags( $this->get_email_subject(), $email_tag_args );
544
545
			// Send email.
546
			$email_status = Give()->emails->send( $this->get_recipient(), $subject, $message, $attachments );
547
548
			/**
549
			 * Fire action after after email send.
550
			 *
551
			 * @since 2.0
552
			 */
553
			do_action( "give_{$this->config['id']}_email_send_after", $email_status, $this );
554
555
			return $email_status;
556
		}
557
558
559
		/**
560
		 * Decode preview email template tags.
561
		 *
562
		 * @since 2.0
563
		 *
564
		 * @param string $message
565
		 *
566
		 * @return string
567
		 */
568
		public function preview_email_template_tags( $message ) {
569
			$user_id    = give_check_variable( give_clean( $_GET ), 'isset_empty', 0, 'user_id' );
570
			$user       = ! empty( $user_id ) ? get_user_by( 'id', $user_id ) : wp_get_current_user();
571
			$receipt_id = strtolower( md5( uniqid() ) );
572
573
			$receipt_link_url = esc_url( add_query_arg( array(
574
				'payment_key' => $receipt_id,
575
				'give_action' => 'view_receipt',
576
			), home_url() ) );
577
578
			$receipt_link = sprintf(
579
				'<a href="%1$s">%2$s</a>',
580
				$receipt_link_url,
581
				esc_html__( 'View the receipt in your browser &raquo;', 'give' )
582
			);
583
584
			// Set default values for tags.
585
			$this->config['preview_email_tags_values'] = wp_parse_args(
586
				$this->config['preview_email_tags_values'],
587
				array(
588
					'name'              => $user->display_name,
589
					'fullname'          => $user->display_name,
590
					'username'          => $user->user_login,
591
					'user_email'        => $user->user_email,
592
					'payment_total'     => give_currency_filter( give_format_amount( 10.50 ) ),
593
					'amount'            => give_currency_filter( give_format_amount( 10.50 ) ),
594
					'price'             => give_currency_filter( give_format_amount( 10.50 ) ),
595
					'payment_method'    => 'Paypal',
596
					'receipt_id'        => $receipt_id,
597
					'payment_id'        => give_check_variable( give_clean( $_GET ), 'isset_empty', rand( 2000, 2050 ), 'preview_id' ),
598
					'receipt_link_url'  => $receipt_link_url,
599
					'receipt_link'      => $receipt_link,
600
					'date'              => date( give_date_format(), current_time( 'timestamp' ) ),
601
					'donation'          => esc_html__( 'Sample Donation Form Title', 'give' ),
602
					'form_title'        => esc_html__( 'Sample Donation Form Title - Sample Donation Level', 'give' ),
603
					'sitename'          => get_bloginfo( 'name' ),
604
					'pdf_receipt'       => '<a href="#">Download Receipt</a>',
605
					'billing_address'   => '',
606
					'email_access_link' => sprintf(
607
						'<a href="%1$s">%2$s</a>',
608
						add_query_arg(
609
							array(
610
								'give_nl' => uniqid(),
611
							),
612
							get_permalink( give_get_option( 'history_page' ) )
613
						),
614
						__( 'Access Donation Details &raquo;', 'give' )
615
					),
616
				)
617
			);
618
619
			// Decode tags.
620
			foreach ( $this->config['preview_email_tags_values'] as $preview_tag => $value ) {
621
				if ( isset( $this->config['preview_email_tags_values'][ $preview_tag ] ) ) {
622
					$message = str_replace( "{{$preview_tag}}", $this->config['preview_email_tags_values'][ $preview_tag ], $message );
623
				}
624
			}
625
626
			return apply_filters( 'give_email_preview_template_tags', $message );
627
		}
628
629
		/**
630
		 * Setup email data
631
		 *
632
		 * @since 2.0
633
		 */
634
		public function setup_email_data() {
635
		}
636
	}
637
638
endif; // End class_exists check
639