Failed Conditions
Branch release-2.1 (4e22cf)
by Rick
07:22
created

CreatePost_Notify_Background::execute()   F

Complexity

Conditions 49
Paths > 20000

Size

Total Lines 202
Code Lines 117

Duplication

Lines 8
Ratio 3.96 %

Importance

Changes 0
Metric Value
cc 49
eloc 117
nc 70524
nop 0
dl 8
loc 202
rs 2
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
 * This file contains background notification code for any create post action
4
 *
5
 * Simple Machines Forum (SMF)
6
 *
7
 * @package SMF
8
 * @author Simple Machines http://www.simplemachines.org
9
 * @copyright 2017 Simple Machines and individual contributors
10
 * @license http://www.simplemachines.org/about/smf/license.php BSD
11
 *
12
 * @version 2.1 Beta 4
13
 */
14
15
/**
16
 * Class CreatePost_Notify_Background
17
 */
18
class CreatePost_Notify_Background extends SMF_BackgroundTask
0 ignored issues
show
Coding Style introduced by
This class is not in CamelCase format.

Classes in PHP are usually named in CamelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. The whole name starts with a capital letter as well.

Thus the name database provider becomes DatabaseProvider.

Loading history...
19
{
20
	/**
21
     * This handles notifications when a new post is created - new topic, reply, quotes and mentions.
22
	 * @return bool Always returns true
23
	 */
24
	public function execute()
25
	{
26
		global $smcFunc, $sourcedir, $scripturl, $language, $modSettings;
27
28
		require_once($sourcedir . '/Subs-Post.php');
29
		require_once($sourcedir . '/Mentions.php');
30
		require_once($sourcedir . '/Subs-Notify.php');
31
32
		$msgOptions = $this->_details['msgOptions'];
33
		$topicOptions = $this->_details['topicOptions'];
34
		$posterOptions = $this->_details['posterOptions'];
35
		$type = $this->_details['type'];
36
37
		$members = array();
38
		$quotedMembers = array();
39
		$done_members = array();
40
		$alert_rows = array();
41
42
		if ($type == 'reply' || $type == 'topic')
43
		{
44
			$quotedMembers = self::getQuotedMembers($msgOptions, $posterOptions);
45
			$members = array_keys($quotedMembers);
46
		}
47
48
		// Insert the post mentions
49
		if (!empty($msgOptions['mentioned_members']))
50
		{
51
			Mentions::insertMentions('msg', $msgOptions['id'], $msgOptions['mentioned_members'], $posterOptions['id']);
52
			$members = array_merge($members, array_keys($msgOptions['mentioned_members']));
53
		}
54
55
		// Find the people interested in receiving notifications for this topic
56
		$request = $smcFunc['db_query']('', '
57
			SELECT mem.id_member, ln.id_topic, ln.id_board, ln.sent, mem.email_address, b.member_groups,
58
				mem.id_group, mem.id_post_group, mem.additional_groups, t.id_member_started, mem.pm_ignore_list,
59
				t.id_member_updated
60
			FROM {db_prefix}log_notify AS ln
61
				INNER JOIN {db_prefix}members AS mem ON (ln.id_member = mem.id_member)
62
				LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = ln.id_topic)
63
				LEFT JOIN {db_prefix}boards AS b ON (b.id_board = ln.id_board OR b.id_board = t.id_board)
64
			WHERE ln.id_topic = {int:topic}
65
				OR ln.id_board = {int:board}',
66
			array(
67
				'topic' => $topicOptions['id'],
68
				'board' => $topicOptions['board'],
69
			)
70
		);
71
72
		$watched = array();
73
		while ($row = $smcFunc['db_fetch_assoc']($request))
74
		{
75
			$groups = array_merge(array($row['id_group'], $row['id_post_group']), (empty($row['additional_groups']) ? array() : explode(',', $row['additional_groups'])));
76
			if (!in_array(1, $groups) && count(array_intersect($groups, explode(',', $row['member_groups']))) == 0)
77
				continue;
78
79
			$members[] = $row['id_member'];
80
			$watched[$row['id_member']] = $row;
81
		}
82
83
		$smcFunc['db_free_result']($request);
84
85
		if (empty($members))
86
			return true;
87
88
		$members = array_unique($members);
89
		$prefs = getNotifyPrefs($members, '', true);
90
91
		// Do we have anyone to notify via mention? Handle them first and cross them off the list
92
		if (!empty($msgOptions['mentioned_members']))
93
		{
94
			$mentioned_members = Mentions::getMentionsByContent('msg', $msgOptions['id'], array_keys($msgOptions['mentioned_members']));
95
			self::handleMentionedNotifications($msgOptions, $mentioned_members, $prefs, $done_members, $alert_rows);
96
		}
97
98
		// Notify members which might've been quoted
99
		self::handleQuoteNotifications($msgOptions, $posterOptions, $quotedMembers, $prefs, $done_members, $alert_rows);
100
101
		// Handle rest of the notifications for watched topics and boards
102
		foreach ($watched as $member => $data)
103
		{
104
			$frequency = !empty($prefs[$member]['msg_notify_pref']) ? $prefs[$member]['msg_notify_pref'] : 1;
105
			$notify_types = !empty($prefs[$member]['msg_notify_type']) ? $prefs[$member]['msg_notify_type'] : 1;
106
107
			// Don't send a notification if the watching member ignored the member who made the action.
108
			if (!empty($data['pm_ignore_list']) && in_array($data['id_member_updated'], explode(',', $data['pm_ignore_list'])))
109
			    continue;
110
			if (!in_array($type, array('reply', 'topic')) && $notify_types == 2 && $member != $data['id_member_started'])
111
				continue;
112
			elseif (in_array($type, array('reply', 'topic')) && $member == $posterOptions['id'])
113
				continue;
114
			elseif (!in_array($type, array('reply', 'topic')) && $notify_types == 3)
115
				continue;
116
			elseif ($notify_types == 4)
117
				continue;
118
119
			if ($frequency > 2 || (!empty($frequency) && $data['sent']) || in_array($member, $done_members)
120
				|| (!empty($this->_details['members_only']) && !in_array($member, $this->_details['members_only'])))
121
				continue;
122
123
			// Watched topic?
124
			if (!empty($data['id_topic']) && $type != 'topic' && !empty($prefs[$member]))
125
			{
126
				$pref = !empty($prefs[$member]['topic_notify_' . $topicOptions['id']]) ? $prefs[$member]['topic_notify_' . $topicOptions['id']] : (!empty($prefs[$member]['topic_notify']) ? $prefs[$member]['topic_notify'] : 0);
127
				$message_type = 'notification_' . $type;
128
129
				if ($type == 'reply')
130
				{
131
					if (!empty($prefs[$member]['msg_receive_body']))
132
						$message_type .= '_body';
133
					if (!empty($frequency))
134
						$message_type .= '_once';
135
				}
136
137
				$content_type = 'topic';
138
			}
139
			// A new topic in a watched board then?
140
			elseif ($type == 'topic')
141
			{
142
				$pref = !empty($prefs[$member]['board_notify_' . $topicOptions['board']]) ? $prefs[$member]['board_notify_' . $topicOptions['board']] : (!empty($prefs[$member]['board_notify']) ? $prefs[$member]['board_notify'] : 0);
143
144
				$content_type = 'board';
145
146
				$message_type = !empty($frequency) ? 'notify_boards_once' : 'notify_boards';
147
				if (!empty($prefs[$member]['msg_receive_body']))
148
					$message_type .= '_body';
149
			}
150
			// If neither of the above, this might be a redundent row due to the OR clause in our SQL query, skip
151
			else
152
				continue;
153
154
			if ($pref & 0x02)
155
			{
156
				$replacements = array(
157
					'TOPICSUBJECT' => $msgOptions['subject'],
158
					'POSTERNAME' => un_htmlspecialchars($posterOptions['name']),
159
					'TOPICLINK' => $scripturl . '?topic=' . $topicOptions['id'] . '.new#new',
160
					'MESSAGE' => $msgOptions['body'],
161
					'UNSUBSCRIBELINK' => $scripturl . '?action=notifyboard;board=' . $topicOptions['board'] . '.0',
162
				);
163
164
				$emaildata = loadEmailTemplate($message_type, $replacements, empty($data['lngfile']) || empty($modSettings['userLanguage']) ? $language : $data['lngfile']);
165
				sendmail($data['email_address'], $emaildata['subject'], $emaildata['body'], null, 'm' . $topicOptions['id'], $emaildata['is_html']);
166
			}
167
168
			if ($pref & 0x01)
169
			{
170
				$alert_rows[] = array(
171
					'alert_time' => time(),
172
					'id_member' => $member,
173
					// Only tell sender's information for new topics and replies
174
					'id_member_started' => in_array($type, array('topic', 'reply')) ? $posterOptions['id'] : 0,
175
					'member_name' => in_array($type, array('topic', 'reply')) ? $posterOptions['name'] : '',
176
					'content_type' => $content_type,
177
					'content_id' => $topicOptions['id'],
178
					'content_action' => $type,
179
					'is_read' => 0,
180
					'extra' => $smcFunc['json_encode'](array(
181
						'topic' => $topicOptions['id'],
182
						'board' => $topicOptions['board'],
183
						'content_subject' => $msgOptions['subject'],
184
						'content_link' => $scripturl . '?topic=' . $topicOptions['id'] . '.new;topicseen#new',
185
					)),
186
				);
187
				updateMemberData($member, array('alerts' => '+'));
188
			}
189
190
			$smcFunc['db_query']('', '
191
				UPDATE {db_prefix}log_notify
192
				SET sent = {int:is_sent}
193
				WHERE (id_topic = {int:topic} OR id_board = {int:board})
194
					AND id_member = {int:member}',
195
				array(
196
					'topic' => $topicOptions['id'],
197
					'board' => $topicOptions['board'],
198
					'member' => $member,
199
					'is_sent' => 1,
200
				)
201
			);
202
		}
203
204
		// Insert it into the digest for daily/weekly notifications
205
		$smcFunc['db_insert']('',
206
			'{db_prefix}log_digest',
207
			array(
208
				'id_topic' => 'int', 'id_msg' => 'int', 'note_type' => 'string', 'exclude' => 'int',
209
			),
210
			array($topicOptions['id'], $msgOptions['id'], $type, $posterOptions['id']),
211
			array()
212
		);
213
214
		// Insert the alerts if any
215 View Code Duplication
		if (!empty($alert_rows))
216
			$smcFunc['db_insert']('',
217
				'{db_prefix}user_alerts',
218
				array('alert_time' => 'int', 'id_member' => 'int', 'id_member_started' => 'int', 'member_name' => 'string',
219
					'content_type' => 'string', 'content_id' => 'int', 'content_action' => 'string', 'is_read' => 'int', 'extra' => 'string'),
220
				$alert_rows,
221
				array()
222
			);
223
224
		return true;
225
	}
