Completed
Push — update/jitm-test ( 03ced2...c48940 )
by
unknown
212:35 queued 203:56
created

Jetpack_Subscriptions_Widget::defaults()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
1
<?php
2
/**
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.
6
 * Sort Order: 9
7
 * Recommendation Order: 8
8
 * First Introduced: 1.2
9
 * Requires Connection: Yes
10
 * Auto Activate: Yes
11
 * Module Tags: Social
12
 * Feature: Engagement, Jumpstart
13
 * Additional Search Queries: subscriptions, subscription, email, follow, followers, subscribers, signup
14
 */
15
16
add_action( 'jetpack_modules_loaded', 'jetpack_subscriptions_load' );
17
18
function jetpack_subscriptions_load() {
19
	Jetpack::enable_module_configurable( __FILE__ );
20
	Jetpack::module_configuration_load( __FILE__, 'jetpack_subscriptions_configuration_load' );
21
}
22
23
function jetpack_subscriptions_configuration_load() {
24
	wp_safe_redirect( admin_url( 'options-discussion.php#jetpack-subscriptions-settings' ) );
25
	exit;
26
}
27
28
/**
29
 * Cherry picks keys from `$_SERVER` array.
30
 *
31
 * @since 6.0.0
32
 *
33
 * @return array An array of server data.
34
 */
35
function jetpack_subscriptions_cherry_pick_server_data() {
36
	$data = array();
37
38
	foreach ( $_SERVER as $key => $value ) {
39
		if ( ! is_string( $value ) || 0 === strpos( $key, 'HTTP_COOKIE' ) ) {
40
			continue;
41
		}
42
43
		if ( 0 === strpos( $key, 'HTTP_' ) || in_array( $key, array( 'REMOTE_ADDR', 'REQUEST_URI', 'DOCUMENT_URI' ), true ) ) {
44
			$data[ $key ] = $value;
45
		}
46
	}
47
48
	return $data;
49
}
50
51
class Jetpack_Subscriptions {
52
	public $jetpack = false;
53
54
	public static $hash;
55
56
	/**
57
	 * Singleton
58
	 * @static
59
	 */
60
	static function init() {
61
		static $instance = false;
62
63
		if ( !$instance ) {
64
			$instance = new Jetpack_Subscriptions;
65
		}
66
67
		return $instance;
68
	}
69
70
	function __construct() {
71
		$this->jetpack = Jetpack::init();
0 ignored issues
show
Documentation Bug introduced by
It seems like \Jetpack::init() of type object<Jetpack> is incompatible with the declared type boolean of property $jetpack.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
72
73
		// Don't use COOKIEHASH as it could be shared across installs && is non-unique in multisite.
74
		// @see: https://twitter.com/nacin/status/378246957451333632
75
		self::$hash = md5( get_option( 'siteurl' ) );
76
77
		add_filter( 'jetpack_xmlrpc_methods', array( $this, 'xmlrpc_methods' ) );
78
79
		// @todo remove sync from subscriptions and move elsewhere...
80
81
		// Add Configuration Page
82
		add_action( 'admin_init', array( $this, 'configure' ) );
83
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'] ) )
89
			add_action( 'template_redirect', array( $this, 'widget_submit' ) );
90
91
		// Set up the comment subscription checkboxes
92
		add_action( 'comment_form_after_fields', array( $this, 'comment_subscribe_init' ) );
93
94
		// Catch comment posts and check for subscriptions.
95
		add_action( 'comment_post', array( $this, 'comment_subscribe_submit' ), 50, 2 );
96
97
		// Adds post meta checkbox in the post submit metabox
98
		add_action( 'post_submitbox_misc_actions', array( $this, 'subscription_post_page_metabox' ) );
99
100
		add_action( 'transition_post_status', array( $this, 'maybe_send_subscription_email' ), 10, 3 );
101
102
		add_filter( 'jetpack_published_post_flags', array( $this, 'set_post_flags' ), 10, 2 );
103
104
		add_filter( 'post_updated_messages', array( $this, 'update_published_message' ), 18, 1 );
105
	}
106
107
	/**
108
	 * Jetpack_Subscriptions::xmlrpc_methods()
109
	 *
110
	 * Register subscriptions methods with the Jetpack XML-RPC server.
111
	 * @param array $methods
112
	 */
113
	function xmlrpc_methods( $methods ) {
114
		return array_merge(
115
			$methods,
116
			array(
117
				'jetpack.subscriptions.subscribe' => array( $this, 'subscribe' ),
118
			)
119
		);
120
	}
121
122
	/*
123
	 * Disable Subscribe on Single Post
124
	 * Register post meta
125
	 */
126
	function subscription_post_page_metabox() {
127
		if (
128
			/**
129
			 * Filter whether or not to show the per-post subscription option.
130
			 *
131
			 * @module subscriptions
132
			 *
133
			 * @since 3.7.0
134
			 *
135
			 * @param bool true = show checkbox option on all new posts | false = hide the option.
136
			 */
137
			 ! apply_filters( 'jetpack_allow_per_post_subscriptions', false ) )
138
		{
139
			return;
140
		}
141
142
		if ( has_filter( 'jetpack_subscriptions_exclude_these_categories' ) || has_filter( 'jetpack_subscriptions_include_only_these_categories' ) ) {
143
			return;
144
		}
145
146
		global $post;
147
		$disable_subscribe_value = get_post_meta( $post->ID, '_jetpack_dont_email_post_to_subs', true );
148
		// only show checkbox if post hasn't been published and is a 'post' post type.
149
		if ( get_post_status( $post->ID ) !== 'publish' && get_post_type( $post->ID ) == 'post' ) :
150
			// Nonce it
151
			wp_nonce_field( 'disable_subscribe', 'disable_subscribe_nonce' );
152
			?>
153
			<div class="misc-pub-section">
154
				<label for="_jetpack_dont_email_post_to_subs"><?php _e( 'Jetpack Subscriptions:', 'jetpack' ); ?></label><br>
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 ); ?> />
156
				<?php _e( 'Don&#8217;t send this to subscribers', 'jetpack' ); ?>
157
			</div>
158
		<?php endif;
159
	}
