Completed
Pull Request — master (#3325)
by Emanuele
11:19
created

ManageFeatures_Controller::_layoutSettings()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 28
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 18
dl 0
loc 28
rs 9.6666
c 0
b 0
f 0
nc 1
nop 0
ccs 20
cts 20
cp 1
crap 1
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 1.1.4
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, $scripturl;
46
47
		// Often Helpful
48
		loadLanguage('Help');
49
		loadLanguage('ManageSettings');
50
		loadLanguage('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'], $scripturl . '?action=admin;area=theme;sa=list;th=' . $settings['theme_id'] . ';' . $context['session_id'] . '=' . $context['session_var']),
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, $scripturl, $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
			Template_Layers::instance()->removeAll();
186
			loadTemplate('Json');
187
			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'] = $scripturl . '?action=admin;area=featuresettings;save;sa=basic';
197
		$context['settings_title'] = $txt['mods_cat_features'];
198
199
		// Show / hide custom jquery fields as required
200
		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, $scripturl, $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'] = $scripturl . '?action=admin;area=featuresettings;save;sa=layout';
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
	public function action_karmaSettings_display()
262
	{
263
		global $txt, $scripturl, $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'] = $scripturl . '?action=admin;area=featuresettings;save;sa=karma';
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
	public function action_likesSettings_display()
297
	{
298
		global $txt, $scripturl, $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'] = $scripturl . '?action=admin;area=featuresettings;save;sa=likes';
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, $scripturl, $modSettings;
334
335
		loadLanguage('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
			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
				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'] = $scripturl . '?action=admin;area=featuresettings;save;sa=mention';
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, $scripturl;
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
		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
			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'] = $scripturl . '?action=admin;area=featuresettings;save;sa=sig';
546
		$context['settings_title'] = $txt['signature_settings'];
547
		$context['settings_message'] = !empty($settings_applied) ? $txt['signature_settings_applied'] : sprintf($txt['signature_settings_warning'], $scripturl . '?action=admin;area=featuresettings;sa=sig;apply;' . $context['session_var'] . '=' . $context['session_id']);
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 1
	public function action_profile()
561
	{
562
		global $txt, $scripturl, $context;
563
564
		loadTemplate('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' => $scripturl . '?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
						'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
						'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' => $scripturl . '?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' => $scripturl . '?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
							global $scripturl;
724
725
							return sprintf('<a href="%1$s?action=admin;area=featuresettings;sa=profileedit;fid=%2$d">%3$s</a><div class="smalltext">%4$s</div>', $scripturl, $rowData['id_field'], $rowData['field_name'], $rowData['field_desc']);
726
						},
727
						'style' => 'width: 65%;',
728
					),
729
					'sort' => array(
730
						'default' => 'field_name',
731
						'reverse' => 'field_name DESC',
732
					),
733
				),
734
				'field_type' => array(
735
					'header' => array(
736
						'value' => $txt['custom_profile_fieldtype'],
737
					),
738
					'data' => array(
739
						'function' => function ($rowData) {
740
							global $txt;
741
742
							$textKey = sprintf('custom_profile_type_%1$s', $rowData['field_type']);
743
							return isset($txt[$textKey]) ? $txt[$textKey] : $textKey;
744
						},
745
						'style' => 'width: 10%;',
746
					),
747
					'sort' => array(
748
						'default' => 'field_type',
749
						'reverse' => 'field_type DESC',
750
					),
751
				),
752
				'cust' => array(
753
					'header' => array(
754
						'value' => $txt['custom_profile_active'],
755
						'class' => 'centertext',
756
					),
757
					'data' => array(
758
						'function' => function ($rowData) {
759
							$isChecked = $rowData['active'] ? ' checked="checked"' : '';
760
							return sprintf('<input type="checkbox" name="cust[]" id="cust_%1$s" value="%1$s" class="input_check"%2$s />', $rowData['id_field'], $isChecked);
761
						},
762
						'style' => 'width: 8%;',
763
						'class' => 'centertext',
764
					),
765
					'sort' => array(
766
						'default' => 'active DESC',
767
						'reverse' => 'active',
768 1
					),
769
				),
770
				'placement' => array(
771
					'header' => array(
772
						'value' => $txt['custom_profile_placement'],
773
					),
774
					'data' => array(
775
						'function' => function ($rowData) {
776
							global $txt;
777
							$placement = 'custom_profile_placement_';
778
779
							switch ((int) $rowData['placement'])
780
							{
781
								case 0:
782
									$placement .= 'standard';
783
									break;
784
								case 1:
785
									$placement .= 'withicons';
786
									break;
787
								case 2:
788
									$placement .= 'abovesignature';
789
									break;
790
								case 3:
791
									$placement .= 'aboveicons';
792
									break;
793
							}
794
795
							return $txt[$placement];
796
						},
797
						'style' => 'width: 5%;',
798
					),
799
					'sort' => array(
800
						'default' => 'placement DESC',
801
						'reverse' => 'placement',
802
					),
803
				),
804
				'show_on_registration' => array(
805
					'data' => array(
806
						'sprintf' => array(
807
							'format' => '<a href="' . $scripturl . '?action=admin;area=featuresettings;sa=profileedit;fid=%1$s">' . $txt['modify'] . '</a>',
808
							'params' => array(
809
								'id_field' => false,
810
							),
811
						),
812
						'style' => 'width: 5%;',
813
					),
814
				),
815
			),
816
			'form' => array(
817
				'href' => $scripturl . '?action=admin;area=featuresettings;sa=profileedit',
818
				'name' => 'customProfileFields',
819
				'token' => 'admin-scp',
820
			),
821
			'additional_rows' => array(
822
				array(
823
					'class' => 'submitbutton',
824
					'position' => 'below_table_data',
825
					'value' => '<input type="submit" name="onoff" value="' . $txt['save'] . '" class="right_submit" />
826
					<input type="submit" name="new" value="' . $txt['custom_profile_make_new'] . '" class="right_submit" />',
827
				),
828
				array(
829
					'position' => 'top_of_list',
830
					'value' => '<p class="infobox">' . $txt['custom_profile_sort'] . '</p>',
831
				),
832
			),
833
			'javascript' => '
834
				$().elkSortable({
835
					sa: "profileorder",
836
					error: "' . $txt['admin_order_error'] . '",
837
					title: "' . $txt['admin_order_title'] . '",
838
					placeholder: "ui-state-highlight",
839
					href: "?action=admin;area=featuresettings;sa=profile",
840
					token: {token_var: "' . $token['admin-sort_token_var'] . '", token_id: "' . $token['admin-sort_token'] . '"}
841
				});
842
			',
843
		);
