Completed
Push — fix/tiled-gallery-amp-mosaic-c... ( b708e7...398dc2 )
by Yaroslav
08:06
created

Sharing_Source   C

Complexity

Total Complexity 54

Size/Duplication

Total Lines 409
Duplicated Lines 3.91 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
dl 16
loc 409
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 16 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
abstract class Sharing_Source {
4
	public	  $button_style;
5
	public	  $smart;
6
	protected $open_link_in_new;
7
	protected $id;
8
9
	public function __construct( $id, array $settings ) {
10
		$this->id = $id;
11
		/**
12
		 * Filter the way sharing links open.
13
		 *
14
		 * By default, sharing links open in a new window.
15
		 *
16
		 * @module sharedaddy
17
		 *
18
		 * @since 3.4.0
19
		 *
20
		 * @param bool true Should Sharing links open in a new window. Default to true.
21
		 */
22
		$this->open_link_in_new = apply_filters( 'jetpack_open_sharing_in_new_window', true );
23
24
		if ( isset( $settings['button_style'] ) ) {
25
			$this->button_style = $settings['button_style'];
26
		}
27
28
		if ( isset( $settings['smart'] ) ) {
29
			$this->smart = $settings['smart'];
30
		}
31
	}
32
33
	public function is_deprecated() {
34
		return false;
35
	}
36
37
	public function http() {
38
		return is_ssl() ? 'https' : 'http';
39
	}
40
41
	public function get_id() {
42
		return $this->id;
43
	}
44
45
	public function get_class() {
46
		return $this->id;
47
	}
48
49
	public function get_share_url( $post_id ) {
50
		/**
51
		 * Filter the sharing permalink.
52
		 *
53
		 * @module sharedaddy
54
		 *
55
		 * @since 1.2.0
56
		 *
57
		 * @param string get_permalink( $post_id ) Post Permalink.
58
		 * @param int $post_id Post ID.
59
		 * @param int $this->id Sharing ID.
60
		 */
61
		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...
62
	}
63
64
	public function get_share_title( $post_id ) {
65
		$post = get_post( $post_id );
66
		/**
67
		 * Filter the sharing title.
68
		 *
69
		 * @module sharedaddy
70
		 *
71
		 * @since 2.8.0
72
		 *
73
		 * @param string $post->post_title Post Title.
74
		 * @param int $post_id Post ID.
75
		 * @param int $this->id Sharing ID.
76
		 */
77
		$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...
78
79
		return html_entity_decode( wp_kses( $title, null ) );
80
	}
81
82
	public function has_custom_button_style() {
83
		return false;
84
	}
85
86
	public function get_link( $url, $text, $title, $query = '', $id = false ) {
87
		$args = func_get_args();
88
		$klasses = array( 'share-' . $this->get_class(), 'sd-button' );
89
90
		if ( 'icon' == $this->button_style || 'icon-text' == $this->button_style ) {
91
			$klasses[] = 'share-icon';
92
		}
93
94
		if ( 'icon' == $this->button_style ) {
95
			$text = $title;
96
			$klasses[] = 'no-text';
97
98
			if ( true == $this->open_link_in_new ) {
99
				$text .= __( ' (Opens in new window)', 'jetpack' );
100
			}
101
		}
102
103
		/**
104
		 * Filter the sharing display ID.
105
		 *
106
		 * @module sharedaddy
107
		 *
108
		 * @since 3.4.0
109
		 *
110
		 * @param int|false $id Sharing ID.
111
		 * @param object $this Sharing service properties.
112
		 * @param array $args Array of sharing service options.
113
		 */
114
		$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...
115
		/**
116
		 * Filter the sharing display link.
117
		 *
118
		 * @module sharedaddy
119
		 *
120
		 * @since 2.8.0
121
		 *
122
		 * @param string $url Post URL.
123
		 * @param object $this Sharing service properties.
124
		 * @param int|false $id Sharing ID.
125
		 * @param array $args Array of sharing service options.
126
		 */
127
		$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...
128
		/**
129
		 * Filter the sharing display link.
130
		 *
131
		 * @module sharedaddy
132
		 *
133
		 * @since 2.8.0
134
		 *
135
		 * @param string $url Post URL.
136
		 * @param object $this Sharing service properties.
137
		 * @param int|false $id Sharing ID.
138
		 * @param array $args Array of sharing service options.
139
		 */
140
		$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...
141
		/**
142
		 * Filter the sharing display query.
143
		 *
144
		 * @module sharedaddy
145
		 *
146
		 * @since 2.8.0
147
		 *
148
		 * @param string $query Sharing service URL parameter.
149
		 * @param object $this Sharing service properties.
150
		 * @param int|false $id Sharing ID.
151
		 * @param array $args Array of sharing service options.
152
		 */
153
		$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...
154
155
		if ( ! empty( $query ) ) {
156
			if ( false === stripos( $url, '?' ) ) {
157
				$url .= '?' . $query;
158
			} else {
159
				$url .= '&amp;' . $query;
160
			}
161
		}
162
163
		if ( 'text' == $this->button_style ) {
164
			$klasses[] = 'no-icon';
165
		}
166
167
		/**
168
		 * Filter the sharing display classes.
169
		 *
170
		 * @module sharedaddy
171
		 *
172
		 * @since 3.4.0
173
		 *
174
		 * @param array $klasses Sharing service classes.
175
		 * @param object $this Sharing service properties.
176
		 * @param int|false $id Sharing ID.
177
		 * @param array $args Array of sharing service options.
178
		 */
179
		$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...
180
		/**
181
		 * Filter the sharing display title.
182
		 *
183
		 * @module sharedaddy
184
		 *
185
		 * @since 3.4.0
186
		 *
187
		 * @param string $title Sharing service title.
188
		 * @param object $this Sharing service properties.
189
		 * @param int|false $id Sharing ID.
190
		 * @param array $args Array of sharing service options.
191
		 */
192
		$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...
193
		/**
194
		 * Filter the sharing display text.
195
		 *
196
		 * @module sharedaddy
197
		 *
198
		 * @since 3.4.0
199
		 *
200
		 * @param string $text Sharing service text.
201
		 * @param object $this Sharing service properties.
202
		 * @param int|false $id Sharing ID.
203
		 * @param array $args Array of sharing service options.
204
		 */
205
		$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...
206
207
		return sprintf(
208
			'<a rel="nofollow%s" data-shared="%s" class="%s" href="%s"%s title="%s"><span%s>%s</span></a>',
209
			( true == $this->open_link_in_new ) ? ' noopener noreferrer' : '',
210
			( $id ? esc_attr( $id ) : '' ),
211
			implode( ' ', $klasses ),
212
			$url,
213
			( true == $this->open_link_in_new ) ? ' target="_blank"' : '',
214
			$title,
215
			( 'icon' == $this->button_style ) ? '></span><span class="sharing-screen-reader-text"' : '',
216
			$text
217
		);
218
	}
219
220
	/**
221
	 * Get an unfiltered post permalink to use when generating a sharing URL with get_link.
222
	 * Use instead of get_share_url for non-official styles as get_permalink ensures that process_request
223
	 * will be executed more reliably, in the case that the filtered URL uses a service that strips query parameters.
224
	 *
225
	 * @since 3.7.0
226
	 * @param int $post_id Post ID.
227
	 * @uses get_permalink
228
	 * @return string get_permalink( $post_id ) Post permalink.
229
	 */
230
	public function get_process_request_url( $post_id ) {
231
		return get_permalink( $post_id );
232
	}
233
234
	abstract public function get_name();
235
	abstract public function get_display( $post );
236
237
	public function display_header() {
238
	}
239
240
	public function display_footer() {
241
	}
242
243
	public function has_advanced_options() {
244
		return false;
245
	}
246
247
	/**
248
	 * Get the AMP specific markup for a sharing button.
249
	 *
250
	 * @param \WP_Post $post The current post being viewed.
251
	 */
252
	public function get_amp_display( $post ) {
253
		// Only display markup if we're on a post.
254
		if ( empty( $post ) ) {
255
			return false;
256
		}
257
258
		return $this->build_amp_markup();
259
	}
260
261
	/**
262
	 * Generates and returns the markup for an AMP sharing button.
263
	 *
264
	 * @param array $attrs Custom attributes for rendering the social icon.
265
	 */
266
	protected function build_amp_markup( $attrs = array() ) {
267
		$attrs        = array_merge(
268
			array(
269
				'type'   => $this->get_id(),
270
				'height' => '32px',
271
				'width'  => '32px',
272
			),
273
			$attrs
274
		);
275
		$sharing_link = '<amp-social-share';
276
		foreach ( $attrs as $key => $value ) {
277
			$sharing_link .= sprintf( ' %s="%s"', sanitize_key( $key ), esc_attr( $value ) );
278
		}
279
		$sharing_link .= '></amp-social-share>';
280
		return $sharing_link;
281
	}
282
283
	public function display_preview( $echo = true, $force_smart = false, $button_style = null ) {
284
		$text = '&nbsp;';
285
		$button_style = ( ! empty( $button_style ) ) ? $button_style : $this->button_style;
286
		if ( ! $this->smart && ! $force_smart ) {
287
			if ( $button_style != 'icon' ) {
288
				$text = $this->get_name();
289
			}
290
		}
291
292
		$klasses = array( 'share-' . $this->get_class(), 'sd-button' );
293
294
		if ( $button_style == 'icon' || $button_style == 'icon-text' ) {
295
			$klasses[] = 'share-icon';
296
		}
297
298
		if ( $button_style == 'icon' ) {
299
			$klasses[] = 'no-text';
300
		}
301
302
		if ( $button_style == 'text' ) {
303
			$klasses[] = 'no-icon';
304
		}
305
306
		$is_deprecated = $this->is_deprecated();
307
308
		$link = sprintf(
309
			'<a rel="nofollow" class="%s" href="javascript:void(0)" title="%s"><span>%s</span></a>',
310
			implode( ' ', $klasses ),
311
			esc_attr(
312
				$is_deprecated
313
					/* translators: %1$s is the name of a deprecated Sharing Service like "Google+" */
314
					? 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() )
315
					: $this->get_name()
316
			),
317
			esc_html(
318
				$is_deprecated
319
					/* translators: %1$s is the name of a deprecated Sharing Service like "Google+" */
320
					? sprintf( __( '%1$s has shut down', 'jetpack' ), $this->get_name() )
321
					: $text
322
			)
323
		);
324
325
		$smart = ( $this->smart || $force_smart ) ? 'on' : 'off';
326
		$return = "<div class='option option-smart-$smart'>$link</div>";
327
		if ( $echo ) {
328
			echo $return;
329
		}
330
331
		return $return;
332
	}
