131 * @since 4.4.0 Added 'paged', 'role__in', and 'role__not_in' parameters. The 'role' parameter was updated to |
134 * @since 4.4.0 Added 'paged', 'role__in', and 'role__not_in' parameters. The 'role' parameter was updated to |
132 * permit an array or comma-separated list of values. The 'number' parameter was updated to support |
135 * permit an array or comma-separated list of values. The 'number' parameter was updated to support |
133 * querying for all users with using -1. |
136 * querying for all users with using -1. |
134 * @since 4.7.0 Added 'nicename', 'nicename__in', 'nicename__not_in', 'login', 'login__in', |
137 * @since 4.7.0 Added 'nicename', 'nicename__in', 'nicename__not_in', 'login', 'login__in', |
135 * and 'login__not_in' parameters. |
138 * and 'login__not_in' parameters. |
|
139 * @since 5.1.0 Introduced the 'meta_compare_key' parameter. |
|
140 * @since 5.3.0 Introduced the 'meta_type_key' parameter. |
|
141 * @since 5.9.0 Added 'capability', 'capability__in', and 'capability__not_in' parameters. |
136 * |
142 * |
137 * @global wpdb $wpdb WordPress database abstraction object. |
143 * @global wpdb $wpdb WordPress database abstraction object. |
138 * @global int $blog_id |
144 * @global int $blog_id |
139 * |
145 * |
140 * @param string|array $query { |
146 * @param string|array $query { |
141 * Optional. Array or string of Query parameters. |
147 * Optional. Array or string of Query parameters. |
142 * |
148 * |
143 * @type int $blog_id The site ID. Default is the current site. |
149 * @type int $blog_id The site ID. Default is the current site. |
144 * @type string|array $role An array or a comma-separated list of role names that users must match |
150 * @type string|string[] $role An array or a comma-separated list of role names that users must match |
145 * to be included in results. Note that this is an inclusive list: users |
151 * to be included in results. Note that this is an inclusive list: users |
146 * must match *each* role. Default empty. |
152 * must match *each* role. Default empty. |
147 * @type string[] $role__in An array of role names. Matched users must have at least one of these |
153 * @type string[] $role__in An array of role names. Matched users must have at least one of these |
148 * roles. Default empty array. |
154 * roles. Default empty array. |
149 * @type string[] $role__not_in An array of role names to exclude. Users matching one or more of these |
155 * @type string[] $role__not_in An array of role names to exclude. Users matching one or more of these |
150 * roles will not be included in results. Default empty array. |
156 * roles will not be included in results. Default empty array. |
151 * @type string $meta_key User meta key. Default empty. |
157 * @type string|string[] $meta_key Meta key or keys to filter by. |
152 * @type string $meta_value User meta value. Default empty. |
158 * @type string|string[] $meta_value Meta value or values to filter by. |
153 * @type string $meta_compare Comparison operator to test the `$meta_value`. Accepts '=', '!=', |
159 * @type string $meta_compare MySQL operator used for comparing the meta value. |
154 * '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', |
160 * See WP_Meta_Query::__construct for accepted values and default value. |
155 * 'BETWEEN', 'NOT BETWEEN', 'EXISTS', 'NOT EXISTS', 'REGEXP', |
161 * @type string $meta_compare_key MySQL operator used for comparing the meta key. |
156 * 'NOT REGEXP', or 'RLIKE'. Default '='. |
162 * See WP_Meta_Query::__construct for accepted values and default value. |
157 * @type int[] $include An array of user IDs to include. Default empty array. |
163 * @type string $meta_type MySQL data type that the meta_value column will be CAST to for comparisons. |
158 * @type int[] $exclude An array of user IDs to exclude. Default empty array. |
164 * See WP_Meta_Query::__construct for accepted values and default value. |
159 * @type string $search Search keyword. Searches for possible string matches on columns. |
165 * @type string $meta_type_key MySQL data type that the meta_key column will be CAST to for comparisons. |
160 * When `$search_columns` is left empty, it tries to determine which |
166 * See WP_Meta_Query::__construct for accepted values and default value. |
161 * column to search in based on search string. Default empty. |
167 * @type array $meta_query An associative array of WP_Meta_Query arguments. |
162 * @type string[] $search_columns Array of column names to be searched. Accepts 'ID', 'user_login', |
168 * See WP_Meta_Query::__construct for accepted values. |
163 * 'user_email', 'user_url', 'user_nicename', 'display_name'. |
169 * @type string|string[] $capability An array or a comma-separated list of capability names that users must match |
164 * Default empty array. |
170 * to be included in results. Note that this is an inclusive list: users |
165 * @type string|array $orderby Field(s) to sort the retrieved users by. May be a single value, |
171 * must match *each* capability. |
166 * an array of values, or a multi-dimensional array with fields as |
172 * Does NOT work for capabilities not in the database or filtered via {@see 'map_meta_cap'}. |
167 * keys and orders ('ASC' or 'DESC') as values. Accepted values are |
173 * Default empty. |
168 * 'ID', 'display_name' (or 'name'), 'include', 'user_login' |
174 * @type string[] $capability__in An array of capability names. Matched users must have at least one of these |
169 * (or 'login'), 'login__in', 'user_nicename' (or 'nicename'), |
175 * capabilities. |
170 * 'nicename__in', 'user_email (or 'email'), 'user_url' (or 'url'), |
176 * Does NOT work for capabilities not in the database or filtered via {@see 'map_meta_cap'}. |
171 * 'user_registered' (or 'registered'), 'post_count', 'meta_value', |
177 * Default empty array. |
172 * 'meta_value_num', the value of `$meta_key`, or an array key of |
178 * @type string[] $capability__not_in An array of capability names to exclude. Users matching one or more of these |
173 * `$meta_query`. To use 'meta_value' or 'meta_value_num', `$meta_key` |
179 * capabilities will not be included in results. |
174 * must be also be defined. Default 'user_login'. |
180 * Does NOT work for capabilities not in the database or filtered via {@see 'map_meta_cap'}. |
175 * @type string $order Designates ascending or descending order of users. Order values |
181 * Default empty array. |
176 * passed as part of an `$orderby` array take precedence over this |
182 * @type int[] $include An array of user IDs to include. Default empty array. |
177 * parameter. Accepts 'ASC', 'DESC'. Default 'ASC'. |
183 * @type int[] $exclude An array of user IDs to exclude. Default empty array. |
178 * @type int $offset Number of users to offset in retrieved results. Can be used in |
184 * @type string $search Search keyword. Searches for possible string matches on columns. |
179 * conjunction with pagination. Default 0. |
185 * When `$search_columns` is left empty, it tries to determine which |
180 * @type int $number Number of users to limit the query for. Can be used in |
186 * column to search in based on search string. Default empty. |
181 * conjunction with pagination. Value -1 (all) is supported, but |
187 * @type string[] $search_columns Array of column names to be searched. Accepts 'ID', 'user_login', |
182 * should be used with caution on larger sites. |
188 * 'user_email', 'user_url', 'user_nicename', 'display_name'. |
183 * Default -1 (all users). |
189 * Default empty array. |
184 * @type int $paged When used with number, defines the page of results to return. |
190 * @type string|array $orderby Field(s) to sort the retrieved users by. May be a single value, |
185 * Default 1. |
191 * an array of values, or a multi-dimensional array with fields as |
186 * @type bool $count_total Whether to count the total number of users found. If pagination |
192 * keys and orders ('ASC' or 'DESC') as values. Accepted values are: |
187 * is not needed, setting this to false can improve performance. |
193 * - 'ID' |
188 * Default true. |
194 * - 'display_name' (or 'name') |
189 * @type string|array $fields Which fields to return. Single or all fields (string), or array |
195 * - 'include' |
190 * of fields. Accepts 'ID', 'display_name', 'user_login', |
196 * - 'user_login' (or 'login') |
191 * 'user_nicename', 'user_email', 'user_url', 'user_registered'. |
197 * - 'login__in' |
192 * Use 'all' for all fields and 'all_with_meta' to include |
198 * - 'user_nicename' (or 'nicename'), |
193 * meta fields. Default 'all'. |
199 * - 'nicename__in' |
194 * @type string $who Type of users to query. Accepts 'authors'. |
200 * - 'user_email (or 'email') |
195 * Default empty (all users). |
201 * - 'user_url' (or 'url'), |
196 * @type bool|array $has_published_posts Pass an array of post types to filter results to users who have |
202 * - 'user_registered' (or 'registered') |
197 * published posts in those post types. `true` is an alias for all |
203 * - 'post_count' |
198 * public post types. |
204 * - 'meta_value', |
199 * @type string $nicename The user nicename. Default empty. |
205 * - 'meta_value_num' |
200 * @type string[] $nicename__in An array of nicenames to include. Users matching one of these |
206 * - The value of `$meta_key` |
201 * nicenames will be included in results. Default empty array. |
207 * - An array key of `$meta_query` |
202 * @type string[] $nicename__not_in An array of nicenames to exclude. Users matching one of these |
208 * To use 'meta_value' or 'meta_value_num', `$meta_key` |
203 * nicenames will not be included in results. Default empty array. |
209 * must be also be defined. Default 'user_login'. |
204 * @type string $login The user login. Default empty. |
210 * @type string $order Designates ascending or descending order of users. Order values |
205 * @type string[] $login__in An array of logins to include. Users matching one of these |
211 * passed as part of an `$orderby` array take precedence over this |
206 * logins will be included in results. Default empty array. |
212 * parameter. Accepts 'ASC', 'DESC'. Default 'ASC'. |
207 * @type string[] $login__not_in An array of logins to exclude. Users matching one of these |
213 * @type int $offset Number of users to offset in retrieved results. Can be used in |
208 * logins will not be included in results. Default empty array. |
214 * conjunction with pagination. Default 0. |
|
215 * @type int $number Number of users to limit the query for. Can be used in |
|
216 * conjunction with pagination. Value -1 (all) is supported, but |
|
217 * should be used with caution on larger sites. |
|
218 * Default -1 (all users). |
|
219 * @type int $paged When used with number, defines the page of results to return. |
|
220 * Default 1. |
|
221 * @type bool $count_total Whether to count the total number of users found. If pagination |
|
222 * is not needed, setting this to false can improve performance. |
|
223 * Default true. |
|
224 * @type string|string[] $fields Which fields to return. Single or all fields (string), or array |
|
225 * of fields. Accepts: |
|
226 * - 'ID' |
|
227 * - 'display_name' |
|
228 * - 'user_login' |
|
229 * - 'user_nicename' |
|
230 * - 'user_email' |
|
231 * - 'user_url' |
|
232 * - 'user_registered' |
|
233 * - 'user_pass' |
|
234 * - 'user_activation_key' |
|
235 * - 'user_status' |
|
236 * - 'spam' (only available on multisite installs) |
|
237 * - 'deleted' (only available on multisite installs) |
|
238 * - 'all' for all fields |
|
239 * - 'all_with_meta' to include meta fields. |
|
240 * Default 'all'. |
|
241 * @type string $who Type of users to query. Accepts 'authors'. |
|
242 * Default empty (all users). |
|
243 * @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 |
|
245 * public post types. |
|
246 * @type string $nicename The user nicename. Default empty. |
|
247 * @type string[] $nicename__in An array of nicenames to include. Users matching one of these |
|
248 * nicenames will be included in results. Default empty array. |
|
249 * @type string[] $nicename__not_in An array of nicenames to exclude. Users matching one of these |
|
250 * nicenames will not be included in results. Default empty array. |
|
251 * @type string $login The user login. Default empty. |
|
252 * @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. |
|
254 * @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. |
209 * } |
256 * } |
210 */ |
257 */ |
211 public function prepare_query( $query = array() ) { |
258 public function prepare_query( $query = array() ) { |
212 global $wpdb; |
259 global $wpdb; |
213 |
260 |
358 } |
442 } |
359 |
443 |
360 $role__not_in = array(); |
444 $role__not_in = array(); |
361 if ( isset( $qv['role__not_in'] ) ) { |
445 if ( isset( $qv['role__not_in'] ) ) { |
362 $role__not_in = (array) $qv['role__not_in']; |
446 $role__not_in = (array) $qv['role__not_in']; |
|
447 } |
|
448 |
|
449 // Capabilities. |
|
450 $available_roles = array(); |
|
451 |
|
452 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 ); |
|
456 $available_roles = $wp_roles->roles; |
|
457 } |
|
458 |
|
459 $capabilities = array(); |
|
460 if ( ! empty( $qv['capability'] ) ) { |
|
461 if ( is_array( $qv['capability'] ) ) { |
|
462 $capabilities = $qv['capability']; |
|
463 } elseif ( is_string( $qv['capability'] ) ) { |
|
464 $capabilities = array_map( 'trim', explode( ',', $qv['capability'] ) ); |
|
465 } |
|
466 } |
|
467 |
|
468 $capability__in = array(); |
|
469 if ( ! empty( $qv['capability__in'] ) ) { |
|
470 $capability__in = (array) $qv['capability__in']; |
|
471 } |
|
472 |
|
473 $capability__not_in = array(); |
|
474 if ( ! empty( $qv['capability__not_in'] ) ) { |
|
475 $capability__not_in = (array) $qv['capability__not_in']; |
|
476 } |
|
477 |
|
478 // Keep track of all capabilities and the roles they're added on. |
|
479 $caps_with_roles = array(); |
|
480 |
|
481 foreach ( $available_roles as $role => $role_data ) { |
|
482 $role_caps = array_keys( array_filter( $role_data['capabilities'] ) ); |
|
483 |
|
484 foreach ( $capabilities as $cap ) { |
|
485 if ( in_array( $cap, $role_caps, true ) ) { |
|
486 $caps_with_roles[ $cap ][] = $role; |
|
487 break; |
|
488 } |
|
489 } |
|
490 |
|
491 foreach ( $capability__in as $cap ) { |
|
492 if ( in_array( $cap, $role_caps, true ) ) { |
|
493 $role__in[] = $role; |
|
494 break; |
|
495 } |
|
496 } |
|
497 |
|
498 foreach ( $capability__not_in as $cap ) { |
|
499 if ( in_array( $cap, $role_caps, true ) ) { |
|
500 $role__not_in[] = $role; |
|
501 break; |
|
502 } |
|
503 } |
|
504 } |
|
505 |
|
506 $role__in = array_merge( $role__in, $capability__in ); |
|
507 $role__not_in = array_merge( $role__not_in, $capability__not_in ); |
|
508 |
|
509 $roles = array_unique( $roles ); |
|
510 $role__in = array_unique( $role__in ); |
|
511 $role__not_in = array_unique( $role__not_in ); |
|
512 |
|
513 // Support querying by capabilities added directly to users. |
|
514 if ( $blog_id && ! empty( $capabilities ) ) { |
|
515 $capabilities_clauses = array( 'relation' => 'AND' ); |
|
516 |
|
517 foreach ( $capabilities as $cap ) { |
|
518 $clause = array( 'relation' => 'OR' ); |
|
519 |
|
520 $clause[] = array( |
|
521 'key' => $wpdb->get_blog_prefix( $blog_id ) . 'capabilities', |
|
522 'value' => '"' . $cap . '"', |
|
523 'compare' => 'LIKE', |
|
524 ); |
|
525 |
|
526 if ( ! empty( $caps_with_roles[ $cap ] ) ) { |
|
527 foreach ( $caps_with_roles[ $cap ] as $role ) { |
|
528 $clause[] = array( |
|
529 'key' => $wpdb->get_blog_prefix( $blog_id ) . 'capabilities', |
|
530 'value' => '"' . $role . '"', |
|
531 'compare' => 'LIKE', |
|
532 ); |
|
533 } |
|
534 } |
|
535 |
|
536 $capabilities_clauses[] = $clause; |
|
537 } |
|
538 |
|
539 $role_queries[] = $capabilities_clauses; |
|
540 |
|
541 if ( empty( $this->meta_query->queries ) ) { |
|
542 $this->meta_query->queries[] = $capabilities_clauses; |
|
543 } else { |
|
544 // Append the cap query to the original queries and reparse the query. |
|
545 $this->meta_query->queries = array( |
|
546 'relation' => 'AND', |
|
547 array( $this->meta_query->queries, array( $capabilities_clauses ) ), |
|
548 ); |
|
549 } |
|
550 |
|
551 $this->meta_query->parse_query_vars( $this->meta_query->queries ); |
363 } |
552 } |
364 |
553 |
365 if ( $blog_id && ( ! empty( $roles ) || ! empty( $role__in ) || ! empty( $role__not_in ) || is_multisite() ) ) { |
554 if ( $blog_id && ( ! empty( $roles ) || ! empty( $role__in ) || ! empty( $role__not_in ) || is_multisite() ) ) { |
366 $role_queries = array(); |
555 $role_queries = array(); |
367 |
556 |
684 public function set( $query_var, $value ) { |
885 public function set( $query_var, $value ) { |
685 $this->query_vars[ $query_var ] = $value; |
886 $this->query_vars[ $query_var ] = $value; |
686 } |
887 } |
687 |
888 |
688 /** |
889 /** |
689 * Used internally to generate an SQL string for searching across multiple columns |
890 * Used internally to generate an SQL string for searching across multiple columns. |
690 * |
891 * |
691 * @since 3.1.0 |
892 * @since 3.1.0 |
692 * |
893 * |
693 * @global wpdb $wpdb WordPress database abstraction object. |
894 * @global wpdb $wpdb WordPress database abstraction object. |
694 * |
895 * |
695 * @param string $string |
896 * @param string $search Search string. |
696 * @param array $cols |
897 * @param string[] $columns Array of columns to search. |
697 * @param bool $wild Whether to allow wildcard searches. Default is false for Network Admin, true for single site. |
898 * @param bool $wild Whether to allow wildcard searches. Default is false for Network Admin, true for single site. |
698 * Single site allows leading and trailing wildcards, Network Admin only trailing. |
899 * Single site allows leading and trailing wildcards, Network Admin only trailing. |
699 * @return string |
900 * @return string |
700 */ |
901 */ |
701 protected function get_search_sql( $string, $cols, $wild = false ) { |
902 protected function get_search_sql( $search, $columns, $wild = false ) { |
702 global $wpdb; |
903 global $wpdb; |
703 |
904 |
704 $searches = array(); |
905 $searches = array(); |
705 $leading_wild = ( 'leading' === $wild || 'both' === $wild ) ? '%' : ''; |
906 $leading_wild = ( 'leading' === $wild || 'both' === $wild ) ? '%' : ''; |
706 $trailing_wild = ( 'trailing' === $wild || 'both' === $wild ) ? '%' : ''; |
907 $trailing_wild = ( 'trailing' === $wild || 'both' === $wild ) ? '%' : ''; |
707 $like = $leading_wild . $wpdb->esc_like( $string ) . $trailing_wild; |
908 $like = $leading_wild . $wpdb->esc_like( $search ) . $trailing_wild; |
708 |
909 |
709 foreach ( $cols as $col ) { |
910 foreach ( $columns as $column ) { |
710 if ( 'ID' === $col ) { |
911 if ( 'ID' === $column ) { |
711 $searches[] = $wpdb->prepare( "$col = %s", $string ); |
912 $searches[] = $wpdb->prepare( "$column = %s", $search ); |
712 } else { |
913 } else { |
713 $searches[] = $wpdb->prepare( "$col LIKE %s", $like ); |
914 $searches[] = $wpdb->prepare( "$column LIKE %s", $like ); |
714 } |
915 } |
715 } |
916 } |
716 |
917 |
717 return ' AND (' . implode( ' OR ', $searches ) . ')'; |
918 return ' AND (' . implode( ' OR ', $searches ) . ')'; |
718 } |
919 } |
719 |
920 |
720 /** |
921 /** |
721 * Return the list of users. |
922 * Returns the list of users. |
722 * |
923 * |
723 * @since 3.1.0 |
924 * @since 3.1.0 |
724 * |
925 * |
725 * @return array Array of results. |
926 * @return array Array of results. |
726 */ |
927 */ |
727 public function get_results() { |
928 public function get_results() { |
728 return $this->results; |
929 return $this->results; |
729 } |
930 } |
730 |
931 |
731 /** |
932 /** |
732 * Return the total number of users for the current query. |
933 * Returns the total number of users for the current query. |
733 * |
934 * |
734 * @since 3.1.0 |
935 * @since 3.1.0 |
735 * |
936 * |
736 * @return int Number of total users. |
937 * @return int Number of total users. |
737 */ |
938 */ |
738 public function get_total() { |
939 public function get_total() { |
739 return $this->total_users; |
940 return $this->total_users; |
740 } |
941 } |
741 |
942 |
742 /** |
943 /** |
743 * Parse and sanitize 'orderby' keys passed to the user query. |
944 * Parses and sanitizes 'orderby' keys passed to the user query. |
744 * |
945 * |
745 * @since 4.2.0 |
946 * @since 4.2.0 |
746 * |
947 * |
747 * @global wpdb $wpdb WordPress database abstraction object. |
948 * @global wpdb $wpdb WordPress database abstraction object. |
748 * |
949 * |