Completed
Pull Request — development (#3246)
by Emanuele
16:38
created

ManageFeatures_Controller::_basicSettings()   B

Complexity

Conditions 3
Paths 2

Size

Total Lines 56

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 3.0006

Importance

Changes 0
Metric Value
cc 3
nc 2
nop 0
dl 0
loc 56
ccs 23
cts 24
cp 0.9583
crap 3.0006
rs 8.9599
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Manage features and options administration page.
5
 *
6
 * @name      ElkArte Forum
7
 * @copyright ElkArte Forum contributors
8
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause
9
 *
10
 * This file contains code covered by:
11
 * copyright:	2011 Simple Machines (http://www.simplemachines.org)
12
 * license:		BSD, See included LICENSE.TXT for terms and conditions.
13
 *
14
 * @version 2.0 dev
15
 *
16
 */
17
18
/**
19
 * Manage features and options administration page.
20
 *
21
 * This controller handles the pages which allow the admin
22
 * to see and change the basic feature settings of their site.
23
 */
24
class ManageFeatures_Controller extends Action_Controller
25
{
26
	/**
27
	 * Pre Dispatch, called before other methods.
28
	 */
29 1
	public function pre_dispatch()
30
	{
31
		// We need this in few places so it's easier to have it loaded here
32 1
		require_once(SUBSDIR . '/ManageFeatures.subs.php');
33 1
	}
34
35
	/**
36
	 * This function passes control through to the relevant tab.
37
	 *
38
	 * @event integrate_sa_modify_features Use to add new Configuration tabs
39
	 * @see Action_Controller::action_index()
40
	 * @uses Help, ManageSettings languages
41
	 * @uses sub_template show_settings
42
	 */
43
	public function action_index()
44
	{
45
		global $context, $txt, $settings;
46
47
		// Often Helpful
48
		theme()->getTemplates()->loadLanguageFile('Help');
49
		theme()->getTemplates()->loadLanguageFile('ManageSettings');
50
		theme()->getTemplates()->loadLanguageFile('Mentions');
51
52
		// All the actions we know about
53
		$subActions = array(
54
			'basic' => array(
55
				'controller' => $this,
56
				'function' => 'action_basicSettings_display',
57
				'permission' => 'admin_forum'
58
			),
59
			'layout' => array(
60
				'controller' => $this,
61
				'function' => 'action_layoutSettings_display',
62
				'permission' => 'admin_forum'
63
			),
64
			'karma' => array(
65
				'controller' => $this,
66
				'function' => 'action_karmaSettings_display',
67
				'enabled' => in_array('k', $context['admin_features']),
68
				'permission' => 'admin_forum'
69
			),
70
			'pmsettings' => array(
71
				'controller' => $this,
72
				'function' => 'action_pmsettings',
73
				'permission' => 'admin_forum'
74
			),
75
			'likes' => array(
76
				'controller' => $this,
77
				'function' => 'action_likesSettings_display',
78
				'enabled' => in_array('l', $context['admin_features']),
79
				'permission' => 'admin_forum'
80
			),
81
			'mention' => array(
82
				'controller' => $this,
83
				'function' => 'action_notificationsSettings_display',
84
				'permission' => 'admin_forum'
85
			),
86
			'sig' => array(
87
				'controller' => $this,
88
				'function' => 'action_signatureSettings_display',
89
				'permission' => 'admin_forum'
90
			),
91
			'profile' => array(
92
				'controller' => $this,
93
				'function' => 'action_profile',
94
				'enabled' => in_array('cp', $context['admin_features']),
95
				'permission' => 'admin_forum'
96
			),
97
			'profileedit' => array(
98
				'controller' => $this,
99
				'function' => 'action_profileedit',
100
				'permission' => 'admin_forum'
101
			),
102
		);
103
104
		// Set up the action control
105
		$action = new Action('modify_features');
106
107
		// Load up all the tabs...
108
		$context[$context['admin_menu_name']]['tab_data'] = array(
109
			'title' => $txt['modSettings_title'],
110
			'help' => 'featuresettings',
111
			'description' => sprintf($txt['modSettings_desc'], getUrl('admin', ['action' => 'admin', 'area' => 'theme', 'sa' => 'list', 'th' => $settings['theme_id'], '{session_data}'])),
112
			'tabs' => array(
113
				'basic' => array(
114
				),
115
				'layout' => array(
116
				),
117
				'pmsettings' => array(
118
				),
119
				'karma' => array(
120
				),
121
				'likes' => array(
122
				),
123
				'mention' => array(
124
					'description' => $txt['mentions_settings_desc'],
125
				),
126
				'sig' => array(
127
					'description' => $txt['signature_settings_desc'],
128
				),
129
				'profile' => array(
130
					'description' => $txt['custom_profile_desc'],
131
				),
132
			),
133
		);
134
135
		// By default do the basic settings, call integrate_sa_modify_features
136
		$subAction = $action->initialize($subActions, 'basic');
137
138
		// Some final pieces for the template
139
		$context['sub_template'] = 'show_settings';
140
		$context['sub_action'] = $subAction;
141
		$context['page_title'] = $txt['modSettings_title'];
142
143
		// Call the right function for this sub-action.
144
		$action->dispatch($subAction);
145
	}
146
147
	/**
148
	 * Config array for changing the basic forum settings
149
	 *
150
	 * - Accessed from ?action=admin;area=featuresettings;sa=basic;
151
	 *
152
	 * @event integrate_save_basic_settings
153
	 */
154
	public function action_basicSettings_display()
155
	{
156
		global $txt, $context;
157
158
		// Initialize the form
159
		$settingsForm = new Settings_Form(Settings_Form::DB_ADAPTER);
160
161
		// Initialize it with our settings
162
		$settingsForm->setConfigVars($this->_basicSettings());
163
164
		// Saving?
165
		if (isset($this->_req->query->save))
166
		{
167
			checkSession();
168
169
			// Prevent absurd boundaries here - make it a day tops.
170
			if (isset($this->_req->post->lastActive))
171
				$this->_req->post->lastActive = min((int) $this->_req->post->lastActive, 1440);
172
173
			call_integration_hook('integrate_save_basic_settings');
174
175
			$settingsForm->setConfigValues((array) $this->_req->post);
176
			$settingsForm->save();
177
178
			writeLog();
179
			redirectexit('action=admin;area=featuresettings;sa=basic');
180
		}
181
		if (isset($this->_req->post->cleanhives))
182
		{
183
			$clean_hives_result = theme()->cleanHives();
184
185
			theme()->getLayers()->removeAll();
186
			theme()->getTemplates()->load('Json');
187
			theme()->addJavascriptVar(array('txt_invalid_response' => $txt['ajax_bad_response']), true);
188
			$context['sub_template'] = 'send_json';
189
			$context['json_data'] = array(
190
				'success' => $clean_hives_result,
191
				'response' => $clean_hives_result ? $txt['clean_hives_sucess'] : $txt['clean_hives_failed']
192
			);
193
			return;
194
		}
195
196
		$context['post_url'] = getUrl('admin', ['action' => 'admin', 'area' => 'featuresettings', 'sa' => 'basic', 'save']);
197
		$context['settings_title'] = $txt['mods_cat_features'];
198
199
		// Show / hide custom jquery fields as required
200
		theme()->addInlineJavascript('showhideJqueryOptions();', true);
201
202
		$settingsForm->prepare();
203
	}
204
205
	/**
206
	 * Allows modifying the global layout settings in the forum
207
	 *
208
	 * - Accessed through ?action=admin;area=featuresettings;sa=layout;
209
	 *
210
	 * @event integrate_save_layout_settings
211
	 */
212
	public function action_layoutSettings_display()
213
	{
214
		global $txt, $context, $modSettings;
215
216
		// Initialize the form
217
		$settingsForm = new Settings_Form(Settings_Form::DB_ADAPTER);
218
219
		// Initialize it with our settings
220
		$settingsForm->setConfigVars($this->_layoutSettings());
221
222
		// Saving?
223
		if (isset($this->_req->query->save))
224
		{
225
			// Setting a custom frontpage, set the hook to the FrontpageInterface of the controller
226
			if (!empty($this->_req->post->front_page))
227
			{
228
				$front_page = (string) $this->_req->post->front_page;
229
				if (
230
					is_callable(array($modSettings['front_page'], 'validateFrontPageOptions'))
231
					&& !$front_page::validateFrontPageOptions($this->_req->post)
232
				) {
233
					$this->_req->post->front_page = '';
234
				}
235
			}
236
237
			checkSession();
238
239
			call_integration_hook('integrate_save_layout_settings');
240
241
			$settingsForm->setConfigValues((array) $this->_req->post);
242
			$settingsForm->save();
243
			writeLog();
244
245
			redirectexit('action=admin;area=featuresettings;sa=layout');
246
		}
247
248
		$context['post_url'] = getUrl('admin', ['action' => 'admin', 'area' => 'featuresettings', 'sa' => 'layout', 'save']);
249
		$context['settings_title'] = $txt['mods_cat_layout'];
250
251
		$settingsForm->prepare();
252
	}
253
254
	/**
255
	 * Display configuration settings page for karma settings.
256
	 *
257
	 * - Accessed from ?action=admin;area=featuresettings;sa=karma;
258
	 *
259
	 * @event integrate_save_karma_settings
260
	 */
261 View Code Duplication
	public function action_karmaSettings_display()
262
	{
263
		global $txt, $context;
264
265
		// Initialize the form
266
		$settingsForm = new Settings_Form(Settings_Form::DB_ADAPTER);
267
268
		// Initialize it with our settings
269
		$settingsForm->setConfigVars($this->_karmaSettings());
270
271
		// Saving?
272
		if (isset($this->_req->query->save))
273
		{
274
			checkSession();
275
276
			call_integration_hook('integrate_save_karma_settings');
277
278
			$settingsForm->setConfigValues((array) $this->_req->post);
279
			$settingsForm->save();
280
			redirectexit('action=admin;area=featuresettings;sa=karma');
281
		}
282
283
		$context['post_url'] = getUrl('admin', ['action' => 'admin', 'area' => 'featuresettings', 'sa' => 'karm', 'save']);
284
		$context['settings_title'] = $txt['karma'];
285
286
		$settingsForm->prepare();
287
	}
288
289
	/**
290
	 * Display configuration settings page for likes settings.
291
	 *
292
	 * - Accessed from ?action=admin;area=featuresettings;sa=likes;
293
	 *
294
	 * @event integrate_save_likes_settings
295
	 */
296 View Code Duplication
	public function action_likesSettings_display()
297
	{
298
		global $txt, $context;
299
300
		// Initialize the form
301
		$settingsForm = new Settings_Form(Settings_Form::DB_ADAPTER);
302
303
		// Initialize it with our settings
304
		$settingsForm->setConfigVars($this->_likesSettings());
305
306
		// Saving?
307
		if (isset($this->_req->query->save))
308
		{
309
			checkSession();
310
311
			call_integration_hook('integrate_save_likes_settings');
312
313
			$settingsForm->setConfigValues((array) $this->_req->post);
314
			$settingsForm->save();
315
			redirectexit('action=admin;area=featuresettings;sa=likes');
316
		}
317
318
		$context['post_url'] = getUrl('admin', ['action' => 'admin', 'area' => 'featuresettings', 'sa' => 'likes', 'save']);
319
		$context['settings_title'] = $txt['likes'];
320
321
		$settingsForm->prepare();
322
	}
323
324
	/**
325
	 * Initializes the mentions settings admin page.
326
	 *
327
	 * - Accessed from ?action=admin;area=featuresettings;sa=mention;
328
	 *
329
	 * @event integrate_save_modify_mention_settings
330
	 */
331
	public function action_notificationsSettings_display()
332
	{
333
		global $txt, $context, $modSettings;
334
335
		theme()->getTemplates()->loadLanguageFile('Mentions');
336
337
		// Instantiate the form
338
		$settingsForm = new Settings_Form(Settings_Form::DB_ADAPTER);
339
340
		// Initialize it with our settings
341
		$settingsForm->setConfigVars($this->_notificationsSettings());
342
343
		// Some context stuff
344
		$context['page_title'] = $txt['mentions_settings'];
345
		$context['sub_template'] = 'show_settings';
346
347
		// Saving the settings?
348
		if (isset($this->_req->query->save))
349
		{
350
			checkSession();
351
352
			call_integration_hook('integrate_save_modify_mention_settings');
353
354
			if (!empty($this->_req->post->mentions_enabled))
355
			{
356
				enableModules('mentions', array('post', 'display'));
357
			}
358
			else
359
			{
360
				disableModules('mentions', array('post', 'display'));
361
			}
362
363
			if (empty($this->_req->post->notifications))
364
			{
365
				$notification_methods = serialize(array());
366
			}
367
			else
368
			{
369
				$notification_methods = serialize($this->_req->post->notifications);
370
			}
371
372
			require_once(SUBSDIR . '/Mentions.subs.php');
373
			$enabled_mentions = array();
374
			$current_settings = unserialize($modSettings['notification_methods']);
375
376
			// Fist hide what was visible
377
			$modules_toggle = array('enable' => array(), 'disable' => array());
378 View Code Duplication
			foreach ($current_settings as $type => $val)
379
			{
380
				if (!isset($this->_req->post->notifications[$type]))
381
				{
382
					toggleMentionsVisibility($type, false);
383
					$modules_toggle['disable'][] = $type;
384
				}
385
			}
386
387
			// Then make visible what was hidden, but only if there is anything
388
			if (!empty($this->_req->post->notifications))
389
			{
390 View Code Duplication
				foreach ($this->_req->post->notifications as $type => $val)
391
				{
392
					if (!isset($current_settings[$type]))
393
					{
394
						toggleMentionsVisibility($type, true);
395
						$modules_toggle['enable'][] = $type;
396
					}
397
				}
398
399
				$enabled_mentions = array_keys($this->_req->post->notifications);
400
			}
401
402
			// Let's just keep it active, there are too many reasons it should be.
403
			require_once(SUBSDIR . '/ScheduledTasks.subs.php');
404
			toggleTaskStatusByName('user_access_mentions', true);
405
406
			// Disable or enable modules as needed
407
			foreach ($modules_toggle as $action => $toggles)
408
			{
409
				if (!empty($toggles))
410
				{
411
					// The modules associated with the notification (mentionmem, likes, etc) area
412
					$modules = getMentionsModules($toggles);
413
414
					// The action will either be enable to disable
415
					$function = $action . 'Modules';
416
417
					// Something like enableModule('mentions', array('post', 'display');
418
					foreach ($modules as $key => $val)
419
						$function($key, $val);
420
				}
421
			}
422
423
			updateSettings(array('enabled_mentions' => implode(',', array_unique($enabled_mentions)), 'notification_methods' => $notification_methods));
424
			$settingsForm->setConfigValues((array) $this->_req->post);
425
			$settingsForm->save();
426
			redirectexit('action=admin;area=featuresettings;sa=mention');
427
		}
428
429
		// Prepare the settings for display
430
		$context['post_url'] = getUrl('admin', ['action' => 'admin', 'area' => 'featuresettings', 'sa' => 'mention', 'save']);
431
		$settingsForm->prepare();
432
	}
433
434
	/**
435
	 * Display configuration settings for signatures on forum.
436
	 *
437
	 * - Accessed from ?action=admin;area=featuresettings;sa=sig;
438
	 *
439
	 * @event integrate_save_signature_settings
440
	 */
441
	public function action_signatureSettings_display()
442
	{
443
		global $context, $txt, $modSettings, $sig_start;
444
445
		// Initialize the form
446
		$settingsForm = new Settings_Form(Settings_Form::DB_ADAPTER);
447
448
		// Initialize it with our settings
449
		$settingsForm->setConfigVars($this->_signatureSettings());
450
451
		// Setup the template.
452
		$context['page_title'] = $txt['signature_settings'];
453
		$context['sub_template'] = 'show_settings';
454
455
		// Disable the max smileys option if we don't allow smileys at all!
456
		theme()->addInlineJavascript('
457
			document.getElementById(\'signature_max_smileys\').disabled = !document.getElementById(\'signature_allow_smileys\').checked;', true);
458
459
		// Load all the signature settings.
460
		list ($sig_limits, $sig_bbc) = explode(':', $modSettings['signature_settings']);
461
		$sig_limits = explode(',', $sig_limits);
462
		$disabledTags = !empty($sig_bbc) ? explode(',', $sig_bbc) : array();
463
464
		// @todo temporary since it does not work, and seriously why would you do this?
465
		$disabledTags[] = 'footnote';
466
467
		// Applying to ALL signatures?!!
468
		if (isset($this->_req->query->apply))
469
		{
470
			// Security!
471
			checkSession('get');
472
473
			$sig_start = time();
474
475
			// This is horrid - but I suppose some people will want the option to do it.
476
			$applied_sigs = $this->_req->getQuery('step', 'intval', 0);
477
			updateAllSignatures($applied_sigs);
478
479
			$settings_applied = true;
480
		}
481
482
		$context['signature_settings'] = array(
483
			'enable' => isset($sig_limits[0]) ? $sig_limits[0] : 0,
484
			'max_length' => isset($sig_limits[1]) ? $sig_limits[1] : 0,
485
			'max_lines' => isset($sig_limits[2]) ? $sig_limits[2] : 0,
486
			'max_images' => isset($sig_limits[3]) ? $sig_limits[3] : 0,
487
			'allow_smileys' => isset($sig_limits[4]) && $sig_limits[4] == -1 ? 0 : 1,
488
			'max_smileys' => isset($sig_limits[4]) && $sig_limits[4] != -1 ? $sig_limits[4] : 0,
489
			'max_image_width' => isset($sig_limits[5]) ? $sig_limits[5] : 0,
490
			'max_image_height' => isset($sig_limits[6]) ? $sig_limits[6] : 0,
491
			'max_font_size' => isset($sig_limits[7]) ? $sig_limits[7] : 0,
492
			'repetition_guests' => isset($sig_limits[8]) ? $sig_limits[8] : 0,
493
			'repetition_members' => isset($sig_limits[9]) ? $sig_limits[9] : 0,
494
		);
495
496
		// Temporarily make each setting a modSetting!
497
		foreach ($context['signature_settings'] as $key => $value)
498
			$modSettings['signature_' . $key] = $value;
499
500
		// Make sure we check the right tags!
501
		$modSettings['bbc_disabled_signature_bbc'] = $disabledTags;
502
503
		// Saving?
504
		if (isset($this->_req->query->save))
505
		{
506
			checkSession();
507
508
			// Clean up the tag stuff!
509
			$codes = \BBC\ParserWrapper::instance()->getCodes();
510
			$bbcTags = $codes->getTags();
511
512 View Code Duplication
			if (!isset($this->_req->post->signature_bbc_enabledTags))
513
				$this->_req->post->signature_bbc_enabledTags = array();
514
			elseif (!is_array($this->_req->post->signature_bbc_enabledTags))
515
				$this->_req->post->signature_bbc_enabledTags = array($this->_req->post->signature_bbc_enabledTags);
516
517
			$sig_limits = array();
518
			foreach ($context['signature_settings'] as $key => $value)
519
			{
520
				if ($key == 'allow_smileys')
521
					continue;
522
				elseif ($key == 'max_smileys' && empty($this->_req->post->signature_allow_smileys))
523
					$sig_limits[] = -1;
524
				else
525
				{
526
					$current_key = $this->_req->getPost('signature_' . $key, 'intval');
527
					$sig_limits[] = !empty($current_key) ? max(1, $current_key) : 0;
528
				}
529
			}
530
531
			call_integration_hook('integrate_save_signature_settings', array(&$sig_limits, &$bbcTags));
532
533
			$this->_req->post->signature_settings = implode(',', $sig_limits) . ':' . implode(',', array_diff($bbcTags, $this->_req->post->signature_bbc_enabledTags));
534
535
			// Even though we have practically no settings let's keep the convention going!
536
			$save_vars = array();
537
			$save_vars[] = array('text', 'signature_settings');
538
539
			$settingsForm->setConfigVars($save_vars);
540
			$settingsForm->setConfigValues((array) $this->_req->post);
541
			$settingsForm->save();
542
			redirectexit('action=admin;area=featuresettings;sa=sig');
543
		}
544
545
		$context['post_url'] = getUrl('admin', ['action' => 'admin', 'area' => 'featuresettings', 'sa' => 'sig', 'save']);
546
		$context['settings_title'] = $txt['signature_settings'];
547
		$context['settings_message'] = !empty($settings_applied) ? $txt['signature_settings_applied'] : sprintf($txt['signature_settings_warning'], getUrl('admin', ['action' => 'admin', 'area' => 'featuresettings', 'sa' => 'sig', 'apply', '{session_data}']));
548
549
		$settingsForm->prepare();
550
	}
551
552
	/**
553
	 * Show all the custom profile fields available to the user.
554
	 *
555
	 * - Allows for drag/drop sorting of custom profile fields
556
	 * - Accessed with ?action=admin;area=featuresettings;sa=profile
557
	 *
558
	 * @uses sub template show_custom_profile
559
	 */
560
	public function action_profile()
561
	{
562
		global $txt, $scripturl, $context;
563
564
		theme()->getTemplates()->load('ManageFeatures');
565
		$context['page_title'] = $txt['custom_profile_title'];
566
		$context['sub_template'] = 'show_custom_profile';
567
568
		// What about standard fields they can tweak?
569
		$standard_fields = array('website', 'posts', 'warning_status', 'date_registered');
570
571
		// What fields can't you put on the registration page?
572
		$context['fields_no_registration'] = array('posts', 'warning_status', 'date_registered');
573
574
		// Are we saving any standard field changes?
575
		if (isset($this->_req->post->save))
576
		{
577
			checkSession();
578
			validateToken('admin-scp');
579
580
			$changes = array();
581
582
			// Do the active ones first.
583
			$disable_fields = array_flip($standard_fields);
584
			if (!empty($this->_req->post->active))
585
			{
586
				foreach ($this->_req->post->active as $value)
587
				{
588
					if (isset($disable_fields[$value]))
589
					{
590
						unset($disable_fields[$value]);
591
					}
592
				}
593
			}
594
595
			// What we have left!
596
			$changes['disabled_profile_fields'] = empty($disable_fields) ? '' : implode(',', array_keys($disable_fields));
597
598
			// Things we want to show on registration?
599
			$reg_fields = array();
600
			if (!empty($this->_req->post->reg))
601
			{
602
				foreach ($this->_req->post->reg as $value)
603
				{
604
					if (in_array($value, $standard_fields) && !isset($disable_fields[$value]))
605
						$reg_fields[] = $value;
606
				}
607
			}
608
609
			// What we have left!
610
			$changes['registration_fields'] = empty($reg_fields) ? '' : implode(',', $reg_fields);
611
612
			if (!empty($changes))
613
				updateSettings($changes);
614
		}
615
616
		createToken('admin-scp');
617
618
		// Create a listing for all our standard fields
619
		$listOptions = array(
620
			'id' => 'standard_profile_fields',
621
			'title' => $txt['standard_profile_title'],
622
			'base_href' => getUrl('admin', ['action' => 'admin', 'area' => 'featuresettings', 'sa' => 'profile']),
623
			'get_items' => array(
624
				'function' => 'list_getProfileFields',
625
				'params' => array(
626
					true,
627
				),
628
			),
629
			'columns' => array(
630
				'field' => array(
631
					'header' => array(
632
						'value' => $txt['standard_profile_field'],
633
					),
634
					'data' => array(
635
						'db' => 'label',
636
						'style' => 'width: 60%;',
637
					),
638
				),
639
				'active' => array(
640
					'header' => array(
641
						'value' => $txt['custom_edit_active'],
642
						'class' => 'centertext',
643
					),
644
					'data' => array(
645 View Code Duplication
						'function' => function ($rowData) {
646
							$isChecked = $rowData['disabled'] ? '' : ' checked="checked"';
647
							$onClickHandler = $rowData['can_show_register'] ? sprintf('onclick="document.getElementById(\'reg_%1$s\').disabled = !this.checked;"', $rowData['id']) : '';
648
							return sprintf('<input type="checkbox" name="active[]" id="active_%1$s" value="%1$s" class="input_check" %2$s %3$s />', $rowData['id'], $isChecked, $onClickHandler);
649
						},
650
						'style' => 'width: 20%;',
651
						'class' => 'centertext',
652
					),
653
				),
654
				'show_on_registration' => array(
655
					'header' => array(
656
						'value' => $txt['custom_edit_registration'],
657
						'class' => 'centertext',
658
					),
659
					'data' => array(
660 View Code Duplication
						'function' => function ($rowData) {
661
							$isChecked = $rowData['on_register'] && !$rowData['disabled'] ? ' checked="checked"' : '';
662
							$isDisabled = $rowData['can_show_register'] ? '' : ' disabled="disabled"';
663
							return sprintf('<input type="checkbox" name="reg[]" id="reg_%1$s" value="%1$s" class="input_check" %2$s %3$s />', $rowData['id'], $isChecked, $isDisabled);
664
						},
665
						'style' => 'width: 20%;',
666
						'class' => 'centertext',
667
					),
668
				),
669
			),
670
			'form' => array(
671
				'href' => getUrl('admin', ['action' => 'admin', 'area' => 'featuresettings', 'sa' => 'profile']),
672
				'name' => 'standardProfileFields',
673
				'token' => 'admin-scp',
674
			),
675
			'additional_rows' => array(
676
				array(
677
					'position' => 'below_table_data',
678
					'value' => '<input type="submit" name="save" value="' . $txt['save'] . '" class="right_submit" />',
679
				),
680
			),
681
		);
682
		createList($listOptions);
683
684
		// And now we do the same for all of our custom ones
685
		$token = createToken('admin-sort');
686
		$listOptions = array(
687
			'id' => 'custom_profile_fields',
688
			'title' => $txt['custom_profile_title'],
689
			'base_href' => getUrl('admin', ['action' => 'admin', 'area' => 'featuresettings', 'sa' => 'profile']),
690
			'default_sort_col' => 'vieworder',
691
			'no_items_label' => $txt['custom_profile_none'],
692
			'items_per_page' => 25,
693
			'sortable' => true,
694
			'get_items' => array(
695
				'function' => 'list_getProfileFields',
696
				'params' => array(
697
					false,
698
				),
699
			),
700
			'get_count' => array(
701
				'function' => 'list_getProfileFieldSize',
702
			),
703
			'columns' => array(
704
				'vieworder' => array(
705
					'header' => array(
706
						'value' => '',
707
						'class' => 'hide',
708
					),
709
					'data' => array(
710
						'db' => 'vieworder',
711
						'class' => 'hide',
712
					),
713
					'sort' => array(
714
						'default' => 'vieworder',
715
					),
716
				),
717
				'field_name' => array(
718
					'header' => array(
719
						'value' => $txt['custom_profile_fieldname'],
720
					),
721
					'data' => array(
722
						'function' => function ($rowData) {
723
							return sprintf('<a href="%1$s">%3$s</a><div class="smalltext">%4$s</div>', getUrl('admin', ['action' => 'admin', 'area' => 'featuresettings', 'sa' => 'profileedit', 'fid' => (int) $rowData['id_field']]), $rowData['field_name'], $rowData['field_desc']);
724
						},
725
						'style' => 'width: 65%;',
726
					),
727
					'sort' => array(
728
						'default' => 'field_name',
729
						'reverse' => 'field_name DESC',
730
					),
731
				),
732
				'field_type' => array(
733
					'header' => array(
734
						'value' => $txt['custom_profile_fieldtype'],
735
					),
736
					'data' => array(
737
						'function' => function ($rowData) {
738
							global $txt;
739
740
							$textKey = sprintf('custom_profile_type_%1$s', $rowData['field_type']);
741
							return isset($txt[$textKey]) ? $txt[$textKey] : $textKey;
742
						},
743
						'style' => 'width: 10%;',
744
					),
745
					'sort' => array(
746
						'default' => 'field_type',
747
						'reverse' => 'field_type DESC',
748
					),
749
				),
750
				'cust' => array(
751
					'header' => array(
752
						'value' => $txt['custom_profile_active'],
753
						'class' => 'centertext',
754
					),
755
					'data' => array(
756
						'function' => function ($rowData) {
757
							$isChecked = $rowData['active'] ? ' checked="checked"' : '';
758
							return sprintf('<input type="checkbox" name="cust[]" id="cust_%1$s" value="%1$s" class="input_check"%2$s />', $rowData['id_field'], $isChecked);
759
						},
760
						'style' => 'width: 8%;',
761
						'class' => 'centertext',
762
					),
763
					'sort' => array(
764
						'default' => 'active DESC',
765
						'reverse' => 'active',
766
					),
767
				),
768
				'placement' => array(
769
					'header' => array(
770
						'value' => $txt['custom_profile_placement'],
771
					),
772
					'data' => array(
773
						'function' => function ($rowData) {
774
							global $txt;
775
							$placement = 'custom_profile_placement_';
776
777
							switch ((int) $rowData['placement'])
778
							{
779
								case 0:
780
									$placement .= 'standard';
781
									break;
782
								case 1:
783
									$placement .= 'withicons';
784
									break;
785
								case 2:
786
									$placement .= 'abovesignature';
787
									break;
788
								case 3:
789
									$placement .= 'aboveicons';
790
									break;
791
							}
792
793
							return $txt[$placement];
794
						},
795
						'style' => 'width: 5%;',
796
					),
797
					'sort' => array(
798
						'default' => 'placement DESC',
799
						'reverse' => 'placement',
800
					),
801
				),
802
				'show_on_registration' => array(
803
					'data' => array(
804
						'sprintf' => array(
805
							'format' => '<a href="' . $scripturl . '?action=admin;area=featuresettings;sa=profileedit;fid=%1$s">' . $txt['modify'] . '</a>',
806
							'params' => array(
807
								'id_field' => false,
808
							),
809
						),
810
						'style' => 'width: 5%;',
811
					),
812
				),
813
			),
814
			'form' => array(
815
				'href' => getUrl('admin', ['action' => 'admin', 'area' => 'featuresettings', 'sa' => 'profileedit']),
816
				'name' => 'customProfileFields',
817
				'token' => 'admin-scp',
818
			),
819
			'additional_rows' => array(
820
				array(
821
					'class' => 'submitbutton',
822
					'position' => 'below_table_data',
823
					'value' => '<input type="submit" name="onoff" value="' . $txt['save'] . '" class="right_submit" />
824
					<input type="submit" name="new" value="' . $txt['custom_profile_make_new'] . '" class="right_submit" />',
825
				),
826
				array(
827
					'position' => 'top_of_list',
828
					'value' => '<p class="infobox">' . $txt['custom_profile_sort'] . '</p>',
829
				),
830
			),
831
			'javascript' => '
832
				$().elkSortable({
833
					sa: "profileorder",
834
					error: "' . $txt['admin_order_error'] . '",
835
					title: "' . $txt['admin_order_title'] . '",
836
					placeholder: "ui-state-highlight",
837
					href: "?action=admin;area=featuresettings;sa=profile",
838
					token: {token_var: "' . $token['admin-sort_token_var'] . '", token_id: "' . $token['admin-sort_token'] . '"}
839
				});
840
			',
841
		);
842
843
		createList($listOptions);
844
	}
845
846
	/**
847
	 * Edit some profile fields?
848
	 *
849
	 * - Accessed with ?action=admin;area=featuresettings;sa=profileedit
850
	 *
851
	 * @uses sub template edit_profile_field
852
	 */
853
	public function action_profileedit()
854
	{
855
		global $txt, $context;
856
857
		theme()->getTemplates()->load('ManageFeatures');
858
859
		// Sort out the context!
860
		$context['fid'] = $this->_req->getQuery('fid', 'intval', 0);
861
		$context[$context['admin_menu_name']]['current_subsection'] = 'profile';
862
		$context['page_title'] = $context['fid'] ? $txt['custom_edit_title'] : $txt['custom_add_title'];
863
		$context['sub_template'] = 'edit_profile_field';
864
865
		// Any errors messages to show?
866
		if (isset($this->_req->query->msg))
867
		{
868
			theme()->getTemplates()->loadLanguageFile('Errors');
869
870
			if (isset($txt['custom_option_' . $this->_req->query->msg]))
871
				$context['custom_option__error'] = $txt['custom_option_' . $this->_req->query->msg];
872
		}
873
874
		// Load the profile language for section names.
875
		theme()->getTemplates()->loadLanguageFile('Profile');
876
877
		// Load up the profile field, if one was supplied
878
		if ($context['fid'])
879
			$context['field'] = getProfileField($context['fid']);
880
881
		// Setup the default values as needed.
882
		if (empty($context['field']))
883
			$context['field'] = array(
884
				'name' => '',
885
				'colname' => '???',
886
				'desc' => '',
887
				'profile_area' => 'forumprofile',
888
				'reg' => false,
889
				'display' => false,
890
				'memberlist' => false,
891
				'type' => 'text',
892
				'max_length' => 255,
893
				'rows' => 4,
894
				'cols' => 30,
895
				'bbc' => false,
896
				'default_check' => false,
897
				'default_select' => '',
898
				'default_value' => '',
899
				'options' => array('', '', ''),
900
				'active' => true,
901
				'private' => false,
902
				'can_search' => false,
903
				'mask' => 'nohtml',
904
				'regex' => '',
905
				'enclose' => '',
906
				'placement' => 0,
907
			);
908
909
		// All the javascript for this page... everything else is in admin.js
910
		theme()->addJavascriptVar(array('startOptID' => count($context['field']['options'])));
911
		theme()->addInlineJavascript('updateInputBoxes();', true);
912
913
		// Are we toggling which ones are active?
914
		if (isset($this->_req->post->onoff))
915
		{
916
			checkSession();
917
			validateToken('admin-scp');
918
919
			// Enable and disable custom fields as required.
920
			$enabled = array(0);
921
			if (isset($this->_req->post->cust) && is_array($this->_req->post->cust)) {
922
				foreach ($this->_req->post->cust as $id)
923
					$enabled[] = (int) $id;
924
			}
925
926
			updateRenamedProfileStatus($enabled);
927
		}
928
		// Are we saving?
929
		elseif (isset($this->_req->post->save))
930
		{
931
			checkSession();
932
			validateToken('admin-ecp');
933
934
			// Everyone needs a name - even the (bracket) unknown...
935
			if (trim($this->_req->post->field_name) == '')
936
				redirectexit('action=admin;area=featuresettings;sa=profileedit;fid=' . $this->_req->query->fid . ';msg=need_name');
937
938
			// Regex you say?  Do a very basic test to see if the pattern is valid
939
			if (!empty($this->_req->post->regex) && @preg_match($this->_req->post->regex, 'dummy') === false)
940
				redirectexit('action=admin;area=featuresettings;sa=profileedit;fid=' . $this->_req->query->fid . ';msg=regex_error');
941
942
			$this->_req->post->field_name = $this->_req->getPost('field_name', 'Util::htmlspecialchars');
943
			$this->_req->post->field_desc = $this->_req->getPost('field_desc', 'Util::htmlspecialchars');
944
945
			$rows = isset($this->_req->post->rows) ? (int) $this->_req->post->rows : 4;
946
			$cols = isset($this->_req->post->cols) ? (int) $this->_req->post->cols : 30;
947
948
			// Checkboxes...
949
			$show_reg = $this->_req->getPost('reg', 'intval', 0);
950
			$show_display = isset($this->_req->post->display) ? 1 : 0;
951
			$show_memberlist = isset($this->_req->post->memberlist) ? 1 : 0;
952
			$bbc = isset($this->_req->post->bbc) ? 1 : 0;
953
			$show_profile = $this->_req->post->profile_area;
954
			$active = isset($this->_req->post->active) ? 1 : 0;
955
			$private = $this->_req->getPost('private', 'intval', 0);
956
			$can_search = isset($this->_req->post->can_search) ? 1 : 0;
957
958
			// Some masking stuff...
959
			$mask = $this->_req->getPost('mask', 'strval', '');
960
			if ($mask == 'regex' && isset($this->_req->post->regex))
961
				$mask .= $this->_req->post->regex;
962
963
			$field_length = $this->_req->getPost('max_length', 'intval', 255);
964
			$enclose = $this->_req->getPost('enclose', 'strval', '');
965
			$placement = $this->_req->getPost('placement', 'intval', 0);
966
967
			// Select options?
968
			$field_options = '';
969
			$newOptions = array();
970
971
			// Set default
972
			$default = '';
973
974
			switch ($this->_req->post->field_type)
975
			{
976
				case 'check':
977
					$default = isset($this->_req->post->default_check) ? 1 : '';
978
					break;
979
				case 'select':
980
				case 'radio':
981
					if (!empty($this->_req->post->select_option))
982
					{
983
						foreach ($this->_req->post->select_option as $k => $v)
984
						{
985
							// Clean, clean, clean...
986
							$v = Util::htmlspecialchars($v);
987
							$v = strtr($v, array(',' => ''));
988
989
							// Nada, zip, etc...
990
							if (trim($v) == '')
991
								continue;
992
993
							// Otherwise, save it boy.
994
							$field_options .= $v . ',';
995
996
							// This is just for working out what happened with old options...
997
							$newOptions[$k] = $v;
998
999
							// Is it default?
1000
							if (isset($this->_req->post->default_select) && $this->_req->post->default_select == $k)
1001
								$default = $v;
1002
						}
1003
1004
						if (isset($_POST['default_select']) && $_POST['default_select'] == 'no_default')
1005
							$default = 'no_default';
1006
1007
						$field_options = substr($field_options, 0, -1);
1008
					}
1009
					break;
1010
				default:
1011
					$default = isset($this->_req->post->default_value) ? $this->_req->post->default_value : '';
1012
			}
1013
1014
			// Text area by default has dimensions
1015
//			if ($this->_req->post->field_type == 'textarea')
1016
//				$default = (int) $this->_req->post->rows . ',' . (int) $this->_req->post->cols;
1017
1018
			// Come up with the unique name?
1019
			if (empty($context['fid']))
1020
			{
1021
				$colname = Util::substr(strtr($this->_req->post->field_name, array(' ' => '')), 0, 6);
1022
				preg_match('~([\w\d_-]+)~', $colname, $matches);
1023
1024
				// If there is nothing to the name, then let's start our own - for foreign languages etc.
1025
				if (isset($matches[1]))
1026
					$colname = $initial_colname = 'cust_' . strtolower($matches[1]);
1027
				else
1028
					$colname = $initial_colname = 'cust_' . mt_rand(1, 999999);
1029
1030
				$unique = ensureUniqueProfileField($colname, $initial_colname);
1031
1032
				// Still not a unique column name? Leave it up to the user, then.
1033
				if (!$unique)
1034
					throw new Elk_Exception('custom_option_not_unique');
1035
1036
				// And create a new field
1037
				$new_field = array(
1038
					'col_name' => $colname,
1039
					'field_name' => $this->_req->post->field_name,
1040
					'field_desc' => $this->_req->post->field_desc,
1041
					'field_type' => $this->_req->post->field_type,
1042
					'field_length' => $field_length,
1043
					'field_options' => $field_options,
1044
					'show_reg' => $show_reg,
1045
					'show_display' => $show_display,
1046
					'show_memberlist' => $show_memberlist,
1047
					'show_profile' => $show_profile,
1048
					'private' => $private,
1049
					'active' => $active,
1050
					'default_value' => $default,
1051
					'rows' => $rows,
1052
					'cols' => $cols,
1053
					'can_search' => $can_search,
1054
					'bbc' => $bbc,
1055
					'mask' => $mask,
1056
					'enclose' => $enclose,
1057
					'placement' => $placement,
1058
					'vieworder' => list_getProfileFieldSize() + 1,
1059
				);
1060
				addProfileField($new_field);
1061
			}
1062
			// Work out what to do with the user data otherwise...
1063
			else
1064
			{
1065
				// Anything going to check or select is pointless keeping - as is anything coming from check!
1066
				if (($this->_req->post->field_type == 'check' && $context['field']['type'] != 'check')
1067
					|| (($this->_req->post->field_type == 'select' || $this->_req->post->field_type == 'radio') && $context['field']['type'] != 'select' && $context['field']['type'] != 'radio')
1068
					|| ($context['field']['type'] == 'check' && $this->_req->post->field_type != 'check'))
1069
				{
1070
					deleteProfileFieldUserData($context['field']['colname']);
1071
				}
1072
				// Otherwise - if the select is edited may need to adjust!
1073
				elseif ($this->_req->post->field_type == 'select' || $this->_req->post->field_type == 'radio')
1074
				{
1075
					$optionChanges = array();
1076
					$takenKeys = array();
1077
1078
					// Work out what's changed!
1079
					foreach ($context['field']['options'] as $k => $option)
1080
					{
1081
						if (trim($option) == '')
1082
							continue;
1083
1084
						// Still exists?
1085
						if (in_array($option, $newOptions))
1086
						{
1087
							$takenKeys[] = $k;
1088
							continue;
1089
						}
1090
					}
1091
1092
					// Finally - have we renamed it - or is it really gone?
1093
					foreach ($optionChanges as $k => $option)
1094
					{
1095
						// Just been renamed?
1096
						if (!in_array($k, $takenKeys) && !empty($newOptions[$k]))
1097
							updateRenamedProfileField($k, $newOptions, $context['field']['colname'], $option);
1098
					}
1099
				}
1100
				// @todo Maybe we should adjust based on new text length limits?
1101
1102
				// And finally update an existing field
1103
				$field_data = array(
1104
					'field_length' => $field_length,
1105
					'show_reg' => $show_reg,
1106
					'show_display' => $show_display,
1107
					'show_memberlist' => $show_memberlist,
1108
					'private' => $private,
1109
					'active' => $active,
1110
					'can_search' => $can_search,
1111
					'bbc' => $bbc,
1112
					'current_field' => $context['fid'],
1113
					'field_name' => $this->_req->post->field_name,
1114
					'field_desc' => $this->_req->post->field_desc,
1115
					'field_type' => $this->_req->post->field_type,
1116
					'field_options' => $field_options,
1117
					'show_profile' => $show_profile,
1118
					'default_value' => $default,
1119
					'mask' => $mask,
1120
					'enclose' => $enclose,
1121
					'placement' => $placement,
1122
					'rows' => $rows,
1123
					'cols' => $cols,
1124
				);
1125
1126
				updateProfileField($field_data);
1127
1128
				// Just clean up any old selects - these are a pain!
1129
				if (($this->_req->post->field_type == 'select' || $this->_req->post->field_type == 'radio') && !empty($newOptions))
1130
					deleteOldProfileFieldSelects($newOptions, $context['field']['colname']);
1131
			}
1132
		}
1133
		// Deleting?
1134
		elseif (isset($this->_req->post->delete) && $context['field']['colname'])
1135
		{
1136
			checkSession();
1137
			validateToken('admin-ecp');
1138
1139
			// Delete the old data first, then the field.
1140
			deleteProfileFieldUserData($context['field']['colname']);
1141
			deleteProfileField($context['fid']);
1142
		}
1143
1144
		// Rebuild display cache etc.
1145
		if (isset($this->_req->post->delete) || isset($this->_req->post->save) || isset($this->_req->post->onoff))
1146
		{
1147
			checkSession();
1148
1149
			// Update the display cache
1150
			updateDisplayCache();
1151
			redirectexit('action=admin;area=featuresettings;sa=profile');
1152
		}
1153
1154
		createToken('admin-ecp');
1155
	}
1156
1157
	/**
1158
	 * Editing personal messages settings
1159
	 *
1160
	 * - Accessed with ?action=admin;area=featuresettings;sa=pmsettings
1161
	 *
1162
	 * @event integrate_save_pmsettings_settings
1163
	 */
1164
	public function action_pmsettings()
1165
	{
1166
		global $txt, $context;
1167
1168
		// Initialize the form
1169
		$settingsForm = new Settings_Form(Settings_Form::DB_ADAPTER);
1170
1171
		// Initialize it with our settings
1172
		$settingsForm->setConfigVars($this->_pmSettings());
1173
1174
		require_once(SUBSDIR . '/PersonalMessage.subs.php');
1175
		theme()->getTemplates()->loadLanguageFile('ManageMembers');
1176
1177
		$context['pm_limits'] = loadPMLimits();
1178
1179
		// Saving?
1180
		if (isset($this->_req->query->save))
1181
		{
1182
			checkSession();
1183
1184
			require_once(SUBSDIR . '/Membergroups.subs.php');
1185
			foreach ($context['pm_limits'] as $group_id => $group)
1186
			{
1187
				if (isset($this->_req->post->group[$group_id]) && $this->_req->post->group[$group_id] != $group['max_messages'])
1188
					updateMembergroupProperties(array('current_group' => $group_id, 'max_messages' => $this->_req->post->group[$group_id]));
1189
			}
1190
1191
			call_integration_hook('integrate_save_pmsettings_settings');
1192
1193
			$settingsForm->setConfigValues((array) $this->_req->post);
1194
			$settingsForm->save();
1195
			redirectexit('action=admin;area=featuresettings;sa=pmsettings');
1196
		}
1197
1198
		$context['post_url'] = getUrl('admin', ['action' => 'admin', 'area' => 'featuresettings', 'sa' => 'pmsettings', 'save']);
1199
		$context['settings_title'] = $txt['personal_messages'];
1200
1201
		$settingsForm->prepare();
1202
	}
1203
1204
	/**
1205
	 * Return basic feature settings.
1206
	 *
1207
	 * @event integrate_modify_basic_settings Adds to General features and Options
1208
	 */
1209 1
	private function _basicSettings()
1210
	{
1211 1
		global $txt;
1212
1213
		$config_vars = array(
1214
				// Basic stuff, titles, permissions...
1215 1
				array('check', 'allow_guestAccess'),
1216
				array('check', 'enable_buddylist'),
1217
				array('check', 'allow_editDisplayName'),
1218
				array('check', 'allow_hideOnline'),
1219
				array('check', 'titlesEnable'),
1220 1
			'',
1221
				// Javascript and CSS options
1222 1
				array('select', 'jquery_source', array('auto' => $txt['jquery_auto'], 'local' => $txt['jquery_local'], 'cdn' => $txt['jquery_cdn'])),
1223
				array('check', 'jquery_default', 'onchange' => 'showhideJqueryOptions();'),
1224 1
				array('text', 'jquery_version', 'postinput' => $txt['jquery_custom_after']),
1225
				array('check', 'jqueryui_default', 'onchange' => 'showhideJqueryOptions();'),
1226 1
				array('text', 'jqueryui_version', 'postinput' => $txt['jqueryui_custom_after']),
1227 1
				array('check', 'minify_css_js', 'postinput' => '<a href="#" id="clean_hives" class="linkbutton">' . $txt['clean_hives'] . '</a>'),
1228 1
			'',
1229 1
				array('select', 'url_format', array('standard' => $txt['url_format_standard'], 'semantic' => $txt['url_format_semantic'])),
1230 1
			'',
1231
				// Number formatting, timezones.
1232
				array('text', 'time_format'),
1233 1
				array('float', 'time_offset', 'subtext' => $txt['setting_time_offset_note'], 6, 'postinput' => $txt['hours']),
1234
				'default_timezone' => array('select', 'default_timezone', array()),
1235 1
			'',
1236
				// Who's online?
1237
				array('check', 'who_enabled'),
1238 1
				array('int', 'lastActive', 6, 'postinput' => $txt['minutes']),
1239 1
			'',
1240
				// Statistics.
1241
				array('check', 'trackStats'),
1242
				array('check', 'hitStats'),
1243 1
			'',
1244
				// Option-ish things... miscellaneous sorta.
1245
				array('check', 'allow_disableAnnounce'),
1246
				array('check', 'disallow_sendBody'),
1247 1
				array('select', 'enable_contactform', array('disabled' => $txt['contact_form_disabled'], 'registration' => $txt['contact_form_registration'], 'menu' => $txt['contact_form_menu'])),
1248
		);
1249
1250
		// Get all the time zones.
1251 1
		$all_zones = timezone_identifiers_list();
1252 1
		if ($all_zones === false)
1253
			unset($config_vars['default_timezone']);
1254
		else
1255
		{
1256
			// Make sure we set the value to the same as the printed value.
1257 1
			foreach ($all_zones as $zone)
1258 1
				$config_vars['default_timezone'][2][$zone] = $zone;
1259
		}
1260
1261 1
		call_integration_hook('integrate_modify_basic_settings', array(&$config_vars));
1262
1263 1
		return $config_vars;
1264
	}
1265
1266
	/**
1267
	 * Public method to return the basic settings, used for admin search
1268
	 */
1269 1
	public function basicSettings_search()
1270
	{
1271 1
		return $this->_basicSettings();
1272
	}
1273
1274
	/**
1275
	 * Return layout settings.
1276
	 *
1277
	 * @event integrate_modify_layout_settings Adds options to Configuration->Layout
1278
	 */
1279 1
	private function _layoutSettings()
1280
	{
1281 1
		global $txt;
1282
1283 1
		$config_vars = array_merge(getFrontPageControllers(), array(
1284 1
			'',
1285
				// Pagination stuff.
1286
				array('check', 'compactTopicPagesEnable'),
1287 1
				array('int', 'compactTopicPagesContiguous', 'subtext' => str_replace(' ', '&nbsp;', '"3" ' . $txt['to_display'] . ': <strong>1 ... 4 [5] 6 ... 9</strong>') . '<br />' . str_replace(' ', '&nbsp;', '"5" ' . $txt['to_display'] . ': <strong>1 ... 3 4 [5] 6 7 ... 9</strong>')),
1288
				array('int', 'defaultMaxMembers'),
1289
				array('check', 'displayMemberNames'),
1290 1
			'',
1291
				// Stuff that just is everywhere - today, search, online, etc.
1292 1
				array('select', 'todayMod', array($txt['today_disabled'], $txt['today_only'], $txt['yesterday_today'], $txt['relative_time'])),
1293
				array('check', 'onlineEnable'),
1294
				array('check', 'enableVBStyleLogin'),
1295 1
			'',
1296
				// Automagic image resizing.
1297 1
				array('int', 'max_image_width', 'subtext' => $txt['zero_for_no_limit']),
1298 1
				array('int', 'max_image_height', 'subtext' => $txt['zero_for_no_limit']),
1299 1
			'',
1300
				// This is like debugging sorta.
1301
				array('check', 'timeLoadPageEnable'),
1302
		));
1303
1304 1
		call_integration_hook('integrate_modify_layout_settings', array(&$config_vars));
1305
1306 1
		return $config_vars;
1307
	}
1308
1309
	/**
1310
	 * Public method to return the layout settings, used for admin search
1311
	 */
1312 1
	public function layoutSettings_search()
1313
	{
1314 1
		return $this->_layoutSettings();
1315
	}
1316
1317
	/**
1318
	 * Return karma settings.
1319
	 *
1320
	 * @event integrate_modify_karma_settings Adds to Configuration->Karma
1321
	 */
1322 1
	private function _karmaSettings()
1323
	{
1324 1
		global $txt;
1325
1326
		$config_vars = array(
1327
				// Karma - On or off?
1328 1
				array('select', 'karmaMode', explode('|', $txt['karma_options'])),
1329 1
			'',
1330
				// Who can do it.... and who is restricted by time limits?
1331 1
				array('int', 'karmaMinPosts', 6, 'postinput' => $txt['manageposts_posts']),
1332 1
				array('float', 'karmaWaitTime', 6, 'postinput' => $txt['hours']),
1333
				array('check', 'karmaTimeRestrictAdmins'),
1334
				array('check', 'karmaDisableSmite'),
1335 1
			'',
1336
				// What does it look like?  [smite]?
1337
				array('text', 'karmaLabel'),
1338
				array('text', 'karmaApplaudLabel', 'mask' => 'nohtml'),
1339
				array('text', 'karmaSmiteLabel', 'mask' => 'nohtml'),
1340
		);
1341
1342 1
		call_integration_hook('integrate_modify_karma_settings', array(&$config_vars));
1343
1344 1
		return $config_vars;
1345
	}
1346
1347
	/**
1348
	 * Public method to return the karma settings, used for admin search
1349
	 */
1350 1
	public function karmaSettings_search()
1351
	{
1352 1
		return $this->_karmaSettings();
1353
	}
1354
1355
	/**
1356
	 * Return likes settings.
1357
	 *
1358
	 * @event integrate_modify_likes_settings Adds to Configuration->Likes
1359
	 */
1360 1
	private function _likesSettings()
1361
	{
1362 1
		global $txt;
1363
1364
		$config_vars = array(
1365
				// Likes - On or off?
1366 1
				array('check', 'likes_enabled'),
1367 1
			'',
1368
				// Who can do it.... and who is restricted by count limits?
1369 1
				array('int', 'likeMinPosts', 6, 'postinput' => $txt['manageposts_posts']),
1370 1
				array('int', 'likeWaitTime', 6, 'postinput' => $txt['minutes']),
1371
				array('int', 'likeWaitCount', 6),
1372
				array('check', 'likeRestrictAdmins'),
1373
				array('check', 'likeAllowSelf'),
1374 1
			'',
1375
				array('int', 'likeDisplayLimit', 6)
1376
		);
1377
1378 1
		call_integration_hook('integrate_modify_likes_settings', array(&$config_vars));
1379
1380 1
		return $config_vars;
1381
	}
1382
1383
	/**
1384
	 * Public method to return the likes settings, used for admin search
1385
	 */
1386 1
	public function likesSettings_search()
1387
	{
1388 1
		return $this->_likesSettings();
1389
	}
1390
1391
	/**
1392
	 * Return mentions settings.
1393
	 *
1394
	 * @event integrate_modify_mention_settings Adds to Configuration->Mentions
1395
	 */
1396 1
	private function _notificationsSettings()
1397
	{
1398 1
		global $txt, $modSettings;
1399
1400 1
		theme()->getTemplates()->loadLanguageFile('Profile');
1401 1
		theme()->getTemplates()->loadLanguageFile('UserNotifications');
1402
1403
		// The mentions settings
1404
		$config_vars = array(
1405 1
			array('title', 'mentions_settings'),
1406
			array('check', 'mentions_enabled'),
1407
		);
1408
1409 1
		$notification_methods = Notifications::instance()->getNotifiers();
1410 1
		$notification_types = getNotificationTypes();
1411 1
		$current_settings = unserialize($modSettings['notification_methods']);
1412
1413 1
		foreach ($notification_types as $title)
1414
		{
1415 1
			$config_vars[] = array('title', 'setting_' . $title);
1416
1417 1
			foreach ($notification_methods as $method)
1418
			{
1419 1
				if ($method === 'notification')
1420 1
					$text_label = $txt['setting_notify_enable_this'];
1421
				else
1422 1
					$text_label = $txt['notify_' . $method];
1423
1424 1
				$config_vars[] = array('check', 'notifications[' . $title . '][' . $method . ']', 'text_label' => $text_label);
1425 1
				$modSettings['notifications[' . $title . '][' . $method . ']'] = !empty($current_settings[$title][$method]);
1426
			}
1427
		}
1428
1429 1
		call_integration_hook('integrate_modify_mention_settings', array(&$config_vars));
1430
1431 1
		return $config_vars;
1432
	}
1433
1434
	/**
1435
	 * Public method to return the mention settings, used for admin search
1436
	 */
1437 1
	public function mentionSettings_search()
1438
	{
1439 1
		return $this->_notificationsSettings();
1440
	}
1441
1442
	/**
1443
	 * Return signature settings.
1444
	 *
1445
	 * - Used in admin center search and settings form
1446
	 *
1447
	 * @event integrate_modify_signature_settings Adds options to Signature Settings
1448
	 */
1449 1
	private function _signatureSettings()
1450
	{
1451 1
		global $txt;
1452
1453
		$config_vars = array(
1454
				// Are signatures even enabled?
1455 1
				array('check', 'signature_enable'),
1456 1
			'',
1457
				// Tweaking settings!
1458 1
				array('int', 'signature_max_length', 'subtext' => $txt['zero_for_no_limit']),
1459 1
				array('int', 'signature_max_lines', 'subtext' => $txt['zero_for_no_limit']),
1460 1
				array('int', 'signature_max_font_size', 'subtext' => $txt['zero_for_no_limit']),
1461
				array('check', 'signature_allow_smileys', 'onclick' => 'document.getElementById(\'signature_max_smileys\').disabled = !this.checked;'),
1462 1
				array('int', 'signature_max_smileys', 'subtext' => $txt['zero_for_no_limit']),
1463 1
				array('select', 'signature_repetition_guests',
1464
					array(
1465 1
						$txt['signature_always'],
1466 1
						$txt['signature_onlyfirst'],
1467 1
						$txt['signature_never'],
1468
					),
1469
				),
1470 1
				array('select', 'signature_repetition_members',
1471
					array(
1472 1
						$txt['signature_always'],
1473 1
						$txt['signature_onlyfirst'],
1474 1
						$txt['signature_never'],
1475
					),
1476
				),
1477 1
			'',
1478
				// Image settings.
1479 1
				array('int', 'signature_max_images', 'subtext' => $txt['signature_max_images_note']),
1480 1
				array('int', 'signature_max_image_width', 'subtext' => $txt['zero_for_no_limit']),
1481 1
				array('int', 'signature_max_image_height', 'subtext' => $txt['zero_for_no_limit']),
1482 1
			'',
1483
				array('bbc', 'signature_bbc'),
1484
		);
1485
1486 1
		call_integration_hook('integrate_modify_signature_settings', array(&$config_vars));
1487
1488 1
		return $config_vars;
1489
	}
1490
1491
	/**
1492
	 * Public method to return the signature settings, used for admin search
1493
	 */
1494 1
	public function signatureSettings_search()
1495
	{
1496 1
		return $this->_signatureSettings();
1497
	}
1498
1499
	/**
1500
	 * Return pm settings.
1501
	 *
1502
	 * - Used in admin center search and settings form
1503
	 *
1504
	 * @event integrate_modify_pmsettings_settings Adds / Modifies PM Settings
1505
	 */
1506
	private function _pmSettings()
1507
	{
1508
		global $txt;
1509
1510
		$config_vars = array(
1511
			// Reporting of personal messages?
1512
			array('check', 'enableReportPM'),
1513
			// Inline permissions.
1514
			array('permissions', 'pm_send'),
1515
			// PM Settings
1516
			array('title', 'antispam_PM'),
1517
				'pm1' => array('int', 'max_pm_recipients', 'postinput' => $txt['max_pm_recipients_note']),
1518
				'pm2' => array('int', 'pm_posts_verification', 'postinput' => $txt['pm_posts_verification_note']),
1519
				'pm3' => array('int', 'pm_posts_per_hour', 'postinput' => $txt['pm_posts_per_hour_note']),
1520
			array('title', 'membergroups_max_messages'),
1521
				array('desc', 'membergroups_max_messages_desc'),
1522
				array('callback', 'pm_limits'),
1523
		);
1524
1525
		call_integration_hook('integrate_modify_pmsettings_settings', array(&$config_vars));
1526
1527
		return $config_vars;
1528
	}
1529
}
1530
1531
/**
1532
 * Just pause the signature applying thing.
1533
 *
1534
 * @todo Move to subs file
1535
 * @todo Merge with other pause functions?
1536
 *    pausePermsSave(), pauseAttachmentMaintenance(), pauseRepairProcess()
1537
 *
1538
 * @param int $applied_sigs
1539
 * @throws Elk_Exception
1540
 */
1541
function pauseSignatureApplySettings($applied_sigs)
1542
{
1543
	global $context, $txt, $sig_start;
1544
1545
	// Try get more time...
1546
	detectServer()->setTimeLimit(600);
1547
1548
	// Have we exhausted all the time we allowed?
1549
	if (time() - array_sum(explode(' ', $sig_start)) < 3)
1550
		return;
1551
1552
	$context['continue_get_data'] = '?action=admin;area=featuresettings;sa=sig;apply;step=' . $applied_sigs . ';' . $context['session_var'] . '=' . $context['session_id'];
1553
	$context['page_title'] = $txt['not_done_title'];
1554
	$context['continue_post_data'] = '';
1555
	$context['continue_countdown'] = '2';
1556
	$context['sub_template'] = 'not_done';
1557
1558
	// Specific stuff to not break this template!
1559
	$context[$context['admin_menu_name']]['current_subsection'] = 'sig';
1560
1561
	// Get the right percent.
1562
	$context['continue_percent'] = round(($applied_sigs / $context['max_member']) * 100);
1563
1564
	// Never more than 100%!
1565
	$context['continue_percent'] = min($context['continue_percent'], 100);
1566
1567
	obExit();
1568
}
1569