333
334
	public function get_total( $post = false ) {
335
		global $wpdb, $blog_id;
336
337
		$name = strtolower( $this->get_id() );
338
339
		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...
340
			// get total number of shares for service
341
			return (int) $wpdb->get_var( $wpdb->prepare( 'SELECT SUM( count ) FROM sharing_stats WHERE blog_id = %d AND share_service = %s', $blog_id, $name ) );
342
		}
343
344
		// get total shares for a post
345
		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 ) );
346
	}
347
348 View Code Duplication
	public function get_posts_total() {
349
		global $wpdb, $blog_id;
350
351
		$totals = array();
352
		$name	= strtolower( $this->get_id() );
353
354
		$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 ) );
355
356
		if ( ! empty( $my_data ) ) {
357
			foreach ( $my_data as $row ) {
358
				$totals[] = new Sharing_Post_Total( $row->id, $row->total );
359
			}
360
		}
361
362
		usort( $totals, array( 'Sharing_Post_Total', 'cmp' ) );
363
364
		return $totals;
365
	}
366
367
	public function process_request( $post, array $post_data ) {
368
		/**
369
		 * Fires when a post is shared via one of the sharing buttons.
370
		 *
371
		 * @module sharedaddy
372
		 *
373
		 * @since 1.1.0
374
		 *
375
		 * @param array $args Aray of information about the sharing service.
376
		 */
377
		do_action( 'sharing_bump_stats', array( 'service' => $this, 'post' => $post ) );
378
	}
379
380
	public function js_dialog( $name, $params = array() ) {
381
		if ( true !== $this->open_link_in_new ) {
382
			return;
383
		}
384
385
		$defaults = array(
386
			'menubar'	=> 1,
387
			'resizable' => 1,
388
			'width'		=> 600,
389
			'height'	=> 400,
390
		);
391
		$params = array_merge( $defaults, $params );
392
		$opts = array();
393
		foreach ( $params as $key => $val ) {
394
			$opts[] = "$key=$val";
395
		}
396
		$opts = implode( ',', $opts );
397
398
		// Add JS after sharing-js has been enqueued.
399
		wp_add_inline_script( 'sharing-js',
400
			"var windowOpen;
401
			jQuery( document.body ).on( 'click', 'a.share-$name', function() {
402
				// If there's another sharing window open, close it.
403
				if ( 'undefined' !== typeof windowOpen ) {
404
					windowOpen.close();
405
				}
406
				windowOpen = window.open( jQuery( this ).attr( 'href' ), 'wpcom$name', '$opts' );
407
				return false;
408
			});"
409
		);
410
	}
411
}
412
413
abstract class Deprecated_Sharing_Source extends Sharing_Source {
414
	public	  $button_style = 'text';
415
	public	  $smart = false;
416
	protected $open_link_in_new = false;
417
	protected $id;
418
	protected $deprecated = true;
419
420
	final public function __construct( $id, array $settings ) {
421
		$this->id = $id;
422
423
		if ( isset( $settings['button_style'] ) ) {
424
			$this->button_style = $settings['button_style'];
425
		}
426
	}
427
428
	final public function is_deprecated() {
429
		return true;
430
	}
431
432
	final public function get_share_url( $post_id ) {
433
		return get_permalink( $post_id );
434
	}
435
436
	/**
437
	 * No AMP display for deprecated sources.
438
	 *
439
	 * @param \WP_Post $post The current post being viewed.
440
	 */
441
	final public function get_amp_display( $post ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
442
		return false;
443
	}
444
445
	final public function display_preview( $echo = true, $force_smart = false, $button_style = null ) {
446
		return parent::display_preview( $echo, false, $button_style );
447
	}
448
449
	final public function get_total( $post = false ) {
450
		return 0;
451
	}
452
453
	final public function get_posts_total() {
454
		return 0;
455
	}
456
457
	final public function process_request( $post, array $post_data ) {
458
		parent::process_request( $post, $post_data );
459
	}
460
461
	final public function get_display( $post ) {
462
		if ( current_user_can( 'manage_options' ) ) {
463
			return $this->display_deprecated( $post );
464
		}
465
466
		return '';
467
	}
468
469
	public function display_deprecated( $post ) {
470
		return $this->get_link(
471
			$this->get_share_url( $post->ID ),
472
			/* translators: %1$s is the name of a deprecated Sharing Service like "Google+" */
473
			sprintf( __( '%1$s has shut down', 'jetpack' ), $this->get_name() ),
474
			/* translators: %1$s is the name of a deprecated Sharing Service like "Google+" */
475
			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() )
476
		);
477
	}