160
161
	/**
162
	 * Checks whether or not the post should be emailed to subscribers
163
	 *
164
	 * It checks for the following things in order:
165
	 * - Usage of filter jetpack_subscriptions_exclude_these_categories
166
	 * - Usage of filter jetpack_subscriptions_include_only_these_categories
167
	 * - Existence of the per-post checkbox option
168
	 *
169
	 * Only one of these can be used at any given time.
170
	 *
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
174
	 */
175
	function maybe_send_subscription_email( $new_status, $old_status, $post ) {
176
177
		if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
178
			return;
179
		}
180
181
		// Make sure that the checkbox is preseved
182
		if ( ! empty( $_POST['disable_subscribe_nonce'] ) && wp_verify_nonce( $_POST['disable_subscribe_nonce'], 'disable_subscribe' ) ) {
183
			$set_checkbox = isset( $_POST['_jetpack_dont_email_post_to_subs'] ) ? 1 : 0;
184
			update_post_meta( $post->ID, '_jetpack_dont_email_post_to_subs', $set_checkbox );
185
		}
186
	}
187
188
	function update_published_message( $messages ) {
189
		global $post;
190
		if ( ! $this->should_email_post_to_subscribers( $post ) ) {
191
			return $messages;
192
		}
193
194
		$view_post_link_html = sprintf( ' <a href="%1$s">%2$s</a>',
195
			esc_url( get_permalink( $post ) ),
196
			__( 'View post', 'jetpack' )
197
		);
198
199
		$messages['post'][6] = sprintf(
200
			/* translators: Message shown after a post is published */
201
			esc_html__( 'Post published and sending emails to subscribers.', 'jetpack' )
202
			) . $view_post_link_html;
203
		return $messages;
204
	}
205
206
	public function should_email_post_to_subscribers( $post ) {
207
		$should_email = true;
208
		if ( get_post_meta( $post->ID, '_jetpack_dont_email_post_to_subs', true ) ) {
209
			return false;
210
		}
211
212
		// Only posts are currently supported
213
		if ( $post->post_type !== 'post' ) {
214
			return false;
215
		}
216
217
		/**
218
		 * Array of categories that will never trigger subscription emails.
219
		 *
220
		 * Will not send subscription emails from any post from within these categories.
221
		 *
222
		 * @module subscriptions
223
		 *
224
		 * @since 3.7.0
225
		 *
226
		 * @param array $args Array of category slugs or ID's.
227
		 */
228
		$excluded_categories = apply_filters( 'jetpack_subscriptions_exclude_these_categories', array() );
229
230
		// Never email posts from these categories
231
		if ( ! empty( $excluded_categories ) && in_category( $excluded_categories, $post->ID ) ) {
232
			$should_email = false;
233
		}
234
235
		/**
236
		 * ONLY send subscription emails for these categories
237
		 *
238
		 * Will ONLY send subscription emails to these categories.
239
		 *
240
		 * @module subscriptions
241
		 *
242
		 * @since 3.7.0
243
		 *
244
		 * @param array $args Array of category slugs or ID's.
245
		 */
246
		$only_these_categories = apply_filters( 'jetpack_subscriptions_exclude_all_categories_except', array() );
247
248
		// Only emails posts from these categories
249
		if ( ! empty( $only_these_categories ) && ! in_category( $only_these_categories, $post->ID ) ) {
250
			$should_email = false;
251
		}
252
253
		return $should_email;
254
	}
255
256
	function set_post_flags( $flags, $post ) {
257
		$flags['send_subscription'] = $this->should_email_post_to_subscribers( $post );
258
		return $flags;
259
	}
260
261
	/**
262
	 * Jetpack_Subscriptions::configure()
263
	 *
264
	 * Jetpack Subscriptions configuration screen.
265
	 */
