' ){
if ( is_array( $this->messages ) ) {
echo wp_kses_post( $before_all );
foreach ( $this->messages as $message )
echo wp_kses_post( $before_each . $message . $after_each );
echo wp_kses_post( $after_all );
}
$this->messages = array();
}
/**
* Read a query prepared by a caller, with a request-local cache for private subscription data.
* Core has no API for reverse email lookups across the legacy postmeta records or network table.
*/
function subscription_query( $prepared_query, $format = 'results' ) {
global $wpdb;
$cache_key = $format . ':' . md5( $prepared_query );
if ( array_key_exists( $cache_key, $this->query_cache ) )
return $this->query_cache[$cache_key];
if ( 'var' === $format ) {
// phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Prepared by callers; cached above and below, with invalidation on subscription writes.
$result = $wpdb->get_var( $prepared_query );
} elseif ( 'col' === $format ) {
// phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Prepared by callers; cached above and below, with invalidation on subscription writes.
$result = $wpdb->get_col( $prepared_query );
} else {
// phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Prepared by callers; cached above and below, with invalidation on subscription writes.
$result = $wpdb->get_results( $prepared_query );
}
$this->query_cache[$cache_key] = $result;
return $result;
}
function clear_subscription_cache() {
$this->query_cache = array();
$this->bid_post_subscriptions = array();
$this->email_subscriptions = false;
}
function subscription_meta_changed( $meta_id, $post_id, $meta_key ) {
if ( in_array( $meta_key, array( '_sg_subscribe-to-comments', '_sg_subscribe-to-comments-pending', '_sg_subscribe-to-comments-pending-with-email' ), true ) )
$this->clear_subscription_cache();
}
function is_subscribed_email_post_bid( $email, $post_id, $bid = NULL ) {
global $wpdb, $blog_id;
$bid = ( NULL == $bid ) ? $blog_id : $bid;
$email = strtolower( $email );
if ( $this->is_multisite() && $this->subscription_query( $wpdb->prepare( "SELECT email FROM %i WHERE email = %s AND post_id = %d AND blog_id = %d", $this->ms_table, $email, $post_id, $bid ), 'var' ) )
return true;
elseif ( $this->subscription_query( $wpdb->prepare( "SELECT meta_value FROM %i WHERE LCASE( meta_value ) = %s AND meta_key = '_sg_subscribe-to-comments' AND post_id = %d", $wpdb->postmeta, $email, $post_id ), 'var' ) )
return true;
return false;
}
function subscriptions_from_post( $postid, $bid=NULL ) {
global $wpdb, $blog_id;
if ( NULL == $bid )
$bid = $blog_id;
if ( isset( $this->bid_post_subscriptions[$bid][$postid] ) && is_array( $this->bid_post_subscriptions[$bid][$postid] ) )
return $this->bid_post_subscriptions[$bid][$postid];
$postid = (int) $postid;
if ( $this->is_multisite() ) {
$subscriptions = (array) $this->subscription_query( $wpdb->prepare( "SELECT DISTINCT email FROM %i WHERE blog_id = %d AND post_id = %d AND status = 'active'", $this->ms_table, $bid, $postid ), 'col' );
} else {
$subscriptions = (array) get_post_meta( $postid, '_sg_subscribe-to-comments' );
}
// Cleanup uses local data, because writes invalidate the request-local caches.
$duplicates = $this->array_duplicates( $subscriptions );
if ( $this->is_multisite() ) {
if ( $duplicates ) {
foreach ( (array) $duplicates as $duplicate ) {
// phpcs:ignore WordPress.DB.DirectDatabaseQuery -- Custom network-table duplicate cleanup; remove/add methods invalidate the request-local cache.
$wpdb->query( $wpdb->prepare( "DELETE FROM %i WHERE blog_id = %d AND post_id = %d AND email = %s AND status = 'active'", $this->ms_table, $bid, $postid, $duplicate ) );
$this->clear_subscription_cache();
$this->add_subscriber_by_post_id_and_email( $postid, $duplicate, $bid );
}
}
} else {
if ( $duplicates ) {
foreach ( (array) $duplicates as $duplicate ) {
delete_post_meta( $postid, '_sg_subscribe-to-comments', $duplicate );
$this->add_subscriber_by_post_id_and_email( $postid, $duplicate, $bid );
}
}
}
$this->bid_post_subscriptions[$bid][$postid] = array_unique( $subscriptions );
return $this->bid_post_subscriptions[$bid][$postid];
}
function subscriptions_from_email( $email='' ) {
global $wpdb, $blog_id;
if ( is_array( $this->email_subscriptions ) )
return $this->email_subscriptions;
if ( !is_email( $email ) )
$email = $this->email;
$email = strtolower( $email );
if ( $this->is_multisite() ) {
if ( current_user_can( 'manage_options' ) )
$subscriptions = $this->subscription_query( $wpdb->prepare( "SELECT blog_id, post_id FROM %i WHERE email = %s AND status = 'active' AND blog_id = %d", $this->ms_table, $email, $blog_id ) );
else
$subscriptions = $this->subscription_query( $wpdb->prepare( "SELECT blog_id, post_id FROM %i WHERE email = %s AND status = 'active'", $this->ms_table, $email ) );
} else {
$subscriptions = $this->subscription_query( $wpdb->prepare( "SELECT post_id FROM %i WHERE meta_key = '_sg_subscribe-to-comments' AND LCASE(meta_value) = %s GROUP BY post_id", $wpdb->postmeta, $email ) );
}
$this->email_subscriptions = array();
foreach ( (array) $subscriptions as $subscription)
$this->email_subscriptions[] = array( ( isset( $subscription->blog_id ) ) ? $subscription->blog_id : $blog_id, $subscription->post_id );
if ( is_array( $this->email_subscriptions ) ) {
usort( $this->email_subscriptions, array( $this, 'email_sort' ) );
return $this->email_subscriptions;
}
return false;
}
function email_sort( $a, $b ) {
if ( $a[0] == $b[0] ) {
if ( $a[1] == $b[1] )
return 0;
return ( $a[1] < $b[1] ) ? -1 : 1;
} else {
return ( $a[0] < $b[0] ) ? -1 : 1;
}
}
function maybe_solo_subscribe() {
if ( !isset( $_POST['solo-comment-subscribe'] ) || 'solo-comment-subscribe' !== $_POST['solo-comment-subscribe'] )
return;
if ( !isset( $_POST['stc_solo_nonce'] ) || !is_string( $_POST['stc_solo_nonce'] ) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['stc_solo_nonce'] ) ), 'stc-solo-subscribe' ) )
wp_die( esc_html__( 'Invalid subscription request. Please reload the page and try again.', 'subscribe-to-comments' ), '', array( 'response' => 403 ) );
if ( !isset( $_POST['email'], $_POST['postid'] ) || !is_string( $_POST['email'] ) || !is_scalar( $_POST['postid'] ) || !ctype_digit( sanitize_text_field( wp_unslash( (string) $_POST['postid'] ) ) ) ) {
$this->add_error( __( 'Please provide a valid e-mail address.', 'subscribe-to-comments' ), 'solo_subscribe' );
return;
}
$this->solo_subscribe( sanitize_email( wp_unslash( $_POST['email'] ) ), absint( $_POST['postid'] ) );
}
function solo_subscribe ( $email, $postid ) {
global $wpdb, $blog_id, $cache_userdata, $user_email;
$postid = (int) $postid;
$email = strtolower( $email );
if ( !is_email( $email ) ) {
$user_email = wp_get_current_user()->user_email;
if ( is_email( $user_email ) )
$email = strtolower( $user_email );
else
$this->add_error( __( 'Please provide a valid e-mail address.', 'subscribe-to-comments' ),'solo_subscribe' );
}
if ( ( $email == $this->site_email && is_email( $this->site_email ) ) || ( $email == get_option( 'admin_email' ) && is_email( get_option( 'admin_email' ) ) ) )
$this->add_error( __( 'This e-mail address may not be subscribed', 'subscribe-to-comments' ),'solo_subscribe' );
if ( $this->is_subscribed_email_post_bid( $email, $postid, $blog_id ) ) {
// already subscribed
setcookie( 'comment_author_email_' . COOKIEHASH, $email, time() + 30000000, COOKIEPATH );
$this->add_error( __( 'You appear to be already subscribed to this entry.', 'subscribe-to-comments' ),'solo_subscribe' );
}
$post = get_post( $postid );
if ( !$this->public_subscription_post( $post ) || !comments_open( $postid ) ) {
$this->add_error( __( 'Comments are not allowed on this entry.', 'subscribe-to-comments' ), 'solo_subscribe' );
return;
}
$post_author = get_userdata( $post->post_author );
if ( $post_author && strtolower( $post_author->user_email ) == $email )
$this->add_error( __( 'You appear to be already subscribed to this entry.', 'subscribe-to-comments' ),'solo_subscribe' );
if ( empty( $this->errors['solo_subscribe'] ) ) {
$user = wp_get_current_user();
$verified_owner = current_user_can( 'manage_options' ) && strtolower( $user->user_email ) === $email;
if ( !empty( $this->settings['double_opt_in'] ) && !$verified_owner ) {
if ( $this->is_multisite() ) {
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- The experimental network table has no core metadata API; wpdb escapes inserted values.
$wpdb->insert( $this->ms_table, array( 'email' => $email, 'blog_id' => $blog_id, 'post_id' => $postid, 'status' => 'pending', 'date_gmt' => current_time( 'mysql', 1 ) ) );
} elseif ( !in_array( $email, get_post_meta( $postid, '_sg_subscribe-to-comments-pending' ), true ) ) {
add_post_meta( $postid, '_sg_subscribe-to-comments-pending', $email );
}
$this->send_pending_confirmation( $email );
$this->add_message( __( 'Your subscription request has been received. Please check your e-mail to confirm it.', 'subscribe-to-comments' ) );
} else {
$this->add_subscriber_by_post_id_and_email( $postid, $email, $blog_id );
$this->add_message( __( 'Your subscription request has been received. You can manage your subscription using the link in notification e-mails.', 'subscribe-to-comments' ) );
}
setcookie( 'comment_author_email_' . COOKIEHASH, $email, time() + 30000000, COOKIEPATH );
$this->clear_subscription_cache();
}
}
// From: http://php.net/manual/en/function.array-unique.php#85109
function array_duplicates( $array ) {
if ( !is_array( $array ) )
return false;
$duplicates = array();
foreach ( $array as $key => $val ) {
end( $array );
$k = key( $array );
$v = current( $array );
while ( $k !== $key ) {
if ( $v === $val ) {
$duplicates[$key] = $v;
break;
}
$v = prev( $array );
$k = key( $array );
}
}
return $duplicates;
}
/** Email-only subscriptions must not bypass WordPress content visibility or password changes. */
function public_subscription_post( $post ) {
return $post && is_post_publicly_viewable( $post ) && '' === $post->post_password;
}
function maybe_add_subscriber( $cid ) {
global $wpdb;
$comment = get_comment( $cid );
if ( !$comment || !$this->public_subscription_post( get_post( $comment->comment_post_ID ) ) )
return $cid;
if ( !empty( $this->settings['double_opt_in'] ) ) {
$email = strtolower( $comment->comment_author_email );
$user = wp_get_current_user();
// A previous subscription is not proof that this request owns the supplied address.
$proceed = current_user_can( 'manage_options' ) && strtolower( $user->user_email ) === $email;
} else {
$proceed = true;
}
if ( 'spam' != $comment->comment_approved && $this->comment_subscribe_requested() ) {
if ( $proceed )
$this->add_subscriber( $cid );
else
$this->add_pending_subscriber( $cid );
}
return $cid;
}
function add_subscriber_by_post_id_and_email( $postid, $email, $bid = NULL ) {
global $wpdb, $blog_id;
$this->clear_subscription_cache();
$email = strtolower( $email );
if ( $this->is_multisite() ) {
$bid = ( NULL == $bid ) ? $blog_id : $bid;
$already_subscribed_to_this_post = !!$this->subscription_query( $wpdb->prepare( "SELECT email FROM %i WHERE email = %s AND blog_id = %d AND post_id = %d AND status = 'active'", $this->ms_table, $email, $bid, $postid ), 'var' );
if ( is_email( $email ) && !$already_subscribed_to_this_post )
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Custom network table; wpdb escapes values and this method invalidates its request-local cache.
$wpdb->insert( $this->ms_table, array( 'email' => $email, 'blog_id' => $bid, 'post_id' => $postid, 'status' => 'active' ) );
} else {
$already_subscribed_to_this_post = in_array( $email, (array) get_post_meta( $postid, '_sg_subscribe-to-comments' ) );
if ( is_email( $email ) && !$already_subscribed_to_this_post )
add_post_meta( $postid, '_sg_subscribe-to-comments', $email );
}
$this->clear_subscription_cache();
}
function add_subscriber( $cid ) {
global $blog_id;
$comment = get_comment( $cid );
$email = strtolower( $comment->comment_author_email );
$postid = $comment->comment_post_ID;
$this->add_subscriber_by_post_id_and_email( $postid, $email, $blog_id );
return $cid;
}
function add_pending_subscriber( $cid ) {
global $wpdb, $blog_id;
$this->clear_subscription_cache();
$comment = get_comment( $cid );
$email = strtolower( $comment->comment_author_email );
$postid = $comment->comment_post_ID;
if ( $this->is_multisite() ) {
$already_pending_on_this_post = !!$this->subscription_query( $wpdb->prepare( "SELECT email FROM %i WHERE email = %s AND blog_id = %d AND post_id = %d AND status IN( 'pending', 'pending-with-email' )", $this->ms_table, $email, $blog_id, $postid ), 'var' );
if ( is_email( $email ) && !$already_pending_on_this_post ) {
if ( !$this->subscription_query( $wpdb->prepare( "SELECT COUNT(*) FROM %i WHERE email = %s AND status = 'pending-with-email' AND date_gmt > DATE_SUB( NOW(), INTERVAL 1 DAY)", $this->ms_table, $email ), 'var' ) ) {
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Custom network table; wpdb escapes values and this method invalidates its request-local cache.
$wpdb->insert( $this->ms_table, array( 'email' => $email, 'blog_id' => $blog_id, 'post_id' => $postid, 'status' => 'pending-with-email', 'date_gmt' => current_time( 'mysql', 1 ) ) );
$this->send_pending_nag( $cid );
} else {
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Custom network table; wpdb escapes values and this method invalidates its request-local cache.
$wpdb->insert( $this->ms_table, array( 'email' => $email, 'blog_id' => $blog_id, 'post_id' => $postid, 'status' => 'pending', 'date_gmt' => current_time( 'mysql', 1 ) ) );
}
}
} else {
$already_pending_on_this_post = in_array( $email, (array) get_post_meta( $postid, '_sg_subscribe-to-comments-pending' ) );
if ( is_email( $email ) && !$already_pending_on_this_post ) {
if ( !$this->subscription_query( $wpdb->prepare( "SELECT COUNT(*) FROM %i, %i WHERE comment_post_ID = post_id AND LCASE( meta_value ) = %s AND meta_key = '_sg_subscribe-to-comments-pending-with-email' AND comment_date_gmt > DATE_SUB( NOW(), INTERVAL 1 DAY)", $wpdb->comments, $wpdb->postmeta, $email ), 'var' ) ) {
add_post_meta( $postid, '_sg_subscribe-to-comments-pending-with-email', strtolower( $email ) );
$this->send_pending_nag( $cid );
} else {
add_post_meta( $postid, '_sg_subscribe-to-comments-pending', strtolower( $email ) );
}
}
}
$this->clear_subscription_cache();
return $cid;
}
function confirm_pending_subscriber( $email ) {
global $wpdb, $blog_id;
$this->clear_subscription_cache();
$email = strtolower( $email );
if ( $this->is_multisite() ) {
// phpcs:ignore WordPress.DB.DirectDatabaseQuery -- Custom network table; wpdb escapes values and the request-local cache was invalidated above.
return (bool) $wpdb->update( $this->ms_table, array( 'status' => 'active' ), array( 'email' => $email ) );
} else {
$pending = $this->subscription_query( $wpdb->prepare( "SELECT post_id, meta_key FROM %i WHERE LCASE(meta_value) = %s AND meta_key IN( '_sg_subscribe-to-comments-pending', '_sg_subscribe-to-comments-pending-with-email' )", $wpdb->postmeta, $email ) );
foreach ( (array) $pending as $p ) {
$this->add_subscriber_by_post_id_and_email( $p->post_id, $email, $blog_id );
delete_post_meta( $p->post_id, $p->meta_key, $email );
}
}
return !!count( $pending );
}
function is_subscribed( $cid ) {
$comment = get_comment( $cid );
if ( !$comment )
return false;
$email = strtolower( $comment->comment_author_email );
$postid = $comment->comment_post_ID;
return in_array( $email, (array) $this->subscriptions_from_post( $postid ), true );
}
function is_blocked( $email='' ) {
global $wpdb;
if ( !is_email( $email ) )
$email = $this->email;
if ( empty( $email ) )
return false;
$email = strtolower( $email );
// add the option if it doesn't exist
add_option( 'do_not_mail', '' );
$stored = get_option( 'do_not_mail' );
$blocked = is_array( $stored ) ? $stored : explode( ' ', (string) $stored );
if ( in_array( $email, $blocked ) )
return true;
return false;
}
function add_block( $email='' ) {
global $wpdb;
if ( !is_email( $email ) )
$email = $this->email;
$email = strtolower( $email );
// add the option if it doesn't exist
add_option( 'do_not_mail', '' );
// check to make sure this email isn't already in there
if ( !$this->is_blocked( $email ) ) {
// email hasn't already been added - so add it
$stored = get_option( 'do_not_mail' );
$blocked = is_array( $stored ) ? $stored : explode( ' ', (string) $stored );
$blocked[] = $email;
update_option( 'do_not_mail', implode( ' ', array_filter( $blocked ) ) );
return true;
}
return false;
}
function remove_block( $email='' ) {
global $wpdb;
if ( !is_email( $email ) )
$email = $this->email;
$email = strtolower( $email );
if ( $this->is_blocked( $email ) ) {
// e-mail is in the list - so remove it
$stored = get_option( 'do_not_mail' );
$blocked = is_array( $stored ) ? $stored : explode( ' ', (string) $stored );
update_option( 'do_not_mail', implode( ' ', array_diff( $blocked, array( $email ) ) ) );
return true;
}
return false;
}
function has_subscribers() {
if ( count( $this->get_unique_subscribers() ) > 0 )
return true;
return false;
}
function get_unique_subscribers() {
global $comments, $comment, $sg_subscribers;
if ( isset( $sg_subscribers ) )
return $sg_subscribers;
$sg_subscribers = array();
$subscriber_emails = array();
// We run the comment loop, and put each unique subscriber into a new array
foreach ( (array) $comments as $comment ) {
if ( comment_subscription_status() && !in_array( $comment->comment_author_email, $subscriber_emails ) ) {
$sg_subscribers[] = $comment;
$subscriber_emails[] = $comment->comment_author_email;
}
}
return $sg_subscribers;
}
function hidden_form_fields() { ?>
settings['salt'] )
die( 'fatal error: corrupted salt' );
return md5( md5( $this->settings['salt'] . $data ) );
}
function change_email_key( $email, $new_email ) {
// Colons cannot occur in WordPress-validated addresses; bind an unambiguous pair and purpose.
return $this->generate_key( 'change_email:' . $email . ':' . $new_email );
}
function management_key_signature( $salt ) {
// Older author-accessible settings must not preseed a trusted migration marker and known salt.
return hash_hmac( 'sha256', 'stc-management-keys-v2:' . $salt, wp_salt( 'auth' ) );
}
/**
* Recognizes retired keys only to explain their rejection, never to grant access.
*/
function is_revoked_key() {
if ( !is_email( $this->email ) || !is_string( $this->key ) )
return false;
$salts = isset( $this->settings['revoked_salts'] ) ? (array) $this->settings['revoked_salts'] : array();
if ( !empty( $this->settings['revoked_salt'] ) )
$salts[] = $this->settings['revoked_salt'];
foreach ( array_unique( array_filter( $salts, 'is_string' ) ) as $salt ) {
foreach ( array( $this->email, $this->email . $this->new_email, 'change_email:' . $this->email . ':' . $this->new_email, $this->email . 'blockrequest', 'block:' . $this->email, 'opt_in:' . $this->email ) as $data ) {
if ( $this->key === md5( md5( $salt . $data ) ) )
return true;
}
}
return false;
}
function validate_key() {
$this->key_type = '';
// Reject retired links even for administrators, before their capability bypass.
if ( $this->is_revoked_key() )
return false;
if ( $this->key === $this->generate_key( $this->email ) )
$this->key_type = 'normal';
elseif ( is_email( $this->new_email ) && $this->key === $this->change_email_key( $this->email, $this->new_email ) && get_transient( 'stc_change_' . $this->key ) )
$this->key_type = 'change_email';
elseif ( $this->key === $this->generate_key( 'block:' . $this->email ) )
$this->key_type = 'block';
elseif ( $this->key === $this->generate_key( 'opt_in:' . $this->email ) )
$this->key_type = 'opt_in';
elseif ( current_user_can( 'manage_options' ) )
$this->key_type = 'admin';
else
return false;
return true;
}
function determine_action() {
// rather than check it a bunch of times
$is_email = is_email( $this->email );
if ( is_email( $this->new_email) && $is_email && $this->key_type == 'change_email' )
$this->action = 'change_email';
elseif ( $this->key_type == 'opt_in' && $is_email )
$this->action = 'opt_in';
elseif ( $this->post_action_requested( 'removesubscrips' ) && $is_email )
$this->action = 'remove_subscriptions';
elseif ( $this->post_action_requested( 'removeBlock' ) && $is_email && current_user_can( 'manage_options' ) )
$this->action = 'remove_block';
elseif ( $this->post_action_requested( 'changeemailrequest' ) && $is_email && is_email( $this->new_email ) )
$this->action = 'email_change_request';
elseif ( $is_email && $this->post_action_requested( 'blockemail' ) )
$this->action = 'block_request';
elseif ( $this->request_text( 'subscribeid' ) )
$this->action = 'solo_subscribe';
elseif ( $is_email && $this->request_text( 'blockemailconfirm' ) && $this->key === $this->generate_key( 'block:' . $this->email ) )
$this->action = 'block';
else
$this->action = 'none';
}
function remove_subscriber( $email, $postid, $bid = NULL ) {
global $wpdb, $blog_id;
$this->clear_subscription_cache();
$postid = (int) $postid;
$bid = absint( ( NULL == $bid ) ? $blog_id : $bid );
$email = strtolower( $email );
if ( $this->is_multisite() ) {
// phpcs:ignore WordPress.DB.DirectDatabaseQuery -- Custom network table; identifiers/values are prepared and the request-local cache was invalidated above.
if ( $wpdb->query( $wpdb->prepare( "DELETE FROM %i WHERE email = %s AND post_id = %d AND blog_id = %d", $this->ms_table, $email, $postid, $bid ) ) )
return true;
} else {
if ( delete_post_meta( $postid, '_sg_subscribe-to-comments', $email ) || delete_post_meta( $postid, '_sg_subscribe-to-comments-pending-with-email', $email ) || delete_post_meta( $postid, '_sg_subscribe-to-comments-pending', $email ) )
return true;
}
return false;
}
function remove_subscriptions ( $bid_post_ids ) {
global $wpdb;
$removed = 0;
if ( !is_array( $bid_post_ids ) )
return $removed;
foreach ( $bid_post_ids as $bp ) {
if ( !is_string( $bp ) || !preg_match( '/^[0-9]+-[0-9]+$/D', $bp ) )
continue;
$bp = array_map( 'absint', explode( '-', $bp ) );
// echo 'Removing BID: ' . $bp[0] . ' PID:' . $bp[1];
if ( $this->remove_subscriber( $this->email, $bp[1], $bp[0] ) )
$removed++;
}
return $removed;
}
function send_notifications( $cid ) {
global $wpdb;
$comment = get_comment( $cid );
if ( !$comment )
return $cid;
$post = get_post( $comment->comment_post_ID );
if ( $this->public_subscription_post( $post ) && $comment->comment_approved == '1' && in_array( $comment->comment_type, array( '', 'comment' ), true ) ) {
// Comment has been approved and isn't a trackback or a pingback, so we should send out notifications
$message = sprintf( /* translators: %s: post title. */ __( "There is a new comment on the post \"%s\"", 'subscribe-to-comments' ) . ". \n%s\n\n", $post->post_title, get_permalink( $comment->comment_post_ID ) );
$message .= sprintf( /* translators: %s: comment author name. */ __( "Author: %s\n", 'subscribe-to-comments' ), $comment->comment_author );
$message .= __( "Comment:\n", 'subscribe-to-comments' ) . $comment->comment_content . "\n\n";
$message .= __( "See all comments on this post here:\n", 'subscribe-to-comments' );
$message .= get_permalink( $comment->comment_post_ID ) . "#comments\n\n";
//add link to manage comment notifications
$message .= __( "To manage your subscriptions or to block all notifications from this site, click the link below:\n", 'subscribe-to-comments' );
$message .= get_option( 'home' ) . '/?wp-subscription-manager=1&email=[email]&key=[key]';
$subject = sprintf( /* translators: %s: post title. */ __( 'New Comment On: %s', 'subscribe-to-comments' ), $post->post_title );
$subscriptions = $this->subscriptions_from_post( $comment->comment_post_ID );
foreach ( (array) $subscriptions as $email ) {
if ( !$this->is_blocked( $email ) && $email != $comment->comment_author_email && is_email( $email ) ) {
$message_final = str_replace( '[email]', urlencode( $email ), $message );
$message_final = str_replace( '[key]', $this->generate_key( $email ), $message_final );
$this->send_mail( $email, $subject, $message_final );
}
} // foreach subscription
} // end if comment approved
return $cid;
}
function send_pending_nag( $cid ) {
$comment = get_comment( $cid );
return $comment ? $this->send_pending_confirmation( strtolower( $comment->comment_author_email ) ) : false;
}
function send_pending_confirmation( $email ) {
$throttle = 'stc_pending_' . md5( $email );
if ( get_transient( $throttle ) )
return false;
set_transient( $throttle, 1, DAY_IN_SECONDS );
$subject = __( 'Subscription Confirmation', 'subscribe-to-comments' );
$message = sprintf( /* translators: %s: site name. */ __( "You are receiving this message to confirm your comment subscription at \"%s\"\n\n", 'subscribe-to-comments' ), get_bloginfo( 'blogname' ) );
$message .= __( "To confirm your subscription, click this link:\n\n", 'subscribe-to-comments' );
$message .= get_option( 'home' ) . "/?wp-subscription-manager=1&email=" . urlencode( $email ) . "&key=" . $this->generate_key( 'opt_in:' . $email ) . "\n\n";
$message .= __( 'If you did not request this subscription, please disregard this message.', 'subscribe-to-comments' );
return $this->send_mail( $email, $subject, $message );
}
function change_email_request() {
if ( $this->is_blocked() || $this->is_blocked( $this->new_email ) )
return false;
set_transient( 'stc_change_' . $this->change_email_key( $this->email, $this->new_email ), 1, DAY_IN_SECONDS );
$subject = __( 'E-mail change confirmation', 'subscribe-to-comments' );
$message = sprintf( /* translators: %s: site name. */ __( "You are receiving this message to confirm a change of e-mail address for your subscriptions at \"%s\"\n\n", 'subscribe-to-comments' ), get_bloginfo( 'blogname' ) );
$message .= sprintf( /* translators: %s: new email address. */ __( "To change your e-mail address to %s, click this link:\n\n", 'subscribe-to-comments' ), $this->new_email );
$message .= get_option( 'home' ) . "/?wp-subscription-manager=1&email=" . urlencode( $this->email ) . "&new_email=" . urlencode( $this->new_email ) . "&key=" . $this->change_email_key( $this->email, $this->new_email ) . ".\n\n";
$message .= __( 'If you did not request this action, please disregard this message.', 'subscribe-to-comments' );
// The old address was authenticated by the request; only the destination inbox may approve the transfer.
return $this->send_mail( $this->new_email, $subject, $message );
}
function block_email_request( $email ) {
if ( $this->is_blocked( $email ) )
return false;
$subject = __( 'E-mail block confirmation', 'subscribe-to-comments' );
$message = sprintf( /* translators: %s: site name. */ __( "You are receiving this message to confirm that you no longer wish to receive e-mail comment notifications from \"%s\"\n\n", 'subscribe-to-comments' ), get_bloginfo( 'name' ) );
$message .= __( "To cancel all future notifications for this address, click this link:\n\n", 'subscribe-to-comments' );
$message .= get_option( 'home' ) . "/?wp-subscription-manager=1&email=" . urlencode( $email ) . "&key=" . $this->generate_key( 'block:' . $email ) . "&blockemailconfirm=true" . ".\n\n";
$message .= __( "If you did not request this action, please disregard this message.", 'subscribe-to-comments' );
return $this->send_mail( $email, $subject, $message );
}
function send_mail( $to, $subject, $message ) {
$subject = '[' . get_bloginfo( 'name' ) . '] ' . $subject;
// strip out some chars that might cause issues, and assemble vars
// Sanitize at send time as well, so previously saved settings cannot inject headers.
$site_name = str_replace( array( "\r", "\n", '"', '\\' ), array( '', '', "'", '' ), $this->site_name );
$site_email = sanitize_email( $this->site_email );
$charset = str_replace( array( "\r", "\n", '"' ), '', get_option( 'blog_charset' ) );
$headers = "From: \"{$site_name}\" <{$site_email}>\n";
$headers .= "MIME-Version: 1.0\n";
$headers .= "Content-Type: text/plain; charset=\"{$charset}\"\n";
return wp_mail( $to, $subject, $message, $headers );
}
function change_email() {
global $wpdb;
delete_transient( 'stc_change_' . $this->change_email_key( $this->email, $this->new_email ) );
$this->clear_subscription_cache();
$return = false;
$new_email = strtolower( $this->new_email );
$email = strtolower( $this->email );
// Core APIs invalidate comment/query and postmeta caches, including persistent object caches.
$comments = get_comments( array( 'author_email' => $email, 'status' => 'all', 'fields' => 'ids', 'number' => 0 ) );
foreach ( $comments as $comment_id ) {
if ( wp_update_comment( array( 'comment_ID' => $comment_id, 'comment_author_email' => $new_email ) ) )
$return = true;
}
$subscriptions = $this->subscription_query( $wpdb->prepare( "SELECT meta_id FROM %i WHERE meta_key = '_sg_subscribe-to-comments' AND LCASE(meta_value) = %s", $wpdb->postmeta, $email ), 'col' );
foreach ( $subscriptions as $meta_id ) {
if ( update_metadata_by_mid( 'post', $meta_id, $new_email ) )
$return = true;
}
// phpcs:ignore WordPress.DB.DirectDatabaseQuery -- Custom network table; wpdb escapes values and the request-local cache is invalidated before and after writes.
if ( $this->is_multisite() && $wpdb->update( $this->ms_table, array( 'email' => $new_email ), array( 'email' => $email ) ) )
$return = true;
$this->clear_subscription_cache();
return $return;
}
function entry_link( $bid, $postid, $uri='') {
global $blog_id;
$switched = false;
if ( $blog_id != $bid ) {
$switched = true;
switch_to_blog( $bid );
}
$postid = absint( $postid );
$post = $postid ? get_post( $postid ) : false;
if ( !$post && !empty( $uri ) ) {
// An external return URL has no WordPress post or title; never resolve ID zero to the manager.
$output = '' . esc_html__( 'click here', 'subscribe-to-comments' ) . '';
} elseif ( !$post || ( !is_post_publicly_viewable( $post ) && ( !get_post_type_object( $post->post_type ) || !current_user_can( 'read_post', $postid ) ) ) ) {
$output = esc_html__( 'Unavailable post', 'subscribe-to-comments' );
} else {
if ( empty( $uri ) )
$uri = get_permalink( $postid );
$uri = esc_url( $uri, array( 'http', 'https' ) );
$title = get_the_title( $postid );
if ( empty( $title ) )
$title = __( 'click here', 'subscribe-to-comments' );
$output = ''. esc_html( get_option( 'blogname' ) ) . ' → ' . esc_html( $title ).'';
}
if ( $switched )
restore_current_blog();
return $output;
}
function admin_head() { ?>
settings['management_keys_rotated'] ) )
return;
echo '
' . esc_html( __( 'Subscribe to Comments: Subscription-management keys have been rotated following a security update. Links in older e-mails have been revoked, but subscriptions have not been removed. New notification e-mails will contain working management links.', 'subscribe-to-comments' ) ) . '
';
// Show the notice once, to an administrator, rather than on every admin page.
$this->settings['management_keys_rotated'] = false;
$this->update_settings( $this->settings );
}
function db_upgrade_check () {
global $wpdb, $blog_id;
$update = false;
// add the options
$fresh_install = add_option( 'sg_subscribe_settings', array( 'use_custom_style' => '', 'email' => get_bloginfo( 'admin_email' ), 'name' => get_bloginfo( 'name' ), 'header' => '[theme_path]/header.php', 'sidebar' => '', 'footer' => '[theme_path]/footer.php', 'before_manager' => '
', 'after_manager' => '
', 'not_subscribed_text' => __( 'Notify me of followup comments via e-mail', 'subscribe-to-comments' ), 'subscribed_text' => __( 'You are subscribed to this entry. Manage your subscriptions.', 'subscribe-to-comments' ), 'author_text' => __( 'You are the author of this entry. Manage subscriptions.', 'subscribe-to-comments' ), 'version' => 0, 'management_key_version' => 2, 'double_opt_in' => '', 'subscribed_format' => '%NAME%' ) );
$settings = $this->get_options();
if ( $fresh_install ) {
$settings['salt'] = wp_generate_password( 64, true, true );
$settings['management_key_signature'] = $this->management_key_signature( $settings['salt'] );
$update = true;
}
// Existing installations must revoke keys that may have been disclosed before the security fix.
// Fresh installations start at this key version and have no retired links to recognize.
$signature = isset( $settings['salt'] ) && is_string( $settings['salt'] ) ? $this->management_key_signature( $settings['salt'] ) : '';
if ( !isset( $settings['management_key_version'], $settings['management_key_signature'] ) || 2 !== (int) $settings['management_key_version'] || !is_string( $settings['management_key_signature'] ) || '' === $signature || !hash_equals( $signature, $settings['management_key_signature'] ) ) {
$salts = isset( $settings['revoked_salts'] ) ? (array) $settings['revoked_salts'] : array();
if ( !empty( $settings['revoked_salt'] ) )
$salts[] = $settings['revoked_salt'];
if ( array_key_exists( 'salt', $settings ) ) {
// Legacy concatenation coerced arrays to "Array" and null/false to an empty string.
$retired = is_array( $settings['salt'] ) ? 'Array' : ( is_scalar( $settings['salt'] ) ? (string) $settings['salt'] : '' );
$salts[] = $retired;
$settings['revoked_salt'] = $retired;
}
$settings['revoked_salts'] = array_values( array_unique( array_filter( $salts, 'is_string' ) ) );
$settings['salt'] = wp_generate_password( 64, true, true );
$settings['management_key_version'] = 2;
$settings['management_key_signature'] = $this->management_key_signature( $settings['salt'] );
$settings['management_keys_rotated'] = true;
$update = true;
}
if ( !isset( $settings['salt'] ) ) {
$settings['salt'] = wp_generate_password( 64, true, true );
$update = true;
}
if ( !isset( $settings['clear_both'] ) ) {
$settings['clear_both'] = 'clear_both';
$update = true;
}
if ( !isset( $settings['version'] ) ) {
$settings = stripslashes_deep( $settings );
$settings['version'] = '0';
$update = true;
}
if ( !isset( $settings['double_opt_in'] ) ) {
$settings['double_opt_in'] = '';
$update = true;
}
if ( !isset( $settings['subscribed_format'] ) ) {
$settings['subscribed_format'] = '%NAME%';
$update = true;
}
if ( !$this->is_multisite() && version_compare( $settings['version'], '2.2', '<' ) ) { // Upgrade to postmeta-driven subscriptions
foreach ( (array) $this->subscription_query( $wpdb->prepare( 'DESC %i', $wpdb->comments ), 'col' ) as $column ) {
if ( $column == 'comment_subscribe' ) {
$upgrade_comments = $this->subscription_query( $wpdb->prepare( "SELECT comment_post_ID, comment_author_email FROM %i WHERE comment_subscribe = 'Y'", $wpdb->comments ) );
foreach ( (array) $upgrade_comments as $upgrade_comment )
$this->add_subscriber_by_post_id_and_email( $upgrade_comment->comment_post_ID, $upgrade_comment->comment_author_email, $blog_id );
// Done. Drop the column
// phpcs:ignore WordPress.DB.DirectDatabaseQuery -- One-time pre-2.2 schema migration after copying subscriptions; no core API removes legacy columns.
$wpdb->query( $wpdb->prepare( 'ALTER TABLE %i DROP COLUMN comment_subscribe', $wpdb->comments ) );
$this->clear_subscription_cache();
}
}
$update = true;
}
elseif ( $this->is_multisite() && ( version_compare( $settings['version'], '2.2', '<' ) || !isset( $settings['version'] ) ) ) {
// Create WPMU tables
if ( $wpdb->has_cap( 'collation' ) ) {
if ( ! empty( $wpdb->charset ) )
$charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
if ( ! empty( $wpdb->collate ) )
$charset_collate .= " COLLATE $wpdb->collate";
}
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
$queries = "CREATE TABLE IF NOT EXISTS $this->ms_table (
id int(11) NOT NULL auto_increment,
email varchar(100) NOT NULL,
blog_id int(11) NOT NULL default 0,
post_id int(11) NOT NULL default 0,
date_gmt datetime NOT NULL default '0000-00-00 00:00:00',
status varchar(20) NOT NULL default '',
PRIMARY KEY (id),
KEY email_blog_post_status (email,blog_id,post_id,status),
KEY email_status (email,status)
) $charset_collate";
dbDelta( $queries );
}
if ( $update || !isset( $settings['version'] ) )
$this->update_settings( $settings );
}
function update_settings( $settings ) {
$settings['version'] = $this->version;
$settings = $this->sanitize_settings( $settings );
update_option( 'sg_subscribe_settings', $settings );
}
function sanitize_settings( $settings ) {
$settings = wp_parse_args( $settings, array( 'use_custom_style' => '', 'clear_both' => '', 'double_opt_in' => '', 'subscribed_format' => '%NAME%' ) );
foreach ( array( 'name', 'email', 'header', 'sidebar', 'footer', 'before_manager', 'after_manager', 'not_subscribed_text', 'subscribed_text', 'author_text', 'subscribed_format' ) as $field ) {
if ( !isset( $settings[$field] ) || !is_string( $settings[$field] ) )
$settings[$field] = '';
}
if ( isset( $settings['name'] ) )
$settings['name'] = sanitize_text_field( $settings['name'] );
if ( isset( $settings['email'] ) )
$settings['email'] = sanitize_email( $settings['email'] );
if ( strpos( $settings['subscribed_format'], '%NAME%' ) === false ) {
$settings['subscribed_format'] = '%NAME%';
}
if ( ! empty( $settings['header'] ) ) {
$settings['header'] = '[theme_path]/header.php';
}
if ( ! empty( $settings['sidebar'] ) ) {
$settings['sidebar'] = '[theme_path]/sidebar.php';
}
if ( ! empty( $settings['footer'] ) ) {
$settings['footer'] = '[theme_path]/footer.php';
}
return $settings;
}
function current_viewer_subscription_status(){
global $post;
// Neither unsigned comment cookies nor self-edited account emails prove inbox ownership.
// Administrators already have authority over all records; other users use emailed bearer links.
$user = wp_get_current_user();
if ( !current_user_can( 'manage_options' ) || !$user->ID || !is_email( $user->user_email ) )
return false;
$email = strtolower( $user->user_email );
$post_author = get_userdata( $post->post_author );
if ( $post_author && strtolower( $post_author->user_email ) == $email )
return 'admin';
if ( in_array( $email, (array) $this->subscriptions_from_post( $post->ID ) ) )
return $email;
return false;
}
function manage_link( $email='', $html=true, $echo=true ) {
// Account emails can be self-edited through REST without inbox verification.
// Only administrators may generate keys here; everyone else proves ownership through emailed links.
if ( !current_user_can( 'manage_options' ) )
return '';
$link = get_option( 'home' ) . '/?wp-subscription-manager=1';
if ( $email != 'admin' ) {
$link = add_query_arg( 'email', urlencode( $email ), $link );
$link = add_query_arg( 'key', $this->generate_key( $email ), $link );
}
$ref = get_permalink();
if ( !$ref )
$ref = home_url( '/' );
$link = add_query_arg( 'ref', rawurlencode( $ref ), $link );
//$link = str_replace('+', '%2B', $link);
if ( $html )
$link = esc_url( $link );
if ( !$echo )
return $link;
echo esc_url( $link );
}
function on_edit( $cid ) {
global $blog_id;
$comment = get_comment( $cid );
if ( !$comment )
return $cid;
$email = strtolower( $comment->comment_author_email );
$postid = $comment->comment_post_ID;
if ( !is_email( $email ) )
_stc()->remove_subscriber( $email, $postid, $blog_id );
return $cid;
}
function on_delete( $cid ) {
global $blog_id;
$comment = get_comment( $cid );
if ( !$comment )
return $cid;
$email = strtolower( $comment->comment_author_email );
$postid = $comment->comment_post_ID;
_stc()->remove_subscriber( $email, $postid, $blog_id );
return $cid;
}
function get_comment_author_format() {
if ( strpos( $this->subscribed_format, '%NAME%' ) === false )
return '%NAME%';
else
return $this->subscribed_format;
}
function comment_author_filter( $author ) {
if ( comment_subscription_status() )
$author = str_replace( '%NAME%', $author, $this->get_comment_author_format() );
return $author;
}
function add_admin_menu() {
$manager_callback = add_submenu_page( 'edit-comments.php', __( 'Comment Subscription Manager', 'subscribe-to-comments' ), __( 'Subscriptions', 'subscribe-to-comments' ), 'manage_options', 'stc-management', 'sg_subscribe_admin' );
add_action( "load-{$manager_callback}", array( $this, 'check_manager_request' ) );
$opt_callback = add_options_page( __( 'Subscribe to Comments', 'subscribe-to-comments' ), __( 'Subscribe to Comments', 'subscribe-to-comments' ), 'manage_options', 'stc-options', array( _stc(), 'options_page' ) );
add_action( "load-{$opt_callback}", array( _stc(), 'save_options' ) );
}
//////////////////// OPTIONS ////////////////////////
function tr( $option_slug, $option_title, $option_text, $description ='' ) {
echo "
\n\t
\n\t
";
// Static form-control markup assembled below; all interpolated settings use form_setting()/textarea_setting().
echo $option_text; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Escaped control templates, not request-supplied HTML.
if ( !empty( $description ) )
echo '' . wp_kses_post( $description ) . '';
echo "
\n
\n";
}
function save_options() {
if ( isset( $_POST['sg_subscribe_settings_submit'] ) ) {
if ( !current_user_can( 'manage_options' ) )
wp_die( esc_html__( 'You do not have permission to change these settings.', 'subscribe-to-comments' ) );
check_admin_referer( 'subscribe-to-comments-update_options' );
if ( !isset( $_POST['sg_subscribe_settings'] ) || !is_array( $_POST['sg_subscribe_settings'] ) )
wp_die( esc_html__( 'Invalid settings.', 'subscribe-to-comments' ) );
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Types are checked below; update_settings() applies field-specific sanitization to the complete array.
$update_settings = wp_unslash( $_POST['sg_subscribe_settings'] );
foreach ( $update_settings as $value ) {
if ( !is_string( $value ) )
wp_die( esc_html__( 'Invalid settings.', 'subscribe-to-comments' ), '', array( 'response' => 400 ) );
}
// These private fields are not editable form settings. Preserve them across saves.
$current_settings = $this->get_options();
foreach ( array( 'salt', 'revoked_salt', 'revoked_salts', 'management_key_version', 'management_key_signature', 'management_keys_rotated', 'manage_id' ) as $field ) {
unset( $update_settings[$field] );
if ( isset( $current_settings[$field] ) )
$update_settings[$field] = $current_settings[$field];
}
_stc()->update_settings( $update_settings );
wp_safe_redirect( add_query_arg( 'updated', '1', menu_page_url( 'stc-options', false ) ) );
add_settings_error( 'general', 'settings_updated', esc_html__( 'Settings saved.', 'subscribe-to-comments' ), 'updated' );
set_transient( 'settings_errors', get_settings_errors(), 30 );
exit();
}
}
function options_page_contents() {
echo '
';
$this->tr( 'name', __( '"From" name', 'subscribe-to-comments' ), '' );
$this->tr( 'email', __( '"From" address', 'subscribe-to-comments' ), '', __( 'You may want this to be a special account that you set up for this purpose, as it will go out to everyone who subscribes', 'subscribe-to-comments' ) );
$this->tr( 'double_opt_in', __( 'Double opt-in', 'subscribe-to-comments' ), 'checkflag( 'double_opt_in' ) . ' /> ' );
echo '
';
echo '
' . esc_html__( 'Subscriber name formatting', 'subscribe-to-comments' ) . '
';
echo '
';
$this->tr( 'subscribed_format', __( 'Subscribed format', 'subscribe-to-comments' ), '', __( 'e.g. %NAME% (subscribed) will display John Smith (subscribed)', 'subscribe-to-comments' ) );
echo '
';
echo '
' . esc_html__( 'Comment form layout', 'subscribe-to-comments' ) . '
' . esc_html__( 'Comment form text', 'subscribe-to-comments' ) . '
';
echo '
' . wp_kses_post( __( 'Customize the messages shown to different people. Use [manager_link] to insert the URI to the Subscription Manager.', 'subscribe-to-comments' ) ) . '
' . wp_kses_post( __( 'These settings only matter if you are using a custom style. [theme_path] will be replaced with the path to your current theme.', 'subscribe-to-comments' ) ) . '
';
echo '
';
$this->tr( 'header', __( 'Path to header', 'subscribe-to-comments' ), '' );
$this->tr( 'sidebar', __( 'Path to sidebar', 'subscribe-to-comments' ), '' );
$this->tr( 'footer', __( 'Path to footer', 'subscribe-to-comments' ), '' );
$this->tr( 'before_manager', __( 'HTML for before the subscription manager', 'subscribe-to-comments' ), '' );
$this->tr( 'after_manager', __( 'HTML for after the subscription manager', 'subscribe-to-comments' ), '' );
echo '
';
echo '
';
}
function get_options() {
return $this->sanitize_settings( get_option( 'sg_subscribe_settings' ) );
}
function checkflag( $optname ) {
$options = $this->get_options();
if ( !isset( $options[$optname] ) || $options[$optname] != $optname )
return;
return ' checked="checked"';
}
/**
* Returns an HTML attribute sanitized version of a setting
* @param string $option_name The name of the STC option to fetch
* @return string the sanitized setting
*/
function form_setting( $option_name ) {
$options = $this->get_options();
if ( isset( $options[$option_name] ) )
return esc_attr( $options[$option_name] );
else
return '';
}
function textarea_setting( $optname ) {
$options = $this->get_options();
if ( isset( $options[$optname] ) )
return esc_textarea( $options[$optname] );
else
return '';
}
function options_page() {
if ( !current_user_can( 'manage_options' ) )
wp_die( esc_html__( 'You do not have permission to change these settings.', 'subscribe-to-comments' ) );
echo '';
}
} // class sg_subscribe
function stc_checkbox_state( $data ) {
if ( _stc()->comment_subscribe_requested() )
setcookie( 'subscribe_checkbox_'. COOKIEHASH, 'checked', time() + 30000000, COOKIEPATH );
else
setcookie( 'subscribe_checkbox_'. COOKIEHASH, 'unchecked', time() + 30000000, COOKIEPATH );
return $data;
}
function stc_comment_author_filter( $author ) {
return _stc()->comment_author_filter( $author );
}
function sg_subscribe_start() {
_stc();
}
function sg_subscribe_admin_standalone() {
sg_subscribe_admin( true );
}
function sg_subscribe_admin( $standalone = false ) {
global $wpdb, $sg_subscribe, $wp_version, $blog_id;
if ( $standalone ) {
_stc()->form_action = get_option( 'home' ) . '/?wp-subscription-manager=1';
_stc()->standalone = true;
} else {
_stc()->form_action = 'edit-comments.php?page=stc-management';
_stc()->standalone = false;
}
_stc()->check_manager_request();
_stc()->determine_action();
switch ( _stc()->action ) :
case "opt_in" :
if ( _stc()->confirm_pending_subscriber( _stc()->email ) ) {
_stc()->add_message( sprintf( /* translators: %1$s: confirmed email address. */ __( 'Thank you! %1$s has been confirmed, and is now subscribed to comments.', 'subscribe-to-comments' ), _stc()->email ) );
}
// Inbox proof permits a normal manager session; subsequent form submissions must not re-run confirmation.
_stc()->key = _stc()->generate_key( _stc()->email );
_stc()->validate_key();
break;
case "change_email" :
if ( _stc()->change_email() ) {
_stc()->add_message( sprintf( /* translators: 1: old email address, 2: new email address. */ __( 'All notifications that were formerly sent to %1$s will now be sent to %2$s!', 'subscribe-to-comments' ), _stc()->email, _stc()->new_email ) );
// change info to the new email
_stc()->email = _stc()->new_email;
_stc()->new_email = '';
_stc()->key = _stc()->generate_key( _stc()->email );
_stc()->validate_key();
}
break;
case "remove_subscriptions" :
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- check_manager_request() has verified the manager nonce before this dispatch.
$selected = isset( $_POST['subscrips'] ) && is_array( $_POST['subscrips'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['subscrips'] ) ) : array();
$postsremoved = _stc()->remove_subscriptions( $selected );
if ( $postsremoved > 0 )
_stc()->add_message( sprintf( /* translators: 1: count, 2: subscription or subscriptions. */ __( '%1$s %2$s removed successfully.', 'subscribe-to-comments' ), $postsremoved, ( $postsremoved != 1 ) ? __( 'subscriptions', 'subscribe-to-comments' ) : __( 'subscription', 'subscribe-to-comments' ) ) );
break;
case "remove_block" :
if ( _stc()->remove_block( _stc()->email ) )
_stc()->add_message( sprintf( /* translators: %s: email address. */ __( 'The block on %s has been successfully removed.', 'subscribe-to-comments' ), _stc()->email ) );
else
_stc()->add_error( sprintf( /* translators: %s: email address. */ __( '%s isn\'t blocked!', 'subscribe-to-comments' ), _stc()->email ), 'manager' );
break;
case "email_change_request" :
if ( _stc()->is_blocked( _stc()->email ) )
_stc()->add_error( sprintf( /* translators: %s: email address. */ __( '%s has been blocked from receiving notifications. You will have to have the administrator remove the block before you will be able to change your notification address.', 'subscribe-to-comments' ), _stc()->email ) );
else
if ( _stc()->change_email_request( _stc()->email, _stc()->new_email ) )
_stc()->add_message( sprintf( /* translators: %s: destination email address. */ __( 'Your change of e-mail request was successfully received. Please check the new account (%s) in order to confirm the change.', 'subscribe-to-comments' ), _stc()->new_email ) );
break;
case "block_request" :
if ( _stc()->block_email_request( _stc()->email ) )
_stc()->add_message( sprintf( /* translators: %s: email address. */ __( 'Your request to block %s from receiving any further notifications has been received. In order for you to complete the block, please check your e-mail and click on the link in the message that has been sent to you.', 'subscribe-to-comments' ), _stc()->email ) );
break;
case "solo_subscribe" :
_stc()->add_message( sprintf( /* translators: 1: email address, 2: linked post title. */ __( '%1$s has been successfully subscribed to %2$s', 'subscribe-to-comments' ), _stc()->email, _stc()->entry_link( $blog_id, absint( _stc()->request_text( 'subscribeid' ) ) ) ) );
break;
case "block" :
if ( _stc()->add_block( _stc()->email ) )
_stc()->add_message( sprintf( /* translators: 1: blocked email address, 2: administrator email address. */ __( '%1$s has been added to the "do not mail" list. You will no longer receive any notifications from this site. If this was done in error, please contact the site administrator to remove this block.', 'subscribe-to-comments' ), _stc()->email, _stc()->site_email ) );
else
_stc()->add_error( sprintf( /* translators: %s: email address. */ __( '%s has already been blocked!', 'subscribe-to-comments' ), _stc()->email), 'manager');
_stc()->key = _stc()->generate_key( _stc()->email );
_stc()->validate_key();
break;
endswitch;
?>
show_messages(); ?>
show_errors(); ?>
standalone ) : ?>
ref ) ) : ?>
add_message( sprintf( /* translators: %s: linked post title. */ __( 'Return to the page you were viewing: %s', 'subscribe-to-comments' ), _stc()->entry_link( $blog_id, url_to_postid( _stc()->ref ), _stc()->ref ) ) ); ?>
show_messages(); ?>
is_blocked() ) { ?>
%s. This should only be done if the user has specifically requested it.', 'subscribe-to-comments' ), esc_html( _stc()->email ) ) ); ?>
%1$s from this site. If this is incorrect, or if you wish to have the block removed, please contact the site administrator.', 'subscribe-to-comments' ), esc_html( _stc()->email ), esc_attr( _stc()->site_email ) ) ); ?>
subscriptions_from_email(); ?>
email ) && !is_array( $postlist ) && _stc()->email != _stc()->site_email && _stc()->email != get_bloginfo( 'admin_email' ) ) {
if ( is_email( _stc()->email ) )
_stc()->add_error( sprintf( /* translators: %s: email address. */ __( '%s is not subscribed to any posts on this site.', 'subscribe-to-comments' ), _stc()->email ) );
else
_stc()->add_error( sprintf( /* translators: %s: email address. */ __( '%s is not a valid e-mail address.', 'subscribe-to-comments' ), _stc()->email ) );
}
?>
show_errors(); ?>
email ) : ?>
email ) : ?>
request_text( 'showallsubscribers' ) ) : ?>
request_text( 'showallsubscribers' ) ? PHP_INT_MAX : 25;
if ( _stc()->is_multisite() ) {
$all_pm_subscriptions = _stc()->subscription_query( $wpdb->prepare( "SELECT email, count(post_id) as ccount FROM %i WHERE status = 'active' GROUP BY email ORDER BY ccount DESC LIMIT %d", _stc()->ms_table, $stc_limit ) );
} else {
$all_pm_subscriptions = _stc()->subscription_query( $wpdb->prepare( "SELECT LCASE(meta_value) as email, count(post_id) as ccount FROM %i WHERE meta_key = '_sg_subscribe-to-comments' GROUP BY email ORDER BY ccount DESC LIMIT %d", $wpdb->postmeta, $stc_limit ) );
}
$all_subscriptions = array();
foreach ( (array) $all_pm_subscriptions as $sub ) {
if ( !isset( $all_subscriptions[$sub->email] ) )
$all_subscriptions[$sub->email] = (int) $sub->ccount;
else
$all_subscriptions[$sub->email] += (int) $sub->ccount;
}
if ( !_stc()->request_text( 'showallsubscribers' ) ) : ?>
%s is subscribed to the posts listed below. To unsubscribe to one or more posts, click the checkbox next to the title, then click "Remove Selected Subscription(s)" at the bottom of the list.', 'subscribe-to-comments' ), esc_html( _stc()->email ) ) ); ?>