Completed
Push — update/editor-blocks-icon-colo... ( 093ab2...3cfb5e )
by
unknown
08:47
created

Sharing_Source   C

Complexity

Total Complexity 54

Size/Duplication

Total Lines 418
Duplicated Lines 3.83 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
dl 16
loc 418
rs 6.4799
c 0
b 0
f 0
wmc 54
lcom 1
cbo 1

22 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 23 3
A is_deprecated() 0 3 1
A http() 0 3 2
A get_id() 0 3 1
A get_class() 0 3 1
A get_share_url() 0 14 1
A get_share_title() 0 17 1
A has_custom_button_style() 0 3 1
C get_link() 0 133 12
A get_process_request_url() 0 3 1
get_name() 0 1 ?
get_display() 0 1 ?
A display_header() 0 2 1
A display_footer() 0 2 1
A has_advanced_options() 0 3 1
A get_amp_display() 0 8 2
A build_amp_markup() 0 25 2
F display_preview() 0 50 14
A get_total() 0 13 2
A get_posts_total() 16 18 3
A process_request() 0 12 1
A js_dialog() 0 31 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Sharing_Source often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Sharing_Source, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
use Automattic\Jetpack\Device_Detection\User_Agent_Info;
4
5
abstract class Sharing_Source {
6
	public	  $button_style;
7
	public	  $smart;
8
	protected $open_link_in_new;
9
	protected $id;
10
11
	public function __construct( $id, array $settings ) {
12
		$this->id = $id;
13
		/**
14
		 * Filter the way sharing links open.
15
		 *
16
		 * By default, sharing links open in a new window.
17
		 *
18
		 * @module sharedaddy
19
		 *
20
		 * @since 3.4.0
21
		 *
22
		 * @param bool true Should Sharing links open in a new window. Default to true.
23
		 */
24
		$this->open_link_in_new = apply_filters( 'jetpack_open_sharing_in_new_window', true );
25
26
		if ( isset( $settings['button_style'] ) ) {
27
			$this->button_style = $settings['button_style'];
28
		}
29
30
		if ( isset( $settings['smart'] ) ) {
31
			$this->smart = $settings['smart'];
32
		}
33
	}
34
35
	public function is_deprecated() {
36
		return false;
37
	}
38
39
	public function http() {
40
		return is_ssl() ? 'https' : 'http';
41
	}
42
43
	public function get_id() {
44
		return $this->id;
45
	}
46
47
	public function get_class() {
48
		return $this->id;
49
	}
50
51
	public function get_share_url( $post_id ) {
52
		/**
53
		 * Filter the sharing permalink.
54
		 *
55
		 * @module sharedaddy
56
		 *
57
		 * @since 1.2.0
58
		 *
59
		 * @param string get_permalink( $post_id ) Post Permalink.
60
		 * @param int $post_id Post ID.
61
		 * @param int $this->id Sharing ID.
62
		 */
63
		return apply_filters( 'sharing_permalink', get_permalink( $post_id ), $post_id, $this->id );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $post_id.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
64
	}
65
66
	public function get_share_title( $post_id ) {
67
		$post = get_post( $post_id );
68
		/**
69
		 * Filter the sharing title.
70
		 *
71
		 * @module sharedaddy
72
		 *
73
		 * @since 2.8.0
74
		 *
75
		 * @param string $post->post_title Post Title.
76
		 * @param int $post_id Post ID.
77
		 * @param int $this->id Sharing ID.
78
		 */
79
		$title = apply_filters( 'sharing_title', $post->post_title, $post_id, $this->id );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $post_id.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
80
81
		return html_entity_decode( wp_kses( $title, null ) );
82
	}
83
84
	public function has_custom_button_style() {
85
		return false;
86
	}
87
88
	public function get_link( $url, $text, $title, $query = '', $id = false ) {
89
		$args = func_get_args();
90
		$klasses = array( 'share-' . $this->get_class(), 'sd-button' );
91
92
		if ( 'icon' == $this->button_style || 'icon-text' == $this->button_style ) {
93
			$klasses[] = 'share-icon';
94
		}
95
96
		if ( 'icon' == $this->button_style ) {
97
			$text = $title;
98
			$klasses[] = 'no-text';
99
100
			if ( true == $this->open_link_in_new ) {
101
				$text .= __( ' (Opens in new window)', 'jetpack' );
102
			}
103
		}
104
105
		/**
106
		 * Filter the sharing display ID.
107
		 *
108
		 * @module sharedaddy
109
		 *
110
		 * @since 3.4.0
111
		 *
112
		 * @param int|false $id Sharing ID.
113
		 * @param object $this Sharing service properties.
114
		 * @param array $args Array of sharing service options.
115
		 */
116
		$id = apply_filters( 'jetpack_sharing_display_id', $id, $this, $args );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $this.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
117
		/**
118
		 * Filter the sharing display link.
119
		 *
120
		 * @module sharedaddy
121
		 *
122
		 * @since 2.8.0
123
		 *
124
		 * @param string $url Post URL.
125
		 * @param object $this Sharing service properties.
126
		 * @param int|false $id Sharing ID.
127
		 * @param array $args Array of sharing service options.
128
		 */
129
		$url = apply_filters( 'sharing_display_link', $url, $this, $id, $args ); // backwards compatibility
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $this.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
130
		/**
131
		 * Filter the sharing display link.
132
		 *
133
		 * @module sharedaddy
134
		 *
135
		 * @since 2.8.0
136
		 *
137
		 * @param string $url Post URL.
138
		 * @param object $this Sharing service properties.
139
		 * @param int|false $id Sharing ID.
140
		 * @param array $args Array of sharing service options.
141
		 */
142
		$url = apply_filters( 'jetpack_sharing_display_link', $url, $this, $id, $args );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $this.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
143
		/**
144
		 * Filter the sharing display query.
145
		 *
146
		 * @module sharedaddy
147
		 *
148
		 * @since 2.8.0
149
		 *
150
		 * @param string $query Sharing service URL parameter.
151
		 * @param object $this Sharing service properties.
152
		 * @param int|false $id Sharing ID.
153
		 * @param array $args Array of sharing service options.
154
		 */
155
		$query = apply_filters( 'jetpack_sharing_display_query', $query, $this, $id, $args );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $this.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
156
157
		if ( ! empty( $query ) ) {
158
			if ( false === stripos( $url, '?' ) ) {
159
				$url .= '?' . $query;
160
			} else {
161
				$url .= '&amp;' . $query;
162
			}
163
		}
164
165
		if ( 'text' == $this->button_style ) {
166
			$klasses[] = 'no-icon';
167
		}
168
169
		/**
170
		 * Filter the sharing display classes.
171
		 *
172
		 * @module sharedaddy
173
		 *
174
		 * @since 3.4.0
175
		 *
176
		 * @param array $klasses Sharing service classes.
177
		 * @param object $this Sharing service properties.
178
		 * @param int|false $id Sharing ID.
179
		 * @param array $args Array of sharing service options.
180
		 */
181
		$klasses = apply_filters( 'jetpack_sharing_display_classes', $klasses, $this, $id, $args );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $this.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
182
		/**
183
		 * Filter the sharing display title.
184
		 *
185
		 * @module sharedaddy
186
		 *
187
		 * @since 3.4.0
188
		 *
189
		 * @param string $title Sharing service title.
190
		 * @param object $this Sharing service properties.
191
		 * @param int|false $id Sharing ID.
192
		 * @param array $args Array of sharing service options.
193
		 */
194
		$title = apply_filters( 'jetpack_sharing_display_title', $title, $this, $id, $args );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $this.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
195
		/**
196
		 * Filter the sharing display text.
197
		 *
198
		 * @module sharedaddy
199
		 *
200
		 * @since 3.4.0
201
		 *
202
		 * @param string $text Sharing service text.
203
		 * @param object $this Sharing service properties.
204
		 * @param int|false $id Sharing ID.
205
		 * @param array $args Array of sharing service options.
206
		 */
207
		$text = apply_filters( 'jetpack_sharing_display_text', $text, $this, $id, $args );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $this.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
208
209
		return sprintf(
210
			'<a rel="nofollow%s" data-shared="%s" class="%s" href="%s"%s title="%s"><span%s>%s</span></a>',
211
			( true == $this->open_link_in_new ) ? ' noopener noreferrer' : '',
212
			( $id ? esc_attr( $id ) : '' ),
213
			implode( ' ', $klasses ),
214
			$url,
215
			( true == $this->open_link_in_new ) ? ' target="_blank"' : '',
216
			$title,
217
			( 'icon' == $this->button_style ) ? '></span><span class="sharing-screen-reader-text"' : '',
218
			$text
219
		);
220
	}
221
222
	/**
223
	 * Get an unfiltered post permalink to use when generating a sharing URL with get_link.
224
	 * Use instead of get_share_url for non-official styles as get_permalink ensures that process_request
225
	 * will be executed more reliably, in the case that the filtered URL uses a service that strips query parameters.
226
	 *
227
	 * @since 3.7.0
228
	 * @param int $post_id Post ID.
229
	 * @uses get_permalink
230
	 * @return string get_permalink( $post_id ) Post permalink.
231
	 */
232
	public function get_process_request_url( $post_id ) {
233
		return get_permalink( $post_id );
234
	}
235
236
	abstract public function get_name();
237
	abstract public function get_display( $post );
238
239
	public function display_header() {
240
	}
241
242
	public function display_footer() {
243
	}
244
245
	public function has_advanced_options() {
246
		return false;
247
	}
248
249
	/**
250
	 * Get the AMP specific markup for a sharing button.
251
	 *
252
	 * @param \WP_Post $post The current post being viewed.
253
	 */
254
	public function get_amp_display( $post ) {
255
		// Only display markup if we're on a post.
256
		if ( empty( $post ) ) {
257
			return false;
258
		}
259
260
		return $this->build_amp_markup();
261
	}
262
263
	/**
264
	 * Generates and returns the markup for an AMP sharing button.
265
	 *
266
	 * @param array $attrs Custom attributes for rendering the social icon.
267
	 */
268
	protected function build_amp_markup( $attrs = array() ) {
269
270
		$title = sprintf(
271
			/* translators: placeholder is a service name, such as "Twitter" or "Facebook". */
272
			__( 'Click to share on %s', 'jetpack' ),
273
			$this->get_name()
274
		);
275
276
		$attrs        = array_merge(
277
			array(
278
				'type'       => $this->get_id(),
279
				'height'     => '32px',
280
				'width'      => '32px',
281
				'aria-label' => $title,
282
				'title'      => $title,
283
			),
284
			$attrs
285
		);
286
		$sharing_link = '<amp-social-share';
287
		foreach ( $attrs as $key => $value ) {
288
			$sharing_link .= sprintf( ' %s="%s"', sanitize_key( $key ), esc_attr( $value ) );
289
		}
290
		$sharing_link .= '></amp-social-share>';
291
		return $sharing_link;
292
	}
293
294
	public function display_preview( $echo = true, $force_smart = false, $button_style = null ) {
295
		$text = '&nbsp;';
296
		$button_style = ( ! empty( $button_style ) ) ? $button_style : $this->button_style;
297
		if ( ! $this->smart && ! $force_smart ) {
298
			if ( $button_style != 'icon' ) {
299
				$text = $this->get_name();
300
			}
301
		}
302
303
		$klasses = array( 'share-' . $this->get_class(), 'sd-button' );
304
305
		if ( $button_style == 'icon' || $button_style == 'icon-text' ) {
306
			$klasses[] = 'share-icon';
307
		}
308
309
		if ( $button_style == 'icon' ) {
310
			$klasses[] = 'no-text';
311
		}
312
313
		if ( $button_style == 'text' ) {
314
			$klasses[] = 'no-icon';
315
		}
316
317
		$is_deprecated = $this->is_deprecated();
318
319
		$link = sprintf(
320
			'<a rel="nofollow" class="%s" href="javascript:void(0)" title="%s"><span>%s</span></a>',
321
			implode( ' ', $klasses ),
322
			esc_attr(
323
				$is_deprecated
324
					/* translators: %1$s is the name of a deprecated Sharing Service like "Google+" */
325
					? sprintf( __( 'The %1$s service has shut down. This sharing button is not displayed to your visitors and should be removed.', 'jetpack' ), $this->get_name() )
326
					: $this->get_name()
327
			),
328
			esc_html(
329
				$is_deprecated
330
					/* translators: %1$s is the name of a deprecated Sharing Service like "Google+" */
331
					? sprintf( __( '%1$s has shut down', 'jetpack' ), $this->get_name() )
332
					: $text
333
			)
334
		);
335
336
		$smart = ( $this->smart || $force_smart ) ? 'on' : 'off';
337
		$return = "<div class='option option-smart-$smart'>$link</div>";
338
		if ( $echo ) {
339
			echo $return;
340
		}
341
342
		return $return;
343
	}
344
345
	public function get_total( $post = false ) {
346
		global $wpdb, $blog_id;
347
348
		$name = strtolower( $this->get_id() );
349
350
		if ( $post == false ) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
351
			// get total number of shares for service
352
			return (int) $wpdb->get_var( $wpdb->prepare( 'SELECT SUM( count ) FROM sharing_stats WHERE blog_id = %d AND share_service = %s', $blog_id, $name ) );
353
		}
354
355
		// get total shares for a post
356
		return (int) $wpdb->get_var( $wpdb->prepare( 'SELECT count FROM sharing_stats WHERE blog_id = %d AND post_id = %d AND share_service = %s', $blog_id, $post->ID, $name ) );
357
	}
