Passed
Pull Request — patch_1-1-7 (#3421)
by Spuds
37:02 queued 22:02
created

action_layoutSettings_display()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 41
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

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