844
845
		createList($listOptions);
846
	}
847
848
	/**
849
	 * Edit some profile fields?
850
	 *
851
	 * - Accessed with ?action=admin;area=featuresettings;sa=profileedit
852
	 *
853
	 * @uses sub template edit_profile_field
854
	 */
855
	public function action_profileedit()
856
	{
857
		global $txt, $scripturl, $context;
858
859
		loadTemplate('ManageFeatures');
860
861
		// Sort out the context!
862
		$context['fid'] = $this->_req->getQuery('fid', 'intval', 0);
863
		$context[$context['admin_menu_name']]['current_subsection'] = 'profile';
864
		$context['page_title'] = $context['fid'] ? $txt['custom_edit_title'] : $txt['custom_add_title'];
865
		$context['sub_template'] = 'edit_profile_field';
866
867
		// Any errors messages to show?
868
		if (isset($this->_req->query->msg))
869
		{
870
			loadLanguage('Errors');
871
872
			if (isset($txt['custom_option_' . $this->_req->query->msg]))
873
				$context['custom_option__error'] = $txt['custom_option_' . $this->_req->query->msg];
874
		}
875
876
		// Load the profile language for section names.
877
		loadLanguage('Profile');
878
879
		// Load up the profile field, if one was supplied
880
		if ($context['fid'])
881
		{
882
			$context['field'] = getProfileField($context['fid']);
883
		}
884
885
		// Setup the default values as needed.
886
		if (empty($context['field']))
887
		{
888
			$context['field'] = array(
889
				'name' => '',
890
				'colname' => '???',
891
				'desc' => '',
892
				'profile_area' => 'forumprofile',
893
				'reg' => false,
894
				'display' => false,
895
				'memberlist' => false,
896
				'type' => 'text',
897
				'max_length' => 255,
898
				'rows' => 4,
899
				'cols' => 30,
900
				'bbc' => false,
901
				'default_check' => false,
902
				'default_select' => '',
903
				'default_value' => '',
904
				'options' => array('', '', ''),
905
				'active' => true,
906
				'private' => false,
907
				'can_search' => false,
908
				'mask' => 'nohtml',
909
				'regex' => '',
910
				'enclose' => '',
911
				'placement' => 0,
912
			);
913
		}
914
915
		// All the javascript for this page... everything else is in admin.js
916
		addJavascriptVar(array('startOptID' => count($context['field']['options'])));
917
		addInlineJavascript('updateInputBoxes();', true);
918
919
		// Are we toggling which ones are active?
920
		if (isset($this->_req->post->onoff))
921
		{
922
			checkSession();
923
			validateToken('admin-scp');
924
925
			// Enable and disable custom fields as required.
926
			$enabled = array(0);
927
			if(isset($this->_req->post->cust) && is_array($this->_req->post->cust)) {
928
				foreach ($this->_req->post->cust as $id)
929
					$enabled[] = (int) $id;
930
			}
931
932
			updateRenamedProfileStatus($enabled);
933
		}
934
		// Are we saving?
935
		elseif (isset($this->_req->post->save))
936
		{
937
			checkSession();
938
			validateToken('admin-ecp');
939
940
			// Everyone needs a name - even the (bracket) unknown...
941
			if (trim($this->_req->post->field_name) == '')
942
				redirectexit($scripturl . '?action=admin;area=featuresettings;sa=profileedit;fid=' . $this->_req->query->fid . ';msg=need_name');
943
944
			// Regex you say?  Do a very basic test to see if the pattern is valid
945
			if (!empty($this->_req->post->regex) && @preg_match($this->_req->post->regex, 'dummy') === false)
946
				redirectexit($scripturl . '?action=admin;area=featuresettings;sa=profileedit;fid=' . $this->_req->query->fid . ';msg=regex_error');
947
948
			$this->_req->post->field_name = $this->_req->getPost('field_name', 'Util::htmlspecialchars');
949
			$this->_req->post->field_desc = $this->_req->getPost('field_desc', 'Util::htmlspecialchars');
950
951
			$rows = isset($this->_req->post->rows) ? (int) $this->_req->post->rows : 4;
952
			$cols = isset($this->_req->post->cols) ? (int) $this->_req->post->cols : 30;
953
954
			// Checkboxes...
955
			$show_reg = $this->_req->getPost('reg', 'intval', 0);
956
			$show_display = isset($this->_req->post->display) ? 1 : 0;
957
			$show_memberlist = isset($this->_req->post->memberlist) ? 1 : 0;
958
			$bbc = isset($this->_req->post->bbc) ? 1 : 0;
959
			$show_profile = $this->_req->post->profile_area;
960
			$active = isset($this->_req->post->active) ? 1 : 0;
961
			$private = $this->_req->getPost('private', 'intval', 0);
962
			$can_search = isset($this->_req->post->can_search) ? 1 : 0;
963
964
			// Some masking stuff...
965
			$mask = $this->_req->getPost('mask', 'strval', '');
966
			if ($mask == 'regex' && isset($this->_req->post->regex))
967
				$mask .= $this->_req->post->regex;
968
969
			$field_length = $this->_req->getPost('max_length', 'intval', 255);
970
			$enclose = $this->_req->getPost('enclose', 'strval', '');
971
			$placement = $this->_req->getPost('placement', 'intval', 0);
972
973
			// Select options?
974
			$field_options = '';
975
			$newOptions = array();
976
977
			// Set default
978
			$default = '';
979
980
			switch ($this->_req->post->field_type)
981
			{
982
				case 'check':
983
					$default = isset($this->_req->post->default_check) ? 1 : '';
984
					break;
985
				case 'select':
986
				case 'radio':
987
					if (!empty($this->_req->post->select_option))
988
					{
989
						foreach ($this->_req->post->select_option as $k => $v)
990
						{
991
							// Clean, clean, clean...
992
							$v = Util::htmlspecialchars($v);
993
							$v = strtr($v, array(',' => ''));
994
995
							// Nada, zip, etc...
996
							if (trim($v) == '')
997
								continue;
998
999
							// Otherwise, save it boy.
1000
							$field_options .= $v . ',';
1001
1002
							// This is just for working out what happened with old options...
1003
							$newOptions[$k] = $v;
1004
1005
							// Is it default?
1006
							if (isset($this->_req->post->default_select) && $this->_req->post->default_select == $k)
1007
							{
1008
								$default = $v;
1009
							}
1010
						}
1011
1012
						if (isset($_POST['default_select']) && $_POST['default_select'] == 'no_default')
1013
							$default = 'no_default';
1014
1015
						$field_options = substr($field_options, 0, -1);
1016
					}
1017
					break;
1018
				default:
1019
					$default = isset($this->_req->post->default_value) ? $this->_req->post->default_value : '';
1020
			}
1021
1022
			// Text area by default has dimensions
1023
//			if ($this->_req->post->field_type == 'textarea')
1024
//				$default = (int) $this->_req->post->rows . ',' . (int) $this->_req->post->cols;
1025
1026
			// Come up with the unique name?
1027
			if (empty($context['fid']))
1028
			{
1029
				$colname = Util::substr(strtr($this->_req->post->field_name, array(' ' => '')), 0, 6);
1030
				preg_match('~([\w\d_-]+)~', $colname, $matches);
1031
1032
				// If there is nothing to the name, then let's start our own - for foreign languages etc.
1033
				if (isset($matches[1]))
1034
					$colname = $initial_colname = 'cust_' . strtolower($matches[1]);
1035
				else
1036
					$colname = $initial_colname = 'cust_' . mt_rand(1, 999999);
1037
1038
				$unique = ensureUniqueProfileField($colname, $initial_colname);
1039
1040
				// Still not a unique column name? Leave it up to the user, then.
1041
				if (!$unique)
1042
					throw new Elk_Exception('custom_option_not_unique');
1043
1044
				// And create a new field
1045
				$new_field = array(
1046
					'col_name' => $colname,
1047
					'field_name' => $this->_req->post->field_name,
1048
					'field_desc' => $this->_req->post->field_desc,
1049
					'field_type' => $this->_req->post->field_type,
1050
					'field_length' => $field_length,
1051
					'field_options' => $field_options,
1052
					'show_reg' => $show_reg,
1053
					'show_display' => $show_display,
1054
					'show_memberlist' => $show_memberlist,
1055
					'show_profile' => $show_profile,
1056
					'private' => $private,
1057
					'active' => $active,
1058
					'default_value' => $default,
1059
					'rows' => $rows,
1060
					'cols' => $cols,
1061
					'can_search' => $can_search,
1062
					'bbc' => $bbc,
1063
					'mask' => $mask,
1064
					'enclose' => $enclose,
1065
					'placement' => $placement,
1066
					'vieworder' => list_getProfileFieldSize() + 1,
1067
				);
1068
				addProfileField($new_field);
1069
			}
1070
			// Work out what to do with the user data otherwise...
1071
			else
1072
			{
1073
				// Anything going to check or select is pointless keeping - as is anything coming from check!
1074
				if (($this->_req->post->field_type == 'check' && $context['field']['type'] != 'check')
1075
					|| (($this->_req->post->field_type == 'select' || $this->_req->post->field_type == 'radio') && $context['field']['type'] != 'select' && $context['field']['type'] != 'radio')
1076
					|| ($context['field']['type'] == 'check' && $this->_req->post->field_type != 'check'))
1077
				{
1078
					deleteProfileFieldUserData($context['field']['colname']);
1079
				}
1080
				// Otherwise - if the select is edited may need to adjust!
1081
				elseif ($this->_req->post->field_type == 'select' || $this->_req->post->field_type == 'radio')
1082
				{
1083
					$optionChanges = array();
1084
					$takenKeys = array();
1085
1086
					// Work out what's changed!
1087
					foreach ($context['field']['options'] as $k => $option)
1088
					{
1089
						if (trim($option) == '')
1090
							continue;
1091
1092
						// Still exists?
1093
						if (in_array($option, $newOptions))
1094
						{
1095
							$takenKeys[] = $k;
1096
							continue;
1097
						}
1098
					}
1099
1100
					// Finally - have we renamed it - or is it really gone?
1101
					foreach ($optionChanges as $k => $option)
1102
					{
1103
						// Just been renamed?
1104
						if (!in_array($k, $takenKeys) && !empty($newOptions[$k]))
1105
							updateRenamedProfileField($k, $newOptions, $context['field']['colname'], $option);
1106
					}
1107
				}
1108
				// @todo Maybe we should adjust based on new text length limits?
1109
1110
				// And finally update an existing field
1111
				$field_data = array(
1112
					'field_length' => $field_length,
1113
					'show_reg' => $show_reg,
1114
					'show_display' => $show_display,
1115
					'show_memberlist' => $show_memberlist,
1116
					'private' => $private,
1117
					'active' => $active,
1118
					'can_search' => $can_search,
1119
					'bbc' => $bbc,
1120
					'current_field' => $context['fid'],
1121
					'field_name' => $this->_req->post->field_name,
1122
					'field_desc' => $this->_req->post->field_desc,
1123
					'field_type' => $this->_req->post->field_type,
1124
					'field_options' => $field_options,
1125
					'show_profile' => $show_profile,
1126
					'default_value' => $default,
1127
					'mask' => $mask,
1128
					'enclose' => $enclose,
1129
					'placement' => $placement,
1130
					'rows' => $rows,
1131
					'cols' => $cols,
1132
				);
1133
1134
				updateProfileField($field_data);
1135
1136
				// Just clean up any old selects - these are a pain!
1137
				if (($this->_req->post->field_type == 'select' || $this->_req->post->field_type == 'radio') && !empty($newOptions))
1138
					deleteOldProfileFieldSelects($newOptions, $context['field']['colname']);
1139
			}
1140
		}
1141
		// Deleting?
1142
		elseif (isset($this->_req->post->delete) && $context['field']['colname'])
1143
		{
1144
			checkSession();
1145
			validateToken('admin-ecp');
1146
1147
			// Delete the old data first, then the field.
1148
			deleteProfileFieldUserData($context['field']['colname']);
1149
			deleteProfileField($context['fid']);
1150
		}
1151
1152
		// Rebuild display cache etc.
1153
		if (isset($this->_req->post->delete) || isset($this->_req->post->save) || isset($this->_req->post->onoff))
1154
		{
1155
			checkSession();
1156
1157
			// Update the display cache
1158
			updateDisplayCache();
1159
			redirectexit('action=admin;area=featuresettings;sa=profile');
1160
		}
1161
1162
		createToken('admin-ecp');
1163
	}
