PluginProbe
Edit Flow / 0.9.2
Edit Flow v0.9.2
0.11.1 0.11.0 0.7.2 0.7.3 0.7.4 0.7.5 0.7.6 0.8 0.8.1 0.8.2 0.9 0.9.1 0.9.2 0.9.3 0.9.4 0.9.5 0.9.6 0.9.7 0.9.8 0.9.9 trunk 0.1.5 0.10.0 0.10.1 0.10.2 All 44 releases
← All changes | modules/notifications/notifications.php +188 -59 0.8.2 → 0.9.2 View file →
@@ -68,8 +68,11 @@
68 68 $this->edit_post_subscriptions_cap = apply_filters( 'ef_edit_post_subscriptions_cap', $this->edit_post_subscriptions_cap );
69 69
70 70 // Set up metabox and related actions
71 71 add_action( 'add_meta_boxes', array( $this, 'add_post_meta_box' ) );
72 +
73 + // Add "access badge" to the subscribers list.
74 + add_action( 'ef_user_subscribe_actions', array( $this, 'display_subscriber_warning_badges' ), 10, 2 );
72 75
73 76 // Saving post actions
74 77 // self::save_post_subscriptions() is hooked into transition_post_status so we can ensure usergroup data
75 78 // is properly saved before sending notifs
@@ -190,8 +193,16 @@
190 193 if ( $this->is_whitelisted_functional_view() ) {
191 194 wp_enqueue_script( 'jquery-listfilterizer' );
192 195 wp_enqueue_script( 'jquery-quicksearch' );
193 196 wp_enqueue_script( 'edit-flow-notifications-js', $this->module_url . 'lib/notifications.js', array( 'jquery', 'jquery-listfilterizer', 'jquery-quicksearch' ), EDIT_FLOW_VERSION, true );
197 + wp_localize_script(
198 + 'edit-flow-notifications-js',
199 + 'ef_notifications_localization',
200 + array(
201 + 'no_access' => esc_html__( 'No Access', 'edit-flow' ),
202 + 'no_email' => esc_html__( 'No Email', 'edit-flow' )
203 + )
204 + );
194 205 }
195 206 }
196 207
197 208 /**
@@ -322,9 +333,8 @@
322 333 * @todo add_cap to set subscribers for posts; default to Admin and editors
323 334 */
324 335 function notifications_meta_box() {
325 336 global $post, $post_ID, $edit_flow;
326 -
327 337 ?>
328 338 <div id="ef-post_following_box">
329 339 <a name="subscriptions"></a>
330 340
@@ -353,8 +363,38 @@
353 363 </div>
354 364
355 365 <?php
356 366 }
367 +
368 + /**
369 + * Show warning badges next to a subscriber's name if they won't receive notifications
370 + *
371 + * Applies on initial loading of list via. PHP. JS will set these spans based on AJAX response when box is ticked/unticked.
372 + *
373 + * @param int $user_id
374 + * @param bool $checked True if the user is subscribed already, false otherwise.
375 + * @return void
376 + */
377 + function display_subscriber_warning_badges( $user_id, $checked ) {
378 + global $post;
379 +
380 + if (!isset( $post ) OR !$checked ) {
381 + return;
382 + }
383 +
384 + // Add No Access span if they won't be notified
385 + if (! $this->user_can_be_notified( get_user_by( 'id', $user_id ), $post->ID )) {
386 + // span.post_following_list-no_access is also added in notifications.js after AJAX that ticks/unticks a user
387 + echo '<span class="post_following_list-no_access">' . esc_html__( 'No Access', 'edit-flow' ) . '</span>';
388 + }
389 +
390 + // Add No Email span if they have no email
391 + $user_object = get_user_by( 'id', $user_id );
392 + if ( !is_a( $user_object, 'WP_User') OR empty( $user_object->user_email ) ) {
393 + // span.post_following_list-no_email is also added in notifications.js after AJAX that ticks/unticks a user
394 + echo '<span class="post_following_list-no_email">' . esc_html__( 'No Email', 'edit-flow' ) . '</span>';
395 + }
396 + }
357 397
358 398 /**
359 399 * Called when a notification editorial metadata checkbox is checked. Handles saving of a user/usergroup to a post.
360 400 */
@@ -359,26 +399,65 @@
359 399 * Called when a notification editorial metadata checkbox is checked. Handles saving of a user/usergroup to a post.
360 400 */
361 401 function ajax_save_post_subscriptions() {
362 402 global $edit_flow;
363 -
364 - // Verify nonce
365 - if ( !wp_verify_nonce( $_POST['_nonce'], 'save_user_usergroups') )
366 - die( __( "Nonce check failed. Please ensure you can add users or user groups to a post.", 'edit-flow' ) );
367 403
368 - $post_id = (int)$_POST['post_id'];
369 - $post = get_post( $post_id );
370 - $user_usergroup_ids = array_map( 'intval', $_POST['user_group_ids'] );
371 - if( ( !wp_is_post_revision( $post_id ) && !wp_is_post_autosave( $post_id ) ) && current_user_can( $this->edit_post_subscriptions_cap ) ) {
372 - if( $_POST['ef_notifications_name'] === 'ef-selected-users[]' ) {
373 - $this->save_post_following_users( $post, $user_usergroup_ids );
374 - }
375 - else if ( $_POST['ef_notifications_name'] == 'following_usergroups[]' ) {
376 - if ( $this->module_enabled( 'user_groups' ) && in_array( get_post_type( $post_id ), $this->get_post_types_for_module( $edit_flow->user_groups->module ) ) ) {
377 - $this->save_post_following_usergroups( $post, $user_usergroup_ids );
404 + // Verify nonce.
405 + if ( ! isset( $_POST['_nonce'] ) || ! wp_verify_nonce( $_POST['_nonce'], 'save_user_usergroups' ) ) {
406 + die( __( 'Nonce check failed. Please ensure you can add users or user groups to a post.', 'edit-flow' ) );
407 + }
408 +
409 + $post_id = isset( $_POST['post_id'] ) ? (int) $_POST['post_id'] : 0;
410 + $post = get_post( $post_id );
411 +
412 + $valid_post = ! is_null( $post ) && ! wp_is_post_revision( $post_id ) && ! wp_is_post_autosave( $post_id );
413 + if ( ! isset( $_POST['ef_notifications_name'] ) || ! $valid_post || ! current_user_can( $this->edit_post_subscriptions_cap ) ) {
414 + die();
415 + }
416 +
417 + $user_group_ids = array();
418 + if ( isset( $_POST['user_group_ids'] ) && is_array( $_POST['user_group_ids'] ) ) {
419 + $user_group_ids = array_map( 'intval', $_POST['user_group_ids'] );
420 + }
421 +
422 + if ( 'ef-selected-users[]' === $_POST['ef_notifications_name'] ) {
423 + // Prevent auto-subscribing users that have opted out of notifications.
424 + add_filter( 'ef_notification_auto_subscribe_current_user', '__return_false', PHP_INT_MAX );
425 + $this->save_post_following_users( $post, $user_group_ids );
426 +
427 + if ( defined( 'DOING_AJAX' ) && DOING_AJAX && isset( $_POST['post_id'] ) ) {
428 +
429 + // Determine if any of the selected users won't have notification access
430 + $subscribers_with_no_access = array_filter( $user_group_ids, function( $user_id ) {
431 + return ! $this->user_can_be_notified( get_user_by( 'id', $user_id ), $_POST['post_id'] );
432 + } );
433 +
434 + // Determine if any of the selected users are missing their emails
435 + $subscribers_with_no_email = array();
436 + foreach ( $user_group_ids AS $user_id ) {
437 + $user_object = get_user_by( 'id', $user_id );
438 + if ( !is_a( $user_object, 'WP_User') OR empty( $user_object->user_email ) ) {
439 + $subscribers_with_no_email[] = $user_id;
440 + }
378 441 }
442 +
443 + // Assemble the json reply with various lists of problematic users
444 + $json_success = array(
445 + 'subscribers_with_no_access' => array_values( $subscribers_with_no_access ),
446 + 'subscribers_with_no_email' => array_values( $subscribers_with_no_email ),
447 + );
448 +
449 + wp_send_json_success( $json_success );
379 450 }
451 + // Remove auto-subscribe prevention behavior from earlier.
452 + remove_filter( 'ef_notification_auto_subscribe_current_user', '__return_false', PHP_INT_MAX );
380 453 }
454 +
455 + $groups_enabled = $this->module_enabled( 'user_groups' ) && in_array( get_post_type( $post_id ), $this->get_post_types_for_module( $edit_flow->user_groups->module ) );
456 + if ( 'following_usergroups[]' === $_POST['ef_notifications_name'] && $groups_enabled ) {
457 + $this->save_post_following_usergroups( $post, $user_group_ids );
458 + }
459 +
381 460 die();
382 461 }
383 462
384 463 /**
@@ -510,8 +589,9 @@
510 589
511 590 // Email subject and first line of body
512 591 // Set message subjects according to what action is being taken on the Post
513 592 if ( $old_status == 'new' || $old_status == 'auto-draft' ) {
593 + $old_status_friendly_name = "New";
514 594 /* translators: 1: site name, 2: post type, 3. post title */
515 595 $subject = sprintf( __( '[%1$s] New %2$s Created: "%3$s"', 'edit-flow' ), $blogname, $post_type, $post_title );
516 596 /* translators: 1: post type, 2: post id, 3. post title, 4. user name, 5. user email */
517 597 $body .= sprintf( __( 'A new %1$s (#%2$s "%3$s") was created by %4$s %5$s', 'edit-flow' ), $post_type, $post_id, $post_title, $current_user->display_name, $current_user->user_email ) . "\r\n";
@@ -544,16 +624,18 @@
544 624 /* translators: 1: site name, 2: post type, 3. post title */
545 625 $subject = sprintf( __( '[%1$s] %2$s Status Changed for "%3$s"', 'edit-flow' ), $blogname, $post_type, $post_title );
546 626 /* translators: 1: post type, 2: post id, 3. post title, 4. user name, 5. user email */
547 627 $body .= sprintf( __( 'Status was changed for %1$s #%2$s "%3$s" by %4$s %5$s', 'edit-flow'), $post_type, $post_id, $post_title, $current_user_display_name, $current_user_email ) . "\r\n";
628 + $old_status_post_obj = get_post_status_object( $old_status );
629 + $old_status_friendly_name = $old_status_post_obj->label;
548 630 }
549 631
550 632 /* translators: 1: date, 2: time, 3: timezone */
551 633 $body .= sprintf( __( 'This action was taken on %1$s at %2$s %3$s', 'edit-flow' ), date_i18n( get_option( 'date_format' ) ), date_i18n( get_option( 'time_format' ) ), get_option( 'timezone_string' ) ) . "\r\n";
552 -
553 - $old_status_friendly_name = $this->get_post_status_friendly_name( $old_status );
554 - $new_status_friendly_name = $this->get_post_status_friendly_name( $new_status );
555 -
634 +
635 + $new_status_post_obj = get_post_status_object( $new_status );
636 + $new_status_friendly_name = $new_status_post_obj->label;
637 +
556 638 // Email body
557 639 $body .= "\r\n";
558 640 /* translators: 1: old status, 2: new status */
559 641 $body .= sprintf( __( '%1$s => %2$s', 'edit-flow' ), $old_status_friendly_name, $new_status_friendly_name );
@@ -588,8 +670,11 @@
588 670 }
589 671
590 672 /**
591 673 * Set up and set editorial comment notification email
674 + *
675 + * @param WP_Comment $comment
676 + * @return boolean|null|void
592 677 */
593 678 function notification_comment( $comment ) {
594 679
595 680 $post = get_post($comment->comment_post_ID);
@@ -607,9 +692,12 @@
607 692
608 693 $post_id = $post->ID;
609 694 $post_type = get_post_type_object( $post->post_type )->labels->singular_name;
610 695 $post_title = ef_draft_or_post_title( $post_id );
611 -
696 +
697 + // Fetch the text list of people who were notified from comment meta @see EF_Editorial_Comments->maybe_output_comment_meta()
698 + $notification_list = get_comment_meta( $comment->comment_ID, 'notification_list', true );
699 +
612 700 // Check if this a reply
613 701 //$parent_ID = isset( $comment->comment_parent_ID ) ? $comment->comment_parent_ID : 0;
614 702 //if($parent_ID) $parent = get_comment($parent_ID);
615 703
@@ -638,9 +726,14 @@
638 726
639 727 }
640 728 */
641 729
730 +
642 731 $body .= "\r\n--------------------\r\n";
732 + // Insert the notification list from comment meta @see EF_Editorial_Comments->maybe_output_comment_meta()
733 + if ($notification_list) {
734 + $body .= esc_html__( 'Notified', 'edit-flow' ) . ": " . esc_html( $notification_list ) . "\n";
735 + }
643 736
644 737 $edit_link = htmlspecialchars_decode( get_edit_post_link( $post_id ) );
645 738 $view_link = htmlspecialchars_decode( get_permalink( $post_id ) );
646 739
@@ -725,64 +818,73 @@
725 818 */
726 819 function send_single_email( $to, $subject, $message, $message_headers = '' ) {
727 820 wp_mail( $to, $subject, $message, $message_headers );
728 821 }
729 -
822 +
730 823 /**
731 - * Returns a list of recipients for a given post
824 + * Returns a list of recipients for a given post.
732 825 *
733 - * @param $post object
734 - * @param $string bool Whether to return recipients as comma-delimited string or array
735 - * @return string or array of recipients to receive notification
826 + * @param WP_Post $post
827 + * @param bool $string Whether to return recipients as comma-delimited string or array.
828 + * @return string|array Recipients to receive notification.
736 829 */
737 830 private function _get_notification_recipients( $post, $string = false ) {
738 831 global $edit_flow;
739 -
832 +
740 833 $post_id = $post->ID;
741 - if( !$post_id ) return;
742 -
743 - $authors = array();
834 + if ( ! $post_id ) {
835 + return $string ? '' : array();
836 + }
837 +
838 + // Email all admins if enabled.
744 839 $admins = array();
745 - $recipients = array();
840 + if ( 'on' === $this->module->options->always_notify_admin ) {
841 + $admins[] = get_option('admin_email');
842 + }
746 843
747 - // Email all admins, if enabled
748 - if( 'on' == $this->module->options->always_notify_admin )
749 - $admins[] = get_option('admin_email');
750 -
751 - $usergroup_users = array();
844 + $usergroup_recipients = array();
752 845 if ( $this->module_enabled( 'user_groups' ) ) {
753 - // Get following users and usergroups
754 846 $usergroups = $this->get_following_usergroups( $post_id, 'ids' );
755 - foreach( (array)$usergroups as $usergroup_id ) {
847 + foreach ( (array) $usergroups as $usergroup_id ) {
756 848 $usergroup = $edit_flow->user_groups->get_usergroup_by( 'id', $usergroup_id );
757 - foreach( (array)$usergroup->user_ids as $user_id ) {
849 + foreach ( (array) $usergroup->user_ids as $user_id ) {
758 850 $usergroup_user = get_user_by( 'id', $user_id );
759 - if ( $usergroup_user && is_user_member_of_blog( $user_id ) )
760 - $usergroup_users[] = $usergroup_user->user_email;
851 + if ( $this->user_can_be_notified( $usergroup_user, $post_id ) ) {
852 + $usergroup_recipients[] = $usergroup_user->user_email;
853 + }
761 854 }
762 855 }
763 856 }
764 -
765 - $users = $this->get_following_users( $post_id, 'user_email' );
766 -
767 - // Merge arrays and filter any duplicates
768 - $recipients = array_merge( $authors, $admins, $users, $usergroup_users );
769 - $recipients = array_unique( $recipients );
770 857
771 - // Process the recipients for this email to be sent
772 - foreach( $recipients as $key => $user_email ) {
773 - // Get rid of empty email entries
774 - if ( empty( $recipients[$key] ) )
775 - unset( $recipients[$key] );
776 - // Don't send the email to the current user unless we've explicitly indicated they should receive it
777 - if ( false === apply_filters( 'ef_notification_email_current_user', false ) && wp_get_current_user()->user_email == $user_email )
778 - unset( $recipients[$key] );
858 + $user_recipients = $this->get_following_users( $post_id, 'user_email' );
859 + foreach( $user_recipients as $key => $user ) {
860 + $user_object = get_user_by( 'email', $user );
861 + if ( ! $this->user_can_be_notified( $user_object, $post_id ) ) {
862 + unset( $user_recipients[ $key ] );
863 + }
779 864 }
780 -
781 - // Filter to allow further modification of recipients
865 +
866 + // Merge arrays, filter any duplicates, and remove empty entries.
867 + $recipients = array_filter( array_unique( array_merge( $admins, $user_recipients, $usergroup_recipients ) ) );
868 +
869 + // Process the recipients for this email to be sent.
870 + foreach( $recipients as $key => $user_email ) {
871 + // Don't send the email to the current user unless we've explicitly indicated they should receive it.
872 + if ( false === apply_filters( 'ef_notification_email_current_user', false ) && wp_get_current_user()->user_email == $user_email ) {
873 + unset( $recipients[ $key ] );
874 + }
875 + }
876 +
877 + /**
878 + * Filters the list of notification recipients.
879 + *
880 + * @param array $recipients List of recipient email addresses.
881 + * @param WP_Post $post
882 + * @param bool $string True if the recipients list will later be returned as a string.
883 + */
782 884 $recipients = apply_filters( 'ef_notification_recipients', $recipients, $post, $string );
783 -
784 - // If string set to true, return comma-delimited
885 +
886 + // If string set to true, return comma-delimited.
785 887 if ( $string && is_array( $recipients ) ) {
786 888 return implode( ',', $recipients );
787 889 } else {
788 890 return $recipients;
@@ -787,9 +889,36 @@
787 889 } else {
788 890 return $recipients;
789 891 }
790 892 }
791 -
893 +
894 + /**
895 + * Check if a user can be notified.
896 + * This is based off of the ability to edit the post/page by default.
897 + *
898 + * @since 0.8.3
899 + * @param WP_User $user
900 + * @param int $post_id
901 + * @return bool True if the user can be notified, false otherwise.
902 + */
903 + function user_can_be_notified( $user, $post_id ) {
904 + $can_be_notified = false;
905 +
906 + if ( $user instanceof WP_User && is_user_member_of_blog( $user->ID ) && is_numeric( $post_id ) ) {
907 + // The 'edit_post' cap check also covers the undocumented 'edit_page' cap.
908 + $can_be_notified = $user->has_cap( 'edit_post', $post_id );
909 + }
910 +
911 + /**
912 + * Filters if a user can be notified. Defaults to true if they can edit the post/page.
913 + *
914 + * @param bool $can_be_notified True if the user can be notified.
915 + * @param WP_User|bool $user The user object, otherwise false.
916 + * @param int $post_id The post the user will be notified about.
917 + */
918 + return (bool) apply_filters( 'ef_notification_user_can_be_notified', $can_be_notified, $user, $post_id );
919 + }
920 +
792 921 /**
793 922 * Set a user or users to follow a post
794 923 *
795 924 * @param int|object $post Post object or ID