PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 2.7.5
Jetpack – WP Security, Backup, Speed, & Growth v2.7.5
16.2-beta 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 All 501 releases
jetpack / modules / subscriptions.php

subscriptions.php in Jetpack – WP Security, Backup, Speed, & Growth 2.7.5, at modules/subscriptions.php

770 lines 26.3 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: Allow users to subscribe to your posts and comments to receive a notification via email.
5 * Sort Order: 3
6 * First Introduced: 1.2
7 * Requires Connection: Yes
8 * Auto Activate: Yes
9 * Module Tags: Social
10 */
11
12 add_action( 'jetpack_modules_loaded', 'jetpack_subscriptions_load' );
13
14 Jetpack_Sync::sync_options(
15 __FILE__,
16 'home',
17 'blogname',
18 'siteurl',
19 'page_on_front',
20 'permalink_structure',
21 'category_base',
22 'rss_use_excerpt',
23 'subscription_options',
24 'stb_enabled',
25 'stc_enabled',
26 'tag_base'
27 );
28
29 Jetpack_Sync::sync_posts( __FILE__ );
30 Jetpack_Sync::sync_comments( __FILE__ );
31
32 function jetpack_subscriptions_load() {
33 Jetpack::enable_module_configurable( __FILE__ );
34 Jetpack::module_configuration_load( __FILE__, 'jetpack_subscriptions_configuration_load' );
35 }
36
37 function jetpack_subscriptions_configuration_load() {
38 wp_safe_redirect( admin_url( 'options-discussion.php#jetpack-subscriptions-settings' ) );
39 exit;
40 }
41
42 class Jetpack_Subscriptions {
43 var $jetpack = false;
44
45 public static $hash;
46
47 /**
48 * Singleton
49 * @static
50 */
51 static function init() {
52 static $instance = false;
53
54 if ( !$instance ) {
55 $instance = new Jetpack_Subscriptions;
56 }
57
58 return $instance;
59 }
60
61 function Jetpack_Subscriptions() {
62 $this->jetpack = Jetpack::init();
63
64 // Don't use COOKIEHASH as it could be shared across installs && is non-unique in multisite.
65 // @see: https://twitter.com/nacin/status/378246957451333632
66 self::$hash = md5( get_option( 'siteurl' ) );
67
68 add_filter( 'jetpack_xmlrpc_methods', array( $this, 'xmlrpc_methods' ) );
69
70 // @todo remove sync from subscriptions and move elsewhere...
71
72 // Add Configuration Page
73 add_action( 'admin_init', array( $this, 'configure' ) );
74
75 // Set up the subscription widget.
76 add_action( 'widgets_init', array( $this, 'widget_init' ) );
77
78 // Catch subscription widget submits
79 if ( isset( $_REQUEST['jetpack_subscriptions_widget'] ) )
80 add_action( 'template_redirect', array( $this, 'widget_submit' ) );
81
82 // Set up the comment subscription checkboxes
83 add_action( 'comment_form', array( $this, 'comment_subscribe_init' ) );
84
85 // Catch comment posts and check for subscriptions.
86 add_action( 'comment_post', array( $this, 'comment_subscribe_submit' ), 50, 2 );
87 }
88
89 function post_is_public( $the_post ) {
90 if ( !$post = get_post( $the_post ) ) {
91 return false;
92 }
93
94 if ( 'publish' === $post->post_status && strlen( (string) $post->post_password ) < 1 ) {
95 return apply_filters( 'jetpack_is_post_mailable', true );
96 }
97 }
98
99 /**
100 * Jetpack_Subscriptions::xmlrpc_methods()
101 *
102 * Register subscriptions methods with the Jetpack XML-RPC server.
103 * @param array $methods
104 */
105 function xmlrpc_methods( $methods ) {
106 return array_merge(
107 $methods,
108 array(
109 'jetpack.subscriptions.subscribe' => array( $this, 'subscribe' ),
110 )
111 );
112 }
113
114 /**
115 * Jetpack_Subscriptions::configure()
116 *
117 * Jetpack Subscriptions configuration screen.
118 */
119 function configure() {
120 // Create the section
121 add_settings_section(
122 'jetpack_subscriptions',
123 __( 'Jetpack Subscriptions Settings', 'jetpack' ),
124 array( $this, 'subscriptions_settings_section' ),
125 'discussion'
126 );
127
128 /** Subscribe to Posts ***************************************************/
129
130 add_settings_field(
131 'jetpack_subscriptions_post_subscribe',
132 __( 'Follow Blog', 'jetpack' ),
133 array( $this, 'subscription_post_subscribe_setting' ),
134 'discussion',
135 'jetpack_subscriptions'
136 );
137
138 register_setting(
139 'discussion',
140 'stb_enabled'
141 );
142
143 /** Subscribe to Comments ******************************************************/
144
145 add_settings_field(
146 'jetpack_subscriptions_comment_subscribe',
147 __( 'Follow Comments', 'jetpack' ),
148 array( $this, 'subscription_comment_subscribe_setting' ),
149 'discussion',
150 'jetpack_subscriptions'
151 );
152
153 register_setting(
154 'discussion',
155 'stc_enabled'
156 );
157
158 /** Subscription Messaging Options ******************************************************/
159
160 register_setting(
161 'reading',
162 'subscription_options',
163 array( $this, 'validate_settings' )
164 );
165
166 add_settings_section(
167 'email_settings',
168 __( 'Follower Settings', 'jetpack' ),
169 array( $this, 'reading_section' ),
170 'reading'
171 );
172
173 add_settings_field(
174 'invitation',
175 __( 'Blog follow email text', 'jetpack' ),
176 array( $this, 'setting_invitation' ),
177 'reading',
178 'email_settings'
179 );
180
181 add_settings_field(
182 'comment-follow',
183 __( 'Comment follow email text', 'jetpack' ),
184 array( $this, 'setting_comment_follow' ),
185 'reading',
186 'email_settings'
187 );
188 }
189
190 /**
191 * Discussions setting section blurb
192 *
193 */
194 function subscriptions_settings_section() {
195 ?>
196
197 <p id="jetpack-subscriptions-settings"><?php _e( 'Change whether your visitors can subscribe to your posts or comments or both.', 'jetpack' ); ?></p>
198
199 <?php
200 }
201
202 /**
203 * Post Subscriptions Toggle
204 *
205 */
206 function subscription_post_subscribe_setting() {
207
208 $stb_enabled = get_option( 'stb_enabled', 1 ); ?>
209
210 <p class="description">
211 <input type="checkbox" name="stb_enabled" id="jetpack-post-subscribe" value="1" <?php checked( $stb_enabled, 1 ); ?> />
212 <?php _e( "Show a <em>'follow blog'</em> option in the comment form", 'jetpack' ); ?>
213 </p>
214 <?php
215 }
216
217 /**
218 * Comments Subscriptions Toggle
219 *
220 */
221 function subscription_comment_subscribe_setting() {
222
223 $stc_enabled = get_option( 'stc_enabled', 1 ); ?>
224
225 <p class="description">
226 <input type="checkbox" name="stc_enabled" id="jetpack-comment-subscribe" value="1" <?php checked( $stc_enabled, 1 ); ?> />
227 <?php _e( "Show a <em>'follow comments'</em> option in the comment form", 'jetpack' ); ?>
228 </p>
229
230 <?php
231 }
232
233 function validate_settings( $settings ) {
234 global $allowedposttags;
235
236 $default = $this->get_default_settings();
237
238 // Blog Follow
239 $settings['invitation'] = trim( wp_kses( $settings['invitation'], $allowedposttags ) );
240 if ( empty( $settings['invitation'] ) )
241 $settings['invitation'] = $default['invitation'];
242
243 // Comments Follow (single post)
244 $settings['comment_follow'] = trim( wp_kses( $settings['comment_follow'], $allowedposttags ) );
245 if ( empty( $settings['comment_follow'] ) )
246 $settings['comment_follow'] = $default['comment_follow'];
247
248 return $settings;
249 }
250
251 public function reading_section() {
252 _e( 'These settings change emails sent from your blog to followers.', 'jetpack' );
253 }
254
255 public function setting_invitation() {
256 $settings = $this->get_settings();
257 echo '<textarea name="subscription_options[invitation]" class="large-text" cols="50" rows="5">'.$settings['invitation'].'</textarea>';
258 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>';
259 }
260
261 public function setting_comment_follow() {
262 $settings = $this->get_settings();
263 echo '<textarea name="subscription_options[comment_follow]" class="large-text" cols="50" rows="5">'.$settings['comment_follow'].'</textarea>';
264 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>';
265 }
266
267 function get_default_settings() {
268 return array(
269 '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' ),
270 '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' )
271 );
272 }
273
274 function get_settings() {
275 return wp_parse_args( (array) get_option( 'subscription_options', array() ), $this->get_default_settings() );
276 }
277
278 /**
279 * Jetpack_Subscriptions::subscribe()
280 *
281 * Send a synchronous XML-RPC subscribe to blog posts or subscribe to post comments request.
282 *
283 * @param string $email
284 * @param array $post_ids (optional) defaults to 0 for blog posts only: array of post IDs to subscribe to blog's posts
285 * @param bool $async (optional) Should the subscription be performed asynchronously? Defaults to true.
286 *
287 * @return true|Jetpack_Error true on success
288 * invalid_email : not a valid email address
289 * invalid_post_id : not a valid post ID
290 * unknown_post_id : unknown post
291 * not_subscribed : strange error. Jetpack servers at WordPress.com could subscribe the email.
292 * disabled : Site owner has disabled subscriptions.
293 * active : Already subscribed.
294 * unknown : strange error. Jetpack servers at WordPress.com returned something malformed.
295 * unknown_status : strange error. Jetpack servers at WordPress.com returned something I didn't understand.
296 */
297 function subscribe( $email, $post_ids = 0, $async = true, $extra_data = array() ) {
298 if ( !is_email( $email ) ) {
299 return new Jetpack_Error( 'invalid_email' );
300 }
301
302 if ( !$async ) {
303 Jetpack::load_xml_rpc_client();
304 $xml = new Jetpack_IXR_ClientMulticall();
305 }
306
307 foreach ( (array) $post_ids as $post_id ) {
308 $post_id = (int) $post_id;
309 if ( $post_id < 0 ) {
310 return new Jetpack_Error( 'invalid_post_id' );
311 } else if ( $post_id && !$post = get_post( $post_id ) ) {
312 return new Jetpack_Error( 'unknown_post_id' );
313 }
314
315 if ( $async ) {
316 Jetpack::xmlrpc_async_call( 'jetpack.subscribeToSite', $email, $post_id, serialize( $extra_data ) );
317 } else {
318 $xml->addCall( 'jetpack.subscribeToSite', $email, $post_id, serialize( $extra_data ) );
319 }
320 }
321
322 if ( $async ) {
323 return;
324 }
325
326 // Call
327 $xml->query();
328
329 if ( $xml->isError() ) {
330 return $xml->get_jetpack_error();
331 }
332
333 $responses = $xml->getResponse();
334
335 $r = array();
336 foreach ( (array) $responses as $response ) {
337 if ( isset( $response['faultCode'] ) || isset( $response['faultString'] ) ) {
338 $r[] = $xml->get_jetpack_error( $response['faultCode'], $response['faultString'] );
339 continue;
340 }
341
342 if ( !is_array( $response[0] ) || empty( $response[0]['status'] ) ) {
343 $r[] = new Jetpack_Error( 'unknown' );
344 continue;
345 }
346
347 switch ( $response[0]['status'] ) {
348 case 'error' :
349 $r[] = new Jetpack_Error( 'not_subscribed' );
350 continue 2;
351 case 'disabled' :
352 $r[] = new Jetpack_Error( 'disabled' );
353 continue 2;
354 case 'active' :
355 $r[] = new Jetpack_Error( 'active' );
356 continue 2;
357 case 'pending' :
358 $r[] = true;
359 continue 2;
360 default :
361 $r[] = new Jetpack_Error( 'unknown_status', (string) $response[0]['status'] );
362 continue 2;
363 }
364 }
365
366 return $r;
367 }
368
369 /**
370 * Jetpack_Subscriptions::widget_init()
371 *
372 * Initialize and register the Jetpack Subscriptions widget.
373 */
374 function widget_init() {
375 register_widget( 'Jetpack_Subscriptions_Widget' );
376 }
377
378 /**
379 * Jetpack_Subscriptions::widget_submit()
380 *
381 * When a user submits their email via the blog subscription widget, check the details and call the subsribe() method.
382 */
383 function widget_submit() {
384 // Check the nonce.
385 if ( is_user_logged_in() ) {
386 check_admin_referer( 'blogsub_subscribe_' . get_current_blog_id() );
387 }
388
389 if ( empty( $_REQUEST['email'] ) )
390 return false;
391
392 $redirect_fragment = false;
393 if ( isset( $_REQUEST['redirect_fragment'] ) ) {
394 $redirect_fragment = preg_replace( '/[^a-z0-9_-]/i', '', $_REQUEST['redirect_fragment'] );
395 }
396 if ( !$redirect_fragment ) {
397 $redirect_fragment = 'subscribe-blog';
398 }
399
400 $subscribe = Jetpack_Subscriptions::subscribe(
401 $_REQUEST['email'],
402 0,
403 false,
404 array(
405 'source' => 'widget',
406 'widget-in-use' => is_active_widget( false, false, 'blog_subscription', true ) ? 'yes' : 'no',
407 'comment_status' => '',
408 'server_data' => $_SERVER,
409 )
410 );
411
412 if ( is_wp_error( $subscribe ) ) {
413 $error = $subscribe->get_error_code();
414 } else {
415 $error = false;
416 foreach ( $subscribe as $response ) {
417 if ( is_wp_error( $response ) ) {
418 $error = $response->get_error_code();
419 break;
420 }
421 }
422 }
423
424 if ( $error ) {
425 switch ( $error ) {
426 case 'invalid_email':
427 $redirect = add_query_arg( 'subscribe', 'invalid_email' );
428 break;
429 case 'active': case 'pending':
430 $redirect = add_query_arg( 'subscribe', 'already' );
431 break;
432 default:
433 $redirect = add_query_arg( 'subscribe', 'error' );
434 break;
435 }
436 } else {
437 $redirect = add_query_arg( 'subscribe', 'success' );
438 }
439
440 wp_safe_redirect( "$redirect#$redirect_fragment" );
441 exit;
442 }
443
444 /**
445 * Jetpack_Subscriptions::comment_subscribe_init()
446 *
447 * Set up and add the comment subscription checkbox to the comment form.
448 */
449 function comment_subscribe_init() {
450 global $post;
451
452 $comments_checked = '';
453 $blog_checked = '';
454
455 // Check for a comment / blog submission and set a cookie to retain the setting and check the boxes.
456 if ( isset( $_COOKIE[ 'jetpack_comments_subscribe_' . self::$hash ] ) && $_COOKIE[ 'jetpack_comments_subscribe_' . self::$hash ] == $post->ID )
457 $comments_checked = ' checked="checked"';
458
459 if ( isset( $_COOKIE[ 'jetpack_blog_subscribe_' . self::$hash ] ) )
460 $blog_checked = ' checked="checked"';
461
462 // Some themes call this function, don't show the checkbox again
463 remove_action( 'comment_form', 'subscription_comment_form' );
464
465 // Check if Mark Jaquith's Subscribe to Comments plugin is active - if so, suppress Jetpack checkbox
466
467 $str = '';
468
469 if ( FALSE === has_filter( 'comment_form', 'show_subscription_checkbox' ) && 1 == get_option( 'stc_enabled', 1 ) ) {
470 // Subscribe to comments checkbox
471 $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 . ' /> ';
472 $str .= '<label class="subscribe-label" id="subscribe-label" for="subscribe_comments" style="display: inline;">' . __( 'Notify me of follow-up comments by email.', 'jetpack' ) . '</label>';
473 $str .= '</p>';
474 }
475
476 if ( 1 == get_option( 'stb_enabled', 1 ) ) {
477 // Subscribe to blog checkbox
478 $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 . ' /> ';
479 $str .= '<label class="subscribe-label" id="subscribe-blog-label" for="subscribe_blog" style="display: inline;">' . __( 'Notify me of new posts by email.', 'jetpack' ) . '</label>';
480 $str .= '</p>';
481 }
482
483 echo apply_filters( 'jetpack_comment_subscription_form', $str );
484 }
485
486 /**
487 * Jetpack_Subscriptions::comment_subscribe_init()
488 *
489 * When a user checks the comment subscribe box and submits a comment, subscribe them to the comment thread.
490 */
491 function comment_subscribe_submit( $comment_id, $approved ) {
492 if ( 'spam' === $approved ) {
493 return;
494 }
495
496 // Set cookies for this post/comment
497 $this->set_cookies( isset( $_REQUEST['subscribe_comments'] ), isset( $_REQUEST['subscribe_blog'] ) );
498
499 if ( !isset( $_REQUEST['subscribe_comments'] ) && !isset( $_REQUEST['subscribe_blog'] ) )
500 return;
501
502 $comment = get_comment( $comment_id );
503 $post_ids = array();
504
505 if ( isset( $_REQUEST['subscribe_comments'] ) )
506 $post_ids[] = $comment->comment_post_ID;
507
508 if ( isset( $_REQUEST['subscribe_blog'] ) )
509 $post_ids[] = 0;
510
511 Jetpack_Subscriptions::subscribe(
512 $comment->comment_author_email,
513 $post_ids,
514 true,
515 array(
516 'source' => 'comment-form',
517 'widget-in-use' => is_active_widget( false, false, 'blog_subscription', true ) ? 'yes' : 'no',
518 'comment_status' => $approved,
519 'server_data' => $_SERVER,
520 )
521 );
522 }
523
524 /**
525 * Jetpack_Subscriptions::set_cookies()
526 *
527 * Set a cookie to save state on the comment and post subscription checkboxes.
528 */
529 function set_cookies( $comments = true, $posts = true ) {
530 global $post;
531
532 $cookie_lifetime = apply_filters( 'comment_cookie_lifetime', 30000000 );
533 $cookie_path = apply_filters( 'jetpack_comment_cookie_path', COOKIEPATH );
534 $cookie_domain = apply_filters( 'jetpack_comment_cookie_domain', COOKIE_DOMAIN );
535
536 if ( $comments )
537 setcookie( 'jetpack_comments_subscribe_' . self::$hash, $post->ID, time() + $cookie_lifetime, $cookie_path, $cookie_domain );
538 else
539 setcookie( 'jetpack_comments_subscribe_' . self::$hash, '', time() - 3600, $cookie_path, $cookie_domain );
540
541 if ( $posts )
542 setcookie( 'jetpack_blog_subscribe_' . self::$hash, 1, time() + $cookie_lifetime, $cookie_path, $cookie_domain );
543 else
544 setcookie( 'jetpack_blog_subscribe_' . self::$hash, '', time() - 3600, $cookie_path, $cookie_domain );
545 }
546 }
547
548 Jetpack_Subscriptions::init();
549
550
551 /***
552 * Blog Subscription Widget
553 */
554
555 class Jetpack_Subscriptions_Widget extends WP_Widget {
556 function Jetpack_Subscriptions_Widget() {
557 $widget_ops = array( 'classname' => 'jetpack_subscription_widget', 'description' => __( 'Add an email signup form to allow people to subscribe to your blog.', 'jetpack' ) );
558 $control_ops = array( 'width' => 300 );
559
560 $this->WP_Widget( 'blog_subscription', __( 'Blog Subscriptions (Jetpack)', 'jetpack' ), $widget_ops, $control_ops );
561
562 add_action( 'init', array( $this, 'maybe_add_style' ) );
563 }
564
565 function maybe_add_style() {
566 if ( is_active_widget( false, false, $this->id_base, true ) ) {
567 wp_register_style( 'jetpack-subscriptions', plugins_url( 'subscriptions/subscriptions.css', __FILE__ ) );
568 wp_enqueue_style( 'jetpack-subscriptions' );
569 }
570 }
571
572 function widget( $args, $instance ) {
573 global $current_user;
574
575
576
577 $source = 'widget';
578 $instance = wp_parse_args( (array) $instance, $this->defaults() );
579 $subscribe_text = isset( $instance['subscribe_text'] ) ? stripslashes( $instance['subscribe_text'] ) : '';
580 $subscribe_button = isset( $instance['subscribe_button'] ) ? stripslashes( $instance['subscribe_button'] ) : '';
581 $show_subscribers_total = (bool) $instance['show_subscribers_total'];
582 $subscribers_total = $this->fetch_subscriber_count();
583 $widget_id = esc_attr( !empty( $args['widget_id'] ) ? esc_attr( $args['widget_id'] ) : mt_rand( 450, 550 ) );
584
585 if ( ! is_array( $subscribers_total ) )
586 $show_subscribers_total = FALSE;
587
588 // Give the input element a unique ID
589 $subscribe_field_id = apply_filters( 'subscribe_field_id', 'subscribe-field', $widget_id );
590
591 echo $args['before_widget'];
592 echo $args['before_title'] . '<label for="' . esc_attr( $subscribe_field_id ) . '">' . esc_attr( $instance['title'] ) . '</label>' . $args['after_title'] . "\n";
593
594 $referer = ( is_ssl() ? 'https' : 'http' ) . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
595
596 // Check for subscription confirmation.
597 if ( isset( $_GET['subscribe'] ) && 'success' == $_GET['subscribe'] ) : ?>
598
599 <div class="success">
600 <p><?php esc_html_e( 'An email was just sent to confirm your subscription. Please find the email now and click activate to start subscribing.', 'jetpack' ); ?></p>
601 </div>
602
603 <?php endif;
604
605 // Display any errors
606 if ( isset( $_GET['subscribe'] ) ) :
607 switch ( $_GET['subscribe'] ) :
608 case 'invalid_email' : ?>
609 <p class="error"><?php esc_html_e( 'The email you entered was invalid, please check and try again.', 'jetpack' ); ?></p>
610 <?php break;
611 case 'already' : ?>
612 <p class="error"><?php esc_html_e( 'You have already subscribed to this site, please check your inbox.', 'jetpack' ); ?></p>
613 <?php break;
614 case 'success' :
615 echo wpautop( $subscribe_text );
616 break;
617 default : ?>
618 <p class="error"><?php esc_html_e( 'There was an error when subscribing, please try again.', 'jetpack' ) ?></p>
619 <?php break;
620 endswitch;
621 endif;
622
623 // Display a subscribe form ?>
624 <form action="" method="post" accept-charset="utf-8" id="subscribe-blog-<?php echo $widget_id; ?>">
625 <?php
626 if ( ! isset ( $_GET['subscribe'] ) ) {
627 ?><p id="subscribe-text"><?php echo $subscribe_text ?></p><?php
628 }
629
630 if ( $show_subscribers_total && 0 < $subscribers_total['value'] ) {
631 echo wpautop( sprintf( _n( 'Join %s other subscriber', 'Join %s other subscribers', $subscribers_total['value'], 'jetpack' ), number_format_i18n( $subscribers_total['value'] ) ) );
632 }
633 ?>
634
635 <p id="subscribe-email"><input type="text" name="email" value="<?php echo !empty( $current_user->user_email ) ? esc_attr( $current_user->user_email ) : esc_html__( 'Email Address', 'jetpack' ); ?>" id="<?php echo esc_attr($subscribe_field_id) ?>" onclick="if ( this.value == '<?php esc_html_e( 'Email Address', 'jetpack' ) ?>' ) { this.value = ''; }" onblur="if ( this.value == '' ) { this.value = '<?php esc_html_e( 'Email Address', 'jetpack' ) ?>'; }" /></p>
636
637 <p id="subscribe-submit">
638 <input type="hidden" name="action" value="subscribe" />
639 <input type="hidden" name="source" value="<?php echo esc_url( $referer ); ?>" />
640 <input type="hidden" name="sub-type" value="<?php echo esc_attr( $source ); ?>" />
641 <input type="hidden" name="redirect_fragment" value="<?php echo $widget_id; ?>" />
642 <?php
643 if ( is_user_logged_in() ) {
644 wp_nonce_field( 'blogsub_subscribe_'. get_current_blog_id(), '_wpnonce', false );
645 }
646 ?>
647 <input type="submit" value="<?php echo esc_attr( $subscribe_button ); ?>" name="jetpack_subscriptions_widget" />
648 </p>
649 </form>
650
651 <?php
652
653 echo "\n" . $args['after_widget'];
654 }
655
656 function increment_subscriber_count( $current_subs_array = array() ) {
657 $current_subs_array['value']++;
658
659 set_transient( 'wpcom_subscribers_total', $current_subs_array, 3600 ); // try to cache the result for at least 1 hour
660
661 return $current_subs_array;
662 }
663
664 function fetch_subscriber_count() {
665 $subs_count = get_transient( 'wpcom_subscribers_total' );
666
667 if ( FALSE === $subs_count || 'failed' == $subs_count['status'] ) {
668 Jetpack:: load_xml_rpc_client();
669
670 $xml = new Jetpack_IXR_Client( array( 'user_id' => JETPACK_MASTER_USER, ) );
671
672 $xml->query( 'jetpack.fetchSubscriberCount' );
673
674 if ( $xml->isError() ) { // if we get an error from .com, set the status to failed so that we will try again next time the data is requested
675 $subs_count = array(
676 'status' => 'failed',
677 'code' => $xml->getErrorCode(),
678 'message' => $xml->getErrorMessage(),
679 'value' => ( isset( $subs_count['value'] ) ) ? $subs_count['value'] : 0,
680 );
681 } else {
682 $subs_count = array(
683 'status' => 'success',
684 'value' => $xml->getResponse(),
685 );
686 }
687
688 set_transient( 'wpcom_subscribers_total', $subs_count, 3600 ); // try to cache the result for at least 1 hour
689 }
690
691 return $subs_count;
692 }
693
694 function update( $new_instance, $old_instance ) {
695 $instance = $old_instance;
696
697 $instance['title'] = wp_kses( stripslashes( $new_instance['title'] ), array() );
698 $instance['subscribe_text'] = wp_filter_post_kses( stripslashes( $new_instance['subscribe_text'] ) );
699 $instance['subscribe_logged_in'] = wp_filter_post_kses( stripslashes( $new_instance['subscribe_logged_in'] ) );
700 $instance['subscribe_button'] = wp_kses( stripslashes( $new_instance['subscribe_button'] ), array() );
701 $instance['show_subscribers_total'] = isset( $new_instance['show_subscribers_total'] ) && $new_instance['show_subscribers_total'];
702
703 return $instance;
704 }
705
706 public static function defaults() {
707 return array(
708 'title' => esc_html__( 'Subscribe to Blog via Email', 'jetpack' ),
709 'subscribe_text' => esc_html__( 'Enter your email address to subscribe to this blog and receive notifications of new posts by email.', 'jetpack' ),
710 'subscribe_button' => esc_html__( 'Subscribe', 'jetpack' ),
711 'subscribe_logged_in' => esc_html__( 'Click to subscribe to this blog and receive notifications of new posts by email.', 'jetpack' ),
712 'show_subscribers_total' => true,
713 );
714 }
715
716 function form( $instance ) {
717 $instance = wp_parse_args( (array) $instance, $this->defaults() );
718
719 $title = stripslashes( $instance['title'] );
720 $subscribe_text = stripslashes( $instance['subscribe_text'] );
721 $subscribe_button = stripslashes( $instance['subscribe_button'] );
722 $show_subscribers_total = checked( $instance['show_subscribers_total'], true, false );
723
724 $subs_fetch = $this->fetch_subscriber_count();
725
726 if ( 'failed' == $subs_fetch['status'] ) {
727 printf( '<div class="error inline"><p>' . __( '%s: %s', 'jetpack' ) . '</p></div>', esc_html( $subs_fetch['code'] ), esc_html( $subs_fetch['message'] ) );
728 }
729 $subscribers_total = number_format_i18n( $subs_fetch['value'] );
730
731 ?>
732 <p>
733 <label for="<?php echo $this->get_field_id( 'title' ); ?>">
734 <?php _e( 'Widget title:', 'jetpack' ); ?>
735 <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />
736 </label>
737 </p>
738 <p>
739 <label for="<?php echo $this->get_field_id( 'subscribe_text' ); ?>">
740 <?php _e( 'Optional text to display to your readers:', 'jetpack' ); ?>
741 <textarea style="width: 95%" id="<?php echo $this->get_field_id( 'subscribe_text' ); ?>" name="<?php echo $this->get_field_name( 'subscribe_text' ); ?>" type="text"><?php echo esc_html( $subscribe_text ); ?></textarea>
742 </label>
743 </p>
744 <p>
745 <label for="<?php echo $this->get_field_id( 'subscribe_button' ); ?>">
746 <?php _e( 'Subscribe Button:', 'jetpack' ); ?>
747 <input class="widefat" id="<?php echo $this->get_field_id( 'subscribe_button' ); ?>" name="<?php echo $this->get_field_name( 'subscribe_button' ); ?>" type="text" value="<?php echo esc_attr( $subscribe_button ); ?>" />
748 </label>
749 </p>
750 <p>
751 <label for="<?php echo $this->get_field_id( 'show_subscribers_total' ); ?>">
752 <input type="checkbox" id="<?php echo $this->get_field_id( 'show_subscribers_total' ); ?>" name="<?php echo $this->get_field_name( 'show_subscribers_total' ); ?>" value="1"<?php echo $show_subscribers_total; ?> />
753 <?php echo esc_html( sprintf( _n( 'Show total number of subscribers? (%s subscriber)', 'Show total number of subscribers? (%s subscribers)', $subscribers_total, 'jetpack' ), $subscribers_total ) ); ?>
754 </label>
755 </p>
756 <?php
757 }
758 }
759
760 add_shortcode( 'jetpack_subscription_form', 'jetpack_do_subscription_form' );
761
762 function jetpack_do_subscription_form( $args ) {
763 $args['show_subscribers_total'] = empty( $args['show_subscribers_total'] ) ? false : true;
764 $args = shortcode_atts( Jetpack_Subscriptions_Widget::defaults(), $args );
765 ob_start();
766 the_widget( 'Jetpack_Subscriptions_Widget', $args );
767 $output = ob_get_clean();
768 return $output;
769 }
770