Current File : /var/www/e360ban/wp-content/plugins/bnfw/bnfw.php
<?php
/**
 * Plugin Name: Better Notifications for WP
 * Plugin URI: https://wordpress.org/plugins/bnfw/
 * Description: Supercharge your WordPress notifications using a WYSIWYG editor and shortcodes. Default and new notifications available. Add more power with Add-ons.
 * Version: 1.9.1
 * Requires at least: 4.8
 * Requires PHP: 7.1
 * Author: Made with Fuel
 * Author URI: https://madewithfuel.com/
 * License: GPLv2 or later
 * License URI: http://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain: bnfw
 * Domain Path: /languages
 *
 * @package bnfw
 */

/**
 * Copyright © 2022 Made with Fuel Ltd. (hello@betternotificationsforwp.com)
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, version 2, as
 * published by the Free Software Foundation.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
if ( ! class_exists( 'BNFW', false ) ) {
	/**
	 * BNFW main class.
	 */
	class BNFW {
		/**
		 * BNFW version.
		 *
		 * @var string
		 */
		public $bnfw_version = '1.9.1';
		/**
		 * Class Constructor.
		 *
		 * @since 1.0
		 */
		public function __construct() {
			$this->bnfw_define_constants();
			$this->load_textdomain();
			$this->includes();
			$this->hooks();
			/**
			 * BNFW Notification.
			 *
			 * @var \BNFW_Notification
			 */
			$this->notifier = new BNFW_Notification();

			/**
			 * BNFW Engine.
			 *
			 * @var \BNFW_Engine
			 */
			$this->engine = new BNFW_Engine();
		}

		/**
		 * Factory method to return the instance of the class.
		 *
		 * Makes sure that only one instance is created.
		 *
		 * @return \BNFW Instance of the class.
		 */
		public static function factory() {
			static $instance = false;
			if ( ! $instance ) {
				$instance = new self();
			}
			return $instance;
		}

		/**
		 * Loads the plugin language files
		 *
		 * @since  1.0
		 */
		public function load_textdomain() {
			// Load localization domain.
			$this->translations = dirname( plugin_basename( __FILE__ ) ) . '/languages/';
			load_plugin_textdomain( 'bnfw', false, $this->translations );
		}

		/**
		 * Include required files.
		 *
		 * @since 1.0
		 */
		public function includes() {

			// Load license related classes.
			if ( ! class_exists( 'EDD_SL_Plugin_Updater' ) ) {
				require_once 'includes/libraries/class-edd-sl-plugin-updater.php';
			}

			include_once ABSPATH . 'wp-admin/includes/plugin.php';

			require_once 'vendor/persist-admin-notices-dismissal/persist-admin-notices-dismissal.php';

			require_once 'includes/license/class-bnfw-license.php';
			require_once 'includes/license/class-bnfw-license-setting.php';

			// Load Engine.
			require_once 'includes/engine/class-bnfw-engine.php';
			require_once 'includes/overrides.php';

			// Load notification post type and notification helpers.
			require_once 'includes/admin/class-bnfw-notification.php';
			require_once 'includes/notification/post-notification.php';

			// Helpers.
			require_once 'includes/helpers/helpers.php';
			require_once 'includes/helpers/class-bnfw-ajax.php';

			// Load Admin Pages.
			if ( is_admin() ) {
				require_once 'includes/admin/class-bnfw-settings.php';
			}
		}
		/**
		 * Define BNFW Constants.
		 */
		private function bnfw_define_constants() {
			define( 'BNFW_VERSION', $this->bnfw_version );
		}
		/**
		 * Register Hooks.
		 *
		 * @since 1.0
		 */
		public function hooks() {
			global $wp_version;

			register_activation_hook( __FILE__, array( $this, 'activate' ) );

			add_action( 'admin_init', array( 'PAnD', 'init' ) );
			add_action( 'admin_init', array( $this, 'add_capability_to_admin' ) );

			// Fire when privately publish.
			add_action( 'auto-draft_to_private', array( $this, 'publish_private_post' ), 10, 1 );

			add_action( 'draft_to_private', array( $this, 'private_post' ) );
			add_action( 'future_to_private', array( $this, 'private_post' ) );
			add_action( 'pending_to_private', array( $this, 'private_post' ) );
			add_action( 'publish_to_private', array( $this, 'private_post' ) );

			add_action( 'wp_insert_post', array( $this, 'insert_post' ), 10, 3 );

			add_action( 'attachment_updated', array( $this, 'trash_attachment' ), 10, 3 );

			add_action( 'publish_to_trash', array( $this, 'trash_post' ) );

			add_action( 'auto-draft_to_publish', array( $this, 'publish_post' ) );
			add_action( 'draft_to_publish', array( $this, 'publish_post' ) );
			add_action( 'future_to_publish', array( $this, 'publish_post' ) );
			add_action( 'pending_to_publish', array( $this, 'publish_post' ) );
			add_action( 'private_to_publish', array( $this, 'publish_post' ) );

			add_action( 'publish_to_publish', array( $this, 'update_post' ) );
			add_action( 'private_to_private', array( $this, 'update_post' ) );

			add_action( 'add_attachment', array( $this, 'new_publish_media_notification' ), 10, 1 );
			add_action( 'edit_attachment', array( $this, 'media_attachment_data_update_notification' ), 10 );

			add_action( 'transition_post_status', array( $this, 'on_post_transition' ), 10, 3 );

			add_action( 'init', array( $this, 'custom_post_type_hooks' ), 100 );
			add_action( 'create_term', array( $this, 'create_term' ), 10, 3 );

			add_action( 'transition_comment_status', array( $this, 'on_comment_status_change' ), 10, 3 );
			add_action( 'comment_post', array( $this, 'comment_post' ) );
			add_action( 'trackback_post', array( $this, 'trackback_post' ) );
			add_action( 'pingback_post', array( $this, 'pingback_post' ) );

			add_action( 'user_register', array( $this, 'user_register' ) );

			add_action( 'user_register', array( $this, 'welcome_email' ) );

			if ( is_plugin_active( 'members/members.php' ) ) {

				add_action( 'add_user_role', array( $this, 'user_role_added_from_member_plugin' ), 10, 2 );
				add_action( 'remove_user_role', array( $this, 'user_role_removed_from_member_plugin' ), 10, 2 );
				add_action( 'set_user_role', array( $this, 'user_role_changed' ), 10, 3 );

				add_action( 'profile_update', array( $this, 'user_role_added' ), 10, 2 );
			} else {
				add_action( 'set_user_role', array( $this, 'user_role_changed' ), 10, 3 );
			}

			add_action( 'wp_login', array( $this, 'user_login' ), 10, 2 );

			if ( version_compare( $wp_version, '4.4', '>=' ) ) {
				add_filter( 'retrieve_password_title', array( $this, 'change_password_email_title' ), 10, 3 );
			} else {
				add_filter( 'retrieve_password_title', array( $this, 'change_password_email_title' ) );
			}
			add_action( 'lostpassword_post', array( $this, 'on_lost_password' ) );
			add_filter( 'retrieve_password_message', array( $this, 'change_password_email_message' ), 10, 4 );

			add_action( 'after_password_reset', array( $this, 'on_password_reset' ) );

			add_filter( 'send_password_change_email', array( $this, 'should_password_changed_email_be_sent' ), 10, 3 );
			add_filter( 'password_change_email', array( $this, 'on_password_changed' ), 10, 2 );

			add_filter( 'send_email_change_email', array( $this, 'should_email_changed_email_be_sent' ), 10, 3 );
			add_filter( 'email_change_email', array( $this, 'on_email_changed' ), PHP_INT_MAX, 3 );
			add_filter( 'new_user_email_content', array( $this, 'on_email_changing' ), PHP_INT_MAX, 2 );

			add_filter( 'auto_core_update_email', array( $this, 'on_core_updated' ), 10, 4 );

			add_filter( 'user_request_action_email_content', array( $this, 'handle_user_request_email_content' ), 10, 2 );
			add_filter( 'user_request_action_email_subject', array( $this, 'handle_user_request_email_subject' ), 10, 3 );

			add_filter( 'user_confirmed_action_email_content', array( $this, 'handle_user_confirmed_action_email_content' ), 10, 2 );

			add_filter( 'wp_privacy_personal_data_email_content', array( $this, 'handle_data_export_email_content' ), 10, 3 );

			add_filter( 'user_erasure_complete_email_subject', array( $this, 'handle_erasure_complete_email_subject' ), 10, 3 );
			add_filter( 'user_confirmed_action_email_content', array( $this, 'handle_erasure_complete_email_content' ), 10, 2 );

			add_filter( 'plugin_action_links', array( $this, 'plugin_action_links' ), 10, 4 );
			add_filter( 'wp_mail', array( $this, 'bnfw_update_email_changing_subject' ), 10, 1 );
			add_action( 'shutdown', array( $this, 'on_shutdown' ) );

		}

		/**
		 * Changed the subject when use request to change the email.
		 *
		 * @param array $args Email arguments.
		 *
		 * @return mixed
		 */
		public function bnfw_update_email_changing_subject( $args ) {
			$notification_name = 'email-changed';
			$notifications     = $this->notifier->get_notifications( $notification_name );
			if ( count( $notifications ) > 0 ) {
				$setting = $this->notifier->read_settings( end( $notifications )->ID );
				if ( str_contains( $args['message'], '/profile.php?newuseremail=' ) ) {
					$subject         = str_replace( '[global_site_title]', get_bloginfo( 'name' ), $setting['subject'] );
					$subject         = str_replace( '[[global_site_title]]', get_bloginfo( 'name' ), $subject );
					$args['subject'] = $subject;
				} elseif ( str_contains( $args['message'], '?newuseremail=' ) ) {
					$subject         = str_replace( '[global_site_title]', get_bloginfo( 'name' ), $setting['subject'] );
					$subject         = str_replace( '[[global_site_title]]', get_bloginfo( 'name' ), $subject );
					$args['subject'] = $subject;
				}
			}

			return $args;
		}

		/**
		 * Fires when a media is moved to trash.
		 *
		 * @param int     $post_id Post ID.
		 * @param WP_Post $post_after Post object following the update.
		 * @param WP_Post $post_before  Post object before the update.
		 */
		public function trash_attachment( $post_id, $post_after, $post_before ) {
			$post_type          = get_post_type( $post_id );
			$post_status_before = $post_before->post_status;
			$post_status_after  = $post_after->post_status;
			if ( BNFW_Notification::POST_TYPE !== $post_type && 'inherit' === $post_status_before && 'trash' === $post_status_after ) {
				$this->send_notification_async( 'trash-' . $post_type, $post_id );
			}
		}

		/**
		 * Add 'bnfw' capability to admin.
		 */
		public function add_capability_to_admin() {
			$admins = get_role( 'administrator' );

			if ( is_null( $admins ) ) {
				return;
			}

			if ( ! $admins->has_cap( 'bnfw' ) ) {
				$admins->add_cap( 'bnfw' );
			}
		}

		/**
		 * On post transition.
		 *
		 * @param string   $new_status New post status.
		 * @param string   $old_status Old post status.
		 * @param \WP_Post $post       Post object.
		 */
		public function on_post_transition( $new_status, $old_status, $post ) {
			if ( ! is_a( $post, 'WP_Post' ) ) {
				return;
			}

			if ( 'pending' === $old_status ) {
				return;
			}

			if ( 'pending' !== $new_status ) {
				return;
			}

			$this->on_post_pending( $post->ID, $post );
		}

		/**
		 * Setup hooks for custom post types.
		 *
		 * @since 1.2
		 */
		public function custom_post_type_hooks() {
			$post_types = get_post_types( array( 'public' => true ), 'names' );
			$post_types = array_diff( $post_types, array( BNFW_Notification::POST_TYPE ) );

			foreach ( $post_types as $post_type ) {
				add_action( 'future_' . $post_type, array( $this, 'on_post_scheduled' ), 10, 2 );
			}
		}

		/**
		 * Importer.
		 */
		public function activate() {
			require_once dirname( __FILE__ ) . '/includes/class-bnfw-import.php';
			$importer = new BNFW_Import();
			$importer->import();
		}

		/**
		 * Add 'Settings' link below BNFW in Plugins list.
		 *
		 * @since 1.0
		 * @param string[] $links     An array of plugin action links. By default this can include 'activate',
		 *                              'deactivate', and 'delete'. With Multisite active this can also include.
		 * @param string   $file Path to the plugin file relative to the plugins directory.
		 * @return array plugin action links.
		 */
		public function plugin_action_links( $links, $file ) {
			$plugin_file = 'bnfw/bnfw.php';
			if ( $file === $plugin_file ) {
				$settings_link = '<a href="' . esc_url( admin_url( 'edit.php?post_type=bnfw_notification&page=bnfw-settings' ) ) . '">' . esc_html__( 'Settings', 'bnfw' ) . '</a>';
				array_unshift( $links, $settings_link );
			}
			return $links;
		}

		/**
		 * When a new term is created.
		 *
		 * @since 1.0
		 * @param int    $term_id Term ID.
		 * @param int    $tt_id Term taxonomy ID.
		 * @param string $taxonomy Taxonomy slug.
		 */
		public function create_term( $term_id, $tt_id, $taxonomy ) {
			$this->send_notification( 'newterm-' . $taxonomy, $term_id );
		}

		/**
		 * Fires when a post is created for the first time.
		 *
		 * @param int    $post_id Post ID.
		 * @param object $post    Post object.
		 * @param bool   $update  Whether this is an existing post being updated or not.
		 *
		 * @since 1.3.1
		 */
		public function insert_post( $post_id, $post, $update ) {
			// Some themes like P2, directly insert posts into DB.
			$insert_post_themes = apply_filters( 'bnfw_insert_post_themes', array( 'P2', 'Syncope' ) );
			$current_theme      = wp_get_theme();

			/**
			 * Whether to trigger insert post hook.
			 *
			 * @since 1.4
			 */
			$trigger_insert_post = apply_filters( 'bnfw_trigger_insert_post', false, $post_id, $update );

			if ( in_array( $current_theme->get( 'Name' ), $insert_post_themes, true ) || $trigger_insert_post ) {
				$this->handle_inserted_post( $post_id, $update );
			}
		}

		/**
		 * Trigger New Post published notification for ACF forms.
		 *
		 * @param string $form ACF Form.
		 * @param int    $post_id Post ID.
		 */
		public function acf_submit_form( $form, $post_id ) {
			$this->handle_inserted_post( $post_id );
		}

		/**
		 * Trigger correct notifications for inserted posts.
		 *
		 * @param int  $post_id Post id.
		 * @param bool $update Whether the post was updated.
		 *
		 * @since 1.6.7
		 */
		private function handle_inserted_post( $post_id, $update ) {
			$post = get_post( $post_id );

			if ( ! is_a( $post, 'WP_Post' ) ) {
				return;
			}

			switch ( $post->post_status ) {
				case 'publish':
					if ( $update ) {
						$this->update_post( $post );
					} else {
						$this->publish_post( $post );
					}
					break;

				case 'private':
					$this->private_post( $post );
					break;

				case 'pending':
					$this->on_post_pending( $post_id, $post );
					break;

				case 'future':
					$this->on_post_scheduled( $post_id, $post );
					break;
			}
		}

		/**
		 * Fires when a post is created for the first time.
		 *
		 * @since 1.0
		 * @param object $post Post Object.
		 */
		public function publish_post( $post ) {
			$post_id   = $post->ID;
			$post_type = $post->post_type;

			if ( BNFW_Notification::POST_TYPE !== $post_type ) {
				$this->send_notification_async( 'new-' . $post_type, $post_id );
			}
		}

		/**
		 * Fire an email when post status change to private.
		 *
		 * @param object $post Post Object.
		 *
		 * @return void
		 */
		public function publish_private_post( $post ) {
			$this->private_post( $post );
		}

		/**
		 * Fires when a private post is created.
		 *
		 * @since 1.6
		 * @param object $post Post Object.
		 */
		public function private_post( $post ) {
			$post_id   = $post->ID;
			$post_type = $post->post_type;

			if ( BNFW_Notification::POST_TYPE !== $post_type ) {
				$this->send_notification_async( 'private-' . $post_type, $post_id );
			}
		}

		/**
		 * Fires when a post is updated.
		 *
		 * @since 1.0
		 * @param WP_Post $post Post object.
		 */
		public function update_post( $post ) {
			if ( $this->is_metabox_request() ) {
				return;
			}

			$post_id   = $post->ID;
			$post_type = $post->post_type;

			if ( BNFW_Notification::POST_TYPE !== $post_type ) {
				$this->send_notification_async( 'update-' . $post_type, $post_id );
			}
		}

		/**
		 * Fires when a post is moved publish to trash.
		 *
		 * @param WP_Post $post Post object.
		 */
		public function trash_post( $post ) {
			if ( $this->is_metabox_request() ) {
				return;
			}
			$post_id   = $post->ID;
			$post_type = $post->post_type;

			if ( BNFW_Notification::POST_TYPE !== $post_type ) {
				$this->send_notification_async( 'trash-' . $post_type, $post_id );
			}
		}

		/**
		 * Fires when a post is pending for review.
		 *
		 * @since 1.1
		 * @param int    $post_id Post ID.
		 * @param object $post Post object.
		 */
		public function on_post_pending( $post_id, $post ) {
			if ( $this->is_metabox_request() ) {
				return;
			}

			$post_type = $post->post_type;

			if ( BNFW_Notification::POST_TYPE !== $post_type ) {
				$this->send_notification_async( 'pending-' . $post_type, $post_id );
			}
		}

		/**
		 * On Media Published.
		 *
		 * @param int $post_id Attachment post id.
		 */
		public function new_publish_media_notification( $post_id ) {
			$post_type = get_post_type( $post_id );

			if ( BNFW_Notification::POST_TYPE !== $post_type && 'attachment' === $post_type ) {
				$this->send_notification_async( 'new-media', $post_id );
			}
		}

		/**
		 * On Media Attachment Data Update.
		 *
		 * @param int $post_id Attachment post id.
		 */
		public function media_attachment_data_update_notification( $post_id ) {
			$post_type = get_post_type( $post_id );
			if ( BNFW_Notification::POST_TYPE !== $post_type && 'attachment' === $post_type ) {
				$this->send_notification_async( 'update-media', $post_id );
			}
		}

		/**
		 * Fires when a post is scheduled.
		 *
		 * @since 1.1.5
		 * @param int    $post_id Post ID.
		 * @param object $post Post object.
		 */
		public function on_post_scheduled( $post_id, $post ) {
			// Rest request also triggers the same hook. We can ignore it.
			if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
				return;
			}

			$post_type = $post->post_type;

			if ( BNFW_Notification::POST_TYPE !== $post_type ) {
				$this->send_notification_async( 'future-' . $post_type, $post_id );
			}
		}

		/**
		 * When the status of a comment is changed.
		 *
		 * @param string      $new_status New status.
		 * @param string      $old_status Old status.
		 * @param \WP_Comment $comment    Comment.
		 */
		public function on_comment_status_change( $new_status, $old_status, $comment ) {
			if ( 'approved' !== $new_status ) {
				return;
			}

			$post = get_post( $comment->comment_post_ID );

			$notification_type = 'approve-' . $post->post_type . '-comment';

			$this->send_notification( $notification_type, $comment->comment_ID, false );

			// Send new comment notification after comment approve.
			$notification_type = 'new-comment'; // old notification name.

			if ( 'post' !== $post->post_type ) {
				$notification_type = 'comment-' . $post->post_type;
			}

			$this->send_notification( $notification_type, $comment->comment_ID );

			// Send comment reply notification after comment approve.
			$this->comments_reply( $comment->comment_ID );
		}

		/**
		 * Send notification for new comments
		 *
		 * @since 1.0
		 * @param int $comment_id The comment ID.
		 */
		public function comment_post( $comment_id ) {
			$the_comment = get_comment( $comment_id );
			$post        = get_post( $the_comment->comment_post_ID );

			if ( '1' !== $the_comment->comment_approved ) {
				if ( $this->can_send_comment_notification( $the_comment ) ) {
					$notification_type = 'moderate-' . $post->post_type . '-comment';
					$this->send_notification( $notification_type, $comment_id );
				}
			} else {
				$notification_type = 'new-comment'; // old notification name.

				if ( 'post' !== $post->post_type ) {
					$notification_type = 'comment-' . $post->post_type;
				}

				$this->send_notification( $notification_type, $comment_id );

				// comment reply notification.
				$this->comments_reply( $comment_id );
			}
		}

		/**
		 * Send notification for comments reply
		 *
		 * @since 1.0
		 * @param int $comment_id The comment ID.
		 */
		public function comments_reply( $comment_id ) {
			$the_comment = get_comment( $comment_id );
			$post        = get_post( $the_comment->comment_post_ID );

			// comment reply notification.
			if ( $this->can_send_comment_notification( $the_comment ) ) {
				if ( $the_comment->comment_parent > 0 ) {
					$notification_type = 'reply-comment'; // old notification name.
					if ( 'post' !== $post->post_type ) {
						$notification_type = 'commentreply-' . $post->post_type;
					}
					$notifications = $this->notifier->get_notifications( $notification_type );
					if ( count( $notifications ) > 0 ) {
						$parent = get_comment( $the_comment->comment_parent );
						if ( $parent->comment_author_email !== $the_comment->comment_author_email ) {
							foreach ( $notifications as $notification ) {
								$this->engine->send_comment_reply_email( $this->notifier->read_settings( $notification->ID ), $the_comment, $parent );
							}
						}
					}
				}
			}
		}

		/**
		 * Send notification for new trackback.
		 *
		 * @since 1.0
		 * @param int $comment_id Trackback ID.
		 */
		public function trackback_post( $comment_id ) {
			$the_comment = get_comment( $comment_id );
			if ( $this->can_send_comment_notification( $the_comment ) ) {
				$this->send_notification( 'new-trackback', $comment_id );
			}
		}

		/**
		 * Send notification for new pingbacks
		 *
		 * @since 1.0
		 * @param int $comment_id Comment ID.
		 */
		public function pingback_post( $comment_id ) {
			$the_comment = get_comment( $comment_id );
			if ( $this->can_send_comment_notification( $the_comment ) ) {
				$this->send_notification( 'new-pingback', $comment_id );
			}
		}

		/**
		 * Send notification for lost password.
		 *
		 * @since 1.0
		 */
		public function on_lost_password() {
			$user_login = ! empty( $_POST['user_login'] ) ? sanitize_text_field( wp_unslash( $_POST['user_login'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
			$user       = get_user_by( 'login', $user_login );
			if ( false === $user ) {
				$user = get_user_by( 'email', $user_login );
			}
			if ( $user ) {
				$this->send_notification( 'admin-password', $user->ID );
			}
		}

		/**
		 * Change the title of the password reset email that is sent to the user.
		 *
		 * @since 1.1
		 *
		 * @param string $title Email subject.
		 * @param string $user_login The username for the user.
		 * @param string $user_data WP_User object.
		 *
		 * @return string
		 */
		public function change_password_email_title( $title, $user_login = '', $user_data = '' ) {
			$notifications = $this->notifier->get_notifications( 'user-password' );
			if ( count( $notifications ) > 0 ) {
				// Ideally there should be only one notification for this type.
				// If there are multiple notification then we will read data about only the last one.
				$setting = $this->notifier->read_settings( end( $notifications )->ID );

				if ( '' === $user_data ) {
					return $this->engine->handle_shortcodes( $setting['subject'], 'user-password', $user_data->ID );
				} else {
					return $this->engine->handle_shortcodes( $setting['subject'], 'user-password', $user_data->ID );
				}
			}

			return $title;
		}

		/**
		 * Change the message of the password reset email.
		 *
		 * @since 1.1
		 *
		 * @param string $message Email message.
		 * @param string $key The activation key.
		 * @param string $user_login The username for the user.
		 * @param string $user_data WP_User object.
		 *
		 * @return string
		 */
		public function change_password_email_message( $message, $key, $user_login = '', $user_data = '' ) {
			$notifications = $this->notifier->get_notifications( 'user-password' );
			if ( count( $notifications ) > 0 ) {
				// Ideally there should be only one notification for this type.
				// If there are multiple notification then we will read data about only the last one.
				$setting = $this->notifier->read_settings( end( $notifications )->ID );

				$message = $this->engine->handle_password_reset_shortcodes( $setting, $key, $user_login, $user_data );

				if ( 'html' === $setting['email-formatting'] ) {
					add_filter( 'wp_mail_content_type', array( $this, 'set_html_content_type' ) );
					if ( 'true' !== $setting['disable-autop'] ) {
						$message = wpautop( $message );
					}
				} else {
					add_filter( 'wp_mail_content_type', array( $this, 'set_text_content_type' ) );
					if ( 'text' === $setting['email-formatting'] ) {
						$message = wp_strip_all_tags( $message );
					}
				}
			} else {
				if ( $this->notifier->notification_exists( 'user-password', false ) ) {
					// disabled notification exists, so disable the email by returning empty string.
					return '';
				}
			}

			return $message;
		}

		/**
		 * On Password reset.
		 *
		 * @param WP_User $user User who's password was changed.
		 */
		public function on_password_reset( $user ) {
			$notifications = $this->notifier->get_notifications( 'password-changed' );
			foreach ( $notifications as $notification ) {
				$this->engine->send_password_changed_email( $this->notifier->read_settings( $notification->ID ), $user );
			}
		}

		/**
		 * Should the password changed email be sent?
		 *
		 * @param bool  $send Whether to send the email.
		 * @param array $user The original user array.
		 * @param array $userdata The updated user array.
		 *
		 * @return bool
		 */
		public function should_password_changed_email_be_sent( $send, $user, $userdata ) {
			$bnfw = self::factory();

			if ( ! $send ) {
				return $send;
			}

			return ! $bnfw->notifier->is_notification_disabled( 'password-changed' );
		}

		/**
		 * On Password Changed.
		 *
		 * @since 1.6
		 *
		 * @param array $email_data Email Data.
		 * @param array $user       User data.
		 *
		 * @return array Modified Email Data
		 */
		public function on_password_changed( $email_data, $user ) {
			return $this->handle_filtered_data_notification( 'password-changed', $email_data, $user['ID'] );
		}

		/**
		 * Should the email changed email be sent?
		 *
		 * @param bool  $send Whether to send the email.
		 * @param array $user_old_data The original user array.
		 * @param array $user_new_data The updated user array.
		 *
		 * @return bool
		 */
		public function should_email_changed_email_be_sent( $send, $user_old_data, $user_new_data ) {
			$bnfw = self::factory();

			if ( $bnfw->notifier->notification_exists( 'admin-email-changed', false ) ) {
				$notifications = $bnfw->notifier->get_notifications( 'admin-email-changed' );

				if ( count( $notifications ) > 0 ) {
					// Ideally there should be only one notification for this type.
					// If there are multiple notification then we will read data about only the last one.
					$setting               = $bnfw->notifier->read_settings( end( $notifications )->ID );
					$notification_disabled = apply_filters( 'bnfw_notification_disabled', ( 'true' === $setting['disabled'] ), $id, $setting );

					if ( ! $notification_disabled ) {

						$setting['message'] = str_replace( '[user_old_email]', $user_old_data['user_email'], $setting['message'] );
						$setting['message'] = str_replace( '[user_new_email]', $user_new_data['user_email'], $setting['message'] );
						$bnfw->engine->send_notification( $setting, $user_old_data['ID'] );
					}
				}
			}

			if ( ! $send ) {
				return $send;
			}

			return ! $bnfw->notifier->is_notification_disabled( 'email-changed' );
		}

		/**
		 * On Email Changed.
		 *
		 * @since 1.6
		 *
		 * @param array $email_data    Email Data.
		 * @param array $user_old_data The original user array.
		 * @param array $user_new_data The updated user array.
		 *
		 * @return array Modified Email Data
		 */
		public function on_email_changed( $email_data, $user_old_data, $user_new_data ) {

			$email                 = $this->handle_filtered_data_notification( 'email-changed', $email_data, $user_old_data['ID'] );
			$user                  = get_user_by( 'ID', $user_old_data['ID'] );
			$email['message']      = str_replace( '[user_nicename]', $user->user_login, $email['message'] );
			$email['message']      = str_replace( '[user_old_email]', $user_old_data['user_email'], $email['message'] );
			$email['message']      = str_replace( '[user_new_email]', $user_new_data['user_email'], $email['message'] );
			$email_data['message'] = $email['message'];

			$notifications = $this->notifier->get_notifications( 'email-changed' );
			if ( count( $notifications ) > 0 ) {
				$setting = $this->notifier->read_settings( end( $notifications )->ID );
				// Ensures the content type of the message.
				if ( 'html' === $setting['email-formatting'] ) {
					$email_data['message'] = wpautop( $email_data['message'] );
				}
			}

			return $email_data;
		}
		/**
		 * Filters the text of the email sent when a change of user email address is attempted.
		 *
		 * @param string $email_text     Text in the email.
		 * @param array  $new_user_details {
		 *     Data relating to the new user email address.
		 *
		 *     @type string $hash     The secure hash used in the confirmation link URL.
		 *     @type string $newemail The proposed new email address.
		 * }
		 */
		public function on_email_changing( $email_text, $new_user_details ) {
			$notification_name = 'email-changing';

			$notifications = $this->notifier->get_notifications( $notification_name );
			if ( count( $notifications ) > 0 ) {

				$user = wp_get_current_user();

				// Ideally there should be only one notification for this type.
				// If there are multiple notification then we will read data about only the last one.
				$setting = $this->notifier->read_settings( end( $notifications )->ID );

				// Ensures the content type of the message.
				if ( 'html' === $setting['email-formatting'] ) {
					add_filter( 'wp_mail_content_type', array( $this, 'set_html_content_type' ) );
				} else {
					add_filter( 'wp_mail_content_type', array( $this, 'set_text_content_type' ) );
				}

				$email_text = $this->engine->handle_shortcodes( $setting['message'], $setting['notification'], $new_user_details['newemail'] );
				$email_text = $this->engine->handle_global_user_shortcodes( $email_text, $new_user_details['newemail'] );
				$email_text = str_replace( '[email_change_confirmation_link]', esc_url( admin_url( 'profile.php?newuseremail=' . $new_user_details['hash'] ) ), $email_text );
				$email_text = str_replace( '[user_nicename]', $user->data->user_nicename, $email_text );
				$email_text = str_replace( '[user_id]', $user->data->ID, $email_text );
				$email_text = str_replace( '[user_login]', $user->data->user_login, $email_text );
				$email_text = str_replace( '[user_email]', $user->data->user_email, $email_text );
				$email_text = str_replace( '[user_url]', $user->data->user_url, $email_text );
				$email_text = str_replace( '[user_registered]', $user->data->user_registered, $email_text );
				$email_text = str_replace( '[user_display_name]', $user->data->display_name, $email_text );
				$email_text = str_replace( '[user_firstname]', get_user_meta( $user->data->ID, 'first_name', true ), $email_text );
				$email_text = str_replace( '[user_lastname]', get_user_meta( $user->data->ID, 'last_name', true ), $email_text );
				$email_text = str_replace( '[user_nickname]', get_user_meta( $user->data->ID, 'nickname', true ), $email_text );
				$email_text = str_replace( '[user_description]', get_user_meta( $user->data->ID, 'description', true ), $email_text );
				$email_text = str_replace( '[user_wp_capabilities]', implode( ', ', $user->roles ), $email_text );
				$email_text = str_replace( '[user_avatar]', get_avatar( $user->data->ID ), $email_text );
				$email_text = str_replace( '[nickname]', $user->nickname, $email_text );
				$email_text = str_replace( '[display_name]', $user->display_name, $email_text );
				$email_text = str_replace( '[email_user_id]', $user->data->ID, $email_text );
				$email_text = str_replace( '[email_user_login]', $user->data->user_login, $email_text );
				$email_text = str_replace( '[email_user_nicename]', $user->data->user_nicename, $email_text );
				$email_text = str_replace( '[email_user_email]', $user->data->user_email, $email_text );
				$email_text = str_replace( '[email_user_url]', $user->data->user_url, $email_text );
				$email_text = str_replace( '[email_user_registered]', $user->data->user_registered, $email_text );
				$email_text = str_replace( '[email_user_display_name]', $user->data->display_name, $email_text );
				$email_text = str_replace( '[email_user_firstname]', get_user_meta( $user->data->ID, 'first_name', true ), $email_text );
				$email_text = str_replace( '[email_user_lastname]', get_user_meta( $user->data->ID, 'last_name', true ), $email_text );
				$email_text = str_replace( '[email_user_nickname]', get_user_meta( $user->data->ID, 'nickname', true ), $email_text );
				$email_text = str_replace( '[email_user_description]', get_user_meta( $user->data->ID, 'description', true ), $email_text );
				$email_text = str_replace( '[email_user_wp_capabilities]', implode( ', ', $user->roles ), $email_text );
				$email_text = str_replace( '[email_user_avatar]', get_avatar( $user->data->ID ), $email_text );
				$email_text = str_replace( '[user_old_email]', $user->data->user_email, $email_text );
				$email_text = str_replace( '[user_new_email]', $new_user_details['newemail'], $email_text );
				$email_text = str_replace( '[user_role]', implode( ',', $user->roles ), $email_text );

				$user_capabilities = bnfw_format_user_capabilities( $user->wp_capabilities );
				if ( ! empty( $user_capabilities ) ) {
					$email_text = str_replace( '[wp_capabilities]', $user_capabilities, $email_text );
				}

				if ( 'html' === $setting['email-formatting'] ) {
					$email_text = wpautop( $email_text );
				}
			}

			return $email_text;
		}

		/**
		 * Send notification on core updated event.
		 *
		 * @since 1.6
		 *
		 * @param array  $email_data  Email Data.
		 * @param string $type        The type of email being sent. Can be one of
		 *                            'success', 'fail', 'manual', 'critical'.
		 * @param object $core_update The update offer that was attempted.
		 * @param mixed  $result      The result for the core update. Can be WP_Error.
		 *
		 * @return array Modified Email Data.
		 */
		public function on_core_updated( $email_data, $type, $core_update, $result ) {
			$notifications = $this->notifier->get_notifications( 'core-updated' );
			if ( count( $notifications ) > 0 ) {
				// Ideally there should be only one notification for this type.
				// If there are multiple notification then we will read data about only the last one.
				$setting = $this->notifier->read_settings( end( $notifications )->ID );

				$email_data = $this->engine->handle_core_updated_notification( $email_data, $setting, $type );
			}

			return $email_data;
		}

		/**
		 * Process User update notifications.
		 *
		 * @since 1.6
		 *
		 * @param string     $notification_name Notification Name.
		 * @param array      $email_data        Email Data.
		 * @param string|int $extra_data        User Id.
		 *
		 * @return array Modified Email Data.
		 */
		private function handle_filtered_data_notification( $notification_name, $email_data, $extra_data ) {
			$notifications = $this->notifier->get_notifications( $notification_name );
			if ( count( $notifications ) > 0 ) {
				// Ideally there should be only one notification for this type.
				// If there are multiple notification then we will read data about only the last one.
				$setting = $this->notifier->read_settings( end( $notifications )->ID );

				// Ensures the content type of the message.
				if ( 'html' === $setting['email-formatting'] ) {
					add_filter( 'wp_mail_content_type', array( $this, 'set_html_content_type' ) );
				} else {
					add_filter( 'wp_mail_content_type', array( $this, 'set_text_content_type' ) );
				}

				$email_data = $this->engine->handle_filtered_data_notification( $email_data, $setting, $extra_data );
			}

			return $email_data;
		}

		/**
		 * Set the email formatting to HTML.
		 *
		 * @since 1.4
		 */
		public function set_html_content_type() {
			return 'text/html';
		}

		/**
		 * Set the email formatting to text.
		 *
		 * @since 1.4
		 */
		public function set_text_content_type() {
			return 'text/plain';
		}

		/**
		 * Send notification for new users.
		 *
		 * @since 1.0
		 * @param int $user_id User ID.
		 */
		public function user_register( $user_id ) {
			$this->send_notification( 'admin-user', $user_id );
		}

		/**
		 * Send notification for user when user login.
		 *
		 * @since 1.0
		 * @param string $user_name Username.
		 * @param object $user_data User object.
		 */
		public function user_login( $user_name, $user_data ) {
			$user_id       = $user_data->ID;
			$notifications = $this->notifier->get_notifications( 'user-login' );

			foreach ( $notifications as $notification ) {
				$this->engine->send_user_login_email( $this->notifier->read_settings( $notification->ID ), get_userdata( $user_id ) );
			}

			$this->user_login_admin_notification( $user_id );
		}

		/**
		 * Send notification for admin when user login.
		 *
		 * @since 1.0
		 * @param int $user_id User ID.
		 */
		public function user_login_admin_notification( $user_id ) {
			$notifications = $this->notifier->get_notifications( 'admin-user-login' );

			foreach ( $notifications as $notification ) {
				$this->engine->send_user_login_email_for_admin( $this->notifier->read_settings( $notification->ID ), get_userdata( $user_id ) );
			}
		}

		/**
		 * Send notification about new users to site admin.
		 *
		 * @since 1.7.1
		 *
		 * @param array   $email_data Email details.
		 * @param WP_User $user       User object.
		 * @param string  $blogname   Blog name.
		 *
		 * @return array Modified email details.
		 */
		public function handle_user_registered_admin_email( $email_data, $user, $blogname ) {
			return $this->handle_filtered_data_notification( 'admin-user', $email_data, $user->ID );
		}

		/**
		 * New User - Post-registration Email
		 *
		 * @since 1.1
		 * @param int $user_id New user id.
		 */
		public function welcome_email( $user_id ) {
			$notifications = $this->notifier->get_notifications( 'welcome-email' );
			foreach ( $notifications as $notification ) {
				$this->engine->send_registration_email( $this->notifier->read_settings( $notification->ID ), get_userdata( $user_id ) );
			}
		}

		/**
		 * Send notification when a user role changes.
		 *
		 * @since 1.3.9
		 *
		 * @param int    $user_id   User ID.
		 * @param string $new_role  New User role.
		 * @param array  $old_roles Old User role.
		 */
		public function user_role_changed( $user_id, $new_role, $old_roles ) {
			if ( ! empty( $old_roles ) ) {
				$notifications = $this->notifier->get_notifications( 'user-role' );
				foreach ( $notifications as $notification ) {

					/**
					 * Trigger User Role Changed - For User notification.
					 *
					 * @since 1.6.5
					 */
					if ( apply_filters( 'bnfw_trigger_user-role_notification', true, $notification, $new_role, $old_roles ) ) {
						$this->engine->send_user_role_changed_email( $this->notifier->read_settings( $notification->ID ), $user_id, $old_roles[0], $new_role );
					}
				}
				$notifications = $this->notifier->get_notifications( 'admin-role' );
				foreach ( $notifications as $notification ) {

					/**
					 * Trigger User Role Changed - For User notification.
					 *
					 * @since 1.6.5
					 */
					if ( apply_filters( 'bnfw_trigger_admin-role_notification', true, $notification, $new_role, $old_roles ) ) {
						$setting            = $this->notifier->read_settings( $notification->ID );
						$setting['message'] = $this->engine->handle_user_role_shortcodes( $setting['message'], $old_roles[0], $new_role );
						$setting['subject'] = $this->engine->handle_user_role_shortcodes( $setting['subject'], $old_roles[0], $new_role );

						$this->engine->send_notification( $setting, $user_id );
					}
				}
			}
		}

		/**
		 * Send notification when a user role added through Members Plugin.
		 *
		 * @since 1.8.4
		 *
		 * @param int    $user_id   User ID.
		 * @param string $new_role  New User role.
		 */
		public function user_role_added_from_member_plugin( $user_id, $new_role ) {

			global $pagenow;

			if ( 'users.php' !== $pagenow ) {
				return;
			}
			if ( ! $user_id ) {
				return;
			}

			$notifications = $this->notifier->get_notifications( 'user-role' );

			foreach ( $notifications as $notification ) {
				if ( apply_filters( 'bnfw_trigger_user-role_notification', true, $notification, $new_role, null ) ) {
					$this->engine->send_user_role_changed_email( $this->notifier->read_settings( $notification->ID ), $user_id, null, $new_role );
				}
			}

			$notifications_admin = $this->notifier->get_notifications( 'admin-role' );
			foreach ( $notifications_admin as $notification ) {
				if ( apply_filters( 'bnfw_trigger_admin-role_notification', true, $notification, $new_role, null ) ) {
					$setting            = $this->notifier->read_settings( $notification->ID );
					$setting['message'] = $this->engine->handle_user_role_shortcodes( $setting['message'], null, $new_role );
					$setting['subject'] = $this->engine->handle_user_role_shortcodes( $setting['subject'], null, $new_role );

					$this->engine->send_notification( $setting, $user_id );
				}
			}

		}

		/**
		 * Send notification when a user role removed through Members Plugin.
		 *
		 * @since 1.8.4
		 *
		 * @param int    $user_id   User ID.
		 * @param string $old_role  New User role.
		 */
		public function user_role_removed_from_member_plugin( $user_id, $old_role ) {
			global $pagenow;

			if ( 'users.php' !== $pagenow ) {
				return;
			}
			if ( ! $user_id ) {
				return;
			}

			$notifications = $this->notifier->get_notifications( 'user-role' );

			foreach ( $notifications as $notification ) {
				if ( apply_filters( 'bnfw_trigger_user-role_notification', true, $notification, null, array( $old_role ) ) ) {
					$this->engine->send_user_role_changed_email( $this->notifier->read_settings( $notification->ID ), $user_id, $old_role, null );
				}
			}

			$notifications_admin = $this->notifier->get_notifications( 'admin-role' );
			foreach ( $notifications_admin as $notification ) {
				if ( apply_filters( 'bnfw_trigger_admin-role_notification', true, $notification, null, array( $old_role ) ) ) {
					$setting            = $this->notifier->read_settings( $notification->ID );
					$setting['message'] = $this->engine->handle_user_role_shortcodes( $setting['message'], $old_role, null );
					$setting['subject'] = $this->engine->handle_user_role_shortcodes( $setting['subject'], $old_role, null );

					$this->engine->send_notification( $setting, $user_id );
				}
			}

		}

		/**
		 * Send notification when a user role added support User Role Editor by Members Plugin.
		 *
		 * @since 1.3.9
		 *
		 * @param int   $user_id User ID.
		 * @param array $old_user_data Old User role.
		 */
		public function user_role_added( $user_id, $old_user_data ) {

			if ( isset( $_POST['members_user_roles'] ) && ! empty( $_POST['members_user_roles'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
				// Get the current user roles.
				$old_roles = (array) $old_user_data->roles;

				// Sanitize the posted roles.
				$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

				sort( $old_roles );
				sort( $new_roles );
				$old_roles_str = implode( '', $old_roles );
				$new_roles_str = implode( '', $new_roles );
				if ( ! empty( $old_roles ) && $old_roles_str !== $new_roles_str ) {
					$notifications = $this->notifier->get_notifications( 'user-role' );
					foreach ( $notifications as $notification ) {

						/**
						 * Trigger User Role Changed - For User notification.
						 *
						 * @since 1.6.5
						 */
						if ( apply_filters( 'bnfw_trigger_user-role-added_notification', true, $notification, $new_roles, $old_roles ) ) {
							$this->engine->send_user_role_added_email( $this->notifier->read_settings( $notification->ID ), $user_id, $old_roles, $new_roles );
						}
					}

					$notifications = $this->notifier->get_notifications( 'admin-role' );
					foreach ( $notifications as $notification ) {

						/**
						 * Trigger User Role Changed - For User notification.
						 *
						 * @since 1.6.5
						 */
						if ( apply_filters( 'bnfw_trigger_user-role-added_notification', true, $notification, $new_roles, $old_roles ) ) {
							$setting            = $this->notifier->read_settings( $notification->ID );
							$setting['message'] = $this->engine->handle_user_added_role_shortcodes( $setting['message'], $old_roles, $new_roles );
							$setting['subject'] = $this->engine->handle_user_added_role_shortcodes( $setting['subject'], $old_roles, $new_roles );

							$this->engine->send_notification( $setting, $user_id );
						}
					}
				}
			}
		}

		/**
		 * Sanitizes a role name.  This is a wrapper for the `sanitize_key()` WordPress function.  Only
		 * alphanumeric characters and underscores are allowed.  Hyphens are also replaced with underscores.
		 *
		 * @since  1.0.0
		 * @access public
		 * @param array $role Posted user role.
		 * @return int
		 */
		public function bnfw_members_sanitize_role( $role ) {

			$_role = strtolower( $role );
			$_role = preg_replace( '/[^a-z0-9_\-\s]/', '', $_role );

			return apply_filters( 'bnfw_members_sanitize_role', str_replace( ' ', '_', $_role ), $role );
		}

		/**
		 * Send notification based on type and ref id.
		 *
		 * @since 1.0
		 * @param string $type   Notification type.
		 * @param mixed  $ref_id Reference data.
		 * @param bool   $include_disabled Include disabled.
		 */
		public function send_notification( $type, $ref_id, $include_disabled = true ) {
			$notifications = $this->notifier->get_notifications( $type, $include_disabled );
			foreach ( $notifications as $notification ) {
				$this->engine->send_notification( $this->notifier->read_settings( $notification->ID ), $ref_id );
			}
		}

		/**
		 * Send notification async based on type and ref id.
		 *
		 * @param string $type Notification type.
		 * @param mixed  $ref_id Reference data.
		 */
		public function send_notification_async( $type, $ref_id ) {
			$notifications = $this->notifier->get_notifications( $type, false );
			foreach ( $notifications as $notification ) {
				$transient = get_transient( 'bnfw-async-notifications' );
				if ( ! is_array( $transient ) ) {
					$transient = array();
				}

				$notification_data = array(
					'ref_id'            => $ref_id,
					'notification_id'   => $notification->ID,
					'notification_type' => $type,
				);

				if ( ! in_array( $notification_data, $transient, true ) ) {
					$transient[] = $notification_data;
					set_transient( 'bnfw-async-notifications', $transient, 600 );
				}
			}
		}

		/**
		 * Can send comment notification or not.
		 *
		 * @since 1.0
		 * @param  WP_Comment $comment Comment data.
		 * @return bool
		 */
		private function can_send_comment_notification( $comment ) {
			// Returns false if the comment is marked as spam AND admin has enabled suppression of spam.
			$suppress_spam = get_option( 'bnfw_suppress_spam' );
			if ( '1' === $suppress_spam && ( 0 === strcmp( $comment->comment_approved, 'spam' ) ) ) {
				return false;
			}
			return true;
		}

		/**
		 * Handle user request email content.
		 *
		 * @param string $content Content.
		 * @param array  $email_data Email data.
		 *
		 * @return string Modified content.
		 */
		public function handle_user_request_email_content( $content, $email_data ) {
			$field       = 'message';
			$new_content = '';

			switch ( $email_data['description'] ) {
				case 'Export Personal Data':
					$notification_name = 'ca-export-data';
					$new_content       = $this->handle_user_request_notification( $notification_name, $field, $email_data );
					break;
				case 'Erase Personal Data':
					$notification_name = 'ca-erase-data';
					$new_content       = $this->handle_user_request_notification( $notification_name, $field, $email_data );
					break;
			}

			if ( ! empty( $new_content ) ) {
				return $new_content;
			} else {
				return $content;
			}
		}

		/**
		 * Handle user request email subject.
		 *
		 * @param string $subject    Subject.
		 * @param string $blogname   Blog name.
		 * @param array  $email_data Email data.
		 *
		 * @return string Modified subject.
		 */
		public function handle_user_request_email_subject( $subject, $blogname, $email_data ) {
			$field       = 'subject';
			$new_subject = '';

			switch ( $email_data['description'] ) {
				case 'Export Personal Data':
					$notification_name = 'ca-export-data';
					$new_subject       = $this->handle_user_request_notification( $notification_name, $field, $email_data );
					break;
				case 'Erase Personal Data':
					$notification_name = 'ca-erase-data';
					$new_subject       = $this->handle_user_request_notification( $notification_name, $field, $email_data );
					break;
			}
			if ( ! empty( $new_subject ) ) {
				return $new_subject;
			} else {
				return $subject;
			}
		}

		/**
		 * Handle user confirmed action email content.
		 *
		 * @param string $content    Content.
		 * @param array  $email_data Email data.
		 *
		 * @return string Modified content.
		 */
		public function handle_user_confirmed_action_email_content( $content, $email_data ) {
			$field       = 'message';
			$new_content = '';

			switch ( $email_data['description'] ) {
				case 'Export Personal Data':
					$notification_name = 'uc-export-data';
					$new_content       = $this->handle_user_confirmed_action_notification( $notification_name, $field, $email_data );
					break;
				case 'Erase Personal Data':
					$notification_name = 'uc-erase-data';
					$new_content       = $this->handle_user_confirmed_action_notification( $notification_name, $field, $email_data );
					break;
			}

			if ( ! empty( $new_content ) ) {
				return $new_content;
			} else {
				return $content;
			}
		}

		/**
		 * Handle data exported email content.
		 *
		 * @param string $content Text in the email.
		 * @param int    $request_id The request ID for this personal data export.
		 * @param array  $email_data  Data relating to the account action email.
		 *
		 * @return string Modified content.
		 */
		public function handle_data_export_email_content( $content, $request_id, $email_data ) {

			$field             = 'message';
			$notification_name = 'data-export';
			$new_content       = '';

			$notifications = $this->notifier->get_notifications( $notification_name );
			if ( count( $notifications ) > 0 ) {
				// Ideally there should be only one notification for this type.
				// If there are multiple notification then we will read data about only the last one.
				$setting = $this->notifier->read_settings( end( $notifications )->ID );

				$new_content = $this->engine->handle_data_export_email_shortcodes( $setting[ $field ], $setting, $request_id );
				$new_content = $this->engine->handle_global_user_shortcodes( $new_content, $email_data['message_recipient'] );
			}

			if ( ! empty( $new_content ) ) {
				return $new_content;
			} else {
				return $content;
			}
		}
		/**
		 * Filters the subject of the email sent when an erasure request is completed.
		 *
		 * @param string $subject    The email subject.
		 * @param string $sitename   The name of the site.
		 * @param array  $email_data Data relating to the account action email.
		 */
		public function handle_erasure_complete_email_subject( $subject, $sitename, $email_data ) {
			return $this->handle_erasure_complete_email_notification( 'subject', $subject, $email_data );
		}
		/**
		 * Filters the body of the data erasure fulfillment notification.
		 *
		 * @param string $content The email content.
		 * @param array  $email_data Data relating to the account action email.
		 */
		public function handle_erasure_complete_email_content( $content, $email_data ) {
			if ( isset( $email_data['privacy_policy_url'] ) ) {
				return $this->handle_erasure_complete_email_notification( 'message', $content, $email_data );
			}

			return $content;
		}
		/**
		 * Handles erasure fulfillment notification.
		 *
		 * @param string $field Field name.
		 * @param string $content The email content.
		 * @param array  $email_data Data relating to the account action email.
		 */
		protected function handle_erasure_complete_email_notification( $field, $content, $email_data ) {
			$notification_name = 'data-erased';
			$new_content       = '';
			$notifications     = $this->notifier->get_notifications( $notification_name );
			if ( count( $notifications ) > 0 ) {
				// Ideally there should be only one notification for this type.
				// If there are multiple notification then we will read data about only the last one.
				$setting     = $this->notifier->read_settings( end( $notifications )->ID );
				$new_content = $this->engine->handle_shortcodes( $setting[ $field ], $notification_name, $email_data );
			}
			if ( ! empty( $new_content ) ) {
				return $new_content;
			} else {
				return $content;
			}
		}

		/**
		 * Send notification emails on shutdown.
		 */
		public function on_shutdown() {
			if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
				return;
			}

			$transient = get_transient( 'bnfw-async-notifications' );
			if ( is_array( $transient ) ) {
				delete_transient( 'bnfw-async-notifications' );
				foreach ( $transient as $id_pairs ) {
					$this->engine->send_notification( $this->notifier->read_settings( $id_pairs['notification_id'] ), $id_pairs['ref_id'] );
				}
			}
		}

		/**
		 * Handle user request notification.
		 *
		 * @param string $notification_name Notification name.
		 * @param string $field             Field name.
		 * @param array  $email_data        Email data.
		 *
		 * @return string Content.
		 */
		protected function handle_user_request_notification( $notification_name, $field, $email_data ) {
			$notifications = $this->notifier->get_notifications( $notification_name );
			if ( count( $notifications ) > 0 ) {
				// Ideally there should be only one notification for this type.
				// If there are multiple notification then we will read data about only the last one.
				$setting = $this->notifier->read_settings( end( $notifications )->ID );

				return $this->engine->handle_user_request_email_shortcodes( $setting[ $field ], $setting, $email_data );
			}

			return '';
		}

		/**
		 * Handle user confirmed action notification.
		 *
		 * @param string $notification_name Notification name.
		 * @param string $field             Field name.
		 * @param array  $email_data        Email data.
		 *
		 * @return string Content.
		 */
		protected function handle_user_confirmed_action_notification( $notification_name, $field, $email_data ) {
			$notifications = $this->notifier->get_notifications( $notification_name );
			if ( count( $notifications ) > 0 ) {
				// Ideally there should be only one notification for this type.
				// If there are multiple notification then we will read data about only the last one.
				$setting = $this->notifier->read_settings( end( $notifications )->ID );

				return $this->engine->handle_user_confirmed_action_email_shortcodes( $setting[ $field ], $setting, $email_data );
			}

			return '';
		}

		/**
		 * Is this a metabox request?
		 *
		 * Block editor sends duplicate requests on post update.
		 *
		 * @return bool True if metabox request, False otherwise.
		 */
		protected function is_metabox_request() {
			return ( isset( $_GET['meta-box-loader'] ) || isset( $_GET['meta_box'] ) );
		}

		/**
		 * Check if Gutenberg is active.
		 *
		 * @return bool
		 * @since 1.3
		 */
		public function is_gutenberg_active() {
			$gutenberg    = false;
			$block_editor = false;

			if ( has_filter( 'replace_editor', 'gutenberg_init' ) ) {
				// Gutenberg is installed and activated.
				$gutenberg = true;
			}

			if ( version_compare( $GLOBALS['wp_version'], '5.0-beta', '>' ) ) {
				// Block editor.
				$block_editor = true;
			}

			if ( ! $gutenberg && ! $block_editor ) {
				return false;
			}

			include_once ABSPATH . 'wp-admin/includes/plugin.php';

			if ( ! is_plugin_active( 'classic-editor/classic-editor.php' ) ) {
				return true;
			}

			$use_block_editor = ( get_option( 'classic-editor-replace' ) === 'no-replace' );

			return $use_block_editor;
		}

	}
	/**
	 * Fire up the plugin.
	 */
	BNFW::factory();
}
Page Not Found
Parece que el enlace que apuntaba aquí no sirve. ¿Quieres probar con una búsqueda?
¡Hola!