Completed
Push — master-stable ( a8674f...27ffc4 )
by
unknown
28:24 queued 18:30
created

Jetpack_Subscriptions::setting_comment_follow()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 0
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Module Name: Subscriptions
4
 * Module Description: Notify your readers of new posts and comments by 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;
0 ignored issues
show
Coding Style Compatibility introduced by
The function jetpack_subscriptions_configuration_load() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
26
}
27
28
class Jetpack_Subscriptions {
29
	public $jetpack = false;
30
31
	public static $hash;
32
33
	/**
34
	 * Singleton
35
	 * @static
36
	 */
37
	static function init() {
38
		static $instance = false;
39
40
		if ( !$instance ) {
41
			$instance = new Jetpack_Subscriptions;
42
		}
43
44
		return $instance;
45
	}
46
47
	function __construct() {
48
		$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...
49
50
		// Don't use COOKIEHASH as it could be shared across installs && is non-unique in multisite.
51
		// @see: https://twitter.com/nacin/status/378246957451333632
52
		self::$hash = md5( get_option( 'siteurl' ) );
53
54
		add_filter( 'jetpack_xmlrpc_methods', array( $this, 'xmlrpc_methods' ) );
55
56
		// @todo remove sync from subscriptions and move elsewhere...
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
57
58
		// Add Configuration Page
59
		add_action( 'admin_init', array( $this, 'configure' ) );
60
61
		// Set up the subscription widget.
62
		add_action( 'widgets_init', array( $this, 'widget_init' ) );
63
64
		// Catch subscription widget submits
65
		if ( isset( $_REQUEST['jetpack_subscriptions_widget'] ) )
66
			add_action( 'template_redirect', array( $this, 'widget_submit' ) );
67
68
		// Set up the comment subscription checkboxes
69
		add_action( 'comment_form', array( $this, 'comment_subscribe_init' ) );
70
71
		// Catch comment posts and check for subscriptions.
72
		add_action( 'comment_post', array( $this, 'comment_subscribe_submit' ), 50, 2 );
73
74
		// Adds post meta checkbox in the post submit metabox
75
		add_action( 'post_submitbox_misc_actions', array( $this, 'subscription_post_page_metabox' ) );
76
77
		add_action( 'transition_post_status', array( $this, 'maybe_send_subscription_email' ), 10, 3 );
78
79
		add_filter( 'jetpack_published_post_flags', array( $this, 'set_post_flags' ), 10, 2 );
80
	}
81
82
	/**
83
	 * Jetpack_Subscriptions::xmlrpc_methods()
84
	 *
85
	 * Register subscriptions methods with the Jetpack XML-RPC server.
86
	 * @param array $methods
87
	 */
88
	function xmlrpc_methods( $methods ) {
89
		return array_merge(
90
			$methods,
91
			array(
92
				'jetpack.subscriptions.subscribe' => array( $this, 'subscribe' ),
93
			)
94
		);
95
	}
96
97
	/*
98
	 * Disable Subscribe on Single Post
99
	 * Register post meta
100
	 */
101
	function subscription_post_page_metabox() {
102
		if (
103
			/**
104
			 * Filter whether or not to show the per-post subscription option.
105
			 *
106
			 * @module subscriptions
107
			 *
108
			 * @since 3.7.0
109
			 *
110
			 * @param bool true = show checkbox option on all new posts | false = hide the option.
111
			 */
112
			 ! apply_filters( 'jetpack_allow_per_post_subscriptions', false ) )
113
		{
114
			return;
115
		}
116
117
		if ( has_filter( 'jetpack_subscriptions_exclude_these_categories' ) || has_filter( 'jetpack_subscriptions_include_only_these_categories' ) ) {
118
			return;
119
		}
120
121
		global $post;
122
		$disable_subscribe_value = get_post_meta( $post->ID, '_jetpack_dont_email_post_to_subs', true );
123
		// only show checkbox if post hasn't been published and is a 'post' post type.
124
		if ( get_post_status( $post->ID ) !== 'publish' && get_post_type( $post->ID ) == 'post' ) :
125
			// Nonce it
126
			wp_nonce_field( 'disable_subscribe', 'disable_subscribe_nonce' );
127
			?>
128
			<div class="misc-pub-section">
129
				<label for="_jetpack_dont_email_post_to_subs"><?php _e( 'Jetpack Subscriptions:', 'jetpack' ); ?></label><br>
130
				<input type="checkbox" name="_jetpack_dont_email_post_to_subs" id="jetpack-per-post-subscribe" value="1" <?php checked( $disable_subscribe_value, 1, true ); ?> />
131
				<?php _e( 'Don&#8217;t send this to subscribers', 'jetpack' ); ?>
132
			</div>
133
		<?php endif;
134
	}
135
136
	/**
137
	 * Checks whether or not the post should be emailed to subscribers
138
	 *
139
	 * It checks for the following things in order:
140
	 * - Usage of filter jetpack_subscriptions_exclude_these_categories
141
	 * - Usage of filter jetpack_subscriptions_include_only_these_categories
142
	 * - Existence of the per-post checkbox option
143
	 *
144
	 * Only one of these can be used at any given time.
145
	 *
146
	 * @param $new_status string - the "new" post status of the transition when saved
147
	 * @param $old_status string - the "old" post status of the transition when saved
148
	 * @param $post obj - The post object
149
	 */
150
	function maybe_send_subscription_email( $new_status, $old_status, $post ) {
151
152
		if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
153
			return;
154
		}
155
156
		// Make sure that the checkbox is preseved
157
		if ( ! empty( $_POST['disable_subscribe_nonce'] ) && wp_verify_nonce( $_POST['disable_subscribe_nonce'], 'disable_subscribe' ) ) {
158
			$set_checkbox = isset( $_POST['_jetpack_dont_email_post_to_subs'] ) ? 1 : 0;
159
			update_post_meta( $post->ID, '_jetpack_dont_email_post_to_subs', $set_checkbox );
160
		}
161
	}