358
359 View Code Duplication
	public function get_posts_total() {
360
		global $wpdb, $blog_id;
361
362
		$totals = array();
363
		$name	= strtolower( $this->get_id() );
364
365
		$my_data = $wpdb->get_results( $wpdb->prepare( 'SELECT post_id as id, SUM( count ) as total FROM sharing_stats WHERE blog_id = %d AND share_service = %s GROUP BY post_id ORDER BY count DESC ', $blog_id, $name ) );
366
367
		if ( ! empty( $my_data ) ) {
368
			foreach ( $my_data as $row ) {
369
				$totals[] = new Sharing_Post_Total( $row->id, $row->total );
370
			}
371
		}
372
373
		usort( $totals, array( 'Sharing_Post_Total', 'cmp' ) );
374
375
		return $totals;
376
	}
377
378
	public function process_request( $post, array $post_data ) {
379
		/**
380
		 * Fires when a post is shared via one of the sharing buttons.
381
		 *
382
		 * @module sharedaddy
383
		 *
384
		 * @since 1.1.0
385
		 *
386
		 * @param array $args Aray of information about the sharing service.
387
		 */
388
		do_action( 'sharing_bump_stats', array( 'service' => $this, 'post' => $post ) );
389
	}
390
391
	public function js_dialog( $name, $params = array() ) {
392
		if ( true !== $this->open_link_in_new ) {
393
			return;
394
		}
395
396
		$defaults = array(
397
			'menubar'	=> 1,
398
			'resizable' => 1,
399
			'width'		=> 600,
400
			'height'	=> 400,
401
		);
402
		$params = array_merge( $defaults, $params );
403
		$opts = array();
404
		foreach ( $params as $key => $val ) {
405
			$opts[] = "$key=$val";
406
		}
407
		$opts = implode( ',', $opts );
408
409
		// Add JS after sharing-js has been enqueued.
410
		wp_add_inline_script( 'sharing-js',
411
			"var windowOpen;
412
			jQuery( document.body ).on( 'click', 'a.share-$name', function() {
413
				// If there's another sharing window open, close it.
414
				if ( 'undefined' !== typeof windowOpen ) {
415
					windowOpen.close();
416
				}
417
				windowOpen = window.open( jQuery( this ).attr( 'href' ), 'wpcom$name', '$opts' );
418
				return false;
419
			});"
420
		);
421
	}
