PluginProbe
Customize WordPress Emails and Alerts – Better Notifications for WP / trunk
Customize WordPress Emails and Alerts – Better Notifications for WP vtrunk
1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.8 1.8.1 1.8.10 1.8.11 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9 1.9.1 1.9.2 1.9.3 1.9.4 1.9.5 All 81 releases
bnfw / bnfw.php

bnfw.php in Customize WordPress Emails and Alerts – Better Notifications for WP trunk, at bnfw.php

1,826 lines 61.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: Better Notifications for WP
4 * Plugin URI: https://wordpress.org/plugins/bnfw/
5 * Description: Supercharge your WordPress notifications using a WYSIWYG editor and shortcodes. Default and new notifications available. Add more power with Add-ons.
6 * Version: 1.9.9.2
7 * Requires at least: 4.8
8 * Requires PHP: 7.4
9 * Author: Made with Fuel
10 * Author URI: https://betternotificationsforwp.com/
11 * License: GPLv2 or later
12 * License URI: http://www.gnu.org/licenses/gpl-2.0.html
13 * Text Domain: bnfw
14 * Domain Path: /languages
15 *
16 * @package bnfw
17 */
18
19 /**
20 * Copyright © 2025 Made with Fuel Ltd. (hello@betternotificationsforwp.com)
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License, version 2, as
23 * published by the Free Software Foundation.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 */
32 if ( ! class_exists( 'BNFW', false ) ) {
33 /**
34 * BNFW main class.
35 */
36 #[\AllowDynamicProperties]
37 class BNFW {
38 /**
39 * BNFW version.
40 *
41 * @var string
42 */
43 public $bnfw_version = '1.9.9.2';
44 /**
45 * Class Constructor.
46 *
47 * @since 1.0
48 */
49 public function __construct() {
50 $this->bnfw_define_constants();
51 $this->includes();
52 $this->hooks();
53
54 /**
55 * BNFW Notification.
56 *
57 * @var \BNFW_Notification
58 */
59 $this->notifier = new BNFW_Notification();
60
61 /**
62 * BNFW Engine.
63 *
64 * @var \BNFW_Engine
65 */
66 $this->engine = new BNFW_Engine();
67 }
68
69 /**
70 * Factory method to return the instance of the class.
71 *
72 * Makes sure that only one instance is created.
73 *
74 * @return \BNFW Instance of the class.
75 */
76 public static function factory() {
77 static $instance = false;
78 if ( ! $instance ) {
79 $instance = new self();
80 }
81 return $instance;
82 }
83
84 /**
85 * Loads the plugin language files
86 *
87 * @since 1.0
88 */
89 public function load_textdomain() {
90 // Load localization domain.
91 $this->translations = dirname( plugin_basename( __FILE__ ) ) . '/languages/';
92 load_plugin_textdomain( 'bnfw', false, $this->translations );
93 }
94
95 /**
96 * Include required files.
97 *
98 * @since 1.0
99 */
100 public function includes() {
101
102 // Load license related classes.
103 if ( ! class_exists( 'EDD_SL_Plugin_Updater' ) ) {
104 require_once 'includes/libraries/class-edd-sl-plugin-updater.php';
105 }
106
107 include_once ABSPATH . 'wp-admin/includes/plugin.php';
108
109 require_once 'vendor/persist-admin-notices-dismissal/persist-admin-notices-dismissal.php';
110
111 require_once 'includes/license/class-bnfw-license.php';
112 require_once 'includes/license/class-bnfw-license-setting.php';
113
114 // Load Engine.
115 require_once 'includes/engine/class-bnfw-engine.php';
116 require_once 'includes/overrides.php';
117
118 // Load notification post type and notification helpers.
119 require_once 'includes/admin/class-bnfw-notification.php';
120 require_once 'includes/notification/post-notification.php';
121
122 // Helpers.
123 require_once 'includes/helpers/helpers.php';
124 require_once 'includes/helpers/class-bnfw-ajax.php';
125
126 // Load Admin Pages.
127 if ( is_admin() ) {
128 require_once 'includes/admin/class-bnfw-settings.php';
129 }
130 }
131 /**
132 * Define BNFW Constants.
133 */
134 private function bnfw_define_constants() {
135 define( 'BNFW_VERSION', $this->bnfw_version );
136 }
137 /**
138 * Register Hooks.
139 *
140 * @since 1.0
141 */
142 public function hooks() {
143 global $wp_version;
144
145 register_activation_hook( __FILE__, array( $this, 'activate' ) );
146
147 add_action( 'init', array( $this, 'bnfw_init' ) );
148 add_action( 'admin_init', array( 'PAnD', 'init' ) );
149 add_action( 'admin_init', array( $this, 'add_capability_to_admin' ) );
150
151 // Fire when privately publish.
152 add_action( 'auto-draft_to_private', array( $this, 'publish_private_post' ), 10, 1 );
153
154 add_action( 'draft_to_private', array( $this, 'private_post' ) );
155 add_action( 'future_to_private', array( $this, 'private_post' ) );
156 add_action( 'pending_to_private', array( $this, 'private_post' ) );
157 add_action( 'publish_to_private', array( $this, 'private_post' ) );
158
159 add_action( 'wp_insert_post', array( $this, 'insert_post' ), 10, 3 );
160
161 add_action( 'attachment_updated', array( $this, 'trash_attachment' ), 10, 3 );
162
163 add_action( 'publish_to_trash', array( $this, 'trash_post' ) );
164
165 add_action( 'auto-draft_to_publish', array( $this, 'publish_post' ) );
166 add_action( 'draft_to_publish', array( $this, 'publish_post' ) );
167 add_action( 'future_to_publish', array( $this, 'publish_post' ) );
168 add_action( 'pending_to_publish', array( $this, 'publish_post' ) );
169 add_action( 'private_to_publish', array( $this, 'publish_post' ) );
170
171 add_action( 'publish_to_publish', array( $this, 'update_post' ) );
172 add_action( 'private_to_private', array( $this, 'update_post' ) );
173
174 add_action( 'add_attachment', array( $this, 'new_publish_media_notification' ), 10, 1 );
175 add_action( 'edit_attachment', array( $this, 'media_attachment_data_update_notification' ), 10 );
176
177 add_action( 'transition_post_status', array( $this, 'on_post_transition' ), 10, 3 );
178
179 add_action( 'init', array( $this, 'custom_post_type_hooks' ), 100 );
180 add_action( 'create_term', array( $this, 'create_term' ), 10, 3 );
181
182 add_action( 'transition_comment_status', array( $this, 'on_comment_status_change' ), 10, 3 );
183 add_action( 'comment_post', array( $this, 'comment_post' ) );
184 add_action( 'trackback_post', array( $this, 'trackback_post' ) );
185 add_action( 'pingback_post', array( $this, 'pingback_post' ) );
186
187 add_action( 'user_register', array( $this, 'user_register' ) );
188
189 add_action( 'user_register', array( $this, 'welcome_email' ) );
190
191 if ( is_plugin_active( 'members/members.php' ) ) {
192
193 add_action( 'add_user_role', array( $this, 'user_role_added_from_member_plugin' ), 10, 2 );
194 add_action( 'remove_user_role', array( $this, 'user_role_removed_from_member_plugin' ), 10, 2 );
195 add_action( 'set_user_role', array( $this, 'user_role_changed' ), 10, 3 );
196
197 add_action( 'profile_update', array( $this, 'user_role_added' ), 10, 2 );
198 } else {
199 add_action( 'set_user_role', array( $this, 'user_role_changed' ), 10, 3 );
200 }
201
202 add_action( 'wp_login', array( $this, 'user_login' ), 10, 2 );
203
204 if ( version_compare( $wp_version, '4.4', '>=' ) ) {
205 add_filter( 'retrieve_password_title', array( $this, 'change_password_email_title' ), 10, 3 );
206 } else {
207 add_filter( 'retrieve_password_title', array( $this, 'change_password_email_title' ) );
208 }
209 add_action( 'lostpassword_post', array( $this, 'on_lost_password' ) );
210 add_filter( 'retrieve_password_message', array( $this, 'change_password_email_message' ), 10, 4 );
211
212 add_action( 'after_password_reset', array( $this, 'on_password_reset' ) );
213
214 add_filter( 'send_password_change_email', array( $this, 'should_password_changed_email_be_sent' ), 10, 3 );
215 add_filter( 'password_change_email', array( $this, 'on_password_changed' ), 10, 2 );
216
217 add_filter( 'send_email_change_email', array( $this, 'should_email_changed_email_be_sent' ), 10, 3 );
218 add_filter( 'email_change_email', array( $this, 'on_email_changed' ), PHP_INT_MAX, 3 );
219 add_filter( 'new_user_email_content', array( $this, 'on_email_changing' ), PHP_INT_MAX, 2 );
220
221 add_filter( 'auto_core_update_email', array( $this, 'on_core_updated' ), 10, 4 );
222
223 add_filter( 'user_request_action_email_content', array( $this, 'handle_user_request_email_content' ), 10, 2 );
224 add_filter( 'user_request_action_email_subject', array( $this, 'handle_user_request_email_subject' ), 10, 3 );
225
226 add_filter( 'user_confirmed_action_email_content', array( $this, 'handle_user_confirmed_action_email_content' ), 10, 2 );
227
228 add_filter( 'wp_privacy_personal_data_email_content', array( $this, 'handle_data_export_email_content' ), 10, 3 );
229
230 add_filter( 'user_erasure_complete_email_subject', array( $this, 'handle_erasure_complete_email_subject' ), 10, 3 );
231 add_filter( 'user_confirmed_action_email_content', array( $this, 'handle_erasure_complete_email_content' ), 10, 2 );
232
233 add_filter( 'plugin_action_links', array( $this, 'plugin_action_links' ), 10, 4 );
234 add_filter( 'wp_mail', array( $this, 'bnfw_update_email_changing_subject' ), 10, 1 );
235 add_action( 'shutdown', array( $this, 'on_shutdown' ) );
236
237 }
238
239 /**
240 * Loads the plugin language files
241 *
242 * @since 1.8.7
243 */
244 public function bnfw_init() {
245 // Load localization domain
246 $this->load_textdomain();
247 }
248
249 /**
250 * Changed the subject when use request to change the email.
251 *
252 * @param array $args Email arguments.
253 *
254 * @return mixed
255 */
256 public function bnfw_update_email_changing_subject( $args ) {
257 $notification_name = 'email-changing';
258 $notifications = $this->notifier->get_notifications( $notification_name );
259
260 if ( count( $notifications ) > 0 ) {
261 $setting = $this->notifier->read_settings( end( $notifications )->ID );
262 if ( str_contains( $args['message'], '/profile.php?newuseremail=' ) ) {
263 $subject = str_replace( '[global_site_title]', get_bloginfo( 'name' ), $setting['subject'] );
264 $subject = str_replace( '[[global_site_title]]', get_bloginfo( 'name' ), $subject );
265 $args['subject'] = $subject;
266 } elseif ( str_contains( $args['message'], '?newuseremail=' ) ) {
267 $subject = str_replace( '[global_site_title]', get_bloginfo( 'name' ), $setting['subject'] );
268 $subject = str_replace( '[[global_site_title]]', get_bloginfo( 'name' ), $subject );
269 $args['subject'] = $subject;
270 }
271
272 /**
273 * Filters the subject of the email sent when a change of user email address is attempted.
274 *
275 * @param array $args An array of email TO, Subject, Message and Header.
276 * @param array $setting Notification settings.
277 *
278 * @since 1.9.9
279 */
280 $args = apply_filters( 'bnfw_user_on_email_change_request_subject', $args, $setting );
281 }
282
283 return $args;
284 }
285
286 /**
287 * Fires when a media is moved to trash.
288 *
289 * @param int $post_id Post ID.
290 * @param WP_Post $post_after Post object following the update.
291 * @param WP_Post $post_before Post object before the update.
292 */
293 public function trash_attachment( $post_id, $post_after, $post_before ) {
294 $post_type = get_post_type( $post_id );
295 $post_status_before = $post_before->post_status;
296 $post_status_after = $post_after->post_status;
297 if ( BNFW_Notification::POST_TYPE !== $post_type && 'inherit' === $post_status_before && 'trash' === $post_status_after ) {
298 $this->send_notification_async( 'trash-' . $post_type, $post_id );
299 }
300 }
301
302 /**
303 * Add 'bnfw' capability to admin.
304 */
305 public function add_capability_to_admin() {
306 $admins = get_role( 'administrator' );
307
308 if ( is_null( $admins ) ) {
309 return;
310 }
311
312 if ( ! $admins->has_cap( 'bnfw' ) ) {
313 $admins->add_cap( 'bnfw' );
314 }
315 }
316
317 /**
318 * On post transition.
319 *
320 * @param string $new_status New post status.
321 * @param string $old_status Old post status.
322 * @param \WP_Post $post Post object.
323 */
324 public function on_post_transition( $new_status, $old_status, $post ) {
325 if ( ! is_a( $post, 'WP_Post' ) ) {
326 return;
327 }
328
329 if ( 'pending' === $old_status ) {
330 return;
331 }
332
333 if ( 'pending' !== $new_status ) {
334 return;
335 }
336
337 $this->on_post_pending( $post->ID, $post );
338 }
339
340 /**
341 * Setup hooks for custom post types.
342 *
343 * @since 1.2
344 */
345 public function custom_post_type_hooks() {
346 $post_types = get_post_types( array( 'public' => true ), 'names' );
347 $post_types = array_diff( $post_types, array( BNFW_Notification::POST_TYPE ) );
348
349 foreach ( $post_types as $post_type ) {
350 add_action( 'future_' . $post_type, array( $this, 'on_post_scheduled' ), 10, 2 );
351 }
352 }
353
354 /**
355 * Importer.
356 */
357 public function activate() {
358 require_once dirname( __FILE__ ) . '/includes/class-bnfw-import.php';
359 $importer = new BNFW_Import();
360 $importer->import();
361 }
362
363 /**
364 * Add 'Settings' link below BNFW in Plugins list.
365 *
366 * @since 1.0
367 * @param string[] $links An array of plugin action links. By default this can include 'activate',
368 * 'deactivate', and 'delete'. With Multisite active this can also include.
369 * @param string $file Path to the plugin file relative to the plugins directory.
370 * @return array plugin action links.
371 */
372 public function plugin_action_links( $links, $file ) {
373 $plugin_file = 'bnfw/bnfw.php';
374 if ( $file === $plugin_file ) {
375 $settings_link = '<a href="' . esc_url( admin_url( 'edit.php?post_type=bnfw_notification&page=bnfw-settings' ) ) . '">' . esc_html__( 'Settings', 'bnfw' ) . '</a>';
376 array_unshift( $links, $settings_link );
377 }
378 return $links;
379 }
380
381 /**
382 * When a new term is created.
383 *
384 * @since 1.0
385 * @param int $term_id Term ID.
386 * @param int $tt_id Term taxonomy ID.
387 * @param string $taxonomy Taxonomy slug.
388 */
389 public function create_term( $term_id, $tt_id, $taxonomy ) {
390 $this->send_notification( 'newterm-' . $taxonomy, $term_id );
391 }
392
393 /**
394 * Fires when a post is created for the first time.
395 *
396 * @param int $post_id Post ID.
397 * @param object $post Post object.
398 * @param bool $update Whether this is an existing post being updated or not.
399 *
400 * @since 1.3.1
401 */
402 public function insert_post( $post_id, $post, $update ) {
403 // Some themes like P2, directly insert posts into DB.
404 $insert_post_themes = apply_filters( 'bnfw_insert_post_themes', array( 'P2', 'Syncope' ) );
405 $current_theme = wp_get_theme();
406
407 /**
408 * Whether to trigger insert post hook.
409 *
410 * @since 1.4
411 */
412 $trigger_insert_post = apply_filters( 'bnfw_trigger_insert_post', false, $post_id, $update );
413
414 if ( in_array( $current_theme->get( 'Name' ), $insert_post_themes, true ) || $trigger_insert_post ) {
415 $this->handle_inserted_post( $post_id, $update );
416 }
417 }
418
419 /**
420 * Trigger New Post published notification for ACF forms.
421 *
422 * @param string $form ACF Form.
423 * @param int $post_id Post ID.
424 */
425 public function acf_submit_form( $form, $post_id ) {
426 $this->handle_inserted_post( $post_id );
427 }
428
429 /**
430 * Trigger correct notifications for inserted posts.
431 *
432 * @param int $post_id Post id.
433 * @param bool $update Whether the post was updated.
434 *
435 * @since 1.6.7
436 */
437 private function handle_inserted_post( $post_id, $update ) {
438 $post = get_post( $post_id );
439
440 if ( ! is_a( $post, 'WP_Post' ) ) {
441 return;
442 }
443
444 switch ( $post->post_status ) {
445 case 'publish':
446 if ( $update ) {
447 $this->update_post( $post );
448 } else {
449 $this->publish_post( $post );
450 }
451 break;
452
453 case 'private':
454 $this->private_post( $post );
455 break;
456
457 case 'pending':
458 $this->on_post_pending( $post_id, $post );
459 break;
460
461 case 'future':
462 $this->on_post_scheduled( $post_id, $post );
463 break;
464 }
465 }
466
467 /**
468 * Fires when a post is created for the first time.
469 *
470 * @since 1.0
471 * @param object $post Post Object.
472 */
473 public function publish_post( $post ) {
474 $post_id = $post->ID;
475 $post_type = $post->post_type;
476
477 if ( BNFW_Notification::POST_TYPE !== $post_type ) {
478 $this->send_notification_async( 'new-' . $post_type, $post_id );
479 }
480 }
481
482 /**
483 * Fire an email when post status change to private.
484 *
485 * @param object $post Post Object.
486 *
487 * @return void
488 */
489 public function publish_private_post( $post ) {
490 $this->private_post( $post );
491 }
492
493 /**
494 * Fires when a private post is created.
495 *
496 * @since 1.6
497 * @param object $post Post Object.
498 */
499 public function private_post( $post ) {
500 $post_id = $post->ID;
501 $post_type = $post->post_type;
502
503 if ( BNFW_Notification::POST_TYPE !== $post_type ) {
504 $this->send_notification_async( 'private-' . $post_type, $post_id );
505 }
506 }
507
508 /**
509 * Fires when a post is updated.
510 *
511 * @since 1.0
512 * @param WP_Post $post Post object.
513 */
514 public function update_post( $post ) {
515 if ( $this->is_metabox_request() ) {
516 return;
517 }
518
519 $post_id = $post->ID;
520 $post_type = $post->post_type;
521
522 if ( BNFW_Notification::POST_TYPE !== $post_type ) {
523 $this->send_notification_async( 'update-' . $post_type, $post_id );
524 }
525 }
526
527 /**
528 * Fires when a post is moved publish to trash.
529 *
530 * @param WP_Post $post Post object.
531 */
532 public function trash_post( $post ) {
533 if ( $this->is_metabox_request() ) {
534 return;
535 }
536 $post_id = $post->ID;
537 $post_type = $post->post_type;
538
539 if ( BNFW_Notification::POST_TYPE !== $post_type ) {
540 $this->send_notification_async( 'trash-' . $post_type, $post_id );
541 }
542 }
543
544 /**
545 * Fires when a post is pending for review.
546 *
547 * @since 1.1
548 * @param int $post_id Post ID.
549 * @param object $post Post object.
550 */
551 public function on_post_pending( $post_id, $post ) {
552 if ( $this->is_metabox_request() ) {
553 return;
554 }
555
556 $post_type = $post->post_type;
557
558 if ( BNFW_Notification::POST_TYPE !== $post_type ) {
559 $this->send_notification_async( 'pending-' . $post_type, $post_id );
560 }
561 }
562
563 /**
564 * On Media Published.
565 *
566 * @param int $post_id Attachment post id.
567 */
568 public function new_publish_media_notification( $post_id ) {
569 $post_type = get_post_type( $post_id );
570
571 if ( BNFW_Notification::POST_TYPE !== $post_type && 'attachment' === $post_type ) {
572 $this->send_notification_async( 'new-media', $post_id );
573 }
574 }
575
576 /**
577 * On Media Attachment Data Update.
578 *
579 * @param int $post_id Attachment post id.
580 */
581 public function media_attachment_data_update_notification( $post_id ) {
582 $post_type = get_post_type( $post_id );
583 if ( BNFW_Notification::POST_TYPE !== $post_type && 'attachment' === $post_type ) {
584 $this->send_notification_async( 'update-media', $post_id );
585 }
586 }
587
588 /**
589 * Fires when a post is scheduled.
590 *
591 * @since 1.1.5
592 * @param int $post_id Post ID.
593 * @param object $post Post object.
594 */
595 public function on_post_scheduled( $post_id, $post ) {
596 // Rest request also triggers the same hook. We can ignore it.
597 if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
598 return;
599 }
600
601 $post_type = $post->post_type;
602
603 if ( BNFW_Notification::POST_TYPE !== $post_type ) {
604 $this->send_notification_async( 'future-' . $post_type, $post_id );
605 }
606 }
607
608 /**
609 * When the status of a comment is changed.
610 *
611 * @param string $new_status New status.
612 * @param string $old_status Old status.
613 * @param \WP_Comment $comment Comment.
614 */
615 public function on_comment_status_change( $new_status, $old_status, $comment ) {
616 if ( 'approved' !== $new_status ) {
617 return;
618 }
619
620 $post = get_post( $comment->comment_post_ID );
621
622 $notification_type = 'approve-' . $post->post_type . '-comment';
623
624 $this->send_notification( $notification_type, $comment->comment_ID, false );
625
626 // Send new comment notification after comment approve.
627 $notification_type = 'new-comment'; // old notification name.
628
629 if ( 'post' !== $post->post_type ) {
630 $notification_type = 'comment-' . $post->post_type;
631 }
632
633 $this->send_notification( $notification_type, $comment->comment_ID );
634
635 // Send comment reply notification after comment approve.
636 $this->comments_reply( $comment->comment_ID );
637 }
638
639 /**
640 * Send notification for new comments
641 *
642 * @since 1.0
643 * @param int $comment_id The comment ID.
644 */
645 public function comment_post( $comment_id ) {
646 $the_comment = get_comment( $comment_id );
647 $post = get_post( $the_comment->comment_post_ID );
648
649 if ( '1' !== $the_comment->comment_approved ) {
650 if ( $this->can_send_comment_notification( $the_comment ) ) {
651 $notification_type = 'moderate-' . $post->post_type . '-comment';
652 $this->send_notification( $notification_type, $comment_id );
653 }
654 } else {
655 $notification_type = 'new-comment'; // old notification name.
656
657 if ( 'post' !== $post->post_type ) {
658 $notification_type = 'comment-' . $post->post_type;
659 }
660
661 $this->send_notification( $notification_type, $comment_id );
662
663 // comment reply notification.
664 $this->comments_reply( $comment_id );
665 }
666 }
667
668 /**
669 * Send notification for comments reply
670 *
671 * @since 1.0
672 * @param int $comment_id The comment ID.
673 */
674 public function comments_reply( $comment_id ) {
675 $the_comment = get_comment( $comment_id );
676 $post = get_post( $the_comment->comment_post_ID );
677
678 // comment reply notification.
679 if ( $this->can_send_comment_notification( $the_comment ) ) {
680 if ( $the_comment->comment_parent > 0 ) {
681 $notification_type = 'reply-comment'; // old notification name.
682 if ( 'post' !== $post->post_type ) {
683 $notification_type = 'commentreply-' . $post->post_type;
684 }
685 $notifications = $this->notifier->get_notifications( $notification_type );
686 if ( count( $notifications ) > 0 ) {
687 $parent = get_comment( $the_comment->comment_parent );
688 if ( $parent->comment_author_email !== $the_comment->comment_author_email ) {
689 foreach ( $notifications as $notification ) {
690 $this->engine->send_comment_reply_email( $this->notifier->read_settings( $notification->ID ), $the_comment, $parent );
691 }
692 }
693 }
694 }
695 }
696 }
697
698 /**
699 * Send notification for new trackback.
700 *
701 * @since 1.0
702 * @param int $comment_id Trackback ID.
703 */
704 public function trackback_post( $comment_id ) {
705 $the_comment = get_comment( $comment_id );
706 if ( $this->can_send_comment_notification( $the_comment ) ) {
707 $this->send_notification( 'new-trackback', $comment_id );
708 }
709 }
710
711 /**
712 * Send notification for new pingbacks
713 *
714 * @since 1.0
715 * @param int $comment_id Comment ID.
716 */
717 public function pingback_post( $comment_id ) {
718 $the_comment = get_comment( $comment_id );
719 if ( $this->can_send_comment_notification( $the_comment ) ) {
720 $this->send_notification( 'new-pingback', $comment_id );
721 }
722 }
723
724 /**
725 * Send notification for lost password.
726 *
727 * @since 1.0
728 */
729 public function on_lost_password() {
730 $user_login = ! empty( $_POST['user_login'] ) ? sanitize_text_field( wp_unslash( $_POST['user_login'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
731 $user = get_user_by( 'login', $user_login );
732 if ( false === $user ) {
733 $user = get_user_by( 'email', $user_login );
734 }
735 if ( $user ) {
736 $this->send_notification( 'admin-password', $user->ID );
737 }
738 }
739
740 /**
741 * Change the title of the password reset email that is sent to the user.
742 *
743 * @since 1.1
744 *
745 * @param string $title Email subject.
746 * @param string $user_login The username for the user.
747 * @param WP_User $user_data WP_User object.
748 *
749 * @return string
750 */
751 public function change_password_email_title( $title, $user_login = '', $user_data = '' ) {
752 $notifications = $this->notifier->get_notifications( 'user-password' );
753 if ( count( $notifications ) > 0 ) {
754 // Ideally there should be only one notification for this type.
755 // If there are multiple notification then we will read data about only the last one.
756 $setting = $this->notifier->read_settings( end( $notifications )->ID );
757 $user_id = ! empty( $user_data->ID ) ? $user_data->ID : 0;
758
759 $title = $this->engine->handle_shortcodes( $setting['subject'], 'user-password', $user_id );
760
761 /**
762 * Filters the subject of the password reset email.
763 *
764 * @since 1.9.9
765 *
766 * @param string $title Email subject.
767 * @param array $setting Notification settings.
768 * @param string $user_login The username for the user.
769 * @param WP_User $user_data WP_User object.
770 */
771 $title = apply_filters( 'bnfw_user_retrieve_password_title', $title, $setting, $user_login, $user_data );
772 }
773
774 return $title;
775 }
776
777 /**
778 * Change the message of the password reset email.
779 *
780 * @since 1.1
781 *
782 * @param string $message Email message.
783 * @param string $key The activation key.
784 * @param string $user_login The username for the user.
785 * @param WP_User $user_data WP_User object.
786 *
787 * @return string
788 */
789 public function change_password_email_message( $message, $key, $user_login = '', $user_data = '' ) {
790 $notifications = $this->notifier->get_notifications( 'user-password' );
791 if ( count( $notifications ) > 0 ) {
792 // Ideally there should be only one notification for this type.
793 // If there are multiple notification then we will read data about only the last one.
794 $setting = $this->notifier->read_settings( end( $notifications )->ID );
795
796 /**
797 * Filters the override the notification settings.
798 *
799 * @param array $setting Notification settings.
800 * @param WP_User $user_data WP_User object.
801 *
802 * @since 1.9.9
803 */
804 $setting = apply_filters( 'bnfw_change_password_email_message_notification_settings', $setting, $user_data );
805
806 $message = $this->engine->handle_password_reset_shortcodes( $setting, $key, $user_login, $user_data );
807
808 if ( 'html' === $setting['email-formatting'] ) {
809 add_filter( 'wp_mail_content_type', array( $this, 'set_html_content_type' ) );
810 if ( 'true' !== $setting['disable-autop'] ) {
811 $message = wpautop( $message );
812 }
813 } else {
814 add_filter( 'wp_mail_content_type', array( $this, 'set_text_content_type' ) );
815 if ( 'text' === $setting['email-formatting'] ) {
816 $message = wp_strip_all_tags( $message );
817 }
818 }
819 } else {
820 if ( $this->notifier->notification_exists( 'user-password', false ) ) {
821 // disabled notification exists, so disable the email by returning empty string.
822 return '';
823 }
824 }
825
826 return $message;
827 }
828
829 /**
830 * On Password reset.
831 *
832 * @param WP_User $user User who's password was changed.
833 */
834 public function on_password_reset( $user ) {
835 $notifications = $this->notifier->get_notifications( 'password-changed' );
836 foreach ( $notifications as $notification ) {
837 $this->engine->send_password_changed_email( $this->notifier->read_settings( $notification->ID ), $user );
838 }
839 }
840
841 /**
842 * Should the password changed email be sent?
843 *
844 * @param bool $send Whether to send the email.
845 * @param array $user The original user array.
846 * @param array $userdata The updated user array.
847 *
848 * @return bool
849 */
850 public function should_password_changed_email_be_sent( $send, $user, $userdata ) {
851 $bnfw = self::factory();
852
853 if ( ! $send ) {
854 return $send;
855 }
856
857 return ! $bnfw->notifier->is_notification_disabled( 'password-changed' );
858 }
859
860 /**
861 * On Password Changed.
862 *
863 * @since 1.6
864 *
865 * @param array $email_data Email Data.
866 * @param array $user User data.
867 *
868 * @return array Modified Email Data
869 */
870 public function on_password_changed( $email_data, $user ) {
871 return $this->handle_filtered_data_notification( 'password-changed', $email_data, $user['ID'] );
872 }
873
874 /**
875 * Should the email changed email be sent?
876 *
877 * @param bool $send Whether to send the email.
878 * @param array $user_old_data The original user array.
879 * @param array $user_new_data The updated user array.
880 *
881 * @return bool
882 */
883 public function should_email_changed_email_be_sent( $send, $user_old_data, $user_new_data ) {
884 $bnfw = self::factory();
885
886 if ( $bnfw->notifier->notification_exists( 'admin-email-changed', false ) ) {
887 $notifications = $bnfw->notifier->get_notifications( 'admin-email-changed' );
888
889 if ( count( $notifications ) > 0 ) {
890 // Ideally there should be only one notification for this type.
891 // If there are multiple notification then we will read data about only the last one.
892 $setting = $bnfw->notifier->read_settings( end( $notifications )->ID );
893 $notification_disabled = apply_filters( 'bnfw_notification_disabled', ( 'true' === $setting['disabled'] ), $user_old_data['ID'], $setting );
894
895 if ( ! $notification_disabled ) {
896
897 $setting['message'] = str_replace( '[user_old_email]', $user_old_data['user_email'], $setting['message'] );
898 $setting['message'] = str_replace( '[user_new_email]', $user_new_data['user_email'], $setting['message'] );
899 $bnfw->engine->send_notification( $setting, $user_old_data['ID'] );
900 }
901 }
902 }
903
904 if ( ! $send ) {
905 return $send;
906 }
907
908 return ! $bnfw->notifier->is_notification_disabled( 'email-changed' );
909 }
910
911 /**
912 * On Email Changed.
913 *
914 * @since 1.6
915 *
916 * @param array $email_data Email Data.
917 * @param array $user_old_data The original user array.
918 * @param array $user_new_data The updated user array.
919 *
920 * @return array Modified Email Data
921 */
922 public function on_email_changed( $email_data, $user_old_data, $user_new_data ) {
923
924 $email = $this->handle_filtered_data_notification( 'email-changed', $email_data, $user_old_data['ID'] );
925 $user = get_user_by( 'ID', $user_old_data['ID'] );
926 $email['message'] = str_replace( '[user_nicename]', $user->user_login, $email['message'] );
927 $email['message'] = str_replace( '[user_old_email]', $user_old_data['user_email'], $email['message'] );
928 $email['message'] = str_replace( '[user_new_email]', $user_new_data['user_email'], $email['message'] );
929 $email_data['message'] = $email['message'];
930
931 $notifications = $this->notifier->get_notifications( 'email-changed' );
932 if ( count( $notifications ) > 0 ) {
933 $setting = $this->notifier->read_settings( end( $notifications )->ID );
934 // Ensures the content type of the message.
935 if ( 'html' === $setting['email-formatting'] ) {
936 $email_data['message'] = wpautop( $email_data['message'] );
937 }
938 }
939 $email_data['subject'] = $email['subject'];
940
941 return $email_data;
942 }
943
944 /**
945 * Filters the text of the email sent when a change of user email address is attempted.
946 *
947 * @param string $email_text Text in the email.
948 * @param array $new_user_details {
949 * Data relating to the new user email address.
950 *
951 * @type string $hash The secure hash used in the confirmation link URL.
952 * @type string $newemail The proposed new email address.
953 * }
954 */
955 public function on_email_changing( $email_text, $new_user_details ) {
956 $notification_name = 'email-changing';
957
958 $notifications = $this->notifier->get_notifications( $notification_name );
959 if ( count( $notifications ) > 0 ) {
960
961 $user = wp_get_current_user();
962
963 // Ideally there should be only one notification for this type.
964 // If there are multiple notification then we will read data about only the last one.
965 $setting = $this->notifier->read_settings( end( $notifications )->ID );
966
967 /**
968 * Filters the override notification settings.
969 *
970 * @param array $setting Notification settings.
971 * @param WP_User $user Current WP_User instance.
972 * @param array $new_user_details {
973 * Data relating to the new user email address.
974 *
975 * @type string $hash The secure hash used in the confirmation link URL.
976 * @type string $newemail The proposed new email address.
977 * }
978 *
979 * @since 1.9.9
980 */
981 $setting = apply_filters( 'bnfw_user_on_email_changing_notification_settings', $setting, $user, $new_user_details );
982
983 // Ensures the content type of the message.
984 if ( 'html' === $setting['email-formatting'] ) {
985 add_filter( 'wp_mail_content_type', array( $this, 'set_html_content_type' ) );
986 } else {
987 add_filter( 'wp_mail_content_type', array( $this, 'set_text_content_type' ) );
988 }
989
990 $email_text = $this->engine->handle_shortcodes( $setting['message'], $setting['notification'], $new_user_details['newemail'] );
991 $email_text = $this->engine->handle_global_user_shortcodes( $email_text, $new_user_details['newemail'] );
992 $email_text = str_replace( '[email_change_confirmation_link]', esc_url( self_admin_url( 'profile.php?newuseremail=' . $new_user_details['hash'] ) ), $email_text );
993 $email_text = str_replace( '[user_nicename]', $user->data->user_nicename, $email_text );
994 $email_text = str_replace( '[user_id]', $user->data->ID, $email_text );
995 $email_text = str_replace( '[user_login]', $user->data->user_login, $email_text );
996 $email_text = str_replace( '[user_email]', $user->data->user_email, $email_text );
997 $email_text = str_replace( '[user_url]', $user->data->user_url, $email_text );
998 $email_text = str_replace( '[user_registered]', $user->data->user_registered, $email_text );
999 $email_text = str_replace( '[user_display_name]', $user->data->display_name, $email_text );
1000 $email_text = str_replace( '[user_firstname]', get_user_meta( $user->data->ID, 'first_name', true ), $email_text );
1001 $email_text = str_replace( '[user_lastname]', get_user_meta( $user->data->ID, 'last_name', true ), $email_text );
1002 $email_text = str_replace( '[user_nickname]', get_user_meta( $user->data->ID, 'nickname', true ), $email_text );
1003 $email_text = str_replace( '[user_description]', get_user_meta( $user->data->ID, 'description', true ), $email_text );
1004 $email_text = str_replace( '[user_wp_capabilities]', implode( ', ', $user->roles ), $email_text );
1005 $email_text = str_replace( '[user_avatar]', get_avatar( $user->data->ID ), $email_text );
1006 $email_text = str_replace( '[nickname]', $user->nickname, $email_text );
1007 $email_text = str_replace( '[display_name]', $user->display_name, $email_text );
1008 $email_text = str_replace( '[email_user_id]', $user->data->ID, $email_text );
1009 $email_text = str_replace( '[email_user_login]', $user->data->user_login, $email_text );
1010 $email_text = str_replace( '[email_user_nicename]', $user->data->user_nicename, $email_text );
1011 $email_text = str_replace( '[email_user_email]', $user->data->user_email, $email_text );
1012 $email_text = str_replace( '[email_user_url]', $user->data->user_url, $email_text );
1013 $email_text = str_replace( '[email_user_registered]', $user->data->user_registered, $email_text );
1014 $email_text = str_replace( '[email_user_display_name]', $user->data->display_name, $email_text );
1015 $email_text = str_replace( '[email_user_firstname]', get_user_meta( $user->data->ID, 'first_name', true ), $email_text );
1016 $email_text = str_replace( '[email_user_lastname]', get_user_meta( $user->data->ID, 'last_name', true ), $email_text );
1017 $email_text = str_replace( '[email_user_nickname]', get_user_meta( $user->data->ID, 'nickname', true ), $email_text );
1018 $email_text = str_replace( '[email_user_description]', get_user_meta( $user->data->ID, 'description', true ), $email_text );
1019 $email_text = str_replace( '[email_user_wp_capabilities]', implode( ', ', $user->roles ), $email_text );
1020 $email_text = str_replace( '[email_user_avatar]', get_avatar( $user->data->ID ), $email_text );
1021 $email_text = str_replace( '[user_old_email]', $user->data->user_email, $email_text );
1022 $email_text = str_replace( '[user_new_email]', $new_user_details['newemail'], $email_text );
1023 $email_text = str_replace( '[user_role]', implode( ',', $user->roles ), $email_text );
1024
1025 $user_capabilities = bnfw_format_user_capabilities( $user->wp_capabilities );
1026 if ( ! empty( $user_capabilities ) ) {
1027 $email_text = str_replace( '[wp_capabilities]', $user_capabilities, $email_text );
1028 }
1029
1030 if ( 'html' === $setting['email-formatting'] ) {
1031 $email_text = wpautop( $email_text );
1032 }
1033 }
1034
1035 return $email_text;
1036 }
1037
1038 /**
1039 * Send notification on core updated event.
1040 *
1041 * @since 1.6
1042 *
1043 * @param array $email_data Email Data.
1044 * @param string $type The type of email being sent. Can be one of
1045 * 'success', 'fail', 'manual', 'critical'.
1046 * @param object $core_update The update offer that was attempted.
1047 * @param mixed $result The result for the core update. Can be WP_Error.
1048 *
1049 * @return array Modified Email Data.
1050 */
1051 public function on_core_updated( $email_data, $type, $core_update, $result ) {
1052 $notifications = $this->notifier->get_notifications( 'core-updated' );
1053 if ( count( $notifications ) > 0 ) {
1054 // Ideally there should be only one notification for this type.
1055 // If there are multiple notification then we will read data about only the last one.
1056 $setting = $this->notifier->read_settings( end( $notifications )->ID );
1057
1058 $email_data = $this->engine->handle_core_updated_notification( $email_data, $setting, $type );
1059 }
1060
1061 return $email_data;
1062 }
1063
1064 /**
1065 * Process User update notifications.
1066 *
1067 * @since 1.6
1068 *
1069 * @param string $notification_name Notification Name.
1070 * @param array $email_data Email Data.
1071 * @param string|int $extra_data User Id.
1072 *
1073 * @return array Modified Email Data.
1074 */
1075 private function handle_filtered_data_notification( $notification_name, $email_data, $extra_data ) {
1076 $notifications = $this->notifier->get_notifications( $notification_name );
1077 if ( count( $notifications ) > 0 ) {
1078 // Ideally there should be only one notification for this type.
1079 // If there are multiple notification then we will read data about only the last one.
1080 $setting = $this->notifier->read_settings( end( $notifications )->ID );
1081
1082 /**
1083 * Filters the override the notification settings.
1084 *
1085 * @param array $setting Notification settings.
1086 * @param array $email_data Email Data.
1087 * @param string|int $extra_data Extra data like ID of user.
1088 *
1089 * @since 1.9.9
1090 */
1091 $setting = apply_filters( 'bnfw_handle_filtered_data_notification_settings', $setting, $email_data, $extra_data );
1092
1093 // Ensures the content type of the message.
1094 if ( 'html' === $setting['email-formatting'] ) {
1095 add_filter( 'wp_mail_content_type', array( $this, 'set_html_content_type' ) );
1096 } else {
1097 add_filter( 'wp_mail_content_type', array( $this, 'set_text_content_type' ) );
1098 }
1099
1100 $email_data = $this->engine->handle_filtered_data_notification( $email_data, $setting, $extra_data );
1101 }
1102
1103 return $email_data;
1104 }
1105
1106 /**
1107 * Set the email formatting to HTML.
1108 *
1109 * @since 1.4
1110 */
1111 public function set_html_content_type() {
1112 return 'text/html';
1113 }
1114
1115 /**
1116 * Set the email formatting to text.
1117 *
1118 * @since 1.4
1119 */
1120 public function set_text_content_type() {
1121 return 'text/plain';
1122 }
1123
1124 /**
1125 * Send notification for new users.
1126 *
1127 * @since 1.0
1128 * @param int $user_id User ID.
1129 */
1130 public function user_register( $user_id ) {
1131 $this->send_notification( 'admin-user', $user_id );
1132 }
1133
1134 /**
1135 * Send notification for user when user login.
1136 *
1137 * @since 1.0
1138 * @param string $user_name Username.
1139 * @param object $user_data User object.
1140 */
1141 public function user_login( $user_name, $user_data ) {
1142 $user_id = $user_data->ID;
1143 $notifications = $this->notifier->get_notifications( 'user-login' );
1144
1145 foreach ( $notifications as $notification ) {
1146 $this->engine->send_user_login_email( $this->notifier->read_settings( $notification->ID ), get_userdata( $user_id ) );
1147 }
1148
1149 $this->user_login_admin_notification( $user_id );
1150 }
1151
1152 /**
1153 * Send notification for admin when user login.
1154 *
1155 * @since 1.0
1156 * @param int $user_id User ID.
1157 */
1158 public function user_login_admin_notification( $user_id ) {
1159 $notifications = $this->notifier->get_notifications( 'admin-user-login' );
1160
1161 foreach ( $notifications as $notification ) {
1162 $this->engine->send_user_login_email_for_admin( $this->notifier->read_settings( $notification->ID ), get_userdata( $user_id ) );
1163 }
1164 }
1165
1166 /**
1167 * Send notification about new users to site admin.
1168 *
1169 * @since 1.7.1
1170 *
1171 * @param array $email_data Email details.
1172 * @param WP_User $user User object.
1173 * @param string $blogname Blog name.
1174 *
1175 * @return array Modified email details.
1176 */
1177 public function handle_user_registered_admin_email( $email_data, $user, $blogname ) {
1178 return $this->handle_filtered_data_notification( 'admin-user', $email_data, $user->ID );
1179 }
1180
1181 /**
1182 * New User - Post-registration Email
1183 *
1184 * @since 1.1
1185 * @param int $user_id New user id.
1186 */
1187 public function welcome_email( $user_id ) {
1188 $notifications = $this->notifier->get_notifications( 'welcome-email' );
1189 foreach ( $notifications as $notification ) {
1190 $this->engine->send_registration_email( $this->notifier->read_settings( $notification->ID ), get_userdata( $user_id ) );
1191 }
1192 }
1193
1194 /**
1195 * Send notification when a user role changes.
1196 *
1197 * @since 1.3.9
1198 *
1199 * @param int $user_id User ID.
1200 * @param string $new_role New User role.
1201 * @param array $old_roles Old User role.
1202 */
1203 public function user_role_changed( $user_id, $new_role, $old_roles ) {
1204 if ( ! empty( $old_roles ) ) {
1205 $notifications = $this->notifier->get_notifications( 'user-role' );
1206 foreach ( $notifications as $notification ) {
1207
1208 /**
1209 * Trigger User Role Changed - For User notification.
1210 *
1211 * @since 1.6.5
1212 * @since 1.9.9 Added `$user_id` parameter.
1213 */
1214 if ( apply_filters( 'bnfw_trigger_user-role_notification', true, $notification, $new_role, $old_roles, $user_id ) ) {
1215 $this->engine->send_user_role_changed_email( $this->notifier->read_settings( $notification->ID ), $user_id, $old_roles[0], $new_role );
1216 }
1217 }
1218 $notifications = $this->notifier->get_notifications( 'admin-role' );
1219 foreach ( $notifications as $notification ) {
1220
1221 /**
1222 * Trigger User Role Changed - For User notification.
1223 *
1224 * @since 1.6.5
1225 * @since 1.9.9 Added `$user_id` parameter.
1226 */
1227 if ( apply_filters( 'bnfw_trigger_admin-role_notification', true, $notification, $new_role, $old_roles, $user_id ) ) {
1228 $setting = $this->notifier->read_settings( $notification->ID );
1229 $setting['message'] = $this->engine->handle_user_role_shortcodes( $setting['message'], $old_roles[0], $new_role );
1230 $setting['subject'] = $this->engine->handle_user_role_shortcodes( $setting['subject'], $old_roles[0], $new_role );
1231
1232 $this->engine->send_notification( $setting, $user_id );
1233 }
1234 }
1235 }
1236 }
1237
1238 /**
1239 * Send notification when a user role added through Members Plugin.
1240 *
1241 * @since 1.8.4
1242 *
1243 * @param int $user_id User ID.
1244 * @param string $new_role New User role.
1245 */
1246 public function user_role_added_from_member_plugin( $user_id, $new_role ) {
1247
1248 global $pagenow;
1249
1250 if ( 'users.php' !== $pagenow ) {
1251 return;
1252 }
1253 if ( ! $user_id ) {
1254 return;
1255 }
1256
1257 $notifications = $this->notifier->get_notifications( 'user-role' );
1258
1259 foreach ( $notifications as $notification ) {
1260 if ( apply_filters( 'bnfw_trigger_user-role_notification', true, $notification, $new_role, null, $user_id ) ) {
1261 $this->engine->send_user_role_changed_email( $this->notifier->read_settings( $notification->ID ), $user_id, null, $new_role );
1262 }
1263 }
1264
1265 $notifications_admin = $this->notifier->get_notifications( 'admin-role' );
1266 foreach ( $notifications_admin as $notification ) {
1267 if ( apply_filters( 'bnfw_trigger_admin-role_notification', true, $notification, $new_role, null, $user_id ) ) {
1268 $setting = $this->notifier->read_settings( $notification->ID );
1269 $setting['message'] = $this->engine->handle_user_role_shortcodes( $setting['message'], null, $new_role );
1270 $setting['subject'] = $this->engine->handle_user_role_shortcodes( $setting['subject'], null, $new_role );
1271
1272 $this->engine->send_notification( $setting, $user_id );
1273 }
1274 }
1275
1276 }
1277
1278 /**
1279 * Send notification when a user role removed through Members Plugin.
1280 *
1281 * @since 1.8.4
1282 *
1283 * @param int $user_id User ID.
1284 * @param string $old_role New User role.
1285 */
1286 public function user_role_removed_from_member_plugin( $user_id, $old_role ) {
1287 global $pagenow;
1288
1289 if ( 'users.php' !== $pagenow ) {
1290 return;
1291 }
1292 if ( ! $user_id ) {
1293 return;
1294 }
1295
1296 $notifications = $this->notifier->get_notifications( 'user-role' );
1297
1298 foreach ( $notifications as $notification ) {
1299 if ( apply_filters( 'bnfw_trigger_user-role_notification', true, $notification, null, array( $old_role ), $user_id ) ) {
1300 $this->engine->send_user_role_changed_email( $this->notifier->read_settings( $notification->ID ), $user_id, $old_role, null );
1301 }
1302 }
1303
1304 $notifications_admin = $this->notifier->get_notifications( 'admin-role' );
1305 foreach ( $notifications_admin as $notification ) {
1306 if ( apply_filters( 'bnfw_trigger_admin-role_notification', true, $notification, null, array( $old_role ), $user_id ) ) {
1307 $setting = $this->notifier->read_settings( $notification->ID );
1308 $setting['message'] = $this->engine->handle_user_role_shortcodes( $setting['message'], $old_role, null );
1309 $setting['subject'] = $this->engine->handle_user_role_shortcodes( $setting['subject'], $old_role, null );
1310
1311 $this->engine->send_notification( $setting, $user_id );
1312 }
1313 }
1314
1315 }
1316
1317 /**
1318 * Send notification when a user role added support User Role Editor by Members Plugin.
1319 *
1320 * @since 1.3.9
1321 *
1322 * @param int $user_id User ID.
1323 * @param array $old_user_data Old User role.
1324 */
1325 public function user_role_added( $user_id, $old_user_data ) {
1326
1327 if ( isset( $_POST['members_user_roles'] ) && ! empty( $_POST['members_user_roles'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
1328 // Get the current user roles.
1329 $old_roles = (array) $old_user_data->roles;
1330
1331 // Sanitize the posted roles.
1332 $new_roles = array_map( array( $this, 'bnfw_members_sanitize_role' ), $_POST['members_user_roles'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
1333
1334 sort( $old_roles );
1335 sort( $new_roles );
1336 $old_roles_str = implode( '', $old_roles );
1337 $new_roles_str = implode( '', $new_roles );
1338 if ( ! empty( $old_roles ) && $old_roles_str !== $new_roles_str ) {
1339 $notifications = $this->notifier->get_notifications( 'user-role' );
1340 foreach ( $notifications as $notification ) {
1341
1342 /**
1343 * Trigger User Role Changed - For User notification.
1344 *
1345 * @since 1.6.5
1346 * @since 1.9.9 Added `$user_id` parameter.
1347 */
1348 if ( apply_filters( 'bnfw_trigger_user-role-added_notification', true, $notification, $new_roles, $old_roles, $user_id ) ) {
1349 $this->engine->send_user_role_added_email( $this->notifier->read_settings( $notification->ID ), $user_id, $old_roles, $new_roles );
1350 }
1351 }
1352
1353 $notifications = $this->notifier->get_notifications( 'admin-role' );
1354 foreach ( $notifications as $notification ) {
1355
1356 /**
1357 * Trigger User Role Changed - For User notification.
1358 *
1359 * @since 1.6.5
1360 * @since 1.9.9 Added `$user_id` parameter.
1361 */
1362 if ( apply_filters( 'bnfw_trigger_admin-role-added_notification', true, $notification, $new_roles, $old_roles, $user_id ) ) {
1363 $setting = $this->notifier->read_settings( $notification->ID );
1364 $setting['message'] = $this->engine->handle_user_added_role_shortcodes( $setting['message'], $old_roles, $new_roles );
1365 $setting['subject'] = $this->engine->handle_user_added_role_shortcodes( $setting['subject'], $old_roles, $new_roles );
1366
1367 $this->engine->send_notification( $setting, $user_id );
1368 }
1369 }
1370 }
1371 }
1372 }
1373
1374 /**
1375 * Sanitizes a role name. This is a wrapper for the `sanitize_key()` WordPress function. Only
1376 * alphanumeric characters and underscores are allowed. Hyphens are also replaced with underscores.
1377 *
1378 * @since 1.0.0
1379 * @access public
1380 * @param array $role Posted user role.
1381 * @return int
1382 */
1383 public function bnfw_members_sanitize_role( $role ) {
1384
1385 $_role = strtolower( $role );
1386 $_role = preg_replace( '/[^a-z0-9_\-\s]/', '', $_role );
1387
1388 return apply_filters( 'bnfw_members_sanitize_role', str_replace( ' ', '_', $_role ), $role );
1389 }
1390
1391 /**
1392 * Send notification based on type and ref id.
1393 *
1394 * @since 1.0
1395 * @param string $type Notification type.
1396 * @param mixed $ref_id Reference data.
1397 * @param bool $include_disabled Include disabled.
1398 */
1399 public function send_notification( $type, $ref_id, $include_disabled = true ) {
1400 $notifications = $this->notifier->get_notifications( $type, $include_disabled );
1401 foreach ( $notifications as $notification ) {
1402 $this->engine->send_notification( $this->notifier->read_settings( $notification->ID ), $ref_id );
1403 }
1404 }
1405
1406 /**
1407 * Send notification async based on type and ref id.
1408 *
1409 * @param string $type Notification type.
1410 * @param mixed $ref_id Reference data.
1411 */
1412 public function send_notification_async( $type, $ref_id ) {
1413 $notifications = $this->notifier->get_notifications( $type, false );
1414 foreach ( $notifications as $notification ) {
1415 $transient = get_transient( 'bnfw-async-notifications' );
1416 if ( ! is_array( $transient ) ) {
1417 $transient = array();
1418 }
1419
1420 $notification_data = array(
1421 'ref_id' => $ref_id,
1422 'notification_id' => $notification->ID,
1423 'notification_type' => $type,
1424 );
1425
1426 if (
1427 ! in_array( $notification_data, $transient, true ) &&
1428 apply_filters( 'bnfw_is_send_only_once_notification', true, $notification_data )
1429 ) {
1430 $transient[] = $notification_data;
1431 set_transient( 'bnfw-async-notifications', $transient, 600 );
1432 }
1433 }
1434 }
1435
1436 /**
1437 * Can send comment notification or not.
1438 *
1439 * @since 1.0
1440 * @param WP_Comment $comment Comment data.
1441 * @return bool
1442 */
1443 private function can_send_comment_notification( $comment ) {
1444 // Returns false if the comment is marked as spam AND admin has enabled suppression of spam.
1445 $suppress_spam = get_option( 'bnfw_suppress_spam' );
1446 if ( '1' === $suppress_spam && ( 0 === strcmp( $comment->comment_approved, 'spam' ) ) ) {
1447 return false;
1448 }
1449 return true;
1450 }
1451
1452 /**
1453 * Handle user request email content.
1454 *
1455 * @param string $content Content.
1456 * @param array $email_data Email data.
1457 *
1458 * @return string Modified content.
1459 */
1460 public function handle_user_request_email_content( $content, $email_data ) {
1461 $field = 'message';
1462 $new_content = '';
1463
1464 switch ( $email_data['description'] ) {
1465 case 'Export Personal Data':
1466 $notification_name = 'ca-export-data';
1467 $new_content = $this->handle_user_request_notification( $notification_name, $field, $email_data );
1468 break;
1469 case 'Erase Personal Data':
1470 $notification_name = 'ca-erase-data';
1471 $new_content = $this->handle_user_request_notification( $notification_name, $field, $email_data );
1472 break;
1473 }
1474
1475 if ( ! empty( $new_content ) ) {
1476 return $new_content;
1477 } else {
1478 return $content;
1479 }
1480 }
1481
1482 /**
1483 * Handle user request email subject.
1484 *
1485 * @param string $subject Subject.
1486 * @param string $blogname Blog name.
1487 * @param array $email_data Email data.
1488 *
1489 * @return string Modified subject.
1490 */
1491 public function handle_user_request_email_subject( $subject, $blogname, $email_data ) {
1492 $field = 'subject';
1493 $new_subject = '';
1494
1495 switch ( $email_data['description'] ) {
1496 case 'Export Personal Data':
1497 $notification_name = 'ca-export-data';
1498 $new_subject = $this->handle_user_request_notification( $notification_name, $field, $email_data );
1499 break;
1500 case 'Erase Personal Data':
1501 $notification_name = 'ca-erase-data';
1502 $new_subject = $this->handle_user_request_notification( $notification_name, $field, $email_data );
1503 break;
1504 }
1505 if ( ! empty( $new_subject ) ) {
1506 return $new_subject;
1507 } else {
1508 return $subject;
1509 }
1510 }
1511
1512 /**
1513 * Handle user confirmed action email content.
1514 *
1515 * @param string $content Content.
1516 * @param array $email_data Email data.
1517 *
1518 * @return string Modified content.
1519 */
1520 public function handle_user_confirmed_action_email_content( $content, $email_data ) {
1521 $field = 'message';
1522 $new_content = '';
1523
1524 switch ( $email_data['description'] ) {
1525 case 'Export Personal Data':
1526 $notification_name = 'uc-export-data';
1527 $new_content = $this->handle_user_confirmed_action_notification( $notification_name, $field, $email_data );
1528 break;
1529 case 'Erase Personal Data':
1530 $notification_name = 'uc-erase-data';
1531 $new_content = $this->handle_user_confirmed_action_notification( $notification_name, $field, $email_data );
1532 break;
1533 }
1534
1535 if ( ! empty( $new_content ) ) {
1536 return $new_content;
1537 } else {
1538 return $content;
1539 }
1540 }
1541
1542 /**
1543 * Handle data exported email content.
1544 *
1545 * @param string $content Text in the email.
1546 * @param int $request_id The request ID for this personal data export.
1547 * @param array $email_data Data relating to the account action email.
1548 *
1549 * @return string Modified content.
1550 */
1551 public function handle_data_export_email_content( $content, $request_id, $email_data ) {
1552
1553 $field = 'message';
1554 $notification_name = 'data-export';
1555 $new_content = '';
1556
1557 $notifications = $this->notifier->get_notifications( $notification_name );
1558 if ( count( $notifications ) > 0 ) {
1559 // Ideally there should be only one notification for this type.
1560 // If there are multiple notification then we will read data about only the last one.
1561 $setting = $this->notifier->read_settings( end( $notifications )->ID );
1562
1563 /**
1564 * Filters the text of the email sent with a personal data export file.
1565 *
1566 * @param array $setting Setting of the notification.
1567 * @param array $email_data Data relating to the account action email.
1568 *
1569 * @since 1.9.9
1570 */
1571 $setting = apply_filters( 'bnfw_handle_data_export_email_content_settings', $setting, $email_data );
1572
1573 $new_content = $this->engine->handle_data_export_email_shortcodes( $setting[ $field ], $setting, $request_id );
1574 $new_content = $this->engine->handle_global_user_shortcodes( $new_content, $email_data['message_recipient'] );
1575 }
1576
1577 if ( ! empty( $new_content ) ) {
1578 return $new_content;
1579 } else {
1580 return $content;
1581 }
1582 }
1583 /**
1584 * Filters the subject of the email sent when an erasure request is completed.
1585 *
1586 * @param string $subject The email subject.
1587 * @param string $sitename The name of the site.
1588 * @param array $email_data Data relating to the account action email.
1589 */
1590 public function handle_erasure_complete_email_subject( $subject, $sitename, $email_data ) {
1591 return $this->handle_erasure_complete_email_notification( 'subject', $subject, $email_data );
1592 }
1593 /**
1594 * Filters the body of the data erasure fulfillment notification.
1595 *
1596 * @param string $content The email content.
1597 * @param array $email_data Data relating to the account action email.
1598 */
1599 public function handle_erasure_complete_email_content( $content, $email_data ) {
1600 if ( isset( $email_data['privacy_policy_url'] ) ) {
1601 return $this->handle_erasure_complete_email_notification( 'message', $content, $email_data );
1602 }
1603
1604 return $content;
1605 }
1606 /**
1607 * Handles erasure fulfillment notification.
1608 *
1609 * @param string $field Field name.
1610 * @param string $content The email content.
1611 * @param array $email_data Data relating to the account action email.
1612 */
1613 protected function handle_erasure_complete_email_notification( $field, $content, $email_data ) {
1614 $notification_name = 'data-erased';
1615 $new_content = '';
1616 $notifications = $this->notifier->get_notifications( $notification_name );
1617 if ( count( $notifications ) > 0 ) {
1618 // Ideally there should be only one notification for this type.
1619 // If there are multiple notification then we will read data about only the last one.
1620 $setting = $this->notifier->read_settings( end( $notifications )->ID );
1621
1622 /**
1623 * Filters the subject of the email sent when an erasure request is completed.
1624 *
1625 * @param array $setting Setting of the notification.
1626 * @param array $email_data Data relating to the account action email.
1627 *
1628 * @since 1.9.9
1629 */
1630 $setting = apply_filters( 'bnfw_handle_erasure_complete_email_notification_settings', $setting, $email_data );
1631
1632 $new_content = $this->engine->handle_shortcodes( $setting[ $field ], $notification_name, $email_data );
1633 }
1634 if ( ! empty( $new_content ) ) {
1635 return $new_content;
1636 } else {
1637 return $content;
1638 }
1639 }
1640
1641 /**
1642 * Send notification emails on shutdown.
1643 */
1644 public function on_shutdown() {
1645 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
1646 return;
1647 }
1648
1649 // Get all notifications.
1650 $transient = get_transient( 'bnfw-async-notifications' );
1651
1652 // Check if the add-on is activated.
1653 $is_keep_notifications = class_exists( 'BNFW_Per_Post_Override' ) && ! $this->is_metabox_request();
1654 if ( $is_keep_notifications && is_array( $transient ) ) {
1655 $keep_notifications = array();
1656 $send_notifications = array();
1657 foreach ( $transient as $id_pairs ) {
1658
1659 // Keep the notifications which are start with '-update' and check the block editor is enabled for this post/page.
1660 if (
1661 $this->is_block_editor_page( $id_pairs['ref_id'] ) &&
1662 $this->notifier->starts_with( $id_pairs['notification_type'], 'update-' )
1663 ) {
1664 $keep_notifications[] = $id_pairs;
1665
1666 // Send other notifications.
1667 } else {
1668 $send_notifications[] = $id_pairs;
1669 }
1670 }
1671
1672 // Unset the variable.
1673 unset( $transient );
1674
1675 // Set the latest notifications to send immediately.
1676 $transient = $send_notifications;
1677
1678 // Save again notification to send after the save metabox values.
1679 set_transient( 'bnfw-async-notifications', $keep_notifications, 600 );
1680 } else {
1681 delete_transient( 'bnfw-async-notifications' );
1682 }
1683
1684 if ( is_array( $transient ) ) {
1685 foreach ( $transient as $id_pairs ) {
1686 $this->engine->send_notification( $this->notifier->read_settings( $id_pairs['notification_id'] ), $id_pairs['ref_id'] );
1687 }
1688 }
1689 }
1690
1691 /**
1692 * Handle user request notification.
1693 *
1694 * @param string $notification_name Notification name.
1695 * @param string $field Field name.
1696 * @param array $email_data Email data.
1697 *
1698 * @return string Content.
1699 */
1700 protected function handle_user_request_notification( $notification_name, $field, $email_data ) {
1701 $notifications = $this->notifier->get_notifications( $notification_name );
1702 if ( count( $notifications ) > 0 ) {
1703 // Ideally there should be only one notification for this type.
1704 // If there are multiple notification then we will read data about only the last one.
1705 $setting = $this->notifier->read_settings( end( $notifications )->ID );
1706
1707 /**
1708 * Filters the text of the email sent when an account action is attempted.
1709 *
1710 * @param array $setting Setting of the notification.
1711 * @param array $email_data Data relating to the account action email.
1712 *
1713 * @since 1.9.9
1714 */
1715 $setting = apply_filters( 'bnfw_handle_user_request_notification_settings', $setting, $email_data );
1716
1717 return $this->engine->handle_user_request_email_shortcodes( $setting[ $field ], $setting, $email_data );
1718 }
1719
1720 return '';
1721 }
1722
1723 /**
1724 * Handle user confirmed action notification.
1725 *
1726 * @param string $notification_name Notification name.
1727 * @param string $field Field name.
1728 * @param array $email_data Email data.
1729 *
1730 * @return string Content.
1731 */
1732 protected function handle_user_confirmed_action_notification( $notification_name, $field, $email_data ) {
1733 $notifications = $this->notifier->get_notifications( $notification_name );
1734 if ( count( $notifications ) > 0 ) {
1735 // Ideally there should be only one notification for this type.
1736 // If there are multiple notification then we will read data about only the last one.
1737 $setting = $this->notifier->read_settings( end( $notifications )->ID );
1738
1739 /**
1740 * Filters the body of the user request confirmation email.
1741 *
1742 * @param array $setting Setting of the notification.
1743 * @param array $email_data Data relating to the account action email.
1744 *
1745 * @since 1.9.9
1746 */
1747 $setting = apply_filters( 'bnfw_handle_user_confirmed_action_notification_settings', $setting, $email_data );
1748
1749 return $this->engine->handle_user_confirmed_action_email_shortcodes( $setting[ $field ], $setting, $email_data );
1750 }
1751
1752 return '';
1753 }
1754
1755 /**
1756 * Is this a metabox request?
1757 *
1758 * Block editor sends duplicate requests on post update.
1759 *
1760 * @return bool True if metabox request, False otherwise.
1761 */
1762 protected function is_metabox_request() {
1763 return ( isset( $_GET['meta-box-loader'] ) || isset( $_GET['meta_box'] ) );
1764 }
1765
1766 /**
1767 * Check if Gutenberg is active.
1768 *
1769 * @return bool
1770 * @since 1.3
1771 */
1772 public function is_gutenberg_active() {
1773 $gutenberg = false;
1774 $block_editor = false;
1775
1776 if ( has_filter( 'replace_editor', 'gutenberg_init' ) ) {
1777 // Gutenberg is installed and activated.
1778 $gutenberg = true;
1779 }
1780
1781 if ( version_compare( $GLOBALS['wp_version'], '5.0-beta', '>' ) ) {
1782 // Block editor.
1783 $block_editor = true;
1784 }
1785
1786 if ( ! $gutenberg && ! $block_editor ) {
1787 return false;
1788 }
1789
1790 include_once ABSPATH . 'wp-admin/includes/plugin.php';
1791
1792 if ( ! is_plugin_active( 'classic-editor/classic-editor.php' ) ) {
1793 return true;
1794 }
1795
1796 $use_block_editor = ( get_option( 'classic-editor-replace' ) === 'no-replace' );
1797
1798 return $use_block_editor;
1799 }
1800
1801 /**
1802 * Check is block editor enabled for a particular post/page.
1803 *
1804 * @since 1.9.6
1805 *
1806 * @param int $ID ID of page/post.
1807 *
1808 * @return bool
1809 */
1810 public function is_block_editor_page( $ID ) {
1811
1812 // In case, WordPress is lower than version 5.0.
1813 if ( ! function_exists( 'use_block_editor_for_post' ) ) {
1814 return false;
1815 }
1816
1817 return use_block_editor_for_post( $ID );
1818 }
1819
1820 }
1821 /**
1822 * Fire up the plugin.
1823 */
1824 BNFW::factory();
1825 }
1826