226
227
	protected static function handleQuoteNotifications($msgOptions, $posterOptions, $quotedMembers, $prefs, &$done_members, &$alert_rows)
0 ignored issues
show
Coding Style Naming introduced by
The parameter $done_members is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The parameter $alert_rows is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
228
	{
229
		global $smcFunc, $modSettings, $language, $scripturl;
230
231
		foreach ($quotedMembers as $id => $member)
232
		{
233
			if (!isset($prefs[$id]) || $id == $posterOptions['id'] || empty($prefs[$id]['msg_quote']))
234
				continue;
235
236
			$done_members[] = $id;
237
238 View Code Duplication
			if ($prefs[$id]['msg_quote'] & 0x02)
239
			{
240
				$replacements = array(
241
					'CONTENTSUBJECT' => $msgOptions['subject'],
242
					'QUOTENAME' => $posterOptions['name'],
243
					'MEMBERNAME' => $member['real_name'],
244
					'CONTENTLINK' => $scripturl . '?msg=' . $msgOptions['id'],
245
				);
246
247
				$emaildata = loadEmailTemplate('msg_quote', $replacements, empty($member['lngfile']) || empty($modSettings['userLanguage']) ? $language : $member['lngfile']);
248
				sendmail($member['email_address'], $emaildata['subject'], $emaildata['body'], null, 'msg_quote_' . $msgOptions['id'], $emaildata['is_html'], 2);
249
			}
250
251 View Code Duplication
			if ($prefs[$id]['msg_quote'] & 0x01)
252
			{
253
				$alert_rows[] = array(
254
					'alert_time' => time(),
255
					'id_member' => $member['id_member'],
256
					'id_member_started' => $posterOptions['id'],
257
					'member_name' => $posterOptions['name'],
258
					'content_type' => 'msg',
259
					'content_id' => $msgOptions['id'],
260
					'content_action' => 'quote',
261
					'is_read' => 0,
262
					'extra' => $smcFunc['json_encode'](array(
263
						'content_subject' => $msgOptions['subject'],
264
						'content_link' => $scripturl . '?msg=' . $msgOptions['id'],
265
					)),
266
				);
267
268
				updateMemberData($member['id_member'], array('alerts' => '+'));
269
			}
270
		}
271
	}