422
}
423
424
abstract class Deprecated_Sharing_Source extends Sharing_Source {
425
	public	  $button_style = 'text';
426
	public	  $smart = false;
427
	protected $open_link_in_new = false;
428
	protected $id;
429
	protected $deprecated = true;
430
431
	final public function __construct( $id, array $settings ) {
432
		$this->id = $id;
433
434
		if ( isset( $settings['button_style'] ) ) {
435
			$this->button_style = $settings['button_style'];
436
		}
437
	}
438
439
	final public function is_deprecated() {
440
		return true;
441
	}
442
443
	final public function get_share_url( $post_id ) {
444
		return get_permalink( $post_id );
445
	}
446
447
	/**
448
	 * No AMP display for deprecated sources.
449
	 *
450
	 * @param \WP_Post $post The current post being viewed.
451
	 */
452
	final public function get_amp_display( $post ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
453
		return false;
454
	}
455
456
	final public function display_preview( $echo = true, $force_smart = false, $button_style = null ) {
457
		return parent::display_preview( $echo, false, $button_style );
458
	}
459
460
	final public function get_total( $post = false ) {
461
		return 0;
462
	}
463
464
	final public function get_posts_total() {
465
		return 0;
466
	}
467
468
	final public function process_request( $post, array $post_data ) {
469
		parent::process_request( $post, $post_data );
470
	}
471
472
	final public function get_display( $post ) {
473
		if ( current_user_can( 'manage_options' ) ) {
474
			return $this->display_deprecated( $post );
475
		}
476
477
		return '';
478
	}
479
480
	public function display_deprecated( $post ) {
481
		return $this->get_link(
482
			$this->get_share_url( $post->ID ),
483
			/* translators: %1$s is the name of a deprecated Sharing Service like "Google+" */
484
			sprintf( __( '%1$s has shut down', 'jetpack' ), $this->get_name() ),
485
			/* translators: %1$s is the name of a deprecated Sharing Service like "Google+" */
486
			sprintf( __( 'The %1$s service has shut down. This sharing button is not displayed to your visitors and should be removed.', 'jetpack' ), $this->get_name() )
487
		);
488
	}
489
}
490
491
abstract class Sharing_Advanced_Source extends Sharing_Source {
492
	public function has_advanced_options() {
493
		return true;
494
	}
495
496
	abstract public function display_options();
497
	abstract public function update_options( array $data );
498
	abstract public function get_options();
499
}
500
501
class Share_Email extends Sharing_Source {
502
	public $shortname = 'email';
503
	public $icon = '\f410';
504 View Code Duplication
	public function __construct( $id, array $settings ) {
505
		parent::__construct( $id, $settings );
506
507
		if ( 'official' == $this->button_style ) {
508
			$this->smart = true;
509
		} else {
510
			$this->smart = false;
511
		}
512
	}
513
514
	public function get_name() {
515
		return _x( 'Email', 'as sharing source', 'jetpack' );
516
	}
517
518
	// Default does nothing
519
	public function process_request( $post, array $post_data ) {
520
		$ajax = false;
521
		if ( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && strtolower( $_SERVER['HTTP_X_REQUESTED_WITH'] ) == 'xmlhttprequest' ) {
522
			$ajax = true;
523
		}
524
525
		$source_email = $target_email = $source_name = false;
0 ignored issues
show
Unused Code introduced by
$source_name is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
526
527
		if ( isset( $post_data['source_email'] ) && is_email( $post_data['source_email'] ) ) {
528
			$source_email = $post_data['source_email'];
529
		}
530
531
		if ( isset( $post_data['target_email'] ) && is_email( $post_data['target_email'] ) ) {
532
			$target_email = $post_data['target_email'];
533
		}
534
535
		if ( isset( $post_data['source_name'] ) && strlen( $post_data['source_name'] ) < 200 ) {
536
			$source_name = $post_data['source_name'];
537
		} elseif ( isset( $post_data['source_name'] ) ) {
538
			$source_name = substr( $post_data['source_name'], 0, 200 );
539
		} else {
540
			$source_name = '';
541
		}
542
543
		// Test email
544
		$error = 1;	  // Failure in data
545
		if ( empty( $post_data['source_f_name'] ) && $source_email && $target_email && $source_name ) {
546
			/**
547
			 * Allow plugins to stop the email sharing button from running the shared message through Akismet.
548
			 *
549
			 * @module sharedaddy
550
			 *
551
			 * @since 1.1.0
552
			 *
553
			 * @param bool true Should we check if the message isn't spam?
554
			 * @param object $post Post information.
555
			 * @param array $post_data Information about the shared message.
556
			 */
557
			if ( apply_filters( 'sharing_email_check', true, $post, $post_data ) ) {
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $post.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
558
				$data = array(
559
					'post'           => $post,
560
					'source'         => $source_email,
561
					'target'         => $target_email,
562
					'name'           => $source_name,
563
					'sharing_source' => $this,
564
				);
565
				// todo: implement an error message when email doesn't get sent.
566
				/**
567
				 * Filter whether an email can be sent from the Email sharing button.
568
				 *
569
				 * @module sharedaddy
570
				 *
571
				 * @since 1.1.0
572
				 *
573
				 * @param array $data Array of information about the shared message.
574
				 */
575
				if ( ( $data = apply_filters( 'sharing_email_can_send', $data ) ) !== false ) {
576
					// Record stats
577
					parent::process_request( $data['post'], $post_data );
578
579
					/**
580
					 * Fires when an email is sent via the Email sharing button.
581
					 *
582
					 * @module sharedaddy
583
					 *
584
					 * @since 1.1.0
585
					 *
586
					 * @param array $data Array of information about the shared message.
587
					 */
588
					do_action( 'sharing_email_send_post', $data );
589
				}
590
591
				// Return a positive regardless of whether the user is subscribed or not
592
				if ( $ajax ) {
593
?>
594
<div class="response">
595
	<div class="response-title"><?php _e( 'This post has been shared!', 'jetpack' ); ?></div>
596
	<div class="response-sub"><?php printf( __( 'You have shared this post with %s', 'jetpack' ), esc_html( $target_email ) ); ?></div>
597
	<div class="response-close"><a href="#" class="sharing_cancel"><?php _e( 'Close', 'jetpack' ); ?></a></div>
598
</div>
599
<?php
600
				} else {
601
					wp_safe_redirect( get_permalink( $post->ID ) . '?shared=email' );
602
				}
603
604
				die();
605
			} else {
606
				$error = 2;	  // Email check failed
607
			}
608
		}
609
610
		if ( $ajax ) {
611
			echo $error;
612
		} else {
613
			wp_safe_redirect( get_permalink( $post->ID ) . '?shared=email&msg=fail' );
614
		}
615
616
		die();
617
	}
618
619
	public function get_display( $post ) {
620
		return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Email', 'share to', 'jetpack' ), __( 'Click to email this to a friend', 'jetpack' ), 'share=email' );
621
	}
622
623
	/**
624
	 * No AMP display for email.
625
	 *
626
	 * @param \WP_Post $post The current post being viewed.
627
	 */
628
	public function get_amp_display( $post ) { // phpcs:ignore
629
		return false;
630
	}
631
632
	/**
633
	 * Outputs the hidden email dialog
634
	 */
635
	public function display_footer() {
636
		global $current_user;
637
638
		$visible = $status = false;
0 ignored issues
show
Unused Code introduced by
$status is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
Unused Code introduced by
$visible is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
639
?>
640
	<div id="sharing_email" style="display: none;">
641
		<form action="<?php echo esc_url( $_SERVER['REQUEST_URI'] ); ?>" method="post">
642
			<label for="target_email"><?php _e( 'Send to Email Address', 'jetpack' ) ?></label>
643
			<input type="email" name="target_email" id="target_email" value="" />
644
645
			<?php if ( is_user_logged_in() ) : ?>
646
				<input type="hidden" name="source_name" value="<?php echo esc_attr( $current_user->display_name ); ?>" />
647
				<input type="hidden" name="source_email" value="<?php echo esc_attr( $current_user->user_email ); ?>" />
648
			<?php else : ?>
649
650
				<label for="source_name"><?php _e( 'Your Name', 'jetpack' ) ?></label>
651
				<input type="text" name="source_name" id="source_name" value="" />
652
653
				<label for="source_email"><?php _e( 'Your Email Address', 'jetpack' ) ?></label>
654
				<input type="email" name="source_email" id="source_email" value="" />
655
656
			<?php endif; ?>
657
			<input type="text" id="jetpack-source_f_name" name="source_f_name" class="input" value="" size="25" autocomplete="off" title="<?php esc_attr_e( 'This field is for validation and should not be changed', 'jetpack' ); ?>" />
658
			<?php
659
				/**
660
				 * Fires when the Email sharing dialog is loaded.
661
				 *
662
				 * @module sharedaddy
663
				 *
664
				 * @since 1.1.0
665
				 *
666
				 * @param string jetpack Eail sharing source.
667
				 */
668
				do_action( 'sharing_email_dialog', 'jetpack' );
669
			?>
670
671
			<img style="float: right; display: none" class="loading" src="<?php
672
			/** This filter is documented in modules/stats.php */
673
			echo apply_filters( 'jetpack_static_url', plugin_dir_url( __FILE__ ) . 'images/loading.gif' ); ?>" alt="loading" width="16" height="16" />
674
			<input type="submit" value="<?php esc_attr_e( 'Send Email', 'jetpack' ); ?>" class="sharing_send" />
675
			<a rel="nofollow" href="#cancel" class="sharing_cancel" role="button"><?php _e( 'Cancel', 'jetpack' ); ?></a>
676
677
			<div class="errors errors-1" style="display: none;">
678
				<?php _e( 'Post was not sent - check your email addresses!', 'jetpack' ); ?>
679
			</div>
680
681
			<div class="errors errors-2" style="display: none;">
682
				<?php _e( 'Email check failed, please try again', 'jetpack' ); ?>
683
			</div>
684
685
			<div class="errors errors-3" style="display: none;">
686
				<?php _e( 'Sorry, your blog cannot share posts by email.', 'jetpack' ); ?>
687
			</div>
688
		</form>
689
	</div>
690
<?php
691
	}
692
}
693
694
class Share_Twitter extends Sharing_Source {
695
	public $shortname = 'twitter';
696
	public $icon = '\f202';
697
	// 'https://dev.twitter.com/rest/reference/get/help/configuration' ( 2015/02/06 ) short_url_length is 22, short_url_length_https is 23
698
	public $short_url_length = 24;
699
700 View Code Duplication
	public function __construct( $id, array $settings ) {
701
		parent::__construct( $id, $settings );
702
703
		if ( 'official' == $this->button_style ) {
704
			$this->smart = true;
705
		} else {
706
			$this->smart = false;
707
		}
708
	}
709
710
	public function get_name() {
711
		return __( 'Twitter', 'jetpack' );
712
	}
713
714
	/**
715
	 * Determine the Twitter 'via' value for a post.
716
	 *
717
	 * @param  WP_Post|int $post Post object or post ID.
718
	 * @return string Twitter handle without the preceding @.
719
	 **/
720
	public static function sharing_twitter_via( $post ) {
721
		$post = get_post( $post );
722
		/**
723
		 * Allow third-party plugins to customize the Twitter username used as "twitter:site" Twitter Card Meta Tag.
724
		 *
725
		 * @module sharedaddy
726
		 *
727
		 * @since 3.0.0
728
		 *
729
		 * @param string $string Twitter Username.
730
		 * @param array $args Array of Open Graph Meta Tags and Twitter Cards tags.
731
		 */
732
		$twitter_site_tag_value = apply_filters(
733
			'jetpack_twitter_cards_site_tag',
734
			'',
735
			/** This action is documented in modules/sharedaddy/sharing-sources.php */
736
			array( 'twitter:creator' => apply_filters( 'jetpack_sharing_twitter_via', '', $post->ID ) )
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $post->ID.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
Unused Code introduced by
The call to apply_filters() has too many arguments starting with array('twitter:creator' ...r_via', '', $post->ID)).

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
737
		);
738
739
		/*
740
		 * Hack to remove the unwanted behavior of adding 'via @jetpack' which
741
		 * was introduced with the adding of the Twitter cards.
742
		 * This should be a temporary solution until a better method is setup.
743
		 */
744
		if ( 'jetpack' == $twitter_site_tag_value ) {
745
			$twitter_site_tag_value = '';
746
		}
747
748
		/**
749
		 * Filters the Twitter username used as "via" in the Twitter sharing button.
750
		 *
751
		 * @module sharedaddy
752
		 *
753
		 * @since 1.7.0
754
		 *
755
		 * @param string $twitter_site_tag_value Twitter Username.
756
		 * @param int $post->ID Post ID.
757
		 */
758
		$twitter_site_tag_value = apply_filters( 'jetpack_sharing_twitter_via', $twitter_site_tag_value, $post->ID );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $post->ID.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
759
760
		// Strip out anything other than a letter, number, or underscore.
761
		// This will prevent the inadvertent inclusion of an extra @, as well as normalizing the handle.
762
		return preg_replace( '/[^\da-z_]+/i', '', $twitter_site_tag_value );
763
	}
764
765
	/**
766
	 * Determine the 'related' Twitter accounts for a post.
767
	 *
768
	 * @param  WP_Post|int $post Post object or post ID.
769
	 * @return string Comma-separated list of Twitter handles.
770
	 **/
771
	public static function get_related_accounts( $post ) {
772
		$post = get_post( $post );
773
		/**
774
		 * Filter the list of related Twitter accounts added to the Twitter sharing button.
775
		 *
776
		 * @module sharedaddy
777
		 *
778
		 * @since 1.7.0
779
		 *
780
		 * @param array $args Array of Twitter usernames. Format is 'username' => 'Optional description'
781
		 * @param int $post->ID Post ID.
782
		 */
783
		$related_accounts = apply_filters( 'jetpack_sharing_twitter_related', array(), $post->ID );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $post->ID.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
784
785
		// Example related string: account1,account2:Account 2 description,account3
786
		$related = array();
787
788
		foreach ( $related_accounts as $related_account_username => $related_account_description ) {
789
			// Join the description onto the end of the username
790
			if ( $related_account_description ) {
791
				$related_account_username .= ':' . $related_account_description;
792
			}
793
794
			$related[] = $related_account_username;
795
		}
796
797
		return implode( ',', $related );
798
	}
799
800
	public function get_display( $post ) {
801
		$via = $this->sharing_twitter_via( $post );
802
803
		if ( $via ) {
804
			$via = 'data-via="' . esc_attr( $via ) . '"';
805
		} else {
806
			$via = '';
807
		}
808
809
		$related = $this->get_related_accounts( $post );
810
		if ( ! empty( $related ) && $related !== $via ) {
811
			$related = 'data-related="' . esc_attr( $related ) . '"';
812
		} else {
813
			$related = '';
814
		}
815
816
		if ( $this->smart ) {
817
			$share_url = $this->get_share_url( $post->ID );
818
			$post_title = $this->get_share_title( $post->ID );
819
			return sprintf(
820
				'<a href="https://twitter.com/share" class="twitter-share-button" data-url="%1$s" data-text="%2$s" %3$s %4$s>Tweet</a>',
821
				esc_url( $share_url ),
822
				esc_attr( $post_title ),
823
				$via,
824
				$related
825
			);
826
		} else {
827
			if (
828
				/**
829
				 * Allow plugins to disable sharing counts for specific sharing services.
830
				 *
831
				 * @module sharedaddy
832
				 *
833
				 * @since 3.0.0
834
				 *
835
				 * @param bool true Should sharing counts be enabled for this specific service. Default to true.
836
				 * @param int $post->ID Post ID.
837
				 * @param string $str Sharing service name.
838
				 */
839
				apply_filters( 'jetpack_register_post_for_share_counts', true, $post->ID, 'twitter' )
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $post->ID.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
840
			) {
841
				sharing_register_post_for_share_counts( $post->ID );
842
			}
843
			return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Twitter', 'share to', 'jetpack' ), __( 'Click to share on Twitter', 'jetpack' ), 'share=twitter', 'sharing-twitter-' . $post->ID );
844
		}
845
	}
846
847
	public function process_request( $post, array $post_data ) {
848
		$post_title = $this->get_share_title( $post->ID );
849
		$post_link = $this->get_share_url( $post->ID );
850
851
		if ( function_exists( 'mb_stripos' ) ) {
852
			$strlen = 'mb_strlen';
853
			$substr = 'mb_substr';
854
		} else {
855
			$strlen = 'strlen';
856
			$substr = 'substr';
857
		}
858
859
		$via = $this->sharing_twitter_via( $post );
860
		$related = $this->get_related_accounts( $post );
861
		if ( $via ) {
862
			$sig = " via @$via";
863
			if ( $related === $via ) {
864
				$related = false;
865
			}
866
		} else {
867
			$via = false;
868
			$sig = '';
869
		}
870
871
		$suffix_length = $this->short_url_length + $strlen( $sig );
872
		// $sig is handled by twitter in their 'via' argument.
873
		// $post_link is handled by twitter in their 'url' argument.
874
		if ( 280 < $strlen( $post_title ) + $suffix_length ) {
875
			// The -1 is for "\xE2\x80\xA6", a UTF-8 ellipsis.
876
			$text = $substr( $post_title, 0, 280 - $suffix_length - 1 ) . "\xE2\x80\xA6";
877
		} else {
878
			$text = $post_title;
879
		}
880
881
		// Record stats
882
		parent::process_request( $post, $post_data );
883
884
		$url = $post_link;
885
		$twitter_url = add_query_arg(
886
			rawurlencode_deep( array_filter( compact( 'via', 'related', 'text', 'url' ) ) ),
887
			'https://twitter.com/intent/tweet'
888
		);
889
890
		// Redirect to Twitter
891
		wp_redirect( $twitter_url );
892
		die();
893
	}
894
895
	public function has_custom_button_style() {
896
		return $this->smart;
897
	}
898
899
	public function display_footer() {
900
		if ( $this->smart ) {
901
			?>
902
			<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
903
			<?php
904
		} else {
905
			$this->js_dialog( $this->shortname, array( 'height' => 350 ) );
906
		}
907
	}
908
}
909
910
911
class Share_Reddit extends Sharing_Source {
912
	public $shortname = 'reddit';
913
	public $icon = '\f222';
914 View Code Duplication
	public function __construct( $id, array $settings ) {
915
		parent::__construct( $id, $settings );
916
917
		if ( 'official' == $this->button_style ) {
918
			$this->smart = true;
919
		} else {
920
			$this->smart = false;
921
		}
922
	}
923
924
	public function get_name() {
925
		return __( 'Reddit', 'jetpack' );
926
	}
927
928
	public function get_display( $post ) {
929
		if ( $this->smart ) {
930
			return '<div class="reddit_button"><iframe src="' . $this->http() . '://www.reddit.com/static/button/button1.html?newwindow=true&width=120&amp;url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&amp;title=' . rawurlencode( $this->get_share_title( $post->ID ) ) . '" height="22" width="120" scrolling="no" frameborder="0"></iframe></div>';
931 View Code Duplication
		} else {
932
			return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Reddit', 'share to', 'jetpack' ), __( 'Click to share on Reddit', 'jetpack' ), 'share=reddit' );
933
		}
934
	}
935
936
	/**
937
	 * AMP display for Reddit.
938
	 *
939
	 * @param \WP_Post $post The current post being viewed.
940
	 */
941 View Code Duplication
	public function get_amp_display( $post ) {
942
		$attrs = array(
943
			'data-share-endpoint' => esc_url_raw( 'https://reddit.com/submit?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&title=' . rawurlencode( $this->get_share_title( $post->ID ) ) ),
944
		);
945
946
		return $this->build_amp_markup( $attrs );
947
	}
948
949 View Code Duplication
	public function process_request( $post, array $post_data ) {
950
		$reddit_url = $this->http() . '://reddit.com/submit?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&title=' . rawurlencode( $this->get_share_title( $post->ID ) );
951
952
		// Record stats
953
		parent::process_request( $post, $post_data );
954
955
		// Redirect to Reddit
956
		wp_redirect( $reddit_url );
957
		die();
958
	}
959
}
960
961
class Share_LinkedIn extends Sharing_Source {
962
	public $shortname = 'linkedin';
963
	public $icon = '\f207';
964 View Code Duplication
	public function __construct( $id, array $settings ) {
965
		parent::__construct( $id, $settings );
966
967
		if ( 'official' == $this->button_style ) {
968
			$this->smart = true;
969
		} else {
970
			$this->smart = false;
971
		}
972
	}
973
974
	public function get_name() {
975
		return __( 'LinkedIn', 'jetpack' );
976
	}
977
978
	public function has_custom_button_style() {
979
		return $this->smart;
980
	}
981
982
	public function get_display( $post ) {
983
		$display = '';
984
985
		if ( $this->smart ) {
986
			$share_url = $this->get_share_url( $post->ID );
987
			$display .= sprintf( '<div class="linkedin_button"><script type="in/share" data-url="%s" data-counter="right"></script></div>', esc_url( $share_url ) );
988 View Code Duplication
		} else {
989
			$display = $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'LinkedIn', 'share to', 'jetpack' ), __( 'Click to share on LinkedIn', 'jetpack' ), 'share=linkedin', 'sharing-linkedin-' . $post->ID );
990
		}
991
992
		/** This filter is already documented in modules/sharedaddy/sharing-sources.php */
993
		if ( apply_filters( 'jetpack_register_post_for_share_counts', true, $post->ID, 'linkedin' ) ) {
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $post->ID.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
994
			sharing_register_post_for_share_counts( $post->ID );
995
		}
996
997
		return $display;
998
	}