1164
1165
	/**
1166
	 * Editing personal messages settings
1167
	 *
1168
	 * - Accessed with ?action=admin;area=featuresettings;sa=pmsettings
1169
	 *
1170
	 * @event integrate_save_pmsettings_settings
1171
	 */
1172
	public function action_pmsettings()
1173
	{
1174
		global $txt, $scripturl, $context;
1175
1176
		// Initialize the form
1177
		$settingsForm = new Settings_Form(Settings_Form::DB_ADAPTER);
1178
1179
		// Initialize it with our settings
1180
		$settingsForm->setConfigVars($this->_pmSettings());
1181
1182
		require_once(SUBSDIR . '/PersonalMessage.subs.php');
1183
		loadLanguage('ManageMembers');
1184
1185
		$context['pm_limits'] = loadPMLimits();
1186
1187
		// Saving?
1188
		if (isset($this->_req->query->save))
1189
		{
1190
			checkSession();
1191
1192
			require_once(SUBSDIR . '/Membergroups.subs.php');
1193
			foreach ($context['pm_limits'] as $group_id => $group)
1194
			{
1195
				if (isset($this->_req->post->group[$group_id]) && $this->_req->post->group[$group_id] != $group['max_messages'])
1196
					updateMembergroupProperties(array('current_group' => $group_id, 'max_messages' => $this->_req->post->group[$group_id]));
1197
			}
1198
1199
			call_integration_hook('integrate_save_pmsettings_settings');
1200
1201
			$settingsForm->setConfigValues((array) $this->_req->post);
1202
			$settingsForm->save();
1203
			redirectexit('action=admin;area=featuresettings;sa=pmsettings');
1204
		}
1205
1206
		$context['post_url'] = $scripturl . '?action=admin;area=featuresettings;save;sa=pmsettings';
1207
		$context['settings_title'] = $txt['personal_messages'];
1208
1209
		$settingsForm->prepare();
1210
	}
