Ticket #19867: 19867.3.diff
File 19867.3.diff, 17.1 KB (added by , 11 years ago) |
---|
-
src/wp-admin/includes/ajax-actions.php
187 187 } 188 188 189 189 function wp_ajax_autocomplete_user() { 190 if ( ! is_multisite() || ! current_user_can( 'promote_users' ) || wp_is_large_network( 'users' ) ) 190 /** 191 * Filter the minimum autocomplete search term length. 192 * 193 * The search term length is also specified in JS. 194 * 195 * @since 3.9.0 196 * @param int $length Minimum length for the autocomplete search term. 197 * @param string $context The context for the autocomplete search. 198 */ 199 if ( trim( strlen( $_REQUEST['term'] ) ) < apply_filters( 'autocomplete_term_length', 2, 'users' ) ) { 191 200 wp_die( -1 ); 201 } 192 202 193 /** This filter is documented in wp-admin/user-new.php */194 if ( ! is_super_admin() && ! apply_filters( 'autocomplete_users_for_site_admins', false ) )195 wp_die( -1 );196 197 $return = array();198 199 203 // Check the type of request 200 204 // Current allowed values are `add` and `search` 201 205 if ( isset( $_REQUEST['autocomplete_type'] ) && 'search' === $_REQUEST['autocomplete_type'] ) { … … 204 208 $type = 'add'; 205 209 } 206 210 211 // Adding users needs the right permissions, 212 // shouldn't run the search on large networks, 213 // and requires that you are a superadmin. 214 // If in the future a `search` type is used at the network level, 215 // this will need a bit of a rethink for passing context. 216 if ( is_multisite() && 'add' === $type ) { 217 if ( ! current_user_can( 'promote_users' ) || wp_is_large_network( 'users' ) ) { 218 wp_die( -1 ); 219 } 220 221 /** This filter is documented in wp-admin/user-new.php */ 222 if ( ! is_super_admin() && ! apply_filters( 'autocomplete_users_for_site_admins', false ) ) { 223 wp_die( -1 ); 224 } 225 } 226 227 $return = array(); 228 207 229 // Check the desired field for value 208 // Current allowed values are `user_email` and `user_login`230 // Current allowed values are `user_email`, `user_login`, and `id` 209 231 if ( isset( $_REQUEST['autocomplete_field'] ) && 'user_email' === $_REQUEST['autocomplete_field'] ) { 210 232 $field = $_REQUEST['autocomplete_field']; 233 } elseif ( 'user_id' === $_REQUEST['autocomplete_field'] ) { 234 $field = 'id'; 211 235 } else { 212 236 $field = 'user_login'; 213 237 } 214 238 215 // Exclude current users of this blog216 if ( isset( $_REQUEST[' site_id'] ) ) {217 $ id = absint( $_REQUEST['site_id'] );239 // Get the return label template. 240 if ( isset( $_REQUEST['autocomplete_label'] ) && ! empty( $_REQUEST['autocomplete_label' ] ) ) { 241 $label_template = $_REQUEST['autocomplete_label']; 218 242 } else { 219 $id = get_current_blog_id(); 243 // default label 244 $label_template = '{{display_name}}'; 220 245 } 221 246 222 $include_blog_users = ( $type == 'search' ? get_users( array( 'blog_id' => $id, 'fields' => 'ID' ) ) : array() ); 223 $exclude_blog_users = ( $type == 'add' ? get_users( array( 'blog_id' => $id, 'fields' => 'ID' ) ) : array() ); 247 // Email addresses should only be shown to (super)admins. 248 if ( ! is_super_admin() ) { 249 $label_template = str_replace( '{{user_email}}', '', $label_template ); 250 } 224 251 252 $id = false; 253 $include_blog_users = $exclude_blog_users = array(); 254 $search_columns = array( 'user_login', 'user_nicename', 'display_name' ); 255 256 // Exclude current users of this blog in multisite in add mode 257 if ( is_multisite() ) { 258 if ( isset( $_REQUEST['site_id'] ) ) { 259 $id = absint( $_REQUEST['site_id'] ); 260 } else { 261 $id = get_current_blog_id(); 262 } 263 264 if ( 'add' === $type ) { 265 $exclude_blog_users = get_users( array( 'blog_id' => $id, 'fields' => 'ID' ) ); 266 // set the blog ID to false because we want the rest of the network's users 267 $id = false; 268 } 269 270 // Include email in search columns - at this point the user must be a superadmin 271 $search_columns[] = 'user_email'; 272 } 273 225 274 $users = get_users( array( 226 'blog_id' => false,275 'blog_id' => $id, 227 276 'search' => '*' . $_REQUEST['term'] . '*', 228 'include' => $include_blog_users,229 277 'exclude' => $exclude_blog_users, 230 'search_columns' => array( 'user_login', 'user_nicename', 'user_email' ),278 'search_columns' => $search_columns, 231 279 ) ); 232 280 233 281 foreach ( $users as $user ) { 282 // Replace a given set of tokens. The rest can be handled with the filter later. 283 $label = $label_template; 284 foreach( array( 'user_id', 'user_login', 'user_email', 'display_name' ) as $token ) { 285 $label = str_replace( '{{' . $token . '}}', $user->$token, $label ); 286 } 287 288 // If the label ends up empty, show user login in parens. 289 if ( empty( $label ) ) { 290 $label = "({$user->user_login})"; 291 } 292 234 293 $return[] = array( 235 /* translators: 1: user_login, 2: user_email */ 236 'label' => sprintf( __( '%1$s (%2$s)' ), $user->user_login, $user->user_email ), 294 'label' => esc_html( $label ), 237 295 'value' => $user->$field, 238 296 ); 239 297 } 240 298 299 /** 300 * Filter the user autocomplete results array. 301 * 302 * Useful if using custom tokens in the label. 303 * 304 * @since 3.9.0 305 * @param array $return Array of results. 306 */ 307 $return = apply_filters( 'autocomplete_user_results', $return ); 308 241 309 wp_die( json_encode( $return ) ); 242 310 } 243 311 -
src/wp-admin/js/user-suggest.js
12 12 var $this = $( this ), 13 13 autocompleteType = ( typeof $this.data( 'autocompleteType' ) !== 'undefined' ) ? $this.data( 'autocompleteType' ) : 'add', 14 14 autocompleteField = ( typeof $this.data( 'autocompleteField' ) !== 'undefined' ) ? $this.data( 'autocompleteField' ) : 'user_login'; 15 autocompleteLabel = ( typeof $this.data( 'autocompleteLabel' ) !== 'undefined' ) ? $this.data( 'autocompleteLabel' ) : ''; 15 16 16 17 $this.autocomplete({ 17 source: ajaxurl + '?action=autocomplete-user&autocomplete_type=' + autocompleteType + '&autocomplete_field=' + autocompleteField + id,18 source: ajaxurl + '?action=autocomplete-user&autocomplete_type=' + autocompleteType + '&autocomplete_field=' + autocompleteField + '&autocomplete_label=' + autocompleteLabel + id, 18 19 delay: 500, 19 20 minLength: 2, 20 21 position: position, … … 23 24 }, 24 25 close: function() { 25 26 $( this ).removeClass( 'open' ); 27 }, 28 focus: function( e, ui ) { 29 $el = $( this ); 30 if ( typeof $el.data( 'autocompleteHelper' ) !== 'undefined' ) { 31 $el.val( ui.item.label ); 32 } else { 33 $el.val( ui.item.value ); 34 } 35 return false; 36 }, 37 select: function( e, ui ) { 38 $el = $( this ); 39 if ( typeof $el.data( 'autocompleteHelper' ) !== 'undefined' ) { 40 $el.next( '.wp-suggest-user-helper' ).val( ui.item.value ); 41 $el.val( ui.item.label ); 42 } else { 43 $el.val( ui.item.value ); 44 } 45 return false; 26 46 } 27 47 }); 28 48 }); -
src/wp-admin/network/site-new.php
140 140 </tr> 141 141 <tr class="form-field form-required"> 142 142 <th scope="row"><?php _e( 'Admin Email' ) ?></th> 143 <td><input name="blog[email]" type="text" class="regular-text wp-suggest-user" data-autocomplete-type="search" data-autocomplete-field="user_email" title="<?php esc_attr_e( 'Email' ) ?>"/></td>143 <td><input name="blog[email]" type="text" class="regular-text wp-suggest-user" data-autocomplete-type="search" data-autocomplete-field="user_email" data-autocomplete-label="{{user_login}} ({{user_email}})" title="<?php esc_attr_e( 'Email' ) ?>"/></td> 144 144 </tr> 145 145 <tr class="form-field"> 146 146 <td colspan="2"><?php _e( 'A new user will be created if the above email address is not in the database.' ) ?><br /><?php _e( 'The username and password will be mailed to this email address.' ) ?></td> -
src/wp-admin/network/site-users.php
265 265 <table class="form-table"> 266 266 <tr> 267 267 <th scope="row"><?php _e( 'Username' ); ?></th> 268 <td><input type="text" class="regular-text wp-suggest-user" name="newuser" id="newuser" /></td>268 <td><input type="text" class="regular-text wp-suggest-user" name="newuser" id="newuser" data-autocomplete-label="{{user_login}} ({{user_email}})" /></td> 269 269 </tr> 270 270 <tr> 271 271 <th scope="row"><?php _e( 'Role' ); ?></th> -
src/wp-admin/user-new.php
293 293 <table class="form-table"> 294 294 <tr class="form-field form-required"> 295 295 <th scope="row"><label for="adduser-email"><?php echo $label; ?></label></th> 296 <td><input name="email" type="text" id="adduser-email" class="wp-suggest-user" value="" /></td>296 <td><input name="email" type="text" id="adduser-email" class="wp-suggest-user" value="" data-autocomplete-label="{{user_login}} ({{user_email}})" /></td> 297 297 </tr> 298 298 <tr class="form-field"> 299 299 <th scope="row"><label for="adduser-role"><?php _e('Role'); ?></label></th> -
src/wp-includes/user.php
1129 1129 * need to be used; all users will be displayed in that case. Only one can be 1130 1130 * used, either 'include' or 'exclude', but not both. 1131 1131 * 1132 * The available arguments are as follows: 1133 * <ol> 1134 * <li>show_option_all - Text to show all and whether HTML option exists.</li> 1135 * <li>show_option_none - Text for show none and whether HTML option exists.</li> 1136 * <li>hide_if_only_one_author - Don't create the dropdown if there is only one user.</li> 1137 * <li>orderby - SQL order by clause for what order the users appear. Default is 'display_name'.</li> 1138 * <li>order - Default is 'ASC'. Can also be 'DESC'.</li> 1139 * <li>include - User IDs to include.</li> 1140 * <li>exclude - User IDs to exclude.</li> 1141 * <li>multi - Default is 'false'. Whether to skip the ID attribute on the 'select' element. A 'true' value is overridden when id argument is set.</li> 1142 * <li>show - Default is 'display_name'. User table column to display. If the selected item is empty then the user_login will be displayed in parentheses</li> 1143 * <li>echo - Default is '1'. Whether to display or retrieve content.</li> 1144 * <li>selected - Which User ID is selected.</li> 1145 * <li>include_selected - Always include the selected user ID in the dropdown. Default is false.</li> 1146 * <li>name - Default is 'user'. Name attribute of select element.</li> 1147 * <li>id - Default is the value of the 'name' parameter. ID attribute of select element.</li> 1148 * <li>class - Class attribute of select element.</li> 1149 * <li>blog_id - ID of blog (Multisite only). Defaults to ID of current blog.</li> 1150 * <li>who - Which users to query. Currently only 'authors' is supported. Default is all users.</li> 1151 * </ol> 1132 * @param array $args { 1133 * An array of arguments. Optional. 1152 1134 * 1135 * @string $show_option_all Text to show all and whether HTML option exists. 1136 * @string $show_option_none Text for show none and whether HTML option exists. 1137 * @bool $hide_if_only_one_author Hide the dropdown if there is only one user. 1138 * @string $orderby SQL order by clause for what order the users appear. 1139 * Default is 'display_name'. 1140 * @string $order Default is 'ASC'. Accepts 'ASC', 'DESC'. 1141 * @array $include User IDs to include. 1142 * @array $exclude User IDs to exclude. 1143 * @bool $multi Whether to skip the ID attribute on the 'select' element. 1144 * A 'true' value is overridden when id argument is set. 1145 * Default is 'false'. 1146 * @string $show User table column to display. Default is 'display_name'. 1147 * If the selected item is empty then the user_login will be 1148 * displayed in parentheses 1149 * @bool $echo Default is '1'. Whether to display or retrieve content. 1150 * @int $selected Which User ID is selected. 1151 * @bool $include_selected Always include the selected user ID in the dropdown. 1152 * Default is false. 1153 * @string $name Name attribute of select element. Default is 'user'. 1154 * @string $id ID attribute of select element. 1155 * Default is the value of the 'name' parameter. 1156 * @string $class Class attribute of select element. 1157 * @int $blog_id ID of blog (Multisite only). Defaults to ID of current blog. 1158 * @array $who Which users to query. Currently only 'authors' is supported. 1159 * Default is all users. 1160 * @bool $autocomplete Whether to use jQuery UI autocomplete instead of a select. 1161 * Default false. 1162 * } 1163 * 1153 1164 * @since 2.3.0 1154 1165 * @uses $wpdb WordPress database object for queries 1155 1166 * … … 1163 1174 'include' => '', 'exclude' => '', 'multi' => 0, 1164 1175 'show' => 'display_name', 'echo' => 1, 1165 1176 'selected' => 0, 'name' => 'user', 'class' => '', 'id' => '', 1166 'blog_id' => $GLOBALS['blog_id'], 'who' => '', 'include_selected' => false 1177 'blog_id' => $GLOBALS['blog_id'], 'who' => '', 'include_selected' => false, 1178 'autocomplete' => false 1167 1179 ); 1168 1180 1169 1181 $defaults['selected'] = is_author() ? get_query_var( 'author' ) : 0; … … 1175 1187 $query_args['fields'] = array( 'ID', 'user_login', $show ); 1176 1188 $users = get_users( $query_args ); 1177 1189 1190 /** 1191 * Filter whether to enable autocomplete for the user select in the admin. 1192 * 1193 * wp_dropdown_users() defaults to using jQuery UI autocomplete in the admin 1194 * when there are over 100 users. To use autocomplete on the front-end, 1195 * set the arg to true when calling the function. 1196 * 1197 * @since 3.9.0 1198 * @param bool $autocomplete Whether or not to use autocomplete for the dropdown. 1199 * @param array $users The results of the get_users() call. Most useful for count(). 1200 * @param array $args The passed args to wp_dropdown_users(). 1201 */ 1202 if ( is_admin() ) { 1203 $autocomplete = apply_filters( 'admin_user_dropdown_autocomplete', count( $users ) > 100, $users, $args ); 1204 } 1205 1178 1206 $output = ''; 1179 1207 if ( !empty($users) && ( empty($hide_if_only_one_author) || count($users) > 1 ) ) { 1180 1208 $name = esc_attr( $name ); … … 1183 1211 else 1184 1212 $id = $id ? " id='" . esc_attr( $id ) . "'" : " id='$name'"; 1185 1213 1186 $output = "<select name='{$name}'{$id} class='$class'>\n"; 1214 if ( $autocomplete ) { 1215 wp_enqueue_script( 'user-suggest' ); 1187 1216 1188 if ( $show_option_all ) 1189 $output .= "\t<option value='0'>$show_option_all</option>\n"; 1217 $display = ''; 1190 1218 1191 if ( $show_option_none) {1192 $_selected = selected( -1, $selected, false);1193 $output .= "\t<option value='-1'$_selected>$show_option_none</option>\n";1194 }1219 if ( $selected > 0 ) { 1220 $user = get_user_by( 'id', $selected ); 1221 $display = ! empty( $user->$show ) ? $user->$show : '('. $user->user_login . ')'; 1222 } 1195 1223 1196 $found_selected = false; 1197 foreach ( (array) $users as $user ) { 1198 $user->ID = (int) $user->ID; 1199 $_selected = selected( $user->ID, $selected, false ); 1200 if ( $_selected ) 1201 $found_selected = true; 1202 $display = !empty($user->$show) ? $user->$show : '('. $user->user_login . ')'; 1203 $output .= "\t<option value='$user->ID'$_selected>" . esc_html($display) . "</option>\n"; 1204 } 1224 $output = '<input type="text" class="' . $class . 'wp-suggest-user hide-if-no-js" data-autocomplete-type="search" data-autocomplete-field="user_id" data-autocomplete-helper="y" data-autocomplete-label="{{' . $show . '}}" value="' . $display . '" />'; 1205 1225 1206 if ( $include_selected && ! $found_selected && ( $selected > 0 ) ) { 1207 $user = get_userdata( $selected ); 1208 $_selected = selected( $user->ID, $selected, false ); 1209 $display = !empty($user->$show) ? $user->$show : '('. $user->user_login . ')'; 1210 $output .= "\t<option value='$user->ID'$_selected>" . esc_html($display) . "</option>\n"; 1226 $output .= "<input type='text' name='{$name}'{$id} class='{$class} wp-suggest-user-helper hide-if-js' value='{$selected}' />"; 1227 } else { 1228 $output = "<select name='{$name}'{$id} class='$class'>\n"; 1229 1230 if ( $show_option_all ) 1231 $output .= "\t<option value='0'>$show_option_all</option>\n"; 1232 1233 if ( $show_option_none ) { 1234 $_selected = selected( -1, $selected, false ); 1235 $output .= "\t<option value='-1'$_selected>$show_option_none</option>\n"; 1236 } 1237 1238 $found_selected = false; 1239 foreach ( (array) $users as $user ) { 1240 $user->ID = (int) $user->ID; 1241 $_selected = selected( $user->ID, $selected, false ); 1242 if ( $_selected ) 1243 $found_selected = true; 1244 $display = !empty($user->$show) ? $user->$show : '('. $user->user_login . ')'; 1245 $output .= "\t<option value='$user->ID'$_selected>" . esc_html($display) . "</option>\n"; 1246 } 1247 1248 if ( $include_selected && ! $found_selected && ( $selected > 0 ) ) { 1249 $user = get_userdata( $selected ); 1250 $_selected = selected( $user->ID, $selected, false ); 1251 $display = !empty($user->$show) ? $user->$show : '('. $user->user_login . ')'; 1252 $output .= "\t<option value='$user->ID'$_selected>" . esc_html($display) . "</option>\n"; 1253 } 1254 1255 $output .= "</select>"; 1211 1256 } 1212 1213 $output .= "</select>";1214 1257 } 1215 1258 1216 1259 /**