272
273
	protected static function getQuotedMembers($msgOptions, $posterOptions)
274
	{
275
		global $smcFunc;
276
277
		$blocks = preg_split('/(\[quote.*?\]|\[\/quote\])/i', $msgOptions['body'], -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
278
279
		$quote_level = 0;
280
		$message = '';
281
282
		foreach ($blocks as $block)
283
		{
284
			if (preg_match('/\[quote(.*)?\]/i', $block, $matches))
285
			{
286
				if ($quote_level == 0)
287
					$message .= '[quote' . $matches[1] . ']';
288
				$quote_level++;
289
			}
290
			elseif (preg_match('/\[\/quote\]/i', $block))
291
			{
292
				if ($quote_level <= 1)
293
					$message .= '[/quote]';
294
				if ($quote_level >= 1)
295
				{
296
					$quote_level--;
297
					$message .= "\n";
298
				}
299
			}
300
			elseif ($quote_level <= 1)
301
				$message .= $block;
302
		}
303
304
		preg_match_all('/\[quote.*?link=msg=([0-9]+).*?\]/i', $message, $matches);
305
306
		$id_msgs = $matches[1];
307
		foreach ($id_msgs as $k => $id_msg)
308
			$id_msgs[$k] = (int) $id_msg;
309
310
		if (empty($id_msgs))
311
			return array();
312
313
		// Get the messages
314
		$request = $smcFunc['db_query']('', '
315
			SELECT m.id_member, mem.email_address, mem.lngfile, mem.real_name
316
			FROM {db_prefix}messages AS m
317
				INNER JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)
318
			WHERE id_msg IN ({array_int:msgs})
319
			LIMIT {int:count}',
320
			array(
321
				'msgs' => array_unique($id_msgs),
322
				'count' => count(array_unique($id_msgs)),
323
			)
324
		);
325
326
		$members = array();
327 View Code Duplication
		while ($row = $smcFunc['db_fetch_assoc']($request))
328
		{
329
			if ($posterOptions['id'] == $row['id_member'])
330
				continue;
331
332
			$members[$row['id_member']] = $row;
333
		}
334
335
		return $members;
336
	}
