BP_REST_Members_Endpoint
BuddyPress Members endpoints.
Description Description
Source Source
File: bp-members/classes/class-bp-rest-members-endpoint.php
class BP_REST_Members_Endpoint extends WP_REST_Users_Controller { /** * Constructor. * * @since 5.0.0 */ public function __construct() { $this->namespace = bp_rest_namespace() . '/' . bp_rest_version(); $this->rest_base = 'members'; } /** * Retrieve users. * * @since 5.0.0 * * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response */ public function get_items( $request ) { $args = array( 'type' => $request['type'], 'user_id' => $request['user_id'], 'user_ids' => $request['user_ids'], 'xprofile_query' => $request['xprofile'], 'include' => $request['include'], 'exclude' => $request['exclude'], 'member_type' => $request['member_type'], 'search_terms' => $request['search'], 'per_page' => $request['per_page'], 'page' => $request['page'], ); if ( empty( $request['user_ids'] ) ) { $args['user_ids'] = false; } if ( empty( $request['exclude'] ) ) { $args['exclude'] = false; } if ( empty( $request['include'] ) ) { $args['include'] = false; } if ( empty( $request['xprofile'] ) ) { $args['xprofile_query'] = false; } if ( empty( $request['member_type'] ) ) { $args['member_type'] = ''; } /** * Filter the query arguments for the request. * * @since 5.0.0 * * @param array $args Key value array of query var to query value. * @param WP_REST_Request $request The request sent to the API. */ $args = apply_filters( 'bp_rest_members_get_items_query_args', $args, $request ); // Actually, query it. $member_query = new BP_User_Query( $args ); $members = array_values( $member_query->results ); $retval = array(); foreach ( $members as $member ) { $retval[] = $this->prepare_response_for_collection( $this->prepare_item_for_response( $member, $request ) ); } $response = rest_ensure_response( $retval ); $response = bp_rest_response_add_total_headers( $response, $member_query->total_users, $args['per_page'] ); /** * Fires after a list of members is fetched via the REST API. * * @since 5.0.0 * * @param array $members Fetched members. * @param WP_REST_Response $response The response data. * @param WP_REST_Request $request The request sent to the API. */ do_action( 'bp_rest_members_get_items', $members, $response, $request ); return $response; } /** * Checks if a given request has access to get all users. * * @since 5.0.0 * * @param WP_REST_Request $request Full details about the request. * @return bool */ public function get_items_permissions_check( $request ) { /** * Filter the members `get_items` permissions check. * * @since 5.0.0 * * @param bool $retval Returned value. * @param WP_REST_Request $request The request sent to the API. */ return apply_filters( 'bp_rest_members_get_items_permissions_check', true, $request ); } /** * Checks if a given request has access to read a user. * * @since 5.0.0 * * @param WP_REST_Request $request Full details about the request. * @return bool|WP_Error */ public function get_item_permissions_check( $request ) { $retval = true; if ( ! is_user_logged_in() ) { $retval = new WP_Error( 'bp_rest_authorization_required', __( 'Sorry, you are not allowed to view members.', 'buddypress' ), array( 'status' => rest_authorization_required_code(), ) ); } $user = bp_rest_get_user( $request['id'] ); if ( true === $retval && ! $user instanceof WP_User ) { $retval = new WP_Error( 'bp_rest_member_invalid_id', __( 'Invalid member ID.', 'buddypress' ), array( 'status' => 404, ) ); } if ( true === $retval && get_current_user_id() === $user->ID ) { $retval = true; } elseif ( true === $retval && 'edit' === $request['context'] && ! current_user_can( 'list_users' ) ) { $retval = new WP_Error( 'bp_rest_authorization_required', __( 'Sorry, you are not allowed to view members.', 'buddypress' ), array( 'status' => rest_authorization_required_code(), ) ); } /** * Filter the members `get_item` permissions check. * * @since 5.0.0 * * @param bool|WP_Error $retval Returned value. * @param WP_REST_Request $request The request sent to the API. */ return apply_filters( 'bp_rest_members_get_item_permissions_check', $retval, $request ); } /** * Checks if a given request has access create members. * * @since 5.0.0 * * @param WP_REST_Request $request Full details about the request. * @return bool|WP_Error */ public function create_item_permissions_check( $request ) { $retval = true; if ( ! ( is_user_logged_in() && current_user_can( 'bp_moderate' ) ) ) { $retval = new WP_Error( 'bp_rest_authorization_required', __( 'Sorry, you are not allowed to view members.', 'buddypress' ), array( 'status' => rest_authorization_required_code(), ) ); } /** * Filter or override the members `create_item` permissions check. * * @since 5.0.0 * * @param bool|WP_Error $retval Returned value. * @param WP_REST_Request $request The request sent to the API. */ return apply_filters( 'bp_rest_members_create_item_permissions_check', $retval, $request ); } /** * Check if a given request has access to update a member. * * @since 5.0.0 * * @param WP_REST_Request $request Full details about the request. * @return bool|WP_Error */ public function update_item_permissions_check( $request ) { $retval = true; $user = bp_rest_get_user( $request['id'] ); if ( ! $user instanceof WP_User ) { $retval = new WP_Error( 'bp_rest_member_invalid_id', __( 'Invalid member ID.', 'buddypress' ), array( 'status' => 404, ) ); } $action = 'delete'; if ( 'DELETE' !== $request->get_method() ) { $action = 'update'; } if ( true === $retval && ! $this->can_manage_member( $user, $action ) ) { $retval = new WP_Error( 'bp_rest_authorization_required', __( 'Sorry, you are not allowed to view members.', 'buddypress' ), array( 'status' => rest_authorization_required_code(), ) ); } /** * Filter the members `update_item` permissions check. * * @since 5.0.0 * * @param bool|WP_Error $retval Returned value. * @param WP_REST_Request $request The request sent to the API. */ return apply_filters( 'bp_rest_members_update_item_permissions_check', $retval, $request ); } /** * Check if a given request has access to delete a member. * * @since 5.0.0 * * @param WP_REST_Request $request Full details about the request. * @return bool|WP_Error */ public function delete_item_permissions_check( $request ) { $retval = $this->update_item_permissions_check( $request ); /** * Filter the members `delete_item` permissions check. * * @since 5.0.0 * * @param bool|WP_Error $retval Returned value. * @param WP_REST_Request $request The request sent to the API. */ return apply_filters( 'bp_rest_members_delete_item_permissions_check', $retval, $request ); } /** * Deleting the current user is not implemented into this endpoint. * * This action is specific to the User Settings endpoint. * * @since 5.0.0 * * @param WP_REST_Request $request Full details about the request. * @return WP_Error WP_Error object to inform it's not implemented. */ public function delete_current_item_permissions_check( $request ) { return new WP_Error( 'bp_rest_invalid_method', /* translators: %s: transport method name */ sprintf( __( '\'%s\' Transport Method not implemented.', 'buddypress' ), $request->get_method() ), array( 'status' => 405, ) ); } /** * Deleting the current user is not implemented into this endpoint. * * This action is specific to the User Settings endpoint. * * @since 5.0.0 * * @param WP_REST_Request $request Full details about the request. * @return WP_Error WP_Error to inform it's not implemented. */ public function delete_current_item( $request ) { return new WP_Error( 'bp_rest_invalid_method', /* translators: %s: transport method name */ sprintf( __( '\'%s\' Transport method not implemented.', 'buddypress' ), $request->get_method() ), array( 'status' => 405, ) ); } /** * Prepares a single user output for response. * * @since 5.0.0 * * @param WP_User $user User object. * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response */ public function prepare_item_for_response( $user, $request ) { $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; $data = $this->user_data( $user, $context ); $data = $this->add_additional_fields_to_object( $data, $request ); $data = $this->filter_response_by_context( $data, $context ); $response = rest_ensure_response( $data ); $response->add_links( $this->prepare_links( $user ) ); /** * Filters user data returned from the API. * * @since 5.0.0 * * @param WP_REST_Response $response The response object. * @param WP_REST_Request $request The request object. * @param WP_User $user WP_User object. */ return apply_filters( 'bp_rest_members_prepare_value', $response, $request, $user ); } /** * Method to facilitate fetching of user data. * * This was abstracted to be used in other BuddyPress endpoints. * * @since 5.0.0 * * @param WP_User $user User object. * @param string $context The context of the request. Defaults to 'view'. * @return array */ public function user_data( $user, $context = 'view' ) { $data = array( 'id' => $user->ID, 'name' => $user->display_name, 'user_login' => $user->user_login, 'link' => bp_core_get_user_domain( $user->ID, $user->user_nicename, $user->user_login ), 'member_types' => bp_get_member_type( $user->ID, false ), 'roles' => array(), 'capabilities' => array(), 'extra_capabilities' => array(), 'registered_date' => '', 'xprofile' => $this->xprofile_data( $user->ID ), ); if ( 'edit' === $context ) { $data['registered_date'] = bp_rest_prepare_date_response( $user->data->user_registered ); $data['roles'] = (array) array_values( $user->roles ); $data['capabilities'] = (array) array_keys( $user->allcaps ); $data['extra_capabilities'] = (array) array_keys( $user->caps ); } // The name used for that user in @-mentions. if ( bp_is_active( 'activity' ) ) { $data['mention_name'] = bp_activity_get_user_mentionname( $user->ID ); } // Avatars. $data['avatar_urls'] = array( 'full' => bp_core_fetch_avatar( array( 'item_id' => $user->ID, 'html' => false, 'type' => 'full', ) ), 'thumb' => bp_core_fetch_avatar( array( 'item_id' => $user->ID, 'html' => false, ) ), ); // Fallback. if ( false === $data['member_types'] ) { $data['member_types'] = array(); } return $data; } /** * Prepares a single user for creation or update. * * @todo Improve sanitization and schema verification. * * @since 5.0.0 * * @param WP_REST_Request $request Request object. * @return stdClass */ protected function prepare_item_for_database( $request ) { $prepared_user = parent::prepare_item_for_database( $request ); // The parent class uses username instead of user_login. if ( ! isset( $prepared_user->user_login ) && isset( $request['user_login'] ) ) { $prepared_user->user_login = $request['user_login']; } /** * Filters an user object before it is inserted or updated via the REST API. * * @since 5.0.0 * * @param stdClass $prepared_user An object prepared for inserting or updating the database. * @param WP_REST_Request $request Request object. */ return apply_filters( 'bp_rest_members_pre_insert_value', $prepared_user, $request ); } /** * Get XProfile info from the user. * * @since 5.0.0 * * @param int $user_id User ID. * @return array */ protected function xprofile_data( $user_id ) { $data = array(); // Get XProfile groups, only if the component is active. if ( bp_is_active( 'xprofile' ) ) { $fields_endpoint = new BP_REST_XProfile_Fields_Endpoint(); $groups = bp_xprofile_get_groups( array( 'user_id' => $user_id, 'fetch_fields' => true, 'fetch_field_data' => true, ) ); foreach ( $groups as $group ) { $data['groups'][ $group->id ] = array( 'name' => $group->name, ); foreach ( $group->fields as $item ) { $data['groups'][ $group->id ]['fields'][ $item->id ] = array( 'name' => $item->name, 'value' => array( 'raw' => $item->data->value, 'unserialized' => $fields_endpoint->get_profile_field_unserialized_value( $item->data->value ), 'rendered' => $fields_endpoint->get_profile_field_rendered_value( $item->data->value, $item ), ), ); } } } else { $data = array( __( 'No extended profile data available as the component is inactive', 'buddypress' ) ); } return $data; } /** * Can user manage (delete/update) a member? * * @since 5.0.0 * * @param WP_User $user User object. * @param string $action The action to perform (update or delete). * @return bool */ protected function can_manage_member( $user, $action = 'delete' ) { $capability = 'delete_user'; if ( 'update' === $action ) { $capability = 'edit_user'; } return ( current_user_can( 'bp_moderate' ) || current_user_can( $capability, $user->ID ) ); } /** * Updates the values of additional fields added to a data object. * * This function makes sure updating the field value thanks to the `id` property of * the created/updated object type is consistent accross BuddyPress components. * * @since 5.0.0 * * @param WP_User $object The WordPress user object. * @param WP_REST_Request $request Full details about the request. * @return bool|WP_Error True on success, WP_Error object if a field cannot be updated. */ protected function update_additional_fields_for_object( $object, $request ) { if ( ! isset( $object->data ) ) { return new WP_Error( 'invalid_user', __( 'The data for the user was not found.', 'buddypress' ) ); } $member = $object->data; $member->id = $member->ID; return WP_REST_Controller::update_additional_fields_for_object( $member, $request ); } /** * Make sure to retrieve the needed arguments for the endpoint CREATABLE method. * * @since 5.0.0 * * @param string $method Optional. HTTP method of the request. * @return array Endpoint arguments. */ public function get_endpoint_args_for_item_schema( $method = WP_REST_Server::CREATABLE ) { $args = WP_REST_Controller::get_endpoint_args_for_item_schema( $method ); $key = 'get_item'; if ( WP_REST_Server::CREATABLE === $method ) { $key = 'create_item'; // We don't need the mention name to create a user. unset( $args['mention_name'] ); // But we absolutely need the email. $args['email'] = array( 'description' => __( 'The email address for the member.', 'buddypress' ), 'type' => 'string', 'format' => 'email', 'context' => array( 'edit' ), 'required' => true, ); } elseif ( WP_REST_Server::EDITABLE === $method ) { $key = 'update_item'; /** * 1. The mention name or user login are not updatable. * 2. The password belongs to the Settings endpoint parameter. */ unset( $args['mention_name'], $args['user_login'], $args['password'] ); } elseif ( WP_REST_Server::DELETABLE === $method ) { $key = 'delete_item'; } /** * Filters the method query arguments. * * @since 5.0.0 * * @param array $args Query arguments. * @param string $method HTTP method of the request. */ return apply_filters( "bp_rest_members_{$key}_query_arguments", $args, $method ); } /** * Get the members schema, conforming to JSON Schema. * * @since 5.0.0 * * @return array */ public function get_item_schema() { $schema = array( '$schema' => 'http://json-schema.org/draft-04/schema#', 'title' => 'bp_members', 'type' => 'object', 'properties' => array( 'id' => array( 'description' => __( 'A unique numeric ID for the Member.', 'buddypress' ), 'type' => 'integer', 'context' => array( 'embed', 'view', 'edit' ), 'readonly' => true, ), 'name' => array( 'description' => __( 'Display name for the member.', 'buddypress' ), 'type' => 'string', 'context' => array( 'embed', 'view', 'edit' ), 'arg_options' => array( 'sanitize_callback' => 'sanitize_text_field', ), ), 'mention_name' => array( 'description' => __( 'The name used for that user in @-mentions.', 'buddypress' ), 'type' => 'string', 'context' => array( 'embed', 'view', 'edit' ), 'arg_options' => array( 'sanitize_callback' => 'sanitize_text_field', ), ), 'link' => array( 'description' => __( 'Profile URL of the member.', 'buddypress' ), 'type' => 'string', 'format' => 'uri', 'context' => array( 'embed', 'view', 'edit' ), 'readonly' => true, ), 'user_login' => array( 'description' => __( 'An alphanumeric identifier for the Member.', 'buddypress' ), 'type' => 'string', 'context' => array( 'embed', 'view', 'edit' ), 'required' => true, 'arg_options' => array( 'sanitize_callback' => array( $this, 'check_username' ), ), ), 'member_types' => array( 'description' => __( 'Member types associated with the member.', 'buddypress' ), 'type' => 'object', 'context' => array( 'embed', 'view', 'edit' ), 'readonly' => true, ), 'registered_date' => array( 'description' => __( 'Registration date for the member.', 'buddypress' ), 'type' => 'string', 'format' => 'date-time', 'context' => array( 'edit' ), 'readonly' => true, ), 'password' => array( 'description' => __( 'Password for the member (never included).', 'buddypress' ), 'type' => 'string', 'context' => array(), // Password is never displayed. 'required' => true, 'arg_options' => array( 'sanitize_callback' => array( $this, 'check_user_password' ), ), ), 'roles' => array( 'description' => __( 'Roles assigned to the member.', 'buddypress' ), 'type' => 'array', 'context' => array( 'edit' ), 'items' => array( 'type' => 'string', ), ), 'capabilities' => array( 'description' => __( 'All capabilities assigned to the user.', 'buddypress' ), 'type' => 'object', 'context' => array( 'edit' ), 'readonly' => true, ), 'extra_capabilities' => array( 'description' => __( 'Any extra capabilities assigned to the user.', 'buddypress' ), 'type' => 'object', 'context' => array( 'edit' ), 'readonly' => true, ), 'xprofile' => array( 'description' => __( 'Member XProfile groups and its fields.', 'buddypress' ), 'type' => 'array', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), ), ); // Avatars. if ( true === buddypress()->avatar->show_avatars ) { $avatar_properties = array(); $avatar_properties['full'] = array( /* translators: Full image size for the member Avatar */ 'description' => sprintf( __( 'Avatar URL with full image size (%1$d x %2$d pixels).', 'buddypress' ), number_format_i18n( bp_core_avatar_full_width() ), number_format_i18n( bp_core_avatar_full_height() ) ), 'type' => 'string', 'format' => 'uri', 'context' => array( 'embed', 'view', 'edit' ), ); $avatar_properties['thumb'] = array( /* translators: Thumb imaze size for the member Avatar */ 'description' => sprintf( __( 'Avatar URL with thumb image size (%1$d x %2$d pixels).', 'buddypress' ), number_format_i18n( bp_core_avatar_thumb_width() ), number_format_i18n( bp_core_avatar_thumb_height() ) ), 'type' => 'string', 'format' => 'uri', 'context' => array( 'embed', 'view', 'edit' ), ); $schema['properties']['avatar_urls'] = array( 'description' => __( 'Avatar URLs for the member.', 'buddypress' ), 'type' => 'object', 'context' => array( 'embed', 'view', 'edit' ), 'readonly' => true, 'properties' => $avatar_properties, ); } /** * Filters the members schema. * * @param array $schema The endpoint schema. */ return apply_filters( 'bp_rest_members_schema', $this->add_additional_fields_schema( $schema ) ); } /** * Get the query params for collections. * * @since 5.0.0 * * @return array */ public function get_collection_params() { $params = array_intersect_key( parent::get_collection_params(), array( 'context' => true, 'page' => true, 'per_page' => true, 'search' => true, ) ); $params['type'] = array( 'description' => __( 'Shorthand for certain orderby/order combinations.', 'buddypress' ), 'default' => 'newest', 'type' => 'string', 'enum' => array( 'active', 'newest', 'alphabetical', 'random', 'online', 'popular' ), 'sanitize_callback' => 'sanitize_key', 'validate_callback' => 'rest_validate_request_arg', ); $params['user_id'] = array( 'description' => __( 'Limit results to friends of a user.', 'buddypress' ), 'default' => 0, 'type' => 'integer', 'sanitize_callback' => 'absint', 'validate_callback' => 'rest_validate_request_arg', ); $params['user_ids'] = array( 'description' => __( 'Pass IDs of users to limit result set.', 'buddypress' ), 'default' => array(), 'type' => 'array', 'items' => array( 'type' => 'integer' ), 'sanitize_callback' => 'wp_parse_id_list', 'validate_callback' => 'rest_validate_request_arg', ); $params['include'] = array( 'description' => __( 'Ensure result set includes specific IDs.', 'buddypress' ), 'default' => array(), 'type' => 'array', 'items' => array( 'type' => 'integer' ), 'sanitize_callback' => 'wp_parse_id_list', 'validate_callback' => 'rest_validate_request_arg', ); $params['exclude'] = array( 'description' => __( 'Ensure result set excludes specific IDs.', 'buddypress' ), 'default' => array(), 'type' => 'array', 'items' => array( 'type' => 'integer' ), 'sanitize_callback' => 'wp_parse_id_list', 'validate_callback' => 'rest_validate_request_arg', ); $params['member_type'] = array( 'description' => __( 'Limit results set to certain type(s).', 'buddypress' ), 'default' => array(), 'type' => 'array', 'items' => array( 'type' => 'string' ), 'sanitize_callback' => 'bp_rest_sanitize_string_list', 'validate_callback' => 'rest_validate_request_arg', ); $params['xprofile'] = array( 'description' => __( 'Limit results set to a certain XProfile field.', 'buddypress' ), 'default' => '', 'type' => 'string', 'sanitize_callback' => 'sanitize_key', 'validate_callback' => 'rest_validate_request_arg', ); /** * Filters the collection query params. * * @param array $params Query params. */ return apply_filters( 'bp_rest_members_collection_params', $params ); } }
Changelog Changelog
Version | Description |
---|---|
5.0.0 | Introduced. |
Methods Methods
- __construct — Constructor.
- can_manage_member — Can user manage (delete/update) a member?
- create_item_permissions_check — Checks if a given request has access create members.
- delete_current_item — Deleting the current user is not implemented into this endpoint.
- delete_current_item_permissions_check — Deleting the current user is not implemented into this endpoint.
- delete_item_permissions_check — Check if a given request has access to delete a member.
- get_collection_params — Get the query params for collections.
- get_endpoint_args_for_item_schema — Make sure to retrieve the needed arguments for the endpoint CREATABLE method.
- get_item — Retrieves a single member.
- get_item_permissions_check — Checks if a given request has access to read a user.
- get_item_schema — Get the members schema, conforming to JSON Schema.
- get_items — Retrieve users.
- get_items_permissions_check — Checks if a given request has access to get all users.
- prepare_item_for_database — Prepares a single user for creation or update.
- prepare_item_for_response — Prepares a single user output for response.
- register_routes — Registers the routes for the objects of the controller.
- update_additional_fields_for_object — Updates the values of additional fields added to a data object.
- update_item_permissions_check — Check if a given request has access to update a member.
- user_data — Method to facilitate fetching of user data.
- xprofile_data — Get XProfile info from the user.