functions.wp-notify.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. <?php
  2. if ( ! function_exists( 'wp_notify_postauthor' ) && Jetpack::is_active() ) :
  3. /**
  4. * Notify an author (and/or others) of a comment/trackback/pingback on a post.
  5. *
  6. * @since 1.0.0
  7. *
  8. * @param int|WP_Comment $comment_id Comment ID or WP_Comment object.
  9. * @param string $deprecated Not used
  10. * @return bool True on completion. False if no email addresses were specified.
  11. */
  12. function wp_notify_postauthor( $comment_id, $deprecated = null ) {
  13. if ( null !== $deprecated ) {
  14. _deprecated_argument( __FUNCTION__, '3.8.0' );
  15. }
  16. $comment = get_comment( $comment_id );
  17. if ( empty( $comment ) || empty( $comment->comment_post_ID ) ) {
  18. return false;
  19. }
  20. $post = get_post( $comment->comment_post_ID );
  21. $author = get_userdata( $post->post_author );
  22. // Who to notify? By default, just the post author, but others can be added.
  23. $emails = array();
  24. if ( $author ) {
  25. $emails[] = $author->user_email;
  26. }
  27. /** This filter is documented in core/src/wp-includes/pluggable.php */
  28. $emails = apply_filters( 'comment_notification_recipients', $emails, $comment->comment_ID );
  29. $emails = array_filter( $emails );
  30. // If there are no addresses to send the comment to, bail.
  31. if ( ! count( $emails ) ) {
  32. return false;
  33. }
  34. // Facilitate unsetting below without knowing the keys.
  35. $emails = array_flip( $emails );
  36. /** This filter is documented in core/src/wp-includes/pluggable.php */
  37. $notify_author = apply_filters( 'comment_notification_notify_author', false, $comment->comment_ID );
  38. // The comment was left by the author
  39. if ( $author && ! $notify_author && $comment->user_id == $post->post_author ) {
  40. unset( $emails[ $author->user_email ] );
  41. }
  42. // The author moderated a comment on their own post
  43. if ( $author && ! $notify_author && $post->post_author == get_current_user_id() ) {
  44. unset( $emails[ $author->user_email ] );
  45. }
  46. // The post author is no longer a member of the blog
  47. if ( $author && ! $notify_author && ! user_can( $post->post_author, 'read_post', $post->ID ) ) {
  48. unset( $emails[ $author->user_email ] );
  49. }
  50. // If there's no email to send the comment to, bail, otherwise flip array back around for use below
  51. if ( ! count( $emails ) ) {
  52. return false;
  53. } else {
  54. $emails = array_flip( $emails );
  55. }
  56. $switched_locale = switch_to_locale( get_locale() );
  57. $comment_author_domain = @gethostbyaddr( $comment->comment_author_IP );
  58. // The blogname option is escaped with esc_html on the way into the database in sanitize_option
  59. // we want to reverse this for the plain text arena of emails.
  60. $blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
  61. $comment_content = wp_specialchars_decode( $comment->comment_content );
  62. function is_user_connected( $email ) {
  63. $user = get_user_by( 'email', $email );
  64. return Jetpack::is_user_connected( $user->ID );
  65. }
  66. $moderate_on_wpcom = ! in_array( false, array_map( 'is_user_connected', $emails ) );
  67. $primary_site_slug = Jetpack::build_raw_urls( get_home_url() );
  68. switch ( $comment->comment_type ) {
  69. case 'trackback':
  70. /* translators: 1: Post title */
  71. $notify_message = sprintf( __( 'New trackback on your post "%s"' ), $post->post_title ) . "\r\n";
  72. /* translators: 1: Trackback/pingback website name, 2: website IP address, 3: website hostname */
  73. $notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
  74. $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
  75. $notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
  76. $notify_message .= __( 'You can see all trackbacks on this post here:' ) . "\r\n";
  77. /* translators: 1: blog name, 2: post title */
  78. $subject = sprintf( __( '[%1$s] Trackback: "%2$s"' ), $blogname, $post->post_title );
  79. break;
  80. case 'pingback':
  81. /* translators: 1: Post title */
  82. $notify_message = sprintf( __( 'New pingback on your post "%s"' ), $post->post_title ) . "\r\n";
  83. /* translators: 1: Trackback/pingback website name, 2: website IP address, 3: website hostname */
  84. $notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
  85. $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
  86. $notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
  87. $notify_message .= __( 'You can see all pingbacks on this post here:' ) . "\r\n";
  88. /* translators: 1: blog name, 2: post title */
  89. $subject = sprintf( __( '[%1$s] Pingback: "%2$s"' ), $blogname, $post->post_title );
  90. break;
  91. default: // Comments
  92. $notify_message = sprintf( __( 'New comment on your post "%s"' ), $post->post_title ) . "\r\n";
  93. /* translators: 1: comment author, 2: comment author's IP address, 3: comment author's hostname */
  94. $notify_message .= sprintf( __( 'Author: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
  95. $notify_message .= sprintf( __( 'Email: %s' ), $comment->comment_author_email ) . "\r\n";
  96. $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
  97. $notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
  98. $notify_message .= __( 'You can see all comments on this post here:' ) . "\r\n";
  99. /* translators: 1: blog name, 2: post title */
  100. $subject = sprintf( __( '[%1$s] Comment: "%2$s"' ), $blogname, $post->post_title );
  101. break;
  102. }
  103. $notify_message .= $moderate_on_wpcom
  104. ? "https://wordpress.com/comments/all/{$primary_site_slug}/{$comment->comment_post_ID}/\r\n\r\n"
  105. : get_permalink( $comment->comment_post_ID ) . "#comments\r\n\r\n";
  106. $notify_message .= sprintf( __( 'Permalink: %s' ), get_comment_link( $comment ) ) . "\r\n";
  107. if ( user_can( $post->post_author, 'edit_comment', $comment->comment_ID ) ) {
  108. if ( EMPTY_TRASH_DAYS ) {
  109. $notify_message .= sprintf(
  110. __( 'Trash it: %s' ), $moderate_on_wpcom
  111. ? "https://wordpress.com/comment/{$primary_site_slug}/{$comment_id}?action=trash"
  112. : admin_url( "comment.php?action=trash&c={$comment->comment_ID}#wpbody-content" )
  113. ) . "\r\n";
  114. } else {
  115. $notify_message .= sprintf(
  116. __( 'Delete it: %s' ), $moderate_on_wpcom
  117. ? "https://wordpress.com/comment/{$primary_site_slug}/{$comment_id}?action=delete"
  118. : admin_url( "comment.php?action=delete&c={$comment->comment_ID}#wpbody-content" )
  119. ) . "\r\n";
  120. }
  121. $notify_message .= sprintf(
  122. __( 'Spam it: %s' ), $moderate_on_wpcom ?
  123. "https://wordpress.com/comment/{$primary_site_slug}/{$comment_id}?action=spam"
  124. : admin_url( "comment.php?action=spam&c={$comment->comment_ID}#wpbody-content" )
  125. ) . "\r\n";
  126. }
  127. $wp_email = 'wordpress@' . preg_replace( '#^www\.#', '', strtolower( $_SERVER['SERVER_NAME'] ) );
  128. if ( '' == $comment->comment_author ) {
  129. $from = "From: \"$blogname\" <$wp_email>";
  130. if ( '' != $comment->comment_author_email ) {
  131. $reply_to = "Reply-To: $comment->comment_author_email";
  132. }
  133. } else {
  134. $from = "From: \"$comment->comment_author\" <$wp_email>";
  135. if ( '' != $comment->comment_author_email ) {
  136. $reply_to = "Reply-To: \"$comment->comment_author_email\" <$comment->comment_author_email>";
  137. }
  138. }
  139. $message_headers = "$from\n"
  140. . 'Content-Type: text/plain; charset="' . get_option( 'blog_charset' ) . "\"\n";
  141. if ( isset( $reply_to ) ) {
  142. $message_headers .= $reply_to . "\n";
  143. }
  144. /** This filter is documented in core/src/wp-includes/pluggable.php */
  145. $notify_message = apply_filters( 'comment_notification_text', $notify_message, $comment->comment_ID );
  146. /** This filter is documented in core/src/wp-includes/pluggable.php */
  147. $subject = apply_filters( 'comment_notification_subject', $subject, $comment->comment_ID );
  148. /** This filter is documented in core/src/wp-includes/pluggable.php */
  149. $message_headers = apply_filters( 'comment_notification_headers', $message_headers, $comment->comment_ID );
  150. foreach ( $emails as $email ) {
  151. @wp_mail( $email, wp_specialchars_decode( $subject ), $notify_message, $message_headers );
  152. }
  153. if ( $switched_locale ) {
  154. restore_previous_locale();
  155. }
  156. return true;
  157. }
  158. endif;
  159. if ( ! function_exists( 'wp_notify_moderator' ) && Jetpack::is_active() ) :
  160. /**
  161. * Notifies the moderator of the site about a new comment that is awaiting approval.
  162. *
  163. * @since 1.0.0
  164. *
  165. * @global wpdb $wpdb WordPress database abstraction object.
  166. *
  167. * Uses the {@see 'notify_moderator'} filter to determine whether the site moderator
  168. * should be notified, overriding the site setting.
  169. *
  170. * @param int $comment_id Comment ID.
  171. * @return true Always returns true.
  172. */
  173. function wp_notify_moderator( $comment_id ) {
  174. global $wpdb;
  175. $maybe_notify = get_option( 'moderation_notify' );
  176. /** This filter is documented in core/src/wp-includes/pluggable.php */
  177. $maybe_notify = apply_filters( 'notify_moderator', $maybe_notify, $comment_id );
  178. if ( ! $maybe_notify ) {
  179. return true;
  180. }
  181. $comment = get_comment( $comment_id );
  182. $post = get_post( $comment->comment_post_ID );
  183. $user = get_userdata( $post->post_author );
  184. // Send to the administration and to the post author if the author can modify the comment.
  185. $emails = array( get_option( 'admin_email' ) );
  186. if ( $user && user_can( $user->ID, 'edit_comment', $comment_id ) && ! empty( $user->user_email ) ) {
  187. if ( 0 !== strcasecmp( $user->user_email, get_option( 'admin_email' ) ) ) {
  188. $emails[] = $user->user_email;
  189. }
  190. }
  191. $switched_locale = switch_to_locale( get_locale() );
  192. $comment_author_domain = @gethostbyaddr( $comment->comment_author_IP );
  193. $comments_waiting = $wpdb->get_var( "SELECT count(comment_ID) FROM $wpdb->comments WHERE comment_approved = '0'" );
  194. // The blogname option is escaped with esc_html on the way into the database in sanitize_option
  195. // we want to reverse this for the plain text arena of emails.
  196. $blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
  197. $comment_content = wp_specialchars_decode( $comment->comment_content );
  198. switch ( $comment->comment_type ) {
  199. case 'trackback':
  200. /* translators: 1: Post title */
  201. $notify_message = sprintf( __( 'A new trackback on the post "%s" is waiting for your approval' ), $post->post_title ) . "\r\n";
  202. $notify_message .= get_permalink( $comment->comment_post_ID ) . "\r\n\r\n";
  203. /* translators: 1: Trackback/pingback website name, 2: website IP address, 3: website hostname */
  204. $notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
  205. /* translators: 1: Trackback/pingback/comment author URL */
  206. $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
  207. $notify_message .= __( 'Trackback excerpt: ' ) . "\r\n" . $comment_content . "\r\n\r\n";
  208. break;
  209. case 'pingback':
  210. /* translators: 1: Post title */
  211. $notify_message = sprintf( __( 'A new pingback on the post "%s" is waiting for your approval' ), $post->post_title ) . "\r\n";
  212. $notify_message .= get_permalink( $comment->comment_post_ID ) . "\r\n\r\n";
  213. /* translators: 1: Trackback/pingback website name, 2: website IP address, 3: website hostname */
  214. $notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
  215. /* translators: 1: Trackback/pingback/comment author URL */
  216. $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
  217. $notify_message .= __( 'Pingback excerpt: ' ) . "\r\n" . $comment_content . "\r\n\r\n";
  218. break;
  219. default: // Comments
  220. /* translators: 1: Post title */
  221. $notify_message = sprintf( __( 'A new comment on the post "%s" is waiting for your approval' ), $post->post_title ) . "\r\n";
  222. $notify_message .= get_permalink( $comment->comment_post_ID ) . "\r\n\r\n";
  223. /* translators: 1: Comment author name, 2: comment author's IP address, 3: comment author's hostname */
  224. $notify_message .= sprintf( __( 'Author: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
  225. /* translators: 1: Comment author URL */
  226. $notify_message .= sprintf( __( 'Email: %s' ), $comment->comment_author_email ) . "\r\n";
  227. /* translators: 1: Trackback/pingback/comment author URL */
  228. $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
  229. /* translators: 1: Comment text */
  230. $notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
  231. break;
  232. }
  233. /** This filter is documented in core/src/wp-includes/pluggable.php */
  234. $emails = apply_filters( 'comment_moderation_recipients', $emails, $comment_id );
  235. function is_user_connected( $email ) {
  236. $user = get_user_by( 'email', $email );
  237. return Jetpack::is_user_connected( $user->ID );
  238. }
  239. $moderate_on_wpcom = ! in_array( false, array_map( 'is_user_connected', $emails ) );
  240. $primary_site_slug = Jetpack::build_raw_urls( get_home_url() );
  241. /* translators: Comment moderation. 1: Comment action URL */
  242. $notify_message .= sprintf(
  243. __( 'Approve it: %s' ), $moderate_on_wpcom
  244. ? "https://wordpress.com/comment/{$primary_site_slug}/{$comment_id}?action=approve"
  245. : admin_url( "comment.php?action=approve&c={$comment_id}#wpbody-content" )
  246. ) . "\r\n";
  247. if ( EMPTY_TRASH_DAYS ) {
  248. /* translators: Comment moderation. 1: Comment action URL */
  249. $notify_message .= sprintf(
  250. __( 'Trash it: %s' ), $moderate_on_wpcom
  251. ? "https://wordpress.com/comment/{$primary_site_slug}/{$comment_id}?action=trash"
  252. : admin_url( "comment.php?action=trash&c={$comment_id}#wpbody-content" )
  253. ) . "\r\n";
  254. } else {
  255. /* translators: Comment moderation. 1: Comment action URL */
  256. $notify_message .= sprintf(
  257. __( 'Delete it: %s' ), $moderate_on_wpcom
  258. ? "https://wordpress.com/comment/{$primary_site_slug}/{$comment_id}?action=delete"
  259. : admin_url( "comment.php?action=delete&c={$comment_id}#wpbody-content" )
  260. ) . "\r\n";
  261. }
  262. /* translators: Comment moderation. 1: Comment action URL */
  263. $notify_message .= sprintf(
  264. __( 'Spam it: %s' ), $moderate_on_wpcom
  265. ? "https://wordpress.com/comment/{$primary_site_slug}/{$comment_id}?action=spam"
  266. : admin_url( "comment.php?action=spam&c={$comment_id}#wpbody-content" )
  267. ) . "\r\n";
  268. /* translators: Comment moderation. 1: Number of comments awaiting approval */
  269. $notify_message .= sprintf(
  270. _n(
  271. 'Currently %s comment is waiting for approval. Please visit the moderation panel:',
  272. 'Currently %s comments are waiting for approval. Please visit the moderation panel:', $comments_waiting
  273. ), number_format_i18n( $comments_waiting )
  274. ) . "\r\n";
  275. $notify_message .= $moderate_on_wpcom
  276. ? "https://wordpress.com/comments/pending/{$primary_site_slug}/"
  277. : admin_url( 'edit-comments.php?comment_status=moderated#wpbody-content' ) . "\r\n";
  278. /* translators: Comment moderation notification email subject. 1: Site name, 2: Post title */
  279. $subject = sprintf( __( '[%1$s] Please moderate: "%2$s"' ), $blogname, $post->post_title );
  280. $message_headers = '';
  281. /** This filter is documented in core/src/wp-includes/pluggable.php */
  282. $notify_message = apply_filters( 'comment_moderation_text', $notify_message, $comment_id );
  283. /** This filter is documented in core/src/wp-includes/pluggable.php */
  284. $subject = apply_filters( 'comment_moderation_subject', $subject, $comment_id );
  285. /** This filter is documented in core/src/wp-includes/pluggable.php */
  286. $message_headers = apply_filters( 'comment_moderation_headers', $message_headers, $comment_id );
  287. foreach ( $emails as $email ) {
  288. @wp_mail( $email, wp_specialchars_decode( $subject ), $notify_message, $message_headers );
  289. }
  290. if ( $switched_locale ) {
  291. restore_previous_locale();
  292. }
  293. return true;
  294. }
  295. endif;