478
}
479
480
abstract class Sharing_Advanced_Source extends Sharing_Source {
481
	public function has_advanced_options() {
482
		return true;
483
	}
484
485
	abstract public function display_options();
486
	abstract public function update_options( array $data );
487
	abstract public function get_options();
488
}
489
490
class Share_Email extends Sharing_Source {
491
	public $shortname = 'email';
492
	public $icon = '\f410';
493 View Code Duplication
	public function __construct( $id, array $settings ) {
494
		parent::__construct( $id, $settings );
495
496
		if ( 'official' == $this->button_style ) {
497
			$this->smart = true;
498
		} else {
499
			$this->smart = false;
500
		}
501
	}
502
503
	public function get_name() {
504
		return _x( 'Email', 'as sharing source', 'jetpack' );
505
	}
506
507
	// Default does nothing
508
	public function process_request( $post, array $post_data ) {
509
		$ajax = false;
510
		if ( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && strtolower( $_SERVER['HTTP_X_REQUESTED_WITH'] ) == 'xmlhttprequest' ) {
511
			$ajax = true;
512
		}
513
514
		$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...
515
516
		if ( isset( $post_data['source_email'] ) && is_email( $post_data['source_email'] ) ) {
517
			$source_email = $post_data['source_email'];
518
		}
519
520
		if ( isset( $post_data['target_email'] ) && is_email( $post_data['target_email'] ) ) {
521
			$target_email = $post_data['target_email'];
522
		}
523
524
		if ( isset( $post_data['source_name'] ) && strlen( $post_data['source_name'] ) < 200 ) {
525
			$source_name = $post_data['source_name'];
526
		} elseif ( isset( $post_data['source_name'] ) ) {
527
			$source_name = substr( $post_data['source_name'], 0, 200 );
528
		} else {
529
			$source_name = '';
530
		}
531
532
		// Test email
533
		$error = 1;	  // Failure in data
534
		if ( empty( $post_data['source_f_name'] ) && $source_email && $target_email && $source_name ) {
535
			/**
536
			 * Allow plugins to stop the email sharing button from running the shared message through Akismet.
537
			 *
538
			 * @module sharedaddy
539
			 *
540
			 * @since 1.1.0
541
			 *
542
			 * @param bool true Should we check if the message isn't spam?
543
			 * @param object $post Post information.
544
			 * @param array $post_data Information about the shared message.
545
			 */
546
			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...
547
				$data = array(
548
					'post'           => $post,
549
					'source'         => $source_email,
550
					'target'         => $target_email,
551
					'name'           => $source_name,
552
					'sharing_source' => $this,
553
				);
554
				// todo: implement an error message when email doesn't get sent.
555
				/**
556
				 * Filter whether an email can be sent from the Email sharing button.
557
				 *
558
				 * @module sharedaddy
559
				 *
560
				 * @since 1.1.0
561
				 *
562
				 * @param array $data Array of information about the shared message.
563
				 */
564
				if ( ( $data = apply_filters( 'sharing_email_can_send', $data ) ) !== false ) {
565
					// Record stats
566
					parent::process_request( $data['post'], $post_data );
567
568
					/**
569
					 * Fires when an email is sent via the Email sharing button.
570
					 *
571
					 * @module sharedaddy
572
					 *
573
					 * @since 1.1.0
574
					 *
575
					 * @param array $data Array of information about the shared message.
576
					 */
577
					do_action( 'sharing_email_send_post', $data );
578
				}
579
580
				// Return a positive regardless of whether the user is subscribed or not
581
				if ( $ajax ) {
582
?>
583
<div class="response">
584
	<div class="response-title"><?php _e( 'This post has been shared!', 'jetpack' ); ?></div>
585
	<div class="response-sub"><?php printf( __( 'You have shared this post with %s', 'jetpack' ), esc_html( $target_email ) ); ?></div>
586
	<div class="response-close"><a href="#" class="sharing_cancel"><?php _e( 'Close', 'jetpack' ); ?></a></div>
587
</div>
588
<?php
589
				} else {
590
					wp_safe_redirect( get_permalink( $post->ID ) . '?shared=email' );
591
				}
592
593
				die();
594
			} else {
595
				$error = 2;	  // Email check failed
596
			}
597
		}
598
599
		if ( $ajax ) {
600
			echo $error;
601
		} else {
602
			wp_safe_redirect( get_permalink( $post->ID ) . '?shared=email&msg=fail' );
603
		}
604
605
		die();
606
	}
607
608
	public function get_display( $post ) {
609
		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' );
610
	}
611
612
	/**
613
	 * No AMP display for email.
614
	 *
615
	 * @param \WP_Post $post The current post being viewed.
616
	 */
617
	public function get_amp_display( $post ) { // phpcs:ignore
618
		return false;
619
	}
620
621
	/**
622
	 * Outputs the hidden email dialog
623
	 */
624
	public function display_footer() {
625
		global $current_user;
626
627
		$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...
628
?>
629
	<div id="sharing_email" style="display: none;">
630
		<form action="<?php echo esc_url( $_SERVER['REQUEST_URI'] ); ?>" method="post">
631
			<label for="target_email"><?php _e( 'Send to Email Address', 'jetpack' ) ?></label>
632
			<input type="email" name="target_email" id="target_email" value="" />
633
634
			<?php if ( is_user_logged_in() ) : ?>
635
				<input type="hidden" name="source_name" value="<?php echo esc_attr( $current_user->display_name ); ?>" />
636
				<input type="hidden" name="source_email" value="<?php echo esc_attr( $current_user->user_email ); ?>" />
637
			<?php else : ?>
638
639
				<label for="source_name"><?php _e( 'Your Name', 'jetpack' ) ?></label>
640
				<input type="text" name="source_name" id="source_name" value="" />
641
642
				<label for="source_email"><?php _e( 'Your Email Address', 'jetpack' ) ?></label>
643
				<input type="email" name="source_email" id="source_email" value="" />
644
645
			<?php endif; ?>
646
			<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' ); ?>" />
647
			<?php
648
				/**
649
				 * Fires when the Email sharing dialog is loaded.
650
				 *
651
				 * @module sharedaddy
652
				 *
653
				 * @since 1.1.0
654
				 *
655
				 * @param string jetpack Eail sharing source.
656
				 */
657
				do_action( 'sharing_email_dialog', 'jetpack' );
658
			?>
659
660
			<img style="float: right; display: none" class="loading" src="<?php
661
			/** This filter is documented in modules/stats.php */
662
			echo apply_filters( 'jetpack_static_url', plugin_dir_url( __FILE__ ) . 'images/loading.gif' ); ?>" alt="loading" width="16" height="16" />
663
			<input type="submit" value="<?php esc_attr_e( 'Send Email', 'jetpack' ); ?>" class="sharing_send" />
664
			<a rel="nofollow" href="#cancel" class="sharing_cancel" role="button"><?php _e( 'Cancel', 'jetpack' ); ?></a>
665
666
			<div class="errors errors-1" style="display: none;">
667
				<?php _e( 'Post was not sent - check your email addresses!', 'jetpack' ); ?>
668
			</div>
669
670
			<div class="errors errors-2" style="display: none;">
671
				<?php _e( 'Email check failed, please try again', 'jetpack' ); ?>
672
			</div>
673
674
			<div class="errors errors-3" style="display: none;">
675
				<?php _e( 'Sorry, your blog cannot share posts by email.', 'jetpack' ); ?>
676
			</div>
677
		</form>
678
	</div>
679
<?php
680
	}
681
}
682
683
class Share_Twitter extends Sharing_Source {
684
	public $shortname = 'twitter';
685
	public $icon = '\f202';
686
	// 'https://dev.twitter.com/rest/reference/get/help/configuration' ( 2015/02/06 ) short_url_length is 22, short_url_length_https is 23
687
	public $short_url_length = 24;
688
689 View Code Duplication
	public function __construct( $id, array $settings ) {
690
		parent::__construct( $id, $settings );
691
692
		if ( 'official' == $this->button_style ) {
693
			$this->smart = true;
694
		} else {
695
			$this->smart = false;
696
		}
697
	}
698
699
	public function get_name() {
700
		return __( 'Twitter', 'jetpack' );
701
	}
702
703
	/**
704
	 * Determine the Twitter 'via' value for a post.
705
	 *
706
	 * @param  WP_Post|int $post Post object or post ID.
707
	 * @return string Twitter handle without the preceding @.
708
	 **/
709
	public static function sharing_twitter_via( $post ) {
710
		$post = get_post( $post );
711
		/**
712
		 * Allow third-party plugins to customize the Twitter username used as "twitter:site" Twitter Card Meta Tag.
713
		 *
714
		 * @module sharedaddy
715
		 *
716
		 * @since 3.0.0
717
		 *
718
		 * @param string $string Twitter Username.
719
		 * @param array $args Array of Open Graph Meta Tags and Twitter Cards tags.
720
		 */
721
		$twitter_site_tag_value = apply_filters(
722
			'jetpack_twitter_cards_site_tag',
723
			'',
724
			/** This action is documented in modules/sharedaddy/sharing-sources.php */
725
			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...
726
		);
727
728
		/*
729
		 * Hack to remove the unwanted behavior of adding 'via @jetpack' which
730
		 * was introduced with the adding of the Twitter cards.
731
		 * This should be a temporary solution until a better method is setup.
732
		 */
733
		if ( 'jetpack' == $twitter_site_tag_value ) {
734
			$twitter_site_tag_value = '';
735
		}
736
737
		/**
738
		 * Filters the Twitter username used as "via" in the Twitter sharing button.
739
		 *
740
		 * @module sharedaddy
741
		 *
742
		 * @since 1.7.0
743
		 *
744
		 * @param string $twitter_site_tag_value Twitter Username.
745
		 * @param int $post->ID Post ID.
746
		 */
747
		$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...
748
749
		// Strip out anything other than a letter, number, or underscore.
750
		// This will prevent the inadvertent inclusion of an extra @, as well as normalizing the handle.
751
		return preg_replace( '/[^\da-z_]+/i', '', $twitter_site_tag_value );
752
	}
753
754
	/**
755
	 * Determine the 'related' Twitter accounts for a post.
756
	 *
757
	 * @param  WP_Post|int $post Post object or post ID.
758
	 * @return string Comma-separated list of Twitter handles.
759
	 **/
760
	public static function get_related_accounts( $post ) {
761
		$post = get_post( $post );
762
		/**
763
		 * Filter the list of related Twitter accounts added to the Twitter sharing button.
764
		 *
765
		 * @module sharedaddy
766
		 *
767
		 * @since 1.7.0
768
		 *
769
		 * @param array $args Array of Twitter usernames. Format is 'username' => 'Optional description'
770
		 * @param int $post->ID Post ID.
771
		 */
772
		$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...
773
774
		// Example related string: account1,account2:Account 2 description,account3
775
		$related = array();
776
777
		foreach ( $related_accounts as $related_account_username => $related_account_description ) {
778
			// Join the description onto the end of the username
779
			if ( $related_account_description ) {
780
				$related_account_username .= ':' . $related_account_description;
781
			}
782
783
			$related[] = $related_account_username;
784
		}
785
786
		return implode( ',', $related );
787
	}
788
789
	public function get_display( $post ) {
790
		$via = $this->sharing_twitter_via( $post );
791
792
		if ( $via ) {
793
			$via = 'data-via="' . esc_attr( $via ) . '"';
794
		} else {
795
			$via = '';
796
		}
797
798
		$related = $this->get_related_accounts( $post );
799
		if ( ! empty( $related ) && $related !== $via ) {
800
			$related = 'data-related="' . esc_attr( $related ) . '"';
801
		} else {
802
			$related = '';
803
		}
804
805
		if ( $this->smart ) {
806
			$share_url = $this->get_share_url( $post->ID );
807
			$post_title = $this->get_share_title( $post->ID );
808
			return sprintf(
809
				'<a href="https://twitter.com/share" class="twitter-share-button" data-url="%1$s" data-text="%2$s" %3$s %4$s>Tweet</a>',
810
				esc_url( $share_url ),
811
				esc_attr( $post_title ),
812
				$via,
813
				$related
814
			);
815
		} else {
816
			if (
817
				/**
818
				 * Allow plugins to disable sharing counts for specific sharing services.
819
				 *
820
				 * @module sharedaddy
821
				 *
822
				 * @since 3.0.0
823
				 *
824
				 * @param bool true Should sharing counts be enabled for this specific service. Default to true.
825
				 * @param int $post->ID Post ID.
826
				 * @param string $str Sharing service name.
827
				 */
828
				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...
829
			) {
830
				sharing_register_post_for_share_counts( $post->ID );
831
			}
832
			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 );
833
		}
834
	}