337
338
	protected static function handleMentionedNotifications($msgOptions, $members, $prefs, &$done_members, &$alert_rows)
0 ignored issues
show
Coding Style Naming introduced by
The parameter $done_members is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The parameter $alert_rows is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
339
	{
340
		global $smcFunc, $scripturl, $language, $modSettings;
341
342
		foreach ($members as $id => $member)
343
		{
344
			if (!empty($prefs[$id]['msg_mention']))
345
				$done_members[] = $id;
346
			else
347
				continue;
348
349
			// Alerts' emails are always instant
350 View Code Duplication
			if ($prefs[$id]['msg_mention'] & 0x02)
351
			{
352
				$replacements = array(
353
					'CONTENTSUBJECT' => $msgOptions['subject'],
354
					'MENTIONNAME' => $member['mentioned_by']['name'],
355
					'MEMBERNAME' => $member['real_name'],
356
					'CONTENTLINK' => $scripturl . '?msg=' . $msgOptions['id'],
357
				);
358
359
				$emaildata = loadEmailTemplate('msg_mention', $replacements, empty($member['lngfile']) || empty($modSettings['userLanguage']) ? $language : $member['lngfile']);
360
				sendmail($member['email_address'], $emaildata['subject'], $emaildata['body'], null, 'msg_mention_' . $msgOptions['id'], $emaildata['is_html'], 2);
361
			}
362
363 View Code Duplication
			if ($prefs[$id]['msg_mention'] & 0x01)
364
			{
365
				$alert_rows[] = array(
366
					'alert_time' => time(),
367
					'id_member' => $member['id'],
368
					'id_member_started' => $member['mentioned_by']['id'],
369
					'member_name' => $member['mentioned_by']['name'],
370
					'content_type' => 'msg',
371
					'content_id' => $msgOptions['id'],
372
					'content_action' => 'mention',
373
					'is_read' => 0,
374
					'extra' => $smcFunc['json_encode'](array(
375
						'content_subject' => $msgOptions['subject'],
376
						'content_link' => $scripturl . '?msg=' . $msgOptions['id'],
377
					)),
378
				);
379
380
				updateMemberData($member['id'], array('alerts' => '+'));
381
			}
382
		}
383
	}
384
}
385
386
?>