|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/** |
|
4
|
|
|
* This file currently just shows group info, and allows certain priviledged members to add/remove 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
|
|
|
* Entry point function, permission checks, admin bars, etc. |
|
21
|
|
|
* It allows moderators and users to access the group showing functions. |
|
22
|
|
|
* It handles permission checks, and puts the moderation bar on as required. |
|
23
|
|
|
*/ |
|
24
|
|
|
function Groups() |
|
25
|
|
|
{ |
|
26
|
|
|
global $context, $txt, $scripturl, $sourcedir, $user_info; |
|
27
|
|
|
|
|
28
|
|
|
// The sub-actions that we can do. Format "Function Name, Mod Bar Index if appropriate". |
|
29
|
|
|
$subActions = array( |
|
30
|
|
|
'index' => array('GroupList', 'view_groups'), |
|
31
|
|
|
'members' => array('MembergroupMembers', 'view_groups'), |
|
32
|
|
|
'requests' => array('GroupRequests', 'group_requests'), |
|
33
|
|
|
); |
|
34
|
|
|
|
|
35
|
|
|
// Default to sub action 'index'. |
|
36
|
|
|
$_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : 'index'; |
|
37
|
|
|
|
|
38
|
|
|
// Get the template stuff up and running. |
|
39
|
|
|
loadLanguage('ManageMembers'); |
|
40
|
|
|
loadLanguage('ModerationCenter'); |
|
41
|
|
|
loadTemplate('ManageMembergroups'); |
|
42
|
|
|
|
|
43
|
|
|
// If we can see the moderation center, and this has a mod bar entry, add the mod center bar. |
|
44
|
|
|
if (allowedTo('access_mod_center') || $user_info['mod_cache']['bq'] != '0=1' || $user_info['mod_cache']['gq'] != '0=1' || allowedTo('manage_membergroups')) |
|
45
|
|
|
{ |
|
46
|
|
|
require_once($sourcedir . '/ModerationCenter.php'); |
|
47
|
|
|
$_GET['area'] = $_REQUEST['sa'] == 'requests' ? 'groups' : 'viewgroups'; |
|
48
|
|
|
ModerationMain(true); |
|
49
|
|
|
} |
|
50
|
|
|
// Otherwise add something to the link tree, for normal people. |
|
51
|
|
|
else |
|
52
|
|
|
{ |
|
53
|
|
|
isAllowedTo('view_mlist'); |
|
54
|
|
|
|
|
55
|
|
|
$context['linktree'][] = array( |
|
56
|
|
|
'url' => $scripturl . '?action=groups', |
|
57
|
|
|
'name' => $txt['groups'], |
|
58
|
|
|
); |
|
59
|
|
|
} |
|
60
|
|
|
|
|
61
|
|
|
// CRUD $subActions as needed. |
|
62
|
|
|
call_integration_hook('integrate_manage_groups', array(&$subActions)); |
|
63
|
|
|
|
|
64
|
|
|
// Call the actual function. |
|
65
|
|
|
call_helper($subActions[$_REQUEST['sa']][0]); |
|
66
|
|
|
} |
|
67
|
|
|
|
|
68
|
|
|
/** |
|
69
|
|
|
* This very simply lists the groups, nothing snazy. |
|
70
|
|
|
*/ |
|
71
|
|
|
function GroupList() |
|
72
|
|
|
{ |
|
73
|
|
|
global $txt, $context, $sourcedir, $scripturl; |
|
74
|
|
|
|
|
75
|
|
|
$context['page_title'] = $txt['viewing_groups']; |
|
76
|
|
|
|
|
77
|
|
|
// Making a list is not hard with this beauty. |
|
78
|
|
|
require_once($sourcedir . '/Subs-List.php'); |
|
79
|
|
|
|
|
80
|
|
|
// Use the standard templates for showing this. |
|
81
|
|
|
$listOptions = array( |
|
82
|
|
|
'id' => 'group_lists', |
|
83
|
|
|
'title' => $context['page_title'], |
|
84
|
|
|
'base_href' => $scripturl . '?action=moderate;area=viewgroups;sa=view', |
|
85
|
|
|
'default_sort_col' => 'group', |
|
86
|
|
|
'get_items' => array( |
|
87
|
|
|
'file' => $sourcedir . '/Subs-Membergroups.php', |
|
88
|
|
|
'function' => 'list_getMembergroups', |
|
89
|
|
|
'params' => array( |
|
90
|
|
|
'regular', |
|
91
|
|
|
), |
|
92
|
|
|
), |
|
93
|
|
|
'columns' => array( |
|
94
|
|
|
'group' => array( |
|
95
|
|
|
'header' => array( |
|
96
|
|
|
'value' => $txt['name'], |
|
97
|
|
|
), |
|
98
|
|
|
'data' => array( |
|
99
|
|
|
'function' => function($rowData) use ($scripturl) |
|
100
|
|
|
{ |
|
101
|
|
|
// Since the moderator group has no explicit members, no link is needed. |
|
102
|
|
|
if ($rowData['id_group'] == 3) |
|
103
|
|
|
$group_name = $rowData['group_name']; |
|
104
|
|
|
else |
|
105
|
|
|
{ |
|
106
|
|
|
$color_style = empty($rowData['online_color']) ? '' : sprintf(' style="color: %1$s;"', $rowData['online_color']); |
|
107
|
|
|
|
|
108
|
|
View Code Duplication |
if (allowedTo('manage_membergroups')) |
|
|
|
|
|
|
109
|
|
|
{ |
|
110
|
|
|
$group_name = sprintf('<a href="%1$s?action=admin;area=membergroups;sa=members;group=%2$d"%3$s>%4$s</a>', $scripturl, $rowData['id_group'], $color_style, $rowData['group_name']); |
|
111
|
|
|
} |
|
112
|
|
|
else |
|
113
|
|
|
{ |
|
114
|
|
|
$group_name = sprintf('<a href="%1$s?action=groups;sa=members;group=%2$d"%3$s>%4$s</a>', $scripturl, $rowData['id_group'], $color_style, $rowData['group_name']); |
|
115
|
|
|
} |
|
116
|
|
|
} |
|
117
|
|
|
|
|
118
|
|
|
// Add a help option for moderator and administrator. |
|
119
|
|
View Code Duplication |
if ($rowData['id_group'] == 1) |
|
|
|
|
|
|
120
|
|
|
$group_name .= sprintf(' (<a href="%1$s?action=helpadmin;help=membergroup_administrator" onclick="return reqOverlayDiv(this.href);">?</a>)', $scripturl); |
|
121
|
|
|
elseif ($rowData['id_group'] == 3) |
|
122
|
|
|
$group_name .= sprintf(' (<a href="%1$s?action=helpadmin;help=membergroup_moderator" onclick="return reqOverlayDiv(this.href);">?</a>)', $scripturl); |
|
123
|
|
|
|
|
124
|
|
|
return $group_name; |
|
125
|
|
|
}, |
|
126
|
|
|
), |
|
127
|
|
|
'sort' => array( |
|
128
|
|
|
'default' => 'CASE WHEN mg.id_group < 4 THEN mg.id_group ELSE 4 END, mg.group_name', |
|
129
|
|
|
'reverse' => 'CASE WHEN mg.id_group < 4 THEN mg.id_group ELSE 4 END, mg.group_name DESC', |
|
130
|
|
|
), |
|
131
|
|
|
), |
|
132
|
|
|
'icons' => array( |
|
133
|
|
|
'header' => array( |
|
134
|
|
|
'value' => $txt['membergroups_icons'], |
|
135
|
|
|
), |
|
136
|
|
|
'data' => array( |
|
137
|
|
|
'db' => 'icons', |
|
138
|
|
|
), |
|
139
|
|
|
'sort' => array( |
|
140
|
|
|
'default' => 'mg.icons', |
|
141
|
|
|
'reverse' => 'mg.icons DESC', |
|
142
|
|
|
) |
|
143
|
|
|
), |
|
144
|
|
|
'moderators' => array( |
|
145
|
|
|
'header' => array( |
|
146
|
|
|
'value' => $txt['moderators'], |
|
147
|
|
|
), |
|
148
|
|
|
'data' => array( |
|
149
|
|
|
'function' => function($group) use ($txt) |
|
150
|
|
|
{ |
|
151
|
|
|
return empty($group['moderators']) ? '<em>' . $txt['membergroups_new_copy_none'] . '</em>' : implode(', ', $group['moderators']); |
|
152
|
|
|
}, |
|
153
|
|
|
), |
|
154
|
|
|
), |
|
155
|
|
|
'members' => array( |
|
156
|
|
|
'header' => array( |
|
157
|
|
|
'value' => $txt['membergroups_members_top'], |
|
158
|
|
|
), |
|
159
|
|
|
'data' => array( |
|
160
|
|
View Code Duplication |
'function' => function($rowData) use ($txt) |
|
|
|
|
|
|
161
|
|
|
{ |
|
162
|
|
|
// No explicit members for the moderator group. |
|
163
|
|
|
return $rowData['id_group'] == 3 ? $txt['membergroups_guests_na'] : comma_format($rowData['num_members']); |
|
164
|
|
|
}, |
|
165
|
|
|
'class' => 'centercol', |
|
166
|
|
|
), |
|
167
|
|
|
'sort' => array( |
|
168
|
|
|
'default' => 'CASE WHEN mg.id_group < 4 THEN mg.id_group ELSE 4 END, 1', |
|
169
|
|
|
'reverse' => 'CASE WHEN mg.id_group < 4 THEN mg.id_group ELSE 4 END, 1 DESC', |
|
170
|
|
|
), |
|
171
|
|
|
), |
|
172
|
|
|
), |
|
173
|
|
|
); |
|
174
|
|
|
|
|
175
|
|
|
// Create the request list. |
|
176
|
|
|
createList($listOptions); |
|
177
|
|
|
|
|
178
|
|
|
$context['sub_template'] = 'show_list'; |
|
179
|
|
|
$context['default_list'] = 'group_lists'; |
|
180
|
|
|
} |
|
181
|
|
|
|
|
182
|
|
|
/** |
|
183
|
|
|
* Display members of a group, and allow adding of members to a group. Silly function name though ;) |
|
184
|
|
|
* It can be called from ManageMembergroups if it needs templating within the admin environment. |
|
185
|
|
|
* It shows a list of members that are part of a given membergroup. |
|
186
|
|
|
* It is called by ?action=moderate;area=viewgroups;sa=members;group=x |
|
187
|
|
|
* It requires the manage_membergroups permission. |
|
188
|
|
|
* It allows to add and remove members from the selected membergroup. |
|
189
|
|
|
* It allows sorting on several columns. |
|
190
|
|
|
* It redirects to itself. |
|
191
|
|
|
* @uses ManageMembergroups template, group_members sub template. |
|
192
|
|
|
* @todo: use createList |
|
193
|
|
|
*/ |
|
194
|
|
|
function MembergroupMembers() |
|
195
|
|
|
{ |
|
196
|
|
|
global $txt, $scripturl, $context, $modSettings, $sourcedir, $user_info, $settings, $smcFunc; |
|
197
|
|
|
|
|
198
|
|
|
$_REQUEST['group'] = isset($_REQUEST['group']) ? (int) $_REQUEST['group'] : 0; |
|
199
|
|
|
|
|
200
|
|
|
// No browsing of guests, membergroup 0 or moderators. |
|
201
|
|
|
if (in_array($_REQUEST['group'], array(-1, 0, 3))) |
|
202
|
|
|
fatal_lang_error('membergroup_does_not_exist', false); |
|
203
|
|
|
|
|
204
|
|
|
// Load up the group details. |
|
205
|
|
|
$request = $smcFunc['db_query']('', ' |
|
206
|
|
|
SELECT id_group AS id, group_name AS name, CASE WHEN min_posts = {int:min_posts} THEN 1 ELSE 0 END AS assignable, hidden, online_color, |
|
207
|
|
|
icons, description, CASE WHEN min_posts != {int:min_posts} THEN 1 ELSE 0 END AS is_post_group, group_type |
|
208
|
|
|
FROM {db_prefix}membergroups |
|
209
|
|
|
WHERE id_group = {int:id_group} |
|
210
|
|
|
LIMIT 1', |
|
211
|
|
|
array( |
|
212
|
|
|
'min_posts' => -1, |
|
213
|
|
|
'id_group' => $_REQUEST['group'], |
|
214
|
|
|
) |
|
215
|
|
|
); |
|
216
|
|
|
// Doesn't exist? |
|
217
|
|
|
if ($smcFunc['db_num_rows']($request) == 0) |
|
218
|
|
|
fatal_lang_error('membergroup_does_not_exist', false); |
|
219
|
|
|
$context['group'] = $smcFunc['db_fetch_assoc']($request); |
|
220
|
|
|
$smcFunc['db_free_result']($request); |
|
221
|
|
|
|
|
222
|
|
|
// Fix the membergroup icons. |
|
223
|
|
|
$context['group']['icons'] = explode('#', $context['group']['icons']); |
|
224
|
|
|
$context['group']['icons'] = !empty($context['group']['icons'][0]) && !empty($context['group']['icons'][1]) ? str_repeat('<img src="' . $settings['images_url'] . '/membericons/' . $context['group']['icons'][1] . '" alt="*">', $context['group']['icons'][0]) : ''; |
|
225
|
|
|
$context['group']['can_moderate'] = allowedTo('manage_membergroups') && (allowedTo('admin_forum') || $context['group']['group_type'] != 1); |
|
226
|
|
|
|
|
227
|
|
|
$context['linktree'][] = array( |
|
228
|
|
|
'url' => $scripturl . '?action=groups;sa=members;group=' . $context['group']['id'], |
|
229
|
|
|
'name' => $context['group']['name'], |
|
230
|
|
|
); |
|
231
|
|
|
$context['can_send_email'] = allowedTo('moderate_forum'); |
|
232
|
|
|
|
|
233
|
|
|
// Load all the group moderators, for fun. |
|
234
|
|
|
$request = $smcFunc['db_query']('', ' |
|
235
|
|
|
SELECT mem.id_member, mem.real_name |
|
236
|
|
|
FROM {db_prefix}group_moderators AS mods |
|
237
|
|
|
INNER JOIN {db_prefix}members AS mem ON (mem.id_member = mods.id_member) |
|
238
|
|
|
WHERE mods.id_group = {int:id_group}', |
|
239
|
|
|
array( |
|
240
|
|
|
'id_group' => $_REQUEST['group'], |
|
241
|
|
|
) |
|
242
|
|
|
); |
|
243
|
|
|
$context['group']['moderators'] = array(); |
|
244
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
245
|
|
|
{ |
|
246
|
|
|
$context['group']['moderators'][] = array( |
|
247
|
|
|
'id' => $row['id_member'], |
|
248
|
|
|
'name' => $row['real_name'] |
|
249
|
|
|
); |
|
250
|
|
|
|
|
251
|
|
|
if ($user_info['id'] == $row['id_member'] && $context['group']['group_type'] != 1) |
|
252
|
|
|
$context['group']['can_moderate'] = true; |
|
253
|
|
|
} |
|
254
|
|
|
$smcFunc['db_free_result']($request); |
|
255
|
|
|
|
|
256
|
|
|
// If this group is hidden then it can only "exists" if the user can moderate it! |
|
257
|
|
|
if ($context['group']['hidden'] && !$context['group']['can_moderate']) |
|
258
|
|
|
fatal_lang_error('membergroup_does_not_exist', false); |
|
259
|
|
|
|
|
260
|
|
|
// You can only assign membership if you are the moderator and/or can manage groups! |
|
261
|
|
|
if (!$context['group']['can_moderate']) |
|
262
|
|
|
$context['group']['assignable'] = 0; |
|
263
|
|
|
// Non-admins cannot assign admins. |
|
264
|
|
|
elseif ($context['group']['id'] == 1 && !allowedTo('admin_forum')) |
|
265
|
|
|
$context['group']['assignable'] = 0; |
|
266
|
|
|
|
|
267
|
|
|
// Removing member from group? |
|
268
|
|
|
if (isset($_POST['remove']) && !empty($_REQUEST['rem']) && is_array($_REQUEST['rem']) && $context['group']['assignable']) |
|
269
|
|
|
{ |
|
270
|
|
|
checkSession(); |
|
271
|
|
|
validateToken('mod-mgm'); |
|
272
|
|
|
|
|
273
|
|
|
// Make sure we're dealing with integers only. |
|
274
|
|
|
foreach ($_REQUEST['rem'] as $key => $group) |
|
275
|
|
|
$_REQUEST['rem'][$key] = (int) $group; |
|
276
|
|
|
|
|
277
|
|
|
require_once($sourcedir . '/Subs-Membergroups.php'); |
|
278
|
|
|
removeMembersFromGroups($_REQUEST['rem'], $_REQUEST['group'], true); |
|
279
|
|
|
} |
|
280
|
|
|
// Must be adding new members to the group... |
|
281
|
|
|
elseif (isset($_REQUEST['add']) && (!empty($_REQUEST['toAdd']) || !empty($_REQUEST['member_add'])) && $context['group']['assignable']) |
|
282
|
|
|
{ |
|
283
|
|
|
checkSession(); |
|
284
|
|
|
validateToken('mod-mgm'); |
|
285
|
|
|
|
|
286
|
|
|
$member_query = array(); |
|
287
|
|
|
$member_parameters = array(); |
|
288
|
|
|
|
|
289
|
|
|
// Get all the members to be added... taking into account names can be quoted ;) |
|
290
|
|
|
$_REQUEST['toAdd'] = strtr($smcFunc['htmlspecialchars']($_REQUEST['toAdd'], ENT_QUOTES), array('"' => '"')); |
|
291
|
|
|
preg_match_all('~"([^"]+)"~', $_REQUEST['toAdd'], $matches); |
|
292
|
|
|
$member_names = array_unique(array_merge($matches[1], explode(',', preg_replace('~"[^"]+"~', '', $_REQUEST['toAdd'])))); |
|
293
|
|
|
|
|
294
|
|
|
foreach ($member_names as $index => $member_name) |
|
295
|
|
|
{ |
|
296
|
|
|
$member_names[$index] = trim($smcFunc['strtolower']($member_names[$index])); |
|
297
|
|
|
|
|
298
|
|
|
if (strlen($member_names[$index]) == 0) |
|
299
|
|
|
unset($member_names[$index]); |
|
300
|
|
|
} |
|
301
|
|
|
|
|
302
|
|
|
// Any passed by ID? |
|
303
|
|
|
$member_ids = array(); |
|
304
|
|
|
if (!empty($_REQUEST['member_add'])) |
|
305
|
|
|
foreach ($_REQUEST['member_add'] as $id) |
|
|
|
|
|
|
306
|
|
|
if ($id > 0) |
|
307
|
|
|
$member_ids[] = (int) $id; |
|
308
|
|
|
|
|
309
|
|
|
// Construct the query pelements. |
|
310
|
|
|
if (!empty($member_ids)) |
|
311
|
|
|
{ |
|
312
|
|
|
$member_query[] = 'id_member IN ({array_int:member_ids})'; |
|
313
|
|
|
$member_parameters['member_ids'] = $member_ids; |
|
314
|
|
|
} |
|
315
|
|
|
if (!empty($member_names)) |
|
316
|
|
|
{ |
|
317
|
|
|
$member_query[] = 'LOWER(member_name) IN ({array_string:member_names})'; |
|
318
|
|
|
$member_query[] = 'LOWER(real_name) IN ({array_string:member_names})'; |
|
319
|
|
|
$member_parameters['member_names'] = $member_names; |
|
320
|
|
|
} |
|
321
|
|
|
|
|
322
|
|
|
$members = array(); |
|
323
|
|
|
if (!empty($member_query)) |
|
324
|
|
|
{ |
|
325
|
|
|
$request = $smcFunc['db_query']('', ' |
|
326
|
|
|
SELECT id_member |
|
327
|
|
|
FROM {db_prefix}members |
|
328
|
|
|
WHERE (' . implode(' OR ', $member_query) . ') |
|
329
|
|
|
AND id_group != {int:id_group} |
|
330
|
|
|
AND FIND_IN_SET({int:id_group}, additional_groups) = 0', |
|
331
|
|
|
array_merge($member_parameters, array( |
|
332
|
|
|
'id_group' => $_REQUEST['group'], |
|
333
|
|
|
)) |
|
334
|
|
|
); |
|
335
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
336
|
|
|
$members[] = $row['id_member']; |
|
337
|
|
|
$smcFunc['db_free_result']($request); |
|
338
|
|
|
} |
|
339
|
|
|
|
|
340
|
|
|
// @todo Add $_POST['additional'] to templates! |
|
|
|
|
|
|
341
|
|
|
|
|
342
|
|
|
// Do the updates... |
|
343
|
|
|
if (!empty($members)) |
|
344
|
|
|
{ |
|
345
|
|
|
require_once($sourcedir . '/Subs-Membergroups.php'); |
|
346
|
|
|
addMembersToGroup($members, $_REQUEST['group'], isset($_POST['additional']) || $context['group']['hidden'] ? 'only_additional' : 'auto', true); |
|
347
|
|
|
} |
|
348
|
|
|
} |
|
349
|
|
|
|
|
350
|
|
|
// Sort out the sorting! |
|
351
|
|
|
$sort_methods = array( |
|
352
|
|
|
'name' => 'real_name', |
|
353
|
|
|
'email' => 'email_address', |
|
354
|
|
|
'active' => 'last_login', |
|
355
|
|
|
'registered' => 'date_registered', |
|
356
|
|
|
'posts' => 'posts', |
|
357
|
|
|
); |
|
358
|
|
|
|
|
359
|
|
|
// They didn't pick one, default to by name.. |
|
360
|
|
|
if (!isset($_REQUEST['sort']) || !isset($sort_methods[$_REQUEST['sort']])) |
|
361
|
|
|
{ |
|
362
|
|
|
$context['sort_by'] = 'name'; |
|
363
|
|
|
$querySort = 'real_name'; |
|
364
|
|
|
} |
|
365
|
|
|
// Otherwise default to ascending. |
|
366
|
|
|
else |
|
367
|
|
|
{ |
|
368
|
|
|
$context['sort_by'] = $_REQUEST['sort']; |
|
369
|
|
|
$querySort = $sort_methods[$_REQUEST['sort']]; |
|
370
|
|
|
} |
|
371
|
|
|
|
|
372
|
|
|
$context['sort_direction'] = isset($_REQUEST['desc']) ? 'down' : 'up'; |
|
373
|
|
|
|
|
374
|
|
|
// The where on the query is interesting. Non-moderators should only see people who are in this group as primary. |
|
375
|
|
|
if ($context['group']['can_moderate']) |
|
376
|
|
|
$where = $context['group']['is_post_group'] ? 'id_post_group = {int:group}' : 'id_group = {int:group} OR FIND_IN_SET({int:group}, additional_groups) != 0'; |
|
377
|
|
|
else |
|
378
|
|
|
$where = $context['group']['is_post_group'] ? 'id_post_group = {int:group}' : 'id_group = {int:group}'; |
|
379
|
|
|
|
|
380
|
|
|
// Count members of the group. |
|
381
|
|
|
$request = $smcFunc['db_query']('', ' |
|
382
|
|
|
SELECT COUNT(*) |
|
383
|
|
|
FROM {db_prefix}members |
|
384
|
|
|
WHERE ' . $where, |
|
385
|
|
|
array( |
|
386
|
|
|
'group' => $_REQUEST['group'], |
|
387
|
|
|
) |
|
388
|
|
|
); |
|
389
|
|
|
list ($context['total_members']) = $smcFunc['db_fetch_row']($request); |
|
390
|
|
|
$smcFunc['db_free_result']($request); |
|
391
|
|
|
$context['total_members'] = comma_format($context['total_members']); |
|
392
|
|
|
|
|
393
|
|
|
// Create the page index. |
|
394
|
|
|
$context['page_index'] = constructPageIndex($scripturl . '?action=' . ($context['group']['can_moderate'] ? 'moderate;area=viewgroups' : 'groups') . ';sa=members;group=' . $_REQUEST['group'] . ';sort=' . $context['sort_by'] . (isset($_REQUEST['desc']) ? ';desc' : ''), $_REQUEST['start'], $context['total_members'], $modSettings['defaultMaxMembers']); |
|
395
|
|
|
$context['start'] = $_REQUEST['start']; |
|
396
|
|
|
$context['can_moderate_forum'] = allowedTo('moderate_forum'); |
|
397
|
|
|
|
|
398
|
|
|
// Load up all members of this group. |
|
399
|
|
|
$request = $smcFunc['db_query']('', ' |
|
400
|
|
|
SELECT id_member, member_name, real_name, email_address, member_ip, date_registered, last_login, |
|
401
|
|
|
posts, is_activated, real_name |
|
402
|
|
|
FROM {db_prefix}members |
|
403
|
|
|
WHERE ' . $where . ' |
|
404
|
|
|
ORDER BY ' . $querySort . ' ' . ($context['sort_direction'] == 'down' ? 'DESC' : 'ASC') . ' |
|
405
|
|
|
LIMIT {int:start}, {int:max}', |
|
406
|
|
|
array( |
|
407
|
|
|
'group' => $_REQUEST['group'], |
|
408
|
|
|
'start' => $context['start'], |
|
409
|
|
|
'max' => $modSettings['defaultMaxMembers'], |
|
410
|
|
|
) |
|
411
|
|
|
); |
|
412
|
|
|
$context['members'] = array(); |
|
413
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
414
|
|
|
{ |
|
415
|
|
|
$row['member_ip'] = inet_dtop($row['member_ip']); |
|
416
|
|
|
$last_online = empty($row['last_login']) ? $txt['never'] : timeformat($row['last_login']); |
|
417
|
|
|
|
|
418
|
|
|
// Italicize the online note if they aren't activated. |
|
419
|
|
|
if ($row['is_activated'] % 10 != 1) |
|
420
|
|
|
$last_online = '<em title="' . $txt['not_activated'] . '">' . $last_online . '</em>'; |
|
421
|
|
|
|
|
422
|
|
|
$context['members'][] = array( |
|
423
|
|
|
'id' => $row['id_member'], |
|
424
|
|
|
'name' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>', |
|
425
|
|
|
'email' => $row['email_address'], |
|
426
|
|
|
'ip' => '<a href="' . $scripturl . '?action=trackip;searchip=' . $row['member_ip'] . '">' . $row['member_ip'] . '</a>', |
|
427
|
|
|
'registered' => timeformat($row['date_registered']), |
|
428
|
|
|
'last_online' => $last_online, |
|
429
|
|
|
'posts' => comma_format($row['posts']), |
|
430
|
|
|
'is_activated' => $row['is_activated'] % 10 == 1, |
|
431
|
|
|
); |
|
432
|
|
|
} |
|
433
|
|
|
$smcFunc['db_free_result']($request); |
|
434
|
|
|
|
|
435
|
|
|
// Select the template. |
|
436
|
|
|
$context['sub_template'] = 'group_members'; |
|
437
|
|
|
$context['page_title'] = $txt['membergroups_members_title'] . ': ' . $context['group']['name']; |
|
438
|
|
|
createToken('mod-mgm'); |
|
439
|
|
|
|
|
440
|
|
|
if ($context['group']['assignable']) |
|
441
|
|
|
loadJavaScriptFile('suggest.js', array('defer' => false), 'smf_suggest'); |
|
442
|
|
|
} |
|
443
|
|
|
|
|
444
|
|
|
/** |
|
445
|
|
|
* Show and manage all group requests. |
|
446
|
|
|
*/ |
|
447
|
|
|
function GroupRequests() |
|
448
|
|
|
{ |
|
449
|
|
|
global $txt, $context, $scripturl, $user_info, $sourcedir, $smcFunc, $modSettings; |
|
450
|
|
|
|
|
451
|
|
|
// Set up the template stuff... |
|
452
|
|
|
$context['page_title'] = $txt['mc_group_requests']; |
|
453
|
|
|
$context['sub_template'] = 'show_list'; |
|
454
|
|
|
|
|
455
|
|
|
// Verify we can be here. |
|
456
|
|
|
if ($user_info['mod_cache']['gq'] == '0=1') |
|
457
|
|
|
isAllowedTo('manage_membergroups'); |
|
458
|
|
|
|
|
459
|
|
|
// Normally, we act normally... |
|
460
|
|
|
$where = ($user_info['mod_cache']['gq'] == '1=1' || $user_info['mod_cache']['gq'] == '0=1' ? $user_info['mod_cache']['gq'] : 'lgr.' . $user_info['mod_cache']['gq']); |
|
461
|
|
|
|
|
462
|
|
|
if (isset($_GET['closed'])) |
|
463
|
|
|
$where .= ' AND lgr.status != {int:status_open}'; |
|
464
|
|
|
else |
|
465
|
|
|
$where .= ' AND lgr.status = {int:status_open}'; |
|
466
|
|
|
|
|
467
|
|
|
$where_parameters = array( |
|
468
|
|
|
'status_open' => 0, |
|
469
|
|
|
); |
|
470
|
|
|
|
|
471
|
|
|
// We've submitted? |
|
472
|
|
|
if (isset($_POST[$context['session_var']]) && !empty($_POST['groupr']) && !empty($_POST['req_action'])) |
|
473
|
|
|
{ |
|
474
|
|
|
checkSession(); |
|
475
|
|
|
validateToken('mod-gr'); |
|
476
|
|
|
|
|
477
|
|
|
// Clean the values. |
|
478
|
|
|
foreach ($_POST['groupr'] as $k => $request) |
|
479
|
|
|
$_POST['groupr'][$k] = (int) $request; |
|
480
|
|
|
|
|
481
|
|
|
$log_changes = array(); |
|
482
|
|
|
|
|
483
|
|
|
// If we are giving a reason (And why shouldn't we?), then we don't actually do much. |
|
484
|
|
|
if ($_POST['req_action'] == 'reason') |
|
485
|
|
|
{ |
|
486
|
|
|
// Different sub template... |
|
487
|
|
|
$context['sub_template'] = 'group_request_reason'; |
|
488
|
|
|
// And a limitation. We don't care that the page number bit makes no sense, as we don't need it! |
|
489
|
|
|
$where .= ' AND lgr.id_request IN ({array_int:request_ids})'; |
|
490
|
|
|
$where_parameters['request_ids'] = $_POST['groupr']; |
|
491
|
|
|
|
|
492
|
|
|
$context['group_requests'] = list_getGroupRequests(0, $modSettings['defaultMaxListItems'], 'lgr.id_request', $where, $where_parameters); |
|
|
|
|
|
|
493
|
|
|
|
|
494
|
|
|
// Need to make another token for this. |
|
495
|
|
|
createToken('mod-gr'); |
|
496
|
|
|
|
|
497
|
|
|
// Let obExit etc sort things out. |
|
498
|
|
|
obExit(); |
|
499
|
|
|
} |
|
500
|
|
|
// Otherwise we do something! |
|
501
|
|
|
else |
|
502
|
|
|
{ |
|
503
|
|
|
$request = $smcFunc['db_query']('', ' |
|
504
|
|
|
SELECT lgr.id_request |
|
505
|
|
|
FROM {db_prefix}log_group_requests AS lgr |
|
506
|
|
|
WHERE ' . $where . ' |
|
507
|
|
|
AND lgr.id_request IN ({array_int:request_list})', |
|
508
|
|
|
array( |
|
509
|
|
|
'request_list' => $_POST['groupr'], |
|
510
|
|
|
'status_open' => 0, |
|
511
|
|
|
) |
|
512
|
|
|
); |
|
513
|
|
|
$request_list = array(); |
|
514
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
515
|
|
|
{ |
|
516
|
|
|
if (!isset($log_changes[$row['id_request']])) |
|
517
|
|
|
$log_changes[$row['id_request']] = array( |
|
518
|
|
|
'id_request' => $row['id_request'], |
|
519
|
|
|
'status' => $_POST['req_action'] == 'approve' ? 1 : 2, // 1 = approved, 2 = rejected |
|
520
|
|
|
'id_member_acted' => $user_info['id'], |
|
521
|
|
|
'member_name_acted' => $user_info['name'], |
|
522
|
|
|
'time_acted' => time(), |
|
523
|
|
|
'act_reason' => $_POST['req_action'] != 'approve' && !empty($_POST['groupreason']) && !empty($_POST['groupreason'][$row['id_request']]) ? $smcFunc['htmlspecialchars']($_POST['groupreason'][$row['id_request']], ENT_QUOTES) : '', |
|
524
|
|
|
); |
|
525
|
|
|
$request_list[] = $row['id_request']; |
|
526
|
|
|
} |
|
527
|
|
|
$smcFunc['db_free_result']($request); |
|
528
|
|
|
|
|
529
|
|
|
// Add a background task to handle notifying people of this request |
|
530
|
|
|
$data = json_encode(array('member_id' => $user_info['id'], 'member_ip' => $user_info['ip'], 'request_list' => $request_list, 'status' => $_POST['req_action'], 'reason' => isset($_POST['groupreason']) ? $_POST['groupreason'] : '', 'time' => time())); |
|
531
|
|
|
$smcFunc['db_insert']('insert', '{db_prefix}background_tasks', |
|
532
|
|
|
array('task_file' => 'string-255', 'task_class' => 'string-255', 'task_data' => 'string', 'claimed_time' => 'int'), |
|
533
|
|
|
array('$sourcedir/tasks/GroupAct-Notify.php', 'GroupAct_Notify_Background', $data, 0), array() |
|
534
|
|
|
); |
|
535
|
|
|
|
|
536
|
|
|
// Some changes to log? |
|
537
|
|
|
if (!empty($log_changes)) |
|
538
|
|
|
{ |
|
539
|
|
|
foreach ($log_changes as $id_request => $details) |
|
540
|
|
|
{ |
|
541
|
|
|
$smcFunc['db_query']('', ' |
|
542
|
|
|
UPDATE {db_prefix}log_group_requests |
|
543
|
|
|
SET status = {int:status}, |
|
544
|
|
|
id_member_acted = {int:id_member_acted}, |
|
545
|
|
|
member_name_acted = {string:member_name_acted}, |
|
546
|
|
|
time_acted = {int:time_acted}, |
|
547
|
|
|
act_reason = {string:act_reason} |
|
548
|
|
|
WHERE id_request = {int:id_request}', |
|
549
|
|
|
$details |
|
550
|
|
|
); |
|
551
|
|
|
} |
|
552
|
|
|
} |
|
553
|
|
|
} |
|
554
|
|
|
} |
|
555
|
|
|
|
|
556
|
|
|
// We're going to want this for making our list. |
|
557
|
|
|
require_once($sourcedir . '/Subs-List.php'); |
|
558
|
|
|
|
|
559
|
|
|
// This is all the information required for a group listing. |
|
560
|
|
|
$listOptions = array( |
|
561
|
|
|
'id' => 'group_request_list', |
|
562
|
|
|
'width' => '100%', |
|
563
|
|
|
'items_per_page' => $modSettings['defaultMaxListItems'], |
|
564
|
|
|
'no_items_label' => $txt['mc_groupr_none_found'], |
|
565
|
|
|
'base_href' => $scripturl . '?action=groups;sa=requests', |
|
566
|
|
|
'default_sort_col' => 'member', |
|
567
|
|
|
'get_items' => array( |
|
568
|
|
|
'function' => 'list_getGroupRequests', |
|
569
|
|
|
'params' => array( |
|
570
|
|
|
$where, |
|
571
|
|
|
$where_parameters, |
|
572
|
|
|
), |
|
573
|
|
|
), |
|
574
|
|
|
'get_count' => array( |
|
575
|
|
|
'function' => 'list_getGroupRequestCount', |
|
576
|
|
|
'params' => array( |
|
577
|
|
|
$where, |
|
578
|
|
|
$where_parameters, |
|
579
|
|
|
), |
|
580
|
|
|
), |
|
581
|
|
|
'columns' => array( |
|
582
|
|
|
'member' => array( |
|
583
|
|
|
'header' => array( |
|
584
|
|
|
'value' => $txt['mc_groupr_member'], |
|
585
|
|
|
), |
|
586
|
|
|
'data' => array( |
|
587
|
|
|
'db' => 'member_link', |
|
588
|
|
|
), |
|
589
|
|
|
'sort' => array( |
|
590
|
|
|
'default' => 'mem.member_name', |
|
591
|
|
|
'reverse' => 'mem.member_name DESC', |
|
592
|
|
|
), |
|
593
|
|
|
), |
|
594
|
|
|
'group' => array( |
|
595
|
|
|
'header' => array( |
|
596
|
|
|
'value' => $txt['mc_groupr_group'], |
|
597
|
|
|
), |
|
598
|
|
|
'data' => array( |
|
599
|
|
|
'db' => 'group_link', |
|
600
|
|
|
), |
|
601
|
|
|
'sort' => array( |
|
602
|
|
|
'default' => 'mg.group_name', |
|
603
|
|
|
'reverse' => 'mg.group_name DESC', |
|
604
|
|
|
), |
|
605
|
|
|
), |
|
606
|
|
|
'reason' => array( |
|
607
|
|
|
'header' => array( |
|
608
|
|
|
'value' => $txt['mc_groupr_reason'], |
|
609
|
|
|
), |
|
610
|
|
|
'data' => array( |
|
611
|
|
|
'db' => 'reason', |
|
612
|
|
|
), |
|
613
|
|
|
), |
|
614
|
|
|
'date' => array( |
|
615
|
|
|
'header' => array( |
|
616
|
|
|
'value' => $txt['date'], |
|
617
|
|
|
'style' => 'width: 18%; white-space:nowrap;', |
|
618
|
|
|
), |
|
619
|
|
|
'data' => array( |
|
620
|
|
|
'db' => 'time_submitted', |
|
621
|
|
|
), |
|
622
|
|
|
), |
|
623
|
|
|
'action' => array( |
|
624
|
|
|
'header' => array( |
|
625
|
|
|
'value' => '<input type="checkbox" class="input_check" onclick="invertAll(this, this.form);">', |
|
626
|
|
|
'style' => 'width: 4%;', |
|
627
|
|
|
'class' => 'centercol', |
|
628
|
|
|
), |
|
629
|
|
|
'data' => array( |
|
630
|
|
|
'sprintf' => array( |
|
631
|
|
|
'format' => '<input type="checkbox" name="groupr[]" value="%1$d" class="input_check">', |
|
632
|
|
|
'params' => array( |
|
633
|
|
|
'id' => false, |
|
634
|
|
|
), |
|
635
|
|
|
), |
|
636
|
|
|
'class' => 'centercol', |
|
637
|
|
|
), |
|
638
|
|
|
), |
|
639
|
|
|
), |
|
640
|
|
|
'form' => array( |
|
641
|
|
|
'href' => $scripturl . '?action=groups;sa=requests', |
|
642
|
|
|
'include_sort' => true, |
|
643
|
|
|
'include_start' => true, |
|
644
|
|
|
'hidden_fields' => array( |
|
645
|
|
|
$context['session_var'] => $context['session_id'], |
|
646
|
|
|
), |
|
647
|
|
|
'token' => 'mod-gr', |
|
648
|
|
|
), |
|
649
|
|
|
'additional_rows' => array( |
|
650
|
|
|
array( |
|
651
|
|
|
'position' => 'bottom_of_list', |
|
652
|
|
|
'value' => ' |
|
653
|
|
|
<select name="req_action" onchange="if (this.value != 0 && (this.value == \'reason\' || confirm(\'' . $txt['mc_groupr_warning'] . '\'))) this.form.submit();"> |
|
654
|
|
|
<option value="0">' . $txt['with_selected'] . ':</option> |
|
655
|
|
|
<option value="0" disabled>---------------------</option> |
|
656
|
|
|
<option value="approve">' . $txt['mc_groupr_approve'] . '</option> |
|
657
|
|
|
<option value="reject">' . $txt['mc_groupr_reject'] . '</option> |
|
658
|
|
|
<option value="reason">' . $txt['mc_groupr_reject_w_reason'] . '</option> |
|
659
|
|
|
</select> |
|
660
|
|
|
<input type="submit" name="go" value="' . $txt['go'] . '" onclick="var sel = document.getElementById(\'req_action\'); if (sel.value != 0 && sel.value != \'reason\' && !confirm(\'' . $txt['mc_groupr_warning'] . '\')) return false;" class="button_submit">', |
|
661
|
|
|
'class' => 'floatright', |
|
662
|
|
|
), |
|
663
|
|
|
), |
|
664
|
|
|
); |
|
665
|
|
|
|
|
666
|
|
|
if (isset($_GET['closed'])) |
|
667
|
|
|
{ |
|
668
|
|
|
// Closed requests don't require interaction. |
|
669
|
|
|
unset($listOptions['columns']['action'], $listOptions['form'], $listOptions['additional_rows'][0]); |
|
670
|
|
|
$listOptions['base_href'] .= 'closed'; |
|
671
|
|
|
} |
|
672
|
|
|
|
|
673
|
|
|
// Create the request list. |
|
674
|
|
|
createToken('mod-gr'); |
|
675
|
|
|
createList($listOptions); |
|
676
|
|
|
|
|
677
|
|
|
$context['default_list'] = 'group_request_list'; |
|
678
|
|
|
$context[$context['moderation_menu_name']]['tab_data'] = array( |
|
679
|
|
|
'title' => $txt['mc_group_requests'], |
|
680
|
|
|
); |
|
681
|
|
|
} |
|
682
|
|
|
|
|
683
|
|
|
/** |
|
684
|
|
|
* Callback function for createList(). |
|
685
|
|
|
* |
|
686
|
|
|
* @param string $where The WHERE clause for the query |
|
687
|
|
|
* @param array $where_parameters The parameters for the WHERE clause |
|
688
|
|
|
* @return int The number of group requests |
|
689
|
|
|
*/ |
|
690
|
|
View Code Duplication |
function list_getGroupRequestCount($where, $where_parameters) |
|
|
|
|
|
|
691
|
|
|
{ |
|
692
|
|
|
global $smcFunc; |
|
693
|
|
|
|
|
694
|
|
|
$request = $smcFunc['db_query']('', ' |
|
695
|
|
|
SELECT COUNT(*) |
|
696
|
|
|
FROM {db_prefix}log_group_requests AS lgr |
|
697
|
|
|
WHERE ' . $where, |
|
698
|
|
|
array_merge($where_parameters, array( |
|
699
|
|
|
)) |
|
700
|
|
|
); |
|
701
|
|
|
list ($totalRequests) = $smcFunc['db_fetch_row']($request); |
|
702
|
|
|
$smcFunc['db_free_result']($request); |
|
703
|
|
|
|
|
704
|
|
|
return $totalRequests; |
|
705
|
|
|
} |
|
706
|
|
|
|
|
707
|
|
|
/** |
|
708
|
|
|
* Callback function for createList() |
|
709
|
|
|
* |
|
710
|
|
|
* @param int $start The result to start with |
|
711
|
|
|
* @param int $items_per_page The number of items per page |
|
712
|
|
|
* @param string $sort An SQL sort expression (column/direction) |
|
713
|
|
|
* @param string $where Data for the WHERE clause |
|
714
|
|
|
* @param string $where_parameters Parameter values to be inserted into the WHERE clause |
|
715
|
|
|
* @return array An array of group requests |
|
716
|
|
|
* Each group request has: |
|
717
|
|
|
* 'id' |
|
718
|
|
|
* 'member_link' |
|
719
|
|
|
* 'group_link' |
|
720
|
|
|
* 'reason' |
|
721
|
|
|
* 'time_submitted' |
|
722
|
|
|
*/ |
|
723
|
|
|
function list_getGroupRequests($start, $items_per_page, $sort, $where, $where_parameters) |
|
724
|
|
|
{ |
|
725
|
|
|
global $smcFunc, $scripturl, $txt; |
|
726
|
|
|
|
|
727
|
|
|
$request = $smcFunc['db_query']('', ' |
|
728
|
|
|
SELECT |
|
729
|
|
|
lgr.id_request, lgr.id_member, lgr.id_group, lgr.time_applied, lgr.reason, |
|
730
|
|
|
lgr.status, lgr.id_member_acted, lgr.member_name_acted, lgr.time_acted, lgr.act_reason, |
|
731
|
|
|
mem.member_name, mg.group_name, mg.online_color, mem.real_name |
|
732
|
|
|
FROM {db_prefix}log_group_requests AS lgr |
|
733
|
|
|
INNER JOIN {db_prefix}members AS mem ON (mem.id_member = lgr.id_member) |
|
734
|
|
|
INNER JOIN {db_prefix}membergroups AS mg ON (mg.id_group = lgr.id_group) |
|
735
|
|
|
WHERE ' . $where . ' |
|
736
|
|
|
ORDER BY {raw:sort} |
|
737
|
|
|
LIMIT {int:start}, {int:max}', |
|
738
|
|
|
array_merge($where_parameters, array( |
|
739
|
|
|
'sort' => $sort, |
|
740
|
|
|
'start' => $start, |
|
741
|
|
|
'max' => $items_per_page, |
|
742
|
|
|
)) |
|
743
|
|
|
); |
|
744
|
|
|
$group_requests = array(); |
|
745
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
746
|
|
|
{ |
|
747
|
|
|
if (empty($row['reason'])) |
|
748
|
|
|
$reason = '<em>(' . $txt['mc_groupr_no_reason'] . ')</em>'; |
|
749
|
|
|
else |
|
750
|
|
|
$reason = censorText($row['reason']); |
|
751
|
|
|
|
|
752
|
|
|
if (isset($_GET['closed'])) |
|
753
|
|
|
{ |
|
754
|
|
|
if ($row['status'] == 1) |
|
755
|
|
|
$reason .= '<br><br><strong>' . $txt['mc_groupr_approved'] . '</strong>'; |
|
756
|
|
|
elseif ($row['status'] == 2) |
|
757
|
|
|
$reason .= '<br><br><strong>' . $txt['mc_groupr_rejected'] . '</strong>'; |
|
758
|
|
|
|
|
759
|
|
|
$reason .= ' (' . timeformat($row['time_acted']) . ')'; |
|
760
|
|
|
if (!empty($row['act_reason'])) |
|
761
|
|
|
$reason .= '<br><br>' . censorText($row['act_reason']); |
|
762
|
|
|
} |
|
763
|
|
|
|
|
764
|
|
|
$group_requests[] = array( |
|
765
|
|
|
'id' => $row['id_request'], |
|
766
|
|
|
'member_link' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>', |
|
767
|
|
|
'group_link' => '<span style="color: ' . $row['online_color'] . '">' . $row['group_name'] . '</span>', |
|
768
|
|
|
'reason' => $reason, |
|
769
|
|
|
'time_submitted' => timeformat($row['time_applied']), |
|
770
|
|
|
); |
|
771
|
|
|
} |
|
772
|
|
|
$smcFunc['db_free_result']($request); |
|
773
|
|
|
|
|
774
|
|
|
return $group_requests; |
|
775
|
|
|
} |
|
776
|
|
|
|
|
777
|
|
|
?> |
|
|
|
|
|
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.