266
	function configure() {
267
		// Create the section
268
		add_settings_section(
269
			'jetpack_subscriptions',
270
			__( 'Jetpack Subscriptions Settings', 'jetpack' ),
271
			array( $this, 'subscriptions_settings_section' ),
272
			'discussion'
273
		);
274
275
		/** Subscribe to Posts ***************************************************/
276
277
		add_settings_field(
278
			'jetpack_subscriptions_post_subscribe',
279
			__( 'Follow Blog', 'jetpack' ),
280
			array( $this, 'subscription_post_subscribe_setting' ),
281
			'discussion',
282
			'jetpack_subscriptions'
283
		);
284
285
		register_setting(
286
			'discussion',
287
			'stb_enabled'
288
		);
289
290
		/** Subscribe to Comments ******************************************************/
291
292
		add_settings_field(
293
			'jetpack_subscriptions_comment_subscribe',
294
			__( 'Follow Comments', 'jetpack' ),
295
			array( $this, 'subscription_comment_subscribe_setting' ),
296
			'discussion',
297
			'jetpack_subscriptions'
298
		);
299
300
		register_setting(
301
			'discussion',
302
			'stc_enabled'
303
		);
304
305
		/** Subscription Messaging Options ******************************************************/
306
307
		register_setting(
308
			'reading',
309
			'subscription_options',
310
			array( $this, 'validate_settings' )
311
		);
312
313
		add_settings_section(
314
			'email_settings',
315
			__( 'Follower Settings', 'jetpack' ),
316
			array( $this, 'reading_section' ),
317
			'reading'
318
		);
319
320
		add_settings_field(
321
			'invitation',
322
			__( 'Blog follow email text', 'jetpack' ),
323
			array( $this, 'setting_invitation' ),
324
			'reading',
325
			'email_settings'
326
		);
327
328
		add_settings_field(
329
			'comment-follow',
330
			__( 'Comment follow email text', 'jetpack' ),
331
			array( $this, 'setting_comment_follow' ),
332
			'reading',
333
			'email_settings'
334
		);
335
	}
336
337
	/**
338
	 * Discussions setting section blurb
339
	 *
340
	 */
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>
344
345
	<?php
346
	}
347
348
	/**
349
	 * Post Subscriptions Toggle
350
	 *
351
	 */
352 View Code Duplication
	function subscription_post_subscribe_setting() {
353
354
		$stb_enabled = get_option( 'stb_enabled', 1 ); ?>
355
356
		<p class="description">
357
			<input type="checkbox" name="stb_enabled" id="jetpack-post-subscribe" value="1" <?php checked( $stb_enabled, 1 ); ?> />
358
			<?php _e( "Show a <em>'follow blog'</em> option in the comment form", 'jetpack' ); ?>
359
		</p>
360
	<?php
361
	}
362
363
	/**
364
	 * Comments Subscriptions Toggle
365
	 *
366
	 */
367 View Code Duplication
	function subscription_comment_subscribe_setting() {
368
369
		$stc_enabled = get_option( 'stc_enabled', 1 ); ?>
370
371
		<p class="description">
372
			<input type="checkbox" name="stc_enabled" id="jetpack-comment-subscribe" value="1" <?php checked( $stc_enabled, 1 ); ?> />
373
			<?php _e( "Show a <em>'follow comments'</em> option in the comment form", 'jetpack' ); ?>
374
		</p>
375
376
	<?php
377
	}
378
379
	function validate_settings( $settings ) {
380
		global $allowedposttags;
381
382
		$default = $this->get_default_settings();
383
384
		// Blog Follow
385
		$settings['invitation'] = trim( wp_kses( $settings['invitation'], $allowedposttags ) );
386
		if ( empty( $settings['invitation'] ) )
387
			$settings['invitation'] = $default['invitation'];
388
389
		// Comments Follow (single post)
390
		$settings['comment_follow'] = trim( wp_kses( $settings['comment_follow'], $allowedposttags ) );
391
		if ( empty( $settings['comment_follow'] ) )
392
			$settings['comment_follow'] = $default['comment_follow'];
393
394
		return $settings;
395
	}
396
397
	public function reading_section() {
398
		echo '<p id="follower-settings">';
399
		_e( 'These settings change emails sent from your blog to followers.', 'jetpack' );
400
		echo '</p>';
401
	}
402
403
	public function setting_invitation() {
404
		$settings = $this->get_settings();
405
		echo '<textarea name="subscription_options[invitation]" class="large-text" cols="50" rows="5">' . esc_textarea( $settings['invitation'] ) . '</textarea>';
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>';
407
	}
408
409
	public function setting_comment_follow() {
410
		$settings = $this->get_settings();
411
		echo '<textarea name="subscription_options[comment_follow]" class="large-text" cols="50" rows="5">' . esc_textarea( $settings['comment_follow'] ) . '</textarea>';
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>';
413
	}
414
415
	function get_default_settings() {
416
		return array(
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' )
419
		);
420
	}
421
422
	function get_settings() {
423
		return wp_parse_args( (array) get_option( 'subscription_options', array() ), $this->get_default_settings() );
424
	}
