Passed
Push — development ( 2d06b1...8e8389 )
by Spuds
01:13 queued 23s
created

About::handleCoppa()   A

Complexity

Conditions 5
Paths 16

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 11
nc 16
nop 0
dl 0
loc 16
rs 9.6111
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Handle credits, license, privacy policy?, cookie policy?, registration agreement?, contact
5
 * staff, COPPA contact
6
 *
7
 * @package   ElkArte Forum
8
 * @copyright ElkArte Forum contributors
9
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file)
10
 *
11
 * @version 2.0 dev
12
 *
13
 */
14
15
namespace ElkArte\Controller;
16
17
use ArrayObject;
18
use ElkArte\AbstractController;
19
use ElkArte\Action;
20
use ElkArte\Exceptions\Exception;
21
use ElkArte\Helper\DataValidator;
22
use ElkArte\Http\Headers;
23
use ElkArte\Languages\Txt;
24
25
/**
26
 * About Controller
27
 */
28
class About extends AbstractController
29
{
30
	private const STATUS_AWAITING_COPPA = 5;
31
32
	/**
33
	 * Default action of this class.
34
	 * Accessed with ?action=about
35
	 */
36
	public function action_index()
37
	{
38
		// Add an subaction array to act accordingly
39
		$subActions = [
40
			'credits' => [$this, 'action_credits'],
41
			'contact' => [$this, 'action_contact'],
42
			'coppa' => [$this, 'action_coppa'],
43
		];
44
45
		// Setup the action handler
46
		$action = new Action();
47
		$subAction = $action->initialize($subActions, 'credits');
48
49
		// Call the action
50
		$action->dispatch($subAction);
51
	}
52
53
	/**
54
	 * Shows the contact form for the user to fill out
55
	 *
56
	 * - Functionality needs to be enabled in the ACP for this to be used
57
	 * - Triggers the verify_contact event
58
	 */
59
	public function action_contact()
60
	{
61
		global $context, $txt, $modSettings;
62
63
		// Users have no need to use this, just send a PM
64
		// Disabled, you cannot enter.
65
		if ($this->user->is_guest === false || empty($modSettings['enable_contactform']) || $modSettings['enable_contactform'] === 'disabled')
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...
66
		{
67
			redirectexit();
68
		}
69
70
		Txt::load('Login');
71
		theme()->getTemplates()->load('Register');
72
73
		// Submitted the contact form?
74
		if (isset($this->_req->post->send))
75
		{
76
			checkSession();
77
			validateToken('contact');
78
79
			// Can't send a lot of these in a row, no sir!
80
			spamProtection('contact');
81
82
			// No errors, yet.
83
			$context['errors'] = [];
84
			Txt::load('Errors');
85
86
			// Could they get the right send topic verification code?
87
			require_once(SUBSDIR . '/Members.subs.php');
88
89
			// Form validation
90
			$validator = new DataValidator();
91
			$validator->sanitation_rules([
92
				'emailaddress' => 'trim',
93
				'contactmessage' => 'trim'
94
			]);
95
			$validator->validation_rules([
96
				'emailaddress' => 'required|valid_email',
97
				'contactmessage' => 'required'
98
			]);
99
			$validator->text_replacements([
100
				'emailaddress' => $txt['error_email'],
101
				'contactmessage' => $txt['error_message']
102
			]);
103
104
			// Any form errors
105
			if (!$validator->validate($this->_req->post))
106
			{
107
				$context['errors'] = $validator->validation_errors();
108
			}
109
110
			// Get the clean data
111
			$this->_req->post = new ArrayObject($validator->validation_data(), ArrayObject::ARRAY_AS_PROPS);
112
113
			// Trigger the verify contact event for captcha checks
114
			$this->_events->trigger('verify_contact', []);
115
116
			// No errors, then send the PM to the admins
117
			if (empty($context['errors']))
118
			{
119
				$admins = admins();
120
				if (!empty($admins))
121
				{
122
					require_once(SUBSDIR . '/PersonalMessage.subs.php');
123
					sendpm(['to' => array_keys($admins), 'bcc' => []], $txt['contact_subject'], $this->_req->post->contactmessage, false, ['id' => 0, 'name' => $this->_req->post->emailaddress, 'username' => $this->_req->post->emailaddress]);
124
				}
125
126
				// Send the PM
127
				redirectexit('action=about;sa=contact;done');
128
			}
129
			else
130
			{
131
				$context['emailaddress'] = $this->_req->post->emailaddress;
132
				$context['contactmessage'] = $this->_req->post->contactmessage;
133
			}
134
		}
135
136
		// Show the contact done form or the form itself
137
		if (isset($this->_req->query->done))
138
		{
139
			$context['sub_template'] = 'contact_form_done';
140
		}
141
		else
142
		{
143
			loadJavascriptFile('ext/mailcheck.min.js');
144
			$context['sub_template'] = 'contact_form';
145
			$context['page_title'] = $txt['admin_contact_form'];
146
147
			// Setup any contract form events, like validation
148
			$this->_events->trigger('setup_contact', []);
149
		}
150
151
		createToken('contact');
152
	}
153
154
	/**
155
	 * This function will display the contact information for the forum, as well a form to fill in.
156
	 *
157
	 * - Accessed by action=about;sa=coppa
158
	 */
159
	public function action_coppa()
160
	{
161
		global $context, $modSettings, $txt;
162
163
		Txt::load('Login');
164
		theme()->getTemplates()->load('About');
165
166
		// No User ID??
167
		if (!isset($this->_req->query->member))
168
		{
169
			throw new Exception('no_access', false);
170
		}
171
172
		// Get the user details...
173
		require_once(SUBSDIR . '/Members.subs.php');
174
		$member = getBasicMemberData((int) $this->_req->query->member, ['authentication' => true]);
175
176
		// If doesn't exist or not pending coppa
177
		if (empty($member) || (int) $member['is_activated'] !== self::STATUS_AWAITING_COPPA)
178
		{
179
			throw new Exception('no_access', false);
180
		}
181
182
		if (isset($this->_req->query->form))
183
		{
184
			$this->handleContactForm();
185
		}
186
		else
187
		{
188
			$this->handleCoppa();
189
		}
190
	}
191
192
	/**
193
	 * Handle the contact form for the forum.
194
	 *
195
	 * This method allows for the viewing or downloading of the COPPA form.
196
	 * Accessed by action=about;sa=coppa;form;dl;member= and action=about;sa=coppa;form;member=
197
	 *
198
	 * @return void
199
	 */
200
	private function handleContactForm()
201
	{
202
		global $context, $modSettings, $txt;
203
204
		// Some simple contact stuff for the forum.
205
		$context['forum_contacts'] = (empty($modSettings['coppaPost']) ? '' : $modSettings['coppaPost'] . '<br /><br />') . (empty($modSettings['coppaFax']) ? '' : $modSettings['coppaFax'] . '<br />');
206
		$context['forum_contacts'] = empty($context['forum_contacts']) ? '' : $context['forum_name_html_safe'] . '<br />' . $context['forum_contacts'];
207
208
		// Showing template?
209
		if (!isset($this->_req->query->dl))
210
		{
211
			// Shortcut for producing underlines.
212
			$context['ul'] = '<span class="underline">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>';
213
			theme()->getLayers()->removeAll();
214
			$context['sub_template'] = 'coppa_form';
215
			$context['page_title'] = replaceBasicActionUrl($txt['coppa_form_title']);
216
			$context['coppa_body'] = str_replace(['{PARENT_NAME}', '{CHILD_NAME}', '{USER_NAME}'], [$context['ul'], $context['ul'], $member['member_name']], replaceBasicActionUrl($txt['coppa_form_body']));
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $member seems to be never defined.
Loading history...
217
		}
218
		// Downloading.
219
		else
220
		{
221
			// Set up to output a file to the users browser
222
			while (ob_get_level() > 0)
223
			{
224
				@ob_end_clean();
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for ob_end_clean(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

224
				/** @scrutinizer ignore-unhandled */ @ob_end_clean();

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
225
			}
226
227
			// The data.
228
			$ul = '                ';
229
			$crlf = "\r\n";
230
			$data = $context['forum_contacts'] . $crlf . $txt['coppa_form_address'] . ':' . $crlf . $txt['coppa_form_date'] . ':' . $crlf . $crlf . $crlf . replaceBasicActionUrl($txt['coppa_form_body']);
231
			$data = str_replace(['{PARENT_NAME}', '{CHILD_NAME}', '{USER_NAME}', '<br />', '<br />'], [$ul, $ul, $member['member_name'], $crlf, $crlf], $data);
232
233
			// Send the headers.
234
			Headers::instance()
235
				->removeHeader('all')
236
				->header('Content-Encoding', 'none')
237
				->header('Pragma', 'no-cache')
238
				->header('Cache-Control', 'no-cache')
239
				->header('Connection', 'close')
240
				->header('Content-Disposition', 'attachment; filename="approval.txt"')
241
				->contentType('application/octet-stream', '')
242
				->sendHeaders();
243
244
			echo $data;
245
246
			obExit(false, false);
247
		}
248
	}
249
250
	/**
251
	 * Handle the Children's Online Privacy Protection Act (COPPA) for member registration.
252
	 *
253
	 * This method sets the necessary variables in the global $context for displaying the COPPA page.
254
	 *
255
	 * @return void
256
	 */
257
	private function handleCoppa()
258
	{
259
		global $context, $modSettings, $txt;
260
261
		$context += [
262
			'page_title' => $txt['coppa_title'],
263
			'sub_template' => 'coppa',
264
		];
265
266
		$context['coppa'] = [
267
			'body' => str_replace('{MINIMUM_AGE}', $modSettings['coppaAge'], replaceBasicActionUrl($txt['coppa_after_registration'])),
268
			'many_options' => !empty($modSettings['coppaPost']) && !empty($modSettings['coppaFax']),
269
			'post' => empty($modSettings['coppaPost']) ? '' : $modSettings['coppaPost'],
270
			'fax' => empty($modSettings['coppaFax']) ? '' : $modSettings['coppaFax'],
271
			'phone' => empty($modSettings['coppaPhone']) ? '' : str_replace('{PHONE_NUMBER}', $modSettings['coppaPhone'], $txt['coppa_send_by_phone']),
272
			'id' => $this->_req->query->member,
273
		];
274
	}
275
276
	/**
277
	 * It prepares credit and copyright information for the credits page or the admin page.
278
	 *
279
	 * - Accessed by ?action=who;sa=credits
280
	 *
281
	 * @uses Who language file
282
	 * @uses template_credits() sub template in Who.template,
283
	 */
284
	public function action_credits()
285
	{
286
		global $context, $txt;
287
288
		require_once(SUBSDIR . '/About.subs.php');
289
		Txt::load('About');
290
291
		$context += prepareCreditsData();
292
293
		theme()->getTemplates()->load('About');
294
		$context['sub_template'] = 'credits';
295
		$context['robot_no_index'] = true;
296
		$context['page_title'] = $txt['credits'];
297
	}
298
}