999
1000 View Code Duplication
	public function process_request( $post, array $post_data ) {
1001
1002
		$post_link = $this->get_share_url( $post->ID );
1003
1004
		// Using the same URL as the official button, which is *not* LinkedIn's documented sharing link
1005
		// https://www.linkedin.com/cws/share?url={url}&token=&isFramed=false
1006
		$linkedin_url = add_query_arg( array(
1007
			'url' => rawurlencode( $post_link ),
1008
		), 'https://www.linkedin.com/cws/share?token=&isFramed=false' );
1009
1010
		// Record stats
1011
		parent::process_request( $post, $post_data );
1012
1013
		// Redirect to LinkedIn
1014
		wp_redirect( $linkedin_url );
1015
		die();
1016
	}
1017
1018 View Code Duplication
	public function display_footer() {
1019
		if ( ! $this->smart ) {
1020
			$this->js_dialog( $this->shortname, array( 'width' => 580, 'height' => 450 ) );
1021
		} else {
1022
			?><script type="text/javascript">
1023
			jQuery( document ).ready( function() {
1024
				jQuery.getScript( 'https://platform.linkedin.com/in.js?async=true', function success() {
1025
					IN.init();
1026
				});
1027
			});
1028
			jQuery( document.body ).on( 'post-load', function() {
1029
				if ( typeof IN != 'undefined' )
1030
					IN.parse();
1031
			});
1032
			</script><?php
1033
		}
1034
	}