835
836
	public function process_request( $post, array $post_data ) {
837
		$post_title = $this->get_share_title( $post->ID );
838
		$post_link = $this->get_share_url( $post->ID );
839
840
		if ( function_exists( 'mb_stripos' ) ) {
841
			$strlen = 'mb_strlen';
842
			$substr = 'mb_substr';
843
		} else {
844
			$strlen = 'strlen';
845
			$substr = 'substr';
846
		}
847
848
		$via = $this->sharing_twitter_via( $post );
849
		$related = $this->get_related_accounts( $post );
850
		if ( $via ) {
851
			$sig = " via @$via";
852
			if ( $related === $via ) {
853
				$related = false;
854
			}
855
		} else {
856
			$via = false;
857
			$sig = '';
858
		}
859
860
		$suffix_length = $this->short_url_length + $strlen( $sig );
861
		// $sig is handled by twitter in their 'via' argument.
862
		// $post_link is handled by twitter in their 'url' argument.
863
		if ( 280 < $strlen( $post_title ) + $suffix_length ) {
864
			// The -1 is for "\xE2\x80\xA6", a UTF-8 ellipsis.
865
			$text = $substr( $post_title, 0, 280 - $suffix_length - 1 ) . "\xE2\x80\xA6";
866
		} else {
867
			$text = $post_title;
868
		}
869
870
		// Record stats
871
		parent::process_request( $post, $post_data );
872
873
		$url = $post_link;
874
		$twitter_url = add_query_arg(
875
			rawurlencode_deep( array_filter( compact( 'via', 'related', 'text', 'url' ) ) ),
876
			'https://twitter.com/intent/tweet'
877
		);
878
879
		// Redirect to Twitter
880
		wp_redirect( $twitter_url );
881
		die();
882
	}
883
884
	public function has_custom_button_style() {
885
		return $this->smart;
886
	}
887
888
	public function display_footer() {
889
		if ( $this->smart ) {
890
			?>
891
			<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>
892
			<?php
893
		} else {
894
			$this->js_dialog( $this->shortname, array( 'height' => 350 ) );
895
		}
896
	}
897
}
898
899
900
class Share_Reddit extends Sharing_Source {
901
	public $shortname = 'reddit';
902
	public $icon = '\f222';
903 View Code Duplication
	public function __construct( $id, array $settings ) {
904
		parent::__construct( $id, $settings );
905
906
		if ( 'official' == $this->button_style ) {
907
			$this->smart = true;
908
		} else {
909
			$this->smart = false;
910
		}
911
	}
912
913
	public function get_name() {
914
		return __( 'Reddit', 'jetpack' );
915
	}
916
917
	public function get_display( $post ) {
918
		if ( $this->smart ) {
919
			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>';
920 View Code Duplication
		} else {
921
			return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Reddit', 'share to', 'jetpack' ), __( 'Click to share on Reddit', 'jetpack' ), 'share=reddit' );
922
		}
923
	}
924
925
	/**
926
	 * AMP display for Reddit.
927
	 *
928
	 * @param \WP_Post $post The current post being viewed.
929
	 */
930 View Code Duplication
	public function get_amp_display( $post ) {
931
		$attrs = array(
932
			'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 ) ) ),
933
		);
934
935
		return $this->build_amp_markup( $attrs );
936
	}
937
938 View Code Duplication
	public function process_request( $post, array $post_data ) {
939
		$reddit_url = $this->http() . '://reddit.com/submit?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&title=' . rawurlencode( $this->get_share_title( $post->ID ) );
940
941
		// Record stats
942
		parent::process_request( $post, $post_data );
943
944
		// Redirect to Reddit
945
		wp_redirect( $reddit_url );
946
		die();
947
	}
948
}
949
950
class Share_LinkedIn extends Sharing_Source {
951
	public $shortname = 'linkedin';
952
	public $icon = '\f207';
953 View Code Duplication
	public function __construct( $id, array $settings ) {
954
		parent::__construct( $id, $settings );
955
956
		if ( 'official' == $this->button_style ) {
957
			$this->smart = true;
958
		} else {
959
			$this->smart = false;
960
		}
961
	}
962
963
	public function get_name() {
964
		return __( 'LinkedIn', 'jetpack' );
965
	}
966
967
	public function has_custom_button_style() {
968
		return $this->smart;
969
	}
970
971
	public function get_display( $post ) {
972
		$display = '';
973
974
		if ( $this->smart ) {
975
			$share_url = $this->get_share_url( $post->ID );
976
			$display .= sprintf( '<div class="linkedin_button"><script type="in/share" data-url="%s" data-counter="right"></script></div>', esc_url( $share_url ) );
977 View Code Duplication
		} else {
978
			$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 );
979
		}
980
981
		/** This filter is already documented in modules/sharedaddy/sharing-sources.php */
982
		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...
983
			sharing_register_post_for_share_counts( $post->ID );
984
		}
985
986
		return $display;
987
	}
988
989 View Code Duplication
	public function process_request( $post, array $post_data ) {
990
991
		$post_link = $this->get_share_url( $post->ID );
992
993
		// Using the same URL as the official button, which is *not* LinkedIn's documented sharing link
994
		// https://www.linkedin.com/cws/share?url={url}&token=&isFramed=false
995
		$linkedin_url = add_query_arg( array(
996
			'url' => rawurlencode( $post_link ),
997
		), 'https://www.linkedin.com/cws/share?token=&isFramed=false' );
998
999
		// Record stats
1000
		parent::process_request( $post, $post_data );
1001
1002
		// Redirect to LinkedIn
1003
		wp_redirect( $linkedin_url );
1004
		die();
1005
	}
1006
1007 View Code Duplication
	public function display_footer() {
1008
		if ( ! $this->smart ) {
1009
			$this->js_dialog( $this->shortname, array( 'width' => 580, 'height' => 450 ) );
1010
		} else {
1011
			?><script type="text/javascript">
1012
			jQuery( document ).ready( function() {
1013
				jQuery.getScript( 'https://platform.linkedin.com/in.js?async=true', function success() {
1014
					IN.init();
1015
				});
1016
			});
1017
			jQuery( document.body ).on( 'post-load', function() {
1018
				if ( typeof IN != 'undefined' )
1019
					IN.parse();
1020
			});
1021
			</script><?php
1022
		}
1023
	}
