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