Completed
Pull Request — patch_1-1-4 (#3191)
by Emanuele
13:25
created

ManageRegistration_Controller::action_agreement()   C

Complexity

Conditions 10
Paths 32

Size

Total Lines 69
Code Lines 33

Duplication

Lines 25
Ratio 36.23 %

Code Coverage

Tests 0
CRAP Score 110

Importance

Changes 0
Metric Value
cc 10
eloc 33
nc 32
nop 0
dl 25
loc 69
ccs 0
cts 37
cp 0
crap 110
rs 6.0493
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * This file helps the administrator setting registration settings and policy
5
 * as well as allow the administrator to register new members themselves.
6
 *
7
 * @name      ElkArte Forum
8
 * @copyright ElkArte Forum contributors
9
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause
10
 *
11
 * This file contains code covered by:
12
 * copyright:	2011 Simple Machines (http://www.simplemachines.org)
13
 * license:		BSD, See included LICENSE.TXT for terms and conditions.
14
 *
15
 * @version 1.1
16
 *
17
 */
18
19
use ElkArte\Errors\ErrorContext;
20
21
/**
22
 * ManageRegistration admin controller: handles the registration pages
23
 *
24
 * - allow admins (or moderators with moderate_forum permission)
25
 * to register a new member,
26
 * - to see and edit the registration agreement,
27
 * - to set up reserved words for forum names.
28
 *
29
 * @package Registration
30
 */
31
class ManageRegistration_Controller extends Action_Controller
32
{
33
	/**
34
	 * Entrance point for the registration center, it checks permissions and forwards
35
	 * to the right method based on the subaction.
36
	 *
37
	 * - Accessed by ?action=admin;area=regcenter.
38
	 * - Requires either the moderate_forum or the admin_forum permission.
39
	 *
40
	 * @event integrate_sa_manage_registrations add new registration sub actions
41
	 * @uses Login language file
42
	 * @uses Register template.
43
	 * @see Action_Controller::action_index()
44
	 */
45
	public function action_index()
46
	{
47
		global $context, $txt;
48
49
		// Loading, always loading.
50
		loadLanguage('Login');
51
		loadTemplate('Register');
52
		loadJavascriptFile('register.js');
53
54
		$subActions = array(
55
			'register' => array(
56
				'controller' => $this,
57
				'function' => 'action_register',
58
				'permission' => 'moderate_forum',
59
			),
60
			'agreement' => array(
61
				'controller' => $this,
62
				'function' => 'action_agreement',
63
				'permission' => 'admin_forum',
64
			),
65
			'privacypol' => array(
66
				'controller' => $this,
67
				'function' => 'action_privacypol',
68
				'permission' => 'admin_forum',
69
			),
70
			'reservednames' => array(
71
				'controller' => $this,
72
				'function' => 'action_reservednames',
73
				'permission' => 'admin_forum',
74
			),
75
			'settings' => array(
76
				'controller' => $this,
77
				'function' => 'action_registerSettings_display',
78
				'permission' => 'admin_forum',
79
			),
80
		);
81
82
		// Action controller
83
		$action = new Action('manage_registrations');
84
85
		// Next create the tabs for the template.
86
		$context[$context['admin_menu_name']]['tab_data'] = array(
87
			'title' => $txt['registration_center'],
88
			'help' => 'registrations',
89
			'description' => $txt['admin_settings_desc'],
90
			'tabs' => array(
91
				'register' => array(
92
					'description' => $txt['admin_register_desc'],
93
				),
94
				'agreement' => array(
95
					'description' => $txt['registration_agreement_desc'],
96
				),
97
				'privacypol' => array(
98
					'description' => $txt['privacy_policy_desc'],
99
				),
100
				'reservednames' => array(
101
					'description' => $txt['admin_reserved_desc'],
102
				),
103
				'settings' => array(
104
					'description' => $txt['admin_settings_desc'],
105
				)
106
			)
107
		);
108
109
		// Work out which to call... call integrate_sa_manage_registrations
110
		$subAction = $action->initialize($subActions, 'register');
111
112
		// Final bits
113
		$context['page_title'] = $txt['maintain_title'];
114
		$context['sub_action'] = $subAction;
115
116
		// Call the right function for this sub-action.
117
		$action->dispatch($subAction);
118
	}
119
120
	/**
121
	 * This function allows the admin to register a new member by hand.
122
	 *
123
	 * - It also allows assigning a primary group to the member being registered.
124
	 * - Accessed by ?action=admin;area=regcenter;sa=register
125
	 * - Requires the moderate_forum permission.
126
	 *
127
	 * @uses Register template, admin_register sub-template.
128
	 */
129
	public function action_register()
130
	{
131
		global $txt, $context, $scripturl, $user_info;
132
133
		if (!empty($this->_req->post->regSubmit))
134
		{
135
			checkSession();
136
			validateToken('admin-regc');
137
138
			// @todo move this to a filter/sanitation class
139 View Code Duplication
			foreach ($this->_req->post as $key => $value)
140
				if (!is_array($value))
141
					$this->_req->post[$key] = htmltrim__recursive(str_replace(array("\n", "\r"), '', $value));
142
143
			// Generate a password
144
			if (empty($this->_req->post->password) || !is_string($this->_req->post->password) || trim($this->_req->post->password) === '')
145
			{
146
				$tokenizer = new Token_Hash();
147
				$password = $tokenizer->generate_hash(14);
148
			}
149
			else
150
			{
151
				$password = $this->_req->post->password;
152
			}
153
154
			$regOptions = array(
155
				'interface' => 'admin',
156
				'username' => $this->_req->post->user,
157
				'email' => $this->_req->post->email,
158
				'password' => $password,
159
				'password_check' => $password,
160
				'check_reserved_name' => true,
161
				'check_password_strength' => true,
162
				'check_email_ban' => false,
163
				'send_welcome_email' => isset($this->_req->post->emailPassword),
164
				'require' => isset($this->_req->post->emailActivate) ? 'activation' : 'nothing',
165
				'memberGroup' => empty($this->_req->post->group) || !allowedTo('manage_membergroups') ? 0 : (int) $this->_req->post->group,
166
				'ip' => '127.0.0.1',
167
				'ip2' => '127.0.0.1',
168
				'auth_method' => 'password',
169
			);
170
171
			require_once(SUBSDIR . '/Members.subs.php');
172
			$reg_errors = ErrorContext::context('register', 0);
173
			$memberID = registerMember($regOptions, 'register');
174
175
			// If there are "important" errors and you are not an admin: log the first error
176
			// Otherwise grab all of them and don't log anything
177
			$error_severity = $reg_errors->hasErrors(1) && !$user_info['is_admin'] ? 1 : null;
178 View Code Duplication
			foreach ($reg_errors->prepareErrors($error_severity) as $error)
179
			{
180
				throw new Elk_Exception($error, $error_severity === null ? false : 'general');
181
			}
182
183
			if (!empty($memberID))
184
			{
185
				$context['new_member'] = array(
186
					'id' => $memberID,
187
					'name' => $this->_req->post->user,
188
					'href' => $scripturl . '?action=profile;u=' . $memberID,
189
					'link' => '<a href="' . $scripturl . '?action=profile;u=' . $memberID . '">' . $this->_req->post->user . '</a>',
190
				);
191
				$context['registration_done'] = sprintf($txt['admin_register_done'], $context['new_member']['link']);
192
			}
193
		}
194
195
		// Load the assignable member groups.
196
		if (allowedTo('manage_membergroups'))
197
		{
198
			require_once(SUBSDIR . '/Membergroups.subs.php');
199
			if (allowedTo('admin_forum'))
200
			{
201
				$includes = array('admin', 'globalmod', 'member');
202
			}
203
			else
204
			{
205
				$includes = array('globalmod', 'member', 'custom');
206
			}
207
208
			$groups = array();
209
			$membergroups = getBasicMembergroupData($includes, array('hidden', 'protected'));
210
			foreach ($membergroups as $membergroup)
211
			{
212
				$groups[$membergroup['id']] = $membergroup['name'];
213
			}
214
215
			$context['member_groups'] = $groups;
216
		}
217
		else
218
		{
219
			$context['member_groups'] = array();
220
		}
221
222
		// Basic stuff.
223
		loadJavascriptFile('mailcheck.min.js');
224
		addInlineJavascript('disableAutoComplete();
225
		$("input[type=email]").on("blur", function(event) {
226
			$(this).mailcheck({
227
				suggested: function(element, suggestion) {
228
				  	$("#suggestion").html("' . $txt['register_did_you'] . ' <b><i>" + suggestion.full + "</b></i>");
229
				},
230
				empty: function(element) {
231
				  	$("#suggestion").html("");
232
				}
233
			});
234
		});', true);
235
		$context['sub_template'] = 'admin_register';
236
		$context['page_title'] = $txt['registration_center'];
237
		createToken('admin-regc');
238
	}
239
240
	/**
241
	 * Allows the administrator to edit the registration agreement, and choose whether
242
	 * it should be shown or not.
243
	 *
244
	 * - It writes and saves the agreement to the agreement.txt file.
245
	 * - Accessed by ?action=admin;area=regcenter;sa=agreement.
246
	 * - Requires the admin_forum permission.
247
	 *
248
	 * @uses Admin template and the edit_agreement sub template.
249
	 */
250
	public function action_agreement()
251
	{
252
		// I hereby agree not to be a lazy bum.
253
		global $txt, $context, $modSettings;
254
255
		// By default we look at agreement.txt.
256
		$context['current_agreement'] = '';
257
258
		// Is there more than one to edit?
259
		$context['editable_agreements'] = array(
260
			'' => $txt['admin_agreement_default'],
261
		);
262
263
		// Get our languages.
264
		$languages = getLanguages();
265
266
		// Try to figure out if we have more agreements.
267 View Code Duplication
		foreach ($languages as $lang)
268
		{
269
			if (file_exists(BOARDDIR . '/agreement.' . $lang['filename'] . '.txt'))
270
			{
271
				$context['editable_agreements'][$lang['filename']] = $lang['name'];
272
273
				// Are we editing this?
274
				if (isset($this->_req->post->agree_lang) && $this->_req->post->agree_lang === $lang['filename'])
275
				{
276
					$context['current_agreement'] = $lang['filename'];
277
					break;
278
				}
279
			}
280
		}
281
282
		$context['warning'] = '';
283
		$agreement = new \Agreement($context['current_agreement']);
284
285
		if (isset($this->_req->post->save) && isset($this->_req->post->agreement))
286
		{
287
			checkSession();
288
			validateToken('admin-rega');
289
290
			// Off it goes to the agreement file.
291
			$success = $agreement->save($this->_req->post->agreement, !empty($this->_req->post->checkboxAcceptAgreement));
292 View Code Duplication
			if (!empty($this->_req->post->checkboxAcceptAgreement))
293
			{
294
				if ($success === false)
295
				{
296
					$context['warning'] .= $txt['agreement_backup_not_writable'] . '<br />';
297
				}
298
				else
299
				{
300
					updateSettings(array('agreementRevision' => $success));
301
				}
302
			}
303
304
			updateSettings(array('requireAgreement' => !empty($this->_req->post->requireAgreement), 'checkboxAgreement' => !empty($this->_req->post->checkboxAgreement)));
305
		}
306
307
		$context['agreement'] = Util::htmlspecialchars($agreement->getPlainText(false));
308
309
		$context['warning'] .= $agreement->isWritable() ? '' : $txt['agreement_not_writable'];
310
		$context['require_agreement'] = !empty($modSettings['requireAgreement']);
311
		$context['checkbox_agreement'] = !empty($modSettings['checkboxAgreement']);
312
313
		$context['sub_template'] = 'edit_agreement';
314
		$context['subaction'] = 'agreement';
315
		$context['agreement_show_options'] = true;
316
		$context['page_title'] = $txt['registration_agreement'];
317
		createToken('admin-rega');
318
	}
319
320
	/**
321
	 * Allows the administrator to edit the privacy policy, and choose whether
322
	 * it should be shown or not.
323
	 *
324
	 * - It writes and saves the privacy policy to the privacypolicy.txt file.
325
	 * - Accessed by ?action=admin;area=regcenter;sa=privacypol
326
	 * - Requires the admin_forum permission.
327
	 *
328
	 * @uses Admin template and the edit_agreement sub template.
329
	 */
330
	public function action_privacypol()
331
	{
332
		// I hereby agree not to be a lazy bum.
333
		global $txt, $context, $modSettings;
334
335
		// By default we look at privacypolicy.txt.
336
		$context['current_agreement'] = '';
337
338
		// Is there more than one to edit?
339
		$context['editable_agreements'] = array(
340
			'' => $txt['admin_agreement_default'],
341
		);
342
343
		// Get our languages.
344
		$languages = getLanguages();
345
346
		// Try to figure out if we have more agreements.
347 View Code Duplication
		foreach ($languages as $lang)
348
		{
349
			if (file_exists(BOARDDIR . '/privacypolicy.' . $lang['filename'] . '.txt'))
350
			{
351
				$context['editable_agreements'][$lang['filename']] = $lang['name'];
352
353
				// Are we editing this?
354
				if (isset($this->_req->post->agree_lang) && $this->_req->post->agree_lang === $lang['filename'])
355
				{
356
					$context['current_agreement'] = $lang['filename'];
357
					break;
358
				}
359
			}
360
		}
361
362
		$context['warning'] = '';
363
		$privacypol = new \PrivacyPolicy($context['current_agreement']);
364
365
		if (isset($this->_req->post->save) && isset($this->_req->post->agreement))
366
		{
367
			checkSession();
368
			validateToken('admin-rega');
369
370
			// Off it goes to the agreement file.
371
			$success = $privacypol->save($this->_req->post->agreement, !empty($this->_req->post->checkboxAcceptAgreement));
372 View Code Duplication
			if (!empty($this->_req->post->checkboxAcceptAgreement))
373
			{
374
				if ($success === false)
375
				{
376
					$context['warning'] .= $txt['privacypol_backup_not_writable'] . '<br />';
377
				}
378
				else
379
				{
380
					updateSettings(array('privacypolicyRevision' => $success));
381
				}
382
			}
383
384
			updateSettings(array('requirePrivacypolicy' => !empty($this->_req->post->requireAgreement)));
385
		}
386
387
		$context['agreement'] = Util::htmlspecialchars($privacypol->getPlainText(false));
388
389
		$context['warning'] .= $privacypol->isWritable() ? '' : $txt['privacypol_not_writable'];
390
		$context['require_agreement'] = !empty($modSettings['requirePrivacypolicy']);
391
392
		$context['sub_template'] = 'edit_agreement';
393
		$context['subaction'] = 'privacypol';
394
		$context['page_title'] = $txt['privacy_policy'];
395
		// These overrides are here to be able to reuse the template in a simple way without having to change much.
396
		$txt['admin_agreement'] = $txt['admin_privacypol'];
397
		$txt['admin_checkbox_accept_agreement'] = $txt['admin_checkbox_accept_privacypol'];
398
		$txt['confirm_request_accept_agreement'] = $txt['confirm_request_accept_privacy_policy'];
399
400
		createToken('admin-rega');
401
	}
402
403
	/**
404
	 * Set the names under which users are not allowed to register.
405
	 *
406
	 * - Accessed by ?action=admin;area=regcenter;sa=reservednames.
407
	 * - Requires the admin_forum permission.
408
	 *
409
	 * @uses Register template, reserved_words sub-template.
410
	 */
411 1
	public function action_reservednames()
412
	{
413 1
		global $txt, $context, $modSettings;
414
415
		// Submitting new reserved words.
416 1
		if (!empty($this->_req->post->save_reserved_names))
417 1
		{
418 1
			checkSession();
419 1
			validateToken('admin-regr');
420 1
421 1
			// Set all the options....
422 1
			updateSettings(array(
423 1
				'reserveWord' => (isset($this->_req->post->matchword) ? '1' : '0'),
424 1
				'reserveCase' => (isset($this->_req->post->matchcase) ? '1' : '0'),
425 1
				'reserveUser' => (isset($this->_req->post->matchuser) ? '1' : '0'),
426 1
				'reserveName' => (isset($this->_req->post->matchname) ? '1' : '0'),
427 1
				'reserveNames' => str_replace("\r", '', $this->_req->post->reserved)
428
			));
429
		}
430 1
431
		// Get the reserved word options and words.
432 1
		$modSettings['reserveNames'] = str_replace('\n', "\n", $modSettings['reserveNames']);
433
		$context['reserved_words'] = explode("\n", $modSettings['reserveNames']);
434
		$context['reserved_word_options'] = array();
435
		$context['reserved_word_options']['match_word'] = $modSettings['reserveWord'] == '1';
436
		$context['reserved_word_options']['match_case'] = $modSettings['reserveCase'] == '1';
437
		$context['reserved_word_options']['match_user'] = $modSettings['reserveUser'] == '1';
438 1
		$context['reserved_word_options']['match_name'] = $modSettings['reserveName'] == '1';
439
440 1
		// Ready the template......
441
		$context['sub_template'] = 'edit_reserved_words';
442
		$context['page_title'] = $txt['admin_reserved_set'];
443
		createToken('admin-regr');
444
	}
445
446
	/**
447
	 * This function handles registration settings, and provides a few pretty stats too while it's at it.
448
	 *
449
	 * - General registration settings and Coppa compliance settings.
450
	 * - Accessed by ?action=admin;area=regcenter;sa=settings.
451
	 * - Requires the admin_forum permission.
452
	 *
453
	 * @event integrate_save_registration_settings
454
	 */
455
	public function action_registerSettings_display()
456
	{
457
		global $txt, $context, $scripturl, $modSettings;
458
459
		// Initialize the form
460
		$settingsForm = new Settings_Form(Settings_Form::DB_ADAPTER);
461
462
		// Initialize it with our settings
463
		$settingsForm->setConfigVars($this->_settings());
464
465
		// Setup the template
466
		$context['sub_template'] = 'show_settings';
467
		$context['page_title'] = $txt['registration_center'];
468
469
		if (isset($this->_req->query->save))
470
		{
471
			checkSession();
472
473
			// Are there some contacts missing?
474
			if (!empty($this->_req->post->coppaAge) && !empty($this->_req->post->coppaType) && empty($this->_req->post->coppaPost) && empty($this->_req->post->coppaFax))
475
				throw new Elk_Exception('admin_setting_coppa_require_contact');
476
477
			// Post needs to take into account line breaks.
478
			$this->_req->post->coppaPost = str_replace("\n", '<br />', empty($this->_req->post->coppaPost) ? '' : $this->_req->post->coppaPost);
479
480
			call_integration_hook('integrate_save_registration_settings');
481
482
			$settingsForm->setConfigValues((array) $this->_req->post);
483
			$settingsForm->save();
484
485
			redirectexit('action=admin;area=regcenter;sa=settings');
486
		}
487
488
		$context['post_url'] = $scripturl . '?action=admin;area=regcenter;save;sa=settings';
489
		$context['settings_title'] = $txt['settings'];
490
491
		// Define some javascript for COPPA.
492
		addInlineJavascript('
493
			function checkCoppa()
494
			{
495
				var coppaDisabled = document.getElementById(\'coppaAge\').value == 0;
496
				document.getElementById(\'coppaType\').disabled = coppaDisabled;
497
498
				var disableContacts = coppaDisabled || document.getElementById(\'coppaType\').options[document.getElementById(\'coppaType\').selectedIndex].value != 1;
499
				document.getElementById(\'coppaPost\').disabled = disableContacts;
500
				document.getElementById(\'coppaFax\').disabled = disableContacts;
501
				document.getElementById(\'coppaPhone\').disabled = disableContacts;
502
			}
503
			checkCoppa();', true);
504
505
		// Turn the postal address into something suitable for a textbox.
506
		$modSettings['coppaPost'] = !empty($modSettings['coppaPost']) ? preg_replace('~<br ?/?' . '>~', "\n", $modSettings['coppaPost']) : '';
507
508
		$settingsForm->prepare();
509
	}
510
511
	/**
512
	 * Return configuration settings for new members registration.
513
	 *
514
	 * @event integrate_modify_registration_settings
515
	 */
516
	private function _settings()
517
	{
518
		global $txt;
519
520
		$config_vars = array(
521
			array('select', 'registration_method', array($txt['setting_registration_standard'], $txt['setting_registration_activate'], $txt['setting_registration_approval'], $txt['setting_registration_disabled'])),
522
			array('check', 'enableOpenID'),
523
			array('check', 'notify_new_registration'),
524
			array('check', 'force_accept_agreement'),
525
			array('check', 'force_accept_privacy_policy'),
526
			array('check', 'send_welcomeEmail'),
527
			array('check', 'show_DisplayNameOnRegistration'),
528
			'',
529
			array('int', 'coppaAge', 'subtext' => $txt['setting_coppaAge_desc'], 'onchange' => 'checkCoppa();', 'onkeyup' => 'checkCoppa();'),
530
			array('select', 'coppaType', array($txt['setting_coppaType_reject'], $txt['setting_coppaType_approval']), 'onchange' => 'checkCoppa();'),
531
			array('large_text', 'coppaPost', 'subtext' => $txt['setting_coppaPost_desc']),
532
			array('text', 'coppaFax'),
533
			array('text', 'coppaPhone'),
534
		);
535
536
		// Add new settings with a nice hook, makes them available for admin settings search as well
537
		call_integration_hook('integrate_modify_registration_settings', array(&$config_vars));
538
539
		return $config_vars;
540
	}
541
542
	/**
543
	 * Return the registration settings for use in admin search
544
	 */
545
	public function settings_search()
546
	{
547
		return $this->_settings();
548
	}
549
}
550