1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* Show a list of members or a selection of members. |
5
|
|
|
* |
6
|
|
|
* Simple Machines Forum (SMF) |
7
|
|
|
* |
8
|
|
|
* @package SMF |
9
|
|
|
* @author Simple Machines http://www.simplemachines.org |
10
|
|
|
* @copyright 2018 Simple Machines and individual contributors |
11
|
|
|
* @license http://www.simplemachines.org/about/smf/license.php BSD |
12
|
|
|
* |
13
|
|
|
* @version 2.1 Beta 4 |
14
|
|
|
*/ |
15
|
|
|
|
16
|
|
|
if (!defined('SMF')) |
17
|
|
|
die('No direct access...'); |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* The main entrance point for the Manage Members screen. |
21
|
|
|
* As everyone else, it calls a function based on the given sub-action. |
22
|
|
|
* Called by ?action=admin;area=viewmembers. |
23
|
|
|
* Requires the moderate_forum permission. |
24
|
|
|
* |
25
|
|
|
* @uses ManageMembers template |
26
|
|
|
* @uses ManageMembers language file. |
27
|
|
|
*/ |
28
|
|
|
function ViewMembers() |
29
|
|
|
{ |
30
|
|
|
global $txt, $scripturl, $context, $modSettings, $smcFunc; |
31
|
|
|
|
32
|
|
|
$subActions = array( |
33
|
|
|
'all' => array('ViewMemberlist', 'moderate_forum'), |
34
|
|
|
'approve' => array('AdminApprove', 'moderate_forum'), |
35
|
|
|
'browse' => array('MembersAwaitingActivation', 'moderate_forum'), |
36
|
|
|
'search' => array('SearchMembers', 'moderate_forum'), |
37
|
|
|
'query' => array('ViewMemberlist', 'moderate_forum'), |
38
|
|
|
); |
39
|
|
|
|
40
|
|
|
// Default to sub action 'index' or 'settings' depending on permissions. |
41
|
|
|
$context['current_subaction'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : 'all'; |
42
|
|
|
|
43
|
|
|
// Load the essentials. |
44
|
|
|
loadLanguage('ManageMembers'); |
45
|
|
|
loadTemplate('ManageMembers'); |
46
|
|
|
|
47
|
|
|
// Fetch our activation counts. |
48
|
|
|
GetMemberActivationCounts(); |
49
|
|
|
|
50
|
|
|
// For the page header... do we show activation? |
51
|
|
|
$context['show_activate'] = (!empty($modSettings['registration_method']) && $modSettings['registration_method'] == 1) || !empty($context['awaiting_activation']); |
52
|
|
|
|
53
|
|
|
// What about approval? |
54
|
|
|
$context['show_approve'] = (!empty($modSettings['registration_method']) && $modSettings['registration_method'] == 2) || !empty($context['awaiting_approval']) || !empty($modSettings['approveAccountDeletion']); |
55
|
|
|
|
56
|
|
|
// Setup the admin tabs. |
57
|
|
|
$context[$context['admin_menu_name']]['tab_data'] = array( |
58
|
|
|
'title' => $txt['admin_members'], |
59
|
|
|
'help' => 'view_members', |
60
|
|
|
'description' => $txt['admin_members_list'], |
61
|
|
|
'tabs' => array(), |
62
|
|
|
); |
63
|
|
|
|
64
|
|
|
$context['tabs'] = array( |
65
|
|
|
'viewmembers' => array( |
66
|
|
|
'label' => $txt['view_all_members'], |
67
|
|
|
'description' => $txt['admin_members_list'], |
68
|
|
|
'url' => $scripturl . '?action=admin;area=viewmembers;sa=all', |
69
|
|
|
'selected_actions' => array('all'), |
70
|
|
|
), |
71
|
|
|
'search' => array( |
72
|
|
|
'label' => $txt['mlist_search'], |
73
|
|
|
'description' => $txt['admin_members_list'], |
74
|
|
|
'url' => $scripturl . '?action=admin;area=viewmembers;sa=search', |
75
|
|
|
'selected_actions' => array('search', 'query'), |
76
|
|
|
), |
77
|
|
|
); |
78
|
|
|
$context['last_tab'] = 'search'; |
79
|
|
|
|
80
|
|
|
// Do we have approvals |
81
|
|
|
if ($context['show_approve']) |
82
|
|
|
{ |
83
|
|
|
$context['tabs']['approve'] = array( |
84
|
|
|
'label' => sprintf($txt['admin_browse_awaiting_approval'], $context['awaiting_approval']), |
85
|
|
|
'description' => $txt['admin_browse_approve_desc'], |
86
|
|
|
'url' => $scripturl . '?action=admin;area=viewmembers;sa=browse;type=approve', |
87
|
|
|
); |
88
|
|
|
$context['last_tab'] = 'approve'; |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
// Do we have activations to show? |
92
|
|
|
if ($context['show_activate']) |
93
|
|
|
{ |
94
|
|
|
$context['tabs']['activate'] = array( |
95
|
|
|
'label' => sprintf($txt['admin_browse_awaiting_activate'], $context['awaiting_activation']), |
96
|
|
|
'description' => $txt['admin_browse_activate_desc'], |
97
|
|
|
'url' => $scripturl . '?action=admin;area=viewmembers;sa=browse;type=activate', |
98
|
|
|
); |
99
|
|
|
$context['last_tab'] = 'activate'; |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
// Call our hook now, letting customizations add to the subActions and/or modify $context as needed. |
103
|
|
|
call_integration_hook('integrate_manage_members', array(&$subActions)); |
104
|
|
|
|
105
|
|
|
// We know the sub action, now we know what you're allowed to do. |
106
|
|
|
isAllowedTo($subActions[$context['current_subaction']][1]); |
107
|
|
|
|
108
|
|
|
// Set the last tab. |
109
|
|
|
$context['tabs'][$context['last_tab']]['is_last'] = true; |
110
|
|
|
|
111
|
|
|
// Find the active tab. |
112
|
|
|
if (isset($context['tabs'][$context['current_subaction']])) |
113
|
|
|
$context['tabs'][$context['current_subaction']]['is_selected'] = true; |
114
|
|
|
elseif (isset($context['current_subaction'])) |
115
|
|
|
foreach ($context['tabs'] as $id_tab => $tab_data) |
116
|
|
|
if (!empty($tab_data['selected_actions']) && in_array($context['current_subaction'], $tab_data['selected_actions'])) |
117
|
|
|
$context['tabs'][$id_tab]['is_selected'] = true; |
118
|
|
|
|
119
|
|
|
call_helper($subActions[$context['current_subaction']][0]); |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* View all members list. It allows sorting on several columns, and deletion of |
124
|
|
|
* selected members. It also handles the search query sent by |
125
|
|
|
* ?action=admin;area=viewmembers;sa=search. |
126
|
|
|
* Called by ?action=admin;area=viewmembers;sa=all or ?action=admin;area=viewmembers;sa=query. |
127
|
|
|
* Requires the moderate_forum permission. |
128
|
|
|
* |
129
|
|
|
* @uses the view_members sub template of the ManageMembers template. |
130
|
|
|
*/ |
131
|
|
|
function ViewMemberlist() |
132
|
|
|
{ |
133
|
|
|
global $txt, $scripturl, $context, $modSettings, $sourcedir, $smcFunc, $user_info; |
134
|
|
|
|
135
|
|
|
// Set the current sub action. |
136
|
|
|
$context['sub_action'] = $_REQUEST['sa']; |
137
|
|
|
|
138
|
|
|
// Are we performing a delete? |
139
|
|
|
if (isset($_POST['delete_members']) && !empty($_POST['delete']) && allowedTo('profile_remove_any')) |
140
|
|
|
{ |
141
|
|
|
checkSession(); |
142
|
|
|
|
143
|
|
|
// Clean the input. |
144
|
|
|
foreach ($_POST['delete'] as $key => $value) |
145
|
|
|
{ |
146
|
|
|
// Don't delete yourself, idiot. |
147
|
|
|
if ($value != $user_info['id']) |
148
|
|
|
$delete[$key] = (int) $value; |
|
|
|
|
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
if (!empty($delete)) |
152
|
|
|
{ |
153
|
|
|
// Delete all the selected members. |
154
|
|
|
require_once($sourcedir . '/Subs-Members.php'); |
155
|
|
|
deleteMembers($delete, true); |
156
|
|
|
} |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
// Check input after a member search has been submitted. |
160
|
|
|
if ($context['sub_action'] == 'query') |
161
|
|
|
{ |
162
|
|
|
// Retrieving the membergroups and postgroups. |
163
|
|
|
$context['membergroups'] = array( |
164
|
|
|
array( |
165
|
|
|
'id' => 0, |
166
|
|
|
'name' => $txt['membergroups_members'], |
167
|
|
|
'can_be_additional' => false |
168
|
|
|
) |
169
|
|
|
); |
170
|
|
|
$context['postgroups'] = array(); |
171
|
|
|
|
172
|
|
|
$request = $smcFunc['db_query']('', ' |
173
|
|
|
SELECT id_group, group_name, min_posts |
174
|
|
|
FROM {db_prefix}membergroups |
175
|
|
|
WHERE id_group != {int:moderator_group} |
176
|
|
|
ORDER BY min_posts, CASE WHEN id_group < {int:newbie_group} THEN id_group ELSE 4 END, group_name', |
177
|
|
|
array( |
178
|
|
|
'moderator_group' => 3, |
179
|
|
|
'newbie_group' => 4, |
180
|
|
|
) |
181
|
|
|
); |
182
|
|
View Code Duplication |
while ($row = $smcFunc['db_fetch_assoc']($request)) |
183
|
|
|
{ |
184
|
|
|
if ($row['min_posts'] == -1) |
185
|
|
|
$context['membergroups'][] = array( |
186
|
|
|
'id' => $row['id_group'], |
187
|
|
|
'name' => $row['group_name'], |
188
|
|
|
'can_be_additional' => true |
189
|
|
|
); |
190
|
|
|
else |
191
|
|
|
$context['postgroups'][] = array( |
192
|
|
|
'id' => $row['id_group'], |
193
|
|
|
'name' => $row['group_name'] |
194
|
|
|
); |
195
|
|
|
} |
196
|
|
|
$smcFunc['db_free_result']($request); |
197
|
|
|
|
198
|
|
|
// Some data about the form fields and how they are linked to the database. |
199
|
|
|
$params = array( |
200
|
|
|
'mem_id' => array( |
201
|
|
|
'db_fields' => array('id_member'), |
202
|
|
|
'type' => 'int', |
203
|
|
|
'range' => true |
204
|
|
|
), |
205
|
|
|
'age' => array( |
206
|
|
|
'db_fields' => array('birthdate'), |
207
|
|
|
'type' => 'age', |
208
|
|
|
'range' => true |
209
|
|
|
), |
210
|
|
|
'posts' => array( |
211
|
|
|
'db_fields' => array('posts'), |
212
|
|
|
'type' => 'int', |
213
|
|
|
'range' => true |
214
|
|
|
), |
215
|
|
|
'reg_date' => array( |
216
|
|
|
'db_fields' => array('date_registered'), |
217
|
|
|
'type' => 'date', |
218
|
|
|
'range' => true |
219
|
|
|
), |
220
|
|
|
'last_online' => array( |
221
|
|
|
'db_fields' => array('last_login'), |
222
|
|
|
'type' => 'date', |
223
|
|
|
'range' => true |
224
|
|
|
), |
225
|
|
|
'activated' => array( |
226
|
|
|
'db_fields' => array('CASE WHEN is_activated IN (1, 11) THEN 1 ELSE 0 END'), |
227
|
|
|
'type' => 'checkbox', |
228
|
|
|
'values' => array('0', '1'), |
229
|
|
|
), |
230
|
|
|
'membername' => array( |
231
|
|
|
'db_fields' => array('member_name', 'real_name'), |
232
|
|
|
'type' => 'string' |
233
|
|
|
), |
234
|
|
|
'email' => array( |
235
|
|
|
'db_fields' => array('email_address'), |
236
|
|
|
'type' => 'string' |
237
|
|
|
), |
238
|
|
|
'website' => array( |
239
|
|
|
'db_fields' => array('website_title', 'website_url'), |
240
|
|
|
'type' => 'string' |
241
|
|
|
), |
242
|
|
|
'ip' => array( |
243
|
|
|
'db_fields' => array('member_ip'), |
244
|
|
|
'type' => 'inet' |
245
|
|
|
), |
246
|
|
|
'membergroups' => array( |
247
|
|
|
'db_fields' => array('id_group'), |
248
|
|
|
'type' => 'groups' |
249
|
|
|
), |
250
|
|
|
'postgroups' => array( |
251
|
|
|
'db_fields' => array('id_group'), |
252
|
|
|
'type' => 'groups' |
253
|
|
|
) |
254
|
|
|
); |
255
|
|
|
$range_trans = array( |
256
|
|
|
'--' => '<', |
257
|
|
|
'-' => '<=', |
258
|
|
|
'=' => '=', |
259
|
|
|
'+' => '>=', |
260
|
|
|
'++' => '>' |
261
|
|
|
); |
262
|
|
|
|
263
|
|
|
call_integration_hook('integrate_view_members_params', array(&$params)); |
264
|
|
|
|
265
|
|
|
$search_params = array(); |
266
|
|
|
if ($context['sub_action'] == 'query' && !empty($_REQUEST['params']) && empty($_POST['types'])) |
267
|
|
|
$search_params = $smcFunc['json_decode'](base64_decode($_REQUEST['params']), true); |
268
|
|
|
elseif (!empty($_POST)) |
269
|
|
|
{ |
270
|
|
|
$search_params['types'] = $_POST['types']; |
271
|
|
|
foreach ($params as $param_name => $param_info) |
272
|
|
|
if (isset($_POST[$param_name])) |
273
|
|
|
$search_params[$param_name] = $_POST[$param_name]; |
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
$search_url_params = isset($search_params) ? base64_encode($smcFunc['json_encode']($search_params)) : null; |
277
|
|
|
|
278
|
|
|
// @todo Validate a little more. |
279
|
|
|
|
280
|
|
|
// Loop through every field of the form. |
281
|
|
|
$query_parts = array(); |
282
|
|
|
$where_params = array(); |
283
|
|
|
foreach ($params as $param_name => $param_info) |
284
|
|
|
{ |
285
|
|
|
// Not filled in? |
286
|
|
|
if (!isset($search_params[$param_name]) || $search_params[$param_name] === '') |
287
|
|
|
continue; |
288
|
|
|
|
289
|
|
|
// Make sure numeric values are really numeric. |
290
|
|
|
if (in_array($param_info['type'], array('int', 'age'))) |
291
|
|
|
$search_params[$param_name] = (int) $search_params[$param_name]; |
292
|
|
|
// Date values have to match the specified format. |
293
|
|
View Code Duplication |
elseif ($param_info['type'] == 'date') |
294
|
|
|
{ |
295
|
|
|
// Check if this date format is valid. |
296
|
|
|
if (preg_match('/^\d{4}-\d{1,2}-\d{1,2}$/', $search_params[$param_name]) == 0) |
297
|
|
|
continue; |
298
|
|
|
|
299
|
|
|
$search_params[$param_name] = strtotime($search_params[$param_name]); |
300
|
|
|
} |
301
|
|
View Code Duplication |
elseif ($param_info['type'] == 'inet') |
302
|
|
|
{ |
303
|
|
|
$search_params[$param_name] = ip2range($search_params[$param_name]); |
304
|
|
|
if (empty($search_params[$param_name])) |
305
|
|
|
continue; |
306
|
|
|
} |
307
|
|
|
|
308
|
|
|
// Those values that are in some kind of range (<, <=, =, >=, >). |
309
|
|
|
if (!empty($param_info['range'])) |
310
|
|
|
{ |
311
|
|
|
// Default to '=', just in case... |
312
|
|
|
if (empty($range_trans[$search_params['types'][$param_name]])) |
313
|
|
|
$search_params['types'][$param_name] = '='; |
314
|
|
|
|
315
|
|
|
// Handle special case 'age'. |
316
|
|
|
if ($param_info['type'] == 'age') |
317
|
|
|
{ |
318
|
|
|
// All people that were born between $lowerlimit and $upperlimit are currently the specified age. |
319
|
|
|
$datearray = getdate(forum_time()); |
320
|
|
|
$upperlimit = sprintf('%04d-%02d-%02d', $datearray['year'] - $search_params[$param_name], $datearray['mon'], $datearray['mday']); |
321
|
|
|
$lowerlimit = sprintf('%04d-%02d-%02d', $datearray['year'] - $search_params[$param_name] - 1, $datearray['mon'], $datearray['mday']); |
322
|
|
|
if (in_array($search_params['types'][$param_name], array('-', '--', '='))) |
323
|
|
|
{ |
324
|
|
|
$query_parts[] = ($param_info['db_fields'][0]) . ' > {string:' . $param_name . '_minlimit}'; |
325
|
|
|
$where_params[$param_name . '_minlimit'] = ($search_params['types'][$param_name] == '--' ? $upperlimit : $lowerlimit); |
326
|
|
|
} |
327
|
|
|
if (in_array($search_params['types'][$param_name], array('+', '++', '='))) |
328
|
|
|
{ |
329
|
|
|
$query_parts[] = ($param_info['db_fields'][0]) . ' <= {string:' . $param_name . '_pluslimit}'; |
330
|
|
|
$where_params[$param_name . '_pluslimit'] = ($search_params['types'][$param_name] == '++' ? $lowerlimit : $upperlimit); |
331
|
|
|
|
332
|
|
|
// Make sure that members that didn't set their birth year are not queried. |
333
|
|
|
$query_parts[] = ($param_info['db_fields'][0]) . ' > {date:dec_zero_date}'; |
334
|
|
|
$where_params['dec_zero_date'] = '0004-12-31'; |
335
|
|
|
} |
336
|
|
|
} |
337
|
|
|
// Special case - equals a date. |
338
|
|
|
elseif ($param_info['type'] == 'date' && $search_params['types'][$param_name] == '=') |
339
|
|
|
{ |
340
|
|
|
$query_parts[] = $param_info['db_fields'][0] . ' > ' . $search_params[$param_name] . ' AND ' . $param_info['db_fields'][0] . ' < ' . ($search_params[$param_name] + 86400); |
341
|
|
|
} |
342
|
|
|
else |
343
|
|
|
$query_parts[] = $param_info['db_fields'][0] . ' ' . $range_trans[$search_params['types'][$param_name]] . ' ' . $search_params[$param_name]; |
344
|
|
|
} |
345
|
|
|
// Checkboxes. |
346
|
|
|
elseif ($param_info['type'] == 'checkbox') |
347
|
|
|
{ |
348
|
|
|
// Each checkbox or no checkbox at all is checked -> ignore. |
349
|
|
|
if (!is_array($search_params[$param_name]) || count($search_params[$param_name]) == 0 || count($search_params[$param_name]) == count($param_info['values'])) |
350
|
|
|
continue; |
351
|
|
|
|
352
|
|
|
$query_parts[] = ($param_info['db_fields'][0]) . ' IN ({array_string:' . $param_name . '_check})'; |
353
|
|
|
$where_params[$param_name . '_check'] = $search_params[$param_name]; |
354
|
|
|
} |
355
|
|
|
// INET. |
356
|
|
|
elseif ($param_info['type'] == 'inet') |
357
|
|
|
{ |
358
|
|
|
if(count($search_params[$param_name]) === 1) |
359
|
|
|
{ |
360
|
|
|
$query_parts[] = '(' . $param_info['db_fields'][0] . ' = {inet:' . $param_name . '})'; |
361
|
|
|
$where_params[$param_name] = $search_params[$param_name][0]; |
362
|
|
|
} |
363
|
|
|
elseif (count($search_params[$param_name]) === 2) |
364
|
|
|
{ |
365
|
|
|
$query_parts[] = '(' . $param_info['db_fields'][0] . ' <= {inet:' . $param_name . '_high} and ' . $param_info['db_fields'][0] . ' >= {inet:' . $param_name . '_low})'; |
366
|
|
|
$where_params[$param_name.'_low'] = $search_params[$param_name]['low']; |
367
|
|
|
$where_params[$param_name.'_high'] = $search_params[$param_name]['high']; |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
} |
371
|
|
|
elseif ($param_info['type'] != 'groups') |
372
|
|
|
{ |
373
|
|
|
// Replace the wildcard characters ('*' and '?') into MySQL ones. |
374
|
|
|
$parameter = strtolower(strtr($smcFunc['htmlspecialchars']($search_params[$param_name], ENT_QUOTES), array('%' => '\%', '_' => '\_', '*' => '%', '?' => '_'))); |
375
|
|
|
|
376
|
|
|
if ($smcFunc['db_case_sensitive']) |
377
|
|
|
$query_parts[] = '(LOWER(' . implode(') LIKE {string:' . $param_name . '_normal} OR LOWER(', $param_info['db_fields']) . ') LIKE {string:' . $param_name . '_normal})'; |
378
|
|
|
else |
379
|
|
|
$query_parts[] = '(' . implode(' LIKE {string:' . $param_name . '_normal} OR ', $param_info['db_fields']) . ' LIKE {string:' . $param_name . '_normal})'; |
380
|
|
|
$where_params[$param_name . '_normal'] = '%' . $parameter . '%'; |
381
|
|
|
} |
382
|
|
|
} |
383
|
|
|
|
384
|
|
|
// Set up the membergroup query part. |
385
|
|
|
$mg_query_parts = array(); |
386
|
|
|
|
387
|
|
|
// Primary membergroups, but only if at least was was not selected. |
388
|
|
|
if (!empty($search_params['membergroups'][1]) && count($context['membergroups']) != count($search_params['membergroups'][1])) |
389
|
|
|
{ |
390
|
|
|
$mg_query_parts[] = 'mem.id_group IN ({array_int:group_check})'; |
391
|
|
|
$where_params['group_check'] = $search_params['membergroups'][1]; |
392
|
|
|
} |
393
|
|
|
|
394
|
|
|
// Additional membergroups (these are only relevant if not all primary groups where selected!). |
395
|
|
|
if (!empty($search_params['membergroups'][2]) && (empty($search_params['membergroups'][1]) || count($context['membergroups']) != count($search_params['membergroups'][1]))) |
396
|
|
|
foreach ($search_params['membergroups'][2] as $mg) |
397
|
|
|
{ |
398
|
|
|
$mg_query_parts[] = 'FIND_IN_SET({int:add_group_' . $mg . '}, mem.additional_groups) != 0'; |
399
|
|
|
$where_params['add_group_' . $mg] = $mg; |
400
|
|
|
} |
401
|
|
|
|
402
|
|
|
// Combine the one or two membergroup parts into one query part linked with an OR. |
403
|
|
|
if (!empty($mg_query_parts)) |
404
|
|
|
$query_parts[] = '(' . implode(' OR ', $mg_query_parts) . ')'; |
405
|
|
|
|
406
|
|
|
// Get all selected post count related membergroups. |
407
|
|
|
if (!empty($search_params['postgroups']) && count($search_params['postgroups']) != count($context['postgroups'])) |
408
|
|
|
{ |
409
|
|
|
$query_parts[] = 'id_post_group IN ({array_int:post_groups})'; |
410
|
|
|
$where_params['post_groups'] = $search_params['postgroups']; |
411
|
|
|
} |
412
|
|
|
|
413
|
|
|
// Construct the where part of the query. |
414
|
|
|
$where = empty($query_parts) ? '1=1' : implode(' |
415
|
|
|
AND ', $query_parts); |
416
|
|
|
} |
417
|
|
|
else |
418
|
|
|
$search_url_params = null; |
419
|
|
|
|
420
|
|
|
// Construct the additional URL part with the query info in it. |
421
|
|
|
$context['params_url'] = $context['sub_action'] == 'query' ? ';sa=query;params=' . $search_url_params : ''; |
422
|
|
|
|
423
|
|
|
// Get the title and sub template ready.. |
424
|
|
|
$context['page_title'] = $txt['admin_members']; |
425
|
|
|
|
426
|
|
|
$listOptions = array( |
427
|
|
|
'id' => 'member_list', |
428
|
|
|
'title' => $txt['members_list'], |
429
|
|
|
'items_per_page' => $modSettings['defaultMaxMembers'], |
430
|
|
|
'base_href' => $scripturl . '?action=admin;area=viewmembers' . $context['params_url'], |
431
|
|
|
'default_sort_col' => 'user_name', |
432
|
|
|
'get_items' => array( |
433
|
|
|
'file' => $sourcedir . '/Subs-Members.php', |
434
|
|
|
'function' => 'list_getMembers', |
435
|
|
|
'params' => array( |
436
|
|
|
isset($where) ? $where : '1=1', |
437
|
|
|
isset($where_params) ? $where_params : array(), |
438
|
|
|
), |
439
|
|
|
), |
440
|
|
|
'get_count' => array( |
441
|
|
|
'file' => $sourcedir . '/Subs-Members.php', |
442
|
|
|
'function' => 'list_getNumMembers', |
443
|
|
|
'params' => array( |
444
|
|
|
isset($where) ? $where : '1=1', |
445
|
|
|
isset($where_params) ? $where_params : array(), |
446
|
|
|
), |
447
|
|
|
), |
448
|
|
|
'columns' => array( |
449
|
|
|
'id_member' => array( |
450
|
|
|
'header' => array( |
451
|
|
|
'value' => $txt['member_id'], |
452
|
|
|
), |
453
|
|
|
'data' => array( |
454
|
|
|
'db' => 'id_member', |
455
|
|
|
), |
456
|
|
|
'sort' => array( |
457
|
|
|
'default' => 'id_member', |
458
|
|
|
'reverse' => 'id_member DESC', |
459
|
|
|
), |
460
|
|
|
), |
461
|
|
|
'user_name' => array( |
462
|
|
|
'header' => array( |
463
|
|
|
'value' => $txt['username'], |
464
|
|
|
), |
465
|
|
|
'data' => array( |
466
|
|
|
'sprintf' => array( |
467
|
|
|
'format' => '<a href="' . strtr($scripturl, array('%' => '%%')) . '?action=profile;u=%1$d">%2$s</a>', |
468
|
|
|
'params' => array( |
469
|
|
|
'id_member' => false, |
470
|
|
|
'member_name' => false, |
471
|
|
|
), |
472
|
|
|
), |
473
|
|
|
'class' => 'hidden', |
474
|
|
|
), |
475
|
|
|
'sort' => array( |
476
|
|
|
'default' => 'member_name', |
477
|
|
|
'reverse' => 'member_name DESC', |
478
|
|
|
), |
479
|
|
|
), |
480
|
|
|
'display_name' => array( |
481
|
|
|
'header' => array( |
482
|
|
|
'value' => $txt['display_name'], |
483
|
|
|
), |
484
|
|
|
'data' => array( |
485
|
|
|
'sprintf' => array( |
486
|
|
|
'format' => '<a href="' . strtr($scripturl, array('%' => '%%')) . '?action=profile;u=%1$d">%2$s</a>', |
487
|
|
|
'params' => array( |
488
|
|
|
'id_member' => false, |
489
|
|
|
'real_name' => false, |
490
|
|
|
), |
491
|
|
|
), |
492
|
|
|
), |
493
|
|
|
'sort' => array( |
494
|
|
|
'default' => 'real_name', |
495
|
|
|
'reverse' => 'real_name DESC', |
496
|
|
|
), |
497
|
|
|
), |
498
|
|
|
'email' => array( |
499
|
|
|
'header' => array( |
500
|
|
|
'value' => $txt['email_address'], |
501
|
|
|
), |
502
|
|
|
'data' => array( |
503
|
|
|
'sprintf' => array( |
504
|
|
|
'format' => '<a href="mailto:%1$s">%1$s</a>', |
505
|
|
|
'params' => array( |
506
|
|
|
'email_address' => true, |
507
|
|
|
), |
508
|
|
|
), |
509
|
|
|
), |
510
|
|
|
'sort' => array( |
511
|
|
|
'default' => 'email_address', |
512
|
|
|
'reverse' => 'email_address DESC', |
513
|
|
|
), |
514
|
|
|
), |
515
|
|
|
'ip' => array( |
516
|
|
|
'header' => array( |
517
|
|
|
'value' => $txt['ip_address'], |
518
|
|
|
), |
519
|
|
|
'data' => array( |
520
|
|
|
'sprintf' => array( |
521
|
|
|
'format' => '<a href="' . strtr($scripturl, array('%' => '%%')) . '?action=trackip;searchip=%1$s">%1$s</a>', |
522
|
|
|
'params' => array( |
523
|
|
|
'member_ip' => false, |
524
|
|
|
), |
525
|
|
|
), |
526
|
|
|
'class' => 'hidden', |
527
|
|
|
), |
528
|
|
|
'sort' => array( |
529
|
|
|
'default' => 'member_ip', |
530
|
|
|
'reverse' => 'member_ip DESC', |
531
|
|
|
), |
532
|
|
|
), |
533
|
|
|
'last_active' => array( |
534
|
|
|
'header' => array( |
535
|
|
|
'value' => $txt['viewmembers_online'], |
536
|
|
|
), |
537
|
|
|
'data' => array( |
538
|
|
|
'function' => function($rowData) use ($txt) |
539
|
|
|
{ |
540
|
|
|
// Calculate number of days since last online. |
541
|
|
|
if (empty($rowData['last_login'])) |
542
|
|
|
$difference = $txt['never']; |
543
|
|
|
else |
544
|
|
|
{ |
545
|
|
|
$num_days_difference = jeffsdatediff($rowData['last_login']); |
546
|
|
|
|
547
|
|
|
// Today. |
548
|
|
|
if (empty($num_days_difference)) |
549
|
|
|
$difference = $txt['viewmembers_today']; |
550
|
|
|
|
551
|
|
|
// Yesterday. |
552
|
|
|
elseif ($num_days_difference == 1) |
553
|
|
|
$difference = sprintf('1 %1$s', $txt['viewmembers_day_ago']); |
554
|
|
|
|
555
|
|
|
// X days ago. |
556
|
|
|
else |
557
|
|
|
$difference = sprintf('%1$d %2$s', $num_days_difference, $txt['viewmembers_days_ago']); |
558
|
|
|
} |
559
|
|
|
|
560
|
|
|
// Show it in italics if they're not activated... |
561
|
|
|
if ($rowData['is_activated'] % 10 != 1) |
562
|
|
|
$difference = sprintf('<em title="%1$s">%2$s</em>', $txt['not_activated'], $difference); |
563
|
|
|
|
564
|
|
|
return $difference; |
565
|
|
|
}, |
566
|
|
|
'class' => 'hidden', |
567
|
|
|
), |
568
|
|
|
'sort' => array( |
569
|
|
|
'default' => 'last_login DESC', |
570
|
|
|
'reverse' => 'last_login', |
571
|
|
|
), |
572
|
|
|
), |
573
|
|
|
'posts' => array( |
574
|
|
|
'header' => array( |
575
|
|
|
'value' => $txt['member_postcount'], |
576
|
|
|
), |
577
|
|
|
'data' => array( |
578
|
|
|
'db' => 'posts', |
579
|
|
|
'class' => 'hidden', |
580
|
|
|
), |
581
|
|
|
'sort' => array( |
582
|
|
|
'default' => 'posts', |
583
|
|
|
'reverse' => 'posts DESC', |
584
|
|
|
), |
585
|
|
|
), |
586
|
|
|
'check' => array( |
587
|
|
|
'header' => array( |
588
|
|
|
'value' => '<input type="checkbox" onclick="invertAll(this, this.form);">', |
589
|
|
|
'class' => 'centercol', |
590
|
|
|
), |
591
|
|
|
'data' => array( |
592
|
|
|
'function' => function($rowData) use ($user_info) |
593
|
|
|
{ |
594
|
|
|
return '<input type="checkbox" name="delete[]" value="' . $rowData['id_member'] . '"' . ($rowData['id_member'] == $user_info['id'] || $rowData['id_group'] == 1 || in_array(1, explode(',', $rowData['additional_groups'])) ? ' disabled' : '') . '>'; |
595
|
|
|
}, |
596
|
|
|
'class' => 'centercol', |
597
|
|
|
), |
598
|
|
|
), |
599
|
|
|
), |
600
|
|
|
'form' => array( |
601
|
|
|
'href' => $scripturl . '?action=admin;area=viewmembers' . $context['params_url'], |
602
|
|
|
'include_start' => true, |
603
|
|
|
'include_sort' => true, |
604
|
|
|
), |
605
|
|
|
'additional_rows' => array( |
606
|
|
|
array( |
607
|
|
|
'position' => 'below_table_data', |
608
|
|
|
'value' => '<input type="submit" name="delete_members" value="' . $txt['admin_delete_members'] . '" data-confirm="' . $txt['confirm_delete_members'] . '" class="button you_sure">', |
609
|
|
|
), |
610
|
|
|
), |
611
|
|
|
); |
612
|
|
|
|
613
|
|
|
// Without enough permissions, don't show 'delete members' checkboxes. |
614
|
|
|
if (!allowedTo('profile_remove_any')) |
615
|
|
|
unset($listOptions['cols']['check'], $listOptions['form'], $listOptions['additional_rows']); |
616
|
|
|
|
617
|
|
|
require_once($sourcedir . '/Subs-List.php'); |
618
|
|
|
createList($listOptions); |
619
|
|
|
|
620
|
|
|
$context['sub_template'] = 'show_list'; |
621
|
|
|
$context['default_list'] = 'member_list'; |
622
|
|
|
} |
623
|
|
|
|
624
|
|
|
/** |
625
|
|
|
* Search the member list, using one or more criteria. |
626
|
|
|
* Called by ?action=admin;area=viewmembers;sa=search. |
627
|
|
|
* Requires the moderate_forum permission. |
628
|
|
|
* form is submitted to action=admin;area=viewmembers;sa=query. |
629
|
|
|
* |
630
|
|
|
* @uses the search_members sub template of the ManageMembers template. |
631
|
|
|
*/ |
632
|
|
|
function SearchMembers() |
633
|
|
|
{ |
634
|
|
|
global $context, $txt, $smcFunc; |
635
|
|
|
|
636
|
|
|
// Get a list of all the membergroups and postgroups that can be selected. |
637
|
|
|
$context['membergroups'] = array( |
638
|
|
|
array( |
639
|
|
|
'id' => 0, |
640
|
|
|
'name' => $txt['membergroups_members'], |
641
|
|
|
'can_be_additional' => false |
642
|
|
|
) |
643
|
|
|
); |
644
|
|
|
$context['postgroups'] = array(); |
645
|
|
|
|
646
|
|
|
$request = $smcFunc['db_query']('', ' |
647
|
|
|
SELECT id_group, group_name, min_posts |
648
|
|
|
FROM {db_prefix}membergroups |
649
|
|
|
WHERE id_group != {int:moderator_group} |
650
|
|
|
ORDER BY min_posts, CASE WHEN id_group < {int:newbie_group} THEN id_group ELSE 4 END, group_name', |
651
|
|
|
array( |
652
|
|
|
'moderator_group' => 3, |
653
|
|
|
'newbie_group' => 4, |
654
|
|
|
) |
655
|
|
|
); |
656
|
|
View Code Duplication |
while ($row = $smcFunc['db_fetch_assoc']($request)) |
657
|
|
|
{ |
658
|
|
|
if ($row['min_posts'] == -1) |
659
|
|
|
$context['membergroups'][] = array( |
660
|
|
|
'id' => $row['id_group'], |
661
|
|
|
'name' => $row['group_name'], |
662
|
|
|
'can_be_additional' => true |
663
|
|
|
); |
664
|
|
|
else |
665
|
|
|
$context['postgroups'][] = array( |
666
|
|
|
'id' => $row['id_group'], |
667
|
|
|
'name' => $row['group_name'] |
668
|
|
|
); |
669
|
|
|
} |
670
|
|
|
$smcFunc['db_free_result']($request); |
671
|
|
|
|
672
|
|
|
$context['page_title'] = $txt['admin_members']; |
673
|
|
|
$context['sub_template'] = 'search_members'; |
674
|
|
|
} |
675
|
|
|
|
676
|
|
|
/** |
677
|
|
|
* List all members who are awaiting approval / activation, sortable on different columns. |
678
|
|
|
* It allows instant approval or activation of (a selection of) members. |
679
|
|
|
* Called by ?action=admin;area=viewmembers;sa=browse;type=approve |
680
|
|
|
* or ?action=admin;area=viewmembers;sa=browse;type=activate. |
681
|
|
|
* The form submits to ?action=admin;area=viewmembers;sa=approve. |
682
|
|
|
* Requires the moderate_forum permission. |
683
|
|
|
* |
684
|
|
|
* @uses the admin_browse sub template of the ManageMembers template. |
685
|
|
|
*/ |
686
|
|
|
function MembersAwaitingActivation() |
687
|
|
|
{ |
688
|
|
|
global $txt, $context, $scripturl, $modSettings; |
689
|
|
|
global $sourcedir; |
690
|
|
|
|
691
|
|
|
// Not a lot here! |
692
|
|
|
$context['page_title'] = $txt['admin_members']; |
693
|
|
|
$context['sub_template'] = 'admin_browse'; |
694
|
|
|
$context['browse_type'] = isset($_REQUEST['type']) ? $_REQUEST['type'] : (!empty($modSettings['registration_method']) && $modSettings['registration_method'] == 1 ? 'activate' : 'approve'); |
695
|
|
|
if (isset($context['tabs'][$context['browse_type']])) |
696
|
|
|
$context['tabs'][$context['browse_type']]['is_selected'] = true; |
697
|
|
|
|
698
|
|
|
// Allowed filters are those we can have, in theory. |
699
|
|
|
$context['allowed_filters'] = $context['browse_type'] == 'approve' ? array(3, 4, 5) : array(0, 2); |
700
|
|
|
$context['current_filter'] = isset($_REQUEST['filter']) && in_array($_REQUEST['filter'], $context['allowed_filters']) && !empty($context['activation_numbers'][$_REQUEST['filter']]) ? (int) $_REQUEST['filter'] : -1; |
701
|
|
|
|
702
|
|
|
// Sort out the different sub areas that we can actually filter by. |
703
|
|
|
$context['available_filters'] = array(); |
704
|
|
|
foreach ($context['activation_numbers'] as $type => $amount) |
705
|
|
|
{ |
706
|
|
|
// We have some of these... |
707
|
|
|
if (in_array($type, $context['allowed_filters']) && $amount > 0) |
708
|
|
|
$context['available_filters'][] = array( |
709
|
|
|
'type' => $type, |
710
|
|
|
'amount' => $amount, |
711
|
|
|
'desc' => isset($txt['admin_browse_filter_type_' . $type]) ? $txt['admin_browse_filter_type_' . $type] : '?', |
712
|
|
|
'selected' => $type == $context['current_filter'] |
713
|
|
|
); |
714
|
|
|
} |
715
|
|
|
|
716
|
|
|
// If the filter was not sent, set it to whatever has people in it! |
717
|
|
|
if ($context['current_filter'] == -1 && !empty($context['available_filters'][0]['amount'])) |
718
|
|
|
$context['current_filter'] = $context['available_filters'][0]['type']; |
719
|
|
|
|
720
|
|
|
// This little variable is used to determine if we should flag where we are looking. |
721
|
|
|
$context['show_filter'] = ($context['current_filter'] != 0 && $context['current_filter'] != 3) || count($context['available_filters']) > 1; |
722
|
|
|
|
723
|
|
|
// The columns that can be sorted. |
724
|
|
|
$context['columns'] = array( |
725
|
|
|
'id_member' => array('label' => $txt['admin_browse_id']), |
726
|
|
|
'member_name' => array('label' => $txt['admin_browse_username']), |
727
|
|
|
'email_address' => array('label' => $txt['admin_browse_email']), |
728
|
|
|
'member_ip' => array('label' => $txt['admin_browse_ip']), |
729
|
|
|
'date_registered' => array('label' => $txt['admin_browse_registered']), |
730
|
|
|
); |
731
|
|
|
|
732
|
|
|
// Are we showing duplicate information? |
733
|
|
|
if (isset($_GET['showdupes'])) |
734
|
|
|
$_SESSION['showdupes'] = (int) $_GET['showdupes']; |
735
|
|
|
$context['show_duplicates'] = !empty($_SESSION['showdupes']); |
736
|
|
|
|
737
|
|
|
// Determine which actions we should allow on this page. |
738
|
|
|
if ($context['browse_type'] == 'approve') |
739
|
|
|
{ |
740
|
|
|
// If we are approving deleted accounts we have a slightly different list... actually a mirror ;) |
741
|
|
|
if ($context['current_filter'] == 4) |
742
|
|
|
$context['allowed_actions'] = array( |
743
|
|
|
'reject' => $txt['admin_browse_w_approve_deletion'], |
744
|
|
|
'ok' => $txt['admin_browse_w_reject'], |
745
|
|
|
); |
746
|
|
|
else |
747
|
|
|
$context['allowed_actions'] = array( |
748
|
|
|
'ok' => $txt['admin_browse_w_approve'], |
749
|
|
|
'okemail' => $txt['admin_browse_w_approve'] . ' ' . $txt['admin_browse_w_email'], |
750
|
|
|
'require_activation' => $txt['admin_browse_w_approve_require_activate'], |
751
|
|
|
'reject' => $txt['admin_browse_w_reject'], |
752
|
|
|
'rejectemail' => $txt['admin_browse_w_reject'] . ' ' . $txt['admin_browse_w_email'], |
753
|
|
|
); |
754
|
|
|
} |
755
|
|
|
elseif ($context['browse_type'] == 'activate') |
756
|
|
|
$context['allowed_actions'] = array( |
757
|
|
|
'ok' => $txt['admin_browse_w_activate'], |
758
|
|
|
'okemail' => $txt['admin_browse_w_activate'] . ' ' . $txt['admin_browse_w_email'], |
759
|
|
|
'delete' => $txt['admin_browse_w_delete'], |
760
|
|
|
'deleteemail' => $txt['admin_browse_w_delete'] . ' ' . $txt['admin_browse_w_email'], |
761
|
|
|
'remind' => $txt['admin_browse_w_remind'] . ' ' . $txt['admin_browse_w_email'], |
762
|
|
|
); |
763
|
|
|
|
764
|
|
|
// Create an option list for actions allowed to be done with selected members. |
765
|
|
|
$allowed_actions = ' |
766
|
|
|
<option selected value="">' . $txt['admin_browse_with_selected'] . ':</option> |
767
|
|
|
<option value="" disabled>-----------------------------</option>'; |
768
|
|
|
foreach ($context['allowed_actions'] as $key => $desc) |
769
|
|
|
$allowed_actions .= ' |
770
|
|
|
<option value="' . $key . '">' . $desc . '</option>'; |
771
|
|
|
|
772
|
|
|
// Setup the Javascript function for selecting an action for the list. |
773
|
|
|
$javascript = ' |
774
|
|
|
function onSelectChange() |
775
|
|
|
{ |
776
|
|
|
if (document.forms.postForm.todo.value == "") |
777
|
|
|
return; |
778
|
|
|
|
779
|
|
|
var message = "";'; |
780
|
|
|
|
781
|
|
|
// We have special messages for approving deletion of accounts - it's surprisingly logical - honest. |
782
|
|
|
if ($context['current_filter'] == 4) |
783
|
|
|
$javascript .= ' |
784
|
|
|
if (document.forms.postForm.todo.value.indexOf("reject") != -1) |
785
|
|
|
message = "' . $txt['admin_browse_w_delete'] . '"; |
786
|
|
|
else |
787
|
|
|
message = "' . $txt['admin_browse_w_reject'] . '";'; |
788
|
|
|
// Otherwise a nice standard message. |
789
|
|
|
else |
790
|
|
|
$javascript .= ' |
791
|
|
|
if (document.forms.postForm.todo.value.indexOf("delete") != -1) |
792
|
|
|
message = "' . $txt['admin_browse_w_delete'] . '"; |
793
|
|
|
else if (document.forms.postForm.todo.value.indexOf("reject") != -1) |
794
|
|
|
message = "' . $txt['admin_browse_w_reject'] . '"; |
795
|
|
|
else if (document.forms.postForm.todo.value == "remind") |
796
|
|
|
message = "' . $txt['admin_browse_w_remind'] . '"; |
797
|
|
|
else |
798
|
|
|
message = "' . ($context['browse_type'] == 'approve' ? $txt['admin_browse_w_approve'] : $txt['admin_browse_w_activate']) . '";'; |
799
|
|
|
$javascript .= ' |
800
|
|
|
if (confirm(message + " ' . $txt['admin_browse_warn'] . '")) |
801
|
|
|
document.forms.postForm.submit(); |
802
|
|
|
}'; |
803
|
|
|
|
804
|
|
|
$listOptions = array( |
805
|
|
|
'id' => 'approve_list', |
806
|
|
|
// 'title' => $txt['members_approval_title'], |
807
|
|
|
'items_per_page' => $modSettings['defaultMaxMembers'], |
808
|
|
|
'base_href' => $scripturl . '?action=admin;area=viewmembers;sa=browse;type=' . $context['browse_type'] . (!empty($context['show_filter']) ? ';filter=' . $context['current_filter'] : ''), |
809
|
|
|
'default_sort_col' => 'date_registered', |
810
|
|
|
'get_items' => array( |
811
|
|
|
'file' => $sourcedir . '/Subs-Members.php', |
812
|
|
|
'function' => 'list_getMembers', |
813
|
|
|
'params' => array( |
814
|
|
|
'is_activated = {int:activated_status}', |
815
|
|
|
array('activated_status' => $context['current_filter']), |
816
|
|
|
$context['show_duplicates'], |
817
|
|
|
), |
818
|
|
|
), |
819
|
|
|
'get_count' => array( |
820
|
|
|
'file' => $sourcedir . '/Subs-Members.php', |
821
|
|
|
'function' => 'list_getNumMembers', |
822
|
|
|
'params' => array( |
823
|
|
|
'is_activated = {int:activated_status}', |
824
|
|
|
array('activated_status' => $context['current_filter']), |
825
|
|
|
), |
826
|
|
|
), |
827
|
|
|
'columns' => array( |
828
|
|
|
'id_member' => array( |
829
|
|
|
'header' => array( |
830
|
|
|
'value' => $txt['member_id'], |
831
|
|
|
), |
832
|
|
|
'data' => array( |
833
|
|
|
'db' => 'id_member', |
834
|
|
|
), |
835
|
|
|
'sort' => array( |
836
|
|
|
'default' => 'id_member', |
837
|
|
|
'reverse' => 'id_member DESC', |
838
|
|
|
), |
839
|
|
|
), |
840
|
|
|
'user_name' => array( |
841
|
|
|
'header' => array( |
842
|
|
|
'value' => $txt['username'], |
843
|
|
|
), |
844
|
|
|
'data' => array( |
845
|
|
|
'sprintf' => array( |
846
|
|
|
'format' => '<a href="' . strtr($scripturl, array('%' => '%%')) . '?action=profile;u=%1$d">%2$s</a>', |
847
|
|
|
'params' => array( |
848
|
|
|
'id_member' => false, |
849
|
|
|
'member_name' => false, |
850
|
|
|
), |
851
|
|
|
), |
852
|
|
|
), |
853
|
|
|
'sort' => array( |
854
|
|
|
'default' => 'member_name', |
855
|
|
|
'reverse' => 'member_name DESC', |
856
|
|
|
), |
857
|
|
|
), |
858
|
|
|
'email' => array( |
859
|
|
|
'header' => array( |
860
|
|
|
'value' => $txt['email_address'], |
861
|
|
|
), |
862
|
|
|
'data' => array( |
863
|
|
|
'sprintf' => array( |
864
|
|
|
'format' => '<a href="mailto:%1$s">%1$s</a>', |
865
|
|
|
'params' => array( |
866
|
|
|
'email_address' => true, |
867
|
|
|
), |
868
|
|
|
), |
869
|
|
|
), |
870
|
|
|
'sort' => array( |
871
|
|
|
'default' => 'email_address', |
872
|
|
|
'reverse' => 'email_address DESC', |
873
|
|
|
), |
874
|
|
|
), |
875
|
|
|
'ip' => array( |
876
|
|
|
'header' => array( |
877
|
|
|
'value' => $txt['ip_address'], |
878
|
|
|
), |
879
|
|
|
'data' => array( |
880
|
|
|
'sprintf' => array( |
881
|
|
|
'format' => '<a href="' . strtr($scripturl, array('%' => '%%')) . '?action=trackip;searchip=%1$s">%1$s</a>', |
882
|
|
|
'params' => array( |
883
|
|
|
'member_ip' => false, |
884
|
|
|
), |
885
|
|
|
), |
886
|
|
|
), |
887
|
|
|
'sort' => array( |
888
|
|
|
'default' => 'member_ip', |
889
|
|
|
'reverse' => 'member_ip DESC', |
890
|
|
|
), |
891
|
|
|
), |
892
|
|
|
'hostname' => array( |
893
|
|
|
'header' => array( |
894
|
|
|
'value' => $txt['hostname'], |
895
|
|
|
), |
896
|
|
|
'data' => array( |
897
|
|
|
'function' => function($rowData) |
898
|
|
|
{ |
899
|
|
|
return host_from_ip(inet_dtop($rowData['member_ip'])); |
|
|
|
|
900
|
|
|
}, |
901
|
|
|
'class' => 'smalltext', |
902
|
|
|
), |
903
|
|
|
), |
904
|
|
|
'date_registered' => array( |
905
|
|
|
'header' => array( |
906
|
|
|
'value' => $context['current_filter'] == 4 ? $txt['viewmembers_online'] : $txt['date_registered'], |
907
|
|
|
), |
908
|
|
|
'data' => array( |
909
|
|
|
'function' => function($rowData) use ($context) |
910
|
|
|
{ |
911
|
|
|
return timeformat($rowData['' . ($context['current_filter'] == 4 ? 'last_login' : 'date_registered') . '']); |
912
|
|
|
}, |
913
|
|
|
), |
914
|
|
|
'sort' => array( |
915
|
|
|
'default' => $context['current_filter'] == 4 ? 'mem.last_login DESC' : 'date_registered DESC', |
916
|
|
|
'reverse' => $context['current_filter'] == 4 ? 'mem.last_login' : 'date_registered', |
917
|
|
|
), |
918
|
|
|
), |
919
|
|
|
'duplicates' => array( |
920
|
|
|
'header' => array( |
921
|
|
|
'value' => $txt['duplicates'], |
922
|
|
|
// Make sure it doesn't go too wide. |
923
|
|
|
'style' => 'width: 20%;', |
924
|
|
|
), |
925
|
|
|
'data' => array( |
926
|
|
|
'function' => function($rowData) use ($scripturl, $txt) |
927
|
|
|
{ |
928
|
|
|
$member_links = array(); |
929
|
|
|
foreach ($rowData['duplicate_members'] as $member) |
930
|
|
|
{ |
931
|
|
|
if ($member['id']) |
932
|
|
|
$member_links[] = '<a href="' . $scripturl . '?action=profile;u=' . $member['id'] . '" ' . (!empty($member['is_banned']) ? 'class="red"' : '') . '>' . $member['name'] . '</a>'; |
933
|
|
|
else |
934
|
|
|
$member_links[] = $member['name'] . ' (' . $txt['guest'] . ')'; |
935
|
|
|
} |
936
|
|
|
return implode(', ', $member_links); |
937
|
|
|
}, |
938
|
|
|
'class' => 'smalltext', |
939
|
|
|
), |
940
|
|
|
), |
941
|
|
|
'check' => array( |
942
|
|
|
'header' => array( |
943
|
|
|
'value' => '<input type="checkbox" onclick="invertAll(this, this.form);">', |
944
|
|
|
'class' => 'centercol', |
945
|
|
|
), |
946
|
|
|
'data' => array( |
947
|
|
|
'sprintf' => array( |
948
|
|
|
'format' => '<input type="checkbox" name="todoAction[]" value="%1$d">', |
949
|
|
|
'params' => array( |
950
|
|
|
'id_member' => false, |
951
|
|
|
), |
952
|
|
|
), |
953
|
|
|
'class' => 'centercol', |
954
|
|
|
), |
955
|
|
|
), |
956
|
|
|
), |
957
|
|
|
'javascript' => $javascript, |
958
|
|
|
'form' => array( |
959
|
|
|
'href' => $scripturl . '?action=admin;area=viewmembers;sa=approve;type=' . $context['browse_type'], |
960
|
|
|
'name' => 'postForm', |
961
|
|
|
'include_start' => true, |
962
|
|
|
'include_sort' => true, |
963
|
|
|
'hidden_fields' => array( |
964
|
|
|
'orig_filter' => $context['current_filter'], |
965
|
|
|
), |
966
|
|
|
), |
967
|
|
|
'additional_rows' => array( |
968
|
|
|
array( |
969
|
|
|
'position' => 'below_table_data', |
970
|
|
|
'value' => ' |
971
|
|
|
[<a href="' . $scripturl . '?action=admin;area=viewmembers;sa=browse;showdupes=' . ($context['show_duplicates'] ? 0 : 1) . ';type=' . $context['browse_type'] . (!empty($context['show_filter']) ? ';filter=' . $context['current_filter'] : '') . ';' . $context['session_var'] . '=' . $context['session_id'] . '">' . ($context['show_duplicates'] ? $txt['dont_check_for_duplicate'] : $txt['check_for_duplicate']) . '</a>] |
972
|
|
|
<select name="todo" onchange="onSelectChange();"> |
973
|
|
|
' . $allowed_actions . ' |
974
|
|
|
</select> |
975
|
|
|
<noscript><input type="submit" value="' . $txt['go'] . '" class="button"><br class="clear_right"></noscript> |
976
|
|
|
', |
977
|
|
|
'class' => 'floatright', |
978
|
|
|
), |
979
|
|
|
), |
980
|
|
|
); |
981
|
|
|
|
982
|
|
|
// Pick what column to actually include if we're showing duplicates. |
983
|
|
|
if ($context['show_duplicates']) |
984
|
|
|
unset($listOptions['columns']['email']); |
985
|
|
|
else |
986
|
|
|
unset($listOptions['columns']['duplicates']); |
987
|
|
|
|
988
|
|
|
// Only show hostname on duplicates as it takes a lot of time. |
989
|
|
|
if (!$context['show_duplicates'] || !empty($modSettings['disableHostnameLookup'])) |
990
|
|
|
unset($listOptions['columns']['hostname']); |
991
|
|
|
|
992
|
|
|
// Is there any need to show filters? |
993
|
|
|
if (isset($context['available_filters']) && count($context['available_filters']) > 1) |
994
|
|
|
{ |
995
|
|
|
$filterOptions = ' |
996
|
|
|
<strong>' . $txt['admin_browse_filter_by'] . ':</strong> |
997
|
|
|
<select name="filter" onchange="this.form.submit();">'; |
998
|
|
|
foreach ($context['available_filters'] as $filter) |
999
|
|
|
$filterOptions .= ' |
1000
|
|
|
<option value="' . $filter['type'] . '"' . ($filter['selected'] ? ' selected' : '') . '>' . $filter['desc'] . ' - ' . $filter['amount'] . ' ' . ($filter['amount'] == 1 ? $txt['user'] : $txt['users']) . '</option>'; |
1001
|
|
|
$filterOptions .= ' |
1002
|
|
|
</select> |
1003
|
|
|
<noscript><input type="submit" value="' . $txt['go'] . '" name="filter" class="button"></noscript>'; |
1004
|
|
|
$listOptions['additional_rows'][] = array( |
1005
|
|
|
'position' => 'top_of_list', |
1006
|
|
|
'value' => $filterOptions, |
1007
|
|
|
'class' => 'righttext', |
1008
|
|
|
); |
1009
|
|
|
} |
1010
|
|
|
|
1011
|
|
|
// What about if we only have one filter, but it's not the "standard" filter - show them what they are looking at. |
1012
|
|
|
if (!empty($context['show_filter']) && !empty($context['available_filters'])) |
1013
|
|
|
$listOptions['additional_rows'][] = array( |
1014
|
|
|
'position' => 'above_column_headers', |
1015
|
|
|
'value' => '<strong>' . $txt['admin_browse_filter_show'] . ':</strong> ' . $context['available_filters'][0]['desc'], |
1016
|
|
|
'class' => 'smalltext floatright', |
1017
|
|
|
); |
1018
|
|
|
|
1019
|
|
|
// Now that we have all the options, create the list. |
1020
|
|
|
require_once($sourcedir . '/Subs-List.php'); |
1021
|
|
|
createList($listOptions); |
1022
|
|
|
} |
1023
|
|
|
|
1024
|
|
|
/** |
1025
|
|
|
* This function handles the approval, rejection, activation or deletion of members. |
1026
|
|
|
* Called by ?action=admin;area=viewmembers;sa=approve. |
1027
|
|
|
* Requires the moderate_forum permission. |
1028
|
|
|
* Redirects to ?action=admin;area=viewmembers;sa=browse |
1029
|
|
|
* with the same parameters as the calling page. |
1030
|
|
|
*/ |
1031
|
|
|
function AdminApprove() |
1032
|
|
|
{ |
1033
|
|
|
global $scripturl, $modSettings, $sourcedir, $language, $user_info, $smcFunc; |
1034
|
|
|
|
1035
|
|
|
// First, check our session. |
1036
|
|
|
checkSession(); |
1037
|
|
|
|
1038
|
|
|
require_once($sourcedir . '/Subs-Post.php'); |
1039
|
|
|
|
1040
|
|
|
// We also need to the login languages here - for emails. |
1041
|
|
|
loadLanguage('Login'); |
1042
|
|
|
|
1043
|
|
|
// Sort out where we are going... |
1044
|
|
|
$current_filter = (int) $_REQUEST['orig_filter']; |
1045
|
|
|
|
1046
|
|
|
// If we are applying a filter do just that - then redirect. |
1047
|
|
|
if (isset($_REQUEST['filter']) && $_REQUEST['filter'] != $_REQUEST['orig_filter']) |
1048
|
|
|
redirectexit('action=admin;area=viewmembers;sa=browse;type=' . $_REQUEST['type'] . ';sort=' . $_REQUEST['sort'] . ';filter=' . $_REQUEST['filter'] . ';start=' . $_REQUEST['start']); |
1049
|
|
|
|
1050
|
|
|
// Nothing to do? |
1051
|
|
|
if (!isset($_POST['todoAction']) && !isset($_POST['time_passed'])) |
1052
|
|
|
redirectexit('action=admin;area=viewmembers;sa=browse;type=' . $_REQUEST['type'] . ';sort=' . $_REQUEST['sort'] . ';filter=' . $current_filter . ';start=' . $_REQUEST['start']); |
1053
|
|
|
|
1054
|
|
|
// Are we dealing with members who have been waiting for > set amount of time? |
1055
|
|
|
if (isset($_POST['time_passed'])) |
1056
|
|
|
{ |
1057
|
|
|
$timeBefore = time() - 86400 * (int) $_POST['time_passed']; |
1058
|
|
|
$condition = ' |
1059
|
|
|
AND date_registered < {int:time_before}'; |
1060
|
|
|
} |
1061
|
|
|
// Coming from checkboxes - validate the members passed through to us. |
1062
|
|
|
else |
1063
|
|
|
{ |
1064
|
|
|
$members = array(); |
1065
|
|
|
foreach ($_POST['todoAction'] as $id) |
1066
|
|
|
$members[] = (int) $id; |
1067
|
|
|
$condition = ' |
1068
|
|
|
AND id_member IN ({array_int:members})'; |
1069
|
|
|
} |
1070
|
|
|
|
1071
|
|
|
// Get information on each of the members, things that are important to us, like email address... |
1072
|
|
|
$request = $smcFunc['db_query']('', ' |
1073
|
|
|
SELECT id_member, member_name, real_name, email_address, validation_code, lngfile |
1074
|
|
|
FROM {db_prefix}members |
1075
|
|
|
WHERE is_activated = {int:activated_status}' . $condition . ' |
1076
|
|
|
ORDER BY lngfile', |
1077
|
|
|
array( |
1078
|
|
|
'activated_status' => $current_filter, |
1079
|
|
|
'time_before' => empty($timeBefore) ? 0 : $timeBefore, |
1080
|
|
|
'members' => empty($members) ? array() : $members, |
1081
|
|
|
) |
1082
|
|
|
); |
1083
|
|
|
|
1084
|
|
|
$member_count = $smcFunc['db_num_rows']($request); |
1085
|
|
|
|
1086
|
|
|
// If no results then just return! |
1087
|
|
|
if ($member_count == 0) |
1088
|
|
|
redirectexit('action=admin;area=viewmembers;sa=browse;type=' . $_REQUEST['type'] . ';sort=' . $_REQUEST['sort'] . ';filter=' . $current_filter . ';start=' . $_REQUEST['start']); |
1089
|
|
|
|
1090
|
|
|
$member_info = array(); |
1091
|
|
|
$members = array(); |
1092
|
|
|
// Fill the info array. |
1093
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
1094
|
|
|
{ |
1095
|
|
|
$members[] = $row['id_member']; |
1096
|
|
|
$member_info[] = array( |
1097
|
|
|
'id' => $row['id_member'], |
1098
|
|
|
'username' => $row['member_name'], |
1099
|
|
|
'name' => $row['real_name'], |
1100
|
|
|
'email' => $row['email_address'], |
1101
|
|
|
'language' => empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile'], |
1102
|
|
|
'code' => $row['validation_code'] |
1103
|
|
|
); |
1104
|
|
|
} |
1105
|
|
|
$smcFunc['db_free_result']($request); |
1106
|
|
|
|
1107
|
|
|
// Are we activating or approving the members? |
1108
|
|
|
if ($_POST['todo'] == 'ok' || $_POST['todo'] == 'okemail') |
1109
|
|
|
{ |
1110
|
|
|
// Approve/activate this member. |
1111
|
|
|
$smcFunc['db_query']('', ' |
1112
|
|
|
UPDATE {db_prefix}members |
1113
|
|
|
SET validation_code = {string:blank_string}, is_activated = {int:is_activated} |
1114
|
|
|
WHERE is_activated = {int:activated_status}' . $condition, |
1115
|
|
|
array( |
1116
|
|
|
'is_activated' => 1, |
1117
|
|
|
'time_before' => empty($timeBefore) ? 0 : $timeBefore, |
1118
|
|
|
'members' => empty($members) ? array() : $members, |
1119
|
|
|
'activated_status' => $current_filter, |
1120
|
|
|
'blank_string' => '', |
1121
|
|
|
) |
1122
|
|
|
); |
1123
|
|
|
|
1124
|
|
|
// Do we have to let the integration code know about the activations? |
1125
|
|
|
if (!empty($modSettings['integrate_activate'])) |
1126
|
|
|
{ |
1127
|
|
|
foreach ($member_info as $member) |
1128
|
|
|
call_integration_hook('integrate_activate', array($member['username'])); |
1129
|
|
|
} |
1130
|
|
|
|
1131
|
|
|
// Check for email. |
1132
|
|
|
if ($_POST['todo'] == 'okemail') |
1133
|
|
|
{ |
1134
|
|
|
foreach ($member_info as $member) |
1135
|
|
|
{ |
1136
|
|
|
$replacements = array( |
1137
|
|
|
'NAME' => $member['name'], |
1138
|
|
|
'USERNAME' => $member['username'], |
1139
|
|
|
'PROFILELINK' => $scripturl . '?action=profile;u=' . $member['id'], |
1140
|
|
|
'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', |
1141
|
|
|
); |
1142
|
|
|
|
1143
|
|
|
$emaildata = loadEmailTemplate('admin_approve_accept', $replacements, $member['language']); |
1144
|
|
|
sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, 'accapp' . $member['id'], $emaildata['is_html'], 0); |
1145
|
|
|
} |
1146
|
|
|
} |
1147
|
|
|
} |
1148
|
|
|
// Maybe we're sending it off for activation? |
1149
|
|
|
elseif ($_POST['todo'] == 'require_activation') |
1150
|
|
|
{ |
1151
|
|
|
require_once($sourcedir . '/Subs-Members.php'); |
1152
|
|
|
|
1153
|
|
|
// We have to do this for each member I'm afraid. |
1154
|
|
|
foreach ($member_info as $member) |
1155
|
|
|
{ |
1156
|
|
|
// Generate a random activation code. |
1157
|
|
|
$validation_code = generateValidationCode(); |
1158
|
|
|
|
1159
|
|
|
// Set these members for activation - I know this includes two id_member checks but it's safer than bodging $condition ;). |
1160
|
|
|
$smcFunc['db_query']('', ' |
1161
|
|
|
UPDATE {db_prefix}members |
1162
|
|
|
SET validation_code = {string:validation_code}, is_activated = {int:not_activated} |
1163
|
|
|
WHERE is_activated = {int:activated_status} |
1164
|
|
|
' . $condition . ' |
1165
|
|
|
AND id_member = {int:selected_member}', |
1166
|
|
|
array( |
1167
|
|
|
'not_activated' => 0, |
1168
|
|
|
'activated_status' => $current_filter, |
1169
|
|
|
'selected_member' => $member['id'], |
1170
|
|
|
'validation_code' => $validation_code, |
1171
|
|
|
'time_before' => empty($timeBefore) ? 0 : $timeBefore, |
1172
|
|
|
'members' => empty($members) ? array() : $members, |
1173
|
|
|
) |
1174
|
|
|
); |
1175
|
|
|
|
1176
|
|
|
$replacements = array( |
1177
|
|
|
'USERNAME' => $member['name'], |
1178
|
|
|
'ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $member['id'] . ';code=' . $validation_code, |
1179
|
|
|
'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $member['id'], |
1180
|
|
|
'ACTIVATIONCODE' => $validation_code, |
1181
|
|
|
); |
1182
|
|
|
|
1183
|
|
|
$emaildata = loadEmailTemplate('admin_approve_activation', $replacements, $member['language']); |
1184
|
|
|
sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, 'accact' . $member['id'], $emaildata['is_html'], 0); |
1185
|
|
|
} |
1186
|
|
|
} |
1187
|
|
|
// Are we rejecting them? |
1188
|
|
View Code Duplication |
elseif ($_POST['todo'] == 'reject' || $_POST['todo'] == 'rejectemail') |
1189
|
|
|
{ |
1190
|
|
|
require_once($sourcedir . '/Subs-Members.php'); |
1191
|
|
|
deleteMembers($members); |
1192
|
|
|
|
1193
|
|
|
// Send email telling them they aren't welcome? |
1194
|
|
|
if ($_POST['todo'] == 'rejectemail') |
1195
|
|
|
{ |
1196
|
|
|
foreach ($member_info as $member) |
1197
|
|
|
{ |
1198
|
|
|
$replacements = array( |
1199
|
|
|
'USERNAME' => $member['name'], |
1200
|
|
|
); |
1201
|
|
|
|
1202
|
|
|
$emaildata = loadEmailTemplate('admin_approve_reject', $replacements, $member['language']); |
1203
|
|
|
sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, 'accrej', $emaildata['is_html'], 1); |
1204
|
|
|
} |
1205
|
|
|
} |
1206
|
|
|
} |
1207
|
|
|
// A simple delete? |
1208
|
|
View Code Duplication |
elseif ($_POST['todo'] == 'delete' || $_POST['todo'] == 'deleteemail') |
1209
|
|
|
{ |
1210
|
|
|
require_once($sourcedir . '/Subs-Members.php'); |
1211
|
|
|
deleteMembers($members); |
1212
|
|
|
|
1213
|
|
|
// Send email telling them they aren't welcome? |
1214
|
|
|
if ($_POST['todo'] == 'deleteemail') |
1215
|
|
|
{ |
1216
|
|
|
foreach ($member_info as $member) |
1217
|
|
|
{ |
1218
|
|
|
$replacements = array( |
1219
|
|
|
'USERNAME' => $member['name'], |
1220
|
|
|
); |
1221
|
|
|
|
1222
|
|
|
$emaildata = loadEmailTemplate('admin_approve_delete', $replacements, $member['language']); |
1223
|
|
|
sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, 'accdel', $emaildata['is_html'], 1); |
1224
|
|
|
} |
1225
|
|
|
} |
1226
|
|
|
} |
1227
|
|
|
// Remind them to activate their account? |
1228
|
|
|
elseif ($_POST['todo'] == 'remind') |
1229
|
|
|
{ |
1230
|
|
|
foreach ($member_info as $member) |
1231
|
|
|
{ |
1232
|
|
|
$replacements = array( |
1233
|
|
|
'USERNAME' => $member['name'], |
1234
|
|
|
'ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $member['id'] . ';code=' . $member['code'], |
1235
|
|
|
'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $member['id'], |
1236
|
|
|
'ACTIVATIONCODE' => $member['code'], |
1237
|
|
|
); |
1238
|
|
|
|
1239
|
|
|
$emaildata = loadEmailTemplate('admin_approve_remind', $replacements, $member['language']); |
1240
|
|
|
sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, 'accrem' . $member['id'], $emaildata['is_html'], 1); |
1241
|
|
|
} |
1242
|
|
|
} |
1243
|
|
|
|
1244
|
|
|
// @todo current_language is never set, no idea what this is for. Remove? |
1245
|
|
|
// Back to the user's language! |
1246
|
|
|
if (isset($current_language) && $current_language != $user_info['language']) |
|
|
|
|
1247
|
|
|
{ |
1248
|
|
|
loadLanguage('index'); |
1249
|
|
|
loadLanguage('ManageMembers'); |
1250
|
|
|
} |
1251
|
|
|
|
1252
|
|
|
// Log what we did? |
1253
|
|
|
if (!empty($modSettings['modlog_enabled']) && in_array($_POST['todo'], array('ok', 'okemail', 'require_activation', 'remind'))) |
1254
|
|
|
{ |
1255
|
|
|
$log_action = $_POST['todo'] == 'remind' ? 'remind_member' : 'approve_member'; |
1256
|
|
|
|
1257
|
|
|
require_once($sourcedir . '/Logging.php'); |
1258
|
|
|
foreach ($member_info as $member) |
1259
|
|
|
logAction($log_action, array('member' => $member['id']), 'admin'); |
1260
|
|
|
} |
1261
|
|
|
|
1262
|
|
|
// Although updateStats *may* catch this, best to do it manually just in case (Doesn't always sort out unapprovedMembers). |
1263
|
|
|
if (in_array($current_filter, array(3, 4, 5))) |
1264
|
|
|
updateSettings(array('unapprovedMembers' => ($modSettings['unapprovedMembers'] > $member_count ? $modSettings['unapprovedMembers'] - $member_count : 0))); |
1265
|
|
|
|
1266
|
|
|
// Update the member's stats. (but, we know the member didn't change their name.) |
1267
|
|
|
updateStats('member', false); |
1268
|
|
|
|
1269
|
|
|
// If they haven't been deleted, update the post group statistics on them... |
1270
|
|
|
if (!in_array($_POST['todo'], array('delete', 'deleteemail', 'reject', 'rejectemail', 'remind'))) |
1271
|
|
|
updateStats('postgroups', $members); |
1272
|
|
|
|
1273
|
|
|
redirectexit('action=admin;area=viewmembers;sa=browse;type=' . $_REQUEST['type'] . ';sort=' . $_REQUEST['sort'] . ';filter=' . $current_filter . ';start=' . $_REQUEST['start']); |
1274
|
|
|
} |
1275
|
|
|
|
1276
|
|
|
/** |
1277
|
|
|
* Nifty function to calculate the number of days ago a given date was. |
1278
|
|
|
* Requires a unix timestamp as input, returns an integer. |
1279
|
|
|
* Named in honour of Jeff Lewis, the original creator of...this function. |
1280
|
|
|
* |
1281
|
|
|
* @param int $old The timestamp of the old date |
1282
|
|
|
* @return int The number of days since $old, based on the forum time |
|
|
|
|
1283
|
|
|
*/ |
1284
|
|
|
function jeffsdatediff($old) |
1285
|
|
|
{ |
1286
|
|
|
// Get the current time as the user would see it... |
1287
|
|
|
$forumTime = forum_time(); |
1288
|
|
|
|
1289
|
|
|
// Calculate the seconds that have passed since midnight. |
1290
|
|
|
$sinceMidnight = date('H', $forumTime) * 60 * 60 + date('i', $forumTime) * 60 + date('s', $forumTime); |
1291
|
|
|
|
1292
|
|
|
// Take the difference between the two times. |
1293
|
|
|
$dis = time() - $old; |
1294
|
|
|
|
1295
|
|
|
// Before midnight? |
1296
|
|
|
if ($dis < $sinceMidnight) |
1297
|
|
|
return 0; |
1298
|
|
|
else |
1299
|
|
|
$dis -= $sinceMidnight; |
1300
|
|
|
|
1301
|
|
|
// Divide out the seconds in a day to get the number of days. |
1302
|
|
|
return ceil($dis / (24 * 60 * 60)); |
1303
|
|
|
} |
1304
|
|
|
|
1305
|
|
|
/** |
1306
|
|
|
* Fetches all the activation counts for ViewMembers. |
1307
|
|
|
* |
1308
|
|
|
*/ |
1309
|
|
|
function GetMemberActivationCounts() |
1310
|
|
|
{ |
1311
|
|
|
global $smcFunc, $context; |
1312
|
|
|
|
1313
|
|
|
// Get counts on every type of activation - for sections and filtering alike. |
1314
|
|
|
$request = $smcFunc['db_query']('', ' |
1315
|
|
|
SELECT COUNT(*) AS total_members, is_activated |
1316
|
|
|
FROM {db_prefix}members |
1317
|
|
|
WHERE is_activated != {int:is_activated} |
1318
|
|
|
GROUP BY is_activated', |
1319
|
|
|
array( |
1320
|
|
|
'is_activated' => 1, |
1321
|
|
|
) |
1322
|
|
|
); |
1323
|
|
|
$context['activation_numbers'] = array(); |
1324
|
|
|
$context['awaiting_activation'] = 0; |
1325
|
|
|
$context['awaiting_approval'] = 0; |
1326
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
1327
|
|
|
$context['activation_numbers'][$row['is_activated']] = $row['total_members']; |
1328
|
|
|
$smcFunc['db_free_result']($request); |
1329
|
|
|
|
1330
|
|
|
foreach ($context['activation_numbers'] as $activation_type => $total_members) |
1331
|
|
|
{ |
1332
|
|
|
if (in_array($activation_type, array(0, 2))) |
1333
|
|
|
$context['awaiting_activation'] += $total_members; |
1334
|
|
|
elseif (in_array($activation_type, array(3, 4, 5))) |
1335
|
|
|
$context['awaiting_approval'] += $total_members; |
1336
|
|
|
} |
1337
|
|
|
|
1338
|
|
|
} |
1339
|
|
|
|
1340
|
|
|
?> |
Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.
Let’s take a look at an example:
As you can see in this example, the array
$myArray
is initialized the first time when the foreach loop is entered. You can also see that the value of thebar
key is only written conditionally; thus, its value might result from a previous iteration.This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.