1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* This file is here to make it easier for installed mods to have |
5
|
|
|
* settings and options. |
6
|
|
|
* |
7
|
|
|
* Simple Machines Forum (SMF) |
8
|
|
|
* |
9
|
|
|
* @package SMF |
10
|
|
|
* @author Simple Machines https://www.simplemachines.org |
11
|
|
|
* @copyright 2022 Simple Machines and individual contributors |
12
|
|
|
* @license https://www.simplemachines.org/about/smf/license.php BSD |
13
|
|
|
* |
14
|
|
|
* @version 2.1.2 |
15
|
|
|
*/ |
16
|
|
|
|
17
|
|
|
if (!defined('SMF')) |
18
|
|
|
die('No direct access...'); |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* This function makes sure the requested subaction does exists, if it doesn't, it sets a default action or. |
22
|
|
|
* |
23
|
|
|
* @param array $subActions An array containing all possible subactions. |
24
|
|
|
* @param string $defaultAction The default action to be called if no valid subaction was found. |
25
|
|
|
*/ |
26
|
|
|
function loadGeneralSettingParameters($subActions = array(), $defaultAction = null) |
27
|
|
|
{ |
28
|
|
|
global $context, $sourcedir; |
29
|
|
|
|
30
|
|
|
// You need to be an admin to edit settings! |
31
|
|
|
isAllowedTo('admin_forum'); |
32
|
|
|
|
33
|
|
|
// Will need the utility functions from here. |
34
|
|
|
require_once($sourcedir . '/ManageServer.php'); |
35
|
|
|
|
36
|
|
|
$context['sub_template'] = 'show_settings'; |
37
|
|
|
|
38
|
|
|
// If no fallback was specified, use the first subaction. |
39
|
|
|
$defaultAction = $defaultAction ?: key($subActions); |
40
|
|
|
|
41
|
|
|
// I want... |
42
|
|
|
$_REQUEST['sa'] = isset($_REQUEST['sa'], $subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : $defaultAction; |
43
|
|
|
$context['sub_action'] = $_REQUEST['sa']; |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* This function passes control through to the relevant tab. |
48
|
|
|
*/ |
49
|
|
|
function ModifyFeatureSettings() |
50
|
|
|
{ |
51
|
|
|
global $context, $txt, $settings, $scripturl, $modSettings, $language; |
52
|
|
|
|
53
|
|
|
loadLanguage('Help'); |
54
|
|
|
loadLanguage('ManageSettings'); |
55
|
|
|
|
56
|
|
|
$context['page_title'] = $txt['modSettings_title']; |
57
|
|
|
$context['show_privacy_policy_warning'] = empty($modSettings['policy_' . $language]); |
58
|
|
|
|
59
|
|
|
$subActions = array( |
60
|
|
|
'basic' => 'ModifyBasicSettings', |
61
|
|
|
'bbc' => 'ModifyBBCSettings', |
62
|
|
|
'layout' => 'ModifyLayoutSettings', |
63
|
|
|
'sig' => 'ModifySignatureSettings', |
64
|
|
|
'profile' => 'ShowCustomProfiles', |
65
|
|
|
'profileedit' => 'EditCustomProfiles', |
66
|
|
|
'likes' => 'ModifyLikesSettings', |
67
|
|
|
'mentions' => 'ModifyMentionsSettings', |
68
|
|
|
'alerts' => 'ModifyAlertsSettings', |
69
|
|
|
); |
70
|
|
|
|
71
|
|
|
// Load up all the tabs... |
72
|
|
|
$context[$context['admin_menu_name']]['tab_data'] = array( |
73
|
|
|
'title' => $txt['modSettings_title'], |
74
|
|
|
'help' => 'featuresettings', |
75
|
|
|
'description' => sprintf($txt['modSettings_desc'], $settings['theme_id'], $context['session_id'], $context['session_var'], $scripturl), |
76
|
|
|
'tabs' => array( |
77
|
|
|
'basic' => array( |
78
|
|
|
), |
79
|
|
|
'bbc' => array( |
80
|
|
|
'description' => $txt['manageposts_bbc_settings_description'], |
81
|
|
|
), |
82
|
|
|
'layout' => array( |
83
|
|
|
), |
84
|
|
|
'sig' => array( |
85
|
|
|
'description' => $txt['signature_settings_desc'], |
86
|
|
|
), |
87
|
|
|
'profile' => array( |
88
|
|
|
'description' => $txt['custom_profile_desc'], |
89
|
|
|
), |
90
|
|
|
'likes' => array( |
91
|
|
|
), |
92
|
|
|
'mentions' => array( |
93
|
|
|
), |
94
|
|
|
'alerts' => array( |
95
|
|
|
'description' => $txt['notifications_desc'], |
96
|
|
|
), |
97
|
|
|
), |
98
|
|
|
); |
99
|
|
|
|
100
|
|
|
call_integration_hook('integrate_modify_features', array(&$subActions)); |
101
|
|
|
|
102
|
|
|
loadGeneralSettingParameters($subActions, 'basic'); |
103
|
|
|
|
104
|
|
|
// Call the right function for this sub-action. |
105
|
|
|
call_helper($subActions[$_REQUEST['sa']]); |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* This my friend, is for all the mod authors out there. |
110
|
|
|
*/ |
111
|
|
|
function ModifyModSettings() |
112
|
|
|
{ |
113
|
|
|
global $context, $txt; |
114
|
|
|
|
115
|
|
|
loadLanguage('Help'); |
116
|
|
|
loadLanguage('ManageSettings'); |
117
|
|
|
|
118
|
|
|
$context['page_title'] = $txt['admin_modifications']; |
119
|
|
|
|
120
|
|
|
$subActions = array( |
121
|
|
|
'general' => 'ModifyGeneralModSettings', |
122
|
|
|
// Mod authors, once again, if you have a whole section to add do it AFTER this line, and keep a comma at the end. |
123
|
|
|
); |
124
|
|
|
|
125
|
|
|
// Load up all the tabs... |
126
|
|
|
$context[$context['admin_menu_name']]['tab_data'] = array( |
127
|
|
|
'title' => $txt['admin_modifications'], |
128
|
|
|
'help' => 'modsettings', |
129
|
|
|
'description' => $txt['modification_settings_desc'], |
130
|
|
|
'tabs' => array( |
131
|
|
|
'general' => array( |
132
|
|
|
), |
133
|
|
|
), |
134
|
|
|
); |
135
|
|
|
|
136
|
|
|
// Make it easier for mods to add new areas. |
137
|
|
|
call_integration_hook('integrate_modify_modifications', array(&$subActions)); |
138
|
|
|
|
139
|
|
|
loadGeneralSettingParameters($subActions, 'general'); |
140
|
|
|
|
141
|
|
|
// Call the right function for this sub-action. |
142
|
|
|
call_helper($subActions[$_REQUEST['sa']]); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* Config array for changing the basic forum settings |
147
|
|
|
* Accessed from ?action=admin;area=featuresettings;sa=basic; |
148
|
|
|
* |
149
|
|
|
* @param bool $return_config Whether or not to return the config_vars array (used for admin search) |
150
|
|
|
* @return void|array Returns nothing or returns the $config_vars array if $return_config is true |
151
|
|
|
*/ |
152
|
|
|
function ModifyBasicSettings($return_config = false) |
153
|
|
|
{ |
154
|
|
|
global $txt, $scripturl, $context, $modSettings, $sourcedir; |
155
|
|
|
|
156
|
|
|
// We need to know if personal text is enabled, and if it's in the registration fields option. |
157
|
|
|
// If admins have set it up as an on-registration thing, they can't set a default value (because it'll never be used) |
158
|
|
|
$disabled_fields = isset($modSettings['disabled_profile_fields']) ? explode(',', $modSettings['disabled_profile_fields']) : array(); |
159
|
|
|
$reg_fields = isset($modSettings['registration_fields']) ? explode(',', $modSettings['registration_fields']) : array(); |
160
|
|
|
$can_personal_text = !in_array('personal_text', $disabled_fields) && !in_array('personal_text', $reg_fields); |
161
|
|
|
|
162
|
|
|
$config_vars = array( |
163
|
|
|
// Big Options... polls, sticky, bbc.... |
164
|
|
|
array('select', 'pollMode', array($txt['disable_polls'], $txt['enable_polls'], $txt['polls_as_topics'])), |
165
|
|
|
'', |
166
|
|
|
|
167
|
|
|
// Basic stuff, titles, flash, permissions... |
168
|
|
|
array('check', 'allow_guestAccess'), |
169
|
|
|
array('check', 'enable_buddylist'), |
170
|
|
|
array('check', 'allow_hideOnline'), |
171
|
|
|
array('check', 'titlesEnable'), |
172
|
|
|
array('text', 'default_personal_text', 'subtext' => $txt['default_personal_text_note'], 'disabled' => !$can_personal_text), |
173
|
|
|
array('check', 'topic_move_any'), |
174
|
|
|
array('int', 'defaultMaxListItems', 'step' => 1, 'min' => 1, 'max' => 999), |
175
|
|
|
'', |
176
|
|
|
|
177
|
|
|
// Jquery source |
178
|
|
|
array( |
179
|
|
|
'select', |
180
|
|
|
'jquery_source', |
181
|
|
|
array( |
182
|
|
|
'cdn' => $txt['jquery_google_cdn'], |
183
|
|
|
'jquery_cdn' => $txt['jquery_jquery_cdn'], |
184
|
|
|
'microsoft_cdn' => $txt['jquery_microsoft_cdn'], |
185
|
|
|
'local' => $txt['jquery_local'], |
186
|
|
|
'custom' => $txt['jquery_custom'] |
187
|
|
|
), |
188
|
|
|
'onchange' => 'if (this.value == \'custom\'){document.getElementById(\'jquery_custom\').disabled = false; } else {document.getElementById(\'jquery_custom\').disabled = true;}' |
189
|
|
|
), |
190
|
|
|
array( |
191
|
|
|
'text', |
192
|
|
|
'jquery_custom', |
193
|
|
|
'disabled' => !isset($modSettings['jquery_source']) || (isset($modSettings['jquery_source']) && $modSettings['jquery_source'] != 'custom'), 'size' => 75 |
194
|
|
|
), |
195
|
|
|
'', |
196
|
|
|
|
197
|
|
|
// css and js minification. |
198
|
|
|
array('check', 'minimize_files'), |
199
|
|
|
'', |
200
|
|
|
|
201
|
|
|
// SEO stuff |
202
|
|
|
array('check', 'queryless_urls', 'subtext' => '<strong>' . $txt['queryless_urls_note'] . '</strong>'), |
203
|
|
|
array('text', 'meta_keywords', 'subtext' => $txt['meta_keywords_note'], 'size' => 50), |
204
|
|
|
'', |
205
|
|
|
|
206
|
|
|
// Time zone and formatting. |
207
|
|
|
array('text', 'time_format'), |
208
|
|
|
array('select', 'default_timezone', array_filter(smf_list_timezones(), 'is_string', ARRAY_FILTER_USE_KEY)), |
209
|
|
|
array('text', 'timezone_priority_countries', 'subtext' => $txt['setting_timezone_priority_countries_note']), |
210
|
|
|
'', |
211
|
|
|
|
212
|
|
|
// Who's online? |
213
|
|
|
array('check', 'who_enabled'), |
214
|
|
|
array('int', 'lastActive', 6, 'postinput' => $txt['minutes']), |
215
|
|
|
'', |
216
|
|
|
|
217
|
|
|
// Statistics. |
218
|
|
|
array('check', 'trackStats'), |
219
|
|
|
array('check', 'hitStats'), |
220
|
|
|
'', |
221
|
|
|
|
222
|
|
|
// Option-ish things... miscellaneous sorta. |
223
|
|
|
array('check', 'disallow_sendBody'), |
224
|
|
|
'', |
225
|
|
|
|
226
|
|
|
// Alerts stuff |
227
|
|
|
array('check', 'enable_ajax_alerts'), |
228
|
|
|
array('select', 'alerts_auto_purge', |
229
|
|
|
array( |
230
|
|
|
'0' => $txt['alerts_auto_purge_0'], |
231
|
|
|
'7' => $txt['alerts_auto_purge_7'], |
232
|
|
|
'30' => $txt['alerts_auto_purge_30'], |
233
|
|
|
'90' => $txt['alerts_auto_purge_90'], |
234
|
|
|
), |
235
|
|
|
), |
236
|
|
|
array('int', 'alerts_per_page', 'step' => 1, 'min' => 0, 'max' => 999), |
237
|
|
|
); |
238
|
|
|
|
239
|
|
|
call_integration_hook('integrate_modify_basic_settings', array(&$config_vars)); |
240
|
|
|
|
241
|
|
|
if ($return_config) |
242
|
|
|
return $config_vars; |
243
|
|
|
|
244
|
|
|
// Saving? |
245
|
|
|
if (isset($_GET['save'])) |
246
|
|
|
{ |
247
|
|
|
checkSession(); |
248
|
|
|
|
249
|
|
|
// Make sure the country codes are valid. |
250
|
|
|
if (!empty($_POST['timezone_priority_countries'])) |
251
|
|
|
{ |
252
|
|
|
require_once($sourcedir . '/Subs-Timezones.php'); |
253
|
|
|
|
254
|
|
|
$_POST['timezone_priority_countries'] = validate_iso_country_codes($_POST['timezone_priority_countries'], true); |
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
// Prevent absurd boundaries here - make it a day tops. |
258
|
|
|
if (isset($_POST['lastActive'])) |
259
|
|
|
$_POST['lastActive'] = min((int) $_POST['lastActive'], 1440); |
260
|
|
|
|
261
|
|
|
call_integration_hook('integrate_save_basic_settings'); |
262
|
|
|
|
263
|
|
|
saveDBSettings($config_vars); |
264
|
|
|
$_SESSION['adm-save'] = true; |
265
|
|
|
|
266
|
|
|
// Do a bit of housekeeping |
267
|
|
|
if (empty($_POST['minimize_files']) || $_POST['minimize_files'] != $modSettings['minimize_files']) |
268
|
|
|
deleteAllMinified(); |
269
|
|
|
|
270
|
|
|
writeLog(); |
271
|
|
|
redirectexit('action=admin;area=featuresettings;sa=basic'); |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
$context['post_url'] = $scripturl . '?action=admin;area=featuresettings;save;sa=basic'; |
275
|
|
|
$context['settings_title'] = $txt['mods_cat_features']; |
276
|
|
|
|
277
|
|
|
prepareDBSettingContext($config_vars); |
278
|
|
|
} |
279
|
|
|
|
280
|
|
|
/** |
281
|
|
|
* Set a few Bulletin Board Code settings. It loads a list of Bulletin Board Code tags to allow disabling tags. |
282
|
|
|
* Requires the admin_forum permission. |
283
|
|
|
* Accessed from ?action=admin;area=featuresettings;sa=bbc. |
284
|
|
|
* @uses template_show_settings() |
285
|
|
|
* |
286
|
|
|
* @param bool $return_config Whether or not to return the config_vars array (used for admin search) |
287
|
|
|
* @return void|array Returns nothing or returns the $config_vars array if $return_config is true |
288
|
|
|
*/ |
289
|
|
|
function ModifyBBCSettings($return_config = false) |
290
|
|
|
{ |
291
|
|
|
global $context, $txt, $modSettings, $scripturl, $sourcedir; |
292
|
|
|
|
293
|
|
|
$config_vars = array( |
294
|
|
|
// Main tweaks |
295
|
|
|
array('check', 'enableBBC'), |
296
|
|
|
array('check', 'enableBBC', 0, 'onchange' => 'toggleBBCDisabled(\'disabledBBC\', !this.checked); toggleBBCDisabled(\'legacyBBC\', !this.checked);'), |
297
|
|
|
array('check', 'enablePostHTML'), |
298
|
|
|
array('check', 'autoLinkUrls'), |
299
|
|
|
'', |
300
|
|
|
|
301
|
|
|
array('bbc', 'disabledBBC'), |
302
|
|
|
|
303
|
|
|
// This one is actually pretend... |
304
|
|
|
array('bbc', 'legacyBBC', 'help' => 'legacy_bbc'), |
305
|
|
|
); |
306
|
|
|
|
307
|
|
|
// Permissions for restricted BBC |
308
|
|
|
if (!empty($context['restricted_bbc'])) |
309
|
|
|
$config_vars[] = ''; |
310
|
|
|
|
311
|
|
|
foreach ($context['restricted_bbc'] as $bbc) |
312
|
|
|
$config_vars[] = array('permissions', 'bbc_' . $bbc, 'text_label' => sprintf($txt['groups_can_use'], '[' . $bbc . ']')); |
313
|
|
|
|
314
|
|
|
$context['settings_post_javascript'] = ' |
315
|
|
|
toggleBBCDisabled(\'disabledBBC\', ' . (empty($modSettings['enableBBC']) ? 'true' : 'false') . '); |
316
|
|
|
toggleBBCDisabled(\'legacyBBC\', ' . (empty($modSettings['enableBBC']) ? 'true' : 'false') . ');'; |
317
|
|
|
|
318
|
|
|
call_integration_hook('integrate_modify_bbc_settings', array(&$config_vars)); |
319
|
|
|
|
320
|
|
|
if ($return_config) |
321
|
|
|
return $config_vars; |
322
|
|
|
|
323
|
|
|
// Setup the template. |
324
|
|
|
require_once($sourcedir . '/ManageServer.php'); |
325
|
|
|
$context['sub_template'] = 'show_settings'; |
326
|
|
|
$context['page_title'] = $txt['manageposts_bbc_settings_title']; |
327
|
|
|
|
328
|
|
|
// Make sure we check the right tags! |
329
|
|
|
$modSettings['bbc_disabled_disabledBBC'] = empty($modSettings['disabledBBC']) ? array() : explode(',', $modSettings['disabledBBC']); |
330
|
|
|
|
331
|
|
|
// Legacy BBC are listed separately, but we use the same info in both cases |
332
|
|
|
$modSettings['bbc_disabled_legacyBBC'] = $modSettings['bbc_disabled_disabledBBC']; |
333
|
|
|
|
334
|
|
|
$extra = ''; |
335
|
|
|
if (isset($_REQUEST['cowsay'])) |
336
|
|
|
{ |
337
|
|
|
$config_vars[] = array('permissions', 'bbc_cowsay', 'text_label' => sprintf($txt['groups_can_use'], '[cowsay]')); |
338
|
|
|
$extra = ';cowsay'; |
339
|
|
|
} |
340
|
|
|
|
341
|
|
|
// Saving? |
342
|
|
|
if (isset($_GET['save'])) |
343
|
|
|
{ |
344
|
|
|
checkSession(); |
345
|
|
|
|
346
|
|
|
// Clean up the tags. |
347
|
|
|
$bbcTags = array(); |
348
|
|
|
$bbcTagsChildren = array(); |
349
|
|
|
foreach (parse_bbc(false) as $tag) |
350
|
|
|
{ |
351
|
|
|
$bbcTags[] = $tag['tag']; |
352
|
|
|
if (isset($tag['require_children'])) |
353
|
|
|
$bbcTagsChildren[$tag['tag']] = !isset($bbcTagsChildren[$tag['tag']]) ? $tag['require_children'] : array_unique(array_merge($bbcTagsChildren[$tag['tag']], $tag['require_children'])); |
354
|
|
|
} |
355
|
|
|
|
356
|
|
|
// Clean up tags with children |
357
|
|
|
foreach($bbcTagsChildren as $parent_tag => $children) |
358
|
|
|
foreach($children as $index => $child_tag) |
359
|
|
|
{ |
360
|
|
|
// Remove entries where parent and child tag is the same |
361
|
|
|
if ($child_tag == $parent_tag) |
362
|
|
|
{ |
363
|
|
|
unset($bbcTagsChildren[$parent_tag][$index]); |
364
|
|
|
continue; |
365
|
|
|
} |
366
|
|
|
// Combine chains of tags |
367
|
|
|
if (isset($bbcTagsChildren[$child_tag])) |
368
|
|
|
{ |
369
|
|
|
$bbcTagsChildren[$parent_tag] = array_merge($bbcTagsChildren[$parent_tag], $bbcTagsChildren[$child_tag]); |
370
|
|
|
unset($bbcTagsChildren[$child_tag]); |
371
|
|
|
} |
372
|
|
|
} |
373
|
|
|
|
374
|
|
|
if (!isset($_POST['disabledBBC_enabledTags'])) |
375
|
|
|
$_POST['disabledBBC_enabledTags'] = array(); |
376
|
|
|
elseif (!is_array($_POST['disabledBBC_enabledTags'])) |
377
|
|
|
$_POST['disabledBBC_enabledTags'] = array($_POST['disabledBBC_enabledTags']); |
378
|
|
|
|
379
|
|
|
if (!isset($_POST['legacyBBC_enabledTags'])) |
380
|
|
|
$_POST['legacyBBC_enabledTags'] = array(); |
381
|
|
|
elseif (!is_array($_POST['legacyBBC_enabledTags'])) |
382
|
|
|
$_POST['legacyBBC_enabledTags'] = array($_POST['legacyBBC_enabledTags']); |
383
|
|
|
|
384
|
|
|
$_POST['disabledBBC_enabledTags'] = array_unique(array_merge($_POST['disabledBBC_enabledTags'], $_POST['legacyBBC_enabledTags'])); |
385
|
|
|
|
386
|
|
|
// Enable all children if parent is enabled |
387
|
|
|
foreach ($bbcTagsChildren as $tag => $children) |
388
|
|
|
if (in_array($tag, $_POST['disabledBBC_enabledTags'])) |
389
|
|
|
$_POST['disabledBBC_enabledTags'] = array_merge($_POST['disabledBBC_enabledTags'], $children); |
390
|
|
|
|
391
|
|
|
// Work out what is actually disabled! |
392
|
|
|
$_POST['disabledBBC'] = implode(',', array_diff($bbcTags, $_POST['disabledBBC_enabledTags'])); |
393
|
|
|
|
394
|
|
|
// $modSettings['legacyBBC'] isn't really a thing... |
395
|
|
|
unset($_POST['legacyBBC_enabledTags']); |
396
|
|
|
$config_vars = array_filter($config_vars, function($config_var) |
397
|
|
|
{ |
398
|
|
|
return !isset($config_var[1]) || $config_var[1] != 'legacyBBC'; |
399
|
|
|
}); |
400
|
|
|
|
401
|
|
|
call_integration_hook('integrate_save_bbc_settings', array($bbcTags)); |
402
|
|
|
|
403
|
|
|
saveDBSettings($config_vars); |
404
|
|
|
$_SESSION['adm-save'] = true; |
405
|
|
|
redirectexit('action=admin;area=featuresettings;sa=bbc' . $extra); |
406
|
|
|
} |
407
|
|
|
|
408
|
|
|
$context['post_url'] = $scripturl . '?action=admin;area=featuresettings;save;sa=bbc' . $extra; |
409
|
|
|
$context['settings_title'] = $txt['manageposts_bbc_settings_title']; |
410
|
|
|
|
411
|
|
|
prepareDBSettingContext($config_vars); |
412
|
|
|
} |
413
|
|
|
|
414
|
|
|
/** |
415
|
|
|
* Allows modifying the global layout settings in the forum |
416
|
|
|
* Accessed through ?action=admin;area=featuresettings;sa=layout; |
417
|
|
|
* |
418
|
|
|
* @param bool $return_config Whether or not to return the config_vars array (used for admin search) |
419
|
|
|
* @return void|array Returns nothing or returns the $config_vars array if $return_config is true |
420
|
|
|
*/ |
421
|
|
|
function ModifyLayoutSettings($return_config = false) |
422
|
|
|
{ |
423
|
|
|
global $txt, $scripturl, $context; |
424
|
|
|
|
425
|
|
|
$config_vars = array( |
426
|
|
|
// Pagination stuff. |
427
|
|
|
array('check', 'compactTopicPagesEnable'), |
428
|
|
|
array( |
429
|
|
|
'int', |
430
|
|
|
'compactTopicPagesContiguous', |
431
|
|
|
null, |
432
|
|
|
$txt['contiguous_page_display'] . '<div class="smalltext">' . str_replace(' ', ' ', '"3" ' . $txt['to_display'] . ': <strong>1 ... 4 [5] 6 ... 9</strong>') . '<br>' . str_replace(' ', ' ', '"5" ' . $txt['to_display'] . ': <strong>1 ... 3 4 [5] 6 7 ... 9</strong>') . '</div>' |
433
|
|
|
), |
434
|
|
|
array('int', 'defaultMaxMembers'), |
435
|
|
|
'', |
436
|
|
|
|
437
|
|
|
// Stuff that just is everywhere - today, search, online, etc. |
438
|
|
|
array('select', 'todayMod', array($txt['today_disabled'], $txt['today_only'], $txt['yesterday_today'])), |
439
|
|
|
array('check', 'onlineEnable'), |
440
|
|
|
'', |
441
|
|
|
|
442
|
|
|
// This is like debugging sorta. |
443
|
|
|
array('check', 'timeLoadPageEnable'), |
444
|
|
|
); |
445
|
|
|
|
446
|
|
|
call_integration_hook('integrate_layout_settings', array(&$config_vars)); |
447
|
|
|
|
448
|
|
|
if ($return_config) |
449
|
|
|
return $config_vars; |
450
|
|
|
|
451
|
|
|
// Saving? |
452
|
|
|
if (isset($_GET['save'])) |
453
|
|
|
{ |
454
|
|
|
checkSession(); |
455
|
|
|
|
456
|
|
|
call_integration_hook('integrate_save_layout_settings'); |
457
|
|
|
|
458
|
|
|
saveDBSettings($config_vars); |
459
|
|
|
$_SESSION['adm-save'] = true; |
460
|
|
|
writeLog(); |
461
|
|
|
|
462
|
|
|
redirectexit('action=admin;area=featuresettings;sa=layout'); |
463
|
|
|
} |
464
|
|
|
|
465
|
|
|
$context['post_url'] = $scripturl . '?action=admin;area=featuresettings;save;sa=layout'; |
466
|
|
|
$context['settings_title'] = $txt['mods_cat_layout']; |
467
|
|
|
|
468
|
|
|
prepareDBSettingContext($config_vars); |
469
|
|
|
} |
470
|
|
|
|
471
|
|
|
/** |
472
|
|
|
* Config array for changing like settings |
473
|
|
|
* Accessed from ?action=admin;area=featuresettings;sa=likes; |
474
|
|
|
* |
475
|
|
|
* @param bool $return_config Whether or not to return the config_vars array |
476
|
|
|
* @return void|array Returns nothing or returns the $config_vars array if $return_config is true |
477
|
|
|
*/ |
478
|
|
|
function ModifyLikesSettings($return_config = false) |
479
|
|
|
{ |
480
|
|
|
global $txt, $scripturl, $context; |
481
|
|
|
|
482
|
|
|
$config_vars = array( |
483
|
|
|
array('check', 'enable_likes'), |
484
|
|
|
array('permissions', 'likes_like'), |
485
|
|
|
); |
486
|
|
|
|
487
|
|
|
call_integration_hook('integrate_likes_settings', array(&$config_vars)); |
488
|
|
|
|
489
|
|
|
if ($return_config) |
490
|
|
|
return $config_vars; |
491
|
|
|
|
492
|
|
|
// Saving? |
493
|
|
|
if (isset($_GET['save'])) |
494
|
|
|
{ |
495
|
|
|
checkSession(); |
496
|
|
|
|
497
|
|
|
call_integration_hook('integrate_save_likes_settings'); |
498
|
|
|
|
499
|
|
|
saveDBSettings($config_vars); |
500
|
|
|
$_SESSION['adm-save'] = true; |
501
|
|
|
redirectexit('action=admin;area=featuresettings;sa=likes'); |
502
|
|
|
} |
503
|
|
|
|
504
|
|
|
$context['post_url'] = $scripturl . '?action=admin;area=featuresettings;save;sa=likes'; |
505
|
|
|
$context['settings_title'] = $txt['likes']; |
506
|
|
|
|
507
|
|
|
prepareDBSettingContext($config_vars); |
508
|
|
|
} |
509
|
|
|
|
510
|
|
|
/** |
511
|
|
|
* Config array for changing like settings |
512
|
|
|
* Accessed from ?action=admin;area=featuresettings;sa=mentions; |
513
|
|
|
* |
514
|
|
|
* @param bool $return_config Whether or not to return the config_vars array (used for admin search) |
515
|
|
|
* @return void|array Returns nothing or returns the $config_vars array if $return_config is true |
516
|
|
|
*/ |
517
|
|
|
function ModifyMentionsSettings($return_config = false) |
518
|
|
|
{ |
519
|
|
|
global $txt, $scripturl, $context; |
520
|
|
|
|
521
|
|
|
$config_vars = array( |
522
|
|
|
array('check', 'enable_mentions'), |
523
|
|
|
array('permissions', 'mention'), |
524
|
|
|
); |
525
|
|
|
|
526
|
|
|
call_integration_hook('integrate_mentions_settings', array(&$config_vars)); |
527
|
|
|
|
528
|
|
|
if ($return_config) |
529
|
|
|
return $config_vars; |
530
|
|
|
|
531
|
|
|
// Saving? |
532
|
|
|
if (isset($_GET['save'])) |
533
|
|
|
{ |
534
|
|
|
checkSession(); |
535
|
|
|
|
536
|
|
|
call_integration_hook('integrate_save_mentions_settings'); |
537
|
|
|
|
538
|
|
|
saveDBSettings($config_vars); |
539
|
|
|
$_SESSION['adm-save'] = true; |
540
|
|
|
redirectexit('action=admin;area=featuresettings;sa=mentions'); |
541
|
|
|
} |
542
|
|
|
|
543
|
|
|
$context['post_url'] = $scripturl . '?action=admin;area=featuresettings;save;sa=mentions'; |
544
|
|
|
$context['settings_title'] = $txt['mentions']; |
545
|
|
|
|
546
|
|
|
prepareDBSettingContext($config_vars); |
547
|
|
|
} |
548
|
|
|
|
549
|
|
|
/** |
550
|
|
|
* Moderation type settings - although there are fewer than we have you believe ;) |
551
|
|
|
* |
552
|
|
|
* @param bool $return_config Whether or not to return the config_vars array (used for admin search) |
553
|
|
|
* @return void|array Returns nothing or returns the $config_vars array if $return_config is true |
554
|
|
|
*/ |
555
|
|
|
function ModifyWarningSettings($return_config = false) |
556
|
|
|
{ |
557
|
|
|
global $txt, $scripturl, $context, $modSettings, $sourcedir; |
558
|
|
|
|
559
|
|
|
// You need to be an admin to edit settings! |
560
|
|
|
isAllowedTo('admin_forum'); |
561
|
|
|
|
562
|
|
|
loadLanguage('Help'); |
563
|
|
|
loadLanguage('ManageSettings'); |
564
|
|
|
|
565
|
|
|
// We need the existing ones for this |
566
|
|
|
list ($currently_enabled, $modSettings['user_limit'], $modSettings['warning_decrement']) = explode(',', $modSettings['warning_settings']); |
567
|
|
|
|
568
|
|
|
$config_vars = array( |
569
|
|
|
// Warning system? |
570
|
|
|
'enable' => array('check', 'warning_enable'), |
571
|
|
|
); |
572
|
|
|
|
573
|
|
|
if (!empty($modSettings['warning_settings']) && $currently_enabled) |
574
|
|
|
$config_vars += array( |
575
|
|
|
'', |
576
|
|
|
|
577
|
|
|
array( |
578
|
|
|
'int', |
579
|
|
|
'warning_watch', |
580
|
|
|
'subtext' => $txt['setting_warning_watch_note'] . ' ' . $txt['zero_to_disable'] |
581
|
|
|
), |
582
|
|
|
'moderate' => array( |
583
|
|
|
'int', |
584
|
|
|
'warning_moderate', |
585
|
|
|
'subtext' => $txt['setting_warning_moderate_note'] . ' ' . $txt['zero_to_disable'] |
586
|
|
|
), |
587
|
|
|
array( |
588
|
|
|
'int', |
589
|
|
|
'warning_mute', |
590
|
|
|
'subtext' => $txt['setting_warning_mute_note'] . ' ' . $txt['zero_to_disable'] |
591
|
|
|
), |
592
|
|
|
'rem1' => array( |
593
|
|
|
'int', |
594
|
|
|
'user_limit', |
595
|
|
|
'subtext' => $txt['setting_user_limit_note'] |
596
|
|
|
), |
597
|
|
|
'rem2' => array( |
598
|
|
|
'int', |
599
|
|
|
'warning_decrement', |
600
|
|
|
'subtext' => $txt['setting_warning_decrement_note'] . ' ' . $txt['zero_to_disable'] |
601
|
|
|
), |
602
|
|
|
array('permissions', 'view_warning_any'), |
603
|
|
|
array('permissions', 'view_warning_own'), |
604
|
|
|
); |
605
|
|
|
|
606
|
|
|
call_integration_hook('integrate_warning_settings', array(&$config_vars)); |
607
|
|
|
|
608
|
|
|
if ($return_config) |
609
|
|
|
return $config_vars; |
610
|
|
|
|
611
|
|
|
// Cannot use moderation if post moderation is not enabled. |
612
|
|
|
if (!$modSettings['postmod_active']) |
613
|
|
|
unset($config_vars['moderate']); |
614
|
|
|
|
615
|
|
|
// Will need the utility functions from here. |
616
|
|
|
require_once($sourcedir . '/ManageServer.php'); |
617
|
|
|
|
618
|
|
|
// Saving? |
619
|
|
|
if (isset($_GET['save'])) |
620
|
|
|
{ |
621
|
|
|
checkSession(); |
622
|
|
|
|
623
|
|
|
// Make sure these don't have an effect. |
624
|
|
|
if (!$currently_enabled && empty($_POST['warning_enable'])) |
625
|
|
|
{ |
626
|
|
|
$_POST['warning_watch'] = 0; |
627
|
|
|
$_POST['warning_moderate'] = 0; |
628
|
|
|
$_POST['warning_mute'] = 0; |
629
|
|
|
} |
630
|
|
|
// If it was disabled and we're enabling it now, set some sane defaults. |
631
|
|
|
elseif (!$currently_enabled && !empty($_POST['warning_enable'])) |
632
|
|
|
{ |
633
|
|
|
// Need to add these, these weren't there before... |
634
|
|
|
$vars = array( |
635
|
|
|
'warning_watch' => 10, |
636
|
|
|
'warning_mute' => 60, |
637
|
|
|
); |
638
|
|
|
if ($modSettings['postmod_active']) |
639
|
|
|
$vars['warning_moderate'] = 35; |
640
|
|
|
|
641
|
|
|
foreach ($vars as $var => $value) |
642
|
|
|
{ |
643
|
|
|
$config_vars[] = array('int', $var); |
644
|
|
|
$_POST[$var] = $value; |
645
|
|
|
} |
646
|
|
|
} |
647
|
|
|
else |
648
|
|
|
{ |
649
|
|
|
$_POST['warning_watch'] = min($_POST['warning_watch'], 100); |
650
|
|
|
$_POST['warning_moderate'] = $modSettings['postmod_active'] ? min($_POST['warning_moderate'], 100) : 0; |
651
|
|
|
$_POST['warning_mute'] = min($_POST['warning_mute'], 100); |
652
|
|
|
} |
653
|
|
|
|
654
|
|
|
// We might not have these already depending on how we got here. |
655
|
|
|
$_POST['user_limit'] = isset($_POST['user_limit']) ? (int) $_POST['user_limit'] : $modSettings['user_limit']; |
656
|
|
|
$_POST['warning_decrement'] = isset($_POST['warning_decrement']) ? (int) $_POST['warning_decrement'] : $modSettings['warning_decrement']; |
657
|
|
|
|
658
|
|
|
// Fix the warning setting array! |
659
|
|
|
$_POST['warning_settings'] = (!empty($_POST['warning_enable']) ? 1 : 0) . ',' . min(100, $_POST['user_limit']) . ',' . min(100, $_POST['warning_decrement']); |
660
|
|
|
$save_vars = $config_vars; |
661
|
|
|
$save_vars[] = array('text', 'warning_settings'); |
662
|
|
|
unset($save_vars['enable'], $save_vars['rem1'], $save_vars['rem2']); |
663
|
|
|
|
664
|
|
|
call_integration_hook('integrate_save_warning_settings', array(&$save_vars)); |
665
|
|
|
|
666
|
|
|
saveDBSettings($save_vars); |
667
|
|
|
$_SESSION['adm-save'] = true; |
668
|
|
|
redirectexit('action=admin;area=warnings'); |
669
|
|
|
} |
670
|
|
|
|
671
|
|
|
// We actually store lots of these together - for efficiency. |
672
|
|
|
list ($modSettings['warning_enable'], $modSettings['user_limit'], $modSettings['warning_decrement']) = explode(',', $modSettings['warning_settings']); |
673
|
|
|
|
674
|
|
|
$context['sub_template'] = 'show_settings'; |
675
|
|
|
$context['post_url'] = $scripturl . '?action=admin;area=warnings;save'; |
676
|
|
|
$context['settings_title'] = $txt['warnings']; |
677
|
|
|
$context['page_title'] = $txt['warnings']; |
678
|
|
|
|
679
|
|
|
$context[$context['admin_menu_name']]['tab_data'] = array( |
680
|
|
|
'title' => $txt['warnings'], |
681
|
|
|
'help' => '', |
682
|
|
|
'description' => $txt['warnings_desc'], |
683
|
|
|
); |
684
|
|
|
|
685
|
|
|
prepareDBSettingContext($config_vars); |
686
|
|
|
} |
687
|
|
|
|
688
|
|
|
/** |
689
|
|
|
* Let's try keep the spam to a minimum ah Thantos? |
690
|
|
|
* |
691
|
|
|
* @param bool $return_config Whether or not to return the config_vars array (used for admin search) |
692
|
|
|
* @return void|array Returns nothing or returns the $config_vars array if $return_config is true |
693
|
|
|
*/ |
694
|
|
|
function ModifyAntispamSettings($return_config = false) |
695
|
|
|
{ |
696
|
|
|
global $txt, $scripturl, $context, $modSettings, $smcFunc, $language, $sourcedir; |
697
|
|
|
|
698
|
|
|
loadLanguage('Help'); |
699
|
|
|
loadLanguage('ManageSettings'); |
700
|
|
|
|
701
|
|
|
// Generate a sample registration image. |
702
|
|
|
$context['use_graphic_library'] = in_array('gd', get_loaded_extensions()); |
703
|
|
|
$context['verification_image_href'] = $scripturl . '?action=verificationcode;rand=' . md5(mt_rand()); |
704
|
|
|
|
705
|
|
|
$config_vars = array( |
706
|
|
|
array('check', 'reg_verification'), |
707
|
|
|
array('check', 'search_enable_captcha'), |
708
|
|
|
// This, my friend, is a cheat :p |
709
|
|
|
'guest_verify' => array( |
710
|
|
|
'check', |
711
|
|
|
'guests_require_captcha', |
712
|
|
|
'subtext' => $txt['setting_guests_require_captcha_desc'] |
713
|
|
|
), |
714
|
|
|
array( |
715
|
|
|
'int', |
716
|
|
|
'posts_require_captcha', |
717
|
|
|
'subtext' => $txt['posts_require_captcha_desc'], |
718
|
|
|
'min' => -1, |
719
|
|
|
'onchange' => 'if (this.value > 0){ document.getElementById(\'guests_require_captcha\').checked = true; document.getElementById(\'guests_require_captcha\').disabled = true;} else {document.getElementById(\'guests_require_captcha\').disabled = false;}' |
720
|
|
|
), |
721
|
|
|
'', |
722
|
|
|
|
723
|
|
|
// PM Settings |
724
|
|
|
'pm1' => array('int', 'max_pm_recipients', 'subtext' => $txt['max_pm_recipients_note']), |
725
|
|
|
'pm2' => array('int', 'pm_posts_verification', 'subtext' => $txt['pm_posts_verification_note']), |
726
|
|
|
'pm3' => array('int', 'pm_posts_per_hour', 'subtext' => $txt['pm_posts_per_hour_note']), |
727
|
|
|
// Visual verification. |
728
|
|
|
array('title', 'configure_verification_means'), |
729
|
|
|
array('desc', 'configure_verification_means_desc'), |
730
|
|
|
'vv' => array( |
731
|
|
|
'select', |
732
|
|
|
'visual_verification_type', |
733
|
|
|
array( |
734
|
|
|
$txt['setting_image_verification_off'], |
735
|
|
|
$txt['setting_image_verification_vsimple'], |
736
|
|
|
$txt['setting_image_verification_simple'], |
737
|
|
|
$txt['setting_image_verification_medium'], |
738
|
|
|
$txt['setting_image_verification_high'], |
739
|
|
|
$txt['setting_image_verification_extreme'] |
740
|
|
|
), |
741
|
|
|
'subtext' => $txt['setting_visual_verification_type_desc'], |
742
|
|
|
'onchange' => $context['use_graphic_library'] ? 'refreshImages();' : '' |
743
|
|
|
), |
744
|
|
|
// reCAPTCHA |
745
|
|
|
array('title', 'recaptcha_configure'), |
746
|
|
|
array('desc', 'recaptcha_configure_desc', 'class' => 'windowbg'), |
747
|
|
|
array('check', 'recaptcha_enabled', 'subtext' => $txt['recaptcha_enable_desc']), |
748
|
|
|
array('text', 'recaptcha_site_key', 'subtext' => $txt['recaptcha_site_key_desc']), |
749
|
|
|
array('text', 'recaptcha_secret_key', 'subtext' => $txt['recaptcha_secret_key_desc']), |
750
|
|
|
array('select', 'recaptcha_theme', array('light' => $txt['recaptcha_theme_light'], 'dark' => $txt['recaptcha_theme_dark'])), |
751
|
|
|
// Clever Thomas, who is looking sheepy now? Not I, the mighty sword swinger did say. |
752
|
|
|
array('title', 'setup_verification_questions'), |
753
|
|
|
array('desc', 'setup_verification_questions_desc'), |
754
|
|
|
array('int', 'qa_verification_number', 'subtext' => $txt['setting_qa_verification_number_desc']), |
755
|
|
|
array('callback', 'question_answer_list'), |
756
|
|
|
); |
757
|
|
|
|
758
|
|
|
call_integration_hook('integrate_spam_settings', array(&$config_vars)); |
759
|
|
|
|
760
|
|
|
if ($return_config) |
761
|
|
|
return $config_vars; |
762
|
|
|
|
763
|
|
|
// You need to be an admin to edit settings! |
764
|
|
|
isAllowedTo('admin_forum'); |
765
|
|
|
|
766
|
|
|
// Firstly, figure out what languages we're dealing with, and do a little processing for the form's benefit. |
767
|
|
|
getLanguages(); |
768
|
|
|
$context['qa_languages'] = array(); |
769
|
|
|
foreach ($context['languages'] as $lang_id => $lang) |
770
|
|
|
{ |
771
|
|
|
$lang_id = strtr($lang_id, array('-utf8' => '')); |
772
|
|
|
$lang['name'] = strtr($lang['name'], array('-utf8' => '')); |
773
|
|
|
$context['qa_languages'][$lang_id] = $lang; |
774
|
|
|
} |
775
|
|
|
|
776
|
|
|
// Secondly, load any questions we currently have. |
777
|
|
|
$context['question_answers'] = array(); |
778
|
|
|
$request = $smcFunc['db_query']('', ' |
779
|
|
|
SELECT id_question, lngfile, question, answers |
780
|
|
|
FROM {db_prefix}qanda' |
781
|
|
|
); |
782
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
783
|
|
|
{ |
784
|
|
|
$lang = strtr($row['lngfile'], array('-utf8' => '')); |
785
|
|
|
$context['question_answers'][$row['id_question']] = array( |
786
|
|
|
'lngfile' => $lang, |
787
|
|
|
'question' => $row['question'], |
788
|
|
|
'answers' => (array) $smcFunc['json_decode']($row['answers'], true), |
789
|
|
|
); |
790
|
|
|
$context['qa_by_lang'][$lang][] = $row['id_question']; |
791
|
|
|
} |
792
|
|
|
|
793
|
|
|
if (empty($context['qa_by_lang'][strtr($language, array('-utf8' => ''))]) && !empty($context['question_answers'])) |
794
|
|
|
{ |
795
|
|
|
if (empty($context['settings_insert_above'])) |
796
|
|
|
$context['settings_insert_above'] = ''; |
797
|
|
|
|
798
|
|
|
$context['settings_insert_above'] .= '<div class="noticebox">' . sprintf($txt['question_not_defined'], $context['languages'][$language]['name']) . '</div>'; |
799
|
|
|
} |
800
|
|
|
|
801
|
|
|
// Thirdly, push some JavaScript for the form to make it work. |
802
|
|
|
addInlineJavaScript(' |
803
|
|
|
var nextrow = ' . (!empty($context['question_answers']) ? max(array_keys($context['question_answers'])) + 1 : 1) . '; |
804
|
|
|
$(".qa_link a").click(function() { |
805
|
|
|
var id = $(this).parent().attr("id").substring(6); |
806
|
|
|
$("#qa_fs_" + id).show(); |
807
|
|
|
$(this).parent().hide(); |
808
|
|
|
}); |
809
|
|
|
$(".qa_fieldset legend a").click(function() { |
810
|
|
|
var id = $(this).closest("fieldset").attr("id").substring(6); |
811
|
|
|
$("#qa_dt_" + id).show(); |
812
|
|
|
$(this).closest("fieldset").hide(); |
813
|
|
|
}); |
814
|
|
|
$(".qa_add_question a").click(function() { |
815
|
|
|
var id = $(this).closest("fieldset").attr("id").substring(6); |
816
|
|
|
$(\'<dt><input type="text" name="question[\' + id + \'][\' + nextrow + \']" value="" size="50" class="verification_question"></dt><dd><input type="text" name="answer[\' + id + \'][\' + nextrow + \'][]" value="" size="50" class="verification_answer" / ><div class="qa_add_answer"><a href="javascript:void(0);">[ \' + ' . JavaScriptEscape($txt['setup_verification_add_answer']) . ' + \' ]</a></div></dd>\').insertBefore($(this).parent()); |
817
|
|
|
nextrow++; |
818
|
|
|
}); |
819
|
|
|
$(".qa_fieldset ").on("click", ".qa_add_answer a", function() { |
820
|
|
|
var attr = $(this).closest("dd").find(".verification_answer:last").attr("name"); |
821
|
|
|
$(\'<input type="text" name="\' + attr + \'" value="" size="50" class="verification_answer">\').insertBefore($(this).closest("div")); |
822
|
|
|
return false; |
823
|
|
|
}); |
824
|
|
|
$("#qa_dt_' . strtr($language, array('-utf8' => '')) . ' a").click();', true); |
825
|
|
|
|
826
|
|
|
// Will need the utility functions from here. |
827
|
|
|
require_once($sourcedir . '/ManageServer.php'); |
828
|
|
|
|
829
|
|
|
// Saving? |
830
|
|
|
if (isset($_GET['save'])) |
831
|
|
|
{ |
832
|
|
|
checkSession(); |
833
|
|
|
|
834
|
|
|
// Fix PM settings. |
835
|
|
|
$_POST['pm_spam_settings'] = (int) $_POST['max_pm_recipients'] . ',' . (int) $_POST['pm_posts_verification'] . ',' . (int) $_POST['pm_posts_per_hour']; |
836
|
|
|
|
837
|
|
|
// Hack in guest requiring verification! |
838
|
|
|
if (empty($_POST['posts_require_captcha']) && !empty($_POST['guests_require_captcha'])) |
839
|
|
|
$_POST['posts_require_captcha'] = -1; |
840
|
|
|
|
841
|
|
|
$save_vars = $config_vars; |
842
|
|
|
unset($save_vars['pm1'], $save_vars['pm2'], $save_vars['pm3'], $save_vars['guest_verify']); |
843
|
|
|
|
844
|
|
|
$save_vars[] = array('text', 'pm_spam_settings'); |
845
|
|
|
|
846
|
|
|
// Handle verification questions. |
847
|
|
|
$changes = array( |
848
|
|
|
'insert' => array(), |
849
|
|
|
'replace' => array(), |
850
|
|
|
'delete' => array(), |
851
|
|
|
); |
852
|
|
|
$qs_per_lang = array(); |
853
|
|
|
foreach ($context['qa_languages'] as $lang_id => $dummy) |
854
|
|
|
{ |
855
|
|
|
// If we had some questions for this language before, but don't now, delete everything from that language. |
856
|
|
|
if ((!isset($_POST['question'][$lang_id]) || !is_array($_POST['question'][$lang_id])) && !empty($context['qa_by_lang'][$lang_id])) |
857
|
|
|
$changes['delete'] = array_merge($changes['delete'], $context['qa_by_lang'][$lang_id]); |
858
|
|
|
|
859
|
|
|
// Now step through and see if any existing questions no longer exist. |
860
|
|
|
if (!empty($context['qa_by_lang'][$lang_id])) |
861
|
|
|
foreach ($context['qa_by_lang'][$lang_id] as $q_id) |
862
|
|
|
if (empty($_POST['question'][$lang_id][$q_id])) |
863
|
|
|
$changes['delete'][] = $q_id; |
864
|
|
|
|
865
|
|
|
// Now let's see if there are new questions or ones that need updating. |
866
|
|
|
if (isset($_POST['question'][$lang_id])) |
867
|
|
|
{ |
868
|
|
|
foreach ($_POST['question'][$lang_id] as $q_id => $question) |
869
|
|
|
{ |
870
|
|
|
// Ignore junky ids. |
871
|
|
|
$q_id = (int) $q_id; |
872
|
|
|
if ($q_id <= 0) |
873
|
|
|
continue; |
874
|
|
|
|
875
|
|
|
// Check the question isn't empty (because they want to delete it?) |
876
|
|
|
if (empty($question) || trim($question) == '') |
877
|
|
|
{ |
878
|
|
|
if (isset($context['question_answers'][$q_id])) |
879
|
|
|
$changes['delete'][] = $q_id; |
880
|
|
|
continue; |
881
|
|
|
} |
882
|
|
|
$question = $smcFunc['htmlspecialchars'](trim($question)); |
883
|
|
|
|
884
|
|
|
// Get the answers. Firstly check there actually might be some. |
885
|
|
|
if (!isset($_POST['answer'][$lang_id][$q_id]) || !is_array($_POST['answer'][$lang_id][$q_id])) |
886
|
|
|
{ |
887
|
|
|
if (isset($context['question_answers'][$q_id])) |
888
|
|
|
$changes['delete'][] = $q_id; |
889
|
|
|
continue; |
890
|
|
|
} |
891
|
|
|
// Now get them and check that they might be viable. |
892
|
|
|
$answers = array(); |
893
|
|
|
foreach ($_POST['answer'][$lang_id][$q_id] as $answer) |
894
|
|
|
if (!empty($answer) && trim($answer) !== '') |
895
|
|
|
$answers[] = $smcFunc['htmlspecialchars'](trim($answer)); |
896
|
|
|
if (empty($answers)) |
897
|
|
|
{ |
898
|
|
|
if (isset($context['question_answers'][$q_id])) |
899
|
|
|
$changes['delete'][] = $q_id; |
900
|
|
|
continue; |
901
|
|
|
} |
902
|
|
|
$answers = $smcFunc['json_encode']($answers); |
903
|
|
|
|
904
|
|
|
// At this point we know we have a question and some answers. What are we doing with it? |
905
|
|
|
if (!isset($context['question_answers'][$q_id])) |
906
|
|
|
{ |
907
|
|
|
// New question. Now, we don't want to randomly consume ids, so we'll set those, rather than trusting the browser's supplied ids. |
908
|
|
|
$changes['insert'][] = array($lang_id, $question, $answers); |
909
|
|
|
} |
910
|
|
|
else |
911
|
|
|
{ |
912
|
|
|
// It's an existing question. Let's see what's changed, if anything. |
913
|
|
|
if ($lang_id != $context['question_answers'][$q_id]['lngfile'] || $question != $context['question_answers'][$q_id]['question'] || $answers != $context['question_answers'][$q_id]['answers']) |
914
|
|
|
$changes['replace'][$q_id] = array('lngfile' => $lang_id, 'question' => $question, 'answers' => $answers); |
915
|
|
|
} |
916
|
|
|
|
917
|
|
|
if (!isset($qs_per_lang[$lang_id])) |
918
|
|
|
$qs_per_lang[$lang_id] = 0; |
919
|
|
|
$qs_per_lang[$lang_id]++; |
920
|
|
|
} |
921
|
|
|
} |
922
|
|
|
} |
923
|
|
|
|
924
|
|
|
// OK, so changes? |
925
|
|
|
if (!empty($changes['delete'])) |
926
|
|
|
{ |
927
|
|
|
$smcFunc['db_query']('', ' |
928
|
|
|
DELETE FROM {db_prefix}qanda |
929
|
|
|
WHERE id_question IN ({array_int:questions})', |
930
|
|
|
array( |
931
|
|
|
'questions' => $changes['delete'], |
932
|
|
|
) |
933
|
|
|
); |
934
|
|
|
} |
935
|
|
|
|
936
|
|
|
if (!empty($changes['replace'])) |
937
|
|
|
{ |
938
|
|
|
foreach ($changes['replace'] as $q_id => $question) |
939
|
|
|
{ |
940
|
|
|
$smcFunc['db_query']('', ' |
941
|
|
|
UPDATE {db_prefix}qanda |
942
|
|
|
SET lngfile = {string:lngfile}, |
943
|
|
|
question = {string:question}, |
944
|
|
|
answers = {string:answers} |
945
|
|
|
WHERE id_question = {int:id_question}', |
946
|
|
|
array( |
947
|
|
|
'id_question' => $q_id, |
948
|
|
|
'lngfile' => $question['lngfile'], |
949
|
|
|
'question' => $question['question'], |
950
|
|
|
'answers' => $question['answers'], |
951
|
|
|
) |
952
|
|
|
); |
953
|
|
|
} |
954
|
|
|
} |
955
|
|
|
|
956
|
|
|
if (!empty($changes['insert'])) |
957
|
|
|
{ |
958
|
|
|
$smcFunc['db_insert']('insert', |
959
|
|
|
'{db_prefix}qanda', |
960
|
|
|
array('lngfile' => 'string-50', 'question' => 'string-255', 'answers' => 'string-65534'), |
961
|
|
|
$changes['insert'], |
962
|
|
|
array('id_question') |
963
|
|
|
); |
964
|
|
|
} |
965
|
|
|
|
966
|
|
|
// Lastly, the count of messages needs to be no more than the lowest number of questions for any one language. |
967
|
|
|
$count_questions = empty($qs_per_lang) ? 0 : min($qs_per_lang); |
968
|
|
|
if (empty($count_questions) || $_POST['qa_verification_number'] > $count_questions) |
969
|
|
|
$_POST['qa_verification_number'] = $count_questions; |
970
|
|
|
|
971
|
|
|
call_integration_hook('integrate_save_spam_settings', array(&$save_vars)); |
972
|
|
|
|
973
|
|
|
// Now save. |
974
|
|
|
saveDBSettings($save_vars); |
975
|
|
|
$_SESSION['adm-save'] = true; |
976
|
|
|
|
977
|
|
|
cache_put_data('verificationQuestions', null, 300); |
978
|
|
|
|
979
|
|
|
redirectexit('action=admin;area=antispam'); |
980
|
|
|
} |
981
|
|
|
|
982
|
|
|
$character_range = array_merge(range('A', 'H'), array('K', 'M', 'N', 'P', 'R'), range('T', 'Y')); |
983
|
|
|
$_SESSION['visual_verification_code'] = ''; |
984
|
|
|
for ($i = 0; $i < 6; $i++) |
985
|
|
|
$_SESSION['visual_verification_code'] .= $character_range[array_rand($character_range)]; |
986
|
|
|
|
987
|
|
|
// Some javascript for CAPTCHA. |
988
|
|
|
$context['settings_post_javascript'] = ''; |
989
|
|
|
if ($context['use_graphic_library']) |
990
|
|
|
$context['settings_post_javascript'] .= ' |
991
|
|
|
function refreshImages() |
992
|
|
|
{ |
993
|
|
|
var imageType = document.getElementById(\'visual_verification_type\').value; |
994
|
|
|
document.getElementById(\'verification_image\').src = \'' . $context['verification_image_href'] . ';type=\' + imageType; |
995
|
|
|
}'; |
996
|
|
|
|
997
|
|
|
// Show the image itself, or text saying we can't. |
998
|
|
|
if ($context['use_graphic_library']) |
999
|
|
|
$config_vars['vv']['postinput'] = '<br><img src="' . $context['verification_image_href'] . ';type=' . (empty($modSettings['visual_verification_type']) ? 0 : $modSettings['visual_verification_type']) . '" alt="' . $txt['setting_image_verification_sample'] . '" id="verification_image"><br>'; |
1000
|
|
|
else |
1001
|
|
|
$config_vars['vv']['postinput'] = '<br><span class="smalltext">' . $txt['setting_image_verification_nogd'] . '</span>'; |
1002
|
|
|
|
1003
|
|
|
// Hack for PM spam settings. |
1004
|
|
|
list ($modSettings['max_pm_recipients'], $modSettings['pm_posts_verification'], $modSettings['pm_posts_per_hour']) = explode(',', $modSettings['pm_spam_settings']); |
1005
|
|
|
|
1006
|
|
|
// Hack for guests requiring verification. |
1007
|
|
|
$modSettings['guests_require_captcha'] = !empty($modSettings['posts_require_captcha']); |
1008
|
|
|
$modSettings['posts_require_captcha'] = !isset($modSettings['posts_require_captcha']) || $modSettings['posts_require_captcha'] == -1 ? 0 : $modSettings['posts_require_captcha']; |
1009
|
|
|
|
1010
|
|
|
// Some minor javascript for the guest post setting. |
1011
|
|
|
if ($modSettings['posts_require_captcha']) |
1012
|
|
|
$context['settings_post_javascript'] .= ' |
1013
|
|
|
document.getElementById(\'guests_require_captcha\').disabled = true;'; |
1014
|
|
|
|
1015
|
|
|
// And everything else. |
1016
|
|
|
$context['post_url'] = $scripturl . '?action=admin;area=antispam;save'; |
1017
|
|
|
$context['settings_title'] = $txt['antispam_Settings']; |
1018
|
|
|
$context['page_title'] = $txt['antispam_title']; |
1019
|
|
|
$context['sub_template'] = 'show_settings'; |
1020
|
|
|
|
1021
|
|
|
$context[$context['admin_menu_name']]['tab_data'] = array( |
1022
|
|
|
'title' => $txt['antispam_title'], |
1023
|
|
|
'description' => $txt['antispam_Settings_desc'], |
1024
|
|
|
); |
1025
|
|
|
|
1026
|
|
|
prepareDBSettingContext($config_vars); |
1027
|
|
|
} |
1028
|
|
|
|
1029
|
|
|
/** |
1030
|
|
|
* You'll never guess what this function does... |
1031
|
|
|
* |
1032
|
|
|
* @param bool $return_config Whether or not to return the config_vars array (used for admin search) |
1033
|
|
|
* @return void|array Returns nothing or returns the $config_vars array if $return_config is true |
1034
|
|
|
*/ |
1035
|
|
|
function ModifySignatureSettings($return_config = false) |
1036
|
|
|
{ |
1037
|
|
|
global $context, $txt, $modSettings, $sig_start, $smcFunc, $scripturl; |
1038
|
|
|
|
1039
|
|
|
$config_vars = array( |
1040
|
|
|
// Are signatures even enabled? |
1041
|
|
|
array('check', 'signature_enable'), |
1042
|
|
|
'', |
1043
|
|
|
|
1044
|
|
|
// Tweaking settings! |
1045
|
|
|
array('int', 'signature_max_length', 'subtext' => $txt['zero_for_no_limit']), |
1046
|
|
|
array('int', 'signature_max_lines', 'subtext' => $txt['zero_for_no_limit']), |
1047
|
|
|
array('int', 'signature_max_font_size', 'subtext' => $txt['zero_for_no_limit']), |
1048
|
|
|
array('check', 'signature_allow_smileys', 'onclick' => 'document.getElementById(\'signature_max_smileys\').disabled = !this.checked;'), |
1049
|
|
|
array('int', 'signature_max_smileys', 'subtext' => $txt['zero_for_no_limit']), |
1050
|
|
|
'', |
1051
|
|
|
|
1052
|
|
|
// Image settings. |
1053
|
|
|
array('int', 'signature_max_images', 'subtext' => $txt['signature_max_images_note']), |
1054
|
|
|
array('int', 'signature_max_image_width', 'subtext' => $txt['zero_for_no_limit']), |
1055
|
|
|
array('int', 'signature_max_image_height', 'subtext' => $txt['zero_for_no_limit']), |
1056
|
|
|
'', |
1057
|
|
|
|
1058
|
|
|
array('bbc', 'signature_bbc'), |
1059
|
|
|
); |
1060
|
|
|
|
1061
|
|
|
call_integration_hook('integrate_signature_settings', array(&$config_vars)); |
1062
|
|
|
|
1063
|
|
|
if ($return_config) |
1064
|
|
|
return $config_vars; |
1065
|
|
|
|
1066
|
|
|
// Setup the template. |
1067
|
|
|
$context['page_title'] = $txt['signature_settings']; |
1068
|
|
|
$context['sub_template'] = 'show_settings'; |
1069
|
|
|
|
1070
|
|
|
// Disable the max smileys option if we don't allow smileys at all! |
1071
|
|
|
$context['settings_post_javascript'] = 'document.getElementById(\'signature_max_smileys\').disabled = !document.getElementById(\'signature_allow_smileys\').checked;'; |
1072
|
|
|
|
1073
|
|
|
// Load all the signature settings. |
1074
|
|
|
list ($sig_limits, $sig_bbc) = explode(':', $modSettings['signature_settings']); |
1075
|
|
|
$sig_limits = explode(',', $sig_limits); |
1076
|
|
|
$disabledTags = !empty($sig_bbc) ? explode(',', $sig_bbc) : array(); |
1077
|
|
|
|
1078
|
|
|
// Applying to ALL signatures?!! |
1079
|
|
|
if (isset($_GET['apply'])) |
1080
|
|
|
{ |
1081
|
|
|
// Security! |
1082
|
|
|
checkSession('get'); |
1083
|
|
|
|
1084
|
|
|
$sig_start = time(); |
1085
|
|
|
// This is horrid - but I suppose some people will want the option to do it. |
1086
|
|
|
$_GET['step'] = isset($_GET['step']) ? (int) $_GET['step'] : 0; |
1087
|
|
|
$done = false; |
1088
|
|
|
|
1089
|
|
|
$request = $smcFunc['db_query']('', ' |
1090
|
|
|
SELECT MAX(id_member) |
1091
|
|
|
FROM {db_prefix}members', |
1092
|
|
|
array( |
1093
|
|
|
) |
1094
|
|
|
); |
1095
|
|
|
list ($context['max_member']) = $smcFunc['db_fetch_row']($request); |
1096
|
|
|
$smcFunc['db_free_result']($request); |
1097
|
|
|
|
1098
|
|
|
while (!$done) |
1099
|
|
|
{ |
1100
|
|
|
$changes = array(); |
1101
|
|
|
|
1102
|
|
|
$request = $smcFunc['db_query']('', ' |
1103
|
|
|
SELECT id_member, signature |
1104
|
|
|
FROM {db_prefix}members |
1105
|
|
|
WHERE id_member BETWEEN {int:step} AND {int:step} + 49 |
1106
|
|
|
AND id_group != {int:admin_group} |
1107
|
|
|
AND FIND_IN_SET({int:admin_group}, additional_groups) = 0', |
1108
|
|
|
array( |
1109
|
|
|
'admin_group' => 1, |
1110
|
|
|
'step' => $_GET['step'], |
1111
|
|
|
) |
1112
|
|
|
); |
1113
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
1114
|
|
|
{ |
1115
|
|
|
// Apply all the rules we can realistically do. |
1116
|
|
|
$sig = strtr($row['signature'], array('<br>' => "\n")); |
1117
|
|
|
|
1118
|
|
|
// Max characters... |
1119
|
|
|
if (!empty($sig_limits[1])) |
1120
|
|
|
$sig = $smcFunc['substr']($sig, 0, $sig_limits[1]); |
1121
|
|
|
// Max lines... |
1122
|
|
|
if (!empty($sig_limits[2])) |
1123
|
|
|
{ |
1124
|
|
|
$count = 0; |
1125
|
|
|
for ($i = 0; $i < strlen($sig); $i++) |
1126
|
|
|
{ |
1127
|
|
|
if ($sig[$i] == "\n") |
1128
|
|
|
{ |
1129
|
|
|
$count++; |
1130
|
|
|
if ($count >= $sig_limits[2]) |
1131
|
|
|
$sig = substr($sig, 0, $i) . strtr(substr($sig, $i), array("\n" => ' ')); |
1132
|
|
|
} |
1133
|
|
|
} |
1134
|
|
|
} |
1135
|
|
|
|
1136
|
|
|
if (!empty($sig_limits[7]) && preg_match_all('~\[size=([\d\.]+)?(px|pt|em|x-large|larger)~i', $sig, $matches) !== false && isset($matches[2])) |
1137
|
|
|
{ |
1138
|
|
|
foreach ($matches[1] as $ind => $size) |
1139
|
|
|
{ |
1140
|
|
|
$limit_broke = 0; |
1141
|
|
|
// Attempt to allow all sizes of abuse, so to speak. |
1142
|
|
|
if ($matches[2][$ind] == 'px' && $size > $sig_limits[7]) |
1143
|
|
|
$limit_broke = $sig_limits[7] . 'px'; |
1144
|
|
|
elseif ($matches[2][$ind] == 'pt' && $size > ($sig_limits[7] * 0.75)) |
1145
|
|
|
$limit_broke = ((int) $sig_limits[7] * 0.75) . 'pt'; |
1146
|
|
|
elseif ($matches[2][$ind] == 'em' && $size > ((float) $sig_limits[7] / 16)) |
1147
|
|
|
$limit_broke = ((float) $sig_limits[7] / 16) . 'em'; |
1148
|
|
|
elseif ($matches[2][$ind] != 'px' && $matches[2][$ind] != 'pt' && $matches[2][$ind] != 'em' && $sig_limits[7] < 18) |
1149
|
|
|
$limit_broke = 'large'; |
1150
|
|
|
|
1151
|
|
|
if ($limit_broke) |
1152
|
|
|
$sig = str_replace($matches[0][$ind], '[size=' . $sig_limits[7] . 'px', $sig); |
1153
|
|
|
} |
1154
|
|
|
} |
1155
|
|
|
|
1156
|
|
|
// Stupid images - this is stupidly, stupidly challenging. |
1157
|
|
|
if ((!empty($sig_limits[3]) || !empty($sig_limits[5]) || !empty($sig_limits[6]))) |
1158
|
|
|
{ |
1159
|
|
|
$replaces = array(); |
1160
|
|
|
$img_count = 0; |
1161
|
|
|
// Get all BBC tags... |
1162
|
|
|
preg_match_all('~\[img(\s+width=([\d]+))?(\s+height=([\d]+))?(\s+width=([\d]+))?\s*\](?:<br>)*([^<">]+?)(?:<br>)*\[/img\]~i', $sig, $matches); |
1163
|
|
|
// ... and all HTML ones. |
1164
|
|
|
preg_match_all('~<img\s+src=(?:")?((?:http://|ftp://|https://|ftps://).+?)(?:")?(?:\s+alt=(?:")?(.*?)(?:")?)?(?:\s?/)?>~i', $sig, $matches2, PREG_PATTERN_ORDER); |
1165
|
|
|
// And stick the HTML in the BBC. |
1166
|
|
|
if (!empty($matches2)) |
1167
|
|
|
{ |
1168
|
|
|
foreach ($matches2[0] as $ind => $dummy) |
1169
|
|
|
{ |
1170
|
|
|
$matches[0][] = $matches2[0][$ind]; |
1171
|
|
|
$matches[1][] = ''; |
1172
|
|
|
$matches[2][] = ''; |
1173
|
|
|
$matches[3][] = ''; |
1174
|
|
|
$matches[4][] = ''; |
1175
|
|
|
$matches[5][] = ''; |
1176
|
|
|
$matches[6][] = ''; |
1177
|
|
|
$matches[7][] = $matches2[1][$ind]; |
1178
|
|
|
} |
1179
|
|
|
} |
1180
|
|
|
// Try to find all the images! |
1181
|
|
|
if (!empty($matches)) |
1182
|
|
|
{ |
1183
|
|
|
$image_count_holder = array(); |
1184
|
|
|
foreach ($matches[0] as $key => $image) |
1185
|
|
|
{ |
1186
|
|
|
$width = -1; |
1187
|
|
|
$height = -1; |
1188
|
|
|
$img_count++; |
1189
|
|
|
// Too many images? |
1190
|
|
|
if (!empty($sig_limits[3]) && $img_count > $sig_limits[3]) |
1191
|
|
|
{ |
1192
|
|
|
// If we've already had this before we only want to remove the excess. |
1193
|
|
|
if (isset($image_count_holder[$image])) |
1194
|
|
|
{ |
1195
|
|
|
$img_offset = -1; |
1196
|
|
|
$rep_img_count = 0; |
1197
|
|
|
while ($img_offset !== false) |
1198
|
|
|
{ |
1199
|
|
|
$img_offset = strpos($sig, $image, $img_offset + 1); |
1200
|
|
|
$rep_img_count++; |
1201
|
|
|
if ($rep_img_count > $image_count_holder[$image]) |
1202
|
|
|
{ |
1203
|
|
|
// Only replace the excess. |
1204
|
|
|
$sig = substr($sig, 0, $img_offset) . str_replace($image, '', substr($sig, $img_offset)); |
1205
|
|
|
// Stop looping. |
1206
|
|
|
$img_offset = false; |
1207
|
|
|
} |
1208
|
|
|
} |
1209
|
|
|
} |
1210
|
|
|
else |
1211
|
|
|
$replaces[$image] = ''; |
1212
|
|
|
|
1213
|
|
|
continue; |
1214
|
|
|
} |
1215
|
|
|
|
1216
|
|
|
// Does it have predefined restraints? Width first. |
1217
|
|
|
if ($matches[6][$key]) |
1218
|
|
|
$matches[2][$key] = $matches[6][$key]; |
1219
|
|
|
if ($matches[2][$key] && $sig_limits[5] && $matches[2][$key] > $sig_limits[5]) |
1220
|
|
|
{ |
1221
|
|
|
$width = $sig_limits[5]; |
1222
|
|
|
$matches[4][$key] = $matches[4][$key] * ($width / $matches[2][$key]); |
1223
|
|
|
} |
1224
|
|
|
elseif ($matches[2][$key]) |
1225
|
|
|
$width = $matches[2][$key]; |
1226
|
|
|
// ... and height. |
1227
|
|
|
if ($matches[4][$key] && $sig_limits[6] && $matches[4][$key] > $sig_limits[6]) |
1228
|
|
|
{ |
1229
|
|
|
$height = $sig_limits[6]; |
1230
|
|
|
if ($width != -1) |
1231
|
|
|
$width = $width * ($height / $matches[4][$key]); |
1232
|
|
|
} |
1233
|
|
|
elseif ($matches[4][$key]) |
1234
|
|
|
$height = $matches[4][$key]; |
1235
|
|
|
|
1236
|
|
|
// If the dimensions are still not fixed - we need to check the actual image. |
1237
|
|
|
if (($width == -1 && $sig_limits[5]) || ($height == -1 && $sig_limits[6])) |
1238
|
|
|
{ |
1239
|
|
|
$sizes = url_image_size($matches[7][$key]); |
1240
|
|
|
if (is_array($sizes)) |
1241
|
|
|
{ |
1242
|
|
|
// Too wide? |
1243
|
|
|
if ($sizes[0] > $sig_limits[5] && $sig_limits[5]) |
1244
|
|
|
{ |
1245
|
|
|
$width = $sig_limits[5]; |
1246
|
|
|
$sizes[1] = $sizes[1] * ($width / $sizes[0]); |
1247
|
|
|
} |
1248
|
|
|
// Too high? |
1249
|
|
|
if ($sizes[1] > $sig_limits[6] && $sig_limits[6]) |
1250
|
|
|
{ |
1251
|
|
|
$height = $sig_limits[6]; |
1252
|
|
|
if ($width == -1) |
1253
|
|
|
$width = $sizes[0]; |
1254
|
|
|
$width = $width * ($height / $sizes[1]); |
1255
|
|
|
} |
1256
|
|
|
elseif ($width != -1) |
1257
|
|
|
$height = $sizes[1]; |
1258
|
|
|
} |
1259
|
|
|
} |
1260
|
|
|
|
1261
|
|
|
// Did we come up with some changes? If so remake the string. |
1262
|
|
|
if ($width != -1 || $height != -1) |
1263
|
|
|
{ |
1264
|
|
|
$replaces[$image] = '[img' . ($width != -1 ? ' width=' . round($width) : '') . ($height != -1 ? ' height=' . round($height) : '') . ']' . $matches[7][$key] . '[/img]'; |
1265
|
|
|
} |
1266
|
|
|
|
1267
|
|
|
// Record that we got one. |
1268
|
|
|
$image_count_holder[$image] = isset($image_count_holder[$image]) ? $image_count_holder[$image] + 1 : 1; |
1269
|
|
|
} |
1270
|
|
|
if (!empty($replaces)) |
1271
|
|
|
$sig = str_replace(array_keys($replaces), array_values($replaces), $sig); |
1272
|
|
|
} |
1273
|
|
|
} |
1274
|
|
|
// Try to fix disabled tags. |
1275
|
|
|
if (!empty($disabledTags)) |
1276
|
|
|
{ |
1277
|
|
|
$sig = preg_replace('~\[(?:' . implode('|', $disabledTags) . ').+?\]~i', '', $sig); |
1278
|
|
|
$sig = preg_replace('~\[/(?:' . implode('|', $disabledTags) . ')\]~i', '', $sig); |
1279
|
|
|
} |
1280
|
|
|
|
1281
|
|
|
$sig = strtr($sig, array("\n" => '<br>')); |
1282
|
|
|
call_integration_hook('integrate_apply_signature_settings', array(&$sig, $sig_limits, $disabledTags)); |
1283
|
|
|
if ($sig != $row['signature']) |
1284
|
|
|
$changes[$row['id_member']] = $sig; |
1285
|
|
|
} |
1286
|
|
|
if ($smcFunc['db_num_rows']($request) == 0) |
1287
|
|
|
$done = true; |
1288
|
|
|
$smcFunc['db_free_result']($request); |
1289
|
|
|
|
1290
|
|
|
// Do we need to delete what we have? |
1291
|
|
|
if (!empty($changes)) |
1292
|
|
|
{ |
1293
|
|
|
foreach ($changes as $id => $sig) |
1294
|
|
|
$smcFunc['db_query']('', ' |
1295
|
|
|
UPDATE {db_prefix}members |
1296
|
|
|
SET signature = {string:signature} |
1297
|
|
|
WHERE id_member = {int:id_member}', |
1298
|
|
|
array( |
1299
|
|
|
'id_member' => $id, |
1300
|
|
|
'signature' => $sig, |
1301
|
|
|
) |
1302
|
|
|
); |
1303
|
|
|
} |
1304
|
|
|
|
1305
|
|
|
$_GET['step'] += 50; |
1306
|
|
|
if (!$done) |
1307
|
|
|
pauseSignatureApplySettings(); |
1308
|
|
|
} |
1309
|
|
|
$settings_applied = true; |
1310
|
|
|
} |
1311
|
|
|
|
1312
|
|
|
$context['signature_settings'] = array( |
1313
|
|
|
'enable' => isset($sig_limits[0]) ? $sig_limits[0] : 0, |
1314
|
|
|
'max_length' => isset($sig_limits[1]) ? $sig_limits[1] : 0, |
1315
|
|
|
'max_lines' => isset($sig_limits[2]) ? $sig_limits[2] : 0, |
1316
|
|
|
'max_images' => isset($sig_limits[3]) ? $sig_limits[3] : 0, |
1317
|
|
|
'allow_smileys' => isset($sig_limits[4]) && $sig_limits[4] == -1 ? 0 : 1, |
1318
|
|
|
'max_smileys' => isset($sig_limits[4]) && $sig_limits[4] != -1 ? $sig_limits[4] : 0, |
1319
|
|
|
'max_image_width' => isset($sig_limits[5]) ? $sig_limits[5] : 0, |
1320
|
|
|
'max_image_height' => isset($sig_limits[6]) ? $sig_limits[6] : 0, |
1321
|
|
|
'max_font_size' => isset($sig_limits[7]) ? $sig_limits[7] : 0, |
1322
|
|
|
); |
1323
|
|
|
|
1324
|
|
|
// Temporarily make each setting a modSetting! |
1325
|
|
|
foreach ($context['signature_settings'] as $key => $value) |
1326
|
|
|
$modSettings['signature_' . $key] = $value; |
1327
|
|
|
|
1328
|
|
|
// Make sure we check the right tags! |
1329
|
|
|
$modSettings['bbc_disabled_signature_bbc'] = $disabledTags; |
1330
|
|
|
|
1331
|
|
|
// Saving? |
1332
|
|
|
if (isset($_GET['save'])) |
1333
|
|
|
{ |
1334
|
|
|
checkSession(); |
1335
|
|
|
|
1336
|
|
|
// Clean up the tag stuff! |
1337
|
|
|
$bbcTags = array(); |
1338
|
|
|
foreach (parse_bbc(false) as $tag) |
1339
|
|
|
$bbcTags[] = $tag['tag']; |
1340
|
|
|
|
1341
|
|
|
if (!isset($_POST['signature_bbc_enabledTags'])) |
1342
|
|
|
$_POST['signature_bbc_enabledTags'] = array(); |
1343
|
|
|
elseif (!is_array($_POST['signature_bbc_enabledTags'])) |
1344
|
|
|
$_POST['signature_bbc_enabledTags'] = array($_POST['signature_bbc_enabledTags']); |
1345
|
|
|
|
1346
|
|
|
$sig_limits = array(); |
1347
|
|
|
foreach ($context['signature_settings'] as $key => $value) |
1348
|
|
|
{ |
1349
|
|
|
if ($key == 'allow_smileys') |
1350
|
|
|
continue; |
1351
|
|
|
elseif ($key == 'max_smileys' && empty($_POST['signature_allow_smileys'])) |
1352
|
|
|
$sig_limits[] = -1; |
1353
|
|
|
else |
1354
|
|
|
$sig_limits[] = !empty($_POST['signature_' . $key]) ? max(1, (int) $_POST['signature_' . $key]) : 0; |
1355
|
|
|
} |
1356
|
|
|
|
1357
|
|
|
call_integration_hook('integrate_save_signature_settings', array(&$sig_limits, &$bbcTags)); |
1358
|
|
|
|
1359
|
|
|
$_POST['signature_settings'] = implode(',', $sig_limits) . ':' . implode(',', array_diff($bbcTags, $_POST['signature_bbc_enabledTags'])); |
1360
|
|
|
|
1361
|
|
|
// Even though we have practically no settings let's keep the convention going! |
1362
|
|
|
$save_vars = array(); |
1363
|
|
|
$save_vars[] = array('text', 'signature_settings'); |
1364
|
|
|
|
1365
|
|
|
saveDBSettings($save_vars); |
1366
|
|
|
$_SESSION['adm-save'] = true; |
1367
|
|
|
redirectexit('action=admin;area=featuresettings;sa=sig'); |
1368
|
|
|
} |
1369
|
|
|
|
1370
|
|
|
$context['post_url'] = $scripturl . '?action=admin;area=featuresettings;save;sa=sig'; |
1371
|
|
|
$context['settings_title'] = $txt['signature_settings']; |
1372
|
|
|
|
1373
|
|
|
if (!empty($settings_applied)) |
1374
|
|
|
$context['settings_message'] = array( |
1375
|
|
|
'label' => $txt['signature_settings_applied'], |
1376
|
|
|
'tag' => 'div', |
1377
|
|
|
'class' => 'infobox' |
1378
|
|
|
); |
1379
|
|
|
else |
1380
|
|
|
$context['settings_message'] = array( |
1381
|
|
|
'label' => sprintf($txt['signature_settings_warning'], $context['session_id'], $context['session_var'], $scripturl), |
1382
|
|
|
'tag' => 'div', |
1383
|
|
|
'class' => 'centertext' |
1384
|
|
|
); |
1385
|
|
|
|
1386
|
|
|
prepareDBSettingContext($config_vars); |
1387
|
|
|
} |
1388
|
|
|
|
1389
|
|
|
/** |
1390
|
|
|
* Just pause the signature applying thing. |
1391
|
|
|
*/ |
1392
|
|
|
function pauseSignatureApplySettings() |
1393
|
|
|
{ |
1394
|
|
|
global $context, $txt, $sig_start; |
1395
|
|
|
|
1396
|
|
|
// Try get more time... |
1397
|
|
|
@set_time_limit(600); |
1398
|
|
|
if (function_exists('apache_reset_timeout')) |
1399
|
|
|
@apache_reset_timeout(); |
1400
|
|
|
|
1401
|
|
|
// Have we exhausted all the time we allowed? |
1402
|
|
|
if (time() - array_sum(explode(' ', $sig_start)) < 3) |
1403
|
|
|
return; |
1404
|
|
|
|
1405
|
|
|
$context['continue_get_data'] = '?action=admin;area=featuresettings;sa=sig;apply;step=' . $_GET['step'] . ';' . $context['session_var'] . '=' . $context['session_id']; |
1406
|
|
|
$context['page_title'] = $txt['not_done_title']; |
1407
|
|
|
$context['continue_post_data'] = ''; |
1408
|
|
|
$context['continue_countdown'] = '2'; |
1409
|
|
|
$context['sub_template'] = 'not_done'; |
1410
|
|
|
|
1411
|
|
|
// Specific stuff to not break this template! |
1412
|
|
|
$context[$context['admin_menu_name']]['current_subsection'] = 'sig'; |
1413
|
|
|
|
1414
|
|
|
// Get the right percent. |
1415
|
|
|
$context['continue_percent'] = round(($_GET['step'] / $context['max_member']) * 100); |
1416
|
|
|
|
1417
|
|
|
// Never more than 100%! |
1418
|
|
|
$context['continue_percent'] = min($context['continue_percent'], 100); |
1419
|
|
|
|
1420
|
|
|
obExit(); |
1421
|
|
|
} |
1422
|
|
|
|
1423
|
|
|
/** |
1424
|
|
|
* Show all the custom profile fields available to the user. |
1425
|
|
|
*/ |
1426
|
|
|
function ShowCustomProfiles() |
1427
|
|
|
{ |
1428
|
|
|
global $txt, $scripturl, $context; |
1429
|
|
|
global $sourcedir; |
1430
|
|
|
|
1431
|
|
|
$context['page_title'] = $txt['custom_profile_title']; |
1432
|
|
|
$context['sub_template'] = 'show_custom_profile'; |
1433
|
|
|
|
1434
|
|
|
// What about standard fields they can tweak? |
1435
|
|
|
$standard_fields = array('website', 'personal_text', 'timezone', 'posts', 'warning_status'); |
1436
|
|
|
// What fields can't you put on the registration page? |
1437
|
|
|
$context['fields_no_registration'] = array('posts', 'warning_status'); |
1438
|
|
|
|
1439
|
|
|
// Are we saving any standard field changes? |
1440
|
|
|
if (isset($_POST['save'])) |
1441
|
|
|
{ |
1442
|
|
|
checkSession(); |
1443
|
|
|
validateToken('admin-scp'); |
1444
|
|
|
|
1445
|
|
|
// Do the active ones first. |
1446
|
|
|
$disable_fields = array_flip($standard_fields); |
1447
|
|
|
if (!empty($_POST['active'])) |
1448
|
|
|
{ |
1449
|
|
|
foreach ($_POST['active'] as $value) |
1450
|
|
|
if (isset($disable_fields[$value])) |
1451
|
|
|
unset($disable_fields[$value]); |
1452
|
|
|
} |
1453
|
|
|
// What we have left! |
1454
|
|
|
$changes['disabled_profile_fields'] = empty($disable_fields) ? '' : implode(',', array_keys($disable_fields)); |
|
|
|
|
1455
|
|
|
|
1456
|
|
|
// Things we want to show on registration? |
1457
|
|
|
$reg_fields = array(); |
1458
|
|
|
if (!empty($_POST['reg'])) |
1459
|
|
|
{ |
1460
|
|
|
foreach ($_POST['reg'] as $value) |
1461
|
|
|
if (in_array($value, $standard_fields) && !isset($disable_fields[$value])) |
1462
|
|
|
$reg_fields[] = $value; |
1463
|
|
|
} |
1464
|
|
|
// What we have left! |
1465
|
|
|
$changes['registration_fields'] = empty($reg_fields) ? '' : implode(',', $reg_fields); |
1466
|
|
|
|
1467
|
|
|
$_SESSION['adm-save'] = true; |
1468
|
|
|
if (!empty($changes)) |
1469
|
|
|
updateSettings($changes); |
1470
|
|
|
} |
1471
|
|
|
|
1472
|
|
|
createToken('admin-scp'); |
1473
|
|
|
|
1474
|
|
|
// Need to know the max order for custom fields |
1475
|
|
|
$context['custFieldsMaxOrder'] = custFieldsMaxOrder(); |
1476
|
|
|
|
1477
|
|
|
require_once($sourcedir . '/Subs-List.php'); |
1478
|
|
|
|
1479
|
|
|
$listOptions = array( |
1480
|
|
|
'id' => 'standard_profile_fields', |
1481
|
|
|
'title' => $txt['standard_profile_title'], |
1482
|
|
|
'base_href' => $scripturl . '?action=admin;area=featuresettings;sa=profile', |
1483
|
|
|
'get_items' => array( |
1484
|
|
|
'function' => 'list_getProfileFields', |
1485
|
|
|
'params' => array( |
1486
|
|
|
true, |
1487
|
|
|
), |
1488
|
|
|
), |
1489
|
|
|
'columns' => array( |
1490
|
|
|
'field' => array( |
1491
|
|
|
'header' => array( |
1492
|
|
|
'value' => $txt['standard_profile_field'], |
1493
|
|
|
), |
1494
|
|
|
'data' => array( |
1495
|
|
|
'db' => 'label', |
1496
|
|
|
'style' => 'width: 60%;', |
1497
|
|
|
), |
1498
|
|
|
), |
1499
|
|
|
'active' => array( |
1500
|
|
|
'header' => array( |
1501
|
|
|
'value' => $txt['custom_edit_active'], |
1502
|
|
|
'class' => 'centercol', |
1503
|
|
|
), |
1504
|
|
|
'data' => array( |
1505
|
|
|
'function' => function($rowData) |
1506
|
|
|
{ |
1507
|
|
|
$isChecked = $rowData['disabled'] ? '' : ' checked'; |
1508
|
|
|
$onClickHandler = $rowData['can_show_register'] ? sprintf(' onclick="document.getElementById(\'reg_%1$s\').disabled = !this.checked;"', $rowData['id']) : ''; |
1509
|
|
|
return sprintf('<input type="checkbox" name="active[]" id="active_%1$s" value="%1$s" %2$s%3$s>', $rowData['id'], $isChecked, $onClickHandler); |
1510
|
|
|
}, |
1511
|
|
|
'style' => 'width: 20%;', |
1512
|
|
|
'class' => 'centercol', |
1513
|
|
|
), |
1514
|
|
|
), |
1515
|
|
|
'show_on_registration' => array( |
1516
|
|
|
'header' => array( |
1517
|
|
|
'value' => $txt['custom_edit_registration'], |
1518
|
|
|
'class' => 'centercol', |
1519
|
|
|
), |
1520
|
|
|
'data' => array( |
1521
|
|
|
'function' => function($rowData) |
1522
|
|
|
{ |
1523
|
|
|
$isChecked = $rowData['on_register'] && !$rowData['disabled'] ? ' checked' : ''; |
1524
|
|
|
$isDisabled = $rowData['can_show_register'] ? '' : ' disabled'; |
1525
|
|
|
return sprintf('<input type="checkbox" name="reg[]" id="reg_%1$s" value="%1$s" %2$s%3$s>', $rowData['id'], $isChecked, $isDisabled); |
1526
|
|
|
}, |
1527
|
|
|
'style' => 'width: 20%;', |
1528
|
|
|
'class' => 'centercol', |
1529
|
|
|
), |
1530
|
|
|
), |
1531
|
|
|
), |
1532
|
|
|
'form' => array( |
1533
|
|
|
'href' => $scripturl . '?action=admin;area=featuresettings;sa=profile', |
1534
|
|
|
'name' => 'standardProfileFields', |
1535
|
|
|
'token' => 'admin-scp', |
1536
|
|
|
), |
1537
|
|
|
'additional_rows' => array( |
1538
|
|
|
array( |
1539
|
|
|
'position' => 'below_table_data', |
1540
|
|
|
'value' => '<input type="submit" name="save" value="' . $txt['save'] . '" class="button">', |
1541
|
|
|
), |
1542
|
|
|
), |
1543
|
|
|
); |
1544
|
|
|
createList($listOptions); |
1545
|
|
|
|
1546
|
|
|
$listOptions = array( |
1547
|
|
|
'id' => 'custom_profile_fields', |
1548
|
|
|
'title' => $txt['custom_profile_title'], |
1549
|
|
|
'base_href' => $scripturl . '?action=admin;area=featuresettings;sa=profile', |
1550
|
|
|
'default_sort_col' => 'field_order', |
1551
|
|
|
'no_items_label' => $txt['custom_profile_none'], |
1552
|
|
|
'items_per_page' => 25, |
1553
|
|
|
'get_items' => array( |
1554
|
|
|
'function' => 'list_getProfileFields', |
1555
|
|
|
'params' => array( |
1556
|
|
|
false, |
1557
|
|
|
), |
1558
|
|
|
), |
1559
|
|
|
'get_count' => array( |
1560
|
|
|
'function' => 'list_getProfileFieldSize', |
1561
|
|
|
), |
1562
|
|
|
'columns' => array( |
1563
|
|
|
'field_order' => array( |
1564
|
|
|
'header' => array( |
1565
|
|
|
'value' => $txt['custom_profile_fieldorder'], |
1566
|
|
|
), |
1567
|
|
|
'data' => array( |
1568
|
|
|
'function' => function($rowData) use ($context, $txt, $scripturl) |
1569
|
|
|
{ |
1570
|
|
|
$return = '<p class="centertext bold_text">'; |
1571
|
|
|
|
1572
|
|
|
if ($rowData['field_order'] > 1) |
1573
|
|
|
$return .= '<a href="' . $scripturl . '?action=admin;area=featuresettings;sa=profileedit;fid=' . $rowData['id_field'] . ';move=up"><span class="toggle_up" title="' . $txt['custom_edit_order_move'] . ' ' . $txt['custom_edit_order_up'] . '"></span></a>'; |
1574
|
|
|
|
1575
|
|
|
if ($rowData['field_order'] < $context['custFieldsMaxOrder']) |
1576
|
|
|
$return .= '<a href="' . $scripturl . '?action=admin;area=featuresettings;sa=profileedit;fid=' . $rowData['id_field'] . ';move=down"><span class="toggle_down" title="' . $txt['custom_edit_order_move'] . ' ' . $txt['custom_edit_order_down'] . '"></span></a>'; |
1577
|
|
|
|
1578
|
|
|
$return .= '</p>'; |
1579
|
|
|
|
1580
|
|
|
return $return; |
1581
|
|
|
}, |
1582
|
|
|
'style' => 'width: 12%;', |
1583
|
|
|
), |
1584
|
|
|
'sort' => array( |
1585
|
|
|
'default' => 'field_order', |
1586
|
|
|
'reverse' => 'field_order DESC', |
1587
|
|
|
), |
1588
|
|
|
), |
1589
|
|
|
'field_name' => array( |
1590
|
|
|
'header' => array( |
1591
|
|
|
'value' => $txt['custom_profile_fieldname'], |
1592
|
|
|
), |
1593
|
|
|
'data' => array( |
1594
|
|
|
'function' => function($rowData) use ($scripturl) |
1595
|
|
|
{ |
1596
|
|
|
$field_name = tokenTxtReplace($rowData['field_name']); |
1597
|
|
|
$field_desc = tokenTxtReplace($rowData['field_desc']); |
1598
|
|
|
|
1599
|
|
|
return sprintf('<a href="%1$s?action=admin;area=featuresettings;sa=profileedit;fid=%2$d">%3$s</a><div class="smalltext">%4$s</div>', |
1600
|
|
|
$scripturl, |
1601
|
|
|
$rowData['id_field'], |
1602
|
|
|
$field_name, |
1603
|
|
|
$field_desc); |
1604
|
|
|
}, |
1605
|
|
|
'style' => 'width: 62%;', |
1606
|
|
|
), |
1607
|
|
|
'sort' => array( |
1608
|
|
|
'default' => 'field_name', |
1609
|
|
|
'reverse' => 'field_name DESC', |
1610
|
|
|
), |
1611
|
|
|
), |
1612
|
|
|
'field_type' => array( |
1613
|
|
|
'header' => array( |
1614
|
|
|
'value' => $txt['custom_profile_fieldtype'], |
1615
|
|
|
), |
1616
|
|
|
'data' => array( |
1617
|
|
|
'function' => function($rowData) use ($txt) |
1618
|
|
|
{ |
1619
|
|
|
$textKey = sprintf('custom_profile_type_%1$s', $rowData['field_type']); |
1620
|
|
|
return isset($txt[$textKey]) ? $txt[$textKey] : $textKey; |
1621
|
|
|
}, |
1622
|
|
|
'style' => 'width: 15%;', |
1623
|
|
|
), |
1624
|
|
|
'sort' => array( |
1625
|
|
|
'default' => 'field_type', |
1626
|
|
|
'reverse' => 'field_type DESC', |
1627
|
|
|
), |
1628
|
|
|
), |
1629
|
|
|
'active' => array( |
1630
|
|
|
'header' => array( |
1631
|
|
|
'value' => $txt['custom_profile_active'], |
1632
|
|
|
), |
1633
|
|
|
'data' => array( |
1634
|
|
|
'function' => function($rowData) use ($txt) |
1635
|
|
|
{ |
1636
|
|
|
return $rowData['active'] ? $txt['yes'] : $txt['no']; |
1637
|
|
|
}, |
1638
|
|
|
'style' => 'width: 8%;', |
1639
|
|
|
), |
1640
|
|
|
'sort' => array( |
1641
|
|
|
'default' => 'active DESC', |
1642
|
|
|
'reverse' => 'active', |
1643
|
|
|
), |
1644
|
|
|
), |
1645
|
|
|
'placement' => array( |
1646
|
|
|
'header' => array( |
1647
|
|
|
'value' => $txt['custom_profile_placement'], |
1648
|
|
|
), |
1649
|
|
|
'data' => array( |
1650
|
|
|
'function' => function($rowData) |
1651
|
|
|
{ |
1652
|
|
|
global $txt, $context; |
1653
|
|
|
|
1654
|
|
|
return $txt['custom_profile_placement_' . (empty($rowData['placement']) ? 'standard' : $context['cust_profile_fields_placement'][$rowData['placement']])]; |
1655
|
|
|
}, |
1656
|
|
|
'style' => 'width: 8%;', |
1657
|
|
|
), |
1658
|
|
|
'sort' => array( |
1659
|
|
|
'default' => 'placement DESC', |
1660
|
|
|
'reverse' => 'placement', |
1661
|
|
|
), |
1662
|
|
|
), |
1663
|
|
|
'show_on_registration' => array( |
1664
|
|
|
'data' => array( |
1665
|
|
|
'sprintf' => array( |
1666
|
|
|
'format' => '<a href="' . $scripturl . '?action=admin;area=featuresettings;sa=profileedit;fid=%1$s">' . $txt['modify'] . '</a>', |
1667
|
|
|
'params' => array( |
1668
|
|
|
'id_field' => false, |
1669
|
|
|
), |
1670
|
|
|
), |
1671
|
|
|
'style' => 'width: 15%;', |
1672
|
|
|
), |
1673
|
|
|
), |
1674
|
|
|
), |
1675
|
|
|
'form' => array( |
1676
|
|
|
'href' => $scripturl . '?action=admin;area=featuresettings;sa=profileedit', |
1677
|
|
|
'name' => 'customProfileFields', |
1678
|
|
|
), |
1679
|
|
|
'additional_rows' => array( |
1680
|
|
|
array( |
1681
|
|
|
'position' => 'below_table_data', |
1682
|
|
|
'value' => '<input type="submit" name="new" value="' . $txt['custom_profile_make_new'] . '" class="button">', |
1683
|
|
|
), |
1684
|
|
|
), |
1685
|
|
|
); |
1686
|
|
|
createList($listOptions); |
1687
|
|
|
|
1688
|
|
|
// There are two different ways we could get to this point. To keep it simple, they both do |
1689
|
|
|
// the same basic thing. |
1690
|
|
|
if (isset($_SESSION['adm-save'])) |
1691
|
|
|
{ |
1692
|
|
|
$context['saved_successful'] = true; |
1693
|
|
|
unset ($_SESSION['adm-save']); |
1694
|
|
|
} |
1695
|
|
|
} |
1696
|
|
|
|
1697
|
|
|
/** |
1698
|
|
|
* Callback for createList(). |
1699
|
|
|
* |
1700
|
|
|
* @param int $start The item to start with (used for pagination purposes) |
1701
|
|
|
* @param int $items_per_page The number of items to display per page |
1702
|
|
|
* @param string $sort A string indicating how to sort the results |
1703
|
|
|
* @param bool $standardFields Whether or not to include standard fields as well |
1704
|
|
|
* @return array An array of info about the various profile fields |
1705
|
|
|
*/ |
1706
|
|
|
function list_getProfileFields($start, $items_per_page, $sort, $standardFields) |
1707
|
|
|
{ |
1708
|
|
|
global $txt, $modSettings, $smcFunc; |
1709
|
|
|
|
1710
|
|
|
$list = array(); |
1711
|
|
|
|
1712
|
|
|
if ($standardFields) |
1713
|
|
|
{ |
1714
|
|
|
$standard_fields = array('website', 'personal_text', 'timezone', 'posts', 'warning_status'); |
1715
|
|
|
$fields_no_registration = array('posts', 'warning_status'); |
1716
|
|
|
$disabled_fields = isset($modSettings['disabled_profile_fields']) ? explode(',', $modSettings['disabled_profile_fields']) : array(); |
1717
|
|
|
$registration_fields = isset($modSettings['registration_fields']) ? explode(',', $modSettings['registration_fields']) : array(); |
1718
|
|
|
|
1719
|
|
|
foreach ($standard_fields as $field) |
1720
|
|
|
$list[] = array( |
1721
|
|
|
'id' => $field, |
1722
|
|
|
'label' => isset($txt['standard_profile_field_' . $field]) ? $txt['standard_profile_field_' . $field] : (isset($txt[$field]) ? $txt[$field] : $field), |
1723
|
|
|
'disabled' => in_array($field, $disabled_fields), |
1724
|
|
|
'on_register' => in_array($field, $registration_fields) && !in_array($field, $fields_no_registration), |
1725
|
|
|
'can_show_register' => !in_array($field, $fields_no_registration), |
1726
|
|
|
); |
1727
|
|
|
} |
1728
|
|
|
else |
1729
|
|
|
{ |
1730
|
|
|
// Load all the fields. |
1731
|
|
|
$request = $smcFunc['db_query']('', ' |
1732
|
|
|
SELECT id_field, col_name, field_name, field_desc, field_type, field_order, active, placement |
1733
|
|
|
FROM {db_prefix}custom_fields |
1734
|
|
|
ORDER BY {raw:sort} |
1735
|
|
|
LIMIT {int:start}, {int:items_per_page}', |
1736
|
|
|
array( |
1737
|
|
|
'sort' => $sort, |
1738
|
|
|
'start' => $start, |
1739
|
|
|
'items_per_page' => $items_per_page, |
1740
|
|
|
) |
1741
|
|
|
); |
1742
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
1743
|
|
|
$list[] = $row; |
1744
|
|
|
$smcFunc['db_free_result']($request); |
1745
|
|
|
} |
1746
|
|
|
|
1747
|
|
|
return $list; |
1748
|
|
|
} |
1749
|
|
|
|
1750
|
|
|
/** |
1751
|
|
|
* Callback for createList(). |
1752
|
|
|
* |
1753
|
|
|
* @return int The total number of custom profile fields |
1754
|
|
|
*/ |
1755
|
|
|
function list_getProfileFieldSize() |
1756
|
|
|
{ |
1757
|
|
|
global $smcFunc; |
1758
|
|
|
|
1759
|
|
|
$request = $smcFunc['db_query']('', ' |
1760
|
|
|
SELECT COUNT(*) |
1761
|
|
|
FROM {db_prefix}custom_fields', |
1762
|
|
|
array( |
1763
|
|
|
) |
1764
|
|
|
); |
1765
|
|
|
|
1766
|
|
|
list ($numProfileFields) = $smcFunc['db_fetch_row']($request); |
1767
|
|
|
$smcFunc['db_free_result']($request); |
1768
|
|
|
|
1769
|
|
|
return $numProfileFields; |
1770
|
|
|
} |
1771
|
|
|
|
1772
|
|
|
/** |
1773
|
|
|
* Edit some profile fields? |
1774
|
|
|
*/ |
1775
|
|
|
function EditCustomProfiles() |
1776
|
|
|
{ |
1777
|
|
|
global $txt, $scripturl, $context, $smcFunc; |
1778
|
|
|
|
1779
|
|
|
// Sort out the context! |
1780
|
|
|
$context['fid'] = isset($_GET['fid']) ? (int) $_GET['fid'] : 0; |
1781
|
|
|
$context[$context['admin_menu_name']]['current_subsection'] = 'profile'; |
1782
|
|
|
$context['page_title'] = $context['fid'] ? $txt['custom_edit_title'] : $txt['custom_add_title']; |
1783
|
|
|
$context['sub_template'] = 'edit_profile_field'; |
1784
|
|
|
|
1785
|
|
|
// Load the profile language for section names. |
1786
|
|
|
loadLanguage('Profile'); |
1787
|
|
|
|
1788
|
|
|
// There's really only a few places we can go... |
1789
|
|
|
$move_to = array('up', 'down'); |
1790
|
|
|
|
1791
|
|
|
// We need this for both moving and saving so put it right here. |
1792
|
|
|
$order_count = custFieldsMaxOrder(); |
1793
|
|
|
|
1794
|
|
|
if ($context['fid'] && !isset($_GET['move'])) |
1795
|
|
|
{ |
1796
|
|
|
$request = $smcFunc['db_query']('', ' |
1797
|
|
|
SELECT |
1798
|
|
|
id_field, col_name, field_name, field_desc, field_type, field_order, field_length, field_options, |
1799
|
|
|
show_reg, show_display, show_mlist, show_profile, private, active, default_value, can_search, |
1800
|
|
|
bbc, mask, enclose, placement |
1801
|
|
|
FROM {db_prefix}custom_fields |
1802
|
|
|
WHERE id_field = {int:current_field}', |
1803
|
|
|
array( |
1804
|
|
|
'current_field' => $context['fid'], |
1805
|
|
|
) |
1806
|
|
|
); |
1807
|
|
|
$context['field'] = array(); |
1808
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
1809
|
|
|
{ |
1810
|
|
|
if ($row['field_type'] == 'textarea') |
1811
|
|
|
@list ($rows, $cols) = @explode(',', $row['default_value']); |
1812
|
|
|
else |
1813
|
|
|
{ |
1814
|
|
|
$rows = 3; |
1815
|
|
|
$cols = 30; |
1816
|
|
|
} |
1817
|
|
|
|
1818
|
|
|
$context['field'] = array( |
1819
|
|
|
'name' => $row['field_name'], |
1820
|
|
|
'desc' => $row['field_desc'], |
1821
|
|
|
'col_name' => $row['col_name'], |
1822
|
|
|
'profile_area' => $row['show_profile'], |
1823
|
|
|
'reg' => $row['show_reg'], |
1824
|
|
|
'display' => $row['show_display'], |
1825
|
|
|
'mlist' => $row['show_mlist'], |
1826
|
|
|
'type' => $row['field_type'], |
1827
|
|
|
'order' => $row['field_order'], |
1828
|
|
|
'max_length' => $row['field_length'], |
1829
|
|
|
'rows' => $rows, |
1830
|
|
|
'cols' => $cols, |
1831
|
|
|
'bbc' => $row['bbc'] ? true : false, |
1832
|
|
|
'default_check' => $row['field_type'] == 'check' && $row['default_value'] ? true : false, |
1833
|
|
|
'default_select' => $row['field_type'] == 'select' || $row['field_type'] == 'radio' ? $row['default_value'] : '', |
1834
|
|
|
'options' => strlen($row['field_options']) > 1 ? explode(',', $row['field_options']) : array('', '', ''), |
1835
|
|
|
'active' => $row['active'], |
1836
|
|
|
'private' => $row['private'], |
1837
|
|
|
'can_search' => $row['can_search'], |
1838
|
|
|
'mask' => $row['mask'], |
1839
|
|
|
'regex' => substr($row['mask'], 0, 5) == 'regex' ? substr($row['mask'], 5) : '', |
1840
|
|
|
'enclose' => $row['enclose'], |
1841
|
|
|
'placement' => $row['placement'], |
1842
|
|
|
); |
1843
|
|
|
} |
1844
|
|
|
$smcFunc['db_free_result']($request); |
1845
|
|
|
} |
1846
|
|
|
|
1847
|
|
|
// Setup the default values as needed. |
1848
|
|
|
if (empty($context['field'])) |
1849
|
|
|
$context['field'] = array( |
1850
|
|
|
'name' => '', |
1851
|
|
|
'col_name' => '???', |
1852
|
|
|
'desc' => '', |
1853
|
|
|
'profile_area' => 'forumprofile', |
1854
|
|
|
'reg' => false, |
1855
|
|
|
'display' => false, |
1856
|
|
|
'mlist' => false, |
1857
|
|
|
'type' => 'text', |
1858
|
|
|
'order' => 0, |
1859
|
|
|
'max_length' => 255, |
1860
|
|
|
'rows' => 4, |
1861
|
|
|
'cols' => 30, |
1862
|
|
|
'bbc' => false, |
1863
|
|
|
'default_check' => false, |
1864
|
|
|
'default_select' => '', |
1865
|
|
|
'options' => array('', '', ''), |
1866
|
|
|
'active' => true, |
1867
|
|
|
'private' => false, |
1868
|
|
|
'can_search' => false, |
1869
|
|
|
'mask' => 'nohtml', |
1870
|
|
|
'regex' => '', |
1871
|
|
|
'enclose' => '', |
1872
|
|
|
'placement' => 0, |
1873
|
|
|
); |
1874
|
|
|
|
1875
|
|
|
// Are we moving it? |
1876
|
|
|
if ($context['fid'] && isset($_GET['move']) && in_array($smcFunc['htmlspecialchars']($_GET['move']), $move_to)) |
1877
|
|
|
{ |
1878
|
|
|
$request = $smcFunc['db_query']('', ' |
1879
|
|
|
SELECT |
1880
|
|
|
id_field, field_order |
1881
|
|
|
FROM {db_prefix}custom_fields |
1882
|
|
|
ORDER BY field_order', |
1883
|
|
|
array() |
1884
|
|
|
); |
1885
|
|
|
$fields = array(); |
1886
|
|
|
$new_sort = array(); |
1887
|
|
|
|
1888
|
|
|
while($row = $smcFunc['db_fetch_assoc']($request)) |
1889
|
|
|
$fields[] = $row['id_field']; |
1890
|
|
|
$smcFunc['db_free_result']($request); |
1891
|
|
|
|
1892
|
|
|
$idx = array_search($context['fid'], $fields); |
1893
|
|
|
|
1894
|
|
|
if ($_GET['move'] == 'down' && count($fields) - 1 > $idx ) |
1895
|
|
|
{ |
1896
|
|
|
$new_sort = array_slice($fields ,0 ,$idx ,true); |
|
|
|
|
1897
|
|
|
$new_sort[] = $fields[$idx + 1]; |
1898
|
|
|
$new_sort[] = $fields[$idx]; |
1899
|
|
|
$new_sort += array_slice($fields ,$idx + 2 ,count($fields) ,true); |
1900
|
|
|
} |
1901
|
|
|
elseif ($context['fid'] > 0 and $idx < count($fields)) |
1902
|
|
|
{ |
1903
|
|
|
$new_sort = array_slice($fields ,0 ,($idx - 1) ,true); |
1904
|
|
|
$new_sort[] = $fields[$idx]; |
1905
|
|
|
$new_sort[] = $fields[$idx - 1]; |
1906
|
|
|
$new_sort += array_slice($fields ,($idx + 1) ,count($fields) ,true); |
1907
|
|
|
} |
1908
|
|
|
else |
1909
|
|
|
redirectexit('action=admin;area=featuresettings;sa=profile'); // @todo implement an error handler |
1910
|
|
|
|
1911
|
|
|
$sql_update = 'CASE '; |
1912
|
|
|
foreach ($new_sort as $orderKey => $PKid) |
1913
|
|
|
{ |
1914
|
|
|
$sql_update .= 'WHEN id_field = ' . $PKid . ' THEN ' . ($orderKey + 1) . ' '; |
1915
|
|
|
} |
1916
|
|
|
$sql_update .= 'END'; |
1917
|
|
|
|
1918
|
|
|
$smcFunc['db_query']('', ' |
1919
|
|
|
UPDATE {db_prefix}custom_fields |
1920
|
|
|
SET field_order = ' . $sql_update, |
1921
|
|
|
array() |
1922
|
|
|
); |
1923
|
|
|
|
1924
|
|
|
redirectexit('action=admin;area=featuresettings;sa=profile'); // @todo perhaps a nice confirmation message, dunno. |
1925
|
|
|
} |
1926
|
|
|
|
1927
|
|
|
// Are we saving? |
1928
|
|
|
if (isset($_POST['save'])) |
1929
|
|
|
{ |
1930
|
|
|
checkSession(); |
1931
|
|
|
validateToken('admin-ecp'); |
1932
|
|
|
|
1933
|
|
|
// Everyone needs a name - even the (bracket) unknown... |
1934
|
|
|
if (trim($_POST['field_name']) == '') |
1935
|
|
|
redirectexit($scripturl . '?action=admin;area=featuresettings;sa=profileedit;fid=' . $_GET['fid'] . ';msg=need_name'); |
1936
|
|
|
|
1937
|
|
|
// Regex you say? Do a very basic test to see if the pattern is valid |
1938
|
|
|
if (!empty($_POST['regex']) && @preg_match($_POST['regex'], 'dummy') === false) |
1939
|
|
|
redirectexit($scripturl . '?action=admin;area=featuresettings;sa=profileedit;fid=' . $_GET['fid'] . ';msg=regex_error'); |
1940
|
|
|
|
1941
|
|
|
$_POST['field_name'] = $smcFunc['htmlspecialchars']($_POST['field_name']); |
1942
|
|
|
$_POST['field_desc'] = $smcFunc['htmlspecialchars']($_POST['field_desc']); |
1943
|
|
|
|
1944
|
|
|
// Checkboxes... |
1945
|
|
|
$show_reg = isset($_POST['reg']) ? (int) $_POST['reg'] : 0; |
1946
|
|
|
$show_display = isset($_POST['display']) ? 1 : 0; |
1947
|
|
|
$show_mlist = isset($_POST['mlist']) ? 1 : 0; |
1948
|
|
|
$bbc = isset($_POST['bbc']) ? 1 : 0; |
1949
|
|
|
$show_profile = $_POST['profile_area']; |
1950
|
|
|
$active = isset($_POST['active']) ? 1 : 0; |
1951
|
|
|
$private = isset($_POST['private']) ? (int) $_POST['private'] : 0; |
1952
|
|
|
$can_search = isset($_POST['can_search']) ? 1 : 0; |
1953
|
|
|
|
1954
|
|
|
// Some masking stuff... |
1955
|
|
|
$mask = isset($_POST['mask']) ? $_POST['mask'] : ''; |
1956
|
|
|
if ($mask == 'regex' && isset($_POST['regex'])) |
1957
|
|
|
$mask .= $_POST['regex']; |
1958
|
|
|
$mask = $smcFunc['normalize']($mask); |
1959
|
|
|
|
1960
|
|
|
$field_length = isset($_POST['max_length']) ? (int) $_POST['max_length'] : 255; |
1961
|
|
|
$enclose = isset($_POST['enclose']) ? $smcFunc['normalize']($_POST['enclose']) : ''; |
1962
|
|
|
$placement = isset($_POST['placement']) ? (int) $_POST['placement'] : 0; |
1963
|
|
|
|
1964
|
|
|
// Select options? |
1965
|
|
|
$field_options = ''; |
1966
|
|
|
$newOptions = array(); |
1967
|
|
|
$default = isset($_POST['default_check']) && $_POST['field_type'] == 'check' ? 1 : ''; |
1968
|
|
|
if (!empty($_POST['select_option']) && ($_POST['field_type'] == 'select' || $_POST['field_type'] == 'radio')) |
1969
|
|
|
{ |
1970
|
|
|
foreach ($_POST['select_option'] as $k => $v) |
1971
|
|
|
{ |
1972
|
|
|
// Clean, clean, clean... |
1973
|
|
|
$v = $smcFunc['htmlspecialchars']($v); |
1974
|
|
|
$v = strtr($v, array(',' => '')); |
1975
|
|
|
|
1976
|
|
|
// Nada, zip, etc... |
1977
|
|
|
if (trim($v) == '') |
1978
|
|
|
continue; |
1979
|
|
|
|
1980
|
|
|
// Otherwise, save it boy. |
1981
|
|
|
$field_options .= $v . ','; |
1982
|
|
|
// This is just for working out what happened with old options... |
1983
|
|
|
$newOptions[$k] = $v; |
1984
|
|
|
|
1985
|
|
|
// Is it default? |
1986
|
|
|
if (isset($_POST['default_select']) && $_POST['default_select'] == $k) |
1987
|
|
|
$default = $v; |
1988
|
|
|
} |
1989
|
|
|
$field_options = substr($field_options, 0, -1); |
1990
|
|
|
} |
1991
|
|
|
|
1992
|
|
|
// Text area has default has dimensions |
1993
|
|
|
if ($_POST['field_type'] == 'textarea') |
1994
|
|
|
$default = (int) $_POST['rows'] . ',' . (int) $_POST['cols']; |
1995
|
|
|
|
1996
|
|
|
// Come up with the unique name? |
1997
|
|
|
if (empty($context['fid'])) |
1998
|
|
|
{ |
1999
|
|
|
$col_name = $smcFunc['substr'](strtr($_POST['field_name'], array(' ' => '')), 0, 6); |
2000
|
|
|
preg_match('~([\w\d_-]+)~', $col_name, $matches); |
2001
|
|
|
|
2002
|
|
|
// If there is nothing to the name, then let's start out own - for foreign languages etc. |
2003
|
|
|
if (isset($matches[1])) |
2004
|
|
|
$col_name = $initial_col_name = 'cust_' . strtolower($matches[1]); |
2005
|
|
|
else |
2006
|
|
|
$col_name = $initial_col_name = 'cust_' . mt_rand(1, 9999); |
2007
|
|
|
|
2008
|
|
|
// Make sure this is unique. |
2009
|
|
|
$current_fields = array(); |
2010
|
|
|
$request = $smcFunc['db_query']('', ' |
2011
|
|
|
SELECT id_field, col_name |
2012
|
|
|
FROM {db_prefix}custom_fields' |
2013
|
|
|
); |
2014
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
2015
|
|
|
$current_fields[$row['id_field']] = $row['col_name']; |
2016
|
|
|
|
2017
|
|
|
$smcFunc['db_free_result']($request); |
2018
|
|
|
|
2019
|
|
|
$unique = false; |
2020
|
|
|
for ($i = 0; !$unique && $i < 9; $i++) |
2021
|
|
|
{ |
2022
|
|
|
if (!in_array($col_name, $current_fields)) |
2023
|
|
|
$unique = true; |
2024
|
|
|
else |
2025
|
|
|
$col_name = $initial_col_name . $i; |
2026
|
|
|
} |
2027
|
|
|
|
2028
|
|
|
// Still not a unique column name? Leave it up to the user, then. |
2029
|
|
|
if (!$unique) |
2030
|
|
|
fatal_lang_error('custom_option_not_unique'); |
2031
|
|
|
} |
2032
|
|
|
// Work out what to do with the user data otherwise... |
2033
|
|
|
else |
2034
|
|
|
{ |
2035
|
|
|
// Anything going to check or select is pointless keeping - as is anything coming from check! |
2036
|
|
|
if (($_POST['field_type'] == 'check' && $context['field']['type'] != 'check') |
2037
|
|
|
|| (($_POST['field_type'] == 'select' || $_POST['field_type'] == 'radio') && $context['field']['type'] != 'select' && $context['field']['type'] != 'radio') |
2038
|
|
|
|| ($context['field']['type'] == 'check' && $_POST['field_type'] != 'check')) |
2039
|
|
|
{ |
2040
|
|
|
$smcFunc['db_query']('', ' |
2041
|
|
|
DELETE FROM {db_prefix}themes |
2042
|
|
|
WHERE variable = {string:current_column} |
2043
|
|
|
AND id_member > {int:no_member}', |
2044
|
|
|
array( |
2045
|
|
|
'no_member' => 0, |
2046
|
|
|
'current_column' => $context['field']['col_name'], |
2047
|
|
|
) |
2048
|
|
|
); |
2049
|
|
|
} |
2050
|
|
|
// Otherwise - if the select is edited may need to adjust! |
2051
|
|
|
elseif ($_POST['field_type'] == 'select' || $_POST['field_type'] == 'radio') |
2052
|
|
|
{ |
2053
|
|
|
$optionChanges = array(); |
2054
|
|
|
$takenKeys = array(); |
2055
|
|
|
// Work out what's changed! |
2056
|
|
|
foreach ($context['field']['options'] as $k => $option) |
2057
|
|
|
{ |
2058
|
|
|
if (trim($option) == '') |
2059
|
|
|
continue; |
2060
|
|
|
|
2061
|
|
|
// Still exists? |
2062
|
|
|
if (in_array($option, $newOptions)) |
2063
|
|
|
{ |
2064
|
|
|
$takenKeys[] = $k; |
2065
|
|
|
continue; |
2066
|
|
|
} |
2067
|
|
|
} |
2068
|
|
|
|
2069
|
|
|
// Finally - have we renamed it - or is it really gone? |
2070
|
|
|
foreach ($optionChanges as $k => $option) |
2071
|
|
|
{ |
2072
|
|
|
// Just been renamed? |
2073
|
|
|
if (!in_array($k, $takenKeys) && !empty($newOptions[$k])) |
2074
|
|
|
$smcFunc['db_query']('', ' |
2075
|
|
|
UPDATE {db_prefix}themes |
2076
|
|
|
SET value = {string:new_value} |
2077
|
|
|
WHERE variable = {string:current_column} |
2078
|
|
|
AND value = {string:old_value} |
2079
|
|
|
AND id_member > {int:no_member}', |
2080
|
|
|
array( |
2081
|
|
|
'no_member' => 0, |
2082
|
|
|
'new_value' => $newOptions[$k], |
2083
|
|
|
'current_column' => $context['field']['col_name'], |
2084
|
|
|
'old_value' => $option, |
2085
|
|
|
) |
2086
|
|
|
); |
2087
|
|
|
} |
2088
|
|
|
} |
2089
|
|
|
// @todo Maybe we should adjust based on new text length limits? |
2090
|
|
|
} |
2091
|
|
|
|
2092
|
|
|
// Do the insertion/updates. |
2093
|
|
|
if ($context['fid']) |
2094
|
|
|
{ |
2095
|
|
|
$smcFunc['db_query']('', ' |
2096
|
|
|
UPDATE {db_prefix}custom_fields |
2097
|
|
|
SET |
2098
|
|
|
field_name = {string:field_name}, field_desc = {string:field_desc}, |
2099
|
|
|
field_type = {string:field_type}, field_length = {int:field_length}, |
2100
|
|
|
field_options = {string:field_options}, show_reg = {int:show_reg}, |
2101
|
|
|
show_display = {int:show_display}, show_mlist = {int:show_mlist}, show_profile = {string:show_profile}, |
2102
|
|
|
private = {int:private}, active = {int:active}, default_value = {string:default_value}, |
2103
|
|
|
can_search = {int:can_search}, bbc = {int:bbc}, mask = {string:mask}, |
2104
|
|
|
enclose = {string:enclose}, placement = {int:placement} |
2105
|
|
|
WHERE id_field = {int:current_field}', |
2106
|
|
|
array( |
2107
|
|
|
'field_length' => $field_length, |
2108
|
|
|
'show_reg' => $show_reg, |
2109
|
|
|
'show_display' => $show_display, |
2110
|
|
|
'show_mlist' => $show_mlist, |
2111
|
|
|
'private' => $private, |
2112
|
|
|
'active' => $active, |
2113
|
|
|
'can_search' => $can_search, |
2114
|
|
|
'bbc' => $bbc, |
2115
|
|
|
'current_field' => $context['fid'], |
2116
|
|
|
'field_name' => $_POST['field_name'], |
2117
|
|
|
'field_desc' => $_POST['field_desc'], |
2118
|
|
|
'field_type' => $_POST['field_type'], |
2119
|
|
|
'field_options' => $field_options, |
2120
|
|
|
'show_profile' => $show_profile, |
2121
|
|
|
'default_value' => $default, |
2122
|
|
|
'mask' => $mask, |
2123
|
|
|
'enclose' => $enclose, |
2124
|
|
|
'placement' => $placement, |
2125
|
|
|
) |
2126
|
|
|
); |
2127
|
|
|
|
2128
|
|
|
// Just clean up any old selects - these are a pain! |
2129
|
|
|
if (($_POST['field_type'] == 'select' || $_POST['field_type'] == 'radio') && !empty($newOptions)) |
2130
|
|
|
$smcFunc['db_query']('', ' |
2131
|
|
|
DELETE FROM {db_prefix}themes |
2132
|
|
|
WHERE variable = {string:current_column} |
2133
|
|
|
AND value NOT IN ({array_string:new_option_values}) |
2134
|
|
|
AND id_member > {int:no_member}', |
2135
|
|
|
array( |
2136
|
|
|
'no_member' => 0, |
2137
|
|
|
'new_option_values' => $newOptions, |
2138
|
|
|
'current_column' => $context['field']['col_name'], |
2139
|
|
|
) |
2140
|
|
|
); |
2141
|
|
|
} |
2142
|
|
|
else |
2143
|
|
|
{ |
2144
|
|
|
// Gotta figure it out the order. |
2145
|
|
|
$new_order = $order_count > 1 ? ($order_count + 1) : 1; |
2146
|
|
|
|
2147
|
|
|
$smcFunc['db_insert']('', |
2148
|
|
|
'{db_prefix}custom_fields', |
2149
|
|
|
array( |
2150
|
|
|
'col_name' => 'string', 'field_name' => 'string', 'field_desc' => 'string', |
2151
|
|
|
'field_type' => 'string', 'field_length' => 'string', 'field_options' => 'string', 'field_order' => 'int', |
2152
|
|
|
'show_reg' => 'int', 'show_display' => 'int', 'show_mlist' => 'int', 'show_profile' => 'string', |
2153
|
|
|
'private' => 'int', 'active' => 'int', 'default_value' => 'string', 'can_search' => 'int', |
2154
|
|
|
'bbc' => 'int', 'mask' => 'string', 'enclose' => 'string', 'placement' => 'int', |
2155
|
|
|
), |
2156
|
|
|
array( |
2157
|
|
|
$col_name, $_POST['field_name'], $_POST['field_desc'], |
|
|
|
|
2158
|
|
|
$_POST['field_type'], $field_length, $field_options, $new_order, |
2159
|
|
|
$show_reg, $show_display, $show_mlist, $show_profile, |
2160
|
|
|
$private, $active, $default, $can_search, |
2161
|
|
|
$bbc, $mask, $enclose, $placement, |
2162
|
|
|
), |
2163
|
|
|
array('id_field') |
2164
|
|
|
); |
2165
|
|
|
} |
2166
|
|
|
} |
2167
|
|
|
// Deleting? |
2168
|
|
|
elseif (isset($_POST['delete']) && $context['field']['col_name']) |
2169
|
|
|
{ |
2170
|
|
|
checkSession(); |
2171
|
|
|
validateToken('admin-ecp'); |
2172
|
|
|
|
2173
|
|
|
// Delete the user data first. |
2174
|
|
|
$smcFunc['db_query']('', ' |
2175
|
|
|
DELETE FROM {db_prefix}themes |
2176
|
|
|
WHERE variable = {string:current_column} |
2177
|
|
|
AND id_member > {int:no_member}', |
2178
|
|
|
array( |
2179
|
|
|
'no_member' => 0, |
2180
|
|
|
'current_column' => $context['field']['col_name'], |
2181
|
|
|
) |
2182
|
|
|
); |
2183
|
|
|
// Finally - the field itself is gone! |
2184
|
|
|
$smcFunc['db_query']('', ' |
2185
|
|
|
DELETE FROM {db_prefix}custom_fields |
2186
|
|
|
WHERE id_field = {int:current_field}', |
2187
|
|
|
array( |
2188
|
|
|
'current_field' => $context['fid'], |
2189
|
|
|
) |
2190
|
|
|
); |
2191
|
|
|
|
2192
|
|
|
// Re-arrange the order. |
2193
|
|
|
$smcFunc['db_query']('', ' |
2194
|
|
|
UPDATE {db_prefix}custom_fields |
2195
|
|
|
SET field_order = field_order - 1 |
2196
|
|
|
WHERE field_order > {int:current_order}', |
2197
|
|
|
array( |
2198
|
|
|
'current_order' => $context['field']['order'], |
2199
|
|
|
) |
2200
|
|
|
); |
2201
|
|
|
} |
2202
|
|
|
|
2203
|
|
|
// Rebuild display cache etc. |
2204
|
|
|
if (isset($_POST['delete']) || isset($_POST['save'])) |
2205
|
|
|
{ |
2206
|
|
|
checkSession(); |
2207
|
|
|
|
2208
|
|
|
$request = $smcFunc['db_query']('', ' |
2209
|
|
|
SELECT col_name, field_name, field_type, field_order, bbc, enclose, placement, show_mlist, field_options |
2210
|
|
|
FROM {db_prefix}custom_fields |
2211
|
|
|
WHERE show_display = {int:is_displayed} |
2212
|
|
|
AND active = {int:active} |
2213
|
|
|
AND private != {int:not_owner_only} |
2214
|
|
|
AND private != {int:not_admin_only} |
2215
|
|
|
ORDER BY field_order', |
2216
|
|
|
array( |
2217
|
|
|
'is_displayed' => 1, |
2218
|
|
|
'active' => 1, |
2219
|
|
|
'not_owner_only' => 2, |
2220
|
|
|
'not_admin_only' => 3, |
2221
|
|
|
) |
2222
|
|
|
); |
2223
|
|
|
|
2224
|
|
|
$fields = array(); |
2225
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
2226
|
|
|
{ |
2227
|
|
|
$fields[] = array( |
2228
|
|
|
'col_name' => strtr($row['col_name'], array('|' => '', ';' => '')), |
2229
|
|
|
'title' => strtr($row['field_name'], array('|' => '', ';' => '')), |
2230
|
|
|
'type' => $row['field_type'], |
2231
|
|
|
'order' => $row['field_order'], |
2232
|
|
|
'bbc' => $row['bbc'] ? '1' : '0', |
2233
|
|
|
'placement' => !empty($row['placement']) ? $row['placement'] : '0', |
2234
|
|
|
'enclose' => !empty($row['enclose']) ? $row['enclose'] : '', |
2235
|
|
|
'mlist' => $row['show_mlist'], |
2236
|
|
|
'options' => (!empty($row['field_options']) ? explode(',', $row['field_options']) : array()), |
2237
|
|
|
); |
2238
|
|
|
} |
2239
|
|
|
$smcFunc['db_free_result']($request); |
2240
|
|
|
|
2241
|
|
|
updateSettings(array('displayFields' => $smcFunc['json_encode']($fields))); |
2242
|
|
|
$_SESSION['adm-save'] = true; |
2243
|
|
|
redirectexit('action=admin;area=featuresettings;sa=profile'); |
2244
|
|
|
} |
2245
|
|
|
|
2246
|
|
|
createToken('admin-ecp'); |
2247
|
|
|
} |
2248
|
|
|
|
2249
|
|
|
/** |
2250
|
|
|
* Returns the maximum field_order value for the custom fields |
2251
|
|
|
* |
2252
|
|
|
* @return int The maximum value of field_order from the custom_fields table |
2253
|
|
|
*/ |
2254
|
|
|
function custFieldsMaxOrder() |
2255
|
|
|
{ |
2256
|
|
|
global $smcFunc; |
2257
|
|
|
|
2258
|
|
|
// Gotta know the order limit |
2259
|
|
|
$result = $smcFunc['db_query']('', ' |
2260
|
|
|
SELECT MAX(field_order) |
2261
|
|
|
FROM {db_prefix}custom_fields', |
2262
|
|
|
array() |
2263
|
|
|
); |
2264
|
|
|
|
2265
|
|
|
list ($order_count) = $smcFunc['db_fetch_row']($result); |
2266
|
|
|
$smcFunc['db_free_result']($result); |
2267
|
|
|
|
2268
|
|
|
return (int) $order_count; |
2269
|
|
|
} |
2270
|
|
|
|
2271
|
|
|
/** |
2272
|
|
|
* Allow to edit the settings on the pruning screen. |
2273
|
|
|
* |
2274
|
|
|
* @param bool $return_config Whether or not to return the config_vars array (used for admin search) |
2275
|
|
|
* @return void|array Returns nothing or returns the $config_vars array if $return_config is true |
2276
|
|
|
*/ |
2277
|
|
|
function ModifyLogSettings($return_config = false) |
2278
|
|
|
{ |
2279
|
|
|
global $txt, $scripturl, $sourcedir, $context, $modSettings; |
2280
|
|
|
|
2281
|
|
|
// Make sure we understand what's going on. |
2282
|
|
|
loadLanguage('ManageSettings'); |
2283
|
|
|
|
2284
|
|
|
$context['page_title'] = $txt['log_settings']; |
2285
|
|
|
|
2286
|
|
|
$config_vars = array( |
2287
|
|
|
array('check', 'modlog_enabled', 'help' => 'modlog'), |
2288
|
|
|
array('check', 'adminlog_enabled', 'help' => 'adminlog'), |
2289
|
|
|
array('check', 'userlog_enabled', 'help' => 'userlog'), |
2290
|
|
|
// The error log is a wonderful thing. |
2291
|
|
|
array('title', 'errorlog', 'force_div_id' => 'errorlog'), |
2292
|
|
|
array('desc', 'error_log_desc'), |
2293
|
|
|
array('check', 'enableErrorLogging'), |
2294
|
|
|
array('check', 'enableErrorQueryLogging'), |
2295
|
|
|
// The 'mark read' log settings. |
2296
|
|
|
array('title', 'markread_title', 'force_div_id' => 'markread_title'), |
2297
|
|
|
array('desc', 'mark_read_desc'), |
2298
|
|
|
array('int', 'mark_read_beyond', 'step' => 1, 'min' => 0, 'max' => 18000, 'subtext' => $txt['zero_to_disable']), |
2299
|
|
|
array('int', 'mark_read_delete_beyond', 'step' => 1, 'min' => 0, 'max' => 18000, 'subtext' => $txt['zero_to_disable']), |
2300
|
|
|
array('int', 'mark_read_max_users', 'step' => 1, 'min' => 0, 'max' => 20000, 'subtext' => $txt['zero_to_disable']), |
2301
|
|
|
// Even do the pruning? |
2302
|
|
|
array('title', 'pruning_title', 'force_div_id' => 'pruning_title'), |
2303
|
|
|
array('desc', 'pruning_desc'), |
2304
|
|
|
// The array indexes are there so we can remove/change them before saving. |
2305
|
|
|
'pruningOptions' => array('check', 'pruningOptions'), |
2306
|
|
|
'', |
2307
|
|
|
|
2308
|
|
|
// Various logs that could be pruned. |
2309
|
|
|
array('int', 'pruneErrorLog', 'postinput' => $txt['days_word'], 'subtext' => $txt['zero_to_disable']), // Error log. |
2310
|
|
|
array('int', 'pruneModLog', 'postinput' => $txt['days_word'], 'subtext' => $txt['zero_to_disable']), // Moderation log. |
2311
|
|
|
array('int', 'pruneBanLog', 'postinput' => $txt['days_word'], 'subtext' => $txt['zero_to_disable']), // Ban hit log. |
2312
|
|
|
array('int', 'pruneReportLog', 'postinput' => $txt['days_word'], 'subtext' => $txt['zero_to_disable']), // Report to moderator log. |
2313
|
|
|
array('int', 'pruneScheduledTaskLog', 'postinput' => $txt['days_word'], 'subtext' => $txt['zero_to_disable']), // Log of the scheduled tasks and how long they ran. |
2314
|
|
|
array('int', 'pruneSpiderHitLog', 'postinput' => $txt['days_word'], 'subtext' => $txt['zero_to_disable']), // Log of the scheduled tasks and how long they ran. |
2315
|
|
|
// If you add any additional logs make sure to add them after this point. Additionally, make sure you add them to the weekly scheduled task. |
2316
|
|
|
// Mod Developers: Do NOT use the pruningOptions master variable for this as SMF Core may overwrite your setting in the future! |
2317
|
|
|
); |
2318
|
|
|
|
2319
|
|
|
// We want to be toggling some of these for a nice user experience. If you want to add yours to the list of those magically hidden when the 'pruning' option is off, add to this. |
2320
|
|
|
$prune_toggle = array('pruneErrorLog', 'pruneModLog', 'pruneBanLog', 'pruneReportLog', 'pruneScheduledTaskLog', 'pruneSpiderHitLog'); |
2321
|
|
|
|
2322
|
|
|
call_integration_hook('integrate_prune_settings', array(&$config_vars, &$prune_toggle, false)); |
2323
|
|
|
|
2324
|
|
|
$prune_toggle_dt = array(); |
2325
|
|
|
foreach ($prune_toggle as $item) |
2326
|
|
|
$prune_toggle_dt[] = 'setting_' . $item; |
2327
|
|
|
|
2328
|
|
|
if ($return_config) |
2329
|
|
|
return $config_vars; |
2330
|
|
|
|
2331
|
|
|
addInlineJavaScript(' |
2332
|
|
|
function togglePruned() |
2333
|
|
|
{ |
2334
|
|
|
var newval = $("#pruningOptions").prop("checked"); |
2335
|
|
|
$("#' . implode(', #', $prune_toggle) . '").closest("dd").toggle(newval); |
2336
|
|
|
$("#' . implode(', #', $prune_toggle_dt) . '").closest("dt").toggle(newval); |
2337
|
|
|
}; |
2338
|
|
|
togglePruned(); |
2339
|
|
|
$("#pruningOptions").click(function() { togglePruned(); });', true); |
2340
|
|
|
|
2341
|
|
|
// We'll need this in a bit. |
2342
|
|
|
require_once($sourcedir . '/ManageServer.php'); |
2343
|
|
|
|
2344
|
|
|
// Saving? |
2345
|
|
|
if (isset($_GET['save'])) |
2346
|
|
|
{ |
2347
|
|
|
checkSession(); |
2348
|
|
|
|
2349
|
|
|
// Because of the excitement attached to combining pruning log items, we need to duplicate everything here. |
2350
|
|
|
$savevar = array( |
2351
|
|
|
array('check', 'modlog_enabled'), |
2352
|
|
|
array('check', 'adminlog_enabled'), |
2353
|
|
|
array('check', 'userlog_enabled'), |
2354
|
|
|
array('check', 'enableErrorLogging'), |
2355
|
|
|
array('check', 'enableErrorQueryLogging'), |
2356
|
|
|
array('int', 'mark_read_beyond'), |
2357
|
|
|
array('int', 'mark_read_delete_beyond'), |
2358
|
|
|
array('int', 'mark_read_max_users'), |
2359
|
|
|
array('text', 'pruningOptions') |
2360
|
|
|
); |
2361
|
|
|
|
2362
|
|
|
call_integration_hook('integrate_prune_settings', array(&$savevar, &$prune_toggle, true)); |
2363
|
|
|
|
2364
|
|
|
if (!empty($_POST['pruningOptions'])) |
2365
|
|
|
{ |
2366
|
|
|
$vals = array(); |
2367
|
|
|
foreach ($config_vars as $index => $dummy) |
2368
|
|
|
{ |
2369
|
|
|
if (!is_array($dummy) || $index == 'pruningOptions' || !in_array($dummy[1], $prune_toggle)) |
2370
|
|
|
continue; |
2371
|
|
|
|
2372
|
|
|
$vals[] = empty($_POST[$dummy[1]]) || $_POST[$dummy[1]] < 0 ? 0 : (int) $_POST[$dummy[1]]; |
2373
|
|
|
} |
2374
|
|
|
$_POST['pruningOptions'] = implode(',', $vals); |
2375
|
|
|
} |
2376
|
|
|
else |
2377
|
|
|
$_POST['pruningOptions'] = ''; |
2378
|
|
|
|
2379
|
|
|
saveDBSettings($savevar); |
2380
|
|
|
$_SESSION['adm-save'] = true; |
2381
|
|
|
redirectexit('action=admin;area=logs;sa=settings'); |
2382
|
|
|
} |
2383
|
|
|
|
2384
|
|
|
$context['post_url'] = $scripturl . '?action=admin;area=logs;save;sa=settings'; |
2385
|
|
|
$context['settings_title'] = $txt['log_settings']; |
2386
|
|
|
$context['sub_template'] = 'show_settings'; |
2387
|
|
|
|
2388
|
|
|
// Get the actual values |
2389
|
|
|
if (!empty($modSettings['pruningOptions'])) |
2390
|
|
|
@list ($modSettings['pruneErrorLog'], $modSettings['pruneModLog'], $modSettings['pruneBanLog'], $modSettings['pruneReportLog'], $modSettings['pruneScheduledTaskLog'], $modSettings['pruneSpiderHitLog']) = explode(',', $modSettings['pruningOptions']); |
2391
|
|
|
else |
2392
|
|
|
$modSettings['pruneErrorLog'] = $modSettings['pruneModLog'] = $modSettings['pruneBanLog'] = $modSettings['pruneReportLog'] = $modSettings['pruneScheduledTaskLog'] = $modSettings['pruneSpiderHitLog'] = 0; |
2393
|
|
|
|
2394
|
|
|
prepareDBSettingContext($config_vars); |
2395
|
|
|
} |
2396
|
|
|
|
2397
|
|
|
/** |
2398
|
|
|
* If you have a general mod setting to add stick it here. |
2399
|
|
|
* |
2400
|
|
|
* @param bool $return_config Whether or not to return the config_vars array (used for admin search) |
2401
|
|
|
* @return void|array Returns nothing or returns the $config_vars array if $return_config is true |
2402
|
|
|
*/ |
2403
|
|
|
function ModifyGeneralModSettings($return_config = false) |
2404
|
|
|
{ |
2405
|
|
|
global $txt, $scripturl, $context; |
2406
|
|
|
|
2407
|
|
|
$config_vars = array( |
2408
|
|
|
// Mod authors, add any settings UNDER this line. Include a comma at the end of the line and don't remove this statement!! |
2409
|
|
|
); |
2410
|
|
|
|
2411
|
|
|
// Make it even easier to add new settings. |
2412
|
|
|
call_integration_hook('integrate_general_mod_settings', array(&$config_vars)); |
2413
|
|
|
|
2414
|
|
|
if ($return_config) |
2415
|
|
|
return $config_vars; |
2416
|
|
|
|
2417
|
|
|
$context['post_url'] = $scripturl . '?action=admin;area=modsettings;save;sa=general'; |
2418
|
|
|
$context['settings_title'] = $txt['mods_cat_modifications_misc']; |
2419
|
|
|
|
2420
|
|
|
// No removing this line you, dirty unwashed mod authors. :p |
2421
|
|
|
if (empty($config_vars)) |
2422
|
|
|
{ |
2423
|
|
|
$context['settings_save_dont_show'] = true; |
2424
|
|
|
$context['settings_message'] = array( |
2425
|
|
|
'label' => $txt['modification_no_misc_settings'], |
2426
|
|
|
'tag' => 'div', |
2427
|
|
|
'class' => 'centertext' |
2428
|
|
|
); |
2429
|
|
|
|
2430
|
|
|
return prepareDBSettingContext($config_vars); |
|
|
|
|
2431
|
|
|
} |
2432
|
|
|
|
2433
|
|
|
// Saving? |
2434
|
|
|
if (isset($_GET['save'])) |
2435
|
|
|
{ |
2436
|
|
|
checkSession(); |
2437
|
|
|
|
2438
|
|
|
$save_vars = $config_vars; |
2439
|
|
|
|
2440
|
|
|
call_integration_hook('integrate_save_general_mod_settings', array(&$save_vars)); |
2441
|
|
|
|
2442
|
|
|
// This line is to help mod authors do a search/add after if you want to add something here. Keyword: FOOT TAPPING SUCKS! |
2443
|
|
|
saveDBSettings($save_vars); |
2444
|
|
|
|
2445
|
|
|
// This line is to remind mod authors that it's nice to let the users know when something has been saved. |
2446
|
|
|
$_SESSION['adm-save'] = true; |
2447
|
|
|
|
2448
|
|
|
// This line is to help mod authors do a search/add after if you want to add something here. Keyword: I LOVE TEA! |
2449
|
|
|
redirectexit('action=admin;area=modsettings;sa=general'); |
2450
|
|
|
} |
2451
|
|
|
|
2452
|
|
|
// This line is to help mod authors do a search/add after if you want to add something here. Keyword: RED INK IS FOR TEACHERS AND THOSE WHO LIKE PAIN! |
2453
|
|
|
prepareDBSettingContext($config_vars); |
2454
|
|
|
} |
2455
|
|
|
|
2456
|
|
|
/** |
2457
|
|
|
* Handles modifying the alerts settings |
2458
|
|
|
*/ |
2459
|
|
|
function ModifyAlertsSettings() |
2460
|
|
|
{ |
2461
|
|
|
global $context, $modSettings, $sourcedir, $txt; |
2462
|
|
|
|
2463
|
|
|
// Dummy settings for the template... |
2464
|
|
|
$context['user']['is_owner'] = false; |
2465
|
|
|
$context['member'] = array(); |
2466
|
|
|
$context['id_member'] = 0; |
2467
|
|
|
$context['menu_item_selected'] = 'alerts'; |
2468
|
|
|
$context['token_check'] = 'noti-admin'; |
2469
|
|
|
|
2470
|
|
|
// Specify our action since we'll want to post back here instead of the profile |
2471
|
|
|
$context['action'] = 'action=admin;area=featuresettings;sa=alerts;' . $context['session_var'] . '=' . $context['session_id']; |
2472
|
|
|
|
2473
|
|
|
loadTemplate('Profile'); |
2474
|
|
|
loadLanguage('Profile'); |
2475
|
|
|
|
2476
|
|
|
include_once($sourcedir . '/Profile-Modify.php'); |
2477
|
|
|
alert_configuration(0, true); |
2478
|
|
|
|
2479
|
|
|
$context['page_title'] = $txt['notify_settings']; |
2480
|
|
|
|
2481
|
|
|
// Override the description |
2482
|
|
|
$context['description'] = $txt['notifications_desc']; |
2483
|
|
|
$context['sub_template'] = 'alert_configuration'; |
2484
|
|
|
} |
2485
|
|
|
|
2486
|
|
|
?> |