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

657 lines 19.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: Send customisable emails to your users for different WordPress notifications.
6 * Version: 1.6
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 Voltronik (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_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 * @param bool $update Whether it was an update
228 */
229 public function insert_post( $post_id, $post, $update ) {
230 $this->publish_post( $post );
231 }
232
233 /**
234 * Fires when a post is created for the first time.
235 *
236 * @since 1.0
237 * @param object $post Post Object
238 */
239 function publish_post( $post ) {
240 $post_id = $post->ID;
241 $post_type = $post->post_type;
242
243 if ( BNFW_Notification::POST_TYPE != $post_type ) {
244 $this->send_notification_async( 'new-' . $post_type, $post_id );
245 }
246 }
247
248 /**
249 * Fires when a private post is created.
250 *
251 * @since 1.6
252 * @param object $post Post Object
253 */
254 public function private_post( $post ) {
255 $post_id = $post->ID;
256 $post_type = $post->post_type;
257
258 if ( BNFW_Notification::POST_TYPE != $post_type ) {
259 $this->send_notification_async( 'private-' . $post_type, $post_id );
260 }
261 }
262
263 /**
264 * Fires when a post is updated.
265 *
266 * @since 1.0
267 * @param unknown $post
268 */
269 function update_post( $post ) {
270 $post_id = $post->ID;
271 $post_type = $post->post_type;
272
273 if ( BNFW_Notification::POST_TYPE != $post_type ) {
274 $this->send_notification_async( 'update-' . $post_type, $post_id );
275 }
276 }
277
278 /**
279 * Fires when a post is pending for review.
280 *
281 * @since 1.1
282 * @param int $post_id Post ID
283 * @param object $post Post object
284 */
285 function on_post_pending( $post_id, $post ) {
286 $post_type = $post->post_type;
287
288 if ( BNFW_Notification::POST_TYPE != $post_type ) {
289 $this->send_notification_async( 'pending-' . $post_type, $post_id );
290 }
291 }
292
293 /**
294 * Fires when a post is scheduled.
295 *
296 * @since 1.1.5
297 * @param int $post_id Post ID
298 * @param object $post Post object
299 */
300 function on_post_scheduled( $post_id, $post ) {
301 $post_type = $post->post_type;
302
303 if ( BNFW_Notification::POST_TYPE != $post_type ) {
304 $this->send_notification_async( 'future-' . $post_type, $post_id );
305 }
306 }
307
308 /**
309 * Send notification for new comments
310 *
311 * @since 1.0
312 * @param int $comment_id
313 */
314 function comment_post( $comment_id ) {
315 $the_comment = get_comment( $comment_id );
316 if ( $this->can_send_comment_notification( $the_comment ) ) {
317 $post = get_post( $the_comment->comment_post_ID );
318 $notification_type = 'new-comment'; // old notification name
319 if ( 'post' != $post->post_type ) {
320 $notification_type = 'comment-' . $post->post_type;
321 }
322 $this->send_notification( $notification_type, $comment_id );
323
324 // comment reply notification.
325 if ( $the_comment->comment_parent > 0 ) {
326 $notification_type = 'reply-comment'; // old notification name
327 if ( 'post' != $post->post_type ) {
328 $notification_type = 'commentreply-' . $post->post_type;
329 }
330 $notifications = $this->notifier->get_notifications( $notification_type );
331 if ( count( $notifications ) > 0 ) {
332 $parent = get_comment( $the_comment->comment_parent );
333 if ( $parent->comment_author_email != $the_comment->comment_author_email ) {
334 foreach ( $notifications as $notification ) {
335 $this->engine->send_comment_reply_email( $this->notifier->read_settings( $notification->ID ), $the_comment, $parent );
336 }
337 }
338 }
339 }
340 }
341 }
342
343 /**
344 * Send notification for new trackback
345 *
346 * @since 1.0
347 * @param unknown $comment_id
348 */
349 function trackback_post( $comment_id ) {
350 $the_comment = get_comment( $comment_id );
351 if ( $this->can_send_comment_notification( $the_comment ) ) {
352 $this->send_notification( 'new-trackback', $comment_id );
353 }
354 }
355
356 /**
357 * Send notification for new pingbacks
358 *
359 * @since 1.0
360 * @param unknown $comment_id
361 */
362 function pingback_post( $comment_id ) {
363 $the_comment = get_comment( $comment_id );
364 if ( $this->can_send_comment_notification( $the_comment ) ) {
365 $this->send_notification( 'new-pingback', $comment_id );
366 }
367 }
368
369 /**
370 * Send notification for lost password.
371 *
372 * @since 1.0
373 */
374 function on_lost_password() {
375 $user_login = sanitize_text_field( $_POST['user_login'] );
376 $user = get_user_by( 'login', $user_login );
377 if ( $user ) {
378 $this->send_notification( 'admin-password', $user->ID );
379 }
380 }
381
382 /**
383 * Change the title of the password reset email that is sent to the user.
384 *
385 * @since 1.1
386 *
387 * @param string $title
388 * @param string $user_login
389 * @param string $user_data
390 *
391 * @return string
392 */
393 public function change_password_email_title( $title, $user_login = '', $user_data = '' ) {
394 $notifications = $this->notifier->get_notifications( 'user-password' );
395 if ( count( $notifications ) > 0 ) {
396 // Ideally there should be only one notification for this type.
397 // If there are multiple notification then we will read data about only the last one
398 $setting = $this->notifier->read_settings( end( $notifications )->ID );
399
400 if ( '' === $user_data ) {
401 return $this->engine->handle_shortcodes( $setting['subject'], 'user-password', $user_data->ID );
402 } else {
403 return $setting['subject'];
404 }
405 }
406
407 return $title;
408 }
409
410 /**
411 * Change the message of the password reset email.
412 *
413 * @since 1.1
414 *
415 * @param string $message
416 * @param string $key
417 * @param string $user_login
418 * @param string $user_data
419 *
420 * @return string
421 */
422 public function change_password_email_message( $message, $key, $user_login = '', $user_data = '' ) {
423 $notifications = $this->notifier->get_notifications( 'user-password' );
424 if ( count( $notifications ) > 0 ) {
425 // Ideally there should be only one notification for this type.
426 // If there are multiple notification then we will read data about only the last one
427 $setting = $this->notifier->read_settings( end( $notifications )->ID );
428
429 $message = $this->engine->handle_password_reset_shortcodes( $setting, $key, $user_login, $user_data );
430
431 if ( 'html' == $setting['email-formatting'] ) {
432 add_filter( 'wp_mail_content_type', array( $this, 'set_html_content_type' ) );
433 $message = wpautop( $message );
434 } else {
435 add_filter( 'wp_mail_content_type', array( $this, 'set_text_content_type' ) );
436 }
437 }
438
439 return $message;
440 }
441
442 /**
443 * On Password Changed.
444 *
445 * @since 1.6
446 *
447 * @param array $email_data Email Data.
448 * @param array $user User data.
449 *
450 * @return array Modified Email Data
451 */
452 public function on_password_changed( $email_data, $user ) {
453 return $this->handle_filtered_data_notification( 'password-changed', $email_data, $user['ID'] );
454 }
455
456 /**
457 * On Email Changed.
458 *
459 * @since 1.6
460 *
461 * @param array $email_data Email Data.
462 * @param array $user User data.
463 *
464 * @return array Modified Email Data
465 */
466 public function on_email_changed( $email_data, $user ) {
467 return $this->handle_filtered_data_notification( 'email-changed', $email_data, $user['ID'] );
468 }
469
470 /**
471 * Send notification on core updated event.
472 *
473 * @since 1.6
474 *
475 * @param array $email_data Email Data.
476 * @param string $type The type of email being sent. Can be one of
477 * 'success', 'fail', 'manual', 'critical'.
478 * @param object $core_update The update offer that was attempted.
479 * @param mixed $result The result for the core update. Can be WP_Error.
480 *
481 * @return array Modified Email Data.
482 */
483 public function on_core_updated( $email_data, $type, $core_update, $result ) {
484 return $this->handle_filtered_data_notification( 'core-updated', $email_data, $type );
485 }
486
487 /**
488 * Process User update notifications.
489 *
490 * @since 1.6
491 *
492 * @param string $notification_name Notification Name.
493 * @param array $email_data Email Data.
494 * @param string|int $extra_data User Id.
495 *
496 * @return array Modified Email Data.
497 */
498 private function handle_filtered_data_notification( $notification_name, $email_data, $extra_data ) {
499 $notifications = $this->notifier->get_notifications( $notification_name );
500 if ( count( $notifications ) > 0 ) {
501 // Ideally there should be only one notification for this type.
502 // If there are multiple notification then we will read data about only the last one
503 $setting = $this->notifier->read_settings( end( $notifications )->ID );
504
505 $email_data = $this->engine->handle_filtered_data_notification( $email_data, $setting, $extra_data );
506 }
507
508 return $email_data;
509 }
510
511 /**
512 * Set the email formatting to HTML.
513 *
514 * @since 1.4
515 */
516 public function set_html_content_type() {
517 return 'text/html';
518 }
519
520 /**
521 * Set the email formatting to text.
522 *
523 * @since 1.4
524 */
525 public function set_text_content_type() {
526 return 'text/plain';
527 }
528
529 /**
530 * Send notification for new users.
531 *
532 * @since 1.0
533 * @param int $user_id
534 */
535 function user_register( $user_id ) {
536 $this->send_notification( 'admin-user', $user_id );
537 }
538
539 /**
540 * New User - Post-registration Email
541 *
542 * @since 1.1
543 * @param int $user_id New user id
544 */
545 function welcome_email( $user_id ) {
546 $notifications = $this->notifier->get_notifications( 'welcome-email' );
547 foreach ( $notifications as $notification ) {
548 $this->engine->send_registration_email( $this->notifier->read_settings( $notification->ID ), get_userdata( $user_id ) );
549 }
550 }
551
552 /**
553 * Send notification when a user role changes.
554 *
555 * @since 1.3.9
556 *
557 * @param int $user_id User ID
558 * @param string $new_role New User role
559 * @param array $old_role Old User role
560 */
561 public function user_role_changed( $user_id, $new_role, $old_role ) {
562 if ( ! empty( $old_role ) ) {
563 $notifications = $this->notifier->get_notifications( 'user-role' );
564 foreach ( $notifications as $notification ) {
565 $this->engine->send_user_role_changed_email(
566 $this->notifier->read_settings( $notification->ID ),
567 $user_id,
568 $old_role[0],
569 $new_role
570 );
571 }
572
573 $notifications = $this->notifier->get_notifications( 'admin-role' );
574 foreach ( $notifications as $notification ) {
575 $setting = $this->notifier->read_settings( $notification->ID );
576 $setting['message'] = $this->engine->handle_user_role_shortcodes( $setting['message'], $old_role[0], $new_role );
577 $setting['subject'] = $this->engine->handle_user_role_shortcodes( $setting['subject'], $old_role[0], $new_role );
578
579 $this->engine->send_notification( $setting , $user_id );
580 }
581 }
582 }
583
584 /**
585 * Send notification based on type and ref id
586 *
587 * @access private
588 * @since 1.0
589 * @param string $type Notification type.
590 * @param int $ref_id Reference id.
591 */
592 private function send_notification( $type, $ref_id ) {
593 $notifications = $this->notifier->get_notifications( $type );
594 foreach ( $notifications as $notification ) {
595 $this->engine->send_notification( $this->notifier->read_settings( $notification->ID ), $ref_id );
596 }
597 }
598
599 /**
600 * Send notification async based on type and ref id.
601 *
602 * @access private
603 * @param string $type Notification type.
604 * @param int $ref_id Reference id.
605 */
606 private function send_notification_async( $type, $ref_id ) {
607 $notifications = $this->notifier->get_notifications( $type );
608 foreach ( $notifications as $notification ) {
609 $transient = get_transient( 'bnfw-async-notifications' );
610 if ( ! is_array( $transient ) ) {
611 $transient = array();
612 }
613
614 $transient[] = array( 'ref_id' => $ref_id, 'notification_id' => $notification->ID, 'notification_type' => $type );
615 set_transient( 'bnfw-async-notifications', $transient, 600 );
616 }
617 }
618
619 /**
620 * Can send comment notification or not
621 *
622 * @since 1.0
623 * @param unknown $comment
624 * @return unknown
625 */
626 private function can_send_comment_notification( $comment ) {
627 // Returns false if the comment is marked as spam AND admin has enabled suppression of spam
628 $suppress_spam = get_option( 'bnfw_suppress_spam' );
629 if ( '1' === $suppress_spam && ( 0 === strcmp( $comment->comment_approved, 'spam' ) ) ) {
630 return false;
631 }
632 return true;
633 }
634
635 /**
636 * Send notification emails on shutdown.
637 */
638 public function on_shutdown() {
639 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
640 return;
641 }
642
643 $transient = get_transient( 'bnfw-async-notifications' );
644 if ( is_array( $transient ) ) {
645 delete_transient( 'bnfw-async-notifications' );
646 foreach ( $transient as $id_pairs ) {
647 $this->engine->send_notification( $this->notifier->read_settings( $id_pairs['notification_id'] ), $id_pairs['ref_id'] );
648 }
649 }
650 }
651 }
652
653 /* ------------------------------------------------------------------------ *
654 * Fire up the plugin
655 * ------------------------------------------------------------------------ */
656 BNFW::factory();
657