1211
1212
	/**
1213
	 * Return basic feature settings.
1214
	 *
1215
	 * @event integrate_modify_basic_settings Adds to General features and Options
1216
	 */
1217 1
	private function _basicSettings()
1218
	{
1219 1
		global $txt;
1220
1221
		$config_vars = array(
1222
				// Basic stuff, titles, permissions...
1223 1
				array('check', 'allow_guestAccess'),
1224 1
				array('check', 'enable_buddylist'),
1225 1
				array('check', 'allow_editDisplayName'),
1226 1
				array('check', 'allow_hideOnline'),
1227 1
				array('check', 'titlesEnable'),
1228 1
			'',
1229
				// Javascript and CSS options
1230 1
				array('select', 'jquery_source', array('auto' => $txt['jquery_auto'], 'local' => $txt['jquery_local'], 'cdn' => $txt['jquery_cdn'])),
1231 1
				array('check', 'jquery_default', 'onchange' => 'showhideJqueryOptions();'),
1232 1
				array('text', 'jquery_version', 'postinput' => $txt['jquery_custom_after']),
1233 1
				array('check', 'jqueryui_default', 'onchange' => 'showhideJqueryOptions();'),
1234 1
				array('text', 'jqueryui_version', 'postinput' => $txt['jqueryui_custom_after']),
1235 1
				array('check', 'minify_css_js', 'postinput' => '<a href="#" id="clean_hives" class="linkbutton">' . $txt['clean_hives'] . '</a>'),
1236 1
			'',
1237
				// Number formatting, timezones.
1238 1
				array('text', 'time_format'),
1239 1
				array('float', 'time_offset', 'subtext' => $txt['setting_time_offset_note'], 6, 'postinput' => $txt['hours']),
1240 1
				'default_timezone' => array('select', 'default_timezone', array()),
1241 1
			'',
1242
				// Who's online?
1243 1
				array('check', 'who_enabled'),
1244 1
				array('int', 'lastActive', 6, 'postinput' => $txt['minutes']),
1245 1
			'',
1246
				// Statistics.
1247 1
				array('check', 'trackStats'),
1248 1
				array('check', 'hitStats'),
1249 1
			'',
1250
				// Option-ish things... miscellaneous sorta.
1251 1
				array('check', 'allow_disableAnnounce'),
1252 1
				array('check', 'disallow_sendBody'),
1253 1
				array('select', 'enable_contactform', array('disabled' => $txt['contact_form_disabled'], 'registration' => $txt['contact_form_registration'], 'menu' => $txt['contact_form_menu'])),
1254 1
		);
1255
1256
		// Get all the time zones.
1257 1
		$all_zones = timezone_identifiers_list();
1258 1
		if ($all_zones === false)
1259 1
			unset($config_vars['default_timezone']);
1260
		else
1261
		{
1262
			// Make sure we set the value to the same as the printed value.
1263 1
			foreach ($all_zones as $zone)
1264 1
				$config_vars['default_timezone'][2][$zone] = $zone;
1265
		}
1266
1267 1
		call_integration_hook('integrate_modify_basic_settings', array(&$config_vars));
1268
1269 1
		return $config_vars;
1270
	}