425
426
	/**
427
	 * Jetpack_Subscriptions::subscribe()
428
	 *
429
	 * Send a synchronous XML-RPC subscribe to blog posts or subscribe to post comments request.
430
	 *
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
0 ignored issues
show
Documentation introduced by
Should the type for parameter $post_ids not be integer?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
433
	 * @param bool   $async    (optional) Should the subscription be performed asynchronously?  Defaults to true.
434
	 *
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.
444
	 */
445
	function subscribe( $email, $post_ids = 0, $async = true, $extra_data = array() ) {
446
		if ( !is_email( $email ) ) {
447
			return new Jetpack_Error( 'invalid_email' );
448
		}
449
450
		if ( !$async ) {
451
			Jetpack::load_xml_rpc_client();
452
			$xml = new Jetpack_IXR_ClientMulticall();
453
		}
454
455
		foreach ( (array) $post_ids as $post_id ) {
456
			$post_id = (int) $post_id;
457
			if ( $post_id < 0 ) {
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' );
461
			}
462
463
			if ( $async ) {
464
				Jetpack::xmlrpc_async_call( 'jetpack.subscribeToSite', $email, $post_id, serialize( $extra_data ) );
465
			} else {
466
				$xml->addCall( 'jetpack.subscribeToSite', $email, $post_id, serialize( $extra_data ) );
0 ignored issues
show
Bug introduced by
The variable $xml does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
467
			}
468
		}
469
470
		if ( $async ) {
471
			return;
472
		}
473
474
		// Call
475
		$xml->query();
476
477
		if ( $xml->isError() ) {
478
			return $xml->get_jetpack_error();
479
		}
480
481
		$responses = $xml->getResponse();
482
483
		$r = array();
484
		foreach ( (array) $responses as $response ) {
485
			if ( isset( $response['faultCode'] ) || isset( $response['faultString'] ) ) {
486
				$r[] = $xml->get_jetpack_error( $response['faultCode'], $response['faultString'] );
487
				continue;
488
			}
489
490
			if ( !is_array( $response[0] ) || empty( $response[0]['status'] ) ) {
491
				$r[] = new Jetpack_Error( 'unknown' );
492
				continue;
493
			}
494
495
			switch ( $response[0]['status'] ) {
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;
511
			}
512
		}
513
514
		return $r;
515
	}
516
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
	/**
527
	 * Jetpack_Subscriptions::widget_submit()
528
	 *
529
	 * When a user submits their email via the blog subscription widget, check the details and call the subsribe() method.
530
	 */
531
	function widget_submit() {
532
		// Check the nonce.
533
		if ( is_user_logged_in() ) {
534
			check_admin_referer( 'blogsub_subscribe_' . get_current_blog_id() );
535
		}
536
537
		if ( empty( $_REQUEST['email'] ) )
538
			return false;
539
540
		$redirect_fragment = false;
541
		if ( isset( $_REQUEST['redirect_fragment'] ) ) {
542
			$redirect_fragment = preg_replace( '/[^a-z0-9_-]/i', '', $_REQUEST['redirect_fragment'] );
543
		}
544
		if ( !$redirect_fragment ) {
545
			$redirect_fragment = 'subscribe-blog';
546
		}
547
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
												)
558
		);
559
560
		if ( is_wp_error( $subscribe ) ) {
561
			$error = $subscribe->get_error_code();
562
		} else {
563
			$error = false;
564
			foreach ( $subscribe as $response ) {
0 ignored issues
show
Bug introduced by
The expression $subscribe of type object<Jetpack_Error>|null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
565
				if ( is_wp_error( $response ) ) {
566
					$error = $response->get_error_code();
567
					break;
568
				}
569
			}
570
		}
571
572
		switch ( $error ) {
573
			case false:
574
				$result = 'success';
575
				break;
576
			case 'invalid_email':
577
				$result = $error;
578
				break;
579
			case 'blocked_email':
580
				$result = 'opted_out';
581
				break;
582
			case 'active':
583
			case 'pending':
584
				$result = 'already';
585
				break;
586
			default:
587
				$result = 'error';
588
				break;
589
		}
590
591
		$redirect = add_query_arg( 'subscribe', $result );
592
593
		/**
594
		 * Fires on each subscription form submission.
595
		 *
596
		 * @module subscriptions
597
		 *
598
		 * @since 3.7.0
599
		 *
600
		 * @param string $result Result of form submission: success, invalid_email, already, error.
601
		 */
602
		do_action( 'jetpack_subscriptions_form_submission', $result );
603
604
		wp_safe_redirect( "$redirect#$redirect_fragment" );
605
		exit;
606
	}
607
608
	/**
609
	 * Jetpack_Subscriptions::comment_subscribe_init()
610
	 *
611
	 * Set up and add the comment subscription checkbox to the comment form.
612
	 */
