Completed
Push — update/add-paid-icon-symbol ( 81553a...7061eb )
by
unknown
194:41 queued 186:21
created

sharing-service.php ➔ get_sharing_buttons_customisation_url()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 12

Duplication

Lines 12
Ratio 100 %

Importance

Changes 0
Metric Value
cc 6
nc 6
nop 0
dl 12
loc 12
rs 9.2222
c 0
b 0
f 0
1
<?php
2
3
use Automattic\Jetpack\Assets;
4
use Automattic\Jetpack\Sync\Settings;
5
6
include_once dirname( __FILE__ ) . '/sharing-sources.php';
7
8
define( 'WP_SHARING_PLUGIN_VERSION', JETPACK__VERSION );
9
10
class Sharing_Service {
11
	private $global               = false;
12
	public $default_sharing_label = '';
13
14
	/**
15
	 * Initialize the sharing service.
16
	 * Only run this method once upon module loading.
17
	 */
18
	public static function init() {
19
		add_filter( 'the_content', 'sharing_display', 19 );
20
		add_filter( 'the_excerpt', 'sharing_display', 19 );
21
	}
22
23
	public function __construct() {
24
		$this->default_sharing_label = __( 'Share this:', 'jetpack' );
25
	}
26
27
	/**
28
	 * Gets a generic list of all services, without any config
29
	 */
30
	public function get_all_services_blog() {
31
		$options = get_option( 'sharing-options' );
32
33
		$all      = $this->get_all_services();
34
		$services = array();
35
36
		foreach ( $all as $id => $name ) {
37
			if ( isset( $all[ $id ] ) ) {
38
				$config = array();
39
40
				// Pre-load custom modules otherwise they won't know who they are
41
				if ( substr( $id, 0, 7 ) == 'custom-' && is_array( $options[ $id ] ) ) {
42
					$config = $options[ $id ];
43
				}
44
45
				$services[ $id ] = new $all[ $id ]( $id, $config );
46
			}
47
		}
48
49
		return $services;
50
	}
51
52
	/**
53
	 * Gets a list of all available service names and classes
54
	 */
55
	public function get_all_services( $include_custom = true ) {
56
		// Default services
57
		// if you update this list, please update the REST API tests
58
		// in bin/tests/api/suites/SharingTest.php
59
		$services = array(
60
			'print'            => 'Share_Print',
61
			'facebook'         => 'Share_Facebook',
62
			'linkedin'         => 'Share_LinkedIn',
63
			'reddit'           => 'Share_Reddit',
64
			'twitter'          => 'Share_Twitter',
65
			'tumblr'           => 'Share_Tumblr',
66
			'pinterest'        => 'Share_Pinterest',
67
			'pocket'           => 'Share_Pocket',
68
			'telegram'         => 'Share_Telegram',
69
			'jetpack-whatsapp' => 'Jetpack_Share_WhatsApp',
70
			'skype'            => 'Share_Skype',
71
		);
72
73
		/**
74
		 * Filters if Email Sharing is enabled.
75
		 *
76
		 * E-Mail sharing is often problematic due to spam concerns, so this filter enables it to be quickly and simply toggled.
77
		 * @module sharedaddy
78
		 *
79
		 * @since 5.1.0
80
		 *
81
		 * @param bool $email Is e-mail sharing enabled? Default false if Akismet is not active or true if Akismet is active.
82
		 */
83
		if ( apply_filters( 'sharing_services_email', Jetpack::is_akismet_active() ) ) {
84
			$services['email'] = 'Share_Email';
85
		}
86
87
		if ( is_multisite() && is_plugin_active( 'press-this/press-this-plugin.php' ) ) {
88
			$services['press-this'] = 'Share_PressThis';
89
		}
90
91
		if ( $include_custom ) {
92
			// Add any custom services in
93
			$options = $this->get_global_options();
94
			foreach ( (array) $options['custom'] as $custom_id ) {
95
				$services[ $custom_id ] = 'Share_Custom';
96
			}
97
		}
98
99
		/**
100
		 * Filters the list of available Sharing Services.
101
		 *
102
		 * @module sharedaddy
103
		 *
104
		 * @since 1.1.0
105
		 *
106
		 * @param array $services Array of all available Sharing Services.
107
		 */
108
		return apply_filters( 'sharing_services', $services );
109
	}
110
111
	public function new_service( $label, $url, $icon ) {
112
		// Validate
113
		$label = trim( wp_html_excerpt( wp_kses( $label, array() ), 30 ) );
114
		$url   = trim( esc_url_raw( $url ) );
115
		$icon  = trim( esc_url_raw( $icon ) );
116
117
		if ( $label && $url && $icon ) {
118
			$options = get_option( 'sharing-options' );
119
			if ( ! is_array( $options ) ) {
120
				$options = array();
121
			}
122
123
			$service_id = 'custom-' . time();
124
125
			// Add a new custom service
126
			$options['global']['custom'][] = $service_id;
127
			if ( false !== $this->global ) {
128
				$this->global['custom'][] = $service_id;
129
			}
130
131
			update_option( 'sharing-options', $options );
132
133
			// Create a custom service and set the options for it
134
			$service = new Share_Custom(
135
				$service_id, array(
136
					'name' => $label,
137
					'url'  => $url,
138
					'icon' => $icon,
139
				)
140
			);
141
			$this->set_service( $service_id, $service );
142
143
			// Return the service
144
			return $service;
145
		}
146
147
		return false;
148
	}
149
150
	public function delete_service( $service_id ) {
151
		$options = get_option( 'sharing-options' );
152
		if ( isset( $options[ $service_id ] ) ) {
153
			unset( $options[ $service_id ] );
154
		}
155
156
		$key = array_search( $service_id, $options['global']['custom'] );
157
		if ( $key !== false ) {
158
			unset( $options['global']['custom'][ $key ] );
159
		}
160
161
		update_option( 'sharing-options', $options );
162
		return true;
163
	}
164
165
	public function set_blog_services( array $visible, array $hidden ) {
166
		$services = $this->get_all_services();
167
		// Validate the services
168
		$available = array_keys( $services );
169
170
		// Only allow services that we have defined
171
		$hidden  = array_intersect( $hidden, $available );
172
		$visible = array_intersect( $visible, $available );
173
174
		// Ensure we don't have the same ones in hidden and visible
175
		$hidden = array_diff( $hidden, $visible );
176
177
		/**
178
		 * Control the state of the list of sharing services.
179
		 *
180
		 * @module sharedaddy
181
		 *
182
		 * @since 1.1.0
183
		 *
184
		 * @param array $args {
185
		 *  Array of options describing the state of the sharing services.
186
		 *
187
		 *  @type array $services List of all available service names and classes.
188
		 *  @type array $available Validated list of all available service names and classes.
189
		 *  @type array $hidden List of services hidden behind a "More" button.
190
		 *  @type array $visible List of visible services.
191
		 *  @type array $this->get_blog_services() Array of Sharing Services currently enabled.
192
		 * }
193
		 */
194
		do_action(
195
			'sharing_get_services_state', array(
196
				'services'          => $services,
197
				'available'         => $available,
198
				'hidden'            => $hidden,
199
				'visible'           => $visible,
200
				'currently_enabled' => $this->get_blog_services(),
201
			)
202
		);
203
204
		return update_option(
205
			'sharing-services', array(
206
				'visible' => $visible,
207
				'hidden'  => $hidden,
208
			)
209
		);
210
	}
211
212
	public function get_blog_services() {
213
		$options  = get_option( 'sharing-options' );
214
		$enabled  = get_option( 'sharing-services' );
215
		$services = $this->get_all_services();
216
217
		/**
218
		 * Check if options exist and are well formatted.
219
		 * This avoids issues on sites with corrupted options.
220
		 * @see https://github.com/Automattic/jetpack/issues/6121
221
		 */
222
		if ( ! is_array( $options ) || ! isset( $options['button_style'], $options['global'] ) ) {
223
			$global_options = array( 'global' => $this->get_global_options() );
224
			$options        = is_array( $options )
225
				? array_merge( $options, $global_options )
226
				: $global_options;
227
		}
228
229
		$global = $options['global'];
230
231
		// Default services
232
		if ( ! is_array( $enabled ) ) {
233
			$enabled = array(
234
				'visible' => array(
235
					'twitter',
236
					'facebook',
237
				),
238
				'hidden'  => array(),
239
			);
240
241
			/**
242
			 * Filters the list of default Sharing Services.
243
			 *
244
			 * @module sharedaddy
245
			 *
246
			 * @since 1.1.0
247
			 *
248
			 * @param array $enabled Array of default Sharing Services.
249
			 */
250
			$enabled = apply_filters( 'sharing_default_services', $enabled );
251
		}
252
253
		// Cleanup after any filters that may have produced duplicate services
254 View Code Duplication
		if ( is_array( $enabled['visible'] ) ) {
255
			$enabled['visible'] = array_unique( $enabled['visible'] );
256
		} else {
257
			$enabled['visible'] = array();
258
		}
259
260 View Code Duplication
		if ( is_array( $enabled['hidden'] ) ) {
261
			$enabled['hidden'] = array_unique( $enabled['hidden'] );
262
		} else {
263
			$enabled['hidden'] = array();
264
		}
265
266
		// Form the enabled services
267
		$blog = array(
268
			'visible' => array(),
269
			'hidden'  => array(),
270
		);
271
272
		foreach ( $blog as $area => $stuff ) {
273
			foreach ( (array) $enabled[ $area ] as $service ) {
274
				if ( isset( $services[ $service ] ) ) {
275
					if ( ! isset( $options[ $service ] ) || ! is_array( $options[ $service ] ) ) {
276
						$options[ $service ] = array();
277
					}
278
					$blog[ $area ][ $service ] = new $services[ $service ]( $service, array_merge( $global, $options[ $service ] ) );
279
				}
280
			}
281
		}
282
283
		/**
284
		 * Filters the list of enabled Sharing Services.
285
		 *
286
		 * @module sharedaddy
287
		 *
288
		 * @since 1.1.0
289
		 *
290
		 * @param array $blog Array of enabled Sharing Services.
291
		 */
292
		$blog = apply_filters( 'sharing_services_enabled', $blog );
293
294
		// Add CSS for NASCAR
295
		if ( count( $blog['visible'] ) || count( $blog['hidden'] ) ) {
296
			add_filter( 'post_flair_block_css', 'post_flair_service_enabled_sharing' );
297
		}
298
299
		// Convenience for checking if a service is present
300
		$blog['all'] = array_flip( array_merge( array_keys( $blog['visible'] ), array_keys( $blog['hidden'] ) ) );
301
		return $blog;
302
	}
303
304
	public function get_service( $service_name ) {
305
		$services = $this->get_blog_services();
306
307
		if ( isset( $services['visible'][ $service_name ] ) ) {
308
			return $services['visible'][ $service_name ];
309
		}
310
311
		if ( isset( $services['hidden'][ $service_name ] ) ) {
312
			return $services['hidden'][ $service_name ];
313
		}
314
315
		return false;
316
	}
317
318
	public function set_global_options( $data ) {
319
		$options = get_option( 'sharing-options' );
320
321
		// No options yet.
322
		if ( ! is_array( $options ) ) {
323
			$options = array();
324
		}
325
326
		// Defaults.
327
		$options['global'] = array(
328
			'button_style'  => 'icon-text',
329
			'sharing_label' => $this->default_sharing_label,
330
			'open_links'    => 'same',
331
			'show'          => ! isset( $options['global'] ) ? array( 'post', 'page' ) : array(),
332
			'custom'        => isset( $options['global']['custom'] ) ? $options['global']['custom'] : array(),
333
		);
334
335
		/**
336
		 * Filters global sharing settings.
337
		 *
338
		 * @module sharedaddy
339
		 *
340
		 * @since 1.1.0
341
		 *
342
		 * @param array $options['global'] Array of global sharing settings.
343
		 */
344
		$options['global'] = apply_filters( 'sharing_default_global', $options['global'] );
345
346
		// Validate options and set from our data
347
		if ( isset( $data['button_style'] ) && in_array( $data['button_style'], array( 'icon-text', 'icon', 'text', 'official' ) ) ) {
348
			$options['global']['button_style'] = $data['button_style'];
349
		}
350
351
		if ( isset( $data['sharing_label'] ) ) {
352
			if ( $this->default_sharing_label === $data['sharing_label'] ) {
353
				$options['global']['sharing_label'] = false;
354
			} else {
355
				$options['global']['sharing_label'] = trim( wp_kses( stripslashes( $data['sharing_label'] ), array() ) );
356
			}
357
		}
358
359
		if ( isset( $data['open_links'] ) && in_array( $data['open_links'], array( 'new', 'same' ) ) ) {
360
			$options['global']['open_links'] = $data['open_links'];
361
		}
362
363
		$shows   = array_values( get_post_types( array( 'public' => true ) ) );
364
		$shows[] = 'index';
365
		if ( isset( $data['show'] ) ) {
366
			if ( is_scalar( $data['show'] ) ) {
367
				switch ( $data['show'] ) {
368
					case 'posts':
369
						$data['show'] = array( 'post', 'page' );
370
						break;
371
					case 'index':
372
						$data['show'] = array( 'index' );
373
						break;
374
					case 'posts-index':
375
						$data['show'] = array( 'post', 'page', 'index' );
376
						break;
377
				}
378
			}
379
380 View Code Duplication
			if ( $data['show'] = array_intersect( $data['show'], $shows ) ) {
381
				$options['global']['show'] = $data['show'];
382
			}
383
		}
384
385
		update_option( 'sharing-options', $options );
386
		return $options['global'];
387
	}
388
389
	public function get_global_options() {
390
		if ( $this->global === false ) {
391
			$options = get_option( 'sharing-options' );
392
393
			if ( is_array( $options ) && isset( $options['global'] ) && is_array( $options['global'] ) ) {
394
				$this->global = $options['global'];
0 ignored issues
show
Documentation Bug introduced by
It seems like $options['global'] of type array is incompatible with the declared type boolean of property $global.

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

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

Loading history...
395
			} else {
396
				$this->global = $this->set_global_options( $options );
397
			}
398
		}
399
400
		if ( ! isset( $this->global['show'] ) ) {
401
			$this->global['show'] = array( 'post', 'page' );
402
		} elseif ( is_scalar( $this->global['show'] ) ) {
403
			switch ( $this->global['show'] ) {
404
				case 'posts':
405
					$this->global['show'] = array( 'post', 'page' );
406
					break;
407
				case 'index':
408
					$this->global['show'] = array( 'index' );
409
					break;
410
				case 'posts-index':
411
					$this->global['show'] = array( 'post', 'page', 'index' );
412
					break;
413
			}
414
		}
415
416
		if ( false === $this->global['sharing_label'] ) {
417
			$this->global['sharing_label'] = $this->default_sharing_label;
418
		}
419
420
		return $this->global;
421
	}
422
423
	public function set_service( $id, Sharing_Source $service ) {
424
		// Update the options for this service
425
		$options = get_option( 'sharing-options' );
426
427
		// No options yet
428
		if ( ! is_array( $options ) ) {
429
			$options = array();
430
		}
431
432
		/**
433
		 * Get the state of a sharing button.
434
		 *
435
		 * @module sharedaddy
436
		 *
437
		 * @since 1.1.0
438
		 *
439
		 * @param array $args {
440
		 *  State of a sharing button.
441
		 *
442
		 *  @type string $id Service ID.
443
		 *  @type array $options Array of all sharing options.
444
		 *  @type array $service Details about a service.
445
		 * }
446
		 */
447
		do_action(
448
			'sharing_get_button_state', array(
449
				'id'      => $id,
450
				'options' => $options,
451
				'service' => $service,
452
			)
453
		);
454
455
		$options[ $id ] = $service->get_options();
0 ignored issues
show
Bug introduced by
The method get_options cannot be called on $service (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
456
457
		update_option( 'sharing-options', array_filter( $options ) );
458
	}
459
460
	// Soon to come to a .org plugin near you!
461
	public function get_total( $service_name = false, $post_id = false, $_blog_id = false ) {
462
		global $wpdb, $blog_id;
463
		if ( ! $_blog_id ) {
464
			$_blog_id = $blog_id;
465
		}
466 View Code Duplication
		if ( $service_name == 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...
467
			if ( $post_id > 0 ) {
468
				// total number of shares for this post
469
				return (int) $wpdb->get_var( $wpdb->prepare( 'SELECT SUM( count ) FROM sharing_stats WHERE blog_id = %d AND post_id = %d', $_blog_id, $post_id ) );
470
			} else {
471
				// total number of shares for this blog
472
				return (int) $wpdb->get_var( $wpdb->prepare( 'SELECT SUM( count ) FROM sharing_stats WHERE blog_id = %d', $_blog_id ) );
473
			}
474
		}
475
476 View Code Duplication
		if ( $post_id > 0 ) {
477
			return (int) $wpdb->get_var( $wpdb->prepare( 'SELECT SUM( count ) FROM sharing_stats WHERE blog_id = %d AND post_id = %d AND share_service = %s', $_blog_id, $post_id, $service_name ) );
478
		} else {
479
			return (int) $wpdb->get_var( $wpdb->prepare( 'SELECT SUM( count ) FROM sharing_stats WHERE blog_id = %d AND share_service = %s', $_blog_id, $service_name ) );
480
		}
481
	}
482
483
	public function get_services_total( $post_id = false ) {
484
		$totals   = array();
485
		$services = $this->get_blog_services();
486
487
		if ( ! empty( $services ) && isset( $services['all'] ) ) {
488
			foreach ( $services['all'] as $key => $value ) {
489
				$totals[ $key ] = new Sharing_Service_Total( $key, $this->get_total( $key, $post_id ) );
0 ignored issues
show
Documentation introduced by
$key is of type integer|string, but the function expects a boolean.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
490
			}
491
		}
492
		usort( $totals, array( 'Sharing_Service_Total', 'cmp' ) );
493
494
		return $totals;
495
	}
496
497 View Code Duplication
	public function get_posts_total() {
498
		$totals = array();
499
		global $wpdb, $blog_id;
500
501
		$my_data = $wpdb->get_results( $wpdb->prepare( 'SELECT post_id as id, SUM( count ) as total FROM sharing_stats WHERE blog_id = %d GROUP BY post_id ORDER BY count DESC ', $blog_id ) );
502
503
		if ( ! empty( $my_data ) ) {
504
			foreach ( $my_data as $row ) {
505
				$totals[] = new Sharing_Post_Total( $row->id, $row->total );
506
			}
507
		}
508
509
		usort( $totals, array( 'Sharing_Post_Total', 'cmp' ) );
510
511
		return $totals;
512
	}
513
}
514
515
class Sharing_Service_Total {
516
	public $id      = '';
517
	public $name    = '';
518
	public $service = '';
519
	public $total   = 0;
520
521
	public function __construct( $id, $total ) {
522
		$services      = new Sharing_Service();
523
		$this->id      = esc_html( $id );
524
		$this->service = $services->get_service( $id );
525
		$this->total   = (int) $total;
526
527
		$this->name = $this->service->get_name();
528
	}
529
530
	static function cmp( $a, $b ) {
531
		if ( $a->total == $b->total ) {
532
			return $a->name < $b->name;
533
		}
534
		return $a->total < $b->total;
535
	}
536
}
537
538
class Sharing_Post_Total {
539
	public $id    = 0;
540
	public $total = 0;
541
	public $title = '';
542
	public $url   = '';
543
544
	public function __construct( $id, $total ) {
545
		$this->id    = (int) $id;
546
		$this->total = (int) $total;
547
		$this->title = get_the_title( $this->id );
548
		$this->url   = get_permalink( $this->id );
549
	}
550
551
	static function cmp( $a, $b ) {
552
		if ( $a->total == $b->total ) {
553
			return $a->id < $b->id;
554
		}
555
		return $a->total < $b->total;
556
	}
557
}
558
559
function sharing_register_post_for_share_counts( $post_id ) {
560
	global $jetpack_sharing_counts;
561
562
	if ( ! isset( $jetpack_sharing_counts ) || ! is_array( $jetpack_sharing_counts ) ) {
563
		$jetpack_sharing_counts = array();
564
	}
565
566
	$jetpack_sharing_counts[ (int) $post_id ] = get_permalink( $post_id );
567
}
568
569
function sharing_maybe_enqueue_scripts() {
570
	$sharer         = new Sharing_Service();
571
	$global_options = $sharer->get_global_options();
572
573
	$enqueue = false;
574
	if ( is_singular() && in_array( get_post_type(), $global_options['show'] ) ) {
575
		$enqueue = true;
576 View Code Duplication
	} elseif ( in_array( 'index', $global_options['show'] ) && ( is_home() || is_front_page() || is_archive() || is_search() || in_array( get_post_type(), $global_options['show'] ) ) ) {
577
		$enqueue = true;
578
	}
579
580
	/**
581
	 * Filter to decide when sharing scripts should be enqueued.
582
	 *
583
	 * @module sharedaddy
584
	 *
585
	 * @since 3.2.0
586
	 *
587
	 * @param bool $enqueue Decide if the sharing scripts should be enqueued.
588
	 */
589
	return (bool) apply_filters( 'sharing_enqueue_scripts', $enqueue );
590
}
591
592
function sharing_add_footer() {
593
	if (
594
		class_exists( 'Jetpack_AMP_Support' )
595
		&& Jetpack_AMP_Support::is_amp_request()
596
	) {
597
		return;
598
	}
599
600
	global $jetpack_sharing_counts;
601
602
	/**
603
	 * Filter all JavaScript output by the sharing module.
604
	 *
605
	 * @module sharedaddy
606
	 *
607
	 * @since 1.1.0
608
	 *
609
	 * @param bool true Control whether the sharing module should add any JavaScript to the site. Default to true.
610
	 */
611
	if ( apply_filters( 'sharing_js', true ) && sharing_maybe_enqueue_scripts() ) {
612
613
		/**
614
		 * Filter the display of sharing counts next to the sharing buttons.
615
		 *
616
		 * @module sharedaddy
617
		 *
618
		 * @since 3.2.0
619
		 *
620
		 * @param bool true Control the display of counters next to the sharing buttons. Default to true.
621
		 */
622
		if ( apply_filters( 'jetpack_sharing_counts', true ) && is_array( $jetpack_sharing_counts ) && count( $jetpack_sharing_counts ) ) :
623
			$sharing_post_urls = array_filter( $jetpack_sharing_counts );
624
			if ( $sharing_post_urls ) :
0 ignored issues
show
Bug Best Practice introduced by
The expression $sharing_post_urls of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
625
				?>
626
627
	<script type="text/javascript">
628
		window.WPCOM_sharing_counts = <?php echo json_encode( array_flip( $sharing_post_urls ) ); ?>;
629
	</script>
630
				<?php
631
			endif;
632
		endif;
633
634
		wp_enqueue_script( 'sharing-js' );
635
		$sharing_js_options = array(
636
			'lang'            => get_base_recaptcha_lang_code(),
637
			/** This filter is documented in modules/sharedaddy/sharing-service.php */
638
			'counts'          => apply_filters( 'jetpack_sharing_counts', true ),
639
			'is_stats_active' => Jetpack::is_module_active( 'stats' ),
640
		);
641
		wp_localize_script( 'sharing-js', 'sharing_js_options', $sharing_js_options );
642
	}
643
	$sharer  = new Sharing_Service();
644
	$enabled = $sharer->get_blog_services();
645
	foreach ( array_merge( $enabled['visible'], $enabled['hidden'] ) as $service ) {
646
		$service->display_footer();
647
	}
648
}
649
650
function sharing_add_header() {
651
	$sharer  = new Sharing_Service();
652
	$enabled = $sharer->get_blog_services();
653
654
	foreach ( array_merge( $enabled['visible'], $enabled['hidden'] ) as $service ) {
655
		$service->display_header();
656
	}
657
658
	if ( count( $enabled['all'] ) > 0 && sharing_maybe_enqueue_scripts() ) {
659
		wp_enqueue_style( 'sharedaddy', plugin_dir_url( __FILE__ ) . 'sharing.css', array(), JETPACK__VERSION );
660
		wp_enqueue_style( 'social-logos' );
661
	}
662
663
}
664
add_action( 'wp_head', 'sharing_add_header', 1 );
665
666
function sharing_process_requests() {
667
	global $post;
668
669
	// Only process if: single post and share=X defined
670
	if ( ( is_page() || is_single() ) && isset( $_GET['share'] ) && is_string( $_GET['share'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
671
		$sharer = new Sharing_Service();
672
673
		$service = $sharer->get_service( $_GET['share'] );
674
		if ( $service ) {
675
			$service->process_request( $post, $_POST );
676
		}
677
	}
678
}
679
add_action( 'template_redirect', 'sharing_process_requests', 9 );
680
681
/**
682
 * Gets the url to customise the sharing buttons in Calypso.
683
 *
684
 * @return string the customisation URL or null if it couldn't be determinde.
685
 */
686 View Code Duplication
function get_sharing_buttons_customisation_url() {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
687
	if ( class_exists( 'Jetpack' ) && method_exists( 'Jetpack', 'build_raw_urls' ) ) {
688
		$site_suffix = Jetpack::build_raw_urls( home_url() );
689
	} elseif ( class_exists( 'WPCOM_Masterbar' ) && method_exists( 'WPCOM_Masterbar', 'get_calypso_site_slug' ) ) {
690
		$site_suffix = WPCOM_Masterbar::get_calypso_site_slug( get_current_blog_id() );
691
	}
692
693
	if ( $site_suffix ) {
694
		return Automattic\Jetpack\Redirect::get_url( 'calypso-marketing-sharing-buttons', array( 'site' => $site_suffix ) );
0 ignored issues
show
Bug introduced by
The variable $site_suffix does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
695
	}
696
	return null;
697
}
698
699
/**
700
 * Append sharing links to text.
701
 *
702
 * @param string $text The original text to append sharing links onto.
703
 * @param bool   $echo Where to echo the text or return.
704
 *
705
 * @return string The original $text with, if conditions are met, the sharing links.
706
 */
707
function sharing_display( $text = '', $echo = false ) {
708
	global $post, $wp_current_filter;
709
710
	if ( Settings::is_syncing() ) {
711
		return $text;
712
	}
713
714
	if ( empty( $post ) ) {
715
		return $text;
716
	}
717
718
	if ( ( is_preview() || is_admin() ) && ! ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
719
		return $text;
720
	}
721
722
	// Don't output flair on excerpts.
723
	if ( in_array( 'get_the_excerpt', (array) $wp_current_filter, true ) ) {
724
		return $text;
725
	}
726
727
	// Don't allow flair to be added to the_content more than once (prevent infinite loops).
728
	$done = false;
729
	foreach ( $wp_current_filter as $filter ) {
730
		if ( 'the_content' === $filter ) {
731
			if ( $done ) {
732
				return $text;
733
			} else {
734
				$done = true;
735
			}
736
		}
737
	}
738
739
	// check whether we are viewing the front page and whether the front page option is checked.
740
	$options         = get_option( 'sharing-options' );
741
	$display_options = null;
742
743
	if ( is_array( $options ) ) {
744
		$display_options = $options['global']['show'];
745
	}
746
747
	if ( is_front_page() && ( is_array( $display_options ) && ! in_array( 'index', $display_options, true ) ) ) {
748
		return $text;
749
	}
750
751
	if ( is_attachment() && in_array( 'the_excerpt', (array) $wp_current_filter, true ) ) {
752
		// Many themes run the_excerpt() conditionally on an attachment page, then run the_content().
753
		// We only want to output the sharing buttons once.  Let's stick with the_content().
754
		return $text;
755
	}
756
757
	$sharer = new Sharing_Service();
758
	$global = $sharer->get_global_options();
759
760
	$show = false;
761
	if ( ! is_feed() ) {
762
		if ( is_singular() && in_array( get_post_type(), $global['show'], true ) ) {
763
			$show = true;
764 View Code Duplication
		} elseif ( in_array( 'index', $global['show'], true ) && ( is_home() || is_front_page() || is_archive() || is_search() || in_array( get_post_type(), $global['show'], true ) ) ) {
765
			$show = true;
766
		}
767
	}
768
769
	/**
770
	 * Filter to decide if sharing buttons should be displayed.
771
	 *
772
	 * @module sharedaddy
773
	 *
774
	 * @since 1.1.0
775
	 *
776
	 * @param bool $show Should the sharing buttons be displayed.
777
	 * @param WP_Post $post The post to share.
778
	 */
779
	$show = apply_filters( 'sharing_show', $show, $post );
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...
780
781
	// Disabled for this post?
782
	$switched_status = get_post_meta( $post->ID, 'sharing_disabled', false );
783
784
	if ( ! empty( $switched_status ) ) {
785
		$show = false;
786
	}
787
788
	// Is the post private?
789
	$post_status = get_post_status( $post->ID );
790
791
	if ( 'private' === $post_status ) {
792
		$show = false;
793
	}
794
795
	/**
796
	 * Filter the Sharing buttons' Ajax action name Jetpack checks for.
797
	 * This allows the use of the buttons with your own Ajax implementation.
798
	 *
799
	 * @module sharedaddy
800
	 *
801
	 * @since 7.3.0
802
	 *
803
	 * @param string $sharing_ajax_action_name Name of the Sharing buttons' Ajax action.
804
	 */
805
	$ajax_action = apply_filters( 'sharing_ajax_action', 'get_latest_posts' );
806
807
	// Allow to be used in ajax requests for latest posts.
808
	if (
809
		defined( 'DOING_AJAX' )
810
		&& DOING_AJAX
811
		&& isset( $_REQUEST['action'] )
812
		&& $ajax_action === $_REQUEST['action']
813
	) {
814
		$show = true;
815
	}
816
817
	$sharing_content = '';
818
	$enabled         = false;
819
820
	if ( $show ) {
821
		/**
822
		 * Filters the list of enabled Sharing Services.
823
		 *
824
		 * @module sharedaddy
825
		 *
826
		 * @since 2.2.3
827
		 *
828
		 * @param array $sharer->get_blog_services() Array of Sharing Services currently enabled.
829
		 */
830
		$enabled = apply_filters( 'sharing_enabled', $sharer->get_blog_services() );
831
832
		if ( count( $enabled['all'] ) > 0 ) {
833
			$dir = get_option( 'text_direction' );
834
835
			// Wrapper.
836
			$sharing_content .= '<div class="sharedaddy sd-sharing-enabled"><div class="robots-nocontent sd-block sd-social sd-social-' . $global['button_style'] . ' sd-sharing">';
837
			if ( '' !== $global['sharing_label'] ) {
838
				$sharing_content .= sprintf(
839
					/**
840
					 * Filter the sharing buttons' headline structure.
841
					 *
842
					 * @module sharedaddy
843
					 *
844
					 * @since 4.4.0
845
					 *
846
					 * @param string $sharing_headline Sharing headline structure.
847
					 * @param string $global['sharing_label'] Sharing title.
848
					 * @param string $sharing Module name.
849
					 */
850
					apply_filters( 'jetpack_sharing_headline_html', '<h3 class="sd-title">%s</h3>', $global['sharing_label'], 'sharing' ),
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $global['sharing_label'].

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...
851
					esc_html( $global['sharing_label'] )
852
				);
853
			}
854
			$sharing_content .= '<div class="sd-content"><ul>';
855
856
			// Visible items.
857
			$visible = '';
858
			foreach ( $enabled['visible'] as $id => $service ) {
859
				$klasses = array( 'share-' . $service->get_class() );
860
				if ( $service->is_deprecated() ) {
861
					if ( ! current_user_can( 'manage_options' ) ) {
862
						continue;
863
					}
864
					$klasses[] = 'share-deprecated';
865
				}
866
				// Individual HTML for sharing service.
867
				$visible .= '<li class="' . implode( ' ', $klasses ) . '">' . $service->get_display( $post ) . '</li>';
868
			}
869
870
			$parts   = array();
871
			$parts[] = $visible;
872
			if ( count( $enabled['hidden'] ) > 0 ) {
873
				if ( count( $enabled['visible'] ) > 0 ) {
874
					$expand = __( 'More', 'jetpack' );
875
				} else {
876
					$expand = __( 'Share', 'jetpack' );
877
				}
878
				$parts[] = '<li><a href="#" class="sharing-anchor sd-button share-more"><span>' . $expand . '</span></a></li>';
879
			}
880
881
			if ( 'rtl' === $dir ) {
882
				$parts = array_reverse( $parts );
883
			}
884
885
			$sharing_content .= implode( '', $parts );
886
			$sharing_content .= '<li class="share-end"></li></ul>';
887
888
			// Link to customization options if user can manage them.
889
			if ( current_user_can( 'manage_options' ) ) {
890
				$link_url = get_sharing_buttons_customisation_url();
891
				if ( ! empty( $link_url ) ) {
892
					$link_text        = __( 'Customize buttons', 'jetpack' );
893
					$sharing_content .= '<p class="share-customize-link"><a href="' . esc_url( $link_url ) . '" target="_blank" rel="noopener noreferrer">' . esc_html( $link_text ) . '</a></p>';
894
				}
895
			}
896
897
			if ( count( $enabled['hidden'] ) > 0 ) {
898
				$sharing_content .= '<div class="sharing-hidden"><div class="inner" style="display: none;';
899
900
				if ( count( $enabled['hidden'] ) === 1 ) {
901
					$sharing_content .= 'width:150px;';
902
				}
903
904
				$sharing_content .= '">';
905
906
				if ( count( $enabled['hidden'] ) === 1 ) {
907
					$sharing_content .= '<ul style="background-image:none;">';
908
				} else {
909
					$sharing_content .= '<ul>';
910
				}
911
912
				$count = 1;
913
				foreach ( $enabled['hidden'] as $id => $service ) {
914
					// Individual HTML for sharing service.
915
					$klasses = array( 'share-' . $service->get_class() );
916
					if ( $service->is_deprecated() ) {
917
						if ( ! current_user_can( 'manage_options' ) ) {
918
							continue;
919
						}
920
						$klasses[] = 'share-deprecated';
921
					}
922
					$sharing_content .= '<li class="' . implode( ' ', $klasses ) . '">';
923
					$sharing_content .= $service->get_display( $post );
924
					$sharing_content .= '</li>';
925
926
					if ( ( $count % 2 ) === 0 ) {
927
						$sharing_content .= '<li class="share-end"></li>';
928
					}
929
930
					$count ++;
931
				}
932
933
				// End of wrapper.
934
				$sharing_content .= '<li class="share-end"></li></ul></div></div>';
935
			}
936
937
			$sharing_content .= '</div></div></div>';
938
939
			// Register our JS.
940
			if ( defined( 'JETPACK__VERSION' ) ) {
941
				$ver = JETPACK__VERSION;
942
			} else {
943
				$ver = '20141212';
944
			}
945
946
			// @todo: Investigate if we can load this JS in the footer instead.
947
			wp_register_script(
948
				'sharing-js',
949
				Assets::get_file_url_for_environment(
950
					'_inc/build/sharedaddy/sharing.min.js',
951
					'modules/sharedaddy/sharing.js'
952
				),
953
				array( 'jquery' ),
954
				$ver,
955
				false
956
			);
957
958
			// Enqueue scripts for the footer.
959
			add_action( 'wp_footer', 'sharing_add_footer' );
960
		}
961
	}
962
963
	/**
964
	 * Filters the content markup of the Jetpack sharing links
965
	 *
966
	 * @module sharedaddy
967
	 *
968
	 * @since 3.8.0
969
	 * @since 6.2.0 Started sending $enabled as a second parameter.
970
	 *
971
	 * @param string $sharing_content Content markup of the Jetpack sharing links
972
	 * @param array  $enabled         Array of Sharing Services currently enabled.
973
	 */
974
	$sharing_markup = apply_filters( 'jetpack_sharing_display_markup', $sharing_content, $enabled );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $enabled.

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...
975
976
	if ( $echo ) {
977
		echo $text . $sharing_markup;
978
	} else {
979
		return $text . $sharing_markup;
980
	}
981
}
982
983
function get_base_recaptcha_lang_code() {
984
985
	$base_recaptcha_lang_code_mapping = array(
986
		'en'    => 'en',
987
		'nl'    => 'nl',
988
		'fr'    => 'fr',
989
		'fr-be' => 'fr',
990
		'fr-ca' => 'fr',
991
		'fr-ch' => 'fr',
992
		'de'    => 'de',
993
		'pt'    => 'pt',
994
		'pt-br' => 'pt',
995
		'ru'    => 'ru',
996
		'es'    => 'es',
997
		'tr'    => 'tr',
998
	);
999
1000
	$blog_lang_code = function_exists( 'get_blog_lang_code' ) ? get_blog_lang_code() : get_bloginfo( 'language' );
1001
	if ( isset( $base_recaptcha_lang_code_mapping[ $blog_lang_code ] ) ) {
1002
		return $base_recaptcha_lang_code_mapping[ $blog_lang_code ];
1003
	}
1004
1005
	// if no base mapping is found return default 'en'
1006
	return 'en';
1007
}
1008
1009
Sharing_Service::init();
1010