PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.2
Jetpack – WP Security, Backup, Speed, & Growth v16.2
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 13.7.2 13.8.3 13.9.2 14.0.1 All 504 releases
← All changes | modules/sharedaddy/sharing-sources.php +351 -264 12.9.516.2 View file →
@@ -5,9 +5,14 @@
5 5 * phpcs:disable Generic.Files.OneObjectStructurePerFile.MultipleFound
6 6 */
7 7
8 8 use Automattic\Jetpack\Device_Detection\User_Agent_Info;
9 +use Automattic\Jetpack\Post_Media\Images;
9 10
11 +if ( ! defined( 'ABSPATH' ) ) {
12 + exit( 0 );
13 +}
14 +
10 15 /**
11 16 * Base class for sharing sources.
12 17 * See individual sharing classes below for the implementation of this class.
13 18 */
@@ -26,8 +31,15 @@
26 31 */
27 32 public $smart;
28 33
29 34 /**
35 + * Service short name.
36 + *
37 + * @var string
38 + */
39 + public $shortname;
40 +
41 + /**
30 42 * Should the sharing link open in a new tab.
31 43 *
32 44 * @var bool
33 45 */
@@ -147,9 +159,9 @@
147 159 * @param string $post->post_title Post Title.
148 160 * @param int $post_id Post ID.
149 161 * @param int $this->id Sharing ID.
150 162 */
151 - $title = apply_filters( 'sharing_title', $post->post_title, $post_id, $this->id );
163 + $title = apply_filters( 'sharing_title', $post->post_title ?? '', $post_id, $this->id );
152 164
153 165 return html_entity_decode( wp_kses( $title, '' ), ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 );
154 166 }
155 167
@@ -206,9 +218,9 @@
206 218 * Get the HTML markup to display a sharing link.
207 219 *
208 220 * @param string $url Post URL to share.
209 221 * @param string $text Sharing display text.
210 - * @param string $title The title for the link.
222 + * @param string $accessible_name Accessible name for the link.
211 223 * @param string $query Additional query arguments to add to the link. They should be in 'foo=bar&baz=1' format.
212 224 * @param bool|string $id Sharing ID to include in the data-shared attribute.
213 225 * @param array $data_attributes The keys are used as additional attribute names with 'data-' prefix.
214 226 * The values are used as the attribute values.
@@ -214,9 +226,9 @@
214 226 * The values are used as the attribute values.
215 227 *
216 228 * @return string The HTML for the link.
217 229 */
218 - public function get_link( $url, $text, $title, $query = '', $id = false, $data_attributes = array() ) {
230 + public function get_link( $url, $text, $accessible_name = '', $query = '', $id = false, $data_attributes = array() ) {
219 231 $args = func_get_args();
220 232 $klasses = array( 'share-' . $this->get_class(), 'sd-button' );
221 233
222 234 if ( 'icon' === $this->button_style || 'icon-text' === $this->button_style ) {
@@ -223,14 +235,13 @@
223 235 $klasses[] = 'share-icon';
224 236 }
225 237
226 238 if ( 'icon' === $this->button_style ) {
227 - $text = $title;
228 239 $klasses[] = 'no-text';
240 + }
229 241
230 - if ( true === $this->open_link_in_new ) {
231 - $text .= __( ' (Opens in new window)', 'jetpack' );
232 - }
242 + if ( true === $this->open_link_in_new ) {
243 + $accessible_name .= __( ' (Opens in new window)', 'jetpack' );
233 244 }
234 245
235 246 /**
236 247 * Filter the sharing display ID.
@@ -291,8 +302,9 @@
291 302 $url .= '&' . $query;
292 303 }
293 304 }
294 305
306 + // @phan-suppress-next-line PhanSuspiciousValueComparison
295 307 if ( 'text' === $this->button_style ) {
296 308 $klasses[] = 'no-icon';
297 309 }
298 310
@@ -314,8 +326,9 @@
314 326 *
315 327 * @module sharedaddy
316 328 *
317 329 * @since 3.4.0
330 + * @deprecated 14.6 Use jetpack_sharing_accessible_name instead.
318 331 *
319 332 * @param string $title Sharing service title.
320 333 * @param object $this Sharing service properties.
321 334 * @param string|false $id Sharing ID.
@@ -320,10 +333,24 @@
320 333 * @param object $this Sharing service properties.
321 334 * @param string|false $id Sharing ID.
322 335 * @param array $args Array of sharing service options.
323 336 */
324 - $title = apply_filters( 'jetpack_sharing_display_title', $title, $this, $id, $args );
337 + $accessible_name = apply_filters_deprecated( 'jetpack_sharing_display_title', array( $accessible_name, $this, $id, $args ), '14.6', 'jetpack_sharing_accessible_name' );
338 +
325 339 /**
340 + * Filter the sharing accessible name.
341 + *
342 + * @module sharedaddy
343 + *
344 + * @since 14.6
345 + *
346 + * @param string $accessible_name Sharing service accessible name.
347 + * @param object $this Sharing service properties.
348 + * @param string|false $id Sharing ID.
349 + * @param array $args Array of sharing service options.
350 + */
351 + $accessible_name = apply_filters( 'jetpack_sharing_accessible_name', $accessible_name, $this, $id, $args );
352 + /**
326 353 * Filter the sharing display text.
327 354 *
328 355 * @module sharedaddy
329 356 *
@@ -350,13 +377,21 @@
350 377 * @param array $args Array of sharing service options.
351 378 */
352 379 $data_attributes = apply_filters( 'jetpack_sharing_data_attributes', (array) $data_attributes, $this, $id, $args );
353 380
381 + $id_attr = $id ? esc_attr( $id ) : '';
354 382 $encoded_data_attributes = '';
355 383 if ( ! empty( $data_attributes ) ) {
384 + // Check for aria-labelledby first, and separate this out.
385 + if ( isset( $data_attributes['aria-labelledby'] ) ) {
386 + $id_attr = $data_attributes['aria-labelledby'];
387 + unset( $data_attributes['aria-labelledby'] );
388 + }
389 +
356 390 $encoded_data_attributes = implode(
357 391 ' ',
358 392 array_map(
393 + /** Filter for formatting attributes */
359 394 function ( $data_key, $data_value ) {
360 395 return sprintf(
361 396 'data-%s="%s"',
362 397 esc_attr( str_replace( array( ' ', '"' ), '', $data_key ) ),
@@ -368,19 +403,34 @@
368 403 )
369 404 );
370 405 }
371 406
407 + $rel_attr = ( true === $this->open_link_in_new ) ? 'noopener noreferrer' : '';
408 + $target_attr = ( true === $this->open_link_in_new ) ? 'target="_blank"' : '';
409 +
410 + $classes = implode( ' ', $klasses );
411 +
372 412 return sprintf(
373 - '<a rel="nofollow%s" data-shared="%s" class="%s" href="%s"%s title="%s" %s><span%s>%s</span></a>',
374 - ( true === $this->open_link_in_new ) ? ' noopener noreferrer' : '',
375 - ( $id ? esc_attr( $id ) : '' ),
376 - implode( ' ', $klasses ),
377 - $url,
378 - ( true === $this->open_link_in_new ) ? ' target="_blank"' : '',
379 - $title,
413 + '<a rel="nofollow %s"
414 + data-shared="%s"
415 + class="%s"
416 + href="%s"
417 + %s
418 + aria-labelledby="%s"
419 + %s>
420 + <span id="%s" hidden>%s</span>
421 + <span>%s</span>
422 + </a>',
423 + $rel_attr,
424 + $id_attr,
425 + esc_attr( $classes ),
426 + esc_url( $url ),
427 + $target_attr,
428 + $id_attr,
380 429 $encoded_data_attributes,
381 - ( 'icon' === $this->button_style ) ? '></span><span class="sharing-screen-reader-text"' : '',
382 - $text
430 + $id_attr,
431 + esc_html( $accessible_name ),
432 + esc_html( $text )
383 433 );
384 434 }
385 435
386 436 /**
@@ -458,9 +508,9 @@
458 508 protected function build_amp_markup( $attrs = array() ) {
459 509
460 510 $title = sprintf(
461 511 /* translators: placeholder is a service name, such as "Twitter" or "Facebook". */
462 - __( 'Click to share on %s', 'jetpack' ),
512 + __( 'Share on %s', 'jetpack' ),
463 513 $this->get_name()
464 514 );
465 515
466 516 $attrs = array_merge(
@@ -550,9 +600,9 @@
550 600 */
551 601 public function get_total( $post = false ) {
552 602 global $wpdb, $blog_id;
553 603
554 - $name = strtolower( $this->get_id() );
604 + $name = strtolower( (string) $this->get_id() );
555 605
556 606 if ( $post === false ) {
557 607 // get total number of shares for service
558 608 return (int) $wpdb->get_var( $wpdb->prepare( 'SELECT SUM( count ) FROM sharing_stats WHERE blog_id = %d AND share_service = %s', $blog_id, $name ) );
@@ -570,9 +620,9 @@
570 620 public function get_posts_total() {
571 621 global $wpdb, $blog_id;
572 622
573 623 $totals = array();
574 - $name = strtolower( $this->get_id() );
624 + $name = strtolower( (string) $this->get_id() );
575 625
576 626 $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 ) );
577 627
578 628 if ( ! empty( $my_data ) ) {
@@ -616,8 +666,9 @@
616 666 /**
617 667 * Redirect to an external social network site to finish sharing.
618 668 *
619 669 * @param string $url Sharing URL for a given service.
670 + * @return never
620 671 */
621 672 public function redirect_request( $url ) {
622 673 wp_redirect( $url ); // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect -- We allow external redirects here; we define them ourselves.
623 674
@@ -622,14 +673,26 @@
622 673 wp_redirect( $url ); // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect -- We allow external redirects here; we define them ourselves.
623 674
624 675 // We set up this custom header to indicate to search engines not to index this page.
625 676 header( 'X-Robots-Tag: noindex, nofollow' );
626 - die();
677 + die( 0 );
627 678 }
628 679
629 680 /**
630 - * Add extra JavaScript to a sharing service.
681 + * Register a sharing service's popup window features with the front-end script.
631 682 *
683 + * Services that open their share link in a popup publish the window features
684 + * they need in `window.WPCOM_sharing_popups`. A single delegated click handler
685 + * in sharing.js reads them and opens the popup, so no per-service handler is
686 + * emitted.
687 + *
688 + * $name has to be the same slug that appears in the share link's `share-<name>`
689 + * class, since that class is all the handler has to look the features back up
690 + * with. Every caller passes $this->shortname, which works because get_link()
691 + * builds the class from get_class() and the built-in services register under
692 + * the slug they declare as their shortname. Share_Custom is the exception: its
693 + * class and shortname do not round-trip, but it does not register a popup.
694 + *
632 695 * @param string $name Sharing service name.
633 696 * @param array $params Array of sharing options.
634 697 *
635 698 * @return void
@@ -654,41 +717,13 @@
654 717
655 718 // Add JS after sharing-js has been enqueued.
656 719 wp_add_inline_script(
657 720 'sharing-js',
658 - "var windowOpen;
659 - ( function () {
660 - function matches( el, sel ) {
661 - return !! (
662 - el.matches && el.matches( sel ) ||
663 - el.msMatchesSelector && el.msMatchesSelector( sel )
664 - );
665 - }
666 -
667 - document.body.addEventListener( 'click', function ( event ) {
668 - if ( ! event.target ) {
669 - return;
670 - }
671 -
672 - var el;
673 - if ( matches( event.target, 'a.share-$name' ) ) {
674 - el = event.target;
675 - } else if ( event.target.parentNode && matches( event.target.parentNode, 'a.share-$name' ) ) {
676 - el = event.target.parentNode;
677 - }
678 -
679 - if ( el ) {
680 - event.preventDefault();
681 -
682 - // If there's another sharing window open, close it.
683 - if ( typeof windowOpen !== 'undefined' ) {
684 - windowOpen.close();
685 - }
686 - windowOpen = window.open( el.getAttribute( 'href' ), 'wpcom$name', '$opts' );
687 - return false;
688 - }
689 - } );
690 - } )();"
721 + sprintf(
722 + "window.WPCOM_sharing_popups = window.WPCOM_sharing_popups || {};\nwindow.WPCOM_sharing_popups[ %s ] = %s;",
723 + wp_json_encode( (string) $name, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ),
724 + wp_json_encode( $opts, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP )
725 + )
691 726 );
692 727 }
693 728 }
694 729
@@ -950,9 +985,9 @@
950 985 *
951 986 * @param WP_Post $post Post object.
952 987 * @param array $post_data Array of information about the post we're sharing.
953 988 *
954 - * @return void
989 + * @return never
955 990 */
956 991 public function process_request( $post, array $post_data ) {
957 992 $is_ajax = false;
958 993 if (
@@ -972,15 +1007,14 @@
972 1007 parent::process_request( $post, $post_data );
973 1008 }
974 1009
975 1010 if ( $is_ajax ) {
976 - wp_send_json_success();
1011 + // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
1012 + wp_send_json_success( null, null, JSON_UNESCAPED_SLASHES );
977 1013 } else {
978 1014 wp_safe_redirect( get_permalink( $post->ID ) . '?shared=email&msg=fail' );
979 - exit;
1015 + exit( 0 );
980 1016 }
981 -
982 - wp_die();
983 1017 }
984 1018
985 1019 /**
986 1020 * Get the markup of the sharing button.
@@ -1005,8 +1039,9 @@
1005 1039 'jetpack'
1006 1040 ),
1007 1041 'email-share-nonce' => wp_create_nonce( $this->get_email_share_nonce_action( $post ) ),
1008 1042 'email-share-track-url' => $tracking_url,
1043 + 'aria-labelledby' => 'sharing-email-' . $post->ID,
1009 1044 );
1010 1045
1011 1046 $post_title = $this->get_share_title( $post->ID );
1012 1047 $post_url = $this->get_share_url( $post->ID );
@@ -1025,9 +1060,9 @@
1025 1060
1026 1061 return $this->get_link(
1027 1062 'mailto:',
1028 1063 _x( 'Email', 'share to', 'jetpack' ),
1029 - __( 'Click to email a link to a friend', 'jetpack' ),
1064 + __( 'Email a link to a friend', 'jetpack' ),
1030 1065 $mailto_query,
1031 1066 false,
1032 1067 $data_attributes
1033 1068 );
@@ -1048,9 +1083,10 @@
1048 1083 }
1049 1084 }
1050 1085
1051 1086 /**
1052 - * Twitter sharing button.
1087 + * Legacy Twitter sharing button.
1088 + * Share_X is the new Twitter sharing button.
1053 1089 */
1054 1090 class Share_Twitter extends Sharing_Source {
1055 1091 /**
1056 1092 * Service short name.
@@ -1063,9 +1099,9 @@
1063 1099 * Service icon font code.
1064 1100 *
1065 1101 * @var string
1066 1102 */
1067 - public $icon = '\f202';
1103 + public $icon = '\f10e';
1068 1104
1069 1105 /**
1070 1106 * Length of a URL on Twitter.
1071 1107 * 'https://dev.twitter.com/rest/reference/get/help/configuration'
@@ -1096,9 +1132,9 @@
1096 1132 *
1097 1133 * @return string
1098 1134 */
1099 1135 public function get_name() {
1100 - return __( 'Twitter', 'jetpack' );
1136 + return __( 'X', 'jetpack' );
1101 1137 }
1102 1138
1103 1139 /**
1104 1140 * Determine the Twitter 'via' value for a post.
@@ -1235,9 +1271,9 @@
1235 1271 apply_filters( 'jetpack_register_post_for_share_counts', true, $post->ID, 'twitter' )
1236 1272 ) {
1237 1273 sharing_register_post_for_share_counts( $post->ID );
1238 1274 }
1239 - 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 );
1275 + return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'X', 'share to', 'jetpack' ), __( 'Share on X', 'jetpack' ), 'share=twitter', 'sharing-twitter-' . $post->ID );
1240 1276 }
1241 1277 }
1242 1278
1243 1279 /**
@@ -1287,9 +1323,9 @@
1287 1323
1288 1324 $url = $post_link;
1289 1325 $twitter_url = add_query_arg(
1290 1326 rawurlencode_deep( array_filter( compact( 'via', 'related', 'text', 'url' ) ) ),
1291 - 'https://twitter.com/intent/tweet'
1327 + 'https://x.com/intent/tweet'
1292 1328 );
1293 1329
1294 1330 parent::redirect_request( $twitter_url );
1295 1331 }
@@ -1346,8 +1382,24 @@
1346 1382 */
1347 1383 public $short_url_length = 24;
1348 1384
1349 1385 /**
1386 + * Constructor.
1387 + *
1388 + * @param int $id Sharing source ID.
1389 + * @param array $settings Sharing settings.
1390 + */
1391 + public function __construct( $id, array $settings ) {
1392 + parent::__construct( $id, $settings );
1393 +
1394 + if ( 'official' === $this->button_style ) {
1395 + $this->smart = true;
1396 + } else {
1397 + $this->smart = false;
1398 + }
1399 + }
1400 +
1401 + /**
1350 1402 * Service name.
1351 1403 *
1352 1404 * @return string
1353 1405 */
@@ -1362,15 +1414,49 @@
1362 1414 *
1363 1415 * @return string
1364 1416 */
1365 1417 public function get_display( $post ) {
1366 - return $this->get_link(
1367 - $this->get_process_request_url( $post->ID ),
1368 - _x( 'X', 'share to', 'jetpack' ),
1369 - __( 'Click to share on X', 'jetpack' ),
1370 - 'share=x',
1371 - 'sharing-x-' . $post->ID
1372 - );
1418 + $via = static::sharing_x_via( $post );
1419 +
1420 + if ( $via ) {
1421 + $via = 'data-via="' . esc_attr( $via ) . '"';
1422 + } else {
1423 + $via = '';
1424 + }
1425 +
1426 + $related = static::get_related_accounts( $post );
1427 + if ( ! empty( $related ) && $related !== $via ) {
1428 + $related = 'data-related="' . esc_attr( $related ) . '"';
1429 + } else {
1430 + $related = '';
1431 + }
1432 +
1433 + if ( $this->smart ) {
1434 + $share_url = $this->get_share_url( $post->ID );
1435 + $post_title = $this->get_share_title( $post->ID );
1436 + return sprintf(
1437 + '<a href="https://x.com/share" class="twitter-share-button" data-url="%1$s" data-text="%2$s" %3$s %4$s>%5$s</a>',
1438 + esc_url( $share_url ),
1439 + esc_attr( $post_title ),
1440 + $via,
1441 + $related,
1442 + esc_html__( 'Post', 'jetpack' )
1443 + );
1444 + } else {
1445 + if (
1446 + /** This filter is documented in modules/sharedaddy/sharing-sources.php */
1447 + apply_filters( 'jetpack_register_post_for_share_counts', true, $post->ID, 'x' )
1448 + ) {
1449 + sharing_register_post_for_share_counts( $post->ID );
1450 + }
1451 + return $this->get_link(
1452 + $this->get_process_request_url( $post->ID ),
1453 + _x( 'X', 'share to', 'jetpack' ),
1454 + __( 'Share on X', 'jetpack' ),
1455 + 'share=x',
1456 + 'sharing-x-' . $post->ID
1457 + );
1458 + }
1373 1459 }
1374 1460
1375 1461 /**
1376 1462 * Determine the X 'via' value for a post.
@@ -1434,9 +1520,15 @@
1434 1520 /**
1435 1521 * Add content specific to a service in the footer.
1436 1522 */
1437 1523 public function display_footer() {
1438 - $this->js_dialog( $this->shortname, array( 'height' => 350 ) );
1524 + if ( $this->smart ) {
1525 + ?>
1526 + <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>
1527 + <?php
1528 + } else {
1529 + $this->js_dialog( $this->shortname, array( 'height' => 350 ) );
1530 + }
1439 1531 }
1440 1532
1441 1533 /**
1442 1534 * Process sharing request. Add actions that need to happen when sharing here.
@@ -1490,8 +1582,17 @@
1490 1582 );
1491 1583
1492 1584 parent::redirect_request( $twitter_url );
1493 1585 }
1586 +
1587 + /**
1588 + * Does this sharing source have a custom style.
1589 + *
1590 + * @return bool
1591 + */
1592 + public function has_custom_button_style() {
1593 + return $this->smart;
1594 + }
1494 1595 }
1495 1596
1496 1597 /**
1497 1598 * Reddit sharing button.
@@ -1530,10 +1631,11 @@
1530 1631 public function get_display( $post ) {
1531 1632 return $this->get_link(
1532 1633 $this->get_process_request_url( $post->ID ),
1533 1634 _x( 'Reddit', 'share to', 'jetpack' ),
1534 - __( 'Click to share on Reddit', 'jetpack' ),
1535 - 'share=reddit'
1635 + __( 'Share on Reddit', 'jetpack' ),
1636 + 'share=reddit',
1637 + 'sharing-reddit-' . $post->ID
1536 1638 );
1537 1639 }
1538 1640
1539 1641 /**
@@ -1632,9 +1734,9 @@
1632 1734 if ( $this->smart ) {
1633 1735 $share_url = $this->get_share_url( $post->ID );
1634 1736 $display .= sprintf( '<div class="linkedin_button"><script type="in/share" data-url="%s" data-counter="right"></script></div>', esc_url( $share_url ) );
1635 1737 } else {
1636 - $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 );
1738 + $display = $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'LinkedIn', 'share to', 'jetpack' ), __( 'Share on LinkedIn', 'jetpack' ), 'share=linkedin', 'sharing-linkedin-' . $post->ID );
1637 1739 }
1638 1740
1639 1741 /** This filter is already documented in modules/sharedaddy/sharing-sources.php */
1640 1742 if ( apply_filters( 'jetpack_register_post_for_share_counts', true, $post->ID, 'linkedin' ) ) {
@@ -1655,15 +1757,13 @@
1655 1757 public function process_request( $post, array $post_data ) {
1656 1758
1657 1759 $post_link = $this->get_share_url( $post->ID );
1658 1760
1659 - // Using the same URL as the official button, which is *not* LinkedIn's documented sharing link
1660 - // https://www.linkedin.com/cws/share?url={url}&token=&isFramed=false
1661 1761 $linkedin_url = add_query_arg(
1662 1762 array(
1663 1763 'url' => rawurlencode( $post_link ),
1664 1764 ),
1665 - 'https://www.linkedin.com/cws/share?token=&isFramed=false'
1765 + 'https://www.linkedin.com/sharing/share-offsite/'
1666 1766 );
1667 1767
1668 1768 // Record stats
1669 1769 parent::process_request( $post, $post_data );
@@ -1859,9 +1959,9 @@
1859 1959 /** This filter is already documented in modules/sharedaddy/sharing-sources.php */
1860 1960 if ( apply_filters( 'jetpack_register_post_for_share_counts', true, $post->ID, 'facebook' ) ) {
1861 1961 sharing_register_post_for_share_counts( $post->ID );
1862 1962 }
1863 - 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 );
1963 + return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Facebook', 'share to', 'jetpack' ), __( 'Share on Facebook', 'jetpack' ), 'share=facebook', 'sharing-facebook-' . $post->ID );
1864 1964 }
1865 1965
1866 1966 /**
1867 1967 * AMP display for Facebook.
@@ -1885,9 +1985,9 @@
1885 1985 *
1886 1986 * @return void
1887 1987 */
1888 1988 public function process_request( $post, array $post_data ) {
1889 - $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 ) );
1989 + $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 ) );
1890 1990
1891 1991 // Record stats
1892 1992 parent::process_request( $post, $post_data );
1893 1993
@@ -1982,9 +2082,9 @@
1982 2082 *
1983 2083 * @return string
1984 2084 */
1985 2085 public function get_display( $post ) {
1986 - 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' ) );
2086 + return $this->get_link( $this->get_process_request_url( $post->ID ) . ( ( is_single() || is_page() ) ? '#print' : '' ), _x( 'Print', 'share to', 'jetpack' ), __( 'Print', 'jetpack' ), 'share=print', 'sharing-print-' . $post->ID );
1987 2087 }
1988 2088
1989 2089 /**
1990 2090 * AMP display for Print.
@@ -2073,9 +2173,9 @@
2073 2173 }
2074 2174
2075 2175 if ( empty( $blogs ) ) {
2076 2176 wp_safe_redirect( get_permalink( $post->ID ) );
2077 - die();
2177 + die( 0 );
2078 2178 }
2079 2179
2080 2180 $blog = current( $blogs );
2081 2181
@@ -2102,9 +2202,9 @@
2102 2202 *
2103 2203 * @return string
2104 2204 */
2105 2205 public function get_display( $post ) {
2106 - 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' );
2206 + return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Press This', 'share to', 'jetpack' ), __( 'Press This!', 'jetpack' ), 'share=press-this', 'sharing-press-this-' . $post->ID );
2107 2207 }
2108 2208
2109 2209 /**
2110 2210 * No AMP display for PressThis.
@@ -2221,14 +2321,18 @@
2221 2321 $this->get_process_request_url( $post->ID ),
2222 2322 esc_html( $this->name ),
2223 2323 sprintf(
2224 2324 /* Translators: placeholder is the name of a social network. */
2225 - __( 'Click to share on %s', 'jetpack' ),
2325 + __( 'Share on %s', 'jetpack' ),
2226 2326 esc_attr( $this->name )
2227 2327 ),
2228 - 'share=' . $this->id
2328 + 'share=' . $this->id,
2329 + 'sharing-custom-' . $post->ID
2229 2330 );
2230 - return str_replace( '<span>', '<span style="' . esc_attr( 'background-image:url("' . addcslashes( esc_url_raw( $this->icon ), '"' ) . '");' ) . '">', $str );
2331 +
2332 + $style = 'background-image:url("' . addcslashes( esc_url_raw( $this->icon ), '"' ) . '");';
2333 + $class = ( 'icon' === $this->button_style ) ? ' class="custom-sharing-span"' : '';
2334 + return str_replace( '<span>', '<span' . $class . ' style="' . esc_attr( $style ) . '">', $str );
2231 2335 }
2232 2336
2233 2337 /**
2234 2338 * No AMP display for custom elements.
@@ -2248,9 +2352,9 @@
2248 2352 * @return void
2249 2353 */
2250 2354 public function process_request( $post, array $post_data ) {
2251 2355 $url = str_replace( '&amp;', '&', $this->url );
2252 - $url = str_replace( '%post_id%', rawurlencode( $post->ID ), $url );
2356 + $url = str_replace( '%post_id%', rawurlencode( (string) $post->ID ), $url );
2253 2357 $url = str_replace( '%post_url%', rawurlencode( $this->get_share_url( $post->ID ) ), $url );
2254 2358 $url = str_replace( '%post_full_url%', rawurlencode( get_permalink( $post->ID ) ), $url );
2255 2359 $url = str_replace( '%post_title%', rawurlencode( $this->get_share_title( $post->ID ) ), $url );
2256 2360 $url = str_replace( '%home_url%', rawurlencode( home_url() ), $url );
@@ -2477,9 +2581,9 @@
2477 2581 * If we are not looking at a single post, content from other posts can appear on the page and Tumblr will pick that up.
2478 2582 * 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.
2479 2583 */
2480 2584 if ( ! is_single() ) {
2481 - $posttype = 'data-posttype="link"';
2585 + $posttype = ' data-posttype="link"'; // Leading space separates it from the preceding title attribute.
2482 2586 } else {
2483 2587 $posttype = '';
2484 2588 }
2485 2589
@@ -2484,18 +2588,19 @@
2484 2588 }
2485 2589
2486 2590 // Documentation: https://www.tumblr.com/docs/en/share_button
2487 2591 return sprintf(
2488 - '<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>',
2592 + '<a class="tumblr-share-button" target="%1$s" href="%2$s" data-title="%3$s" data-content="%4$s" title="%5$s"%6$s>%7$s</a>',
2489 2593 $target,
2490 2594 'https://www.tumblr.com/share',
2491 - $this->get_share_title( $post->ID ),
2492 - $this->get_share_url( $post->ID ),
2493 - __( 'Share on Tumblr', 'jetpack' ),
2494 - $posttype
2595 + esc_attr( $this->get_share_title( $post->ID ) ),
2596 + esc_url( $this->get_share_url( $post->ID ) ),
2597 + esc_attr__( 'Share on Tumblr', 'jetpack' ),
2598 + $posttype,
2599 + esc_html__( 'Share on Tumblr', 'jetpack' )
2495 2600 );
2496 2601 } else {
2497 - return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Tumblr', 'share to', 'jetpack' ), __( 'Click to share on Tumblr', 'jetpack' ), 'share=tumblr' );
2602 + return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Tumblr', 'share to', 'jetpack' ), __( 'Share on Tumblr', 'jetpack' ), 'share=tumblr', 'sharing-tumblr-' . $post->ID );
2498 2603 }
2499 2604 }
2500 2605
2501 2606 /**
@@ -2587,13 +2692,11 @@
2587 2692 *
2588 2693 * @return string
2589 2694 */
2590 2695 public function get_image( $post ) {
2591 - if ( class_exists( 'Jetpack_PostImages' ) ) {
2592 - $image = Jetpack_PostImages::get_image( $post->ID, array( 'fallback_to_avatars' => true ) );
2593 - if ( ! empty( $image ) ) {
2594 - return $image['src'];
2595 - }
2696 + $image = Images::get_image( $post->ID, array( 'fallback_to_avatars' => true ) );
2697 + if ( ! empty( $image ) ) {
2698 + return $image['src'];
2596 2699 }
2597 2700
2598 2701 /**
2599 2702 * Filters the default image used by the Pinterest Pin It share button.
@@ -2614,9 +2717,9 @@
2614 2717 *
2615 2718 * @return string
2616 2719 */
2617 2720 public function get_external_url( $post ) {
2618 - $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 );
2721 + $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 );
2619 2722
2620 2723 /**
2621 2724 * Filters the Pinterest share URL used in sharing button output.
2622 2725 *
@@ -2665,9 +2768,9 @@
2665 2768 esc_url( $this->get_external_url( $post ) ),
2666 2769 esc_attr( $this->get_widget_type() )
2667 2770 );
2668 2771 } else {
2669 - $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 );
2772 + $display = $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Pinterest', 'share to', 'jetpack' ), __( 'Share on Pinterest', 'jetpack' ), 'share=pinterest', 'sharing-pinterest-' . $post->ID );
2670 2773 }
2671 2774
2672 2775 /** This filter is already documented in modules/sharedaddy/sharing-sources.php */
2673 2776 if ( apply_filters( 'jetpack_register_post_for_share_counts', true, $post->ID, 'linkedin' ) ) {
@@ -2693,9 +2796,9 @@
2693 2796 $pinterest_url = esc_url_raw( $this->get_external_url( $post ) );
2694 2797 parent::redirect_request( $pinterest_url );
2695 2798 } else {
2696 2799 echo '// share count bumped';
2697 - die();
2800 + die( 0 );
2698 2801 }
2699 2802 }
2700 2803
2701 2804 /**
@@ -2789,143 +2892,8 @@
2789 2892 }
2790 2893 }
2791 2894
2792 2895 /**
2793 - * Pocket sharing service.
2794 - */
2795 -class Share_Pocket extends Sharing_Source {
2796 - /**
2797 - * Service short name.
2798 - *
2799 - * @var string
2800 - */
2801 - public $shortname = 'pocket';
2802 -
2803 - /**
2804 - * Service icon font code.
2805 - *
2806 - * @var string
2807 - */
2808 - public $icon = '\f224';
2809 -
2810 - /**
2811 - * Constructor.
2812 - *
2813 - * @param int $id Sharing source ID.
2814 - * @param array $settings Sharing settings.
2815 - */
2816 - public function __construct( $id, array $settings ) {
2817 - parent::__construct( $id, $settings );
2818 -
2819 - if ( 'official' === $this->button_style ) {
2820 - $this->smart = true;
2821 - } else {
2822 - $this->smart = false;
2823 - }
2824 - }
2825 -
2826 - /**
2827 - * Service name.
2828 - *
2829 - * @return string
2830 - */
2831 - public function get_name() {
2832 - return __( 'Pocket', 'jetpack' );
2833 - }
2834 -
2835 - /**
2836 - * Process sharing request. Add actions that need to happen when sharing here.
2837 - *
2838 - * @param WP_Post $post Post object.
2839 - * @param array $post_data Array of information about the post we're sharing.
2840 - *
2841 - * @return void
2842 - */
2843 - public function process_request( $post, array $post_data ) {
2844 - // Record stats
2845 - parent::process_request( $post, $post_data );
2846 -
2847 - $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 ) ) );
2848 -
2849 - parent::redirect_request( $pocket_url );
2850 - }
2851 -
2852 - /**
2853 - * Get the markup of the sharing button.
2854 - *
2855 - * @param WP_Post $post Post object.
2856 - *
2857 - * @return string
2858 - */
2859 - public function get_display( $post ) {
2860 - if ( $this->smart ) {
2861 - $post_count = 'horizontal';
2862 -
2863 - $button = '';
2864 - $button .= '<div class="pocket_button">';
2865 - $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' ) );
2866 - $button .= '</div>';
2867 -
2868 - return $button;
2869 - } else {
2870 - return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Pocket', 'share to', 'jetpack' ), __( 'Click to share on Pocket', 'jetpack' ), 'share=pocket' );
2871 - }
2872 - }
2873 -
2874 - /**
2875 - * AMP display for Pocket.
2876 - *
2877 - * @param \WP_Post $post The current post being viewed.
2878 - */
2879 - public function get_amp_display( $post ) {
2880 - $attrs = array(
2881 - '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 ) ) ),
2882 - );
2883 -
2884 - return $this->build_amp_markup( $attrs );
2885 - }
2886 -
2887 - /**
2888 - * Add content specific to a service in the footer.
2889 - */
2890 - public function display_footer() {
2891 - if ( $this->smart ) :
2892 - ?>
2893 - <script>
2894 - ( function () {
2895 - var currentScript = document.currentScript;
2896 -
2897 - // Don't use Pocket's default JS as it we need to force init new Pocket share buttons loaded via JS.
2898 - function jetpack_sharing_pocket_init() {
2899 - var script = document.createElement( 'script' );
2900 - var prev = currentScript || document.getElementsByTagName( 'script' )[ 0 ];
2901 - script.setAttribute( 'async', true );
2902 - script.setAttribute( 'src', 'https://widgets.getpocket.com/v1/j/btn.js?v=1' );
2903 - prev.parentNode.insertBefore( script, prev );
2904 - }
2905 -
2906 - if ( document.readyState === 'loading' ) {
2907 - document.addEventListener( 'DOMContentLoaded', jetpack_sharing_pocket_init );
2908 - } else {
2909 - jetpack_sharing_pocket_init();
2910 - }
2911 - document.body.addEventListener( 'is.post-load', jetpack_sharing_pocket_init );
2912 - } )();
2913 - </script>
2914 - <?php
2915 - else :
2916 - $this->js_dialog(
2917 - $this->shortname,
2918 - array(
2919 - 'width' => 450,
2920 - 'height' => 450,
2921 - )
2922 - );
2923 - endif;
2924 - }
2925 -}
2926 -
2927 -/**
2928 2896 * Telegram sharing service.
2929 2897 */
2930 2898 class Share_Telegram extends Sharing_Source {
2931 2899 /**
@@ -2978,9 +2946,9 @@
2978 2946 *
2979 2947 * @return string
2980 2948 */
2981 2949 public function get_display( $post ) {
2982 - return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Telegram', 'share to', 'jetpack' ), __( 'Click to share on Telegram', 'jetpack' ), 'share=telegram' );
2950 + return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Telegram', 'share to', 'jetpack' ), __( 'Share on Telegram', 'jetpack' ), 'share=telegram', 'sharing-telegram-' . $post->ID );
2983 2951 }
2984 2952
2985 2953 /**
2986 2954 * AMP display for Telegram.
@@ -3046,9 +3014,9 @@
3046 3014 *
3047 3015 * @return string
3048 3016 */
3049 3017 public function get_display( $post ) {
3050 - 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' );
3018 + return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'WhatsApp', 'share to', 'jetpack' ), __( 'Share on WhatsApp', 'jetpack' ), 'share=jetpack-whatsapp', 'sharing-whatsapp-' . $post->ID );
3051 3019 }
3052 3020
3053 3021 /**
3054 3022 * AMP display for Whatsapp.
@@ -3088,29 +3056,8 @@
3088 3056 }
3089 3057 }
3090 3058
3091 3059 /**
3092 - * Skype sharing service.
3093 - */
3094 -class Share_Skype extends Deprecated_Sharing_Source {
3095 - /**
3096 - * Service short name.
3097 - *
3098 - * @var string
3099 - */
3100 - public $shortname = 'skype';
3101 -
3102 - /**
3103 - * Service name.
3104 - *
3105 - * @return string
3106 - */
3107 - public function get_name() {
3108 - return __( 'Skype', 'jetpack' );
3109 - }
3110 -}
3111 -
3112 -/**
3113 3060 * Mastodon sharing service.
3114 3061 */
3115 3062 class Share_Mastodon extends Sharing_Source {
3116 3063 /**
@@ -3146,9 +3093,9 @@
3146 3093 public function get_display( $post ) {
3147 3094 return $this->get_link(
3148 3095 $this->get_process_request_url( $post->ID ),
3149 3096 _x( 'Mastodon', 'share to', 'jetpack' ),
3150 - __( 'Click to share on Mastodon', 'jetpack' ),
3097 + __( 'Share on Mastodon', 'jetpack' ),
3151 3098 'share=mastodon',
3152 3099 'sharing-mastodon-' . $post->ID
3153 3100 );
3154 3101 }
@@ -3258,9 +3205,9 @@
3258 3205 public function get_display( $post ) {
3259 3206 return $this->get_link(
3260 3207 $this->get_process_request_url( $post->ID ),
3261 3208 _x( 'Nextdoor', 'share to', 'jetpack' ),
3262 - __( 'Click to share on Nextdoor', 'jetpack' ),
3209 + __( 'Share on Nextdoor', 'jetpack' ),
3263 3210 'share=nextdoor',
3264 3211 'sharing-nextdoor-' . $post->ID
3265 3212 );
3266 3213 }
@@ -3280,6 +3227,146 @@
3280 3227 $url = 'https://nextdoor.com/sharekit/?source=jetpack&body=';
3281 3228 $url .= rawurlencode( $this->get_share_title( $post->ID ) . ' ' . $this->get_share_url( $post->ID ) );
3282 3229
3283 3230 parent::redirect_request( $url );
3231 + }
3232 +}
3233 +
3234 +/**
3235 + * Threads sharing service.
3236 + */
3237 +class Share_Threads extends Sharing_Source {
3238 + /**
3239 + * Service short name.
3240 + *
3241 + * @var string
3242 + */
3243 + public $shortname = 'threads';
3244 +
3245 + /**
3246 + * Service icon font code.
3247 + *
3248 + * @var string
3249 + */
3250 + public $icon = '\f10d';
3251 +
3252 + /**
3253 + * Service name.
3254 + *
3255 + * @return string
3256 + */
3257 + public function get_name() {
3258 + return __( 'Threads', 'jetpack' );
3259 + }
3260 +
3261 + /**
3262 + * Get the markup of the sharing button.
3263 + *
3264 + * @param WP_Post $post Post object.
3265 + *
3266 + * @return string
3267 + */
3268 + public function get_display( $post ) {
3269 + return $this->get_link(
3270 + $this->get_process_request_url( $post->ID ),
3271 + _x( 'Threads', 'share to', 'jetpack' ),
3272 + __( 'Share on Threads', 'jetpack' ),
3273 + 'share=threads',
3274 + 'sharing-threads-' . $post->ID
3275 + );
3276 + }
3277 +
3278 + /**
3279 + * Process sharing request. Add actions that need to happen when sharing here.
3280 + *
3281 + * @param WP_Post $post Post object.
3282 + * @param array $post_data Array of information about the post we're sharing.
3283 + *
3284 + * @return void
3285 + */
3286 + public function process_request( $post, array $post_data ) {
3287 + // Record stats
3288 + parent::process_request( $post, $post_data );
3289 +
3290 + $url = 'https://threads.net/intent/post?text=';
3291 + $url .= rawurlencode( $this->get_share_title( $post->ID ) . ' ' . $this->get_share_url( $post->ID ) );
3292 +
3293 + parent::redirect_request( $url );
3294 + }
3295 +
3296 + /**
3297 + * Add content specific to a service in the footer.
3298 + */
3299 + public function display_footer() {
3300 + $this->js_dialog( $this->shortname );
3301 + }
3302 +}
3303 +
3304 +/**
3305 + * Bluesky sharing service.
3306 + */
3307 +class Share_Bluesky extends Sharing_Source {
3308 + /**
3309 + * Service short name.
3310 + *
3311 + * @var string
3312 + */
3313 + public $shortname = 'bluesky';
3314 +
3315 + /**
3316 + * Service icon font code.
3317 + *
3318 + * @var string
3319 + */
3320 + public $icon = '\f10f';
3321 +
3322 + /**
3323 + * Service name.
3324 + *
3325 + * @return string
3326 + */
3327 + public function get_name() {
3328 + return __( 'Bluesky', 'jetpack' );
3329 + }
3330 +
3331 + /**
3332 + * Get the markup of the sharing button.
3333 + *
3334 + * @param WP_Post $post Post object.
3335 + *
3336 + * @return string
3337 + */
3338 + public function get_display( $post ) {
3339 + return $this->get_link(
3340 + $this->get_process_request_url( $post->ID ),
3341 + _x( 'Bluesky', 'share to', 'jetpack' ),
3342 + __( 'Share on Bluesky', 'jetpack' ),
3343 + 'share=bluesky',
3344 + 'sharing-bluesky-' . $post->ID
3345 + );
3346 + }
3347 +
3348 + /**
3349 + * Process sharing request. Add actions that need to happen when sharing here.
3350 + *
3351 + * @param WP_Post $post Post object.
3352 + * @param array $post_data Array of information about the post we're sharing.
3353 + *
3354 + * @return void
3355 + */
3356 + public function process_request( $post, array $post_data ) {
3357 + // Record stats
3358 + parent::process_request( $post, $post_data );
3359 +
3360 + $url = 'https://bsky.app/intent/compose?text=';
3361 + $url .= rawurlencode( $this->get_share_title( $post->ID ) . ' ' . $this->get_share_url( $post->ID ) );
3362 +
3363 + parent::redirect_request( $url );
3364 + }
3365 +
3366 + /**
3367 + * Add content specific to a service in the footer.
3368 + */
3369 + public function display_footer() {
3370 + $this->js_dialog( $this->shortname );
3284 3371 }
3285 3372 }