1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* User account management - approval/block. |
4
|
|
|
* |
5
|
|
|
* @package user-approval |
6
|
|
|
*/ |
7
|
|
|
|
8
|
|
|
namespace User_Approval\Management; |
9
|
|
|
|
10
|
|
|
use function User_Approval\filter_input; |
11
|
|
|
use function User_Approval\get_default_user_role; |
12
|
|
|
use function User_Approval\get_pre_approved_user_roles; |
13
|
|
|
use function User_Approval\get_user_status; |
14
|
|
|
|
15
|
|
|
use WP_User; |
16
|
|
|
|
17
|
|
|
const APPROVE_STATUS_NONCE = 'aj-user-approve'; |
18
|
|
|
const BLOCKED_STATUS_NONCE = 'aj-user-blocked'; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* Hook up all the filters and actions. |
22
|
|
|
*/ |
23
|
|
|
function bootstrap() { |
24
|
1 |
|
add_action( 'manage_users_columns', __NAMESPACE__ . '\\user_verification_column', 1 ); |
25
|
|
|
|
26
|
1 |
|
add_filter( 'manage_users_custom_column', __NAMESPACE__ . '\\add_user_verification_status', 10, 3 ); |
27
|
1 |
|
add_filter( 'user_row_actions', __NAMESPACE__ . '\\add_user_verification_action', 10, 2 ); |
28
|
|
|
|
29
|
1 |
|
add_action( 'admin_action_aj_user_status', __NAMESPACE__ . '\\aj_user_status_update' ); |
30
|
|
|
|
31
|
1 |
|
add_filter( 'wp_new_user_notification_email', __NAMESPACE__ . '\\update_approved_new_user_email', 50, 3 ); |
32
|
|
|
|
33
|
1 |
|
add_filter( 'manage_users_extra_tablenav', __NAMESPACE__ . '\\add_user_status_filters', 10 ); |
34
|
1 |
|
add_filter( 'users_list_table_query_args', __NAMESPACE__ . '\\filter_user_list_by_status', 100 ); |
35
|
|
|
|
36
|
1 |
|
} |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* Add new column for users list page for user status. |
40
|
|
|
* |
41
|
|
|
* @param array $columns Columns list of user data. |
42
|
|
|
* |
43
|
|
|
* @return array |
44
|
|
|
*/ |
45
|
|
|
function user_verification_column( $columns ) { |
46
|
|
|
|
47
|
1 |
|
$columns['aj_user_status'] = esc_html__( 'Status', 'user-approval' ); |
48
|
|
|
|
49
|
1 |
|
return $columns; |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* Add a user status to status column of respective user row. |
54
|
|
|
* |
55
|
|
|
* @param string $val Default value of column. |
56
|
|
|
* @param string $column_name Column id/name. |
57
|
|
|
* @param int $user_id User id of respective user row. |
58
|
|
|
* |
59
|
|
|
* @return array|string |
60
|
|
|
*/ |
61
|
|
|
function add_user_verification_status( $val, $column_name, $user_id ) { |
62
|
|
|
|
63
|
2 |
|
if ( 'aj_user_status' !== $column_name ) { |
64
|
|
|
return $val; |
65
|
|
|
} |
66
|
|
|
|
67
|
2 |
|
$user_status = get_user_meta( $user_id, 'aj_user_status', true ) ?: 'pending'; |
68
|
2 |
|
$user = get_userdata( $user_id ); |
69
|
2 |
|
$user_status = ( ! empty( $user ) && in_array( get_default_user_role(), $user->roles, true ) ) ? $user_status : 'pre-approved'; |
70
|
|
|
|
71
|
2 |
|
return get_user_status( $user_status ); |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* Add action links to respective user row to approve/block the user. |
76
|
|
|
* |
77
|
|
|
* @param array $actions All action link lists. |
78
|
|
|
* @param WP_User $user WP_User object for respective user row. |
79
|
|
|
* |
80
|
|
|
* @return array |
81
|
|
|
*/ |
82
|
|
|
function add_user_verification_action( $actions, $user ) { |
83
|
|
|
|
84
|
1 |
|
if ( ! in_array( get_default_user_role(), $user->roles, true ) ) { |
85
|
1 |
|
return $actions; |
86
|
|
|
} |
87
|
|
|
|
88
|
1 |
|
$user_current_status = get_user_meta( $user->ID, 'aj_user_status', true ); |
89
|
|
|
|
90
|
|
|
$query_args = [ |
91
|
1 |
|
'user' => $user->ID, |
92
|
1 |
|
'action' => 'aj_user_status', |
93
|
1 |
|
'status' => 'approve', |
94
|
|
|
]; |
95
|
|
|
|
96
|
|
|
// Approve action link. |
97
|
1 |
|
$approve_link = add_query_arg( $query_args ); |
98
|
1 |
|
$approve_link = remove_query_arg( [ 'new_role' ], $approve_link ); |
99
|
1 |
|
$approve_link = wp_nonce_url( $approve_link, APPROVE_STATUS_NONCE ); |
100
|
|
|
|
101
|
1 |
|
$query_args['status'] = 'block'; |
102
|
|
|
|
103
|
|
|
// Block action link. |
104
|
1 |
|
$block_link = add_query_arg( $query_args ); |
105
|
1 |
|
$block_link = remove_query_arg( [ 'new_role' ], $block_link ); |
106
|
1 |
|
$block_link = wp_nonce_url( $block_link, BLOCKED_STATUS_NONCE ); |
107
|
|
|
|
108
|
1 |
|
$approve_action = sprintf( |
109
|
1 |
|
'<a href="%s">%s</a>', |
110
|
1 |
|
esc_url( $approve_link ), |
111
|
1 |
|
get_user_status( 'approved' ) |
|
|
|
|
112
|
|
|
); |
113
|
|
|
|
114
|
1 |
|
$block_action = sprintf( |
115
|
1 |
|
'<a href="%s">%s</a>', |
116
|
1 |
|
esc_url( $block_link ), |
117
|
1 |
|
get_user_status( 'blocked' ) |
118
|
|
|
); |
119
|
|
|
|
120
|
1 |
|
$actions = array_merge( $actions, [ |
121
|
1 |
|
'approved' => $approve_action, |
122
|
1 |
|
'blocked' => $block_action, |
123
|
|
|
] ); |
124
|
|
|
|
125
|
1 |
|
if ( isset( $actions[ $user_current_status ] ) ) { |
126
|
1 |
|
unset( $actions[ $user_current_status ] ); |
127
|
|
|
} |
128
|
|
|
|
129
|
1 |
|
return $actions; |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* Update user status on post request. |
134
|
|
|
*/ |
135
|
|
|
function aj_user_status_update() { |
136
|
1 |
|
$user_id = filter_input( INPUT_GET, 'user', FILTER_VALIDATE_INT ); |
137
|
1 |
|
$status = filter_input( INPUT_GET, 'status', FILTER_SANITIZE_STRING ); |
138
|
|
|
|
139
|
1 |
|
$user = get_userdata( $user_id ); |
|
|
|
|
140
|
1 |
|
$user_status = get_user_meta( $user_id, 'aj_user_status', true ); |
|
|
|
|
141
|
|
|
|
142
|
|
|
if ( |
143
|
1 |
|
! $user instanceof WP_User |
144
|
1 |
|
|| ! in_array( get_default_user_role(), $user->roles, true ) |
145
|
1 |
|
|| ( $status === $user_status ) // Avoid any refresh page. |
146
|
1 |
|
|| ! current_user_can( 'list_users' ) |
147
|
|
|
) { |
148
|
|
|
return; |
149
|
|
|
} |
150
|
|
|
|
151
|
1 |
|
$current_user_id = get_current_user_id(); |
152
|
|
|
|
153
|
1 |
|
if ( 'approve' === $status && check_admin_referer( APPROVE_STATUS_NONCE ) ) { |
154
|
1 |
|
update_user_meta( $user_id, 'aj_user_status', 'approved' ); |
155
|
1 |
|
wp_send_new_user_notifications( $user_id, 'user' ); |
156
|
1 |
|
update_user_meta( $user_id, 'aj_user_verified_by', $current_user_id ); |
157
|
1 |
|
} elseif ( 'block' === $status && check_admin_referer( BLOCKED_STATUS_NONCE ) ) { |
158
|
1 |
|
update_user_meta( $user_id, 'aj_user_status', 'blocked' ); |
159
|
1 |
|
send_user_blocked_email( $user ); |
160
|
1 |
|
update_user_meta( $user_id, 'aj_user_verified_by', $current_user_id ); |
161
|
|
|
} |
162
|
1 |
|
} |
163
|
|
|
|
164
|
|
|
/** |
165
|
|
|
* Send a notification/email to approved user. |
166
|
|
|
* |
167
|
|
|
* @param array $email_data { |
168
|
|
|
* Used to build wp_mail(). |
169
|
|
|
* |
170
|
|
|
* @type string $to The intended recipient - New user email address. |
171
|
|
|
* @type string $subject The subject of the email. |
172
|
|
|
* @type string $message The body of the email. |
173
|
|
|
* @type string $headers The headers of the email. |
174
|
|
|
* } |
175
|
|
|
* @param WP_User $user User object for new user. |
176
|
|
|
* @param string $blogname The site title. |
177
|
|
|
* |
178
|
|
|
* @return array Updated email data for wp_mail. |
179
|
|
|
*/ |
180
|
|
|
function update_approved_new_user_email( $email_data, $user, $blogname ) { |
181
|
|
|
|
182
|
1 |
|
if ( empty( $user ) || ! in_array( get_default_user_role(), $user->roles, true ) ) { |
183
|
|
|
return $email_data; |
184
|
|
|
} |
185
|
|
|
|
186
|
1 |
|
$message = sprintf( |
187
|
|
|
/* translators: %s: User login. */ |
188
|
1 |
|
esc_html__( 'You have been approved to access %s', 'user-approval' ), |
189
|
|
|
$blogname |
190
|
|
|
); |
191
|
1 |
|
$message .= "\r\n\r\n"; |
192
|
1 |
|
$message .= $email_data['message']; |
193
|
|
|
|
194
|
|
|
/* translators: Login details notification email subject. %s: Site title. */ |
195
|
1 |
|
$email_data['subject'] = esc_html__( '[%s] Login Details [Account Approved]', 'user-approval' ); |
196
|
1 |
|
$email_data['message'] = $message; |
197
|
|
|
|
198
|
1 |
|
return apply_filters( 'user_approval_approved_user_email_data', $email_data ); |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
/** |
202
|
|
|
* Send a notification/email to blocked user. |
203
|
|
|
* |
204
|
|
|
* @param WP_User $user WP_User object. |
205
|
|
|
*/ |
206
|
|
|
function send_user_blocked_email( $user ) { |
207
|
1 |
|
$blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ); |
|
|
|
|
208
|
|
|
|
209
|
1 |
|
$message = sprintf( |
210
|
|
|
/* translators: %s: Site title. */ |
211
|
1 |
|
esc_html__( 'You have been denied access to %s.', 'user-approval' ), |
212
|
|
|
$blogname |
213
|
|
|
); |
214
|
|
|
|
215
|
1 |
|
$subject = sprintf( |
216
|
|
|
/* translators: %s: Site title. */ |
217
|
1 |
|
esc_html__( '[%s] Account Blocked.', 'user-approval' ), |
218
|
|
|
$blogname |
219
|
|
|
); |
220
|
|
|
|
221
|
|
|
$email_data = [ |
222
|
1 |
|
'to' => $user->user_email, |
223
|
1 |
|
'subject' => $subject, |
224
|
1 |
|
'message' => $message, |
225
|
1 |
|
'headers' => '', |
226
|
|
|
]; |
227
|
|
|
|
228
|
1 |
|
$email_data = apply_filters( 'user_approval_blocked_user_email_data', $email_data ); |
229
|
|
|
|
230
|
|
|
// phpcs:ignore WordPressVIPMinimum.VIP.RestrictedFunctions.wp_mail_wp_mail, WordPressVIPMinimum.Functions.RestrictedFunctions.wp_mail_wp_mail |
231
|
1 |
|
wp_mail( |
232
|
1 |
|
$email_data['to'], |
233
|
1 |
|
wp_specialchars_decode( $email_data['subject'] ), |
234
|
1 |
|
$email_data['message'], |
235
|
1 |
|
$email_data['headers'] |
236
|
|
|
); |
237
|
1 |
|
} |
238
|
|
|
|
239
|
|
|
/** |
240
|
|
|
* Add a filter to list users based on user status. |
241
|
|
|
* |
242
|
|
|
* @param string $which The location of the extra table nav markup: 'top' or 'bottom'. |
243
|
|
|
*/ |
244
|
|
|
function add_user_status_filters( $which ) { |
245
|
|
|
|
246
|
1 |
|
if ( 'top' !== $which ) { |
247
|
1 |
|
return; |
248
|
|
|
} |
249
|
|
|
|
250
|
1 |
|
$status = filter_input( INPUT_GET, 'user_status', FILTER_SANITIZE_STRING ); |
251
|
1 |
|
$all_user_status = get_user_status( 'all' ); |
252
|
|
|
|
253
|
|
|
?> |
254
|
1 |
|
<div class="alignleft actions"> |
255
|
|
|
<label for="filter-by-date" class="screen-reader-text">Filter by user status</label> |
256
|
|
|
<select name="user_status" id="filter-by-user-status"> |
257
|
|
|
<?php |
258
|
1 |
|
printf( |
259
|
1 |
|
'<option %s value="%s">%s</option>', |
260
|
1 |
|
( 'all' === $status ) ? esc_html( 'selected="selected"' ) : '', |
261
|
1 |
|
esc_attr( 'all' ), |
262
|
1 |
|
esc_html__( 'All', 'user-approval' ) |
263
|
|
|
); |
264
|
1 |
|
foreach ( $all_user_status as $value => $label ) { |
265
|
|
|
|
266
|
1 |
|
printf( |
267
|
1 |
|
'<option %s value="%s">%s</option>', |
268
|
1 |
|
( $value === $status ) ? esc_html( 'selected="selected"' ) : '', |
269
|
1 |
|
esc_attr( $value ), |
270
|
1 |
|
esc_html( $label ) |
271
|
|
|
); |
272
|
|
|
} |
273
|
|
|
?> |
274
|
1 |
|
</select> |
275
|
|
|
<button type="submit" name="filter_action" class="button">Filter</button> |
276
|
|
|
</div> |
277
|
|
|
<?php |
278
|
1 |
|
} |
279
|
|
|
|
280
|
|
|
/** |
281
|
|
|
* Filter user list in WP Admin filter by user status. |
282
|
|
|
* |
283
|
|
|
* @param array $args Arguments passed to WP_User_Query to retrieve items for the current |
284
|
|
|
* users list table. |
285
|
|
|
* |
286
|
|
|
* @return array |
287
|
|
|
*/ |
288
|
|
|
function filter_user_list_by_status( $args ) { |
289
|
|
|
|
290
|
1 |
|
$current_screen = get_current_screen(); |
|
|
|
|
291
|
|
|
|
292
|
1 |
|
$status = filter_input( INPUT_GET, 'user_status', FILTER_SANITIZE_STRING ); |
293
|
|
|
|
294
|
|
|
if ( |
295
|
1 |
|
! is_admin() |
296
|
1 |
|
|| empty( $current_screen ) |
297
|
1 |
|
|| 'users' !== $current_screen->id |
298
|
1 |
|
|| empty( $status ) |
299
|
1 |
|
|| is_array( get_user_status( $status ) ) |
300
|
|
|
) { |
301
|
1 |
|
return $args; |
302
|
|
|
} |
303
|
|
|
|
304
|
1 |
|
if ( in_array( $status, [ 'blocked', 'approved' ], true ) ) { |
305
|
1 |
|
$args['meta_key'] = 'aj_user_status'; // phpcs:ignore WordPress.VIP.SlowDBQuery.slow_db_query_meta_key |
306
|
1 |
|
$args['meta_value'] = $status; // phpcs:ignore WordPress.VIP.SlowDBQuery.slow_db_query_meta_value, WordPress.DB.SlowDBQuery.slow_db_query_meta_value |
307
|
1 |
|
} elseif ( 'pending' === $status ) { |
308
|
1 |
|
$args['role'] = get_default_user_role(); |
309
|
1 |
|
$args['meta_key'] = 'aj_user_status'; // phpcs:ignore WordPress.VIP.SlowDBQuery.slow_db_query_meta_key |
310
|
1 |
|
$args['meta_compare'] = 'NOT EXISTS'; |
311
|
|
|
} else { |
312
|
1 |
|
$user_roles_data = get_pre_approved_user_roles(); |
313
|
|
|
|
314
|
1 |
|
if ( ! empty( $user_roles_data ) ) { |
315
|
1 |
|
$args['role__in'] = array_keys( $user_roles_data ); |
316
|
|
|
} |
317
|
|
|
} |
318
|
|
|
|
319
|
1 |
|
return $args; |
320
|
|
|
} |
321
|
|
|
|