162
163
	public function should_email_post_to_subscribers( $post ) {
164
		$should_email = true;
165
		if ( get_post_meta( $post->ID, '_jetpack_dont_email_post_to_subs', true ) ) {
166
			return false;
167
		}
168
169
		/**
170
		 * Array of categories that will never trigger subscription emails.
171
		 *
172
		 * Will not send subscription emails from any post from within these categories.
173
		 *
174
		 * @module subscriptions
175
		 *
176
		 * @since 3.7.0
177
		 *
178
		 * @param array $args Array of category slugs or ID's.
179
		 */
180
		$excluded_categories = apply_filters( 'jetpack_subscriptions_exclude_these_categories', array() );
181
182
		// Never email posts from these categories
183
		if ( ! empty( $excluded_categories ) && in_category( $excluded_categories, $post->ID ) ) {
184
			$should_email = false;
185
		}
186
187
		/**
188
		 * ONLY send subscription emails for these categories
189
		 *
190
		 * Will ONLY send subscription emails to these categories.
191
		 *
192
		 * @module subscriptions
193
		 *
194
		 * @since 3.7.0
195
		 *
196
		 * @param array $args Array of category slugs or ID's.
197
		 */
198
		$only_these_categories = apply_filters( 'jetpack_subscriptions_exclude_all_categories_except', array() );
199
200
		// Only emails posts from these categories
201
		if ( ! empty( $only_these_categories ) && ! in_category( $only_these_categories, $post->ID ) ) {
202
			$should_email = false;
203
		}
204
205
206
		return $should_email;
207
	}
208
209
	function set_post_flags( $flags, $post ) {
210
		$flags['send_subscription'] = $this->should_email_post_to_subscribers( $post );
211
		return $flags;
212
	}
213
214
	/**
215
	 * Jetpack_Subscriptions::configure()
216
	 *
217
	 * Jetpack Subscriptions configuration screen.
218
	 */
219
	function configure() {
220
		// Create the section
221
		add_settings_section(
222
			'jetpack_subscriptions',
223
			__( 'Jetpack Subscriptions Settings', 'jetpack' ),
224
			array( $this, 'subscriptions_settings_section' ),
225
			'discussion'
226
		);
227
228
		/** Subscribe to Posts ***************************************************/
229
230
		add_settings_field(
231
			'jetpack_subscriptions_post_subscribe',
232
			__( 'Follow Blog', 'jetpack' ),
233
			array( $this, 'subscription_post_subscribe_setting' ),
234
			'discussion',
235
			'jetpack_subscriptions'
236
		);
237
238
		register_setting(
239
			'discussion',
240
			'stb_enabled'
241
		);
242
243
		/** Subscribe to Comments ******************************************************/
244
245
		add_settings_field(
246
			'jetpack_subscriptions_comment_subscribe',
247
			__( 'Follow Comments', 'jetpack' ),
248
			array( $this, 'subscription_comment_subscribe_setting' ),
249
			'discussion',
250
			'jetpack_subscriptions'
251
		);
252
253
		register_setting(
254
			'discussion',
255
			'stc_enabled'
256
		);
257
258
		/** Subscription Messaging Options ******************************************************/
259
260
		register_setting(
261
			'reading',
262
			'subscription_options',
263
			array( $this, 'validate_settings' )
264
		);
265
266
		add_settings_section(
267
			'email_settings',
268
			__( 'Follower Settings', 'jetpack' ),
269
			array( $this, 'reading_section' ),
270
			'reading'
271
		);
272
273
		add_settings_field(
274
			'invitation',
275
			__( 'Blog follow email text', 'jetpack' ),
276
			array( $this, 'setting_invitation' ),
277
			'reading',
278
			'email_settings'
279
		);
280
281
		add_settings_field(
282
			'comment-follow',
283
			__( 'Comment follow email text', 'jetpack' ),
284
			array( $this, 'setting_comment_follow' ),
285
			'reading',
286
			'email_settings'
287
		);
288
	}
289
290
	/**
291
	 * Discussions setting section blurb
292
	 *
293
	 */
294
	function subscriptions_settings_section() {
295
	?>
296
297
		<p id="jetpack-subscriptions-settings"><?php _e( 'Change whether your visitors can subscribe to your posts or comments or both.', 'jetpack' ); ?></p>
298
299
	<?php
300
	}
301
302
	/**
303
	 * Post Subscriptions Toggle
304
	 *
305
	 */
306 View Code Duplication
	function subscription_post_subscribe_setting() {
307
308
		$stb_enabled = get_option( 'stb_enabled', 1 ); ?>
309
310
		<p class="description">
311
			<input type="checkbox" name="stb_enabled" id="jetpack-post-subscribe" value="1" <?php checked( $stb_enabled, 1 ); ?> />
312
			<?php _e( "Show a <em>'follow blog'</em> option in the comment form", 'jetpack' ); ?>
313
		</p>
314
	<?php
315
	}
316
317
	/**
318
	 * Comments Subscriptions Toggle
319
	 *
320
	 */
