| @@ -12,12 +12,14 @@ | ||
| 12 | 12 | |
| 13 | 13 | // phpcs:disable Universal.Files.SeparateFunctionsFromOO.Mixed -- TODO: Move classes to appropriately-named class files. |
| 14 | 14 | |
| 15 | 15 | use Automattic\Jetpack\Assets; |
| 16 | -use Automattic\Jetpack\Redirect; | |
| 17 | -use Automattic\Jetpack\Status; | |
| 18 | 16 | use Automattic\Jetpack\Sync\Settings; |
| 19 | 17 | |
| 18 | +if ( ! defined( 'ABSPATH' ) ) { | |
| 19 | + exit( 0 ); | |
| 20 | +} | |
| 21 | + | |
| 20 | 22 | require_once __DIR__ . '/sharing-sources.php'; |
| 21 | 23 | |
| 22 | 24 | define( 'WP_SHARING_PLUGIN_VERSION', JETPACK__VERSION ); |
| 23 | 25 | |
| @@ -71,9 +73,9 @@ | ||
| 71 | 73 | if ( isset( $all[ $id ] ) ) { |
| 72 | 74 | $config = array(); |
| 73 | 75 | |
| 74 | 76 | // Pre-load custom modules otherwise they won't know who they are |
| 75 | - if ( substr( $id, 0, 7 ) === 'custom-' && is_array( $options[ $id ] ) ) { | |
| 77 | + if ( str_starts_with( $id, 'custom-' ) && is_array( $options[ $id ] ) ) { | |
| 76 | 78 | $config = $options[ $id ]; |
| 77 | 79 | } |
| 78 | 80 | |
| 79 | 81 | $services[ $id ] = new $all[ $id ]( $id, $config ); |
| @@ -102,13 +104,15 @@ | ||
| 102 | 104 | 'reddit' => 'Share_Reddit', |
| 103 | 105 | 'twitter' => 'Share_Twitter', |
| 104 | 106 | 'tumblr' => 'Share_Tumblr', |
| 105 | 107 | 'pinterest' => 'Share_Pinterest', |
| 106 | - 'pocket' => 'Share_Pocket', | |
| 107 | 108 | 'telegram' => 'Share_Telegram', |
| 109 | + 'threads' => 'Share_Threads', | |
| 108 | 110 | 'jetpack-whatsapp' => 'Jetpack_Share_WhatsApp', |
| 109 | - 'skype' => 'Share_Skype', | |
| 110 | 111 | 'mastodon' => 'Share_Mastodon', |
| 112 | + 'nextdoor' => 'Share_Nextdoor', | |
| 113 | + 'x' => 'Share_X', | |
| 114 | + 'bluesky' => 'Share_Bluesky', | |
| 111 | 115 | ); |
| 112 | 116 | |
| 113 | 117 | if ( is_multisite() && is_plugin_active( 'press-this/press-this-plugin.php' ) ) { |
| 114 | 118 | $services['press-this'] = 'Share_PressThis'; |
| @@ -116,10 +120,12 @@ | ||
| 116 | 120 | |
| 117 | 121 | if ( $include_custom ) { |
| 118 | 122 | // Add any custom services in |
| 119 | 123 | $options = $this->get_global_options(); |
| 120 | - foreach ( (array) $options['custom'] as $custom_id ) { | |
| 121 | - $services[ $custom_id ] = 'Share_Custom'; | |
| 124 | + if ( isset( $options['custom'] ) ) { | |
| 125 | + foreach ( $options['custom'] as $custom_id ) { | |
| 126 | + $services[ $custom_id ] = 'Share_Custom'; | |
| 127 | + } | |
| 122 | 128 | } |
| 123 | 129 | } |
| 124 | 130 | |
| 125 | 131 | /** |
| @@ -277,9 +283,9 @@ | ||
| 277 | 283 | * This avoids issues on sites with corrupted options. |
| 278 | 284 | * |
| 279 | 285 | * @see https://github.com/Automattic/jetpack/issues/6121 |
| 280 | 286 | */ |
| 281 | - if ( ! is_array( $options ) || ! isset( $options['button_style'], $options['global'] ) ) { | |
| 287 | + if ( ! is_array( $options ) || ! isset( $options['button_style'] ) || ! isset( $options['global'] ) ) { | |
| 282 | 288 | $global_options = array( 'global' => $this->get_global_options() ); |
| 283 | 289 | $options = is_array( $options ) |
| 284 | 290 | ? array_merge( $options, $global_options ) |
| 285 | 291 | : $global_options; |
| @@ -290,10 +296,10 @@ | ||
| 290 | 296 | // Default services |
| 291 | 297 | if ( ! is_array( $enabled ) ) { |
| 292 | 298 | $enabled = array( |
| 293 | 299 | 'visible' => array( |
| 294 | - 'twitter', | |
| 295 | 300 | 'facebook', |
| 301 | + 'x', | |
| 296 | 302 | ), |
| 297 | 303 | 'hidden' => array(), |
| 298 | 304 | ); |
| 299 | 305 | |
| @@ -309,15 +315,15 @@ | ||
| 309 | 315 | $enabled = apply_filters( 'sharing_default_services', $enabled ); |
| 310 | 316 | } |
| 311 | 317 | |
| 312 | 318 | // Cleanup after any filters that may have produced duplicate services |
| 313 | - if ( is_array( $enabled['visible'] ) ) { | |
| 319 | + if ( isset( $enabled['visible'] ) && is_array( $enabled['visible'] ) ) { | |
| 314 | 320 | $enabled['visible'] = array_unique( $enabled['visible'] ); |
| 315 | 321 | } else { |
| 316 | 322 | $enabled['visible'] = array(); |
| 317 | 323 | } |
| 318 | 324 | |
| 319 | - if ( is_array( $enabled['hidden'] ) ) { | |
| 325 | + if ( isset( $enabled['hidden'] ) && is_array( $enabled['hidden'] ) ) { | |
| 320 | 326 | $enabled['hidden'] = array_unique( $enabled['hidden'] ); |
| 321 | 327 | } else { |
| 322 | 328 | $enabled['hidden'] = array(); |
| 323 | 329 | } |
| @@ -350,9 +356,9 @@ | ||
| 350 | 356 | */ |
| 351 | 357 | $blog = apply_filters( 'sharing_services_enabled', $blog ); |
| 352 | 358 | |
| 353 | 359 | // Add CSS for NASCAR |
| 354 | - if ( count( $blog['visible'] ) || count( $blog['hidden'] ) ) { | |
| 360 | + if ( ( is_countable( $blog['visible'] ) && count( $blog['visible'] ) ) || ( is_countable( $blog['hidden'] ) && count( $blog['hidden'] ) ) ) { | |
| 355 | 361 | add_filter( 'post_flair_block_css', 'post_flair_service_enabled_sharing' ); |
| 356 | 362 | } |
| 357 | 363 | |
| 358 | 364 | // Convenience for checking if a service is present |
| @@ -399,9 +405,9 @@ | ||
| 399 | 405 | 'button_style' => 'icon-text', |
| 400 | 406 | 'sharing_label' => $this->default_sharing_label, |
| 401 | 407 | 'open_links' => 'same', |
| 402 | 408 | 'show' => ! isset( $options['global'] ) ? array( 'post', 'page' ) : array(), |
| 403 | - 'custom' => isset( $options['global']['custom'] ) ? $options['global']['custom'] : array(), | |
| 409 | + 'custom' => $options['global']['custom'] ?? array(), | |
| 404 | 410 | ); |
| 405 | 411 | |
| 406 | 412 | /** |
| 407 | 413 | * Filters global sharing settings. |
| @@ -495,9 +501,9 @@ | ||
| 495 | 501 | break; |
| 496 | 502 | } |
| 497 | 503 | } |
| 498 | 504 | |
| 499 | - if ( false === $this->global['sharing_label'] ) { | |
| 505 | + if ( ! isset( $this->global['sharing_label'] ) || false === $this->global['sharing_label'] || $this->global['sharing_label'] === 'Share this:' ) { | |
| 500 | 506 | $this->global['sharing_label'] = $this->default_sharing_label; |
| 501 | 507 | } |
| 502 | 508 | |
| 503 | 509 | return $this->global; |
| @@ -505,14 +511,14 @@ | ||
| 505 | 511 | |
| 506 | 512 | /** |
| 507 | 513 | * Save a sharing service for use. |
| 508 | 514 | * |
| 509 | - * @param int $id Sharing unique ID. | |
| 510 | - * @param Sharing_Source $service Sharing service. | |
| 515 | + * @param int $id Sharing unique ID. | |
| 516 | + * @param Sharing_Advanced_Source $service Sharing service. | |
| 511 | 517 | * |
| 512 | 518 | * @return void |
| 513 | 519 | */ |
| 514 | - public function set_service( $id, Sharing_Source $service ) { | |
| 520 | + public function set_service( $id, Sharing_Advanced_Source $service ) { | |
| 515 | 521 | // Update the options for this service |
| 516 | 522 | $options = get_option( 'sharing-options' ); |
| 517 | 523 | |
| 518 | 524 | // No options yet |
| @@ -683,9 +689,11 @@ | ||
| 683 | 689 | $this->id = esc_html( $id ); |
| 684 | 690 | $this->service = $services->get_service( $id ); |
| 685 | 691 | $this->total = (int) $total; |
| 686 | 692 | |
| 687 | - $this->name = $this->service->get_name(); | |
| 693 | + if ( $this->service instanceof Sharing_Source ) { | |
| 694 | + $this->name = $this->service->get_name(); | |
| 695 | + } | |
| 688 | 696 | } |
| 689 | 697 | |
| 690 | 698 | /** |
| 691 | 699 | * Compare total shares between 2 posts. |
| @@ -692,15 +700,15 @@ | ||
| 692 | 700 | * |
| 693 | 701 | * @param object $a Sharing_Service_Total object. |
| 694 | 702 | * @param object $b Sharing_Service_Total object. |
| 695 | 703 | * |
| 696 | - * @return bool | |
| 704 | + * @return int -1, 0, or 1 if $a is <, =, or > $b | |
| 697 | 705 | */ |
| 698 | 706 | public static function cmp( $a, $b ) { |
| 699 | 707 | if ( $a->total === $b->total ) { |
| 700 | - return $a->name < $b->name; | |
| 708 | + return $b->name <=> $a->name; | |
| 701 | 709 | } |
| 702 | - return $a->total < $b->total; | |
| 710 | + return $b->total <=> $a->total; | |
| 703 | 711 | } |
| 704 | 712 | } |
| 705 | 713 | |
| 706 | 714 | /** |
| @@ -753,15 +761,15 @@ | ||
| 753 | 761 | * |
| 754 | 762 | * @param object $a Sharing_Post_Total object. |
| 755 | 763 | * @param object $b Sharing_Post_Total object. |
| 756 | 764 | * |
| 757 | - * @return bool | |
| 765 | + * @return int -1, 0, or 1 if $a is <, =, or > $b | |
| 758 | 766 | */ |
| 759 | 767 | public static function cmp( $a, $b ) { |
| 760 | 768 | if ( $a->total === $b->total ) { |
| 761 | - return $a->id < $b->id; | |
| 769 | + return $b->id <=> $a->id; | |
| 762 | 770 | } |
| 763 | - return $a->total < $b->total; | |
| 771 | + return $b->total <=> $a->total; | |
| 764 | 772 | } |
| 765 | 773 | } |
| 766 | 774 | |
| 767 | 775 | /** |
| @@ -864,9 +872,9 @@ | ||
| 864 | 872 | if ( $sharing_post_urls ) : |
| 865 | 873 | ?> |
| 866 | 874 | |
| 867 | 875 | <script type="text/javascript"> |
| 868 | - window.WPCOM_sharing_counts = <?php echo wp_json_encode( array_flip( $sharing_post_urls ) ); ?>; | |
| 876 | + window.WPCOM_sharing_counts = <?php echo wp_json_encode( array_flip( $sharing_post_urls ), JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ); ?>; | |
| 869 | 877 | </script> |
| 870 | 878 | <?php |
| 871 | 879 | endif; |
| 872 | 880 | endif; |
| @@ -899,9 +907,9 @@ | ||
| 899 | 907 | foreach ( array_merge( $enabled['visible'], $enabled['hidden'] ) as $service ) { |
| 900 | 908 | $service->display_header(); |
| 901 | 909 | } |
| 902 | 910 | |
| 903 | - if ( count( $enabled['all'] ) > 0 && sharing_maybe_enqueue_scripts() ) { | |
| 911 | + if ( is_countable( $enabled['all'] ) && ( count( $enabled['all'] ) > 0 ) && sharing_maybe_enqueue_scripts() ) { | |
| 904 | 912 | wp_enqueue_style( 'sharedaddy', plugin_dir_url( __FILE__ ) . 'sharing.css', array(), JETPACK__VERSION ); |
| 905 | 913 | wp_enqueue_style( 'social-logos' ); |
| 906 | 914 | } |
| 907 | 915 | } |
| @@ -924,17 +932,21 @@ | ||
| 924 | 932 | $service->process_request( $post, $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing |
| 925 | 933 | } |
| 926 | 934 | } |
| 927 | 935 | } |
| 928 | -add_action( 'template_redirect', 'sharing_process_requests', 9 ); | |
| 929 | 936 | |
| 937 | +// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Only checking for the data being present. | |
| 938 | +if ( isset( $_GET['share'] ) ) { | |
| 939 | + add_action( 'template_redirect', 'sharing_process_requests', 9 ); | |
| 940 | +} | |
| 941 | + | |
| 930 | 942 | /** |
| 931 | - * Gets the url to customise the sharing buttons in Calypso. | |
| 943 | + * Gets the url to customise the sharing buttons in WP-Admin. | |
| 932 | 944 | * |
| 933 | - * @return string the customisation URL or null if it couldn't be determinde. | |
| 945 | + * @return string the customisation URL. | |
| 934 | 946 | */ |
| 935 | 947 | function get_sharing_buttons_customisation_url() { |
| 936 | - return Redirect::get_url( 'calypso-marketing-sharing-buttons', array( 'site' => ( new Status() )->get_site_suffix() ) ); | |
| 948 | + return admin_url( 'options-general.php?page=sharing' ); | |
| 937 | 949 | } |
| 938 | 950 | |
| 939 | 951 | /** |
| 940 | 952 | * Append sharing links to text. |
| @@ -950,9 +962,10 @@ | ||
| 950 | 962 | if ( Settings::is_syncing() ) { |
| 951 | 963 | return $text; |
| 952 | 964 | } |
| 953 | 965 | |
| 954 | - if ( empty( $post ) ) { | |
| 966 | + // We require the post to not be empty and be an actual WordPress post object. If it's not - we just return. | |
| 967 | + if ( empty( $post ) || ! $post instanceof \WP_Post ) { | |
| 955 | 968 | return $text; |
| 956 | 969 | } |
| 957 | 970 | |
| 958 | 971 | if ( ( is_preview() || is_admin() ) && ! ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) { |
| @@ -963,8 +976,16 @@ | ||
| 963 | 976 | if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) { |
| 964 | 977 | return $text; |
| 965 | 978 | } |
| 966 | 979 | |
| 980 | + // Do not output sharing buttons for ActivityPub requests. | |
| 981 | + if ( | |
| 982 | + function_exists( '\Activitypub\is_activitypub_request' ) | |
| 983 | + && \Activitypub\is_activitypub_request() | |
| 984 | + ) { | |
| 985 | + return $text; | |
| 986 | + } | |
| 987 | + | |
| 967 | 988 | // Don't output flair on excerpts. |
| 968 | 989 | if ( in_array( 'get_the_excerpt', (array) $wp_current_filter, true ) ) { |
| 969 | 990 | return $text; |
| 970 | 991 | } |
| @@ -1084,13 +1105,13 @@ | ||
| 1084 | 1105 | * @param array $sharer->get_blog_services() Array of Sharing Services currently enabled. |
| 1085 | 1106 | */ |
| 1086 | 1107 | $enabled = apply_filters( 'sharing_enabled', $sharer->get_blog_services() ); |
| 1087 | 1108 | |
| 1088 | - if ( count( $enabled['all'] ) > 0 ) { | |
| 1109 | + if ( is_countable( $enabled['all'] ) && ( count( $enabled['all'] ) > 0 ) ) { | |
| 1089 | 1110 | $dir = get_option( 'text_direction' ); |
| 1090 | 1111 | |
| 1091 | 1112 | // Wrapper. |
| 1092 | - $sharing_content .= '<div class="sharedaddy sd-sharing-enabled"><div class="robots-nocontent sd-block sd-social sd-social-' . $global['button_style'] . ' sd-sharing">'; | |
| 1113 | + $sharing_content .= '<div class="sharedaddy sd-sharing-enabled"><div class="robots-nocontent sd-block sd-social sd-social-' . ( $global['button_style'] ?? 'icon-text' ) . ' sd-sharing">'; | |
| 1093 | 1114 | if ( '' !== $global['sharing_label'] ) { |
| 1094 | 1115 | $sharing_content .= sprintf( |
| 1095 | 1116 | /** |
| 1096 | 1117 | * Filter the sharing buttons' headline structure. |
| @@ -1122,12 +1143,14 @@ | ||
| 1122 | 1143 | // Individual HTML for sharing service. |
| 1123 | 1144 | $visible .= '<li class="' . implode( ' ', $klasses ) . '">' . $service->get_display( $post ) . '</li>'; |
| 1124 | 1145 | } |
| 1125 | 1146 | |
| 1126 | - $parts = array(); | |
| 1127 | - $parts[] = $visible; | |
| 1128 | - if ( count( $enabled['hidden'] ) > 0 ) { | |
| 1129 | - if ( count( $enabled['visible'] ) > 0 ) { | |
| 1147 | + $parts = array(); | |
| 1148 | + $parts[] = $visible; | |
| 1149 | + $count_hidden = is_countable( $enabled['hidden'] ) ? count( $enabled['hidden'] ) : 0; | |
| 1150 | + $count_visible = is_countable( $enabled['visible'] ) ? count( $enabled['visible'] ) : 0; | |
| 1151 | + if ( $count_hidden > 0 ) { | |
| 1152 | + if ( $count_visible > 0 ) { | |
| 1130 | 1153 | $expand = __( 'More', 'jetpack' ); |
| 1131 | 1154 | } else { |
| 1132 | 1155 | $expand = __( 'Share', 'jetpack' ); |
| 1133 | 1156 | } |
| @@ -1149,18 +1172,18 @@ | ||
| 1149 | 1172 | $sharing_content .= '<p class="share-customize-link"><a href="' . esc_url( $link_url ) . '" target="_blank" rel="noopener noreferrer">' . esc_html( $link_text ) . '</a></p>'; |
| 1150 | 1173 | } |
| 1151 | 1174 | } |
| 1152 | 1175 | |
| 1153 | - if ( count( $enabled['hidden'] ) > 0 ) { | |
| 1176 | + if ( $count_hidden > 0 ) { | |
| 1154 | 1177 | $sharing_content .= '<div class="sharing-hidden"><div class="inner" style="display: none;'; |
| 1155 | 1178 | |
| 1156 | - if ( count( $enabled['hidden'] ) === 1 ) { | |
| 1179 | + if ( $count_hidden === 1 ) { | |
| 1157 | 1180 | $sharing_content .= 'width:150px;'; |
| 1158 | 1181 | } |
| 1159 | 1182 | |
| 1160 | 1183 | $sharing_content .= '">'; |
| 1161 | 1184 | |
| 1162 | - if ( count( $enabled['hidden'] ) === 1 ) { | |
| 1185 | + if ( $count_hidden === 1 ) { | |
| 1163 | 1186 | $sharing_content .= '<ul style="background-image:none;">'; |
| 1164 | 1187 | } else { |
| 1165 | 1188 | $sharing_content .= '<ul>'; |
| 1166 | 1189 | } |