PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
16.3 16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 All 508 releases
← All changes | extensions/blocks/sharing-button/class-sharing-source-block.php +1441 -0 16.2-beta → 16.3 View file →
@@ -1,0 +1,1441 @@
1 +<?php
2 +/**
3 + * Define all sharing sources.
4 + *
5 + * @since 13.0
6 + *
7 + * @package automattic/jetpack
8 + *
9 + * phpcs:disable Generic.Files.OneObjectStructurePerFile.MultipleFound
10 + */
11 +
12 +namespace Automattic\Jetpack\Extensions\Sharing_Button_Block;
13 +
14 +use Automattic\Jetpack\Device_Detection\User_Agent_Info;
15 +use Automattic\Jetpack\Post_Media\Images;
16 +use WP_Post;
17 +
18 +/**
19 + * Base class for sharing sources.
20 + * See individual sharing classes below for the implementation of this class.
21 + */
22 +abstract class Sharing_Source_Block {
23 + /**
24 + * Sharing unique ID.
25 + *
26 + * @var int
27 + */
28 + protected $id;
29 +
30 + /**
31 + * Constructor.
32 + *
33 + * @param int $id Sharing source ID.
34 + */
35 + public function __construct( $id ) {
36 + $this->id = $id;
37 + }
38 +
39 + /**
40 + * Get the protocol to use for a sharing service, based on the site settings.
41 + *
42 + * @return string
43 + */
44 + public function http() {
45 + return 'https';
46 + }
47 +
48 + /**
49 + * Get unique sharing ID.
50 + *
51 + * @return int
52 + */
53 + public function get_id() {
54 + return $this->id;
55 + }
56 +
57 + /**
58 + * Get unique sharing ID. Similar to get_id().
59 + *
60 + * @return int
61 + */
62 + public function get_class() {
63 + return $this->id;
64 + }
65 +
66 + /**
67 + * Get stats for a site, a post, or a sharing service.
68 + * Soon to come to a .org plugin near you!
69 + *
70 + * @param WP_Post|bool $post Post object.
71 + *
72 + * @return int
73 + */
74 + public function get_total( $post = false ) {
75 + global $wpdb, $blog_id;
76 +
77 + $name = strtolower( (string) $this->get_id() );
78 +
79 + if ( $post === false ) {
80 + // get total number of shares for service
81 + return (int) $wpdb->get_var( // phpcs:ignore WordPress.DB.DirectDatabaseQuery
82 + $wpdb->prepare(
83 + 'SELECT SUM( count ) FROM sharing_stats WHERE blog_id = %d AND share_service = %s',
84 + $blog_id,
85 + $name
86 + )
87 + );
88 + }
89 +
90 + // get total shares for a post
91 + return (int) $wpdb->get_var( // phpcs:ignore WordPress.DB.DirectDatabaseQuery
92 + $wpdb->prepare(
93 + 'SELECT count FROM sharing_stats WHERE blog_id = %d AND post_id = %d AND share_service = %s',
94 + $blog_id,
95 + $post->ID,
96 + $name
97 + )
98 + );
99 + }
100 +
101 + /**
102 + * Get a post's permalink to use for sharing.
103 + *
104 + * @param int $post_id Post ID.
105 + *
106 + * @return string
107 + */
108 + public function get_share_url( $post_id ) {
109 + /**
110 + * Filter the sharing permalink.
111 + *
112 + * @module sharedaddy
113 + *
114 + * @since 1.2.0
115 + *
116 + * @param string get_permalink( $post_id ) Post Permalink.
117 + * @param int $post_id Post ID.
118 + * @param int $this->id Sharing ID.
119 + */
120 + return apply_filters( 'sharing_permalink', get_permalink( $post_id ), $post_id, $this->id );
121 + }
122 +
123 + /**
124 + * Get a post's title to use for sharing.
125 + *
126 + * @param int $post_id Post ID.
127 + *
128 + * @return string
129 + */
130 + public function get_share_title( $post_id ) {
131 + $post = get_post( $post_id );
132 + /**
133 + * Filter the sharing title.
134 + *
135 + * @module sharedaddy
136 + *
137 + * @since 2.8.0
138 + *
139 + * @param string $post->post_title Post Title.
140 + * @param int $post_id Post ID.
141 + * @param int $this->id Sharing ID.
142 + */
143 + $title = $post instanceof WP_Post ? apply_filters( 'sharing_title', $post->post_title, $post_id, $this->id ) : '';
144 + return html_entity_decode( wp_kses( $title, '' ), ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 );
145 + }
146 +
147 + /**
148 + * Get a comma-separated list of the post's tags to use for sharing.
149 + * Prepends a '#' to each tag.
150 + *
151 + * @param int $post_id Post ID.
152 + *
153 + * @return string
154 + */
155 + public function get_share_tags( $post_id ) {
156 + $tags = get_the_tags( $post_id );
157 + if ( ! $tags ) {
158 + return '';
159 + }
160 +
161 + $tags = array_map(
162 + function ( $tag ) {
163 + // Camel case the tag name and remove spaces as well as apostrophes.
164 + $tag = preg_replace( '/\s+|\'/', '', ucwords( $tag->name ) );
165 +
166 + // Return with a '#' prepended.
167 + return '#' . $tag;
168 + },
169 + $tags
170 + );
171 +
172 + /**
173 + * Allow customizing how the list of tags is displayed.
174 + *
175 + * @module sharedaddy
176 + * @since 11.9
177 + *
178 + * @param string $tags Comma-separated list of tags.
179 + * @param int $post_id Post ID.
180 + * @param int $this->id Sharing ID.
181 + */
182 + $tag_list = (string) apply_filters( 'jetpack_sharing_tag_list', implode( ', ', $tags ), $post_id, $this->id );
183 +
184 + return html_entity_decode( wp_kses( $tag_list, '' ), ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 );
185 + }
186 +
187 + /**
188 + * Get the URL for the link.
189 + *
190 + * @param int $post_id Post ID.
191 + * @param string $query Additional query arguments to add to the link. They should be in 'foo=bar&baz=1' format.
192 + * @param bool|string $id Sharing ID to include in the data-shared attribute.
193 + * @param array $data_attributes The keys are used as additional attribute names with 'data-' prefix.
194 + * The values are used as the attribute values.
195 + * @return object Link related data (url and data_attributes);
196 + */
197 + public function get_link( $post_id, $query = '', $id = false, $data_attributes = array() ) {
198 + $url = $this->get_url( $this->get_process_request_url( $post_id ), $query, $id );
199 + $data_attributes = $this->get_data_attributes( $id, $data_attributes );
200 +
201 + return array(
202 + 'url' => $url,
203 + 'data_attributes' => $data_attributes,
204 + );
205 + }
206 +
207 + /**
208 + * Get the URL for the link.
209 + *
210 + * @param string $url Post URL to share.
211 + * @param string $query Additional query arguments to add to the link. They should be in 'foo=bar&baz=1' format.
212 + * @param bool|string $id Sharing ID to include in the data-shared attribute.
213 + *
214 + * @return string The link URL.
215 + */
216 + public function get_url( $url, $query = '', $id = false ) {
217 + $args = func_get_args();
218 +
219 + /**
220 + * Filter the sharing display ID.
221 + *
222 + * @module sharedaddy
223 + *
224 + * @since 3.4.0
225 + *
226 + * @param string|false $id Sharing ID.
227 + * @param object $this Sharing service properties.
228 + * @param array $args Array of sharing service options.
229 + */
230 + $id = apply_filters( 'jetpack_sharing_display_id', $id, $this, $args );
231 + /**
232 + * Filter the sharing display link.
233 + *
234 + * @module sharedaddy
235 + *
236 + * @since 2.8.0
237 + *
238 + * @param string $url Post URL.
239 + * @param object $this Sharing service properties.
240 + * @param string|false $id Sharing ID.
241 + * @param array $args Array of sharing service options.
242 + */
243 + $url = apply_filters( 'sharing_display_link', $url, $this, $id, $args ); // backwards compatibility
244 + /**
245 + * Filter the sharing display link.
246 + *
247 + * @module sharedaddy
248 + *
249 + * @since 2.8.0
250 + *
251 + * @param string $url Post URL.
252 + * @param object $this Sharing service properties.
253 + * @param string|false $id Sharing ID.
254 + * @param array $args Array of sharing service options.
255 + */
256 + $url = apply_filters( 'jetpack_sharing_display_link', $url, $this, $id, $args );
257 + /**
258 + * Filter the sharing display query.
259 + *
260 + * @module sharedaddy
261 + *
262 + * @since 2.8.0
263 + *
264 + * @param string $query Sharing service URL parameter.
265 + * @param object $this Sharing service properties.
266 + * @param string|false $id Sharing ID.
267 + * @param array $args Array of sharing service options.
268 + */
269 + $query = apply_filters( 'jetpack_sharing_display_query', $query, $this, $id, $args );
270 +
271 + if ( ! empty( $query ) ) {
272 + if ( false === stripos( $url, '?' ) ) {
273 + $url .= '?' . $query;
274 + } else {
275 + $url .= '&amp;' . $query;
276 + }
277 + }
278 +
279 + return $url;
280 + }
281 +
282 + /**
283 + * Add extra JavaScript to a sharing service.
284 + *
285 + * @param array $params Array of sharing options.
286 + *
287 + * @return void
288 + */
289 + public function js_dialog( $params = array() ) {
290 + }
291 +
292 + /**
293 + * Get custom data attributes for the link.
294 + *
295 + * @param bool|string $id Sharing ID to include in the data-shared attribute.
296 + * @param array $data_attributes The keys are used as additional attribute names with 'data-' prefix.
297 + * The values are used as the attribute values.
298 + *
299 + * @return string Encoded data attributes.
300 + */
301 + public function get_data_attributes( $id = false, $data_attributes = array() ) {
302 + $args = func_get_args();
303 +
304 + /**
305 + * Filter the sharing data attributes.
306 + *
307 + * @module sharedaddy
308 + *
309 + * @since 11.0
310 + *
311 + * @param array $data_attributes Attributes supplied from the sharing source.
312 + * Note that 'data-' will be prepended to all keys.
313 + * @param Sharing_Source $this Sharing source instance.
314 + * @param string|false $id Sharing ID.
315 + * @param array $args Array of sharing service options.
316 + */
317 + $data_attributes = apply_filters( 'jetpack_sharing_data_attributes', (array) $data_attributes, $this, $id, $args );
318 +
319 + $encoded_data_attributes = '';
320 + if ( ! empty( $data_attributes ) ) {
321 + $encoded_data_attributes = implode(
322 + ' ',
323 + array_map(
324 + /** Format attributes */
325 + function ( $data_key, $data_value ) {
326 + return sprintf(
327 + 'data-%s="%s"',
328 + esc_attr( str_replace( array( ' ', '"' ), '', $data_key ) ),
329 + esc_attr( $data_value )
330 + );
331 + },
332 + array_keys( $data_attributes ),
333 + array_values( $data_attributes )
334 + )
335 + );
336 + }
337 + return $encoded_data_attributes;
338 + }
339 +
340 + /**
341 + * Get an unfiltered post permalink to use when generating a sharing URL with get_link.
342 + * Use instead of get_share_url for non-official styles as get_permalink ensures that process_request
343 + * will be executed more reliably, in the case that the filtered URL uses a service that strips query parameters.
344 + *
345 + * @since 3.7.0
346 + * @param int $post_id Post ID.
347 + *
348 + * @uses get_permalink
349 + *
350 + * @return string get_permalink( $post_id ) Post permalink.
351 + */
352 + public function get_process_request_url( $post_id ) {
353 + return get_permalink( $post_id );
354 + }
355 +
356 + /**
357 + * Does the service have advanced options.
358 + *
359 + * @return bool
360 + */
361 + public function has_advanced_options() {
362 + return false;
363 + }
364 +
365 + /**
366 + * Process sharing request. Add actions that need to happen when sharing here.
367 + *
368 + * @param WP_Post $post Post object.
369 + * @param array $post_data Array of information about the post we're sharing.
370 + *
371 + * @return void
372 + */
373 + public function process_request( $post, array $post_data ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
374 + /**
375 + * Fires when a post is shared via one of the sharing buttons.
376 + *
377 + * @module sharedaddy
378 + *
379 + * @since 1.1.0
380 + *
381 + * @param array $args Aray of information about the sharing service.
382 + */
383 + do_action(
384 + 'sharing_bump_stats',
385 + array(
386 + 'service' => $this,
387 + 'post' => $post,
388 + )
389 + );
390 + }
391 +
392 + /**
393 + * Redirect to an external social network site to finish sharing.
394 + *
395 + * @param string $url Sharing URL for a given service.
396 + * @return never
397 + */
398 + public function redirect_request( $url ) {
399 + wp_redirect( $url ); // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect -- We allow external redirects here; we define them ourselves.
400 +
401 + // We set up this custom header to indicate to search engines not to index this page.
402 + header( 'X-Robots-Tag: noindex, nofollow' );
403 + die( 0 );
404 + }
405 +}
406 +
407 +/**
408 + * Handle the display of the email sharing button.
409 + */
410 +class Share_Email_Block extends Sharing_Source_Block {
411 + /**
412 + * Service short name.
413 + *
414 + * @var string
415 + */
416 + public $shortname = 'email';
417 +
418 + /**
419 + * Service name.
420 + *
421 + * @return string
422 + */
423 + public function get_name() {
424 + return _x( 'Email', 'as sharing source', 'jetpack' );
425 + }
426 +
427 + /**
428 + * Helper function to return a nonce action based on the current post.
429 + *
430 + * @param int $post_id The current post id if it is defined.
431 + * @return string The nonce action name.
432 + */
433 + protected function get_email_share_nonce_action( $post_id ) {
434 + if ( ! empty( $post_id ) ) {
435 + return 'jetpack-email-share-' . $post_id;
436 + }
437 +
438 + return 'jetpack-email-share';
439 + }
440 +
441 + /**
442 + * Get the URL for the link.
443 + *
444 + * @param int $post_id Post ID.
445 + * @param string $query Additional query arguments to add to the link. They should be in 'foo=bar&baz=1' format.
446 + * @param bool|string $id Sharing ID to include in the data-shared attribute.
447 + * @param array $data_attributes The keys are used as additional attribute names with 'data-' prefix.
448 + * The values are used as the attribute values.
449 + * @return object Link related data (url and data_attributes);
450 + */
451 + public function get_link( $post_id, $query = '', $id = false, $data_attributes = array() ) {
452 + // We don't need to open new window, so we set it to false.
453 + $id = false;
454 + $tracking_url = $this->get_process_request_url( $post_id );
455 + if ( false === stripos( $tracking_url, '?' ) ) {
456 + $tracking_url .= '?';
457 + } else {
458 + $tracking_url .= '&';
459 + }
460 + $tracking_url .= 'share=email';
461 +
462 + $data_attributes = array(
463 + 'email-share-error-title' => __( 'Do you have email set up?', 'jetpack' ),
464 + 'email-share-error-text' => __(
465 + "If you're having problems sharing via email, you might not have email set up for your browser. You may need to create a new email yourself.",
466 + 'jetpack'
467 + ),
468 + 'email-share-nonce' => wp_create_nonce( $this->get_email_share_nonce_action( $post_id ) ),
469 + 'email-share-track-url' => $tracking_url,
470 + );
471 +
472 + $post_title = $this->get_share_title( $post_id );
473 + $post_url = $this->get_share_url( $post_id );
474 +
475 + /** This filter is documented in plugins/jetpack/modules/sharedaddy/sharedaddy.php */
476 + $email_subject = apply_filters(
477 + 'wp_sharing_email_send_post_subject',
478 + sprintf( '[%s] %s', __( 'Shared Post', 'jetpack' ), $post_title )
479 + );
480 +
481 + $mailto_query = sprintf(
482 + 'subject=%s&body=%s&share=email',
483 + rawurlencode( $email_subject ),
484 + rawurlencode( $post_url )
485 + );
486 +
487 + $url = $this->get_url( 'mailto:', $mailto_query, $id );
488 + $data_attributes = $this->get_data_attributes( $id, $data_attributes );
489 +
490 + return array(
491 + 'url' => $url,
492 + 'data_attributes' => $data_attributes,
493 + );
494 + }
495 +
496 + /**
497 + * Process sharing request. Add actions that need to happen when sharing here.
498 + *
499 + * @param WP_Post $post Post object.
500 + * @param array $post_data Array of information about the post we're sharing.
501 + *
502 + * @return never
503 + */
504 + public function process_request( $post, array $post_data ) {
505 + $is_ajax = false;
506 + if (
507 + isset( $_SERVER['HTTP_X_REQUESTED_WITH'] )
508 + && strtolower( sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_REQUESTED_WITH'] ) ) ) === 'xmlhttprequest'
509 + ) {
510 + $is_ajax = true;
511 + }
512 +
513 + // Require an AJAX-driven submit and a valid nonce to process the request
514 + if (
515 + $is_ajax
516 + && isset( $post_data['email-share-nonce'] )
517 + && wp_verify_nonce( $post_data['email-share-nonce'], $this->get_email_share_nonce_action( $post ) )
518 + ) {
519 + // Ensure that we bump stats
520 + parent::process_request( $post, $post_data );
521 + }
522 +
523 + if ( $is_ajax ) {
524 + // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
525 + wp_send_json_success( null, null, JSON_UNESCAPED_SLASHES );
526 + } else {
527 + wp_safe_redirect( get_permalink( $post->ID ) . '?shared=email&msg=fail' );
528 + exit( 0 );
529 + }
530 + }
531 +}
532 +
533 +/**
534 + * Facebook sharing button.
535 + */
536 +class Share_Facebook_Block extends Sharing_Source_Block {
537 + /**
538 + * Service short name.
539 + *
540 + * @var string
541 + */
542 + public $shortname = 'facebook';
543 +
544 + /**
545 + * Sharing type.
546 + *
547 + * @var string
548 + */
549 + private $share_type = 'default';
550 +
551 + /**
552 + * Service name.
553 + *
554 + * @return string
555 + */
556 + public function get_name() {
557 + return __( 'Facebook', 'jetpack' );
558 + }
559 +
560 + /**
561 + * Process sharing request. Add actions that need to happen when sharing here.
562 + *
563 + * @param WP_Post $post Post object.
564 + * @param array $post_data Array of information about the post we're sharing.
565 + *
566 + * @return void
567 + */
568 + public function process_request( $post, array $post_data ) {
569 + $post_id = $post instanceof WP_Post ? $post->ID : 0;
570 + $fb_url = 'https://www.facebook.com/sharer/sharer.php?u=' . rawurlencode( $this->get_share_url( $post_id ) ) . '&t=' . rawurlencode( $this->get_share_title( $post_id ) );
571 +
572 + // Record stats
573 + parent::process_request( $post, $post_data );
574 +
575 + parent::redirect_request( $fb_url );
576 + }
577 +}
578 +
579 +/**
580 + * Print button.
581 + */
582 +class Share_Print_Block extends Sharing_Source_Block {
583 + /**
584 + * Service short name.
585 + *
586 + * @var string
587 + */
588 + public $shortname = 'print';
589 +
590 + /**
591 + * Service name.
592 + *
593 + * @return string
594 + */
595 + public function get_name() {
596 + return __( 'Print', 'jetpack' );
597 + }
598 +}
599 +
600 +/**
601 + * Native Share button (relying on the Web Share API).
602 + */
603 +class Share_Native_Block extends Sharing_Source_Block {
604 + /**
605 + * Service short name.
606 + *
607 + * @var string
608 + */
609 + public $shortname = 'native';
610 +
611 + /**
612 + * Service name.
613 + *
614 + * @return string
615 + */
616 + public function get_name() {
617 + return __( 'Web Share', 'jetpack' );
618 + }
619 +}
620 +
621 +/**
622 + * Tumblr sharing service.
623 + */
624 +class Share_Tumblr_Block extends Sharing_Source_Block {
625 + /**
626 + * Service short name.
627 + *
628 + * @var string
629 + */
630 + public $shortname = 'tumblr';
631 +
632 + /**
633 + * Service name.
634 + *
635 + * @return string
636 + */
637 + public function get_name() {
638 + return __( 'Tumblr', 'jetpack' );
639 + }
640 +
641 + /**
642 + * Process sharing request. Add actions that need to happen when sharing here.
643 + *
644 + * @param WP_Post $post Post object.
645 + * @param array $post_data Array of information about the post we're sharing.
646 + *
647 + * @return void
648 + */
649 + public function process_request( $post, array $post_data ) {
650 + // Record stats
651 + parent::process_request( $post, $post_data );
652 +
653 + // Redirect to Tumblr's sharing endpoint (a la their bookmarklet)
654 + $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=';
655 +
656 + parent::redirect_request( $url );
657 + }
658 +}
659 +
660 +/**
661 + * Pinterest sharing service.
662 + */
663 +class Share_Pinterest_Block extends Sharing_Source_Block {
664 + /**
665 + * Service short name.
666 + *
667 + * @var string
668 + */
669 + public $shortname = 'pinterest';
670 +
671 + /**
672 + * Service name.
673 + *
674 + * @return string
675 + */
676 + public function get_name() {
677 + return __( 'Pinterest', 'jetpack' );
678 + }
679 +
680 + /**
681 + * Get image representative of the post to pass on to Pinterest.
682 + *
683 + * @param WP_Post $post Post object.
684 + *
685 + * @return string
686 + */
687 + public function get_image( $post ) {
688 + $image = Images::get_image( $post->ID, array( 'fallback_to_avatars' => true ) );
689 + if ( ! empty( $image ) ) {
690 + return $image['src'];
691 + }
692 +
693 + /**
694 + * Filters the default image used by the Pinterest Pin It share button.
695 + *
696 + * @module sharedaddy
697 + *
698 + * @since 3.6.0
699 + *
700 + * @param string $url Default image URL.
701 + */
702 + return apply_filters( 'jetpack_sharing_pinterest_default_image', 'https://s0.wp.com/i/blank.jpg' );
703 + }
704 +
705 + /**
706 + * Get Pinterest external sharing URL.
707 + *
708 + * @param WP_Post $post Post object.
709 + *
710 + * @return string
711 + */
712 + public function get_external_url( $post ) {
713 + $url = 'https://www.pinterest.com/pin/create/link/?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&media=' . rawurlencode( $this->get_image( $post ) ) . '&description=' . rawurlencode( $post->post_title );
714 +
715 + /**
716 + * Filters the Pinterest share URL used in sharing button output.
717 + *
718 + * @module sharedaddy
719 + *
720 + * @since 3.6.0
721 + *
722 + * @param string $url Pinterest share URL.
723 + */
724 + return apply_filters( 'jetpack_sharing_pinterest_share_url', $url );
725 + }
726 +
727 + /**
728 + * Get Pinterest widget type.
729 + *
730 + * @return string
731 + */
732 + public function get_widget_type() {
733 + /**
734 + * Filters the Pinterest widget type.
735 + *
736 + * @see https://business.pinterest.com/en/widget-builder
737 + *
738 + * @module sharedaddy
739 + *
740 + * @since 3.6.0
741 + *
742 + * @param string $type Pinterest widget type. Default of 'buttonPin' for single-image selection. 'buttonBookmark' for multi-image modal.
743 + */
744 + return apply_filters( 'jetpack_sharing_pinterest_widget_type', 'buttonPin' );
745 + }
746 +
747 + /**
748 + * Process sharing request. Add actions that need to happen when sharing here.
749 + *
750 + * @param WP_Post $post Post object.
751 + * @param array $post_data Array of information about the post we're sharing.
752 + *
753 + * @return void
754 + */
755 + public function process_request( $post, array $post_data ) {
756 + // Record stats
757 + parent::process_request( $post, $post_data );
758 + // If we're triggering the multi-select panel, then we don't need to redirect to Pinterest
759 + if ( ! isset( $_GET['js_only'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
760 + $pinterest_url = esc_url_raw( $this->get_external_url( $post ) );
761 + parent::redirect_request( $pinterest_url );
762 + } else {
763 + echo '// share count bumped';
764 + die( 0 );
765 + }
766 + }
767 +}
768 +
769 +/**
770 + * Telegram sharing service.
771 + */
772 +class Share_Telegram_Block extends Sharing_Source_Block {
773 + /**
774 + * Service short name.
775 + *
776 + * @var string
777 + */
778 + public $shortname = 'telegram';
779 +
780 + /**
781 + * Service name.
782 + *
783 + * @return string
784 + */
785 + public function get_name() {
786 + return __( 'Telegram', 'jetpack' );
787 + }
788 +
789 + /**
790 + * Process sharing request. Add actions that need to happen when sharing here.
791 + *
792 + * @param WP_Post $post Post object.
793 + * @param array $post_data Array of information about the post we're sharing.
794 + *
795 + * @return void
796 + */
797 + public function process_request( $post, array $post_data ) {
798 + // Record stats
799 + parent::process_request( $post, $post_data );
800 +
801 + $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 ) ) );
802 +
803 + parent::redirect_request( $telegram_url );
804 + }
805 +}
806 +
807 +/**
808 + * WhatsApp sharing service.
809 + */
810 +class Jetpack_Share_WhatsApp_Block extends Sharing_Source_Block {
811 + /**
812 + * Service short name.
813 + *
814 + * @var string
815 + */
816 + public $shortname = 'jetpack-whatsapp';
817 +
818 + /**
819 + * Service name.
820 + *
821 + * @return string
822 + */
823 + public function get_name() {
824 + return __( 'WhatsApp', 'jetpack' );
825 + }
826 +
827 + /**
828 + * Process sharing request. Add actions that need to happen when sharing here.
829 + *
830 + * @param WP_Post $post Post object.
831 + * @param array $post_data Array of information about the post we're sharing.
832 + *
833 + * @return void
834 + */
835 + public function process_request( $post, array $post_data ) {
836 + // Record stats
837 + parent::process_request( $post, $post_data );
838 +
839 + // Firefox for desktop doesn't handle the "api.whatsapp.com" URL properly, so use "web.whatsapp.com"
840 + if ( User_Agent_Info::is_firefox_desktop() ) {
841 + $url = 'https://web.whatsapp.com/send?text=';
842 + } else {
843 + $url = 'https://api.whatsapp.com/send?text=';
844 + }
845 +
846 + $url .= rawurlencode( $this->get_share_title( $post->ID ) . ' ' . $this->get_share_url( $post->ID ) );
847 +
848 + parent::redirect_request( $url );
849 + }
850 +}
851 +
852 +/**
853 + * Mastodon sharing service.
854 + */
855 +class Share_Mastodon_Block extends Sharing_Source_Block {
856 + /**
857 + * Service short name.
858 + *
859 + * @var string
860 + */
861 + public $shortname = 'mastodon';
862 +
863 + /**
864 + * Service name.
865 + *
866 + * @return string
867 + */
868 + public function get_name() {
869 + return __( 'Mastodon', 'jetpack' );
870 + }
871 +
872 + /**
873 + * Process sharing request. Add actions that need to happen when sharing here.
874 + *
875 + * @param WP_Post $post Post object.
876 + * @param array $post_data Array of information about the post we're sharing.
877 + *
878 + * @return void
879 + */
880 + public function process_request( $post, array $post_data ) {
881 + if ( empty( $_POST['jetpack-mastodon-instance'] ) ) {
882 + require_once __DIR__ . '/components/class-jetpack-mastodon-modal.php';
883 + add_action( 'template_redirect', array( Jetpack_Mastodon_Modal::class, 'modal' ) );
884 + return;
885 + }
886 +
887 + check_admin_referer( 'jetpack_share_mastodon_instance' );
888 +
889 + $mastodon_instance = isset( $_POST['jetpack-mastodon-instance'] )
890 + ? trailingslashit( sanitize_text_field( wp_unslash( $_POST['jetpack-mastodon-instance'] ) ) )
891 + : null;
892 +
893 + $post_title = $this->get_share_title( $post->ID );
894 + $post_link = $this->get_share_url( $post->ID );
895 + $post_tags = $this->get_share_tags( $post->ID );
896 +
897 + /**
898 + * Allow filtering the default message that gets posted to Mastodon.
899 + *
900 + * @module sharedaddy
901 + * @since 11.9
902 + *
903 + * @param string $share_url The default message that gets posted to Mastodon.
904 + * @param WP_Post $post The post object.
905 + * @param array $post_data Array of information about the post we're sharing.
906 + */
907 + $shared_message = apply_filters(
908 + 'jetpack_sharing_mastodon_default_message',
909 + $post_title . ' ' . $post_link . ' ' . $post_tags,
910 + $post,
911 + $post_data
912 + );
913 +
914 + $share_url = sprintf(
915 + '%1$sshare?text=%2$s',
916 + $mastodon_instance,
917 + rawurlencode( $shared_message )
918 + );
919 +
920 + // Record stats
921 + parent::process_request( $post, $post_data );
922 +
923 + parent::redirect_request( $share_url );
924 + }
925 +}
926 +
927 +/**
928 + * Nextdoor sharing service.
929 + */
930 +class Share_Nextdoor_Block extends Sharing_Source_Block {
931 + /**
932 + * Service short name.
933 + *
934 + * @var string
935 + */
936 + public $shortname = 'nextdoor';
937 +
938 + /**
939 + * Service name.
940 + *
941 + * @return string
942 + */
943 + public function get_name() {
944 + return __( 'Nextdoor', 'jetpack' );
945 + }
946 +
947 + /**
948 + * Process sharing request. Add actions that need to happen when sharing here.
949 + *
950 + * @param WP_Post $post Post object.
951 + * @param array $post_data Array of information about the post we're sharing.
952 + *
953 + * @return void
954 + */
955 + public function process_request( $post, array $post_data ) {
956 + // Record stats
957 + parent::process_request( $post, $post_data );
958 +
959 + $url = 'https://nextdoor.com/sharekit/?source=jetpack&body=';
960 + $url .= rawurlencode( $this->get_share_title( $post->ID ) . ' ' . $this->get_share_url( $post->ID ) );
961 +
962 + parent::redirect_request( $url );
963 + }
964 +}
965 +
966 +/**
967 + * Bluesky sharing button.
968 + */
969 +class Share_Bluesky_Block extends Sharing_Source_Block {
970 + /**
971 + * Service short name.
972 + *
973 + * @var string
974 + */
975 + public $shortname = 'bluesky';
976 +
977 + /**
978 + * Service name.
979 + *
980 + * @return string
981 + */
982 + public function get_name() {
983 + return __( 'Bluesky', 'jetpack' );
984 + }
985 +
986 + /**
987 + * Process sharing request. Add actions that need to happen when sharing here.
988 + *
989 + * @param WP_Post $post Post object.
990 + * @param array $post_data Array of information about the post we're sharing.
991 + *
992 + * @return void
993 + */
994 + public function process_request( $post, array $post_data ) {
995 + // Record stats
996 + parent::process_request( $post, $post_data );
997 +
998 + $url = 'https://bsky.app/intent/compose?text=';
999 + $url .= rawurlencode( $this->get_share_title( $post->ID ) . ' ' . $this->get_share_url( $post->ID ) );
1000 +
1001 + parent::redirect_request( $url );
1002 + }
1003 +}
1004 +
1005 +/**
1006 + * X sharing button.
1007 + *
1008 + * While the old Twitter button had an official button,
1009 + * this new X button does not, since there is no official X button yet.
1010 + */
1011 +class Share_X_Block extends Sharing_Source_Block {
1012 + /**
1013 + * Service short name.
1014 + *
1015 + * @var string
1016 + */
1017 + public $shortname = 'x';
1018 +
1019 + /**
1020 + * Length of a URL on X.
1021 + * https://developer.twitter.com/en/docs/tco
1022 + *
1023 + * @var int
1024 + */
1025 + public $short_url_length = 24;
1026 +
1027 + /**
1028 + * Service name.
1029 + *
1030 + * @return string
1031 + */
1032 + public function get_name() {
1033 + return __( 'X', 'jetpack' );
1034 + }
1035 +
1036 + /**
1037 + * Determine the X 'via' value for a post.
1038 + *
1039 + * @param WP_Post|int $post Post object or post ID.
1040 + * @return string X handle without the preceding @.
1041 + **/
1042 + public static function sharing_x_via( $post ) {
1043 + $post = get_post( $post );
1044 + /** This filter is documented in modules/sharedaddy/sharing-sources.php */
1045 + $twitter_site_tag_value = apply_filters(
1046 + 'jetpack_twitter_cards_site_tag',
1047 + '',
1048 + /** This action is documented in modules/sharedaddy/sharing-sources.php */
1049 + array( 'twitter:creator' => apply_filters( 'jetpack_sharing_twitter_via', '', $post->ID ) )
1050 + );
1051 +
1052 + /*
1053 + * Hack to remove the unwanted behavior of adding 'via @jetpack' which
1054 + * was introduced with the adding of the Twitter cards.
1055 + * This should be a temporary solution until a better method is setup.
1056 + */
1057 + if ( 'jetpack' === $twitter_site_tag_value ) {
1058 + $twitter_site_tag_value = '';
1059 + }
1060 +
1061 + /** This filter is documented in modules/sharedaddy/sharing-sources.php */
1062 + $twitter_site_tag_value = apply_filters( 'jetpack_sharing_twitter_via', $twitter_site_tag_value, $post->ID );
1063 +
1064 + // Strip out anything other than a letter, number, or underscore.
1065 + // This will prevent the inadvertent inclusion of an extra @, as well as normalizing the handle.
1066 + return preg_replace( '/[^\da-z_]+/i', '', $twitter_site_tag_value );
1067 + }
1068 +
1069 + /**
1070 + * Determine the 'related' X accounts for a post.
1071 + *
1072 + * @param WP_Post|int $post Post object or post ID.
1073 + * @return string Comma-separated list of X handles.
1074 + **/
1075 + public static function get_related_accounts( $post ) {
1076 + $post = get_post( $post );
1077 + /** This filter is documented in modules/sharedaddy/sharing-sources.php */
1078 + $related_accounts = apply_filters( 'jetpack_sharing_twitter_related', array(), $post->ID );
1079 +
1080 + // Example related string: account1,account2:Account 2 description,account3
1081 + $related = array();
1082 +
1083 + foreach ( $related_accounts as $related_account_username => $related_account_description ) {
1084 + // Join the description onto the end of the username
1085 + if ( $related_account_description ) {
1086 + $related_account_username .= ':' . $related_account_description;
1087 + }
1088 +
1089 + $related[] = $related_account_username;
1090 + }
1091 +
1092 + return implode( ',', $related );
1093 + }
1094 +
1095 + /**
1096 + * Process sharing request. Add actions that need to happen when sharing here.
1097 + *
1098 + * @param WP_Post $post Post object.
1099 + * @param array $post_data Array of information about the post we're sharing.
1100 + *
1101 + * @return void
1102 + */
1103 + public function process_request( $post, array $post_data ) {
1104 + $post_title = $this->get_share_title( $post->ID );
1105 + $post_link = $this->get_share_url( $post->ID );
1106 +
1107 + if ( function_exists( 'mb_stripos' ) ) {
1108 + $strlen = 'mb_strlen';
1109 + $substr = 'mb_substr';
1110 + } else {
1111 + $strlen = 'strlen';
1112 + $substr = 'substr';
1113 + }
1114 +
1115 + $via = static::sharing_x_via( $post );
1116 + $related = static::get_related_accounts( $post );
1117 + if ( $via ) {
1118 + $sig = " via @$via";
1119 + if ( $related === $via ) {
1120 + $related = false;
1121 + }
1122 + } else {
1123 + $via = false;
1124 + $sig = '';
1125 + }
1126 +
1127 + $suffix_length = $this->short_url_length + $strlen( $sig );
1128 + // $sig is handled by twitter in their 'via' argument.
1129 + // $post_link is handled by twitter in their 'url' argument.
1130 + if ( 280 < $strlen( $post_title ) + $suffix_length ) {
1131 + // The -1 is for "\xE2\x80\xA6", a UTF-8 ellipsis.
1132 + $text = $substr( $post_title, 0, 280 - $suffix_length - 1 ) . "\xE2\x80\xA6";
1133 + } else {
1134 + $text = $post_title;
1135 + }
1136 +
1137 + // Record stats
1138 + parent::process_request( $post, $post_data );
1139 +
1140 + $url = $post_link;
1141 + $twitter_url = add_query_arg(
1142 + rawurlencode_deep( array_filter( compact( 'via', 'related', 'text', 'url' ) ) ),
1143 + 'https://x.com/intent/tweet'
1144 + );
1145 +
1146 + parent::redirect_request( $twitter_url );
1147 + }
1148 +}
1149 +
1150 +/**
1151 + * Twitter sharing button.
1152 + */
1153 +class Share_Twitter_Block extends Sharing_Source_Block {
1154 + /**
1155 + * Service short name.
1156 + *
1157 + * @var string
1158 + */
1159 + public $shortname = 'twitter';
1160 +
1161 + /**
1162 + * Length of a URL on Twitter.
1163 + * 'https://dev.twitter.com/rest/reference/get/help/configuration'
1164 + * ( 2015/02/06 ) short_url_length is 22, short_url_length_https is 23
1165 + *
1166 + * @var int
1167 + */
1168 + public $short_url_length = 24;
1169 +
1170 + /**
1171 + * Service name.
1172 + *
1173 + * @return string
1174 + */
1175 + public function get_name() {
1176 + return __( 'X', 'jetpack' );
1177 + }
1178 +
1179 + /**
1180 + * Determine the Twitter 'via' value for a post.
1181 + *
1182 + * @param WP_Post|int $post Post object or post ID.
1183 + * @return string Twitter handle without the preceding @.
1184 + **/
1185 + public static function sharing_twitter_via( $post ) {
1186 + $post = get_post( $post );
1187 + /**
1188 + * Allow third-party plugins to customize the Twitter username used as "twitter:site" Twitter Card Meta Tag.
1189 + *
1190 + * @module sharedaddy
1191 + *
1192 + * @since 3.0.0
1193 + *
1194 + * @param string $string Twitter Username.
1195 + * @param array $args Array of Open Graph Meta Tags and Twitter Cards tags.
1196 + */
1197 + $twitter_site_tag_value = apply_filters(
1198 + 'jetpack_twitter_cards_site_tag',
1199 + '',
1200 + /** This action is documented in modules/sharedaddy/sharing-sources.php */
1201 + array( 'twitter:creator' => apply_filters( 'jetpack_sharing_twitter_via', '', $post->ID ) )
1202 + );
1203 +
1204 + /*
1205 + * Hack to remove the unwanted behavior of adding 'via @jetpack' which
1206 + * was introduced with the adding of the Twitter cards.
1207 + * This should be a temporary solution until a better method is setup.
1208 + */
1209 + if ( 'jetpack' === $twitter_site_tag_value ) {
1210 + $twitter_site_tag_value = '';
1211 + }
1212 +
1213 + /**
1214 + * Filters the Twitter username used as "via" in the Twitter sharing button.
1215 + *
1216 + * @module sharedaddy
1217 + *
1218 + * @since 1.7.0
1219 + *
1220 + * @param string $twitter_site_tag_value Twitter Username.
1221 + * @param int $post->ID Post ID.
1222 + */
1223 + $twitter_site_tag_value = apply_filters( 'jetpack_sharing_twitter_via', $twitter_site_tag_value, $post->ID );
1224 +
1225 + // Strip out anything other than a letter, number, or underscore.
1226 + // This will prevent the inadvertent inclusion of an extra @, as well as normalizing the handle.
1227 + return preg_replace( '/[^\da-z_]+/i', '', $twitter_site_tag_value );
1228 + }
1229 +
1230 + /**
1231 + * Determine the 'related' Twitter accounts for a post.
1232 + *
1233 + * @param WP_Post|int $post Post object or post ID.
1234 + * @return string Comma-separated list of Twitter handles.
1235 + **/
1236 + public static function get_related_accounts( $post ) {
1237 + $post = get_post( $post );
1238 + /**
1239 + * Filter the list of related Twitter accounts added to the Twitter sharing button.
1240 + *
1241 + * @module sharedaddy
1242 + *
1243 + * @since 1.7.0
1244 + *
1245 + * @param array $args Array of Twitter usernames. Format is 'username' => 'Optional description'
1246 + * @param int $post->ID Post ID.
1247 + */
1248 + $related_accounts = apply_filters( 'jetpack_sharing_twitter_related', array(), $post->ID );
1249 +
1250 + // Example related string: account1,account2:Account 2 description,account3
1251 + $related = array();
1252 +
1253 + foreach ( $related_accounts as $related_account_username => $related_account_description ) {
1254 + // Join the description onto the end of the username
1255 + if ( $related_account_description ) {
1256 + $related_account_username .= ':' . $related_account_description;
1257 + }
1258 +
1259 + $related[] = $related_account_username;
1260 + }
1261 +
1262 + return implode( ',', $related );
1263 + }
1264 +
1265 + /**
1266 + * Process sharing request. Add actions that need to happen when sharing here.
1267 + *
1268 + * @param WP_Post $post Post object.
1269 + * @param array $post_data Array of information about the post we're sharing.
1270 + *
1271 + * @return void
1272 + */
1273 + public function process_request( $post, array $post_data ) {
1274 + $post_title = $this->get_share_title( $post->ID );
1275 + $post_link = $this->get_share_url( $post->ID );
1276 +
1277 + if ( function_exists( 'mb_stripos' ) ) {
1278 + $strlen = 'mb_strlen';
1279 + $substr = 'mb_substr';
1280 + } else {
1281 + $strlen = 'strlen';
1282 + $substr = 'substr';
1283 + }
1284 +
1285 + $via = static::sharing_twitter_via( $post );
1286 + $related = static::get_related_accounts( $post );
1287 + if ( $via ) {
1288 + $sig = " via @$via";
1289 + if ( $related === $via ) {
1290 + $related = false;
1291 + }
1292 + } else {
1293 + $via = false;
1294 + $sig = '';
1295 + }
1296 +
1297 + $suffix_length = $this->short_url_length + $strlen( $sig );
1298 + // $sig is handled by twitter in their 'via' argument.
1299 + // $post_link is handled by twitter in their 'url' argument.
1300 + if ( 280 < $strlen( $post_title ) + $suffix_length ) {
1301 + // The -1 is for "\xE2\x80\xA6", a UTF-8 ellipsis.
1302 + $text = $substr( $post_title, 0, 280 - $suffix_length - 1 ) . "\xE2\x80\xA6";
1303 + } else {
1304 + $text = $post_title;
1305 + }
1306 +
1307 + // Record stats
1308 + parent::process_request( $post, $post_data );
1309 +
1310 + $url = $post_link;
1311 + $twitter_url = add_query_arg(
1312 + rawurlencode_deep( array_filter( compact( 'via', 'related', 'text', 'url' ) ) ),
1313 + 'https://x.com/intent/tweet'
1314 + );
1315 +
1316 + parent::redirect_request( $twitter_url );
1317 + }
1318 +}
1319 +
1320 +/**
1321 + * Reddit sharing button.
1322 + */
1323 +class Share_Reddit_Block extends Sharing_Source_Block {
1324 + /**
1325 + * Service short name.
1326 + *
1327 + * @var string
1328 + */
1329 + public $shortname = 'reddit';
1330 +
1331 + /**
1332 + * Service name.
1333 + *
1334 + * @return string
1335 + */
1336 + public function get_name() {
1337 + return __( 'Reddit', 'jetpack' );
1338 + }
1339 +
1340 + /**
1341 + * Process sharing request. Add actions that need to happen when sharing here.
1342 + *
1343 + * @param WP_Post $post Post object.
1344 + * @param array $post_data Array of information about the post we're sharing.
1345 + *
1346 + * @return void
1347 + */
1348 + public function process_request( $post, array $post_data ) {
1349 + $reddit_url = $this->http() . '://reddit.com/submit?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&title=' . rawurlencode( $this->get_share_title( $post->ID ) );
1350 +
1351 + // Record stats
1352 + parent::process_request( $post, $post_data );
1353 +
1354 + parent::redirect_request( $reddit_url );
1355 + }
1356 +}
1357 +
1358 +/**
1359 + * LinkedIn sharing button.
1360 + */
1361 +class Share_LinkedIn_Block extends Sharing_Source_Block {
1362 + /**
1363 + * Service short name.
1364 + *
1365 + * @var string
1366 + */
1367 + public $shortname = 'linkedin';
1368 +
1369 + /**
1370 + * Service name.
1371 + *
1372 + * @return string
1373 + */
1374 + public function get_name() {
1375 + return __( 'LinkedIn', 'jetpack' );
1376 + }
1377 +
1378 + /**
1379 + * Process sharing request. Add actions that need to happen when sharing here.
1380 + *
1381 + * @param WP_Post $post Post object.
1382 + * @param array $post_data Array of information about the post we're sharing.
1383 + *
1384 + * @return void
1385 + */
1386 + public function process_request( $post, array $post_data ) {
1387 +
1388 + $post_link = $this->get_share_url( $post->ID );
1389 +
1390 + $linkedin_url = add_query_arg(
1391 + array(
1392 + 'url' => rawurlencode( $post_link ),
1393 + ),
1394 + 'https://www.linkedin.com/sharing/share-offsite/'
1395 + );
1396 +
1397 + // Record stats
1398 + parent::process_request( $post, $post_data );
1399 +
1400 + parent::redirect_request( $linkedin_url );
1401 + }
1402 +}
1403 +
1404 +/**
1405 + * Threads sharing button.
1406 + */
1407 +class Share_Threads_Block extends Sharing_Source_Block {
1408 + /**
1409 + * Service short name.
1410 + *
1411 + * @var string
1412 + */
1413 + public $shortname = 'threads';
1414 +
1415 + /**
1416 + * Service name.
1417 + *
1418 + * @return string
1419 + */
1420 + public function get_name() {
1421 + return __( 'Threads', 'jetpack' );
1422 + }
1423 +
1424 + /**
1425 + * Process sharing request. Add actions that need to happen when sharing here.
1426 + *
1427 + * @param WP_Post $post Post object.
1428 + * @param array $post_data Array of information about the post we're sharing.
1429 + *
1430 + * @return void
1431 + */
1432 + public function process_request( $post, array $post_data ) {
1433 + // Record stats
1434 + parent::process_request( $post, $post_data );
1435 +
1436 + $url = 'https://www.threads.net/intent/post/?text=';
1437 + $url .= rawurlencode( $this->get_share_title( $post->ID ) . ' ' . $this->get_share_url( $post->ID ) );
1438 +
1439 + parent::redirect_request( $url );
1440 + }
1441 +}