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

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