File Editor
Directories:
.. (Back)
carousel
cloudflare-analytics
comment-likes
comments
custom-css
custom-post-types
geo-location
google-fonts
gravatar
infinite-scroll
likes
markdown
masterbar
memberships
photon-cdn
plugin-search
post-by-email
related-posts
scan
seo-tools
sharedaddy
shortcodes
simple-payments
site-icon
sitemaps
sso
stats
subscriptions
theme-tools
tiled-gallery
verification-tools
videopress
widget-visibility
widgets
woocommerce-analytics
wordads
wpcom-tos
Files:
blaze.php
carousel.php
comment-likes.php
comments.php
contact-form.php
copy-post.php
custom-content-types.php
custom-css.php
geo-location.php
google-fonts.php
gravatar-hovercards.php
infinite-scroll.php
json-api.php
latex.php
likes.php
markdown.php
masterbar.php
module-extras.php
module-headings.php
module-info.php
monitor.php
notes.php
photon-cdn.php
photon.php
plugin-search.php
post-by-email.php
post-list.php
protect.php
publicize.php
related-posts.php
search.php
seo-tools.php
sharedaddy.php
shortcodes.php
shortlinks.php
sitemaps.php
sso.php
stats.php
subscriptions.php
theme-tools.php
tiled-gallery.php
vaultpress.php
verification-tools.php
videopress.php
waf.php
widget-visibility.php
widgets.php
woocommerce-analytics.php
wordads.php
wpgroho.js
Create New File
Create
Edit File: subscriptions.php
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName) /** * Module Name: Newsletter * Module Description: Let visitors subscribe to new posts and comments via email * Sort Order: 9 * Recommendation Order: 8 * First Introduced: 1.2 * Requires Connection: Yes * Requires User Connection: Yes * Auto Activate: No * Module Tags: Social * Feature: Engagement * Additional Search Queries: subscriptions, subscription, email, follow, followers, subscribers, signup, newsletter, creator */ // phpcs:disable Universal.Files.SeparateFunctionsFromOO.Mixed -- TODO: Move classes to appropriately-named class files. use Automattic\Jetpack\Connection\Manager as Connection_Manager; use Automattic\Jetpack\Connection\XMLRPC_Async_Call; use Automattic\Jetpack\Redirect; use Automattic\Jetpack\Status; use Automattic\Jetpack\Status\Host; add_action( 'jetpack_modules_loaded', 'jetpack_subscriptions_load' ); // Loads the User Content Link Redirection feature. require_once __DIR__ . '/subscriptions/jetpack-user-content-link-redirection.php'; /** * Loads the Subscriptions module. */ function jetpack_subscriptions_load() { Jetpack::enable_module_configurable( __FILE__ ); } /** * Cherry picks keys from `$_SERVER` array. * * @since 6.0.0 * * @return array An array of server data. */ function jetpack_subscriptions_cherry_pick_server_data() { $data = array(); foreach ( $_SERVER as $key => $value ) { if ( ! is_string( $value ) || str_starts_with( $key, 'HTTP_COOKIE' ) ) { continue; } if ( str_starts_with( $key, 'HTTP_' ) || in_array( $key, array( 'REMOTE_ADDR', 'REQUEST_URI', 'DOCUMENT_URI' ), true ) ) { $data[ $key ] = $value; } } return $data; } /** * Main class file for the Subscriptions module. */ class Jetpack_Subscriptions { /** * Whether Jetpack has been instantiated or not. * * @var bool */ public $jetpack = false; /** * Hash of the siteurl option. * * @var string */ public static $hash; /** * Singleton * * @static */ public static function init() { static $instance = false; if ( ! $instance ) { $instance = new Jetpack_Subscriptions(); } return $instance; } /** * Jetpack_Subscriptions constructor. */ public function __construct() { $this->jetpack = Jetpack::init(); // Don't use COOKIEHASH as it could be shared across installs && is non-unique in multisite. // @see: https://twitter.com/nacin/status/378246957451333632 . self::$hash = md5( get_option( 'siteurl' ) ); add_filter( 'jetpack_xmlrpc_methods', array( $this, 'xmlrpc_methods' ) ); // @todo remove sync from subscriptions and move elsewhere... // Add Configuration Page. add_action( 'admin_init', array( $this, 'configure' ) ); // Catch subscription widget submits. if ( isset( $_REQUEST['jetpack_subscriptions_widget'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce checked in widget_submit() for logged in users. add_action( 'template_redirect', array( $this, 'widget_submit' ) ); } // Set up the comment subscription checkboxes. add_filter( 'comment_form_submit_field', array( $this, 'comment_subscribe_init' ), 10, 2 ); // Catch comment posts and check for subscriptions. add_action( 'comment_post', array( $this, 'comment_subscribe_submit' ), 50, 2 ); // Adds post meta checkbox in the post submit metabox. add_action( 'post_submitbox_misc_actions', array( $this, 'subscription_post_page_metabox' ) ); add_action( 'transition_post_status', array( $this, 'maybe_send_subscription_email' ), 10, 3 ); add_filter( 'jetpack_published_post_flags', array( $this, 'set_post_flags' ), 10, 2 ); add_filter( 'post_updated_messages', array( $this, 'update_published_message' ), 18, 1 ); // Set "social_notifications_subscribe" option during the first-time activation. add_action( 'jetpack_activate_module_subscriptions', array( $this, 'set_social_notifications_subscribe' ) ); // Hide subscription messaging in Publish panel for posts that were published in the past add_action( 'init', array( $this, 'register_post_meta' ), 20 ); add_action( 'transition_post_status', array( $this, 'maybe_set_first_published_status' ), 10, 3 ); // Add Subscribers menu to Jetpack navigation. add_action( 'jetpack_admin_menu', array( $this, 'add_subscribers_menu' ) ); // Customize the configuration URL to lead to the Subscriptions settings. add_filter( 'jetpack_module_configuration_url_subscriptions', function () { return Jetpack::admin_url( array( 'page' => 'jetpack#/newsletter' ) ); } ); // Track categories created through the category editor page add_action( 'wp_ajax_add-tag', array( $this, 'track_newsletter_category_creation' ), 1 ); } /** * Jetpack_Subscriptions::xmlrpc_methods() * * Register subscriptions methods with the Jetpack XML-RPC server. * * @param array $methods Methods being registered. */ public function xmlrpc_methods( $methods ) { return array_merge( $methods, array( 'jetpack.subscriptions.subscribe' => array( $this, 'subscribe' ), ) ); } /** * Disable Subscribe on Single Post * Register post meta */ public function subscription_post_page_metabox() { if ( /** * Filter whether or not to show the per-post subscription option. * * @module subscriptions * * @since 3.7.0 * * @param bool true = show checkbox option on all new posts | false = hide the option. */ ! apply_filters( 'jetpack_allow_per_post_subscriptions', false ) ) { return; } if ( has_filter( 'jetpack_subscriptions_exclude_these_categories' ) || has_filter( 'jetpack_subscriptions_include_only_these_categories' ) ) { return; } global $post; $disable_subscribe_value = get_post_meta( $post->ID, '_jetpack_dont_email_post_to_subs', true ); // only show checkbox if post hasn't been published and is a 'post' post type. if ( get_post_status( $post->ID ) !== 'publish' && get_post_type( $post->ID ) === 'post' ) : // Nonce it. wp_nonce_field( 'disable_subscribe', 'disable_subscribe_nonce' ); ?> <div class="misc-pub-section"> <label for="_jetpack_dont_email_post_to_subs"><?php esc_html_e( 'Jetpack Subscriptions:', 'jetpack' ); ?></label><br> <input type="checkbox" name="_jetpack_dont_email_post_to_subs" id="jetpack-per-post-subscribe" value="1" <?php checked( $disable_subscribe_value, 1, true ); ?> /> <?php esc_html_e( 'Don’t send this to subscribers', 'jetpack' ); ?> </div> <?php endif; } /** * Checks whether or not the post should be emailed to subscribers * * It checks for the following things in order: * - Usage of filter jetpack_subscriptions_exclude_these_categories * - Usage of filter jetpack_subscriptions_include_only_these_categories * - Existence of the per-post checkbox option * * Only one of these can be used at any given time. * * @param string $new_status Tthe "new" post status of the transition when saved. * @param string $old_status The "old" post status of the transition when saved. * @param object $post obj The post object. */ public function maybe_send_subscription_email( $new_status, $old_status, $post ) { if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return; } // Make sure that the checkbox is preseved. if ( ! empty( $_POST['disable_subscribe_nonce'] ) && wp_verify_nonce( $_POST['disable_subscribe_nonce'], 'disable_subscribe' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- WP Core doesn't unslash or sanitize nonces either. $set_checkbox = isset( $_POST['_jetpack_dont_email_post_to_subs'] ) ? 1 : 0; update_post_meta( $post->ID, '_jetpack_dont_email_post_to_subs', $set_checkbox ); } } /** * Message used when publishing a post. * * @param array $messages Message array for a post. */ public function update_published_message( $messages ) { global $post; if ( ! $this->should_email_post_to_subscribers( $post ) ) { return $messages; } $view_post_link_html = sprintf( ' <a href="%1$s">%2$s</a>', esc_url( get_permalink( $post ) ), __( 'View post', 'jetpack' ) ); $messages['post'][6] = sprintf( /* translators: Message shown after a post is published */ esc_html__( 'Post published and sending emails to subscribers.', 'jetpack' ) ) . $view_post_link_html; return $messages; } /** * Determine if a post should notifiy subscribers via email. * * @param object $post The post. */ public function should_email_post_to_subscribers( $post ) { $should_email = true; if ( get_post_meta( $post->ID, '_jetpack_dont_email_post_to_subs', true ) ) { return false; } // Only posts are currently supported. if ( 'post' !== $post->post_type ) { return false; } // Private posts are not sent to subscribers. if ( 'private' === $post->post_status ) { return false; } /** * Array of categories that will never trigger subscription emails. * * Will not send subscription emails from any post from within these categories. * * @module subscriptions * * @since 3.7.0 * * @param array $args Array of category slugs or ID's. */ $excluded_categories = apply_filters( 'jetpack_subscriptions_exclude_these_categories', array() ); // Never email posts from these categories. if ( ! empty( $excluded_categories ) && in_category( $excluded_categories, $post->ID ) ) { $should_email = false; } /** * ONLY send subscription emails for these categories * * Will ONLY send subscription emails to these categories. * * @module subscriptions * * @since 3.7.0 * * @param array $args Array of category slugs or ID's. */ $only_these_categories = apply_filters( 'jetpack_subscriptions_exclude_all_categories_except', array() ); // Only emails posts from these categories. if ( ! empty( $only_these_categories ) && ! in_category( $only_these_categories, $post->ID ) ) { $should_email = false; } return $should_email; } /** * Retrieve which flags should be added to a particular post. * * @param array $flags Flags to be added. * @param object $post A post object. */ public function set_post_flags( $flags, $post ) { $flags['send_subscription'] = $this->should_email_post_to_subscribers( $post ); return $flags; } /** * Jetpack_Subscriptions::configure() * * Jetpack Subscriptions configuration screen. */ public function configure() { // Create the section. add_settings_section( 'jetpack_subscriptions', __( 'Jetpack Subscriptions Settings', 'jetpack' ), array( $this, 'subscriptions_settings_section' ), 'discussion' ); /** Subscribe to Posts */ add_settings_field( 'jetpack_subscriptions_post_subscribe', __( 'Follow Blog', 'jetpack' ), array( $this, 'subscription_post_subscribe_setting' ), 'discussion', 'jetpack_subscriptions' ); register_setting( 'discussion', 'stb_enabled' ); /** Subscribe to Comments */ add_settings_field( 'jetpack_subscriptions_comment_subscribe', __( 'Follow Comments', 'jetpack' ), array( $this, 'subscription_comment_subscribe_setting' ), 'discussion', 'jetpack_subscriptions' ); register_setting( 'discussion', 'stc_enabled' ); /** Enable Subscribe Modal */ add_settings_field( 'jetpack_subscriptions_comment_subscribe', __( 'Enable Subscribe Modal', 'jetpack' ), array( $this, 'subscribe_modal_setting' ), 'discussion', 'jetpack_subscriptions' ); register_setting( 'discussion', 'sm_enabled' ); /** Email me whenever: Someone subscribes to my blog */ /* @since 8.1 */ add_settings_section( 'notifications_section', __( 'Someone subscribes to my blog', 'jetpack' ), array( $this, 'social_notifications_subscribe_section' ), 'discussion' ); add_settings_field( 'jetpack_subscriptions_social_notifications_subscribe', __( 'Email me whenever', 'jetpack' ), array( $this, 'social_notifications_subscribe_field' ), 'discussion', 'notifications_section' ); register_setting( 'discussion', 'social_notifications_subscribe', array( $this, 'social_notifications_subscribe_validate' ) ); } /** * Discussions setting section blurb. */ public function subscriptions_settings_section() { ?> <p id="jetpack-subscriptions-settings"><?php esc_html_e( 'Change whether your visitors can subscribe to your posts or comments or both.', 'jetpack' ); ?></p> <?php } /** * Post Subscriptions Toggle. */ public function subscription_post_subscribe_setting() { $stb_enabled = get_option( 'stb_enabled', 1 ); ?> <p class="description"> <input type="checkbox" name="stb_enabled" id="jetpack-post-subscribe" value="1" <?php checked( $stb_enabled, 1 ); ?> /> <?php echo wp_kses( __( "Show a <em>'follow blog'</em> option in the comment form", 'jetpack' ), array( 'em' => array() ) ); ?> </p> <?php } /** * Comments Subscriptions Toggle. */ public function subscription_comment_subscribe_setting() { $stc_enabled = get_option( 'stc_enabled', 1 ); ?> <p class="description"> <input type="checkbox" name="stc_enabled" id="jetpack-comment-subscribe" value="1" <?php checked( $stc_enabled, 1 ); ?> /> <?php echo wp_kses( __( "Show a <em>'follow comments'</em> option in the comment form", 'jetpack' ), array( 'em' => array() ) ); ?> </p> <?php } /** * Subscribe Modal Toggle. */ public function subscribe_modal_setting() { $sm_enabled = get_option( 'sm_enabled', 1 ); ?> <p class="description"> <input type="checkbox" name="sm_enabled" id="jetpack-subscribe-modal" value="1" <?php checked( $sm_enabled, 1 ); ?> /> <?php esc_html_e( 'Show a popup subscribe modal to readers.', 'jetpack' ); ?> </p> <?php } /** * Someone subscribes to my blog section * * @since 8.1 */ public function social_notifications_subscribe_section() { // Atypical usage here. We emit jquery to move subscribe notification checkbox to be with the rest of the email notification settings. ?> <script type="text/javascript"> jQuery( function( $ ) { var table = $( '#social_notifications_subscribe' ).parents( 'table:first' ), header = table.prevAll( 'h2:first' ), newParent = $( '#moderation_notify' ).parent( 'label' ).parent(); if ( ! table.length || ! header.length || ! newParent.length ) { return; } newParent.append( '<br/>' ).append( table.end().parent( 'label' ).siblings().andSelf() ); header.remove(); table.remove(); } ); </script> <?php } /** * Someone subscribes to my blog Toggle * * @since 8.1 */ public function social_notifications_subscribe_field() { $checked = (int) ( 'on' === get_option( 'social_notifications_subscribe', 'on' ) ); ?> <label> <input type="checkbox" name="social_notifications_subscribe" id="social_notifications_subscribe" value="1" <?php checked( $checked ); ?> /> <?php /* translators: this is a label for a setting that starts with "Email me whenever" */ esc_html_e( 'Someone subscribes to my blog', 'jetpack' ); ?> </label> <?php } /** * Validate "Someone subscribes to my blog" option * * @since 8.1 * * @param String $input the input string to be validated. * @return string on|off */ public function social_notifications_subscribe_validate( $input ) { // If it's not set (was unchecked during form submission) or was set to off (during option update), return 'off'. if ( ! $input || 'off' === $input ) { return 'off'; } // Otherwise we return 'on'. return 'on'; } /** * Jetpack_Subscriptions::subscribe() * * Send a synchronous XML-RPC subscribe to blog posts or subscribe to post comments request. * * @param string $email being subscribed. * @param array $post_ids (optional) defaults to 0 for blog posts only: array of post IDs to subscribe to blog's posts. * @param bool $async (optional) Should the subscription be performed asynchronously? Defaults to true. * @param array $extra_data Additional data passed to the `jetpack.subscribeToSite` call. * * @return true|WP_Error true on success * invalid_email : not a valid email address * invalid_post_id : not a valid post ID * unknown_post_id : unknown post * not_subscribed : strange error. Jetpack servers at WordPress.com could subscribe the email. * disabled : Site owner has disabled subscriptions. * active : Already subscribed. * pending : Tried to subscribe before but the confirmation link is never clicked. No confirmation email is sent. * unknown : strange error. Jetpack servers at WordPress.com returned something malformed. * unknown_status : strange error. Jetpack servers at WordPress.com returned something I didn't understand. */ public function subscribe( $email, $post_ids = 0, $async = true, $extra_data = array() ) { if ( ! is_email( $email ) ) { return new WP_Error( 'invalid_email' ); } if ( ! $async ) { $xml = new Jetpack_IXR_ClientMulticall(); } foreach ( (array) $post_ids as $post_id ) { $post_id = (int) $post_id; if ( $post_id < 0 ) { return new WP_Error( 'invalid_post_id' ); } elseif ( $post_id && ! get_post( $post_id ) ) { return new WP_Error( 'unknown_post_id' ); } if ( $async ) { XMLRPC_Async_Call::add_call( 'jetpack.subscribeToSite', 0, $email, $post_id, serialize( $extra_data ) ); //phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize } else { $xml->addCall( 'jetpack.subscribeToSite', $email, $post_id, serialize( $extra_data ) ); //phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize } } if ( $async ) { return; } // Call. $xml->query(); if ( $xml->isError() ) { return $xml->get_jetpack_error(); } $responses = $xml->getResponse(); $r = array(); foreach ( (array) $responses as $response ) { if ( isset( $response['faultCode'] ) || isset( $response['faultString'] ) ) { $r[] = $xml->get_jetpack_error( $response['faultCode'], $response['faultString'] ); continue; } if ( ! is_array( $response[0] ) || empty( $response[0]['status'] ) ) { $r[] = new WP_Error( 'unknown' ); continue; } switch ( $response[0]['status'] ) { case 'error': $r[] = new WP_Error( 'not_subscribed' ); continue 2; case 'disabled': $r[] = new WP_Error( 'disabled' ); continue 2; case 'active': $r[] = new WP_Error( 'active' ); continue 2; case 'confirming': $r[] = true; continue 2; case 'pending': $r[] = new WP_Error( 'pending' ); continue 2; default: $r[] = new WP_Error( 'unknown_status', (string) $response[0]['status'] ); continue 2; } } return $r; } /** * Jetpack_Subscriptions::widget_submit() * * When a user submits their email via the blog subscription widget, check the details and call the subsribe() method. */ public function widget_submit() { // Check the nonce. if ( ! wp_verify_nonce( isset( $_REQUEST['_wpnonce'] ) ? sanitize_key( $_REQUEST['_wpnonce'] ) : '', 'blogsub_subscribe_' . \Jetpack_Options::get_option( 'id' ) ) ) { return false; } if ( empty( $_REQUEST['email'] ) || ! is_string( $_REQUEST['email'] ) ) { return false; } $redirect_fragment = false; if ( isset( $_REQUEST['redirect_fragment'] ) ) { $redirect_fragment = preg_replace( '/[^a-z0-9_-]/i', '', $_REQUEST['redirect_fragment'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- This is manually unslashing and sanitizing. } if ( ! $redirect_fragment || ! is_string( $redirect_fragment ) ) { $redirect_fragment = 'subscribe-blog'; } $subscribe = self::subscribe( isset( $_REQUEST['email'] ) ? wp_unslash( $_REQUEST['email'] ) : null, // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Validated inside self::subscribe(). 0, false, array( 'source' => 'widget', 'widget-in-use' => is_active_widget( false, false, 'blog_subscription', true ) ? 'yes' : 'no', 'comment_status' => '', 'server_data' => jetpack_subscriptions_cherry_pick_server_data(), ) ); if ( is_wp_error( $subscribe ) ) { $error = $subscribe->get_error_code(); } else { $error = false; foreach ( $subscribe as $response ) { if ( is_wp_error( $response ) ) { $error = $response->get_error_code(); break; } } } switch ( $error ) { case false: $result = 'success'; break; case 'invalid_email': $result = $error; break; case 'blocked_email': $result = 'opted_out'; break; case 'active': $result = 'already'; break; case 'flooded_email': $result = 'many_pending_subs'; break; case 'pending': $result = 'pending'; break; default: $result = 'error'; break; } $redirect = add_query_arg( 'subscribe', $result ); /** * Fires on each subscription form submission. * * @module subscriptions * * @since 3.7.0 * * @param string $result Result of form submission: success, invalid_email, already, error. */ do_action( 'jetpack_subscriptions_form_submission', $result ); wp_safe_redirect( "$redirect#$redirect_fragment" ); exit; } /** * Jetpack_Subscriptions::comment_subscribe_init() * * Set up and add the comment subscription checkbox to the comment form. * * @param string $submit_button HTML markup for the submit field. */ public function comment_subscribe_init( $submit_button ) { global $post; // Subscriptions are only available for posts so far. if ( ! $post || 'post' !== $post->post_type ) { return $submit_button; } $comments_checked = ''; $blog_checked = ''; // Check for a comment / blog submission and set a cookie to retain the setting and check the boxes. if ( isset( $_COOKIE[ 'jetpack_comments_subscribe_' . self::$hash . '_' . $post->ID ] ) ) { $comments_checked = ' checked="checked"'; } if ( isset( $_COOKIE[ 'jetpack_blog_subscribe_' . self::$hash ] ) ) { $blog_checked = ' checked="checked"'; } // Some themes call this function, don't show the checkbox again. remove_action( 'comment_form', 'subscription_comment_form' ); // Check if Mark Jaquith's Subscribe to Comments plugin is active - if so, suppress Jetpack checkbox. $str = ''; if ( false === has_filter( 'comment_form', 'show_subscription_checkbox' ) && 1 === (int) get_option( 'stc_enabled', 1 ) && empty( $post->post_password ) && 'post' === get_post_type() ) { // Subscribe to comments checkbox. $str .= '<p class="comment-subscription-form"><input type="checkbox" name="subscribe_comments" id="subscribe_comments" value="subscribe" style="width: auto; -moz-appearance: checkbox; -webkit-appearance: checkbox;"' . $comments_checked . ' /> '; $comment_sub_text = __( 'Notify me of follow-up comments by email.', 'jetpack' ); $str .= '<label class="subscribe-label" id="subscribe-label" for="subscribe_comments">' . esc_html( /** * Filter the Subscribe to comments text appearing below the comment form. * * @module subscriptions * * @since 3.4.0 * * @param string $comment_sub_text Subscribe to comments text. */ apply_filters( 'jetpack_subscribe_comment_label', $comment_sub_text ) ) . '</label>'; $str .= '</p>'; } if ( 1 === (int) get_option( 'stb_enabled', 1 ) ) { // Subscribe to blog checkbox. $str .= '<p class="comment-subscription-form"><input type="checkbox" name="subscribe_blog" id="subscribe_blog" value="subscribe" style="width: auto; -moz-appearance: checkbox; -webkit-appearance: checkbox;"' . $blog_checked . ' /> '; $blog_sub_text = __( 'Notify me of new posts by email.', 'jetpack' ); $str .= '<label class="subscribe-label" id="subscribe-blog-label" for="subscribe_blog">' . esc_html( /** * Filter the Subscribe to blog text appearing below the comment form. * * @module subscriptions * * @since 3.4.0 * * @param string $comment_sub_text Subscribe to blog text. */ apply_filters( 'jetpack_subscribe_blog_label', $blog_sub_text ) ) . '</label>'; $str .= '</p>'; } /** * Filter the output of the subscription options appearing below the comment form. * * @module subscriptions * * @since 1.2.0 * * @param string $str Comment Subscription form HTML output. */ $str = apply_filters( 'jetpack_comment_subscription_form', $str ); return $str . $submit_button; } /** * Jetpack_Subscriptions::comment_subscribe_init() * * When a user checks the comment subscribe box and submits a comment, subscribe them to the comment thread. * * @param int|string $comment_id Comment thread being subscribed to. * @param string $approved Comment status. */ public function comment_subscribe_submit( $comment_id, $approved ) { if ( 'spam' === $approved ) { return; } $comment = get_comment( $comment_id ); if ( ! $comment ) { return; } // Set cookies for this post/comment. $this->set_cookies( isset( $_REQUEST['subscribe_comments'] ), $comment->comment_post_ID, isset( $_REQUEST['subscribe_blog'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended if ( ! isset( $_REQUEST['subscribe_comments'] ) && ! isset( $_REQUEST['subscribe_blog'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended return; } $post_ids = array(); if ( isset( $_REQUEST['subscribe_comments'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $post_ids[] = $comment->comment_post_ID; } if ( isset( $_REQUEST['subscribe_blog'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $post_ids[] = 0; } $result = self::subscribe( $comment->comment_author_email, $post_ids, true, array( 'source' => 'comment-form', 'widget-in-use' => is_active_widget( false, false, 'blog_subscription', true ) ? 'yes' : 'no', 'comment_status' => $approved, 'server_data' => jetpack_subscriptions_cherry_pick_server_data(), ) ); /** * Fires on each comment subscription form submission. * * @module subscriptions * * @since 5.5.0 * * @param NULL|WP_Error $result Result of form submission: NULL on success, WP_Error otherwise. * @param array $post_ids An array of post IDs that the user subscribed to, 0 means blog subscription. */ do_action( 'jetpack_subscriptions_comment_form_submission', $result, $post_ids ); } /** * Jetpack_Subscriptions::set_cookies() * * Set a cookie to save state on the comment and post subscription checkboxes. * * @param bool $subscribe_to_post Whether the user chose to subscribe to subsequent comments on this post. * @param int $post_id If $subscribe_to_post is true, the post ID they've subscribed to. * @param bool $subscribe_to_blog Whether the user chose to subscribe to all new posts on the blog. */ public function set_cookies( $subscribe_to_post = false, $post_id = null, $subscribe_to_blog = false ) { $post_id = (int) $post_id; /** This filter is already documented in core/wp-includes/comment-functions.php */ $cookie_lifetime = apply_filters( 'comment_cookie_lifetime', 30000000 ); /** * Filter the Jetpack Comment cookie path. * * @module subscriptions * * @since 2.5.0 * * @param string COOKIEPATH Cookie path. */ $cookie_path = apply_filters( 'jetpack_comment_cookie_path', COOKIEPATH ); /** * Filter the Jetpack Comment cookie domain. * * @module subscriptions * * @since 2.5.0 * * @param string COOKIE_DOMAIN Cookie domain. */ $cookie_domain = apply_filters( 'jetpack_comment_cookie_domain', COOKIE_DOMAIN ); if ( $subscribe_to_post && $post_id >= 0 ) { setcookie( 'jetpack_comments_subscribe_' . self::$hash . '_' . $post_id, 1, time() + $cookie_lifetime, $cookie_path, $cookie_domain, is_ssl(), true ); } else { setcookie( 'jetpack_comments_subscribe_' . self::$hash . '_' . $post_id, '', time() - 3600, $cookie_path, $cookie_domain, is_ssl(), true ); } if ( $subscribe_to_blog ) { setcookie( 'jetpack_blog_subscribe_' . self::$hash, 1, time() + $cookie_lifetime, $cookie_path, $cookie_domain, is_ssl(), true ); } else { setcookie( 'jetpack_blog_subscribe_' . self::$hash, '', time() - 3600, $cookie_path, $cookie_domain, is_ssl(), true ); } } /** * Set the social_notifications_subscribe option to `off` when the Subscriptions module is activated in the first time. * * @since 8.1 * * @return void */ public function set_social_notifications_subscribe() { if ( false === get_option( 'social_notifications_subscribe' ) ) { add_option( 'social_notifications_subscribe', 'off' ); } } /** * Save a flag when a post was ever published. * * It saves the post meta when the post was published and becomes a draft. * Then this meta is used to hide subscription messaging in Publish panel. * * @param string $new_status Tthe "new" post status of the transition when saved. * @param string $old_status The "old" post status of the transition when saved. * @param object $post obj The post object. */ public function maybe_set_first_published_status( $new_status, $old_status, $post ) { $was_post_ever_published = get_post_meta( $post->ID, '_jetpack_post_was_ever_published', true ); if ( ! $was_post_ever_published && 'publish' === $old_status && 'draft' === $new_status ) { update_post_meta( $post->ID, '_jetpack_post_was_ever_published', true ); } } /** * Checks if the current user can publish posts. * * @return bool */ public function first_published_status_meta_auth_callback() { /** * Filter the capability to view if a post was ever published in the Subscription Module. * * @module subscriptions * * @since 13.4 * * @param string $capability User capability needed to view if a post was ever published. Default to publish_posts. */ $capability = apply_filters( 'jetpack_subscriptions_post_was_ever_published_capability', 'publish_posts' ); if ( current_user_can( $capability ) ) { return true; } return false; } /** * Registers the 'post_was_ever_published' post meta for use in the REST API. */ public function register_post_meta() { $jetpack_post_was_ever_published = array( 'type' => 'boolean', 'description' => __( 'Whether the post was ever published.', 'jetpack' ), 'single' => true, 'default' => false, 'show_in_rest' => array( 'name' => 'jetpack_post_was_ever_published', ), 'auth_callback' => array( $this, 'first_published_status_meta_auth_callback' ), ); register_meta( 'post', '_jetpack_post_was_ever_published', $jetpack_post_was_ever_published ); } /** * Create a Subscribers menu displayed on self-hosted sites. * * - It is not displayed on WordPress.com sites. * - It directs you to Calypso to the existing Subscribers page. * * @return void */ public function add_subscribers_menu() { /* * Do not display any menu on WoA and WordPress.com Simple sites (unless Classic wp-admin is enabled). * They already get a menu item under Users via nav-unification. */ if ( ( new Host() )->is_wpcom_platform() && get_option( 'wpcom_admin_interface' ) !== 'wp-admin' ) { return; } $status = new Status(); /* * Do not display if we're in Offline mode, * or if the user is not connected. */ if ( $status->is_offline_mode() || ! ( new Connection_Manager( 'jetpack' ) )->is_user_connected() ) { return; } $blog_id = Connection_Manager::get_site_id( true ); $link = Redirect::get_url( 'jetpack-menu-jetpack-manage-subscribers', array( 'site' => $blog_id ? $blog_id : $status->get_site_suffix() ) ); add_submenu_page( 'jetpack', esc_attr__( 'Subscribers', 'jetpack' ), __( 'Subscribers', 'jetpack' ) . ' <span class="dashicons dashicons-external"></span>', 'manage_options', esc_url( $link ), null ); } /** * Record tracks event if categories is created when user enters * the edit category page through the newsletter settings page. * * @return void */ public function track_newsletter_category_creation() { // phpcs:disable WordPress.Security.NonceVerification.Missing if ( empty( $_POST['_wp_http_referer'] ) ) { return; } if ( strpos( sanitize_url( wp_unslash( $_POST['_wp_http_referer'] ) ), 'referer=newsletter-categories' ) > -1 ) { $parent = filter_var( empty( $_POST['parent'] ) ? 0 : wp_unslash( $_POST['parent'] ), FILTER_SANITIZE_NUMBER_INT ); $is_child_category = $parent > 0; $tracking = new Automattic\Jetpack\Tracking(); $tracking->tracks_record_event( wp_get_current_user(), 'jetpack_newsletter_add_category', array( 'is_child_category' => $is_child_category, ) ); } } } Jetpack_Subscriptions::init(); require __DIR__ . '/subscriptions/views.php'; require __DIR__ . '/subscriptions/subscribe-modal/class-jetpack-subscribe-modal.php'; require __DIR__ . '/subscriptions/subscribe-overlay/class-jetpack-subscribe-overlay.php';
Save Changes
Rename File
Rename