321 View Code Duplication
	function subscription_comment_subscribe_setting() {
322
323
		$stc_enabled = get_option( 'stc_enabled', 1 ); ?>
324
325
		<p class="description">
326
			<input type="checkbox" name="stc_enabled" id="jetpack-comment-subscribe" value="1" <?php checked( $stc_enabled, 1 ); ?> />
327
			<?php _e( "Show a <em>'follow comments'</em> option in the comment form", 'jetpack' ); ?>
328
		</p>
329
330
	<?php
331
	}
332
333
	function validate_settings( $settings ) {
334
		global $allowedposttags;
335
336
		$default = $this->get_default_settings();
337
338
		// Blog Follow
339
		$settings['invitation'] = trim( wp_kses( $settings['invitation'], $allowedposttags ) );
340
		if ( empty( $settings['invitation'] ) )
341
			$settings['invitation'] = $default['invitation'];
342
343
		// Comments Follow (single post)
344
		$settings['comment_follow'] = trim( wp_kses( $settings['comment_follow'], $allowedposttags ) );
345
		if ( empty( $settings['comment_follow'] ) )
346
			$settings['comment_follow'] = $default['comment_follow'];
347
348
		return $settings;
349
	}
350
351
	public function reading_section() {
352
		echo '<p id="follower-settings">';
353
		_e( 'These settings change emails sent from your blog to followers.', 'jetpack' );
354
		echo '</p>';
355
	}
356
357
	public function setting_invitation() {
358
		$settings = $this->get_settings();
359
		echo '<textarea name="subscription_options[invitation]" class="large-text" cols="50" rows="5">' . esc_textarea( $settings['invitation'] ) . '</textarea>';
360
		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>';
361
	}
362
363
	public function setting_comment_follow() {
364
		$settings = $this->get_settings();
365
		echo '<textarea name="subscription_options[comment_follow]" class="large-text" cols="50" rows="5">' . esc_textarea( $settings['comment_follow'] ) . '</textarea>';
366
		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>';
367
	}
368
369
	function get_default_settings() {
370
		return array(
371
			'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' ),
372
			'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' )
373
		);
374
	}
375
376
	function get_settings() {
377
		return wp_parse_args( (array) get_option( 'subscription_options', array() ), $this->get_default_settings() );
378
	}
379
380
	/**
381
	 * Jetpack_Subscriptions::subscribe()
382
	 *
383
	 * Send a synchronous XML-RPC subscribe to blog posts or subscribe to post comments request.
384
	 *
385
	 * @param string $email
386
	 * @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...
387
	 * @param bool   $async    (optional) Should the subscription be performed asynchronously?  Defaults to true.
388
	 *
389
	 * @return true|Jetpack_Error true on success
390
	 *	invalid_email   : not a valid email address
391
	 *	invalid_post_id : not a valid post ID
392
	 *	unknown_post_id : unknown post
393
	 *	not_subscribed  : strange error.  Jetpack servers at WordPress.com could subscribe the email.
394
	 *	disabled        : Site owner has disabled subscriptions.
395
	 *	active          : Already subscribed.
396
	 *	unknown         : strange error.  Jetpack servers at WordPress.com returned something malformed.
397
	 *	unknown_status  : strange error.  Jetpack servers at WordPress.com returned something I didn't understand.
398
	 */