613
	function comment_subscribe_init() {
614
		global $post;
615
616
		$comments_checked = '';
617
		$blog_checked     = '';
618
619
		// Check for a comment / blog submission and set a cookie to retain the setting and check the boxes.
620
		if ( isset( $_COOKIE[ 'jetpack_comments_subscribe_' . self::$hash . '_' . $post->ID ] ) ) {
621
			$comments_checked = ' checked="checked"';
622
		}
623
624
		if ( isset( $_COOKIE[ 'jetpack_blog_subscribe_' . self::$hash ] ) ) {
625
			$blog_checked = ' checked="checked"';
626
		}
627
628
		// Some themes call this function, don't show the checkbox again
629
		remove_action( 'comment_form', 'subscription_comment_form' );
630
631
		// Check if Mark Jaquith's Subscribe to Comments plugin is active - if so, suppress Jetpack checkbox
632
633
		$str = '';
634
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 . ' /> ';
638
			$comment_sub_text = __( 'Notify me of follow-up comments by email.', 'jetpack' );
639
			$str .=	'<label class="subscribe-label" id="subscribe-label" for="subscribe_comments">' . esc_html(
640
				/**
641
				 * Filter the Subscribe to comments text appearing below the comment form.
642
				 *
643
				 * @module subscriptions
644
				 *
645
				 * @since 3.4.0
646
				 *
647
				 * @param string $comment_sub_text Subscribe to comments text.
648
				 */
649
				apply_filters( 'jetpack_subscribe_comment_label', $comment_sub_text )
650
			) . '</label>';
651
			$str .= '</p>';
652
		}
653
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 . ' /> ';
657
			$blog_sub_text = __( 'Notify me of new posts by email.', 'jetpack' );
658
			$str .=	'<label class="subscribe-label" id="subscribe-blog-label" for="subscribe_blog">' . esc_html(
659
				/**
660
				 * Filter the Subscribe to blog text appearing below the comment form.
661
				 *
662
				 * @module subscriptions
663
				 *
664
				 * @since 3.4.0
665
				 *
666
				 * @param string $comment_sub_text Subscribe to blog text.
667
				 */
668
				apply_filters( 'jetpack_subscribe_blog_label', $blog_sub_text )
669
			) . '</label>';
670
			$str .= '</p>';
671
		}
672
673
		/**
674
		 * Filter the output of the subscription options appearing below the comment form.
675
		 *
676
		 * @module subscriptions
677
		 *
678
		 * @since 1.2.0
679
		 *
680
		 * @param string $str Comment Subscription form HTML output.
681
		 */
682
		echo apply_filters( 'jetpack_comment_subscription_form', $str );
683
	}
684
685
	/**
686
	 * Jetpack_Subscriptions::comment_subscribe_init()
687
	 *
688
	 * When a user checks the comment subscribe box and submits a comment, subscribe them to the comment thread.
689
	 */
690
	function comment_subscribe_submit( $comment_id, $approved ) {
691
		if ( 'spam' === $approved ) {
692
			return;
693
		}
694
695
		$comment = get_comment( $comment_id );
696
697
		// Set cookies for this post/comment
698
		$this->set_cookies( isset( $_REQUEST['subscribe_comments'] ), $comment->comment_post_ID, isset( $_REQUEST['subscribe_blog'] ) );
699
700
		if ( !isset( $_REQUEST['subscribe_comments'] ) && !isset( $_REQUEST['subscribe_blog'] ) )
701
			return;
702
703
		$post_ids = array();
704
705
		if ( isset( $_REQUEST['subscribe_comments'] ) )
706
			$post_ids[] = $comment->comment_post_ID;
707
708
		if ( isset( $_REQUEST['subscribe_blog'] ) )
709
			$post_ids[] = 0;
710
711
		$result = Jetpack_Subscriptions::subscribe(
712
									$comment->comment_author_email,
713
									$post_ids,
0 ignored issues
show
Documentation introduced by
$post_ids is of type array, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
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
									)
721
		);
722
723
		/**
724
		 * Fires on each comment subscription form submission.
725
		 *
726
		 * @module subscriptions
727
		 *
728
		 * @since 5.5.0
729
		 *
730
		 * @param NULL|WP_Error $result Result of form submission: NULL on success, WP_Error otherwise.
731
		 * @param Array $post_ids An array of post IDs that the user subscribed to, 0 means blog subscription.
732
		 */
733
		do_action( 'jetpack_subscriptions_comment_form_submission', $result, $post_ids );
734
	}
735
736
	/**
737
	 * Jetpack_Subscriptions::set_cookies()
738
	 *
739
	 * Set a cookie to save state on the comment and post subscription checkboxes.
740
	 *
741
	 * @param bool $subscribe_to_post Whether the user chose to subscribe to subsequent comments on this post.
742
	 * @param int $post_id If $subscribe_to_post is true, the post ID they've subscribed to.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $post_id not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
743
	 * @param bool $subscribe_to_blog Whether the user chose to subscribe to all new posts on the blog.
744
	 */