1271
1272
	/**
1273
	 * Public method to return the basic settings, used for admin search
1274
	 */
1275 1
	public function basicSettings_search()
1276
	{
1277 1
		return $this->_basicSettings();
1278
	}
1279
1280
	/**
1281
	 * Return layout settings.
1282
	 *
1283
	 * @event integrate_modify_layout_settings Adds options to Configuration->Layout
1284
	 */
1285 1
	private function _layoutSettings()
1286
	{
1287 1
		global $txt;
1288
1289 1
		$config_vars = array_merge(getFrontPageControllers(), array(
1290 1
			'',
1291
				// Pagination stuff.
1292 1
				array('check', 'compactTopicPagesEnable'),
1293 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>')),
1294 1
				array('int', 'defaultMaxMembers'),
1295 1
				array('check', 'displayMemberNames'),
1296 1
			'',
1297
				// Stuff that just is everywhere - today, search, online, etc.
1298 1
				array('select', 'todayMod', array($txt['today_disabled'], $txt['today_only'], $txt['yesterday_today'], $txt['relative_time'])),
1299 1
				array('check', 'onlineEnable'),
1300 1
				array('check', 'enableVBStyleLogin'),
1301 1
			'',
1302
				// Automagic image resizing.
1303 1
				array('int', 'max_image_width', 'subtext' => $txt['zero_for_no_limit']),
1304 1
				array('int', 'max_image_height', 'subtext' => $txt['zero_for_no_limit']),
1305 1
			'',
1306
				// This is like debugging sorta.
1307 1
				array('check', 'timeLoadPageEnable'),
1308 1
		));
1309
1310 1
		call_integration_hook('integrate_modify_layout_settings', array(&$config_vars));
1311
1312 1
		return $config_vars;
1313
	}
