Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

REST API: Enhance author details by including additional data when either user_id or site_id are available. #41159

Merged
merged 10 commits into from
Feb 4, 2025
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Significance: patch
Type: enhancement
Comment: REST API: Enhance author details by including additional data when either user_id or site_id are available.
187 changes: 98 additions & 89 deletions projects/plugins/jetpack/class.json-api-endpoints.php
Original file line number Diff line number Diff line change
Expand Up @@ -1388,109 +1388,118 @@ public function get_author( $author, $show_email_and_ip = false ) {
$nice = null;
$url = null;
$ip_address = isset( $author->comment_author_IP ) ? $author->comment_author_IP : '';
$site_id = -1;

if ( isset( $author->comment_author_email ) ) {
$id = ( isset( $author->user_id ) && $author->user_id ) ? $author->user_id : 0;
$login = '';
$email = $author->comment_author_email;
$name = $author->comment_author;
$first_name = '';
$last_name = '';
$url = $author->comment_author_url;
$avatar_url = $this->api->get_avatar_url( $author );
$profile_url = 'https://gravatar.com/' . md5( strtolower( trim( $email ) ) );
$nice = '';
$site_id = -1;
$id = empty( $author->user_id ) ? 0 : (int) $author->user_id;
$login = '';
$email = $author->comment_author_email;
$name = $author->comment_author;
$first_name = '';
$last_name = '';
$url = $author->comment_author_url;
$avatar_url = $this->api->get_avatar_url( $author );
$nice = '';

// Add additional user data to the response if a valid user ID is available.
if ( 0 < $id ) {
$user = get_user_by( 'id', $id );
if ( $user instanceof WP_User ) {
$login = $user->user_login ?? '';
$first_name = $user->first_name ?? '';
$last_name = $user->last_name ?? '';
$nice = $user->user_nicename ?? '';
} else {
trigger_error( 'Unknown user', E_USER_WARNING ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error
}
}

// Comment author URLs and Emails are sent through wp_kses() on save, which replaces "&" with "&amp;"
// "&" is the only email/URL character altered by wp_kses().
foreach ( array( 'email', 'url' ) as $field ) {
$$field = str_replace( '&amp;', '&', $$field );
}
} else {
if ( $author instanceof WP_User || isset( $author->user_email ) ) {
$author = $author->ID;
} elseif ( isset( $author->user_id ) && $author->user_id ) {
$author = $author->user_id;
} elseif ( isset( $author->post_author ) ) {
// then $author is a Post Object.
if ( ! $author->post_author ) {
return null;
}
/**
* Filter whether the current site is a Jetpack site.
*
* @module json-api
*
* @since 3.3.0
*
* @param bool false Is the current site a Jetpack site. Default to false.
* @param int get_current_blog_id() Blog ID.
*/
$is_jetpack = true === apply_filters( 'is_jetpack_site', false, get_current_blog_id() );
$post_id = $author->ID;
if ( $is_jetpack && ( defined( 'IS_WPCOM' ) && IS_WPCOM ) ) {
$id = get_post_meta( $post_id, '_jetpack_post_author_external_id', true );
$email = get_post_meta( $post_id, '_jetpack_author_email', true );
$login = '';
$name = get_post_meta( $post_id, '_jetpack_author', true );
$first_name = '';
$last_name = '';
$url = '';
$nice = '';
} else {
$author = $author->post_author;
}
} elseif ( $author instanceof WP_User || isset( $author->user_email ) ) {
$author = $author->ID;
} elseif ( isset( $author->user_id ) && $author->user_id ) {
$author = $author->user_id;
} elseif ( isset( $author->post_author ) ) {
// then $author is a Post Object.
if ( ! $author->post_author ) {
return null;
}
/**
* Filter whether the current site is a Jetpack site.
*
* @module json-api
*
* @since 3.3.0
*
* @param bool false Is the current site a Jetpack site. Default to false.
* @param int get_current_blog_id() Blog ID.
*/
$is_jetpack = true === apply_filters( 'is_jetpack_site', false, get_current_blog_id() );
$post_id = $author->ID;
if ( $is_jetpack && ( defined( 'IS_WPCOM' ) && IS_WPCOM ) ) {
$id = get_post_meta( $post_id, '_jetpack_post_author_external_id', true );
$email = get_post_meta( $post_id, '_jetpack_author_email', true );
$login = '';
$name = get_post_meta( $post_id, '_jetpack_author', true );
$first_name = '';
$last_name = '';
$url = '';
$nice = '';
} else {
$author = $author->post_author;
}
}

if ( ! isset( $id ) ) {
$user = get_user_by( 'id', $author );
if ( ! $user || is_wp_error( $user ) ) {
trigger_error( 'Unknown user', E_USER_WARNING ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error
if ( ! isset( $id ) ) {
$user = get_user_by( 'id', $author );
if ( ! $user || is_wp_error( $user ) ) {
trigger_error( 'Unknown user', E_USER_WARNING ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error

return null;
}
$id = $user->ID;
$email = $user->user_email;
$login = $user->user_login;
$name = $user->display_name;
$first_name = $user->first_name;
$last_name = $user->last_name;
$url = $user->user_url;
$nice = $user->user_nicename;
return null;
}
if ( defined( 'IS_WPCOM' ) && IS_WPCOM && ! $is_jetpack ) {
$site_id = -1;

/**
* Allow customizing the blog ID returned with the author in WordPress.com REST API queries.
*
* @since 12.9
*
* @module json-api
*
* @param bool|int $active_blog Blog ID, or false by default.
* @param int $id User ID.
*/
$active_blog = apply_filters( 'wpcom_api_pre_get_active_blog_author', false, $id );
if ( false === $active_blog ) {
$active_blog = get_active_blog_for_user( $id );
}
if ( ! empty( $active_blog ) ) {
$site_id = $active_blog->blog_id;
}
if ( $site_id > -1 ) {
$site_visible = (
-1 !== (int) $active_blog->public ||
is_private_blog_user( $site_id, get_current_user_id() )
);
}
$profile_url = "https://gravatar.com/{$login}";
} else {
$profile_url = 'https://gravatar.com/' . md5( strtolower( trim( $email ) ) );
$site_id = -1;
$id = $user->ID;
$email = $user->user_email;
$login = $user->user_login;
$name = $user->display_name;
$first_name = $user->first_name;
$last_name = $user->last_name;
$url = $user->user_url;
$nice = $user->user_nicename;
}
if ( defined( 'IS_WPCOM' ) && IS_WPCOM && ! $is_jetpack ) {
/**
* Allow customizing the blog ID returned with the author in WordPress.com REST API queries.
*
* @since 12.9
*
* @module json-api
*
* @param bool|int $active_blog Blog ID, or false by default.
* @param int $id User ID.
*/
$active_blog = apply_filters( 'wpcom_api_pre_get_active_blog_author', false, $id );
if ( false === $active_blog ) {
$active_blog = get_active_blog_for_user( $id );
}
if ( ! empty( $active_blog ) ) {
$site_id = $active_blog->blog_id;
}
if ( $site_id > - 1 ) {
$site_visible = (
- 1 !== (int) $active_blog->public ||
is_private_blog_user( $site_id, get_current_user_id() )
);
}
$profile_url = "https://gravatar.com/{$login}";
} else {
$profile_url = 'https://gravatar.com/' . md5( strtolower( trim( $email ) ) );
}

if ( ! isset( $avatar_url ) ) {
$avatar_url = $this->api->get_avatar_url( $email );
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ class WP_Test_Jetpack_Base_Json_Api_Endpoints extends WP_UnitTestCase {
*/
private static $super_admin_alt_user_id;

/**
* A contributor user used for test.
*
* @var int
*/
private static $contributor_user_id;

/**
* Inserts globals needed to initialize the endpoint.
*/
Expand All @@ -45,6 +52,21 @@ private function set_globals() {
public static function wpSetUpBeforeClass( $factory ) {
self::$super_admin_user_id = $factory->user->create( array( 'role' => 'administrator' ) );
self::$super_admin_alt_user_id = $factory->user->create( array( 'role' => 'administrator' ) );
self::$contributor_user_id = $factory->user->create(
array(
'user_login' => 'john_doe',
'user_pass' => 'password123',
'user_nicename' => 'John Doe',
'user_email' => 'john.doe@example.com',
'user_url' => 'https://example.com',
'display_name' => 'John Doe',
'nickname' => 'Johnny',
'first_name' => 'John',
'last_name' => 'Doe',
'description' => 'This is a dummy user for testing.',
'role' => 'contributor',
)
);
}

/**
Expand Down Expand Up @@ -113,6 +135,69 @@ public function test_get_author_should_return_the_same_user_if_user_meta_is_set(
$this->assertSame( self::$super_admin_user_id, $author->ID );
}

/**
* @covers Jetpack_JSON_API_Endpoint::get_author
* @group json-api
*/
public function test_get_author_should_provide_additional_data_when_user_id_is_specified() {
$endpoint = $this->get_dummy_endpoint();
$commment_data = new stdClass();
$commment_data->comment_author_email = 'foo@bar.foo';
$commment_data->comment_author = 'John Doe';
$commment_data->comment_author_url = 'https://foo.bar.foo';
$commment_data->user_id = static::$contributor_user_id;
$comment = new WP_Comment( $commment_data );

$author = $endpoint->get_author( $comment, true );

$this->assertIsObject( $author, 'The returned author should be an object.' );
$this->assertNotNull( $author, 'The returned author should not be null.' );
$this->assertSame(
$commment_data->comment_author_email,
$author->email,
'The author email does not match the expected comment author email.'
);
$this->assertSame(
$commment_data->comment_author,
$author->name,
'The author name does not match the expected comment author name.'
);
$this->assertSame(
$commment_data->comment_author_url,
$author->URL, // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
'The author URL does not match the expected comment author URL.'
);

$user = get_user_by( 'id', static::$contributor_user_id );

// The user should be the same as the one passed as object to the method.
$this->assertSame(
static::$contributor_user_id,
$author->ID,
'The author ID does not match the expected user ID.'
);
$this->assertSame(
$user->user_login,
$author->login,
'The author login does not match the expected user login.'
);
$this->assertSame(
$user->first_name,
$author->first_name,
'The author first name does not match the expected first name.'
);
$this->assertSame(
$user->last_name,
$author->last_name,
'The author last name does not match the expected last name.'
);
$this->assertSame(
$user->user_nicename,
$author->nice_name,
'The author nicename does not match the expected nicename.'
);
}

/**
* Generate a dummy endpoint.
*/
Expand Down
Loading