Yoshi2889 /
SMF2.1
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 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
|
|||
| 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
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 Loading history...
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 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
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 Loading history...
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 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 | ?> |
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.