[ Index ] |
PHP Cross Reference of phpBB-3.3.14-deutsch |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * 4 * This file is part of the phpBB Forum Software package. 5 * 6 * @copyright (c) phpBB Limited <https://www.phpbb.com> 7 * @license GNU General Public License, version 2 (GPL-2.0) 8 * 9 * For full copyright and license information, please see 10 * the docs/CREDITS.txt file. 11 * 12 */ 13 14 /** 15 */ 16 if (!defined('IN_PHPBB')) 17 { 18 exit; 19 } 20 21 /* 22 Ability to simply add own rules by doing three things: 23 1) Add an appropriate constant 24 2) Add a new check array to the global_privmsgs_rules variable and the condition array (if one is required) 25 3) Implement the rule logic in the check_rule() function 26 4) Add a new language variable to ucp.php 27 28 The user is then able to select the new rule. It will be checked against and handled as specified. 29 To add new actions (yes, checks can be added here too) to the rule management, the core code has to be modified. 30 */ 31 32 define('RULE_IS_LIKE', 1); // Is Like 33 define('RULE_IS_NOT_LIKE', 2); // Is Not Like 34 define('RULE_IS', 3); // Is 35 define('RULE_IS_NOT', 4); // Is Not 36 define('RULE_BEGINS_WITH', 5); // Begins with 37 define('RULE_ENDS_WITH', 6); // Ends with 38 define('RULE_IS_FRIEND', 7); // Is Friend 39 define('RULE_IS_FOE', 8); // Is Foe 40 define('RULE_IS_USER', 9); // Is User 41 define('RULE_IS_GROUP', 10); // Is In Usergroup 42 define('RULE_ANSWERED', 11); // Answered 43 define('RULE_FORWARDED', 12); // Forwarded 44 define('RULE_TO_GROUP', 14); // Usergroup 45 define('RULE_TO_ME', 15); // Me 46 47 define('ACTION_PLACE_INTO_FOLDER', 1); 48 define('ACTION_MARK_AS_READ', 2); 49 define('ACTION_MARK_AS_IMPORTANT', 3); 50 define('ACTION_DELETE_MESSAGE', 4); 51 52 define('CHECK_SUBJECT', 1); 53 define('CHECK_SENDER', 2); 54 define('CHECK_MESSAGE', 3); 55 define('CHECK_STATUS', 4); 56 define('CHECK_TO', 5); 57 58 /** 59 * Global private message rules 60 * These rules define what to do if a rule is hit 61 */ 62 $global_privmsgs_rules = array( 63 CHECK_SUBJECT => array( 64 RULE_IS_LIKE => array('check0' => 'message_subject'), 65 RULE_IS_NOT_LIKE => array('check0' => 'message_subject'), 66 RULE_IS => array('check0' => 'message_subject'), 67 RULE_IS_NOT => array('check0' => 'message_subject'), 68 RULE_BEGINS_WITH => array('check0' => 'message_subject'), 69 RULE_ENDS_WITH => array('check0' => 'message_subject'), 70 ), 71 72 CHECK_SENDER => array( 73 RULE_IS_LIKE => array('check0' => 'username'), 74 RULE_IS_NOT_LIKE => array('check0' => 'username'), 75 RULE_IS => array('check0' => 'username'), 76 RULE_IS_NOT => array('check0' => 'username'), 77 RULE_BEGINS_WITH => array('check0' => 'username'), 78 RULE_ENDS_WITH => array('check0' => 'username'), 79 RULE_IS_FRIEND => array('check0' => 'friend'), 80 RULE_IS_FOE => array('check0' => 'foe'), 81 RULE_IS_USER => array('check0' => 'author_id'), 82 RULE_IS_GROUP => array('check0' => 'author_in_group'), 83 ), 84 85 CHECK_MESSAGE => array( 86 RULE_IS_LIKE => array('check0' => 'message_text'), 87 RULE_IS_NOT_LIKE => array('check0' => 'message_text'), 88 RULE_IS => array('check0' => 'message_text'), 89 RULE_IS_NOT => array('check0' => 'message_text'), 90 ), 91 92 CHECK_STATUS => array( 93 RULE_ANSWERED => array('check0' => 'pm_replied'), 94 RULE_FORWARDED => array('check0' => 'pm_forwarded'), 95 ), 96 97 CHECK_TO => array( 98 RULE_TO_GROUP => array('check0' => 'to', 'check1' => 'bcc', 'check2' => 'user_in_group'), 99 RULE_TO_ME => array('check0' => 'to', 'check1' => 'bcc'), 100 ) 101 ); 102 103 /** 104 * This is for defining which condition fields to show for which Rule 105 */ 106 $global_rule_conditions = array( 107 RULE_IS_LIKE => 'text', 108 RULE_IS_NOT_LIKE => 'text', 109 RULE_IS => 'text', 110 RULE_IS_NOT => 'text', 111 RULE_BEGINS_WITH => 'text', 112 RULE_ENDS_WITH => 'text', 113 RULE_IS_USER => 'user', 114 RULE_IS_GROUP => 'group' 115 ); 116 117 /** 118 * Get all folder 119 */ 120 function get_folder($user_id, $folder_id = false) 121 { 122 global $db, $user, $template; 123 global $phpbb_root_path, $phpEx; 124 125 $folder = array(); 126 127 // Get folder information 128 $sql = 'SELECT folder_id, COUNT(msg_id) as num_messages, SUM(pm_unread) as num_unread 129 FROM ' . PRIVMSGS_TO_TABLE . " 130 WHERE user_id = $user_id 131 AND folder_id <> " . PRIVMSGS_NO_BOX . ' 132 GROUP BY folder_id'; 133 $result = $db->sql_query($sql); 134 135 $num_messages = $num_unread = array(); 136 while ($row = $db->sql_fetchrow($result)) 137 { 138 $num_messages[(int) $row['folder_id']] = $row['num_messages']; 139 $num_unread[(int) $row['folder_id']] = $row['num_unread']; 140 } 141 $db->sql_freeresult($result); 142 143 // Make sure the default boxes are defined 144 $available_folder = array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX); 145 146 foreach ($available_folder as $default_folder) 147 { 148 if (!isset($num_messages[$default_folder])) 149 { 150 $num_messages[$default_folder] = 0; 151 } 152 153 if (!isset($num_unread[$default_folder])) 154 { 155 $num_unread[$default_folder] = 0; 156 } 157 } 158 159 // Adjust unread status for outbox 160 $num_unread[PRIVMSGS_OUTBOX] = $num_messages[PRIVMSGS_OUTBOX]; 161 162 $folder[PRIVMSGS_INBOX] = array( 163 'folder_name' => $user->lang['PM_INBOX'], 164 'num_messages' => $num_messages[PRIVMSGS_INBOX], 165 'unread_messages' => $num_unread[PRIVMSGS_INBOX] 166 ); 167 168 // Custom Folder 169 $sql = 'SELECT folder_id, folder_name, pm_count 170 FROM ' . PRIVMSGS_FOLDER_TABLE . " 171 WHERE user_id = $user_id"; 172 $result = $db->sql_query($sql); 173 174 while ($row = $db->sql_fetchrow($result)) 175 { 176 $folder[$row['folder_id']] = array( 177 'folder_name' => $row['folder_name'], 178 'num_messages' => $row['pm_count'], 179 'unread_messages' => ((isset($num_unread[$row['folder_id']])) ? $num_unread[$row['folder_id']] : 0) 180 ); 181 } 182 $db->sql_freeresult($result); 183 184 $folder[PRIVMSGS_OUTBOX] = array( 185 'folder_name' => $user->lang['PM_OUTBOX'], 186 'num_messages' => $num_messages[PRIVMSGS_OUTBOX], 187 'unread_messages' => $num_unread[PRIVMSGS_OUTBOX] 188 ); 189 190 $folder[PRIVMSGS_SENTBOX] = array( 191 'folder_name' => $user->lang['PM_SENTBOX'], 192 'num_messages' => $num_messages[PRIVMSGS_SENTBOX], 193 'unread_messages' => $num_unread[PRIVMSGS_SENTBOX] 194 ); 195 196 // Define Folder Array for template designers (and for making custom folders usable by the template too) 197 foreach ($folder as $f_id => $folder_ary) 198 { 199 $folder_id_name = ($f_id == PRIVMSGS_INBOX) ? 'inbox' : (($f_id == PRIVMSGS_OUTBOX) ? 'outbox' : 'sentbox'); 200 201 $template->assign_block_vars('folder', array( 202 'FOLDER_ID' => $f_id, 203 'FOLDER_NAME' => $folder_ary['folder_name'], 204 'NUM_MESSAGES' => $folder_ary['num_messages'], 205 'UNREAD_MESSAGES' => $folder_ary['unread_messages'], 206 207 'U_FOLDER' => ($f_id > 0) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=' . $f_id) : append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=' . $folder_id_name), 208 209 'S_CUR_FOLDER' => ($f_id === $folder_id) ? true : false, 210 'S_UNREAD_MESSAGES' => ($folder_ary['unread_messages']) ? true : false, 211 'S_CUSTOM_FOLDER' => ($f_id > 0) ? true : false) 212 ); 213 } 214 215 if ($folder_id !== false && $folder_id !== PRIVMSGS_HOLD_BOX && !isset($folder[$folder_id])) 216 { 217 trigger_error('UNKNOWN_FOLDER'); 218 } 219 220 return $folder; 221 } 222 223 /** 224 * Delete Messages From Sentbox 225 * we are doing this here because this saves us a bunch of checks and queries 226 */ 227 function clean_sentbox($num_sentbox_messages) 228 { 229 global $db, $user; 230 231 // Check Message Limit 232 if ($user->data['message_limit'] && $num_sentbox_messages > $user->data['message_limit']) 233 { 234 // Delete old messages 235 $sql = 'SELECT t.msg_id 236 FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p 237 WHERE t.msg_id = p.msg_id 238 AND t.user_id = ' . $user->data['user_id'] . ' 239 AND t.folder_id = ' . PRIVMSGS_SENTBOX . ' 240 ORDER BY p.message_time ASC'; 241 $result = $db->sql_query_limit($sql, ($num_sentbox_messages - $user->data['message_limit'])); 242 243 $delete_ids = array(); 244 while ($row = $db->sql_fetchrow($result)) 245 { 246 $delete_ids[] = $row['msg_id']; 247 } 248 $db->sql_freeresult($result); 249 delete_pm($user->data['user_id'], $delete_ids, PRIVMSGS_SENTBOX); 250 } 251 } 252 253 /** 254 * Check Rule against Message Information 255 */ 256 function check_rule(&$rules, &$rule_row, &$message_row, $user_id) 257 { 258 if (!isset($rules[$rule_row['rule_check']][$rule_row['rule_connection']])) 259 { 260 return false; 261 } 262 263 $check_ary = $rules[$rule_row['rule_check']][$rule_row['rule_connection']]; 264 265 $result = false; 266 267 $check0 = $message_row[$check_ary['check0']]; 268 269 switch ($rule_row['rule_connection']) 270 { 271 case RULE_IS_LIKE: 272 $result = preg_match("/" . preg_quote($rule_row['rule_string'], '/') . '/i', $check0); 273 break; 274 275 case RULE_IS_NOT_LIKE: 276 $result = !preg_match("/" . preg_quote($rule_row['rule_string'], '/') . '/i', $check0); 277 break; 278 279 case RULE_IS: 280 $result = ($check0 == $rule_row['rule_string']); 281 break; 282 283 case RULE_IS_NOT: 284 $result = ($check0 != $rule_row['rule_string']); 285 break; 286 287 case RULE_BEGINS_WITH: 288 $result = preg_match("/^" . preg_quote($rule_row['rule_string'], '/') . '/i', $check0); 289 break; 290 291 case RULE_ENDS_WITH: 292 $result = preg_match("/" . preg_quote($rule_row['rule_string'], '/') . '$/i', $check0); 293 break; 294 295 case RULE_IS_FRIEND: 296 case RULE_IS_FOE: 297 case RULE_ANSWERED: 298 case RULE_FORWARDED: 299 $result = ($check0 == 1); 300 break; 301 302 case RULE_IS_USER: 303 $result = ($check0 == $rule_row['rule_user_id']); 304 break; 305 306 case RULE_IS_GROUP: 307 $result = in_array($rule_row['rule_group_id'], $check0); 308 break; 309 310 case RULE_TO_GROUP: 311 $result = (in_array('g_' . $message_row[$check_ary['check2']], $check0) || in_array('g_' . $message_row[$check_ary['check2']], $message_row[$check_ary['check1']])); 312 break; 313 314 case RULE_TO_ME: 315 $result = (in_array('u_' . $user_id, $check0) || in_array('u_' . $user_id, $message_row[$check_ary['check1']])); 316 break; 317 } 318 319 if (!$result) 320 { 321 return false; 322 } 323 324 switch ($rule_row['rule_action']) 325 { 326 case ACTION_PLACE_INTO_FOLDER: 327 return array('action' => $rule_row['rule_action'], 'folder_id' => $rule_row['rule_folder_id']); 328 break; 329 330 case ACTION_MARK_AS_READ: 331 case ACTION_MARK_AS_IMPORTANT: 332 return array('action' => $rule_row['rule_action'], 'pm_unread' => $message_row['pm_unread'], 'pm_marked' => $message_row['pm_marked']); 333 break; 334 335 case ACTION_DELETE_MESSAGE: 336 global $db; 337 338 // Check for admins/mods - users are not allowed to remove those messages... 339 // We do the check here to make sure the data we use is consistent 340 $sql = 'SELECT user_id, user_type, user_permissions 341 FROM ' . USERS_TABLE . ' 342 WHERE user_id = ' . (int) $message_row['author_id']; 343 $result = $db->sql_query($sql); 344 $userdata = $db->sql_fetchrow($result); 345 $db->sql_freeresult($result); 346 347 $auth2 = new \phpbb\auth\auth(); 348 $auth2->acl($userdata); 349 350 if (!$auth2->acl_get('a_') && !$auth2->acl_get('m_') && !$auth2->acl_getf_global('m_')) 351 { 352 return array('action' => $rule_row['rule_action'], 'pm_unread' => $message_row['pm_unread'], 'pm_marked' => $message_row['pm_marked']); 353 } 354 355 return false; 356 break; 357 358 default: 359 return false; 360 } 361 362 return false; 363 } 364 365 /** 366 * Update user PM count 367 */ 368 function update_pm_counts() 369 { 370 global $user, $db; 371 372 // Update unread count 373 $sql = 'SELECT COUNT(msg_id) as num_messages 374 FROM ' . PRIVMSGS_TO_TABLE . ' 375 WHERE pm_unread = 1 376 AND folder_id <> ' . PRIVMSGS_OUTBOX . ' 377 AND user_id = ' . $user->data['user_id']; 378 $result = $db->sql_query($sql); 379 $user->data['user_unread_privmsg'] = (int) $db->sql_fetchfield('num_messages'); 380 $db->sql_freeresult($result); 381 382 // Update new pm count 383 $sql = 'SELECT COUNT(msg_id) as num_messages 384 FROM ' . PRIVMSGS_TO_TABLE . ' 385 WHERE pm_new = 1 386 AND folder_id IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ') 387 AND user_id = ' . $user->data['user_id']; 388 $result = $db->sql_query($sql); 389 $user->data['user_new_privmsg'] = (int) $db->sql_fetchfield('num_messages'); 390 $db->sql_freeresult($result); 391 392 $db->sql_query('UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array( 393 'user_unread_privmsg' => (int) $user->data['user_unread_privmsg'], 394 'user_new_privmsg' => (int) $user->data['user_new_privmsg'], 395 )) . ' WHERE user_id = ' . $user->data['user_id']); 396 397 // Ok, here we need to repair something, other boxes than privmsgs_no_box and privmsgs_hold_box should not carry the pm_new flag. 398 if (!$user->data['user_new_privmsg']) 399 { 400 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' 401 SET pm_new = 0 402 WHERE pm_new = 1 403 AND folder_id NOT IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ') 404 AND user_id = ' . $user->data['user_id']; 405 $db->sql_query($sql); 406 } 407 } 408 409 /** 410 * Place new messages into appropriate folder 411 */ 412 function place_pm_into_folder(&$global_privmsgs_rules, $release = false) 413 { 414 global $db, $user, $config; 415 416 if (!$user->data['user_new_privmsg']) 417 { 418 return array('not_moved' => 0, 'removed' => 0); 419 } 420 421 $user_message_rules = (int) $user->data['user_message_rules']; 422 $user_id = (int) $user->data['user_id']; 423 424 $action_ary = $move_into_folder = array(); 425 $num_removed = 0; 426 427 // Newly processing on-hold messages 428 if ($release) 429 { 430 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' 431 SET folder_id = ' . PRIVMSGS_NO_BOX . ' 432 WHERE folder_id = ' . PRIVMSGS_HOLD_BOX . " 433 AND user_id = $user_id"; 434 $db->sql_query($sql); 435 } 436 437 // Get those messages not yet placed into any box 438 $retrieve_sql = 'SELECT t.*, p.*, u.username, u.user_id, u.group_id 439 FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p, ' . USERS_TABLE . " u 440 WHERE t.user_id = $user_id 441 AND p.author_id = u.user_id 442 AND t.folder_id = " . PRIVMSGS_NO_BOX . ' 443 AND t.msg_id = p.msg_id'; 444 445 // Just place into the appropriate arrays if no rules need to be checked 446 if (!$user_message_rules) 447 { 448 $result = $db->sql_query($retrieve_sql); 449 450 while ($row = $db->sql_fetchrow($result)) 451 { 452 $action_ary[$row['msg_id']][] = array('action' => false); 453 } 454 $db->sql_freeresult($result); 455 } 456 else 457 { 458 $user_rules = $zebra = $check_rows = array(); 459 $user_ids = $memberships = array(); 460 461 // First of all, grab all rules and retrieve friends/foes 462 $sql = 'SELECT * 463 FROM ' . PRIVMSGS_RULES_TABLE . " 464 WHERE user_id = $user_id"; 465 $result = $db->sql_query($sql); 466 $user_rules = $db->sql_fetchrowset($result); 467 $db->sql_freeresult($result); 468 469 if (count($user_rules)) 470 { 471 $sql = 'SELECT zebra_id, friend, foe 472 FROM ' . ZEBRA_TABLE . " 473 WHERE user_id = $user_id"; 474 $result = $db->sql_query($sql); 475 476 while ($row = $db->sql_fetchrow($result)) 477 { 478 $zebra[$row['zebra_id']] = $row; 479 } 480 $db->sql_freeresult($result); 481 } 482 483 // Now build a bare-bone check_row array 484 $result = $db->sql_query($retrieve_sql); 485 486 while ($row = $db->sql_fetchrow($result)) 487 { 488 $check_rows[] = array_merge($row, array( 489 'to' => explode(':', $row['to_address']), 490 'bcc' => explode(':', $row['bcc_address']), 491 'friend' => (isset($zebra[$row['author_id']])) ? $zebra[$row['author_id']]['friend'] : 0, 492 'foe' => (isset($zebra[$row['author_id']])) ? $zebra[$row['author_id']]['foe'] : 0, 493 'user_in_group' => $user->data['group_id'], 494 'author_in_group' => array()) 495 ); 496 497 $user_ids[] = $row['user_id']; 498 } 499 $db->sql_freeresult($result); 500 501 // Retrieve user memberships 502 if (count($user_ids)) 503 { 504 $sql = 'SELECT * 505 FROM ' . USER_GROUP_TABLE . ' 506 WHERE ' . $db->sql_in_set('user_id', $user_ids) . ' 507 AND user_pending = 0'; 508 $result = $db->sql_query($sql); 509 510 while ($row = $db->sql_fetchrow($result)) 511 { 512 $memberships[$row['user_id']][] = $row['group_id']; 513 } 514 $db->sql_freeresult($result); 515 } 516 517 // Now place into the appropriate folder 518 foreach ($check_rows as $row) 519 { 520 // Add membership if set 521 if (isset($memberships[$row['author_id']])) 522 { 523 $row['author_in_group'] = $memberships[$row['user_id']]; 524 } 525 526 // Check Rule - this should be very quick since we have all information we need 527 $is_match = false; 528 foreach ($user_rules as $rule_row) 529 { 530 if (($action = check_rule($global_privmsgs_rules, $rule_row, $row, $user_id)) !== false) 531 { 532 $is_match = true; 533 $action_ary[$row['msg_id']][] = $action; 534 } 535 } 536 537 if (!$is_match) 538 { 539 $action_ary[$row['msg_id']][] = array('action' => false); 540 } 541 } 542 543 unset($user_rules, $zebra, $check_rows, $user_ids, $memberships); 544 } 545 546 // We place actions into arrays, to save queries. 547 $unread_ids = $delete_ids = $important_ids = array(); 548 549 foreach ($action_ary as $msg_id => $msg_ary) 550 { 551 // It is allowed to execute actions more than once, except placing messages into folder 552 $folder_action = $message_removed = false; 553 554 foreach ($msg_ary as $pos => $rule_ary) 555 { 556 if ($folder_action && $rule_ary['action'] == ACTION_PLACE_INTO_FOLDER) 557 { 558 continue; 559 } 560 561 switch ($rule_ary['action']) 562 { 563 case ACTION_PLACE_INTO_FOLDER: 564 // Folder actions have precedence, so we will remove any other ones 565 $folder_action = true; 566 $move_into_folder[(int) $rule_ary['folder_id']][] = $msg_id; 567 break; 568 569 case ACTION_MARK_AS_READ: 570 if ($rule_ary['pm_unread']) 571 { 572 $unread_ids[] = $msg_id; 573 } 574 break; 575 576 case ACTION_DELETE_MESSAGE: 577 $delete_ids[] = $msg_id; 578 $message_removed = true; 579 break; 580 581 case ACTION_MARK_AS_IMPORTANT: 582 if (!$rule_ary['pm_marked']) 583 { 584 $important_ids[] = $msg_id; 585 } 586 break; 587 } 588 } 589 590 // We place this here because it could happen that the messages are doubled if a rule marks a message and then moves it into a specific 591 // folder. Here we simply move the message into the INBOX if it gets not removed and also not put into a custom folder. 592 if (!$folder_action && !$message_removed) 593 { 594 $move_into_folder[PRIVMSGS_INBOX][] = $msg_id; 595 } 596 } 597 598 // Do not change the order of processing 599 // The number of queries needed to be executed here highly depends on the defined rules and are 600 // only gone through if new messages arrive. 601 602 // Delete messages 603 if (count($delete_ids)) 604 { 605 $num_removed += count($delete_ids); 606 delete_pm($user_id, $delete_ids, PRIVMSGS_NO_BOX); 607 } 608 609 // Set messages to Unread 610 if (count($unread_ids)) 611 { 612 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' 613 SET pm_unread = 0 614 WHERE ' . $db->sql_in_set('msg_id', $unread_ids) . " 615 AND user_id = $user_id 616 AND folder_id = " . PRIVMSGS_NO_BOX; 617 $db->sql_query($sql); 618 } 619 620 // mark messages as important 621 if (count($important_ids)) 622 { 623 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' 624 SET pm_marked = 1 - pm_marked 625 WHERE folder_id = ' . PRIVMSGS_NO_BOX . " 626 AND user_id = $user_id 627 AND " . $db->sql_in_set('msg_id', $important_ids); 628 $db->sql_query($sql); 629 } 630 631 // Move into folder 632 $folder = array(); 633 634 if (count($move_into_folder)) 635 { 636 // Determine Full Folder Action - we need the move to folder id later eventually 637 $full_folder_action = ($user->data['user_full_folder'] == FULL_FOLDER_NONE) ? ($config['full_folder_action'] - (FULL_FOLDER_NONE*(-1))) : $user->data['user_full_folder']; 638 639 $sql_folder = array_keys($move_into_folder); 640 if ($full_folder_action >= 0) 641 { 642 $sql_folder[] = $full_folder_action; 643 } 644 645 $sql = 'SELECT folder_id, pm_count 646 FROM ' . PRIVMSGS_FOLDER_TABLE . ' 647 WHERE ' . $db->sql_in_set('folder_id', $sql_folder) . " 648 AND user_id = $user_id"; 649 $result = $db->sql_query($sql); 650 651 while ($row = $db->sql_fetchrow($result)) 652 { 653 $folder[(int) $row['folder_id']] = (int) $row['pm_count']; 654 } 655 $db->sql_freeresult($result); 656 657 unset($sql_folder); 658 659 if (isset($move_into_folder[PRIVMSGS_INBOX])) 660 { 661 $sql = 'SELECT COUNT(msg_id) as num_messages 662 FROM ' . PRIVMSGS_TO_TABLE . " 663 WHERE user_id = $user_id 664 AND folder_id = " . PRIVMSGS_INBOX; 665 $result = $db->sql_query($sql); 666 $folder[PRIVMSGS_INBOX] = (int) $db->sql_fetchfield('num_messages'); 667 $db->sql_freeresult($result); 668 } 669 } 670 671 // Here we have ideally only one folder to move into 672 foreach ($move_into_folder as $folder_id => $msg_ary) 673 { 674 $dest_folder = $folder_id; 675 $full_folder_action = FULL_FOLDER_NONE; 676 677 // Check Message Limit - we calculate with the complete array, most of the time it is one message 678 // But we are making sure that the other way around works too (more messages in queue than allowed to be stored) 679 if ($user->data['message_limit'] && $folder[$folder_id] && ($folder[$folder_id] + count($msg_ary)) > $user->data['message_limit']) 680 { 681 $full_folder_action = ($user->data['user_full_folder'] == FULL_FOLDER_NONE) ? ($config['full_folder_action'] - (FULL_FOLDER_NONE*(-1))) : $user->data['user_full_folder']; 682 683 // If destination folder itself is full... 684 if ($full_folder_action >= 0 && ($folder[$full_folder_action] + count($msg_ary)) > $user->data['message_limit']) 685 { 686 $full_folder_action = $config['full_folder_action'] - (FULL_FOLDER_NONE*(-1)); 687 } 688 689 // If Full Folder Action is to move to another folder, we simply adjust the destination folder 690 if ($full_folder_action >= 0) 691 { 692 $dest_folder = $full_folder_action; 693 } 694 else if ($full_folder_action == FULL_FOLDER_DELETE) 695 { 696 // Delete some messages. NOTE: Ordered by msg_id here instead of message_time! 697 $sql = 'SELECT msg_id 698 FROM ' . PRIVMSGS_TO_TABLE . " 699 WHERE user_id = $user_id 700 AND folder_id = $dest_folder 701 ORDER BY msg_id ASC"; 702 $result = $db->sql_query_limit($sql, (($folder[$dest_folder] + count($msg_ary)) - $user->data['message_limit'])); 703 704 $delete_ids = array(); 705 while ($row = $db->sql_fetchrow($result)) 706 { 707 $delete_ids[] = $row['msg_id']; 708 } 709 $db->sql_freeresult($result); 710 711 $num_removed += count($delete_ids); 712 delete_pm($user_id, $delete_ids, $dest_folder); 713 } 714 } 715 716 // 717 if ($full_folder_action == FULL_FOLDER_HOLD) 718 { 719 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' 720 SET folder_id = ' . PRIVMSGS_HOLD_BOX . ' 721 WHERE folder_id = ' . PRIVMSGS_NO_BOX . " 722 AND user_id = $user_id 723 AND " . $db->sql_in_set('msg_id', $msg_ary); 724 $db->sql_query($sql); 725 } 726 else 727 { 728 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . " 729 SET folder_id = $dest_folder, pm_new = 0 730 WHERE folder_id = " . PRIVMSGS_NO_BOX . " 731 AND user_id = $user_id 732 AND pm_new = 1 733 AND " . $db->sql_in_set('msg_id', $msg_ary); 734 $db->sql_query($sql); 735 736 if ($dest_folder != PRIVMSGS_INBOX) 737 { 738 $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . ' 739 SET pm_count = pm_count + ' . (int) $db->sql_affectedrows() . " 740 WHERE folder_id = $dest_folder 741 AND user_id = $user_id"; 742 $db->sql_query($sql); 743 } 744 } 745 } 746 747 if (count($action_ary)) 748 { 749 // Move from OUTBOX to SENTBOX 750 // We are not checking any full folder status here... SENTBOX is a special treatment (old messages get deleted) 751 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' 752 SET folder_id = ' . PRIVMSGS_SENTBOX . ' 753 WHERE folder_id = ' . PRIVMSGS_OUTBOX . ' 754 AND ' . $db->sql_in_set('msg_id', array_keys($action_ary)); 755 $db->sql_query($sql); 756 } 757 758 // Update new/unread count 759 update_pm_counts(); 760 761 // Now check how many messages got not moved... 762 $sql = 'SELECT COUNT(msg_id) as num_messages 763 FROM ' . PRIVMSGS_TO_TABLE . " 764 WHERE user_id = $user_id 765 AND folder_id = " . PRIVMSGS_HOLD_BOX; 766 $result = $db->sql_query($sql); 767 $num_not_moved = (int) $db->sql_fetchfield('num_messages'); 768 $db->sql_freeresult($result); 769 770 return array('not_moved' => $num_not_moved, 'removed' => $num_removed); 771 } 772 773 /** 774 * Move PM from one to another folder 775 */ 776 function move_pm($user_id, $message_limit, $move_msg_ids, $dest_folder, $cur_folder_id) 777 { 778 global $db, $user; 779 global $phpbb_root_path, $phpEx; 780 781 $num_moved = 0; 782 783 if (!is_array($move_msg_ids)) 784 { 785 $move_msg_ids = array($move_msg_ids); 786 } 787 788 if (count($move_msg_ids) && !in_array($dest_folder, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX)) && 789 !in_array($cur_folder_id, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX)) && $cur_folder_id != $dest_folder) 790 { 791 // We have to check the destination folder ;) 792 if ($dest_folder != PRIVMSGS_INBOX) 793 { 794 $sql = 'SELECT folder_id, folder_name, pm_count 795 FROM ' . PRIVMSGS_FOLDER_TABLE . " 796 WHERE folder_id = $dest_folder 797 AND user_id = $user_id"; 798 $result = $db->sql_query($sql); 799 $row = $db->sql_fetchrow($result); 800 $db->sql_freeresult($result); 801 802 if (!$row) 803 { 804 send_status_line(403, 'Forbidden'); 805 trigger_error('NOT_AUTHORISED'); 806 } 807 808 if ($message_limit && $row['pm_count'] + count($move_msg_ids) > $message_limit) 809 { 810 $message = sprintf($user->lang['NOT_ENOUGH_SPACE_FOLDER'], $row['folder_name']) . '<br /><br />'; 811 $message .= sprintf($user->lang['CLICK_RETURN_FOLDER'], '<a href="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=' . $row['folder_id']) . '">', '</a>', $row['folder_name']); 812 trigger_error($message); 813 } 814 } 815 else 816 { 817 $sql = 'SELECT COUNT(msg_id) as num_messages 818 FROM ' . PRIVMSGS_TO_TABLE . ' 819 WHERE folder_id = ' . PRIVMSGS_INBOX . " 820 AND user_id = $user_id"; 821 $result = $db->sql_query($sql); 822 $num_messages = (int) $db->sql_fetchfield('num_messages'); 823 $db->sql_freeresult($result); 824 825 if ($message_limit && $num_messages + count($move_msg_ids) > $message_limit) 826 { 827 $message = sprintf($user->lang['NOT_ENOUGH_SPACE_FOLDER'], $user->lang['PM_INBOX']) . '<br /><br />'; 828 $message .= sprintf($user->lang['CLICK_RETURN_FOLDER'], '<a href="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=inbox') . '">', '</a>', $user->lang['PM_INBOX']); 829 trigger_error($message); 830 } 831 } 832 833 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . " 834 SET folder_id = $dest_folder 835 WHERE folder_id = $cur_folder_id 836 AND user_id = $user_id 837 AND " . $db->sql_in_set('msg_id', $move_msg_ids); 838 $db->sql_query($sql); 839 $num_moved = $db->sql_affectedrows(); 840 841 // Update pm counts 842 if ($num_moved) 843 { 844 if (!in_array($cur_folder_id, array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX))) 845 { 846 $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . " 847 SET pm_count = pm_count - $num_moved 848 WHERE folder_id = $cur_folder_id 849 AND user_id = $user_id"; 850 $db->sql_query($sql); 851 } 852 853 if ($dest_folder != PRIVMSGS_INBOX) 854 { 855 $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . " 856 SET pm_count = pm_count + $num_moved 857 WHERE folder_id = $dest_folder 858 AND user_id = $user_id"; 859 $db->sql_query($sql); 860 } 861 } 862 } 863 else if (in_array($cur_folder_id, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX))) 864 { 865 trigger_error('CANNOT_MOVE_SPECIAL'); 866 } 867 868 return $num_moved; 869 } 870 871 /** 872 * Update unread message status 873 */ 874 function update_unread_status($unread, $msg_id, $user_id, $folder_id) 875 { 876 if (!$unread) 877 { 878 return; 879 } 880 881 global $db, $user, $phpbb_container; 882 883 /* @var $phpbb_notifications \phpbb\notification\manager */ 884 $phpbb_notifications = $phpbb_container->get('notification_manager'); 885 886 $phpbb_notifications->mark_notifications('notification.type.pm', $msg_id, $user_id); 887 888 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . " 889 SET pm_unread = 0 890 WHERE msg_id = $msg_id 891 AND user_id = $user_id 892 AND folder_id = $folder_id 893 AND pm_unread = 1"; 894 $db->sql_query($sql); 895 896 // If the message is already marked as read, we just skip the rest to avoid negative PM count 897 if (!$db->sql_affectedrows()) 898 { 899 return; 900 } 901 902 $sql = 'UPDATE ' . USERS_TABLE . " 903 SET user_unread_privmsg = user_unread_privmsg - 1 904 WHERE user_id = $user_id"; 905 $db->sql_query($sql); 906 907 if ($user->data['user_id'] == $user_id) 908 { 909 $user->data['user_unread_privmsg']--; 910 911 // Try to cope with previous wrong conversions... 912 if ($user->data['user_unread_privmsg'] < 0) 913 { 914 $sql = 'UPDATE ' . USERS_TABLE . " 915 SET user_unread_privmsg = 0 916 WHERE user_id = $user_id"; 917 $db->sql_query($sql); 918 919 $user->data['user_unread_privmsg'] = 0; 920 } 921 } 922 } 923 924 function mark_folder_read($user_id, $folder_id) 925 { 926 global $db; 927 928 $sql = 'SELECT msg_id 929 FROM ' . PRIVMSGS_TO_TABLE . ' 930 WHERE folder_id = ' . ((int) $folder_id) . ' 931 AND user_id = ' . ((int) $user_id) . ' 932 AND pm_unread = 1'; 933 $result = $db->sql_query($sql); 934 935 while ($row = $db->sql_fetchrow($result)) 936 { 937 update_unread_status(true, $row['msg_id'], $user_id, $folder_id); 938 } 939 $db->sql_freeresult($result); 940 } 941 942 /** 943 * Handle all actions possible with marked messages 944 */ 945 function handle_mark_actions($user_id, $mark_action) 946 { 947 global $db, $user, $phpbb_root_path, $phpEx, $request; 948 949 $msg_ids = $request->variable('marked_msg_id', array(0)); 950 $cur_folder_id = $request->variable('cur_folder_id', PRIVMSGS_NO_BOX); 951 952 if (!count($msg_ids)) 953 { 954 return false; 955 } 956 957 switch ($mark_action) 958 { 959 case 'mark_important': 960 961 if (!check_form_key('ucp_pm_view')) 962 { 963 trigger_error('FORM_INVALID'); 964 } 965 966 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . " 967 SET pm_marked = 1 - pm_marked 968 WHERE folder_id = $cur_folder_id 969 AND user_id = $user_id 970 AND " . $db->sql_in_set('msg_id', $msg_ids); 971 $db->sql_query($sql); 972 973 break; 974 975 case 'delete_marked': 976 977 global $auth; 978 979 if (!$auth->acl_get('u_pm_delete')) 980 { 981 send_status_line(403, 'Forbidden'); 982 trigger_error('NO_AUTH_DELETE_MESSAGE'); 983 } 984 985 if (confirm_box(true)) 986 { 987 delete_pm($user_id, $msg_ids, $cur_folder_id); 988 989 $success_msg = (count($msg_ids) == 1) ? 'MESSAGE_DELETED' : 'MESSAGES_DELETED'; 990 $redirect = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=' . $cur_folder_id); 991 992 meta_refresh(3, $redirect); 993 trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_FOLDER'], '<a href="' . $redirect . '">', '</a>')); 994 } 995 else 996 { 997 $s_hidden_fields = array( 998 'cur_folder_id' => $cur_folder_id, 999 'mark_option' => 'delete_marked', 1000 'submit_mark' => true, 1001 'marked_msg_id' => $msg_ids 1002 ); 1003 1004 confirm_box(false, 'DELETE_MARKED_PM', build_hidden_fields($s_hidden_fields)); 1005 } 1006 1007 break; 1008 1009 default: 1010 return false; 1011 } 1012 1013 return true; 1014 } 1015 1016 /** 1017 * Delete PM(s) 1018 */ 1019 function delete_pm($user_id, $msg_ids, $folder_id) 1020 { 1021 global $db, $user, $phpbb_container, $phpbb_dispatcher; 1022 1023 $user_id = (int) $user_id; 1024 $folder_id = (int) $folder_id; 1025 1026 if (!$user_id) 1027 { 1028 return false; 1029 } 1030 1031 if (!is_array($msg_ids)) 1032 { 1033 if (!$msg_ids) 1034 { 1035 return false; 1036 } 1037 $msg_ids = array($msg_ids); 1038 } 1039 1040 if (!count($msg_ids)) 1041 { 1042 return false; 1043 } 1044 1045 /** 1046 * Get all info for PM(s) before they are deleted 1047 * 1048 * @event core.delete_pm_before 1049 * @var int user_id ID of the user requested the message delete 1050 * @var array msg_ids array of all messages to be deleted 1051 * @var int folder_id ID of the user folder where the messages are stored 1052 * @since 3.1.0-b5 1053 */ 1054 $vars = array('user_id', 'msg_ids', 'folder_id'); 1055 extract($phpbb_dispatcher->trigger_event('core.delete_pm_before', compact($vars))); 1056 1057 // Get PM Information for later deleting 1058 $sql = 'SELECT msg_id, pm_unread, pm_new 1059 FROM ' . PRIVMSGS_TO_TABLE . ' 1060 WHERE ' . $db->sql_in_set('msg_id', array_map('intval', $msg_ids)) . " 1061 AND folder_id = $folder_id 1062 AND user_id = $user_id"; 1063 $result = $db->sql_query($sql); 1064 1065 $delete_rows = array(); 1066 $num_unread = $num_new = $num_deleted = 0; 1067 while ($row = $db->sql_fetchrow($result)) 1068 { 1069 $num_unread += (int) $row['pm_unread']; 1070 $num_new += (int) $row['pm_new']; 1071 1072 $delete_rows[$row['msg_id']] = 1; 1073 } 1074 $db->sql_freeresult($result); 1075 unset($msg_ids); 1076 1077 if (!count($delete_rows)) 1078 { 1079 return false; 1080 } 1081 1082 $db->sql_transaction('begin'); 1083 1084 // if no one has read the message yet (meaning it is in users outbox) 1085 // then mark the message as deleted... 1086 if ($folder_id == PRIVMSGS_OUTBOX) 1087 { 1088 // Remove PM from Outbox 1089 $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . " 1090 WHERE user_id = $user_id AND folder_id = " . PRIVMSGS_OUTBOX . ' 1091 AND ' . $db->sql_in_set('msg_id', array_keys($delete_rows)); 1092 $db->sql_query($sql); 1093 1094 // Update PM Information for safety 1095 $sql = 'UPDATE ' . PRIVMSGS_TABLE . " SET message_text = '' 1096 WHERE " . $db->sql_in_set('msg_id', array_keys($delete_rows)); 1097 $db->sql_query($sql); 1098 1099 // Set delete flag for those intended to receive the PM 1100 // We do not remove the message actually, to retain some basic information (sent time for example) 1101 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' 1102 SET pm_deleted = 1 1103 WHERE ' . $db->sql_in_set('msg_id', array_keys($delete_rows)); 1104 $db->sql_query($sql); 1105 1106 $num_deleted = $db->sql_affectedrows(); 1107 } 1108 else 1109 { 1110 // Delete private message data 1111 $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . " 1112 WHERE user_id = $user_id 1113 AND folder_id = $folder_id 1114 AND " . $db->sql_in_set('msg_id', array_keys($delete_rows)); 1115 $db->sql_query($sql); 1116 $num_deleted = $db->sql_affectedrows(); 1117 } 1118 1119 // if folder id is user defined folder then decrease pm_count 1120 if (!in_array($folder_id, array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX, PRIVMSGS_NO_BOX))) 1121 { 1122 $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . " 1123 SET pm_count = pm_count - $num_deleted 1124 WHERE folder_id = $folder_id"; 1125 $db->sql_query($sql); 1126 } 1127 1128 // Update unread and new status field 1129 if ($num_unread || $num_new) 1130 { 1131 $set_sql = ($num_unread) ? 'user_unread_privmsg = user_unread_privmsg - ' . $num_unread : ''; 1132 1133 if ($num_new) 1134 { 1135 $set_sql .= ($set_sql != '') ? ', ' : ''; 1136 $set_sql .= 'user_new_privmsg = user_new_privmsg - ' . $num_new; 1137 } 1138 1139 $db->sql_query('UPDATE ' . USERS_TABLE . " SET $set_sql WHERE user_id = $user_id"); 1140 1141 $user->data['user_new_privmsg'] -= $num_new; 1142 $user->data['user_unread_privmsg'] -= $num_unread; 1143 } 1144 1145 /* @var $phpbb_notifications \phpbb\notification\manager */ 1146 $phpbb_notifications = $phpbb_container->get('notification_manager'); 1147 1148 $phpbb_notifications->delete_notifications('notification.type.pm', array_keys($delete_rows)); 1149 1150 // Now we have to check which messages we can delete completely 1151 $sql = 'SELECT msg_id 1152 FROM ' . PRIVMSGS_TO_TABLE . ' 1153 WHERE ' . $db->sql_in_set('msg_id', array_keys($delete_rows)); 1154 $result = $db->sql_query($sql); 1155 1156 while ($row = $db->sql_fetchrow($result)) 1157 { 1158 unset($delete_rows[$row['msg_id']]); 1159 } 1160 $db->sql_freeresult($result); 1161 1162 $delete_ids = array_keys($delete_rows); 1163 1164 if (count($delete_ids)) 1165 { 1166 // Check if there are any attachments we need to remove 1167 /** @var \phpbb\attachment\manager $attachment_manager */ 1168 $attachment_manager = $phpbb_container->get('attachment.manager'); 1169 $attachment_manager->delete('message', $delete_ids, false); 1170 unset($attachment_manager); 1171 1172 $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . ' 1173 WHERE ' . $db->sql_in_set('msg_id', $delete_ids); 1174 $db->sql_query($sql); 1175 } 1176 1177 $db->sql_transaction('commit'); 1178 1179 return true; 1180 } 1181 1182 /** 1183 * Delete all PM(s) for given users and delete the ones without references 1184 * 1185 * @param array $user_ids IDs of the users whose private messages we want to delete 1186 * 1187 * @return boolean False if there were no pms found, true otherwise. 1188 */ 1189 function phpbb_delete_users_pms($user_ids) 1190 { 1191 global $db, $phpbb_container; 1192 1193 $user_id_sql = $db->sql_in_set('user_id', $user_ids); 1194 $author_id_sql = $db->sql_in_set('author_id', $user_ids); 1195 1196 // Get PM Information for later deleting 1197 // The two queries where split, so we can use our indexes 1198 $undelivered_msg = $delete_ids = array(); 1199 1200 // Part 1: get PMs the user received 1201 $sql = 'SELECT msg_id 1202 FROM ' . PRIVMSGS_TO_TABLE . ' 1203 WHERE ' . $user_id_sql; 1204 $result = $db->sql_query($sql); 1205 1206 while ($row = $db->sql_fetchrow($result)) 1207 { 1208 $msg_id = (int) $row['msg_id']; 1209 $delete_ids[$msg_id] = $msg_id; 1210 } 1211 $db->sql_freeresult($result); 1212 1213 // Part 2: get PMs the users sent, but are yet to be received. 1214 // We cannot simply delete them. First we have to check 1215 // whether another user already received and read the message. 1216 $sql = 'SELECT msg_id 1217 FROM ' . PRIVMSGS_TO_TABLE . ' 1218 WHERE ' . $author_id_sql . ' 1219 AND folder_id = ' . PRIVMSGS_NO_BOX; 1220 $result = $db->sql_query($sql); 1221 1222 while ($row = $db->sql_fetchrow($result)) 1223 { 1224 $msg_id = (int) $row['msg_id']; 1225 $undelivered_msg[$msg_id] = $msg_id; 1226 } 1227 $db->sql_freeresult($result); 1228 1229 if (empty($delete_ids) && empty($undelivered_msg)) 1230 { 1231 return false; 1232 } 1233 1234 $db->sql_transaction('begin'); 1235 1236 /* @var $phpbb_notifications \phpbb\notification\manager */ 1237 $phpbb_notifications = $phpbb_container->get('notification_manager'); 1238 1239 if (!empty($undelivered_msg)) 1240 { 1241 // A pm is delivered, if for any recipient the message was moved 1242 // from their NO_BOX to another folder. We do not delete such 1243 // messages, but only delete them for users, who have not yet 1244 // received them. 1245 $sql = 'SELECT msg_id 1246 FROM ' . PRIVMSGS_TO_TABLE . ' 1247 WHERE ' . $author_id_sql . ' 1248 AND folder_id <> ' . PRIVMSGS_NO_BOX . ' 1249 AND folder_id <> ' . PRIVMSGS_OUTBOX . ' 1250 AND folder_id <> ' . PRIVMSGS_SENTBOX; 1251 $result = $db->sql_query($sql); 1252 1253 $delivered_msg = array(); 1254 while ($row = $db->sql_fetchrow($result)) 1255 { 1256 $msg_id = (int) $row['msg_id']; 1257 $delivered_msg[$msg_id] = $msg_id; 1258 unset($undelivered_msg[$msg_id]); 1259 } 1260 $db->sql_freeresult($result); 1261 1262 $undelivered_user = array(); 1263 1264 // Count the messages we delete, so we can correct the user pm data 1265 $sql = 'SELECT user_id, COUNT(msg_id) as num_undelivered_privmsgs 1266 FROM ' . PRIVMSGS_TO_TABLE . ' 1267 WHERE ' . $author_id_sql . ' 1268 AND folder_id = ' . PRIVMSGS_NO_BOX . ' 1269 AND ' . $db->sql_in_set('msg_id', array_merge($undelivered_msg, $delivered_msg)) . ' 1270 GROUP BY user_id'; 1271 $result = $db->sql_query($sql); 1272 1273 while ($row = $db->sql_fetchrow($result)) 1274 { 1275 $num_pms = (int) $row['num_undelivered_privmsgs']; 1276 $undelivered_user[$num_pms][] = (int) $row['user_id']; 1277 1278 if (count($undelivered_user[$num_pms]) > 50) 1279 { 1280 // If there are too many users affected the query might get 1281 // too long, so we update the value for the first bunch here. 1282 $sql = 'UPDATE ' . USERS_TABLE . ' 1283 SET user_new_privmsg = user_new_privmsg - ' . $num_pms . ', 1284 user_unread_privmsg = user_unread_privmsg - ' . $num_pms . ' 1285 WHERE ' . $db->sql_in_set('user_id', $undelivered_user[$num_pms]); 1286 $db->sql_query($sql); 1287 unset($undelivered_user[$num_pms]); 1288 } 1289 } 1290 $db->sql_freeresult($result); 1291 1292 foreach ($undelivered_user as $num_pms => $undelivered_user_set) 1293 { 1294 $sql = 'UPDATE ' . USERS_TABLE . ' 1295 SET user_new_privmsg = user_new_privmsg - ' . $num_pms . ', 1296 user_unread_privmsg = user_unread_privmsg - ' . $num_pms . ' 1297 WHERE ' . $db->sql_in_set('user_id', $undelivered_user_set); 1298 $db->sql_query($sql); 1299 } 1300 1301 if (!empty($delivered_msg)) 1302 { 1303 $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . ' 1304 WHERE folder_id = ' . PRIVMSGS_NO_BOX . ' 1305 AND ' . $db->sql_in_set('msg_id', $delivered_msg); 1306 $db->sql_query($sql); 1307 1308 $phpbb_notifications->delete_notifications('notification.type.pm', $delivered_msg); 1309 } 1310 1311 if (!empty($undelivered_msg)) 1312 { 1313 $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . ' 1314 WHERE ' . $db->sql_in_set('msg_id', $undelivered_msg); 1315 $db->sql_query($sql); 1316 1317 $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . ' 1318 WHERE ' . $db->sql_in_set('msg_id', $undelivered_msg); 1319 $db->sql_query($sql); 1320 1321 $phpbb_notifications->delete_notifications('notification.type.pm', $undelivered_msg); 1322 } 1323 } 1324 1325 // Reset the user's pm count to 0 1326 $sql = 'UPDATE ' . USERS_TABLE . ' 1327 SET user_new_privmsg = 0, 1328 user_unread_privmsg = 0 1329 WHERE ' . $user_id_sql; 1330 $db->sql_query($sql); 1331 1332 // Delete private message data of the user 1333 $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . ' 1334 WHERE ' . $user_id_sql; 1335 $db->sql_query($sql); 1336 1337 if (!empty($delete_ids)) 1338 { 1339 // Now we have to check which messages we can delete completely 1340 $sql = 'SELECT msg_id 1341 FROM ' . PRIVMSGS_TO_TABLE . ' 1342 WHERE ' . $db->sql_in_set('msg_id', $delete_ids); 1343 $result = $db->sql_query($sql); 1344 1345 while ($row = $db->sql_fetchrow($result)) 1346 { 1347 unset($delete_ids[$row['msg_id']]); 1348 } 1349 $db->sql_freeresult($result); 1350 1351 if (!empty($delete_ids)) 1352 { 1353 // Check if there are any attachments we need to remove 1354 /** @var \phpbb\attachment\manager $attachment_manager */ 1355 $attachment_manager = $phpbb_container->get('attachment.manager'); 1356 $attachment_manager->delete('message', $delete_ids, false); 1357 unset($attachment_manager); 1358 1359 $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . ' 1360 WHERE ' . $db->sql_in_set('msg_id', $delete_ids); 1361 $db->sql_query($sql); 1362 1363 $phpbb_notifications->delete_notifications('notification.type.pm', $delete_ids); 1364 } 1365 } 1366 1367 // Set the remaining author id to anonymous 1368 // This way users are still able to read messages from users being removed 1369 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' 1370 SET author_id = ' . ANONYMOUS . ' 1371 WHERE ' . $author_id_sql; 1372 $db->sql_query($sql); 1373 1374 $sql = 'UPDATE ' . PRIVMSGS_TABLE . ' 1375 SET author_id = ' . ANONYMOUS . ' 1376 WHERE ' . $author_id_sql; 1377 $db->sql_query($sql); 1378 1379 $db->sql_transaction('commit'); 1380 1381 return true; 1382 } 1383 1384 /** 1385 * Rebuild message header 1386 */ 1387 function rebuild_header($check_ary) 1388 { 1389 $address = array(); 1390 1391 foreach ($check_ary as $check_type => $address_field) 1392 { 1393 // Split Addresses into users and groups 1394 preg_match_all('/:?(u|g)_([0-9]+):?/', $address_field, $match); 1395 1396 $u = $g = array(); 1397 foreach ($match[1] as $id => $type) 1398 { 1399 ${$type}[] = (int) $match[2][$id]; 1400 } 1401 1402 $_types = array('u', 'g'); 1403 foreach ($_types as $type) 1404 { 1405 if (count(${$type})) 1406 { 1407 foreach (${$type} as $id) 1408 { 1409 $address[$type][$id] = $check_type; 1410 } 1411 } 1412 } 1413 } 1414 1415 return $address; 1416 } 1417 1418 /** 1419 * Print out/assign recipient information 1420 */ 1421 function write_pm_addresses($check_ary, $author_id, $plaintext = false) 1422 { 1423 global $db, $user, $template, $phpbb_root_path, $phpEx, $phpbb_container; 1424 1425 /** @var \phpbb\group\helper $group_helper */ 1426 $group_helper = $phpbb_container->get('group_helper'); 1427 1428 $addresses = array(); 1429 1430 foreach ($check_ary as $check_type => $address_field) 1431 { 1432 if (!is_array($address_field)) 1433 { 1434 // Split Addresses into users and groups 1435 preg_match_all('/:?(u|g)_([0-9]+):?/', $address_field, $match); 1436 1437 $u = $g = array(); 1438 foreach ($match[1] as $id => $type) 1439 { 1440 ${$type}[] = (int) $match[2][$id]; 1441 } 1442 } 1443 else 1444 { 1445 $u = $address_field['u']; 1446 $g = $address_field['g']; 1447 } 1448 1449 $address = array(); 1450 if (count($u)) 1451 { 1452 $sql = 'SELECT user_id, username, user_colour 1453 FROM ' . USERS_TABLE . ' 1454 WHERE ' . $db->sql_in_set('user_id', $u); 1455 $result = $db->sql_query($sql); 1456 1457 while ($row = $db->sql_fetchrow($result)) 1458 { 1459 if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id']) 1460 { 1461 if ($plaintext) 1462 { 1463 $address[] = $row['username']; 1464 } 1465 else 1466 { 1467 $address['user'][$row['user_id']] = array('name' => $row['username'], 'colour' => $row['user_colour']); 1468 } 1469 } 1470 } 1471 $db->sql_freeresult($result); 1472 } 1473 1474 if (count($g)) 1475 { 1476 if ($plaintext) 1477 { 1478 $sql = 'SELECT group_name, group_type 1479 FROM ' . GROUPS_TABLE . ' 1480 WHERE ' . $db->sql_in_set('group_id', $g); 1481 $result = $db->sql_query($sql); 1482 1483 while ($row = $db->sql_fetchrow($result)) 1484 { 1485 if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id']) 1486 { 1487 $address[] = $group_helper->get_name($row['group_name']); 1488 } 1489 } 1490 $db->sql_freeresult($result); 1491 } 1492 else 1493 { 1494 $sql = 'SELECT g.group_id, g.group_name, g.group_colour, g.group_type, ug.user_id 1495 FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug 1496 WHERE ' . $db->sql_in_set('g.group_id', $g) . ' 1497 AND g.group_id = ug.group_id 1498 AND ug.user_pending = 0'; 1499 $result = $db->sql_query($sql); 1500 1501 while ($row = $db->sql_fetchrow($result)) 1502 { 1503 if (!isset($address['group'][$row['group_id']])) 1504 { 1505 if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id']) 1506 { 1507 $row['group_name'] = $group_helper->get_name($row['group_name']); 1508 $address['group'][$row['group_id']] = array('name' => $row['group_name'], 'colour' => $row['group_colour']); 1509 } 1510 } 1511 1512 if (isset($address['user'][$row['user_id']])) 1513 { 1514 $address['user'][$row['user_id']]['in_group'] = $row['group_id']; 1515 } 1516 } 1517 $db->sql_freeresult($result); 1518 } 1519 } 1520 1521 if (count($address) && !$plaintext) 1522 { 1523 $template->assign_var('S_' . strtoupper($check_type) . '_RECIPIENT', true); 1524 1525 foreach ($address as $type => $adr_ary) 1526 { 1527 foreach ($adr_ary as $id => $row) 1528 { 1529 $tpl_ary = array( 1530 'IS_GROUP' => ($type == 'group') ? true : false, 1531 'IS_USER' => ($type == 'user') ? true : false, 1532 'UG_ID' => $id, 1533 'NAME' => $row['name'], 1534 'COLOUR' => ($row['colour']) ? '#' . $row['colour'] : '', 1535 'TYPE' => $type, 1536 ); 1537 1538 if ($type == 'user') 1539 { 1540 $tpl_ary = array_merge($tpl_ary, array( 1541 'U_VIEW' => get_username_string('profile', $id, $row['name'], $row['colour']), 1542 'NAME_FULL' => get_username_string('full', $id, $row['name'], $row['colour']), 1543 )); 1544 } 1545 else 1546 { 1547 $tpl_ary = array_merge($tpl_ary, array( 1548 'U_VIEW' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&g=' . $id), 1549 )); 1550 } 1551 1552 $template->assign_block_vars($check_type . '_recipient', $tpl_ary); 1553 } 1554 } 1555 } 1556 1557 $addresses[$check_type] = $address; 1558 } 1559 1560 return $addresses; 1561 } 1562 1563 /** 1564 * Get folder status 1565 */ 1566 function get_folder_status($folder_id, $folder) 1567 { 1568 global $user; 1569 1570 if (isset($folder[$folder_id])) 1571 { 1572 $folder = $folder[$folder_id]; 1573 } 1574 else 1575 { 1576 return false; 1577 } 1578 1579 $return = array( 1580 'folder_name' => $folder['folder_name'], 1581 'cur' => $folder['num_messages'], 1582 'remaining' => ($user->data['message_limit']) ? $user->data['message_limit'] - $folder['num_messages'] : 0, 1583 'max' => $user->data['message_limit'], 1584 'percent' => ($user->data['message_limit']) ? (($user->data['message_limit'] > 0) ? floor(($folder['num_messages'] / $user->data['message_limit']) * 100) : 100) : 0, 1585 ); 1586 1587 $return['message'] = $user->lang('FOLDER_STATUS_MSG', $user->lang('MESSAGES_COUNT', (int) $return['max']), (int) $return['cur'], $return['percent']); 1588 1589 return $return; 1590 } 1591 1592 // 1593 // COMPOSE MESSAGES 1594 // 1595 1596 /** 1597 * Submit PM 1598 */ 1599 function submit_pm($mode, $subject, &$data_ary, $put_in_outbox = true) 1600 { 1601 global $db, $auth, $config, $user, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher, $request; 1602 1603 // We do not handle erasing pms here 1604 if ($mode == 'delete') 1605 { 1606 return false; 1607 } 1608 1609 $current_time = time(); 1610 1611 $data = $data_ary; 1612 /** 1613 * Get all parts of the PM that are to be submited to the DB. 1614 * 1615 * @event core.submit_pm_before 1616 * @var string mode PM Post mode - post|reply|quote|quotepost|forward|edit 1617 * @var string subject Subject of the private message 1618 * @var array data The whole row data of the PM. 1619 * @since 3.1.0-b3 1620 */ 1621 $vars = array('mode', 'subject', 'data'); 1622 extract($phpbb_dispatcher->trigger_event('core.submit_pm_before', compact($vars))); 1623 $data_ary = $data; 1624 unset($data); 1625 1626 // Collect some basic information about which tables and which rows to update/insert 1627 $sql_data = array(); 1628 $root_level = 0; 1629 1630 // Recipient Information 1631 $recipients = $to = $bcc = array(); 1632 1633 if ($mode != 'edit') 1634 { 1635 // Build Recipient List 1636 // u|g => array($user_id => 'to'|'bcc') 1637 $_types = array('u', 'g'); 1638 foreach ($_types as $ug_type) 1639 { 1640 if (isset($data_ary['address_list'][$ug_type]) && count($data_ary['address_list'][$ug_type])) 1641 { 1642 foreach ($data_ary['address_list'][$ug_type] as $id => $field) 1643 { 1644 $id = (int) $id; 1645 1646 // Do not rely on the address list being "valid" 1647 if (!$id || ($ug_type == 'u' && $id == ANONYMOUS)) 1648 { 1649 continue; 1650 } 1651 1652 $field = ($field == 'to') ? 'to' : 'bcc'; 1653 if ($ug_type == 'u') 1654 { 1655 $recipients[$id] = $field; 1656 } 1657 ${$field}[] = $ug_type . '_' . $id; 1658 } 1659 } 1660 } 1661 1662 if (isset($data_ary['address_list']['g']) && count($data_ary['address_list']['g'])) 1663 { 1664 // We need to check the PM status of group members (do they want to receive PM's?) 1665 // Only check if not a moderator or admin, since they are allowed to override this user setting 1666 $sql_allow_pm = (!$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_')) ? ' AND u.user_allow_pm = 1' : ''; 1667 1668 $sql = 'SELECT u.user_type, ug.group_id, ug.user_id 1669 FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . ' ug 1670 WHERE ' . $db->sql_in_set('ug.group_id', array_keys($data_ary['address_list']['g'])) . ' 1671 AND ug.user_pending = 0 1672 AND u.user_id = ug.user_id 1673 AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')' . 1674 $sql_allow_pm; 1675 $result = $db->sql_query($sql); 1676 1677 while ($row = $db->sql_fetchrow($result)) 1678 { 1679 $field = ($data_ary['address_list']['g'][$row['group_id']] == 'to') ? 'to' : 'bcc'; 1680 $recipients[$row['user_id']] = $field; 1681 } 1682 $db->sql_freeresult($result); 1683 } 1684 1685 if (!count($recipients)) 1686 { 1687 trigger_error('NO_RECIPIENT'); 1688 } 1689 } 1690 1691 // First of all make sure the subject are having the correct length. 1692 $subject = truncate_string($subject, $mode === 'post' ? 120 : 124); 1693 1694 $db->sql_transaction('begin'); 1695 1696 $sql = ''; 1697 1698 switch ($mode) 1699 { 1700 case 'reply': 1701 case 'quote': 1702 $root_level = ($data_ary['reply_from_root_level']) ? $data_ary['reply_from_root_level'] : $data_ary['reply_from_msg_id']; 1703 1704 // Set message_replied switch for this user 1705 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' 1706 SET pm_replied = 1 1707 WHERE user_id = ' . $data_ary['from_user_id'] . ' 1708 AND msg_id = ' . $data_ary['reply_from_msg_id']; 1709 1710 // no break 1711 1712 case 'forward': 1713 case 'post': 1714 case 'quotepost': 1715 $sql_data = array( 1716 'root_level' => $root_level, 1717 'author_id' => $data_ary['from_user_id'], 1718 'icon_id' => $data_ary['icon_id'], 1719 'author_ip' => $data_ary['from_user_ip'], 1720 'message_time' => $current_time, 1721 'enable_bbcode' => $data_ary['enable_bbcode'], 1722 'enable_smilies' => $data_ary['enable_smilies'], 1723 'enable_magic_url' => $data_ary['enable_urls'], 1724 'enable_sig' => $data_ary['enable_sig'], 1725 'message_subject' => $subject, 1726 'message_text' => $data_ary['message'], 1727 'message_attachment'=> (!empty($data_ary['attachment_data'])) ? 1 : 0, 1728 'bbcode_bitfield' => $data_ary['bbcode_bitfield'], 1729 'bbcode_uid' => $data_ary['bbcode_uid'], 1730 'to_address' => implode(':', $to), 1731 'bcc_address' => implode(':', $bcc), 1732 'message_reported' => 0, 1733 ); 1734 break; 1735 1736 case 'edit': 1737 $sql_data = array( 1738 'icon_id' => $data_ary['icon_id'], 1739 'message_edit_time' => $current_time, 1740 'enable_bbcode' => $data_ary['enable_bbcode'], 1741 'enable_smilies' => $data_ary['enable_smilies'], 1742 'enable_magic_url' => $data_ary['enable_urls'], 1743 'enable_sig' => $data_ary['enable_sig'], 1744 'message_subject' => $subject, 1745 'message_text' => $data_ary['message'], 1746 'message_attachment'=> (!empty($data_ary['attachment_data'])) ? 1 : 0, 1747 'bbcode_bitfield' => $data_ary['bbcode_bitfield'], 1748 'bbcode_uid' => $data_ary['bbcode_uid'] 1749 ); 1750 break; 1751 } 1752 1753 if (count($sql_data)) 1754 { 1755 if ($mode == 'post' || $mode == 'reply' || $mode == 'quote' || $mode == 'quotepost' || $mode == 'forward') 1756 { 1757 $db->sql_query('INSERT INTO ' . PRIVMSGS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data)); 1758 $data_ary['msg_id'] = $db->sql_nextid(); 1759 } 1760 else if ($mode == 'edit') 1761 { 1762 $sql = 'UPDATE ' . PRIVMSGS_TABLE . ' 1763 SET message_edit_count = message_edit_count + 1, ' . $db->sql_build_array('UPDATE', $sql_data) . ' 1764 WHERE msg_id = ' . $data_ary['msg_id']; 1765 $db->sql_query($sql); 1766 } 1767 } 1768 1769 if ($mode != 'edit') 1770 { 1771 if ($sql) 1772 { 1773 $db->sql_query($sql); 1774 } 1775 unset($sql); 1776 1777 $sql_ary = array(); 1778 foreach ($recipients as $user_id => $type) 1779 { 1780 $sql_ary[] = array( 1781 'msg_id' => (int) $data_ary['msg_id'], 1782 'user_id' => (int) $user_id, 1783 'author_id' => (int) $data_ary['from_user_id'], 1784 'folder_id' => PRIVMSGS_NO_BOX, 1785 'pm_new' => 1, 1786 'pm_unread' => 1, 1787 'pm_forwarded' => ($mode == 'forward') ? 1 : 0 1788 ); 1789 } 1790 1791 $db->sql_multi_insert(PRIVMSGS_TO_TABLE, $sql_ary); 1792 1793 $sql = 'UPDATE ' . USERS_TABLE . ' 1794 SET user_new_privmsg = user_new_privmsg + 1, user_unread_privmsg = user_unread_privmsg + 1, user_last_privmsg = ' . time() . ' 1795 WHERE ' . $db->sql_in_set('user_id', array_keys($recipients)); 1796 $db->sql_query($sql); 1797 1798 // Put PM into outbox 1799 if ($put_in_outbox) 1800 { 1801 $db->sql_query('INSERT INTO ' . PRIVMSGS_TO_TABLE . ' ' . $db->sql_build_array('INSERT', array( 1802 'msg_id' => (int) $data_ary['msg_id'], 1803 'user_id' => (int) $data_ary['from_user_id'], 1804 'author_id' => (int) $data_ary['from_user_id'], 1805 'folder_id' => PRIVMSGS_OUTBOX, 1806 'pm_new' => 0, 1807 'pm_unread' => 0, 1808 'pm_forwarded' => ($mode == 'forward') ? 1 : 0)) 1809 ); 1810 } 1811 } 1812 1813 // Set user last post time 1814 if ($mode == 'reply' || $mode == 'quote' || $mode == 'quotepost' || $mode == 'forward' || $mode == 'post') 1815 { 1816 $sql = 'UPDATE ' . USERS_TABLE . " 1817 SET user_lastpost_time = $current_time 1818 WHERE user_id = " . $data_ary['from_user_id']; 1819 $db->sql_query($sql); 1820 } 1821 1822 // Submit Attachments 1823 if (!empty($data_ary['attachment_data']) && $data_ary['msg_id'] && in_array($mode, array('post', 'reply', 'quote', 'quotepost', 'edit', 'forward'))) 1824 { 1825 $space_taken = $files_added = 0; 1826 $orphan_rows = array(); 1827 1828 foreach ($data_ary['attachment_data'] as $pos => $attach_row) 1829 { 1830 $orphan_rows[(int) $attach_row['attach_id']] = array(); 1831 } 1832 1833 if (count($orphan_rows)) 1834 { 1835 $sql = 'SELECT attach_id, filesize, physical_filename 1836 FROM ' . ATTACHMENTS_TABLE . ' 1837 WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . ' 1838 AND in_message = 1 1839 AND is_orphan = 1 1840 AND poster_id = ' . $user->data['user_id']; 1841 $result = $db->sql_query($sql); 1842 1843 $orphan_rows = array(); 1844 while ($row = $db->sql_fetchrow($result)) 1845 { 1846 $orphan_rows[$row['attach_id']] = $row; 1847 } 1848 $db->sql_freeresult($result); 1849 } 1850 1851 foreach ($data_ary['attachment_data'] as $pos => $attach_row) 1852 { 1853 if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']])) 1854 { 1855 continue; 1856 } 1857 1858 if (!$attach_row['is_orphan']) 1859 { 1860 // update entry in db if attachment already stored in db and filespace 1861 $sql = 'UPDATE ' . ATTACHMENTS_TABLE . " 1862 SET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "' 1863 WHERE attach_id = " . (int) $attach_row['attach_id'] . ' 1864 AND is_orphan = 0'; 1865 $db->sql_query($sql); 1866 } 1867 else 1868 { 1869 // insert attachment into db 1870 if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($orphan_rows[$attach_row['attach_id']]['physical_filename']))) 1871 { 1872 continue; 1873 } 1874 1875 $space_taken += $orphan_rows[$attach_row['attach_id']]['filesize']; 1876 $files_added++; 1877 1878 $attach_sql = array( 1879 'post_msg_id' => $data_ary['msg_id'], 1880 'topic_id' => 0, 1881 'is_orphan' => 0, 1882 'poster_id' => $data_ary['from_user_id'], 1883 'attach_comment' => $attach_row['attach_comment'], 1884 ); 1885 1886 $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $attach_sql) . ' 1887 WHERE attach_id = ' . $attach_row['attach_id'] . ' 1888 AND is_orphan = 1 1889 AND poster_id = ' . $user->data['user_id']; 1890 $db->sql_query($sql); 1891 } 1892 } 1893 1894 if ($space_taken && $files_added) 1895 { 1896 $config->increment('upload_dir_size', $space_taken, false); 1897 $config->increment('num_files', $files_added, false); 1898 } 1899 } 1900 1901 // Delete draft if post was loaded... 1902 $draft_id = $request->variable('draft_loaded', 0); 1903 if ($draft_id) 1904 { 1905 $sql = 'DELETE FROM ' . DRAFTS_TABLE . " 1906 WHERE draft_id = $draft_id 1907 AND user_id = " . $data_ary['from_user_id']; 1908 $db->sql_query($sql); 1909 } 1910 1911 $db->sql_transaction('commit'); 1912 1913 // Send Notifications 1914 $pm_data = array_merge($data_ary, array( 1915 'message_subject' => $subject, 1916 'recipients' => $recipients, 1917 )); 1918 1919 /* @var $phpbb_notifications \phpbb\notification\manager */ 1920 $phpbb_notifications = $phpbb_container->get('notification_manager'); 1921 1922 if ($mode == 'edit') 1923 { 1924 $phpbb_notifications->update_notifications('notification.type.pm', $pm_data); 1925 } 1926 else 1927 { 1928 $phpbb_notifications->add_notifications('notification.type.pm', $pm_data); 1929 } 1930 1931 $data = $data_ary; 1932 /** 1933 * Get PM message ID after submission to DB 1934 * 1935 * @event core.submit_pm_after 1936 * @var string mode PM Post mode - post|reply|quote|quotepost|forward|edit 1937 * @var string subject Subject of the private message 1938 * @var array data The whole row data of the PM. 1939 * @var array pm_data The data sent to notification class 1940 * @since 3.1.0-b5 1941 */ 1942 $vars = array('mode', 'subject', 'data', 'pm_data'); 1943 extract($phpbb_dispatcher->trigger_event('core.submit_pm_after', compact($vars))); 1944 $data_ary = $data; 1945 unset($data); 1946 1947 return $data_ary['msg_id']; 1948 } 1949 1950 /** 1951 * Display Message History 1952 */ 1953 function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode = false) 1954 { 1955 global $db, $user, $template, $phpbb_root_path, $phpEx, $auth, $phpbb_dispatcher; 1956 1957 // Select all receipts and the author from the pm we currently view, to only display their pm-history 1958 $sql = 'SELECT author_id, user_id 1959 FROM ' . PRIVMSGS_TO_TABLE . " 1960 WHERE msg_id = $msg_id 1961 AND folder_id <> " . PRIVMSGS_HOLD_BOX; 1962 $result = $db->sql_query($sql); 1963 1964 $recipients = array(); 1965 while ($row = $db->sql_fetchrow($result)) 1966 { 1967 $recipients[] = (int) $row['user_id']; 1968 $recipients[] = (int) $row['author_id']; 1969 } 1970 $db->sql_freeresult($result); 1971 $recipients = array_unique($recipients); 1972 1973 // Get History Messages (could be newer) 1974 $sql_where = 't.msg_id = p.msg_id 1975 AND p.author_id = u.user_id 1976 AND t.folder_id NOT IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ') 1977 AND ' . $db->sql_in_set('t.author_id', $recipients, false, true) . " 1978 AND t.user_id = $user_id"; 1979 1980 // We no longer need those. 1981 unset($recipients); 1982 1983 if (!$message_row['root_level']) 1984 { 1985 $sql_where .= " AND (p.root_level = $msg_id OR (p.root_level = 0 AND p.msg_id = $msg_id))"; 1986 } 1987 else 1988 { 1989 $sql_where .= " AND (p.root_level = " . $message_row['root_level'] . ' OR p.msg_id = ' . $message_row['root_level'] . ')'; 1990 } 1991 1992 $sql_ary = array( 1993 'SELECT' => 't.*, p.*, u.*', 1994 'FROM' => array( 1995 PRIVMSGS_TABLE => 'p', 1996 PRIVMSGS_TO_TABLE => 't', 1997 USERS_TABLE => 'u' 1998 ), 1999 'LEFT_JOIN' => array(), 2000 'WHERE' => $sql_where, 2001 'ORDER_BY' => 'p.message_time DESC', 2002 ); 2003 2004 /** 2005 * Event to modify the SQL query before the message history in private message is queried 2006 * 2007 * @event core.message_history_modify_sql_ary 2008 * @var array sql_ary The SQL array to get the data of the message history in private message 2009 * @since 3.2.8-RC1 2010 */ 2011 $vars = array('sql_ary'); 2012 extract($phpbb_dispatcher->trigger_event('core.message_history_modify_sql_ary', compact($vars))); 2013 2014 $sql = $db->sql_build_query('SELECT', $sql_ary); 2015 unset($sql_ary); 2016 2017 $result = $db->sql_query($sql); 2018 $row = $db->sql_fetchrow($result); 2019 2020 if (!$row) 2021 { 2022 $db->sql_freeresult($result); 2023 return false; 2024 } 2025 2026 $title = $row['message_subject']; 2027 2028 $rowset = array(); 2029 $folder_url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm') . '&folder='; 2030 2031 do 2032 { 2033 $folder_id = (int) $row['folder_id']; 2034 2035 $row['folder'][] = (isset($folder[$folder_id])) ? '<a href="' . $folder_url . $folder_id . '">' . $folder[$folder_id]['folder_name'] . '</a>' : $user->lang['UNKNOWN_FOLDER']; 2036 2037 if (isset($rowset[$row['msg_id']])) 2038 { 2039 $rowset[$row['msg_id']]['folder'][] = (isset($folder[$folder_id])) ? '<a href="' . $folder_url . $folder_id . '">' . $folder[$folder_id]['folder_name'] . '</a>' : $user->lang['UNKNOWN_FOLDER']; 2040 } 2041 else 2042 { 2043 $rowset[$row['msg_id']] = $row; 2044 } 2045 } 2046 while ($row = $db->sql_fetchrow($result)); 2047 $db->sql_freeresult($result); 2048 2049 $url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm'); 2050 2051 /** 2052 * Modify message rows before displaying the history in private messages 2053 * 2054 * @event core.message_history_modify_rowset 2055 * @var int msg_id ID of the private message 2056 * @var int user_id ID of the message author 2057 * @var array message_row Array with message data 2058 * @var array folder Array with data of user's message folders 2059 * @var bool in_post_mode Whether or not we are viewing or composing 2060 * @var array rowset Array with message history data 2061 * @var string url Base URL used to generate links to private messages 2062 * @var string title Subject of the private message 2063 * @since 3.2.10-RC1 2064 * @since 3.3.1-RC1 2065 */ 2066 $vars = [ 2067 'msg_id', 2068 'user_id', 2069 'message_row', 2070 'folder', 2071 'in_post_mode', 2072 'rowset', 2073 'url', 2074 'title', 2075 ]; 2076 extract($phpbb_dispatcher->trigger_event('core.message_history_modify_rowset', compact($vars))); 2077 2078 if (count($rowset) == 1 && !$in_post_mode) 2079 { 2080 return false; 2081 } 2082 2083 $title = censor_text($title); 2084 2085 $next_history_pm = $previous_history_pm = $prev_id = 0; 2086 2087 // Re-order rowset to be able to get the next/prev message rows... 2088 $rowset = array_values($rowset); 2089 2090 for ($i = 0, $size = count($rowset); $i < $size; $i++) 2091 { 2092 $row = &$rowset[$i]; 2093 $id = (int) $row['msg_id']; 2094 2095 $author_id = $row['author_id']; 2096 $folder_id = (int) $row['folder_id']; 2097 2098 $subject = $row['message_subject']; 2099 $message = $row['message_text']; 2100 2101 $message = censor_text($message); 2102 2103 $decoded_message = false; 2104 2105 if ($in_post_mode && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) 2106 { 2107 $decoded_message = $message; 2108 decode_message($decoded_message, $row['bbcode_uid']); 2109 2110 $decoded_message = bbcode_nl2br($decoded_message); 2111 } 2112 2113 $parse_flags = ($row['bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0); 2114 $parse_flags |= ($row['enable_smilies'] ? OPTION_FLAG_SMILIES : 0); 2115 2116 $message = generate_text_for_display($message, $row['bbcode_uid'], $row['bbcode_bitfield'], $parse_flags, false); 2117 2118 $subject = censor_text($subject); 2119 2120 if ($id == $msg_id) 2121 { 2122 $next_history_pm = (isset($rowset[$i + 1])) ? (int) $rowset[$i + 1]['msg_id'] : 0; 2123 $previous_history_pm = $prev_id; 2124 } 2125 2126 $template_vars = array( 2127 'MESSAGE_AUTHOR_QUOTE' => (($decoded_message) ? addslashes(get_username_string('username', $author_id, $row['username'], $row['user_colour'], $row['username'])) : ''), 2128 'MESSAGE_AUTHOR_FULL' => get_username_string('full', $author_id, $row['username'], $row['user_colour'], $row['username']), 2129 'MESSAGE_AUTHOR_COLOUR' => get_username_string('colour', $author_id, $row['username'], $row['user_colour'], $row['username']), 2130 'MESSAGE_AUTHOR' => get_username_string('username', $author_id, $row['username'], $row['user_colour'], $row['username']), 2131 'U_MESSAGE_AUTHOR' => get_username_string('profile', $author_id, $row['username'], $row['user_colour'], $row['username']), 2132 2133 'SUBJECT' => $subject, 2134 'SENT_DATE' => $user->format_date($row['message_time']), 2135 'MESSAGE' => $message, 2136 'FOLDER' => implode($user->lang['COMMA_SEPARATOR'], $row['folder']), 2137 'DECODED_MESSAGE' => $decoded_message, 2138 2139 'S_CURRENT_MSG' => ($row['msg_id'] == $msg_id), 2140 'S_AUTHOR_DELETED' => ($author_id == ANONYMOUS) ? true : false, 2141 'S_IN_POST_MODE' => $in_post_mode, 2142 2143 'MSG_ID' => $row['msg_id'], 2144 'MESSAGE_TIME' => $row['message_time'], 2145 'USER_ID' => $row['user_id'], 2146 'U_VIEW_MESSAGE' => "$url&f=$folder_id&p=" . $row['msg_id'], 2147 'U_QUOTE' => (!$in_post_mode && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&mode=compose&action=quote&f=" . $folder_id . "&p=" . $row['msg_id'] : '', 2148 'U_POST_REPLY_PM' => ($author_id != $user->data['user_id'] && $author_id != ANONYMOUS && $auth->acl_get('u_sendpm')) ? "$url&mode=compose&action=reply&f=$folder_id&p=" . $row['msg_id'] : '' 2149 ); 2150 2151 /** 2152 * Modify the template vars for displaying the message history in private message 2153 * 2154 * @event core.message_history_modify_template_vars 2155 * @var array template_vars Array containing the query 2156 * @var array row Array containing the action user row 2157 * @since 3.2.8-RC1 2158 */ 2159 $vars = array( 2160 'template_vars', 2161 'row', 2162 ); 2163 extract($phpbb_dispatcher->trigger_event('core.message_history_modify_template_vars', compact($vars))); 2164 2165 $template->assign_block_vars('history_row', $template_vars); 2166 2167 unset($rowset[$i]); 2168 $prev_id = $id; 2169 } 2170 2171 $template->assign_vars(array( 2172 'QUOTE_IMG' => $user->img('icon_post_quote', $user->lang['REPLY_WITH_QUOTE']), 2173 'HISTORY_TITLE' => $title, 2174 2175 'U_VIEW_NEXT_HISTORY' => ($next_history_pm) ? "$url&p=" . $next_history_pm : '', 2176 'U_VIEW_PREVIOUS_HISTORY' => ($previous_history_pm) ? "$url&p=" . $previous_history_pm : '', 2177 )); 2178 2179 return true; 2180 } 2181 2182 /** 2183 * Set correct users max messages in PM folder. 2184 * If several group memberships define different amount of messages, the highest will be chosen. 2185 */ 2186 function set_user_message_limit() 2187 { 2188 global $user, $db, $config; 2189 2190 // Get maximum about from user memberships 2191 $message_limit = phpbb_get_max_setting_from_group($db, $user->data['user_id'], 'message_limit'); 2192 2193 // If it is 0, there is no limit set and we use the maximum value within the config. 2194 $user->data['message_limit'] = (!$message_limit) ? $config['pm_max_msgs'] : $message_limit; 2195 } 2196 2197 /** 2198 * Get the maximum PM setting for the groups of the user 2199 * 2200 * @param \phpbb\db\driver\driver_interface $db 2201 * @param int $user_id 2202 * @param string $setting Only 'max_recipients' and 'message_limit' are supported 2203 * @return int The maximum setting for all groups of the user, unless one group has '0' 2204 * @throws \InvalidArgumentException If selected group setting is not supported 2205 */ 2206 function phpbb_get_max_setting_from_group(\phpbb\db\driver\driver_interface $db, $user_id, $setting) 2207 { 2208 if ($setting !== 'max_recipients' && $setting !== 'message_limit') 2209 { 2210 throw new InvalidArgumentException('Setting "' . $setting . '" is not supported'); 2211 } 2212 2213 // Get maximum number of allowed recipients 2214 $sql = 'SELECT MAX(g.group_' . $setting . ') as max_setting 2215 FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug 2216 WHERE ug.user_id = ' . (int) $user_id . ' 2217 AND ug.user_pending = 0 2218 AND ug.group_id = g.group_id'; 2219 $result = $db->sql_query($sql); 2220 $row = $db->sql_fetchrow($result); 2221 $db->sql_freeresult($result); 2222 $max_setting = (int) $row['max_setting']; 2223 2224 return $max_setting; 2225 } 2226 2227 /** 2228 * Generates an array of coloured recipient names from a list of PMs - (groups & users) 2229 * 2230 * @param array $pm_by_id An array of rows from PRIVMSGS_TABLE, keys are the msg_ids. 2231 * 2232 * @return array 2D Array: array(msg_id => array('username or group string', ...), ...) 2233 * Usernames are generated with {@link get_username_string get_username_string} 2234 * Groups are coloured and have a link to the membership page 2235 */ 2236 function get_recipient_strings($pm_by_id) 2237 { 2238 global $db, $phpbb_root_path, $phpEx, $user, $phpbb_container; 2239 2240 /** @var \phpbb\group\helper $group_helper */ 2241 $group_helper = $phpbb_container->get('group_helper'); 2242 2243 $address_list = $recipient_list = $address = array(); 2244 2245 $_types = array('u', 'g'); 2246 2247 foreach ($pm_by_id as $message_id => $row) 2248 { 2249 $address[$message_id] = rebuild_header(array('to' => $row['to_address'], 'bcc' => $row['bcc_address'])); 2250 2251 foreach ($_types as $ug_type) 2252 { 2253 if (isset($address[$message_id][$ug_type]) && count($address[$message_id][$ug_type])) 2254 { 2255 foreach ($address[$message_id][$ug_type] as $ug_id => $in_to) 2256 { 2257 $recipient_list[$ug_type][$ug_id] = array('name' => $user->lang['NA'], 'colour' => ''); 2258 } 2259 } 2260 } 2261 } 2262 2263 foreach ($_types as $ug_type) 2264 { 2265 if (!empty($recipient_list[$ug_type])) 2266 { 2267 if ($ug_type == 'u') 2268 { 2269 $sql = 'SELECT user_id as id, username as name, user_colour as colour 2270 FROM ' . USERS_TABLE . ' 2271 WHERE '; 2272 } 2273 else 2274 { 2275 $sql = 'SELECT group_id as id, group_name as name, group_colour as colour, group_type 2276 FROM ' . GROUPS_TABLE . ' 2277 WHERE '; 2278 } 2279 $sql .= $db->sql_in_set(($ug_type == 'u') ? 'user_id' : 'group_id', array_map('intval', array_keys($recipient_list[$ug_type]))); 2280 2281 $result = $db->sql_query($sql); 2282 2283 while ($row = $db->sql_fetchrow($result)) 2284 { 2285 if ($ug_type == 'g') 2286 { 2287 $row['name'] = $group_helper->get_name($row['name']); 2288 } 2289 2290 $recipient_list[$ug_type][$row['id']] = array('name' => $row['name'], 'colour' => $row['colour']); 2291 } 2292 $db->sql_freeresult($result); 2293 } 2294 } 2295 2296 foreach ($address as $message_id => $adr_ary) 2297 { 2298 foreach ($adr_ary as $type => $id_ary) 2299 { 2300 foreach ($id_ary as $ug_id => $_id) 2301 { 2302 if ($type == 'u') 2303 { 2304 $address_list[$message_id][] = get_username_string('full', $ug_id, $recipient_list[$type][$ug_id]['name'], $recipient_list[$type][$ug_id]['colour']); 2305 } 2306 else 2307 { 2308 $user_colour = ($recipient_list[$type][$ug_id]['colour']) ? ' style="font-weight: bold; color:#' . $recipient_list[$type][$ug_id]['colour'] . '"' : ''; 2309 $link = '<a href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&g=' . $ug_id) . '"' . $user_colour . '>'; 2310 $address_list[$message_id][] = $link . $recipient_list[$type][$ug_id]['name'] . (($link) ? '</a>' : ''); 2311 } 2312 } 2313 } 2314 } 2315 2316 return $address_list; 2317 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 25 19:05:08 2024 | Cross-referenced by PHPXref 0.7.1 |