1024
}
1025
1026
class Share_Facebook extends Sharing_Source {
1027
	public $shortname = 'facebook';
1028
	public $icon = '\f204';
1029
	private $share_type = 'default';
1030
1031 View Code Duplication
	public function __construct( $id, array $settings ) {
1032
		parent::__construct( $id, $settings );
1033
1034
		if ( isset( $settings['share_type'] ) ) {
1035
			$this->share_type = $settings['share_type'];
1036
		}
1037
1038
		if ( 'official' == $this->button_style ) {
1039
			$this->smart = true;
1040
		} else {
1041
			$this->smart = false;
1042
		}
1043
	}
1044
1045
	public function get_name() {
1046
		return __( 'Facebook', 'jetpack' );
1047
	}
1048
1049
	public function display_header() {
1050
	}
1051
1052 View Code Duplication
	function guess_locale_from_lang( $lang ) {
1053
		if ( 'en' == $lang || 'en_US' == $lang || ! $lang ) {
1054
			return 'en_US';
1055
		}
1056
1057
		if ( ! class_exists( 'GP_Locales' ) ) {
1058
			if ( ! defined( 'JETPACK__GLOTPRESS_LOCALES_PATH' ) || ! file_exists( JETPACK__GLOTPRESS_LOCALES_PATH ) ) {
1059
				return false;
1060
			}
1061
1062
			require JETPACK__GLOTPRESS_LOCALES_PATH;
1063
		}
1064
1065
		if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
1066
			// WP.com: get_locale() returns 'it'
1067
			$locale = GP_Locales::by_slug( $lang );
1068
		} else {
1069
			// Jetpack: get_locale() returns 'it_IT';
1070
			$locale = GP_Locales::by_field( 'wp_locale', $lang );
1071
		}
1072
1073
		if ( ! $locale ) {
1074
			return false;
1075
		}
1076
1077
		if ( empty( $locale->facebook_locale ) ) {
1078
			if ( empty( $locale->wp_locale ) ) {
1079
				return false;
1080
			} else {
1081
				// Facebook SDK is smart enough to fall back to en_US if a
1082
				// locale isn't supported. Since supported Facebook locales
1083
				// can fall out of sync, we'll attempt to use the known
1084
				// wp_locale value and rely on said fallback.
1085
				return $locale->wp_locale;
1086
			}
1087
		}
1088
1089
		return $locale->facebook_locale;
1090
	}
1091
1092
	public function get_display( $post ) {
1093
		if ( $this->smart ) {
1094
			$share_url = $this->get_share_url( $post->ID );
1095
			$fb_share_html = '<div class="fb-share-button" data-href="' . esc_attr( $share_url ) . '" data-layout="button_count"></div>';
1096
			/**
1097
			 * Filter the output of the Facebook Sharing button.
1098
			 *
1099
			 * @module sharedaddy
1100
			 *
1101
			 * @since 3.6.0
1102
			 *
1103
			 * @param string $fb_share_html Facebook Sharing button HTML.
1104
			 * @param string $share_url URL of the post to share.
1105
			 */
1106
			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...
1107
		}
1108
1109
		/** This filter is already documented in modules/sharedaddy/sharing-sources.php */
1110
		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...
1111
			sharing_register_post_for_share_counts( $post->ID );
1112
		}
1113
		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 );
1114
	}
1115
1116
	/**
1117
	 * AMP display for Facebook.
1118
	 *
1119
	 * @param \WP_Post $post The current post being viewed.
1120
	 */
1121
	public function get_amp_display( $post ) {
1122
		$attrs = array(
1123
			/** This filter is documented in modules/sharedaddy/sharing-sources.php */
1124
			'data-param-app_id' => apply_filters( 'jetpack_sharing_facebook_app_id', '249643311490' ),
1125
		);
1126
1127
		return $this->build_amp_markup( $attrs );
1128
	}
1129
1130 View Code Duplication
	public function process_request( $post, array $post_data ) {
1131
		$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 ) );
1132
1133
		// Record stats
1134
		parent::process_request( $post, $post_data );
1135
1136
		// Redirect to Facebook
1137
		wp_redirect( $fb_url );
1138
		die();
1139
	}
1140
1141
	public function display_footer() {
1142
		$this->js_dialog( $this->shortname );
1143
		if ( $this->smart ) {
1144
			$locale = $this->guess_locale_from_lang( get_locale() );
1145
			if ( ! $locale ) {
1146
				$locale = 'en_US';
1147
			}
1148
			/**
1149
			 * Filter the App ID used in the official Facebook Share button.
1150
			 *
1151
			 * @since 3.8.0
1152
			 *
1153
			 * @param int $fb_app_id Facebook App ID. Default to 249643311490 (WordPress.com's App ID).
1154
			 */
1155
			$fb_app_id = apply_filters( 'jetpack_sharing_facebook_app_id', '249643311490' );
1156
			if ( is_numeric( $fb_app_id ) ) {
1157
				$fb_app_id = '&appId=' . $fb_app_id;
1158
			} else {
1159
				$fb_app_id = '';
1160
			}
1161
			?><div id="fb-root"></div>
1162
			<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>
1163
			<script>
1164
			jQuery( document.body ).on( 'post-load', function() {
1165
				if ( 'undefined' !== typeof FB ) {
1166
					FB.XFBML.parse();
1167
				}
1168
			} );
1169
			</script>
1170
			<?php
1171
		}
1172
	}
1173
}
1174
1175
class Share_Print extends Sharing_Source {
1176
	public $shortname = 'print';
1177
	public $icon = '\f469';
1178 View Code Duplication
	public function __construct( $id, array $settings ) {
1179
		parent::__construct( $id, $settings );
1180
1181
		if ( 'official' == $this->button_style ) {
1182
			$this->smart = true;
1183
		} else {
1184
			$this->smart = false;
1185
		}
1186
	}
1187
1188
	public function get_name() {
1189
		return __( 'Print', 'jetpack' );
1190
	}
1191
1192
	public function get_display( $post ) {
1193
		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' ) );
1194
	}
1195
1196
	/**
1197
	 * AMP display for Print.
1198
	 *
1199
	 * @param \WP_Post $post The current post being viewed.
1200
	 */
1201
	public function get_amp_display( $post ) {
1202
		if ( empty( $post ) ) {
1203
			return false;
1204
		}
1205
1206
		return '<button class="amp-social-share print" on="tap:AMP.print">Print</button>';
1207
	}
1208
}
1209
1210
class Share_PressThis extends Sharing_Source {
1211
	public $shortname = 'pressthis';
1212
	public $icon = '\f205';
1213 View Code Duplication
	public function __construct( $id, array $settings ) {
1214
		parent::__construct( $id, $settings );
1215
1216
		if ( 'official' == $this->button_style ) {
1217
			$this->smart = true;
1218
		} else {
1219
			$this->smart = false;
1220
		}
1221
	}
1222
1223
	public function get_name() {
1224
		return __( 'Press This', 'jetpack' );
1225
	}
1226
1227
	public function process_request( $post, array $post_data ) {
1228
		global $current_user;
1229
1230
		$primary_blog = (int) get_user_meta( $current_user->ID, 'primary_blog', true );
1231
		if ( $primary_blog ) {
1232
			$primary_blog_details = get_blog_details( $primary_blog );
1233
		} else {
1234
			$primary_blog_details = false;
1235
		}
1236
1237
		if ( $primary_blog_details ) {
1238
			$blogs = array( $primary_blog_details );
1239
		} elseif ( function_exists( 'get_active_blogs_for_user' ) ) {
1240
			$blogs = get_active_blogs_for_user();
1241
			if ( empty( $blogs ) ) {
1242
				$blogs = get_blogs_of_user( $current_user->ID );
1243
			}
1244
		} else {
1245
			$blogs = get_blogs_of_user( $current_user->ID );
1246
		}
1247
1248
		if ( empty( $blogs ) ) {
1249
			wp_safe_redirect( get_permalink( $post->ID ) );
1250
			die();
1251
		}
1252
1253
		$blog = current( $blogs );
1254
1255
		$args = array(
1256
			'u' => rawurlencode( $this->get_share_url( $post->ID ) ),
1257
			);
1258
1259
		$args[ 'url-scan-submit' ] = 'Scan';
1260
		$args[ '_wpnonce' ]        = wp_create_nonce( 'scan-site' );
1261
1262
		$url = $blog->siteurl . '/wp-admin/press-this.php';
1263
		$url = add_query_arg( $args, $url );
1264
1265
		// Record stats
1266
		parent::process_request( $post, $post_data );
1267
1268
		// Redirect to Press This
1269
		wp_redirect( $url );
1270
		die();
1271
	}
1272
1273
	public function get_display( $post ) {
1274
		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' );
1275
	}
1276
1277
	/**
1278
	 * No AMP display for PressThis.
1279
	 *
1280
	 * @param \WP_Post $post The current post being viewed.
1281
	 */
1282
	public function get_amp_display( $post ) { // phpcs:ignore
1283
		return false;
1284
	}
1285
}
1286
1287
class Share_Custom extends Sharing_Advanced_Source {
1288
	private $name;
1289
	private $icon;
1290
	private $url;
1291
	public $smart = true;
1292
	public $shortname;
1293
1294
	public function get_class() {
1295
		return 'custom share-custom-' . sanitize_html_class( strtolower( $this->name ) );
1296
	}
1297
1298
	public function __construct( $id, array $settings ) {
1299
		parent::__construct( $id, $settings );
1300
1301
		$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...
1302
1303
		if ( isset( $settings['name'] ) ) {
1304
			$this->name = $settings['name'];
1305
			$this->shortname = preg_replace( '/[^a-z0-9]*/', '', $settings['name'] );
1306
		}
1307
1308
		if ( isset( $settings['icon'] ) ) {
1309
			$this->icon = $settings['icon'];
1310
1311
			$new_icon = esc_url_raw( wp_specialchars_decode( $this->icon, ENT_QUOTES ) );
1312
			$i = 0;
1313
			while ( $new_icon != $this->icon ) {
1314
				if ( $i > 5 ) {
1315
					$this->icon = false;
1316
					break;
1317
				} else {
1318
					$this->icon = $new_icon;
1319
					$new_icon = esc_url_raw( wp_specialchars_decode( $this->icon, ENT_QUOTES ) );
1320
				}
1321
				$i++;
1322
			}
1323
		}
1324
1325
		if ( isset( $settings['url'] ) ) {
1326
			$this->url = $settings['url'];
1327
		}
1328
	}
1329
1330
	public function get_name() {
1331
		return $this->name;
1332
	}
1333
1334
	public function get_display( $post ) {
1335
		$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 );
1336
		return str_replace( '<span>', '<span style="' . esc_attr( 'background-image:url("' . addcslashes( esc_url_raw( $this->icon ), '"' ) . '");' ) . '">', $str );
1337
	}