1035
}
1036
1037
class Share_Facebook extends Sharing_Source {
1038
	public $shortname = 'facebook';
1039
	public $icon = '\f204';
1040
	private $share_type = 'default';
1041
1042 View Code Duplication
	public function __construct( $id, array $settings ) {
1043
		parent::__construct( $id, $settings );
1044
1045
		if ( isset( $settings['share_type'] ) ) {
1046
			$this->share_type = $settings['share_type'];
1047
		}
1048
1049
		if ( 'official' == $this->button_style ) {
1050
			$this->smart = true;
1051
		} else {
1052
			$this->smart = false;
1053
		}
1054
	}
1055
1056
	public function get_name() {
1057
		return __( 'Facebook', 'jetpack' );
1058
	}
1059
1060
	public function display_header() {
1061
	}
1062
1063 View Code Duplication
	function guess_locale_from_lang( $lang ) {
1064
		if ( 'en' == $lang || 'en_US' == $lang || ! $lang ) {
1065
			return 'en_US';
1066
		}
1067
1068
		if ( ! class_exists( 'GP_Locales' ) ) {
1069
			if ( ! defined( 'JETPACK__GLOTPRESS_LOCALES_PATH' ) || ! file_exists( JETPACK__GLOTPRESS_LOCALES_PATH ) ) {
1070
				return false;
1071
			}
1072
1073
			require JETPACK__GLOTPRESS_LOCALES_PATH;
1074
		}
1075
1076
		if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
1077
			// WP.com: get_locale() returns 'it'
1078
			$locale = GP_Locales::by_slug( $lang );
1079
		} else {
1080
			// Jetpack: get_locale() returns 'it_IT';
1081
			$locale = GP_Locales::by_field( 'wp_locale', $lang );
1082
		}
1083
1084
		if ( ! $locale ) {
1085
			return false;
1086
		}
1087
1088
		if ( empty( $locale->facebook_locale ) ) {
1089
			if ( empty( $locale->wp_locale ) ) {
1090
				return false;
1091
			} else {
1092
				// Facebook SDK is smart enough to fall back to en_US if a
1093
				// locale isn't supported. Since supported Facebook locales
1094
				// can fall out of sync, we'll attempt to use the known
1095
				// wp_locale value and rely on said fallback.
1096
				return $locale->wp_locale;
1097
			}
1098
		}
1099
1100
		return $locale->facebook_locale;
1101
	}
1102
1103
	public function get_display( $post ) {
1104
		if ( $this->smart ) {
1105
			$share_url = $this->get_share_url( $post->ID );
1106
			$fb_share_html = '<div class="fb-share-button" data-href="' . esc_attr( $share_url ) . '" data-layout="button_count"></div>';
1107
			/**
1108
			 * Filter the output of the Facebook Sharing button.
1109
			 *
1110
			 * @module sharedaddy
1111
			 *
1112
			 * @since 3.6.0
1113
			 *
1114
			 * @param string $fb_share_html Facebook Sharing button HTML.
1115
			 * @param string $share_url URL of the post to share.
1116
			 */
1117
			return apply_filters( 'jetpack_sharing_facebook_official_button_output', $fb_share_html, $share_url );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $share_url.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
1118
		}
1119
1120
		/** This filter is already documented in modules/sharedaddy/sharing-sources.php */
1121
		if ( apply_filters( 'jetpack_register_post_for_share_counts', true, $post->ID, 'facebook' ) ) {
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $post->ID.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
1122
			sharing_register_post_for_share_counts( $post->ID );
1123
		}
1124
		return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Facebook', 'share to', 'jetpack' ), __( 'Click to share on Facebook', 'jetpack' ), 'share=facebook', 'sharing-facebook-' . $post->ID );
1125
	}
1126
1127
	/**
1128
	 * AMP display for Facebook.
1129
	 *
1130
	 * @param \WP_Post $post The current post being viewed.
1131
	 */
1132
	public function get_amp_display( $post ) {
1133
		$attrs = array(
1134
			/** This filter is documented in modules/sharedaddy/sharing-sources.php */
1135
			'data-param-app_id' => apply_filters( 'jetpack_sharing_facebook_app_id', '249643311490' ),
1136
		);
1137
1138
		return $this->build_amp_markup( $attrs );
1139
	}
1140
1141 View Code Duplication
	public function process_request( $post, array $post_data ) {
1142
		$fb_url = $this->http() . '://www.facebook.com/sharer.php?u=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&t=' . rawurlencode( $this->get_share_title( $post->ID ) );
1143
1144
		// Record stats
1145
		parent::process_request( $post, $post_data );
1146
1147
		// Redirect to Facebook
1148
		wp_redirect( $fb_url );
1149
		die();
1150
	}
1151
1152
	public function display_footer() {
1153
		$this->js_dialog( $this->shortname );
1154
		if ( $this->smart ) {
1155
			$locale = $this->guess_locale_from_lang( get_locale() );
1156
			if ( ! $locale ) {
1157
				$locale = 'en_US';
1158
			}
1159
			/**
1160
			 * Filter the App ID used in the official Facebook Share button.
1161
			 *
1162
			 * @since 3.8.0
1163
			 *
1164
			 * @param int $fb_app_id Facebook App ID. Default to 249643311490 (WordPress.com's App ID).
1165
			 */
1166
			$fb_app_id = apply_filters( 'jetpack_sharing_facebook_app_id', '249643311490' );
1167
			if ( is_numeric( $fb_app_id ) ) {
1168
				$fb_app_id = '&appId=' . $fb_app_id;
1169
			} else {
1170
				$fb_app_id = '';
1171
			}
1172
			?><div id="fb-root"></div>
1173
			<script>(function(d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.src = 'https://connect.facebook.net/<?php echo $locale; ?>/sdk.js#xfbml=1<?php echo $fb_app_id; ?>&version=v2.3'; fjs.parentNode.insertBefore(js, fjs); }(document, 'script', 'facebook-jssdk'));</script>
1174
			<script>
1175
			document.body.addEventListener( 'post-load', function() {
1176
				if ( 'undefined' !== typeof FB ) {
1177
					FB.XFBML.parse();
1178
				}
1179
			} );
1180
			</script>
1181
			<?php
1182
		}
1183
	}
