set_template_args()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 15
c 1
b 0
f 0
nc 4
nop 1
dl 0
loc 24
rs 9.7666
1
<?php
2
3
/**
4
 * Email Summaries main class.
5
 *
6
 * @since 8.19.0
7
 */
8
class MonsterInsights_Email_Summaries {
9
10
	/**
11
	 * Email template to use for this class.
12
	 *
13
	 * @since 8.19.0
14
	 *
15
	 * @var string
16
	 */
17
	private $email_template = 'summaries';
18
19
	/**
20
	 * Test email template
21
	 *
22
	 * @since 8.19.0
23
	 *
24
	 * @var string
25
	 */
26
	private $test_email_template = 'summaries-test';
27
28
	/**
29
	 * Email options
30
	 *
31
	 * @since 8.19.0
32
	 *
33
	 * @var string
34
	 */
35
	private $email_options;
36
37
	/**
38
	 * Constructor.
39
	 *
40
	 * @since 8.19.0
41
	 */
42
	public function __construct() {
43
		$options                              = array();
44
		$email_summaries                      = monsterinsights_get_option( 'email_summaries', 'on' );
45
		$options['email_summaries']           = $email_summaries;
46
		$options['summaries_html_template']   = monsterinsights_get_option( 'summaries_html_template', 'yes' );
47
		$options['summaries_carbon_copy']     = 'no';
48
		$options['summaries_email_addresses'] = array(get_option('admin_email'));
49
		$options['summaries_header_image']    = false;
50
51
		$this->email_options = $options;
0 ignored issues
show
Documentation Bug introduced by
It seems like $options of type array is incompatible with the declared type string of property $email_options.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
52
		$this->hooks();
53
54
		// Remove weekly cron job.
55
		wp_clear_scheduled_hook( 'monsterinsights_email_summaries_weekly' );
56
57
		// Schedule or clear Monthly cron job.
58
		if ( ! empty( $email_summaries ) && 'on' !== $email_summaries && wp_next_scheduled( 'monsterinsights_email_summaries_cron' ) ) {
59
			wp_clear_scheduled_hook( 'monsterinsights_email_summaries_cron' );
60
		}
61
62
		if ( ! empty( $email_summaries ) && 'on' === $email_summaries && ! wp_next_scheduled( 'monsterinsights_email_summaries_cron' ) ) {
63
			wp_schedule_event( $this->get_first_cron_date(), 'monsterinsights_email_summaries_monthly', 'monsterinsights_email_summaries_cron' );
64
		}
65
	}
66
67
	/**
68
	 * Email Summaries hooks.
69
	 *
70
	 * @since 8.19.0
71
	 */
72
	public function hooks() {
73
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
74
75
		if ( ! empty( $this->email_options['email_summaries'] ) && 'on' === $this->email_options['email_summaries'] ) {
76
			add_action( 'init', array( $this, 'preview' ) );
77
			add_filter( 'monsterinsights_email_template_paths', array( $this, 'add_email_template_path' ) );
78
			add_filter( 'monsterinsights_emails_templates_set_initial_args', array( $this, 'set_template_args' ) );
79
			add_filter( 'cron_schedules', array( $this, 'add_monthly_cron_schedule' ) );
80
			add_action( 'monsterinsights_email_summaries_cron', array( $this, 'cron' ) );
81
			add_action( 'wp_ajax_monsterinsights_send_test_email', array( $this, 'send_test_email' ) );
82
			add_action( 'monsterinsights_after_update_settings', array(
83
				$this,
84
				'reset_email_summaries_options'
85
			), 10, 2 );
86
		}
87
88
	}
89
90
	/**
91
	 * Load required scripts for email summaries features
92
	 *
93
	 * @return void
94
	 * @since 8.19.0
95
	 *
96
	 */
97
	public function admin_scripts() {
98
		if ( monsterinsights_is_settings_page() ) {
99
			// This will load the required dependencies for the WordPress media uploader
100
			wp_enqueue_media();
101
		}
102
	}
103
104
	/**
105
	 * Check if Email Summaries are enabled in settings.
106
	 *
107
	 * @return bool
108
	 * @since 8.19.0
109
	 *
110
	 */
111
	protected function is_enabled() {
112
		if ( ! isset( $this->is_enabled ) ) {
113
			$this->is_enabled = false;
0 ignored issues
show
Bug Best Practice introduced by
The property is_enabled does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
114
115
			if ( ! $this->is_preview() ) {
116
117
				$info_block      = new MonsterInsights_Summaries_InfoBlocks();
118
				$info_block      = $info_block->fetch_data();
119
				$email_addresses = $this->get_email_addresses();
120
121
				if ( ! empty( $info_block ) ) {
122
					if ( 'on' === $this->email_options['email_summaries'] && ! empty( $email_addresses ) && true === $info_block['status'] ) {
123
						$this->is_enabled = true;
124
					}
125
				}
126
			}
127
		}
128
129
		return apply_filters( 'monsterinsights_emails_summaries_is_enabled', $this->is_enabled );
130
	}
131
132
	/**
133
	 * Preview Email Summary.
134
	 *
135
	 * @since 8.19.0
136
	 */
137
	public function preview() {
138
139
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
140
			return;
141
		}
142
143
		if ( ! $this->is_preview() ) {
144
			return;
145
		}
146
147
		// initiate email class.
148
		$emails = new MonsterInsights_WP_Emails( $this->email_template );
149
150
		// check if html template option is enabled
151
		if ( ! $this->is_enabled_html_template() ) {
152
			$emails->__set( 'html', false );
153
		}
154
155
		$content = $emails->build_email();
156
157
		if ( ! $this->is_enabled_html_template() ) {
158
			$content = wpautop( $content );
159
		}
160
161
		echo $content; // phpcs:ignore
162
163
		exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
164
	}