1338
1339
	/**
1340
	 * No AMP display for custom elements.
1341
	 *
1342
	 * @param \WP_Post $post The current post being viewed.
1343
	 */
1344
	public function get_amp_display( $post ) { // phpcs:ignore
1345
		return false;
1346
	}
1347
1348
	public function process_request( $post, array $post_data ) {
1349
		$url = str_replace( '&amp;', '&', $this->url );
1350
		$url = str_replace( '%post_id%', rawurlencode( $post->ID ), $url );
1351
		$url = str_replace( '%post_url%', rawurlencode( $this->get_share_url( $post->ID ) ), $url );
1352
		$url = str_replace( '%post_full_url%', rawurlencode( get_permalink( $post->ID ) ), $url );
1353
		$url = str_replace( '%post_title%', rawurlencode( $this->get_share_title( $post->ID ) ), $url );
1354
		$url = str_replace( '%home_url%', rawurlencode( home_url() ), $url );
1355
		$url = str_replace( '%post_slug%', rawurlencode( $post->post_name ), $url );
1356
1357
		if ( strpos( $url, '%post_tags%' ) !== false ) {
1358
			$tags	= get_the_tags( $post->ID );
1359
			$tagged = '';
1360
1361
			if ( $tags ) {
1362
				$tagged_raw = array();
1363
				foreach ( $tags as $tag ) {
1364
					$tagged_raw[] = rawurlencode( $tag->name );
1365
				}
1366
1367
				$tagged = implode( ',', $tagged_raw );
1368
			}
1369
1370
			$url = str_replace( '%post_tags%', $tagged, $url );
1371
		}
1372
1373
		if ( strpos( $url, '%post_excerpt%' ) !== false ) {
1374
			$url_excerpt = $post->post_excerpt;
1375
			if ( empty( $url_excerpt ) ) {
1376
				$url_excerpt = $post->post_content;
1377
			}
1378
1379
			$url_excerpt = strip_tags( strip_shortcodes( $url_excerpt ) );
1380
			$url_excerpt = wp_html_excerpt( $url_excerpt, 100 );
1381
			$url_excerpt = rtrim( preg_replace( '/[^ .]*$/', '', $url_excerpt ) );
1382
			$url = str_replace( '%post_excerpt%', rawurlencode( $url_excerpt ), $url );
1383
		}
1384
1385
		// Record stats
1386
		parent::process_request( $post, $post_data );
1387
1388
		// Redirect
1389
		wp_redirect( $url );
1390
		die();
1391
	}
1392
1393
	public function display_options() {
1394
?>
1395
<div class="input">
1396
	<table class="form-table">
1397
		<tbody>
1398
			<tr>
1399
				<th scope="row"><?php _e( 'Label', 'jetpack' ); ?></th>
1400
				<td><input type="text" name="name" value="<?php echo esc_attr( $this->name ); ?>" /></td>
1401
			</tr>
1402
1403
			<tr>
1404
				<th scope="row"><?php _e( 'URL', 'jetpack' ); ?></th>
1405
				<td><input type="text" name="url" value="<?php echo esc_attr( $this->url ); ?>" /></td>
1406
			</tr>
1407
1408
			<tr>
1409
				<th scope="row"><?php _e( 'Icon', 'jetpack' ); ?></th>
1410
				<td><input type="text" name="icon" value="<?php echo esc_attr( $this->icon ); ?>" /></td>
1411
			</tr>
1412
1413
			<tr>
1414
				<th scope="row"></th>
1415
				<td>
1416
					<input class="button-secondary" type="submit" value="<?php esc_attr_e( 'Save', 'jetpack' ); ?>" />
1417
					<a href="#" class="remove"><small><?php _e( 'Remove Service', 'jetpack' ); ?></small></a>
1418
				</td>
1419
			</tr>
1420
		</tbody>
1421
	</table>
1422
</div>
1423
<?php
1424
	}
1425
1426
	public function update_options( array $data ) {
1427
		$name  = trim( wp_html_excerpt( wp_kses( stripslashes( $data['name'] ), array() ), 30 ) );
1428
		$url   = trim( esc_url_raw( $data['url'] ) );
1429
		$icon  = trim( esc_url_raw( $data['icon'] ) );
1430
1431
		if ( $name ) {
1432
			$this->name = $name;
1433
		}
1434
1435
		if ( $url ) {
1436
			$this->url	= $url;
1437
		}
1438
1439
		if ( $icon ) {
1440
			$this->icon = $icon;
1441
		}
1442
	}
1443
1444
	public function get_options() {
1445
		return array(
1446
			'name' => $this->name,
1447
			'icon' => $this->icon,
1448
			'url'  => $this->url,
1449
		);
1450
	}
1451
1452
	public function display_preview( $echo = true, $force_smart = false, $button_style = null ) {
1453
		$opts = $this->get_options();
1454
1455
		$text = '&nbsp;';
1456
		if ( ! $this->smart ) {
1457
			if ( $this->button_style != 'icon' ) {
1458
				$text = $this->get_name();
1459
			}
1460
		}
1461
1462
		$klasses = array( 'share-' . $this->shortname );
1463
1464
		if ( $this->button_style == 'icon' || $this->button_style == 'icon-text' ) {
1465
			$klasses[] = 'share-icon';
1466
		}
1467
1468
		if ( $this->button_style == 'icon' ) {
1469
			$text = '';
1470
			$klasses[] = 'no-text';
1471
		}
1472
1473
		if ( $this->button_style == 'text' ) {
1474
			$klasses[] = 'no-icon';
1475
		}
1476
1477
		$link = sprintf(
1478
			'<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>',
1479
			implode( ' ', $klasses ),
1480
			$this->get_name(),
1481
			addcslashes( esc_url_raw( $opts['icon'] ), '"' ),
1482
			$text
1483
		);
1484
		?>
1485
		<div class="option option-smart-off">
1486
		<?php echo $link ; ?>
1487
		</div><?php
1488
	}
