1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* Emails. |
5
|
|
|
* |
6
|
|
|
* This class handles all (notification) emails sent by MonsterInsights. |
7
|
|
|
* |
8
|
|
|
* Heavily influenced by the AffiliateWP plugin by Pippin Williamson. |
9
|
|
|
* https://github.com/AffiliateWP/AffiliateWP/blob/master/includes/emails/class-affwp-emails.php |
10
|
|
|
* |
11
|
|
|
* @since 7.10.5 |
12
|
|
|
*/ |
13
|
|
|
class MonsterInsights_WP_Emails { |
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* Holds the from address. |
17
|
|
|
* |
18
|
|
|
* @since 7.10.5 |
19
|
|
|
* |
20
|
|
|
* @var string |
21
|
|
|
*/ |
22
|
|
|
private $from_address; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* Holds the from name. |
26
|
|
|
* |
27
|
|
|
* @since 7.10.5 |
28
|
|
|
* |
29
|
|
|
* @var string |
30
|
|
|
*/ |
31
|
|
|
private $from_name; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* Holds the reply-to address. |
35
|
|
|
* |
36
|
|
|
* @since 7.10.5 |
37
|
|
|
* |
38
|
|
|
* @var string |
39
|
|
|
*/ |
40
|
|
|
private $reply_to = false; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Holds the carbon copy addresses. |
44
|
|
|
* |
45
|
|
|
* @since 7.10.5 |
46
|
|
|
* |
47
|
|
|
* @var string |
48
|
|
|
*/ |
49
|
|
|
private $cc = false; |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* Holds the email content type. |
53
|
|
|
* |
54
|
|
|
* @since 7.10.5 |
55
|
|
|
* |
56
|
|
|
* @var string |
57
|
|
|
*/ |
58
|
|
|
private $content_type; |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* Holds the email headers. |
62
|
|
|
* |
63
|
|
|
* @since 7.10.5 |
64
|
|
|
* |
65
|
|
|
* @var string |
66
|
|
|
*/ |
67
|
|
|
private $headers; |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* Whether to send email in HTML. |
71
|
|
|
* |
72
|
|
|
* @since 7.10.5 |
73
|
|
|
* |
74
|
|
|
* @var bool |
75
|
|
|
*/ |
76
|
|
|
private $html = true; |
77
|
|
|
|
78
|
|
|
/** |
79
|
|
|
* The email template to use. |
80
|
|
|
* |
81
|
|
|
* @since 7.10.5 |
82
|
|
|
* |
83
|
|
|
* @var string |
84
|
|
|
*/ |
85
|
|
|
private $template; |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* Header/footer/body arguments. |
89
|
|
|
* |
90
|
|
|
* @since 7.10.5 |
91
|
|
|
* |
92
|
|
|
* @var array |
93
|
|
|
*/ |
94
|
|
|
protected $args; |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* Get things going. |
98
|
|
|
* |
99
|
|
|
* @since 7.10.5 |
100
|
|
|
*/ |
101
|
|
|
public function __construct( $template ) { |
102
|
|
|
$this->template = $template; |
103
|
|
|
|
104
|
|
|
$this->set_initial_args(); |
105
|
|
|
|
106
|
|
|
add_action( 'monsterinsights_email_send_before', array( $this, 'send_before' ) ); |
107
|
|
|
add_action( 'monsterinsights_email_send_after', array( $this, 'send_after' ) ); |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
/** |
111
|
|
|
* Set a property. |
112
|
|
|
* |
113
|
|
|
* @since 7.10.5 |
114
|
|
|
* |
115
|
|
|
* @param string $key Object property key. |
116
|
|
|
* @param mixed $value Object property value. |
117
|
|
|
*/ |
118
|
|
|
public function __set( $key, $value ) { |
119
|
|
|
$this->$key = $value; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* Get the email from name. |
124
|
|
|
* |
125
|
|
|
* @since 7.10.5 |
126
|
|
|
* |
127
|
|
|
* @return string The email from name |
128
|
|
|
*/ |
129
|
|
|
public function get_from_name() { |
130
|
|
|
|
131
|
|
|
if ( ! empty( $this->from_name ) ) { |
132
|
|
|
$this->from_name = $this->process_tag( $this->from_name ); |
133
|
|
|
} else { |
134
|
|
|
$this->from_name = get_bloginfo( 'name' ); |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
return apply_filters( 'monsterinsights_email_from_name', monsterinsights_decode_string( $this->from_name ), $this ); |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
/** |
141
|
|
|
* Get the email from address. |
142
|
|
|
* |
143
|
|
|
* @since 7.10.5 |
144
|
|
|
* |
145
|
|
|
* @return string The email from address. |
146
|
|
|
*/ |
147
|
|
|
public function get_from_address() { |
148
|
|
|
|
149
|
|
|
if ( ! empty( $this->from_address ) ) { |
150
|
|
|
$this->from_address = $this->process_tag( $this->from_address ); |
151
|
|
|
} else { |
152
|
|
|
$this->from_address = get_option( 'admin_email' ); |
|
|
|
|
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
return apply_filters( 'monsterinsights_email_from_address', $this->from_address, $this ); |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
/** |
159
|
|
|
* Get the email reply-to. |
160
|
|
|
* |
161
|
|
|
* @since 7.10.5 |
162
|
|
|
* |
163
|
|
|
* @return string The email reply-to address. |
164
|
|
|
*/ |
165
|
|
|
public function get_reply_to() { |
166
|
|
|
|
167
|
|
|
if ( ! empty( $this->reply_to ) ) { |
168
|
|
|
|
169
|
|
|
$this->reply_to = $this->process_tag( $this->reply_to ); |
170
|
|
|
|
171
|
|
|
if ( ! is_email( $this->reply_to ) ) { |
172
|
|
|
$this->reply_to = false; |
|
|
|
|
173
|
|
|
} |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
return apply_filters( 'monsterinsights_email_reply_to', $this->reply_to, $this ); |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
/** |
180
|
|
|
* Get the email carbon copy addresses. |
181
|
|
|
* |
182
|
|
|
* @since 7.10.5 |
183
|
|
|
* |
184
|
|
|
* @return string The email reply-to address. |
185
|
|
|
*/ |
186
|
|
|
public function get_cc() { |
187
|
|
|
|
188
|
|
|
if ( ! empty( $this->cc ) ) { |
189
|
|
|
|
190
|
|
|
$this->cc = $this->process_tag( $this->cc ); |
191
|
|
|
|
192
|
|
|
$addresses = array_map( 'trim', explode( ',', $this->cc ) ); |
193
|
|
|
|
194
|
|
|
foreach ( $addresses as $key => $address ) { |
195
|
|
|
if ( ! is_email( $address ) ) { |
196
|
|
|
unset( $addresses[ $key ] ); |
197
|
|
|
} |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
$this->cc = implode( ',', $addresses ); |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
return apply_filters( 'monsterinsights_email_cc', $this->cc, $this ); |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
/** |
207
|
|
|
* Get the email content type. |
208
|
|
|
* |
209
|
|
|
* @since 7.10.5 |
210
|
|
|
* |
211
|
|
|
* @return string The email content type. |
212
|
|
|
*/ |
213
|
|
|
public function get_content_type() { |
214
|
|
|
|
215
|
|
|
if ( ! $this->content_type && $this->html ) { |
216
|
|
|
$this->content_type = apply_filters( 'monsterinsights_email_default_content_type', 'text/html', $this ); |
217
|
|
|
} elseif ( ! $this->html ) { |
218
|
|
|
$this->content_type = 'text/plain'; |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
return apply_filters( 'monsterinsights_email_content_type', $this->content_type, $this ); |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
/** |
225
|
|
|
* Get the email headers. |
226
|
|
|
* |
227
|
|
|
* @since 7.10.5 |
228
|
|
|
* |
229
|
|
|
* @return string The email headers. |
230
|
|
|
*/ |
231
|
|
|
public function get_headers() { |
232
|
|
|
|
233
|
|
|
if ( ! $this->headers ) { |
234
|
|
|
$this->headers = "From: {$this->get_from_name()} <{$this->get_from_address()}>\r\n"; |
235
|
|
|
if ( $this->get_reply_to() ) { |
236
|
|
|
$this->headers .= "Reply-To: {$this->get_reply_to()}\r\n"; |
237
|
|
|
} |
238
|
|
|
if ( $this->get_cc() ) { |
239
|
|
|
$this->headers .= "Cc: {$this->get_cc()}\r\n"; |
240
|
|
|
} |
241
|
|
|
$this->headers .= "Content-Type: {$this->get_content_type()}; charset=utf-8\r\n"; |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
return apply_filters( 'monsterinsights_email_headers', $this->headers, $this ); |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
/** |
248
|
|
|
* Set initial arguments to use in a template. |
249
|
|
|
* |
250
|
|
|
* @since 7.10.5 |
251
|
|
|
*/ |
252
|
|
|
public function set_initial_args() { |
253
|
|
|
$header_args = array( |
|
|
|
|
254
|
|
|
'title' => esc_html__( 'MonsterInsights', 'google-analytics-for-wordpress' ), |
255
|
|
|
); |
256
|
|
|
|
257
|
|
|
$args = array( |
258
|
|
|
'header' => array(), |
259
|
|
|
'body' => array(), |
260
|
|
|
'footer' => array(), |
261
|
|
|
); |
262
|
|
|
|
263
|
|
|
$from_address = $this->get_from_address(); |
264
|
|
|
if ( ! empty( $from_address ) ) { |
265
|
|
|
$args['footer']['from_address'] = $from_address; |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
$args = apply_filters( 'monsterinsights_emails_templates_set_initial_args', $args, $this ); |
269
|
|
|
|
270
|
|
|
$this->set_args( $args ); |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
/** |
274
|
|
|
* Set header/footer/body/style arguments to use in a template. |
275
|
|
|
* |
276
|
|
|
* @since 7.10.5 |
277
|
|
|
* |
278
|
|
|
* @param array $args Arguments to set. |
279
|
|
|
* @param bool $merge Merge the arguments with existing once or replace. |
280
|
|
|
* |
281
|
|
|
* @return MI_WP_Emails |
|
|
|
|
282
|
|
|
*/ |
283
|
|
|
public function set_args( $args, $merge = true ) { |
284
|
|
|
|
285
|
|
|
$args = apply_filters( 'monsterinsights_emails_templates_set_args', $args, $this ); |
286
|
|
|
|
287
|
|
|
if ( empty( $args ) || ! is_array( $args ) ) { |
288
|
|
|
return $this; |
289
|
|
|
} |
290
|
|
|
|
291
|
|
|
foreach ( $args as $type => $value ) { |
292
|
|
|
|
293
|
|
|
if ( ! is_array( $value ) ) { |
294
|
|
|
continue; |
295
|
|
|
} |
296
|
|
|
|
297
|
|
|
if ( ! isset( $this->args[ $type ] ) || ! is_array( $this->args[ $type ] ) ) { |
298
|
|
|
$this->args[ $type ] = array(); |
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
$this->args[ $type ] = $merge ? array_merge( $this->args[ $type ], $value ) : $value; |
302
|
|
|
} |
303
|
|
|
|
304
|
|
|
return $this; |
305
|
|
|
} |
306
|
|
|
|
307
|
|
|
/** |
308
|
|
|
* Get header/footer/body arguments |
309
|
|
|
* |
310
|
|
|
* @since 7.10.5 |
311
|
|
|
* |
312
|
|
|
* @param string $type Header/footer/body. |
313
|
|
|
* |
314
|
|
|
* @return array |
315
|
|
|
*/ |
316
|
|
|
public function get_args( $type ) { |
317
|
|
|
if ( ! empty( $type ) ) { |
318
|
|
|
return isset( $this->args[ $type ] ) ? apply_filters( 'monsterinsights_emails_templates_get_args_' . $type, $this->args[ $type ], $this ) : array(); |
319
|
|
|
} |
320
|
|
|
|
321
|
|
|
return apply_filters( 'monsterinsights_emails_templates_get_args', $this->args, $this ); |
322
|
|
|
} |
323
|
|
|
|
324
|
|
|
/** |
325
|
|
|
* Build the email. |
326
|
|
|
* |
327
|
|
|
* @since 7.10.5 |
328
|
|
|
* |
329
|
|
|
* @param string $message The email message. |
330
|
|
|
* |
331
|
|
|
* @return string |
332
|
|
|
*/ |
333
|
|
|
public function build_email( $message=null ) { |
334
|
|
|
// process plain text email |
335
|
|
|
if ( false === $this->html ) { |
336
|
|
|
$body = $this->get_template_part( 'body', $this->get_template(), true ); |
337
|
|
|
$body = wp_strip_all_tags( $body ); |
338
|
|
|
$message = str_replace( '{email}', $message, $body ); |
339
|
|
|
|
340
|
|
|
return apply_filters( 'monsterinsights_email_message', $message, $this ); |
341
|
|
|
} |
342
|
|
|
|
343
|
|
|
// process html email template |
344
|
|
|
$email_parts = array(); |
345
|
|
|
$email_parts['header'] = $this->get_template_part( 'header', $this->get_template(), true ); |
346
|
|
|
|
347
|
|
|
// Hooks into the email header. |
348
|
|
|
do_action( 'monsterinsights_email_header', $email_parts['header'] ); |
349
|
|
|
|
350
|
|
|
$email_parts['body'] = $this->get_template_part( 'body', $this->get_template(), true ); |
351
|
|
|
|
352
|
|
|
// Hooks into the email body. |
353
|
|
|
do_action( 'monsterinsights_email_body', $email_parts['body'] ); |
354
|
|
|
|
355
|
|
|
$email_parts['footer'] = $this->get_template_part( 'footer', $this->get_template(), true ); |
356
|
|
|
|
357
|
|
|
// Hooks into the email footer. |
358
|
|
|
do_action( 'monsterinsights_email_footer', $email_parts['footer'] ); |
359
|
|
|
|
360
|
|
|
|
361
|
|
|
$body = implode( $email_parts ); |
362
|
|
|
$message = $this->process_tag( $message, false ); |
363
|
|
|
$message = nl2br( $message ); |
364
|
|
|
$message = str_replace( '{email}', $message, $body ); |
365
|
|
|
//$message = make_clickable( $message ); |
366
|
|
|
|
367
|
|
|
return apply_filters( 'monsterinsights_email_message', $message, $this ); |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
/** |
371
|
|
|
* Send the email. |
372
|
|
|
* |
373
|
|
|
* @since 7.10.5 |
374
|
|
|
* |
375
|
|
|
* @param string $to The To address. |
376
|
|
|
* @param string $subject The subject line of the email. |
377
|
|
|
* @param string $message The body of the email. |
378
|
|
|
* @param array $attachments Attachments to the email. |
379
|
|
|
* |
380
|
|
|
* @return bool |
381
|
|
|
*/ |
382
|
|
|
public function send( $to, $subject, $message=null, $attachments = array() ) { |
383
|
|
|
|
384
|
|
|
if ( ! did_action( 'init' ) && ! did_action( 'admin_init' ) ) { |
385
|
|
|
_doing_it_wrong( __FUNCTION__, esc_html__( 'You cannot send emails with MI_WP_Emails() until init/admin_init has been reached.', 'google-analytics-for-wordpress' ), null ); |
386
|
|
|
|
387
|
|
|
return false; |
388
|
|
|
} |
389
|
|
|
|
390
|
|
|
// Don't send anything if emails have been disabled. |
391
|
|
|
if ( $this->is_email_disabled() ) { |
392
|
|
|
return false; |
393
|
|
|
} |
394
|
|
|
|
395
|
|
|
// Don't send if email address is invalid. |
396
|
|
|
if ( ! is_email( $to ) ) { |
397
|
|
|
return false; |
398
|
|
|
} |
399
|
|
|
|
400
|
|
|
// Hooks before email is sent. |
401
|
|
|
do_action( 'monsterinsights_email_send_before', $this ); |
402
|
|
|
|
403
|
|
|
/* |
404
|
|
|
* Allow to filter data on per-email basis, |
405
|
|
|
* useful for localizations based on recipient email address, form settings, |
406
|
|
|
* or for specific notifications - whatever available in MI_WP_Emails class. |
407
|
|
|
*/ |
408
|
|
|
$data = apply_filters( |
409
|
|
|
'monsterinsights_emails_send_email_data', |
410
|
|
|
array( |
411
|
|
|
'to' => $to, |
412
|
|
|
'subject' => $subject, |
413
|
|
|
'message' => $message, |
414
|
|
|
'headers' => $this->get_headers(), |
415
|
|
|
'attachments' => $attachments, |
416
|
|
|
), |
417
|
|
|
$this |
418
|
|
|
); |
419
|
|
|
|
420
|
|
|
// Let's do this. |
421
|
|
|
$sent = wp_mail( |
422
|
|
|
$data['to'], |
423
|
|
|
monsterinsights_decode_string( $this->process_tag( $data['subject'] ) ), |
424
|
|
|
$this->build_email( $data['message'] ), |
425
|
|
|
$data['headers'], |
426
|
|
|
$data['attachments'] |
427
|
|
|
); |
428
|
|
|
|
429
|
|
|
// Hooks after the email is sent. |
430
|
|
|
do_action( 'monsterinsights_email_send_after', $this ); |
431
|
|
|
|
432
|
|
|
return $sent; |
433
|
|
|
} |
434
|
|
|
|
435
|
|
|
/** |
436
|
|
|
* Add filters/actions before the email is sent. |
437
|
|
|
* |
438
|
|
|
* @since 7.10.5 |
439
|
|
|
*/ |
440
|
|
|
public function send_before() { |
441
|
|
|
|
442
|
|
|
add_filter( 'wp_mail_from', array( $this, 'get_from_address' ) ); |
443
|
|
|
add_filter( 'wp_mail_from_name', array( $this, 'get_from_name' ) ); |
444
|
|
|
add_filter( 'wp_mail_content_type', array( $this, 'get_content_type' ) ); |
445
|
|
|
} |
446
|
|
|
|
447
|
|
|
/** |
448
|
|
|
* Remove filters/actions after the email is sent. |
449
|
|
|
* |
450
|
|
|
* @since 7.10.5 |
451
|
|
|
*/ |
452
|
|
|
public function send_after() { |
453
|
|
|
|
454
|
|
|
remove_filter( 'wp_mail_from', array( $this, 'get_from_address' ) ); |
455
|
|
|
remove_filter( 'wp_mail_from_name', array( $this, 'get_from_name' ) ); |
456
|
|
|
remove_filter( 'wp_mail_content_type', array( $this, 'get_content_type' ) ); |
457
|
|
|
} |
458
|
|
|
|
459
|
|
|
/** |
460
|
|
|
* Process a smart tag. |
461
|
|
|
* |
462
|
|
|
* @since 7.10.5 |
463
|
|
|
* |
464
|
|
|
* @param string $string String that may contain tags. |
465
|
|
|
* @param bool $sanitize Toggle to maybe sanitize. |
466
|
|
|
* @param bool $linebreaks Toggle to process linebreaks. |
467
|
|
|
* |
468
|
|
|
* @return string |
469
|
|
|
*/ |
470
|
|
|
public function process_tag( $string = '', $sanitize = true, $linebreaks = false ) { |
471
|
|
|
|
472
|
|
|
$tag = apply_filters( 'monsterinsights_process_smart_tags', $string ); |
473
|
|
|
|
474
|
|
|
$tag = monsterinsights_decode_string( $tag ); |
475
|
|
|
|
476
|
|
|
if ( $sanitize ) { |
477
|
|
|
if ( $linebreaks ) { |
478
|
|
|
$tag = monsterinsights_sanitize_textarea_field( $tag ); |
479
|
|
|
} else { |
480
|
|
|
$tag = sanitize_text_field( $tag ); |
481
|
|
|
} |
482
|
|
|
} |
483
|
|
|
|
484
|
|
|
return $tag; |
485
|
|
|
} |
486
|
|
|
|
487
|
|
|
/** |
488
|
|
|
* Email kill switch if needed. |
489
|
|
|
* |
490
|
|
|
* @since 7.10.5 |
491
|
|
|
* |
492
|
|
|
* @return bool |
493
|
|
|
*/ |
494
|
|
|
public function is_email_disabled() { |
495
|
|
|
return (bool) apply_filters( 'monsterinsights_disable_all_emails', false, $this ); |
496
|
|
|
} |
497
|
|
|
|
498
|
|
|
/** |
499
|
|
|
* Get the enabled email template. |
500
|
|
|
* |
501
|
|
|
* @since 7.10.5 |
502
|
|
|
* |
503
|
|
|
* @return string When filtering return 'default' to switch to text/plain email. |
504
|
|
|
*/ |
505
|
|
|
public function get_template() { |
506
|
|
|
|
507
|
|
|
if ( ! empty( $this->template ) ) { |
508
|
|
|
$this->template = $this->process_tag( $this->template ); |
509
|
|
|
} else { |
510
|
|
|
$this->template = 'default'; |
511
|
|
|
} |
512
|
|
|
|
513
|
|
|
return apply_filters( 'monsterinsights_email_template', $this->template); |
514
|
|
|
} |
515
|
|
|
|
516
|
|
|
/** |
517
|
|
|
* Retrieves a template content. |
518
|
|
|
* |
519
|
|
|
* @since 7.10.5 |
520
|
|
|
* |
521
|
|
|
* @param string $slug Template file slug. |
522
|
|
|
* @param string $name Optional. Default null. |
523
|
|
|
* @param bool $load Maybe load. |
524
|
|
|
* |
525
|
|
|
* @return string |
526
|
|
|
*/ |
527
|
|
|
public function get_template_part( $slug, $name = null, $load = true ) { |
|
|
|
|
528
|
|
|
|
529
|
|
|
if ( false === $this->html ) { |
530
|
|
|
$name .= '-plain'; |
531
|
|
|
} |
532
|
|
|
|
533
|
|
|
if ( isset( $name ) ) { |
534
|
|
|
$template = $slug . '-' . $name; |
535
|
|
|
|
536
|
|
|
$html = $this->get_html( |
537
|
|
|
$template, |
538
|
|
|
$this->get_args( $slug ), |
539
|
|
|
true |
540
|
|
|
); |
541
|
|
|
|
542
|
|
|
return apply_filters( 'monsterinsights_emails_templates_get_content_part', $html, $template, $this ); |
543
|
|
|
} |
544
|
|
|
|
545
|
|
|
} |
546
|
|
|
|
547
|
|
|
/** |
548
|
|
|
* Like $this->include_html, but returns the HTML instead of including. |
549
|
|
|
* |
550
|
|
|
* @since 7.10.5 |
551
|
|
|
* |
552
|
|
|
* @param string $template_name Template name. |
553
|
|
|
* @param array $args Arguments. |
554
|
|
|
* @param bool $extract Extract arguments. |
555
|
|
|
* |
556
|
|
|
* @return string |
557
|
|
|
*/ |
558
|
|
|
public static function get_html( $template_name, $args = array(), $extract = false ) { |
559
|
|
|
ob_start(); |
560
|
|
|
self::include_html( $template_name, $args, $extract ); |
561
|
|
|
return ob_get_clean(); |
562
|
|
|
} |
563
|
|
|
|
564
|
|
|
/** |
565
|
|
|
* Include a template. |
566
|
|
|
* Uses 'require' if $args are passed or 'load_template' if not. |
567
|
|
|
* |
568
|
|
|
* @since 7.10.5 |
569
|
|
|
* |
570
|
|
|
* @param string $template_name Template name. |
571
|
|
|
* @param array $args Arguments. |
572
|
|
|
* @param bool $extract Extract arguments. |
573
|
|
|
* |
574
|
|
|
* @throws \RuntimeException If extract() tries to modify the scope. |
575
|
|
|
*/ |
576
|
|
|
public static function include_html( $template_name, $args = array(), $extract = false ) { |
577
|
|
|
|
578
|
|
|
$template_name .= '.php'; |
579
|
|
|
|
580
|
|
|
// Allow 3rd party plugins to filter template file from their plugin. |
581
|
|
|
$located = apply_filters( 'monsterinsights_helpers_templates_include_html_located', self::locate_template( $template_name ), $template_name, $args, $extract ); |
582
|
|
|
$args = apply_filters( 'monsterinsights_helpers_templates_include_html_args', $args, $template_name, $extract ); |
583
|
|
|
|
584
|
|
|
if ( empty( $located ) || ! is_readable( $located ) ) { |
585
|
|
|
return; |
586
|
|
|
} |
587
|
|
|
|
588
|
|
|
// Load template WP way if no arguments were passed. |
589
|
|
|
if ( empty( $args ) ) { |
590
|
|
|
load_template( $located, false ); |
591
|
|
|
return; |
592
|
|
|
} |
593
|
|
|
|
594
|
|
|
$extract = apply_filters( 'monsterinsights_helpers_templates_include_html_extract_args', $extract, $template_name, $args ); |
595
|
|
|
|
596
|
|
|
if ( $extract && is_array( $args ) ) { |
597
|
|
|
|
598
|
|
|
$created_vars_count = extract( $args, EXTR_SKIP ); // phpcs:ignore WordPress.PHP.DontExtract |
599
|
|
|
|
600
|
|
|
// Protecting existing scope from modification. |
601
|
|
|
if ( count( $args ) !== $created_vars_count ) { |
602
|
|
|
throw new RuntimeException( 'Extraction failed: variable names are clashing with the existing ones.' ); |
603
|
|
|
} |
604
|
|
|
} |
605
|
|
|
|
606
|
|
|
require $located; |
607
|
|
|
} |
608
|
|
|
|
609
|
|
|
/** |
610
|
|
|
* Locate a template and return the path for inclusion. |
611
|
|
|
* |
612
|
|
|
* @since 7.10.5 |
613
|
|
|
* |
614
|
|
|
* @param string $template_name Template name. |
615
|
|
|
* |
616
|
|
|
* @return string |
617
|
|
|
*/ |
618
|
|
|
public static function locate_template( $template_name ) { |
619
|
|
|
|
620
|
|
|
// Trim off any slashes from the template name. |
621
|
|
|
$template_name = ltrim( $template_name, '/' ); |
622
|
|
|
|
623
|
|
|
if ( empty( $template_name ) ) { |
624
|
|
|
return apply_filters( 'monsterinsights_helpers_templates_locate', '', $template_name ); |
625
|
|
|
} |
626
|
|
|
|
627
|
|
|
$located = ''; |
628
|
|
|
|
629
|
|
|
// Try locating this template file by looping through the template paths. |
630
|
|
|
foreach ( self::get_theme_template_paths() as $template_path ) { |
631
|
|
|
if ( file_exists( $template_path . $template_name ) ) { |
632
|
|
|
$located = $template_path . $template_name; |
633
|
|
|
break; |
634
|
|
|
} |
635
|
|
|
} |
636
|
|
|
|
637
|
|
|
return apply_filters( 'monsterinsights_helpers_templates_locate', $located, $template_name ); |
638
|
|
|
} |
639
|
|
|
|
640
|
|
|
/** |
641
|
|
|
* Return a list of paths to check for template locations |
642
|
|
|
* |
643
|
|
|
* @since 7.10.5 |
644
|
|
|
* |
645
|
|
|
* @return array |
646
|
|
|
*/ |
647
|
|
|
public static function get_theme_template_paths() { |
648
|
|
|
|
649
|
|
|
$template_dir = 'monsterinsights-email'; |
650
|
|
|
|
651
|
|
|
$file_paths = array( |
652
|
|
|
1 => trailingslashit( get_stylesheet_directory() ) . $template_dir, |
653
|
|
|
10 => trailingslashit( get_template_directory() ) . $template_dir, |
654
|
|
|
100 => trailingslashit( MONSTERINSIGHTS_PLUGIN_DIR ) . 'includes/emails/templates', |
655
|
|
|
); |
656
|
|
|
|
657
|
|
|
$file_paths = apply_filters( 'monsterinsights_email_template_paths', $file_paths ); |
658
|
|
|
|
659
|
|
|
// Sort the file paths based on priority. |
660
|
|
|
ksort( $file_paths, SORT_NUMERIC ); |
661
|
|
|
|
662
|
|
|
return array_map( 'trailingslashit', $file_paths ); |
663
|
|
|
} |
664
|
|
|
} |
665
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.