1314
1315
	/**
1316
	 * Public method to return the layout settings, used for admin search
1317
	 */
1318 1
	public function layoutSettings_search()
1319
	{
1320 1
		return $this->_layoutSettings();
1321
	}
1322
1323
	/**
1324
	 * Return karma settings.
1325
	 *
1326
	 * @event integrate_modify_karma_settings Adds to Configuration->Karma
1327
	 */
1328 1
	private function _karmaSettings()
1329
	{
1330 1
		global $txt;
1331
1332
		$config_vars = array(
1333
				// Karma - On or off?
1334 1
				array('select', 'karmaMode', explode('|', $txt['karma_options'])),
1335 1
			'',
1336
				// Who can do it.... and who is restricted by time limits?
1337 1
				array('int', 'karmaMinPosts', 6, 'postinput' => $txt['manageposts_posts']),
1338 1
				array('float', 'karmaWaitTime', 6, 'postinput' => $txt['hours']),
1339 1
				array('check', 'karmaTimeRestrictAdmins'),
1340 1
				array('check', 'karmaDisableSmite'),
1341 1
			'',
1342
				// What does it look like?  [smite]?
1343 1
				array('text', 'karmaLabel'),
1344 1
				array('text', 'karmaApplaudLabel', 'mask' => 'nohtml'),
1345 1
				array('text', 'karmaSmiteLabel', 'mask' => 'nohtml'),
1346 1
		);
1347
1348 1
		call_integration_hook('integrate_modify_karma_settings', array(&$config_vars));
1349
1350 1
		return $config_vars;
1351
	}