1489
}
1490
1491
class Share_Tumblr extends Sharing_Source {
1492
	public $shortname = 'tumblr';
1493
	public $icon = '\f214';
1494 View Code Duplication
	public function __construct( $id, array $settings ) {
1495
		parent::__construct( $id, $settings );
1496
		if ( 'official' == $this->button_style ) {
1497
			$this->smart = true;
1498
		} else {
1499
			$this->smart = false;
1500
		}
1501
	}
1502
1503
	public function get_name() {
1504
		return __( 'Tumblr', 'jetpack' );
1505
	}
1506
1507
	public function get_display( $post ) {
1508
		if ( $this->smart ) {
1509
			$target = '';
1510
			if ( true == $this->open_link_in_new ) {
1511
				$target = '_blank';
1512
			}
1513
1514
			/**
1515
			 * If we are looking at a single post, let Tumblr figure out the post type (text, photo, link, quote, chat, or video)
1516
			 * based on the content available on the page.
1517
			 * If we are not looking at a single post, content from other posts can appear on the page and Tumblr will pick that up.
1518
			 * 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.
1519
			 */
1520
			if ( ! is_single() ) {
1521
				$posttype = 'data-posttype="link"';
1522
			} else {
1523
				$posttype = '';
1524
			}
1525
1526
			// Documentation: https://www.tumblr.com/docs/en/share_button
1527
			return sprintf(
1528
				'<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>',
1529
				$target,
1530
				'https://www.tumblr.com/share',
1531
				$this->get_share_title( $post->ID ),
1532
				$this->get_share_url( $post->ID ),
1533
				__( 'Share on Tumblr', 'jetpack' ),
1534
				$posttype
1535
			);
1536 View Code Duplication
		 } else {
1537
			return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Tumblr', 'share to', 'jetpack' ), __( 'Click to share on Tumblr', 'jetpack' ), 'share=tumblr' );
1538
		}
1539
	}
1540
1541 View Code Duplication
	public function process_request( $post, array $post_data ) {
1542
		// Record stats
1543
		parent::process_request( $post, $post_data );
1544
1545
		// Redirect to Tumblr's sharing endpoint (a la their bookmarklet)
1546
		$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=';
1547
		wp_redirect( $url );
1548
		die();
1549
	}
1550
1551 View Code Duplication
	public function display_footer() {
1552
		if ( $this->smart ) {
1553
			?><script id="tumblr-js" type="text/javascript" src="https://assets.tumblr.com/share-button.js"></script><?php
1554
		} else {
1555
			$this->js_dialog( $this->shortname, array( 'width' => 450, 'height' => 450 ) );
1556
		}
1557
	}
1558
}
1559
1560
class Share_Pinterest extends Sharing_Source {
1561
	public $shortname = 'pinterest';
1562
	public $icon = '\f209';
1563
1564 View Code Duplication
	public function __construct( $id, array $settings ) {
1565
		parent::__construct( $id, $settings );
1566
		if ( 'official' == $this->button_style ) {
1567
			$this->smart = true;
1568
		} else {
1569
			$this->smart = false;
1570
		}
1571
	}
1572
1573
	public function get_name() {
1574
		return __( 'Pinterest', 'jetpack' );
1575
	}
1576
1577
	public function get_image( $post ) {
1578
		if ( class_exists( 'Jetpack_PostImages' ) ) {
1579
			$image = Jetpack_PostImages::get_image( $post->ID, array( 'fallback_to_avatars' => true ) );
1580
			if ( ! empty( $image ) ) {
1581
				return $image['src'];
1582
			}
1583
		}
1584
1585
		/**
1586
		 * Filters the default image used by the Pinterest Pin It share button.
1587
		 *
1588
		 * @module sharedaddy
1589
		 *
1590
		 * @since 3.6.0
1591
		 *
1592
		 * @param string $url Default image URL.
1593
		 */
1594
		return apply_filters( 'jetpack_sharing_pinterest_default_image', 'https://s0.wp.com/i/blank.jpg' );
1595
	}
1596
1597
	public function get_external_url( $post ) {
1598
		$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 );
1599
1600
		/**
1601
		 * Filters the Pinterest share URL used in sharing button output.
1602
		 *
1603
		 * @module sharedaddy
1604
		 *
1605
		 * @since 3.6.0
1606
		 *
1607
		 * @param string $url Pinterest share URL.
1608
		 */
1609
		return apply_filters( 'jetpack_sharing_pinterest_share_url', $url );
1610
	}
1611
1612
	public function get_widget_type() {
1613
		/**
1614
		 * Filters the Pinterest widget type.
1615
		 *
1616
		 * @see https://business.pinterest.com/en/widget-builder
1617
		 *
1618
		 * @module sharedaddy
1619
		 *
1620
		 * @since 3.6.0
1621
		 *
1622
		 * @param string $type Pinterest widget type. Default of 'buttonPin' for single-image selection. 'buttonBookmark' for multi-image modal.
1623
		 */
1624
		return apply_filters( 'jetpack_sharing_pinterest_widget_type', 'buttonPin' );
1625
	}
1626
1627
	public function get_display( $post ) {
1628
		$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...
1629
1630
		if ( $this->smart ) {
1631
			$display = sprintf(
1632
				'<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>',
1633
				esc_url( $this->get_external_url( $post ) ),
1634
				esc_attr( $this->get_widget_type() )
1635
			);
1636 View Code Duplication
		} else {
1637
			$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 );
1638
		}
1639
1640
		/** This filter is already documented in modules/sharedaddy/sharing-sources.php */
1641
		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...
1642
			sharing_register_post_for_share_counts( $post->ID );
1643
		}
1644
1645
		return $display;
1646
	}
1647
1648
	public function process_request( $post, array $post_data ) {
1649
		// Record stats
1650
		parent::process_request( $post, $post_data );
1651
		// If we're triggering the multi-select panel, then we don't need to redirect to Pinterest
1652
		if ( ! isset( $_GET['js_only'] ) ) {
1653
			$pinterest_url = esc_url_raw( $this->get_external_url( $post ) );
1654
			wp_redirect( $pinterest_url );
1655
		} else {
1656
			echo '// share count bumped';
1657
		}
1658
		die();
1659
	}
1660
1661
	public function display_footer() {
1662
		/**
1663
		 * Filter the Pin it button appearing when hovering over images when using the official button style.
1664
		 *
1665
		 * @module sharedaddy
1666
		 *
1667
		 * @since 3.6.0
1668
		 *
1669
		 * @param bool $jetpack_pinit_over True by default, displays the Pin it button when hovering over images.
1670
		 */
1671
		$jetpack_pinit_over = apply_filters( 'jetpack_pinit_over_button', true );
1672
		?>
1673
		<?php if ( $this->smart ) : ?>
1674
			<script type="text/javascript">
1675
				// Pinterest shared resources
1676
				var s = document.createElement("script");
1677
				s.type = "text/javascript";
1678
				s.async = true;
1679
				<?php if ( $jetpack_pinit_over ) {
1680
				echo "s.setAttribute('data-pin-hover', true);";
1681
				} ?>
1682
				s.src = window.location.protocol + "//assets.pinterest.com/js/pinit.js";
1683
				var x = document.getElementsByTagName("script")[0];
1684
				x.parentNode.insertBefore(s, x);
1685
				// if 'Pin it' button has 'counts' make container wider
1686
				jQuery(window).load( function(){ jQuery( 'li.share-pinterest a span:visible' ).closest( '.share-pinterest' ).width( '80px' ); } );
1687
			</script>
1688
		<?php elseif ( 'buttonPin' != $this->get_widget_type() ) : ?>
1689
			<script type="text/javascript">
1690
				jQuery(document).ready( function(){
1691
					jQuery('body').on('click', 'a.share-pinterest', function(e){
1692
						e.preventDefault();
1693
						// Load Pinterest Bookmarklet code
1694
						var s = document.createElement("script");
1695
						s.type = "text/javascript";
1696
						s.src = window.location.protocol + "//assets.pinterest.com/js/pinmarklet.js?r=" + ( Math.random() * 99999999 );
1697
						var x = document.getElementsByTagName("script")[0];
1698
						x.parentNode.insertBefore(s, x);
1699
						// Trigger Stats
1700
						var s = document.createElement("script");
1701
						s.type = "text/javascript";
1702
						s.src = this + ( this.toString().indexOf( '?' ) ? '&' : '?' ) + 'js_only=1';
1703
						var x = document.getElementsByTagName("script")[0];
1704
						x.parentNode.insertBefore(s, x);
1705
					});
1706
				});
1707
			</script>
1708
		<?php endif;
1709
	}
1710
}
1711
1712
class Share_Pocket extends Sharing_Source {
1713
	public $shortname = 'pocket';
1714
	public $icon = '\f224';
1715
1716 View Code Duplication
	public function __construct( $id, array $settings ) {
1717
		parent::__construct( $id, $settings );
1718
1719
		if ( 'official' == $this->button_style ) {
1720
			$this->smart = true;
1721
		} else {
1722
			$this->smart = false;
1723
		}
1724
	}
1725
1726
	public function get_name() {
1727
		return __( 'Pocket', 'jetpack' );
1728
	}
1729
1730 View Code Duplication
	public function process_request( $post, array $post_data ) {
1731
		// Record stats
1732
		parent::process_request( $post, $post_data );
1733
1734
		$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 ) ) );
