Ticket #16001: 16001.diff

File 16001.diff, 17.2 KB (added by garyc40, 2 years ago)

first attempt to patch this bug

Line 
1diff --git wp-admin/includes/class-wp-ms-users-list-table.php wp-admin/includes/class-wp-ms-users-list-table.php
2index c3bfec2..bd502ed 100644
3--- wp-admin/includes/class-wp-ms-users-list-table.php
4+++ wp-admin/includes/class-wp-ms-users-list-table.php
5@@ -56,8 +56,10 @@ class WP_MS_Users_List_Table extends WP_List_Table {
6 
7                $mode = empty( $_REQUEST['mode'] ) ? 'list' : $_REQUEST['mode'];
8 
9-               // Query the user IDs for this page
10-               $wp_user_search = new WP_User_Query( $args );
11+               if ( $role == 'pending' )
12+                       $wp_user_search = new WP_Pending_User_Query( $args ); // Query for pending users
13+               else
14+                       $wp_user_search = new WP_User_Query( $args ); // Query the user IDs for this page
15 
16                $this->items = $wp_user_search->get_results();
17 
18@@ -68,11 +70,21 @@ class WP_MS_Users_List_Table extends WP_List_Table {
19        }
20 
21        function get_bulk_actions() {
22+               global $role;
23+               
24                $actions = array();
25-               if ( current_user_can( 'delete_users' ) )
26-                       $actions['delete'] = __( 'Delete' );
27-               $actions['spam'] = _x( 'Mark as Spam', 'user' );
28-               $actions['notspam'] = _x( 'Not Spam', 'user' );
29+               
30+               if ( $role == 'pending' ) {
31+                       if ( current_user_can( 'delete_users' ) )
32+                               $actions['deletesignup'] = __( 'Delete' );
33+                       $actions['activate'] = _x( 'Activate', 'user' );
34+                       $actions['resend'] = __( 'Resend Email' );
35+               } else {
36+                       if ( current_user_can( 'delete_users' ) )
37+                               $actions['delete'] = __( 'Delete' );
38+                       $actions['spam'] = _x( 'Mark as Spam', 'user' );
39+                       $actions['notspam'] = _x( 'Not Spam', 'user' );
40+               }
41 
42                return $actions;
43        }
44@@ -87,13 +99,15 @@ class WP_MS_Users_List_Table extends WP_List_Table {
45                $total_users = get_user_count();
46                $super_admins = get_super_admins();
47                $total_admins = count( $super_admins );
48+               $total_pendings = get_pending_user_count();
49 
50-               $current_role = false;
51-               $class = $role != 'super' ? ' class="current"' : '';
52+               $class = in_array( $role, array( 'super', 'pending' ) ) ? '' : ' class="current"';
53                $role_links = array();
54                $role_links['all'] = "<a href='" . network_admin_url('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>';
55                $class = $role == 'super' ? ' class="current"' : '';
56                $role_links['super'] = "<a href='" . network_admin_url('users.php?role=super') . "'$class>" . sprintf( _n( 'Super Admin <span class="count">(%s)</span>', 'Super Admins <span class="count">(%s)</span>', $total_admins ), number_format_i18n( $total_admins ) ) . '</a>';
57+               $class = $role == 'pending' ? ' class="current"' : '';
58+               $role_links['pending'] = "<a href='" . network_admin_url('users.php?role=pending') . "'$class>" . sprintf( _n( 'Pending Confirmation <span class="count">(%s)</span>', 'Pending Confirmation <span class="count">(%s)</span>', $total_pendings ), number_format_i18n( $total_pendings ) ) . '</a>';
59 
60                return $role_links;
61        }
62@@ -108,30 +122,43 @@ class WP_MS_Users_List_Table extends WP_List_Table {
63        }
64 
65        function get_columns() {
66+               global $role;
67+               
68                $users_columns = array(
69                        'cb'         => '<input type="checkbox" />',
70                        'username'   => __( 'Username' ),
71-                       'name'       => __( 'Name' ),
72                        'email'      => __( 'E-mail' ),
73                        'registered' => _x( 'Registered', 'user' ),
74-                       'blogs'      => __( 'Sites' )
75                );
76+               
77+               if ( $role != 'pending' ) {
78+                       $users_columns['name'] = __( 'Name' );
79+                       $users_columns['blogs'] = __( 'Sites' );
80+               }
81+               
82                $users_columns = apply_filters( 'wpmu_users_columns', $users_columns );
83 
84                return $users_columns;
85        }
86 
87        function get_sortable_columns() {
88-               return array(
89+               global $role;
90+               
91+               $sortables = array(
92                        'username'   => 'login',
93-                       'name'       => 'name',
94                        'email'      => 'email',
95                        'registered' => 'id',
96                );
97+               
98+               if ( $role != 'pending' ) {
99+                       $sortables['name'] = 'name';
100+               }
101+               
102+               return $sortables;
103        }
104 
105        function display_rows() {
106-               global $current_site, $mode;
107+               global $current_site, $mode, $role;
108 
109                $alt = '';
110                $super_admins = get_super_admins();
111@@ -140,9 +167,14 @@ class WP_MS_Users_List_Table extends WP_List_Table {
112 
113                        $status_list = array( 'spam' => 'site-spammed', 'deleted' => 'site-deleted' );
114 
115-                       foreach ( $status_list as $status => $col ) {
116-                               if ( $user->$status )
117-                                       $alt .= " $col";
118+                       if ( $role == 'pending' ) {                             
119+                               $user->ID = $user->user_login;
120+                               $user->user_registered = $user->registered;
121+                       } else {
122+                               foreach ( $status_list as $status => $col ) {
123+                                       if ( $user->$status )
124+                                               $alt .= " $col";
125+                               }
126                        }
127 
128                        ?>
129@@ -171,24 +203,44 @@ class WP_MS_Users_List_Table extends WP_List_Table {
130 
131                                        case 'username':
132                                                $avatar = get_avatar( $user->user_email, 32 );
133-                                               if ( get_current_user_id() == $user->ID ) {
134-                                                       $edit_link = esc_url( network_admin_url( 'profile.php' ) );
135+                                               if ( $role == 'pending' ) {
136+                                                       $activate_link = esc_url( network_admin_url( add_query_arg( '_wp_http_referer', urlencode( stripslashes( $_SERVER['REQUEST_URI'] ) ), wp_nonce_url( 'edit.php', 'activatesignup' ) . '&amp;action=activatesignup&amp;user_login=' . $user->user_login ) ) );
137+                                                       $resend_link = esc_url( network_admin_url( add_query_arg( '_wp_http_referer', urlencode( stripslashes( $_SERVER['REQUEST_URI'] ) ), wp_nonce_url( 'edit.php', 'resendsignup' ) . '&amp;action=resendsignup&amp;user_login=' . $user->user_login ) ) );
138                                                } else {
139-                                                       $edit_link = esc_url( network_admin_url( add_query_arg( 'wp_http_referer', urlencode( stripslashes( $_SERVER['REQUEST_URI'] ) ), 'user-edit.php?user_id=' . $user->ID ) ) );
140+                                                       if ( get_current_user_id() == $user->ID ) {
141+                                                               $edit_link = esc_url( network_admin_url( 'profile.php' ) );
142+                                                       } else {
143+                                                               $edit_link = esc_url( network_admin_url( add_query_arg( 'wp_http_referer', urlencode( stripslashes( $_SERVER['REQUEST_URI'] ) ), 'user-edit.php?user_id=' . $user->ID ) ) );
144+                                                       }
145                                                }
146 
147                                                echo "<td $attributes>"; ?>
148-                                                       <?php echo $avatar; ?><strong><a href="<?php echo $edit_link; ?>" class="edit"><?php echo stripslashes( $user->user_login ); ?></a><?php
149+                                                       <?php echo $avatar; ?><strong>
150+                                                               <?php if ( $role == 'pending' ): ?>
151+                                                                       <?php echo stripslashes( $user->user_login ); ?>
152+                                                               <?php else: ?>
153+                                                                       <a href="<?php echo $edit_link; ?>" class="edit"><?php echo stripslashes( $user->user_login ); ?></a>   
154+                                                               <?php endif ?>
155+                                                               <?php
156                                                        if ( in_array( $user->user_login, $super_admins ) )
157                                                                echo ' - ' . __( 'Super Admin' );
158                                                        ?></strong>
159                                                        <br/>
160                                                        <?php
161                                                                $actions = array();
162-                                                               $actions['edit'] = '<a href="' . $edit_link . '">' . __( 'Edit' ) . '</a>';
163+                                                               if ( $role == 'pending' ) {
164+                                                                       $actions['activate'] = '<a href="' . $activate_link . '">' . __( 'Activate' ) . '</a>';
165+                                                                       $actions['resend'] = '<a href="' . $resend_link . '">' . __( 'Resend Email' ) . '</a>';
166+                                                               } else {
167+                                                                       $actions['edit'] = '<a href="' . $edit_link . '">' . __( 'Edit' ) . '</a>';
168+                                                               }
169 
170                                                                if ( current_user_can( 'delete_user', $user->ID) && ! in_array( $user->user_login, $super_admins ) ) {
171-                                                                       $actions['delete'] = '<a href="' . $delete = esc_url( network_admin_url( add_query_arg( '_wp_http_referer', urlencode( stripslashes( $_SERVER['REQUEST_URI'] ) ), wp_nonce_url( 'edit.php', 'deleteuser' ) . '&amp;action=deleteuser&amp;id=' . $user->ID ) ) ) . '" class="delete">' . __( 'Delete' ) . '</a>';
172+                                                                       if ( $role == 'pending' ) {
173+                                                                               $actions['delete'] = '<a href="' . $delete = esc_url( network_admin_url( add_query_arg( '_wp_http_referer', urlencode( stripslashes( $_SERVER['REQUEST_URI'] ) ), wp_nonce_url( 'edit.php', 'deletesignup' ) . '&amp;action=deletesignup&amp;user_login=' . $user->user_login ) ) ) . '" class="delete">' . __( 'Delete' ) . '</a>';
174+                                                                       } else {
175+                                                                               $actions['delete'] = '<a href="' . $delete = esc_url( network_admin_url( add_query_arg( '_wp_http_referer', urlencode( stripslashes( $_SERVER['REQUEST_URI'] ) ), wp_nonce_url( 'edit.php', 'deleteuser' ) . '&amp;action=deleteuser&amp;id=' . $user->ID ) ) ) . '" class="delete">' . __( 'Delete' ) . '</a>';
176+                                                                       }
177                                                                }
178 
179                                                                echo $this->row_actions( $actions );
180diff --git wp-admin/network/edit.php wp-admin/network/edit.php
181index e785d38..5cadac7 100644
182--- wp-admin/network/edit.php
183+++ wp-admin/network/edit.php
184@@ -18,6 +18,54 @@ if ( empty( $_GET['action'] ) ) {
185        exit;
186 }
187 
188+function _wp_activate_by_user_login( $user_login ) {
189+       global $wpdb;
190+       
191+       $key = $wpdb->get_var( $wpdb->prepare( "SELECT activation_key FROM {$wpdb->signups} WHERE active != 1 AND user_login = %s", $user_login ) );
192+       if ( $key ) {
193+               wpmu_activate_signup( $key );
194+       }
195+}
196+
197+function _wp_resend_by_user_login( $user_login ) {
198+       global $wpdb;
199+       
200+       $user = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->signups} WHERE active !=1 AND user_login = %s", $user_login ) );
201+       
202+       if ( $user ) {
203+               wpmu_signup_user_notification($user->user_login, $user->user_email, $user->activation_key, $user->meta);
204+       }
205+}
206+
207+function confirm_delete_signups( $signups ) {
208+       global $wpdb;
209+       
210+       $current_user = wp_get_current_user();
211+       if ( ! is_array( $signups ) ) {
212+               return false;
213+       }
214+       
215+       screen_icon();
216+       ?>
217+       <h2><?php esc_html_e( 'Users' ); ?></h2>
218+       <p><?php _e( 'Are you sure you want to delete the following users?' ); ?></p>
219+       <form action="edit.php?action=dodeletesignup" method="post">
220+       <input type="hidden" name="dodeletesignup" />
221+       <?php
222+       wp_nonce_field( 'ms-signups-delete' );
223+       echo '<ul>';
224+       foreach ( $signups as $delete_signup ) {
225+               echo "<li><input type='hidden' name='user[]' value='{$delete_signup}'/>{$delete_signup}</li>\n";
226+       }
227+       echo '</ul>';
228+
229+       submit_button( __('Confirm Deletion'), 'delete' );
230+       ?>
231+       </form>
232+    <?php
233+       return true;
234+}
235+
236 function confirm_delete_users( $users ) {
237        $current_user = wp_get_current_user();
238        if ( !is_array( $users ) )
239@@ -421,6 +469,30 @@ switch ( $_GET['action'] ) {
240 
241                                                        update_user_status( $val, 'spam', '0', 1 );
242                                                break;
243+                                               
244+                                               case 'activate':
245+                                                       $userfunction = 'all_activate';
246+                                                       _wp_activate_by_user_login( $val );
247+                                               break;
248+                                               
249+                                               case 'resend':
250+                                                       $userfunction = 'all_resend';
251+                                                       _wp_resend_by_user_login( $val );
252+                                               break;
253+                                               
254+                                               case 'deletesignup':
255+                                                       if ( ! current_user_can( 'delete_users' ) )
256+                                                               wp_die( __( 'You do not have permission to access this page.' ) );
257+                                                               
258+                                                       $title = __( 'Users' );
259+                                                       $parent_file = 'users.php';
260+                                                       require_once( '../admin-header.php' );
261+                                                       echo '<div class="wrap">';
262+                                                       confirm_delete_signups( $_POST['allusers'] );
263+                                                       echo '</div>';
264+                                           require_once( '../admin-footer.php' );
265+                                           exit();
266+                                               break;
267                                        }
268                                }
269                        }
270@@ -467,6 +539,71 @@ switch ( $_GET['action'] ) {
271                wp_redirect( add_query_arg( array( 'updated' => 'true', 'action' => $deletefunction ), network_admin_url( 'users.php' ) ) );
272                exit();
273        break;
274+       
275+       case 'activatesignup':
276+               if ( ! current_user_can( 'manage_network_users' ) )
277+                       wp_die( __( 'You do not have permission to access this page.' ) );
278+
279+               check_admin_referer( 'activatesignup' );
280+               
281+               _wp_activate_by_user_login( $_GET['user_login'] );
282+               
283+               wp_redirect( add_query_arg( array( 'role' => 'pending', 'updated' => 'true', 'action' => 'activate' ), network_admin_url( 'users.php' ) ) );
284+               exit();
285+       break;
286+       
287+       case 'resendsignup':
288+               if ( ! current_user_can( 'manage_network_users' ) )
289+                       wp_die( __( 'You do not have permission to access this page.' ) );
290+
291+               check_admin_referer( 'resendsignup' );
292+               
293+               _wp_resend_by_user_login( $_GET['user_login'] );
294+       
295+               wp_redirect( add_query_arg( array( 'role' => 'pending', 'updated' => 'true', 'action' => 'resend' ), network_admin_url( 'users.php' ) ) );
296+               exit();
297+       break;
298+       
299+       case 'deletesignup':
300+               if ( ! current_user_can( 'manage_network_users' ) )
301+                       wp_die( __( 'You do not have permission to access this page.' ) );
302+
303+               check_admin_referer( 'deletesignup' );
304+               
305+               if ( ! empty( $_GET['user_login'] ) ) {
306+                       $title = __( 'Users' );
307+                       $parent_file = 'users.php';
308+                       require_once( '../admin-header.php' );
309+                       echo '<div class="wrap">';
310+                       confirm_delete_signups( array( $_GET['user_login'] ) );
311+                       echo '</div>';
312+            require_once( '../admin-footer.php' );
313+               } else {
314+                       wp_redirect( add_query_arg( array( 'role' => 'pending' ), network_admin_url( 'users.php' ) ) );
315+               }
316+               exit();
317+       break;
318+       
319+       case 'dodeletesignup':
320+               if ( ! ( current_user_can( 'manage_network_users' ) && current_user_can( 'delete_users' ) ) )
321+                       wp_die( __( 'You do not have permission to access this page.' ) );
322+
323+               check_admin_referer( 'ms-signups-delete' );
324+               
325+               if ( ! empty( $_POST['user'] ) ) {
326+                       array_walk( $_POST['user'], array( &$wpdb, 'escape_by_ref' ) );
327+                       $wpdb->query( "DELETE FROM {$wpdb->signups} WHERE active != 1 AND user_login IN ('" . implode( "','", $_POST['user'] ) . "')" );
328+               }
329+
330+               if ( count( $_POST['user'] ) > 1 ) {
331+                       $delete_action = 'all_delete';
332+               } else {
333+                       $delete_action = 'delete';
334+               }
335+
336+               wp_redirect( add_query_arg( array( 'role' => 'pending', 'updated' => 'true', 'action' => $delete_action ), network_admin_url( 'users.php' ) ) );
337+               exit();
338+       break;
339 
340        default:
341                // Let plugins use us as a post handler easily
342diff --git wp-admin/network/users.php wp-admin/network/users.php
343index 15853dd..87eb130 100644
344--- wp-admin/network/users.php
345+++ wp-admin/network/users.php
346@@ -58,6 +58,18 @@ if ( isset( $_REQUEST['updated'] ) && $_REQUEST['updated'] == 'true' && ! empty(
347                        case 'add':
348                                _e( 'User added.' );
349                        break;
350+                       case 'activate':
351+                               _e( 'User activated.' );
352+                       break;
353+                       case 'resend':
354+                               _e( 'Activation instruction resent to user.');
355+                       break;
356+                       case 'all_activate':
357+                               _e( 'Users activated.' );
358+                       break;
359+                       case 'all_resend':
360+                               _e( 'Activation instruction resent to users.');
361+                       break;
362                }
363                ?>
364        </p></div>
365diff --git wp-includes/ms-functions.php wp-includes/ms-functions.php
366index b3b21df..5622a56 100644
367--- wp-includes/ms-functions.php
368+++ wp-includes/ms-functions.php
369@@ -156,6 +156,19 @@ function get_user_count() {
370 }
371 
372 /**
373+ * The number of pending users in your installation.
374+ *
375+ * The count is cached and updated twice daily. This is not a live count.
376+ *
377+ * @since 3.2
378+ *
379+ * @return int
380+ */
381+function get_pending_user_count() {
382+       return get_site_option( 'pending_user_count' );
383+}
384+
385+/**
386  * The number of active sites on your installation.
387  *
388  * The count is cached and updated twice daily. This is not a live count.
389@@ -2067,6 +2080,9 @@ function wp_update_network_counts() {
390 
391        $count = $wpdb->get_var( $wpdb->prepare("SELECT COUNT(ID) as c FROM $wpdb->users WHERE spam = '0' AND deleted = '0'") );
392        update_site_option( 'user_count', $count );
393+       
394+       $count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(user_login) AS c FROM $wpdb->signups WHERE active != 1" ) );
395+       update_site_option( 'pending_user_count', $count );
396 }
397 
398 ?>
399\ No newline at end of file
400diff --git wp-includes/user.php wp-includes/user.php
401index c30f7be..5e792a6 100644
402--- wp-includes/user.php
403+++ wp-includes/user.php
404@@ -617,6 +617,87 @@ class WP_User_Query {
405        }
406 }
407 
408+class WP_Pending_User_Query extends WP_User_Query {
409+       function prepare_query() {
410+               global $wpdb;
411+
412+               $qv = &$this->query_vars;
413+               $this->query_fields = "{$wpdb->signups}.*";
414+
415+               $this->query_from = "FROM {$wpdb->signups}";
416+               $this->query_where = "WHERE 1=1 AND active != 1";
417+
418+               // sorting
419+               if ( in_array( $qv['orderby'], array( 'nicename', 'email' ) ) ) {
420+                       $orderby = 'user_' . $qv['orderby'];
421+               } elseif ( in_array( $qv['orderby'], array( 'user_email', 'registered' ) ) ) {
422+                       $orderby = $qv['orderby'];
423+               } else {
424+                       $orderby = 'user_login';
425+               }
426+
427+               $qv['order'] = strtoupper( $qv['order'] );
428+               if ( 'ASC' == $qv['order'] )
429+                       $order = 'ASC';
430+               else
431+                       $order = 'DESC';
432+               $this->query_orderby = "ORDER BY $orderby $order";
433+
434+               // limit
435+               if ( $qv['number'] ) {
436+                       if ( $qv['offset'] )
437+                               $this->query_limit = $wpdb->prepare("LIMIT %d, %d", $qv['offset'], $qv['number']);
438+                       else
439+                               $this->query_limit = $wpdb->prepare("LIMIT %d", $qv['number']);
440+               }
441+
442+               $search = trim( $qv['search'] );
443+               if ( $search ) {
444+                       $leading_wild = ( ltrim($search, '*') != $search );
445+                       $trailing_wild = ( rtrim($search, '*') != $search );
446+                       if ( $leading_wild && $trailing_wild )
447+                               $wild = 'both';
448+                       elseif ( $leading_wild )
449+                               $wild = 'leading';
450+                       elseif ( $trailing_wild )
451+                               $wild = 'trailing';
452+                       else
453+                               $wild = false;
454+                       if ( $wild )
455+                               $search = trim($search, '*');
456+
457+                       if ( false !== strpos( $search, '@') )
458+                               $search_columns = array('user_email');
459+                       else
460+                               $search_columns = array('user_login');
461+
462+                       $this->query_where .= $this->get_search_sql( $search, $search_columns, $wild );
463+               }
464+
465+               $blog_id = absint( $qv['blog_id'] );
466+
467+               do_action_ref_array( 'pre_user_query', array( &$this ) );
468+       }
469+       
470+       /**
471+        * Execute the query, with the current variables
472+        *
473+        * @since 3.2.0
474+        * @access private
475+        */
476+       function query() {
477+               global $wpdb;
478+               
479+               $this->results = $wpdb->get_results("SELECT $this->query_fields $this->query_from $this->query_where $this->query_orderby $this->query_limit");
480+
481+               if ( !$this->results )
482+                       return;
483+
484+               if ( $this->query_vars['count_total'] )
485+                       $this->total_users = $wpdb->get_var("SELECT COUNT(*) $this->query_from $this->query_where");
486+       }
487+}
488+
489 /**
490  * Retrieve list of users matching criteria.
491  *