[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/rest-api/endpoints/ -> class-wp-rest-users-controller.php (source)

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


Generated : Thu Nov 21 08:20:01 2024 Cross-referenced by PHPXref