1735
		wp_redirect( $pocket_url );
1736
		exit;
1737
	}
1738
1739
	public function get_display( $post ) {
1740
		if ( $this->smart ) {
1741
			$post_count = 'horizontal';
1742
1743
			$button = '';
1744
			$button .= '<div class="pocket_button">';
1745
			$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' ) );
1746
			$button .= '</div>';
1747
1748
			return $button;
1749 View Code Duplication
		} else {
1750
			return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Pocket', 'share to', 'jetpack' ), __( 'Click to share on Pocket', 'jetpack' ), 'share=pocket' );
1751
		}
1752
1753
	}
1754
1755
	/**
1756
	 * AMP display for Pocket.
1757
	 *
1758
	 * @param \WP_Post $post The current post being viewed.
1759
	 */
1760 View Code Duplication
	public function get_amp_display( $post ) {
1761
		$attrs = array(
1762
			'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 ) ) ),
1763
		);
1764
1765
		return $this->build_amp_markup( $attrs );
1766
	}
1767
1768 View Code Duplication
	function display_footer() {
1769
		if ( $this->smart ) :
1770
		?>
1771
		<script>
1772
		// Don't use Pocket's default JS as it we need to force init new Pocket share buttons loaded via JS.
1773
		function jetpack_sharing_pocket_init() {
1774
			jQuery.getScript( 'https://widgets.getpocket.com/v1/j/btn.js?v=1' );
1775
		}
1776
		jQuery( document ).ready( jetpack_sharing_pocket_init );
1777
		jQuery( document.body ).on( 'post-load', jetpack_sharing_pocket_init );
1778
		</script>
1779
		<?php
1780
		else :
1781
			$this->js_dialog( $this->shortname, array( 'width' => 450, 'height' => 450 ) );
1782
		endif;
1783
1784
	}
1785
1786
}
1787
1788
class Share_Telegram extends Sharing_Source {
1789
	public $shortname = 'telegram';
1790
1791
	public function __construct( $id, array $settings ) {
1792
		parent::__construct( $id, $settings );
1793
	}
1794
1795
	public function get_name() {
1796
		return __( 'Telegram', 'jetpack' );
1797
	}
1798 View Code Duplication
	public function process_request( $post, array $post_data ) {
1799
		// Record stats
1800
		parent::process_request( $post, $post_data );
1801
		$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 ) ) );
1802
		wp_redirect( $telegram_url );
1803
		exit;
1804
	}
1805
1806
	public function get_display( $post ) {
1807
		return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Telegram', 'share to', 'jetpack' ), __( 'Click to share on Telegram', 'jetpack' ), 'share=telegram' );
1808
	}
1809
1810
	/**
1811
	 * AMP display for Telegram.
1812
	 *
1813
	 * @param \WP_Post $post The current post being viewed.
1814
	 */
1815 View Code Duplication
	public function get_amp_display( $post ) {
1816
		$attrs = array(
1817
			'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 ) ) ),
1818
		);
1819
1820
		return $this->build_amp_markup( $attrs );
1821
	}
1822
1823
	function display_footer() {
1824
		$this->js_dialog( $this->shortname, array( 'width' => 450, 'height' => 450 ) );
1825
	}
1826
}
1827
1828
class Jetpack_Share_WhatsApp extends Sharing_Source {
1829
	public $shortname = 'jetpack-whatsapp';
1830
1831
	public function __construct( $id, array $settings ) {
1832
		parent::__construct( $id, $settings );
1833
	}
1834
1835
	public function get_name() {
1836
		return __( 'WhatsApp', 'jetpack' );
1837
	}
1838
1839
	public function get_display( $post ) {
1840
		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' );
1841
	}
1842
1843
	/**
1844
	 * AMP display for Whatsapp.
1845
	 *
1846
	 * @param \WP_Post $post The current post being viewed.
1847
	 */
1848
	public function get_amp_display( $post ) {
1849
		$attrs = array(
1850
			'type' => 'whatsapp',
1851
		);
1852
1853
		return $this->build_amp_markup( $attrs );
1854
	}
1855
1856
	public function process_request( $post, array $post_data ) {
1857
		// Record stats
1858
		parent::process_request( $post, $post_data );
1859
1860
		// Firefox for desktop doesn't handle the "api.whatsapp.com" URL properly, so use "web.whatsapp.com"
1861
		if ( Jetpack_User_Agent_Info::is_firefox_desktop() ) {
1862
			$url = 'https://web.whatsapp.com/send?text=';
1863
		} else {
1864
			$url = 'https://api.whatsapp.com/send?text=';
1865
		}
1866
1867
		$url .= rawurlencode( $this->get_share_title( $post->ID ) . ' ' . $this->get_share_url( $post->ID ) );
1868
		wp_redirect( $url );
1869
		exit;
1870
	}
1871
}
1872
1873
class Share_Skype extends Sharing_Source {
1874
	public $shortname = 'skype';
1875
	public $icon = '\f220';
1876
	private $share_type = 'default';
1877
1878 View Code Duplication
	public function __construct( $id, array $settings ) {
1879
		parent::__construct( $id, $settings );
1880
1881
		if ( isset( $settings['share_type'] ) ) {
1882
			$this->share_type = $settings['share_type'];
1883
		}
1884
1885
		if ( 'official' == $this->button_style ) {
1886
			$this->smart = true;
1887
		} else {
1888
			$this->smart = false;
1889
		}
1890
1891
	}
1892
1893
	public function get_name() {
1894
		return __( 'Skype', 'jetpack' );
1895
	}
1896
1897
	public function get_display( $post ) {
1898
		if ( $this->smart ) {
1899
			$skype_share_html = sprintf(
1900
				'<div class="skype-share" data-href="%1$s" data-lang="%2$s" data-style="small" data-source="jetpack" ></div>',
1901
				esc_attr( $this->get_share_url( $post->ID ) ),
1902
				'en-US'
1903
			);
1904
			return $skype_share_html;
1905
		}
1906
1907
		/** This filter is already documented in modules/sharedaddy/sharing-sources.php */
1908
		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...
1909
			sharing_register_post_for_share_counts( $post->ID );
1910
		}
1911
		return $this->get_link(
1912
			$this->get_process_request_url( $post->ID ), _x( 'Skype', 'share to', 'jetpack' ), __( 'Click to share on Skype', 'jetpack' ), 'share=skype', 'sharing-skype-' . $post->ID );
1913
	}
1914
1915
	/**
1916
	 * AMP display for Skype.
1917
	 *
1918
	 * @param \WP_Post $post The current post being viewed.
1919
	 */
1920
	public function get_amp_display( $post ) {
1921
		$attrs = array(
1922
			'data-share-endpoint' => sprintf(
1923
				'https://web.skype.com/share?url=%1$s&lang=%2$s=&source=jetpack',
1924
				rawurlencode( $this->get_share_url( $post->ID ) ),
1925
				'en-US'
1926
			),
1927
		);
1928
1929
		return $this->build_amp_markup( $attrs );
1930
	}
1931
1932 View Code Duplication
	public function process_request( $post, array $post_data ) {
1933
		$skype_url = 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
		// Record stats
1940
		parent::process_request( $post, $post_data );
1941
1942
		// Redirect to Skype
1943
		wp_redirect( $skype_url );
1944
		die();
1945
	}
1946
1947 View Code Duplication
	public function display_footer() {
1948
		if ( $this->smart ) :
1949
			?>
1950
			<script>
1951
				(function(r, d, s) {
1952
					r.loadSkypeWebSdkAsync = r.loadSkypeWebSdkAsync || function(p) {
1953
							var js, sjs = d.getElementsByTagName(s)[0];
1954
							if (d.getElementById(p.id)) { return; }
1955
							js = d.createElement(s);
1956
							js.id = p.id;
1957
							js.src = p.scriptToLoad;
1958
							js.onload = p.callback
1959
							sjs.parentNode.insertBefore(js, sjs);
1960
						};
1961
					var p = {
1962
						scriptToLoad: 'https://swx.cdn.skype.com/shared/v/latest/skypewebsdk.js',
1963
						id: 'skype_web_sdk'
1964
					};
1965
					r.loadSkypeWebSdkAsync(p);
1966
				})(window, document, 'script');
1967
			</script>
1968
			<?php
1969
		else :
1970
			$this->js_dialog( $this->shortname, array( 'width' => 305, 'height' => 665 ) );
1971
		endif;
1972
	}
1973
}
1974