1184
}
1185
1186
class Share_Print extends Sharing_Source {
1187
	public $shortname = 'print';
1188
	public $icon = '\f469';
1189 View Code Duplication
	public function __construct( $id, array $settings ) {
1190
		parent::__construct( $id, $settings );
1191
1192
		if ( 'official' == $this->button_style ) {
1193
			$this->smart = true;
1194
		} else {
1195
			$this->smart = false;
1196
		}
1197
	}
1198
1199
	public function get_name() {
1200
		return __( 'Print', 'jetpack' );
1201
	}
1202
1203
	public function get_display( $post ) {
1204
		return $this->get_link( $this->get_process_request_url( $post->ID ) . ( ( is_single() || is_page() ) ? '#print': '' ), _x( 'Print', 'share to', 'jetpack' ), __( 'Click to print', 'jetpack' ) );
1205
	}
1206
1207
	/**
1208
	 * AMP display for Print.
1209
	 *
1210
	 * @param \WP_Post $post The current post being viewed.
1211
	 */
1212
	public function get_amp_display( $post ) {
1213
		if ( empty( $post ) ) {
1214
			return false;
1215
		}
1216
1217
		return '<button class="amp-social-share print" on="tap:AMP.print">Print</button>';
1218
	}
1219
}
1220
1221
class Share_PressThis extends Sharing_Source {
1222
	public $shortname = 'pressthis';
1223
	public $icon = '\f205';
1224 View Code Duplication
	public function __construct( $id, array $settings ) {
1225
		parent::__construct( $id, $settings );
1226
1227
		if ( 'official' == $this->button_style ) {
1228
			$this->smart = true;
1229
		} else {
1230
			$this->smart = false;
1231
		}
1232
	}
1233
1234
	public function get_name() {
1235
		return __( 'Press This', 'jetpack' );
1236
	}
1237
1238
	public function process_request( $post, array $post_data ) {
1239
		global $current_user;
1240
1241
		$primary_blog = (int) get_user_meta( $current_user->ID, 'primary_blog', true );
1242
		if ( $primary_blog ) {
1243
			$primary_blog_details = get_blog_details( $primary_blog );
1244
		} else {
1245
			$primary_blog_details = false;
1246
		}
1247
1248
		if ( $primary_blog_details ) {
1249
			$blogs = array( $primary_blog_details );
1250
		} elseif ( function_exists( 'get_active_blogs_for_user' ) ) {
1251
			$blogs = get_active_blogs_for_user();
1252
			if ( empty( $blogs ) ) {
1253
				$blogs = get_blogs_of_user( $current_user->ID );
1254
			}
1255
		} else {
1256
			$blogs = get_blogs_of_user( $current_user->ID );
1257
		}
1258
1259
		if ( empty( $blogs ) ) {
1260
			wp_safe_redirect( get_permalink( $post->ID ) );
1261
			die();
1262
		}
1263
1264
		$blog = current( $blogs );
1265
1266
		$args = array(
1267
			'u' => rawurlencode( $this->get_share_url( $post->ID ) ),
1268
			);
1269
1270
		$args[ 'url-scan-submit' ] = 'Scan';
1271
		$args[ '_wpnonce' ]        = wp_create_nonce( 'scan-site' );
1272
1273
		$url = $blog->siteurl . '/wp-admin/press-this.php';
1274
		$url = add_query_arg( $args, $url );
1275
1276
		// Record stats
1277
		parent::process_request( $post, $post_data );
1278
1279
		// Redirect to Press This
1280
		wp_redirect( $url );
1281
		die();
1282
	}
1283
1284
	public function get_display( $post ) {
1285
		return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Press This', 'share to', 'jetpack' ), __( 'Click to Press This!', 'jetpack' ), 'share=press-this' );
1286
	}
1287
1288
	/**
1289
	 * No AMP display for PressThis.
1290
	 *
1291
	 * @param \WP_Post $post The current post being viewed.
1292
	 */
1293
	public function get_amp_display( $post ) { // phpcs:ignore
1294
		return false;
1295
	}
1296
}
1297
1298
class Share_Custom extends Sharing_Advanced_Source {
1299
	private $name;
1300
	private $icon;
1301
	private $url;
1302
	public $smart = true;
1303
	public $shortname;
1304
1305
	public function get_class() {
1306
		return 'custom share-custom-' . sanitize_html_class( strtolower( $this->name ) );
1307
	}
1308
1309
	public function __construct( $id, array $settings ) {
1310
		parent::__construct( $id, $settings );
1311
1312
		$opts = $this->get_options();
0 ignored issues
show
Unused Code introduced by
$opts is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1313
1314
		if ( isset( $settings['name'] ) ) {
1315
			$this->name = $settings['name'];
1316
			$this->shortname = preg_replace( '/[^a-z0-9]*/', '', $settings['name'] );
1317
		}
1318
1319
		if ( isset( $settings['icon'] ) ) {
1320
			$this->icon = $settings['icon'];
1321
1322
			$new_icon = esc_url_raw( wp_specialchars_decode( $this->icon, ENT_QUOTES ) );
1323
			$i = 0;
1324
			while ( $new_icon != $this->icon ) {
1325
				if ( $i > 5 ) {
1326
					$this->icon = false;
1327
					break;
1328
				} else {
1329
					$this->icon = $new_icon;
1330
					$new_icon = esc_url_raw( wp_specialchars_decode( $this->icon, ENT_QUOTES ) );
1331
				}
1332
				$i++;
1333
			}
1334
		}
1335
1336
		if ( isset( $settings['url'] ) ) {
1337
			$this->url = $settings['url'];
1338
		}
1339
	}
1340
1341
	public function get_name() {
1342
		return $this->name;
1343
	}
1344
1345
	public function get_display( $post ) {
1346
		$str = $this->get_link( $this->get_process_request_url( $post->ID ), esc_html( $this->name ), sprintf( __( 'Click to share on %s', 'jetpack' ), esc_attr( $this->name ) ), 'share=' . $this->id );
1347
		return str_replace( '<span>', '<span style="' . esc_attr( 'background-image:url("' . addcslashes( esc_url_raw( $this->icon ), '"' ) . '");' ) . '">', $str );
1348
	}
1349
1350
	/**
1351
	 * No AMP display for custom elements.
1352
	 *
1353
	 * @param \WP_Post $post The current post being viewed.
1354
	 */
1355
	public function get_amp_display( $post ) { // phpcs:ignore
1356
		return false;
1357
	}
1358
1359
	public function process_request( $post, array $post_data ) {
1360
		$url = str_replace( '&amp;', '&', $this->url );
1361
		$url = str_replace( '%post_id%', rawurlencode( $post->ID ), $url );
1362
		$url = str_replace( '%post_url%', rawurlencode( $this->get_share_url( $post->ID ) ), $url );
1363
		$url = str_replace( '%post_full_url%', rawurlencode( get_permalink( $post->ID ) ), $url );
1364
		$url = str_replace( '%post_title%', rawurlencode( $this->get_share_title( $post->ID ) ), $url );
1365
		$url = str_replace( '%home_url%', rawurlencode( home_url() ), $url );
1366
		$url = str_replace( '%post_slug%', rawurlencode( $post->post_name ), $url );
1367
1368
		if ( strpos( $url, '%post_tags%' ) !== false ) {
1369
			$tags	= get_the_tags( $post->ID );
1370
			$tagged = '';
1371
1372
			if ( $tags ) {
1373
				$tagged_raw = array();
1374
				foreach ( $tags as $tag ) {
1375
					$tagged_raw[] = rawurlencode( $tag->name );
1376
				}
1377
1378
				$tagged = implode( ',', $tagged_raw );
1379
			}
1380
1381
			$url = str_replace( '%post_tags%', $tagged, $url );
1382
		}
1383
1384
		if ( strpos( $url, '%post_excerpt%' ) !== false ) {
1385
			$url_excerpt = $post->post_excerpt;
1386
			if ( empty( $url_excerpt ) ) {
1387
				$url_excerpt = $post->post_content;
1388
			}
1389
1390
			$url_excerpt = strip_tags( strip_shortcodes( $url_excerpt ) );
1391
			$url_excerpt = wp_html_excerpt( $url_excerpt, 100 );
1392
			$url_excerpt = rtrim( preg_replace( '/[^ .]*$/', '', $url_excerpt ) );
1393
			$url = str_replace( '%post_excerpt%', rawurlencode( $url_excerpt ), $url );
1394
		}
1395
1396
		// Record stats
1397
		parent::process_request( $post, $post_data );
1398
1399
		// Redirect
1400
		wp_redirect( $url );
1401
		die();
1402
	}
1403
1404
	public function display_options() {
1405
?>
1406
<div class="input">
1407
	<table class="form-table">
1408
		<tbody>
1409
			<tr>
1410
				<th scope="row"><?php _e( 'Label', 'jetpack' ); ?></th>
1411
				<td><input type="text" name="name" value="<?php echo esc_attr( $this->name ); ?>" /></td>
1412
			</tr>
1413
1414
			<tr>
1415
				<th scope="row"><?php _e( 'URL', 'jetpack' ); ?></th>
1416
				<td><input type="text" name="url" value="<?php echo esc_attr( $this->url ); ?>" /></td>
1417
			</tr>
1418
1419
			<tr>
1420
				<th scope="row"><?php _e( 'Icon', 'jetpack' ); ?></th>
1421
				<td><input type="text" name="icon" value="<?php echo esc_attr( $this->icon ); ?>" /></td>
1422
			</tr>
1423
1424
			<tr>
1425
				<th scope="row"></th>
1426
				<td>
1427
					<input class="button-secondary" type="submit" value="<?php esc_attr_e( 'Save', 'jetpack' ); ?>" />
1428
					<a href="#" class="remove"><small><?php _e( 'Remove Service', 'jetpack' ); ?></small></a>
1429
				</td>
1430
			</tr>
1431
		</tbody>
1432
	</table>
1433
</div>
1434
<?php
1435
	}
1436
1437
	public function update_options( array $data ) {
1438
		$name  = trim( wp_html_excerpt( wp_kses( stripslashes( $data['name'] ), array() ), 30 ) );
1439
		$url   = trim( esc_url_raw( $data['url'] ) );
1440
		$icon  = trim( esc_url_raw( $data['icon'] ) );
1441
1442
		if ( $name ) {
1443
			$this->name = $name;
1444
		}
1445
1446
		if ( $url ) {
1447
			$this->url	= $url;
1448
		}
1449
1450
		if ( $icon ) {
1451
			$this->icon = $icon;
1452
		}
1453
	}
1454
1455
	public function get_options() {
1456
		return array(
1457
			'name' => $this->name,
1458
			'icon' => $this->icon,
1459
			'url'  => $this->url,
1460
		);
1461
	}
1462
1463
	public function display_preview( $echo = true, $force_smart = false, $button_style = null ) {
1464
		$opts = $this->get_options();
1465
1466
		$text = '&nbsp;';
1467
		if ( ! $this->smart ) {
1468
			if ( $this->button_style != 'icon' ) {
1469
				$text = $this->get_name();
1470
			}
1471
		}
1472
1473
		$klasses = array( 'share-' . $this->shortname );
1474
1475
		if ( $this->button_style == 'icon' || $this->button_style == 'icon-text' ) {
1476
			$klasses[] = 'share-icon';
1477
		}
1478
1479
		if ( $this->button_style == 'icon' ) {
1480
			$text = '';
1481
			$klasses[] = 'no-text';
1482
		}
1483
1484
		if ( $this->button_style == 'text' ) {
1485
			$klasses[] = 'no-icon';
1486
		}
1487
1488
		$link = sprintf(
1489
			'<a rel="nofollow" class="%s" href="javascript:void(0)" title="%s"><span style="background-image:url(&quot;%s&quot;) !important;background-position:left center;background-repeat:no-repeat;">%s</span></a>',
1490
			implode( ' ', $klasses ),
1491
			$this->get_name(),
1492
			addcslashes( esc_url_raw( $opts['icon'] ), '"' ),
1493
			$text
1494
		);
1495
		?>
1496
		<div class="option option-smart-off">
1497
		<?php echo $link ; ?>
1498
		</div><?php
1499
	}
1500
}
1501
1502
class Share_Tumblr extends Sharing_Source {
1503
	public $shortname = 'tumblr';
1504
	public $icon = '\f214';
1505 View Code Duplication
	public function __construct( $id, array $settings ) {
1506
		parent::__construct( $id, $settings );
1507
		if ( 'official' == $this->button_style ) {
1508
			$this->smart = true;
1509
		} else {
1510
			$this->smart = false;
1511
		}
1512
	}
1513
1514
	public function get_name() {
1515
		return __( 'Tumblr', 'jetpack' );
1516
	}
1517
1518
	public function get_display( $post ) {
1519
		if ( $this->smart ) {
1520
			$target = '';
1521
			if ( true == $this->open_link_in_new ) {
1522
				$target = '_blank';
1523
			}
1524
1525
			/**
1526
			 * If we are looking at a single post, let Tumblr figure out the post type (text, photo, link, quote, chat, or video)
1527
			 * based on the content available on the page.
1528
			 * If we are not looking at a single post, content from other posts can appear on the page and Tumblr will pick that up.
1529
			 * In this case, we want Tumblr to focus on our current post, so we will limit the post type to link, where we can give Tumblr a link to our post.
1530
			 */
1531
			if ( ! is_single() ) {
1532
				$posttype = 'data-posttype="link"';
1533
			} else {
1534
				$posttype = '';
1535
			}
1536
1537
			// Documentation: https://www.tumblr.com/docs/en/share_button
1538
			return sprintf(
1539
				'<a class="tumblr-share-button" target="%1$s" href="%2$s" data-title="%3$s" data-content="%4$s" title="%5$s"%6$s>%5$s</a>',
1540
				$target,
1541
				'https://www.tumblr.com/share',
1542
				$this->get_share_title( $post->ID ),
1543
				$this->get_share_url( $post->ID ),
1544
				__( 'Share on Tumblr', 'jetpack' ),
1545
				$posttype
1546
			);
1547 View Code Duplication
		 } else {
1548
			return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Tumblr', 'share to', 'jetpack' ), __( 'Click to share on Tumblr', 'jetpack' ), 'share=tumblr' );
1549
		}
1550
	}
1551
1552 View Code Duplication
	public function process_request( $post, array $post_data ) {
1553
		// Record stats
1554
		parent::process_request( $post, $post_data );
1555
1556
		// Redirect to Tumblr's sharing endpoint (a la their bookmarklet)
1557
		$url = 'https://www.tumblr.com/share?v=3&u=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&t=' . rawurlencode( $this->get_share_title( $post->ID ) ) . '&s=';
1558
		wp_redirect( $url );
1559
		die();
1560
	}
1561
1562 View Code Duplication
	public function display_footer() {
1563
		if ( $this->smart ) {
1564
			?><script id="tumblr-js" type="text/javascript" src="https://assets.tumblr.com/share-button.js"></script><?php
1565
		} else {
1566
			$this->js_dialog( $this->shortname, array( 'width' => 450, 'height' => 450 ) );
1567
		}
1568
	}
1569
}
1570
1571
class Share_Pinterest extends Sharing_Source {
1572
	public $shortname = 'pinterest';
1573
	public $icon = '\f209';
1574
1575 View Code Duplication
	public function __construct( $id, array $settings ) {
1576
		parent::__construct( $id, $settings );
1577
		if ( 'official' == $this->button_style ) {
1578
			$this->smart = true;
1579
		} else {
1580
			$this->smart = false;
1581
		}
1582
	}
1583
1584
	public function get_name() {
1585
		return __( 'Pinterest', 'jetpack' );
1586
	}
1587
1588
	public function get_image( $post ) {
1589
		if ( class_exists( 'Jetpack_PostImages' ) ) {
1590
			$image = Jetpack_PostImages::get_image( $post->ID, array( 'fallback_to_avatars' => true ) );
1591
			if ( ! empty( $image ) ) {
1592
				return $image['src'];
1593
			}
1594
		}
1595
1596
		/**
1597
		 * Filters the default image used by the Pinterest Pin It share button.
1598
		 *
1599
		 * @module sharedaddy
1600
		 *
1601
		 * @since 3.6.0
1602
		 *
1603
		 * @param string $url Default image URL.
1604
		 */
1605
		return apply_filters( 'jetpack_sharing_pinterest_default_image', 'https://s0.wp.com/i/blank.jpg' );
1606
	}
1607
1608
	public function get_external_url( $post ) {
1609
		$url = 'https://www.pinterest.com/pin/create/button/?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&media=' . rawurlencode( $this->get_image( $post ) ) . '&description=' . rawurlencode( $post->post_title );
1610
1611
		/**
1612
		 * Filters the Pinterest share URL used in sharing button output.
1613
		 *
1614
		 * @module sharedaddy
1615
		 *
1616
		 * @since 3.6.0
1617
		 *
1618
		 * @param string $url Pinterest share URL.
1619
		 */
1620
		return apply_filters( 'jetpack_sharing_pinterest_share_url', $url );
1621
	}
1622
1623
	public function get_widget_type() {
1624
		/**
1625
		 * Filters the Pinterest widget type.
1626
		 *
1627
		 * @see https://business.pinterest.com/en/widget-builder
1628
		 *
1629
		 * @module sharedaddy
1630
		 *
1631
		 * @since 3.6.0
1632
		 *
1633
		 * @param string $type Pinterest widget type. Default of 'buttonPin' for single-image selection. 'buttonBookmark' for multi-image modal.
1634
		 */
1635
		return apply_filters( 'jetpack_sharing_pinterest_widget_type', 'buttonPin' );
1636
	}
1637
1638
	public function get_display( $post ) {
1639
		$display = '';
0 ignored issues
show
Unused Code introduced by
$display is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1640
1641
		if ( $this->smart ) {
1642
			$display = sprintf(
1643
				'<div class="pinterest_button"><a href="%s" data-pin-do="%s" data-pin-config="beside"><img src="//assets.pinterest.com/images/pidgets/pinit_fg_en_rect_gray_20.png" /></a></div>',
1644
				esc_url( $this->get_external_url( $post ) ),
1645
				esc_attr( $this->get_widget_type() )
1646
			);
1647 View Code Duplication
		} else {
1648
			$display = $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Pinterest', 'share to', 'jetpack' ), __( 'Click to share on Pinterest', 'jetpack' ), 'share=pinterest', 'sharing-pinterest-' . $post->ID );
1649
		}
1650
1651
		/** This filter is already documented in modules/sharedaddy/sharing-sources.php */
1652
		if ( apply_filters( 'jetpack_register_post_for_share_counts', true, $post->ID, 'linkedin' ) ) {
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $post->ID.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
1653
			sharing_register_post_for_share_counts( $post->ID );
1654
		}
1655
1656
		return $display;
1657
	}
1658
1659
	public function process_request( $post, array $post_data ) {
1660
		// Record stats
1661
		parent::process_request( $post, $post_data );
1662
		// If we're triggering the multi-select panel, then we don't need to redirect to Pinterest
1663
		if ( ! isset( $_GET['js_only'] ) ) {
1664
			$pinterest_url = esc_url_raw( $this->get_external_url( $post ) );
1665
			wp_redirect( $pinterest_url );
1666
		} else {
1667
			echo '// share count bumped';
1668
		}
1669
		die();
1670
	}
1671
1672
	public function display_footer() {
1673
		/**
1674
		 * Filter the Pin it button appearing when hovering over images when using the official button style.
1675
		 *
1676
		 * @module sharedaddy
1677
		 *
1678
		 * @since 3.6.0
1679
		 *
1680
		 * @param bool $jetpack_pinit_over True by default, displays the Pin it button when hovering over images.
1681
		 */
1682
		$jetpack_pinit_over = apply_filters( 'jetpack_pinit_over_button', true );
1683
		?>
1684
		<?php if ( $this->smart ) : ?>
1685
			<script type="text/javascript">
1686
				// Pinterest shared resources
1687
				var s = document.createElement("script");
1688
				s.type = "text/javascript";
1689
				s.async = true;
1690
				<?php if ( $jetpack_pinit_over ) {
1691
				echo "s.setAttribute('data-pin-hover', true);";
1692
				} ?>
1693
				s.src = window.location.protocol + "//assets.pinterest.com/js/pinit.js";
1694
				var x = document.getElementsByTagName("script")[0];
1695
				x.parentNode.insertBefore(s, x);
1696
				// if 'Pin it' button has 'counts' make container wider
1697
				jQuery(window).load( function(){ jQuery( 'li.share-pinterest a span:visible' ).closest( '.share-pinterest' ).width( '80px' ); } );
1698
			</script>
1699
		<?php elseif ( 'buttonPin' != $this->get_widget_type() ) : ?>
1700
			<script type="text/javascript">
1701
				jQuery(document).ready( function(){
1702
					jQuery('body').on('click', 'a.share-pinterest', function(e){
1703
						e.preventDefault();
1704
						// Load Pinterest Bookmarklet code
1705
						var s = document.createElement("script");
1706
						s.type = "text/javascript";
1707
						s.src = window.location.protocol + "//assets.pinterest.com/js/pinmarklet.js?r=" + ( Math.random() * 99999999 );
1708
						var x = document.getElementsByTagName("script")[0];
1709
						x.parentNode.insertBefore(s, x);
1710
						// Trigger Stats
1711
						var s = document.createElement("script");
1712
						s.type = "text/javascript";
1713
						s.src = this + ( this.toString().indexOf( '?' ) ? '&' : '?' ) + 'js_only=1';
1714
						var x = document.getElementsByTagName("script")[0];
1715
						x.parentNode.insertBefore(s, x);
1716
					});
1717
				});
1718
			</script>
1719
		<?php endif;
1720
	}
1721
}
1722
1723
class Share_Pocket extends Sharing_Source {
1724
	public $shortname = 'pocket';
1725
	public $icon = '\f224';
1726
1727 View Code Duplication
	public function __construct( $id, array $settings ) {
1728
		parent::__construct( $id, $settings );
1729
1730
		if ( 'official' == $this->button_style ) {
1731
			$this->smart = true;
1732
		} else {
1733
			$this->smart = false;
1734
		}
1735
	}
1736
1737
	public function get_name() {
1738
		return __( 'Pocket', 'jetpack' );
1739
	}
1740
1741 View Code Duplication
	public function process_request( $post, array $post_data ) {
1742
		// Record stats
1743
		parent::process_request( $post, $post_data );
1744
1745
		$pocket_url = esc_url_raw( 'https://getpocket.com/save/?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&title=' . rawurlencode( $this->get_share_title( $post->ID ) ) );
1746
		wp_redirect( $pocket_url );
1747
		exit;
1748
	}
1749
1750
	public function get_display( $post ) {
1751
		if ( $this->smart ) {
1752
			$post_count = 'horizontal';
1753
1754
			$button = '';
1755
			$button .= '<div class="pocket_button">';
1756
			$button .= sprintf( '<a href="https://getpocket.com/save" class="pocket-btn" data-lang="%s" data-save-url="%s" data-pocket-count="%s" >%s</a>', 'en', esc_attr( $this->get_share_url( $post->ID ) ), $post_count, esc_attr__( 'Pocket', 'jetpack' ) );
1757
			$button .= '</div>';
1758
1759
			return $button;
1760 View Code Duplication
		} else {
1761
			return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Pocket', 'share to', 'jetpack' ), __( 'Click to share on Pocket', 'jetpack' ), 'share=pocket' );
1762
		}
1763
1764
	}
1765
1766
	/**
1767
	 * AMP display for Pocket.
1768
	 *
1769
	 * @param \WP_Post $post The current post being viewed.
1770
	 */
1771 View Code Duplication
	public function get_amp_display( $post ) {
1772
		$attrs = array(
1773
			'data-share-endpoint' => esc_url_raw( 'https://getpocket.com/save/?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&title=' . rawurlencode( $this->get_share_title( $post->ID ) ) ),
1774
		);
1775
1776
		return $this->build_amp_markup( $attrs );
1777
	}
1778
1779 View Code Duplication
	function display_footer() {
1780
		if ( $this->smart ) :
1781
		?>
1782
		<script>
1783
		// Don't use Pocket's default JS as it we need to force init new Pocket share buttons loaded via JS.
1784
		function jetpack_sharing_pocket_init() {
1785
			jQuery.getScript( 'https://widgets.getpocket.com/v1/j/btn.js?v=1' );
1786
		}
1787
		jQuery( document ).ready( jetpack_sharing_pocket_init );
1788
		jQuery( document.body ).on( 'post-load', jetpack_sharing_pocket_init );
1789
		</script>
1790
		<?php
1791
		else :
1792
			$this->js_dialog( $this->shortname, array( 'width' => 450, 'height' => 450 ) );
1793
		endif;
1794
1795
	}
1796
1797
}
1798
1799
class Share_Telegram extends Sharing_Source {
1800
	public $shortname = 'telegram';
1801
1802
	public function __construct( $id, array $settings ) {
1803
		parent::__construct( $id, $settings );
1804
	}
1805
1806
	public function get_name() {
1807
		return __( 'Telegram', 'jetpack' );
1808
	}
1809 View Code Duplication
	public function process_request( $post, array $post_data ) {
1810
		// Record stats
1811
		parent::process_request( $post, $post_data );
1812
		$telegram_url = esc_url_raw( 'https://telegram.me/share/url?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&text=' . rawurlencode( $this->get_share_title( $post->ID ) ) );
1813
		wp_redirect( $telegram_url );
1814
		exit;
1815
	}
1816
1817
	public function get_display( $post ) {
1818
		return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Telegram', 'share to', 'jetpack' ), __( 'Click to share on Telegram', 'jetpack' ), 'share=telegram' );
1819
	}
1820
1821
	/**
1822
	 * AMP display for Telegram.
1823
	 *
1824
	 * @param \WP_Post $post The current post being viewed.
1825
	 */
1826 View Code Duplication
	public function get_amp_display( $post ) {
1827
		$attrs = array(
1828
			'data-share-endpoint' => esc_url_raw( 'https://telegram.me/share/url?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&text=' . rawurlencode( $this->get_share_title( $post->ID ) ) ),
1829
		);
1830
1831
		return $this->build_amp_markup( $attrs );
1832
	}
1833
1834
	function display_footer() {
1835
		$this->js_dialog( $this->shortname, array( 'width' => 450, 'height' => 450 ) );
1836
	}
1837
}
1838
1839
class Jetpack_Share_WhatsApp extends Sharing_Source {
1840
	public $shortname = 'jetpack-whatsapp';
1841
1842
	public function __construct( $id, array $settings ) {
1843
		parent::__construct( $id, $settings );
1844
	}
1845
1846
	public function get_name() {
1847
		return __( 'WhatsApp', 'jetpack' );
1848
	}
1849
1850
	public function get_display( $post ) {
1851
		return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'WhatsApp', 'share to', 'jetpack' ), __( 'Click to share on WhatsApp', 'jetpack' ), 'share=jetpack-whatsapp' );
