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