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