class-acf-ajax-query-users.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. <?php
  2. if ( ! defined( 'ABSPATH' ) ) {
  3. exit; // Exit if accessed directly
  4. }
  5. if ( ! class_exists( 'ACF_Ajax_Query_Users' ) ) :
  6. class ACF_Ajax_Query_Users extends ACF_Ajax_Query {
  7. /** @var string The AJAX action name. */
  8. var $action = 'acf/ajax/query_users';
  9. /**
  10. * init_request
  11. *
  12. * Called at the beginning of a request to setup properties.
  13. *
  14. * @date 23/5/19
  15. * @since 5.8.1
  16. *
  17. * @param array $request The request args.
  18. * @return void
  19. */
  20. function init_request( $request ) {
  21. parent::init_request( $request );
  22. // Customize query.
  23. add_filter( 'user_search_columns', array( $this, 'filter_search_columns' ), 10, 3 );
  24. /**
  25. * Fires when a request is made.
  26. *
  27. * @date 21/5/19
  28. * @since 5.8.1
  29. *
  30. * @param array $request The query request.
  31. * @param ACF_Ajax_Query $query The query object.
  32. */
  33. do_action( 'acf/ajax/query_users/init', $request, $this );
  34. }
  35. /**
  36. * get_args
  37. *
  38. * Returns an array of args for this query.
  39. *
  40. * @date 31/7/18
  41. * @since 5.7.2
  42. *
  43. * @param array $request The request args.
  44. * @return array
  45. */
  46. function get_args( $request ) {
  47. $args = parent::get_args( $request );
  48. $args['number'] = $this->per_page;
  49. $args['paged'] = $this->page;
  50. if ( $this->is_search ) {
  51. $args['search'] = "*{$this->search}*";
  52. }
  53. /**
  54. * Filters the query args.
  55. *
  56. * @date 21/5/19
  57. * @since 5.8.1
  58. *
  59. * @param array $args The query args.
  60. * @param array $request The query request.
  61. * @param ACF_Ajax_Query $query The query object.
  62. */
  63. return apply_filters( 'acf/ajax/query_users/args', $args, $request, $this );
  64. }
  65. /**
  66. * Prepares args for the get_results() method.
  67. *
  68. * @date 23/3/20
  69. * @since 5.8.9
  70. *
  71. * @param array args The query args.
  72. * @return array
  73. */
  74. function prepare_args( $args ) {
  75. // Parse pagination args that may have been modified.
  76. if ( isset( $args['users_per_page'] ) ) {
  77. $this->per_page = intval( $args['users_per_page'] );
  78. unset( $args['users_per_page'] );
  79. } elseif ( isset( $args['number'] ) ) {
  80. $this->per_page = intval( $args['number'] );
  81. }
  82. if ( isset( $args['paged'] ) ) {
  83. $this->page = intval( $args['paged'] );
  84. unset( $args['paged'] );
  85. }
  86. // Set pagination args for fine control.
  87. $args['number'] = $this->per_page;
  88. $args['offset'] = $this->per_page * ( $this->page - 1 );
  89. $args['count_total'] = true;
  90. return $args;
  91. }
  92. /**
  93. * get_results
  94. *
  95. * Returns an array of results for the given args.
  96. *
  97. * @date 31/7/18
  98. * @since 5.7.2
  99. *
  100. * @param array args The query args.
  101. * @return array
  102. */
  103. function get_results( $args ) {
  104. $results = array();
  105. // Prepare args for quey.
  106. $args = $this->prepare_args( $args );
  107. // Get result groups.
  108. if ( ! empty( $args['role__in'] ) ) {
  109. $roles = acf_get_user_role_labels( $args['role__in'] );
  110. } else {
  111. $roles = acf_get_user_role_labels();
  112. }
  113. // Return a flat array of results when searching or when queriying one group only.
  114. if ( $this->is_search || count( $roles ) === 1 ) {
  115. // Query users and append to results.
  116. $wp_user_query = new WP_User_Query( $args );
  117. $users = (array) $wp_user_query->get_results();
  118. $total_users = $wp_user_query->get_total();
  119. foreach ( $users as $user ) {
  120. $results[] = $this->get_result( $user );
  121. }
  122. // Determine if more results exist.
  123. // As this query does not return grouped results, the calculation can be exact (">").
  124. $this->more = ( $total_users > count( $users ) + $args['offset'] );
  125. // Otherwise, group results via role.
  126. } else {
  127. // Unset args that will interfer with query results.
  128. unset( $args['role__in'], $args['role__not_in'] );
  129. // Loop over each role.
  130. foreach ( $roles as $role => $role_label ) {
  131. // Query users (for this role only).
  132. $args['role'] = $role;
  133. $wp_user_query = new WP_User_Query( $args );
  134. $users = (array) $wp_user_query->get_results();
  135. $total_users = $wp_user_query->get_total();
  136. // acf_log( $args );
  137. // acf_log( '- ', count($users) );
  138. // acf_log( '- ', $total_users );
  139. // If users were found for this query...
  140. if ( $users ) {
  141. // Append optgroup of results.
  142. $role_results = array();
  143. foreach ( $users as $user ) {
  144. $role_results[] = $this->get_result( $user );
  145. }
  146. $results[] = array(
  147. 'text' => $role_label,
  148. 'children' => $role_results,
  149. );
  150. // End loop when enough results have been found.
  151. if ( count( $users ) === $args['number'] ) {
  152. // Determine if more results exist.
  153. // As this query does return grouped results, the calculation is best left fuzzy to avoid querying the next group (">=").
  154. $this->more = ( $total_users >= count( $users ) + $args['offset'] );
  155. break;
  156. // Otherwise, modify the args so that the next query can continue on correctly.
  157. } else {
  158. $args['offset'] = 0;
  159. $args['number'] -= count( $users );
  160. }
  161. // If no users were found (for the current pagination args), but there were users found for previous pages...
  162. // Modify the args so that the next query is offset slightly less (the number of total users) and can continue on correctly.
  163. } elseif ( $total_users ) {
  164. $args['offset'] -= $total_users;
  165. continue;
  166. // Ignore roles that will never return a result.
  167. } else {
  168. continue;
  169. }
  170. }
  171. }
  172. /**
  173. * Filters the query results.
  174. *
  175. * @date 21/5/19
  176. * @since 5.8.1
  177. *
  178. * @param array $results The query results.
  179. * @param array $args The query args.
  180. * @param ACF_Ajax_Query $query The query object.
  181. */
  182. return apply_filters( 'acf/ajax/query_users/results', $results, $args, $this );
  183. }
  184. /**
  185. * get_result
  186. *
  187. * Returns a single result for the given item object.
  188. *
  189. * @date 31/7/18
  190. * @since 5.7.2
  191. *
  192. * @param mixed $item A single item from the queried results.
  193. * @return string
  194. */
  195. function get_result( $user ) {
  196. $item = acf_get_user_result( $user );
  197. /**
  198. * Filters the result item.
  199. *
  200. * @date 21/5/19
  201. * @since 5.8.1
  202. *
  203. * @param array $item The choice id and text.
  204. * @param ACF_User $user The user object.
  205. * @param ACF_Ajax_Query $query The query object.
  206. */
  207. return apply_filters( 'acf/ajax/query_users/result', $item, $user, $this );
  208. }
  209. /**
  210. * Filters the WP_User_Query search columns.
  211. *
  212. * @date 9/3/20
  213. * @since 5.8.8
  214. *
  215. * @param array $columns An array of column names to be searched.
  216. * @param string $search The search term.
  217. * @param WP_User_Query $WP_User_Query The WP_User_Query instance.
  218. * @return array
  219. */
  220. function filter_search_columns( $columns, $search, $WP_User_Query ) {
  221. /**
  222. * Filters the column names to be searched.
  223. *
  224. * @date 21/5/19
  225. * @since 5.8.1
  226. *
  227. * @param array $columns An array of column names to be searched.
  228. * @param string $search The search term.
  229. * @param WP_User_Query $WP_User_Query The WP_User_Query instance.
  230. * @param ACF_Ajax_Query $query The query object.
  231. */
  232. return apply_filters( 'acf/ajax/query_users/search_columns', $columns, $search, $WP_User_Query, $this );
  233. }
  234. }
  235. acf_new_instance( 'ACF_Ajax_Query_Users' );
  236. endif; // class_exists check