PluginProbe
Customize WordPress Emails and Alerts – Better Notifications for WP / 1.6.6
Customize WordPress Emails and Alerts – Better Notifications for WP v1.6.6
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 1.6.6, at bnfw.php

721 lines 21.3 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 WordPress
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.6.6
7 * Author: Made with Fuel
8 * Author URI: https://betternotificationsforwp.com/
9 * Author Email: hello@betternotificationsforwp.com
10 * License: GPLv2 or later
11 * License URI: http://www.gnu.org/licenses/gpl-2.0.html
12 * Text Domain: bnfw
13 * Domain Path: /languages
14 */
15
16 /**
17 * Copyright © 2017 Made with Fuel Ltd. (hello@betternotificationsforwp.com)
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License, version 2, as
20 * published by the Free Software Foundation.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 */
29 class BNFW {
30
31 /**
32 * Constructor.
33 *
34 * @since 1.0
35 */
36 function __construct() {
37 $this->load_textdomain();
38 $this->includes();
39 $this->hooks();
40
41 /**
42 * BNFW Notification.
43 *
44 * @var \BNFW_Notification
45 */
46 $this->notifier = new BNFW_Notification;
47
48 /**
49 * BNFW Engine.
50 *
51 * @var \BNFW_Engine
52 */
53 $this->engine = new BNFW_Engine;
54 }
55
56 /**
57 * Factory method to return the instance of the class.
58 *
59 * Makes sure that only one instance is created.
60 *
61 * @return \BNFW Instance of the class.
62 */
63 public static function factory() {
64 static $instance = false;
65 if ( ! $instance ) {
66 $instance = new self();
67 }
68 return $instance;
69 }
70
71 /**
72 * Loads the plugin language files
73 *
74 * @since 1.0
75 */
76 public function load_textdomain() {
77 // Load localization domain
78 $this->translations = dirname( plugin_basename( __FILE__ ) ) . '/languages/';
79 load_plugin_textdomain( 'bnfw', false, $this->translations );
80 }
81
82 /**
83 * Include required files.
84 *
85 * @since 1.0
86 */
87 public function includes() {
88
89 // Load license related classes
90 if ( ! class_exists( 'EDD_SL_Plugin_Updater' ) ) {
91 require_once 'includes/libraries/EDD_SL_Plugin_Updater.php';
92 }
93 require_once 'includes/license/class-bnfw-license.php';
94 require_once 'includes/license/class-bnfw-license-setting.php';
95
96 // Load Engine
97 require_once 'includes/engine/class-bnfw-engine.php';
98 require_once 'includes/overrides.php';
99
100 // Load notification post type and notification helpers
101 require_once 'includes/admin/class-bnfw-notification.php';
102 require_once 'includes/notification/post-notification.php';
103
104 // Helpers
105 require_once 'includes/helpers/helpers.php';
106 require_once 'includes/helpers/ajax-helpers.php';
107
108 // Load Admin Pages
109 if ( is_admin() ) {
110 require_once 'includes/admin/bnfw-settings.php';
111 }
112 }
113
114 /**
115 * Register Hooks.
116 *
117 * @since 1.0
118 */
119 public function hooks() {
120 global $wp_version;
121
122 register_activation_hook( __FILE__, array( $this, 'activate' ) );
123
124 add_action( 'draft_to_private' , array( $this, 'private_post' ) );
125 add_action( 'future_to_private' , array( $this, 'private_post' ) );
126 add_action( 'pending_to_private' , array( $this, 'private_post' ) );
127 add_action( 'publish_to_private' , array( $this, 'private_post' ) );
128
129 add_action( 'wp_insert_post' , array( $this, 'insert_post' ), 10, 2 );
130
131 add_action( 'draft_to_publish' , array( $this, 'publish_post' ) );
132 add_action( 'future_to_publish' , array( $this, 'publish_post' ) );
133 add_action( 'pending_to_publish' , array( $this, 'publish_post' ) );
134 add_action( 'private_to_publish' , array( $this, 'publish_post' ) );
135 add_action( 'acf/submit_form' , array( $this, 'acf_submit_form' ), 10, 2 );
136
137 add_action( 'publish_to_publish' , array( $this, 'update_post' ) );
138
139 add_action( 'init' , array( $this, 'custom_post_type_hooks' ), 100 );
140 add_action( 'create_term' , array( $this, 'create_term' ), 10, 3 );
141
142 add_action( 'comment_post' , array( $this, 'comment_post' ) );
143 add_action( 'trackback_post' , array( $this, 'trackback_post' ) );
144 add_action( 'pingback_post' , array( $this, 'pingback_post' ) );
145
146 add_action( 'user_register' , array( $this, 'user_register' ) );
147 add_action( 'user_register' , array( $this, 'welcome_email' ) );
148 add_action( 'set_user_role' , array( $this, 'user_role_changed' ), 10, 3 );
149
150 if ( version_compare( $wp_version, '4.4', '>=' ) ) {
151 add_filter( 'retrieve_password_title', array( $this, 'change_password_email_title' ), 10, 3 );
152 } else {
153 add_filter( 'retrieve_password_title', array( $this, 'change_password_email_title' ) );
154 }
155 add_action( 'lostpassword_post' , array( $this, 'on_lost_password' ) );
156 add_filter( 'retrieve_password_message' , array( $this, 'change_password_email_message' ), 10, 4 );
157
158 add_action( 'after_password_reset' , array( $this, 'on_password_reset' ) );
159 add_filter( 'password_change_email' , array( $this, 'on_password_changed' ), 10, 2 );
160 add_filter( 'email_change_email' , array( $this, 'on_email_changed' ), 10, 2 );
161
162 add_filter( 'auto_core_update_email' , array( $this, 'on_core_updated' ), 10, 4 );
163
164 add_filter( 'plugin_action_links' , array( $this, 'plugin_action_links' ), 10, 4 );
165 add_action( 'shutdown' , array( $this, 'on_shutdown' ) );
166 }
167
168 /**
169 * Setup hooks for custom post types.
170 *
171 * @since 1.2
172 */
173 function custom_post_type_hooks() {
174 $post_types = get_post_types( array( 'public' => true ), 'names' );
175 $post_types = array_diff( $post_types, array( BNFW_Notification::POST_TYPE ) );
176
177 foreach ( $post_types as $post_type ) {
178 add_action( 'pending_' . $post_type, array( $this, 'on_post_pending' ), 10, 2 );
179 add_action( 'future_' . $post_type, array( $this, 'on_post_scheduled' ), 10, 2 );
180 }
181 }
182
183 /**
184 * importer
185 */
186 public function activate() {
187 require_once dirname( __FILE__ ) . '/includes/import.php';
188 $importer = new BNFW_Import;
189 $importer->import();
190 }
191
192 /**
193 * Add 'Settings' link below BNFW in Plugins list.
194 *
195 * @since 1.0
196 * @param unknown $links
197 * @param unknown $file
198 * @return unknown
199 */
200 public function plugin_action_links( $links, $file ) {
201 $plugin_file = 'bnfw/bnfw.php';
202 if ( $file == $plugin_file ) {
203 $settings_link = '<a href="' . esc_url( admin_url( 'edit.php?post_type=bnfw_notification&page=bnfw-settings' ) ) . '">' . esc_html__( 'Settings', 'bnfw' ) . '</a>';
204 array_unshift( $links, $settings_link );
205 }
206 return $links;
207 }
208
209 /**
210 * When a new term is created.
211 *
212 * @since 1.0
213 * @param int $term_id
214 * @param int $tt_id
215 * @param string $taxonomy
216 */
217 public function create_term( $term_id, $tt_id, $taxonomy ) {
218 $this->send_notification( 'newterm-' . $taxonomy, $term_id );
219 }
220
221 /**
222 * Fires when a post is created for the first time.
223 *
224 * @since 1.3.1
225 * @param int $post_id Post ID
226 * @param object $post Post object
227 */
228 public function insert_post( $post_id, $post ) {
229 // Some themes like P2, directly insert posts into DB.
230 $insert_post_themes = apply_filters( 'bnfw_insert_post_themes', array( 'P2', 'Syncope' ) );
231 $current_theme = wp_get_theme();
232
233 /**
234 * Whether to trigger insert post hook.
235 *
236 * @since 1.4
237 */
238 $trigger_insert_post = apply_filters( 'bnfw_trigger_insert_post', false );
239
240 if ( in_array( $current_theme->get( 'Name' ), $insert_post_themes ) || $trigger_insert_post ) {
241 $this->publish_post( $post );
242 }
243 }
244
245 /**
246 * Trigger New Post published notification for ACF forms.
247 *
248 * @param string $form ACF Form.
249 * @param int $post_id Post ID.
250 */
251 public function acf_submit_form( $form, $post_id ) {
252 $this->publish_post( get_post( $post_id ) );
253 }
254
255 /**
256 * Fires when a post is created for the first time.
257 *
258 * @since 1.0
259 * @param object $post Post Object
260 */
261 function publish_post( $post ) {
262 $post_id = $post->ID;
263 $post_type = $post->post_type;
264
265 if ( BNFW_Notification::POST_TYPE != $post_type ) {
266 $this->send_notification_async( 'new-' . $post_type, $post_id );
267 }
268 }
269
270 /**
271 * Fires when a private post is created.
272 *
273 * @since 1.6
274 * @param object $post Post Object
275 */
276 public function private_post( $post ) {
277 $post_id = $post->ID;
278 $post_type = $post->post_type;
279
280 if ( BNFW_Notification::POST_TYPE != $post_type ) {
281 $this->send_notification_async( 'private-' . $post_type, $post_id );
282 }
283 }
284
285 /**
286 * Fires when a post is updated.
287 *
288 * @since 1.0
289 * @param unknown $post
290 */
291 function update_post( $post ) {
292 $post_id = $post->ID;
293 $post_type = $post->post_type;
294
295 if ( BNFW_Notification::POST_TYPE != $post_type ) {
296 $this->send_notification_async( 'update-' . $post_type, $post_id );
297 }
298 }
299
300 /**
301 * Fires when a post is pending for review.
302 *
303 * @since 1.1
304 * @param int $post_id Post ID
305 * @param object $post Post object
306 */
307 function on_post_pending( $post_id, $post ) {
308 $post_type = $post->post_type;
309
310 if ( BNFW_Notification::POST_TYPE != $post_type ) {
311 $this->send_notification_async( 'pending-' . $post_type, $post_id );
312 }
313 }
314
315 /**
316 * Fires when a post is scheduled.
317 *
318 * @since 1.1.5
319 * @param int $post_id Post ID
320 * @param object $post Post object
321 */
322 function on_post_scheduled( $post_id, $post ) {
323 $post_type = $post->post_type;
324
325 if ( BNFW_Notification::POST_TYPE != $post_type ) {
326 $this->send_notification_async( 'future-' . $post_type, $post_id );
327 }
328 }
329
330 /**
331 * Send notification for new comments
332 *
333 * @since 1.0
334 * @param int $comment_id
335 */
336 function comment_post( $comment_id ) {
337 $the_comment = get_comment( $comment_id );
338 if ( $this->can_send_comment_notification( $the_comment ) ) {
339 $post = get_post( $the_comment->comment_post_ID );
340 $notification_type = 'new-comment'; // old notification name
341 if ( 'post' != $post->post_type ) {
342 $notification_type = 'comment-' . $post->post_type;
343 }
344 $this->send_notification( $notification_type, $comment_id );
345
346 // comment reply notification.
347 if ( $the_comment->comment_parent > 0 ) {
348 $notification_type = 'reply-comment'; // old notification name
349 if ( 'post' != $post->post_type ) {
350 $notification_type = 'commentreply-' . $post->post_type;
351 }
352 $notifications = $this->notifier->get_notifications( $notification_type );
353 if ( count( $notifications ) > 0 ) {
354 $parent = get_comment( $the_comment->comment_parent );
355 if ( $parent->comment_author_email != $the_comment->comment_author_email ) {
356 foreach ( $notifications as $notification ) {
357 $this->engine->send_comment_reply_email( $this->notifier->read_settings( $notification->ID ), $the_comment, $parent );
358 }
359 }
360 }
361 }
362 }
363 }
364
365 /**
366 * Send notification for new trackback
367 *
368 * @since 1.0
369 * @param unknown $comment_id
370 */
371 function trackback_post( $comment_id ) {
372 $the_comment = get_comment( $comment_id );
373 if ( $this->can_send_comment_notification( $the_comment ) ) {
374 $this->send_notification( 'new-trackback', $comment_id );
375 }
376 }
377
378 /**
379 * Send notification for new pingbacks
380 *
381 * @since 1.0
382 * @param unknown $comment_id
383 */
384 function pingback_post( $comment_id ) {
385 $the_comment = get_comment( $comment_id );
386 if ( $this->can_send_comment_notification( $the_comment ) ) {
387 $this->send_notification( 'new-pingback', $comment_id );
388 }
389 }
390
391 /**
392 * Send notification for lost password.
393 *
394 * @since 1.0
395 */
396 function on_lost_password() {
397 $user_login = sanitize_text_field( $_POST['user_login'] );
398 $user = get_user_by( 'login', $user_login );
399 if ( $user ) {
400 $this->send_notification( 'admin-password', $user->ID );
401 }
402 }
403
404 /**
405 * Change the title of the password reset email that is sent to the user.
406 *
407 * @since 1.1
408 *
409 * @param string $title
410 * @param string $user_login
411 * @param string $user_data
412 *
413 * @return string
414 */
415 public function change_password_email_title( $title, $user_login = '', $user_data = '' ) {
416 $notifications = $this->notifier->get_notifications( 'user-password' );
417 if ( count( $notifications ) > 0 ) {
418 // Ideally there should be only one notification for this type.
419 // If there are multiple notification then we will read data about only the last one
420 $setting = $this->notifier->read_settings( end( $notifications )->ID );
421
422 if ( '' === $user_data ) {
423 return $this->engine->handle_shortcodes( $setting['subject'], 'user-password', $user_data->ID );
424 } else {
425 return $setting['subject'];
426 }
427 }
428
429 return $title;
430 }
431
432 /**
433 * Change the message of the password reset email.
434 *
435 * @since 1.1
436 *
437 * @param string $message
438 * @param string $key
439 * @param string $user_login
440 * @param string $user_data
441 *
442 * @return string
443 */
444 public function change_password_email_message( $message, $key, $user_login = '', $user_data = '' ) {
445 $notifications = $this->notifier->get_notifications( 'user-password' );
446 if ( count( $notifications ) > 0 ) {
447 // Ideally there should be only one notification for this type.
448 // If there are multiple notification then we will read data about only the last one
449 $setting = $this->notifier->read_settings( end( $notifications )->ID );
450
451 $message = $this->engine->handle_password_reset_shortcodes( $setting, $key, $user_login, $user_data );
452
453 if ( 'html' == $setting['email-formatting'] ) {
454 add_filter( 'wp_mail_content_type', array( $this, 'set_html_content_type' ) );
455 $message = wpautop( $message );
456 } else {
457 add_filter( 'wp_mail_content_type', array( $this, 'set_text_content_type' ) );
458 }
459 } else {
460 if ( $this->notifier->notification_exists( 'user-password', false ) ) {
461 // disabled notification exists, so disable the email by returning empty string.
462 return '';
463 }
464 }
465
466 return $message;
467 }
468
469 /**
470 * On Password reset.
471 *
472 * @param WP_User $user User who's password was changed.
473 */
474 public function on_password_reset( $user ) {
475 $notifications = $this->notifier->get_notifications( 'password-changed' );
476 foreach ( $notifications as $notification ) {
477 $this->engine->send_password_changed_email( $this->notifier->read_settings( $notification->ID ), $user );
478 }
479 }
480
481 /**
482 * On Password Changed.
483 *
484 * @since 1.6
485 *
486 * @param array $email_data Email Data.
487 * @param array $user User data.
488 *
489 * @return array Modified Email Data
490 */
491 public function on_password_changed( $email_data, $user ) {
492 return $this->handle_filtered_data_notification( 'password-changed', $email_data, $user['ID'] );
493 }
494
495 /**
496 * On Email Changed.
497 *
498 * @since 1.6
499 *
500 * @param array $email_data Email Data.
501 * @param array $user User data.
502 *
503 * @return array Modified Email Data
504 */
505 public function on_email_changed( $email_data, $user ) {
506 return $this->handle_filtered_data_notification( 'email-changed', $email_data, $user['ID'] );
507 }
508
509 /**
510 * Send notification on core updated event.
511 *
512 * @since 1.6
513 *
514 * @param array $email_data Email Data.
515 * @param string $type The type of email being sent. Can be one of
516 * 'success', 'fail', 'manual', 'critical'.
517 * @param object $core_update The update offer that was attempted.
518 * @param mixed $result The result for the core update. Can be WP_Error.
519 *
520 * @return array Modified Email Data.
521 */
522 public function on_core_updated( $email_data, $type, $core_update, $result ) {
523 $notifications = $this->notifier->get_notifications( 'core-updated' );
524 if ( count( $notifications ) > 0 ) {
525 // Ideally there should be only one notification for this type.
526 // If there are multiple notification then we will read data about only the last one
527 $setting = $this->notifier->read_settings( end( $notifications )->ID );
528
529 $email_data = $this->engine->handle_core_updated_notification( $email_data, $setting, $type );
530 }
531
532 return $email_data;
533 }
534
535 /**
536 * Process User update notifications.
537 *
538 * @since 1.6
539 *
540 * @param string $notification_name Notification Name.
541 * @param array $email_data Email Data.
542 * @param string|int $extra_data User Id.
543 *
544 * @return array Modified Email Data.
545 */
546 private function handle_filtered_data_notification( $notification_name, $email_data, $extra_data ) {
547 $notifications = $this->notifier->get_notifications( $notification_name );
548 if ( count( $notifications ) > 0 ) {
549 // Ideally there should be only one notification for this type.
550 // If there are multiple notification then we will read data about only the last one
551 $setting = $this->notifier->read_settings( end( $notifications )->ID );
552
553 $email_data = $this->engine->handle_filtered_data_notification( $email_data, $setting, $extra_data );
554 }
555
556 return $email_data;
557 }
558
559 /**
560 * Set the email formatting to HTML.
561 *
562 * @since 1.4
563 */
564 public function set_html_content_type() {
565 return 'text/html';
566 }
567
568 /**
569 * Set the email formatting to text.
570 *
571 * @since 1.4
572 */
573 public function set_text_content_type() {
574 return 'text/plain';
575 }
576
577 /**
578 * Send notification for new users.
579 *
580 * @since 1.0
581 * @param int $user_id
582 */
583 function user_register( $user_id ) {
584 $this->send_notification( 'admin-user', $user_id );
585 }
586
587 /**
588 * New User - Post-registration Email
589 *
590 * @since 1.1
591 * @param int $user_id New user id
592 */
593 public function welcome_email( $user_id ) {
594 $notifications = $this->notifier->get_notifications( 'welcome-email' );
595 foreach ( $notifications as $notification ) {
596 $this->engine->send_registration_email( $this->notifier->read_settings( $notification->ID ), get_userdata( $user_id ) );
597 }
598 }
599
600 /**
601 * Send notification when a user role changes.
602 *
603 * @since 1.3.9
604 *
605 * @param int $user_id User ID
606 * @param string $new_role New User role
607 * @param array $old_roles Old User role
608 */
609 public function user_role_changed( $user_id, $new_role, $old_roles ) {
610 if ( ! empty( $old_roles ) ) {
611 $notifications = $this->notifier->get_notifications( 'user-role' );
612 foreach ( $notifications as $notification ) {
613
614 /**
615 * Trigger User Role Changed - For User notification.
616 *
617 * @since 1.6.5
618 */
619 if ( apply_filters( 'bnfw_trigger_user-role_notification', true, $notification, $new_role, $old_roles ) ) {
620 $this->engine->send_user_role_changed_email(
621 $this->notifier->read_settings( $notification->ID ),
622 $user_id,
623 $old_roles[0],
624 $new_role
625 );
626 }
627 }
628
629 $notifications = $this->notifier->get_notifications( 'admin-role' );
630 foreach ( $notifications as $notification ) {
631
632 /**
633 * Trigger User Role Changed - For User notification.
634 *
635 * @since 1.6.5
636 */
637 if ( apply_filters( 'bnfw_trigger_admin-role_notification', true, $notification, $new_role, $old_roles ) ) {
638 $setting = $this->notifier->read_settings( $notification->ID );
639 $setting['message'] = $this->engine->handle_user_role_shortcodes( $setting['message'], $old_roles[0], $new_role );
640 $setting['subject'] = $this->engine->handle_user_role_shortcodes( $setting['subject'], $old_roles[0], $new_role );
641
642 $this->engine->send_notification( $setting, $user_id );
643 }
644 }
645 }
646 }
647
648 /**
649 * Send notification based on type and ref id
650 *
651 * @access private
652 * @since 1.0
653 * @param string $type Notification type.
654 * @param int $ref_id Reference id.
655 */
656 private function send_notification( $type, $ref_id ) {
657 $notifications = $this->notifier->get_notifications( $type );
658 foreach ( $notifications as $notification ) {
659 $this->engine->send_notification( $this->notifier->read_settings( $notification->ID ), $ref_id );
660 }
661 }
662
663 /**
664 * Send notification async based on type and ref id.
665 *
666 * @access private
667 * @param string $type Notification type.
668 * @param int $ref_id Reference id.
669 */
670 private function send_notification_async( $type, $ref_id ) {
671 $notifications = $this->notifier->get_notifications( $type, false );
672 foreach ( $notifications as $notification ) {
673 $transient = get_transient( 'bnfw-async-notifications' );
674 if ( ! is_array( $transient ) ) {
675 $transient = array();
676 }
677
678 $transient[] = array( 'ref_id' => $ref_id, 'notification_id' => $notification->ID, 'notification_type' => $type );
679 set_transient( 'bnfw-async-notifications', $transient, 600 );
680 }
681 }
682
683 /**
684 * Can send comment notification or not
685 *
686 * @since 1.0
687 * @param unknown $comment
688 * @return unknown
689 */
690 private function can_send_comment_notification( $comment ) {
691 // Returns false if the comment is marked as spam AND admin has enabled suppression of spam
692 $suppress_spam = get_option( 'bnfw_suppress_spam' );
693 if ( '1' === $suppress_spam && ( 0 === strcmp( $comment->comment_approved, 'spam' ) ) ) {
694 return false;
695 }
696 return true;
697 }
698
699 /**
700 * Send notification emails on shutdown.
701 */
702 public function on_shutdown() {
703 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
704 return;
705 }
706
707 $transient = get_transient( 'bnfw-async-notifications' );
708 if ( is_array( $transient ) ) {
709 delete_transient( 'bnfw-async-notifications' );
710 foreach ( $transient as $id_pairs ) {
711 $this->engine->send_notification( $this->notifier->read_settings( $id_pairs['notification_id'] ), $id_pairs['ref_id'] );
712 }
713 }
714 }
715 }
716
717 /* ------------------------------------------------------------------------ *
718 * Fire up the plugin
719 * ------------------------------------------------------------------------ */
720 BNFW::factory();
721