745
	function set_cookies( $subscribe_to_post = false, $post_id = null, $subscribe_to_blog = false ) {
746
		$post_id = intval( $post_id );
747
748
		/** This filter is already documented in core/wp-includes/comment-functions.php */
749
		$cookie_lifetime = apply_filters( 'comment_cookie_lifetime',       30000000 );
750
751
		/**
752
		 * Filter the Jetpack Comment cookie path.
753
		 *
754
		 * @module subscriptions
755
		 *
756
		 * @since 2.5.0
757
		 *
758
		 * @param string COOKIEPATH Cookie path.
759
		 */
760
		$cookie_path     = apply_filters( 'jetpack_comment_cookie_path',   COOKIEPATH );
761
762
		/**
763
		 * Filter the Jetpack Comment cookie domain.
764
		 *
765
		 * @module subscriptions
766
		 *
767
		 * @since 2.5.0
768
		 *
769
		 * @param string COOKIE_DOMAIN Cookie domain.
770
		 */
771
		$cookie_domain   = apply_filters( 'jetpack_comment_cookie_domain', COOKIE_DOMAIN );
772
773
		if ( $subscribe_to_post && $post_id >= 0 ) {
774
			setcookie( 'jetpack_comments_subscribe_' . self::$hash . '_' . $post_id, 1, time() + $cookie_lifetime, $cookie_path, $cookie_domain );
775
		} else {
776
			setcookie( 'jetpack_comments_subscribe_' . self::$hash . '_' . $post_id, '', time() - 3600, $cookie_path, $cookie_domain );
777
		}
778
779
		if ( $subscribe_to_blog ) {
780
			setcookie( 'jetpack_blog_subscribe_' . self::$hash, 1, time() + $cookie_lifetime, $cookie_path, $cookie_domain );
781
		} else {
782
			setcookie( 'jetpack_blog_subscribe_' . self::$hash, '', time() - 3600, $cookie_path, $cookie_domain );
783
		}
784
	}
785
786
}
787
788
Jetpack_Subscriptions::init();
789
790
791
/***
792
 * Blog Subscription Widget
793
 */
794
795
class Jetpack_Subscriptions_Widget extends WP_Widget {
796 View Code Duplication
	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' ) );
812
		}
813
	}
814
815
	/**
816
	 * Enqueue the form's CSS.
817
	 *
818
	 * @since 4.5.0
819
	 */
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
			}
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      = self::fetch_subscriber_count();
854
855
		if ( isset( $instance['show_only_email_and_button'] ) && $instance['show_only_email_and_button'] ) {
856
			unset( $instance['title'] );
857
			$subscribe_text = false;
858
		}
859
860
		// Give the input element a unique ID
861
		/**
862
		 * Filter the subscription form's ID prefix.
863
		 *
864
		 * @module subscriptions
865
		 *
866
		 * @since 2.7.0
867
		 *
868
		 * @param string subscribe-field Subscription form field prefix.
869
		 * @param int $widget_id Widget ID.
870
		 */
871
		$subscribe_field_id = apply_filters( 'subscribe_field_id', 'subscribe-field', $widget_id );
872
873
		// Display the subscription form
874
		echo $args['before_widget'];
875
876
		// Only show the title if there actually is a title
877 View Code Duplication
		if( ! empty( $instance['title'] ) ) {
878
			echo $args['before_title'] . esc_attr( $instance['title'] ) . $args['after_title'] . "\n";
879
		}
880
881
		$referer = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
882
883
		// Display any errors
884
		if ( isset( $_GET['subscribe'] ) ) :
885
			switch ( $_GET['subscribe'] ) :
886
				case 'invalid_email' : ?>
887
					<p class="error"><?php esc_html_e( 'The email you entered was invalid. Please check and try again.', 'jetpack' ); ?></p>
888
					<?php break;
889
				case 'opted_out' : ?>
890
					<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' ),
891
							'https://subscribe.wordpress.com/',
892
							__( 'Manage your email preferences.', 'jetpack' )
893
						); ?></p>
894
					<?php break;
895
				case 'already' : ?>
896
					<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' ),
897
							'https://subscribe.wordpress.com/',
898
							__( 'Manage your email preferences.', 'jetpack' )
899
						); ?></p>
900
					<?php break;
901
				case 'success' : ?>
902
					<div class="success"><?php echo wpautop( str_replace( '[total-subscribers]', number_format_i18n( $subscribers_total['value'] ), $success_message ) ); ?></div>
903
					<?php break;
904
				default : ?>
905
					<p class="error"><?php esc_html_e( 'There was an error when subscribing. Please try again.', 'jetpack' ); ?></p>
906
					<?php break;
907
			endswitch;
908
		endif;
909
910
		// Display a subscribe form
