PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 10.5.3
Jetpack – WP Security, Backup, Speed, & Growth v10.5.3
12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 14.4.2 All 500 releases
jetpack / modules / subscriptions.php
subscriptions.php
899 lines 27.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Module Name: Subscriptions
4 * Module Description: Let visitors subscribe to new posts and comments via email
5 * Sort Order: 9
6 * Recommendation Order: 8
7 * First Introduced: 1.2
8 * Requires Connection: Yes
9 * Requires User Connection: Yes
10 * Auto Activate: No
11 * Module Tags: Social
12 * Feature: Engagement
13 * Additional Search Queries: subscriptions, subscription, email, follow, followers, subscribers, signup
14 */
15
16 use Automattic\Jetpack\Connection\XMLRPC_Async_Call;
17
18 add_action( 'jetpack_modules_loaded', 'jetpack_subscriptions_load' );
19
20 function jetpack_subscriptions_load() {
21 Jetpack::enable_module_configurable( __FILE__ );
22 }
23
24 /**
25 * Cherry picks keys from `$_SERVER` array.
26 *
27 * @since 6.0.0
28 *
29 * @return array An array of server data.
30 */
31 function jetpack_subscriptions_cherry_pick_server_data() {
32 $data = array();
33
34 foreach ( $_SERVER as $key => $value ) {
35 if ( ! is_string( $value ) || 0 === strpos( $key, 'HTTP_COOKIE' ) ) {
36 continue;
37 }
38
39 if ( 0 === strpos( $key, 'HTTP_' ) || in_array( $key, array( 'REMOTE_ADDR', 'REQUEST_URI', 'DOCUMENT_URI' ), true ) ) {
40 $data[ $key ] = $value;
41 }
42 }
43
44 return $data;
45 }
46
47 class Jetpack_Subscriptions {
48 public $jetpack = false;
49
50 public static $hash;
51
52 /**
53 * Singleton
54 * @static
55 */
56 static function init() {
57 static $instance = false;
58
59 if ( !$instance ) {
60 $instance = new Jetpack_Subscriptions;
61 }
62
63 return $instance;
64 }
65
66 function __construct() {
67 $this->jetpack = Jetpack::init();
68
69 // Don't use COOKIEHASH as it could be shared across installs && is non-unique in multisite.
70 // @see: https://twitter.com/nacin/status/378246957451333632
71 self::$hash = md5( get_option( 'siteurl' ) );
72
73 add_filter( 'jetpack_xmlrpc_methods', array( $this, 'xmlrpc_methods' ) );
74
75 // @todo remove sync from subscriptions and move elsewhere...
76
77 // Add Configuration Page
78 add_action( 'admin_init', array( $this, 'configure' ) );
79
80 // Catch subscription widget submits
81 if ( isset( $_REQUEST['jetpack_subscriptions_widget'] ) )
82 add_action( 'template_redirect', array( $this, 'widget_submit' ) );
83
84 // Set up the comment subscription checkboxes
85 add_filter( 'comment_form_submit_field', array( $this, 'comment_subscribe_init' ), 10, 2 );
86
87 // Catch comment posts and check for subscriptions.
88 add_action( 'comment_post', array( $this, 'comment_subscribe_submit' ), 50, 2 );
89
90 // Adds post meta checkbox in the post submit metabox
91 add_action( 'post_submitbox_misc_actions', array( $this, 'subscription_post_page_metabox' ) );
92
93 add_action( 'transition_post_status', array( $this, 'maybe_send_subscription_email' ), 10, 3 );
94
95 add_filter( 'jetpack_published_post_flags', array( $this, 'set_post_flags' ), 10, 2 );
96
97 add_filter( 'post_updated_messages', array( $this, 'update_published_message' ), 18, 1 );
98
99 // Set "social_notifications_subscribe" option during the first-time activation.
100 add_action( 'jetpack_activate_module_subscriptions', array( $this, 'set_social_notifications_subscribe' ) );
101 }
102
103 /**
104 * Jetpack_Subscriptions::xmlrpc_methods()
105 *
106 * Register subscriptions methods with the Jetpack XML-RPC server.
107 * @param array $methods
108 */
109 function xmlrpc_methods( $methods ) {
110 return array_merge(
111 $methods,
112 array(
113 'jetpack.subscriptions.subscribe' => array( $this, 'subscribe' ),
114 )
115 );
116 }
117
118 /*
119 * Disable Subscribe on Single Post
120 * Register post meta
121 */
122 function subscription_post_page_metabox() {
123 if (
124 /**
125 * Filter whether or not to show the per-post subscription option.
126 *
127 * @module subscriptions
128 *
129 * @since 3.7.0
130 *
131 * @param bool true = show checkbox option on all new posts | false = hide the option.
132 */
133 ! apply_filters( 'jetpack_allow_per_post_subscriptions', false ) )
134 {
135 return;
136 }
137
138 if ( has_filter( 'jetpack_subscriptions_exclude_these_categories' ) || has_filter( 'jetpack_subscriptions_include_only_these_categories' ) ) {
139 return;
140 }
141
142 global $post;
143 $disable_subscribe_value = get_post_meta( $post->ID, '_jetpack_dont_email_post_to_subs', true );
144 // only show checkbox if post hasn't been published and is a 'post' post type.
145 if ( get_post_status( $post->ID ) !== 'publish' && get_post_type( $post->ID ) == 'post' ) :
146 // Nonce it
147 wp_nonce_field( 'disable_subscribe', 'disable_subscribe_nonce' );
148 ?>
149 <div class="misc-pub-section">
150 <label for="_jetpack_dont_email_post_to_subs"><?php _e( 'Jetpack Subscriptions:', 'jetpack' ); ?></label><br>
151 <input type="checkbox" name="_jetpack_dont_email_post_to_subs" id="jetpack-per-post-subscribe" value="1" <?php checked( $disable_subscribe_value, 1, true ); ?> />
152 <?php _e( 'Don&#8217;t send this to subscribers', 'jetpack' ); ?>
153 </div>
154 <?php endif;
155 }
156
157 /**
158 * Checks whether or not the post should be emailed to subscribers
159 *
160 * It checks for the following things in order:
161 * - Usage of filter jetpack_subscriptions_exclude_these_categories
162 * - Usage of filter jetpack_subscriptions_include_only_these_categories
163 * - Existence of the per-post checkbox option
164 *
165 * Only one of these can be used at any given time.
166 *
167 * @param $new_status string - the "new" post status of the transition when saved
168 * @param $old_status string - the "old" post status of the transition when saved
169 * @param $post obj - The post object
170 */
171 function maybe_send_subscription_email( $new_status, $old_status, $post ) {
172
173 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
174 return;
175 }
176
177 // Make sure that the checkbox is preseved
178 if ( ! empty( $_POST['disable_subscribe_nonce'] ) && wp_verify_nonce( $_POST['disable_subscribe_nonce'], 'disable_subscribe' ) ) {
179 $set_checkbox = isset( $_POST['_jetpack_dont_email_post_to_subs'] ) ? 1 : 0;
180 update_post_meta( $post->ID, '_jetpack_dont_email_post_to_subs', $set_checkbox );
181 }
182 }
183
184 function update_published_message( $messages ) {
185 global $post;
186 if ( ! $this->should_email_post_to_subscribers( $post ) ) {
187 return $messages;
188 }
189
190 $view_post_link_html = sprintf( ' <a href="%1$s">%2$s</a>',
191 esc_url( get_permalink( $post ) ),
192 __( 'View post', 'jetpack' )
193 );
194
195 $messages['post'][6] = sprintf(
196 /* translators: Message shown after a post is published */
197 esc_html__( 'Post published and sending emails to subscribers.', 'jetpack' )
198 ) . $view_post_link_html;
199 return $messages;
200 }
201
202 public function should_email_post_to_subscribers( $post ) {
203 $should_email = true;
204 if ( get_post_meta( $post->ID, '_jetpack_dont_email_post_to_subs', true ) ) {
205 return false;
206 }
207
208 // Only posts are currently supported
209 if ( $post->post_type !== 'post' ) {
210 return false;
211 }
212
213 // Private posts are not sent to subscribers.
214 if ( 'private' === $post->post_status ) {
215 return false;
216 }
217
218 /**
219 * Array of categories that will never trigger subscription emails.
220 *
221 * Will not send subscription emails from any post from within these categories.
222 *
223 * @module subscriptions
224 *
225 * @since 3.7.0
226 *
227 * @param array $args Array of category slugs or ID's.
228 */
229 $excluded_categories = apply_filters( 'jetpack_subscriptions_exclude_these_categories', array() );
230
231 // Never email posts from these categories
232 if ( ! empty( $excluded_categories ) && in_category( $excluded_categories, $post->ID ) ) {
233 $should_email = false;
234 }
235
236 /**
237 * ONLY send subscription emails for these categories
238 *
239 * Will ONLY send subscription emails to these categories.
240 *
241 * @module subscriptions
242 *
243 * @since 3.7.0
244 *
245 * @param array $args Array of category slugs or ID's.
246 */
247 $only_these_categories = apply_filters( 'jetpack_subscriptions_exclude_all_categories_except', array() );
248
249 // Only emails posts from these categories
250 if ( ! empty( $only_these_categories ) && ! in_category( $only_these_categories, $post->ID ) ) {
251 $should_email = false;
252 }
253
254 return $should_email;
255 }
256
257 function set_post_flags( $flags, $post ) {
258 $flags['send_subscription'] = $this->should_email_post_to_subscribers( $post );
259 return $flags;
260 }
261
262 /**
263 * Jetpack_Subscriptions::configure()
264 *
265 * Jetpack Subscriptions configuration screen.
266 */
267 function configure() {
268 // Create the section
269 add_settings_section(
270 'jetpack_subscriptions',
271 __( 'Jetpack Subscriptions Settings', 'jetpack' ),
272 array( $this, 'subscriptions_settings_section' ),
273 'discussion'
274 );
275
276 /** Subscribe to Posts ***************************************************/
277
278 add_settings_field(
279 'jetpack_subscriptions_post_subscribe',
280 __( 'Follow Blog', 'jetpack' ),
281 array( $this, 'subscription_post_subscribe_setting' ),
282 'discussion',
283 'jetpack_subscriptions'
284 );
285
286 register_setting(
287 'discussion',
288 'stb_enabled'
289 );
290
291 /** Subscribe to Comments ******************************************************/
292
293 add_settings_field(
294 'jetpack_subscriptions_comment_subscribe',
295 __( 'Follow Comments', 'jetpack' ),
296 array( $this, 'subscription_comment_subscribe_setting' ),
297 'discussion',
298 'jetpack_subscriptions'
299 );
300
301 register_setting(
302 'discussion',
303 'stc_enabled'
304 );
305
306 /** Email me whenever: Someone follows my blog ***************************************************/
307 /* @since 8.1 */
308
309 add_settings_section(
310 'notifications_section',
311 __( 'Someone follows my blog', 'jetpack' ),
312 array( $this, 'social_notifications_subscribe_section' ),
313 'discussion'
314 );
315
316 add_settings_field(
317 'jetpack_subscriptions_social_notifications_subscribe',
318 __( 'Email me whenever', 'jetpack' ),
319 array( $this, 'social_notifications_subscribe_field' ),
320 'discussion',
321 'notifications_section'
322 );
323
324 register_setting(
325 'discussion',
326 'social_notifications_subscribe',
327 array( $this, 'social_notifications_subscribe_validate' )
328 );
329
330 /** Subscription Messaging Options ******************************************************/
331
332 register_setting(
333 'reading',
334 'subscription_options',
335 array( $this, 'validate_settings' )
336 );
337
338 add_settings_section(
339 'email_settings',
340 __( 'Follower Settings', 'jetpack' ),
341 array( $this, 'reading_section' ),
342 'reading'
343 );
344
345 add_settings_field(
346 'invitation',
347 __( 'Blog follow email text', 'jetpack' ),
348 array( $this, 'setting_invitation' ),
349 'reading',
350 'email_settings'
351 );
352
353 add_settings_field(
354 'comment-follow',
355 __( 'Comment follow email text', 'jetpack' ),
356 array( $this, 'setting_comment_follow' ),
357 'reading',
358 'email_settings'
359 );
360 }
361
362 /**
363 * Discussions setting section blurb
364 *
365 */
366 function subscriptions_settings_section() {
367 ?>
368 <p id="jetpack-subscriptions-settings"><?php _e( 'Change whether your visitors can subscribe to your posts or comments or both.', 'jetpack' ); ?></p>
369
370 <?php
371 }
372
373 /**
374 * Post Subscriptions Toggle
375 *
376 */
377 function subscription_post_subscribe_setting() {
378
379 $stb_enabled = get_option( 'stb_enabled', 1 ); ?>
380
381 <p class="description">
382 <input type="checkbox" name="stb_enabled" id="jetpack-post-subscribe" value="1" <?php checked( $stb_enabled, 1 ); ?> />
383 <?php _e( "Show a <em>'follow blog'</em> option in the comment form", 'jetpack' ); ?>
384 </p>
385 <?php
386 }
387
388 /**
389 * Comments Subscriptions Toggle
390 *
391 */
392 function subscription_comment_subscribe_setting() {
393
394 $stc_enabled = get_option( 'stc_enabled', 1 ); ?>
395
396 <p class="description">
397 <input type="checkbox" name="stc_enabled" id="jetpack-comment-subscribe" value="1" <?php checked( $stc_enabled, 1 ); ?> />
398 <?php _e( "Show a <em>'follow comments'</em> option in the comment form", 'jetpack' ); ?>
399 </p>
400
401 <?php
402 }
403
404 /**
405 * Someone follows my blog section
406 *
407 * @since 8.1
408 */
409 public function social_notifications_subscribe_section() {
410 // Atypical usage here. We emit jquery to move subscribe notification checkbox to be with the rest of the email notification settings
411 ?>
412 <script type="text/javascript">
413 jQuery( function( $ ) {
414 var table = $( '#social_notifications_subscribe' ).parents( 'table:first' ),
415 header = table.prevAll( 'h2:first' ),
416 newParent = $( '#moderation_notify' ).parent( 'label' ).parent();
417
418 if ( ! table.length || ! header.length || ! newParent.length ) {
419 return;
420 }
421
422 newParent.append( '<br/>' ).append( table.end().parent( 'label' ).siblings().andSelf() );
423 header.remove();
424 table.remove();
425 } );
426 </script>
427 <?php
428 }
429
430 /**
431 * Someone follows my blog Toggle
432 *
433 * @since 8.1
434 */
435 public function social_notifications_subscribe_field() {
436 $checked = (int) ( 'on' === get_option( 'social_notifications_subscribe', 'on' ) );
437 ?>
438
439 <label>
440 <input type="checkbox" name="social_notifications_subscribe" id="social_notifications_subscribe" value="1" <?php checked( $checked ); ?> />
441 <?php
442 /* translators: this is a label for a setting that starts with "Email me whenever" */
443 esc_html_e( 'Someone follows my blog', 'jetpack' );
444 ?>
445 </label>
446 <?php
447 }
448
449 /**
450 * Validate "Someone follows my blog" option
451 *
452 * @since 8.1
453 *
454 * @param String $input the input string to be validated.
455 * @return string on|off
456 */
457 public function social_notifications_subscribe_validate( $input ) {
458 // If it's not set (was unchecked during form submission) or was set to off (during option update), return 'off'.
459 if ( ! $input || 'off' === $input ) {
460 return 'off';
461 }
462
463 // Otherwise we return 'on'.
464 return 'on';
465 }
466
467 function validate_settings( $settings ) {
468 global $allowedposttags;
469
470 $default = $this->get_default_settings();
471
472 // Blog Follow
473 $settings['invitation'] = trim( wp_kses( $settings['invitation'], $allowedposttags ) );
474 if ( empty( $settings['invitation'] ) )
475 $settings['invitation'] = $default['invitation'];
476
477 // Comments Follow (single post)
478 $settings['comment_follow'] = trim( wp_kses( $settings['comment_follow'], $allowedposttags ) );
479 if ( empty( $settings['comment_follow'] ) )
480 $settings['comment_follow'] = $default['comment_follow'];
481
482 return $settings;
483 }
484
485 public function reading_section() {
486 echo '<p id="follower-settings">';
487 _e( 'These settings change emails sent from your blog to followers.', 'jetpack' );
488 echo '</p>';
489 }
490
491 public function setting_invitation() {
492 $settings = $this->get_settings();
493 echo '<textarea name="subscription_options[invitation]" class="large-text" cols="50" rows="5">' . esc_textarea( $settings['invitation'] ) . '</textarea>';
494 echo '<p><span class="description">'.__( 'Introduction text sent when someone follows your blog. (Site and confirmation details will be automatically added for you.)', 'jetpack' ).'</span></p>';
495 }
496
497 public function setting_comment_follow() {
498 $settings = $this->get_settings();
499 echo '<textarea name="subscription_options[comment_follow]" class="large-text" cols="50" rows="5">' . esc_textarea( $settings['comment_follow'] ) . '</textarea>';
500 echo '<p><span class="description">'.__( 'Introduction text sent when someone follows a post on your blog. (Site and confirmation details will be automatically added for you.)', 'jetpack' ).'</span></p>';
501 }
502
503 function get_default_settings() {
504 return array(
505 'invitation' => __( "Howdy.\n\nYou recently followed this blog's posts. This means you will receive each new post by email.\n\nTo activate, click confirm below. If you believe this is an error, ignore this message and we'll never bother you again.", 'jetpack' ),
506 'comment_follow' => __( "Howdy.\n\nYou recently followed one of my posts. This means you will receive an email when new comments are posted.\n\nTo activate, click confirm below. If you believe this is an error, ignore this message and we'll never bother you again.", 'jetpack' )
507 );
508 }
509
510 function get_settings() {
511 return wp_parse_args( (array) get_option( 'subscription_options', array() ), $this->get_default_settings() );
512 }
513
514 /**
515 * Jetpack_Subscriptions::subscribe()
516 *
517 * Send a synchronous XML-RPC subscribe to blog posts or subscribe to post comments request.
518 *
519 * @param string $email
520 * @param array $post_ids (optional) defaults to 0 for blog posts only: array of post IDs to subscribe to blog's posts
521 * @param bool $async (optional) Should the subscription be performed asynchronously? Defaults to true.
522 *
523 * @return true|WP_Error true on success
524 * invalid_email : not a valid email address
525 * invalid_post_id : not a valid post ID
526 * unknown_post_id : unknown post
527 * not_subscribed : strange error. Jetpack servers at WordPress.com could subscribe the email.
528 * disabled : Site owner has disabled subscriptions.
529 * active : Already subscribed.
530 * pending : Tried to subscribe before but the confirmation link is never clicked. No confirmation email is sent.
531 * unknown : strange error. Jetpack servers at WordPress.com returned something malformed.
532 * unknown_status : strange error. Jetpack servers at WordPress.com returned something I didn't understand.
533 */
534 function subscribe( $email, $post_ids = 0, $async = true, $extra_data = array() ) {
535 if ( !is_email( $email ) ) {
536 return new WP_Error( 'invalid_email' );
537 }
538
539 if ( !$async ) {
540 $xml = new Jetpack_IXR_ClientMulticall();
541 }
542
543 foreach ( (array) $post_ids as $post_id ) {
544 $post_id = (int) $post_id;
545 if ( $post_id < 0 ) {
546 return new WP_Error( 'invalid_post_id' );
547 } else if ( $post_id && !$post = get_post( $post_id ) ) {
548 return new WP_Error( 'unknown_post_id' );
549 }
550
551 if ( $async ) {
552 XMLRPC_Async_Call::add_call( 'jetpack.subscribeToSite', 0, $email, $post_id, serialize( $extra_data ) ); //phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
553 } else {
554 $xml->addCall( 'jetpack.subscribeToSite', $email, $post_id, serialize( $extra_data ) );
555 }
556 }
557
558 if ( $async ) {
559 return;
560 }
561
562 // Call
563 $xml->query();
564
565 if ( $xml->isError() ) {
566 return $xml->get_jetpack_error();
567 }
568
569 $responses = $xml->getResponse();
570
571 $r = array();
572 foreach ( (array) $responses as $response ) {
573 if ( isset( $response['faultCode'] ) || isset( $response['faultString'] ) ) {
574 $r[] = $xml->get_jetpack_error( $response['faultCode'], $response['faultString'] );
575 continue;
576 }
577
578 if ( !is_array( $response[0] ) || empty( $response[0]['status'] ) ) {
579 $r[] = new WP_Error( 'unknown' );
580 continue;
581 }
582
583 switch ( $response[0]['status'] ) {
584 case 'error':
585 $r[] = new WP_Error( 'not_subscribed' );
586 continue 2;
587 case 'disabled':
588 $r[] = new WP_Error( 'disabled' );
589 continue 2;
590 case 'active':
591 $r[] = new WP_Error( 'active' );
592 continue 2;
593 case 'confirming':
594 $r[] = true;
595 continue 2;
596 case 'pending':
597 $r[] = new WP_Error( 'pending' );
598 continue 2;
599 default:
600 $r[] = new WP_Error( 'unknown_status', (string) $response[0]['status'] );
601 continue 2;
602 }
603 }
604
605 return $r;
606 }
607
608 /**
609 * Jetpack_Subscriptions::widget_submit()
610 *
611 * When a user submits their email via the blog subscription widget, check the details and call the subsribe() method.
612 */
613 function widget_submit() {
614 // Check the nonce.
615 if ( is_user_logged_in() ) {
616 check_admin_referer( 'blogsub_subscribe_' . get_current_blog_id() );
617 }
618
619 if ( empty( $_REQUEST['email'] ) || ! is_string( $_REQUEST['email'] ) )
620 return false;
621
622 $redirect_fragment = false;
623 if ( isset( $_REQUEST['redirect_fragment'] ) ) {
624 $redirect_fragment = preg_replace( '/[^a-z0-9_-]/i', '', $_REQUEST['redirect_fragment'] );
625 }
626 if ( !$redirect_fragment || ! is_string( $redirect_fragment ) ) {
627 $redirect_fragment = 'subscribe-blog';
628 }
629
630 $subscribe = Jetpack_Subscriptions::subscribe(
631 $_REQUEST['email'],
632 0,
633 false,
634 array(
635 'source' => 'widget',
636 'widget-in-use' => is_active_widget( false, false, 'blog_subscription', true ) ? 'yes' : 'no',
637 'comment_status' => '',
638 'server_data' => jetpack_subscriptions_cherry_pick_server_data(),
639 )
640 );
641
642 if ( is_wp_error( $subscribe ) ) {
643 $error = $subscribe->get_error_code();
644 } else {
645 $error = false;
646 foreach ( $subscribe as $response ) {
647 if ( is_wp_error( $response ) ) {
648 $error = $response->get_error_code();
649 break;
650 }
651 }
652 }
653
654 switch ( $error ) {
655 case false:
656 $result = 'success';
657 break;
658 case 'invalid_email':
659 $result = $error;
660 break;
661 case 'blocked_email':
662 $result = 'opted_out';
663 break;
664 case 'active':
665 $result = 'already';
666 break;
667 case 'flooded_email':
668 $result = 'many_pending_subs';
669 break;
670 case 'pending':
671 $result = 'pending';
672 break;
673 default:
674 $result = 'error';
675 break;
676 }
677
678 $redirect = add_query_arg( 'subscribe', $result );
679
680 /**
681 * Fires on each subscription form submission.
682 *
683 * @module subscriptions
684 *
685 * @since 3.7.0
686 *
687 * @param string $result Result of form submission: success, invalid_email, already, error.
688 */
689 do_action( 'jetpack_subscriptions_form_submission', $result );
690
691 wp_safe_redirect( "$redirect#$redirect_fragment" );
692 exit;
693 }
694
695 /**
696 * Jetpack_Subscriptions::comment_subscribe_init()
697 *
698 * Set up and add the comment subscription checkbox to the comment form.
699 *
700 * @param string $submit_button HTML markup for the submit field.
701 * @param array $args Arguments passed to `comment_form()`.
702 */
703 function comment_subscribe_init( $submit_button, $args ) {
704 global $post;
705
706 $comments_checked = '';
707 $blog_checked = '';
708
709 // Check for a comment / blog submission and set a cookie to retain the setting and check the boxes.
710 if ( isset( $_COOKIE[ 'jetpack_comments_subscribe_' . self::$hash . '_' . $post->ID ] ) ) {
711 $comments_checked = ' checked="checked"';
712 }
713
714 if ( isset( $_COOKIE[ 'jetpack_blog_subscribe_' . self::$hash ] ) ) {
715 $blog_checked = ' checked="checked"';
716 }
717
718 // Some themes call this function, don't show the checkbox again
719 remove_action( 'comment_form', 'subscription_comment_form' );
720
721 // Check if Mark Jaquith's Subscribe to Comments plugin is active - if so, suppress Jetpack checkbox
722
723 $str = '';
724
725 if ( FALSE === has_filter( 'comment_form', 'show_subscription_checkbox' ) && 1 == get_option( 'stc_enabled', 1 ) && empty( $post->post_password ) && 'post' == get_post_type() ) {
726 // Subscribe to comments checkbox
727 $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 . ' /> ';
728 $comment_sub_text = __( 'Notify me of follow-up comments by email.', 'jetpack' );
729 $str .= '<label class="subscribe-label" id="subscribe-label" for="subscribe_comments">' . esc_html(
730 /**
731 * Filter the Subscribe to comments text appearing below the comment form.
732 *
733 * @module subscriptions
734 *
735 * @since 3.4.0
736 *
737 * @param string $comment_sub_text Subscribe to comments text.
738 */
739 apply_filters( 'jetpack_subscribe_comment_label', $comment_sub_text )
740 ) . '</label>';
741 $str .= '</p>';
742 }
743
744 if ( 1 == get_option( 'stb_enabled', 1 ) ) {
745 // Subscribe to blog checkbox
746 $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 . ' /> ';
747 $blog_sub_text = __( 'Notify me of new posts by email.', 'jetpack' );
748 $str .= '<label class="subscribe-label" id="subscribe-blog-label" for="subscribe_blog">' . esc_html(
749 /**
750 * Filter the Subscribe to blog text appearing below the comment form.
751 *
752 * @module subscriptions
753 *
754 * @since 3.4.0
755 *
756 * @param string $comment_sub_text Subscribe to blog text.
757 */
758 apply_filters( 'jetpack_subscribe_blog_label', $blog_sub_text )
759 ) . '</label>';
760 $str .= '</p>';
761 }
762
763 /**
764 * Filter the output of the subscription options appearing below the comment form.
765 *
766 * @module subscriptions
767 *
768 * @since 1.2.0
769 *
770 * @param string $str Comment Subscription form HTML output.
771 */
772 $str = apply_filters( 'jetpack_comment_subscription_form', $str );
773
774 return $str . $submit_button;
775 }
776
777 /**
778 * Jetpack_Subscriptions::comment_subscribe_init()
779 *
780 * When a user checks the comment subscribe box and submits a comment, subscribe them to the comment thread.
781 */
782 function comment_subscribe_submit( $comment_id, $approved ) {
783 if ( 'spam' === $approved ) {
784 return;
785 }
786
787 $comment = get_comment( $comment_id );
788 if ( ! $comment ) {
789 return;
790 }
791
792 // Set cookies for this post/comment
793 $this->set_cookies( isset( $_REQUEST['subscribe_comments'] ), $comment->comment_post_ID, isset( $_REQUEST['subscribe_blog'] ) );
794
795 if ( !isset( $_REQUEST['subscribe_comments'] ) && !isset( $_REQUEST['subscribe_blog'] ) )
796 return;
797
798 $post_ids = array();
799
800 if ( isset( $_REQUEST['subscribe_comments'] ) )
801 $post_ids[] = $comment->comment_post_ID;
802
803 if ( isset( $_REQUEST['subscribe_blog'] ) )
804 $post_ids[] = 0;
805
806 $result = Jetpack_Subscriptions::subscribe(
807 $comment->comment_author_email,
808 $post_ids,
809 true,
810 array(
811 'source' => 'comment-form',
812 'widget-in-use' => is_active_widget( false, false, 'blog_subscription', true ) ? 'yes' : 'no',
813 'comment_status' => $approved,
814 'server_data' => jetpack_subscriptions_cherry_pick_server_data(),
815 )
816 );
817
818 /**
819 * Fires on each comment subscription form submission.
820 *
821 * @module subscriptions
822 *
823 * @since 5.5.0
824 *
825 * @param NULL|WP_Error $result Result of form submission: NULL on success, WP_Error otherwise.
826 * @param array $post_ids An array of post IDs that the user subscribed to, 0 means blog subscription.
827 */
828 do_action( 'jetpack_subscriptions_comment_form_submission', $result, $post_ids );
829 }
830
831 /**
832 * Jetpack_Subscriptions::set_cookies()
833 *
834 * Set a cookie to save state on the comment and post subscription checkboxes.
835 *
836 * @param bool $subscribe_to_post Whether the user chose to subscribe to subsequent comments on this post.
837 * @param int $post_id If $subscribe_to_post is true, the post ID they've subscribed to.
838 * @param bool $subscribe_to_blog Whether the user chose to subscribe to all new posts on the blog.
839 */
840 function set_cookies( $subscribe_to_post = false, $post_id = null, $subscribe_to_blog = false ) {
841 $post_id = (int) $post_id;
842
843 /** This filter is already documented in core/wp-includes/comment-functions.php */
844 $cookie_lifetime = apply_filters( 'comment_cookie_lifetime', 30000000 );
845
846 /**
847 * Filter the Jetpack Comment cookie path.
848 *
849 * @module subscriptions
850 *
851 * @since 2.5.0
852 *
853 * @param string COOKIEPATH Cookie path.
854 */
855 $cookie_path = apply_filters( 'jetpack_comment_cookie_path', COOKIEPATH );
856
857 /**
858 * Filter the Jetpack Comment cookie domain.
859 *
860 * @module subscriptions
861 *
862 * @since 2.5.0
863 *
864 * @param string COOKIE_DOMAIN Cookie domain.
865 */
866 $cookie_domain = apply_filters( 'jetpack_comment_cookie_domain', COOKIE_DOMAIN );
867
868 if ( $subscribe_to_post && $post_id >= 0 ) {
869 setcookie( 'jetpack_comments_subscribe_' . self::$hash . '_' . $post_id, 1, time() + $cookie_lifetime, $cookie_path, $cookie_domain );
870 } else {
871 setcookie( 'jetpack_comments_subscribe_' . self::$hash . '_' . $post_id, '', time() - 3600, $cookie_path, $cookie_domain );
872 }
873
874 if ( $subscribe_to_blog ) {
875 setcookie( 'jetpack_blog_subscribe_' . self::$hash, 1, time() + $cookie_lifetime, $cookie_path, $cookie_domain );
876 } else {
877 setcookie( 'jetpack_blog_subscribe_' . self::$hash, '', time() - 3600, $cookie_path, $cookie_domain );
878 }
879 }
880
881 /**
882 * Set the social_notifications_subscribe option to `off` when the Subscriptions module is activated in the first time.
883 *
884 * @since 8.1
885 *
886 * @return null
887 */
888 function set_social_notifications_subscribe() {
889 if ( false === get_option( 'social_notifications_subscribe' ) ) {
890 add_option( 'social_notifications_subscribe', 'off' );
891 }
892 }
893
894 }
895
896 Jetpack_Subscriptions::init();
897
898 include dirname( __FILE__ ) . '/subscriptions/views.php';
899