399
	function subscribe( $email, $post_ids = 0, $async = true, $extra_data = array() ) {
400
		if ( !is_email( $email ) ) {
401
			return new Jetpack_Error( 'invalid_email' );
402
		}
403
404
		if ( !$async ) {
405
			Jetpack::load_xml_rpc_client();
406
			$xml = new Jetpack_IXR_ClientMulticall();
407
		}
408
409
		foreach ( (array) $post_ids as $post_id ) {
410
			$post_id = (int) $post_id;
411
			if ( $post_id < 0 ) {
412
				return new Jetpack_Error( 'invalid_post_id' );
413
			} else if ( $post_id && !$post = get_post( $post_id ) ) {
414
				return new Jetpack_Error( 'unknown_post_id' );
415
			}
416
417
			if ( $async ) {
418
				Jetpack::xmlrpc_async_call( 'jetpack.subscribeToSite', $email, $post_id, serialize( $extra_data ) );
419
			} else {
420
				$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...
421
			}
422
		}
423
424
		if ( $async ) {
425
			return;
426
		}
427
428
		// Call
429
		$xml->query();
430
431
		if ( $xml->isError() ) {
432
			return $xml->get_jetpack_error();
433
		}
434
435
		$responses = $xml->getResponse();
436
437
		$r = array();
438
		foreach ( (array) $responses as $response ) {
439
			if ( isset( $response['faultCode'] ) || isset( $response['faultString'] ) ) {
440
				$r[] = $xml->get_jetpack_error( $response['faultCode'], $response['faultString'] );
441
				continue;
442
			}
443
444
			if ( !is_array( $response[0] ) || empty( $response[0]['status'] ) ) {
445
				$r[] = new Jetpack_Error( 'unknown' );
446
				continue;
447
			}
448
449
			switch ( $response[0]['status'] ) {
450
			case 'error' :
451
				$r[] = new Jetpack_Error( 'not_subscribed' );
452
				continue 2;
453
			case 'disabled' :
454
				$r[] = new Jetpack_Error( 'disabled' );
455
				continue 2;
456
			case 'active' :
457
				$r[] = new Jetpack_Error( 'active' );
458
				continue 2;
459
			case 'pending' :
460
				$r[] = true;
461
				continue 2;
462
			default :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a DEFAULT statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in the default statement.

switch ($expr) {
    default : //wrong
        doSomething();
        break;
}

switch ($expr) {
    default: //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
463
				$r[] = new Jetpack_Error( 'unknown_status', (string) $response[0]['status'] );
464
				continue 2;
465
			}
466
		}
467
468
		return $r;
469
	}
470
471
	/**
472
	 * Jetpack_Subscriptions::widget_init()
473
	 *
474
	 * Initialize and register the Jetpack Subscriptions widget.
475
	 */
476
	function widget_init() {
477
		register_widget( 'Jetpack_Subscriptions_Widget' );
478
	}
479
480
	/**
481
	 * Jetpack_Subscriptions::widget_submit()
482
	 *
483
	 * When a user submits their email via the blog subscription widget, check the details and call the subsribe() method.
484
	 */
485
	function widget_submit() {
486
		// Check the nonce.
487
		if ( is_user_logged_in() ) {
488
			check_admin_referer( 'blogsub_subscribe_' . get_current_blog_id() );
489
		}
490
491
		if ( empty( $_REQUEST['email'] ) )
492
			return false;
493
494
		$redirect_fragment = false;
495
		if ( isset( $_REQUEST['redirect_fragment'] ) ) {
496
			$redirect_fragment = preg_replace( '/[^a-z0-9_-]/i', '', $_REQUEST['redirect_fragment'] );
497
		}
498
		if ( !$redirect_fragment ) {
499
			$redirect_fragment = 'subscribe-blog';
500
		}
501
502
		$subscribe = Jetpack_Subscriptions::subscribe(
503
												$_REQUEST['email'],
504
												0,
505
												false,
506
												array(
507
													'source'         => 'widget',
508
													'widget-in-use'  => is_active_widget( false, false, 'blog_subscription', true ) ? 'yes' : 'no',
509
													'comment_status' => '',
510
													'server_data'    => $_SERVER,
511
												)
512
		);
513
514
		if ( is_wp_error( $subscribe ) ) {
515
			$error = $subscribe->get_error_code();
516
		} else {
517
			$error = false;
518
			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...
519
				if ( is_wp_error( $response ) ) {
520
					$error = $response->get_error_code();
521
					break;
522
				}
523
			}
524
		}
525
526
		switch ( $error ) {
527
			case false:
528
				$result = 'success';
529
				break;
530
			case 'invalid_email':
531
				$result = $error;
532
				break;
533
			case 'active':
534
			case 'blocked_email':
535
				$result = 'opted_out';
536
				break;
537
			case 'pending':
538
				$result = 'already';
539
				break;
540
			default:
541
				$result = 'error';
542
				break;
543
		}
544
545
		$redirect = add_query_arg( 'subscribe', $result );
546
547
		/**
548
		 * Fires on each subscription form submission.
549
		 *
550
		 * @module subscriptions
551
		 *
552
		 * @since 3.7.0
553
		 *
554
		 * @param string $result Result of form submission: success, invalid_email, already, error.
555
		 */
556
		do_action( 'jetpack_subscriptions_form_submission', $result );
557
558
		wp_safe_redirect( "$redirect#$redirect_fragment" );
559
		exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method widget_submit() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
560
	}
561
562
	/**
563
	 * Jetpack_Subscriptions::comment_subscribe_init()
564
	 *
565
	 * Set up and add the comment subscription checkbox to the comment form.
566
	 */
567
	function comment_subscribe_init() {
568
		global $post;
569
570
		$comments_checked = '';
571
		$blog_checked     = '';
572
573
		// Check for a comment / blog submission and set a cookie to retain the setting and check the boxes.
574
		if ( isset( $_COOKIE[ 'jetpack_comments_subscribe_' . self::$hash . '_' . $post->ID ] ) ) {
575
			$comments_checked = ' checked="checked"';
576
		}
577
578
		if ( isset( $_COOKIE[ 'jetpack_blog_subscribe_' . self::$hash ] ) ) {
579
			$blog_checked = ' checked="checked"';
580
		}
581
582
		// Some themes call this function, don't show the checkbox again
583
		remove_action( 'comment_form', 'subscription_comment_form' );
584
585
		// Check if Mark Jaquith's Subscribe to Comments plugin is active - if so, suppress Jetpack checkbox
586
587
		$str = '';
588
589
		if ( FALSE === has_filter( 'comment_form', 'show_subscription_checkbox' ) && 1 == get_option( 'stc_enabled', 1 ) && empty( $post->post_password ) && 'post' == get_post_type() ) {
590
			// Subscribe to comments checkbox
591
			$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 . ' /> ';
592
			$comment_sub_text = __( 'Notify me of follow-up comments by email.', 'jetpack' );
593
			$str .=	'<label class="subscribe-label" id="subscribe-label" for="subscribe_comments">' . esc_html(
594
				/**
595
				 * Filter the Subscribe to comments text appearing below the comment form.
596
				 *
597
				 * @module subscriptions
598
				 *
599
				 * @since 3.4.0
600
				 *
601
				 * @param string $comment_sub_text Subscribe to comments text.
602
				 */
603
				apply_filters( 'jetpack_subscribe_comment_label', $comment_sub_text )
604
			) . '</label>';
605
			$str .= '</p>';
606
		}
607
608
		if ( 1 == get_option( 'stb_enabled', 1 ) ) {
609
			// Subscribe to blog checkbox
610
			$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 . ' /> ';
611
			$blog_sub_text = __( 'Notify me of new posts by email.', 'jetpack' );
612
			$str .=	'<label class="subscribe-label" id="subscribe-blog-label" for="subscribe_blog">' . esc_html(
613
				/**
614
				 * Filter the Subscribe to blog text appearing below the comment form.
615
				 *
616
				 * @module subscriptions
617
				 *
618
				 * @since 3.4.0
619
				 *
620
				 * @param string $comment_sub_text Subscribe to blog text.
621
				 */
622
				apply_filters( 'jetpack_subscribe_blog_label', $blog_sub_text )
623
			) . '</label>';
624
			$str .= '</p>';
625
		}
626
627
		/**
628
		 * Filter the output of the subscription options appearing below the comment form.
629
		 *
630
		 * @module subscriptions
631
		 *
632
		 * @since 1.2.0
633
		 *
634
		 * @param string $str Comment Subscription form HTML output.
635
		 */
636
		echo apply_filters( 'jetpack_comment_subscription_form', $str );
637
	}