911
		if ( isset( $_GET['subscribe'] ) && 'success' == $_GET['subscribe'] ) { ?>
912
			<?php
913
		} else { ?>
914
			<form action="#" method="post" accept-charset="utf-8" id="subscribe-blog-<?php echo $widget_id; ?>">
915
				<?php
916
				if ( $subscribe_text && ( ! isset ( $_GET['subscribe'] ) || 'success' != $_GET['subscribe'] ) ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $subscribe_text of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
917
					?><div id="subscribe-text"><?php echo wpautop( str_replace( '[total-subscribers]', number_format_i18n( $subscribers_total['value'] ), $subscribe_text ) ); ?></div><?php
918
				}
919
920
				if ( $show_subscribers_total && 0 < $subscribers_total['value'] ) {
921
					echo wpautop( sprintf( _n( 'Join %s other subscriber', 'Join %s other subscribers', $subscribers_total['value'], 'jetpack' ), number_format_i18n( $subscribers_total['value'] ) ) );
922
				}
923
				if ( ! isset ( $_GET['subscribe'] ) || 'success' != $_GET['subscribe'] ) { ?>
924
					<p id="subscribe-email">
925
						<label id="jetpack-subscribe-label" for="<?php echo esc_attr( $subscribe_field_id ) . '-' . esc_attr( $widget_id ); ?>">
926
							<?php echo !empty( $subscribe_placeholder ) ? esc_html( $subscribe_placeholder ) : esc_html__( 'Email Address:', 'jetpack' ); ?>
927
						</label>
928
						<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 ); ?>" />
929
					</p>
930
931
					<p id="subscribe-submit">
932
						<input type="hidden" name="action" value="subscribe" />
933
						<input type="hidden" name="source" value="<?php echo esc_url( $referer ); ?>" />
934
						<input type="hidden" name="sub-type" value="<?php echo esc_attr( $source ); ?>" />
935
						<input type="hidden" name="redirect_fragment" value="<?php echo $widget_id; ?>" />
936
						<?php
937
							if ( is_user_logged_in() ) {
938
								wp_nonce_field( 'blogsub_subscribe_'. get_current_blog_id(), '_wpnonce', false );
939
							}
940
						?>
941
						<input type="submit" value="<?php echo esc_attr( $subscribe_button ); ?>" name="jetpack_subscriptions_widget" />
942
					</p>
943
				<?php }?>
944
			</form>
945
946
			<script>
947
			/*
948
			Custom functionality for safari and IE
949
			 */
950
			(function( d ) {
951
				// In case the placeholder functionality is available we remove labels
952
				if ( ( 'placeholder' in d.createElement( 'input' ) ) ) {
953
					var label = d.querySelector( 'label[for=subscribe-field-<?php echo $widget_id; ?>]' );
954
						label.style.clip 	 = 'rect(1px, 1px, 1px, 1px)';
955
						label.style.position = 'absolute';
956
						label.style.height   = '1px';
957
						label.style.width    = '1px';
958
						label.style.overflow = 'hidden';
959
				}
960
961
				// Make sure the email value is filled in before allowing submit
962
				var form = d.getElementById('subscribe-blog-<?php echo $widget_id; ?>'),
963
					input = d.getElementById('<?php echo esc_attr( $subscribe_field_id ) . '-' . esc_attr( $widget_id ); ?>'),
964
					handler = function( event ) {
965
						if ( '' === input.value ) {
966
							input.focus();
967
968
							if ( event.preventDefault ){
969
								event.preventDefault();
970
							}
971
972
							return false;
973
						}
974
					};
975
976
				if ( window.addEventListener ) {
977
					form.addEventListener( 'submit', handler, false );
978
				} else {
979
					form.attachEvent( 'onsubmit', handler );
980
				}
981
			})( document );
982
			</script>
983
		<?php } ?>
984
		<?php
985
986
		echo "\n" . $args['after_widget'];
987
	}
988
989
	function increment_subscriber_count( $current_subs_array = array() ) {
990
		$current_subs_array['value']++;
991
992
		set_transient( 'wpcom_subscribers_total', $current_subs_array, 3600 ); // try to cache the result for at least 1 hour
993
994
		return $current_subs_array;
995
	}
996
997
	static function fetch_subscriber_count() {
998
		$subs_count = get_transient( 'wpcom_subscribers_total' );
999
1000
		if ( FALSE === $subs_count || 'failed' == $subs_count['status'] ) {
1001
			Jetpack:: load_xml_rpc_client();
1002
1003
			$xml = new Jetpack_IXR_Client( array( 'user_id' => JETPACK_MASTER_USER, ) );
1004
1005
			$xml->query( 'jetpack.fetchSubscriberCount' );
1006
1007
			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
1008
				$subs_count = array(
1009
					'status'  => 'failed',
1010
					'code'    => $xml->getErrorCode(),
1011
					'message' => $xml->getErrorMessage(),
1012
					'value'	  => ( isset( $subs_count['value'] ) ) ? $subs_count['value'] : 0,
1013
				);
1014
			} else {
1015
				$subs_count = array(
1016
					'status' => 'success',
1017
					'value'  => $xml->getResponse(),
1018
				);
1019
			}
1020
1021
			set_transient( 'wpcom_subscribers_total', $subs_count, 3600 ); // try to cache the result for at least 1 hour
1022
		}
1023
1024
		return $subs_count;
1025
	}
1026
1027
	function update( $new_instance, $old_instance ) {
1028
		$instance = $old_instance;
1029
1030
		$instance['title']					= wp_kses( stripslashes( $new_instance['title'] ), array() );
1031
		$instance['subscribe_text']			= wp_filter_post_kses( stripslashes( $new_instance['subscribe_text'] ) );
1032
		$instance['subscribe_placeholder']	= wp_kses( stripslashes( $new_instance['subscribe_placeholder'] ), array() );
1033
		$instance['subscribe_button']		= wp_kses( stripslashes( $new_instance['subscribe_button'] ), array() );
1034
		$instance['success_message']		= wp_kses( stripslashes( $new_instance['success_message'] ), array() );
1035
		$instance['show_subscribers_total']	= isset( $new_instance['show_subscribers_total'] ) && $new_instance['show_subscribers_total'];
1036
1037
		return $instance;
1038
	}
