* Generates and returns the markup for an AMP sharing button.
* @param array $attrs Custom attributes for rendering the social icon.
protected function build_amp_markup( $attrs = array() ) {
/* translators: placeholder is a service name, such as "Twitter" or "Facebook". */
__( 'Share on %s', 'jetpack' ),
'type' => $this->get_id(),
$sharing_link = '<amp-social-share';
foreach ( $attrs as $key => $value ) {
$sharing_link .= sprintf( ' %s="%s"', sanitize_key( $key ), esc_attr( $value ) );
$sharing_link .= '></amp-social-share>';
* Display a preview of the sharing button.
* @param bool $echo Whether to echo the output or return it.
* @param bool $force_smart Whether to force the smart (official) services to be shown.
* @param null|string $button_style Button style.
public function display_preview( $echo = true, $force_smart = false, $button_style = null ) {
$button_style = ( ! empty( $button_style ) ) ? $button_style : $this->button_style;
if ( ! $this->smart && ! $force_smart ) {
if ( $button_style !== 'icon' ) {
$text = $this->get_name();
$klasses = array( 'share-' . $this->get_class(), 'sd-button' );
if ( $button_style === 'icon' || $button_style === 'icon-text' ) {
$klasses[] = 'share-icon';
if ( $button_style === 'icon' ) {
if ( $button_style === 'text' ) {
$is_deprecated = $this->is_deprecated();
'<a rel="nofollow" class="%s" href="javascript:void(0)" title="%s"><span>%s</span></a>',
implode( ' ', $klasses ),
/* translators: %1$s is the name of a deprecated Sharing Service like "Google+" */
? sprintf( __( 'The %1$s sharing service has shut down or discontinued support for sharing buttons. This sharing button is not displayed to your visitors and should be removed.', 'jetpack' ), $this->get_name() )
/* translators: %1$s is the name of a deprecated Sharing Service like "Google+" */
? sprintf( __( '%1$s is no longer supported', 'jetpack' ), $this->get_name() )
$smart = ( $this->smart || $force_smart ) ? 'on' : 'off';
$return = "<div class='option option-smart-$smart'>$link</div>";
echo $return; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- we escape things above.
* Get sharing stats for a specific post or sharing service.
* @param bool|WP_Post $post Post object.
public function get_total( $post = false ) {
$name = strtolower( (string) $this->get_id() );
// get total number of shares for service
return (int) $wpdb->get_var( $wpdb->prepare( 'SELECT SUM( count ) FROM sharing_stats WHERE blog_id = %d AND share_service = %s', $blog_id, $name ) );
// get total shares for a post
return (int) $wpdb->get_var( $wpdb->prepare( 'SELECT count FROM sharing_stats WHERE blog_id = %d AND post_id = %d AND share_service = %s', $blog_id, $post->ID, $name ) );
* Get sharing stats for all posts on the site.
public function get_posts_total() {
$name = strtolower( (string) $this->get_id() );
$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 ) );
if ( ! empty( $my_data ) ) {
foreach ( $my_data as $row ) {
$totals[] = new Sharing_Post_Total( $row->id, $row->total );
usort( $totals, array( 'Sharing_Post_Total', 'cmp' ) );
* Process sharing request. Add actions that need to happen when sharing here.
* @param WP_Post $post Post object.
* @param array $post_data Array of information about the post we're sharing.
public function process_request( $post, array $post_data ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
* Fires when a post is shared via one of the sharing buttons.
* @param array $args Aray of information about the sharing service.
* Redirect to an external social network site to finish sharing.
* @param string $url Sharing URL for a given service.
public function redirect_request( $url ) {
wp_redirect( $url ); // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect -- We allow external redirects here; we define them ourselves.
// We set up this custom header to indicate to search engines not to index this page.
header( 'X-Robots-Tag: noindex, nofollow' );
* Add extra JavaScript to a sharing service.
* @param string $name Sharing service name.
* @param array $params Array of sharing options.
public function js_dialog( $name, $params = array() ) {
if ( true !== $this->open_link_in_new ) {
$params = array_merge( $defaults, $params );
foreach ( $params as $key => $val ) {
$opts = implode( ',', $opts );
// Add JS after sharing-js has been enqueued.
function matches( el, sel ) {
el.matches && el.matches( sel ) ||
el.msMatchesSelector && el.msMatchesSelector( sel )
document.body.addEventListener( 'click', function ( event ) {
if ( matches( event.target, 'a.share-$name' ) ) {
} else if ( event.target.parentNode && matches( event.target.parentNode, 'a.share-$name' ) ) {
el = event.target.parentNode;
// If there's another sharing window open, close it.
if ( typeof windowOpen !== 'undefined' ) {
windowOpen = window.open( el.getAttribute( 'href' ), 'wpcom$name', '$opts' );
* Handle the display of deprecated sharing services.
abstract class Deprecated_Sharing_Source extends Sharing_Source {
* Button style (icon-text, icon, or text)
public $button_style = 'text';
* Does the service have an official version.
* Should the sharing link open in a new tab.
protected $open_link_in_new = false;
* Is the service deprecated.
protected $deprecated = true;
* @param int $id Sharing source ID.
* @param array $settings Sharing settings.
final public function __construct( $id, array $settings ) {
if ( isset( $settings['button_style'] ) ) {
$this->button_style = $settings['button_style'];
* Is the service deprecated.
final public function is_deprecated() {
* Get a post's permalink to use for sharing.
* @param int $post_id Post ID.
final public function get_share_url( $post_id ) {
return get_permalink( $post_id );
* No AMP display for deprecated sources.
* @param \WP_Post $post The current post being viewed.
final public function get_amp_display( $post ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
* Display a preview of the sharing button.
* @param bool $echo Whether to echo the output or return it.
* @param bool $force_smart Whether to force the smart (official) services to be shown.
* @param null|string $button_style Button style.
final public function display_preview( $echo = true, $force_smart = false, $button_style = null ) {
return parent::display_preview( $echo, false, $button_style );
* Get sharing stats for a specific post or sharing service.
* @param bool|WP_Post $post Post object.
final public function get_total( $post = false ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
* Get sharing stats for all posts on the site.
final public function get_posts_total() {
* Process sharing request. Add actions that need to happen when sharing here.
* @param WP_Post $post Post object.
* @param array $post_data Array of information about the post we're sharing.
final public function process_request( $post, array $post_data ) { // phpcs:ignore Generic.CodeAnalysis.UselessOverridingMethod.Found
parent::process_request( $post, $post_data );
* Get the markup of the sharing button.
* @param WP_Post $post Post object.
final public function get_display( $post ) {
if ( current_user_can( 'manage_options' ) ) {
return $this->display_deprecated( $post );
* Display a custom message for deprecated services.
* @param WP_Post $post Post object.
public function display_deprecated( $post ) {
$this->get_share_url( $post->ID ),
/* translators: %1$s is the name of a deprecated Sharing Service like "Google+" */
sprintf( __( '%1$s is no longer supported', 'jetpack' ), $this->get_name() ),
/* translators: %1$s is the name of a deprecated Sharing Service like "Google+" */
sprintf( __( 'The %1$s sharing service has shut down or discontinued support for sharing buttons. This sharing button is not displayed to your visitors and should be removed.', 'jetpack' ), $this->get_name() )
* Handle the display of advanced sharing services.
* Custom sharing buttons we create ourselves will be such services.
abstract class Sharing_Advanced_Source extends Sharing_Source {
* Does the service have advanced options.
public function has_advanced_options() {
* Display options for our sharing buttons.
abstract public function display_options();
* Sanitize and save options for our sharing buttons.
* @param array $data Data to be saved.
abstract public function update_options( array $data );
* Get array of information about the service.
abstract public function get_options();
* Handle the display of the email sharing button.
class Share_Email extends Sharing_Source {
public $shortname = 'email';
* Service icon font code.
* @param int $id Sharing source ID.
* @param array $settings Sharing settings.
public function __construct( $id, array $settings ) {
parent::__construct( $id, $settings );
if ( 'official' === $this->button_style ) {
public function get_name() {
return _x( 'Email', 'as sharing source', 'jetpack' );
* Helper function to return a nonce action based on the current post.
* @param WP_Post|null $post The current post if it is defined.
* @return string The nonce action name.
protected function get_email_share_nonce_action( $post ) {
if ( ! empty( $post ) && $post instanceof WP_Post ) {
return 'jetpack-email-share-' . $post->ID;
return 'jetpack-email-share';
* Process sharing request. Add actions that need to happen when sharing here.