638
639
	/**
640
	 * Jetpack_Subscriptions::comment_subscribe_init()
641
	 *
642
	 * When a user checks the comment subscribe box and submits a comment, subscribe them to the comment thread.
643
	 */
644
	function comment_subscribe_submit( $comment_id, $approved ) {
645
		if ( 'spam' === $approved ) {
646
			return;
647
		}
648
649
		$comment = get_comment( $comment_id );
650
651
		// Set cookies for this post/comment
652
		$this->set_cookies( isset( $_REQUEST['subscribe_comments'] ), $comment->comment_post_ID, isset( $_REQUEST['subscribe_blog'] ) );
653
654
		if ( !isset( $_REQUEST['subscribe_comments'] ) && !isset( $_REQUEST['subscribe_blog'] ) )
655
			return;
656
657
		$post_ids = array();
658
659
		if ( isset( $_REQUEST['subscribe_comments'] ) )
660
			$post_ids[] = $comment->comment_post_ID;
661
662
		if ( isset( $_REQUEST['subscribe_blog'] ) )
663
			$post_ids[] = 0;
664
665
		Jetpack_Subscriptions::subscribe(
666
									$comment->comment_author_email,
667
									$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...
668
									true,
669
									array(
670
										'source'         => 'comment-form',
671
										'widget-in-use'  => is_active_widget( false, false, 'blog_subscription', true ) ? 'yes' : 'no',
672
										'comment_status' => $approved,
673
										'server_data'    => $_SERVER,
674
									)
675
		);
676
	}
677
678
	/**
679
	 * Jetpack_Subscriptions::set_cookies()
680
	 *
681
	 * Set a cookie to save state on the comment and post subscription checkboxes.
682
	 *
683
	 * @param bool $subscribe_to_post Whether the user chose to subscribe to subsequent comments on this post.
684
	 * @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...
685
	 * @param bool $subscribe_to_blog Whether the user chose to subscribe to all new posts on the blog.
686
	 */
687
	function set_cookies( $subscribe_to_post = false, $post_id = null, $subscribe_to_blog = false ) {
688
		$post_id = intval( $post_id );
689
690
		/** This filter is already documented in core/wp-includes/comment-functions.php */
691
		$cookie_lifetime = apply_filters( 'comment_cookie_lifetime',       30000000 );
692
693
		/**
694
		 * Filter the Jetpack Comment cookie path.
695
		 *
696
		 * @module subscriptions
697
		 *
698
		 * @since 2.5.0
699
		 *
700
		 * @param string COOKIEPATH Cookie path.
701
		 */
702
		$cookie_path     = apply_filters( 'jetpack_comment_cookie_path',   COOKIEPATH );
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned correctly; expected 1 space but found 5 spaces

This check looks for improperly formatted assignments.

Every assignment must have exactly one space before and one space after the equals operator.

To illustrate:

$a = "a";
$ab = "ab";
$abc = "abc";

will have no issues, while

$a   = "a";
$ab  = "ab";
$abc = "abc";

will report issues in lines 1 and 2.

Loading history...
703
704
		/**
705
		 * Filter the Jetpack Comment cookie domain.
706
		 *
707
		 * @module subscriptions
708
		 *
709
		 * @since 2.5.0
710
		 *
711
		 * @param string COOKIE_DOMAIN Cookie domain.
712
		 */
713
		$cookie_domain   = apply_filters( 'jetpack_comment_cookie_domain', COOKIE_DOMAIN );
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned correctly; expected 1 space but found 3 spaces

This check looks for improperly formatted assignments.

Every assignment must have exactly one space before and one space after the equals operator.

To illustrate:

$a = "a";
$ab = "ab";
$abc = "abc";

will have no issues, while

$a   = "a";
$ab  = "ab";
$abc = "abc";

will report issues in lines 1 and 2.

Loading history...
714
715
		if ( $subscribe_to_post && $post_id >= 0 ) {
716
			setcookie( 'jetpack_comments_subscribe_' . self::$hash . '_' . $post_id, 1, time() + $cookie_lifetime, $cookie_path, $cookie_domain );
717
		} else {
718
			setcookie( 'jetpack_comments_subscribe_' . self::$hash . '_' . $post_id, '', time() - 3600, $cookie_path, $cookie_domain );
719
		}
720
721
		if ( $subscribe_to_blog ) {
722
			setcookie( 'jetpack_blog_subscribe_' . self::$hash, 1, time() + $cookie_lifetime, $cookie_path, $cookie_domain );
723
		} else {
724
			setcookie( 'jetpack_blog_subscribe_' . self::$hash, '', time() - 3600, $cookie_path, $cookie_domain );
725
		}
726
	}
727
728
}
729
730
Jetpack_Subscriptions::init();
731
732
733
/***
734
 * Blog Subscription Widget
735
 */
