wp/wp-includes/class-wp-user-query.php
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
child 22 8c2e4d02f4ef
equal deleted inserted replaced
20:7b1b88e27a20 21:48c4eec2b7e6
    12  *
    12  *
    13  * @since 3.1.0
    13  * @since 3.1.0
    14  *
    14  *
    15  * @see WP_User_Query::prepare_query() for information on accepted arguments.
    15  * @see WP_User_Query::prepare_query() for information on accepted arguments.
    16  */
    16  */
       
    17 #[AllowDynamicProperties]
    17 class WP_User_Query {
    18 class WP_User_Query {
    18 
    19 
    19 	/**
    20 	/**
    20 	 * Query vars, after parsing
    21 	 * Query vars, after parsing
    21 	 *
    22 	 *
    64 	public $query_where;
    65 	public $query_where;
    65 	public $query_orderby;
    66 	public $query_orderby;
    66 	public $query_limit;
    67 	public $query_limit;
    67 
    68 
    68 	/**
    69 	/**
    69 	 * PHP5 constructor.
    70 	 * Constructor.
    70 	 *
    71 	 *
    71 	 * @since 3.1.0
    72 	 * @since 3.1.0
    72 	 *
    73 	 *
    73 	 * @param null|string|array $query Optional. The query variables.
    74 	 * @param null|string|array $query Optional. The query variables.
       
    75 	 *                                 See WP_User_Query::prepare_query() for information on accepted arguments.
    74 	 */
    76 	 */
    75 	public function __construct( $query = null ) {
    77 	public function __construct( $query = null ) {
    76 		if ( ! empty( $query ) ) {
    78 		if ( ! empty( $query ) ) {
    77 			$this->prepare_query( $query );
    79 			$this->prepare_query( $query );
    78 			$this->query();
    80 			$this->query();
    82 	/**
    84 	/**
    83 	 * Fills in missing query variables with default values.
    85 	 * Fills in missing query variables with default values.
    84 	 *
    86 	 *
    85 	 * @since 4.4.0
    87 	 * @since 4.4.0
    86 	 *
    88 	 *
    87 	 * @param array $args Query vars, as passed to `WP_User_Query`.
    89 	 * @param string|array $args Query vars, as passed to `WP_User_Query`.
    88 	 * @return array Complete query variables with undefined ones filled in with defaults.
    90 	 * @return array Complete query variables with undefined ones filled in with defaults.
    89 	 */
    91 	 */
    90 	public static function fill_query_vars( $args ) {
    92 	public static function fill_query_vars( $args ) {
    91 		$defaults = array(
    93 		$defaults = array(
    92 			'blog_id'             => get_current_blog_id(),
    94 			'blog_id'             => get_current_blog_id(),
   116 			'nicename__in'        => array(),
   118 			'nicename__in'        => array(),
   117 			'nicename__not_in'    => array(),
   119 			'nicename__not_in'    => array(),
   118 			'login'               => '',
   120 			'login'               => '',
   119 			'login__in'           => array(),
   121 			'login__in'           => array(),
   120 			'login__not_in'       => array(),
   122 			'login__not_in'       => array(),
       
   123 			'cache_results'       => true,
   121 		);
   124 		);
   122 
   125 
   123 		return wp_parse_args( $args, $defaults );
   126 		return wp_parse_args( $args, $defaults );
   124 	}
   127 	}
   125 
   128 
   137 	 * @since 4.7.0 Added 'nicename', 'nicename__in', 'nicename__not_in', 'login', 'login__in',
   140 	 * @since 4.7.0 Added 'nicename', 'nicename__in', 'nicename__not_in', 'login', 'login__in',
   138 	 *              and 'login__not_in' parameters.
   141 	 *              and 'login__not_in' parameters.
   139 	 * @since 5.1.0 Introduced the 'meta_compare_key' parameter.
   142 	 * @since 5.1.0 Introduced the 'meta_compare_key' parameter.
   140 	 * @since 5.3.0 Introduced the 'meta_type_key' parameter.
   143 	 * @since 5.3.0 Introduced the 'meta_type_key' parameter.
   141 	 * @since 5.9.0 Added 'capability', 'capability__in', and 'capability__not_in' parameters.
   144 	 * @since 5.9.0 Added 'capability', 'capability__in', and 'capability__not_in' parameters.
   142 	 *
   145 	 *              Deprecated the 'who' parameter.
   143 	 * @global wpdb $wpdb WordPress database abstraction object.
   146 	 * @since 6.3.0 Added 'cache_results' parameter.
   144 	 * @global int  $blog_id
   147 	 *
       
   148 	 * @global wpdb     $wpdb     WordPress database abstraction object.
       
   149 	 * @global WP_Roles $wp_roles WordPress role management object.
   145 	 *
   150 	 *
   146 	 * @param string|array $query {
   151 	 * @param string|array $query {
   147 	 *     Optional. Array or string of Query parameters.
   152 	 *     Optional. Array or string of query parameters.
   148 	 *
   153 	 *
   149 	 *     @type int             $blog_id             The site ID. Default is the current site.
   154 	 *     @type int             $blog_id             The site ID. Default is the current site.
   150 	 *     @type string|string[] $role                An array or a comma-separated list of role names that users must match
   155 	 *     @type string|string[] $role                An array or a comma-separated list of role names that users
   151 	 *                                                to be included in results. Note that this is an inclusive list: users
   156 	 *                                                must match to be included in results. Note that this is
   152 	 *                                                must match *each* role. Default empty.
   157 	 *                                                an inclusive list: users must match *each* role. Default empty.
   153 	 *     @type string[]        $role__in            An array of role names. Matched users must have at least one of these
   158 	 *     @type string[]        $role__in            An array of role names. Matched users must have at least one
   154 	 *                                                roles. Default empty array.
   159 	 *                                                of these roles. Default empty array.
   155 	 *     @type string[]        $role__not_in        An array of role names to exclude. Users matching one or more of these
   160 	 *     @type string[]        $role__not_in        An array of role names to exclude. Users matching one or more
   156 	 *                                                roles will not be included in results. Default empty array.
   161 	 *                                                of these roles will not be included in results. Default empty array.
   157 	 *     @type string|string[] $meta_key            Meta key or keys to filter by.
   162 	 *     @type string|string[] $meta_key            Meta key or keys to filter by.
   158 	 *     @type string|string[] $meta_value          Meta value or values to filter by.
   163 	 *     @type string|string[] $meta_value          Meta value or values to filter by.
   159 	 *     @type string          $meta_compare        MySQL operator used for comparing the meta value.
   164 	 *     @type string          $meta_compare        MySQL operator used for comparing the meta value.
   160 	 *                                                See WP_Meta_Query::__construct for accepted values and default value.
   165 	 *                                                See WP_Meta_Query::__construct() for accepted values and default value.
   161 	 *     @type string          $meta_compare_key    MySQL operator used for comparing the meta key.
   166 	 *     @type string          $meta_compare_key    MySQL operator used for comparing the meta key.
   162 	 *                                                See WP_Meta_Query::__construct for accepted values and default value.
   167 	 *                                                See WP_Meta_Query::__construct() for accepted values and default value.
   163 	 *     @type string          $meta_type           MySQL data type that the meta_value column will be CAST to for comparisons.
   168 	 *     @type string          $meta_type           MySQL data type that the meta_value column will be CAST to for comparisons.
   164 	 *                                                See WP_Meta_Query::__construct for accepted values and default value.
   169 	 *                                                See WP_Meta_Query::__construct() for accepted values and default value.
   165 	 *     @type string          $meta_type_key       MySQL data type that the meta_key column will be CAST to for comparisons.
   170 	 *     @type string          $meta_type_key       MySQL data type that the meta_key column will be CAST to for comparisons.
   166 	 *                                                See WP_Meta_Query::__construct for accepted values and default value.
   171 	 *                                                See WP_Meta_Query::__construct() for accepted values and default value.
   167 	 *     @type array           $meta_query          An associative array of WP_Meta_Query arguments.
   172 	 *     @type array           $meta_query          An associative array of WP_Meta_Query arguments.
   168 	 *                                                See WP_Meta_Query::__construct for accepted values.
   173 	 *                                                See WP_Meta_Query::__construct() for accepted values.
   169 	 *     @type string|string[] $capability          An array or a comma-separated list of capability names that users must match
   174 	 *     @type string|string[] $capability          An array or a comma-separated list of capability names that users
   170 	 *                                                to be included in results. Note that this is an inclusive list: users
   175 	 *                                                must match to be included in results. Note that this is
   171 	 *                                                must match *each* capability.
   176 	 *                                                an inclusive list: users must match *each* capability.
   172 	 *                                                Does NOT work for capabilities not in the database or filtered via {@see 'map_meta_cap'}.
   177 	 *                                                Does NOT work for capabilities not in the database or filtered
   173 	 *                                                Default empty.
   178 	 *                                                via {@see 'map_meta_cap'}. Default empty.
   174 	 *     @type string[]        $capability__in      An array of capability names. Matched users must have at least one of these
   179 	 *     @type string[]        $capability__in      An array of capability names. Matched users must have at least one
   175 	 *                                                capabilities.
   180 	 *                                                of these capabilities.
   176 	 *                                                Does NOT work for capabilities not in the database or filtered via {@see 'map_meta_cap'}.
   181 	 *                                                Does NOT work for capabilities not in the database or filtered
   177 	 *                                                Default empty array.
   182 	 *                                                via {@see 'map_meta_cap'}. Default empty array.
   178 	 *     @type string[]        $capability__not_in  An array of capability names to exclude. Users matching one or more of these
   183 	 *     @type string[]        $capability__not_in  An array of capability names to exclude. Users matching one or more
   179 	 *                                                capabilities will not be included in results.
   184 	 *                                                of these capabilities will not be included in results.
   180 	 *                                                Does NOT work for capabilities not in the database or filtered via {@see 'map_meta_cap'}.
   185 	 *                                                Does NOT work for capabilities not in the database or filtered
   181 	 *                                                Default empty array.
   186 	 *                                                via {@see 'map_meta_cap'}. Default empty array.
   182 	 *     @type int[]           $include             An array of user IDs to include. Default empty array.
   187 	 *     @type int[]           $include             An array of user IDs to include. Default empty array.
   183 	 *     @type int[]           $exclude             An array of user IDs to exclude. Default empty array.
   188 	 *     @type int[]           $exclude             An array of user IDs to exclude. Default empty array.
   184 	 *     @type string          $search              Search keyword. Searches for possible string matches on columns.
   189 	 *     @type string          $search              Search keyword. Searches for possible string matches on columns.
   185 	 *                                                When `$search_columns` is left empty, it tries to determine which
   190 	 *                                                When `$search_columns` is left empty, it tries to determine which
   186 	 *                                                column to search in based on search string. Default empty.
   191 	 *                                                column to search in based on search string. Default empty.
   193 	 *                                                - 'ID'
   198 	 *                                                - 'ID'
   194 	 *                                                - 'display_name' (or 'name')
   199 	 *                                                - 'display_name' (or 'name')
   195 	 *                                                - 'include'
   200 	 *                                                - 'include'
   196 	 *                                                - 'user_login' (or 'login')
   201 	 *                                                - 'user_login' (or 'login')
   197 	 *                                                - 'login__in'
   202 	 *                                                - 'login__in'
   198 	 *                                                - 'user_nicename' (or 'nicename'),
   203 	 *                                                - 'user_nicename' (or 'nicename')
   199 	 *                                                - 'nicename__in'
   204 	 *                                                - 'nicename__in'
   200 	 *                                                - 'user_email (or 'email')
   205 	 *                                                - 'user_email (or 'email')
   201 	 *                                                - 'user_url' (or 'url'),
   206 	 *                                                - 'user_url' (or 'url')
   202 	 *                                                - 'user_registered' (or 'registered')
   207 	 *                                                - 'user_registered' (or 'registered')
   203 	 *                                                - 'post_count'
   208 	 *                                                - 'post_count'
   204 	 *                                                - 'meta_value',
   209 	 *                                                - 'meta_value'
   205 	 *                                                - 'meta_value_num'
   210 	 *                                                - 'meta_value_num'
   206 	 *                                                - The value of `$meta_key`
   211 	 *                                                - The value of `$meta_key`
   207 	 *                                                - An array key of `$meta_query`
   212 	 *                                                - An array key of `$meta_query`
   208 	 *                                                To use 'meta_value' or 'meta_value_num', `$meta_key`
   213 	 *                                                To use 'meta_value' or 'meta_value_num', `$meta_key`
   209 	 *                                                must be also be defined. Default 'user_login'.
   214 	 *                                                must be also be defined. Default 'user_login'.
   233 	 *                                                - 'user_pass'
   238 	 *                                                - 'user_pass'
   234 	 *                                                - 'user_activation_key'
   239 	 *                                                - 'user_activation_key'
   235 	 *                                                - 'user_status'
   240 	 *                                                - 'user_status'
   236 	 *                                                - 'spam' (only available on multisite installs)
   241 	 *                                                - 'spam' (only available on multisite installs)
   237 	 *                                                - 'deleted' (only available on multisite installs)
   242 	 *                                                - 'deleted' (only available on multisite installs)
   238 	 *                                                - 'all' for all fields
   243 	 *                                                - 'all' for all fields and loads user meta.
   239 	 *                                                - 'all_with_meta' to include meta fields.
   244 	 *                                                - 'all_with_meta' Deprecated. Use 'all'.
   240 	 *                                                Default 'all'.
   245 	 *                                                Default 'all'.
   241 	 *     @type string          $who                 Type of users to query. Accepts 'authors'.
   246 	 *     @type string          $who                 Deprecated, use `$capability` instead.
       
   247 	 *                                                Type of users to query. Accepts 'authors'.
   242 	 *                                                Default empty (all users).
   248 	 *                                                Default empty (all users).
   243 	 *     @type bool|string[]   $has_published_posts Pass an array of post types to filter results to users who have
   249 	 *     @type bool|string[]   $has_published_posts Pass an array of post types to filter results to users who have
   244 	 *                                                published posts in those post types. `true` is an alias for all
   250 	 *                                                published posts in those post types. `true` is an alias for all
   245 	 *                                                public post types.
   251 	 *                                                public post types.
   246 	 *     @type string          $nicename            The user nicename. Default empty.
   252 	 *     @type string          $nicename            The user nicename. Default empty.
   251 	 *     @type string          $login               The user login. Default empty.
   257 	 *     @type string          $login               The user login. Default empty.
   252 	 *     @type string[]        $login__in           An array of logins to include. Users matching one of these
   258 	 *     @type string[]        $login__in           An array of logins to include. Users matching one of these
   253 	 *                                                logins will be included in results. Default empty array.
   259 	 *                                                logins will be included in results. Default empty array.
   254 	 *     @type string[]        $login__not_in       An array of logins to exclude. Users matching one of these
   260 	 *     @type string[]        $login__not_in       An array of logins to exclude. Users matching one of these
   255 	 *                                                logins will not be included in results. Default empty array.
   261 	 *                                                logins will not be included in results. Default empty array.
       
   262 	 *     @type bool            $cache_results       Whether to cache user information. Default true.
   256 	 * }
   263 	 * }
   257 	 */
   264 	 */
   258 	public function prepare_query( $query = array() ) {
   265 	public function prepare_query( $query = array() ) {
   259 		global $wpdb;
   266 		global $wpdb, $wp_roles;
   260 
   267 
   261 		if ( empty( $this->query_vars ) || ! empty( $query ) ) {
   268 		if ( empty( $this->query_vars ) || ! empty( $query ) ) {
   262 			$this->query_limit = null;
   269 			$this->query_limit = null;
   263 			$this->query_vars  = $this->fill_query_vars( $query );
   270 			$this->query_vars  = $this->fill_query_vars( $query );
   264 		}
   271 		}
   308 			foreach ( $qv['fields'] as $field ) {
   315 			foreach ( $qv['fields'] as $field ) {
   309 				$field                = 'id' === $field ? 'ID' : sanitize_key( $field );
   316 				$field                = 'id' === $field ? 'ID' : sanitize_key( $field );
   310 				$this->query_fields[] = "$wpdb->users.$field";
   317 				$this->query_fields[] = "$wpdb->users.$field";
   311 			}
   318 			}
   312 			$this->query_fields = implode( ',', $this->query_fields );
   319 			$this->query_fields = implode( ',', $this->query_fields );
   313 		} elseif ( 'all' === $qv['fields'] ) {
   320 		} elseif ( 'all_with_meta' === $qv['fields'] || 'all' === $qv['fields'] || ! in_array( $qv['fields'], $allowed_fields, true ) ) {
   314 			$this->query_fields = "$wpdb->users.*";
       
   315 		} elseif ( ! in_array( $qv['fields'], $allowed_fields, true ) ) {
       
   316 			$this->query_fields = "$wpdb->users.ID";
   321 			$this->query_fields = "$wpdb->users.ID";
   317 		} else {
   322 		} else {
   318 			$field              = 'id' === strtolower( $qv['fields'] ) ? 'ID' : sanitize_key( $qv['fields'] );
   323 			$field              = 'id' === strtolower( $qv['fields'] ) ? 'ID' : sanitize_key( $qv['fields'] );
   319 			$this->query_fields = "$wpdb->users.$field";
   324 			$this->query_fields = "$wpdb->users.$field";
   320 		}
   325 		}
   448 
   453 
   449 		// Capabilities.
   454 		// Capabilities.
   450 		$available_roles = array();
   455 		$available_roles = array();
   451 
   456 
   452 		if ( ! empty( $qv['capability'] ) || ! empty( $qv['capability__in'] ) || ! empty( $qv['capability__not_in'] ) ) {
   457 		if ( ! empty( $qv['capability'] ) || ! empty( $qv['capability__in'] ) || ! empty( $qv['capability__not_in'] ) ) {
   453 			global $wp_roles;
       
   454 
       
   455 			$wp_roles->for_site( $blog_id );
   458 			$wp_roles->for_site( $blog_id );
   456 			$available_roles = $wp_roles->roles;
   459 			$available_roles = $wp_roles->roles;
   457 		}
   460 		}
   458 
   461 
   459 		$capabilities = array();
   462 		$capabilities = array();
   690 		if ( isset( $qv['search'] ) ) {
   693 		if ( isset( $qv['search'] ) ) {
   691 			$search = trim( $qv['search'] );
   694 			$search = trim( $qv['search'] );
   692 		}
   695 		}
   693 
   696 
   694 		if ( $search ) {
   697 		if ( $search ) {
   695 			$leading_wild  = ( ltrim( $search, '*' ) != $search );
   698 			$leading_wild  = ( ltrim( $search, '*' ) !== $search );
   696 			$trailing_wild = ( rtrim( $search, '*' ) != $search );
   699 			$trailing_wild = ( rtrim( $search, '*' ) !== $search );
   697 			if ( $leading_wild && $trailing_wild ) {
   700 			if ( $leading_wild && $trailing_wild ) {
   698 				$wild = 'both';
   701 				$wild = 'both';
   699 			} elseif ( $leading_wild ) {
   702 			} elseif ( $leading_wild ) {
   700 				$wild = 'leading';
   703 				$wild = 'leading';
   701 			} elseif ( $trailing_wild ) {
   704 			} elseif ( $trailing_wild ) {
   710 			$search_columns = array();
   713 			$search_columns = array();
   711 			if ( $qv['search_columns'] ) {
   714 			if ( $qv['search_columns'] ) {
   712 				$search_columns = array_intersect( $qv['search_columns'], array( 'ID', 'user_login', 'user_email', 'user_url', 'user_nicename', 'display_name' ) );
   715 				$search_columns = array_intersect( $qv['search_columns'], array( 'ID', 'user_login', 'user_email', 'user_url', 'user_nicename', 'display_name' ) );
   713 			}
   716 			}
   714 			if ( ! $search_columns ) {
   717 			if ( ! $search_columns ) {
   715 				if ( false !== strpos( $search, '@' ) ) {
   718 				if ( str_contains( $search, '@' ) ) {
   716 					$search_columns = array( 'user_email' );
   719 					$search_columns = array( 'user_email' );
   717 				} elseif ( is_numeric( $search ) ) {
   720 				} elseif ( is_numeric( $search ) ) {
   718 					$search_columns = array( 'user_login', 'ID' );
   721 					$search_columns = array( 'user_login', 'ID' );
   719 				} elseif ( preg_match( '|^https?://|', $search ) && ! ( is_multisite() && wp_is_large_network( 'users' ) ) ) {
   722 				} elseif ( preg_match( '|^https?://|', $search ) && ! ( is_multisite() && wp_is_large_network( 'users' ) ) ) {
   720 					$search_columns = array( 'user_url' );
   723 					$search_columns = array( 'user_url' );
   777 	 * @global wpdb $wpdb WordPress database abstraction object.
   780 	 * @global wpdb $wpdb WordPress database abstraction object.
   778 	 */
   781 	 */
   779 	public function query() {
   782 	public function query() {
   780 		global $wpdb;
   783 		global $wpdb;
   781 
   784 
       
   785 		if ( ! did_action( 'plugins_loaded' ) ) {
       
   786 			_doing_it_wrong(
       
   787 				'WP_User_Query::query',
       
   788 				sprintf(
       
   789 				/* translators: %s: plugins_loaded */
       
   790 					__( 'User queries should not be run before the %s hook.' ),
       
   791 					'<code>plugins_loaded</code>'
       
   792 				),
       
   793 				'6.1.1'
       
   794 			);
       
   795 		}
       
   796 
   782 		$qv =& $this->query_vars;
   797 		$qv =& $this->query_vars;
       
   798 
       
   799 		// Do not cache results if more than 3 fields are requested.
       
   800 		if ( is_array( $qv['fields'] ) && count( $qv['fields'] ) > 3 ) {
       
   801 			$qv['cache_results'] = false;
       
   802 		}
   783 
   803 
   784 		/**
   804 		/**
   785 		 * Filters the users array before the query takes place.
   805 		 * Filters the users array before the query takes place.
   786 		 *
   806 		 *
   787 		 * Return a non-null value to bypass WordPress' default user queries.
   807 		 * Return a non-null value to bypass WordPress' default user queries.
   798 		 * @param WP_User_Query $query   The WP_User_Query instance (passed by reference).
   818 		 * @param WP_User_Query $query   The WP_User_Query instance (passed by reference).
   799 		 */
   819 		 */
   800 		$this->results = apply_filters_ref_array( 'users_pre_query', array( null, &$this ) );
   820 		$this->results = apply_filters_ref_array( 'users_pre_query', array( null, &$this ) );
   801 
   821 
   802 		if ( null === $this->results ) {
   822 		if ( null === $this->results ) {
   803 			$this->request = "
   823 			// Beginning of the string is on a new line to prevent leading whitespace. See https://core.trac.wordpress.org/ticket/56841.
   804 				SELECT {$this->query_fields}
   824 			$this->request =
   805 				{$this->query_from}
   825 				"SELECT {$this->query_fields}
   806 				{$this->query_where}
   826 				 {$this->query_from}
   807 				{$this->query_orderby}
   827 				 {$this->query_where}
   808 				{$this->query_limit}
   828 				 {$this->query_orderby}
   809 			";
   829 				 {$this->query_limit}";
   810 
   830 			$cache_value   = false;
   811 			if ( is_array( $qv['fields'] ) || 'all' === $qv['fields'] ) {
   831 			$cache_key     = $this->generate_cache_key( $qv, $this->request );
   812 				$this->results = $wpdb->get_results( $this->request );
   832 			$cache_group   = 'user-queries';
       
   833 			if ( $qv['cache_results'] ) {
       
   834 				$cache_value = wp_cache_get( $cache_key, $cache_group );
       
   835 			}
       
   836 			if ( false !== $cache_value ) {
       
   837 				$this->results     = $cache_value['user_data'];
       
   838 				$this->total_users = $cache_value['total_users'];
   813 			} else {
   839 			} else {
   814 				$this->results = $wpdb->get_col( $this->request );
   840 
   815 			}
   841 				if ( is_array( $qv['fields'] ) ) {
   816 
   842 					$this->results = $wpdb->get_results( $this->request );
   817 			if ( isset( $qv['count_total'] ) && $qv['count_total'] ) {
   843 				} else {
   818 				/**
   844 					$this->results = $wpdb->get_col( $this->request );
   819 				 * Filters SELECT FOUND_ROWS() query for the current WP_User_Query instance.
   845 				}
   820 				 *
   846 
   821 				 * @since 3.2.0
   847 				if ( isset( $qv['count_total'] ) && $qv['count_total'] ) {
   822 				 * @since 5.1.0 Added the `$this` parameter.
   848 					/**
   823 				 *
   849 					 * Filters SELECT FOUND_ROWS() query for the current WP_User_Query instance.
   824 				 * @global wpdb $wpdb WordPress database abstraction object.
   850 					 *
   825 				 *
   851 					 * @since 3.2.0
   826 				 * @param string        $sql   The SELECT FOUND_ROWS() query for the current WP_User_Query.
   852 					 * @since 5.1.0 Added the `$this` parameter.
   827 				 * @param WP_User_Query $query The current WP_User_Query instance.
   853 					 *
   828 				 */
   854 					 * @global wpdb $wpdb WordPress database abstraction object.
   829 				$found_users_query = apply_filters( 'found_users_query', 'SELECT FOUND_ROWS()', $this );
   855 					 *
   830 
   856 					 * @param string        $sql   The SELECT FOUND_ROWS() query for the current WP_User_Query.
   831 				$this->total_users = (int) $wpdb->get_var( $found_users_query );
   857 					 * @param WP_User_Query $query The current WP_User_Query instance.
       
   858 					 */
       
   859 					$found_users_query = apply_filters( 'found_users_query', 'SELECT FOUND_ROWS()', $this );
       
   860 
       
   861 					$this->total_users = (int) $wpdb->get_var( $found_users_query );
       
   862 				}
       
   863 
       
   864 				if ( $qv['cache_results'] ) {
       
   865 					$cache_value = array(
       
   866 						'user_data'   => $this->results,
       
   867 						'total_users' => $this->total_users,
       
   868 					);
       
   869 					wp_cache_add( $cache_key, $cache_value, $cache_group );
       
   870 				}
   832 			}
   871 			}
   833 		}
   872 		}
   834 
   873 
   835 		if ( ! $this->results ) {
   874 		if ( ! $this->results ) {
   836 			return;
   875 			return;
   840 			isset( $this->results[0]->ID )
   879 			isset( $this->results[0]->ID )
   841 		) {
   880 		) {
   842 			foreach ( $this->results as $result ) {
   881 			foreach ( $this->results as $result ) {
   843 				$result->id = $result->ID;
   882 				$result->id = $result->ID;
   844 			}
   883 			}
   845 		} elseif ( 'all_with_meta' === $qv['fields'] ) {
   884 		} elseif ( 'all_with_meta' === $qv['fields'] || 'all' === $qv['fields'] ) {
   846 			cache_users( $this->results );
   885 			if ( function_exists( 'cache_users' ) ) {
       
   886 				cache_users( $this->results );
       
   887 			}
   847 
   888 
   848 			$r = array();
   889 			$r = array();
   849 			foreach ( $this->results as $userid ) {
   890 			foreach ( $this->results as $userid ) {
   850 				$r[ $userid ] = new WP_User( $userid, '', $qv['blog_id'] );
   891 				if ( 'all_with_meta' === $qv['fields'] ) {
       
   892 					$r[ $userid ] = new WP_User( $userid, '', $qv['blog_id'] );
       
   893 				} else {
       
   894 					$r[] = new WP_User( $userid, '', $qv['blog_id'] );
       
   895 				}
   851 			}
   896 			}
   852 
   897 
   853 			$this->results = $r;
   898 			$this->results = $r;
   854 		} elseif ( 'all' === $qv['fields'] ) {
       
   855 			foreach ( $this->results as $key => $user ) {
       
   856 				$this->results[ $key ] = new WP_User( $user, '', $qv['blog_id'] );
       
   857 			}
       
   858 		}
   899 		}
   859 	}
   900 	}
   860 
   901 
   861 	/**
   902 	/**
   862 	 * Retrieves query variable.
   903 	 * Retrieves query variable.
   968 			$this->query_from .= " LEFT OUTER JOIN (
  1009 			$this->query_from .= " LEFT OUTER JOIN (
   969 				SELECT post_author, COUNT(*) as post_count
  1010 				SELECT post_author, COUNT(*) as post_count
   970 				FROM $wpdb->posts
  1011 				FROM $wpdb->posts
   971 				$where
  1012 				$where
   972 				GROUP BY post_author
  1013 				GROUP BY post_author
   973 			) p ON ({$wpdb->users}.ID = p.post_author)
  1014 			) p ON ({$wpdb->users}.ID = p.post_author)";
   974 			";
       
   975 			$_orderby          = 'post_count';
  1015 			$_orderby          = 'post_count';
   976 		} elseif ( 'ID' === $orderby || 'id' === $orderby ) {
  1016 		} elseif ( 'ID' === $orderby || 'id' === $orderby ) {
   977 			$_orderby = 'ID';
  1017 			$_orderby = 'ID';
   978 		} elseif ( 'meta_value' === $orderby || $this->get( 'meta_key' ) == $orderby ) {
  1018 		} elseif ( 'meta_value' === $orderby || $this->get( 'meta_key' ) === $orderby ) {
   979 			$_orderby = "$wpdb->usermeta.meta_value";
  1019 			$_orderby = "$wpdb->usermeta.meta_value";
   980 		} elseif ( 'meta_value_num' === $orderby ) {
  1020 		} elseif ( 'meta_value_num' === $orderby ) {
   981 			$_orderby = "$wpdb->usermeta.meta_value+0";
  1021 			$_orderby = "$wpdb->usermeta.meta_value+0";
   982 		} elseif ( 'include' === $orderby && ! empty( $this->query_vars['include'] ) ) {
  1022 		} elseif ( 'include' === $orderby && ! empty( $this->query_vars['include'] ) ) {
   983 			$include     = wp_parse_id_list( $this->query_vars['include'] );
  1023 			$include     = wp_parse_id_list( $this->query_vars['include'] );
   998 
  1038 
   999 		return $_orderby;
  1039 		return $_orderby;
  1000 	}
  1040 	}
  1001 
  1041 
  1002 	/**
  1042 	/**
       
  1043 	 * Generate cache key.
       
  1044 	 *
       
  1045 	 * @since 6.3.0
       
  1046 	 *
       
  1047 	 * @global wpdb $wpdb WordPress database abstraction object.
       
  1048 	 *
       
  1049 	 * @param array  $args Query arguments.
       
  1050 	 * @param string $sql  SQL statement.
       
  1051 	 * @return string Cache key.
       
  1052 	 */
       
  1053 	protected function generate_cache_key( array $args, $sql ) {
       
  1054 		global $wpdb;
       
  1055 
       
  1056 		// Replace wpdb placeholder in the SQL statement used by the cache key.
       
  1057 		$sql = $wpdb->remove_placeholder_escape( $sql );
       
  1058 
       
  1059 		$key          = md5( $sql );
       
  1060 		$last_changed = wp_cache_get_last_changed( 'users' );
       
  1061 
       
  1062 		if ( empty( $args['orderby'] ) ) {
       
  1063 			// Default order is by 'user_login'.
       
  1064 			$ordersby = array( 'user_login' => '' );
       
  1065 		} elseif ( is_array( $args['orderby'] ) ) {
       
  1066 			$ordersby = $args['orderby'];
       
  1067 		} else {
       
  1068 			// 'orderby' values may be a comma- or space-separated list.
       
  1069 			$ordersby = preg_split( '/[,\s]+/', $args['orderby'] );
       
  1070 		}
       
  1071 
       
  1072 		$blog_id = 0;
       
  1073 		if ( isset( $args['blog_id'] ) ) {
       
  1074 			$blog_id = absint( $args['blog_id'] );
       
  1075 		}
       
  1076 
       
  1077 		if ( $args['has_published_posts'] || in_array( 'post_count', $ordersby, true ) ) {
       
  1078 			$switch = $blog_id && get_current_blog_id() !== $blog_id;
       
  1079 			if ( $switch ) {
       
  1080 				switch_to_blog( $blog_id );
       
  1081 			}
       
  1082 
       
  1083 			$last_changed .= wp_cache_get_last_changed( 'posts' );
       
  1084 
       
  1085 			if ( $switch ) {
       
  1086 				restore_current_blog();
       
  1087 			}
       
  1088 		}
       
  1089 
       
  1090 		return "get_users:$key:$last_changed";
       
  1091 	}
       
  1092 
       
  1093 	/**
  1003 	 * Parses an 'order' query variable and casts it to ASC or DESC as necessary.
  1094 	 * Parses an 'order' query variable and casts it to ASC or DESC as necessary.
  1004 	 *
  1095 	 *
  1005 	 * @since 4.2.0
  1096 	 * @since 4.2.0
  1006 	 *
  1097 	 *
  1007 	 * @param string $order The 'order' query variable.
  1098 	 * @param string $order The 'order' query variable.
  1021 
  1112 
  1022 	/**
  1113 	/**
  1023 	 * Makes private properties readable for backward compatibility.
  1114 	 * Makes private properties readable for backward compatibility.
  1024 	 *
  1115 	 *
  1025 	 * @since 4.0.0
  1116 	 * @since 4.0.0
       
  1117 	 * @since 6.4.0 Getting a dynamic property is deprecated.
  1026 	 *
  1118 	 *
  1027 	 * @param string $name Property to get.
  1119 	 * @param string $name Property to get.
  1028 	 * @return mixed Property.
  1120 	 * @return mixed Property.
  1029 	 */
  1121 	 */
  1030 	public function __get( $name ) {
  1122 	public function __get( $name ) {
  1031 		if ( in_array( $name, $this->compat_fields, true ) ) {
  1123 		if ( in_array( $name, $this->compat_fields, true ) ) {
  1032 			return $this->$name;
  1124 			return $this->$name;
  1033 		}
  1125 		}
       
  1126 
       
  1127 		wp_trigger_error(
       
  1128 			__METHOD__,
       
  1129 			"The property `{$name}` is not declared. Getting a dynamic property is " .
       
  1130 			'deprecated since version 6.4.0! Instead, declare the property on the class.',
       
  1131 			E_USER_DEPRECATED
       
  1132 		);
       
  1133 		return null;
  1034 	}
  1134 	}
  1035 
  1135 
  1036 	/**
  1136 	/**
  1037 	 * Makes private properties settable for backward compatibility.
  1137 	 * Makes private properties settable for backward compatibility.
  1038 	 *
  1138 	 *
  1039 	 * @since 4.0.0
  1139 	 * @since 4.0.0
       
  1140 	 * @since 6.4.0 Setting a dynamic property is deprecated.
  1040 	 *
  1141 	 *
  1041 	 * @param string $name  Property to check if set.
  1142 	 * @param string $name  Property to check if set.
  1042 	 * @param mixed  $value Property value.
  1143 	 * @param mixed  $value Property value.
  1043 	 * @return mixed Newly-set property.
       
  1044 	 */
  1144 	 */
  1045 	public function __set( $name, $value ) {
  1145 	public function __set( $name, $value ) {
  1046 		if ( in_array( $name, $this->compat_fields, true ) ) {
  1146 		if ( in_array( $name, $this->compat_fields, true ) ) {
  1047 			return $this->$name = $value;
  1147 			$this->$name = $value;
  1048 		}
  1148 			return;
       
  1149 		}
       
  1150 
       
  1151 		wp_trigger_error(
       
  1152 			__METHOD__,
       
  1153 			"The property `{$name}` is not declared. Setting a dynamic property is " .
       
  1154 			'deprecated since version 6.4.0! Instead, declare the property on the class.',
       
  1155 			E_USER_DEPRECATED
       
  1156 		);
  1049 	}
  1157 	}
  1050 
  1158 
  1051 	/**
  1159 	/**
  1052 	 * Makes private properties checkable for backward compatibility.
  1160 	 * Makes private properties checkable for backward compatibility.
  1053 	 *
  1161 	 *
  1054 	 * @since 4.0.0
  1162 	 * @since 4.0.0
       
  1163 	 * @since 6.4.0 Checking a dynamic property is deprecated.
  1055 	 *
  1164 	 *
  1056 	 * @param string $name Property to check if set.
  1165 	 * @param string $name Property to check if set.
  1057 	 * @return bool Whether the property is set.
  1166 	 * @return bool Whether the property is set.
  1058 	 */
  1167 	 */
  1059 	public function __isset( $name ) {
  1168 	public function __isset( $name ) {
  1060 		if ( in_array( $name, $this->compat_fields, true ) ) {
  1169 		if ( in_array( $name, $this->compat_fields, true ) ) {
  1061 			return isset( $this->$name );
  1170 			return isset( $this->$name );
  1062 		}
  1171 		}
       
  1172 
       
  1173 		wp_trigger_error(
       
  1174 			__METHOD__,
       
  1175 			"The property `{$name}` is not declared. Checking `isset()` on a dynamic property " .
       
  1176 			'is deprecated since version 6.4.0! Instead, declare the property on the class.',
       
  1177 			E_USER_DEPRECATED
       
  1178 		);
       
  1179 		return false;
  1063 	}
  1180 	}
  1064 
  1181 
  1065 	/**
  1182 	/**
  1066 	 * Makes private properties un-settable for backward compatibility.
  1183 	 * Makes private properties un-settable for backward compatibility.
  1067 	 *
  1184 	 *
  1068 	 * @since 4.0.0
  1185 	 * @since 4.0.0
       
  1186 	 * @since 6.4.0 Unsetting a dynamic property is deprecated.
  1069 	 *
  1187 	 *
  1070 	 * @param string $name Property to unset.
  1188 	 * @param string $name Property to unset.
  1071 	 */
  1189 	 */
  1072 	public function __unset( $name ) {
  1190 	public function __unset( $name ) {
  1073 		if ( in_array( $name, $this->compat_fields, true ) ) {
  1191 		if ( in_array( $name, $this->compat_fields, true ) ) {
  1074 			unset( $this->$name );
  1192 			unset( $this->$name );
  1075 		}
  1193 			return;
       
  1194 		}
       
  1195 
       
  1196 		wp_trigger_error(
       
  1197 			__METHOD__,
       
  1198 			"A property `{$name}` is not declared. Unsetting a dynamic property is " .
       
  1199 			'deprecated since version 6.4.0! Instead, declare the property on the class.',
       
  1200 			E_USER_DEPRECATED
       
  1201 		);
  1076 	}
  1202 	}
  1077 
  1203 
  1078 	/**
  1204 	/**
  1079 	 * Makes private/protected methods readable for backward compatibility.
  1205 	 * Makes private/protected methods readable for backward compatibility.
  1080 	 *
  1206 	 *