1039
1040
	public static function defaults() {
1041
		return array(
1042
			'title'               	 => esc_html__( 'Subscribe to Blog via Email', 'jetpack' ),
1043
			'subscribe_text'      	 => esc_html__( 'Enter your email address to subscribe to this blog and receive notifications of new posts by email.', 'jetpack' ),
1044
			'subscribe_placeholder'	 => esc_html__( 'Email Address', 'jetpack' ),
1045
			'subscribe_button'    	 => esc_html__( 'Subscribe', 'jetpack' ),
1046
			'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' ),
1047
			'show_subscribers_total' => true,
1048
		);
1049
	}
1050
1051
	function form( $instance ) {
1052
		$instance = wp_parse_args( (array) $instance, $this->defaults() );
1053
1054
		$title               	= stripslashes( $instance['title'] );
1055
		$subscribe_text      	= stripslashes( $instance['subscribe_text'] );
1056
		$subscribe_placeholder 	= stripslashes( $instance['subscribe_placeholder'] );
1057
		$subscribe_button    	= stripslashes( $instance['subscribe_button'] );
1058
		$success_message		= stripslashes( $instance['success_message']);
1059
		$show_subscribers_total = checked( $instance['show_subscribers_total'], true, false );
1060
1061
		$subs_fetch = self::fetch_subscriber_count();
1062
1063
		if ( 'failed' == $subs_fetch['status'] ) {
1064
			printf( '<div class="error inline"><p>' . __( '%s: %s', 'jetpack' ) . '</p></div>', esc_html( $subs_fetch['code'] ), esc_html( $subs_fetch['message'] ) );
1065
		}
1066
		$subscribers_total = number_format_i18n( $subs_fetch['value'] );
1067
?>
1068
<p>
1069
	<label for="<?php echo $this->get_field_id( 'title' ); ?>">
1070
		<?php _e( 'Widget title:', 'jetpack' ); ?>
1071
		<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 ); ?>" />
1072
	</label>
1073
</p>
1074
<p>
1075
	<label for="<?php echo $this->get_field_id( 'subscribe_text' ); ?>">
1076
		<?php _e( 'Optional text to display to your readers:', 'jetpack' ); ?>
1077
		<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>
1078
	</label>
1079
</p>
1080
<p>
1081
	<label for="<?php echo $this->get_field_id( 'subscribe_placeholder' ); ?>">
1082
		<?php esc_html_e( 'Subscribe Placeholder:', 'jetpack' ); ?>
1083
		<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 ); ?>" />
1084
	</label>
1085
</p>
1086
<p>
1087
	<label for="<?php echo $this->get_field_id( 'subscribe_button' ); ?>">
1088
		<?php _e( 'Subscribe Button:', 'jetpack' ); ?>
1089
		<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 ); ?>" />
1090
	</label>
1091
</p>
1092
<p>
1093
	<label for="<?php echo $this->get_field_id( 'success_message' ); ?>">
1094
		<?php _e( 'Success Message Text:', 'jetpack' ); ?>
1095
		<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>
1096
	</label>
1097
</p>
1098
<p>
1099
	<label for="<?php echo $this->get_field_id( 'show_subscribers_total' ); ?>">
1100
		<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; ?> />
1101
		<?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 ) ); ?>
1102
	</label>
1103
</p>
1104
<?php
1105
	}
1106
}
1107
1108
add_shortcode( 'jetpack_subscription_form', 'jetpack_do_subscription_form' );
1109
add_shortcode( 'blog_subscription_form', 'jetpack_do_subscription_form' );
1110
1111
function jetpack_do_subscription_form( $instance ) {
1112
	if ( empty( $instance ) || ! is_array( $instance ) ) {
1113
		$instance = array();
1114
	}
1115
	$instance['show_subscribers_total'] = empty( $instance['show_subscribers_total'] ) ? false : true;
1116
	$show_only_email_and_button = isset( $instance['show_only_email_and_button'] ) ? $instance['show_only_email_and_button'] : false;
1117
1118
	$instance = shortcode_atts(
1119
		Jetpack_Subscriptions_Widget::defaults(),
1120
		$instance,
1121
		'jetpack_subscription_form'
1122
	);
1123
	$instance['show_only_email_and_button'] = $show_only_email_and_button;
1124
1125
	$args = array(
1126
		'before_widget' => sprintf( '<div class="%s">', 'jetpack_subscription_widget' ),
1127
	);
1128
	ob_start();
1129
	the_widget( 'Jetpack_Subscriptions_Widget', $instance, $args );
1130
	$output = ob_get_clean();
1131
	return $output;
1132
}
1133
1134
jetpack_register_block( 'subscriptions' );
1135