736
737
class Jetpack_Subscriptions_Widget extends WP_Widget {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
738 View Code Duplication
	function __construct() {
739
		$widget_ops  = array(
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned correctly; expected 1 space but found 2 spaces

This check looks for improperly formatted assignments.

Every assignment must have exactly one space before and one space after the equals operator.

To illustrate:

$a = "a";
$ab = "ab";
$abc = "abc";

will have no issues, while

$a   = "a";
$ab  = "ab";
$abc = "abc";

will report issues in lines 1 and 2.

Loading history...
740
			'classname' => 'jetpack_subscription_widget',
741
			'description' => esc_html__( 'Add an email signup form to allow people to subscribe to your blog.', 'jetpack' ),
742
			'customize_selective_refresh' => true,
743
		);
744
745
		parent::__construct(
746
			'blog_subscription',
747
			/** This filter is documented in modules/widgets/facebook-likebox.php */
748
			apply_filters( 'jetpack_widget_name', __( 'Blog Subscriptions', 'jetpack' ) ),
749
			$widget_ops
750
		);
751
752
		if ( is_active_widget( false, false, $this->id_base ) || is_active_widget( false, false, 'monster' ) || is_customize_preview() ) {
753
			add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_style' ) );
754
		}
755
	}
756
757
	/**
758
	 * Enqueue the form's CSS.
759
	 *
760
	 * @since 4.5.0
761
	 */
762
	function enqueue_style() {
763
		wp_register_style( 'jetpack-subscriptions', plugins_url( 'subscriptions/subscriptions.css', __FILE__ ) );
764
		wp_enqueue_style( 'jetpack-subscriptions' );
765
	}
766
767
	function widget( $args, $instance ) {
768
		if (
769
			( ! defined( 'IS_WPCOM' ) || ! IS_WPCOM ) &&
770
			/** This filter is already documented in modules/contact-form/grunion-contact-form.php */
771
			false === apply_filters( 'jetpack_auto_fill_logged_in_user', false )
772
		) {
773
			$subscribe_email = '';
774
		} else {
775
			$current_user = wp_get_current_user();
776
			if ( ! empty( $current_user->user_email ) ) {
777
				$subscribe_email = esc_attr( $current_user->user_email );
778
			} else {
779
				$subscribe_email = '';
780
			}
781
		}
782
783
		/** This action is already documented in modules/widgets/gravatar-profile.php */
784
		do_action( 'jetpack_stats_extra', 'widget_view', 'jetpack_subscriptions' );
785
786
		$source                 = 'widget';
787
		$instance            	= wp_parse_args( (array) $instance, $this->defaults() );
788
		$subscribe_text      	= isset( $instance['subscribe_text'] )        ? stripslashes( $instance['subscribe_text'] )        : '';
789
		$subscribe_placeholder 	= isset( $instance['subscribe_placeholder'] ) ? stripslashes( $instance['subscribe_placeholder'] ) : '';
790
		$subscribe_button    	= isset( $instance['subscribe_button'] )      ? stripslashes( $instance['subscribe_button'] )      : '';
791
		$success_message    	= isset( $instance['success_message'] )       ? stripslashes( $instance['success_message'] )      : '';
792
		$widget_id              = esc_attr( !empty( $args['widget_id'] )      ? esc_attr( $args['widget_id'] ) : mt_rand( 450, 550 ) );
793
794
		$show_subscribers_total = (bool) $instance['show_subscribers_total'];
795
		$subscribers_total      = $this->fetch_subscriber_count(); // Only used for the shortcode [total-subscribers]
796
797
		// Give the input element a unique ID
798
		/**
799
		 * Filter the subscription form's ID prefix.
800
		 *
801
		 * @module subscriptions
802
		 *
803
		 * @since 2.7.0
804
		 *
805
		 * @param string subscribe-field Subscription form field prefix.
806
		 * @param int $widget_id Widget ID.
807
		 */
808
		$subscribe_field_id = apply_filters( 'subscribe_field_id', 'subscribe-field', $widget_id );
809
810
		// Display the subscription form
811
		echo $args['before_widget'];
812
813
		// Only show the title if there actually is a title
814 View Code Duplication
		if( ! empty( $instance['title'] ) ) {
815
			echo $args['before_title'] . esc_attr( $instance['title'] ) . $args['after_title'] . "\n";
816
		}
817
818
		$referer = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
819
820
		// Display any errors
821
		if ( isset( $_GET['subscribe'] ) ) :
822
			switch ( $_GET['subscribe'] ) :
823
				case 'invalid_email' : ?>
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
824
					<p class="error"><?php esc_html_e( 'The email you entered was invalid. Please check and try again.', 'jetpack' ); ?></p>
825
				<?php break;
0 ignored issues
show
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
826
				case 'opted_out' : ?>
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
827
					<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' ),
828
							'https://subscribe.wordpress.com/',
829
							__( 'Manage your email preferences.', 'jetpack' )
830
						); ?>
831
				<?php break;
0 ignored issues
show
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
832
				case 'already' : ?>
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
833
					<p class="error"><?php esc_html_e( 'You have already subscribed to this site. Please check your inbox.', 'jetpack' ); ?></p>
834
				<?php break;
0 ignored issues
show
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
835
				case 'success' : ?>
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
836
					<div class="success"><?php echo wpautop( str_replace( '[total-subscribers]', number_format_i18n( $subscribers_total['value'] ), $success_message ) ); ?></div>
837
					<?php break;
0 ignored issues
show
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
838
				default : ?>
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a DEFAULT statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in the default statement.

switch ($expr) {
    default : //wrong
        doSomething();
        break;
}

switch ($expr) {
    default: //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
The default body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a default statement must start on the line immediately following the statement.

switch ($expr) {
    default:
        doSomething(); //right
        break;
}


switch ($expr) {
    default:

        doSomething(); //wrong
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
839
					<p class="error"><?php esc_html_e( 'There was an error when subscribing. Please try again.', 'jetpack' ); ?></p>
840
				<?php break;
0 ignored issues
show
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
841
			endswitch;
842
		endif;
843
844
		// Display a subscribe form
845
		if ( isset( $_GET['subscribe'] ) && 'success' == $_GET['subscribe'] ) { ?>
846
			<?php
847
		} else { ?>
848
			<form action="#" method="post" accept-charset="utf-8" id="subscribe-blog-<?php echo $widget_id; ?>">
849
				<?php
850
				if ( ! isset ( $_GET['subscribe'] ) || 'success' != $_GET['subscribe'] ) {
851
					?><div id="subscribe-text"><?php echo wpautop( str_replace( '[total-subscribers]', number_format_i18n( $subscribers_total['value'] ), $subscribe_text ) ); ?></div><?php
852
				}
853
854
				if ( $show_subscribers_total && 0 < $subscribers_total['value'] ) {
855
					echo wpautop( sprintf( _n( 'Join %s other subscriber', 'Join %s other subscribers', $subscribers_total['value'], 'jetpack' ), number_format_i18n( $subscribers_total['value'] ) ) );
856
				}
857
				if ( ! isset ( $_GET['subscribe'] ) || 'success' != $_GET['subscribe'] ) { ?>
858
					<p id="subscribe-email">
859
						<label id="jetpack-subscribe-label" for="<?php echo esc_attr( $subscribe_field_id ) . '-' . esc_attr( $widget_id ); ?>">
860
							<?php echo !empty( $subscribe_placeholder ) ? esc_html( $subscribe_placeholder ) : esc_html__( 'Email Address:', 'jetpack' ); ?>
861
						</label>
862
						<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 ); ?>" />
863
					</p>
864
865
					<p id="subscribe-submit">
866
						<input type="hidden" name="action" value="subscribe" />
867
						<input type="hidden" name="source" value="<?php echo esc_url( $referer ); ?>" />
868
						<input type="hidden" name="sub-type" value="<?php echo esc_attr( $source ); ?>" />
869
						<input type="hidden" name="redirect_fragment" value="<?php echo $widget_id; ?>" />
870
						<?php
871
							if ( is_user_logged_in() ) {
872
								wp_nonce_field( 'blogsub_subscribe_'. get_current_blog_id(), '_wpnonce', false );
873
							}
874
						?>
875
						<input type="submit" value="<?php echo esc_attr( $subscribe_button ); ?>" name="jetpack_subscriptions_widget" />
876
					</p>
877
				<?php }?>
878
			</form>
879
880
			<script>
881
			/*
882
			Custom functionality for safari and IE
883
			 */
884
			(function( d ) {
885
				// In case the placeholder functionality is available we remove labels
886
				if ( ( 'placeholder' in d.createElement( 'input' ) ) ) {
887
					var label = d.querySelector( 'label[for=subscribe-field-<?php echo $widget_id; ?>]' );
888
						label.style.clip 	 = 'rect(1px, 1px, 1px, 1px)';
889
						label.style.position = 'absolute';
890
						label.style.height   = '1px';
891
						label.style.width    = '1px';
892
						label.style.overflow = 'hidden';
893
				}
894
895
				// Make sure the email value is filled in before allowing submit
896
				var form = d.getElementById('subscribe-blog-<?php echo $widget_id; ?>'),
897
					input = d.getElementById('<?php echo esc_attr( $subscribe_field_id ) . '-' . esc_attr( $widget_id ); ?>'),
898
					handler = function( event ) {
899
						if ( '' === input.value ) {
900
							input.focus();
901
902
							if ( event.preventDefault ){
903
								event.preventDefault();
904
							}
905
906
							return false;
907
						}
908
					};
909
910
				if ( window.addEventListener ) {
911
					form.addEventListener( 'submit', handler, false );
912
				} else {
913
					form.attachEvent( 'onsubmit', handler );
914
				}
915
			})( document );
916
			</script>
917
		<?php } ?>
918
		<?php
919
920
		echo "\n" . $args['after_widget'];
921
	}
922
923
	function increment_subscriber_count( $current_subs_array = array() ) {
924
		$current_subs_array['value']++;
925
926
		set_transient( 'wpcom_subscribers_total', $current_subs_array, 3600 ); // try to cache the result for at least 1 hour
927
928
		return $current_subs_array;
929
	}
930
931
	function fetch_subscriber_count() {
932
		$subs_count = get_transient( 'wpcom_subscribers_total' );
933
934
		if ( FALSE === $subs_count || 'failed' == $subs_count['status'] ) {
935
			Jetpack:: load_xml_rpc_client();
0 ignored issues
show
Coding Style introduced by
Expected 0 spaces after double colon; 1 found

This check looks for references to static members where there are spaces between the name of the type and the actual member.

An example:

Certificate:: TRIPLEDES_CBC

will actually work, but is not very readable.

Loading history...
936
937
			$xml = new Jetpack_IXR_Client( array( 'user_id' => JETPACK_MASTER_USER, ) );
938
939
			$xml->query( 'jetpack.fetchSubscriberCount' );
940
941
			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
942
				$subs_count = array(
943
					'status'  => 'failed',
944
					'code'    => $xml->getErrorCode(),
945
					'message' => $xml->getErrorMessage(),
946
					'value'	  => ( isset( $subs_count['value'] ) ) ? $subs_count['value'] : 0,
947
				);
948
			} else {
949
				$subs_count = array(
950
					'status' => 'success',
951
					'value'  => $xml->getResponse(),
952
				);
953
			}
954
955
			set_transient( 'wpcom_subscribers_total', $subs_count, 3600 ); // try to cache the result for at least 1 hour
956
		}
957
958
		return $subs_count;
959
	}
