Skip to content

Commit

Permalink
Publicize: add Fediverse creator meta tag from Mastodon connection (#…
Browse files Browse the repository at this point in the history
…38809)

* Publicize: add Fediverse creator meta tag from Mastodon connection

This is a follow-up to #38198, which was partially reverted in #38612.
It's an alternative to #38565, to ensure better compatibility with WordPress.com Simple.

1. It takes into account the ActivityPub plugin, and ensure we're not adding a tag when the ActivityPub plugin already adds one.
2. It takes into account that on WordPress.com Simple, `get_services()` may return a `Keyring_Access_Token` object instead of an array.
3. It adds the 2 necessary methods directly to the `functions.opengraph.php` file, since we know it is loaded on the frontend on WordPress.com Simple (see conversation here to find out more: #38565 (comment) )

* Add missing since parameter
  • Loading branch information
jeherve authored Aug 12, 2024
1 parent a8217eb commit 3c68c42
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 89 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: changed

Open Graph Meta Tags: do not handle Fediverse tags from Publicize package.
89 changes: 0 additions & 89 deletions projects/packages/publicize/src/class-publicize-base.php
Original file line number Diff line number Diff line change
Expand Up @@ -2140,95 +2140,6 @@ public function get_dismissed_notices() {
public static function can_manage_connection( $connection_data ) {
return current_user_can( 'edit_others_posts' ) || get_current_user_id() === (int) $connection_data['user_id'];
}

/**
* Display a Fediverse actor Open Graph tag when the post author has a Mastodon connection.
*
* @see https://blog.joinmastodon.org/2024/07/highlighting-journalism-on-mastodon/
*
* @param array $tags Current tags.
*
* @return array
*/
public function add_fediverse_creator_open_graph_tag( $tags ) {
global $post;

if (
! is_singular()
|| ! $post instanceof WP_Post
|| ! isset( $post->ID )
|| empty( $post->post_author )
) {
return $tags;
}

$post_mastodon_connections = array();

// Loop through active connections.
foreach ( (array) $this->get_services( 'connected' ) as $service_name => $connections ) {
if ( 'mastodon' !== $service_name ) {
continue;
}

// services can have multiple connections. Store them all in our array.
foreach ( $connections as $connection ) {
$connection_id = $this->get_connection_id( $connection );
$mastodon_handle = $connection['external_display'] ?? '';

if ( empty( $mastodon_handle ) ) {
continue;
}

// Did we skip this connection for this post?
if ( get_post_meta( $post->ID, $this->POST_SKIP_PUBLICIZE . $connection_id, true ) ) {
continue;
}

$post_mastodon_connections[] = array(
'user_id' => (int) $connection['user_id'],
'connection_id' => (int) $connection_id,
'handle' => $mastodon_handle,
'global' => $this->is_global_connection( $connection ),
);
}
}

// If we have no Mastodon connections, skip.
if ( empty( $post_mastodon_connections ) ) {
return $tags;
}

/*
* Select a single Mastodon connection to use.
* It should be either the first connection belonging to the post author,
* or the first global connection.
*/
foreach ( $post_mastodon_connections as $mastodon_connection ) {
if ( $post->post_author === $mastodon_connection['user_id'] ) {
$tags['fediverse:creator'] = esc_attr( $mastodon_connection['handle'] );
break;
}

if ( $mastodon_connection['global'] ) {
$tags['fediverse:creator'] = esc_attr( $mastodon_connection['handle'] );
break;
}
}

return $tags;
}

/**
* Update the markup for the Open Graph tag to match the expected output for Mastodon
* (name instead of property).
*
* @param string $og_tag A single OG tag.
*
* @return string Result of the OG tag.
*/
public static function filter_fediverse_cards_output( $og_tag ) {
return ( str_contains( $og_tag, 'fediverse:' ) ) ? preg_replace( '/property="([^"]+)"/', 'name="\1"', $og_tag ) : $og_tag;
}
}

// phpcs:disable Universal.Files.SeparateFunctionsFromOO.Mixed -- TODO: Move these functions to some other file.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: enhancement

Jetpack Social: display Fediverse creator meta tag when a post has an active Mastodon connection.
119 changes: 119 additions & 0 deletions projects/plugins/jetpack/functions.opengraph.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
add_action( 'wp_head', 'jetpack_og_tags' );
add_action( 'web_stories_story_head', 'jetpack_og_tags' );

// Add a Fediverse Open Graph Tag when an author has connected their Mastodon account.
add_filter( 'jetpack_open_graph_tags', 'jetpack_add_fediverse_creator_open_graph_tag', 10, 1 );
add_filter( 'jetpack_open_graph_output', 'jetpack_filter_fediverse_cards_output', 10, 1 );

/**
* Outputs Open Graph tags generated by Jetpack.
*/
Expand Down Expand Up @@ -533,3 +537,118 @@ function jetpack_og_get_description( $description = '', $data = null ) {

return $description;
}

/**
* Display a Fediverse actor Open Graph tag when the post author has a Mastodon connection.
*
* @see https://blog.joinmastodon.org/2024/07/highlighting-journalism-on-mastodon/
*
* @since $$next-version$$
*
* @param array $tags Current tags.
*
* @return array
*/
function jetpack_add_fediverse_creator_open_graph_tag( $tags ) {
/*
* Let's not add any tags when the ActivityPub plugin already adds its own.
* On WordPress.com simple, let's check if the plugin is active.
* On self-hosted, let's just check if the class exists.
*/
$is_activitypub_active = function_exists( 'wpcom_activitypub_is_active' )
? wpcom_activitypub_is_active()
: class_exists( '\Activitypub\Integration\Opengraph' );

if ( $is_activitypub_active ) {
return $tags;
}

// We pull the Mastodon connection data from Publicize.
if ( ! function_exists( 'publicize_init' ) ) {
return $tags;
}
$publicize = publicize_init();

global $post;
if (
! is_singular()
|| ! $post instanceof WP_Post
|| ! isset( $post->ID )
|| empty( $post->post_author )
) {
return $tags;
}

$post_mastodon_connections = array();

// Loop through active connections.
foreach ( (array) $publicize->get_services( 'connected' ) as $service_name => $connections ) {
if ( 'mastodon' !== $service_name ) {
continue;
}

// services can have multiple connections. Store them all in our array.
foreach ( $connections as $connection ) {
$connection_id = $publicize->get_connection_id( $connection );
$connection_meta = $publicize->get_connection_meta( $connection );

$connection_data = $connection_meta['connection_data'] ?? array();
$mastodon_handle = $connection_meta['external_display'] ?? '';
$connection_user_id = $connection_data['user_id'] ?? 0;

if ( empty( $mastodon_handle ) ) {
continue;
}

// Did we skip this connection for this post?
if ( get_post_meta( $post->ID, $publicize->POST_SKIP_PUBLICIZE . $connection_id, true ) ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
continue;
}

$post_mastodon_connections[] = array(
'user_id' => (int) $connection_user_id,
'connection_id' => (int) $connection_id,
'handle' => $mastodon_handle,
'global' => 0 === $connection_user_id,
);
}
}

// If we have no Mastodon connections, skip.
if ( empty( $post_mastodon_connections ) ) {
return $tags;
}

/*
* Select a single Mastodon connection to use.
* It should be either the first connection belonging to the post author,
* or the first global connection.
*/
foreach ( $post_mastodon_connections as $mastodon_connection ) {
if ( (int) $post->post_author === $mastodon_connection['user_id'] ) {
$tags['fediverse:creator'] = esc_attr( $mastodon_connection['handle'] );
break;
}

if ( $mastodon_connection['global'] ) {
$tags['fediverse:creator'] = esc_attr( $mastodon_connection['handle'] );
break;
}
}

return $tags;
}

/**
* Update the markup for the Open Graph tag to match the expected output for Mastodon
* (name instead of property).
*
* @since $$next-version$$
*
* @param string $og_tag A single OG tag.
*
* @return string Result of the OG tag.
*/
function jetpack_filter_fediverse_cards_output( $og_tag ) {
return ( str_contains( $og_tag, 'fediverse:' ) ) ? preg_replace( '/property="([^"]+)"/', 'name="\1"', $og_tag ) : $og_tag;
}

0 comments on commit 3c68c42

Please sign in to comment.