1352
1353
	/**
1354
	 * Public method to return the karma settings, used for admin search
1355
	 */
1356 1
	public function karmaSettings_search()
1357
	{
1358 1
		return $this->_karmaSettings();
1359
	}
1360
1361
	/**
1362
	 * Return likes settings.
1363
	 *
1364
	 * @event integrate_modify_likes_settings Adds to Configuration->Likes
1365
	 */
1366 1
	private function _likesSettings()
1367
	{
1368 1
		global $txt;
1369
1370
		$config_vars = array(
1371
				// Likes - On or off?
1372 1
				array('check', 'likes_enabled'),
1373 1
			'',
1374
				// Who can do it.... and who is restricted by count limits?
1375 1
				array('int', 'likeMinPosts', 6, 'postinput' => $txt['manageposts_posts']),
1376 1
				array('int', 'likeWaitTime', 6, 'postinput' => $txt['minutes']),
1377 1
				array('int', 'likeWaitCount', 6),
1378 1
				array('check', 'likeRestrictAdmins'),
1379 1
				array('check', 'likeAllowSelf'),
1380 1
			'',
1381 1
				array('int', 'likeDisplayLimit', 6)
1382 1
		);
1383
1384 1
		call_integration_hook('integrate_modify_likes_settings', array(&$config_vars));
1385
1386 1
		return $config_vars;
1387
	}
1388
1389
	/**
1390
	 * Public method to return the likes settings, used for admin search
1391
	 */
1392 1
	public function likesSettings_search()
1393
	{
1394 1
		return $this->_likesSettings();
1395
	}
1396
1397
	/**
1398
	 * Return mentions settings.
1399
	 *
1400
	 * @event integrate_modify_mention_settings Adds to Configuration->Mentions
1401
	 */
1402 1
	private function _notificationsSettings()
1403
	{
1404 1
		global $txt, $modSettings;
1405
1406 1
		loadLanguage('Profile');
1407 1
		loadLanguage('UserNotifications');
1408
1409
		// The mentions settings
1410
		$config_vars = array(
1411 1
			array('title', 'mentions_settings'),
1412 1
			array('check', 'mentions_enabled'),
1413 1
		);
1414
1415 1
		$notification_methods = Notifications::instance()->getNotifiers();
1416 1
		$notification_types = getNotificationTypes();
1417 1
		$current_settings = unserialize($modSettings['notification_methods']);
1418
1419 1
		foreach ($notification_types as $title)
1420
		{
1421 1
			$config_vars[] = array('title', 'setting_' . $title);
1422
1423 1
			foreach ($notification_methods as $method)
1424
			{
1425 1
				if ($method === 'notification')
1426 1
					$text_label = $txt['setting_notify_enable_this'];
1427
				else
1428 1
					$text_label = $txt['notify_' . $method];
1429
1430 1
				$config_vars[] = array('check', 'notifications[' . $title . '][' . $method . ']', 'text_label' => $text_label);
1431 1
				$modSettings['notifications[' . $title . '][' . $method . ']'] = !empty($current_settings[$title][$method]);
1432 1
			}
1433 1
		}
1434
1435 1
		call_integration_hook('integrate_modify_mention_settings', array(&$config_vars));
1436
1437 1
		return $config_vars;
1438
	}
1439
1440
	/**
1441
	 * Public method to return the mention settings, used for admin search
1442
	 */
1443 1
	public function mentionSettings_search()
1444
	{
1445 1
		return $this->_notificationsSettings();
1446
	}
1447
1448
	/**
1449
	 * Return signature settings.
1450
	 *
1451
	 * - Used in admin center search and settings form
1452
	 *
1453
	 * @event integrate_modify_signature_settings Adds options to Signature Settings
1454
	 */
1455 1
	private function _signatureSettings()
