Register::action_register()   F
last analyzed

Complexity

Conditions 29
Paths 9264

Size

Total Lines 151
Code Lines 71

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 870

Importance

Changes 0
Metric Value
eloc 71
dl 0
loc 151
rs 0
c 0
b 0
f 0
cc 29
nc 9264
nop 0
ccs 0
cts 65
cp 0
crap 870

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 has two main jobs, but they really are one.  It registers new
5
 * members, and it helps the administrator moderate member registrations.
6
 * Similarly, it handles account activation as well.
7
 *
8
 * @package   ElkArte Forum
9
 * @copyright ElkArte Forum contributors
10
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file)
11
 *
12
 * This file contains code covered by:
13
 * copyright: 2011 Simple Machines (http://www.simplemachines.org)
14
 *
15
 * @version 2.0 Beta 1
16
 *
17
 */
18
19
namespace ElkArte\Controller;
20
21
use ElkArte\AbstractController;
22
use ElkArte\Action;
23
use ElkArte\Agreement;
24
use ElkArte\Errors\ErrorContext;
25
use ElkArte\Errors\Errors;
0 ignored issues
show
Bug introduced by
The type ElkArte\Errors\Errors was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
26
use ElkArte\Exceptions\Exception;
27
use ElkArte\Helper\DataValidator;
28
use ElkArte\Helper\Util;
29
use ElkArte\Languages\Txt;
30
use ElkArte\PrivacyPolicy;
31
use ElkArte\Profile\ProfileFields;
32
use ElkArte\Profile\ProfileOptions;
33
use ElkArte\Request;
34
35
/**
36
 * It registers new members, and it allows the administrator moderate member registration
37
 */
38
class Register extends AbstractController
39
{
40
	/** @var int is_activated value key is as follows */
41
	private const STATUS_NOT_ACTIVE = 0;
42
	private const STATUS_APPROVED_AND_ACTIVE = 1;
43
	private const STATUS_AWAITING_REACTIVATION = 2;
44
	private const STATUS_AWAITING_COPPA = 5;
45
46
	/** @var array Holds the results of a findUser() request */
47
	private $_row;
48
49
	/**
50
	 * {@inheritDoc}
51
	 */
52
	public function trackStats($action = '')
53
	{
54
		return parent::trackStats($action);
55
	}
56
57
	/**
58
	 * Pre-dispatch, called before other methods.
59
	 */
60
	public function pre_dispatch()
61
	{
62
		global $modSettings;
63
64
		// Check if the administrator has it disabled.
65
		if (empty($modSettings['registration_method']))
66
		{
67
			return;
68
		}
69
70
		if ((int) $modSettings['registration_method'] !== 3)
71
		{
72
			return;
73
		}
74
75
		throw new Exception('registration_disabled', false);
76
	}
77
78
	/**
79
	 * Intended entry point for this class.
80
	 *
81
	 * By default, this is called for action=register
82
	 *
83
	 * @see AbstractController::action_index
84
	 */
85
	public function action_index()
86
	{
87
		// Add the sub-action array to dispatch accordingly
88
		$subActions = [
89
			'register' => [$this, 'action_register'],
90
			'register2' => [$this, 'action_register2'],
91
			'usernamecheck' => [$this, 'action_registerCheckUsername'],
92
			'activate' => [$this, 'action_activate'],
93
			'agrelang' => [$this, 'action_agrelang'],
94
			'privacypol' => [$this, 'action_privacypol'],
95
			'agreement' => [$this, 'action_agreement'],
96
		];
97
98
		// Setup the action handler
99
		$action = new Action('register');
100
		$subAction = $action->initialize($subActions, 'register');
101
102
		// Call the action
103
		$action->dispatch($subAction);
104
	}
105
106
	/**
107
	 * Begin the registration process.
108
	 *
109
	 * - Triggers the prepare_context event
110
	 *
111
	 * Accessed by ?action=register
112
	 *
113
	 * @uses template_registration_agreement or template_registration_form sub template in Register.template,
114
	 * @uses Login language file
115
	 */
116
	public function action_register(): void
117
	{
118
		global $txt, $context, $modSettings, $scripturl;
119
120
		// If this user is an admin - redirect them to the admin registration page.
121
		if ($this->user->is_guest === false && allowedTo('moderate_forum'))
0 ignored issues
show
Bug Best Practice introduced by
The property is_guest does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
122
		{
123
			redirectexit('action=admin;area=regcenter;sa=register');
124
		}
125
		// You are not a guest, so you are a member - and members don't get to register twice!
126
		elseif (empty($this->user->is_guest))
127
		{
128
			redirectexit();
129
		}
130
131
		// Confused and want to contact the admins instead
132
		if (isset($this->_req->post->show_contact))
133
		{
134
			redirectexit('action=about;sa=contact');
135
		}
136
137
		// If we have language support enabled then they need to be loaded
138
		if ($this->_load_language_support())
139
		{
140
			redirectexit('action=register');
141
		}
142
143
		Txt::load('Login+Profile');
144
		theme()->getTemplates()->load('Register');
145
		theme()->getTemplates()->load('ProfileOptions');
146
147
		// Do we need them to agree to the registration agreement, first?
148
		$context['require_agreement'] = !empty($modSettings['requireAgreement']);
149
		$context['checkbox_agreement'] = !empty($modSettings['checkboxAgreement']);
150
		$context['require_privacypol'] = !empty($modSettings['requirePrivacypolicy']);
151
		$context['registration_passed_agreement'] = !empty($_SESSION['registration_agreed']);
152
		$context['registration_passed_privacypol'] = !empty($_SESSION['registration_privacypolicy']);
153
		$context['show_coppa'] = !empty($modSettings['coppaAge']);
154
		$context['show_contact_button'] = !empty($modSettings['enable_contactform']) && $modSettings['enable_contactform'] === 'registration';
155
		$context['insert_display_name'] = !empty($modSettings['show_DisplayNameOnRegistration']);
156
157
		// Underage restrictions?
158
		if ($context['show_coppa'])
159
		{
160
			$context['skip_coppa'] = false;
161
			$context['coppa_agree_above'] = sprintf($txt[($context['require_agreement'] ? 'agreement_' : '') . 'agree_coppa_above'], $modSettings['coppaAge']);
162
			$context['coppa_agree_below'] = sprintf($txt[($context['require_agreement'] ? 'agreement_' : '') . 'agree_coppa_below'], $modSettings['coppaAge']);
163
		}
164
165
		// What step are we at?
166
		$current_step = $this->_req->getPost('step', 'intval', ($context['require_agreement'] && !$context['checkbox_agreement'] ? 1 : 2));
167
168
		// Does this user agree to the registration agreement?
169
		if ($current_step === 1 && (isset($this->_req->post->accept_agreement) || isset($this->_req->post->accept_agreement_coppa)))
170
		{
171
			$context['registration_passed_agreement'] = $_SESSION['registration_agreed'] = true;
172
			$context['registration_passed_privacypol'] = $_SESSION['registration_privacypolicy'] = true;
173
			$current_step = 2;
174
175
			// Skip the coppa procedure if the user says he's old enough.
176
			if ($context['show_coppa'])
177
			{
178
				$_SESSION['skip_coppa'] = !empty($this->_req->post->accept_agreement);
179
180
				// Are they saying they're under age, while under age registration is disabled?
181
				if (empty($modSettings['coppaType']) && empty($_SESSION['skip_coppa']))
182
				{
183
					throw new Exception('Login.under_age_registration_prohibited', false, [$modSettings['coppaAge']]);
184
				}
185
			}
186
		}
187
		// Make sure they don't squeeze through without agreeing.
188
		elseif ($current_step > 1 && $context['require_agreement'] && !$context['checkbox_agreement'] && !$context['registration_passed_agreement'])
189
		{
190
			$current_step = 1;
191
		}
192
193
		// Show the user the right form.
194
		$context['sub_template'] = $current_step === 1 ? 'registration_agreement' : 'registration_form';
195
		$context['page_title'] = $current_step === 1 ? $txt['registration_agreement'] : $txt['registration_form'];
196
		loadJavascriptFile(['register.js', 'ext/mailcheck.min.js']);
197
198
		// Add the register chain to the link tree.
199
		$context['breadcrumbs'][] = [
200
			'url' => $scripturl . '?action=register',
201
			'name' => $txt['register'],
202
		];
203
204
		// Prepare the time gate! Done like this to allow later steps to reset the limit for any reason
205
		if (!isset($_SESSION['register']))
206
		{
207
			$_SESSION['register'] = [
208
				'timenow' => time(),
209
				// minimum number of seconds required on this page for registration
210
				'limit' => 8,
211
			];
212
		}
213
		else
214
		{
215
			$_SESSION['register']['timenow'] = time();
216
		}
217
218
		// If you have to agree to the agreement, it needs to be fetched from the file.
219
		$agreement = new Agreement($this->user->language);
0 ignored issues
show
Bug Best Practice introduced by
The property language does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
220
		$context['agreement'] = $agreement->getParsedText();
221
222
		if (empty($context['agreement']))
223
		{
224
			// No file found or a blank file, log the error so the admin knows there is a problem!
225
			Txt::load('Errors');
226
			Errors::instance()->log_error($txt['registration_agreement_missing'], 'critical');
227
			throw new Exception('registration_disabled', false);
228
		}
229
230
		if (!empty($context['require_privacypol']))
231
		{
232
			$privacypol = new PrivacyPolicy($this->user->language);
233
			$context['privacy_policy'] = $privacypol->getParsedText();
234
235
			if (empty($context['privacy_policy']))
236
			{
237
				// No file found or a blank file, log the error so the admin knows there is a problem!
238
				Txt::load('Errors');
239
				Errors::instance()::instance()->log_error($txt['registration_privacy_policy_missing'], 'critical');
240
				throw new \Exception('registration_disabled', false);
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type integer expected by parameter $code of Exception::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

240
				throw new \Exception('registration_disabled', /** @scrutinizer ignore-type */ false);
Loading history...
241
			}
242
		}
243
244
		// If we have language support enabled then they need to be loaded
245
		$this->_load_language_support();
246
247
		// Any custom or standard profile fields we want filled in during registration?
248
		$this->_load_profile_fields();
249
250
		// Trigger the prepare_context event
251
		$this->_events->trigger('prepare_context', ['current_step' => $current_step]);
252
253
		// See whether we have some pre-filled values.
254
		$context['username'] = $this->_req->getPost('user', 'Util::htmlspecialchars', '');
255
		$context['email'] = $this->_req->getPost('email', 'Util::htmlspecialchars', '');
256
		$context['notify_announcements'] = (int) !empty($this->_req->post->notify_announcements);
257
258
		// Were there any errors?
259
		$context['registration_errors'] = [];
260
		$reg_errors = ErrorContext::context('register', 0);
261
		if ($reg_errors->hasErrors())
262
		{
263
			$context['registration_errors'] = $reg_errors->prepareErrors();
264
		}
265
266
		createToken('register');
267
	}
268
269
	/**
270
	 * Handles the registration process for members using ElkArte registration
271
	 *
272
	 * What it does:
273
	 *
274
	 * - Validates all requirements have been filled in properly
275
	 * - Passes final processing to do_register
276
	 * - Directs back to register on errors
277
	 * - Triggers the before_complete_register event
278
	 *
279
	 * Accessed by ?action=register;sa=register2
280
	 */
281
	public function action_register2(): void
282
	{
283
		global $modSettings;
284
285
		// Start collecting together any errors.
286
		$reg_errors = ErrorContext::context('register', 0);
287
288
		// Make sure registration is enabled
289
		$this->_can_register();
290
291
		checkSession();
292
		if (!validateToken('register', 'post', true, false))
293
		{
294
			$reg_errors->addError('token_verification');
295
		}
296
297
		// If we're using an agreement checkbox, did they check it?
298
		if (!empty($modSettings['checkboxAgreement']) && !empty($this->_req->post->checkbox_agreement))
299
		{
300
			$_SESSION['registration_agreed'] = true;
301
		}
302
303
		// Using coppa and the registration checkbox?
304
		if (!empty($modSettings['coppaAge']) && !empty($modSettings['checkboxAgreement']) && !empty($this->_req->post->accept_agreement))
305
		{
306
			$_SESSION['skip_coppa'] = true;
307
		}
308
309
		// Well, if you don't agree to the Registration Agreement, you can't register.
310
		if (!empty($modSettings['requireAgreement']) && empty($_SESSION['registration_agreed']))
311
		{
312
			redirectexit();
313
		}
314
315
		if (!empty($modSettings['requireAgreement']) && !empty($modSettings['requirePrivacypolicy']) && !empty($this->_req->post->checkbox_privacypol))
316
		{
317
			$_SESSION['registration_privacypolicy'] = true;
318
		}
319
320
		// Well, if you don't agree to the Privacy Policy, you can't register.
321
		if (!empty($modSettings['requireAgreement']) && !empty($modSettings['requirePrivacypolicy']) && empty($_SESSION['registration_privacypolicy']))
322
		{
323
			redirectexit();
324
		}
325
326
		// Make sure they came from *somewhere*, have a session.
327
		if (!isset($_SESSION['old_url']))
328
		{
329
			redirectexit('action=register');
330
		}
331
332
		// If we don't require an agreement, we need a extra check for coppa.
333
		if (empty($modSettings['requireAgreement']) && !empty($modSettings['coppaAge']))
334
		{
335
			$_SESSION['skip_coppa'] = !empty($this->_req->post->accept_agreement);
336
		}
337
338
		// Are they under age, and under age users are banned?
339
		if (!empty($modSettings['coppaAge']) && empty($modSettings['coppaType']) && empty($_SESSION['skip_coppa']))
340
		{
341
			throw new Exception('Login.under_age_registration_prohibited', false, [$modSettings['coppaAge']]);
342
		}
343
344
		// Check the time gate for miscreants. First make sure they came from somewhere that actually set it up.
345
		if (empty($_SESSION['register']['timenow']) || empty($_SESSION['register']['limit']))
346
		{
347
			redirectexit('action=register');
348
		}
349
350
		// Failing that, check the time limit for excessive speed.
351
		if (time() - $_SESSION['register']['timenow'] < $_SESSION['register']['limit'])
352
		{
353
			Txt::load('Login');
354
			$reg_errors->addError('too_quickly');
355
		}
356
357
		// Maybe the filled in our hidden honey pot form field like a good bot would
358
		if (!empty($this->_req->getPost('reason_for_joining_hp', 'trim', '')))
359
		{
360
			// Its not missing, it just should not be there
361
			Txt::load('Login');
362
			$reg_errors->addError('error_missing_information');
363
		}
364
365
		// Trigger any events required before we complete registration, like captcha verification
366
		$this->_events->trigger('before_complete_register', ['reg_errors' => $reg_errors]);
367
368
		$this->do_register();
369
	}
370
371
	/**
372
	 * Actually register the member.
373
	 *
374
	 * - Called from Register controller
375
	 * - Does the actual registration to the system
376
	 */
377
	public function do_register(): ?bool
378
	{
379
		global $txt, $modSettings, $context;
380
381
		// Start collecting together any errors.
382
		$reg_errors = ErrorContext::context('register', 0);
383
384
		// Clean the form values
385
		foreach ($this->_req->post as $key => $value)
386
		{
387
			if (!is_array($value))
388
			{
389
				$this->_req->post->{$key} = Util::htmltrim__recursive(str_replace(["\n", "\r"], '', $value));
390
			}
391
		}
392
393
		// A little security to any secret answer ... @todo increase?
394
		if ($this->_req->getPost('secret_answer', 'trim', '') !== '')
395
		{
396
			$this->_req->post->secret_answer = md5($this->_req->post->secret_answer);
397
		}
398
399
		// Needed for isReservedName() and registerMember().
400
		require_once(SUBSDIR . '/Members.subs.php');
401
402
		// Validation... even if we're not a mall.
403
		if (isset($this->_req->post->real_name) && (!empty($modSettings['allow_editDisplayName']) || allowedTo('moderate_forum')))
404
		{
405
			$this->_req->post->real_name = trim(preg_replace('~[\t\n\r \x0B\0\x{A0}\x{AD}\x{2000}-\x{200F}\x{201F}\x{202F}\x{3000}\x{FEFF}]+~u', ' ', $this->_req->post->real_name));
406
			$has_real_name = true;
407
		}
408
		else
409
		{
410
			$has_real_name = false;
411
		}
412
413
		// Handle a string as a birth date...
414
		if ($this->_req->getPost('birthdate', 'trim', '') !== '')
415
		{
416
			$this->_req->post->birthdate = Util::strftime('%Y-%m-%d', strtotime($this->_req->post->birthdate));
417
		}
418
		// Or birthdate parts...
419
		elseif (!empty($this->_req->post->bday1) && !empty($this->_req->post->bday2))
420
		{
421
			$this->_req->post->birthdate = sprintf('%04d-%02d-%02d', empty($this->_req->post->bday3) ? 0 : (int) $this->_req->post->bday3, (int) $this->_req->post->bday1, (int) $this->_req->post->bday2);
422
		}
423
424
		// Validate the passed language file.
425
		if (isset($this->_req->post->lngfile) && !empty($modSettings['userLanguage']))
426
		{
427
			// Do we have any languages?
428
			$context['languages'] = getLanguages();
429
430
			// Did we find it?
431
			if (isset($context['languages'][$this->_req->post->lngfile]))
432
			{
433
				$_SESSION['language'] = $this->_req->post->lngfile;
434
			}
435
			else
436
			{
437
				$this->_req->clearValue('lngfile', 'post');
438
			}
439
		}
440
		elseif (isset($this->_req->post->lngfile))
441
		{
442
			$this->_req->clearValue('lngfile', 'post');
443
		}
444
445
		// Set the options needed for registration.
446
		$regOptions = [
447
			'interface' => 'guest',
448
			'username' => empty($this->_req->post->user) ? '' : $this->_req->post->user,
449
			'email' => empty($this->_req->post->email) ? '' : $this->_req->post->email,
450
			'password' => empty($this->_req->post->passwrd1) ? '' : $this->_req->post->passwrd1,
451
			'password_check' => empty($this->_req->post->passwrd2) ? '' : $this->_req->post->passwrd2,
452
			'auth_method' => empty($this->_req->post->authenticate) ? '' : $this->_req->post->authenticate,
453
			'check_reserved_name' => true,
454
			'check_password_strength' => true,
455
			'check_email_ban' => true,
456
			'send_welcome_email' => !empty($modSettings['send_welcomeEmail']),
457
			'require' => !empty($modSettings['coppaAge']) && empty($_SESSION['skip_coppa']) ? 'coppa' : (empty($modSettings['registration_method']) ? 'nothing' : ($modSettings['registration_method'] == 1 ? 'activation' : 'approval')),
458
			'extra_register_vars' => $this->_extra_vars($has_real_name),
459
			'theme_vars' => [],
460
		];
461
462
		// Registration options are always default options...
463
		if (isset($this->_req->post->default_options))
464
		{
465
			$this->_req->post->options = isset($this->_req->post->options) ? $this->_req->post->options + $this->_req->post->default_options : $this->_req->post->default_options;
466
		}
467
468
		$regOptions['theme_vars'] = isset($this->_req->post->options) && is_array($this->_req->post->options) ? $this->_req->post->options : [];
469
470
		// Make sure they are clean, dammit!
471
		$regOptions['theme_vars'] = Util::htmlspecialchars__recursive($regOptions['theme_vars']);
472
473
		// Check whether we have fields that simply MUST be displayed?
474
		$profileFields = new ProfileFields();
475
		$profileFields->loadCustomFields(0, 'register', $this->_req->post->customfield ?? []);
476
477
		foreach ($context['custom_fields'] as $row)
478
		{
479
			// Don't allow overriding of the theme variables.
480
			if (isset($regOptions['theme_vars'][$row['colname']]))
481
			{
482
				unset($regOptions['theme_vars'][$row['colname']]);
483
			}
484
485
			// Prepare the value!
486
			$value = isset($this->_req->post->customfield[$row['colname']]) ? trim($this->_req->post->customfield[$row['colname']]) : '';
487
488
			// We only care for text fields as the others are valid to be empty.
489
			if (!in_array($row['field_type'], ['check', 'select', 'radio']))
490
			{
491
				$is_valid = isCustomFieldValid($row, $value);
492
				if ($is_valid !== true)
493
				{
494
					$err_params = [$row['name']];
495
					if ($is_valid === 'custom_field_too_long')
496
					{
497
						$err_params[] = $row['field_length'];
498
					}
499
500
					$reg_errors->addError([$is_valid, $err_params]);
501
				}
502
			}
503
504
			// Is this required but not there?
505
			if ($row['show_reg'] > 1 && trim($value) === '')
506
			{
507
				$reg_errors->addError(['custom_field_empty', [$row['name']]]);
508
			}
509
		}
510
511
		// Lets check for other errors before trying to register the member.
512
		if ($reg_errors->hasErrors())
513
		{
514
			$this->_req->post->step = 2;
515
516
			// If they've filled in some details but made an error then they need less time to finish
517
			$_SESSION['register']['limit'] = 4;
518
519
			$this->action_register();
520
521
			return false;
522
		}
523
524
		// Registration needs to know your IP
525
		$req = Request::instance();
526
527
		$regOptions['ip'] = $this->user->ip;
0 ignored issues
show
Bug Best Practice introduced by
The property ip does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
528
		$regOptions['ip2'] = $req->ban_ip();
529
		$memberID = registerMember($regOptions);
530
531
		// If there are "important" errors and you are not an admin: log the first error
532
		// Otherwise grab all of them and don't log anything
533
		if ($reg_errors->hasErrors(1) && $this->user->is_admin === false)
0 ignored issues
show
Bug Best Practice introduced by
The property is_admin does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
534
		{
535
			foreach ($reg_errors->prepareErrors(1) as $error)
536
			{
537
				throw new Exception($error, 'general');
538
			}
539
		}
540
541
		// Was there actually an error of some kind dear boy?
542
		if ($reg_errors->hasErrors())
543
		{
544
			$this->_req->post->step = 2;
545
			$this->action_register();
546
547
			return false;
548
		}
549
550
		$lang = empty($modSettings['userLanguage']) ? 'english' : $modSettings['userLanguage'];
551
		$agreement = new Agreement($lang);
552
		$agreement->accept($memberID, $this->user->ip, empty($modSettings['agreementRevision']) ? Util::strftime('%Y-%m-%d', forum_time(false)) : $modSettings['agreementRevision']);
553
554
		if (!empty($modSettings['requirePrivacypolicy']))
555
		{
556
			$policy = new PrivacyPolicy($lang);
557
			$policy->accept($memberID, $this->user->ip, empty($modSettings['privacypolicyRevision']) ? Util::strftime('%Y-%m-%d', forum_time(false)) : $modSettings['privacypolicyRevision']);
558
		}
559
560
		// Do our spam protection now.
561
		spamProtection('register');
562
563
		// We'll do custom fields after as then we get to use the helper function!
564
		if (!empty($this->_req->post->customfield))
565
		{
566
			require_once(SUBSDIR . '/Profile.subs.php');
567
			makeCustomFieldChanges($memberID, 'register');
568
		}
569
570
		// If COPPA has been selected then things get complicated, setup the template.
571
		if (!empty($modSettings['coppaAge']) && empty($_SESSION['skip_coppa']))
572
		{
573
			redirectexit('action=about;sa=coppa;member=' . $memberID);
574
		}
575
		// Basic template variable setup.
576
		elseif (!empty($modSettings['registration_method']))
577
		{
578
			theme()->getTemplates()->load('Register');
579
580
			$context += [
581
				'page_title' => $txt['register'],
582
				'title' => $txt['registration_successful'],
583
				'sub_template' => 'after',
584
				'description' => $modSettings['registration_method'] == 2 ? $txt['approval_after_registration'] : $txt['activate_after_registration']
585
			];
586
		}
587
		else
588
		{
589
			call_integration_hook('integrate_activate', [$regOptions['username'], 1, 1]);
590
591
			setLoginCookie(60 * $modSettings['cookieTime'], $memberID, hash('sha256', $regOptions['register_vars']['passwd'] . $regOptions['register_vars']['password_salt']));
592
593
			redirectexit('action=auth;sa=check;member=' . $memberID);
594
		}
595
596
		return null;
597
	}
598
599
	/**
600
	 * Checks if registrations are enabled and the user didn't just register
601
	 */
602
	private function _can_register(): void
603
	{
604
		global $modSettings;
605
606
		// You can't register if it's disabled.
607
		if (!empty($modSettings['registration_method']) && $modSettings['registration_method'] == 3)
608
		{
609
			throw new Exception('registration_disabled', false);
610
		}
611
612
		// Make sure they didn't just register with this session.
613
		if (!empty($_SESSION['just_registered']) && empty($modSettings['disableRegisterCheck']))
614
		{
615
			throw new Exception('register_only_once', false);
616
		}
617
	}
618
619
	/**
620
	 * Collect all extra registration fields someone might have filled in.
621
	 *
622
	 * What it does:
623
	 *
624
	 * - Classifies variables as possible string, int, float or bool
625
	 * - Casts all posted data to the proper type (string, float, etc)
626
	 * - Drops fields that we specially exclude during registration
627
	 *
628
	 * @param bool $has_real_name - if true adds 'real_name' as well
629
	 *
630
	 * @return array
631
	 * @throws Exception
632
	 */
633
	private function _extra_vars($has_real_name): array
634
	{
635
		global $modSettings;
636
637
		// Define the fields that may be enabled for registration
638
		$possible_strings = [
639
			'birthdate',
640
			'time_format',
641
			'buddy_list',
642
			'pm_ignore_list',
643
			'smiley_set',
644
			'avatar',
645
			'lngfile',
646
			'secret_question', 'secret_answer',
647
			'website_url', 'website_title',
648
		];
649
650
		$possible_ints = [
651
			'pm_email_notify',
652
			'notify_types',
653
			'notify_from',
654
			'id_theme',
655
		];
656
657
		$possible_floats = [
658
			'time_offset',
659
		];
660
661
		$possible_bools = [
662
			'notify_announcements', 'notify_regularity', 'notify_send_body', 'show_online',
663
		];
664
665
		if ($has_real_name && trim($this->_req->post->real_name) !== '' && !isReservedName($this->_req->post->real_name) && Util::strlen($this->_req->post->real_name) < 60)
666
		{
667
			$possible_strings[] = 'real_name';
668
		}
669
670
		// Some of these fields we may not want.
671
		if (!empty($modSettings['registration_fields']))
672
		{
673
			// But we might want some of them if the admin asks for them.
674
			$reg_fields = explode(',', $modSettings['registration_fields']);
675
676
			$exclude_fields = [];
677
678
			// Website is a little different
679
			if (!in_array('website', $reg_fields))
680
			{
681
				$exclude_fields = array_merge($exclude_fields, ['website_url', 'website_title']);
682
			}
683
684
			// We used to accept signature on registration but it's being abused by spammers these days, so no more.
685
			$exclude_fields[] = 'signature';
686
		}
687
		else
688
		{
689
			$exclude_fields = ['signature', 'website_url', 'website_title'];
690
		}
691
692
		$possible_strings = array_diff($possible_strings, $exclude_fields);
693
		$possible_ints = array_diff($possible_ints, $exclude_fields);
694
		$possible_floats = array_diff($possible_floats, $exclude_fields);
695
		$possible_bools = array_diff($possible_bools, $exclude_fields);
696
697
		$extra_register_vars = [];
698
699
		// Include the additional options that might have been filled in.
700
		foreach ($possible_strings as $var)
701
		{
702
			if (isset($this->_req->post->{$var}))
703
			{
704
				$extra_register_vars[$var] = Util::htmlspecialchars($this->_req->post->{$var}, ENT_QUOTES);
705
			}
706
		}
707
708
		foreach ($possible_ints as $var)
709
		{
710
			if (isset($this->_req->post->{$var}))
711
			{
712
				$extra_register_vars[$var] = (int) $this->_req->post->{$var};
713
			}
714
		}
715
716
		foreach ($possible_floats as $var)
717
		{
718
			if (isset($this->_req->post->{$var}))
719
			{
720
				$extra_register_vars[$var] = (float) $this->_req->post->{$var};
721
			}
722
		}
723
724
		foreach ($possible_bools as $var)
725
		{
726
			if (isset($this->_req->post->{$var}))
727
			{
728
				$extra_register_vars[$var] = empty($this->_req->post->{$var}) ? 0 : 1;
729
			}
730
		}
731
732
		return $extra_register_vars;
733
	}
734
735
	/**
736
	 * Sets the users language file
737
	 *
738
	 * What it does:
739
	 *
740
	 * - If language support is enabled, loads what's available
741
	 * - Verifies the users choice is available
742
	 * - Sets in context / session
743
	 *
744
	 * @return bool true if the language was changed, false if not.
745
	 */
746
	private function _load_language_support(): bool
747
	{
748
		global $context, $modSettings, $language;
749
750
		// Language support enabled
751
		if (!empty($modSettings['userLanguage']))
752
		{
753
			// Do we have any languages?
754
			$languages = getLanguages();
755
756
			if (isset($this->_req->post->lngfile, $languages[$this->_req->post->lngfile]))
757
			{
758
				$_SESSION['language'] = $this->_req->post->lngfile;
759
				if ($_SESSION['language'] !== ucfirst($this->user->language))
0 ignored issues
show
Bug introduced by
It seems like $this->user->language can also be of type null; however, parameter $string of ucfirst() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

759
				if ($_SESSION['language'] !== ucfirst(/** @scrutinizer ignore-type */ $this->user->language))
Loading history...
Bug Best Practice introduced by
The property language does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
760
				{
761
					return true;
762
				}
763
			}
764
765
			// Not selected, or not found, use the site default
766
			$selectedLanguage = empty($_SESSION['language']) ? $language : $_SESSION['language'];
767
768
			// Try to find our selected language.
769
			foreach ($languages as $key => $lang)
770
			{
771
				$context['languages'][$key]['name'] = $lang['name'];
772
773
				// Found it!
774
				if (ucfirst($selectedLanguage) === $lang['name'])
775
				{
776
					$context['languages'][$key]['selected'] = true;
777
				}
778
			}
779
		}
780
781
		return false;
782
	}
783
784
	/**
785
	 * Load standard and custom registration profile fields
786
	 *
787
	 * @uses ProfileFields->loadCustomFields() Loads standard fields in to context
788
	 * @uses setupProfileContext() Loads supplied fields in to context
789
	 */
790
	private function _load_profile_fields(): void
791
	{
792
		global $context, $modSettings, $cur_profile;
793
794
		// Any custom fields to load?
795
		$profileFields = new ProfileFields();
796
		$profileFields->loadCustomFields(0, 'register');
797
798
		// Or any standard ones?
799
		if (!empty($modSettings['registration_fields']))
800
		{
801
			// Setup some important context.
802
			Txt::load('Profile');
803
			theme()->getTemplates()->load('Profile');
804
805
			$context['user']['is_owner'] = true;
806
807
			// Here, and here only, emulate the permissions the user would have to do this.
808
			$this->user->permissions = array_merge($this->user->permissions, ['profile_account_own', 'profile_extra_own']);
0 ignored issues
show
Bug Best Practice introduced by
The property permissions does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug introduced by
It seems like $this->user->permissions can also be of type null; however, parameter $arrays of array_merge() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

808
			$this->user->permissions = array_merge(/** @scrutinizer ignore-type */ $this->user->permissions, ['profile_account_own', 'profile_extra_own']);
Loading history...
Bug Best Practice introduced by
The property permissions does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __set, consider adding a @property annotation.
Loading history...
809
			$reg_fields = ProfileOptions::getFields('registration');
810
811
			// We might have had some submissions on this front - go check.
812
			foreach ($reg_fields['fields'] as $field)
813
			{
814
				if (isset($this->_req->post->{$field}))
815
				{
816
					$cur_profile[$field] = Util::htmlspecialchars($this->_req->post->{$field});
817
				}
818
			}
819
820
			// Load all the fields in question.
821
			setupProfileContext($reg_fields['fields'], $reg_fields['hook']);
822
		}
823
	}
824
825
	/**
826
	 * Verify the activation code, and activate the user if correct.
827
	 *
828
	 * What it does:
829
	 *
830
	 * - Accessed by ?action=register;sa=activate
831
	 * - Processes activation code requests
832
	 * - Checks if the user is already activate and if so does nothing
833
	 * - Prevents a user from using an existing email
834
	 */
835
	public function action_activate(): void
836
	{
837
		global $context, $txt, $modSettings;
838
839
		require_once(SUBSDIR . '/Auth.subs.php');
840
841
		// Logged in users should not bother to activate their accounts
842
		if (!empty($this->user->id))
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
843
		{
844
			redirectexit();
845
		}
846
847
		Txt::load('Login');
848
		theme()->getTemplates()->load('Login');
849
850
		// Need a user id to activate
851
		if (empty($this->_req->query->u) && empty($this->_req->post->user))
852
		{
853
			// Immediate 0 or disabled 3 means no need to try and activate
854
			if (empty($modSettings['registration_method']) || $modSettings['registration_method'] === '3')
855
			{
856
				throw new Exception('no_access', false);
857
			}
858
859
			// Otherwise its simply invalid
860
			$context['member_id'] = 0;
861
			$context['sub_template'] = 'resend';
862
			$context['page_title'] = $txt['invalid_activation_resend'];
863
			$context['can_activate'] = $modSettings['registration_method'] === '1';
864
			$context['default_username'] = $this->_req->getPost('user', 'trim', '');
865
866
			return;
867
		}
868
869
		// Get the user from the database...
870
		$this->_row = findUser(empty($this->_req->query->u)
0 ignored issues
show
Documentation Bug introduced by
It seems like findUser(empty($this->_r...', 'trim', '')), false) can also be of type boolean. However, the property $_row is declared as type array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
871
			? 'member_name = {string:email_address} OR email_address = {string:email_address}'
872
			: 'id_member = {int:id_member}',
873
			[
874
				'id_member' => $this->_req->getQuery('u', 'intval', 0),
875
				'email_address' => $this->_req->getPost('user', 'trim', ''),
876
			], false
877
		);
878
879
		// Does this user exist at all?
880
		if (empty($this->_row))
881
		{
882
			$context['sub_template'] = 'retry_activate';
883
			$context['page_title'] = $txt['invalid_userid'];
884
			$context['member_id'] = 0;
885
886
			return;
887
		}
888
889
		// Change their email address if not active 0 or awaiting reactivation 2? ( they probably tried a fake one first :P )
890
		$email_change = $this->_activate_change_email();
891
892
		// Resend the password, but only if the account wasn't activated yet (0 or 2)
893
		$this->_activate_resend($email_change);
894
895
		// Quit if this code is not right.
896
		if ($this->_activate_validate_code() === false)
897
		{
898
			return;
899
		}
900
901
		// Validation complete - update the database!
902
		require_once(SUBSDIR . '/Members.subs.php');
903
		approveMembers(['members' => [$this->_row['id_member']], 'activated_status' => $this->_row['is_activated']]);
904
905
		// Also do a proper member stat re-evaluation.
906
		require_once(SUBSDIR . '/Members.subs.php');
907
		updateMemberStats();
908
909
		if (!isset($this->_req->post->new_email) && empty($this->_row['is_activated']))
910
		{
911
			require_once(SUBSDIR . '/Notification.subs.php');
912
			sendAdminNotifications('activation', $this->_row['id_member'], $this->_row['member_name']);
913
		}
914
915
		$context += [
916
			'page_title' => $txt['registration_successful'],
917
			'sub_template' => 'login',
918
			'default_username' => $this->_row['member_name'],
919
			'default_password' => '',
920
			'never_expire' => false,
921
			'description' => $txt['activate_success']
922
		];
923
	}
924
925
	/**
926
	 * Change their email address if not active
927
	 *
928
	 * What it does:
929
	 *
930
	 * - Requires the user enter the id/password for the account
931
	 * - The account must not be active 0 or awaiting reactivation 2
932
	 */
933
	private function _activate_change_email(): bool
934
	{
935
		global $modSettings, $txt;
936
937
		if (isset($this->_req->post->new_email, $this->_req->post->passwd)
938
			&& ($this->_row['is_activated'] === self::STATUS_NOT_ACTIVE || $this->_row['is_activated'] === self::STATUS_AWAITING_REACTIVATION)
939
			&& validateLoginPassword($this->_req->post->passwd, $this->_row['passwd'], $this->_row['member_name'], true))
940
		{
941
			if (empty($modSettings['registration_method']) || $modSettings['registration_method'] == 3)
942
			{
943
				throw new Exception('no_access', false);
944
			}
945
946
			// @todo Separate the sprintf?
947
			if (!DataValidator::is_valid($this->_req->post, ['new_email' => 'valid_email|required|max_length[255]'], ['new_email' => 'trim']))
948
			{
949
				throw new Exception(sprintf($txt['valid_email_needed'], htmlspecialchars($this->_req->post->new_email, ENT_COMPAT, 'UTF-8')), false);
950
			}
951
952
			// Make sure their email isn't banned.
953
			isBannedEmail($this->_req->post->new_email, 'cannot_register', $txt['ban_register_prohibited']);
954
955
			// Ummm... don't take someone else's email during the change
956
			// @todo Separate the sprintf?
957
			if (userByEmail($this->_req->post->new_email) === false)
958
			{
959
				throw new Exception('email_in_use', false, [htmlspecialchars($this->_req->post->new_email, ENT_COMPAT, 'UTF-8')]);
960
			}
961
962
			require_once(SUBSDIR . '/Members.subs.php');
963
			updateMemberData($this->_row['id_member'], ['email_address' => $this->_req->post->new_email]);
964
			$this->_row['email_address'] = $this->_req->post->new_email;
965
966
			return true;
967
		}
968
969
		return false;
970
	}
971
972
	/**
973
	 * Resend an activation code to a user
974
	 *
975
	 * What it does:
976
	 *
977
	 * - Called with action=register;sa=activate;resend
978
	 * - Will resend an activation code to non-active account
979
	 *
980
	 * @param bool $email_change if the email was changed or not
981
	 *
982
	 * @throws Exception
983
	 */
984
	private function _activate_resend($email_change): void
985
	{
986
		global $scripturl, $modSettings, $language, $txt, $context;
987
988
		if (isset($this->_req->query->resend)
989
			&& ($this->_row['is_activated'] === self::STATUS_NOT_ACTIVE || $this->_row['is_activated'] === self::STATUS_AWAITING_REACTIVATION)
990
			&& $this->_req->getPost('code', 'trim', '') === '')
991
		{
992
			require_once(SUBSDIR . '/Mail.subs.php');
993
994
			// Since you lost it, you get a nice new code
995
			$validation_code = generateValidationCode(14);
996
			$this->_row['validation_code'] = substr(hash('sha256', $validation_code), 0, 10);
997
998
			require_once(SUBSDIR . '/Members.subs.php');
999
			updateMemberData($this->_row['id_member'], ['validation_code' => $this->_row['validation_code']]);
1000
1001
			$replacements = [
1002
				'REALNAME' => $this->_row['real_name'],
1003
				'USERNAME' => $this->_row['member_name'],
1004
				'ACTIVATIONLINK' => $scripturl . '?action=register;sa=activate;u=' . $this->_row['id_member'] . ';code=' . $validation_code,
1005
				'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=register;sa=activate;u=' . $this->_row['id_member'],
1006
				'ACTIVATIONCODE' => $validation_code,
1007
				'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder',
1008
			];
1009
1010
			$emaildata = loadEmailTemplate('resend_activate_message', $replacements, empty($this->_row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $this->_row['lngfile']);
1011
			sendmail($this->_row['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 0);
1012
1013
			$context['page_title'] = $txt['invalid_activation_resend'];
1014
1015
			// Don't let them wack away on their resend
1016
			spamProtection('remind');
1017
1018
			// This will ensure we don't actually get an error message if it works!
1019
			$context['error_title'] = $txt['invalid_activation_resend'];
1020
			throw new Exception(empty($email_change) ? 'resend_email_success' : 'change_email_success', false);
1021
		}
1022
	}
1023
1024
	/**
1025
	 * Validates a supplied activation code is valid
1026
	 *
1027
	 * @throws Exception already_activated, registration_not_approved
1028
	 */
1029
	private function _activate_validate_code(): bool
1030
	{
1031
		global $txt, $scripturl, $context;
1032
1033
		$code = substr(hash('sha256', $this->_req->getQuery('code', 'trim', '')), 0, 10);
1034
1035
		if ($code !== $this->_row['validation_code'])
1036
		{
1037
			if (!empty($this->_row['is_activated']) && $this->_row['is_activated'] === self::STATUS_APPROVED_AND_ACTIVE)
1038
			{
1039
				throw new Exception('already_activated', false);
1040
			}
1041
			if ($this->_row['validation_code'] === '')
1042
			{
1043
				Txt::load('Profile');
1044
				throw new Exception($txt['registration_not_approved'] . ' <a href="' . $scripturl . '?action=register;sa=activate;user=' . $this->_row['member_name'] . '">' . $txt['here'] . '</a>.', false);
1045
			}
1046
			$context['sub_template'] = 'retry_activate';
1047
			$context['page_title'] = $txt['invalid_activation_code'];
1048
			$context['member_id'] = $this->_row['id_member'];
1049
			return false;
1050
		}
1051
1052
		return true;
1053
	}
1054
1055
	/**
1056
	 * See if a username already exists.
1057
	 *
1058
	 * - Used by registration template via xml request
1059
	 */
1060
	public function action_registerCheckUsername(): void
1061
	{
1062
		global $context;
1063
1064
		// This is XML!
1065
		theme()->getTemplates()->load('Xml');
1066
		$context['sub_template'] = 'check_username';
1067
		$context['checked_username'] = isset($this->_req->query->username) ? un_htmlspecialchars($this->_req->query->username) : '';
1068
		$context['valid_username'] = true;
1069
1070
		// Clean it up like mother would.
1071
		$context['checked_username'] = preg_replace('~[\t\n\r \x0B\0\x{A0}\x{AD}\x{2000}-\x{200F}\x{201F}\x{202F}\x{3000}\x{FEFF}]+~u', ' ', $context['checked_username']);
1072
1073
		$errors = ErrorContext::context('valid_username', 0);
1074
1075
		require_once(SUBSDIR . '/Auth.subs.php');
1076
		validateUsername(0, $context['checked_username'], 'valid_username', true, false);
1077
1078
		$context['valid_username'] = !$errors->hasErrors();
1079
	}
1080
1081
	public function action_agreement(): void
1082
	{
1083
		global $context, $modSettings, $txt;
1084
1085
		if (isset($this->_req->post->accept_agreement))
1086
		{
1087
			$agreement = new Agreement($this->user->language);
0 ignored issues
show
Bug Best Practice introduced by
The property language does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
1088
			$agreement->accept($this->user->id, $this->user->ip, empty($modSettings['agreementRevision']) ? Util::strftime('%Y-%m-%d', forum_time(false)) : $modSettings['agreementRevision']);
0 ignored issues
show
Bug Best Practice introduced by
The property ip does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug Best Practice introduced by
The property id does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
1089
1090
			$_SESSION['agreement_accepted'] = true;
1091
			if (isset($_SESSION['agreement_url_redirect']))
1092
			{
1093
				redirectexit($_SESSION['agreement_url_redirect']);
1094
			}
1095
			else
1096
			{
1097
				redirectexit();
1098
			}
1099
		}
1100
		elseif (isset($this->_req->post->no_accept))
1101
		{
1102
			redirectexit('action=profile;area=deleteaccount');
1103
		}
1104
		else
1105
		{
1106
			$context['sub_template'] = 'registration_agreement';
1107
			$context['register_subaction'] = 'agreement';
1108
		}
1109
1110
		Txt::load('Login');
1111
		Txt::load('Profile');
1112
		theme()->getTemplates()->load('Register');
1113
1114
		// If you have to agree to the agreement, it needs to be fetched from the file.
1115
		$agreement = new Agreement($this->user->language);
1116
		$context['agreement'] = $agreement->getParsedText();
1117
		$context['page_title'] = $txt['registration_agreement'];
1118
1119
		$context['show_coppa'] = !empty($modSettings['coppaAge']);
1120
		$context['show_contact_button'] = !empty($modSettings['enable_contactform']) && $modSettings['enable_contactform'] === 'registration';
1121
1122
		// Under age restrictions?
1123
		if ($context['show_coppa'])
1124
		{
1125
			$context['skip_coppa'] = false;
1126
			$context['coppa_agree_above'] = sprintf($txt[($context['require_agreement'] ? 'agreement_' : '') . 'agree_coppa_above'], $modSettings['coppaAge']);
1127
			$context['coppa_agree_below'] = sprintf($txt[($context['require_agreement'] ? 'agreement_' : '') . 'agree_coppa_below'], $modSettings['coppaAge']);
1128
		}
1129
1130
		createToken('register');
1131
	}
1132
1133
	/**
1134
	 * Action for handling privacy policy acceptance during registration.
1135
	 *
1136
	 * - Called from Register controller
1137
	 * - Handles the acceptance and redirection
1138
	 *    - If the user accepts the privacy policy, it updates the user's acceptance status in the database,
1139
	 *      sets a session variable indicating acceptance, and redirects the user to the specified URL.
1140
	 *    - If the user declines the privacy policy, it redirects the user to the account deletion page.
1141
	 *    - If the user has not yet made a decision, it loads the registration agreement template for displaying the privacy policy.
1142
	 */
1143
	public function action_privacypol(): void
1144
	{
1145
		global $context, $modSettings, $txt;
1146
1147
		$policy = new PrivacyPolicy($this->user->language);
0 ignored issues
show
Bug Best Practice introduced by
The property language does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
1148
1149
		if (isset($this->_req->post->accept_agreement))
1150
		{
1151
			$policy->accept($this->user->id, $this->user->ip, empty($modSettings['privacypolicyRevision']) ? Util::strftime('%Y-%m-%d', forum_time(false)) : $modSettings['privacypolicyRevision']);
0 ignored issues
show
Bug Best Practice introduced by
The property ip does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug Best Practice introduced by
The property id does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
1152
1153
			$_SESSION['privacypolicy_accepted'] = true;
1154
			if (isset($_SESSION['privacypolicy_url_redirect']))
1155
			{
1156
				redirectexit($_SESSION['privacypolicy_url_redirect']);
1157
			}
1158
			else
1159
			{
1160
				redirectexit();
1161
			}
1162
		}
1163
		elseif (isset($this->_req->post->no_accept))
1164
		{
1165
			redirectexit('action=profile;area=deleteaccount');
1166
		}
1167
		else
1168
		{
1169
			$context['sub_template'] = 'registration_agreement';
1170
			$context['register_subaction'] = 'privacypol';
1171
		}
1172
1173
		Txt::load('Login');
1174
		Txt::load('Profile');
1175
		theme()->getTemplates()->load('Register');
1176
1177
		$txt['agreement_agree'] = $txt['policy_agree'];
1178
		$txt['agreement_no_agree'] = $txt['policy_no_agree'];
1179
		$txt['registration_agreement'] = $txt['registration_privacy_policy'];
1180
		$context['page_title'] = $txt['registration_agreement'];
1181
1182
		// If you have to agree to the privacy policy, it needs to be fetched from the file.
1183
		$context['agreement'] = $policy->getParsedText();
1184
1185
		$context['show_coppa'] = false;
1186
		$context['skip_coppa'] = true;
1187
		$context['show_contact_button'] = !empty($modSettings['enable_contactform']) && $modSettings['enable_contactform'] === 'registration';
1188
1189
		createToken('register');
1190
	}
1191
}
1192