1852
	}
1853
1854
	/**
1855
	 * AMP display for Whatsapp.
1856
	 *
1857
	 * @param \WP_Post $post The current post being viewed.
1858
	 */
1859
	public function get_amp_display( $post ) {
1860
		$attrs = array(
1861
			'type' => 'whatsapp',
1862
		);
1863
1864
		return $this->build_amp_markup( $attrs );
1865
	}
1866
1867
	public function process_request( $post, array $post_data ) {
1868
		// Record stats
1869
		parent::process_request( $post, $post_data );
1870
1871
		// Firefox for desktop doesn't handle the "api.whatsapp.com" URL properly, so use "web.whatsapp.com"
1872
		if ( User_Agent_Info::is_firefox_desktop() ) {
1873
			$url = 'https://web.whatsapp.com/send?text=';
1874
		} else {
1875
			$url = 'https://api.whatsapp.com/send?text=';
1876
		}
1877
1878
		$url .= rawurlencode( $this->get_share_title( $post->ID ) . ' ' . $this->get_share_url( $post->ID ) );
1879
		wp_redirect( $url );
1880
		exit;
1881
	}
1882
}
1883
1884
class Share_Skype extends Sharing_Source {
1885
	public $shortname = 'skype';
1886
	public $icon = '\f220';
1887
	private $share_type = 'default';
1888
1889 View Code Duplication
	public function __construct( $id, array $settings ) {
1890
		parent::__construct( $id, $settings );
1891
1892
		if ( isset( $settings['share_type'] ) ) {
1893
			$this->share_type = $settings['share_type'];
1894
		}
1895
1896
		if ( 'official' == $this->button_style ) {
1897
			$this->smart = true;
1898
		} else {
1899
			$this->smart = false;
1900
		}
1901
1902
	}
1903
1904
	public function get_name() {
1905
		return __( 'Skype', 'jetpack' );
1906
	}
1907
1908
	public function get_display( $post ) {
1909
		if ( $this->smart ) {
1910
			$skype_share_html = sprintf(
1911
				'<div class="skype-share" data-href="%1$s" data-lang="%2$s" data-style="small" data-source="jetpack" ></div>',
1912
				esc_attr( $this->get_share_url( $post->ID ) ),
1913
				'en-US'
1914
			);
1915
			return $skype_share_html;
1916
		}
1917
1918
		/** This filter is already documented in modules/sharedaddy/sharing-sources.php */
1919
		if ( apply_filters( 'jetpack_register_post_for_share_counts', true, $post->ID, 'skype' ) ) {
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $post->ID.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
1920
			sharing_register_post_for_share_counts( $post->ID );
1921
		}
1922
		return $this->get_link(
1923
			$this->get_process_request_url( $post->ID ), _x( 'Skype', 'share to', 'jetpack' ), __( 'Click to share on Skype', 'jetpack' ), 'share=skype', 'sharing-skype-' . $post->ID );
1924
	}
1925
1926
	/**
1927
	 * AMP display for Skype.
1928
	 *
1929
	 * @param \WP_Post $post The current post being viewed.
1930
	 */
1931
	public function get_amp_display( $post ) {
1932
		$attrs = array(
1933
			'data-share-endpoint' => sprintf(
1934
				'https://web.skype.com/share?url=%1$s&lang=%2$s=&source=jetpack',
1935
				rawurlencode( $this->get_share_url( $post->ID ) ),
1936
				'en-US'
1937
			),
1938
		);
1939
1940
		return $this->build_amp_markup( $attrs );
1941
	}
1942
1943 View Code Duplication
	public function process_request( $post, array $post_data ) {
1944
		$skype_url = sprintf(
1945
			'https://web.skype.com/share?url=%1$s&lang=%2$s=&source=jetpack',
1946
			rawurlencode( $this->get_share_url( $post->ID ) ),
1947
			'en-US'
1948
		);
1949
1950
		// Record stats
1951
		parent::process_request( $post, $post_data );
1952
1953
		// Redirect to Skype
1954
		wp_redirect( $skype_url );
1955
		die();
1956
	}
1957
1958 View Code Duplication
	public function display_footer() {
1959
		if ( $this->smart ) :
1960
			?>
1961
			<script>
1962
				(function(r, d, s) {
1963
					r.loadSkypeWebSdkAsync = r.loadSkypeWebSdkAsync || function(p) {
1964
							var js, sjs = d.getElementsByTagName(s)[0];
1965
							if (d.getElementById(p.id)) { return; }
1966
							js = d.createElement(s);
1967
							js.id = p.id;
1968
							js.src = p.scriptToLoad;
1969
							js.onload = p.callback
1970
							sjs.parentNode.insertBefore(js, sjs);
1971
						};
1972
					var p = {
1973
						scriptToLoad: 'https://swx.cdn.skype.com/shared/v/latest/skypewebsdk.js',
1974
						id: 'skype_web_sdk'
1975
					};
1976
					r.loadSkypeWebSdkAsync(p);
1977
				})(window, document, 'script');
1978
			</script>
1979
			<?php
1980
		else :
1981
			$this->js_dialog( $this->shortname, array( 'width' => 305, 'height' => 665 ) );
1982
		endif;
1983
	}
1984
}
1985