165
166
	/**
167
	 * Check whether it's in preview mode
168
	 *
169
	 * @return boolean
170
	 * @since 8.19.0
171
	 *
172
	 */
173
	public function is_preview() {
174
		if ( isset( $_GET['monsterinsights_email_preview'], $_GET['monsterinsights_email_template'] ) && 'summary' === $_GET['monsterinsights_email_template'] ) { // phpcs:ignore
175
			return true;
176
		}
177
178
		return false;
179
	}
180
181
	/**
182
	 * Get the email header image.
183
	 *
184
	 * @return string The email from address.
185
	 * @since 8.19.0
186
	 *
187
	 */
188
	public function get_header_image() {
189
		// set default header image
190
		$img = array(
191
			'url' => plugins_url( "lite/assets/img/emails/summaries/logo-MonsterInsights.png", MONSTERINSIGHTS_PLUGIN_FILE ),
192
			'2x'  => plugins_url( "lite/assets/img/emails/summaries/[email protected]", MONSTERINSIGHTS_PLUGIN_FILE ),
193
		);
194
195
		if ( ! empty( $this->email_options['summaries_header_image'] ) ) {
196
			$img['url'] = $this->email_options['summaries_header_image'];
197
			$img['2x']  = '';
198
		}
199
200
		return apply_filters( 'monsterinsights_email_header_image', $img );
201
	}
202
203
	/**
204
	 * Get next cron occurrence date.
205
	 *
206
	 * @return int
207
	 * @since 8.19.0
208
	 *
209
	 */
210
	protected function get_first_cron_date() {
211
		$schedule           = array();
212
		$schedule['day']    = wp_rand( 0, 1 );
213
		$schedule['hour']   = wp_rand( 0, 23 );
214
		$schedule['minute'] = wp_rand( 0, 59 );
215
		$schedule['second'] = wp_rand( 0, 59 );
216
		$schedule['offset'] = ( $schedule['day'] * DAY_IN_SECONDS ) +
217
		                      ( $schedule['hour'] * HOUR_IN_SECONDS ) +
218
		                      ( $schedule['minute'] * MINUTE_IN_SECONDS ) +
219
		                      $schedule['second'];
220
		$date               = strtotime( 'next saturday' ) + $schedule['offset'];
221
222
		return $date;
223
	}
224
225
	/**
226
	 * Add summaries email template path
227
	 *
228
	 * @param array $schedules WP cron schedules.
229
	 *
230
	 * @return array
231
	 * @since 8.19.0
232
	 *
233
	 */
234
	public function add_email_template_path( $file_paths ) {
235
		$file_paths['1000'] = MONSTERINSIGHTS_PLUGIN_DIR . 'lite/includes/emails/templates';
236
237
		return $file_paths;
238
	}
239
240
	/**
241
	 * Add custom Email Summaries cron schedule.
242
	 *
243
	 * @param array $schedules WP cron schedules.
244
	 *
245
	 * @return array
246
	 * @since 8.19.0
247
	 *
248
	 */
249
	public function add_monthly_cron_schedule( $schedules ) {
250
		$schedules['monsterinsights_email_summaries_monthly'] = array(
251
			'interval' => MONTH_IN_SECONDS,
252
			'display'  => esc_html__( 'Monthly MonsterInsights Email Summaries', 'google-analytics-for-wordpress' ),
253
		);
254
255
		return $schedules;
256
	}
257
258
	/**
259
	 * Get email subject
260
	 *
261
	 * @since 8.19.0
262
	 */