960
961
	function update( $new_instance, $old_instance ) {
962
		$instance = $old_instance;
963
964
		$instance['title']					= wp_kses( stripslashes( $new_instance['title'] ), array() );
965
		$instance['subscribe_text']			= wp_filter_post_kses( stripslashes( $new_instance['subscribe_text'] ) );
966
		$instance['subscribe_placeholder']	= wp_kses( stripslashes( $new_instance['subscribe_placeholder'] ), array() );
967
		$instance['subscribe_button']		= wp_kses( stripslashes( $new_instance['subscribe_button'] ), array() );
968
		$instance['success_message']		= wp_kses( stripslashes( $new_instance['success_message'] ), array() );
969
		$instance['show_subscribers_total']	= isset( $new_instance['show_subscribers_total'] ) && $new_instance['show_subscribers_total'];
970
971
		return $instance;
972
	}
973
974
	public static function defaults() {
975
		return array(
976
			'title'               	 => esc_html__( 'Subscribe to Blog via Email', 'jetpack' ),
977
			'subscribe_text'      	 => esc_html__( 'Enter your email address to subscribe to this blog and receive notifications of new posts by email.', 'jetpack' ),
978
			'subscribe_placeholder'	 => esc_html__( 'Email Address', 'jetpack' ),
979
			'subscribe_button'    	 => esc_html__( 'Subscribe', 'jetpack' ),
980
			'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' ),
981
			'show_subscribers_total' => true,
982
		);
