PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 6.2
Jetpack – WP Security, Backup, Speed, & Growth v6.2
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
← All changes | modules/subscriptions.php +510 -424 12.2.36.2 View file →
@@ -1,32 +1,31 @@
1 -<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName)
1 +<?php
2 2 /**
3 3 * Module Name: Subscriptions
4 - * Module Description: Let visitors subscribe to new posts and comments via email
4 + * Module Description: Allow users to subscribe to your posts and comments and receive notifications via email
5 + * Jumpstart Description: Give visitors two easy subscription options — while commenting, or via a separate email subscription widget you can display.
5 6 * Sort Order: 9
6 7 * Recommendation Order: 8
7 8 * First Introduced: 1.2
8 9 * Requires Connection: Yes
9 - * Requires User Connection: Yes
10 - * Auto Activate: No
10 + * Auto Activate: Yes
11 11 * Module Tags: Social
12 - * Feature: Engagement
12 + * Feature: Engagement, Jumpstart
13 13 * Additional Search Queries: subscriptions, subscription, email, follow, followers, subscribers, signup
14 14 */
15 15
16 -// phpcs:disable Universal.Files.SeparateFunctionsFromOO.Mixed -- TODO: Move classes to appropriately-named class files.
17 -
18 -use Automattic\Jetpack\Connection\XMLRPC_Async_Call;
19 -
20 16 add_action( 'jetpack_modules_loaded', 'jetpack_subscriptions_load' );
21 17
22 -/**
23 - * Loads the Subscriptions module.
24 - */
25 18 function jetpack_subscriptions_load() {
26 19 Jetpack::enable_module_configurable( __FILE__ );
20 + Jetpack::module_configuration_load( __FILE__, 'jetpack_subscriptions_configuration_load' );
27 21 }
28 22
23 +function jetpack_subscriptions_configuration_load() {
24 + wp_safe_redirect( admin_url( 'options-discussion.php#jetpack-subscriptions-settings' ) );
25 + exit;
26 +}
27 +
29 28 /**
30 29 * Cherry picks keys from `$_SERVER` array.
31 30 *
32 31 * @since 6.0.0
@@ -48,49 +47,32 @@
48 47
49 48 return $data;
50 49 }
51 50
52 -/**
53 - * Main class file for the Subscriptions module.
54 - */
55 51 class Jetpack_Subscriptions {
56 - /**
57 - * Whether Jetpack has been instantiated or not.
58 - *
59 - * @var bool
60 - */
61 52 public $jetpack = false;
62 53
63 - /**
64 - * Hash of the siteurl option.
65 - *
66 - * @var string
67 - */
68 54 public static $hash;
69 55
70 56 /**
71 57 * Singleton
72 - *
73 58 * @static
74 59 */
75 - public static function init() {
60 + static function init() {
76 61 static $instance = false;
77 62
78 - if ( ! $instance ) {
79 - $instance = new Jetpack_Subscriptions();
63 + if ( !$instance ) {
64 + $instance = new Jetpack_Subscriptions;
80 65 }
81 66
82 67 return $instance;
83 68 }
84 69
85 - /**
86 - * Jetpack_Subscriptions constructor.
87 - */
88 - public function __construct() {
70 + function __construct() {
89 71 $this->jetpack = Jetpack::init();
90 72
91 73 // Don't use COOKIEHASH as it could be shared across installs && is non-unique in multisite.
92 - // @see: https://twitter.com/nacin/status/378246957451333632 .
74 + // @see: https://twitter.com/nacin/status/378246957451333632
93 75 self::$hash = md5( get_option( 'siteurl' ) );
94 76
95 77 add_filter( 'jetpack_xmlrpc_methods', array( $this, 'xmlrpc_methods' ) );
96 78
@@ -95,23 +77,25 @@
95 77 add_filter( 'jetpack_xmlrpc_methods', array( $this, 'xmlrpc_methods' ) );
96 78
97 79 // @todo remove sync from subscriptions and move elsewhere...
98 80
99 - // Add Configuration Page.
81 + // Add Configuration Page
100 82 add_action( 'admin_init', array( $this, 'configure' ) );
101 83
102 - // Catch subscription widget submits.
103 - if ( isset( $_REQUEST['jetpack_subscriptions_widget'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce checked in widget_submit() for logged in users.
84 + // Set up the subscription widget.
85 + add_action( 'widgets_init', array( $this, 'widget_init' ) );
86 +
87 + // Catch subscription widget submits
88 + if ( isset( $_REQUEST['jetpack_subscriptions_widget'] ) )
104 89 add_action( 'template_redirect', array( $this, 'widget_submit' ) );
105 - }
106 90
107 - // Set up the comment subscription checkboxes.
108 - add_filter( 'comment_form_submit_field', array( $this, 'comment_subscribe_init' ), 10, 2 );
91 + // Set up the comment subscription checkboxes
92 + add_action( 'comment_form', array( $this, 'comment_subscribe_init' ) );
109 93
110 94 // Catch comment posts and check for subscriptions.
111 95 add_action( 'comment_post', array( $this, 'comment_subscribe_submit' ), 50, 2 );
112 96
113 - // Adds post meta checkbox in the post submit metabox.
97 + // Adds post meta checkbox in the post submit metabox
114 98 add_action( 'post_submitbox_misc_actions', array( $this, 'subscription_post_page_metabox' ) );
115 99
116 100 add_action( 'transition_post_status', array( $this, 'maybe_send_subscription_email' ), 10, 3 );
117 101
@@ -117,15 +101,8 @@
117 101
118 102 add_filter( 'jetpack_published_post_flags', array( $this, 'set_post_flags' ), 10, 2 );
119 103
120 104 add_filter( 'post_updated_messages', array( $this, 'update_published_message' ), 18, 1 );
121 -
122 - // Set "social_notifications_subscribe" option during the first-time activation.
123 - add_action( 'jetpack_activate_module_subscriptions', array( $this, 'set_social_notifications_subscribe' ) );
124 -
125 - // Hide subscription messaging in Publish panel for posts that were published in the past
126 - add_action( 'init', array( $this, 'register_post_meta' ), 20 );
127 - add_action( 'transition_post_status', array( $this, 'maybe_set_first_published_status' ), 10, 3 );
128 105 }
129 106
130 107 /**
131 108 * Jetpack_Subscriptions::xmlrpc_methods()
@@ -130,12 +107,11 @@
130 107 /**
131 108 * Jetpack_Subscriptions::xmlrpc_methods()
132 109 *
133 110 * Register subscriptions methods with the Jetpack XML-RPC server.
134 - *
135 - * @param array $methods Methods being registered.
111 + * @param array $methods
136 112 */
137 - public function xmlrpc_methods( $methods ) {
113 + function xmlrpc_methods( $methods ) {
138 114 return array_merge(
139 115 $methods,
140 116 array(
141 117 'jetpack.subscriptions.subscribe' => array( $this, 'subscribe' ),
@@ -142,13 +118,13 @@
142 118 )
143 119 );
144 120 }
145 121
146 - /**
122 + /*
147 123 * Disable Subscribe on Single Post
148 124 * Register post meta
149 125 */
150 - public function subscription_post_page_metabox() {
126 + function subscription_post_page_metabox() {
151 127 if (
152 128 /**
153 129 * Filter whether or not to show the per-post subscription option.
154 130 *
@@ -157,9 +133,10 @@
157 133 * @since 3.7.0
158 134 *
159 135 * @param bool true = show checkbox option on all new posts | false = hide the option.
160 136 */
161 - ! apply_filters( 'jetpack_allow_per_post_subscriptions', false ) ) {
137 + ! apply_filters( 'jetpack_allow_per_post_subscriptions', false ) )
138 + {
162 139 return;
163 140 }
164 141
165 142 if ( has_filter( 'jetpack_subscriptions_exclude_these_categories' ) || has_filter( 'jetpack_subscriptions_include_only_these_categories' ) ) {
@@ -168,19 +145,18 @@
168 145
169 146 global $post;
170 147 $disable_subscribe_value = get_post_meta( $post->ID, '_jetpack_dont_email_post_to_subs', true );
171 148 // only show checkbox if post hasn't been published and is a 'post' post type.
172 - if ( get_post_status( $post->ID ) !== 'publish' && get_post_type( $post->ID ) === 'post' ) :
173 - // Nonce it.
149 + if ( get_post_status( $post->ID ) !== 'publish' && get_post_type( $post->ID ) == 'post' ) :
150 + // Nonce it
174 151 wp_nonce_field( 'disable_subscribe', 'disable_subscribe_nonce' );
175 152 ?>
176 153 <div class="misc-pub-section">
177 - <label for="_jetpack_dont_email_post_to_subs"><?php esc_html_e( 'Jetpack Subscriptions:', 'jetpack' ); ?></label><br>
154 + <label for="_jetpack_dont_email_post_to_subs"><?php _e( 'Jetpack Subscriptions:', 'jetpack' ); ?></label><br>
178 155 <input type="checkbox" name="_jetpack_dont_email_post_to_subs" id="jetpack-per-post-subscribe" value="1" <?php checked( $disable_subscribe_value, 1, true ); ?> />
179 - <?php esc_html_e( 'Don&#8217;t send this to subscribers', 'jetpack' ); ?>
156 + <?php _e( 'Don&#8217;t send this to subscribers', 'jetpack' ); ?>
180 157 </div>
181 - <?php
182 - endif;
158 + <?php endif;
183 159 }
184 160
185 161 /**
186 162 * Checks whether or not the post should be emailed to subscribers
@@ -191,54 +167,43 @@
191 167 * - Existence of the per-post checkbox option
192 168 *
193 169 * Only one of these can be used at any given time.
194 170 *
195 - * @param string $new_status Tthe "new" post status of the transition when saved.
196 - * @param string $old_status The "old" post status of the transition when saved.
197 - * @param object $post obj The post object.
171 + * @param $new_status string - the "new" post status of the transition when saved
172 + * @param $old_status string - the "old" post status of the transition when saved
173 + * @param $post obj - The post object
198 174 */
199 - public function maybe_send_subscription_email( $new_status, $old_status, $post ) {
175 + function maybe_send_subscription_email( $new_status, $old_status, $post ) {
200 176
201 177 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
202 178 return;
203 179 }
204 180
205 - // Make sure that the checkbox is preseved.
206 - 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.
181 + // Make sure that the checkbox is preseved
182 + if ( ! empty( $_POST['disable_subscribe_nonce'] ) && wp_verify_nonce( $_POST['disable_subscribe_nonce'], 'disable_subscribe' ) ) {
207 183 $set_checkbox = isset( $_POST['_jetpack_dont_email_post_to_subs'] ) ? 1 : 0;
208 184 update_post_meta( $post->ID, '_jetpack_dont_email_post_to_subs', $set_checkbox );
209 185 }
210 186 }
211 187
212 - /**
213 - * Message used when publishing a post.
214 - *
215 - * @param array $messages Message array for a post.
216 - */
217 - public function update_published_message( $messages ) {
188 + function update_published_message( $messages ) {
218 189 global $post;
219 190 if ( ! $this->should_email_post_to_subscribers( $post ) ) {
220 191 return $messages;
221 192 }
222 193
223 - $view_post_link_html = sprintf(
224 - ' <a href="%1$s">%2$s</a>',
194 + $view_post_link_html = sprintf( ' <a href="%1$s">%2$s</a>',
225 195 esc_url( get_permalink( $post ) ),
226 - __( 'View post', 'jetpack' )
196 + __( 'View post' ) // intentinally omitted domain
227 197 );
228 198
229 199 $messages['post'][6] = sprintf(
230 200 /* translators: Message shown after a post is published */
231 201 esc_html__( 'Post published and sending emails to subscribers.', 'jetpack' )
232 - ) . $view_post_link_html;
202 + ) . $view_post_link_html;
233 203 return $messages;
234 204 }
235 205
236 - /**
237 - * Determine if a post should notifiy subscribers via email.
238 - *
239 - * @param object $post The post.
240 - */
241 206 public function should_email_post_to_subscribers( $post ) {
242 207 $should_email = true;
243 208 if ( get_post_meta( $post->ID, '_jetpack_dont_email_post_to_subs', true ) ) {
244 209 return false;
@@ -243,18 +208,13 @@
243 208 if ( get_post_meta( $post->ID, '_jetpack_dont_email_post_to_subs', true ) ) {
244 209 return false;
245 210 }
246 211
247 - // Only posts are currently supported.
248 - if ( 'post' !== $post->post_type ) {
212 + // Only posts are currently supported
213 + if ( $post->post_type !== 'post' ) {
249 214 return false;
250 215 }
251 216
252 - // Private posts are not sent to subscribers.
253 - if ( 'private' === $post->post_status ) {
254 - return false;
255 - }
256 -
257 217 /**
258 218 * Array of categories that will never trigger subscription emails.
259 219 *
260 220 * Will not send subscription emails from any post from within these categories.
@@ -266,9 +226,9 @@
266 226 * @param array $args Array of category slugs or ID's.
267 227 */
268 228 $excluded_categories = apply_filters( 'jetpack_subscriptions_exclude_these_categories', array() );
269 229
270 - // Never email posts from these categories.
230 + // Never email posts from these categories
271 231 if ( ! empty( $excluded_categories ) && in_category( $excluded_categories, $post->ID ) ) {
272 232 $should_email = false;
273 233 }
274 234
@@ -284,9 +244,9 @@
284 244 * @param array $args Array of category slugs or ID's.
285 245 */
286 246 $only_these_categories = apply_filters( 'jetpack_subscriptions_exclude_all_categories_except', array() );
287 247
288 - // Only emails posts from these categories.
248 + // Only emails posts from these categories
289 249 if ( ! empty( $only_these_categories ) && ! in_category( $only_these_categories, $post->ID ) ) {
290 250 $should_email = false;
291 251 }
292 252
@@ -292,15 +252,9 @@
292 252
293 253 return $should_email;
294 254 }
295 255
296 - /**
297 - * Retrieve which flags should be added to a particular post.
298 - *
299 - * @param array $flags Flags to be added.
300 - * @param object $post A post object.
301 - */
302 - public function set_post_flags( $flags, $post ) {
256 + function set_post_flags( $flags, $post ) {
303 257 $flags['send_subscription'] = $this->should_email_post_to_subscribers( $post );
304 258 return $flags;
305 259 }
306 260
@@ -308,10 +262,10 @@
308 262 * Jetpack_Subscriptions::configure()
309 263 *
310 264 * Jetpack Subscriptions configuration screen.
311 265 */
312 - public function configure() {
313 - // Create the section.
266 + function configure() {
267 + // Create the section
314 268 add_settings_section(
315 269 'jetpack_subscriptions',
316 270 __( 'Jetpack Subscriptions Settings', 'jetpack' ),
317 271 array( $this, 'subscriptions_settings_section' ),
@@ -317,9 +271,9 @@
317 271 array( $this, 'subscriptions_settings_section' ),
318 272 'discussion'
319 273 );
320 274
321 - /** Subscribe to Posts */
275 + /** Subscribe to Posts ***************************************************/
322 276
323 277 add_settings_field(
324 278 'jetpack_subscriptions_post_subscribe',
325 279 __( 'Follow Blog', 'jetpack' ),
@@ -332,9 +286,9 @@
332 286 'discussion',
333 287 'stb_enabled'
334 288 );
335 289
336 - /** Subscribe to Comments */
290 + /** Subscribe to Comments ******************************************************/
337 291
338 292 add_settings_field(
339 293 'jetpack_subscriptions_comment_subscribe',
340 294 __( 'Follow Comments', 'jetpack' ),
@@ -347,35 +301,11 @@
347 301 'discussion',
348 302 'stc_enabled'
349 303 );
350 304
351 - /** Email me whenever: Someone follows my blog */
352 - /* @since 8.1 */
305 + /** Subscription Messaging Options ******************************************************/
353 306
354 - add_settings_section(
355 - 'notifications_section',
356 - __( 'Someone follows my blog', 'jetpack' ),
357 - array( $this, 'social_notifications_subscribe_section' ),
358 - 'discussion'
359 - );
360 -
361 - add_settings_field(
362 - 'jetpack_subscriptions_social_notifications_subscribe',
363 - __( 'Email me whenever', 'jetpack' ),
364 - array( $this, 'social_notifications_subscribe_field' ),
365 - 'discussion',
366 - 'notifications_section'
367 - );
368 -
369 307 register_setting(
370 - 'discussion',
371 - 'social_notifications_subscribe',
372 - array( $this, 'social_notifications_subscribe_validate' )
373 - );
374 -
375 - /** Subscription Messaging Options */
376 -
377 - register_setting(
378 308 'reading',
379 309 'subscription_options',
380 310 array( $this, 'validate_settings' )
381 311 );
@@ -404,198 +334,94 @@
404 334 );
405 335 }
406 336
407 337 /**
408 - * Discussions setting section blurb.
338 + * Discussions setting section blurb
339 + *
409 340 */
410 - public function subscriptions_settings_section() {
411 - ?>
412 - <p id="jetpack-subscriptions-settings"><?php esc_html_e( 'Change whether your visitors can subscribe to your posts or comments or both.', 'jetpack' ); ?></p>
341 + function subscriptions_settings_section() {
342 + ?>
343 + <p id="jetpack-subscriptions-settings"><?php _e( 'Change whether your visitors can subscribe to your posts or comments or both.', 'jetpack' ); ?></p>
413 344
414 - <?php
345 + <?php
415 346 }
416 347
417 348 /**
418 - * Post Subscriptions Toggle.
349 + * Post Subscriptions Toggle
350 + *
419 351 */
420 - public function subscription_post_subscribe_setting() {
352 + function subscription_post_subscribe_setting() {
421 353
422 - $stb_enabled = get_option( 'stb_enabled', 1 );
423 - ?>
354 + $stb_enabled = get_option( 'stb_enabled', 1 ); ?>
424 355
425 356 <p class="description">
426 357 <input type="checkbox" name="stb_enabled" id="jetpack-post-subscribe" value="1" <?php checked( $stb_enabled, 1 ); ?> />
427 - <?php
428 - echo wp_kses(
429 - __(
430 - "Show a <em>'follow blog'</em> option in the comment form",
431 - 'jetpack'
432 - ),
433 - array( 'em' => array() )
434 - );
435 - ?>
358 + <?php _e( "Show a <em>'follow blog'</em> option in the comment form", 'jetpack' ); ?>
436 359 </p>
437 - <?php
360 + <?php
438 361 }
439 362
440 363 /**
441 - * Comments Subscriptions Toggle.
364 + * Comments Subscriptions Toggle
365 + *
442 366 */
443 - public function subscription_comment_subscribe_setting() {
367 + function subscription_comment_subscribe_setting() {
444 368
445 - $stc_enabled = get_option( 'stc_enabled', 1 );
446 - ?>
369 + $stc_enabled = get_option( 'stc_enabled', 1 ); ?>
447 370
448 371 <p class="description">
449 372 <input type="checkbox" name="stc_enabled" id="jetpack-comment-subscribe" value="1" <?php checked( $stc_enabled, 1 ); ?> />
450 - <?php
451 - echo wp_kses(
452 - __(
453 - "Show a <em>'follow comments'</em> option in the comment form",
454 - 'jetpack'
455 - ),
456 - array( 'em' => array() )
457 - );
458 - ?>
373 + <?php _e( "Show a <em>'follow comments'</em> option in the comment form", 'jetpack' ); ?>
459 374 </p>
460 375
461 - <?php
376 + <?php
462 377 }
463 378
464 - /**
465 - * Someone follows my blog section
466 - *
467 - * @since 8.1
468 - */
469 - public function social_notifications_subscribe_section() {
470 - // Atypical usage here. We emit jquery to move subscribe notification checkbox to be with the rest of the email notification settings.
471 - ?>
472 - <script type="text/javascript">
473 - jQuery( function( $ ) {
474 - var table = $( '#social_notifications_subscribe' ).parents( 'table:first' ),
475 - header = table.prevAll( 'h2:first' ),
476 - newParent = $( '#moderation_notify' ).parent( 'label' ).parent();
477 -
478 - if ( ! table.length || ! header.length || ! newParent.length ) {
479 - return;
480 - }
481 -
482 - newParent.append( '<br/>' ).append( table.end().parent( 'label' ).siblings().andSelf() );
483 - header.remove();
484 - table.remove();
485 - } );
486 - </script>
487 - <?php
488 - }
489 -
490 - /**
491 - * Someone follows my blog Toggle
492 - *
493 - * @since 8.1
494 - */
495 - public function social_notifications_subscribe_field() {
496 - $checked = (int) ( 'on' === get_option( 'social_notifications_subscribe', 'on' ) );
497 - ?>
498 -
499 - <label>
500 - <input type="checkbox" name="social_notifications_subscribe" id="social_notifications_subscribe" value="1" <?php checked( $checked ); ?> />
501 - <?php
502 - /* translators: this is a label for a setting that starts with "Email me whenever" */
503 - esc_html_e( 'Someone follows my blog', 'jetpack' );
504 - ?>
505 - </label>
506 - <?php
507 - }
508 -
509 - /**
510 - * Validate "Someone follows my blog" option
511 - *
512 - * @since 8.1
513 - *
514 - * @param String $input the input string to be validated.
515 - * @return string on|off
516 - */
517 - public function social_notifications_subscribe_validate( $input ) {
518 - // If it's not set (was unchecked during form submission) or was set to off (during option update), return 'off'.
519 - if ( ! $input || 'off' === $input ) {
520 - return 'off';
521 - }
522 -
523 - // Otherwise we return 'on'.
524 - return 'on';
525 - }
526 -
527 - /**
528 - * Validate settings for the Subscriptions module.
529 - *
530 - * @param array $settings Settings to be validated.
531 - */
532 - public function validate_settings( $settings ) {
379 + function validate_settings( $settings ) {
533 380 global $allowedposttags;
534 381
535 382 $default = $this->get_default_settings();
536 383
537 - // Blog Follow.
384 + // Blog Follow
538 385 $settings['invitation'] = trim( wp_kses( $settings['invitation'], $allowedposttags ) );
539 - if ( empty( $settings['invitation'] ) ) {
386 + if ( empty( $settings['invitation'] ) )
540 387 $settings['invitation'] = $default['invitation'];
541 - }
542 388
543 - // Comments Follow (single post).
389 + // Comments Follow (single post)
544 390 $settings['comment_follow'] = trim( wp_kses( $settings['comment_follow'], $allowedposttags ) );
545 - if ( empty( $settings['comment_follow'] ) ) {
391 + if ( empty( $settings['comment_follow'] ) )
546 392 $settings['comment_follow'] = $default['comment_follow'];
547 - }
548 393
549 394 return $settings;
550 395 }
551 396
552 - /**
553 - * HTML output helper for Reading section.
554 - */
555 397 public function reading_section() {
556 398 echo '<p id="follower-settings">';
557 - esc_html_e( 'These settings change emails sent from your blog to followers.', 'jetpack' );
399 + _e( 'These settings change emails sent from your blog to followers.', 'jetpack' );
558 400 echo '</p>';
559 401 }
560 402
561 - /**
562 - * HTML output helper for Invitation section.
563 - */
564 403 public function setting_invitation() {
565 404 $settings = $this->get_settings();
566 405 echo '<textarea name="subscription_options[invitation]" class="large-text" cols="50" rows="5">' . esc_textarea( $settings['invitation'] ) . '</textarea>';
567 - echo '<p><span class="description">' . esc_html__( 'Introduction text sent when someone follows your blog. (Site and confirmation details will be automatically added for you.)', 'jetpack' ) . '</span></p>';
406 + 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>';
568 407 }
569 408
570 - /**
571 - * HTML output helper for Comment Follow section.
572 - */
573 409 public function setting_comment_follow() {
574 410 $settings = $this->get_settings();
575 411 echo '<textarea name="subscription_options[comment_follow]" class="large-text" cols="50" rows="5">' . esc_textarea( $settings['comment_follow'] ) . '</textarea>';
576 - echo '<p><span class="description">' . esc_html__( 'Introduction text sent when someone follows a post on your blog. (Site and confirmation details will be automatically added for you.)', 'jetpack' ) . '</span></p>';
412 + 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>';
577 413 }
578 414
579 - /**
580 - * Get default settings for the Subscriptions module.
581 - */
582 - public function get_default_settings() {
583 - $site_url = get_home_url();
584 - $display_url = preg_replace( '(^https?://)', '', untrailingslashit( $site_url ) );
585 -
415 + function get_default_settings() {
586 416 return array(
587 - /* translators: Both %1$s and %2$s is site address */
588 - 'invitation' => sprintf( __( "Howdy,\nYou recently subscribed to <a href='%1\$s'>%2\$s</a> and we need to verify the email you provided. Once you confirm below, you'll be able to receive and read new posts.\n\nIf you believe this is an error, ignore this message and nothing more will happen.", 'jetpack' ), $site_url, $display_url ),
589 - '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' ),
417 + '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' ),
418 + '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' )
590 419 );
591 420 }
592 421
593 - /**
594 - * Reeturn merged `subscription_options` option with module default settings.
595 - */
596 - public function get_settings() {
597 - return wp_parse_args( (array) get_option( 'subscription_options' ), $this->get_default_settings() );
422 + function get_settings() {
423 + return wp_parse_args( (array) get_option( 'subscription_options', array() ), $this->get_default_settings() );
598 424 }
599 425
600 426 /**
601 427 * Jetpack_Subscriptions::subscribe()
@@ -601,30 +427,29 @@
601 427 * Jetpack_Subscriptions::subscribe()
602 428 *
603 429 * Send a synchronous XML-RPC subscribe to blog posts or subscribe to post comments request.
604 430 *
605 - * @param string $email being subscribed.
606 - * @param array $post_ids (optional) defaults to 0 for blog posts only: array of post IDs to subscribe to blog's posts.
431 + * @param string $email
432 + * @param array $post_ids (optional) defaults to 0 for blog posts only: array of post IDs to subscribe to blog's posts
607 433 * @param bool $async (optional) Should the subscription be performed asynchronously? Defaults to true.
608 - * @param array $extra_data Additional data passed to the `jetpack.subscribeToSite` call.
609 434 *
610 - * @return true|WP_Error true on success
611 - * invalid_email : not a valid email address
612 - * invalid_post_id : not a valid post ID
613 - * unknown_post_id : unknown post
614 - * not_subscribed : strange error. Jetpack servers at WordPress.com could subscribe the email.
615 - * disabled : Site owner has disabled subscriptions.
616 - * active : Already subscribed.
617 - * pending : Tried to subscribe before but the confirmation link is never clicked. No confirmation email is sent.
618 - * unknown : strange error. Jetpack servers at WordPress.com returned something malformed.
619 - * unknown_status : strange error. Jetpack servers at WordPress.com returned something I didn't understand.
435 + * @return true|Jetpack_Error true on success
436 + * invalid_email : not a valid email address
437 + * invalid_post_id : not a valid post ID
438 + * unknown_post_id : unknown post
439 + * not_subscribed : strange error. Jetpack servers at WordPress.com could subscribe the email.
440 + * disabled : Site owner has disabled subscriptions.
441 + * active : Already subscribed.
442 + * unknown : strange error. Jetpack servers at WordPress.com returned something malformed.
443 + * unknown_status : strange error. Jetpack servers at WordPress.com returned something I didn't understand.
620 444 */
621 - public function subscribe( $email, $post_ids = 0, $async = true, $extra_data = array() ) {
622 - if ( ! is_email( $email ) ) {
623 - return new WP_Error( 'invalid_email' );
445 + function subscribe( $email, $post_ids = 0, $async = true, $extra_data = array() ) {
446 + if ( !is_email( $email ) ) {
447 + return new Jetpack_Error( 'invalid_email' );
624 448 }
625 449
626 - if ( ! $async ) {
450 + if ( !$async ) {
451 + Jetpack::load_xml_rpc_client();
627 452 $xml = new Jetpack_IXR_ClientMulticall();
628 453 }
629 454
630 455 foreach ( (array) $post_ids as $post_id ) {
@@ -629,17 +454,17 @@
629 454
630 455 foreach ( (array) $post_ids as $post_id ) {
631 456 $post_id = (int) $post_id;
632 457 if ( $post_id < 0 ) {
633 - return new WP_Error( 'invalid_post_id' );
634 - } elseif ( $post_id && ! get_post( $post_id ) ) {
635 - return new WP_Error( 'unknown_post_id' );
458 + return new Jetpack_Error( 'invalid_post_id' );
459 + } else if ( $post_id && !$post = get_post( $post_id ) ) {
460 + return new Jetpack_Error( 'unknown_post_id' );
636 461 }
637 462
638 463 if ( $async ) {
639 - XMLRPC_Async_Call::add_call( 'jetpack.subscribeToSite', 0, $email, $post_id, serialize( $extra_data ) ); //phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
464 + Jetpack::xmlrpc_async_call( 'jetpack.subscribeToSite', $email, $post_id, serialize( $extra_data ) );
640 465 } else {
641 - $xml->addCall( 'jetpack.subscribeToSite', $email, $post_id, serialize( $extra_data ) ); //phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
466 + $xml->addCall( 'jetpack.subscribeToSite', $email, $post_id, serialize( $extra_data ) );
642 467 }
643 468 }
644 469
645 470 if ( $async ) {
@@ -645,9 +470,9 @@
645 470 if ( $async ) {
646 471 return;
647 472 }
648 473
649 - // Call.
474 + // Call
650 475 $xml->query();
651 476
652 477 if ( $xml->isError() ) {
653 478 return $xml->get_jetpack_error();
@@ -661,32 +486,29 @@
661 486 $r[] = $xml->get_jetpack_error( $response['faultCode'], $response['faultString'] );
662 487 continue;
663 488 }
664 489
665 - if ( ! is_array( $response[0] ) || empty( $response[0]['status'] ) ) {
666 - $r[] = new WP_Error( 'unknown' );
490 + if ( !is_array( $response[0] ) || empty( $response[0]['status'] ) ) {
491 + $r[] = new Jetpack_Error( 'unknown' );
667 492 continue;
668 493 }
669 494
670 495 switch ( $response[0]['status'] ) {
671 - case 'error':
672 - $r[] = new WP_Error( 'not_subscribed' );
673 - continue 2;
674 - case 'disabled':
675 - $r[] = new WP_Error( 'disabled' );
676 - continue 2;
677 - case 'active':
678 - $r[] = new WP_Error( 'active' );
679 - continue 2;
680 - case 'confirming':
681 - $r[] = true;
682 - continue 2;
683 - case 'pending':
684 - $r[] = new WP_Error( 'pending' );
685 - continue 2;
686 - default:
687 - $r[] = new WP_Error( 'unknown_status', (string) $response[0]['status'] );
688 - continue 2;
496 + case 'error' :
497 + $r[] = new Jetpack_Error( 'not_subscribed' );
498 + continue 2;
499 + case 'disabled' :
500 + $r[] = new Jetpack_Error( 'disabled' );
501 + continue 2;
502 + case 'active' :
503 + $r[] = new Jetpack_Error( 'active' );
504 + continue 2;
505 + case 'pending' :
506 + $r[] = true;
507 + continue 2;
508 + default :
509 + $r[] = new Jetpack_Error( 'unknown_status', (string) $response[0]['status'] );
510 + continue 2;
689 511 }
690 512 }
691 513
692 514 return $r;
@@ -692,40 +514,48 @@
692 514 return $r;
693 515 }
694 516
695 517 /**
518 + * Jetpack_Subscriptions::widget_init()
519 + *
520 + * Initialize and register the Jetpack Subscriptions widget.
521 + */
522 + function widget_init() {
523 + register_widget( 'Jetpack_Subscriptions_Widget' );
524 + }
525 +
526 + /**
696 527 * Jetpack_Subscriptions::widget_submit()
697 528 *
698 529 * When a user submits their email via the blog subscription widget, check the details and call the subsribe() method.
699 530 */
700 - public function widget_submit() {
531 + function widget_submit() {
701 532 // Check the nonce.
702 533 if ( is_user_logged_in() ) {
703 534 check_admin_referer( 'blogsub_subscribe_' . get_current_blog_id() );
704 535 }
705 536
706 - if ( empty( $_REQUEST['email'] ) || ! is_string( $_REQUEST['email'] ) ) {
537 + if ( empty( $_REQUEST['email'] ) )
707 538 return false;
708 - }
709 539
710 540 $redirect_fragment = false;
711 541 if ( isset( $_REQUEST['redirect_fragment'] ) ) {
712 - $redirect_fragment = preg_replace( '/[^a-z0-9_-]/i', '', $_REQUEST['redirect_fragment'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- This is manually unslashing and sanitizing.
542 + $redirect_fragment = preg_replace( '/[^a-z0-9_-]/i', '', $_REQUEST['redirect_fragment'] );
713 543 }
714 - if ( ! $redirect_fragment || ! is_string( $redirect_fragment ) ) {
544 + if ( !$redirect_fragment ) {
715 545 $redirect_fragment = 'subscribe-blog';
716 546 }
717 547
718 - $subscribe = self::subscribe(
719 - isset( $_REQUEST['email'] ) ? wp_unslash( $_REQUEST['email'] ) : null, // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Validated inside self::subscribe().
720 - 0,
721 - false,
722 - array(
723 - 'source' => 'widget',
724 - 'widget-in-use' => is_active_widget( false, false, 'blog_subscription', true ) ? 'yes' : 'no',
725 - 'comment_status' => '',
726 - 'server_data' => jetpack_subscriptions_cherry_pick_server_data(),
727 - )
548 + $subscribe = Jetpack_Subscriptions::subscribe(
549 + $_REQUEST['email'],
550 + 0,
551 + false,
552 + array(
553 + 'source' => 'widget',
554 + 'widget-in-use' => is_active_widget( false, false, 'blog_subscription', true ) ? 'yes' : 'no',
555 + 'comment_status' => '',
556 + 'server_data' => jetpack_subscriptions_cherry_pick_server_data(),
557 + )
728 558 );
729 559
730 560 if ( is_wp_error( $subscribe ) ) {
731 561 $error = $subscribe->get_error_code();
@@ -749,16 +579,11 @@
749 579 case 'blocked_email':
750 580 $result = 'opted_out';
751 581 break;
752 582 case 'active':
583 + case 'pending':
753 584 $result = 'already';
754 585 break;
755 - case 'flooded_email':
756 - $result = 'many_pending_subs';
757 - break;
758 - case 'pending':
759 - $result = 'pending';
760 - break;
761 586 default:
762 587 $result = 'error';
763 588 break;
764 589 }
@@ -783,12 +608,10 @@
783 608 /**
784 609 * Jetpack_Subscriptions::comment_subscribe_init()
785 610 *
786 611 * Set up and add the comment subscription checkbox to the comment form.
787 - *
788 - * @param string $submit_button HTML markup for the submit field.
789 612 */
790 - public function comment_subscribe_init( $submit_button ) {
613 + function comment_subscribe_init() {
791 614 global $post;
792 615
793 616 $comments_checked = '';
794 617 $blog_checked = '';
@@ -801,20 +624,20 @@
801 624 if ( isset( $_COOKIE[ 'jetpack_blog_subscribe_' . self::$hash ] ) ) {
802 625 $blog_checked = ' checked="checked"';
803 626 }
804 627
805 - // Some themes call this function, don't show the checkbox again.
628 + // Some themes call this function, don't show the checkbox again
806 629 remove_action( 'comment_form', 'subscription_comment_form' );
807 630
808 - // Check if Mark Jaquith's Subscribe to Comments plugin is active - if so, suppress Jetpack checkbox.
631 + // Check if Mark Jaquith's Subscribe to Comments plugin is active - if so, suppress Jetpack checkbox
809 632
810 633 $str = '';
811 634
812 - if ( false === has_filter( 'comment_form', 'show_subscription_checkbox' ) && 1 === (int) get_option( 'stc_enabled', 1 ) && empty( $post->post_password ) && 'post' === get_post_type() ) {
813 - // Subscribe to comments checkbox.
814 - $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 . ' /> ';
635 + if ( FALSE === has_filter( 'comment_form', 'show_subscription_checkbox' ) && 1 == get_option( 'stc_enabled', 1 ) && empty( $post->post_password ) && 'post' == get_post_type() ) {
636 + // Subscribe to comments checkbox
637 + $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 . ' /> ';
815 638 $comment_sub_text = __( 'Notify me of follow-up comments by email.', 'jetpack' );
816 - $str .= '<label class="subscribe-label" id="subscribe-label" for="subscribe_comments">' . esc_html(
639 + $str .= '<label class="subscribe-label" id="subscribe-label" for="subscribe_comments">' . esc_html(
817 640 /**
818 641 * Filter the Subscribe to comments text appearing below the comment form.
819 642 *
820 643 * @module subscriptions
@@ -827,13 +650,13 @@
827 650 ) . '</label>';
828 651 $str .= '</p>';
829 652 }
830 653
831 - if ( 1 === (int) get_option( 'stb_enabled', 1 ) ) {
832 - // Subscribe to blog checkbox.
833 - $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 . ' /> ';
654 + if ( 1 == get_option( 'stb_enabled', 1 ) ) {
655 + // Subscribe to blog checkbox
656 + $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 . ' /> ';
834 657 $blog_sub_text = __( 'Notify me of new posts by email.', 'jetpack' );
835 - $str .= '<label class="subscribe-label" id="subscribe-blog-label" for="subscribe_blog">' . esc_html(
658 + $str .= '<label class="subscribe-label" id="subscribe-blog-label" for="subscribe_blog">' . esc_html(
836 659 /**
837 660 * Filter the Subscribe to blog text appearing below the comment form.
838 661 *
839 662 * @module subscriptions
@@ -855,11 +678,9 @@
855 678 * @since 1.2.0
856 679 *
857 680 * @param string $str Comment Subscription form HTML output.
858 681 */
859 - $str = apply_filters( 'jetpack_comment_subscription_form', $str );
860 -
861 - return $str . $submit_button;
682 + echo apply_filters( 'jetpack_comment_subscription_form', $str );
862 683 }
863 684
864 685 /**
865 686 * Jetpack_Subscriptions::comment_subscribe_init()
@@ -864,49 +685,40 @@
864 685 /**
865 686 * Jetpack_Subscriptions::comment_subscribe_init()
866 687 *
867 688 * When a user checks the comment subscribe box and submits a comment, subscribe them to the comment thread.
868 - *
869 - * @param int|string $comment_id Comment thread being subscribed to.
870 - * @param string $approved Comment status.
871 689 */
872 - public function comment_subscribe_submit( $comment_id, $approved ) {
690 + function comment_subscribe_submit( $comment_id, $approved ) {
873 691 if ( 'spam' === $approved ) {
874 692 return;
875 693 }
876 694
877 695 $comment = get_comment( $comment_id );
878 - if ( ! $comment ) {
879 - return;
880 - }
881 696
882 - // Set cookies for this post/comment.
883 - $this->set_cookies( isset( $_REQUEST['subscribe_comments'] ), $comment->comment_post_ID, isset( $_REQUEST['subscribe_blog'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
697 + // Set cookies for this post/comment
698 + $this->set_cookies( isset( $_REQUEST['subscribe_comments'] ), $comment->comment_post_ID, isset( $_REQUEST['subscribe_blog'] ) );
884 699
885 - if ( ! isset( $_REQUEST['subscribe_comments'] ) && ! isset( $_REQUEST['subscribe_blog'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
700 + if ( !isset( $_REQUEST['subscribe_comments'] ) && !isset( $_REQUEST['subscribe_blog'] ) )
886 701 return;
887 - }
888 702
889 703 $post_ids = array();
890 704
891 - if ( isset( $_REQUEST['subscribe_comments'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
705 + if ( isset( $_REQUEST['subscribe_comments'] ) )
892 706 $post_ids[] = $comment->comment_post_ID;
893 - }
894 707
895 - if ( isset( $_REQUEST['subscribe_blog'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
708 + if ( isset( $_REQUEST['subscribe_blog'] ) )
896 709 $post_ids[] = 0;
897 - }
898 710
899 - $result = self::subscribe(
900 - $comment->comment_author_email,
901 - $post_ids,
902 - true,
903 - array(
904 - 'source' => 'comment-form',
905 - 'widget-in-use' => is_active_widget( false, false, 'blog_subscription', true ) ? 'yes' : 'no',
906 - 'comment_status' => $approved,
907 - 'server_data' => jetpack_subscriptions_cherry_pick_server_data(),
908 - )
711 + $result = Jetpack_Subscriptions::subscribe(
712 + $comment->comment_author_email,
713 + $post_ids,
714 + true,
715 + array(
716 + 'source' => 'comment-form',
717 + 'widget-in-use' => is_active_widget( false, false, 'blog_subscription', true ) ? 'yes' : 'no',
718 + 'comment_status' => $approved,
719 + 'server_data' => jetpack_subscriptions_cherry_pick_server_data(),
720 + )
909 721 );
910 722
911 723 /**
912 724 * Fires on each comment subscription form submission.
@@ -915,9 +727,9 @@
915 727 *
916 728 * @since 5.5.0
917 729 *
918 730 * @param NULL|WP_Error $result Result of form submission: NULL on success, WP_Error otherwise.
919 - * @param array $post_ids An array of post IDs that the user subscribed to, 0 means blog subscription.
731 + * @param Array $post_ids An array of post IDs that the user subscribed to, 0 means blog subscription.
920 732 */
921 733 do_action( 'jetpack_subscriptions_comment_form_submission', $result, $post_ids );
922 734 }
923 735
@@ -926,16 +738,16 @@
926 738 *
927 739 * Set a cookie to save state on the comment and post subscription checkboxes.
928 740 *
929 741 * @param bool $subscribe_to_post Whether the user chose to subscribe to subsequent comments on this post.
930 - * @param int $post_id If $subscribe_to_post is true, the post ID they've subscribed to.
742 + * @param int $post_id If $subscribe_to_post is true, the post ID they've subscribed to.
931 743 * @param bool $subscribe_to_blog Whether the user chose to subscribe to all new posts on the blog.
932 744 */
933 - public function set_cookies( $subscribe_to_post = false, $post_id = null, $subscribe_to_blog = false ) {
934 - $post_id = (int) $post_id;
745 + function set_cookies( $subscribe_to_post = false, $post_id = null, $subscribe_to_blog = false ) {
746 + $post_id = intval( $post_id );
935 747
936 748 /** This filter is already documented in core/wp-includes/comment-functions.php */
937 - $cookie_lifetime = apply_filters( 'comment_cookie_lifetime', 30000000 );
749 + $cookie_lifetime = apply_filters( 'comment_cookie_lifetime', 30000000 );
938 750
939 751 /**
940 752 * Filter the Jetpack Comment cookie path.
941 753 *
@@ -944,9 +756,9 @@
944 756 * @since 2.5.0
945 757 *
946 758 * @param string COOKIEPATH Cookie path.
947 759 */
948 - $cookie_path = apply_filters( 'jetpack_comment_cookie_path', COOKIEPATH );
760 + $cookie_path = apply_filters( 'jetpack_comment_cookie_path', COOKIEPATH );
949 761
950 762 /**
951 763 * Filter the Jetpack Comment cookie domain.
952 764 *
@@ -955,84 +767,358 @@
955 767 * @since 2.5.0
956 768 *
957 769 * @param string COOKIE_DOMAIN Cookie domain.
958 770 */
959 - $cookie_domain = apply_filters( 'jetpack_comment_cookie_domain', COOKIE_DOMAIN );
771 + $cookie_domain = apply_filters( 'jetpack_comment_cookie_domain', COOKIE_DOMAIN );
960 772
961 773 if ( $subscribe_to_post && $post_id >= 0 ) {
962 - setcookie( 'jetpack_comments_subscribe_' . self::$hash . '_' . $post_id, 1, time() + $cookie_lifetime, $cookie_path, $cookie_domain, is_ssl(), true );
774 + setcookie( 'jetpack_comments_subscribe_' . self::$hash . '_' . $post_id, 1, time() + $cookie_lifetime, $cookie_path, $cookie_domain );
963 775 } else {
964 - setcookie( 'jetpack_comments_subscribe_' . self::$hash . '_' . $post_id, '', time() - 3600, $cookie_path, $cookie_domain, is_ssl(), true );
776 + setcookie( 'jetpack_comments_subscribe_' . self::$hash . '_' . $post_id, '', time() - 3600, $cookie_path, $cookie_domain );
965 777 }
966 778
967 779 if ( $subscribe_to_blog ) {
968 - setcookie( 'jetpack_blog_subscribe_' . self::$hash, 1, time() + $cookie_lifetime, $cookie_path, $cookie_domain, is_ssl(), true );
780 + setcookie( 'jetpack_blog_subscribe_' . self::$hash, 1, time() + $cookie_lifetime, $cookie_path, $cookie_domain );
969 781 } else {
970 - setcookie( 'jetpack_blog_subscribe_' . self::$hash, '', time() - 3600, $cookie_path, $cookie_domain, is_ssl(), true );
782 + setcookie( 'jetpack_blog_subscribe_' . self::$hash, '', time() - 3600, $cookie_path, $cookie_domain );
971 783 }
972 784 }
973 785
974 - /**
975 - * Set the social_notifications_subscribe option to `off` when the Subscriptions module is activated in the first time.
976 - *
977 - * @since 8.1
978 - *
979 - * @return void
980 - */
981 - public function set_social_notifications_subscribe() {
982 - if ( false === get_option( 'social_notifications_subscribe' ) ) {
983 - add_option( 'social_notifications_subscribe', 'off' );
786 +}
787 +
788 +Jetpack_Subscriptions::init();
789 +
790 +
791 +/***
792 + * Blog Subscription Widget
793 + */
794 +
795 +class Jetpack_Subscriptions_Widget extends WP_Widget {
796 + function __construct() {
797 + $widget_ops = array(
798 + 'classname' => 'jetpack_subscription_widget',
799 + 'description' => esc_html__( 'Add an email signup form to allow people to subscribe to your blog.', 'jetpack' ),
800 + 'customize_selective_refresh' => true,
801 + );
802 +
803 + parent::__construct(
804 + 'blog_subscription',
805 + /** This filter is documented in modules/widgets/facebook-likebox.php */
806 + apply_filters( 'jetpack_widget_name', __( 'Blog Subscriptions', 'jetpack' ) ),
807 + $widget_ops
808 + );
809 +
810 + if ( is_active_widget( false, false, $this->id_base ) || is_active_widget( false, false, 'monster' ) || is_customize_preview() ) {
811 + add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_style' ) );
984 812 }
985 813 }
986 814
987 815 /**
988 - * Save a flag when a post was ever published.
816 + * Enqueue the form's CSS.
989 817 *
990 - * It saves the post meta when the post was published and becomes a draft.
991 - * Then this meta is used to hide subscription messaging in Publish panel.
992 - *
993 - * @param string $new_status Tthe "new" post status of the transition when saved.
994 - * @param string $old_status The "old" post status of the transition when saved.
995 - * @param object $post obj The post object.
818 + * @since 4.5.0
996 819 */
997 - public function maybe_set_first_published_status( $new_status, $old_status, $post ) {
998 - $was_post_ever_published = get_post_meta( $post->ID, '_jetpack_post_was_ever_published', true );
999 - if ( ! $was_post_ever_published && 'publish' === $old_status && 'draft' === $new_status ) {
1000 - update_post_meta( $post->ID, '_jetpack_post_was_ever_published', true );
820 + function enqueue_style() {
821 + wp_register_style( 'jetpack-subscriptions', plugins_url( 'subscriptions/subscriptions.css', __FILE__ ) );
822 + wp_enqueue_style( 'jetpack-subscriptions' );
823 + }
824 +
825 + function widget( $args, $instance ) {
826 + if (
827 + ( ! defined( 'IS_WPCOM' ) || ! IS_WPCOM ) &&
828 + /** This filter is already documented in modules/contact-form/grunion-contact-form.php */
829 + false === apply_filters( 'jetpack_auto_fill_logged_in_user', false )
830 + ) {
831 + $subscribe_email = '';
832 + } else {
833 + $current_user = wp_get_current_user();
834 + if ( ! empty( $current_user->user_email ) ) {
835 + $subscribe_email = esc_attr( $current_user->user_email );
836 + } else {
837 + $subscribe_email = '';
838 + }
1001 839 }
840 +
841 + /** This action is already documented in modules/widgets/gravatar-profile.php */
842 + do_action( 'jetpack_stats_extra', 'widget_view', 'jetpack_subscriptions' );
843 +
844 + $source = 'widget';
845 + $instance = wp_parse_args( (array) $instance, $this->defaults() );
846 + $subscribe_text = isset( $instance['subscribe_text'] ) ? stripslashes( $instance['subscribe_text'] ) : '';
847 + $subscribe_placeholder = isset( $instance['subscribe_placeholder'] ) ? stripslashes( $instance['subscribe_placeholder'] ) : '';
848 + $subscribe_button = isset( $instance['subscribe_button'] ) ? stripslashes( $instance['subscribe_button'] ) : '';
849 + $success_message = isset( $instance['success_message'] ) ? stripslashes( $instance['success_message'] ) : '';
850 + $widget_id = esc_attr( !empty( $args['widget_id'] ) ? esc_attr( $args['widget_id'] ) : mt_rand( 450, 550 ) );
851 +
852 + $show_subscribers_total = (bool) $instance['show_subscribers_total'];
853 + $subscribers_total = $this->fetch_subscriber_count(); // Only used for the shortcode [total-subscribers]
854 +
855 + // Give the input element a unique ID
856 + /**
857 + * Filter the subscription form's ID prefix.
858 + *
859 + * @module subscriptions
860 + *
861 + * @since 2.7.0
862 + *
863 + * @param string subscribe-field Subscription form field prefix.
864 + * @param int $widget_id Widget ID.
865 + */
866 + $subscribe_field_id = apply_filters( 'subscribe_field_id', 'subscribe-field', $widget_id );
867 +
868 + // Display the subscription form
869 + echo $args['before_widget'];
870 +
871 + // Only show the title if there actually is a title
872 + if( ! empty( $instance['title'] ) ) {
873 + echo $args['before_title'] . esc_attr( $instance['title'] ) . $args['after_title'] . "\n";
874 + }
875 +
876 + $referer = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
877 +
878 + // Display any errors
879 + if ( isset( $_GET['subscribe'] ) ) :
880 + switch ( $_GET['subscribe'] ) :
881 + case 'invalid_email' : ?>
882 + <p class="error"><?php esc_html_e( 'The email you entered was invalid. Please check and try again.', 'jetpack' ); ?></p>
883 + <?php break;
884 + case 'opted_out' : ?>
885 + <p class="error"><?php printf( __( 'The email address has opted out of subscription emails. <br /> You can manage your preferences at <a href="%1$s" title="%2$s" target="_blank">subscribe.wordpress.com</a>', 'jetpack' ),
886 + 'https://subscribe.wordpress.com/',
887 + __( 'Manage your email preferences.', 'jetpack' )
888 + ); ?></p>
889 + <?php break;
890 + case 'already' : ?>
891 + <p class="error"><?php printf( __( 'You have already subscribed to this site. Please check your inbox. <br /> You can manage your preferences at <a href="%1$s" title="%2$s" target="_blank">subscribe.wordpress.com</a>', 'jetpack' ),
892 + 'https://subscribe.wordpress.com/',
893 + __( 'Manage your email preferences.', 'jetpack' )
894 + ); ?></p>
895 + <?php break;
896 + case 'success' : ?>
897 + <div class="success"><?php echo wpautop( str_replace( '[total-subscribers]', number_format_i18n( $subscribers_total['value'] ), $success_message ) ); ?></div>
898 + <?php break;
899 + default : ?>
900 + <p class="error"><?php esc_html_e( 'There was an error when subscribing. Please try again.', 'jetpack' ); ?></p>
901 + <?php break;
902 + endswitch;
903 + endif;
904 +
905 + // Display a subscribe form
906 + if ( isset( $_GET['subscribe'] ) && 'success' == $_GET['subscribe'] ) { ?>
907 + <?php
908 + } else { ?>
909 + <form action="#" method="post" accept-charset="utf-8" id="subscribe-blog-<?php echo $widget_id; ?>">
910 + <?php
911 + if ( ! isset ( $_GET['subscribe'] ) || 'success' != $_GET['subscribe'] ) {
912 + ?><div id="subscribe-text"><?php echo wpautop( str_replace( '[total-subscribers]', number_format_i18n( $subscribers_total['value'] ), $subscribe_text ) ); ?></div><?php
913 + }
914 +
915 + if ( $show_subscribers_total && 0 < $subscribers_total['value'] ) {
916 + echo wpautop( sprintf( _n( 'Join %s other subscriber', 'Join %s other subscribers', $subscribers_total['value'], 'jetpack' ), number_format_i18n( $subscribers_total['value'] ) ) );
917 + }
918 + if ( ! isset ( $_GET['subscribe'] ) || 'success' != $_GET['subscribe'] ) { ?>
919 + <p id="subscribe-email">
920 + <label id="jetpack-subscribe-label" for="<?php echo esc_attr( $subscribe_field_id ) . '-' . esc_attr( $widget_id ); ?>">
921 + <?php echo !empty( $subscribe_placeholder ) ? esc_html( $subscribe_placeholder ) : esc_html__( 'Email Address:', 'jetpack' ); ?>
922 + </label>
923 + <input type="email" name="email" required="required" class="required" value="<?php echo esc_attr( $subscribe_email ); ?>" id="<?php echo esc_attr( $subscribe_field_id ) . '-' . esc_attr( $widget_id ); ?>" placeholder="<?php echo esc_attr( $subscribe_placeholder ); ?>" />
924 + </p>
925 +
926 + <p id="subscribe-submit">
927 + <input type="hidden" name="action" value="subscribe" />
928 + <input type="hidden" name="source" value="<?php echo esc_url( $referer ); ?>" />
929 + <input type="hidden" name="sub-type" value="<?php echo esc_attr( $source ); ?>" />
930 + <input type="hidden" name="redirect_fragment" value="<?php echo $widget_id; ?>" />
931 + <?php
932 + if ( is_user_logged_in() ) {
933 + wp_nonce_field( 'blogsub_subscribe_'. get_current_blog_id(), '_wpnonce', false );
934 + }
935 + ?>
936 + <input type="submit" value="<?php echo esc_attr( $subscribe_button ); ?>" name="jetpack_subscriptions_widget" />
937 + </p>
938 + <?php }?>
939 + </form>
940 +
941 + <script>
942 + /*
943 + Custom functionality for safari and IE
944 + */
945 + (function( d ) {
946 + // In case the placeholder functionality is available we remove labels
947 + if ( ( 'placeholder' in d.createElement( 'input' ) ) ) {
948 + var label = d.querySelector( 'label[for=subscribe-field-<?php echo $widget_id; ?>]' );
949 + label.style.clip = 'rect(1px, 1px, 1px, 1px)';
950 + label.style.position = 'absolute';
951 + label.style.height = '1px';
952 + label.style.width = '1px';
953 + label.style.overflow = 'hidden';
954 + }
955 +
956 + // Make sure the email value is filled in before allowing submit
957 + var form = d.getElementById('subscribe-blog-<?php echo $widget_id; ?>'),
958 + input = d.getElementById('<?php echo esc_attr( $subscribe_field_id ) . '-' . esc_attr( $widget_id ); ?>'),
959 + handler = function( event ) {
960 + if ( '' === input.value ) {
961 + input.focus();
962 +
963 + if ( event.preventDefault ){
964 + event.preventDefault();
965 + }
966 +
967 + return false;
968 + }
969 + };
970 +
971 + if ( window.addEventListener ) {
972 + form.addEventListener( 'submit', handler, false );
973 + } else {
974 + form.attachEvent( 'onsubmit', handler );
975 + }
976 + })( document );
977 + </script>
978 + <?php } ?>
979 + <?php
980 +
981 + echo "\n" . $args['after_widget'];
1002 982 }
1003 983
1004 - /**
1005 - * Checks if the current user can publish posts.
1006 - *
1007 - * @return bool
1008 - */
1009 - public function first_published_status_meta_auth_callback() {
1010 - if ( current_user_can( 'publish_posts' ) ) {
1011 - return true;
984 + function increment_subscriber_count( $current_subs_array = array() ) {
985 + $current_subs_array['value']++;
986 +
987 + set_transient( 'wpcom_subscribers_total', $current_subs_array, 3600 ); // try to cache the result for at least 1 hour
988 +
989 + return $current_subs_array;
990 + }
991 +
992 + function fetch_subscriber_count() {
993 + $subs_count = get_transient( 'wpcom_subscribers_total' );
994 +
995 + if ( FALSE === $subs_count || 'failed' == $subs_count['status'] ) {
996 + Jetpack:: load_xml_rpc_client();
997 +
998 + $xml = new Jetpack_IXR_Client( array( 'user_id' => JETPACK_MASTER_USER, ) );
999 +
1000 + $xml->query( 'jetpack.fetchSubscriberCount' );
1001 +
1002 + 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
1003 + $subs_count = array(
1004 + 'status' => 'failed',
1005 + 'code' => $xml->getErrorCode(),
1006 + 'message' => $xml->getErrorMessage(),
1007 + 'value' => ( isset( $subs_count['value'] ) ) ? $subs_count['value'] : 0,
1008 + );
1009 + } else {
1010 + $subs_count = array(
1011 + 'status' => 'success',
1012 + 'value' => $xml->getResponse(),
1013 + );
1014 + }
1015 +
1016 + set_transient( 'wpcom_subscribers_total', $subs_count, 3600 ); // try to cache the result for at least 1 hour
1012 1017 }
1013 - return false;
1018 +
1019 + return $subs_count;
1014 1020 }
1015 1021
1016 - /**
1017 - * Registers the 'post_was_ever_published' post meta for use in the REST API.
1018 - */
1019 - public function register_post_meta() {
1020 - $jetpack_post_was_ever_published = array(
1021 - 'type' => 'boolean',
1022 - 'description' => __( 'Whether the post was ever published.', 'jetpack' ),
1023 - 'single' => true,
1024 - 'default' => false,
1025 - 'show_in_rest' => array(
1026 - 'name' => 'jetpack_post_was_ever_published',
1027 - ),
1028 - 'auth_callback' => array( $this, 'first_published_status_meta_auth_callback' ),
1022 + function update( $new_instance, $old_instance ) {
1023 + $instance = $old_instance;
1024 +
1025 + $instance['title'] = wp_kses( stripslashes( $new_instance['title'] ), array() );
1026 + $instance['subscribe_text'] = wp_filter_post_kses( stripslashes( $new_instance['subscribe_text'] ) );
1027 + $instance['subscribe_placeholder'] = wp_kses( stripslashes( $new_instance['subscribe_placeholder'] ), array() );
1028 + $instance['subscribe_button'] = wp_kses( stripslashes( $new_instance['subscribe_button'] ), array() );
1029 + $instance['success_message'] = wp_kses( stripslashes( $new_instance['success_message'] ), array() );
1030 + $instance['show_subscribers_total'] = isset( $new_instance['show_subscribers_total'] ) && $new_instance['show_subscribers_total'];
1031 +
1032 + return $instance;
1033 + }
1034 +
1035 + public static function defaults() {
1036 + return array(
1037 + 'title' => esc_html__( 'Subscribe to Blog via Email', 'jetpack' ),
1038 + 'subscribe_text' => esc_html__( 'Enter your email address to subscribe to this blog and receive notifications of new posts by email.', 'jetpack' ),
1039 + 'subscribe_placeholder' => esc_html__( 'Email Address', 'jetpack' ),
1040 + 'subscribe_button' => esc_html__( 'Subscribe', 'jetpack' ),
1041 + 'success_message' => esc_html__( "Success! An email was just sent to confirm your subscription. Please find the email now and click 'Confirm Follow' to start subscribing.", 'jetpack' ),
1042 + 'show_subscribers_total' => true,
1029 1043 );
1044 + }
1030 1045
1031 - register_meta( 'post', '_jetpack_post_was_ever_published', $jetpack_post_was_ever_published );
1046 + function form( $instance ) {
1047 + $instance = wp_parse_args( (array) $instance, $this->defaults() );
1048 +
1049 + $title = stripslashes( $instance['title'] );
1050 + $subscribe_text = stripslashes( $instance['subscribe_text'] );
1051 + $subscribe_placeholder = stripslashes( $instance['subscribe_placeholder'] );
1052 + $subscribe_button = stripslashes( $instance['subscribe_button'] );
1053 + $success_message = stripslashes( $instance['success_message']);
1054 + $show_subscribers_total = checked( $instance['show_subscribers_total'], true, false );
1055 +
1056 + $subs_fetch = $this->fetch_subscriber_count();
1057 +
1058 + if ( 'failed' == $subs_fetch['status'] ) {
1059 + printf( '<div class="error inline"><p>' . __( '%s: %s', 'jetpack' ) . '</p></div>', esc_html( $subs_fetch['code'] ), esc_html( $subs_fetch['message'] ) );
1060 + }
1061 + $subscribers_total = number_format_i18n( $subs_fetch['value'] );
1062 +?>
1063 +<p>
1064 + <label for="<?php echo $this->get_field_id( 'title' ); ?>">
1065 + <?php _e( 'Widget title:', 'jetpack' ); ?>
1066 + <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 ); ?>" />
1067 + </label>
1068 +</p>
1069 +<p>
1070 + <label for="<?php echo $this->get_field_id( 'subscribe_text' ); ?>">
1071 + <?php _e( 'Optional text to display to your readers:', 'jetpack' ); ?>
1072 + <textarea class="widefat" id="<?php echo $this->get_field_id( 'subscribe_text' ); ?>" name="<?php echo $this->get_field_name( 'subscribe_text' ); ?>" rows="3"><?php echo esc_html( $subscribe_text ); ?></textarea>
1073 + </label>
1074 +</p>
1075 +<p>
1076 + <label for="<?php echo $this->get_field_id( 'subscribe_placeholder' ); ?>">
1077 + <?php esc_html_e( 'Subscribe Placeholder:', 'jetpack' ); ?>
1078 + <input class="widefat" id="<?php echo $this->get_field_id( 'subscribe_placeholder' ); ?>" name="<?php echo $this->get_field_name( 'subscribe_placeholder' ); ?>" type="text" value="<?php echo esc_attr( $subscribe_placeholder ); ?>" />
1079 + </label>
1080 +</p>
1081 +<p>
1082 + <label for="<?php echo $this->get_field_id( 'subscribe_button' ); ?>">
1083 + <?php _e( 'Subscribe Button:', 'jetpack' ); ?>
1084 + <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 ); ?>" />
1085 + </label>
1086 +</p>
1087 +<p>
1088 + <label for="<?php echo $this->get_field_id( 'success_message' ); ?>">
1089 + <?php _e( 'Success Message Text:', 'jetpack' ); ?>
1090 + <textarea class="widefat" id="<?php echo $this->get_field_id( 'success_message' ); ?>" name="<?php echo $this->get_field_name( 'success_message' ); ?>" rows="5"><?php echo esc_html( $success_message ); ?></textarea>
1091 + </label>
1092 +</p>
1093 +<p>
1094 + <label for="<?php echo $this->get_field_id( 'show_subscribers_total' ); ?>">
1095 + <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; ?> />
1096 + <?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 ) ); ?>
1097 + </label>
1098 +</p>
1099 +<?php
1032 1100 }
1101 +}
1033 1102
1034 -}
1103 +add_shortcode( 'jetpack_subscription_form', 'jetpack_do_subscription_form' );
1104 +add_shortcode( 'blog_subscription_form', 'jetpack_do_subscription_form' );
1035 1105
1036 -Jetpack_Subscriptions::init();
1106 +function jetpack_do_subscription_form( $instance ) {
1107 + if ( empty( $instance ) || ! is_array( $instance ) ) {
1108 + $instance = array();
1109 + }
1110 + $instance['show_subscribers_total'] = empty( $instance['show_subscribers_total'] ) ? false : true;
1037 1111
1038 -require __DIR__ . '/subscriptions/views.php';
1112 + $instance = shortcode_atts(
1113 + Jetpack_Subscriptions_Widget::defaults(),
1114 + $instance,
1115 + 'jetpack_subscription_form'
1116 + );
1117 + $args = array(
1118 + 'before_widget' => sprintf( '<div class="%s">', 'jetpack_subscription_widget' ),
1119 + );
1120 + ob_start();
1121 + the_widget( 'Jetpack_Subscriptions_Widget', $instance, $args );
1122 + $output = ob_get_clean();
1123 + return $output;
1124 +}