263
	public function get_email_subject() {
264
265
		$site_url        = get_site_url();
266
		$site_url_parsed = parse_url( $site_url );// Can't use wp_parse_url as that was added in WP 4.4 and we still support 3.8.
267
		$site_url        = isset( $site_url_parsed['host'] ) ? $site_url_parsed['host'] : $site_url;
268
269
		// Translators: The domain of the site is appended to the subject.
270
		$subject = sprintf( __( 'MonsterInsights Summary - %s', 'google-analytics-for-wordpress' ), $site_url );
271
272
		return apply_filters( 'monsterinsights_emails_summaries_cron_subject', $subject );
273
	}
274
275
	/**
276
	 * Get email addresses to send
277
	 *
278
	 * @since 8.19.0
279
	 */
280
	public function get_email_addresses() {
281
		$emails          = $this->email_options['summaries_email_addresses'];
282
		return apply_filters( 'monsterinsights_email_addresses_to_send', $emails );
283
	}
284
285
	/**
286
	 * check if carbon copy option is enabled
287
	 *
288
	 * @since 8.19.0
289
	 */
290
	public function is_cc_enabled() {
291
		$value = false;
292
		if ( 'yes' === $this->email_options['summaries_carbon_copy'] ) {
293
			$value = true;
294
		}
295
296
		return apply_filters( 'monsterinsights_email_cc_enabled', $value, $this );
297
	}
298
299
	/**
300
	 * Check if html template option is turned on
301
	 *
302
	 * @return bool
303
	 * @since 8.19.0
304
	 *
305
	 */
306
	public function is_enabled_html_template() {
307
		$value = true;
308
		if ( 'no' === $this->email_options['summaries_html_template'] ) {
309
			$value = false;
310
		}
311
312
		return apply_filters( 'monsterinsights_email_html_template', $value, $this );
313
	}
314
315
	/**
316
	 * Email Summaries cron callback.
317
	 *
318
	 * @since 8.19.0
319
	 */
320
	public function cron() {
321
322
		if ( ! $this->is_enabled() ) {
323
			return;
324
		}
325
326
		if( !monsterinsights_is_authed() ){
327
			return;
328
		}
329
330
		$email            = array();
331
		$email['subject'] = $this->get_email_subject();
332
		$email['address'] = $this->get_email_addresses();
333
		$email['address'] = array_map( 'sanitize_email', $email['address'] );
334
335
		// Create new email.
336
		$emails = new MonsterInsights_WP_Emails( $this->email_template );
337
338
		// Maybe include CC.
339
		if ( $this->is_cc_enabled() ) {
340
			$emails->__set( 'cc', implode( ',', $this->get_email_addresses() ) );
341
		}
342
343
		// check if html template option is enabled
344
		if ( ! $this->is_enabled_html_template() ) {
345
			$emails->__set( 'html', false );
346
		}
347
348
		$info_blocks = new MonsterInsights_Summaries_InfoBlocks();
349
		$next_block  = $info_blocks->get_next();
350
351
		// Go.
352
		if( !empty( $email['address'] ) ){
353
			foreach ( $email['address'] as $address ) {
354
				$sent = $emails->send( trim( $address ), $email['subject'] );
355
356
				if ( true === $sent && ! empty( $next_block ) ) {
357
					$info_blocks->register_sent( $next_block );
358
				}
359
			}
360
		}
361
	}
362
363
	/**
364
	 * Send test email
365
	 *
366
	 * @since 8.19.0
367
	 */
368
	public function send_test_email() {
369
		// Run a security check first.
370
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
371
372
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
373
			return;
374
		}
375
376
		$email            = array();
377
		$email['subject'] = '[Test email] MonsterInsights Summary';
378
		$email['address'] = $this->get_email_addresses();
379
		$email['address'] = array_map( 'sanitize_email', $email['address'] );
380
381
		// Create new email.
382
		$emails = new MonsterInsights_WP_Emails( $this->test_email_template );
383
384
		// Maybe include CC.
385
		if ( $this->is_cc_enabled() ) {
386
			$emails->__set( 'cc', implode( ',', $this->get_email_addresses() ) );
387
		}
388
389
		// check if html template option is enabled
390
		if ( ! $this->is_enabled_html_template() ) {
391
			$emails->__set( 'html', false );
392
		}
393
394
		// Go.
395
		if(!empty($email['address'])){
396
			foreach ( $email['address'] as $address ) {
397
				if ( ! $emails->send( trim( $address ), $email['subject'] ) ) {
398
					wp_send_json_error();
399
				}
400
			}
401
		}
402
		wp_send_json_success();
403
	}
404
405
	/**
406
	 * Email summaries template arguments
407
	 *
408
	 * @since 8.19.0
409
	 */