1456
	{
1457 1
		global $txt;
1458
1459
		$config_vars = array(
1460
				// Are signatures even enabled?
1461 1
				array('check', 'signature_enable'),
1462 1
			'',
1463
				// Tweaking settings!
1464 1
				array('int', 'signature_max_length', 'subtext' => $txt['zero_for_no_limit']),
1465 1
				array('int', 'signature_max_lines', 'subtext' => $txt['zero_for_no_limit']),
1466 1
				array('int', 'signature_max_font_size', 'subtext' => $txt['zero_for_no_limit']),
1467 1
				array('check', 'signature_allow_smileys', 'onclick' => 'document.getElementById(\'signature_max_smileys\').disabled = !this.checked;'),
1468 1
				array('int', 'signature_max_smileys', 'subtext' => $txt['zero_for_no_limit']),
1469 1
				array('select', 'signature_repetition_guests',
1470
					array(
1471 1
						$txt['signature_always'],
1472 1
						$txt['signature_onlyfirst'],
1473 1
						$txt['signature_never'],
1474 1
					),
1475 1
				),
1476 1
				array('select', 'signature_repetition_members',
1477
					array(
1478 1
						$txt['signature_always'],
1479 1
						$txt['signature_onlyfirst'],
1480 1
						$txt['signature_never'],
1481 1
					),
1482 1
				),
1483 1
			'',
1484
				// Image settings.
1485 1
				array('int', 'signature_max_images', 'subtext' => $txt['signature_max_images_note']),
1486 1
				array('int', 'signature_max_image_width', 'subtext' => $txt['zero_for_no_limit']),
1487 1
				array('int', 'signature_max_image_height', 'subtext' => $txt['zero_for_no_limit']),
1488 1
			'',
1489 1
				array('bbc', 'signature_bbc'),
1490 1
		);
1491
1492 1
		call_integration_hook('integrate_modify_signature_settings', array(&$config_vars));
1493
1494 1
		return $config_vars;
1495
	}
1496
1497
	/**
1498
	 * Public method to return the signature settings, used for admin search
1499
	 */
1500 1
	public function signatureSettings_search()
1501
	{
1502 1
		return $this->_signatureSettings();
1503
	}
1504
1505
	/**
1506
	 * Return pm settings.
1507
	 *
1508
	 * - Used in admin center search and settings form
1509
	 *
1510
	 * @event integrate_modify_pmsettings_settings Adds / Modifies PM Settings
1511
	 */
1512
	private function _pmSettings()
1513
	{
1514
		global $txt;
1515
1516
		$config_vars = array(
1517
			// Reporting of personal messages?
1518
			array('check', 'enableReportPM'),
1519
			// Inline permissions.
1520
			array('permissions', 'pm_send'),
1521
			// PM Settings
1522
			array('title', 'antispam_PM'),
1523
				'pm1' => array('int', 'max_pm_recipients', 'postinput' => $txt['max_pm_recipients_note']),
1524
				'pm2' => array('int', 'pm_posts_verification', 'postinput' => $txt['pm_posts_verification_note']),
1525
				'pm3' => array('int', 'pm_posts_per_hour', 'postinput' => $txt['pm_posts_per_hour_note']),
1526
			array('title', 'membergroups_max_messages'),
1527
				array('desc', 'membergroups_max_messages_desc'),
1528
				array('callback', 'pm_limits'),
1529
		);
1530
1531
		call_integration_hook('integrate_modify_pmsettings_settings', array(&$config_vars));
1532
1533
		return $config_vars;
1534
	}
1535
}
1536
1537
/**
1538
 * Just pause the signature applying thing.
1539
 *
1540
 * @todo Move to subs file
1541
 * @todo Merge with other pause functions?
1542
 *    pausePermsSave(), pauseAttachmentMaintenance(), pauseRepairProcess()
1543
 *
1544
 * @param int $applied_sigs
1545
 * @throws Elk_Exception
1546
 */
1547
function pauseSignatureApplySettings($applied_sigs)
1548
{
1549
	global $context, $txt, $sig_start;
1550
1551
	// Try get more time...
1552
	detectServer()->setTimeLimit(600);
1553
1554
	// Have we exhausted all the time we allowed?
1555
	if (time() - array_sum(explode(' ', $sig_start)) < 3)
1556
		return;
1557
1558
	$context['continue_get_data'] = '?action=admin;area=featuresettings;sa=sig;apply;step=' . $applied_sigs . ';' . $context['session_var'] . '=' . $context['session_id'];
1559
	$context['page_title'] = $txt['not_done_title'];
1560
	$context['continue_post_data'] = '';
1561
	$context['continue_countdown'] = '2';
1562
	$context['sub_template'] = 'not_done';
1563
1564
	// Specific stuff to not break this template!
1565
	$context[$context['admin_menu_name']]['current_subsection'] = 'sig';
1566
1567
	// Get the right percent.
1568
	$context['continue_percent'] = round(($applied_sigs / $context['max_member']) * 100);
1569
1570
	// Never more than 100%!
1571
	$context['continue_percent'] = min($context['continue_percent'], 100);
1572
1573
	obExit();
1574
}
1575