Ticket #11914: 11914.6.diff
File 11914.6.diff, 15.9 KB (added by , 15 years ago) |
---|
-
wp-admin/includes/schema.php
146 146 PRIMARY KEY (ID), 147 147 KEY post_name (post_name), 148 148 KEY type_status_date (post_type,post_status,post_date,ID), 149 KEY post_parent (post_parent) 149 KEY post_parent (post_parent), 150 KEY post_author (post_author) 150 151 ) $charset_collate; 151 152 CREATE TABLE $wpdb->users ( 152 153 ID bigint(20) unsigned NOT NULL auto_increment, -
wp-admin/includes/template.php
1794 1794 } 1795 1795 1796 1796 /** 1797 * {@internal Missing Short Description}}1797 * Generate HTML for a single row on the users.php admin panel. 1798 1798 * 1799 1799 * @since unknown 1800 1800 * 1801 * @param unknown_type $user_object 1802 * @param unknown_type $style 1803 * @param unknown_type $role 1804 * @return unknown 1801 * @param object $user_object 1802 * @param string $style Optional. Attributes added to the TR element. Must be sanitized. 1803 * @param string $role Key for the $wp_roles array. 1804 * @param int $numposts Optional. Post count to display for this user. Defaults to zero, as in, a new user has made zero posts. 1805 * @return string 1805 1806 */ 1806 function user_row( $user_object, $style = '', $role = '' ) {1807 function user_row( $user_object, $style = '', $role = '', $numposts = 0 ) { 1807 1808 global $wp_roles; 1808 1809 1809 1810 $current_user = wp_get_current_user(); … … 1819 1820 $short_url = substr( $short_url, 0, -1 ); 1820 1821 if ( strlen( $short_url ) > 35 ) 1821 1822 $short_url = substr( $short_url, 0, 32 ).'...'; 1822 $numposts = get_usernumposts( $user_object->ID );1823 1823 $checkbox = ''; 1824 1824 // Check if the user for this row is editable 1825 1825 if ( current_user_can( 'edit_user', $user_object->ID ) ) { -
wp-admin/users.php
208 208 $userspage = isset($_GET['userspage']) ? $_GET['userspage'] : null; 209 209 $role = isset($_GET['role']) ? $_GET['role'] : null; 210 210 211 // Query the user s211 // Query the user IDs for this page 212 212 $wp_user_search = new WP_User_Search($usersearch, $userspage, $role); 213 213 214 // Query the post counts for this page 215 $post_counts = count_many_users_posts($wp_user_search->get_results()); 216 217 // Query the users for this page 218 cache_users($wp_user_search->get_results()); 219 214 220 $messages = array(); 215 221 if ( isset($_GET['update']) ) : 216 222 switch($_GET['update']) { … … 263 269 <form id="list-filter" action="" method="get"> 264 270 <ul class="subsubsub"> 265 271 <?php 266 $role_links = array(); 267 $avail_roles = array(); 268 $users_of_blog = get_users_of_blog(); 269 $total_users = count( $users_of_blog ); 270 foreach ( (array) $users_of_blog as $b_user ) { 271 $b_roles = unserialize($b_user->meta_value); 272 foreach ( (array) $b_roles as $b_role => $val ) { 273 if ( !isset($avail_roles[$b_role]) ) 274 $avail_roles[$b_role] = 0; 275 $avail_roles[$b_role]++; 276 } 277 } 272 $users_of_blog = count_users(); 273 $total_users = $users_of_blog['total_users']; 274 $avail_roles =& $users_of_blog['avail_roles']; 278 275 unset($users_of_blog); 279 276 280 277 $current_role = false; 281 278 $class = empty($role) ? ' class="current"' : ''; 279 $role_links = array(); 282 280 $role_links[] = "<li><a href='users.php'$class>" . sprintf( _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $total_users, 'users' ), number_format_i18n( $total_users ) ) . '</a>'; 283 281 foreach ( $wp_roles->get_names() as $this_role => $name ) { 284 282 if ( !isset($avail_roles[$this_role]) ) … … 372 370 $role = array_shift($roles); 373 371 374 372 $style = ( ' class="alternate"' == $style ) ? '' : ' class="alternate"'; 375 echo "\n\t" . user_row($user_object, $style, $role);373 echo "\n\t", user_row($user_object, $style, $role, $post_counts[(string)$userid]); 376 374 } 377 375 ?> 378 376 </tbody> -
wp-includes/author-template.php
151 151 * 152 152 * @since 1.5 153 153 * @uses $post The current post in the Loop's DB object. 154 * @uses get_usernumposts()154 * @uses count_user_posts() 155 155 * @return int The number of posts by the author. 156 156 */ 157 157 function get_the_author_posts() { 158 158 global $post; 159 return get_usernumposts($post->post_author);159 return count_user_posts($post->post_author); 160 160 } 161 161 162 162 /** -
wp-includes/pluggable.php
139 139 } 140 140 endif; 141 141 142 if ( !function_exists('cache_users') ) : 143 /** 144 * Retrieve info for user lists to prevent multiple queries by get_userdata() 145 * 146 * @since 3.0.0 147 * 148 * @param array $users User ID numbers list 149 */ 150 function cache_users( $users ) { 151 global $wpdb; 152 153 $clean = array(); 154 foreach($users as $id) { 155 $id = (int) $id; 156 if (wp_cache_get($id, 'users')) { 157 // seems to be cached already 158 } else { 159 $clean[] = $id; 160 } 161 } 162 163 if ( 0 == count($clean) ) 164 return; 165 166 $list = implode(',', $clean); 167 168 $results = $wpdb->get_results("SELECT * FROM $wpdb->users WHERE ID IN ($list)"); 169 170 _fill_many_users($results); 171 } 172 endif; 173 142 174 if ( !function_exists('get_user_by') ) : 143 175 /** 144 176 * Retrieve user info by a given field -
wp-includes/post.php
3639 3639 * @return string SQL code that can be added to a where clause. 3640 3640 */ 3641 3641 function get_private_posts_cap_sql($post_type) { 3642 global $user_ID;3643 $cap = ''; 3642 return get_posts_by_author_sql($post_type, FALSE); 3643 } 3644 3644 3645 /** 3646 * Retrieve the post SQL based on capability, author, and type. 3647 * 3648 * See above for full description. 3649 * 3650 * @since 3.0.0 3651 * @param string $post_type currently only supports 'post' or 'page'. 3652 * @param bool $full Optional. Returns a full WHERE statement instead of just an 'andalso' term. 3653 * @param int $post_author Optional. Query posts having a single author ID. 3654 * @return string SQL WHERE code that can be added to a query. 3655 */ 3656 function get_posts_by_author_sql($post_type, $full = TRUE, $post_author = NULL) { 3657 global $user_ID, $wpdb; 3658 3645 3659 // Private posts 3646 3660 if ($post_type == 'post') { 3647 3661 $cap = 'read_private_posts'; … … 3650 3664 $cap = 'read_private_pages'; 3651 3665 // Dunno what it is, maybe plugins have their own post type? 3652 3666 } else { 3667 $cap = ''; 3653 3668 $cap = apply_filters('pub_priv_sql_capability', $cap); 3654 3669 3655 3670 if (empty($cap)) { 3656 3671 // We don't know what it is, filters don't change anything, 3657 3672 // so set the SQL up to return nothing. 3658 return ' 1 = 0';3673 return ' 1 = 0 '; 3659 3674 } 3660 3675 } 3661 3676 3662 $sql = '(post_status = \'publish\''; 3677 if ($full) { 3678 if (is_null($post_author)) { 3679 $sql = $wpdb->prepare('WHERE post_type = %s AND ', $post_type); 3680 } else { 3681 $sql = $wpdb->prepare('WHERE post_author = %d AND post_type = %s AND ', $post_author, $post_type); 3682 } 3683 } else { 3684 $sql = ''; 3685 } 3663 3686 3687 $sql .= "(post_status = 'publish'"; 3688 3664 3689 if (current_user_can($cap)) { 3665 3690 // Does the user have the capability to view private posts? Guess so. 3666 $sql .= ' OR post_status = \'private\'';3691 $sql .= " OR post_status = 'private'"; 3667 3692 } elseif (is_user_logged_in()) { 3668 3693 // Users can view their own private posts. 3669 $sql .= ' OR post_status = \'private\' AND post_author = \'' . $user_ID . '\''; 3670 } 3694 $id = (int) $user_ID; 3695 if (is_null($post_author) || !$full) { 3696 $sql .= " OR post_status = 'private' AND post_author = $id"; 3697 } elseif ($id == (int)$post_author) { 3698 $sql .= " OR post_status = 'private'"; 3699 } // else none 3700 } // else none 3671 3701 3672 3702 $sql .= ')'; 3673 3703 -
wp-includes/user.php
176 176 * @param int $userid User ID. 177 177 * @return int Amount of posts user has written. 178 178 */ 179 function get_usernumposts($userid) {179 function count_user_posts($userid) { 180 180 global $wpdb; 181 $userid = (int) $userid; 182 $count = $wpdb->get_var( $wpdb->prepare("SELECT COUNT(*) FROM $wpdb->posts WHERE post_author = %d AND post_type = 'post' AND ", $userid) . get_private_posts_cap_sql('post')); 181 182 $where = get_posts_by_author_sql('post', TRUE, $userid); 183 184 $count = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->posts $where" ); 185 183 186 return apply_filters('get_usernumposts', $count, $userid); 184 187 } 185 188 186 189 /** 190 * Number of posts written by a list of users. 191 * 192 * @since 3.0.0 193 * @param array $userid User ID number list. 194 * @return array Amount of posts each user has written. 195 */ 196 function count_many_users_posts($users) { 197 global $wpdb; 198 199 if (0 == count($users)) 200 return array(); 201 202 $userlist = implode(',', $users); 203 $where = get_posts_by_author_sql('post'); 204 205 $result = $wpdb->get_results( "SELECT post_author, COUNT(*) FROM $wpdb->posts $where AND post_author IN ($userlist) GROUP BY post_author", ARRAY_N ); 206 207 $count = array(); 208 foreach($result as $row) { 209 $count[$row[0]] = $row[1]; 210 } 211 212 foreach($users as $id) { 213 $id = (string) $id; 214 if (!isset($count[$id])) 215 $count[$id] = 0; 216 } 217 218 return $count; 219 } 220 221 /** 187 222 * Check that the user login name and password is correct. 188 223 * 189 224 * @since 0.71 … … 438 473 return true; 439 474 } 440 475 476 /** 477 * Count number of users who have each of the user roles. 478 * 479 * Assumes there are neither duplicated nor orphaned capabilities meta_values. 480 * Assumes role names are unique phrases. Same assumption made by WP_User_Search::prepare_query() 481 * Using $strategy = 'time' this is CPU-intensive and should handle around 10^7 users. 482 * Using $strategy = 'memory' this is memory-intensive and should handle around 10^5 users, but see WP Bug #12257. 483 * 484 * @since 3.0.0 485 * @param string $strategy 'time' or 'memory' 486 * @return array Includes a grand total and an array of counts indexed by role strings. 487 */ 488 function count_users($strategy = 'time') { 489 global $wpdb, $blog_id, $wp_roles; 490 491 // Initialize 492 $id = (int) $blog_id; 493 $blog_prefix = $wpdb->get_blog_prefix($id); 494 $result = array(); 495 496 if ('time' == $strategy) { 497 $avail_roles = $wp_roles->get_names(); 498 499 // Build a CPU-intensive query that will return concise information. 500 $select_count = array(); 501 foreach ( $avail_roles as $this_role => $name ) { 502 $select_count[] = "COUNT(NULLIF(`meta_value` LIKE '%" . like_escape($this_role) . "%', FALSE))"; 503 } 504 $select_count = implode(', ', $select_count); 505 506 // Add the meta_value index to the selection list, then run the query. 507 $row = $wpdb->get_row( "SELECT $select_count, COUNT(*) FROM $wpdb->usermeta WHERE meta_key = '{$blog_prefix}capabilities'", ARRAY_N ); 508 509 // Run the previous loop again to associate results with role names. 510 $col = 0; 511 $role_counts = array(); 512 foreach ( $avail_roles as $this_role => $name ) { 513 $count = (int) $row[$col++]; 514 if ($count > 0) { 515 $role_counts[$this_role] = $count; 516 } 517 } 518 519 // Get the meta_value index from the end of the result set. 520 $total_users = (int) $row[$col]; 521 522 $result['total_users'] = $total_users; 523 $result['avail_roles'] =& $role_counts; 524 } else { 525 $avail_roles = array(); 526 527 $users_of_blog = $wpdb->get_col( "SELECT meta_value FROM $wpdb->usermeta WHERE meta_key = '{$blog_prefix}capabilities'" ); 528 529 foreach ( $users_of_blog as $caps_meta ) { 530 $b_roles = unserialize($caps_meta); 531 if ( is_array($b_roles) ) { 532 foreach ( $b_roles as $b_role => $val ) { 533 if ( isset($avail_roles[$b_role]) ) { 534 $avail_roles[$b_role]++; 535 } else { 536 $avail_roles[$b_role] = 1; 537 } 538 } 539 } 540 } 541 542 $result['total_users'] = count( $users_of_blog ); 543 $result['avail_roles'] =& $avail_roles; 544 } 545 546 return $result; 547 } 548 441 549 // 442 550 // Private helper functions 443 551 // … … 588 696 * 589 697 * The finished user data is cached, but the cache is not used to fill in the 590 698 * user data for the given object. Once the function has been used, the cache 591 * should be used to retrieve user data. The purpose seems then to be to ensure592 * that the data in the object is always fresh.699 * should be used to retrieve user data. The intention is if the current data 700 * had been cached already, there would be no need to call this function. 593 701 * 594 702 * @access private 595 703 * @since 2.5.0 … … 598 706 * @param object $user The user data object. 599 707 */ 600 708 function _fill_user( &$user ) { 709 $metavalues = get_user_metavalues(array($user->ID)); 710 _fill_single_user($user, $metavalues[$user->ID]); 711 } 712 713 /** 714 * Perform the query to get the $metavalues array(s) needed by _fill_user and _fill_many_users 715 * 716 * @since 3.0.0 717 * @param array $ids User ID numbers list. 718 * @return array of arrays. The array is indexed by user_id, containing $metavalues object arrays. 719 */ 720 function get_user_metavalues($ids) { 601 721 global $wpdb; 602 722 723 $clean = array_map('intval', $ids); 724 if ( 0 == count($clean) ) 725 return $objects; 726 727 $list = implode(',', $clean); 728 603 729 $show = $wpdb->hide_errors(); 604 $metavalues = $wpdb->get_results( $wpdb->prepare("SELECT meta_key, meta_value FROM $wpdb->usermeta WHERE user_id = %d", $user->ID));730 $metavalues = $wpdb->get_results("SELECT user_id, meta_key, meta_value FROM $wpdb->usermeta WHERE user_id IN ($list)"); 605 731 $wpdb->show_errors($show); 606 732 607 if ( $metavalues ) { 608 foreach ( (array) $metavalues as $meta ) { 609 $value = maybe_unserialize($meta->meta_value); 610 $user->{$meta->meta_key} = $value; 611 } 733 $objects = array(); 734 foreach($clean as $id) { 735 $objects[$id] = array(); 612 736 } 737 foreach($metavalues as $meta_object) { 738 $objects[$meta_object->user_id][] = $meta_object; 739 } 613 740 741 return $objects; 742 } 743 744 /** 745 * Unserialize user metadata, fill $user object, then cache everything. 746 * 747 * @since 3.0.0 748 * @param object $user The User object. 749 * @param array $metavalues An array of objects provided by get_user_metavalues() 750 */ 751 function _fill_single_user( &$user, &$metavalues ) { 752 global $wpdb; 753 754 foreach ( $metavalues as $meta ) { 755 $value = maybe_unserialize($meta->meta_value); 756 $user->{$meta->meta_key} = $value; 757 } 758 614 759 $level = $wpdb->prefix . 'user_level'; 615 760 if ( isset( $user->{$level} ) ) 616 761 $user->user_level = $user->{$level}; … … 623 768 if ( isset($user->description) ) 624 769 $user->user_description = $user->description; 625 770 626 wp_cache_add($user->ID, $user, 'users'); 627 wp_cache_add($user->user_login, $user->ID, 'userlogins'); 628 wp_cache_add($user->user_email, $user->ID, 'useremail'); 629 wp_cache_add($user->user_nicename, $user->ID, 'userslugs'); 771 update_user_caches($user); 630 772 } 631 773 632 774 /** 775 * Take an array of user objects, fill them with metas, and cache them. 776 * 777 * @since 3.0.0 778 * @param array $users User objects 779 * @param array $metas User metavalues objects 780 */ 781 function _fill_many_users( &$users ) { 782 $ids = array(); 783 foreach($users as $user_object) { 784 $ids[] = $user_object->ID; 785 } 786 787 $metas = get_user_metavalues($ids); 788 789 foreach($users as $user_object) { 790 if (isset($metas[$user_object->ID])) { 791 _fill_single_user($user_object, $metas[$user_object->ID]); 792 } 793 } 794 } 795 796 /** 633 797 * Sanitize every user field. 634 798 * 635 799 * If the context is 'raw', then the user object or array will get minimal santization of the int fields. … … 746 910 } 747 911 748 912 /** 913 * Update all user caches 914 * 915 * @since 3.0.0 916 * 917 * @param object $user User object to be cached 918 */ 919 function update_user_caches(&$user) { 920 wp_cache_add($user->ID, $user, 'users'); 921 wp_cache_add($user->user_login, $user->ID, 'userlogins'); 922 wp_cache_add($user->user_email, $user->ID, 'useremail'); 923 wp_cache_add($user->user_nicename, $user->ID, 'userslugs'); 924 } 925 926 /** 749 927 * Clean all user caches 750 928 * 751 * @since 3.0 929 * @since 3.0.0 752 930 * 753 931 * @param int $id User ID 754 * @return void755 932 */ 756 933 function clean_user_cache($id) { 757 934 $user = new WP_User($id); … … 762 939 wp_cache_delete($user->user_nicename, 'userslugs'); 763 940 } 764 941 765 ?> 766 No newline at end of file 942 ?>