Passed
Pull Request — development (#3834)
by Spuds
08:39
created

Report::_validateRequest()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 17
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 7
nc 3
nop 0
dl 0
loc 17
rs 10
c 1
b 0
f 0
1
<?php
2
3
/**
4
 * This file deals with the report actions related to personal messages.
5
 *
6
 * @package   ElkArte Forum
7
 * @copyright ElkArte Forum contributors
8
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file)
9
 *
10
 * @version 2.0 Beta 1
11
 *
12
 */
13
14
namespace ElkArte\PersonalMessage;
15
16
use ElkArte\AbstractController;
17
use ElkArte\Exceptions\Exception;
18
use ElkArte\Helper\Util;
19
use ElkArte\Languages\Loader;
20
21
/**
22
 * Class Report
23
 * It allows reporting personal messages
24
 *
25
 * @package ElkArte\PersonalMessage
26
 */
27
class Report extends AbstractController
28
{
29
	/**
30
	 * Default action for the class
31
	 */
32
	public function action_index()
33
	{
34
		$this->action_report();
35
	}
36
37
	/**
38
	 * Allows the user to report a personal message to an administrator.
39
	 *
40
	 * What it does:
41
	 *
42
	 * - In the first instance requires that the ID of the message to report is passed through $_GET.
43
	 * - It allows the user to report to either a particular administrator - or the whole admin team.
44
	 * - It will forward on a copy of the original message without allowing the reporter to make changes.
45
	 *
46
	 * @uses report_message sub-template.
47
	 */
48
	public function action_report(): void
49
	{
50
		global $txt, $context;
51
52
		// Check that this feature is even enabled and we have a PM!
53
		$pmsg = $this->_validateRequest();
54
55
		$context['pm_id'] = $pmsg;
56
		$context['page_title'] = $txt['pm_report_title'];
57
		$context['sub_template'] = 'report_message';
58
59
		// If we're here, just send the user to the template, with a few useful context bits.
60
		if ($this->_req->hasPost('report'))
61
		{
62
			// Check the session before proceeding any further!
63
			checkSession();
64
65
			$reason = $this->_getReportReason();
66
67
			// First, load up the message they want to file a complaint against and verify it actually went to them!
68
			$pmData = $this->_loadReportedMessage($pmsg);
69
70
			// Record this report for the admins to see.
71
			$this->_recordReport($pmsg, $pmData, $reason);
72
73
			// Notify the admins that there is a report.
74
			$this->_sendReports($pmData, $reason);
75
76
			// Leave them with a template.
77
			$context['sub_template'] = 'report_message_complete';
78
		}
79
	}
80
81
	/**
82
	 * Check that this feature is even enabled and we have a valid PM!
83
	 *
84
	 * @return int
85
	 * @throws Exception
86
	 */
87
	protected function _validateRequest(): int
88
	{
89
		global $modSettings;
90
91
		$pmsg = $this->_req->getPost('pmsg', 'intval', $this->_req->getQuery('pmsg', 'intval', 0));
92
93
		if (empty($modSettings['enableReportPM']) || empty($pmsg))
94
		{
95
			throw new Exception('no_access', false);
96
		}
97
98
		if (!isAccessiblePM($pmsg, 'inbox'))
99
		{
100
			throw new Exception('no_access', false);
101
		}
102
103
		return $pmsg;
104
	}
105
106
	/**
107
	 * Get and validate the report reason.
108
	 *
109
	 * @return string
110
	 * @throws Exception
111
	 */
112
	protected function _getReportReason(): string
113
	{
114
		$reason = $this->_req->getPost('reason', 'trim|strval', '');
115
		$poster_comment = strtr(Util::htmlspecialchars($reason), ["\r" => '', "\t" => '']);
116
117
		if (Util::strlen($poster_comment) > 254)
118
		{
119
			throw new Exception('post_too_long', false);
120
		}
121
122
		return $poster_comment;
123
	}
124
125
	/**
126
	 * Load the message they want to file a complaint against.
127
	 *
128
	 * @param int $pmsg
129
	 * @return array
130
	 */
131
	protected function _loadReportedMessage(int $pmsg): array
132
	{
133
		[$subject, $body, $time, $memberFromID, $memberFromName, $poster_name, $time_message] = loadPersonalMessage($pmsg);
134
135
		return [
136
			'id_pm' => $pmsg,
137
			'subject' => $subject,
138
			'body' => $body,
139
			'time' => $time,
140
			'memberFromID' => $memberFromID,
141
			'memberFromName' => $memberFromName,
142
			'poster_name' => $poster_name,
143
			'time_message' => $time_message,
144
		];
145
	}
146
147
	/**
148
	 * Record the report for the admins.
149
	 *
150
	 * @param int $pmsg
151
	 * @param array $pmData
152
	 * @param string $comment
153
	 */
154
	protected function _recordReport(int $pmsg, array $pmData, string $comment): void
155
	{
156
		require_once(SUBSDIR . '/Messages.subs.php');
157
158
		recordReport([
159
			'id_msg' => $pmsg,
160
			'id_topic' => 0,
161
			'id_board' => 0,
162
			'type' => 'pm',
163
			'id_poster' => $pmData['memberFromID'],
164
			'real_name' => $pmData['memberFromName'],
165
			'poster_name' => $pmData['poster_name'],
166
			'subject' => $pmData['subject'],
167
			'body' => $pmData['body'],
168
			'time_message' => $pmData['time_message'],
169
		], $comment);
170
	}
171
172
	/**
173
	 * Send the reports to the admins.
174
	 *
175
	 * @param array $pmData
176
	 * @param string $reason
177
	 */
178
	protected function _sendReports(array $pmData, string $reason): void
179
	{
180
		global $language, $modSettings;
181
182
		// Remove the line breaks...
183
		$body = preg_replace('~<br ?/?>~i', "\n", $pmData['body']);
184
185
		$recipients = $this->_getPMRecipients($pmData['id_pm'] ?? (int) $this->_req->getPost('pmsg', 'intval', $this->_req->getQuery('pmsg', 'intval', 0)));
186
187
		// Now let's get out and loop through the admins.
188
		$admins = admins($this->_req->getPost('id_admin', 'intval', 0));
189
190
		// Maybe we shouldn't advertise this?
191
		if (empty($admins))
192
		{
193
			throw new Exception('no_access', false);
194
		}
195
196
		$memberFromName = un_htmlspecialchars($pmData['memberFromName']);
197
198
		// Prepare the message storage array.
199
		$messagesToSend = [];
200
201
		// Loop through each admin and add them to the right language pile...
202
		foreach ($admins as $id_admin => $admin_info)
203
		{
204
			// Need to send in the correct language!
205
			$cur_language = empty($admin_info['lngfile']) || empty($modSettings['userLanguage']) ? $language : $admin_info['lngfile'];
206
207
			if (!isset($messagesToSend[$cur_language]))
208
			{
209
				$mtxt = [];
210
				$lang = new Loader($cur_language, $mtxt, database());
211
				$lang->load('PersonalMessage', false);
212
213
				// Make the body.
214
				$report_body = str_replace(['{REPORTER}', '{SENDER}'], [un_htmlspecialchars($this->user->name), $memberFromName], $mtxt['pm_report_pm_user_sent']);
0 ignored issues
show
Bug Best Practice introduced by
The property name does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
215
				$report_body .= "\n" . '[b]' . $reason . '[/b]' . "\n\n";
216
				if (!empty($recipients))
217
				{
218
					$report_body .= $mtxt['pm_report_pm_other_recipients'] . ' ' . implode(', ', $recipients) . "\n\n";
219
				}
220
221
				$report_body .= $mtxt['pm_report_pm_unedited_below'] . "\n" . '[quote author=' . (empty($pmData['memberFromID']) ? '&quot;' . $memberFromName . '&quot;' : $memberFromName . ' link=action=profile;u=' . $pmData['memberFromID'] . ' date=' . $pmData['time']) . ']' . "\n" . un_htmlspecialchars($body) . '[/quote]';
222
223
				// Plonk it in the array ;)
224
				$messagesToSend[$cur_language] = [
225
					'subject' => (Util::strpos($pmData['subject'], $mtxt['pm_report_pm_subject']) === false ? $mtxt['pm_report_pm_subject'] : '') . un_htmlspecialchars($pmData['subject']),
226
					'body' => $report_body,
227
					'recipients' => [
228
						'to' => [],
229
						'bcc' => []
230
					],
231
				];
232
			}
233
234
			// Add them to the list.
235
			$messagesToSend[$cur_language]['recipients']['to'][$id_admin] = $id_admin;
236
		}
237
238
		// Send a different email for each language.
239
		foreach ($messagesToSend as $message)
240
		{
241
			sendpm($message['recipients'], $message['subject'], $message['body']);
242
		}
243
	}
244
245
	/**
246
	 * Get the list of recipients for the PM.
247
	 *
248
	 * @param int $pmsg
249
	 * @return array
250
	 */
251
	protected function _getPMRecipients(int $pmsg): array
252
	{
253
		$recipients = [];
254
		$temp = loadPMRecipientsAll($pmsg, true);
255
		foreach ($temp as $recipient)
256
		{
257
			$recipients[] = $recipient['link'];
258
		}
259
260
		return $recipients;
261
	}
262
}
263