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

fix: disambiguate WP users vs. guest authors with same ID #1143

Merged
merged 1 commit into from
May 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,28 @@ public function register_routes() {
'methods' => WP_REST_Server::READABLE,
'callback' => [ $this, 'api_get_all_authors' ],
'args' => [
'author_id' => [
'author_id' => [
'sanitize_callback' => 'absint',
],
'offset' => [
'author_roles' => [
'sanitize_callback' => 'WP_REST_Newspack_Author_List_Controller::sanitize_array',
],
'author_types' => [
'sanitize_callback' => 'WP_REST_Newspack_Author_List_Controller::sanitize_array',
],
'exclude_empty' => [
'sanitize_callback' => 'absint',
],
'offset' => [
'sanitize_callback' => 'absint',
],
'per_page' => [
'per_page' => [
'sanitize_callback' => 'absint',
],
'search' => [
'search' => [
'sanitize_callback' => 'sanitize_text_field',
],
'fields' => [
'fields' => [
'sanitize_callback' => 'sanitize_text_field',
],
],
Expand All @@ -59,6 +68,28 @@ public function register_routes() {
);
}

/**
* Sanitize an array of text or number values.
*
* @param array $array Array of text or float values to be sanitized.
* @return array Sanitized array.
*/
public static function sanitize_array( $array ) {
foreach ( $array as $value ) {
if ( is_array( $value ) ) {
$value = sanitize_array( $value );
} else {
if ( is_string( $value ) ) {
$value = sanitize_text_field( $value );
} else {
$value = floatval( $value );
}
}
}

return $array;
}

/**
* Get a list of user roles on this site that have the edit_posts capability.
*
Expand Down Expand Up @@ -99,23 +130,23 @@ function( $acc, $role ) {
public function api_get_all_authors( $request ) {
$options = [];

if ( ! empty( $request->get_param( 'authorType' ) ) ) {
$options['author_type'] = $request->get_param( 'authorType' );
if ( ! empty( $request->get_param( 'author_type' ) ) ) {
$options['author_type'] = $request->get_param( 'author_type' );
}

if ( ! empty( $request->get_param( 'authorRoles' ) ) ) {
$options['author_roles'] = $request->get_param( 'authorRoles' );
if ( ! empty( $request->get_param( 'author_roles' ) ) ) {
$options['author_roles'] = $request->get_param( 'author_roles' );
}

if ( ! empty( $request->get_param( 'exclude' ) ) && is_array( $request->get_param( 'exclude' ) ) ) {
$options['exclude'] = $request->get_param( 'exclude' ); // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude
}

if ( ! empty( $request->get_param( 'excludeEmpty' ) ) ) {
if ( ! empty( $request->get_param( 'exclude_empty' ) ) ) {
$options['exclude_empty'] = true;
}

if ( ! empty( $request->get_param( 'avatarHideDefault' ) ) ) {
if ( ! empty( $request->get_param( 'avatar_hide_default' ) ) ) {
$options['avatar_hide_default'] = true;
}

Expand Down
8 changes: 4 additions & 4 deletions src/blocks/author-list/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,17 @@ const AuthorList = ( { attributes, clientId, setAttributes } ) => {
setIsLoading( true );
try {
const params = {
authorType,
authorRoles,
author_type: authorType,
author_roles: authorRoles,
exclude: exclude.map( exclusion => parseInt( exclusion.value ) ),
};

if ( excludeEmpty ) {
params.excludeEmpty = 1;
params.exclude_empty = 1;
}

if ( avatarHideDefault ) {
params.avatarHideDefault = 1;
params.avatar_hide_default = 1;
}

const response = await apiFetch( {
Expand Down
4 changes: 4 additions & 0 deletions src/blocks/author-profile/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
"type": "number",
"default": 0
},
"isGuestAuthor": {
"type": "boolean",
"default": true
},
"showBio": {
"type": "boolean",
"default": true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,25 @@ public function register_routes() {
'methods' => WP_REST_Server::READABLE,
'callback' => [ $this, 'get_authors' ],
'args' => [
'author_id' => [
'author_id' => [
'sanitize_callback' => 'absint',
],
'offset' => [
'is_guest_author' => [
'sanitize_callback' => 'absint',
],
'per_page' => [
'avatar_hide_default' => [
'sanitize_callback' => 'absint',
],
'search' => [
'offset' => [
'sanitize_callback' => 'absint',
],
'per_page' => [
'sanitize_callback' => 'absint',
],
'search' => [
'sanitize_callback' => 'sanitize_text_field',
],
'fields' => [
'fields' => [
'sanitize_callback' => 'sanitize_text_field',
],
],
Expand All @@ -66,7 +72,8 @@ public function register_routes() {
* @return WP_REST_Response
*/
public function get_authors( $request ) {
$author_id = ! empty( $request->get_param( 'authorId' ) ) ? $request->get_param( 'authorId' ) : 0; // Fetch a specific user or guest author by ID.
$author_id = ! empty( $request->get_param( 'author_id' ) ) ? $request->get_param( 'author_id' ) : 0; // Fetch a specific user or guest author by ID.
$is_guest_author = null !== $request->get_param( 'is_guest_author' ) ? $request->get_param( 'is_guest_author' ) : true; // If $author_id is known to be a regular WP user, not a guest author, this will be `false`.
$search = ! empty( $request->get_param( 'search' ) ) ? $request->get_param( 'search' ) : null; // Fetch authors by search string.
$offset = ! empty( $request->get_param( 'offset' ) ) ? $request->get_param( 'offset' ) : 0; // Offset results (for pagination).
$per_page = ! empty( $request->get_param( 'perPage' ) ) ? $request->get_param( 'perPage' ) : 10; // Number of results to return per page. This is applied to each query, so the actual number of results returned may be up to 2x this number.
Expand All @@ -79,26 +86,29 @@ public function get_authors( $request ) {
$user_total = 0;

// Get Co-authors guest authors.
$guest_author_args = [
'post_type' => 'guest-author',
'posts_per_page' => $per_page,
'offset' => $offset,
];
if ( $is_guest_author ) {
$guest_author_args = [
'post_type' => 'guest-author',
'posts_per_page' => $per_page,
'offset' => $offset,
];

if ( $search && ! $author_id ) {
$guest_author_args['s'] = $search;
}
if ( $author_id ) {
$guest_author_args['p'] = $author_id;
}
if ( $include ) {
$guest_author_args['post__in'] = $include;
$guest_author_args['ignore_sticky_posts'] = true;
if ( $search && ! $author_id ) {
$guest_author_args['s'] = $search;
}
if ( $author_id ) {
$guest_author_args['p'] = $author_id;
}
if ( $include ) {
$guest_author_args['post__in'] = $include;
$guest_author_args['ignore_sticky_posts'] = true;
}

$guest_authors = get_posts( $guest_author_args );
$guest_author_total = count( $guest_authors );
}

$guest_authors = get_posts( $guest_author_args );
$guest_author_total = count( $guest_authors );
$users = [];
$users = [];

// If passed an author ID.
if ( $author_id ) {
Expand Down Expand Up @@ -153,6 +163,7 @@ function( $acc, $guest_author ) use ( $fields, $avatar_hide_default ) {
'id' => intval( $guest_author->ID ),
'registered' => $guest_author->post_date,
'is_guest' => true,
'slug' => $guest_author->post_name,
];

$guest_author = ( new CoAuthors_Guest_Authors() )->get_guest_author_by( 'id', $guest_author->ID );
Expand Down Expand Up @@ -204,6 +215,7 @@ function( $acc, $user ) use ( $fields, $avatar_hide_default ) {
'id' => intval( $user->data->ID ),
'registered' => $user->data->user_registered,
'is_guest' => false,
'slug' => $user->data->user_login,
];

if ( in_array( 'login', $fields, true ) ) {
Expand Down
15 changes: 12 additions & 3 deletions src/blocks/author-profile/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ const AuthorProfile = ( { attributes, setAttributes } ) => {
const [ maxItemsToSuggest, setMaxItemsToSuggest ] = useState( 0 );
const {
authorId,
isGuestAuthor,
showBio,
showSocial,
showEmail,
Expand All @@ -161,12 +162,13 @@ const AuthorProfile = ( { attributes, setAttributes } ) => {
setIsLoading( true );
try {
const params = {
authorId,
author_id: authorId,
is_guest_author: isGuestAuthor ? 1 : 0,
fields: 'id,name,bio,email,social,avatar,url',
};

if ( avatarHideDefault ) {
params.avatarHideDefault = 1;
params.avatar_hide_default = 1;
}

const response = await apiFetch( {
Expand Down Expand Up @@ -397,6 +399,7 @@ const AuthorProfile = ( { attributes, setAttributes } ) => {
path: addQueryArgs( '/newspack-blocks/v1/authors', {
search,
offset,
isGuestAuthor: true,
fields: 'id,name',
} ),
} );
Expand All @@ -412,10 +415,16 @@ const AuthorProfile = ( { attributes, setAttributes } ) => {
return authors.map( _author => ( {
value: _author.id,
label: decodeEntities( _author.name ) || __( '(no name)', 'newspack' ),
isGuestAuthor: _author.is_guest,
} ) );
} }
maxItemsToSuggest={ maxItemsToSuggest }
onChange={ items => setAttributes( { authorId: parseInt( items[ 0 ].value ) } ) }
onChange={ items => {
setAttributes( {
authorId: parseInt( items[ 0 ]?.value || 0 ),
isGuestAuthor: items[ 0 ]?.isGuestAuthor || false,
} );
} }
postTypeLabel={ __( 'author', 'newspack-blocks' ) }
postTypeLabelPlural={ __( 'authors', 'newspack-blocks' ) }
selectedItems={ [] }
Expand Down
7 changes: 4 additions & 3 deletions src/blocks/author-profile/view.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,15 @@ function newspack_blocks_register_author_profile() {
* @param int $author_id Author ID to look up.
* @param int $avatar_size Size of the avatar image to fetch.
* @param boolean $hide_default If true, don't show default avatars.
* @param boolean $is_guest_author If true, search for guest authors. If false, only search for WP users.
* @return object|boolean Author object in standardized format, or false if none exists.
*/
function newspack_blocks_get_author_or_guest_author( $author_id, $avatar_size = 128, $hide_default = false ) {
function newspack_blocks_get_author_or_guest_author( $author_id, $avatar_size = 128, $hide_default = false, $is_guest_author = true ) {
$wp_user = get_user_by( 'id', $author_id );
$author = false;

// First, see if the $author_id is a guest author.
if ( class_exists( 'CoAuthors_Guest_Authors' ) ) {
if ( class_exists( 'CoAuthors_Guest_Authors' ) && $is_guest_author ) {
// Check if the ID given is a WP user with linked guest author.
$linked_guest_author = false;

Expand Down Expand Up @@ -107,7 +108,7 @@ function newspack_blocks_render_block_author_profile( $attributes ) {
}

// Get the author by ID.
$author = newspack_blocks_get_author_or_guest_author( intval( $attributes['authorId'] ), intval( $attributes['avatarSize'] ), $attributes['avatarHideDefault'] );
$author = newspack_blocks_get_author_or_guest_author( intval( $attributes['authorId'] ), intval( $attributes['avatarSize'] ), $attributes['avatarHideDefault'], $attributes['isGuestAuthor'] );

// Bail if there's no author or guest author with the saved ID.
if ( empty( $author ) ) {
Expand Down