[ Index ] |
PHP Cross Reference of phpBB-3.2.11-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 * @ignore 16 */ 17 if (!defined('IN_PHPBB')) 18 { 19 exit; 20 } 21 22 /** 23 * Fill smiley templates (or just the variables) with smilies, either in a window or inline 24 */ 25 function generate_smilies($mode, $forum_id) 26 { 27 global $db, $user, $config, $template, $phpbb_dispatcher, $request; 28 global $phpEx, $phpbb_root_path, $phpbb_container, $phpbb_path_helper; 29 30 /* @var $pagination \phpbb\pagination */ 31 $pagination = $phpbb_container->get('pagination'); 32 $base_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=smilies&f=' . $forum_id); 33 $start = $request->variable('start', 0); 34 35 if ($mode == 'window') 36 { 37 if ($forum_id) 38 { 39 $sql = 'SELECT forum_style 40 FROM ' . FORUMS_TABLE . " 41 WHERE forum_id = $forum_id"; 42 $result = $db->sql_query_limit($sql, 1); 43 $row = $db->sql_fetchrow($result); 44 $db->sql_freeresult($result); 45 46 $user->setup('posting', (int) $row['forum_style']); 47 } 48 else 49 { 50 $user->setup('posting'); 51 } 52 53 page_header($user->lang['SMILIES']); 54 55 $sql_ary = [ 56 'SELECT' => 'COUNT(s.smiley_id) AS item_count', 57 'FROM' => [ 58 SMILIES_TABLE => 's', 59 ], 60 'GROUP_BY' => 's.smiley_url', 61 ]; 62 63 /** 64 * Modify SQL query that fetches the total number of smilies in window mode 65 * 66 * @event core.generate_smilies_count_sql_before 67 * @var int forum_id Forum where smilies are generated 68 * @var array sql_ary Array with the SQL query 69 * @var string base_url URL for the "More smilies" link and its pagination 70 * @since 3.2.9-RC1 71 * @changed 3.2.10-RC1 Added base_url 72 */ 73 $vars = [ 74 'forum_id', 75 'sql_ary', 76 'base_url', 77 ]; 78 extract($phpbb_dispatcher->trigger_event('core.generate_smilies_count_sql_before', compact($vars))); 79 80 $sql = $db->sql_build_query('SELECT', $sql_ary); 81 $result = $db->sql_query($sql, 3600); 82 83 $smiley_count = 0; 84 while ($row = $db->sql_fetchrow($result)) 85 { 86 ++$smiley_count; 87 } 88 $db->sql_freeresult($result); 89 90 $template->set_filenames(array( 91 'body' => 'posting_smilies.html') 92 ); 93 94 $start = $pagination->validate_start($start, $config['smilies_per_page'], $smiley_count); 95 $pagination->generate_template_pagination($base_url, 'pagination', 'start', $smiley_count, $config['smilies_per_page'], $start); 96 } 97 98 $display_link = false; 99 if ($mode == 'inline') 100 { 101 $sql = 'SELECT smiley_id 102 FROM ' . SMILIES_TABLE . ' 103 WHERE display_on_posting = 0'; 104 $result = $db->sql_query_limit($sql, 1, 0, 3600); 105 106 if ($row = $db->sql_fetchrow($result)) 107 { 108 $display_link = true; 109 } 110 $db->sql_freeresult($result); 111 } 112 113 if ($mode == 'window') 114 { 115 $sql_ary = [ 116 'SELECT' => 's.smiley_url, MIN(s.emotion) AS emotion, MIN(s.code) AS code, s.smiley_width, s.smiley_height, MIN(s.smiley_order) AS min_smiley_order', 117 'FROM' => [ 118 SMILIES_TABLE => 's', 119 ], 120 'GROUP_BY' => 's.smiley_url, s.smiley_width, s.smiley_height', 121 'ORDER_BY' => 'min_smiley_order', 122 ]; 123 } 124 else 125 { 126 $sql_ary = [ 127 'SELECT' => 's.*', 128 'FROM' => [ 129 SMILIES_TABLE => 's', 130 ], 131 'WHERE' => 's.display_on_posting = 1', 132 'ORDER_BY' => 's.smiley_order', 133 ]; 134 } 135 136 /** 137 * Modify the SQL query that fetches the smilies 138 * 139 * @event core.generate_smilies_modify_sql 140 * @var string mode Smiley mode, either window or inline 141 * @var int forum_id Forum where smilies are generated, or 0 if composing a private message 142 * @var array sql_ary Array with SQL query data 143 * @since 3.2.10-RC1 144 * @since 3.3.1-RC1 145 */ 146 $vars = [ 147 'mode', 148 'forum_id', 149 'sql_ary', 150 ]; 151 extract($phpbb_dispatcher->trigger_event('core.generate_smilies_modify_sql', compact($vars))); 152 153 $sql = $db->sql_build_query('SELECT', $sql_ary); 154 155 if ($mode == 'window') 156 { 157 $result = $db->sql_query_limit($sql, $config['smilies_per_page'], $start, 3600); 158 } 159 else 160 { 161 $result = $db->sql_query($sql, 3600); 162 } 163 164 $smilies = array(); 165 while ($row = $db->sql_fetchrow($result)) 166 { 167 if (empty($smilies[$row['smiley_url']])) 168 { 169 $smilies[$row['smiley_url']] = $row; 170 } 171 } 172 $db->sql_freeresult($result); 173 174 /** 175 * Modify smilies before they are assigned to the template 176 * 177 * @event core.generate_smilies_modify_rowset 178 * @var string mode Smiley mode, either window or inline 179 * @var int forum_id Forum where smilies are generated, or 0 if composing a private message 180 * @var array smilies Smiley rows fetched from the database 181 * @since 3.2.9-RC1 182 */ 183 $vars = [ 184 'mode', 185 'forum_id', 186 'smilies', 187 ]; 188 extract($phpbb_dispatcher->trigger_event('core.generate_smilies_modify_rowset', compact($vars))); 189 190 if (count($smilies)) 191 { 192 $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_path_helper->get_web_root_path(); 193 194 foreach ($smilies as $row) 195 { 196 /** 197 * Modify smiley root path before populating smiley list 198 * 199 * @event core.generate_smilies_before 200 * @var string root_path root_path for smilies 201 * @since 3.1.11-RC1 202 */ 203 $vars = array('root_path'); 204 extract($phpbb_dispatcher->trigger_event('core.generate_smilies_before', compact($vars))); 205 $template->assign_block_vars('smiley', array( 206 'SMILEY_CODE' => $row['code'], 207 'A_SMILEY_CODE' => addslashes($row['code']), 208 'SMILEY_IMG' => $root_path . $config['smilies_path'] . '/' . $row['smiley_url'], 209 'SMILEY_WIDTH' => $row['smiley_width'], 210 'SMILEY_HEIGHT' => $row['smiley_height'], 211 'SMILEY_DESC' => $row['emotion']) 212 ); 213 } 214 } 215 216 /** 217 * This event is called after the smilies are populated 218 * 219 * @event core.generate_smilies_after 220 * @var string mode Mode of the smilies: window|inline 221 * @var int forum_id The forum ID we are currently in 222 * @var bool display_link Shall we display the "more smilies" link? 223 * @var string base_url URL for the "More smilies" link and its pagination 224 * @since 3.1.0-a1 225 * @changed 3.2.10-RC1 Added base_url 226 */ 227 $vars = [ 228 'mode', 229 'forum_id', 230 'display_link', 231 'base_url', 232 ]; 233 extract($phpbb_dispatcher->trigger_event('core.generate_smilies_after', compact($vars))); 234 235 if ($mode == 'inline' && $display_link) 236 { 237 $template->assign_vars(array( 238 'S_SHOW_SMILEY_LINK' => true, 239 'U_MORE_SMILIES' => $base_url, 240 )); 241 } 242 243 if ($mode == 'window') 244 { 245 page_footer(); 246 } 247 } 248 249 /** 250 * Update last post information 251 * Should be used instead of sync() if only the last post information are out of sync... faster 252 * 253 * @param string $type Can be forum|topic 254 * @param mixed $ids topic/forum ids 255 * @param bool $return_update_sql true: SQL query shall be returned, false: execute SQL 256 */ 257 function update_post_information($type, $ids, $return_update_sql = false) 258 { 259 global $db; 260 261 if (empty($ids)) 262 { 263 return; 264 } 265 if (!is_array($ids)) 266 { 267 $ids = array($ids); 268 } 269 270 $update_sql = $empty_forums = $not_empty_forums = array(); 271 272 if ($type != 'topic') 273 { 274 $topic_join = ', ' . TOPICS_TABLE . ' t'; 275 $topic_condition = 'AND t.topic_id = p.topic_id AND t.topic_visibility = ' . ITEM_APPROVED; 276 } 277 else 278 { 279 $topic_join = ''; 280 $topic_condition = ''; 281 } 282 283 if (count($ids) == 1) 284 { 285 $sql = 'SELECT p.post_id as last_post_id 286 FROM ' . POSTS_TABLE . " p $topic_join 287 WHERE " . $db->sql_in_set('p.' . $type . '_id', $ids) . " 288 $topic_condition 289 AND p.post_visibility = " . ITEM_APPROVED . " 290 ORDER BY p.post_id DESC"; 291 $result = $db->sql_query_limit($sql, 1); 292 } 293 else 294 { 295 $sql = 'SELECT p.' . $type . '_id, MAX(p.post_id) as last_post_id 296 FROM ' . POSTS_TABLE . " p $topic_join 297 WHERE " . $db->sql_in_set('p.' . $type . '_id', $ids) . " 298 $topic_condition 299 AND p.post_visibility = " . ITEM_APPROVED . " 300 GROUP BY p.{$type}_id"; 301 $result = $db->sql_query($sql); 302 } 303 304 $last_post_ids = array(); 305 while ($row = $db->sql_fetchrow($result)) 306 { 307 if (count($ids) == 1) 308 { 309 $row[$type . '_id'] = $ids[0]; 310 } 311 312 if ($type == 'forum') 313 { 314 $not_empty_forums[] = $row['forum_id']; 315 316 if (empty($row['last_post_id'])) 317 { 318 $empty_forums[] = $row['forum_id']; 319 } 320 } 321 322 $last_post_ids[] = $row['last_post_id']; 323 } 324 $db->sql_freeresult($result); 325 326 if ($type == 'forum') 327 { 328 $empty_forums = array_merge($empty_forums, array_diff($ids, $not_empty_forums)); 329 330 foreach ($empty_forums as $void => $forum_id) 331 { 332 $update_sql[$forum_id][] = 'forum_last_post_id = 0'; 333 $update_sql[$forum_id][] = "forum_last_post_subject = ''"; 334 $update_sql[$forum_id][] = 'forum_last_post_time = 0'; 335 $update_sql[$forum_id][] = 'forum_last_poster_id = 0'; 336 $update_sql[$forum_id][] = "forum_last_poster_name = ''"; 337 $update_sql[$forum_id][] = "forum_last_poster_colour = ''"; 338 } 339 } 340 341 if (count($last_post_ids)) 342 { 343 $sql = 'SELECT p.' . $type . '_id, p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour 344 FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u 345 WHERE p.poster_id = u.user_id 346 AND ' . $db->sql_in_set('p.post_id', $last_post_ids); 347 $result = $db->sql_query($sql); 348 349 while ($row = $db->sql_fetchrow($result)) 350 { 351 $update_sql[$row["{$type}_id"]][] = $type . '_last_post_id = ' . (int) $row['post_id']; 352 $update_sql[$row["{$type}_id"]][] = "{$type}_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'"; 353 $update_sql[$row["{$type}_id"]][] = $type . '_last_post_time = ' . (int) $row['post_time']; 354 $update_sql[$row["{$type}_id"]][] = $type . '_last_poster_id = ' . (int) $row['poster_id']; 355 $update_sql[$row["{$type}_id"]][] = "{$type}_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'"; 356 $update_sql[$row["{$type}_id"]][] = "{$type}_last_poster_name = '" . (($row['poster_id'] == ANONYMOUS) ? $db->sql_escape($row['post_username']) : $db->sql_escape($row['username'])) . "'"; 357 } 358 $db->sql_freeresult($result); 359 } 360 unset($empty_forums, $ids, $last_post_ids); 361 362 if ($return_update_sql || !count($update_sql)) 363 { 364 return $update_sql; 365 } 366 367 $table = ($type == 'forum') ? FORUMS_TABLE : TOPICS_TABLE; 368 369 foreach ($update_sql as $update_id => $update_sql_ary) 370 { 371 $sql = "UPDATE $table 372 SET " . implode(', ', $update_sql_ary) . " 373 WHERE {$type}_id = $update_id"; 374 $db->sql_query($sql); 375 } 376 377 return; 378 } 379 380 /** 381 * Generate Topic Icons for display 382 */ 383 function posting_gen_topic_icons($mode, $icon_id) 384 { 385 global $phpbb_root_path, $config, $template, $cache; 386 387 // Grab icons 388 $icons = $cache->obtain_icons(); 389 390 if (!$icon_id) 391 { 392 $template->assign_var('S_NO_ICON_CHECKED', ' checked="checked"'); 393 } 394 395 if (count($icons)) 396 { 397 $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path; 398 399 foreach ($icons as $id => $data) 400 { 401 if ($data['display']) 402 { 403 $template->assign_block_vars('topic_icon', array( 404 'ICON_ID' => $id, 405 'ICON_IMG' => $root_path . $config['icons_path'] . '/' . $data['img'], 406 'ICON_WIDTH' => $data['width'], 407 'ICON_HEIGHT' => $data['height'], 408 'ICON_ALT' => $data['alt'], 409 410 'S_CHECKED' => ($id == $icon_id) ? true : false, 411 'S_ICON_CHECKED' => ($id == $icon_id) ? ' checked="checked"' : '') 412 ); 413 } 414 } 415 416 return true; 417 } 418 419 return false; 420 } 421 422 /** 423 * Build topic types able to be selected 424 */ 425 function posting_gen_topic_types($forum_id, $cur_topic_type = POST_NORMAL) 426 { 427 global $auth, $user, $template; 428 429 $toggle = false; 430 431 $topic_types = array( 432 'sticky' => array('const' => POST_STICKY, 'lang' => 'POST_STICKY'), 433 'announce' => array('const' => POST_ANNOUNCE, 'lang' => 'POST_ANNOUNCEMENT'), 434 'announce_global' => array('const' => POST_GLOBAL, 'lang' => 'POST_GLOBAL') 435 ); 436 437 $topic_type_array = array(); 438 439 foreach ($topic_types as $auth_key => $topic_value) 440 { 441 if ($auth->acl_get('f_' . $auth_key, $forum_id)) 442 { 443 $toggle = true; 444 445 $topic_type_array[] = array( 446 'VALUE' => $topic_value['const'], 447 'S_CHECKED' => ($cur_topic_type == $topic_value['const']) ? ' checked="checked"' : '', 448 'L_TOPIC_TYPE' => $user->lang[$topic_value['lang']] 449 ); 450 } 451 } 452 453 if ($toggle) 454 { 455 $topic_type_array = array_merge(array(0 => array( 456 'VALUE' => POST_NORMAL, 457 'S_CHECKED' => ($cur_topic_type == POST_NORMAL) ? ' checked="checked"' : '', 458 'L_TOPIC_TYPE' => $user->lang['POST_NORMAL'])), 459 460 $topic_type_array 461 ); 462 463 foreach ($topic_type_array as $array) 464 { 465 $template->assign_block_vars('topic_type', $array); 466 } 467 468 $template->assign_vars(array( 469 'S_TOPIC_TYPE_STICKY' => ($auth->acl_get('f_sticky', $forum_id)), 470 'S_TOPIC_TYPE_ANNOUNCE' => ($auth->acl_gets('f_announce', 'f_announce_global', $forum_id)), 471 )); 472 } 473 474 return $toggle; 475 } 476 477 // 478 // Attachment related functions 479 // 480 481 /** 482 * Upload Attachment - filedata is generated here 483 * Uses upload class 484 * 485 * @deprecated 3.2.0-a1 (To be removed: 3.4.0) 486 * 487 * @param string $form_name The form name of the file upload input 488 * @param int $forum_id The id of the forum 489 * @param bool $local Whether the file is local or not 490 * @param string $local_storage The path to the local file 491 * @param bool $is_message Whether it is a PM or not 492 * @param array $local_filedata A filespec object created for the local file 493 * 494 * @return array File data array 495 */ 496 function upload_attachment($form_name, $forum_id, $local = false, $local_storage = '', $is_message = false, $local_filedata = false) 497 { 498 global $phpbb_container; 499 500 /** @var \phpbb\attachment\manager $attachment_manager */ 501 $attachment_manager = $phpbb_container->get('attachment.manager'); 502 $file = $attachment_manager->upload($form_name, $forum_id, $local, $local_storage, $is_message, $local_filedata); 503 unset($attachment_manager); 504 505 return $file; 506 } 507 508 /** 509 * Calculate the needed size for Thumbnail 510 */ 511 function get_img_size_format($width, $height) 512 { 513 global $config; 514 515 // Maximum Width the Image can take 516 $max_width = ($config['img_max_thumb_width']) ? $config['img_max_thumb_width'] : 400; 517 518 if ($width > $height) 519 { 520 return array( 521 round($width * ($max_width / $width)), 522 round($height * ($max_width / $width)) 523 ); 524 } 525 else 526 { 527 return array( 528 round($width * ($max_width / $height)), 529 round($height * ($max_width / $height)) 530 ); 531 } 532 } 533 534 /** 535 * Return supported image types 536 */ 537 function get_supported_image_types($type = false) 538 { 539 if (@extension_loaded('gd')) 540 { 541 $format = imagetypes(); 542 $new_type = 0; 543 544 if ($type !== false) 545 { 546 // Type is one of the IMAGETYPE constants - it is fetched from getimagesize() 547 switch ($type) 548 { 549 // GIF 550 case IMAGETYPE_GIF: 551 $new_type = ($format & IMG_GIF) ? IMG_GIF : false; 552 break; 553 554 // JPG, JPC, JP2 555 case IMAGETYPE_JPEG: 556 case IMAGETYPE_JPC: 557 case IMAGETYPE_JPEG2000: 558 case IMAGETYPE_JP2: 559 case IMAGETYPE_JPX: 560 case IMAGETYPE_JB2: 561 $new_type = ($format & IMG_JPG) ? IMG_JPG : false; 562 break; 563 564 // PNG 565 case IMAGETYPE_PNG: 566 $new_type = ($format & IMG_PNG) ? IMG_PNG : false; 567 break; 568 569 // WBMP 570 case IMAGETYPE_WBMP: 571 $new_type = ($format & IMG_WBMP) ? IMG_WBMP : false; 572 break; 573 } 574 } 575 else 576 { 577 $new_type = array(); 578 $go_through_types = array(IMG_GIF, IMG_JPG, IMG_PNG, IMG_WBMP); 579 580 foreach ($go_through_types as $check_type) 581 { 582 if ($format & $check_type) 583 { 584 $new_type[] = $check_type; 585 } 586 } 587 } 588 589 return array( 590 'gd' => ($new_type) ? true : false, 591 'format' => $new_type, 592 'version' => (function_exists('imagecreatetruecolor')) ? 2 : 1 593 ); 594 } 595 596 return array('gd' => false); 597 } 598 599 /** 600 * Create Thumbnail 601 */ 602 function create_thumbnail($source, $destination, $mimetype) 603 { 604 global $config, $phpbb_filesystem, $phpbb_dispatcher; 605 606 $min_filesize = (int) $config['img_min_thumb_filesize']; 607 $img_filesize = (file_exists($source)) ? @filesize($source) : false; 608 609 if (!$img_filesize || $img_filesize <= $min_filesize) 610 { 611 return false; 612 } 613 614 $dimension = @getimagesize($source); 615 616 if ($dimension === false) 617 { 618 return false; 619 } 620 621 list($width, $height, $type, ) = $dimension; 622 623 if (empty($width) || empty($height)) 624 { 625 return false; 626 } 627 628 list($new_width, $new_height) = get_img_size_format($width, $height); 629 630 // Do not create a thumbnail if the resulting width/height is bigger than the original one 631 if ($new_width >= $width && $new_height >= $height) 632 { 633 return false; 634 } 635 636 $thumbnail_created = false; 637 638 /** 639 * Create thumbnail event to replace GD thumbnail creation with for example ImageMagick 640 * 641 * @event core.thumbnail_create_before 642 * @var string source Image source path 643 * @var string destination Thumbnail destination path 644 * @var string mimetype Image mime type 645 * @var float new_width Calculated thumbnail width 646 * @var float new_height Calculated thumbnail height 647 * @var bool thumbnail_created Set to true to skip default GD thumbnail creation 648 * @since 3.2.4 649 */ 650 $vars = array( 651 'source', 652 'destination', 653 'mimetype', 654 'new_width', 655 'new_height', 656 'thumbnail_created', 657 ); 658 extract($phpbb_dispatcher->trigger_event('core.thumbnail_create_before', compact($vars))); 659 660 if (!$thumbnail_created) 661 { 662 $type = get_supported_image_types($type); 663 664 if ($type['gd']) 665 { 666 // If the type is not supported, we are not able to create a thumbnail 667 if ($type['format'] === false) 668 { 669 return false; 670 } 671 672 switch ($type['format']) 673 { 674 case IMG_GIF: 675 $image = @imagecreatefromgif($source); 676 break; 677 678 case IMG_JPG: 679 @ini_set('gd.jpeg_ignore_warning', 1); 680 $image = @imagecreatefromjpeg($source); 681 break; 682 683 case IMG_PNG: 684 $image = @imagecreatefrompng($source); 685 break; 686 687 case IMG_WBMP: 688 $image = @imagecreatefromwbmp($source); 689 break; 690 } 691 692 if (empty($image)) 693 { 694 return false; 695 } 696 697 if ($type['version'] == 1) 698 { 699 $new_image = imagecreate($new_width, $new_height); 700 701 if ($new_image === false) 702 { 703 return false; 704 } 705 706 imagecopyresized($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height); 707 } 708 else 709 { 710 $new_image = imagecreatetruecolor($new_width, $new_height); 711 712 if ($new_image === false) 713 { 714 return false; 715 } 716 717 // Preserve alpha transparency (png for example) 718 @imagealphablending($new_image, false); 719 @imagesavealpha($new_image, true); 720 721 imagecopyresampled($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height); 722 } 723 724 // If we are in safe mode create the destination file prior to using the gd functions to circumvent a PHP bug 725 if (@ini_get('safe_mode') || @strtolower(ini_get('safe_mode')) == 'on') 726 { 727 @touch($destination); 728 } 729 730 switch ($type['format']) 731 { 732 case IMG_GIF: 733 imagegif($new_image, $destination); 734 break; 735 736 case IMG_JPG: 737 imagejpeg($new_image, $destination, 90); 738 break; 739 740 case IMG_PNG: 741 imagepng($new_image, $destination); 742 break; 743 744 case IMG_WBMP: 745 imagewbmp($new_image, $destination); 746 break; 747 } 748 749 imagedestroy($new_image); 750 } 751 else 752 { 753 return false; 754 } 755 } 756 757 if (!file_exists($destination)) 758 { 759 return false; 760 } 761 762 try 763 { 764 $phpbb_filesystem->phpbb_chmod($destination, \phpbb\filesystem\filesystem_interface::CHMOD_READ | \phpbb\filesystem\filesystem_interface::CHMOD_WRITE); 765 } 766 catch (\phpbb\filesystem\exception\filesystem_exception $e) 767 { 768 // Do nothing 769 } 770 771 return true; 772 } 773 774 /** 775 * Assign Inline attachments (build option fields) 776 */ 777 function posting_gen_inline_attachments(&$attachment_data) 778 { 779 global $template; 780 781 if (count($attachment_data)) 782 { 783 $s_inline_attachment_options = ''; 784 785 foreach ($attachment_data as $i => $attachment) 786 { 787 $s_inline_attachment_options .= '<option value="' . $i . '">' . utf8_basename($attachment['real_filename']) . '</option>'; 788 } 789 790 $template->assign_var('S_INLINE_ATTACHMENT_OPTIONS', $s_inline_attachment_options); 791 792 return true; 793 } 794 795 return false; 796 } 797 798 /** 799 * Generate inline attachment entry 800 */ 801 function posting_gen_attachment_entry($attachment_data, &$filename_data, $show_attach_box = true) 802 { 803 global $template, $config, $phpbb_root_path, $phpEx, $user, $phpbb_dispatcher; 804 805 // Some default template variables 806 $template->assign_vars(array( 807 'S_SHOW_ATTACH_BOX' => $show_attach_box, 808 'S_HAS_ATTACHMENTS' => count($attachment_data), 809 'FILESIZE' => $config['max_filesize'], 810 'FILE_COMMENT' => (isset($filename_data['filecomment'])) ? $filename_data['filecomment'] : '', 811 )); 812 813 if (count($attachment_data)) 814 { 815 // We display the posted attachments within the desired order. 816 ($config['display_order']) ? krsort($attachment_data) : ksort($attachment_data); 817 818 $attachrow_template_vars = []; 819 820 foreach ($attachment_data as $count => $attach_row) 821 { 822 $hidden = ''; 823 $attach_row['real_filename'] = utf8_basename($attach_row['real_filename']); 824 825 foreach ($attach_row as $key => $value) 826 { 827 $hidden .= '<input type="hidden" name="attachment_data[' . $count . '][' . $key . ']" value="' . $value . '" />'; 828 } 829 830 $download_link = append_sid("{$phpbb_root_path}download/file.$phpEx", 'mode=view&id=' . (int) $attach_row['attach_id'], true, ($attach_row['is_orphan']) ? $user->session_id : false); 831 832 $attachrow_template_vars[(int) $attach_row['attach_id']] = array( 833 'FILENAME' => utf8_basename($attach_row['real_filename']), 834 'A_FILENAME' => addslashes(utf8_basename($attach_row['real_filename'])), 835 'FILE_COMMENT' => $attach_row['attach_comment'], 836 'ATTACH_ID' => $attach_row['attach_id'], 837 'S_IS_ORPHAN' => $attach_row['is_orphan'], 838 'ASSOC_INDEX' => $count, 839 'FILESIZE' => get_formatted_filesize($attach_row['filesize']), 840 841 'U_VIEW_ATTACHMENT' => $download_link, 842 'S_HIDDEN' => $hidden, 843 ); 844 } 845 846 /** 847 * Modify inline attachments template vars 848 * 849 * @event core.modify_inline_attachments_template_vars 850 * @var array attachment_data Array containing attachments data 851 * @var array attachrow_template_vars Array containing attachments template vars 852 * @since 3.2.2-RC1 853 */ 854 $vars = array('attachment_data', 'attachrow_template_vars'); 855 extract($phpbb_dispatcher->trigger_event('core.modify_inline_attachments_template_vars', compact($vars))); 856 857 $template->assign_block_vars_array('attach_row', $attachrow_template_vars); 858 } 859 860 return count($attachment_data); 861 } 862 863 // 864 // General Post functions 865 // 866 867 /** 868 * Load Drafts 869 */ 870 function load_drafts($topic_id = 0, $forum_id = 0, $id = 0, $pm_action = '', $msg_id = 0) 871 { 872 global $user, $db, $template, $auth; 873 global $phpbb_root_path, $phpbb_dispatcher, $phpEx; 874 875 $topic_ids = $forum_ids = $draft_rows = array(); 876 877 // Load those drafts not connected to forums/topics 878 // If forum_id == 0 AND topic_id == 0 then this is a PM draft 879 if (!$topic_id && !$forum_id) 880 { 881 $sql_and = ' AND d.forum_id = 0 AND d.topic_id = 0'; 882 } 883 else 884 { 885 $sql_and = ''; 886 $sql_and .= ($forum_id) ? ' AND d.forum_id = ' . (int) $forum_id : ''; 887 $sql_and .= ($topic_id) ? ' AND d.topic_id = ' . (int) $topic_id : ''; 888 } 889 890 $sql = 'SELECT d.*, f.forum_id, f.forum_name 891 FROM ' . DRAFTS_TABLE . ' d 892 LEFT JOIN ' . FORUMS_TABLE . ' f ON (f.forum_id = d.forum_id) 893 WHERE d.user_id = ' . $user->data['user_id'] . " 894 $sql_and 895 ORDER BY d.save_time DESC"; 896 $result = $db->sql_query($sql); 897 898 while ($row = $db->sql_fetchrow($result)) 899 { 900 if ($row['topic_id']) 901 { 902 $topic_ids[] = (int) $row['topic_id']; 903 } 904 $draft_rows[] = $row; 905 } 906 $db->sql_freeresult($result); 907 908 if (!count($draft_rows)) 909 { 910 return; 911 } 912 913 $topic_rows = array(); 914 if (count($topic_ids)) 915 { 916 $sql = 'SELECT topic_id, forum_id, topic_title, topic_poster 917 FROM ' . TOPICS_TABLE . ' 918 WHERE ' . $db->sql_in_set('topic_id', array_unique($topic_ids)); 919 $result = $db->sql_query($sql); 920 921 while ($row = $db->sql_fetchrow($result)) 922 { 923 $topic_rows[$row['topic_id']] = $row; 924 } 925 $db->sql_freeresult($result); 926 } 927 928 /** 929 * Drafts found and their topics 930 * Edit $draft_rows in order to add or remove drafts loaded 931 * 932 * @event core.load_drafts_draft_list_result 933 * @var array draft_rows The drafts query result. Includes its forum id and everything about the draft 934 * @var array topic_ids The list of topics got from the topics table 935 * @var array topic_rows The topics that draft_rows references 936 * @since 3.1.0-RC3 937 */ 938 $vars = array('draft_rows', 'topic_ids', 'topic_rows'); 939 extract($phpbb_dispatcher->trigger_event('core.load_drafts_draft_list_result', compact($vars))); 940 941 unset($topic_ids); 942 943 $template->assign_var('S_SHOW_DRAFTS', true); 944 945 foreach ($draft_rows as $draft) 946 { 947 $link_topic = $link_forum = $link_pm = false; 948 $view_url = $title = ''; 949 950 if (isset($topic_rows[$draft['topic_id']]) 951 && ( 952 ($topic_rows[$draft['topic_id']]['forum_id'] && $auth->acl_get('f_read', $topic_rows[$draft['topic_id']]['forum_id'])) 953 || 954 (!$topic_rows[$draft['topic_id']]['forum_id'] && $auth->acl_getf_global('f_read')) 955 )) 956 { 957 $topic_forum_id = ($topic_rows[$draft['topic_id']]['forum_id']) ? $topic_rows[$draft['topic_id']]['forum_id'] : $forum_id; 958 959 $link_topic = true; 960 $view_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $topic_forum_id . '&t=' . $draft['topic_id']); 961 $title = $topic_rows[$draft['topic_id']]['topic_title']; 962 963 $insert_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'f=' . $topic_forum_id . '&t=' . $draft['topic_id'] . '&mode=reply&d=' . $draft['draft_id']); 964 } 965 else if ($draft['forum_id'] && $auth->acl_get('f_read', $draft['forum_id'])) 966 { 967 $link_forum = true; 968 $view_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $draft['forum_id']); 969 $title = $draft['forum_name']; 970 971 $insert_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'f=' . $draft['forum_id'] . '&mode=post&d=' . $draft['draft_id']); 972 } 973 else 974 { 975 // Either display as PM draft if forum_id and topic_id are empty or if access to the forums has been denied afterwards... 976 $link_pm = true; 977 $insert_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=$id&mode=compose&d={$draft['draft_id']}" . (($pm_action) ? "&action=$pm_action" : '') . (($msg_id) ? "&p=$msg_id" : '')); 978 } 979 980 $template->assign_block_vars('draftrow', array( 981 'DRAFT_ID' => $draft['draft_id'], 982 'DATE' => $user->format_date($draft['save_time']), 983 'DRAFT_SUBJECT' => $draft['draft_subject'], 984 985 'TITLE' => $title, 986 'U_VIEW' => $view_url, 987 'U_INSERT' => $insert_url, 988 989 'S_LINK_PM' => $link_pm, 990 'S_LINK_TOPIC' => $link_topic, 991 'S_LINK_FORUM' => $link_forum) 992 ); 993 } 994 } 995 996 /** 997 * Topic Review 998 */ 999 function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id = 0, $show_quote_button = true) 1000 { 1001 global $user, $auth, $db, $template; 1002 global $config, $phpbb_root_path, $phpEx, $phpbb_container, $phpbb_dispatcher; 1003 1004 /* @var $phpbb_content_visibility \phpbb\content_visibility */ 1005 $phpbb_content_visibility = $phpbb_container->get('content.visibility'); 1006 $sql_sort = ($mode == 'post_review') ? 'ASC' : 'DESC'; 1007 1008 // Go ahead and pull all data for this topic 1009 $sql = 'SELECT p.post_id 1010 FROM ' . POSTS_TABLE . ' p' . " 1011 WHERE p.topic_id = $topic_id 1012 AND " . $phpbb_content_visibility->get_visibility_sql('post', $forum_id, 'p.') . ' 1013 ' . (($mode == 'post_review') ? " AND p.post_id > $cur_post_id" : '') . ' 1014 ' . (($mode == 'post_review_edit') ? " AND p.post_id = $cur_post_id" : '') . ' 1015 ORDER BY p.post_time ' . $sql_sort . ', p.post_id ' . $sql_sort; 1016 $result = $db->sql_query_limit($sql, $config['posts_per_page']); 1017 1018 $post_list = array(); 1019 1020 while ($row = $db->sql_fetchrow($result)) 1021 { 1022 $post_list[] = $row['post_id']; 1023 } 1024 1025 $db->sql_freeresult($result); 1026 1027 if (!count($post_list)) 1028 { 1029 return false; 1030 } 1031 1032 // Handle 'post_review_edit' like 'post_review' from now on 1033 if ($mode == 'post_review_edit') 1034 { 1035 $mode = 'post_review'; 1036 } 1037 1038 $sql_ary = array( 1039 'SELECT' => 'u.username, u.user_id, u.user_colour, p.*, z.friend, z.foe, uu.username as post_delete_username, uu.user_colour as post_delete_user_colour', 1040 1041 'FROM' => array( 1042 USERS_TABLE => 'u', 1043 POSTS_TABLE => 'p', 1044 ), 1045 1046 'LEFT_JOIN' => array( 1047 array( 1048 'FROM' => array(ZEBRA_TABLE => 'z'), 1049 'ON' => 'z.user_id = ' . $user->data['user_id'] . ' AND z.zebra_id = p.poster_id', 1050 ), 1051 array( 1052 'FROM' => array(USERS_TABLE => 'uu'), 1053 'ON' => 'uu.user_id = p.post_delete_user', 1054 ), 1055 ), 1056 1057 'WHERE' => $db->sql_in_set('p.post_id', $post_list) . ' 1058 AND u.user_id = p.poster_id', 1059 ); 1060 1061 /** 1062 * Event to modify the SQL query for topic reviews 1063 * 1064 * @event core.topic_review_modify_sql_ary 1065 * @var int topic_id The topic ID that is being reviewed 1066 * @var int forum_id The topic's forum ID 1067 * @var string mode The topic review mode 1068 * @var int cur_post_id Post offset ID 1069 * @var bool show_quote_button Flag indicating if the quote button should be displayed 1070 * @var array post_list Array with the post IDs 1071 * @var array sql_ary Array with the SQL query 1072 * @since 3.2.8-RC1 1073 */ 1074 $vars = array( 1075 'topic_id', 1076 'forum_id', 1077 'mode', 1078 'cur_post_id', 1079 'show_quote_button', 1080 'post_list', 1081 'sql_ary', 1082 ); 1083 extract($phpbb_dispatcher->trigger_event('core.topic_review_modify_sql_ary', compact($vars))); 1084 1085 $sql = $db->sql_build_query('SELECT', $sql_ary); 1086 $result = $db->sql_query($sql); 1087 1088 $rowset = array(); 1089 $has_attachments = false; 1090 while ($row = $db->sql_fetchrow($result)) 1091 { 1092 $rowset[$row['post_id']] = $row; 1093 1094 if ($row['post_attachment']) 1095 { 1096 $has_attachments = true; 1097 } 1098 } 1099 $db->sql_freeresult($result); 1100 1101 // Grab extensions 1102 $attachments = array(); 1103 if ($has_attachments && $auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id)) 1104 { 1105 // Get attachments... 1106 $sql = 'SELECT * 1107 FROM ' . ATTACHMENTS_TABLE . ' 1108 WHERE ' . $db->sql_in_set('post_msg_id', $post_list) . ' 1109 AND in_message = 0 1110 ORDER BY filetime DESC, post_msg_id ASC'; 1111 $result = $db->sql_query($sql); 1112 1113 while ($row = $db->sql_fetchrow($result)) 1114 { 1115 $attachments[$row['post_msg_id']][] = $row; 1116 } 1117 $db->sql_freeresult($result); 1118 } 1119 1120 /** 1121 * Event to modify the posts list for topic reviews 1122 * 1123 * @event core.topic_review_modify_post_list 1124 * @var array attachments Array with the post attachments data 1125 * @var int cur_post_id Post offset ID 1126 * @var int forum_id The topic's forum ID 1127 * @var string mode The topic review mode 1128 * @var array post_list Array with the post IDs 1129 * @var array rowset Array with the posts data 1130 * @var bool show_quote_button Flag indicating if the quote button should be displayed 1131 * @var int topic_id The topic ID that is being reviewed 1132 * @since 3.1.9-RC1 1133 */ 1134 $vars = array( 1135 'attachments', 1136 'cur_post_id', 1137 'forum_id', 1138 'mode', 1139 'post_list', 1140 'rowset', 1141 'show_quote_button', 1142 'topic_id', 1143 ); 1144 extract($phpbb_dispatcher->trigger_event('core.topic_review_modify_post_list', compact($vars))); 1145 1146 for ($i = 0, $end = count($post_list); $i < $end; ++$i) 1147 { 1148 // A non-existing rowset only happens if there was no user present for the entered poster_id 1149 // This could be a broken posts table. 1150 if (!isset($rowset[$post_list[$i]])) 1151 { 1152 continue; 1153 } 1154 1155 $row = $rowset[$post_list[$i]]; 1156 1157 $poster_id = $row['user_id']; 1158 $post_subject = $row['post_subject']; 1159 1160 $decoded_message = false; 1161 1162 if ($show_quote_button && $auth->acl_get('f_reply', $forum_id)) 1163 { 1164 $decoded_message = censor_text($row['post_text']); 1165 decode_message($decoded_message, $row['bbcode_uid']); 1166 1167 $decoded_message = bbcode_nl2br($decoded_message); 1168 } 1169 1170 $parse_flags = ($row['bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0); 1171 $parse_flags |= ($row['enable_smilies'] ? OPTION_FLAG_SMILIES : 0); 1172 $message = generate_text_for_display($row['post_text'], $row['bbcode_uid'], $row['bbcode_bitfield'], $parse_flags, true); 1173 1174 if (!empty($attachments[$row['post_id']])) 1175 { 1176 $update_count = array(); 1177 parse_attachments($forum_id, $message, $attachments[$row['post_id']], $update_count); 1178 } 1179 1180 $post_subject = censor_text($post_subject); 1181 1182 $post_anchor = ($mode == 'post_review') ? 'ppr' . $row['post_id'] : 'pr' . $row['post_id']; 1183 $u_show_post = append_sid($phpbb_root_path . 'viewtopic.' . $phpEx, "f=$forum_id&t=$topic_id&p={$row['post_id']}&view=show#p{$row['post_id']}"); 1184 1185 $l_deleted_message = ''; 1186 if ($row['post_visibility'] == ITEM_DELETED) 1187 { 1188 $display_postername = get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']); 1189 1190 // User having deleted the post also being the post author? 1191 if (!$row['post_delete_user'] || $row['post_delete_user'] == $poster_id) 1192 { 1193 $display_username = $display_postername; 1194 } 1195 else 1196 { 1197 $display_username = get_username_string('full', $row['post_delete_user'], $row['post_delete_username'], $row['post_delete_user_colour']); 1198 } 1199 1200 if ($row['post_delete_reason']) 1201 { 1202 $l_deleted_message = $user->lang('POST_DELETED_BY_REASON', $display_postername, $display_username, $user->format_date($row['post_delete_time'], false, true), $row['post_delete_reason']); 1203 } 1204 else 1205 { 1206 $l_deleted_message = $user->lang('POST_DELETED_BY', $display_postername, $display_username, $user->format_date($row['post_delete_time'], false, true)); 1207 } 1208 } 1209 1210 $post_row = array( 1211 'POST_AUTHOR_FULL' => get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), 1212 'POST_AUTHOR_COLOUR' => get_username_string('colour', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), 1213 'POST_AUTHOR' => get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), 1214 'U_POST_AUTHOR' => get_username_string('profile', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), 1215 1216 'S_HAS_ATTACHMENTS' => (!empty($attachments[$row['post_id']])) ? true : false, 1217 'S_FRIEND' => ($row['friend']) ? true : false, 1218 'S_IGNORE_POST' => ($row['foe']) ? true : false, 1219 'L_IGNORE_POST' => ($row['foe']) ? sprintf($user->lang['POST_BY_FOE'], get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), "<a href=\"{$u_show_post}\" onclick=\"phpbb.toggleDisplay('{$post_anchor}', 1); return false;\">", '</a>') : '', 1220 'S_POST_DELETED' => ($row['post_visibility'] == ITEM_DELETED) ? true : false, 1221 'L_DELETE_POST' => $l_deleted_message, 1222 1223 'POST_SUBJECT' => $post_subject, 1224 'MINI_POST_IMG' => $user->img('icon_post_target', $user->lang['POST']), 1225 'POST_DATE' => $user->format_date($row['post_time']), 1226 'MESSAGE' => $message, 1227 'DECODED_MESSAGE' => $decoded_message, 1228 'POST_ID' => $row['post_id'], 1229 'POST_TIME' => $row['post_time'], 1230 'USER_ID' => $row['user_id'], 1231 'U_MINI_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'p=' . $row['post_id']) . '#p' . $row['post_id'], 1232 'U_MCP_DETAILS' => ($auth->acl_get('m_info', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&mode=post_details&f=' . $forum_id . '&p=' . $row['post_id'], true, $user->session_id) : '', 1233 'POSTER_QUOTE' => ($show_quote_button && $auth->acl_get('f_reply', $forum_id)) ? addslashes(get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username'])) : '', 1234 ); 1235 1236 $current_row_number = $i; 1237 1238 /** 1239 * Event to modify the template data block for topic reviews 1240 * 1241 * @event core.topic_review_modify_row 1242 * @var string mode The review mode 1243 * @var int topic_id The topic that is being reviewed 1244 * @var int forum_id The topic's forum 1245 * @var int cur_post_id Post offset id 1246 * @var int current_row_number Number of the current row being iterated 1247 * @var array post_row Template block array of the current post 1248 * @var array row Array with original post and user data 1249 * @since 3.1.4-RC1 1250 */ 1251 $vars = array( 1252 'mode', 1253 'topic_id', 1254 'forum_id', 1255 'cur_post_id', 1256 'current_row_number', 1257 'post_row', 1258 'row', 1259 ); 1260 extract($phpbb_dispatcher->trigger_event('core.topic_review_modify_row', compact($vars))); 1261 1262 $template->assign_block_vars($mode . '_row', $post_row); 1263 1264 // Display not already displayed Attachments for this post, we already parsed them. ;) 1265 if (!empty($attachments[$row['post_id']])) 1266 { 1267 foreach ($attachments[$row['post_id']] as $attachment) 1268 { 1269 $template->assign_block_vars($mode . '_row.attachment', array( 1270 'DISPLAY_ATTACHMENT' => $attachment) 1271 ); 1272 } 1273 } 1274 1275 unset($rowset[$post_list[$i]]); 1276 } 1277 1278 if ($mode == 'topic_review') 1279 { 1280 $template->assign_var('QUOTE_IMG', $user->img('icon_post_quote', $user->lang['REPLY_WITH_QUOTE'])); 1281 } 1282 1283 return true; 1284 } 1285 1286 // 1287 // Post handling functions 1288 // 1289 1290 /** 1291 * Delete Post 1292 */ 1293 function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $softdelete_reason = '') 1294 { 1295 global $db, $user, $phpbb_container, $phpbb_dispatcher; 1296 global $config, $phpEx, $phpbb_root_path; 1297 1298 // Specify our post mode 1299 $post_mode = 'delete'; 1300 if (($data['topic_first_post_id'] === $data['topic_last_post_id']) && ($data['topic_posts_approved'] + $data['topic_posts_unapproved'] + $data['topic_posts_softdeleted'] == 1)) 1301 { 1302 $post_mode = 'delete_topic'; 1303 } 1304 else if ($data['topic_first_post_id'] == $post_id) 1305 { 1306 $post_mode = 'delete_first_post'; 1307 } 1308 else if ($data['topic_last_post_id'] == $post_id) 1309 { 1310 $post_mode = 'delete_last_post'; 1311 } 1312 $sql_data = array(); 1313 $next_post_id = false; 1314 1315 include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx); 1316 1317 $db->sql_transaction('begin'); 1318 1319 // we must make sure to update forums that contain the shadow'd topic 1320 if ($post_mode == 'delete_topic') 1321 { 1322 $shadow_forum_ids = array(); 1323 1324 $sql = 'SELECT forum_id 1325 FROM ' . TOPICS_TABLE . ' 1326 WHERE ' . $db->sql_in_set('topic_moved_id', $topic_id); 1327 $result = $db->sql_query($sql); 1328 while ($row = $db->sql_fetchrow($result)) 1329 { 1330 if (!isset($shadow_forum_ids[(int) $row['forum_id']])) 1331 { 1332 $shadow_forum_ids[(int) $row['forum_id']] = 1; 1333 } 1334 else 1335 { 1336 $shadow_forum_ids[(int) $row['forum_id']]++; 1337 } 1338 } 1339 $db->sql_freeresult($result); 1340 } 1341 1342 /* @var $phpbb_content_visibility \phpbb\content_visibility */ 1343 $phpbb_content_visibility = $phpbb_container->get('content.visibility'); 1344 1345 // (Soft) delete the post 1346 if ($is_soft && ($post_mode != 'delete_topic')) 1347 { 1348 $phpbb_content_visibility->set_post_visibility(ITEM_DELETED, $post_id, $topic_id, $forum_id, $user->data['user_id'], time(), $softdelete_reason, ($data['topic_first_post_id'] == $post_id), ($data['topic_last_post_id'] == $post_id)); 1349 } 1350 else if (!$is_soft) 1351 { 1352 if (!delete_posts('post_id', array($post_id), false, false, false)) 1353 { 1354 // Try to delete topic, we may had an previous error causing inconsistency 1355 if ($post_mode == 'delete_topic') 1356 { 1357 delete_topics('topic_id', array($topic_id), false); 1358 } 1359 trigger_error('ALREADY_DELETED'); 1360 } 1361 } 1362 1363 $db->sql_transaction('commit'); 1364 1365 // Collect the necessary information for updating the tables 1366 $sql_data[FORUMS_TABLE] = $sql_data[TOPICS_TABLE] = ''; 1367 switch ($post_mode) 1368 { 1369 case 'delete_topic': 1370 1371 foreach ($shadow_forum_ids as $updated_forum => $topic_count) 1372 { 1373 // counting is fun! we only have to do count($forum_ids) number of queries, 1374 // even if the topic is moved back to where its shadow lives (we count how many times it is in a forum) 1375 $sql = 'UPDATE ' . FORUMS_TABLE . ' 1376 SET forum_topics_approved = forum_topics_approved - ' . $topic_count . ' 1377 WHERE forum_id = ' . $updated_forum; 1378 $db->sql_query($sql); 1379 update_post_information('forum', $updated_forum); 1380 } 1381 1382 if ($is_soft) 1383 { 1384 $phpbb_content_visibility->set_topic_visibility(ITEM_DELETED, $topic_id, $forum_id, $user->data['user_id'], time(), $softdelete_reason); 1385 } 1386 else 1387 { 1388 delete_topics('topic_id', array($topic_id), false); 1389 1390 $phpbb_content_visibility->remove_topic_from_statistic($data, $sql_data); 1391 $config->increment('num_posts', -1, false); 1392 1393 $update_sql = update_post_information('forum', $forum_id, true); 1394 if (count($update_sql)) 1395 { 1396 $sql_data[FORUMS_TABLE] .= ($sql_data[FORUMS_TABLE]) ? ', ' : ''; 1397 $sql_data[FORUMS_TABLE] .= implode(', ', $update_sql[$forum_id]); 1398 } 1399 } 1400 1401 break; 1402 1403 case 'delete_first_post': 1404 $sql = 'SELECT p.post_id, p.poster_id, p.post_time, p.post_username, u.username, u.user_colour 1405 FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u 1406 WHERE p.topic_id = $topic_id 1407 AND p.poster_id = u.user_id 1408 AND p.post_visibility = " . ITEM_APPROVED . ' 1409 ORDER BY p.post_time ASC, p.post_id ASC'; 1410 $result = $db->sql_query_limit($sql, 1); 1411 $row = $db->sql_fetchrow($result); 1412 $db->sql_freeresult($result); 1413 1414 if (!$row) 1415 { 1416 // No approved post, so the first is a not-approved post (unapproved or soft deleted) 1417 $sql = 'SELECT p.post_id, p.poster_id, p.post_time, p.post_username, u.username, u.user_colour 1418 FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u 1419 WHERE p.topic_id = $topic_id 1420 AND p.poster_id = u.user_id 1421 ORDER BY p.post_time ASC, p.post_id ASC"; 1422 $result = $db->sql_query_limit($sql, 1); 1423 $row = $db->sql_fetchrow($result); 1424 $db->sql_freeresult($result); 1425 } 1426 1427 $next_post_id = (int) $row['post_id']; 1428 1429 $sql_data[TOPICS_TABLE] = $db->sql_build_array('UPDATE', array( 1430 'topic_poster' => (int) $row['poster_id'], 1431 'topic_first_post_id' => (int) $row['post_id'], 1432 'topic_first_poster_colour' => $row['user_colour'], 1433 'topic_first_poster_name' => ($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username'], 1434 'topic_time' => (int) $row['post_time'], 1435 )); 1436 break; 1437 1438 case 'delete_last_post': 1439 if (!$is_soft) 1440 { 1441 // Update last post information when hard deleting. Soft delete already did that by itself. 1442 $update_sql = update_post_information('forum', $forum_id, true); 1443 if (count($update_sql)) 1444 { 1445 $sql_data[FORUMS_TABLE] = (($sql_data[FORUMS_TABLE]) ? $sql_data[FORUMS_TABLE] . ', ' : '') . implode(', ', $update_sql[$forum_id]); 1446 } 1447 1448 $sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_bumped = 0, topic_bumper = 0'; 1449 1450 $update_sql = update_post_information('topic', $topic_id, true); 1451 if (!empty($update_sql)) 1452 { 1453 $sql_data[TOPICS_TABLE] .= ', ' . implode(', ', $update_sql[$topic_id]); 1454 $next_post_id = (int) str_replace('topic_last_post_id = ', '', $update_sql[$topic_id][0]); 1455 } 1456 } 1457 1458 if (!$next_post_id) 1459 { 1460 $sql = 'SELECT MAX(post_id) as last_post_id 1461 FROM ' . POSTS_TABLE . " 1462 WHERE topic_id = $topic_id 1463 AND " . $phpbb_content_visibility->get_visibility_sql('post', $forum_id); 1464 $result = $db->sql_query($sql); 1465 $next_post_id = (int) $db->sql_fetchfield('last_post_id'); 1466 $db->sql_freeresult($result); 1467 } 1468 break; 1469 1470 case 'delete': 1471 $sql = 'SELECT post_id 1472 FROM ' . POSTS_TABLE . " 1473 WHERE topic_id = $topic_id 1474 AND " . $phpbb_content_visibility->get_visibility_sql('post', $forum_id) . ' 1475 AND post_time > ' . $data['post_time'] . ' 1476 ORDER BY post_time ASC, post_id ASC'; 1477 $result = $db->sql_query_limit($sql, 1); 1478 $next_post_id = (int) $db->sql_fetchfield('post_id'); 1479 $db->sql_freeresult($result); 1480 break; 1481 } 1482 1483 if (($post_mode == 'delete') || ($post_mode == 'delete_last_post') || ($post_mode == 'delete_first_post')) 1484 { 1485 if (!$is_soft) 1486 { 1487 $phpbb_content_visibility->remove_post_from_statistic($data, $sql_data); 1488 } 1489 1490 $sql = 'SELECT 1 AS has_attachments 1491 FROM ' . ATTACHMENTS_TABLE . ' 1492 WHERE topic_id = ' . $topic_id; 1493 $result = $db->sql_query_limit($sql, 1); 1494 $has_attachments = (int) $db->sql_fetchfield('has_attachments'); 1495 $db->sql_freeresult($result); 1496 1497 if (!$has_attachments) 1498 { 1499 $sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_attachment = 0'; 1500 } 1501 } 1502 1503 $db->sql_transaction('begin'); 1504 1505 $where_sql = array( 1506 FORUMS_TABLE => "forum_id = $forum_id", 1507 TOPICS_TABLE => "topic_id = $topic_id", 1508 USERS_TABLE => 'user_id = ' . $data['poster_id'], 1509 ); 1510 1511 foreach ($sql_data as $table => $update_sql) 1512 { 1513 if ($update_sql) 1514 { 1515 $db->sql_query("UPDATE $table SET $update_sql WHERE " . $where_sql[$table]); 1516 } 1517 } 1518 1519 // Adjust posted info for this user by looking for a post by him/her within this topic... 1520 if ($post_mode != 'delete_topic' && $config['load_db_track'] && $data['poster_id'] != ANONYMOUS) 1521 { 1522 $sql = 'SELECT poster_id 1523 FROM ' . POSTS_TABLE . ' 1524 WHERE topic_id = ' . $topic_id . ' 1525 AND poster_id = ' . $data['poster_id']; 1526 $result = $db->sql_query_limit($sql, 1); 1527 $poster_id = (int) $db->sql_fetchfield('poster_id'); 1528 $db->sql_freeresult($result); 1529 1530 // The user is not having any more posts within this topic 1531 if (!$poster_id) 1532 { 1533 $sql = 'DELETE FROM ' . TOPICS_POSTED_TABLE . ' 1534 WHERE topic_id = ' . $topic_id . ' 1535 AND user_id = ' . $data['poster_id']; 1536 $db->sql_query($sql); 1537 } 1538 } 1539 1540 $db->sql_transaction('commit'); 1541 1542 if ($data['post_reported'] && ($post_mode != 'delete_topic')) 1543 { 1544 sync('topic_reported', 'topic_id', array($topic_id)); 1545 } 1546 1547 /** 1548 * This event is used for performing actions directly after a post or topic 1549 * has been deleted. 1550 * 1551 * @event core.delete_post_after 1552 * @var int forum_id Post forum ID 1553 * @var int topic_id Post topic ID 1554 * @var int post_id Post ID 1555 * @var array data Post data 1556 * @var bool is_soft Soft delete flag 1557 * @var string softdelete_reason Soft delete reason 1558 * @var string post_mode delete_topic, delete_first_post, delete_last_post or delete 1559 * @var mixed next_post_id Next post ID in the topic (post ID or false) 1560 * 1561 * @since 3.1.11-RC1 1562 */ 1563 $vars = array( 1564 'forum_id', 1565 'topic_id', 1566 'post_id', 1567 'data', 1568 'is_soft', 1569 'softdelete_reason', 1570 'post_mode', 1571 'next_post_id', 1572 ); 1573 extract($phpbb_dispatcher->trigger_event('core.delete_post_after', compact($vars))); 1574 1575 return $next_post_id; 1576 } 1577 1578 /** 1579 * Submit Post 1580 * @todo Split up and create lightweight, simple API for this. 1581 */ 1582 function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data_ary, $update_message = true, $update_search_index = true) 1583 { 1584 global $db, $auth, $user, $config, $phpEx, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher, $phpbb_log, $request; 1585 1586 $poll = $poll_ary; 1587 $data = $data_ary; 1588 /** 1589 * Modify the data for post submitting 1590 * 1591 * @event core.modify_submit_post_data 1592 * @var string mode Variable containing posting mode value 1593 * @var string subject Variable containing post subject value 1594 * @var string username Variable containing post author name 1595 * @var int topic_type Variable containing topic type value 1596 * @var array poll Array with the poll data for the post 1597 * @var array data Array with the data for the post 1598 * @var bool update_message Flag indicating if the post will be updated 1599 * @var bool update_search_index Flag indicating if the search index will be updated 1600 * @since 3.1.0-a4 1601 */ 1602 $vars = array( 1603 'mode', 1604 'subject', 1605 'username', 1606 'topic_type', 1607 'poll', 1608 'data', 1609 'update_message', 1610 'update_search_index', 1611 ); 1612 extract($phpbb_dispatcher->trigger_event('core.modify_submit_post_data', compact($vars))); 1613 $poll_ary = $poll; 1614 $data_ary = $data; 1615 unset($poll); 1616 unset($data); 1617 1618 // We do not handle erasing posts here 1619 if ($mode == 'delete') 1620 { 1621 return false; 1622 } 1623 1624 if (!empty($data_ary['post_time'])) 1625 { 1626 $current_time = $data_ary['post_time']; 1627 } 1628 else 1629 { 1630 $current_time = time(); 1631 } 1632 1633 if ($mode == 'post') 1634 { 1635 $post_mode = 'post'; 1636 $update_message = true; 1637 } 1638 else if ($mode != 'edit') 1639 { 1640 $post_mode = 'reply'; 1641 $update_message = true; 1642 } 1643 else if ($mode == 'edit') 1644 { 1645 $post_mode = ($data_ary['topic_posts_approved'] + $data_ary['topic_posts_unapproved'] + $data_ary['topic_posts_softdeleted'] == 1) ? 'edit_topic' : (($data_ary['topic_first_post_id'] == $data_ary['post_id']) ? 'edit_first_post' : (($data_ary['topic_last_post_id'] == $data_ary['post_id']) ? 'edit_last_post' : 'edit')); 1646 } 1647 1648 // First of all make sure the subject and topic title are having the correct length. 1649 // To achieve this without cutting off between special chars we convert to an array and then count the elements. 1650 $subject = truncate_string($subject, 120); 1651 $data_ary['topic_title'] = truncate_string($data_ary['topic_title'], 120); 1652 1653 // Collect some basic information about which tables and which rows to update/insert 1654 $sql_data = $topic_row = array(); 1655 $poster_id = ($mode == 'edit') ? $data_ary['poster_id'] : (int) $user->data['user_id']; 1656 1657 // Retrieve some additional information if not present 1658 if ($mode == 'edit' && (!isset($data_ary['post_visibility']) || !isset($data_ary['topic_visibility']) || $data_ary['post_visibility'] === false || $data_ary['topic_visibility'] === false)) 1659 { 1660 $sql = 'SELECT p.post_visibility, t.topic_type, t.topic_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, t.topic_visibility 1661 FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p 1662 WHERE t.topic_id = p.topic_id 1663 AND p.post_id = ' . $data_ary['post_id']; 1664 $result = $db->sql_query($sql); 1665 $topic_row = $db->sql_fetchrow($result); 1666 $db->sql_freeresult($result); 1667 1668 $data_ary['topic_visibility'] = $topic_row['topic_visibility']; 1669 $data_ary['post_visibility'] = $topic_row['post_visibility']; 1670 } 1671 1672 // This variable indicates if the user is able to post or put into the queue 1673 $post_visibility = ITEM_APPROVED; 1674 1675 // Check the permissions for post approval. 1676 // Moderators must go through post approval like ordinary users. 1677 if (!$auth->acl_get('f_noapprove', $data_ary['forum_id'])) 1678 { 1679 // Post not approved, but in queue 1680 $post_visibility = ITEM_UNAPPROVED; 1681 switch ($post_mode) 1682 { 1683 case 'edit_first_post': 1684 case 'edit': 1685 case 'edit_last_post': 1686 case 'edit_topic': 1687 $post_visibility = ITEM_REAPPROVE; 1688 break; 1689 } 1690 } 1691 else if (isset($data_ary['post_visibility']) && $data_ary['post_visibility'] !== false) 1692 { 1693 $post_visibility = $data_ary['post_visibility']; 1694 } 1695 1696 // MODs/Extensions are able to force any visibility on posts 1697 if (isset($data_ary['force_approved_state'])) 1698 { 1699 $post_visibility = (in_array((int) $data_ary['force_approved_state'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED, ITEM_REAPPROVE))) ? (int) $data_ary['force_approved_state'] : $post_visibility; 1700 } 1701 if (isset($data_ary['force_visibility'])) 1702 { 1703 $post_visibility = (in_array((int) $data_ary['force_visibility'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED, ITEM_REAPPROVE))) ? (int) $data_ary['force_visibility'] : $post_visibility; 1704 } 1705 1706 // Start the transaction here 1707 $db->sql_transaction('begin'); 1708 1709 // Collect Information 1710 switch ($post_mode) 1711 { 1712 case 'post': 1713 case 'reply': 1714 $sql_data[POSTS_TABLE]['sql'] = array( 1715 'forum_id' => $data_ary['forum_id'], 1716 'poster_id' => (int) $user->data['user_id'], 1717 'icon_id' => $data_ary['icon_id'], 1718 'poster_ip' => $user->ip, 1719 'post_time' => $current_time, 1720 'post_visibility' => $post_visibility, 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 'post_username' => (!$user->data['is_registered']) ? $username : '', 1726 'post_subject' => $subject, 1727 'post_text' => $data_ary['message'], 1728 'post_checksum' => $data_ary['message_md5'], 1729 'post_attachment' => (!empty($data_ary['attachment_data'])) ? 1 : 0, 1730 'bbcode_bitfield' => $data_ary['bbcode_bitfield'], 1731 'bbcode_uid' => $data_ary['bbcode_uid'], 1732 'post_postcount' => ($auth->acl_get('f_postcount', $data_ary['forum_id'])) ? 1 : 0, 1733 'post_edit_locked' => $data_ary['post_edit_locked'] 1734 ); 1735 break; 1736 1737 case 'edit_first_post': 1738 case 'edit': 1739 1740 case 'edit_last_post': 1741 case 'edit_topic': 1742 1743 // If edit reason is given always display edit info 1744 1745 // If editing last post then display no edit info 1746 // If m_edit permission then display no edit info 1747 // If normal edit display edit info 1748 1749 // Display edit info if edit reason given or user is editing his post, which is not the last within the topic. 1750 if ($data_ary['post_edit_reason'] || (!$auth->acl_get('m_edit', $data_ary['forum_id']) && ($post_mode == 'edit' || $post_mode == 'edit_first_post'))) 1751 { 1752 $data_ary['post_edit_reason'] = truncate_string($data_ary['post_edit_reason'], 255, 255, false); 1753 1754 $sql_data[POSTS_TABLE]['sql'] = array( 1755 'post_edit_time' => $current_time, 1756 'post_edit_reason' => $data_ary['post_edit_reason'], 1757 'post_edit_user' => (int) $data_ary['post_edit_user'], 1758 ); 1759 1760 $sql_data[POSTS_TABLE]['stat'][] = 'post_edit_count = post_edit_count + 1'; 1761 } 1762 else if (!$data_ary['post_edit_reason'] && $mode == 'edit' && $auth->acl_get('m_edit', $data_ary['forum_id'])) 1763 { 1764 $sql_data[POSTS_TABLE]['sql'] = array( 1765 'post_edit_reason' => '', 1766 ); 1767 } 1768 1769 // If the person editing this post is different to the one having posted then we will add a log entry stating the edit 1770 // Could be simplified by only adding to the log if the edit is not tracked - but this may confuse admins/mods 1771 if ($user->data['user_id'] != $poster_id) 1772 { 1773 $log_subject = ($subject) ? $subject : $data_ary['topic_title']; 1774 $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_POST_EDITED', false, array( 1775 'forum_id' => $data_ary['forum_id'], 1776 'topic_id' => $data_ary['topic_id'], 1777 'post_id' => $data_ary['post_id'], 1778 $log_subject, 1779 (!empty($username)) ? $username : $user->lang['GUEST'], 1780 $data_ary['post_edit_reason'] 1781 )); 1782 } 1783 1784 if (!isset($sql_data[POSTS_TABLE]['sql'])) 1785 { 1786 $sql_data[POSTS_TABLE]['sql'] = array(); 1787 } 1788 1789 $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array( 1790 'forum_id' => $data_ary['forum_id'], 1791 'poster_id' => $data_ary['poster_id'], 1792 'icon_id' => $data_ary['icon_id'], 1793 // We will change the visibility later 1794 //'post_visibility' => $post_visibility, 1795 'enable_bbcode' => $data_ary['enable_bbcode'], 1796 'enable_smilies' => $data_ary['enable_smilies'], 1797 'enable_magic_url' => $data_ary['enable_urls'], 1798 'enable_sig' => $data_ary['enable_sig'], 1799 'post_username' => ($username && $data_ary['poster_id'] == ANONYMOUS) ? $username : '', 1800 'post_subject' => $subject, 1801 'post_checksum' => $data_ary['message_md5'], 1802 'post_attachment' => (!empty($data_ary['attachment_data'])) ? 1 : 0, 1803 'bbcode_bitfield' => $data_ary['bbcode_bitfield'], 1804 'bbcode_uid' => $data_ary['bbcode_uid'], 1805 'post_edit_locked' => $data_ary['post_edit_locked']) 1806 ); 1807 1808 if ($update_message) 1809 { 1810 $sql_data[POSTS_TABLE]['sql']['post_text'] = $data_ary['message']; 1811 } 1812 1813 break; 1814 } 1815 1816 // And the topic ladies and gentlemen 1817 switch ($post_mode) 1818 { 1819 case 'post': 1820 $sql_data[TOPICS_TABLE]['sql'] = array( 1821 'topic_poster' => (int) $user->data['user_id'], 1822 'topic_time' => $current_time, 1823 'topic_last_view_time' => $current_time, 1824 'forum_id' => $data_ary['forum_id'], 1825 'icon_id' => $data_ary['icon_id'], 1826 'topic_posts_approved' => ($post_visibility == ITEM_APPROVED) ? 1 : 0, 1827 'topic_posts_softdeleted' => ($post_visibility == ITEM_DELETED) ? 1 : 0, 1828 'topic_posts_unapproved' => ($post_visibility == ITEM_UNAPPROVED) ? 1 : 0, 1829 'topic_visibility' => $post_visibility, 1830 'topic_delete_user' => ($post_visibility != ITEM_APPROVED) ? (int) $user->data['user_id'] : 0, 1831 'topic_title' => $subject, 1832 'topic_first_poster_name' => (!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : ''), 1833 'topic_first_poster_colour' => $user->data['user_colour'], 1834 'topic_type' => $topic_type, 1835 'topic_time_limit' => $topic_type != POST_NORMAL ? ($data_ary['topic_time_limit'] * 86400) : 0, 1836 'topic_attachment' => (!empty($data_ary['attachment_data'])) ? 1 : 0, 1837 'topic_status' => (isset($data_ary['topic_status'])) ? $data_ary['topic_status'] : ITEM_UNLOCKED, 1838 ); 1839 1840 if (isset($poll_ary['poll_options']) && !empty($poll_ary['poll_options'])) 1841 { 1842 $poll_start = ($poll_ary['poll_start']) ? $poll_ary['poll_start'] : $current_time; 1843 $poll_length = $poll_ary['poll_length'] * 86400; 1844 if ($poll_length < 0) 1845 { 1846 $poll_start = $poll_start + $poll_length; 1847 if ($poll_start < 0) 1848 { 1849 $poll_start = 0; 1850 } 1851 $poll_length = 1; 1852 } 1853 1854 $sql_data[TOPICS_TABLE]['sql'] = array_merge($sql_data[TOPICS_TABLE]['sql'], array( 1855 'poll_title' => $poll_ary['poll_title'], 1856 'poll_start' => $poll_start, 1857 'poll_max_options' => $poll_ary['poll_max_options'], 1858 'poll_length' => $poll_length, 1859 'poll_vote_change' => $poll_ary['poll_vote_change']) 1860 ); 1861 } 1862 1863 $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data_ary['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : ''); 1864 1865 if ($post_visibility == ITEM_APPROVED) 1866 { 1867 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_approved = forum_topics_approved + 1'; 1868 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_approved = forum_posts_approved + 1'; 1869 } 1870 else if ($post_visibility == ITEM_UNAPPROVED) 1871 { 1872 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_unapproved = forum_topics_unapproved + 1'; 1873 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_unapproved = forum_posts_unapproved + 1'; 1874 } 1875 else if ($post_visibility == ITEM_DELETED) 1876 { 1877 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_softdeleted = forum_topics_softdeleted + 1'; 1878 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_softdeleted = forum_posts_softdeleted + 1'; 1879 } 1880 break; 1881 1882 case 'reply': 1883 $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_view_time = ' . $current_time . ', 1884 topic_bumped = 0, 1885 topic_bumper = 0' . 1886 (($post_visibility == ITEM_APPROVED) ? ', topic_posts_approved = topic_posts_approved + 1' : '') . 1887 (($post_visibility == ITEM_UNAPPROVED) ? ', topic_posts_unapproved = topic_posts_unapproved + 1' : '') . 1888 (($post_visibility == ITEM_DELETED) ? ', topic_posts_softdeleted = topic_posts_softdeleted + 1' : '') . 1889 ((!empty($data_ary['attachment_data']) || (isset($data_ary['topic_attachment']) && $data_ary['topic_attachment'])) ? ', topic_attachment = 1' : ''); 1890 1891 $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data_ary['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : ''); 1892 1893 if ($post_visibility == ITEM_APPROVED) 1894 { 1895 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_approved = forum_posts_approved + 1'; 1896 } 1897 else if ($post_visibility == ITEM_UNAPPROVED) 1898 { 1899 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_unapproved = forum_posts_unapproved + 1'; 1900 } 1901 else if ($post_visibility == ITEM_DELETED) 1902 { 1903 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_softdeleted = forum_posts_softdeleted + 1'; 1904 } 1905 break; 1906 1907 case 'edit_topic': 1908 case 'edit_first_post': 1909 if (isset($poll_ary['poll_options'])) 1910 { 1911 $poll_start = ($poll_ary['poll_start'] || empty($poll_ary['poll_options'])) ? $poll_ary['poll_start'] : $current_time; 1912 $poll_length = $poll_ary['poll_length'] * 86400; 1913 if ($poll_length < 0) 1914 { 1915 $poll_start = $poll_start + $poll_length; 1916 if ($poll_start < 0) 1917 { 1918 $poll_start = 0; 1919 } 1920 $poll_length = 1; 1921 } 1922 } 1923 1924 $sql_data[TOPICS_TABLE]['sql'] = array( 1925 'forum_id' => $data_ary['forum_id'], 1926 'icon_id' => $data_ary['icon_id'], 1927 'topic_title' => $subject, 1928 'topic_first_poster_name' => $username, 1929 'topic_type' => $topic_type, 1930 'topic_time_limit' => $topic_type != POST_NORMAL ? ($data_ary['topic_time_limit'] * 86400) : 0, 1931 'poll_title' => (isset($poll_ary['poll_options'])) ? $poll_ary['poll_title'] : '', 1932 'poll_start' => (isset($poll_ary['poll_options'])) ? $poll_start : 0, 1933 'poll_max_options' => (isset($poll_ary['poll_options'])) ? $poll_ary['poll_max_options'] : 1, 1934 'poll_length' => (isset($poll_ary['poll_options'])) ? $poll_length : 0, 1935 'poll_vote_change' => (isset($poll_ary['poll_vote_change'])) ? $poll_ary['poll_vote_change'] : 0, 1936 'topic_last_view_time' => $current_time, 1937 1938 'topic_attachment' => (!empty($data_ary['attachment_data'])) ? 1 : (isset($data_ary['topic_attachment']) ? $data_ary['topic_attachment'] : 0), 1939 ); 1940 1941 break; 1942 } 1943 1944 $poll = $poll_ary; 1945 $data = $data_ary; 1946 /** 1947 * Modify sql query data for post submitting 1948 * 1949 * @event core.submit_post_modify_sql_data 1950 * @var array data Array with the data for the post 1951 * @var array poll Array with the poll data for the post 1952 * @var string post_mode Variable containing posting mode value 1953 * @var bool sql_data Array with the data for the posting SQL query 1954 * @var string subject Variable containing post subject value 1955 * @var int topic_type Variable containing topic type value 1956 * @var string username Variable containing post author name 1957 * @since 3.1.3-RC1 1958 */ 1959 $vars = array( 1960 'data', 1961 'poll', 1962 'post_mode', 1963 'sql_data', 1964 'subject', 1965 'topic_type', 1966 'username', 1967 ); 1968 extract($phpbb_dispatcher->trigger_event('core.submit_post_modify_sql_data', compact($vars))); 1969 $poll_ary = $poll; 1970 $data_ary = $data; 1971 unset($poll); 1972 unset($data); 1973 1974 // Submit new topic 1975 if ($post_mode == 'post') 1976 { 1977 $sql = 'INSERT INTO ' . TOPICS_TABLE . ' ' . 1978 $db->sql_build_array('INSERT', $sql_data[TOPICS_TABLE]['sql']); 1979 $db->sql_query($sql); 1980 1981 $data_ary['topic_id'] = $db->sql_nextid(); 1982 1983 $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array( 1984 'topic_id' => $data_ary['topic_id']) 1985 ); 1986 unset($sql_data[TOPICS_TABLE]['sql']); 1987 } 1988 1989 // Submit new post 1990 if ($post_mode == 'post' || $post_mode == 'reply') 1991 { 1992 if ($post_mode == 'reply') 1993 { 1994 $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array( 1995 'topic_id' => $data_ary['topic_id'], 1996 )); 1997 } 1998 1999 $sql = 'INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data[POSTS_TABLE]['sql']); 2000 $db->sql_query($sql); 2001 $data_ary['post_id'] = $db->sql_nextid(); 2002 2003 if ($post_mode == 'post' || $post_visibility == ITEM_APPROVED) 2004 { 2005 $sql_data[TOPICS_TABLE]['sql'] = array( 2006 'topic_last_post_id' => $data_ary['post_id'], 2007 'topic_last_post_time' => $current_time, 2008 'topic_last_poster_id' => $sql_data[POSTS_TABLE]['sql']['poster_id'], 2009 'topic_last_poster_name' => ($user->data['user_id'] == ANONYMOUS) ? $sql_data[POSTS_TABLE]['sql']['post_username'] : $user->data['username'], 2010 'topic_last_poster_colour' => $user->data['user_colour'], 2011 'topic_last_post_subject' => (string) $subject, 2012 ); 2013 } 2014 2015 if ($post_mode == 'post') 2016 { 2017 $sql_data[TOPICS_TABLE]['sql']['topic_first_post_id'] = $data_ary['post_id']; 2018 } 2019 2020 // Update total post count and forum information 2021 if ($post_visibility == ITEM_APPROVED) 2022 { 2023 if ($post_mode == 'post') 2024 { 2025 $config->increment('num_topics', 1, false); 2026 } 2027 $config->increment('num_posts', 1, false); 2028 2029 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . $data_ary['post_id']; 2030 $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'"; 2031 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . $current_time; 2032 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $user->data['user_id']; 2033 $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape((!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : '')) . "'"; 2034 $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($user->data['user_colour']) . "'"; 2035 } 2036 2037 unset($sql_data[POSTS_TABLE]['sql']); 2038 } 2039 2040 // Update the topics table 2041 if (isset($sql_data[TOPICS_TABLE]['sql'])) 2042 { 2043 $sql = 'UPDATE ' . TOPICS_TABLE . ' 2044 SET ' . $db->sql_build_array('UPDATE', $sql_data[TOPICS_TABLE]['sql']) . ' 2045 WHERE topic_id = ' . $data_ary['topic_id']; 2046 $db->sql_query($sql); 2047 2048 unset($sql_data[TOPICS_TABLE]['sql']); 2049 } 2050 2051 // Update the posts table 2052 if (isset($sql_data[POSTS_TABLE]['sql'])) 2053 { 2054 $sql = 'UPDATE ' . POSTS_TABLE . ' 2055 SET ' . $db->sql_build_array('UPDATE', $sql_data[POSTS_TABLE]['sql']) . ' 2056 WHERE post_id = ' . $data_ary['post_id']; 2057 $db->sql_query($sql); 2058 2059 unset($sql_data[POSTS_TABLE]['sql']); 2060 } 2061 2062 // Update Poll Tables 2063 if (isset($poll_ary['poll_options'])) 2064 { 2065 $cur_poll_options = array(); 2066 2067 if ($mode == 'edit') 2068 { 2069 $sql = 'SELECT * 2070 FROM ' . POLL_OPTIONS_TABLE . ' 2071 WHERE topic_id = ' . $data_ary['topic_id'] . ' 2072 ORDER BY poll_option_id'; 2073 $result = $db->sql_query($sql); 2074 2075 $cur_poll_options = array(); 2076 while ($row = $db->sql_fetchrow($result)) 2077 { 2078 $cur_poll_options[] = $row; 2079 } 2080 $db->sql_freeresult($result); 2081 } 2082 2083 $sql_insert_ary = array(); 2084 2085 for ($i = 0, $size = count($poll_ary['poll_options']); $i < $size; $i++) 2086 { 2087 if (strlen(trim($poll_ary['poll_options'][$i]))) 2088 { 2089 if (empty($cur_poll_options[$i])) 2090 { 2091 // If we add options we need to put them to the end to be able to preserve votes... 2092 $sql_insert_ary[] = array( 2093 'poll_option_id' => (int) count($cur_poll_options) + 1 + count($sql_insert_ary), 2094 'topic_id' => (int) $data_ary['topic_id'], 2095 'poll_option_text' => (string) $poll_ary['poll_options'][$i] 2096 ); 2097 } 2098 else if ($poll_ary['poll_options'][$i] != $cur_poll_options[$i]) 2099 { 2100 $sql = 'UPDATE ' . POLL_OPTIONS_TABLE . " 2101 SET poll_option_text = '" . $db->sql_escape($poll_ary['poll_options'][$i]) . "' 2102 WHERE poll_option_id = " . $cur_poll_options[$i]['poll_option_id'] . ' 2103 AND topic_id = ' . $data_ary['topic_id']; 2104 $db->sql_query($sql); 2105 } 2106 } 2107 } 2108 2109 $db->sql_multi_insert(POLL_OPTIONS_TABLE, $sql_insert_ary); 2110 2111 if (count($poll_ary['poll_options']) < count($cur_poll_options)) 2112 { 2113 $sql = 'DELETE FROM ' . POLL_OPTIONS_TABLE . ' 2114 WHERE poll_option_id > ' . count($poll_ary['poll_options']) . ' 2115 AND topic_id = ' . $data_ary['topic_id']; 2116 $db->sql_query($sql); 2117 } 2118 2119 // If edited, we would need to reset votes (since options can be re-ordered above, you can't be sure if the change is for changing the text or adding an option 2120 if ($mode == 'edit' && count($poll_ary['poll_options']) != count($cur_poll_options)) 2121 { 2122 $db->sql_query('DELETE FROM ' . POLL_VOTES_TABLE . ' WHERE topic_id = ' . $data_ary['topic_id']); 2123 $db->sql_query('UPDATE ' . POLL_OPTIONS_TABLE . ' SET poll_option_total = 0 WHERE topic_id = ' . $data_ary['topic_id']); 2124 } 2125 } 2126 2127 // Submit Attachments 2128 if (!empty($data_ary['attachment_data']) && $data_ary['post_id'] && in_array($mode, array('post', 'reply', 'quote', 'edit'))) 2129 { 2130 $space_taken = $files_added = 0; 2131 $orphan_rows = array(); 2132 2133 foreach ($data_ary['attachment_data'] as $pos => $attach_row) 2134 { 2135 $orphan_rows[(int) $attach_row['attach_id']] = array(); 2136 } 2137 2138 if (count($orphan_rows)) 2139 { 2140 $sql = 'SELECT attach_id, filesize, physical_filename 2141 FROM ' . ATTACHMENTS_TABLE . ' 2142 WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . ' 2143 AND is_orphan = 1 2144 AND poster_id = ' . $user->data['user_id']; 2145 $result = $db->sql_query($sql); 2146 2147 $orphan_rows = array(); 2148 while ($row = $db->sql_fetchrow($result)) 2149 { 2150 $orphan_rows[$row['attach_id']] = $row; 2151 } 2152 $db->sql_freeresult($result); 2153 } 2154 2155 foreach ($data_ary['attachment_data'] as $pos => $attach_row) 2156 { 2157 if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']])) 2158 { 2159 continue; 2160 } 2161 2162 if (preg_match('/[\x{10000}-\x{10FFFF}]/u', $attach_row['attach_comment'])) 2163 { 2164 trigger_error('ATTACH_COMMENT_NO_EMOJIS'); 2165 } 2166 2167 if (!$attach_row['is_orphan']) 2168 { 2169 // update entry in db if attachment already stored in db and filespace 2170 $sql = 'UPDATE ' . ATTACHMENTS_TABLE . " 2171 SET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "' 2172 WHERE attach_id = " . (int) $attach_row['attach_id'] . ' 2173 AND is_orphan = 0'; 2174 $db->sql_query($sql); 2175 } 2176 else 2177 { 2178 // insert attachment into db 2179 if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($orphan_rows[$attach_row['attach_id']]['physical_filename']))) 2180 { 2181 continue; 2182 } 2183 2184 $space_taken += $orphan_rows[$attach_row['attach_id']]['filesize']; 2185 $files_added++; 2186 2187 $attach_sql = array( 2188 'post_msg_id' => $data_ary['post_id'], 2189 'topic_id' => $data_ary['topic_id'], 2190 'is_orphan' => 0, 2191 'poster_id' => $poster_id, 2192 'attach_comment' => $attach_row['attach_comment'], 2193 ); 2194 2195 $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $attach_sql) . ' 2196 WHERE attach_id = ' . $attach_row['attach_id'] . ' 2197 AND is_orphan = 1 2198 AND poster_id = ' . $user->data['user_id']; 2199 $db->sql_query($sql); 2200 } 2201 } 2202 2203 if ($space_taken && $files_added) 2204 { 2205 $config->increment('upload_dir_size', $space_taken, false); 2206 $config->increment('num_files', $files_added, false); 2207 } 2208 } 2209 2210 $first_post_has_topic_info = ($post_mode == 'edit_first_post' && 2211 (($post_visibility == ITEM_DELETED && $data_ary['topic_posts_softdeleted'] == 1) || 2212 ($post_visibility == ITEM_UNAPPROVED && $data_ary['topic_posts_unapproved'] == 1) || 2213 ($post_visibility == ITEM_REAPPROVE && $data_ary['topic_posts_unapproved'] == 1) || 2214 ($post_visibility == ITEM_APPROVED && $data_ary['topic_posts_approved'] == 1))); 2215 // Fix the post's and topic's visibility and first/last post information, when the post is edited 2216 if (($post_mode != 'post' && $post_mode != 'reply') && $data_ary['post_visibility'] != $post_visibility) 2217 { 2218 // If the post was not approved, it could also be the starter, 2219 // so we sync the starter after approving/restoring, to ensure that the stats are correct 2220 // Same applies for the last post 2221 $is_starter = ($post_mode == 'edit_first_post' || $post_mode == 'edit_topic' || $data_ary['post_visibility'] != ITEM_APPROVED); 2222 $is_latest = ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $data_ary['post_visibility'] != ITEM_APPROVED); 2223 2224 /* @var $phpbb_content_visibility \phpbb\content_visibility */ 2225 $phpbb_content_visibility = $phpbb_container->get('content.visibility'); 2226 $phpbb_content_visibility->set_post_visibility($post_visibility, $data_ary['post_id'], $data_ary['topic_id'], $data_ary['forum_id'], $user->data['user_id'], time(), '', $is_starter, $is_latest); 2227 } 2228 else if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $first_post_has_topic_info) 2229 { 2230 if ($post_visibility == ITEM_APPROVED || $data_ary['topic_visibility'] == $post_visibility) 2231 { 2232 // only the subject can be changed from edit 2233 $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($subject) . "'"; 2234 2235 // Maybe not only the subject, but also changing anonymous usernames. ;) 2236 if ($data_ary['poster_id'] == ANONYMOUS) 2237 { 2238 $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape($username) . "'"; 2239 } 2240 2241 if ($post_visibility == ITEM_APPROVED) 2242 { 2243 // this does not _necessarily_ mean that we must update the info again, 2244 // it just means that we might have to 2245 $sql = 'SELECT forum_last_post_id, forum_last_post_subject 2246 FROM ' . FORUMS_TABLE . ' 2247 WHERE forum_id = ' . (int) $data_ary['forum_id']; 2248 $result = $db->sql_query($sql); 2249 $row = $db->sql_fetchrow($result); 2250 $db->sql_freeresult($result); 2251 2252 // this post is the latest post in the forum, better update 2253 if ($row['forum_last_post_id'] == $data_ary['post_id'] && ($row['forum_last_post_subject'] !== $subject || $data_ary['poster_id'] == ANONYMOUS)) 2254 { 2255 // the post's subject changed 2256 if ($row['forum_last_post_subject'] !== $subject) 2257 { 2258 $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'"; 2259 } 2260 2261 // Update the user name if poster is anonymous... just in case a moderator changed it 2262 if ($data_ary['poster_id'] == ANONYMOUS) 2263 { 2264 $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($username) . "'"; 2265 } 2266 } 2267 } 2268 } 2269 } 2270 2271 // Update forum stats 2272 $where_sql = array( 2273 POSTS_TABLE => 'post_id = ' . $data_ary['post_id'], 2274 TOPICS_TABLE => 'topic_id = ' . $data_ary['topic_id'], 2275 FORUMS_TABLE => 'forum_id = ' . $data_ary['forum_id'], 2276 USERS_TABLE => 'user_id = ' . $poster_id 2277 ); 2278 2279 foreach ($sql_data as $table => $update_ary) 2280 { 2281 if (isset($update_ary['stat']) && implode('', $update_ary['stat'])) 2282 { 2283 $sql = "UPDATE $table SET " . implode(', ', $update_ary['stat']) . ' WHERE ' . $where_sql[$table]; 2284 $db->sql_query($sql); 2285 } 2286 } 2287 2288 // Delete topic shadows (if any exist). We do not need a shadow topic for an global announcement 2289 if ($topic_type == POST_GLOBAL) 2290 { 2291 $sql = 'DELETE FROM ' . TOPICS_TABLE . ' 2292 WHERE topic_moved_id = ' . $data_ary['topic_id']; 2293 $db->sql_query($sql); 2294 } 2295 2296 // Committing the transaction before updating search index 2297 $db->sql_transaction('commit'); 2298 2299 // Delete draft if post was loaded... 2300 $draft_id = $request->variable('draft_loaded', 0); 2301 if ($draft_id) 2302 { 2303 $sql = 'DELETE FROM ' . DRAFTS_TABLE . " 2304 WHERE draft_id = $draft_id 2305 AND user_id = {$user->data['user_id']}"; 2306 $db->sql_query($sql); 2307 } 2308 2309 // Index message contents 2310 if ($update_search_index && $data_ary['enable_indexing']) 2311 { 2312 // Select the search method and do some additional checks to ensure it can actually be utilised 2313 $search_type = $config['search_type']; 2314 2315 if (!class_exists($search_type)) 2316 { 2317 trigger_error('NO_SUCH_SEARCH_MODULE'); 2318 } 2319 2320 $error = false; 2321 $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); 2322 2323 if ($error) 2324 { 2325 trigger_error($error); 2326 } 2327 2328 $search->index($mode, $data_ary['post_id'], $data_ary['message'], $subject, $poster_id, $data_ary['forum_id']); 2329 } 2330 2331 // Topic Notification, do not change if moderator is changing other users posts... 2332 if ($user->data['user_id'] == $poster_id) 2333 { 2334 if (!$data_ary['notify_set'] && $data_ary['notify']) 2335 { 2336 $sql = 'INSERT INTO ' . TOPICS_WATCH_TABLE . ' (user_id, topic_id) 2337 VALUES (' . $user->data['user_id'] . ', ' . $data_ary['topic_id'] . ')'; 2338 $db->sql_query($sql); 2339 } 2340 else if (($config['email_enable'] || $config['jab_enable']) && $data_ary['notify_set'] && !$data_ary['notify']) 2341 { 2342 $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . ' 2343 WHERE user_id = ' . $user->data['user_id'] . ' 2344 AND topic_id = ' . $data_ary['topic_id']; 2345 $db->sql_query($sql); 2346 } 2347 } 2348 2349 if ($mode == 'post' || $mode == 'reply' || $mode == 'quote') 2350 { 2351 // Mark this topic as posted to 2352 markread('post', $data_ary['forum_id'], $data_ary['topic_id']); 2353 } 2354 2355 // Mark this topic as read 2356 // We do not use post_time here, this is intended (post_time can have a date in the past if editing a message) 2357 markread('topic', $data_ary['forum_id'], $data_ary['topic_id'], time()); 2358 2359 // 2360 if ($config['load_db_lastread'] && $user->data['is_registered']) 2361 { 2362 $sql = 'SELECT mark_time 2363 FROM ' . FORUMS_TRACK_TABLE . ' 2364 WHERE user_id = ' . $user->data['user_id'] . ' 2365 AND forum_id = ' . $data_ary['forum_id']; 2366 $result = $db->sql_query($sql); 2367 $f_mark_time = (int) $db->sql_fetchfield('mark_time'); 2368 $db->sql_freeresult($result); 2369 } 2370 else if ($config['load_anon_lastread'] || $user->data['is_registered']) 2371 { 2372 $f_mark_time = false; 2373 } 2374 2375 if (($config['load_db_lastread'] && $user->data['is_registered']) || $config['load_anon_lastread'] || $user->data['is_registered']) 2376 { 2377 // Update forum info 2378 $sql = 'SELECT forum_last_post_time 2379 FROM ' . FORUMS_TABLE . ' 2380 WHERE forum_id = ' . $data_ary['forum_id']; 2381 $result = $db->sql_query($sql); 2382 $forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time'); 2383 $db->sql_freeresult($result); 2384 2385 update_forum_tracking_info($data_ary['forum_id'], $forum_last_post_time, $f_mark_time, false); 2386 } 2387 2388 // If a username was supplied or the poster is a guest, we will use the supplied username. 2389 // Doing it this way we can use "...post by guest-username..." in notifications when 2390 // "guest-username" is supplied or ommit the username if it is not. 2391 $username = ($username !== '' || !$user->data['is_registered']) ? $username : $user->data['username']; 2392 2393 // Send Notifications 2394 $notification_data = array_merge($data_ary, array( 2395 'topic_title' => (isset($data_ary['topic_title'])) ? $data_ary['topic_title'] : $subject, 2396 'post_username' => $username, 2397 'poster_id' => $poster_id, 2398 'post_text' => $data_ary['message'], 2399 'post_time' => $current_time, 2400 'post_subject' => $subject, 2401 )); 2402 2403 /** 2404 * This event allows you to modify the notification data upon submission 2405 * 2406 * @event core.modify_submit_notification_data 2407 * @var array notification_data The notification data to be inserted in to the database 2408 * @var array data_ary The data array with a lot of the post submission data 2409 * @var string mode The posting mode 2410 * @var int poster_id The poster id 2411 * @since 3.2.4-RC1 2412 */ 2413 $vars = array('notification_data', 'data_ary', 'mode', 'poster_id'); 2414 extract($phpbb_dispatcher->trigger_event('core.modify_submit_notification_data', compact($vars))); 2415 2416 /* @var $phpbb_notifications \phpbb\notification\manager */ 2417 $phpbb_notifications = $phpbb_container->get('notification_manager'); 2418 2419 if ($post_visibility == ITEM_APPROVED) 2420 { 2421 switch ($mode) 2422 { 2423 case 'post': 2424 $phpbb_notifications->add_notifications(array( 2425 'notification.type.quote', 2426 'notification.type.topic', 2427 ), $notification_data); 2428 break; 2429 2430 case 'reply': 2431 case 'quote': 2432 $phpbb_notifications->add_notifications(array( 2433 'notification.type.quote', 2434 'notification.type.bookmark', 2435 'notification.type.post', 2436 ), $notification_data); 2437 break; 2438 2439 case 'edit_topic': 2440 case 'edit_first_post': 2441 case 'edit': 2442 case 'edit_last_post': 2443 if ($user->data['user_id'] == $poster_id) 2444 { 2445 $phpbb_notifications->update_notifications(array( 2446 'notification.type.quote', 2447 ), $notification_data); 2448 } 2449 2450 $phpbb_notifications->update_notifications(array( 2451 'notification.type.bookmark', 2452 'notification.type.topic', 2453 'notification.type.post', 2454 ), $notification_data); 2455 break; 2456 } 2457 } 2458 else if ($post_visibility == ITEM_UNAPPROVED) 2459 { 2460 switch ($mode) 2461 { 2462 case 'post': 2463 $phpbb_notifications->add_notifications('notification.type.topic_in_queue', $notification_data); 2464 break; 2465 2466 case 'reply': 2467 case 'quote': 2468 $phpbb_notifications->add_notifications('notification.type.post_in_queue', $notification_data); 2469 break; 2470 2471 case 'edit_topic': 2472 case 'edit_first_post': 2473 case 'edit': 2474 case 'edit_last_post': 2475 // Nothing to do here 2476 break; 2477 } 2478 } 2479 else if ($post_visibility == ITEM_REAPPROVE) 2480 { 2481 switch ($mode) 2482 { 2483 case 'edit_topic': 2484 case 'edit_first_post': 2485 $phpbb_notifications->add_notifications('notification.type.topic_in_queue', $notification_data); 2486 2487 // Delete the approve_post notification so we can notify the user again, 2488 // when his post got reapproved 2489 $phpbb_notifications->delete_notifications('notification.type.approve_post', $notification_data['post_id']); 2490 break; 2491 2492 case 'edit': 2493 case 'edit_last_post': 2494 $phpbb_notifications->add_notifications('notification.type.post_in_queue', $notification_data); 2495 2496 // Delete the approve_post notification so we can notify the user again, 2497 // when his post got reapproved 2498 $phpbb_notifications->delete_notifications('notification.type.approve_post', $notification_data['post_id']); 2499 break; 2500 2501 case 'post': 2502 case 'reply': 2503 case 'quote': 2504 // Nothing to do here 2505 break; 2506 } 2507 } 2508 else if ($post_visibility == ITEM_DELETED) 2509 { 2510 switch ($mode) 2511 { 2512 case 'post': 2513 case 'reply': 2514 case 'quote': 2515 case 'edit_topic': 2516 case 'edit_first_post': 2517 case 'edit': 2518 case 'edit_last_post': 2519 // Nothing to do here 2520 break; 2521 } 2522 } 2523 2524 $params = $add_anchor = ''; 2525 2526 if ($post_visibility == ITEM_APPROVED || 2527 ($auth->acl_get('m_softdelete', $data_ary['forum_id']) && $post_visibility == ITEM_DELETED) || 2528 ($auth->acl_get('m_approve', $data_ary['forum_id']) && in_array($post_visibility, array(ITEM_UNAPPROVED, ITEM_REAPPROVE)))) 2529 { 2530 $params .= '&t=' . $data_ary['topic_id']; 2531 2532 if ($mode != 'post') 2533 { 2534 $params .= '&p=' . $data_ary['post_id']; 2535 $add_anchor = '#p' . $data_ary['post_id']; 2536 } 2537 } 2538 else if ($mode != 'post' && $post_mode != 'edit_first_post' && $post_mode != 'edit_topic') 2539 { 2540 $params .= '&t=' . $data_ary['topic_id']; 2541 } 2542 2543 $url = (!$params) ? "{$phpbb_root_path}viewforum.$phpEx" : "{$phpbb_root_path}viewtopic.$phpEx"; 2544 $url = append_sid($url, 'f=' . $data_ary['forum_id'] . $params) . $add_anchor; 2545 2546 $poll = $poll_ary; 2547 $data = $data_ary; 2548 /** 2549 * This event is used for performing actions directly after a post or topic 2550 * has been submitted. When a new topic is posted, the topic ID is 2551 * available in the $data array. 2552 * 2553 * The only action that can be done by altering data made available to this 2554 * event is to modify the return URL ($url). 2555 * 2556 * @event core.submit_post_end 2557 * @var string mode Variable containing posting mode value 2558 * @var string subject Variable containing post subject value 2559 * @var string username Variable containing post author name 2560 * @var int topic_type Variable containing topic type value 2561 * @var array poll Array with the poll data for the post 2562 * @var array data Array with the data for the post 2563 * @var int post_visibility Variable containing up to date post visibility 2564 * @var bool update_message Flag indicating if the post will be updated 2565 * @var bool update_search_index Flag indicating if the search index will be updated 2566 * @var string url The "Return to topic" URL 2567 * 2568 * @since 3.1.0-a3 2569 * @changed 3.1.0-RC3 Added vars mode, subject, username, topic_type, 2570 * poll, update_message, update_search_index 2571 */ 2572 $vars = array( 2573 'mode', 2574 'subject', 2575 'username', 2576 'topic_type', 2577 'poll', 2578 'data', 2579 'post_visibility', 2580 'update_message', 2581 'update_search_index', 2582 'url', 2583 ); 2584 extract($phpbb_dispatcher->trigger_event('core.submit_post_end', compact($vars))); 2585 $data_ary = $data; 2586 $poll_ary = $poll; 2587 unset($data); 2588 unset($poll); 2589 2590 return $url; 2591 } 2592 2593 /** 2594 * Handle topic bumping 2595 * @param int $forum_id The ID of the forum the topic is being bumped belongs to 2596 * @param int $topic_id The ID of the topic is being bumping 2597 * @param array $post_data Passes some topic parameters: 2598 * - 'topic_title' 2599 * - 'topic_last_post_id' 2600 * - 'topic_last_poster_id' 2601 * - 'topic_last_post_subject' 2602 * - 'topic_last_poster_name' 2603 * - 'topic_last_poster_colour' 2604 * @param int $bump_time The time at which topic was bumped, usually it is a current time as obtained via time(). 2605 * @return string An URL to the bumped topic, example: ./viewtopic.php?forum_id=1&topic_id=2&p=3#p3 2606 */ 2607 function phpbb_bump_topic($forum_id, $topic_id, $post_data, $bump_time = false) 2608 { 2609 global $config, $db, $user, $phpEx, $phpbb_root_path, $phpbb_log; 2610 2611 if ($bump_time === false) 2612 { 2613 $bump_time = time(); 2614 } 2615 2616 // Begin bumping 2617 $db->sql_transaction('begin'); 2618 2619 // Update the topic's last post post_time 2620 $sql = 'UPDATE ' . POSTS_TABLE . " 2621 SET post_time = $bump_time 2622 WHERE post_id = {$post_data['topic_last_post_id']} 2623 AND topic_id = $topic_id"; 2624 $db->sql_query($sql); 2625 2626 // Sync the topic's last post time, the rest of the topic's last post data isn't changed 2627 $sql = 'UPDATE ' . TOPICS_TABLE . " 2628 SET topic_last_post_time = $bump_time, 2629 topic_bumped = 1, 2630 topic_bumper = " . $user->data['user_id'] . " 2631 WHERE topic_id = $topic_id"; 2632 $db->sql_query($sql); 2633 2634 // Update the forum's last post info 2635 $sql = 'UPDATE ' . FORUMS_TABLE . " 2636 SET forum_last_post_id = " . $post_data['topic_last_post_id'] . ", 2637 forum_last_poster_id = " . $post_data['topic_last_poster_id'] . ", 2638 forum_last_post_subject = '" . $db->sql_escape($post_data['topic_last_post_subject']) . "', 2639 forum_last_post_time = $bump_time, 2640 forum_last_poster_name = '" . $db->sql_escape($post_data['topic_last_poster_name']) . "', 2641 forum_last_poster_colour = '" . $db->sql_escape($post_data['topic_last_poster_colour']) . "' 2642 WHERE forum_id = $forum_id"; 2643 $db->sql_query($sql); 2644 2645 // Update bumper's time of the last posting to prevent flood 2646 $sql = 'UPDATE ' . USERS_TABLE . " 2647 SET user_lastpost_time = $bump_time 2648 WHERE user_id = " . $user->data['user_id']; 2649 $db->sql_query($sql); 2650 2651 $db->sql_transaction('commit'); 2652 2653 // Mark this topic as posted to 2654 markread('post', $forum_id, $topic_id, $bump_time); 2655 2656 // Mark this topic as read 2657 markread('topic', $forum_id, $topic_id, $bump_time); 2658 2659 // Update forum tracking info 2660 if ($config['load_db_lastread'] && $user->data['is_registered']) 2661 { 2662 $sql = 'SELECT mark_time 2663 FROM ' . FORUMS_TRACK_TABLE . ' 2664 WHERE user_id = ' . $user->data['user_id'] . ' 2665 AND forum_id = ' . $forum_id; 2666 $result = $db->sql_query($sql); 2667 $f_mark_time = (int) $db->sql_fetchfield('mark_time'); 2668 $db->sql_freeresult($result); 2669 } 2670 else if ($config['load_anon_lastread'] || $user->data['is_registered']) 2671 { 2672 $f_mark_time = false; 2673 } 2674 2675 if (($config['load_db_lastread'] && $user->data['is_registered']) || $config['load_anon_lastread'] || $user->data['is_registered']) 2676 { 2677 // Update forum info 2678 $sql = 'SELECT forum_last_post_time 2679 FROM ' . FORUMS_TABLE . ' 2680 WHERE forum_id = ' . $forum_id; 2681 $result = $db->sql_query($sql); 2682 $forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time'); 2683 $db->sql_freeresult($result); 2684 2685 update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_time, false); 2686 } 2687 2688 $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_BUMP_TOPIC', false, array( 2689 'forum_id' => $forum_id, 2690 'topic_id' => $topic_id, 2691 $post_data['topic_title'] 2692 )); 2693 2694 $url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id&p={$post_data['topic_last_post_id']}") . "#p{$post_data['topic_last_post_id']}"; 2695 2696 return $url; 2697 } 2698 2699 /** 2700 * Show upload popup (progress bar) 2701 */ 2702 function phpbb_upload_popup($forum_style = 0) 2703 { 2704 global $template, $user; 2705 2706 ($forum_style) ? $user->setup('posting', $forum_style) : $user->setup('posting'); 2707 2708 page_header($user->lang['PROGRESS_BAR']); 2709 2710 $template->set_filenames(array( 2711 'popup' => 'posting_progress_bar.html') 2712 ); 2713 2714 $template->assign_vars(array( 2715 'PROGRESS_BAR' => $user->img('upload_bar', $user->lang['UPLOAD_IN_PROGRESS'])) 2716 ); 2717 2718 $template->display('popup'); 2719 2720 garbage_collection(); 2721 exit_handler(); 2722 } 2723 2724 /** 2725 * Do the various checks required for removing posts as well as removing it 2726 * 2727 * @param int $forum_id The id of the forum 2728 * @param int $topic_id The id of the topic 2729 * @param int $post_id The id of the post 2730 * @param array $post_data Array with the post data 2731 * @param bool $is_soft The flag indicating whether it is the soft delete mode 2732 * @param string $delete_reason Description for the post deletion reason 2733 * 2734 * @return null 2735 */ 2736 function phpbb_handle_post_delete($forum_id, $topic_id, $post_id, &$post_data, $is_soft = false, $delete_reason = '') 2737 { 2738 global $user, $auth, $config, $request; 2739 global $phpbb_root_path, $phpEx, $phpbb_log, $phpbb_dispatcher; 2740 2741 $force_delete_allowed = $force_softdelete_allowed = false; 2742 $perm_check = ($is_soft) ? 'softdelete' : 'delete'; 2743 2744 /** 2745 * This event allows to modify the conditions for the post deletion 2746 * 2747 * @event core.handle_post_delete_conditions 2748 * @var int forum_id The id of the forum 2749 * @var int topic_id The id of the topic 2750 * @var int post_id The id of the post 2751 * @var array post_data Array with the post data 2752 * @var bool is_soft The flag indicating whether it is the soft delete mode 2753 * @var string delete_reason Description for the post deletion reason 2754 * @var bool force_delete_allowed Allow the user to delete the post (all permissions and conditions are ignored) 2755 * @var bool force_softdelete_allowed Allow the user to softdelete the post (all permissions and conditions are ignored) 2756 * @var string perm_check The deletion mode softdelete|delete 2757 * @since 3.1.11-RC1 2758 */ 2759 $vars = array( 2760 'forum_id', 2761 'topic_id', 2762 'post_id', 2763 'post_data', 2764 'is_soft', 2765 'delete_reason', 2766 'force_delete_allowed', 2767 'force_softdelete_allowed', 2768 'perm_check', 2769 ); 2770 extract($phpbb_dispatcher->trigger_event('core.handle_post_delete_conditions', compact($vars))); 2771 2772 // If moderator removing post or user itself removing post, present a confirmation screen 2773 if ($force_delete_allowed || ($is_soft && $force_softdelete_allowed) || $auth->acl_get("m_$perm_check", $forum_id) || ($post_data['poster_id'] == $user->data['user_id'] && $user->data['is_registered'] && $auth->acl_get("f_$perm_check", $forum_id) && $post_id == $post_data['topic_last_post_id'] && !$post_data['post_edit_locked'] && ($post_data['post_time'] > time() - ($config['delete_time'] * 60) || !$config['delete_time']))) 2774 { 2775 $s_hidden_fields = array( 2776 'p' => $post_id, 2777 'f' => $forum_id, 2778 'mode' => ($is_soft) ? 'soft_delete' : 'delete', 2779 ); 2780 2781 if (confirm_box(true)) 2782 { 2783 $data = array( 2784 'topic_first_post_id' => $post_data['topic_first_post_id'], 2785 'topic_last_post_id' => $post_data['topic_last_post_id'], 2786 'topic_posts_approved' => $post_data['topic_posts_approved'], 2787 'topic_posts_unapproved' => $post_data['topic_posts_unapproved'], 2788 'topic_posts_softdeleted' => $post_data['topic_posts_softdeleted'], 2789 'topic_visibility' => $post_data['topic_visibility'], 2790 'topic_type' => $post_data['topic_type'], 2791 'post_visibility' => $post_data['post_visibility'], 2792 'post_reported' => $post_data['post_reported'], 2793 'post_time' => $post_data['post_time'], 2794 'poster_id' => $post_data['poster_id'], 2795 'post_postcount' => $post_data['post_postcount'], 2796 ); 2797 2798 $next_post_id = delete_post($forum_id, $topic_id, $post_id, $data, $is_soft, $delete_reason); 2799 $post_username = ($post_data['poster_id'] == ANONYMOUS && !empty($post_data['post_username'])) ? $post_data['post_username'] : $post_data['username']; 2800 2801 if ($next_post_id === false) 2802 { 2803 $phpbb_log->add('mod', $user->data['user_id'], $user->ip, (($is_soft) ? 'LOG_SOFTDELETE_TOPIC' : 'LOG_DELETE_TOPIC'), false, array( 2804 'forum_id' => $forum_id, 2805 'topic_id' => $topic_id, 2806 $post_data['topic_title'], 2807 $post_username, 2808 $delete_reason 2809 )); 2810 2811 $meta_info = append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id"); 2812 $message = $user->lang['POST_DELETED']; 2813 } 2814 else 2815 { 2816 $phpbb_log->add('mod', $user->data['user_id'], $user->ip, (($is_soft) ? 'LOG_SOFTDELETE_POST' : 'LOG_DELETE_POST'), false, array( 2817 'forum_id' => $forum_id, 2818 'topic_id' => $topic_id, 2819 'post_id' => $post_id, 2820 $post_data['post_subject'], 2821 $post_username, 2822 $delete_reason 2823 )); 2824 2825 $meta_info = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id&p=$next_post_id") . "#p$next_post_id"; 2826 $message = $user->lang['POST_DELETED']; 2827 2828 if (!$request->is_ajax()) 2829 { 2830 $message .= '<br /><br />' . $user->lang('RETURN_TOPIC', '<a href="' . $meta_info . '">', '</a>'); 2831 } 2832 } 2833 2834 meta_refresh(3, $meta_info); 2835 if (!$request->is_ajax()) 2836 { 2837 $message .= '<br /><br />' . $user->lang('RETURN_FORUM', '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id) . '">', '</a>'); 2838 } 2839 trigger_error($message); 2840 } 2841 else 2842 { 2843 global $template; 2844 2845 $can_delete = $force_delete_allowed || ($auth->acl_get('m_delete', $forum_id) || ($post_data['poster_id'] == $user->data['user_id'] && $user->data['is_registered'] && $auth->acl_get('f_delete', $forum_id))); 2846 $can_softdelete = $force_softdelete_allowed || ($auth->acl_get('m_softdelete', $forum_id) || ($post_data['poster_id'] == $user->data['user_id'] && $user->data['is_registered'] && $auth->acl_get('f_softdelete', $forum_id))); 2847 2848 $template->assign_vars(array( 2849 'S_SOFTDELETED' => $post_data['post_visibility'] == ITEM_DELETED, 2850 'S_CHECKED_PERMANENT' => $request->is_set_post('delete_permanent') ? ' checked="checked"' : '', 2851 'S_ALLOWED_DELETE' => $can_delete, 2852 'S_ALLOWED_SOFTDELETE' => $can_softdelete, 2853 )); 2854 2855 $l_confirm = 'DELETE_POST'; 2856 if ($post_data['post_visibility'] == ITEM_DELETED) 2857 { 2858 $l_confirm .= '_PERMANENTLY'; 2859 $s_hidden_fields['delete_permanent'] = '1'; 2860 } 2861 else if (!$can_softdelete) 2862 { 2863 $s_hidden_fields['delete_permanent'] = '1'; 2864 } 2865 2866 confirm_box(false, [$l_confirm, 1], build_hidden_fields($s_hidden_fields), 'confirm_delete_body.html'); 2867 } 2868 } 2869 2870 // If we are here the user is not able to delete - present the correct error message 2871 if ($post_data['poster_id'] != $user->data['user_id'] && $auth->acl_get('f_delete', $forum_id)) 2872 { 2873 trigger_error('DELETE_OWN_POSTS'); 2874 } 2875 2876 if ($post_data['poster_id'] == $user->data['user_id'] && $auth->acl_get('f_delete', $forum_id) && $post_id != $post_data['topic_last_post_id']) 2877 { 2878 trigger_error('CANNOT_DELETE_REPLIED'); 2879 } 2880 2881 trigger_error('USER_CANNOT_DELETE'); 2882 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Nov 11 20:33:01 2020 | Cross-referenced by PHPXref 0.7.1 |