WordPress 4.7
[autoinstalls/wordpress.git] / wp-includes / rest-api / endpoints / class-wp-rest-users-controller.php
1 <?php
2 /**
3  * REST API: WP_REST_Users_Controller class
4  *
5  * @package WordPress
6  * @subpackage REST_API
7  * @since 4.7.0
8  */
9
10 /**
11  * Core class used to manage users via the REST API.
12  *
13  * @since 4.7.0
14  *
15  * @see WP_REST_Controller
16  */
17 class WP_REST_Users_Controller extends WP_REST_Controller {
18
19         /**
20          * Instance of a user meta fields object.
21          *
22          * @since 4.7.0
23          * @access protected
24          * @var WP_REST_User_Meta_Fields
25          */
26         protected $meta;
27
28         /**
29          * Constructor.
30          *
31          * @since 4.7.0
32          * @access public
33          */
34         public function __construct() {
35                 $this->namespace = 'wp/v2';
36                 $this->rest_base = 'users';
37
38                 $this->meta = new WP_REST_User_Meta_Fields();
39         }
40
41         /**
42          * Registers the routes for the objects of the controller.
43          *
44          * @since 4.7.0
45          * @access public
46          *
47          * @see register_rest_route()
48          */
49         public function register_routes() {
50
51                 register_rest_route( $this->namespace, '/' . $this->rest_base, array(
52                         array(
53                                 'methods'             => WP_REST_Server::READABLE,
54                                 'callback'            => array( $this, 'get_items' ),
55                                 'permission_callback' => array( $this, 'get_items_permissions_check' ),
56                                 'args'                => $this->get_collection_params(),
57                         ),
58                         array(
59                                 'methods'             => WP_REST_Server::CREATABLE,
60                                 'callback'            => array( $this, 'create_item' ),
61                                 'permission_callback' => array( $this, 'create_item_permissions_check' ),
62                                 'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ),
63                         ),
64                         'schema' => array( $this, 'get_public_item_schema' ),
65                 ) );
66
67                 register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array(
68                         array(
69                                 'methods'             => WP_REST_Server::READABLE,
70                                 'callback'            => array( $this, 'get_item' ),
71                                 'permission_callback' => array( $this, 'get_item_permissions_check' ),
72                                 'args'                => array(
73                                         'context' => $this->get_context_param( array( 'default' => 'view' ) ),
74                                 ),
75                         ),
76                         array(
77                                 'methods'             => WP_REST_Server::EDITABLE,
78                                 'callback'            => array( $this, 'update_item' ),
79                                 'permission_callback' => array( $this, 'update_item_permissions_check' ),
80                                 'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
81                         ),
82                         array(
83                                 'methods'             => WP_REST_Server::DELETABLE,
84                                 'callback'            => array( $this, 'delete_item' ),
85                                 'permission_callback' => array( $this, 'delete_item_permissions_check' ),
86                                 'args'                => array(
87                                         'force'    => array(
88                                                 'type'        => 'boolean',
89                                                 'default'     => false,
90                                                 'description' => __( 'Required to be true, as users do not support trashing.' ),
91                                         ),
92                                         'reassign' => array(
93                                                 'type'        => 'integer',
94                                                 'description' => __( 'Reassign the deleted user\'s posts and links to this user ID.' ),
95                                                 'required'    => true,
96                                                 'sanitize_callback' => array( $this, 'check_reassign' ),
97                                         ),
98                                 ),
99                         ),
100                         'schema' => array( $this, 'get_public_item_schema' ),
101                 ) );
102
103                 register_rest_route( $this->namespace, '/' . $this->rest_base . '/me', array(
104                         array(
105                                 'methods'             => WP_REST_Server::READABLE,
106                                 'callback'            => array( $this, 'get_current_item' ),
107                                 'args'                => array(
108                                         'context' => $this->get_context_param( array( 'default' => 'view' ) ),
109                                 ),
110                         ),
111                         array(
112                                 'methods'             => WP_REST_Server::EDITABLE,
113                                 'callback'            => array( $this, 'update_current_item' ),
114                                 'permission_callback' => array( $this, 'update_current_item_permissions_check' ),
115                                 'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
116                         ),
117                         array(
118                                 'methods'             => WP_REST_Server::DELETABLE,
119                                 'callback'            => array( $this, 'delete_current_item' ),
120                                 'permission_callback' => array( $this, 'delete_current_item_permissions_check' ),
121                                 'args'                => array(
122                                         'force'    => array(
123                                                 'type'        => 'boolean',
124                                                 'default'     => false,
125                                                 'description' => __( 'Required to be true, as users do not support trashing.' ),
126                                         ),
127                                         'reassign' => array(
128                                                 'type'        => 'integer',
129                                                 'description' => __( 'Reassign the deleted user\'s posts and links to this user ID.' ),
130                                                 'required'    => true,
131                                                 'sanitize_callback' => array( $this, 'check_reassign' ),
132                                         ),
133                                 ),
134                         ),
135                         'schema' => array( $this, 'get_public_item_schema' ),
136                 ));
137         }
138
139         /**
140          * Checks for a valid value for the reassign parameter when deleting users.
141          *
142          * The value can be an integer, 'false', false, or ''.
143          *
144          * @since 4.7.0
145          *
146          * @param int|bool        $value   The value passed to the reassign parameter.
147          * @param WP_REST_Request $request Full details about the request.
148          * @param string          $param   The parameter that is being sanitized.
149          *
150          * @return int|bool|WP_Error
151          */
152         public function check_reassign( $value, $request, $param ) {
153                 if ( is_numeric( $value ) ) {
154                         return $value;
155                 }
156
157                 if ( empty( $value ) || false === $value || 'false' === $value ) {
158                         return false;
159                 }
160
161                 return new WP_Error( 'rest_invalid_param', __( 'Invalid user parameter(s).' ), array( 'status' => 400 ) );
162         }
163
164         /**
165          * Permissions check for getting all users.
166          *
167          * @since 4.7.0
168          * @access public
169          *
170          * @param WP_REST_Request $request Full details about the request.
171          * @return true|WP_Error True if the request has read access, otherwise WP_Error object.
172          */
173         public function get_items_permissions_check( $request ) {
174                 // Check if roles is specified in GET request and if user can list users.
175                 if ( ! empty( $request['roles'] ) && ! current_user_can( 'list_users' ) ) {
176                         return new WP_Error( 'rest_user_cannot_view', __( 'Sorry, you are not allowed to filter users by role.' ), array( 'status' => rest_authorization_required_code() ) );
177                 }
178
179                 if ( 'edit' === $request['context'] && ! current_user_can( 'list_users' ) ) {
180                         return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to list users.' ), array( 'status' => rest_authorization_required_code() ) );
181                 }
182
183                 if ( in_array( $request['orderby'], array( 'email', 'registered_date' ), true ) && ! current_user_can( 'list_users' ) ) {
184                         return new WP_Error( 'rest_forbidden_orderby', __( 'Sorry, you are not allowed to order users by this parameter.' ), array( 'status' => rest_authorization_required_code() ) );
185                 }
186
187                 return true;
188         }
189
190         /**
191          * Retrieves all users.
192          *
193          * @since 4.7.0
194          * @access public
195          *
196          * @param WP_REST_Request $request Full details about the request.
197          * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
198          */
199         public function get_items( $request ) {
200
201                 // Retrieve the list of registered collection query parameters.
202                 $registered = $this->get_collection_params();
203
204                 /*
205                  * This array defines mappings between public API query parameters whose
206                  * values are accepted as-passed, and their internal WP_Query parameter
207                  * name equivalents (some are the same). Only values which are also
208                  * present in $registered will be set.
209                  */
210                 $parameter_mappings = array(
211                         'exclude'  => 'exclude',
212                         'include'  => 'include',
213                         'order'    => 'order',
214                         'per_page' => 'number',
215                         'search'   => 'search',
216                         'roles'    => 'role__in',
217                 );
218
219                 $prepared_args = array();
220
221                 /*
222                  * For each known parameter which is both registered and present in the request,
223                  * set the parameter's value on the query $prepared_args.
224                  */
225                 foreach ( $parameter_mappings as $api_param => $wp_param ) {
226                         if ( isset( $registered[ $api_param ], $request[ $api_param ] ) ) {
227                                 $prepared_args[ $wp_param ] = $request[ $api_param ];
228                         }
229                 }
230
231                 if ( isset( $registered['offset'] ) && ! empty( $request['offset'] ) ) {
232                         $prepared_args['offset'] = $request['offset'];
233                 } else {
234                         $prepared_args['offset']  = ( $request['page'] - 1 ) * $prepared_args['number'];
235                 }
236
237                 if ( isset( $registered['orderby'] ) ) {
238                         $orderby_possibles = array(
239                                 'id'              => 'ID',
240                                 'include'         => 'include',
241                                 'name'            => 'display_name',
242                                 'registered_date' => 'registered',
243                                 'slug'            => 'user_nicename',
244                                 'email'           => 'user_email',
245                                 'url'             => 'user_url',
246                         );
247                         $prepared_args['orderby'] = $orderby_possibles[ $request['orderby'] ];
248                 }
249
250                 if ( ! current_user_can( 'list_users' ) ) {
251                         $prepared_args['has_published_posts'] = true;
252                 }
253
254                 if ( ! empty( $prepared_args['search'] ) ) {
255                         $prepared_args['search'] = '*' . $prepared_args['search'] . '*';
256                 }
257
258                 if ( isset( $registered['slug'] ) && ! empty( $request['slug'] ) ) {
259                         $prepared_args['search'] = $request['slug'];
260                         $prepared_args['search_columns'] = array( 'user_nicename' );
261                 }
262
263                 /**
264                  * Filters WP_User_Query arguments when querying users via the REST API.
265                  *
266                  * @link https://developer.wordpress.org/reference/classes/wp_user_query/
267                  *
268                  * @since 4.7.0
269                  *
270                  * @param array           $prepared_args Array of arguments for WP_User_Query.
271                  * @param WP_REST_Request $request       The current request.
272                  */
273                 $prepared_args = apply_filters( 'rest_user_query', $prepared_args, $request );
274
275                 $query = new WP_User_Query( $prepared_args );
276
277                 $users = array();
278
279                 foreach ( $query->results as $user ) {
280                         $data = $this->prepare_item_for_response( $user, $request );
281                         $users[] = $this->prepare_response_for_collection( $data );
282                 }
283
284                 $response = rest_ensure_response( $users );
285
286                 // Store pagination values for headers then unset for count query.
287                 $per_page = (int) $prepared_args['number'];
288                 $page     = ceil( ( ( (int) $prepared_args['offset'] ) / $per_page ) + 1 );
289
290                 $prepared_args['fields'] = 'ID';
291
292                 $total_users = $query->get_total();
293
294                 if ( $total_users < 1 ) {
295                         // Out-of-bounds, run the query again without LIMIT for total count.
296                         unset( $prepared_args['number'], $prepared_args['offset'] );
297                         $count_query = new WP_User_Query( $prepared_args );
298                         $total_users = $count_query->get_total();
299                 }
300
301                 $response->header( 'X-WP-Total', (int) $total_users );
302
303                 $max_pages = ceil( $total_users / $per_page );
304
305                 $response->header( 'X-WP-TotalPages', (int) $max_pages );
306
307                 $base = add_query_arg( $request->get_query_params(), rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ) );
308                 if ( $page > 1 ) {
309                         $prev_page = $page - 1;
310
311                         if ( $prev_page > $max_pages ) {
312                                 $prev_page = $max_pages;
313                         }
314
315                         $prev_link = add_query_arg( 'page', $prev_page, $base );
316                         $response->link_header( 'prev', $prev_link );
317                 }
318                 if ( $max_pages > $page ) {
319                         $next_page = $page + 1;
320                         $next_link = add_query_arg( 'page', $next_page, $base );
321
322                         $response->link_header( 'next', $next_link );
323                 }
324
325                 return $response;
326         }
327
328         /**
329          * Checks if a given request has access to read a user.
330          *
331          * @since 4.7.0
332          * @access public
333          *
334          * @param WP_REST_Request $request Full details about the request.
335          * @return true|WP_Error True if the request has read access for the item, otherwise WP_Error object.
336          */
337         public function get_item_permissions_check( $request ) {
338
339                 $id = (int) $request['id'];
340                 $user = get_userdata( $id );
341                 $types = get_post_types( array( 'show_in_rest' => true ), 'names' );
342
343                 if ( empty( $id ) || empty( $user->ID ) ) {
344                         return new WP_Error( 'rest_user_invalid_id', __( 'Invalid user ID.' ), array( 'status' => 404 ) );
345                 }
346
347                 if ( get_current_user_id() === $id ) {
348                         return true;
349                 }
350
351                 if ( 'edit' === $request['context'] && ! current_user_can( 'list_users' ) ) {
352                         return new WP_Error( 'rest_user_cannot_view', __( 'Sorry, you are not allowed to list users.' ), array( 'status' => rest_authorization_required_code() ) );
353                 } elseif ( ! count_user_posts( $id, $types ) && ! current_user_can( 'edit_user', $id ) && ! current_user_can( 'list_users' ) ) {
354                         return new WP_Error( 'rest_user_cannot_view', __( 'Sorry, you are not allowed to list users.' ), array( 'status' => rest_authorization_required_code() ) );
355                 }
356
357                 return true;
358         }
359
360         /**
361          * Retrieves a single user.
362          *
363          * @since 4.7.0
364          * @access public
365          *
366          * @param WP_REST_Request $request Full details about the request.
367          * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
368          */
369         public function get_item( $request ) {
370                 $id   = (int) $request['id'];
371                 $user = get_userdata( $id );
372
373                 if ( empty( $id ) || empty( $user->ID ) ) {
374                         return new WP_Error( 'rest_user_invalid_id', __( 'Invalid user ID.' ), array( 'status' => 404 ) );
375                 }
376
377                 $user = $this->prepare_item_for_response( $user, $request );
378                 $response = rest_ensure_response( $user );
379
380                 return $response;
381         }
382
383         /**
384          * Retrieves the current user.
385          *
386          * @since 4.7.0
387          * @access public
388          *
389          * @param WP_REST_Request $request Full details about the request.
390          * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
391          */
392         public function get_current_item( $request ) {
393                 $current_user_id = get_current_user_id();
394
395                 if ( empty( $current_user_id ) ) {
396                         return new WP_Error( 'rest_not_logged_in', __( 'You are not currently logged in.' ), array( 'status' => 401 ) );
397                 }
398
399                 $user     = wp_get_current_user();
400                 $response = $this->prepare_item_for_response( $user, $request );
401                 $response = rest_ensure_response( $response );
402
403
404                 return $response;
405         }
406
407         /**
408          * Checks if a given request has access create users.
409          *
410          * @since 4.7.0
411          * @access public
412          *
413          * @param WP_REST_Request $request Full details about the request.
414          * @return true|WP_Error True if the request has access to create items, WP_Error object otherwise.
415          */
416         public function create_item_permissions_check( $request ) {
417
418                 if ( ! current_user_can( 'create_users' ) ) {
419                         return new WP_Error( 'rest_cannot_create_user', __( 'Sorry, you are not allowed to create new users.' ), array( 'status' => rest_authorization_required_code() ) );
420                 }
421
422                 return true;
423         }
424
425         /**
426          * Creates a single user.
427          *
428          * @since 4.7.0
429          * @access public
430          *
431          * @param WP_REST_Request $request Full details about the request.
432          * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
433          */
434         public function create_item( $request ) {
435                 if ( ! empty( $request['id'] ) ) {
436                         return new WP_Error( 'rest_user_exists', __( 'Cannot create existing user.' ), array( 'status' => 400 ) );
437                 }
438
439                 $schema = $this->get_item_schema();
440
441                 if ( ! empty( $request['roles'] ) && ! empty( $schema['properties']['roles'] ) ) {
442                         $check_permission = $this->check_role_update( $request['id'], $request['roles'] );
443
444                         if ( is_wp_error( $check_permission ) ) {
445                                 return $check_permission;
446                         }
447                 }
448
449                 $user = $this->prepare_item_for_database( $request );
450
451                 if ( is_multisite() ) {
452                         $ret = wpmu_validate_user_signup( $user->user_login, $user->user_email );
453
454                         if ( is_wp_error( $ret['errors'] ) && ! empty( $ret['errors']->errors ) ) {
455                                 $error = new WP_Error( 'rest_invalid_param', __( 'Invalid user parameter(s).' ), array( 'status' => 400 ) );
456                                 foreach ( $ret['errors']->errors as $code => $messages ) {
457                                         foreach ( $messages as $message ) {
458                                                 $error->add( $code, $message );
459                                         }
460                                         if ( $error_data = $error->get_error_data( $code ) ) {
461                                                 $error->add_data( $error_data, $code );
462                                         }
463                                 }
464                                 return $error;
465                         }
466                 }
467
468                 if ( is_multisite() ) {
469                         $user_id = wpmu_create_user( $user->user_login, $user->user_pass, $user->user_email );
470
471                         if ( ! $user_id ) {
472                                 return new WP_Error( 'rest_user_create', __( 'Error creating new user.' ), array( 'status' => 500 ) );
473                         }
474
475                         $user->ID = $user_id;
476                         $user_id  = wp_update_user( wp_slash( (array) $user ) );
477
478                         if ( is_wp_error( $user_id ) ) {
479                                 return $user_id;
480                         }
481
482                         add_user_to_blog( get_site()->id, $user_id, '' );
483                 } else {
484                         $user_id = wp_insert_user( wp_slash( (array) $user ) );
485
486                         if ( is_wp_error( $user_id ) ) {
487                                 return $user_id;
488                         }
489                 }
490
491                 $user = get_user_by( 'id', $user_id );
492
493                 /**
494                  * Fires immediately after a user is created or updated via the REST API.
495                  *
496                  * @since 4.7.0
497                  *
498                  * @param WP_User         $user     Inserted or updated user object.
499                  * @param WP_REST_Request $request  Request object.
500                  * @param bool            $creating True when creating a user, false when updating.
501                  */
502                 do_action( 'rest_insert_user', $user, $request, true );
503
504                 if ( ! empty( $request['roles'] ) && ! empty( $schema['properties']['roles'] ) ) {
505                         array_map( array( $user, 'add_role' ), $request['roles'] );
506                 }
507
508                 if ( ! empty( $schema['properties']['meta'] ) && isset( $request['meta'] ) ) {
509                         $meta_update = $this->meta->update_value( $request['meta'], $user_id );
510
511                         if ( is_wp_error( $meta_update ) ) {
512                                 return $meta_update;
513                         }
514                 }
515
516                 $user = get_user_by( 'id', $user_id );
517                 $fields_update = $this->update_additional_fields_for_object( $user, $request );
518
519                 if ( is_wp_error( $fields_update ) ) {
520                         return $fields_update;
521                 }
522
523                 $request->set_param( 'context', 'edit' );
524
525                 $response = $this->prepare_item_for_response( $user, $request );
526                 $response = rest_ensure_response( $response );
527
528                 $response->set_status( 201 );
529                 $response->header( 'Location', rest_url( sprintf( '%s/%s/%d', $this->namespace, $this->rest_base, $user_id ) ) );
530
531                 return $response;
532         }
533
534         /**
535          * Checks if a given request has access to update a user.
536          *
537          * @since 4.7.0
538          * @access public
539          *
540          * @param WP_REST_Request $request Full details about the request.
541          * @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise.
542          */
543         public function update_item_permissions_check( $request ) {
544
545                 $id = (int) $request['id'];
546
547                 if ( ! current_user_can( 'edit_user', $id ) ) {
548                         return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to edit this user.' ), array( 'status' => rest_authorization_required_code() ) );
549                 }
550
551                 if ( ! empty( $request['roles'] ) && ! current_user_can( 'edit_users' ) ) {
552                         return new WP_Error( 'rest_cannot_edit_roles', __( 'Sorry, you are not allowed to edit roles of this user.' ), array( 'status' => rest_authorization_required_code() ) );
553                 }
554
555                 return true;
556         }
557
558         /**
559          * Updates a single user.
560          *
561          * @since 4.7.0
562          * @access public
563          *
564          * @param WP_REST_Request $request Full details about the request.
565          * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
566          */
567         public function update_item( $request ) {
568                 $id   = (int) $request['id'];
569                 $user = get_userdata( $id );
570
571                 if ( ! $user ) {
572                         return new WP_Error( 'rest_user_invalid_id', __( 'Invalid user ID.' ), array( 'status' => 404 ) );
573                 }
574
575                 if ( email_exists( $request['email'] ) && $request['email'] !== $user->user_email ) {
576                         return new WP_Error( 'rest_user_invalid_email', __( 'Invalid email address.' ), array( 'status' => 400 ) );
577                 }
578
579                 if ( ! empty( $request['username'] ) && $request['username'] !== $user->user_login ) {
580                         return new WP_Error( 'rest_user_invalid_argument', __( "Username isn't editable." ), array( 'status' => 400 ) );
581                 }
582
583                 if ( ! empty( $request['slug'] ) && $request['slug'] !== $user->user_nicename && get_user_by( 'slug', $request['slug'] ) ) {
584                         return new WP_Error( 'rest_user_invalid_slug', __( 'Invalid slug.' ), array( 'status' => 400 ) );
585                 }
586
587                 if ( ! empty( $request['roles'] ) ) {
588                         $check_permission = $this->check_role_update( $id, $request['roles'] );
589
590                         if ( is_wp_error( $check_permission ) ) {
591                                 return $check_permission;
592                         }
593                 }
594
595                 $user = $this->prepare_item_for_database( $request );
596
597                 // Ensure we're operating on the same user we already checked.
598                 $user->ID = $id;
599
600                 $user_id = wp_update_user( wp_slash( (array) $user ) );
601
602                 if ( is_wp_error( $user_id ) ) {
603                         return $user_id;
604                 }
605
606                 $user = get_user_by( 'id', $user_id );
607
608                 /* This action is documented in lib/endpoints/class-wp-rest-users-controller.php */
609                 do_action( 'rest_insert_user', $user, $request, false );
610
611                 if ( is_multisite() && ! is_user_member_of_blog( $id ) ) {
612                         add_user_to_blog( get_current_blog_id(), $id, '' );
613                 }
614
615                 if ( ! empty( $request['roles'] ) ) {
616                         array_map( array( $user, 'add_role' ), $request['roles'] );
617                 }
618
619                 $schema = $this->get_item_schema();
620
621                 if ( ! empty( $schema['properties']['meta'] ) && isset( $request['meta'] ) ) {
622                         $meta_update = $this->meta->update_value( $request['meta'], $id );
623
624                         if ( is_wp_error( $meta_update ) ) {
625                                 return $meta_update;
626                         }
627                 }
628
629                 $user = get_user_by( 'id', $user_id );
630                 $fields_update = $this->update_additional_fields_for_object( $user, $request );
631
632                 if ( is_wp_error( $fields_update ) ) {
633                         return $fields_update;
634                 }
635
636                 $request->set_param( 'context', 'edit' );
637
638                 $response = $this->prepare_item_for_response( $user, $request );
639                 $response = rest_ensure_response( $response );
640
641                 return $response;
642         }
643
644         /**
645          * Checks if a given request has access to update the current user.
646          *
647          * @since 4.7.0
648          * @access public
649          *
650          * @param WP_REST_Request $request Full details about the request.
651          * @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise.
652          */
653         public function update_current_item_permissions_check( $request ) {
654                 $request['id'] = get_current_user_id();
655
656                 return $this->update_item_permissions_check( $request );
657         }
658
659         /**
660          * Updates the current user.
661          *
662          * @since 4.7.0
663          * @access public
664          *
665          * @param WP_REST_Request $request Full details about the request.
666          * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
667          */
668         function update_current_item( $request ) {
669                 $request['id'] = get_current_user_id();
670
671                 return $this->update_item( $request );
672         }
673
674         /**
675          * Checks if a given request has access delete a user.
676          *
677          * @since 4.7.0
678          * @access public
679          *
680          * @param WP_REST_Request $request Full details about the request.
681          * @return true|WP_Error True if the request has access to delete the item, WP_Error object otherwise.
682          */
683         public function delete_item_permissions_check( $request ) {
684
685                 $id = (int) $request['id'];
686
687                 if ( ! current_user_can( 'delete_user', $id ) ) {
688                         return new WP_Error( 'rest_user_cannot_delete', __( 'Sorry, you are not allowed to delete this user.' ), array( 'status' => rest_authorization_required_code() ) );
689                 }
690
691                 return true;
692         }
693
694         /**
695          * Deletes a single user.
696          *
697          * @since 4.7.0
698          * @access public
699          *
700          * @param WP_REST_Request $request Full details about the request.
701          * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
702          */
703         public function delete_item( $request ) {
704                 // We don't support delete requests in multisite.
705                 if ( is_multisite() ) {
706                         return new WP_Error( 'rest_cannot_delete', __( 'The user cannot be deleted.' ), array( 'status' => 501 ) );
707                 }
708
709                 $id       = (int) $request['id'];
710                 $reassign = false === $request['reassign'] ? null : absint( $request['reassign'] );
711                 $force    = isset( $request['force'] ) ? (bool) $request['force'] : false;
712
713                 // We don't support trashing for users.
714                 if ( ! $force ) {
715                         return new WP_Error( 'rest_trash_not_supported', __( 'Users do not support trashing. Set force=true to delete.' ), array( 'status' => 501 ) );
716                 }
717
718                 $user = get_userdata( $id );
719
720                 if ( ! $user ) {
721                         return new WP_Error( 'rest_user_invalid_id', __( 'Invalid user ID.' ), array( 'status' => 404 ) );
722                 }
723
724                 if ( ! empty( $reassign ) ) {
725                         if ( $reassign === $id || ! get_userdata( $reassign ) ) {
726                                 return new WP_Error( 'rest_user_invalid_reassign', __( 'Invalid user ID for reassignment.' ), array( 'status' => 400 ) );
727                         }
728                 }
729
730                 $request->set_param( 'context', 'edit' );
731
732                 $previous = $this->prepare_item_for_response( $user, $request );
733
734                 /** Include admin user functions to get access to wp_delete_user() */
735                 require_once ABSPATH . 'wp-admin/includes/user.php';
736
737                 $result = wp_delete_user( $id, $reassign );
738
739                 if ( ! $result ) {
740                         return new WP_Error( 'rest_cannot_delete', __( 'The user cannot be deleted.' ), array( 'status' => 500 ) );
741                 }
742
743                 $response = new WP_REST_Response();
744                 $response->set_data( array( 'deleted' => true, 'previous' => $previous->get_data() ) );
745
746                 /**
747                  * Fires immediately after a user is deleted via the REST API.
748                  *
749                  * @since 4.7.0
750                  *
751                  * @param WP_User          $user     The user data.
752                  * @param WP_REST_Response $response The response returned from the API.
753                  * @param WP_REST_Request  $request  The request sent to the API.
754                  */
755                 do_action( 'rest_delete_user', $user, $response, $request );
756
757                 return $response;
758         }
759
760         /**
761          * Checks if a given request has access to delete the current user.
762          *
763          * @since 4.7.0
764          * @access public
765          *
766          * @param WP_REST_Request $request Full details about the request.
767          * @return true|WP_Error True if the request has access to delete the item, WP_Error object otherwise.
768          */
769         public function delete_current_item_permissions_check( $request ) {
770                 $request['id'] = get_current_user_id();
771
772                 return $this->delete_item_permissions_check( $request );
773         }
774
775         /**
776          * Deletes the current user.
777          *
778          * @since 4.7.0
779          * @access public
780          *
781          * @param WP_REST_Request $request Full details about the request.
782          * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
783          */
784         function delete_current_item( $request ) {
785                 $request['id'] = get_current_user_id();
786
787                 return $this->delete_item( $request );
788         }
789
790         /**
791          * Prepares a single user output for response.
792          *
793          * @since 4.7.0
794          * @access public
795          *
796          * @param WP_User         $user    User object.
797          * @param WP_REST_Request $request Request object.
798          * @return WP_REST_Response Response object.
799          */
800         public function prepare_item_for_response( $user, $request ) {
801
802                 $data   = array();
803                 $schema = $this->get_item_schema();
804
805                 if ( ! empty( $schema['properties']['id'] ) ) {
806                         $data['id'] = $user->ID;
807                 }
808
809                 if ( ! empty( $schema['properties']['username'] ) ) {
810                         $data['username'] = $user->user_login;
811                 }
812
813                 if ( ! empty( $schema['properties']['name'] ) ) {
814                         $data['name'] = $user->display_name;
815                 }
816
817                 if ( ! empty( $schema['properties']['first_name'] ) ) {
818                         $data['first_name'] = $user->first_name;
819                 }
820
821                 if ( ! empty( $schema['properties']['last_name'] ) ) {
822                         $data['last_name'] = $user->last_name;
823                 }
824
825                 if ( ! empty( $schema['properties']['email'] ) ) {
826                         $data['email'] = $user->user_email;
827                 }
828
829                 if ( ! empty( $schema['properties']['url'] ) ) {
830                         $data['url'] = $user->user_url;
831                 }
832
833                 if ( ! empty( $schema['properties']['description'] ) ) {
834                         $data['description'] = $user->description;
835                 }
836
837                 if ( ! empty( $schema['properties']['link'] ) ) {
838                         $data['link'] = get_author_posts_url( $user->ID, $user->user_nicename );
839                 }
840
841                 if ( ! empty( $schema['properties']['locale'] ) ) {
842                         $data['locale'] = get_user_locale( $user );
843                 }
844
845                 if ( ! empty( $schema['properties']['nickname'] ) ) {
846                         $data['nickname'] = $user->nickname;
847                 }
848
849                 if ( ! empty( $schema['properties']['slug'] ) ) {
850                         $data['slug'] = $user->user_nicename;
851                 }
852
853                 if ( ! empty( $schema['properties']['roles'] ) ) {
854                         // Defensively call array_values() to ensure an array is returned.
855                         $data['roles'] = array_values( $user->roles );
856                 }
857
858                 if ( ! empty( $schema['properties']['registered_date'] ) ) {
859                         $data['registered_date'] = date( 'c', strtotime( $user->user_registered ) );
860                 }
861
862                 if ( ! empty( $schema['properties']['capabilities'] ) ) {
863                         $data['capabilities'] = (object) $user->allcaps;
864                 }
865
866                 if ( ! empty( $schema['properties']['extra_capabilities'] ) ) {
867                         $data['extra_capabilities'] = (object) $user->caps;
868                 }
869
870                 if ( ! empty( $schema['properties']['avatar_urls'] ) ) {
871                         $data['avatar_urls'] = rest_get_avatar_urls( $user->user_email );
872                 }
873
874                 if ( ! empty( $schema['properties']['meta'] ) ) {
875                         $data['meta'] = $this->meta->get_value( $user->ID, $request );
876                 }
877
878                 $context = ! empty( $request['context'] ) ? $request['context'] : 'embed';
879
880                 $data = $this->add_additional_fields_to_object( $data, $request );
881                 $data = $this->filter_response_by_context( $data, $context );
882
883                 // Wrap the data in a response object.
884                 $response = rest_ensure_response( $data );
885
886                 $response->add_links( $this->prepare_links( $user ) );
887
888                 /**
889                  * Filters user data returned from the REST API.
890                  *
891                  * @since 4.7.0
892                  *
893                  * @param WP_REST_Response $response The response object.
894                  * @param object           $user     User object used to create response.
895                  * @param WP_REST_Request  $request  Request object.
896                  */
897                 return apply_filters( 'rest_prepare_user', $response, $user, $request );
898         }
899
900         /**
901          * Prepares links for the user request.
902          *
903          * @since 4.7.0
904          * @access protected
905          *
906          * @param WP_Post $user User object.
907          * @return array Links for the given user.
908          */
909         protected function prepare_links( $user ) {
910                 $links = array(
911                         'self' => array(
912                                 'href' => rest_url( sprintf( '%s/%s/%d', $this->namespace, $this->rest_base, $user->ID ) ),
913                         ),
914                         'collection' => array(
915                                 'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ),
916                         ),
917                 );
918
919                 return $links;
920         }
921
922         /**
923          * Prepares a single user for creation or update.
924          *
925          * @since 4.7.0
926          * @access protected
927          *
928          * @param WP_REST_Request $request Request object.
929          * @return object $prepared_user User object.
930          */
931         protected function prepare_item_for_database( $request ) {
932                 $prepared_user = new stdClass;
933
934                 $schema = $this->get_item_schema();
935
936                 // required arguments.
937                 if ( isset( $request['email'] ) && ! empty( $schema['properties']['email'] ) ) {
938                         $prepared_user->user_email = $request['email'];
939                 }
940
941                 if ( isset( $request['username'] ) && ! empty( $schema['properties']['username'] ) ) {
942                         $prepared_user->user_login = $request['username'];
943                 }
944
945                 if ( isset( $request['password'] ) && ! empty( $schema['properties']['password'] ) ) {
946                         $prepared_user->user_pass = $request['password'];
947                 }
948
949                 // optional arguments.
950                 if ( isset( $request['id'] ) ) {
951                         $prepared_user->ID = absint( $request['id'] );
952                 }
953
954                 if ( isset( $request['name'] ) && ! empty( $schema['properties']['name'] ) ) {
955                         $prepared_user->display_name = $request['name'];
956                 }
957
958                 if ( isset( $request['first_name'] ) && ! empty( $schema['properties']['first_name'] ) ) {
959                         $prepared_user->first_name = $request['first_name'];
960                 }
961
962                 if ( isset( $request['last_name'] ) && ! empty( $schema['properties']['last_name'] ) ) {
963                         $prepared_user->last_name = $request['last_name'];
964                 }
965
966                 if ( isset( $request['nickname'] ) && ! empty( $schema['properties']['nickname'] ) ) {
967                         $prepared_user->nickname = $request['nickname'];
968                 }
969
970                 if ( isset( $request['slug'] ) && ! empty( $schema['properties']['slug'] ) ) {
971                         $prepared_user->user_nicename = $request['slug'];
972                 }
973
974                 if ( isset( $request['description'] ) && ! empty( $schema['properties']['description'] ) ) {
975                         $prepared_user->description = $request['description'];
976                 }
977
978                 if ( isset( $request['url'] ) && ! empty( $schema['properties']['url'] ) ) {
979                         $prepared_user->user_url = $request['url'];
980                 }
981
982                 if ( isset( $request['locale'] ) && ! empty( $schema['properties']['locale'] ) ) {
983                         $prepared_user->locale = $request['locale'];
984                 }
985
986                 // setting roles will be handled outside of this function.
987                 if ( isset( $request['roles'] ) ) {
988                         $prepared_user->role = false;
989                 }
990
991                 /**
992                  * Filters user data before insertion via the REST API.
993                  *
994                  * @since 4.7.0
995                  *
996                  * @param object          $prepared_user User object.
997                  * @param WP_REST_Request $request       Request object.
998                  */
999                 return apply_filters( 'rest_pre_insert_user', $prepared_user, $request );
1000         }
1001
1002         /**
1003          * Determines if the current user is allowed to make the desired roles change.
1004          *
1005          * @since 4.7.0
1006          * @access protected
1007          *
1008          * @param integer $user_id User ID.
1009          * @param array   $roles   New user roles.
1010          * @return true|WP_Error True if the current user is allowed to make the role change,
1011          *                       otherwise a WP_Error object.
1012          */
1013         protected function check_role_update( $user_id, $roles ) {
1014                 global $wp_roles;
1015
1016                 foreach ( $roles as $role ) {
1017
1018                         if ( ! isset( $wp_roles->role_objects[ $role ] ) ) {
1019                                 /* translators: %s: role key */
1020                                 return new WP_Error( 'rest_user_invalid_role', sprintf( __( 'The role %s does not exist.' ), $role ), array( 'status' => 400 ) );
1021                         }
1022
1023                         $potential_role = $wp_roles->role_objects[ $role ];
1024
1025                         /*
1026                          * Don't let anyone with 'edit_users' (admins) edit their own role to something without it.
1027                          * Multisite super admins can freely edit their blog roles -- they possess all caps.
1028                          */
1029                         if ( ! ( is_multisite()
1030                                 && current_user_can( 'manage_sites' ) )
1031                                 && get_current_user_id() === $user_id
1032                                 && ! $potential_role->has_cap( 'edit_users' )
1033                         ) {
1034                                 return new WP_Error( 'rest_user_invalid_role', __( 'Sorry, you are not allowed to give users that role.' ), array( 'status' => rest_authorization_required_code() ) );
1035                         }
1036
1037                         /** Include admin functions to get access to get_editable_roles() */
1038                         require_once ABSPATH . 'wp-admin/includes/admin.php';
1039
1040                         // The new role must be editable by the logged-in user.
1041                         $editable_roles = get_editable_roles();
1042
1043                         if ( empty( $editable_roles[ $role ] ) ) {
1044                                 return new WP_Error( 'rest_user_invalid_role', __( 'Sorry, you are not allowed to give users that role.' ), array( 'status' => 403 ) );
1045                         }
1046                 }
1047
1048                 return true;
1049         }
1050
1051         /**
1052          * Check a username for the REST API.
1053          *
1054          * Performs a couple of checks like edit_user() in wp-admin/includes/user.php.
1055          *
1056          * @since 4.7.0
1057          *
1058          * @param  mixed            $value   The username submitted in the request.
1059          * @param  WP_REST_Request  $request Full details about the request.
1060          * @param  string           $param   The parameter name.
1061          * @return WP_Error|string The sanitized username, if valid, otherwise an error.
1062          */
1063         public function check_username( $value, $request, $param ) {
1064                 $username = (string) $value;
1065
1066                 if ( ! validate_username( $username ) ) {
1067                         return new WP_Error( 'rest_user_invalid_username', __( 'Username contains invalid characters.' ), array( 'status' => 400 ) );
1068                 }
1069
1070                 /** This filter is documented in wp-includes/user.php */
1071                 $illegal_logins = (array) apply_filters( 'illegal_user_logins', array() );
1072
1073                 if ( in_array( strtolower( $username ), array_map( 'strtolower', $illegal_logins ) ) ) {
1074                         return new WP_Error( 'rest_user_invalid_username', __( 'Sorry, that username is not allowed.' ), array( 'status' => 400 ) );
1075                 }
1076
1077                 return $username;
1078         }
1079
1080         /**
1081          * Check a user password for the REST API.
1082          *
1083          * Performs a couple of checks like edit_user() in wp-admin/includes/user.php.
1084          *
1085          * @since 4.7.0
1086          *
1087          * @param  mixed            $value   The password submitted in the request.
1088          * @param  WP_REST_Request  $request Full details about the request.
1089          * @param  string           $param   The parameter name.
1090          * @return WP_Error|string The sanitized password, if valid, otherwise an error.
1091          */
1092         public function check_user_password( $value, $request, $param ) {
1093                 $password = (string) $value;
1094
1095                 if ( empty( $password ) ) {
1096                         return new WP_Error( 'rest_user_invalid_password', __( 'Passwords cannot be empty.' ), array( 'status' => 400 ) );
1097                 }
1098
1099                 if ( false !== strpos( $password, "\\" ) ) {
1100                         return new WP_Error( 'rest_user_invalid_password', __( 'Passwords cannot contain the "\\" character.' ), array( 'status' => 400 ) );
1101                 }
1102
1103                 return $password;
1104         }
1105
1106         /**
1107          * Retrieves the user's schema, conforming to JSON Schema.
1108          *
1109          * @since 4.7.0
1110          * @access public
1111          *
1112          * @return array Item schema data.
1113          */
1114         public function get_item_schema() {
1115                 $schema = array(
1116                         '$schema'    => 'http://json-schema.org/schema#',
1117                         'title'      => 'user',
1118                         'type'       => 'object',
1119                         'properties' => array(
1120                                 'id'          => array(
1121                                         'description' => __( 'Unique identifier for the user.' ),
1122                                         'type'        => 'integer',
1123                                         'context'     => array( 'embed', 'view', 'edit' ),
1124                                         'readonly'    => true,
1125                                 ),
1126                                 'username'    => array(
1127                                         'description' => __( 'Login name for the user.' ),
1128                                         'type'        => 'string',
1129                                         'context'     => array( 'edit' ),
1130                                         'required'    => true,
1131                                         'arg_options' => array(
1132                                                 'sanitize_callback' => array( $this, 'check_username' ),
1133                                         ),
1134                                 ),
1135                                 'name'        => array(
1136                                         'description' => __( 'Display name for the user.' ),
1137                                         'type'        => 'string',
1138                                         'context'     => array( 'embed', 'view', 'edit' ),
1139                                         'arg_options' => array(
1140                                                 'sanitize_callback' => 'sanitize_text_field',
1141                                         ),
1142                                 ),
1143                                 'first_name'  => array(
1144                                         'description' => __( 'First name for the user.' ),
1145                                         'type'        => 'string',
1146                                         'context'     => array( 'edit' ),
1147                                         'arg_options' => array(
1148                                                 'sanitize_callback' => 'sanitize_text_field',
1149                                         ),
1150                                 ),
1151                                 'last_name'   => array(
1152                                         'description' => __( 'Last name for the user.' ),
1153                                         'type'        => 'string',
1154                                         'context'     => array( 'edit' ),
1155                                         'arg_options' => array(
1156                                                 'sanitize_callback' => 'sanitize_text_field',
1157                                         ),
1158                                 ),
1159                                 'email'       => array(
1160                                         'description' => __( 'The email address for the user.' ),
1161                                         'type'        => 'string',
1162                                         'format'      => 'email',
1163                                         'context'     => array( 'edit' ),
1164                                         'required'    => true,
1165                                 ),
1166                                 'url'         => array(
1167                                         'description' => __( 'URL of the user.' ),
1168                                         'type'        => 'string',
1169                                         'format'      => 'uri',
1170                                         'context'     => array( 'embed', 'view', 'edit' ),
1171                                 ),
1172                                 'description' => array(
1173                                         'description' => __( 'Description of the user.' ),
1174                                         'type'        => 'string',
1175                                         'context'     => array( 'embed', 'view', 'edit' ),
1176                                 ),
1177                                 'link'        => array(
1178                                         'description' => __( 'Author URL of the user.' ),
1179                                         'type'        => 'string',
1180                                         'format'      => 'uri',
1181                                         'context'     => array( 'embed', 'view', 'edit' ),
1182                                         'readonly'    => true,
1183                                 ),
1184                                 'locale'    => array(
1185                                         'description' => __( 'Locale for the user.' ),
1186                                         'type'        => 'string',
1187                                         'enum'        => array_merge( array( '', 'en_US' ), get_available_languages() ),
1188                                         'context'     => array( 'edit' ),
1189                                 ),
1190                                 'nickname'    => array(
1191                                         'description' => __( 'The nickname for the user.' ),
1192                                         'type'        => 'string',
1193                                         'context'     => array( 'edit' ),
1194                                         'arg_options' => array(
1195                                                 'sanitize_callback' => 'sanitize_text_field',
1196                                         ),
1197                                 ),
1198                                 'slug'        => array(
1199                                         'description' => __( 'An alphanumeric identifier for the user.' ),
1200                                         'type'        => 'string',
1201                                         'context'     => array( 'embed', 'view', 'edit' ),
1202                                         'arg_options' => array(
1203                                                 'sanitize_callback' => array( $this, 'sanitize_slug' ),
1204                                         ),
1205                                 ),
1206                                 'registered_date' => array(
1207                                         'description' => __( 'Registration date for the user.' ),
1208                                         'type'        => 'string',
1209                                         'format'      => 'date-time',
1210                                         'context'     => array( 'edit' ),
1211                                         'readonly'    => true,
1212                                 ),
1213                                 'roles'           => array(
1214                                         'description' => __( 'Roles assigned to the user.' ),
1215                                         'type'        => 'array',
1216                                         'items'       => array(
1217                                                 'type'    => 'string',
1218                                         ),
1219                                         'context'     => array( 'edit' ),
1220                                 ),
1221                                 'password'        => array(
1222                                         'description' => __( 'Password for the user (never included).' ),
1223                                         'type'        => 'string',
1224                                         'context'     => array(), // Password is never displayed.
1225                                         'required'    => true,
1226                                         'arg_options' => array(
1227                                                 'sanitize_callback' => array( $this, 'check_user_password' ),
1228                                         ),
1229                                 ),
1230                                 'capabilities'    => array(
1231                                         'description' => __( 'All capabilities assigned to the user.' ),
1232                                         'type'        => 'object',
1233                                         'context'     => array( 'edit' ),
1234                                         'readonly'    => true,
1235                                 ),
1236                                 'extra_capabilities' => array(
1237                                         'description' => __( 'Any extra capabilities assigned to the user.' ),
1238                                         'type'        => 'object',
1239                                         'context'     => array( 'edit' ),
1240                                         'readonly'    => true,
1241                                 ),
1242                         ),
1243                 );
1244
1245                 if ( get_option( 'show_avatars' ) ) {
1246                         $avatar_properties = array();
1247
1248                         $avatar_sizes = rest_get_avatar_sizes();
1249
1250                         foreach ( $avatar_sizes as $size ) {
1251                                 $avatar_properties[ $size ] = array(
1252                                         /* translators: %d: avatar image size in pixels */
1253                                         'description' => sprintf( __( 'Avatar URL with image size of %d pixels.' ), $size ),
1254                                         'type'        => 'string',
1255                                         'format'      => 'uri',
1256                                         'context'     => array( 'embed', 'view', 'edit' ),
1257                                 );
1258                         }
1259
1260                         $schema['properties']['avatar_urls']  = array(
1261                                 'description' => __( 'Avatar URLs for the user.' ),
1262                                 'type'        => 'object',
1263                                 'context'     => array( 'embed', 'view', 'edit' ),
1264                                 'readonly'    => true,
1265                                 'properties'  => $avatar_properties,
1266                         );
1267                 }
1268
1269                 $schema['properties']['meta'] = $this->meta->get_field_schema();
1270
1271                 return $this->add_additional_fields_schema( $schema );
1272         }
1273
1274         /**
1275          * Retrieves the query params for collections.
1276          *
1277          * @since 4.7.0
1278          * @access public
1279          *
1280          * @return array Collection parameters.
1281          */
1282         public function get_collection_params() {
1283                 $query_params = parent::get_collection_params();
1284
1285                 $query_params['context']['default'] = 'view';
1286
1287                 $query_params['exclude'] = array(
1288                         'description'        => __( 'Ensure result set excludes specific IDs.' ),
1289                         'type'               => 'array',
1290                         'items'              => array(
1291                                 'type'           => 'integer',
1292                         ),
1293                         'default'            => array(),
1294                 );
1295
1296                 $query_params['include'] = array(
1297                         'description'        => __( 'Limit result set to specific IDs.' ),
1298                         'type'               => 'array',
1299                         'items'              => array(
1300                                 'type'           => 'integer',
1301                         ),
1302                         'default'            => array(),
1303                 );
1304
1305                 $query_params['offset'] = array(
1306                         'description'        => __( 'Offset the result set by a specific number of items.' ),
1307                         'type'               => 'integer',
1308                 );
1309
1310                 $query_params['order'] = array(
1311                         'default'            => 'asc',
1312                         'description'        => __( 'Order sort attribute ascending or descending.' ),
1313                         'enum'               => array( 'asc', 'desc' ),
1314                         'type'               => 'string',
1315                 );
1316
1317                 $query_params['orderby'] = array(
1318                         'default'            => 'name',
1319                         'description'        => __( 'Sort collection by object attribute.' ),
1320                         'enum'               => array(
1321                                 'id',
1322                                 'include',
1323                                 'name',
1324                                 'registered_date',
1325                                 'slug',
1326                                 'email',
1327                                 'url',
1328                         ),
1329                         'type'               => 'string',
1330                 );
1331
1332                 $query_params['slug']    = array(
1333                         'description'        => __( 'Limit result set to users with a specific slug.' ),
1334                         'type'               => 'string',
1335                 );
1336
1337                 $query_params['roles']   = array(
1338                         'description'        => __( 'Limit result set to users matching at least one specific role provided. Accepts csv list or single role.' ),
1339                         'type'               => 'array',
1340                         'items'              => array(
1341                                 'type'           => 'string',
1342                         ),
1343                 );
1344
1345                 /**
1346                  * Filter collection parameters for the users controller.
1347                  *
1348                  * This filter registers the collection parameter, but does not map the
1349                  * collection parameter to an internal WP_User_Query parameter.  Use the
1350                  * `rest_user_query` filter to set WP_User_Query arguments.
1351                  *
1352                  * @since 4.7.0
1353                  *
1354                  * @param $params JSON Schema-formatted collection parameters.
1355                  */
1356                 return apply_filters( 'rest_user_collection_params', $query_params );
1357         }
1358 }