983
	}
984
985
	function form( $instance ) {
986
		$instance = wp_parse_args( (array) $instance, $this->defaults() );
987
988
		$title               	= stripslashes( $instance['title'] );
989
		$subscribe_text      	= stripslashes( $instance['subscribe_text'] );
990
		$subscribe_placeholder 	= stripslashes( $instance['subscribe_placeholder'] );
991
		$subscribe_button    	= stripslashes( $instance['subscribe_button'] );
992
		$success_message		= stripslashes( $instance['success_message']);
993
		$show_subscribers_total = checked( $instance['show_subscribers_total'], true, false );
994
995
		$subs_fetch = $this->fetch_subscriber_count();
996
997
		if ( 'failed' == $subs_fetch['status'] ) {
998
			printf( '<div class="error inline"><p>' . __( '%s: %s', 'jetpack' ) . '</p></div>', esc_html( $subs_fetch['code'] ), esc_html( $subs_fetch['message'] ) );
999
		}
1000
		$subscribers_total = number_format_i18n( $subs_fetch['value'] );
1001
?>
1002
<p>
1003
	<label for="<?php echo $this->get_field_id( 'title' ); ?>">
1004
		<?php _e( 'Widget title:', 'jetpack' ); ?>
1005
		<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 ); ?>" />
1006
	</label>
1007
</p>
1008
<p>
1009
	<label for="<?php echo $this->get_field_id( 'subscribe_text' ); ?>">
1010
		<?php _e( 'Optional text to display to your readers:', 'jetpack' ); ?>
1011
		<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>
1012
	</label>
1013
</p>
1014
<p>
1015
	<label for="<?php echo $this->get_field_id( 'subscribe_placeholder' ); ?>">
1016
		<?php esc_html_e( 'Subscribe Placeholder:', 'jetpack' ); ?>
1017
		<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 ); ?>" />
1018
	</label>
1019
</p>
1020
<p>
1021
	<label for="<?php echo $this->get_field_id( 'subscribe_button' ); ?>">
1022
		<?php _e( 'Subscribe Button:', 'jetpack' ); ?>
1023
		<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 ); ?>" />
1024
	</label>
1025
</p>
1026
<p>
1027
	<label for="<?php echo $this->get_field_id( 'success_message' ); ?>">
1028
		<?php _e( 'Success Message Text:', 'jetpack' ); ?>
1029
		<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>
1030
	</label>
1031
</p>
1032
<p>
1033
	<label for="<?php echo $this->get_field_id( 'show_subscribers_total' ); ?>">
1034
		<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; ?> />
1035
		<?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 ) ); ?>
1036
	</label>
1037
</p>
1038
<?php
1039
	}
1040
}
1041
1042
add_shortcode( 'jetpack_subscription_form', 'jetpack_do_subscription_form' );
1043
add_shortcode( 'blog_subscription_form', 'jetpack_do_subscription_form' );
1044
1045
function jetpack_do_subscription_form( $instance ) {
1046
	$instance['show_subscribers_total'] = empty( $instance['show_subscribers_total'] ) ? false : true;
1047
	$instance = shortcode_atts( Jetpack_Subscriptions_Widget::defaults(), $instance, 'jetpack_subscription_form' );
1048
	$args = array(
1049
		'before_widget' => sprintf( '<div class="%s">', 'jetpack_subscription_widget' ),
1050
	);
1051
	ob_start();
1052
	the_widget( 'Jetpack_Subscriptions_Widget', $instance, $args );
1053
	$output = ob_get_clean();
1054
	return $output;
1055
}
1056