PluginProbe
Friends / 4.3.2
Friends v4.3.2
4.3.2 4.3.1 4.3.0 4.2.2 4.2.1 4.2.0 4.1.0 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 2.7.9 2.8.0 2.8.1 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 2.9.0 2.9.1 All 88 releases
friends / includes / class-notifications.php

class-notifications.php in Friends 4.3.2, at includes/class-notifications.php

693 lines 23.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Friends Notifications
4 *
5 * This contains the functions for Notifications.
6 *
7 * @package Friends
8 */
9
10 namespace Friends;
11
12 /**
13 * This is the class for the Notifications part of the Friends Plugin.
14 *
15 * @since 0.6
16 *
17 * @package Friends
18 * @author Alex Kirk
19 */
20 class Notifications {
21 /**
22 * Contains a reference to the Friends class.
23 *
24 * @var Friends
25 */
26 private $friends;
27
28 /**
29 * Constructor
30 *
31 * @param Friends $friends A reference to the Friends object.
32 */
33 public function __construct( Friends $friends ) {
34 $this->friends = $friends;
35 $this->register_hooks();
36 }
37
38 /**
39 * Register the WordPress hooks
40 */
41 private function register_hooks() {
42 add_filter( 'friends_rewrite_mail_html', array( $this, 'rewrite_mail_html' ) );
43 add_filter( 'friends_rewrite_mail_html', array( $this, 'highlight_keywords' ), 10, 2 );
44 add_action( 'notify_new_friend_post', array( $this, 'notify_new_friend_post' ), 10, 3 );
45 add_filter( 'friends_notify_keyword_match_post', array( $this, 'notify_keyword_match_post' ), 10, 3 );
46 add_action( 'notify_friend_message_received', array( $this, 'notify_friend_message_received' ), 10, 5 );
47 add_action( 'notify_unknown_friend_message_received', array( $this, 'notify_unknown_friend_message_received' ), 10, 4 );
48 add_action( 'activitypub_new_follower_email', array( $this, 'activitypub_new_follower_email' ), 10, 3 );
49 add_action( 'activitypub_followers_post_follow', array( $this, 'activitypub_followers_post_follow' ), 10, 4 );
50 add_action( 'activitypub_followers_pre_remove_follower', array( $this, 'activitypub_followers_pre_remove_follower' ), 10, 3 );
51 }
52
53 /**
54 * Sets the friends plugin from email address when sending mail.
55 *
56 * If you're having issues with the receiver using the envelope From: address in favor of the mail header,
57 * you can use a filter like this:
58 * add_filter( 'wp_mail_from', function( $from ) {
59 * ini_set( 'sendmail_from', $from );
60 * return $from;
61 * }, 100 );
62 *
63 * @param string $from The from that's supposed to be used.
64 *
65 * @return string The friends plugin from email address.
66 */
67 public function use_friends_plugin_from_email_address( $from ) {
68 $from = preg_replace( '/^wordpress@/', 'friends-plugin@', $from );
69 return $from;
70 }
71
72
73 /**
74 * Gets the friends plugin from email address.
75 *
76 * @return string The friends plugin from email address.
77 */
78 public function get_friends_plugin_from_email_address() {
79 add_filter( 'wp_mail_from', array( $this, 'use_friends_plugin_from_email_address' ) );
80 $address = apply_filters( 'wp_mail_from', 'wordpress@' . preg_replace( '#^www\.#', '', wp_parse_url( network_home_url(), PHP_URL_HOST ) ) );
81 remove_filter( 'wp_mail_from', array( $this, 'use_friends_plugin_from_email_address' ) );
82 return $address;
83 }
84
85 /**
86 * Notify the users of this site about a new friend post
87 *
88 * @param \WP_Post $post The new post by a friend or subscription.
89 * @param User_Feed $user_feed The feed where the post came from.
90 * @param string|false $keyword If a post matched a keyword, the keyword is specified.
91 */
92 public function notify_new_friend_post( \WP_Post $post, User_Feed $user_feed, $keyword ) {
93 if (
94 // Post might be trashed through rules.
95 'trash' === $post->post_status
96 // Don't notify about posts that WordPress scheduled for future publishing.
97 || 'future' === $post->post_status
98 // Don't notify about posts older than a week.
99 || strtotime( $post->post_date_gmt ) + WEEK_IN_SECONDS < time()
100 ) {
101 return;
102 }
103 $user = new User( Friends::get_main_friend_user_id() );
104 if ( defined( 'WP_TESTS_EMAIL' ) ) {
105 $user->user_email = WP_TESTS_EMAIL;
106 }
107 if ( ! $user->user_email ) {
108 return;
109 }
110 $author = $user_feed->get_friend_user();
111
112 if ( ! get_post_format( $post ) ) {
113 $post_format = 'standard';
114 } else {
115 $post_format = get_post_format( $post );
116 }
117
118 $notify_user = ! get_user_option( 'friends_no_new_post_notification', $user->ID );
119 $notify_user = $notify_user && ! get_user_option( 'friends_no_new_post_notification_' . $author->user_login, $user->ID );
120 $notify_user = $notify_user && ! get_user_option( 'friends_no_new_post_format_notification_' . $post_format, $user->ID );
121 $notify_user = $notify_user && ! get_user_option( 'friends_no_new_post_by_parser_notification_' . $user_feed->get_parser(), $user->ID );
122
123 // If the post would notify anyway and it was a keyword match, notify that way.
124 if ( $notify_user && $keyword && get_user_option( 'friends_keyword_notification_override_disabled', $user->ID ) ) {
125 add_filter( 'get_user_option_friends_keyword_notification_override_disabled', '__return_false' );
126 $this->notify_keyword_match_post( false, $post, $keyword );
127 remove_filter( 'get_user_option_friends_keyword_notification_override_disabled', '__return_false' );
128 return;
129 }
130
131 if ( ! apply_filters( 'notify_user_about_friend_post', $notify_user, $user, $post, $author ) ) {
132 return;
133 }
134 $email_title = $post->post_title;
135
136 $params = array(
137 'author' => $author,
138 'post' => $post,
139 );
140
141 $email_message = array();
142 ob_start();
143 Friends::template_loader()->get_template_part( 'email/header', null, array( 'email_title' => $email_title ) );
144 Friends::template_loader()->get_template_part( 'email/new-friend-post', null, $params );
145 Friends::template_loader()->get_template_part( 'email/footer' );
146 $email_message['html'] = ob_get_contents();
147 ob_end_clean();
148
149 ob_start();
150 Friends::template_loader()->get_template_part( 'email/new-friend-post-text', null, $params );
151 Friends::template_loader()->get_template_part( 'email/footer-text' );
152 $email_message['text'] = ob_get_contents();
153 ob_end_clean();
154
155 $this->send_mail( $user->user_email, wp_specialchars_decode( $email_title, ENT_QUOTES ), $email_message, array(), array(), $author->user_login );
156 }
157
158 /**
159 * Notifies about a post that matched the keyword.
160 *
161 * @param bool $notified Whether a notification was sent.
162 * @param \WP_Post $post The new post by a friend or subscription.
163 * @param string $keyword The matched keyword.
164 */
165 public function notify_keyword_match_post( $notified, \WP_Post $post, $keyword ) {
166 if ( 'trash' === $post->post_status ) {
167 return $notified;
168 }
169
170 $user = new User( Friends::get_main_friend_user_id() );
171 if ( defined( 'WP_TESTS_EMAIL' ) ) {
172 $user->user_email = WP_TESTS_EMAIL;
173 }
174 if ( ! $user->user_email ) {
175 return $notified;
176 }
177 $notify_user = ! get_user_option( 'friends_no_keyword_notification_' . $post->post_author, $user->ID );
178 // If the override was disabled, don't notify. This could be temporarily disabled later.
179
180 if ( $notify_user && get_user_option( 'friends_keyword_notification_override_disabled', $user->ID ) ) {
181 return $notified;
182 }
183
184 if ( ! apply_filters( 'notify_user_about_keyword_post', $notify_user, $user, $post, $keyword ) ) {
185 return $notified;
186 }
187
188 $author = User::get_post_author( $post );
189 // translators: %s is a keyword string specified by the user.
190 $email_title = sprintf( __( 'Keyword matched: %s', 'friends' ), $keyword );
191
192 $params = array(
193 'author' => $author,
194 'post' => $post,
195 'keyword' => $keyword,
196 );
197
198 $email_message = array();
199 ob_start();
200 Friends::template_loader()->get_template_part( 'email/header', null, array( 'email_title' => $email_title ) );
201 Friends::template_loader()->get_template_part( 'email/keyword-match-post', null, $params );
202 Friends::template_loader()->get_template_part( 'email/footer' );
203 $email_message['html'] = ob_get_contents();
204 ob_end_clean();
205
206 ob_start();
207 Friends::template_loader()->get_template_part( 'email/keyword-match-post-text', null, $params );
208 Friends::template_loader()->get_template_part( 'email/footer-text' );
209 $email_message['text'] = ob_get_contents();
210 ob_end_clean();
211
212 $this->send_mail( $user->user_email, wp_specialchars_decode( $email_title, ENT_QUOTES ), $email_message, array(), array(), $author->user_login );
213
214 return true;
215 }
216
217 /**
218 * Notify the users of this site about a received message
219 *
220 * @param User $friend_user The user who sent the message.
221 * @param string $message The message.
222 * @param string $subject The subject.
223 * @param string $_feed_url The feed URL.
224 * @param string $remote_url The remote message URL.
225 */
226 public function notify_friend_message_received( User $friend_user, $message, $subject, $_feed_url = null, $remote_url = null ) {
227 $user = new User( Friends::get_main_friend_user_id() );
228 if ( defined( 'WP_TESTS_EMAIL' ) ) {
229 $user->user_email = WP_TESTS_EMAIL;
230 }
231 if ( ! $user->user_email ) {
232 return;
233 }
234
235 if ( ! apply_filters( 'notify_user_about_friend_message', true, $user, $friend_user ) ) {
236 return;
237 }
238
239 // translators: %s is a user display name.
240 $email_title = sprintf( __( '%s sent you a message', 'friends' ), $friend_user->display_name );
241
242 $params = array(
243 'user' => $user,
244 'friend_user' => $friend_user,
245 'subject' => $subject,
246 'message' => $message,
247 'message_url' => $this->get_friend_message_url( $friend_user, $remote_url ),
248 );
249
250 $email_message = array();
251 ob_start();
252 Friends::template_loader()->get_template_part( 'email/header', null, array( 'email_title' => $email_title ) );
253 Friends::template_loader()->get_template_part( 'email/friend-message-received', null, $params );
254 Friends::template_loader()->get_template_part( 'email/footer' );
255 $email_message['html'] = ob_get_contents();
256 ob_end_clean();
257
258 ob_start();
259 Friends::template_loader()->get_template_part( 'email/friend-message-received-text', null, $params );
260 Friends::template_loader()->get_template_part( 'email/footer-text' );
261 $email_message['text'] = ob_get_contents();
262 ob_end_clean();
263
264 $this->send_mail( $user->user_email, $email_title, $email_message );
265 }
266
267 /**
268 * Get the URL for replying to a received direct message.
269 *
270 * @param User $friend_user The message sender.
271 * @param string|null $remote_url The remote ActivityPub message URL.
272 * @return string The reply URL.
273 */
274 private function get_friend_message_url( User $friend_user, $remote_url = null ) {
275 if ( $remote_url ) {
276 add_filter( 'friends_frontend_post_types', array( $this, 'friends_frontend_post_types_only_messages' ), 999 );
277 $message_id = Feed::url_to_postid( $remote_url );
278 remove_filter( 'friends_frontend_post_types', array( $this, 'friends_frontend_post_types_only_messages' ), 999 );
279
280 if ( $message_id ) {
281 $message = get_post( $message_id );
282 if ( $message ) {
283 while ( $message && $message->post_parent ) {
284 $message = get_post( $message->post_parent );
285 }
286
287 if ( $message ) {
288 return add_query_arg( 'conversation', $message->ID, home_url( '/friends/messages/' ) );
289 }
290 }
291 }
292 }
293
294 return $friend_user->get_local_friends_page_url();
295 }
296
297 /**
298 * Limit frontend post type lookups to messages.
299 *
300 * @return array The message post type.
301 */
302 public function friends_frontend_post_types_only_messages() {
303 return array( Messages::CPT );
304 }
305
306 /**
307 * Notify the users of this site about a received message
308 *
309 * @param string $sender_name The user who sent the message.
310 * @param string $message The message.
311 * @param string $subject The subject.
312 * @param string $feed_url The url of the user who sent the message.
313 */
314 public function notify_unknown_friend_message_received( $sender_name, $message, $subject, $feed_url ) {
315 $user = new User( Friends::get_main_friend_user_id() );
316 if ( defined( 'WP_TESTS_EMAIL' ) ) {
317 $user->user_email = WP_TESTS_EMAIL;
318 }
319 if ( ! $user->user_email ) {
320 return;
321 }
322
323 if ( ! apply_filters( 'notify_user_about_friend_message', true, $user ) ) {
324 return;
325 }
326
327 // translators: %s is a user display name.
328 $email_title = sprintf( __( '%s sent you a message', 'friends' ), $sender_name );
329
330 $params = array(
331 'user' => $user,
332 'sender_name' => $sender_name,
333 'feed_url' => $feed_url,
334 'subject' => $subject,
335 'message' => $message,
336 );
337
338 $email_message = array();
339 ob_start();
340 Friends::template_loader()->get_template_part( 'email/header', null, array( 'email_title' => $email_title ) );
341 Friends::template_loader()->get_template_part( 'email/unknown-friend-message-received', null, $params );
342 Friends::template_loader()->get_template_part( 'email/footer' );
343 $email_message['html'] = ob_get_contents();
344 ob_end_clean();
345
346 ob_start();
347 Friends::template_loader()->get_template_part( 'email/unknown-friend-message-received-text', null, $params );
348 Friends::template_loader()->get_template_part( 'email/footer-text' );
349 $email_message['text'] = ob_get_contents();
350 ob_end_clean();
351
352 $this->send_mail( $user->user_email, $email_title, $email_message );
353 }
354
355 /**
356 * Augment the ActivityPub new follower e-mail
357 *
358 * @param array $actor The actor.
359 */
360 public function activitypub_new_follower_email( $actor ) {
361 if ( isset( $actor['id'] ) ) {
362 $url = $actor['id'];
363 } elseif ( isset( $actor['url'] ) ) {
364 $url = $actor['url'];
365 } else {
366 return;
367 }
368
369 $url = \ActivityPub\object_to_uri( $url );
370 $server = wp_parse_url( $url, PHP_URL_HOST );
371 $following = User_Feed::get_by_url( $url );
372 if ( ! $following || is_wp_error( $following ) ) {
373 $following = User_Feed::get_by_url( str_replace( '/users/', '/@', $url ) );
374 }
375 if ( $following && ! is_wp_error( $following ) ) {
376 $following = $following->get_friend_user();
377 } else {
378 $following = false;
379 }
380 echo '<p>';
381 if ( $following ) {
382 echo esc_html__( 'You are already following them!', 'friends' );
383 echo ' ';
384 // translators: %s is a URL.
385 echo wp_kses( sprintf( __( 'Go to their <a href="%s">friends page</a> to see what they recently posted about.', 'friends' ), esc_url( $following->get_local_friends_page_url() ) ), array( 'a' => array( 'href' => array() ) ) );
386 } else {
387 // translators: %s is a URL.
388 echo wp_kses( sprintf( __( 'Maybe you want to <a href="%s">follow them back</a> using the Friends plugin?', 'friends' ), esc_url( add_query_arg( 'url', $url, admin_url( 'admin.php?page=add-friend' ) ) ) ), array( 'a' => array( 'href' => array() ) ) );
389 }
390 echo '</p>';
391 }
392
393 /**
394 * Notify of a follower
395 *
396 * @param string $actor The Actor URL.
397 * @param array $activitypub_object The Activity object.
398 * @param int $user_id The ID of the WordPress User.
399 * @param \WP_Post|\Activitypub\Activity\Actor $follower The Actor post (since ActivityPub 7.5.0) or Actor object.
400 *
401 * @return void
402 */
403 public function activitypub_followers_post_follow( $actor, $activitypub_object, $user_id, $follower ) {
404 if ( ! get_user_option( 'friends_no_friend_follower_notification', $user_id ) ) {
405 return;
406 }
407 $user = new User( $user_id );
408 if ( defined( 'WP_TESTS_EMAIL' ) ) {
409 $user->user_email = WP_TESTS_EMAIL;
410 }
411 if ( ! $user->user_email ) {
412 return;
413 }
414
415 if ( is_wp_error( $follower ) ) {
416 return;
417 }
418
419 $follower_post = null;
420 if ( $follower instanceof \WP_Post ) {
421 $follower_post = $follower;
422 $follower = \Activitypub\Collection\Remote_Actors::get_actor( $follower_post );
423 if ( is_wp_error( $follower ) ) {
424 return;
425 }
426 }
427
428 if ( ! apply_filters( 'notify_user_about_new_follower', true, $user, $actor, $activitypub_object, $follower ) ) {
429 return;
430 }
431
432 $url = \ActivityPub\object_to_uri( $follower->get( 'id' ) );
433 $server = wp_parse_url( $url, PHP_URL_HOST );
434 $following = User_Feed::get_by_url( $url );
435 if ( ! $following || is_wp_error( $following ) ) {
436 $following = User_Feed::get_by_url( $follower->get_url() );
437 }
438 if ( $following && ! is_wp_error( $following ) ) {
439 $following = $following->get_friend_user();
440 } else {
441 $following = false;
442 }
443
444 $icon_url = $follower_post
445 ? \Activitypub\Collection\Remote_Actors::get_avatar_url( $follower_post->ID )
446 : \ActivityPub\object_to_uri( $follower->get_icon() );
447
448 // translators: %s is a user display name.
449 $email_title = sprintf( __( 'New Follower: %s', 'friends' ), $follower->get_name() . '@' . $server );
450
451 $params = array(
452 'user' => $user,
453 'url' => $url,
454 'follower' => $follower,
455 'icon_url' => $icon_url,
456 'server' => $server,
457 'following' => $following,
458 );
459
460 $email_message = array();
461 ob_start();
462 Friends::template_loader()->get_template_part( 'email/header', null, array( 'email_title' => $email_title ) );
463 Friends::template_loader()->get_template_part( 'email/new-follower', null, $params );
464 Friends::template_loader()->get_template_part( 'email/footer' );
465 $email_message['html'] = ob_get_contents();
466 ob_end_clean();
467
468 ob_start();
469 Friends::template_loader()->get_template_part( 'email/new-follower-text', null, $params );
470 Friends::template_loader()->get_template_part( 'email/footer-text' );
471 $email_message['text'] = ob_get_contents();
472 ob_end_clean();
473
474 $this->send_mail( $user->user_email, $email_title, $email_message );
475 }
476
477 /**
478 * Notify of a lost follower
479 *
480 * @param \WP_Post|\Activitypub\Activity\Actor $follower The Actor post (since ActivityPub 7.5.0) or Actor object.
481 * @param int $user_id The ID of the WordPress User.
482 * @param string|\Activitypub\Activity\Actor $actor The Actor URL or Actor object.
483 *
484 * @return void
485 */
486 public function activitypub_followers_pre_remove_follower( $follower, $user_id, $actor ) {
487 if ( ! get_user_option( 'friends_no_friend_follower_notification', $user_id ) ) {
488 return;
489 }
490 $user = new User( $user_id );
491 if ( defined( 'WP_TESTS_EMAIL' ) ) {
492 $user->user_email = WP_TESTS_EMAIL;
493 }
494 if ( ! $user->user_email ) {
495 return;
496 }
497
498 $follower_post = null;
499 $published = null;
500 if ( $follower instanceof \WP_Post ) {
501 $follower_post = $follower;
502 $published = $follower_post->post_date_gmt;
503 if ( $actor instanceof \Activitypub\Activity\Actor ) {
504 $follower = $actor;
505 } else {
506 $follower = \Activitypub\Collection\Remote_Actors::get_actor( $follower_post );
507 if ( is_wp_error( $follower ) ) {
508 return;
509 }
510 }
511 } else {
512 $published = $follower->get_published();
513 }
514
515 if ( ! apply_filters( 'notify_user_about_lost_follower', true, $user, $actor, $follower ) ) {
516 return;
517 }
518
519 $url = \ActivityPub\object_to_uri( $follower->get( 'id' ) );
520 $server = wp_parse_url( $url, PHP_URL_HOST );
521
522 $icon_url = $follower_post
523 ? \Activitypub\Collection\Remote_Actors::get_avatar_url( $follower_post->ID )
524 : \ActivityPub\object_to_uri( $follower->get_icon() );
525
526 // translators: %s is a user display name.
527 $email_title = sprintf( __( 'Lost Follower: %s', 'friends' ), $follower->get_name() . '@' . $server );
528
529 $params = array(
530 'user' => $user,
531 'url' => $url,
532 'follower' => $follower,
533 'icon_url' => $icon_url,
534 'server' => $server,
535 'duration' => human_time_diff( strtotime( $published ) ) . ' (' . sprintf(
536 // translators: %s is a time duration.
537 __( 'since %s', 'friends' ),
538 $published
539 ) . ')',
540
541 );
542
543 $email_message = array();
544 ob_start();
545 Friends::template_loader()->get_template_part( 'email/header', null, array( 'email_title' => $email_title ) );
546 Friends::template_loader()->get_template_part( 'email/lost-follower', null, $params );
547 Friends::template_loader()->get_template_part( 'email/footer' );
548 $email_message['html'] = ob_get_contents();
549 ob_end_clean();
550
551 ob_start();
552 Friends::template_loader()->get_template_part( 'email/lost-follower-text', null, $params );
553 Friends::template_loader()->get_template_part( 'email/footer-text' );
554 $email_message['text'] = ob_get_contents();
555 ob_end_clean();
556
557 $this->send_mail( $user->user_email, $email_title, $email_message );
558 }
559
560 /**
561 * Rewrite HTML for e-mail (by inlining some CSS styles)
562 *
563 * @param string $html The HTML.
564 *
565 * @return string The rewritten HTML.
566 */
567 public function rewrite_mail_html( $html ) {
568 $img_regex = '<figure\b[^>]*>\s*(<a\b[^>]*>\s*)?<img\b';
569 $html = preg_replace( '/' . $img_regex . '/i', '$0 style="max-width: 100% !important; height: auto !important;"', $html );
570 $html = preg_replace( '/(' . $img_regex . '.*?)width=[\'"]\d+[\'"]/i', '$1', $html );
571 $html = preg_replace( '/(' . $img_regex . '.*?)height=[\'"]\d+[\'"]/i', '$1', $html );
572 return $html;
573 }
574
575 public function highlight_keywords( $the_content, $args ) {
576 if ( ! isset( $args['keyword'] ) ) {
577 return $the_content;
578 }
579
580 $tag_stack = array();
581 $protected_tags = array(
582 'pre',
583 'code',
584 'textarea',
585 'style',
586 );
587 $new_content = '';
588 $in_protected_tag = false;
589 foreach ( wp_html_split( $the_content ) as $chunk ) {
590 if ( preg_match( '#^<!--[\s\S]*-->$#i', $chunk, $m ) ) {
591 $new_content .= $chunk;
592 continue;
593 }
594
595 if ( preg_match( '#^<(/)?([a-z-]+)\b[^>]*>$#i', $chunk, $m ) ) {
596 $tag = strtolower( $m[2] );
597 if ( '/' === $m[1] ) {
598 // Closing tag.
599 $i = array_search( $tag, $tag_stack );
600 // We can only remove the tag from the stack if it is in the stack.
601 if ( false !== $i ) {
602 $tag_stack = array_slice( $tag_stack, 0, $i );
603 }
604 } else {
605 // Opening tag, add it to the stack.
606 $tag_stack[] = $tag;
607 }
608
609 // If we're in a protected tag, the tag_stack contains at least one protected tag string.
610 // The protected tag state can only change when we encounter a start or end tag.
611 $in_protected_tag = array_intersect( $tag_stack, $protected_tags );
612
613 // Never inspect tags.
614 $new_content .= $chunk;
615 continue;
616 }
617
618 if ( $in_protected_tag ) {
619 // Don't inspect a chunk inside an inspected tag.
620 $new_content .= $chunk;
621 continue;
622 }
623 // Only reachable when there is no protected tag in the stack.
624 $new_content .= preg_replace( '/(' . preg_quote( $args['keyword'], '/' ) . ')/i', '<mark>$1</mark>', $chunk );
625 }
626
627 return $new_content;
628 }
629
630 /**
631 * Wrapper for wp_mail to be overridden in unit tests
632 *
633 * @param string|array $to Array or comma-separated list of email addresses to send message.
634 * @param string $subject Email subject.
635 * @param string $message Message contents.
636 * @param array $headers Optional. Additional headers.
637 * @param array $attachments Optional. Files to attach.
638 * @param string $override_sitename Optional. Override the sitename.
639 * @return bool Whether the email contents were sent successfully.
640 */
641 public function send_mail( $to, $subject, $message, array $headers = array(), array $attachments = array(), $override_sitename = false ) {
642 $sitename = get_option( 'blogname' );
643
644 if ( $override_sitename ) {
645 $sitename = $override_sitename;
646 }
647
648 // translators: %1$s is the site name, %2$s is the subject.
649 $subject = sprintf( _x( '[%1$s] %2$s', 'email subject', 'friends' ), wp_specialchars_decode( $sitename, ENT_QUOTES ), $subject );
650 $subject = apply_filters( 'friends_send_mail_subject', $subject );
651
652 if ( ! apply_filters( 'friends_send_mail', true, $to, $subject, $message, $headers, $attachments ) ) {
653 return;
654 }
655
656 $alt_function = null;
657 if ( is_array( $message ) ) {
658 if ( isset( $message['html'] ) ) {
659 if ( isset( $message['text'] ) ) {
660 $plain_text = $message['text'];
661 } else {
662 $plain_text = wp_strip_all_tags( $message['html'] );
663 }
664
665 $headers[] = 'Content-type: text/html';
666 $alt_function = function ( $mailer ) use ( $plain_text ) {
667 $mailer->{'AltBody'} = $plain_text;
668 };
669 add_action(
670 'phpmailer_init',
671 $alt_function
672 );
673
674 $message = $message['html'];
675 } elseif ( isset( $message['text'] ) ) {
676 $message = $message['text'];
677 }
678 }
679
680 add_filter( 'wp_mail_from', array( $this, 'use_friends_plugin_from_email_address' ) );
681
682 $mail = wp_mail( $to, $subject, $message, $headers, $attachments );
683
684 remove_filter( 'wp_mail_from', array( $this, 'use_friends_plugin_from_email_address' ) );
685
686 if ( $alt_function ) {
687 remove_action( 'phpmailer_init', $alt_function );
688 }
689
690 return $mail;
691 }
692 }
693