410
	public function set_template_args( $args ) {
411
		if ( $this->is_enabled_html_template() ) {
412
			$args['header']['header_image'] = $this->get_header_image();
413
		}
414
415
		$args['body']['title']       = esc_html__( 'Website Traffic Summary', 'google-analytics-for-wordpress' );
416
		$args['body']['description'] = esc_html__( 'Let’s take a look at how your website traffic performed in the past month.', 'google-analytics-for-wordpress' );
417
		$args['body']['summaries']   = $this->get_summaries();
418
		$args['body']['startDate']   = $this->get_summaries_start_date();
419
		$args['body']['endDate']     = $this->get_summaries_end_date();
420
421
		$info_blocks = new MonsterInsights_Summaries_InfoBlocks();
422
		$next_block  = $info_blocks->get_next();
423
424
		if ( ! empty( $next_block ) ) {
425
			$args['body']['info_block'] = $next_block;
426
		}
427
428
		$args['body']['settings_tab_url']   = esc_url( admin_url( 'admin.php?page=monsterinsights_settings#/advanced' ) );
429
		$args['footer']['settings_tab_url'] = esc_url( admin_url( 'admin.php?page=monsterinsights_settings#/advanced' ) );
430
431
		$args['body']['summaries']['data']['galinks']['topposts']  = admin_url( 'admin.php?page=monsterinsights_reports#/' );
432
433
		return apply_filters( 'monsterinsights_email_summaries_template_args', $args );
434
	}
435
436
	/**
437
	 * get the start date from the last month
438
	 *
439
	 * @since 8.19.0
440
	 */
441
	public function get_summaries_start_date() {
442
		return date( "Y-m-d", strtotime( "first day of last month" ) ); // first day of last month
443
	}
444
445
	/**
446
	 * get the end date from the last week
447
	 *
448
	 * @since 8.19.0
449
	 */
450
	public function get_summaries_end_date() {
451
		return date( "Y-m-d", strtotime( "last day of last month" ) ); // last day of last month
452
	}
453
454
	/**
455
	 * data for email template
456
	 *
457
	 * @since 8.19.0
458
	 */
459
	public function get_summaries() {
460
		$data = array();
461
462
		// get overview report data for email summaries template
463
		$report_name = 'summaries';
464
		$report      = MonsterInsights()->reporting->get_report( $report_name );
465
466
		$isnetwork = ! empty( $_REQUEST['isnetwork'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) : '';
0 ignored issues
show
Bug introduced by
It seems like wp_unslash($_REQUEST['isnetwork']) can also be of type array; however, parameter $str of sanitize_text_field() 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

466
		$isnetwork = ! empty( $_REQUEST['isnetwork'] ) ? sanitize_text_field( /** @scrutinizer ignore-type */ wp_unslash( $_REQUEST['isnetwork'] ) ) : '';
Loading history...
467
468
		// get the data of last month
469
		$args = array(
470
			'start' => $this->get_summaries_start_date(),
471
			'end'   => $this->get_summaries_end_date(),
472
		);
473
474
		if ( $isnetwork ) {
475
			$args['network'] = true;
476
		}
477
478
		if ( monsterinsights_is_pro_version() && ! MonsterInsights()->license->license_can( $report->level ) ) {
0 ignored issues
show
Bug Best Practice introduced by
The property $license is declared protected in MonsterInsights_Lite. Since you implement __get, consider adding a @property or @property-read.
Loading history...
479
			$data = array(
480
				'success' => false,
481
				'message' => __( "You don't have permission to view MonsterInsights reports.", 'google-analytics-for-wordpress' ),
482
			);
483
		} else {
484
			$data = apply_filters( 'monsterinsights_vue_reports_data', $report->get_data( $args ), $report_name, $report );
485
		}
486
487
		return $data;
488
	}
489
490
491
	/**
492
	 * reset email summaries options
493
	 *
494
	 * @since 8.19.0
495
	 */
496
	public function reset_email_summaries_options( $key, $value ) {
497
		if ( isset( $key ) && $key === 'email_summaries' && isset( $value ) && $value === 'off' ) {
498
			$default_email = array(
499
				'email' => get_option( 'admin_email' ),
500
			);
501
			monsterinsights_update_option( 'summaries_email_addresses', array( $default_email ) );
0 ignored issues
show
Bug introduced by
array($default_email) of type array<integer,array<string,false|mixed>> is incompatible with the type string expected by parameter $value of monsterinsights_update_option(). ( Ignorable by Annotation )

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

501
			monsterinsights_update_option( 'summaries_email_addresses', /** @scrutinizer ignore-type */ array( $default_email ) );
Loading history...
502
			monsterinsights_update_option( 'summaries_header_image', '' );
503
		}
504
	}
505
}
506