Verzeichnisstruktur phpBB-3.1.0
- Veröffentlicht
- 27.10.2014
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
functions_posting.php
0001 <?php
0002 /**
0003 *
0004 * This file is part of the phpBB Forum Software package.
0005 *
0006 * @copyright (c) phpBB Limited <https://www.phpbb.com>
0007 * @license GNU General Public License, version 2 (GPL-2.0)
0008 *
0009 * For full copyright and license information, please see
0010 * the docs/CREDITS.txt file.
0011 *
0012 */
0013
0014 /**
0015 * @ignore
0016 */
0017 if (!defined('IN_PHPBB'))
0018 {
0019 exit;
0020 }
0021
0022 /**
0023 * Fill smiley templates (or just the variables) with smilies, either in a window or inline
0024 */
0025 function generate_smilies($mode, $forum_id)
0026 {
0027 global $db, $user, $config, $template, $phpbb_dispatcher;
0028 global $phpEx, $phpbb_root_path, $phpbb_container, $phpbb_path_helper;
0029
0030 $base_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=smilies&f=' . $forum_id);
0031 $pagination = $phpbb_container->get('pagination');
0032 $start = request_var('start', 0);
0033
0034 if ($mode == 'window')
0035 {
0036 if ($forum_id)
0037 {
0038 $sql = 'SELECT forum_style
0039 FROM ' . FORUMS_TABLE . "
0040 WHERE forum_id = $forum_id";
0041 $result = $db->sql_query_limit($sql, 1);
0042 $row = $db->sql_fetchrow($result);
0043 $db->sql_freeresult($result);
0044
0045 $user->setup('posting', (int) $row['forum_style']);
0046 }
0047 else
0048 {
0049 $user->setup('posting');
0050 }
0051
0052 page_header($user->lang['SMILIES']);
0053
0054 $sql = 'SELECT COUNT(smiley_id) AS item_count
0055 FROM ' . SMILIES_TABLE . '
0056 GROUP BY smiley_url';
0057 $result = $db->sql_query($sql, 3600);
0058
0059 $smiley_count = 0;
0060 while ($row = $db->sql_fetchrow($result))
0061 {
0062 ++$smiley_count;
0063 }
0064 $db->sql_freeresult($result);
0065
0066 $template->set_filenames(array(
0067 'body' => 'posting_smilies.html')
0068 );
0069
0070 $start = $pagination->validate_start($start, $config['smilies_per_page'], $smiley_count);
0071 $pagination->generate_template_pagination($base_url, 'pagination', 'start', $smiley_count, $config['smilies_per_page'], $start);
0072 }
0073
0074 $display_link = false;
0075 if ($mode == 'inline')
0076 {
0077 $sql = 'SELECT smiley_id
0078 FROM ' . SMILIES_TABLE . '
0079 WHERE display_on_posting = 0';
0080 $result = $db->sql_query_limit($sql, 1, 0, 3600);
0081
0082 if ($row = $db->sql_fetchrow($result))
0083 {
0084 $display_link = true;
0085 }
0086 $db->sql_freeresult($result);
0087 }
0088
0089 if ($mode == 'window')
0090 {
0091 $sql = 'SELECT smiley_url, MIN(emotion) as emotion, MIN(code) AS code, smiley_width, smiley_height, MIN(smiley_order) AS min_smiley_order
0092 FROM ' . SMILIES_TABLE . '
0093 GROUP BY smiley_url, smiley_width, smiley_height
0094 ORDER BY min_smiley_order';
0095 $result = $db->sql_query_limit($sql, $config['smilies_per_page'], $start, 3600);
0096 }
0097 else
0098 {
0099 $sql = 'SELECT *
0100 FROM ' . SMILIES_TABLE . '
0101 WHERE display_on_posting = 1
0102 ORDER BY smiley_order';
0103 $result = $db->sql_query($sql, 3600);
0104 }
0105
0106 $smilies = array();
0107 while ($row = $db->sql_fetchrow($result))
0108 {
0109 if (empty($smilies[$row['smiley_url']]))
0110 {
0111 $smilies[$row['smiley_url']] = $row;
0112 }
0113 }
0114 $db->sql_freeresult($result);
0115
0116 if (sizeof($smilies))
0117 {
0118 $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_path_helper->get_web_root_path();
0119
0120 foreach ($smilies as $row)
0121 {
0122 $template->assign_block_vars('smiley', array(
0123 'SMILEY_CODE' => $row['code'],
0124 'A_SMILEY_CODE' => addslashes($row['code']),
0125 'SMILEY_IMG' => $root_path . $config['smilies_path'] . '/' . $row['smiley_url'],
0126 'SMILEY_WIDTH' => $row['smiley_width'],
0127 'SMILEY_HEIGHT' => $row['smiley_height'],
0128 'SMILEY_DESC' => $row['emotion'])
0129 );
0130 }
0131 }
0132
0133 /**
0134 * This event is called after the smilies are populated
0135 *
0136 * @event core.generate_smilies_after
0137 * @var string mode Mode of the smilies: window|inline
0138 * @var int forum_id The forum ID we are currently in
0139 * @var bool display_link Shall we display the "more smilies" link?
0140 * @since 3.1.0-a1
0141 */
0142 $vars = array('mode', 'forum_id', 'display_link');
0143 extract($phpbb_dispatcher->trigger_event('core.generate_smilies_after', compact($vars)));
0144
0145 if ($mode == 'inline' && $display_link)
0146 {
0147 $template->assign_vars(array(
0148 'S_SHOW_SMILEY_LINK' => true,
0149 'U_MORE_SMILIES' => $base_url,
0150 ));
0151 }
0152
0153 if ($mode == 'window')
0154 {
0155 page_footer();
0156 }
0157 }
0158
0159 /**
0160 * Update last post information
0161 * Should be used instead of sync() if only the last post information are out of sync... faster
0162 *
0163 * @param string $type Can be forum|topic
0164 * @param mixed $ids topic/forum ids
0165 * @param bool $return_update_sql true: SQL query shall be returned, false: execute SQL
0166 */
0167 function update_post_information($type, $ids, $return_update_sql = false)
0168 {
0169 global $db;
0170
0171 if (empty($ids))
0172 {
0173 return;
0174 }
0175 if (!is_array($ids))
0176 {
0177 $ids = array($ids);
0178 }
0179
0180 $update_sql = $empty_forums = $not_empty_forums = array();
0181
0182 if ($type != 'topic')
0183 {
0184 $topic_join = ', ' . TOPICS_TABLE . ' t';
0185 $topic_condition = 'AND t.topic_id = p.topic_id AND t.topic_visibility = ' . ITEM_APPROVED;
0186 }
0187 else
0188 {
0189 $topic_join = '';
0190 $topic_condition = '';
0191 }
0192
0193 if (sizeof($ids) == 1)
0194 {
0195 $sql = 'SELECT MAX(p.post_id) as last_post_id
0196 FROM ' . POSTS_TABLE . " p $topic_join
0197 WHERE " . $db->sql_in_set('p.' . $type . '_id', $ids) . "
0198 $topic_condition
0199 AND p.post_visibility = " . ITEM_APPROVED;
0200 }
0201 else
0202 {
0203 $sql = 'SELECT p.' . $type . '_id, MAX(p.post_id) as last_post_id
0204 FROM ' . POSTS_TABLE . " p $topic_join
0205 WHERE " . $db->sql_in_set('p.' . $type . '_id', $ids) . "
0206 $topic_condition
0207 AND p.post_visibility = " . ITEM_APPROVED . "
0208 GROUP BY p.{$type}_id";
0209 }
0210 $result = $db->sql_query($sql);
0211
0212 $last_post_ids = array();
0213 while ($row = $db->sql_fetchrow($result))
0214 {
0215 if (sizeof($ids) == 1)
0216 {
0217 $row[$type . '_id'] = $ids[0];
0218 }
0219
0220 if ($type == 'forum')
0221 {
0222 $not_empty_forums[] = $row['forum_id'];
0223
0224 if (empty($row['last_post_id']))
0225 {
0226 $empty_forums[] = $row['forum_id'];
0227 }
0228 }
0229
0230 $last_post_ids[] = $row['last_post_id'];
0231 }
0232 $db->sql_freeresult($result);
0233
0234 if ($type == 'forum')
0235 {
0236 $empty_forums = array_merge($empty_forums, array_diff($ids, $not_empty_forums));
0237
0238 foreach ($empty_forums as $void => $forum_id)
0239 {
0240 $update_sql[$forum_id][] = 'forum_last_post_id = 0';
0241 $update_sql[$forum_id][] = "forum_last_post_subject = ''";
0242 $update_sql[$forum_id][] = 'forum_last_post_time = 0';
0243 $update_sql[$forum_id][] = 'forum_last_poster_id = 0';
0244 $update_sql[$forum_id][] = "forum_last_poster_name = ''";
0245 $update_sql[$forum_id][] = "forum_last_poster_colour = ''";
0246 }
0247 }
0248
0249 if (sizeof($last_post_ids))
0250 {
0251 $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
0252 FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
0253 WHERE p.poster_id = u.user_id
0254 AND ' . $db->sql_in_set('p.post_id', $last_post_ids);
0255 $result = $db->sql_query($sql);
0256
0257 while ($row = $db->sql_fetchrow($result))
0258 {
0259 $update_sql[$row["{$type}_id"]][] = $type . '_last_post_id = ' . (int) $row['post_id'];
0260 $update_sql[$row["{$type}_id"]][] = "{$type}_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'";
0261 $update_sql[$row["{$type}_id"]][] = $type . '_last_post_time = ' . (int) $row['post_time'];
0262 $update_sql[$row["{$type}_id"]][] = $type . '_last_poster_id = ' . (int) $row['poster_id'];
0263 $update_sql[$row["{$type}_id"]][] = "{$type}_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'";
0264 $update_sql[$row["{$type}_id"]][] = "{$type}_last_poster_name = '" . (($row['poster_id'] == ANONYMOUS) ? $db->sql_escape($row['post_username']) : $db->sql_escape($row['username'])) . "'";
0265 }
0266 $db->sql_freeresult($result);
0267 }
0268 unset($empty_forums, $ids, $last_post_ids);
0269
0270 if ($return_update_sql || !sizeof($update_sql))
0271 {
0272 return $update_sql;
0273 }
0274
0275 $table = ($type == 'forum') ? FORUMS_TABLE : TOPICS_TABLE;
0276
0277 foreach ($update_sql as $update_id => $update_sql_ary)
0278 {
0279 $sql = "UPDATE $table
0280 SET " . implode(', ', $update_sql_ary) . "
0281 WHERE {$type}_id = $update_id";
0282 $db->sql_query($sql);
0283 }
0284
0285 return;
0286 }
0287
0288 /**
0289 * Generate Topic Icons for display
0290 */
0291 function posting_gen_topic_icons($mode, $icon_id)
0292 {
0293 global $phpbb_root_path, $config, $template, $cache;
0294
0295 // Grab icons
0296 $icons = $cache->obtain_icons();
0297
0298 if (!$icon_id)
0299 {
0300 $template->assign_var('S_NO_ICON_CHECKED', ' checked="checked"');
0301 }
0302
0303 if (sizeof($icons))
0304 {
0305 $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path;
0306
0307 foreach ($icons as $id => $data)
0308 {
0309 if ($data['display'])
0310 {
0311 $template->assign_block_vars('topic_icon', array(
0312 'ICON_ID' => $id,
0313 'ICON_IMG' => $root_path . $config['icons_path'] . '/' . $data['img'],
0314 'ICON_WIDTH' => $data['width'],
0315 'ICON_HEIGHT' => $data['height'],
0316
0317 'S_CHECKED' => ($id == $icon_id) ? true : false,
0318 'S_ICON_CHECKED' => ($id == $icon_id) ? ' checked="checked"' : '')
0319 );
0320 }
0321 }
0322
0323 return true;
0324 }
0325
0326 return false;
0327 }
0328
0329 /**
0330 * Build topic types able to be selected
0331 */
0332 function posting_gen_topic_types($forum_id, $cur_topic_type = POST_NORMAL)
0333 {
0334 global $auth, $user, $template, $topic_type;
0335
0336 $toggle = false;
0337
0338 $topic_types = array(
0339 'sticky' => array('const' => POST_STICKY, 'lang' => 'POST_STICKY'),
0340 'announce' => array('const' => POST_ANNOUNCE, 'lang' => 'POST_ANNOUNCEMENT'),
0341 'global' => array('const' => POST_GLOBAL, 'lang' => 'POST_GLOBAL')
0342 );
0343
0344 $topic_type_array = array();
0345
0346 foreach ($topic_types as $auth_key => $topic_value)
0347 {
0348 // We do not have a special post global announcement permission
0349 $auth_key = ($auth_key == 'global') ? 'announce' : $auth_key;
0350
0351 if ($auth->acl_get('f_' . $auth_key, $forum_id))
0352 {
0353 $toggle = true;
0354
0355 $topic_type_array[] = array(
0356 'VALUE' => $topic_value['const'],
0357 'S_CHECKED' => ($cur_topic_type == $topic_value['const']) ? ' checked="checked"' : '',
0358 'L_TOPIC_TYPE' => $user->lang[$topic_value['lang']]
0359 );
0360 }
0361 }
0362
0363 if ($toggle)
0364 {
0365 $topic_type_array = array_merge(array(0 => array(
0366 'VALUE' => POST_NORMAL,
0367 'S_CHECKED' => ($cur_topic_type == POST_NORMAL) ? ' checked="checked"' : '',
0368 'L_TOPIC_TYPE' => $user->lang['POST_NORMAL'])),
0369
0370 $topic_type_array
0371 );
0372
0373 foreach ($topic_type_array as $array)
0374 {
0375 $template->assign_block_vars('topic_type', $array);
0376 }
0377
0378 $template->assign_vars(array(
0379 'S_TOPIC_TYPE_STICKY' => ($auth->acl_get('f_sticky', $forum_id)),
0380 'S_TOPIC_TYPE_ANNOUNCE' => ($auth->acl_get('f_announce', $forum_id)))
0381 );
0382 }
0383
0384 return $toggle;
0385 }
0386
0387 //
0388 // Attachment related functions
0389 //
0390
0391 /**
0392 * Upload Attachment - filedata is generated here
0393 * Uses upload class
0394 *
0395 * @param string $form_name The form name of the file upload input
0396 * @param int $forum_id The id of the forum
0397 * @param bool $local Whether the file is local or not
0398 * @param string $local_storage The path to the local file
0399 * @param bool $is_message Whether it is a PM or not
0400 * @param \filespec $local_filedata A filespec object created for the local file
0401 * @param \phpbb\mimetype\guesser $mimetype_guesser The mimetype guesser object if used
0402 * @param \phpbb\plupload\plupload $plupload The plupload object if one is being used
0403 *
0404 * @return object filespec
0405 */
0406 function upload_attachment($form_name, $forum_id, $local = false, $local_storage = '', $is_message = false, $local_filedata = false, \phpbb\mimetype\guesser $mimetype_guesser = null, \phpbb\plupload\plupload $plupload = null)
0407 {
0408 global $auth, $user, $config, $db, $cache;
0409 global $phpbb_root_path, $phpEx, $phpbb_dispatcher;
0410
0411 $filedata = array(
0412 'error' => array()
0413 );
0414
0415 include_once($phpbb_root_path . 'includes/functions_upload.' . $phpEx);
0416 $upload = new fileupload();
0417
0418 if ($config['check_attachment_content'] && isset($config['mime_triggers']))
0419 {
0420 $upload->set_disallowed_content(explode('|', $config['mime_triggers']));
0421 }
0422 else if (!$config['check_attachment_content'])
0423 {
0424 $upload->set_disallowed_content(array());
0425 }
0426
0427 $filedata['post_attach'] = $local || $upload->is_valid($form_name);
0428
0429 if (!$filedata['post_attach'])
0430 {
0431 $filedata['error'][] = $user->lang['NO_UPLOAD_FORM_FOUND'];
0432 return $filedata;
0433 }
0434
0435 $extensions = $cache->obtain_attach_extensions((($is_message) ? false : (int) $forum_id));
0436 $upload->set_allowed_extensions(array_keys($extensions['_allowed_']));
0437
0438 $file = ($local) ? $upload->local_upload($local_storage, $local_filedata, $mimetype_guesser) : $upload->form_upload($form_name, $mimetype_guesser, $plupload);
0439
0440 if ($file->init_error)
0441 {
0442 $filedata['post_attach'] = false;
0443 return $filedata;
0444 }
0445
0446 // Whether the uploaded file is in the image category
0447 $is_image = (isset($extensions[$file->get('extension')]['display_cat'])) ? $extensions[$file->get('extension')]['display_cat'] == ATTACHMENT_CATEGORY_IMAGE : false;
0448
0449 if (!$auth->acl_get('a_') && !$auth->acl_get('m_', $forum_id))
0450 {
0451 // Check Image Size, if it is an image
0452 if ($is_image)
0453 {
0454 $file->upload->set_allowed_dimensions(0, 0, $config['img_max_width'], $config['img_max_height']);
0455 }
0456
0457 // Admins and mods are allowed to exceed the allowed filesize
0458 if (!empty($extensions[$file->get('extension')]['max_filesize']))
0459 {
0460 $allowed_filesize = $extensions[$file->get('extension')]['max_filesize'];
0461 }
0462 else
0463 {
0464 $allowed_filesize = ($is_message) ? $config['max_filesize_pm'] : $config['max_filesize'];
0465 }
0466
0467 $file->upload->set_max_filesize($allowed_filesize);
0468 }
0469
0470 $file->clean_filename('unique', $user->data['user_id'] . '_');
0471
0472 // Are we uploading an image *and* this image being within the image category?
0473 // Only then perform additional image checks.
0474 $file->move_file($config['upload_path'], false, !$is_image);
0475
0476 // Do we have to create a thumbnail?
0477 $filedata['thumbnail'] = ($is_image && $config['img_create_thumbnail']) ? 1 : 0;
0478
0479 if (sizeof($file->error))
0480 {
0481 $file->remove();
0482 $filedata['error'] = array_merge($filedata['error'], $file->error);
0483 $filedata['post_attach'] = false;
0484
0485 return $filedata;
0486 }
0487
0488 // Make sure the image category only holds valid images...
0489 if ($is_image && !$file->is_image())
0490 {
0491 $file->remove();
0492
0493 if ($plupload && $plupload->is_active())
0494 {
0495 $plupload->emit_error(104, 'ATTACHED_IMAGE_NOT_IMAGE');
0496 }
0497
0498 // If this error occurs a user tried to exploit an IE Bug by renaming extensions
0499 // Since the image category is displaying content inline we need to catch this.
0500 trigger_error($user->lang['ATTACHED_IMAGE_NOT_IMAGE']);
0501 }
0502
0503 $filedata['filesize'] = $file->get('filesize');
0504 $filedata['mimetype'] = $file->get('mimetype');
0505 $filedata['extension'] = $file->get('extension');
0506 $filedata['physical_filename'] = $file->get('realname');
0507 $filedata['real_filename'] = $file->get('uploadname');
0508 $filedata['filetime'] = time();
0509
0510 /**
0511 * Event to modify uploaded file before submit to the post
0512 *
0513 * @event core.modify_uploaded_file
0514 * @var array filedata Array containing uploaded file data
0515 * @var bool is_image Flag indicating if the file is an image
0516 * @since 3.1.0-RC3
0517 */
0518 $vars = array(
0519 'filedata',
0520 'is_image',
0521 );
0522 extract($phpbb_dispatcher->trigger_event('core.modify_uploaded_file', compact($vars)));
0523
0524 // Check our complete quota
0525 if ($config['attachment_quota'])
0526 {
0527 if ($config['upload_dir_size'] + $file->get('filesize') > $config['attachment_quota'])
0528 {
0529 $filedata['error'][] = $user->lang['ATTACH_QUOTA_REACHED'];
0530 $filedata['post_attach'] = false;
0531
0532 $file->remove();
0533
0534 return $filedata;
0535 }
0536 }
0537
0538 // Check free disk space
0539 if ($free_space = @disk_free_space($phpbb_root_path . $config['upload_path']))
0540 {
0541 if ($free_space <= $file->get('filesize'))
0542 {
0543 if ($auth->acl_get('a_'))
0544 {
0545 $filedata['error'][] = $user->lang['ATTACH_DISK_FULL'];
0546 }
0547 else
0548 {
0549 $filedata['error'][] = $user->lang['ATTACH_QUOTA_REACHED'];
0550 }
0551 $filedata['post_attach'] = false;
0552
0553 $file->remove();
0554
0555 return $filedata;
0556 }
0557 }
0558
0559 // Create Thumbnail
0560 if ($filedata['thumbnail'])
0561 {
0562 $source = $file->get('destination_file');
0563 $destination = $file->get('destination_path') . '/thumb_' . $file->get('realname');
0564
0565 if (!create_thumbnail($source, $destination, $file->get('mimetype')))
0566 {
0567 $filedata['thumbnail'] = 0;
0568 }
0569 }
0570
0571 return $filedata;
0572 }
0573
0574 /**
0575 * Calculate the needed size for Thumbnail
0576 */
0577 function get_img_size_format($width, $height)
0578 {
0579 global $config;
0580
0581 // Maximum Width the Image can take
0582 $max_width = ($config['img_max_thumb_width']) ? $config['img_max_thumb_width'] : 400;
0583
0584 if ($width > $height)
0585 {
0586 return array(
0587 round($width * ($max_width / $width)),
0588 round($height * ($max_width / $width))
0589 );
0590 }
0591 else
0592 {
0593 return array(
0594 round($width * ($max_width / $height)),
0595 round($height * ($max_width / $height))
0596 );
0597 }
0598 }
0599
0600 /**
0601 * Return supported image types
0602 */
0603 function get_supported_image_types($type = false)
0604 {
0605 if (@extension_loaded('gd'))
0606 {
0607 $format = imagetypes();
0608 $new_type = 0;
0609
0610 if ($type !== false)
0611 {
0612 // Type is one of the IMAGETYPE constants - it is fetched from getimagesize()
0613 switch ($type)
0614 {
0615 // GIF
0616 case IMAGETYPE_GIF:
0617 $new_type = ($format & IMG_GIF) ? IMG_GIF : false;
0618 break;
0619
0620 // JPG, JPC, JP2
0621 case IMAGETYPE_JPEG:
0622 case IMAGETYPE_JPC:
0623 case IMAGETYPE_JPEG2000:
0624 case IMAGETYPE_JP2:
0625 case IMAGETYPE_JPX:
0626 case IMAGETYPE_JB2:
0627 $new_type = ($format & IMG_JPG) ? IMG_JPG : false;
0628 break;
0629
0630 // PNG
0631 case IMAGETYPE_PNG:
0632 $new_type = ($format & IMG_PNG) ? IMG_PNG : false;
0633 break;
0634
0635 // WBMP
0636 case IMAGETYPE_WBMP:
0637 $new_type = ($format & IMG_WBMP) ? IMG_WBMP : false;
0638 break;
0639 }
0640 }
0641 else
0642 {
0643 $new_type = array();
0644 $go_through_types = array(IMG_GIF, IMG_JPG, IMG_PNG, IMG_WBMP);
0645
0646 foreach ($go_through_types as $check_type)
0647 {
0648 if ($format & $check_type)
0649 {
0650 $new_type[] = $check_type;
0651 }
0652 }
0653 }
0654
0655 return array(
0656 'gd' => ($new_type) ? true : false,
0657 'format' => $new_type,
0658 'version' => (function_exists('imagecreatetruecolor')) ? 2 : 1
0659 );
0660 }
0661
0662 return array('gd' => false);
0663 }
0664
0665 /**
0666 * Create Thumbnail
0667 */
0668 function create_thumbnail($source, $destination, $mimetype)
0669 {
0670 global $config;
0671
0672 $min_filesize = (int) $config['img_min_thumb_filesize'];
0673 $img_filesize = (file_exists($source)) ? @filesize($source) : false;
0674
0675 if (!$img_filesize || $img_filesize <= $min_filesize)
0676 {
0677 return false;
0678 }
0679
0680 $dimension = @getimagesize($source);
0681
0682 if ($dimension === false)
0683 {
0684 return false;
0685 }
0686
0687 list($width, $height, $type, ) = $dimension;
0688
0689 if (empty($width) || empty($height))
0690 {
0691 return false;
0692 }
0693
0694 list($new_width, $new_height) = get_img_size_format($width, $height);
0695
0696 // Do not create a thumbnail if the resulting width/height is bigger than the original one
0697 if ($new_width >= $width && $new_height >= $height)
0698 {
0699 return false;
0700 }
0701
0702 $used_imagick = false;
0703
0704 // Only use imagemagick if defined and the passthru function not disabled
0705 if ($config['img_imagick'] && function_exists('passthru'))
0706 {
0707 if (substr($config['img_imagick'], -1) !== '/')
0708 {
0709 $config['img_imagick'] .= '/';
0710 }
0711
0712 @passthru(escapeshellcmd($config['img_imagick']) . 'convert' . ((defined('PHP_OS') && preg_match('#^win#i', PHP_OS)) ? '.exe' : '') . ' -quality 85 -geometry ' . $new_width . 'x' . $new_height . ' "' . str_replace('\\', '/', $source) . '" "' . str_replace('\\', '/', $destination) . '"');
0713
0714 if (file_exists($destination))
0715 {
0716 $used_imagick = true;
0717 }
0718 }
0719
0720 if (!$used_imagick)
0721 {
0722 $type = get_supported_image_types($type);
0723
0724 if ($type['gd'])
0725 {
0726 // If the type is not supported, we are not able to create a thumbnail
0727 if ($type['format'] === false)
0728 {
0729 return false;
0730 }
0731
0732 switch ($type['format'])
0733 {
0734 case IMG_GIF:
0735 $image = @imagecreatefromgif($source);
0736 break;
0737
0738 case IMG_JPG:
0739 @ini_set('gd.jpeg_ignore_warning', 1);
0740 $image = @imagecreatefromjpeg($source);
0741 break;
0742
0743 case IMG_PNG:
0744 $image = @imagecreatefrompng($source);
0745 break;
0746
0747 case IMG_WBMP:
0748 $image = @imagecreatefromwbmp($source);
0749 break;
0750 }
0751
0752 if (empty($image))
0753 {
0754 return false;
0755 }
0756
0757 if ($type['version'] == 1)
0758 {
0759 $new_image = imagecreate($new_width, $new_height);
0760
0761 if ($new_image === false)
0762 {
0763 return false;
0764 }
0765
0766 imagecopyresized($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
0767 }
0768 else
0769 {
0770 $new_image = imagecreatetruecolor($new_width, $new_height);
0771
0772 if ($new_image === false)
0773 {
0774 return false;
0775 }
0776
0777 // Preserve alpha transparency (png for example)
0778 @imagealphablending($new_image, false);
0779 @imagesavealpha($new_image, true);
0780
0781 imagecopyresampled($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
0782 }
0783
0784 // If we are in safe mode create the destination file prior to using the gd functions to circumvent a PHP bug
0785 if (@ini_get('safe_mode') || @strtolower(ini_get('safe_mode')) == 'on')
0786 {
0787 @touch($destination);
0788 }
0789
0790 switch ($type['format'])
0791 {
0792 case IMG_GIF:
0793 imagegif($new_image, $destination);
0794 break;
0795
0796 case IMG_JPG:
0797 imagejpeg($new_image, $destination, 90);
0798 break;
0799
0800 case IMG_PNG:
0801 imagepng($new_image, $destination);
0802 break;
0803
0804 case IMG_WBMP:
0805 imagewbmp($new_image, $destination);
0806 break;
0807 }
0808
0809 imagedestroy($new_image);
0810 }
0811 else
0812 {
0813 return false;
0814 }
0815 }
0816
0817 if (!file_exists($destination))
0818 {
0819 return false;
0820 }
0821
0822 phpbb_chmod($destination, CHMOD_READ | CHMOD_WRITE);
0823
0824 return true;
0825 }
0826
0827 /**
0828 * Assign Inline attachments (build option fields)
0829 */
0830 function posting_gen_inline_attachments(&$attachment_data)
0831 {
0832 global $template;
0833
0834 if (sizeof($attachment_data))
0835 {
0836 $s_inline_attachment_options = '';
0837
0838 foreach ($attachment_data as $i => $attachment)
0839 {
0840 $s_inline_attachment_options .= '<option value="' . $i . '">' . utf8_basename($attachment['real_filename']) . '</option>';
0841 }
0842
0843 $template->assign_var('S_INLINE_ATTACHMENT_OPTIONS', $s_inline_attachment_options);
0844
0845 return true;
0846 }
0847
0848 return false;
0849 }
0850
0851 /**
0852 * Generate inline attachment entry
0853 */
0854 function posting_gen_attachment_entry($attachment_data, &$filename_data, $show_attach_box = true)
0855 {
0856 global $template, $config, $phpbb_root_path, $phpEx, $user;
0857
0858 // Some default template variables
0859 $template->assign_vars(array(
0860 'S_SHOW_ATTACH_BOX' => $show_attach_box,
0861 'S_HAS_ATTACHMENTS' => sizeof($attachment_data),
0862 'FILESIZE' => $config['max_filesize'],
0863 'FILE_COMMENT' => (isset($filename_data['filecomment'])) ? $filename_data['filecomment'] : '',
0864 ));
0865
0866 if (sizeof($attachment_data))
0867 {
0868 // We display the posted attachments within the desired order.
0869 ($config['display_order']) ? krsort($attachment_data) : ksort($attachment_data);
0870
0871 foreach ($attachment_data as $count => $attach_row)
0872 {
0873 $hidden = '';
0874 $attach_row['real_filename'] = utf8_basename($attach_row['real_filename']);
0875
0876 foreach ($attach_row as $key => $value)
0877 {
0878 $hidden .= '<input type="hidden" name="attachment_data[' . $count . '][' . $key . ']" value="' . $value . '" />';
0879 }
0880
0881 $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);
0882
0883 $template->assign_block_vars('attach_row', array(
0884 'FILENAME' => utf8_basename($attach_row['real_filename']),
0885 'A_FILENAME' => addslashes(utf8_basename($attach_row['real_filename'])),
0886 'FILE_COMMENT' => $attach_row['attach_comment'],
0887 'ATTACH_ID' => $attach_row['attach_id'],
0888 'S_IS_ORPHAN' => $attach_row['is_orphan'],
0889 'ASSOC_INDEX' => $count,
0890 'FILESIZE' => get_formatted_filesize($attach_row['filesize']),
0891
0892 'U_VIEW_ATTACHMENT' => $download_link,
0893 'S_HIDDEN' => $hidden)
0894 );
0895 }
0896 }
0897
0898 return sizeof($attachment_data);
0899 }
0900
0901 //
0902 // General Post functions
0903 //
0904
0905 /**
0906 * Load Drafts
0907 */
0908 function load_drafts($topic_id = 0, $forum_id = 0, $id = 0, $pm_action = '', $msg_id = 0)
0909 {
0910 global $user, $db, $template, $auth;
0911 global $phpbb_root_path, $phpbb_dispatcher, $phpEx;
0912
0913 $topic_ids = $forum_ids = $draft_rows = array();
0914
0915 // Load those drafts not connected to forums/topics
0916 // If forum_id == 0 AND topic_id == 0 then this is a PM draft
0917 if (!$topic_id && !$forum_id)
0918 {
0919 $sql_and = ' AND d.forum_id = 0 AND d.topic_id = 0';
0920 }
0921 else
0922 {
0923 $sql_and = '';
0924 $sql_and .= ($forum_id) ? ' AND d.forum_id = ' . (int) $forum_id : '';
0925 $sql_and .= ($topic_id) ? ' AND d.topic_id = ' . (int) $topic_id : '';
0926 }
0927
0928 $sql = 'SELECT d.*, f.forum_id, f.forum_name
0929 FROM ' . DRAFTS_TABLE . ' d
0930 LEFT JOIN ' . FORUMS_TABLE . ' f ON (f.forum_id = d.forum_id)
0931 WHERE d.user_id = ' . $user->data['user_id'] . "
0932 $sql_and
0933 ORDER BY d.save_time DESC";
0934 $result = $db->sql_query($sql);
0935
0936 while ($row = $db->sql_fetchrow($result))
0937 {
0938 if ($row['topic_id'])
0939 {
0940 $topic_ids[] = (int) $row['topic_id'];
0941 }
0942 $draft_rows[] = $row;
0943 }
0944 $db->sql_freeresult($result);
0945
0946 if (!sizeof($draft_rows))
0947 {
0948 return;
0949 }
0950
0951 $topic_rows = array();
0952 if (sizeof($topic_ids))
0953 {
0954 $sql = 'SELECT topic_id, forum_id, topic_title, topic_poster
0955 FROM ' . TOPICS_TABLE . '
0956 WHERE ' . $db->sql_in_set('topic_id', array_unique($topic_ids));
0957 $result = $db->sql_query($sql);
0958
0959 while ($row = $db->sql_fetchrow($result))
0960 {
0961 $topic_rows[$row['topic_id']] = $row;
0962 }
0963 $db->sql_freeresult($result);
0964 }
0965
0966 /**
0967 * Drafts found and their topics
0968 * Edit $draft_rows in order to add or remove drafts loaded
0969 *
0970 * @event core.load_drafts_draft_list_result
0971 * @var array draft_rows The drafts query result. Includes its forum id and everything about the draft
0972 * @var array topic_ids The list of topics got from the topics table
0973 * @var array topic_rows The topics that draft_rows references
0974 * @since 3.1.0-RC3
0975 */
0976 $vars = array('draft_rows', 'topic_ids', 'topic_rows');
0977 extract($phpbb_dispatcher->trigger_event('core.load_drafts_draft_list_result', compact($vars)));
0978
0979 unset($topic_ids);
0980
0981 $template->assign_var('S_SHOW_DRAFTS', true);
0982
0983 foreach ($draft_rows as $draft)
0984 {
0985 $link_topic = $link_forum = $link_pm = false;
0986 $insert_url = $view_url = $title = '';
0987
0988 if (isset($topic_rows[$draft['topic_id']])
0989 && (
0990 ($topic_rows[$draft['topic_id']]['forum_id'] && $auth->acl_get('f_read', $topic_rows[$draft['topic_id']]['forum_id']))
0991 ||
0992 (!$topic_rows[$draft['topic_id']]['forum_id'] && $auth->acl_getf_global('f_read'))
0993 ))
0994 {
0995 $topic_forum_id = ($topic_rows[$draft['topic_id']]['forum_id']) ? $topic_rows[$draft['topic_id']]['forum_id'] : $forum_id;
0996
0997 $link_topic = true;
0998 $view_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $topic_forum_id . '&t=' . $draft['topic_id']);
0999 $title = $topic_rows[$draft['topic_id']]['topic_title'];
1000
1001 $insert_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'f=' . $topic_forum_id . '&t=' . $draft['topic_id'] . '&mode=reply&d=' . $draft['draft_id']);
1002 }
1003 else if ($draft['forum_id'] && $auth->acl_get('f_read', $draft['forum_id']))
1004 {
1005 $link_forum = true;
1006 $view_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $draft['forum_id']);
1007 $title = $draft['forum_name'];
1008
1009 $insert_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'f=' . $draft['forum_id'] . '&mode=post&d=' . $draft['draft_id']);
1010 }
1011 else
1012 {
1013 // Either display as PM draft if forum_id and topic_id are empty or if access to the forums has been denied afterwards...
1014 $link_pm = true;
1015 $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" : ''));
1016 }
1017
1018 $template->assign_block_vars('draftrow', array(
1019 'DRAFT_ID' => $draft['draft_id'],
1020 'DATE' => $user->format_date($draft['save_time']),
1021 'DRAFT_SUBJECT' => $draft['draft_subject'],
1022
1023 'TITLE' => $title,
1024 'U_VIEW' => $view_url,
1025 'U_INSERT' => $insert_url,
1026
1027 'S_LINK_PM' => $link_pm,
1028 'S_LINK_TOPIC' => $link_topic,
1029 'S_LINK_FORUM' => $link_forum)
1030 );
1031 }
1032 }
1033
1034 /**
1035 * Topic Review
1036 */
1037 function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id = 0, $show_quote_button = true)
1038 {
1039 global $user, $auth, $db, $template, $bbcode, $cache;
1040 global $config, $phpbb_root_path, $phpEx, $phpbb_container;
1041
1042 $phpbb_content_visibility = $phpbb_container->get('content.visibility');
1043 $sql_sort = ($mode == 'post_review') ? 'ASC' : 'DESC';
1044
1045 // Go ahead and pull all data for this topic
1046 $sql = 'SELECT p.post_id
1047 FROM ' . POSTS_TABLE . ' p' . "
1048 WHERE p.topic_id = $topic_id
1049 AND " . $phpbb_content_visibility->get_visibility_sql('post', $forum_id, 'p.') . '
1050 ' . (($mode == 'post_review') ? " AND p.post_id > $cur_post_id" : '') . '
1051 ' . (($mode == 'post_review_edit') ? " AND p.post_id = $cur_post_id" : '') . '
1052 ORDER BY p.post_time ' . $sql_sort . ', p.post_id ' . $sql_sort;
1053 $result = $db->sql_query_limit($sql, $config['posts_per_page']);
1054
1055 $post_list = array();
1056
1057 while ($row = $db->sql_fetchrow($result))
1058 {
1059 $post_list[] = $row['post_id'];
1060 }
1061
1062 $db->sql_freeresult($result);
1063
1064 if (!sizeof($post_list))
1065 {
1066 return false;
1067 }
1068
1069 // Handle 'post_review_edit' like 'post_review' from now on
1070 if ($mode == 'post_review_edit')
1071 {
1072 $mode = 'post_review';
1073 }
1074
1075 $sql_ary = array(
1076 'SELECT' => 'u.username, u.user_id, u.user_colour, p.*, z.friend, z.foe',
1077
1078 'FROM' => array(
1079 USERS_TABLE => 'u',
1080 POSTS_TABLE => 'p',
1081 ),
1082
1083 'LEFT_JOIN' => array(
1084 array(
1085 'FROM' => array(ZEBRA_TABLE => 'z'),
1086 'ON' => 'z.user_id = ' . $user->data['user_id'] . ' AND z.zebra_id = p.poster_id',
1087 ),
1088 ),
1089
1090 'WHERE' => $db->sql_in_set('p.post_id', $post_list) . '
1091 AND u.user_id = p.poster_id',
1092 );
1093
1094 $sql = $db->sql_build_query('SELECT', $sql_ary);
1095 $result = $db->sql_query($sql);
1096
1097 $bbcode_bitfield = '';
1098 $rowset = array();
1099 $has_attachments = false;
1100 while ($row = $db->sql_fetchrow($result))
1101 {
1102 $rowset[$row['post_id']] = $row;
1103 $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']);
1104
1105 if ($row['post_attachment'])
1106 {
1107 $has_attachments = true;
1108 }
1109 }
1110 $db->sql_freeresult($result);
1111
1112 // Instantiate BBCode class
1113 if (!isset($bbcode) && $bbcode_bitfield !== '')
1114 {
1115 include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx);
1116 $bbcode = new bbcode(base64_encode($bbcode_bitfield));
1117 }
1118
1119 // Grab extensions
1120 $extensions = $attachments = array();
1121 if ($has_attachments && $auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id))
1122 {
1123 $extensions = $cache->obtain_attach_extensions($forum_id);
1124
1125 // Get attachments...
1126 $sql = 'SELECT *
1127 FROM ' . ATTACHMENTS_TABLE . '
1128 WHERE ' . $db->sql_in_set('post_msg_id', $post_list) . '
1129 AND in_message = 0
1130 ORDER BY filetime DESC, post_msg_id ASC';
1131 $result = $db->sql_query($sql);
1132
1133 while ($row = $db->sql_fetchrow($result))
1134 {
1135 $attachments[$row['post_msg_id']][] = $row;
1136 }
1137 $db->sql_freeresult($result);
1138 }
1139
1140 for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i)
1141 {
1142 // A non-existing rowset only happens if there was no user present for the entered poster_id
1143 // This could be a broken posts table.
1144 if (!isset($rowset[$post_list[$i]]))
1145 {
1146 continue;
1147 }
1148
1149 $row = $rowset[$post_list[$i]];
1150
1151 $poster_id = $row['user_id'];
1152 $post_subject = $row['post_subject'];
1153
1154 $decoded_message = false;
1155
1156 if ($show_quote_button && $auth->acl_get('f_reply', $forum_id))
1157 {
1158 $decoded_message = censor_text($row['post_text']);
1159 decode_message($decoded_message, $row['bbcode_uid']);
1160
1161 $decoded_message = bbcode_nl2br($decoded_message);
1162 }
1163
1164 $parse_flags = ($row['bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0);
1165 $parse_flags |= ($row['enable_smilies'] ? OPTION_FLAG_SMILIES : 0);
1166 $message = generate_text_for_display($row['post_text'], $row['bbcode_uid'], $row['bbcode_bitfield'], $parse_flags, true);
1167
1168 if (!empty($attachments[$row['post_id']]))
1169 {
1170 $update_count = array();
1171 parse_attachments($forum_id, $message, $attachments[$row['post_id']], $update_count);
1172 }
1173
1174 $post_subject = censor_text($post_subject);
1175
1176 $post_anchor = ($mode == 'post_review') ? 'ppr' . $row['post_id'] : 'pr' . $row['post_id'];
1177 $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']}");
1178
1179 $template->assign_block_vars($mode . '_row', array(
1180 'POST_AUTHOR_FULL' => get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
1181 'POST_AUTHOR_COLOUR' => get_username_string('colour', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
1182 'POST_AUTHOR' => get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
1183 'U_POST_AUTHOR' => get_username_string('profile', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
1184
1185 'S_HAS_ATTACHMENTS' => (!empty($attachments[$row['post_id']])) ? true : false,
1186 'S_FRIEND' => ($row['friend']) ? true : false,
1187 'S_IGNORE_POST' => ($row['foe']) ? true : false,
1188 '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>') : '',
1189
1190 'POST_SUBJECT' => $post_subject,
1191 'MINI_POST_IMG' => $user->img('icon_post_target', $user->lang['POST']),
1192 'POST_DATE' => $user->format_date($row['post_time']),
1193 'MESSAGE' => $message,
1194 'DECODED_MESSAGE' => $decoded_message,
1195 'POST_ID' => $row['post_id'],
1196 'U_MINI_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'p=' . $row['post_id']) . '#p' . $row['post_id'],
1197 '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) : '',
1198 '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'])) : '')
1199 );
1200
1201 // Display not already displayed Attachments for this post, we already parsed them. ;)
1202 if (!empty($attachments[$row['post_id']]))
1203 {
1204 foreach ($attachments[$row['post_id']] as $attachment)
1205 {
1206 $template->assign_block_vars($mode . '_row.attachment', array(
1207 'DISPLAY_ATTACHMENT' => $attachment)
1208 );
1209 }
1210 }
1211
1212 unset($rowset[$post_list[$i]]);
1213 }
1214
1215 if ($mode == 'topic_review')
1216 {
1217 $template->assign_var('QUOTE_IMG', $user->img('icon_post_quote', $user->lang['REPLY_WITH_QUOTE']));
1218 }
1219
1220 return true;
1221 }
1222
1223 //
1224 // Post handling functions
1225 //
1226
1227 /**
1228 * Delete Post
1229 */
1230 function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $softdelete_reason = '')
1231 {
1232 global $db, $user, $auth, $phpbb_container;
1233 global $config, $phpEx, $phpbb_root_path;
1234
1235 // Specify our post mode
1236 $post_mode = 'delete';
1237 if (($data['topic_first_post_id'] === $data['topic_last_post_id']) && ($data['topic_posts_approved'] + $data['topic_posts_unapproved'] + $data['topic_posts_softdeleted'] == 1))
1238 {
1239 $post_mode = 'delete_topic';
1240 }
1241 else if ($data['topic_first_post_id'] == $post_id)
1242 {
1243 $post_mode = 'delete_first_post';
1244 }
1245 else if ($data['topic_last_post_id'] == $post_id)
1246 {
1247 $post_mode = 'delete_last_post';
1248 }
1249 $sql_data = array();
1250 $next_post_id = false;
1251
1252 include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
1253
1254 $db->sql_transaction('begin');
1255
1256 // we must make sure to update forums that contain the shadow'd topic
1257 if ($post_mode == 'delete_topic')
1258 {
1259 $shadow_forum_ids = array();
1260
1261 $sql = 'SELECT forum_id
1262 FROM ' . TOPICS_TABLE . '
1263 WHERE ' . $db->sql_in_set('topic_moved_id', $topic_id);
1264 $result = $db->sql_query($sql);
1265 while ($row = $db->sql_fetchrow($result))
1266 {
1267 if (!isset($shadow_forum_ids[(int) $row['forum_id']]))
1268 {
1269 $shadow_forum_ids[(int) $row['forum_id']] = 1;
1270 }
1271 else
1272 {
1273 $shadow_forum_ids[(int) $row['forum_id']]++;
1274 }
1275 }
1276 $db->sql_freeresult($result);
1277 }
1278
1279 $phpbb_content_visibility = $phpbb_container->get('content.visibility');
1280
1281 // (Soft) delete the post
1282 if ($is_soft && ($post_mode != 'delete_topic'))
1283 {
1284 $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));
1285 }
1286 else if (!$is_soft)
1287 {
1288 if (!delete_posts('post_id', array($post_id), false, false, false))
1289 {
1290 // Try to delete topic, we may had an previous error causing inconsistency
1291 if ($post_mode == 'delete_topic')
1292 {
1293 delete_topics('topic_id', array($topic_id), false);
1294 }
1295 trigger_error('ALREADY_DELETED');
1296 }
1297 }
1298
1299 $db->sql_transaction('commit');
1300
1301 // Collect the necessary information for updating the tables
1302 $sql_data[FORUMS_TABLE] = $sql_data[TOPICS_TABLE] = '';
1303 switch ($post_mode)
1304 {
1305 case 'delete_topic':
1306
1307 foreach ($shadow_forum_ids as $updated_forum => $topic_count)
1308 {
1309 // counting is fun! we only have to do sizeof($forum_ids) number of queries,
1310 // even if the topic is moved back to where its shadow lives (we count how many times it is in a forum)
1311 $sql = 'UPDATE ' . FORUMS_TABLE . '
1312 SET forum_topics_approved = forum_topics_approved - ' . $topic_count . '
1313 WHERE forum_id = ' . $updated_forum;
1314 $db->sql_query($sql);
1315 update_post_information('forum', $updated_forum);
1316 }
1317
1318 if ($is_soft)
1319 {
1320 $topic_row = array();
1321 $phpbb_content_visibility->set_topic_visibility(ITEM_DELETED, $topic_id, $forum_id, $user->data['user_id'], time(), $softdelete_reason);
1322 }
1323 else
1324 {
1325 delete_topics('topic_id', array($topic_id), false);
1326
1327 $phpbb_content_visibility->remove_topic_from_statistic($data, $sql_data);
1328
1329 $update_sql = update_post_information('forum', $forum_id, true);
1330 if (sizeof($update_sql))
1331 {
1332 $sql_data[FORUMS_TABLE] .= ($sql_data[FORUMS_TABLE]) ? ', ' : '';
1333 $sql_data[FORUMS_TABLE] .= implode(', ', $update_sql[$forum_id]);
1334 }
1335 }
1336
1337 break;
1338
1339 case 'delete_first_post':
1340 $sql = 'SELECT p.post_id, p.poster_id, p.post_time, p.post_username, u.username, u.user_colour
1341 FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u
1342 WHERE p.topic_id = $topic_id
1343 AND p.poster_id = u.user_id
1344 AND p.post_visibility = " . ITEM_APPROVED . '
1345 ORDER BY p.post_time ASC, p.post_id ASC';
1346 $result = $db->sql_query_limit($sql, 1);
1347 $row = $db->sql_fetchrow($result);
1348 $db->sql_freeresult($result);
1349
1350 if (!$row)
1351 {
1352 // No approved post, so the first is a not-approved post (unapproved or soft deleted)
1353 $sql = 'SELECT p.post_id, p.poster_id, p.post_time, p.post_username, u.username, u.user_colour
1354 FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u
1355 WHERE p.topic_id = $topic_id
1356 AND p.poster_id = u.user_id
1357 ORDER BY p.post_time ASC, p.post_id ASC";
1358 $result = $db->sql_query_limit($sql, 1);
1359 $row = $db->sql_fetchrow($result);
1360 $db->sql_freeresult($result);
1361 }
1362
1363 $next_post_id = (int) $row['post_id'];
1364
1365 $sql_data[TOPICS_TABLE] = $db->sql_build_array('UPDATE', array(
1366 'topic_poster' => (int) $row['poster_id'],
1367 'topic_first_post_id' => (int) $row['post_id'],
1368 'topic_first_poster_colour' => $row['user_colour'],
1369 'topic_first_poster_name' => ($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username'],
1370 'topic_time' => (int) $row['post_time'],
1371 ));
1372 break;
1373
1374 case 'delete_last_post':
1375 if (!$is_soft)
1376 {
1377 // Update last post information when hard deleting. Soft delete already did that by itself.
1378 $update_sql = update_post_information('forum', $forum_id, true);
1379 if (sizeof($update_sql))
1380 {
1381 $sql_data[FORUMS_TABLE] = (($sql_data[FORUMS_TABLE]) ? $sql_data[FORUMS_TABLE] . ', ' : '') . implode(', ', $update_sql[$forum_id]);
1382 }
1383
1384 $sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_bumped = 0, topic_bumper = 0';
1385
1386 $update_sql = update_post_information('topic', $topic_id, true);
1387 if (!empty($update_sql))
1388 {
1389 $sql_data[TOPICS_TABLE] .= ', ' . implode(', ', $update_sql[$topic_id]);
1390 $next_post_id = (int) str_replace('topic_last_post_id = ', '', $update_sql[$topic_id][0]);
1391 }
1392 }
1393
1394 if (!$next_post_id)
1395 {
1396 $sql = 'SELECT MAX(post_id) as last_post_id
1397 FROM ' . POSTS_TABLE . "
1398 WHERE topic_id = $topic_id
1399 AND " . $phpbb_content_visibility->get_visibility_sql('post', $forum_id);
1400 $result = $db->sql_query($sql);
1401 $next_post_id = (int) $db->sql_fetchfield('last_post_id');
1402 $db->sql_freeresult($result);
1403 }
1404 break;
1405
1406 case 'delete':
1407 $sql = 'SELECT post_id
1408 FROM ' . POSTS_TABLE . "
1409 WHERE topic_id = $topic_id
1410 AND " . $phpbb_content_visibility->get_visibility_sql('post', $forum_id) . '
1411 AND post_time > ' . $data['post_time'] . '
1412 ORDER BY post_time ASC, post_id ASC';
1413 $result = $db->sql_query_limit($sql, 1);
1414 $next_post_id = (int) $db->sql_fetchfield('post_id');
1415 $db->sql_freeresult($result);
1416 break;
1417 }
1418
1419 if (($post_mode == 'delete') || ($post_mode == 'delete_last_post') || ($post_mode == 'delete_first_post'))
1420 {
1421 if (!$is_soft)
1422 {
1423 $phpbb_content_visibility->remove_post_from_statistic($data, $sql_data);
1424 }
1425
1426 $sql = 'SELECT 1 AS has_attachments
1427 FROM ' . ATTACHMENTS_TABLE . '
1428 WHERE topic_id = ' . $topic_id;
1429 $result = $db->sql_query_limit($sql, 1);
1430 $has_attachments = (int) $db->sql_fetchfield('has_attachments');
1431 $db->sql_freeresult($result);
1432
1433 if (!$has_attachments)
1434 {
1435 $sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_attachment = 0';
1436 }
1437 }
1438
1439 $db->sql_transaction('begin');
1440
1441 $where_sql = array(
1442 FORUMS_TABLE => "forum_id = $forum_id",
1443 TOPICS_TABLE => "topic_id = $topic_id",
1444 USERS_TABLE => 'user_id = ' . $data['poster_id'],
1445 );
1446
1447 foreach ($sql_data as $table => $update_sql)
1448 {
1449 if ($update_sql)
1450 {
1451 $db->sql_query("UPDATE $table SET $update_sql WHERE " . $where_sql[$table]);
1452 }
1453 }
1454
1455 // Adjust posted info for this user by looking for a post by him/her within this topic...
1456 if ($post_mode != 'delete_topic' && $config['load_db_track'] && $data['poster_id'] != ANONYMOUS)
1457 {
1458 $sql = 'SELECT poster_id
1459 FROM ' . POSTS_TABLE . '
1460 WHERE topic_id = ' . $topic_id . '
1461 AND poster_id = ' . $data['poster_id'];
1462 $result = $db->sql_query_limit($sql, 1);
1463 $poster_id = (int) $db->sql_fetchfield('poster_id');
1464 $db->sql_freeresult($result);
1465
1466 // The user is not having any more posts within this topic
1467 if (!$poster_id)
1468 {
1469 $sql = 'DELETE FROM ' . TOPICS_POSTED_TABLE . '
1470 WHERE topic_id = ' . $topic_id . '
1471 AND user_id = ' . $data['poster_id'];
1472 $db->sql_query($sql);
1473 }
1474 }
1475
1476 $db->sql_transaction('commit');
1477
1478 if ($data['post_reported'] && ($post_mode != 'delete_topic'))
1479 {
1480 sync('topic_reported', 'topic_id', array($topic_id));
1481 }
1482
1483 return $next_post_id;
1484 }
1485
1486 /**
1487 * Submit Post
1488 * @todo Split up and create lightweight, simple API for this.
1489 */
1490 function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true, $update_search_index = true)
1491 {
1492 global $db, $auth, $user, $config, $phpEx, $template, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher;
1493
1494 /**
1495 * Modify the data for post submitting
1496 *
1497 * @event core.modify_submit_post_data
1498 * @var string mode Variable containing posting mode value
1499 * @var string subject Variable containing post subject value
1500 * @var string username Variable containing post author name
1501 * @var int topic_type Variable containing topic type value
1502 * @var array poll Array with the poll data for the post
1503 * @var array data Array with the data for the post
1504 * @var bool update_message Flag indicating if the post will be updated
1505 * @var bool update_search_index Flag indicating if the search index will be updated
1506 * @since 3.1.0-a4
1507 */
1508 $vars = array(
1509 'mode',
1510 'subject',
1511 'username',
1512 'topic_type',
1513 'poll',
1514 'data',
1515 'update_message',
1516 'update_search_index',
1517 );
1518 extract($phpbb_dispatcher->trigger_event('core.modify_submit_post_data', compact($vars)));
1519
1520 // We do not handle erasing posts here
1521 if ($mode == 'delete')
1522 {
1523 return false;
1524 }
1525
1526 $current_time = time();
1527
1528 if ($mode == 'post')
1529 {
1530 $post_mode = 'post';
1531 $update_message = true;
1532 }
1533 else if ($mode != 'edit')
1534 {
1535 $post_mode = 'reply';
1536 $update_message = true;
1537 }
1538 else if ($mode == 'edit')
1539 {
1540 $post_mode = ($data['topic_posts_approved'] + $data['topic_posts_unapproved'] + $data['topic_posts_softdeleted'] == 1) ? 'edit_topic' : (($data['topic_first_post_id'] == $data['post_id']) ? 'edit_first_post' : (($data['topic_last_post_id'] == $data['post_id']) ? 'edit_last_post' : 'edit'));
1541 }
1542
1543 // First of all make sure the subject and topic title are having the correct length.
1544 // To achieve this without cutting off between special chars we convert to an array and then count the elements.
1545 $subject = truncate_string($subject, 120);
1546 $data['topic_title'] = truncate_string($data['topic_title'], 120);
1547
1548 // Collect some basic information about which tables and which rows to update/insert
1549 $sql_data = $topic_row = array();
1550 $poster_id = ($mode == 'edit') ? $data['poster_id'] : (int) $user->data['user_id'];
1551
1552 // Retrieve some additional information if not present
1553 if ($mode == 'edit' && (!isset($data['post_visibility']) || !isset($data['topic_visibility']) || $data['post_visibility'] === false || $data['topic_visibility'] === false))
1554 {
1555 $sql = 'SELECT p.post_visibility, t.topic_type, t.topic_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, t.topic_visibility
1556 FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p
1557 WHERE t.topic_id = p.topic_id
1558 AND p.post_id = ' . $data['post_id'];
1559 $result = $db->sql_query($sql);
1560 $topic_row = $db->sql_fetchrow($result);
1561 $db->sql_freeresult($result);
1562
1563 $data['topic_visibility'] = $topic_row['topic_visibility'];
1564 $data['post_visibility'] = $topic_row['post_visibility'];
1565 }
1566
1567 // This variable indicates if the user is able to post or put into the queue
1568 $post_visibility = ITEM_APPROVED;
1569
1570 // Check the permissions for post approval.
1571 // Moderators must go through post approval like ordinary users.
1572 if (!$auth->acl_get('f_noapprove', $data['forum_id']))
1573 {
1574 // Post not approved, but in queue
1575 $post_visibility = ITEM_UNAPPROVED;
1576 switch ($post_mode)
1577 {
1578 case 'edit_first_post':
1579 case 'edit':
1580 case 'edit_last_post':
1581 case 'edit_topic':
1582 $post_visibility = ITEM_REAPPROVE;
1583 break;
1584 }
1585 }
1586
1587 // MODs/Extensions are able to force any visibility on posts
1588 if (isset($data['force_approved_state']))
1589 {
1590 $post_visibility = (in_array((int) $data['force_approved_state'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED, ITEM_REAPPROVE))) ? (int) $data['force_approved_state'] : $post_visibility;
1591 }
1592 if (isset($data['force_visibility']))
1593 {
1594 $post_visibility = (in_array((int) $data['force_visibility'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED, ITEM_REAPPROVE))) ? (int) $data['force_visibility'] : $post_visibility;
1595 }
1596
1597 // Start the transaction here
1598 $db->sql_transaction('begin');
1599
1600 // Collect Information
1601 switch ($post_mode)
1602 {
1603 case 'post':
1604 case 'reply':
1605 $sql_data[POSTS_TABLE]['sql'] = array(
1606 'forum_id' => $data['forum_id'],
1607 'poster_id' => (int) $user->data['user_id'],
1608 'icon_id' => $data['icon_id'],
1609 'poster_ip' => $user->ip,
1610 'post_time' => $current_time,
1611 'post_visibility' => $post_visibility,
1612 'enable_bbcode' => $data['enable_bbcode'],
1613 'enable_smilies' => $data['enable_smilies'],
1614 'enable_magic_url' => $data['enable_urls'],
1615 'enable_sig' => $data['enable_sig'],
1616 'post_username' => (!$user->data['is_registered']) ? $username : '',
1617 'post_subject' => $subject,
1618 'post_text' => $data['message'],
1619 'post_checksum' => $data['message_md5'],
1620 'post_attachment' => (!empty($data['attachment_data'])) ? 1 : 0,
1621 'bbcode_bitfield' => $data['bbcode_bitfield'],
1622 'bbcode_uid' => $data['bbcode_uid'],
1623 'post_postcount' => ($auth->acl_get('f_postcount', $data['forum_id'])) ? 1 : 0,
1624 'post_edit_locked' => $data['post_edit_locked']
1625 );
1626 break;
1627
1628 case 'edit_first_post':
1629 case 'edit':
1630
1631 case 'edit_last_post':
1632 case 'edit_topic':
1633
1634 // If edit reason is given always display edit info
1635
1636 // If editing last post then display no edit info
1637 // If m_edit permission then display no edit info
1638 // If normal edit display edit info
1639
1640 // Display edit info if edit reason given or user is editing his post, which is not the last within the topic.
1641 if ($data['post_edit_reason'] || (!$auth->acl_get('m_edit', $data['forum_id']) && ($post_mode == 'edit' || $post_mode == 'edit_first_post')))
1642 {
1643 $data['post_edit_reason'] = truncate_string($data['post_edit_reason'], 255, 255, false);
1644
1645 $sql_data[POSTS_TABLE]['sql'] = array(
1646 'post_edit_time' => $current_time,
1647 'post_edit_reason' => $data['post_edit_reason'],
1648 'post_edit_user' => (int) $data['post_edit_user'],
1649 );
1650
1651 $sql_data[POSTS_TABLE]['stat'][] = 'post_edit_count = post_edit_count + 1';
1652 }
1653 else if (!$data['post_edit_reason'] && $mode == 'edit' && $auth->acl_get('m_edit', $data['forum_id']))
1654 {
1655 $sql_data[POSTS_TABLE]['sql'] = array(
1656 'post_edit_reason' => '',
1657 );
1658 }
1659
1660 // If the person editing this post is different to the one having posted then we will add a log entry stating the edit
1661 // Could be simplified by only adding to the log if the edit is not tracked - but this may confuse admins/mods
1662 if ($user->data['user_id'] != $poster_id)
1663 {
1664 $log_subject = ($subject) ? $subject : $data['topic_title'];
1665 add_log('mod', $data['forum_id'], $data['topic_id'], 'LOG_POST_EDITED', $log_subject, (!empty($username)) ? $username : $user->lang['GUEST'], $data['post_edit_reason']);
1666 }
1667
1668 if (!isset($sql_data[POSTS_TABLE]['sql']))
1669 {
1670 $sql_data[POSTS_TABLE]['sql'] = array();
1671 }
1672
1673 $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array(
1674 'forum_id' => $data['forum_id'],
1675 'poster_id' => $data['poster_id'],
1676 'icon_id' => $data['icon_id'],
1677 // We will change the visibility later
1678 //'post_visibility' => $post_visibility,
1679 'enable_bbcode' => $data['enable_bbcode'],
1680 'enable_smilies' => $data['enable_smilies'],
1681 'enable_magic_url' => $data['enable_urls'],
1682 'enable_sig' => $data['enable_sig'],
1683 'post_username' => ($username && $data['poster_id'] == ANONYMOUS) ? $username : '',
1684 'post_subject' => $subject,
1685 'post_checksum' => $data['message_md5'],
1686 'post_attachment' => (!empty($data['attachment_data'])) ? 1 : 0,
1687 'bbcode_bitfield' => $data['bbcode_bitfield'],
1688 'bbcode_uid' => $data['bbcode_uid'],
1689 'post_edit_locked' => $data['post_edit_locked'])
1690 );
1691
1692 if ($update_message)
1693 {
1694 $sql_data[POSTS_TABLE]['sql']['post_text'] = $data['message'];
1695 }
1696
1697 break;
1698 }
1699 $topic_row = array();
1700
1701 // And the topic ladies and gentlemen
1702 switch ($post_mode)
1703 {
1704 case 'post':
1705 $sql_data[TOPICS_TABLE]['sql'] = array(
1706 'topic_poster' => (int) $user->data['user_id'],
1707 'topic_time' => $current_time,
1708 'topic_last_view_time' => $current_time,
1709 'forum_id' => $data['forum_id'],
1710 'icon_id' => $data['icon_id'],
1711 'topic_posts_approved' => ($post_visibility == ITEM_APPROVED) ? 1 : 0,
1712 'topic_posts_softdeleted' => ($post_visibility == ITEM_DELETED) ? 1 : 0,
1713 'topic_posts_unapproved' => ($post_visibility == ITEM_UNAPPROVED) ? 1 : 0,
1714 'topic_visibility' => $post_visibility,
1715 'topic_delete_user' => ($post_visibility != ITEM_APPROVED) ? (int) $user->data['user_id'] : 0,
1716 'topic_title' => $subject,
1717 'topic_first_poster_name' => (!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : ''),
1718 'topic_first_poster_colour' => $user->data['user_colour'],
1719 'topic_type' => $topic_type,
1720 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data['topic_time_limit'] * 86400) : 0,
1721 'topic_attachment' => (!empty($data['attachment_data'])) ? 1 : 0,
1722 );
1723
1724 if (isset($poll['poll_options']) && !empty($poll['poll_options']))
1725 {
1726 $poll_start = ($poll['poll_start']) ? $poll['poll_start'] : $current_time;
1727 $poll_length = $poll['poll_length'] * 86400;
1728 if ($poll_length < 0)
1729 {
1730 $poll_start = $poll_start + $poll_length;
1731 if ($poll_start < 0)
1732 {
1733 $poll_start = 0;
1734 }
1735 $poll_length = 1;
1736 }
1737
1738 $sql_data[TOPICS_TABLE]['sql'] = array_merge($sql_data[TOPICS_TABLE]['sql'], array(
1739 'poll_title' => $poll['poll_title'],
1740 'poll_start' => $poll_start,
1741 'poll_max_options' => $poll['poll_max_options'],
1742 'poll_length' => $poll_length,
1743 'poll_vote_change' => $poll['poll_vote_change'])
1744 );
1745 }
1746
1747 $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : '');
1748
1749 if ($post_visibility == ITEM_APPROVED)
1750 {
1751 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_approved = forum_topics_approved + 1';
1752 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_approved = forum_posts_approved + 1';
1753 }
1754 else if ($post_visibility == ITEM_UNAPPROVED)
1755 {
1756 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_unapproved = forum_topics_unapproved + 1';
1757 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_unapproved = forum_posts_unapproved + 1';
1758 }
1759 else if ($post_visibility == ITEM_DELETED)
1760 {
1761 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_softdeleted = forum_topics_softdeleted + 1';
1762 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_softdeleted = forum_posts_softdeleted + 1';
1763 }
1764 break;
1765
1766 case 'reply':
1767 $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_view_time = ' . $current_time . ',
1768 topic_bumped = 0,
1769 topic_bumper = 0' .
1770 (($post_visibility == ITEM_APPROVED) ? ', topic_posts_approved = topic_posts_approved + 1' : '') .
1771 (($post_visibility == ITEM_UNAPPROVED) ? ', topic_posts_unapproved = topic_posts_unapproved + 1' : '') .
1772 (($post_visibility == ITEM_DELETED) ? ', topic_posts_softdeleted = topic_posts_softdeleted + 1' : '') .
1773 ((!empty($data['attachment_data']) || (isset($data['topic_attachment']) && $data['topic_attachment'])) ? ', topic_attachment = 1' : '');
1774
1775 $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : '');
1776
1777 if ($post_visibility == ITEM_APPROVED)
1778 {
1779 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_approved = forum_posts_approved + 1';
1780 }
1781 else if ($post_visibility == ITEM_UNAPPROVED)
1782 {
1783 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_unapproved = forum_posts_unapproved + 1';
1784 }
1785 else if ($post_visibility == ITEM_DELETED)
1786 {
1787 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_softdeleted = forum_posts_softdeleted + 1';
1788 }
1789 break;
1790
1791 case 'edit_topic':
1792 case 'edit_first_post':
1793 if (isset($poll['poll_options']))
1794 {
1795 $poll_start = ($poll['poll_start'] || empty($poll['poll_options'])) ? $poll['poll_start'] : $current_time;
1796 $poll_length = $poll['poll_length'] * 86400;
1797 if ($poll_length < 0)
1798 {
1799 $poll_start = $poll_start + $poll_length;
1800 if ($poll_start < 0)
1801 {
1802 $poll_start = 0;
1803 }
1804 $poll_length = 1;
1805 }
1806 }
1807
1808 $sql_data[TOPICS_TABLE]['sql'] = array(
1809 'forum_id' => $data['forum_id'],
1810 'icon_id' => $data['icon_id'],
1811 'topic_title' => $subject,
1812 'topic_first_poster_name' => $username,
1813 'topic_type' => $topic_type,
1814 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data['topic_time_limit'] * 86400) : 0,
1815 'poll_title' => (isset($poll['poll_options'])) ? $poll['poll_title'] : '',
1816 'poll_start' => (isset($poll['poll_options'])) ? $poll_start : 0,
1817 'poll_max_options' => (isset($poll['poll_options'])) ? $poll['poll_max_options'] : 1,
1818 'poll_length' => (isset($poll['poll_options'])) ? $poll_length : 0,
1819 'poll_vote_change' => (isset($poll['poll_vote_change'])) ? $poll['poll_vote_change'] : 0,
1820 'topic_last_view_time' => $current_time,
1821
1822 'topic_attachment' => (!empty($data['attachment_data'])) ? 1 : (isset($data['topic_attachment']) ? $data['topic_attachment'] : 0),
1823 );
1824
1825 break;
1826 }
1827
1828 // Submit new topic
1829 if ($post_mode == 'post')
1830 {
1831 $sql = 'INSERT INTO ' . TOPICS_TABLE . ' ' .
1832 $db->sql_build_array('INSERT', $sql_data[TOPICS_TABLE]['sql']);
1833 $db->sql_query($sql);
1834
1835 $data['topic_id'] = $db->sql_nextid();
1836
1837 $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array(
1838 'topic_id' => $data['topic_id'])
1839 );
1840 unset($sql_data[TOPICS_TABLE]['sql']);
1841 }
1842
1843 // Submit new post
1844 if ($post_mode == 'post' || $post_mode == 'reply')
1845 {
1846 if ($post_mode == 'reply')
1847 {
1848 $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array(
1849 'topic_id' => $data['topic_id'],
1850 ));
1851 }
1852
1853 $sql = 'INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data[POSTS_TABLE]['sql']);
1854 $db->sql_query($sql);
1855 $data['post_id'] = $db->sql_nextid();
1856
1857 if ($post_mode == 'post' || $post_visibility == ITEM_APPROVED)
1858 {
1859 $sql_data[TOPICS_TABLE]['sql'] = array(
1860 'topic_last_post_id' => $data['post_id'],
1861 'topic_last_post_time' => $current_time,
1862 'topic_last_poster_id' => $sql_data[POSTS_TABLE]['sql']['poster_id'],
1863 'topic_last_poster_name' => ($user->data['user_id'] == ANONYMOUS) ? $sql_data[POSTS_TABLE]['sql']['post_username'] : $user->data['username'],
1864 'topic_last_poster_colour' => $user->data['user_colour'],
1865 'topic_last_post_subject' => (string) $subject,
1866 );
1867 }
1868
1869 if ($post_mode == 'post')
1870 {
1871 $sql_data[TOPICS_TABLE]['sql']['topic_first_post_id'] = $data['post_id'];
1872 }
1873
1874 // Update total post count and forum information
1875 if ($post_visibility == ITEM_APPROVED)
1876 {
1877 if ($post_mode == 'post')
1878 {
1879 set_config_count('num_topics', 1, true);
1880 }
1881 set_config_count('num_posts', 1, true);
1882
1883 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . $data['post_id'];
1884 $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'";
1885 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . $current_time;
1886 $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $user->data['user_id'];
1887 $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'] : '')) . "'";
1888 $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($user->data['user_colour']) . "'";
1889 }
1890
1891 unset($sql_data[POSTS_TABLE]['sql']);
1892 }
1893
1894 // Update the topics table
1895 if (isset($sql_data[TOPICS_TABLE]['sql']))
1896 {
1897 $sql = 'UPDATE ' . TOPICS_TABLE . '
1898 SET ' . $db->sql_build_array('UPDATE', $sql_data[TOPICS_TABLE]['sql']) . '
1899 WHERE topic_id = ' . $data['topic_id'];
1900 $db->sql_query($sql);
1901
1902 unset($sql_data[TOPICS_TABLE]['sql']);
1903 }
1904
1905 // Update the posts table
1906 if (isset($sql_data[POSTS_TABLE]['sql']))
1907 {
1908 $sql = 'UPDATE ' . POSTS_TABLE . '
1909 SET ' . $db->sql_build_array('UPDATE', $sql_data[POSTS_TABLE]['sql']) . '
1910 WHERE post_id = ' . $data['post_id'];
1911 $db->sql_query($sql);
1912
1913 unset($sql_data[POSTS_TABLE]['sql']);
1914 }
1915
1916 // Update Poll Tables
1917 if (isset($poll['poll_options']))
1918 {
1919 $cur_poll_options = array();
1920
1921 if ($mode == 'edit')
1922 {
1923 $sql = 'SELECT *
1924 FROM ' . POLL_OPTIONS_TABLE . '
1925 WHERE topic_id = ' . $data['topic_id'] . '
1926 ORDER BY poll_option_id';
1927 $result = $db->sql_query($sql);
1928
1929 $cur_poll_options = array();
1930 while ($row = $db->sql_fetchrow($result))
1931 {
1932 $cur_poll_options[] = $row;
1933 }
1934 $db->sql_freeresult($result);
1935 }
1936
1937 $sql_insert_ary = array();
1938
1939 for ($i = 0, $size = sizeof($poll['poll_options']); $i < $size; $i++)
1940 {
1941 if (strlen(trim($poll['poll_options'][$i])))
1942 {
1943 if (empty($cur_poll_options[$i]))
1944 {
1945 // If we add options we need to put them to the end to be able to preserve votes...
1946 $sql_insert_ary[] = array(
1947 'poll_option_id' => (int) sizeof($cur_poll_options) + 1 + sizeof($sql_insert_ary),
1948 'topic_id' => (int) $data['topic_id'],
1949 'poll_option_text' => (string) $poll['poll_options'][$i]
1950 );
1951 }
1952 else if ($poll['poll_options'][$i] != $cur_poll_options[$i])
1953 {
1954 $sql = 'UPDATE ' . POLL_OPTIONS_TABLE . "
1955 SET poll_option_text = '" . $db->sql_escape($poll['poll_options'][$i]) . "'
1956 WHERE poll_option_id = " . $cur_poll_options[$i]['poll_option_id'] . '
1957 AND topic_id = ' . $data['topic_id'];
1958 $db->sql_query($sql);
1959 }
1960 }
1961 }
1962
1963 $db->sql_multi_insert(POLL_OPTIONS_TABLE, $sql_insert_ary);
1964
1965 if (sizeof($poll['poll_options']) < sizeof($cur_poll_options))
1966 {
1967 $sql = 'DELETE FROM ' . POLL_OPTIONS_TABLE . '
1968 WHERE poll_option_id > ' . sizeof($poll['poll_options']) . '
1969 AND topic_id = ' . $data['topic_id'];
1970 $db->sql_query($sql);
1971 }
1972
1973 // 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
1974 if ($mode == 'edit' && sizeof($poll['poll_options']) != sizeof($cur_poll_options))
1975 {
1976 $db->sql_query('DELETE FROM ' . POLL_VOTES_TABLE . ' WHERE topic_id = ' . $data['topic_id']);
1977 $db->sql_query('UPDATE ' . POLL_OPTIONS_TABLE . ' SET poll_option_total = 0 WHERE topic_id = ' . $data['topic_id']);
1978 }
1979 }
1980
1981 // Submit Attachments
1982 if (!empty($data['attachment_data']) && $data['post_id'] && in_array($mode, array('post', 'reply', 'quote', 'edit')))
1983 {
1984 $space_taken = $files_added = 0;
1985 $orphan_rows = array();
1986
1987 foreach ($data['attachment_data'] as $pos => $attach_row)
1988 {
1989 $orphan_rows[(int) $attach_row['attach_id']] = array();
1990 }
1991
1992 if (sizeof($orphan_rows))
1993 {
1994 $sql = 'SELECT attach_id, filesize, physical_filename
1995 FROM ' . ATTACHMENTS_TABLE . '
1996 WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . '
1997 AND is_orphan = 1
1998 AND poster_id = ' . $user->data['user_id'];
1999 $result = $db->sql_query($sql);
2000
2001 $orphan_rows = array();
2002 while ($row = $db->sql_fetchrow($result))
2003 {
2004 $orphan_rows[$row['attach_id']] = $row;
2005 }
2006 $db->sql_freeresult($result);
2007 }
2008
2009 foreach ($data['attachment_data'] as $pos => $attach_row)
2010 {
2011 if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']]))
2012 {
2013 continue;
2014 }
2015
2016 if (!$attach_row['is_orphan'])
2017 {
2018 // update entry in db if attachment already stored in db and filespace
2019 $sql = 'UPDATE ' . ATTACHMENTS_TABLE . "
2020 SET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "'
2021 WHERE attach_id = " . (int) $attach_row['attach_id'] . '
2022 AND is_orphan = 0';
2023 $db->sql_query($sql);
2024 }
2025 else
2026 {
2027 // insert attachment into db
2028 if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($orphan_rows[$attach_row['attach_id']]['physical_filename'])))
2029 {
2030 continue;
2031 }
2032
2033 $space_taken += $orphan_rows[$attach_row['attach_id']]['filesize'];
2034 $files_added++;
2035
2036 $attach_sql = array(
2037 'post_msg_id' => $data['post_id'],
2038 'topic_id' => $data['topic_id'],
2039 'is_orphan' => 0,
2040 'poster_id' => $poster_id,
2041 'attach_comment' => $attach_row['attach_comment'],
2042 );
2043
2044 $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $attach_sql) . '
2045 WHERE attach_id = ' . $attach_row['attach_id'] . '
2046 AND is_orphan = 1
2047 AND poster_id = ' . $user->data['user_id'];
2048 $db->sql_query($sql);
2049 }
2050 }
2051
2052 if ($space_taken && $files_added)
2053 {
2054 set_config_count('upload_dir_size', $space_taken, true);
2055 set_config_count('num_files', $files_added, true);
2056 }
2057 }
2058
2059 $first_post_has_topic_info = ($post_mode == 'edit_first_post' &&
2060 (($post_visibility == ITEM_DELETED && $data['topic_posts_softdeleted'] == 1) ||
2061 ($post_visibility == ITEM_UNAPPROVED && $data['topic_posts_unapproved'] == 1) ||
2062 ($post_visibility == ITEM_REAPPROVE && $data['topic_posts_unapproved'] == 1) ||
2063 ($post_visibility == ITEM_APPROVED && $data['topic_posts_approved'] == 1)));
2064 // Fix the post's and topic's visibility and first/last post information, when the post is edited
2065 if (($post_mode != 'post' && $post_mode != 'reply') && $data['post_visibility'] != $post_visibility)
2066 {
2067 // If the post was not approved, it could also be the starter,
2068 // so we sync the starter after approving/restoring, to ensure that the stats are correct
2069 // Same applies for the last post
2070 $is_starter = ($post_mode == 'edit_first_post' || $post_mode == 'edit_topic' || $data['post_visibility'] != ITEM_APPROVED);
2071 $is_latest = ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $data['post_visibility'] != ITEM_APPROVED);
2072
2073 $phpbb_content_visibility = $phpbb_container->get('content.visibility');
2074 $phpbb_content_visibility->set_post_visibility($post_visibility, $data['post_id'], $data['topic_id'], $data['forum_id'], $user->data['user_id'], time(), '', $is_starter, $is_latest);
2075 }
2076 else if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $first_post_has_topic_info)
2077 {
2078 if ($post_visibility == ITEM_APPROVED || $data['topic_visibility'] == $post_visibility)
2079 {
2080 // only the subject can be changed from edit
2081 $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($subject) . "'";
2082
2083 // Maybe not only the subject, but also changing anonymous usernames. ;)
2084 if ($data['poster_id'] == ANONYMOUS)
2085 {
2086 $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape($username) . "'";
2087 }
2088
2089 if ($post_visibility == ITEM_APPROVED)
2090 {
2091 // this does not _necessarily_ mean that we must update the info again,
2092 // it just means that we might have to
2093 $sql = 'SELECT forum_last_post_id, forum_last_post_subject
2094 FROM ' . FORUMS_TABLE . '
2095 WHERE forum_id = ' . (int) $data['forum_id'];
2096 $result = $db->sql_query($sql);
2097 $row = $db->sql_fetchrow($result);
2098 $db->sql_freeresult($result);
2099
2100 // this post is the latest post in the forum, better update
2101 if ($row['forum_last_post_id'] == $data['post_id'] && ($row['forum_last_post_subject'] !== $subject || $data['poster_id'] == ANONYMOUS))
2102 {
2103 // the post's subject changed
2104 if ($row['forum_last_post_subject'] !== $subject)
2105 {
2106 $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'";
2107 }
2108
2109 // Update the user name if poster is anonymous... just in case a moderator changed it
2110 if ($data['poster_id'] == ANONYMOUS)
2111 {
2112 $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($username) . "'";
2113 }
2114 }
2115 }
2116 }
2117 }
2118
2119 // Update forum stats
2120 $where_sql = array(
2121 POSTS_TABLE => 'post_id = ' . $data['post_id'],
2122 TOPICS_TABLE => 'topic_id = ' . $data['topic_id'],
2123 FORUMS_TABLE => 'forum_id = ' . $data['forum_id'],
2124 USERS_TABLE => 'user_id = ' . $poster_id
2125 );
2126
2127 foreach ($sql_data as $table => $update_ary)
2128 {
2129 if (isset($update_ary['stat']) && implode('', $update_ary['stat']))
2130 {
2131 $sql = "UPDATE $table SET " . implode(', ', $update_ary['stat']) . ' WHERE ' . $where_sql[$table];
2132 $db->sql_query($sql);
2133 }
2134 }
2135
2136 // Delete topic shadows (if any exist). We do not need a shadow topic for an global announcement
2137 if ($topic_type == POST_GLOBAL)
2138 {
2139 $sql = 'DELETE FROM ' . TOPICS_TABLE . '
2140 WHERE topic_moved_id = ' . $data['topic_id'];
2141 $db->sql_query($sql);
2142 }
2143
2144 // Committing the transaction before updating search index
2145 $db->sql_transaction('commit');
2146
2147 // Delete draft if post was loaded...
2148 $draft_id = request_var('draft_loaded', 0);
2149 if ($draft_id)
2150 {
2151 $sql = 'DELETE FROM ' . DRAFTS_TABLE . "
2152 WHERE draft_id = $draft_id
2153 AND user_id = {$user->data['user_id']}";
2154 $db->sql_query($sql);
2155 }
2156
2157 // Index message contents
2158 if ($update_search_index && $data['enable_indexing'])
2159 {
2160 // Select the search method and do some additional checks to ensure it can actually be utilised
2161 $search_type = $config['search_type'];
2162
2163 if (!class_exists($search_type))
2164 {
2165 trigger_error('NO_SUCH_SEARCH_MODULE');
2166 }
2167
2168 $error = false;
2169 $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user);
2170
2171 if ($error)
2172 {
2173 trigger_error($error);
2174 }
2175
2176 $search->index($mode, $data['post_id'], $data['message'], $subject, $poster_id, $data['forum_id']);
2177 }
2178
2179 // Topic Notification, do not change if moderator is changing other users posts...
2180 if ($user->data['user_id'] == $poster_id)
2181 {
2182 if (!$data['notify_set'] && $data['notify'])
2183 {
2184 $sql = 'INSERT INTO ' . TOPICS_WATCH_TABLE . ' (user_id, topic_id)
2185 VALUES (' . $user->data['user_id'] . ', ' . $data['topic_id'] . ')';
2186 $db->sql_query($sql);
2187 }
2188 else if (($config['email_enable'] || $config['jab_enable']) && $data['notify_set'] && !$data['notify'])
2189 {
2190 $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . '
2191 WHERE user_id = ' . $user->data['user_id'] . '
2192 AND topic_id = ' . $data['topic_id'];
2193 $db->sql_query($sql);
2194 }
2195 }
2196
2197 if ($mode == 'post' || $mode == 'reply' || $mode == 'quote')
2198 {
2199 // Mark this topic as posted to
2200 markread('post', $data['forum_id'], $data['topic_id']);
2201 }
2202
2203 // Mark this topic as read
2204 // We do not use post_time here, this is intended (post_time can have a date in the past if editing a message)
2205 markread('topic', $data['forum_id'], $data['topic_id'], time());
2206
2207 //
2208 if ($config['load_db_lastread'] && $user->data['is_registered'])
2209 {
2210 $sql = 'SELECT mark_time
2211 FROM ' . FORUMS_TRACK_TABLE . '
2212 WHERE user_id = ' . $user->data['user_id'] . '
2213 AND forum_id = ' . $data['forum_id'];
2214 $result = $db->sql_query($sql);
2215 $f_mark_time = (int) $db->sql_fetchfield('mark_time');
2216 $db->sql_freeresult($result);
2217 }
2218 else if ($config['load_anon_lastread'] || $user->data['is_registered'])
2219 {
2220 $f_mark_time = false;
2221 }
2222
2223 if (($config['load_db_lastread'] && $user->data['is_registered']) || $config['load_anon_lastread'] || $user->data['is_registered'])
2224 {
2225 // Update forum info
2226 $sql = 'SELECT forum_last_post_time
2227 FROM ' . FORUMS_TABLE . '
2228 WHERE forum_id = ' . $data['forum_id'];
2229 $result = $db->sql_query($sql);
2230 $forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time');
2231 $db->sql_freeresult($result);
2232
2233 update_forum_tracking_info($data['forum_id'], $forum_last_post_time, $f_mark_time, false);
2234 }
2235
2236 // If a username was supplied or the poster is a guest, we will use the supplied username.
2237 // Doing it this way we can use "...post by guest-username..." in notifications when
2238 // "guest-username" is supplied or ommit the username if it is not.
2239 $username = ($username !== '' || !$user->data['is_registered']) ? $username : $user->data['username'];
2240
2241 // Send Notifications
2242 $notification_data = array_merge($data, array(
2243 'topic_title' => (isset($data['topic_title'])) ? $data['topic_title'] : $subject,
2244 'post_username' => $username,
2245 'poster_id' => $poster_id,
2246 'post_text' => $data['message'],
2247 'post_time' => $current_time,
2248 'post_subject' => $subject,
2249 ));
2250
2251 $phpbb_notifications = $phpbb_container->get('notification_manager');
2252
2253 if ($post_visibility == ITEM_APPROVED)
2254 {
2255 switch ($mode)
2256 {
2257 case 'post':
2258 $phpbb_notifications->add_notifications(array(
2259 'notification.type.quote',
2260 'notification.type.topic',
2261 ), $notification_data);
2262 break;
2263
2264 case 'reply':
2265 case 'quote':
2266 $phpbb_notifications->add_notifications(array(
2267 'notification.type.quote',
2268 'notification.type.bookmark',
2269 'notification.type.post',
2270 ), $notification_data);
2271 break;
2272
2273 case 'edit_topic':
2274 case 'edit_first_post':
2275 case 'edit':
2276 case 'edit_last_post':
2277 $phpbb_notifications->update_notifications(array(
2278 'notification.type.quote',
2279 'notification.type.bookmark',
2280 'notification.type.topic',
2281 'notification.type.post',
2282 ), $notification_data);
2283 break;
2284 }
2285 }
2286 else if ($post_visibility == ITEM_UNAPPROVED)
2287 {
2288 switch ($mode)
2289 {
2290 case 'post':
2291 $phpbb_notifications->add_notifications('notification.type.topic_in_queue', $notification_data);
2292 break;
2293
2294 case 'reply':
2295 case 'quote':
2296 $phpbb_notifications->add_notifications('notification.type.post_in_queue', $notification_data);
2297 break;
2298
2299 case 'edit_topic':
2300 case 'edit_first_post':
2301 case 'edit':
2302 case 'edit_last_post':
2303 // Nothing to do here
2304 break;
2305 }
2306 }
2307 else if ($post_visibility == ITEM_REAPPROVE)
2308 {
2309 switch ($mode)
2310 {
2311 case 'edit_topic':
2312 case 'edit_first_post':
2313 $phpbb_notifications->add_notifications('notification.type.topic_in_queue', $notification_data);
2314
2315 // Delete the approve_post notification so we can notify the user again,
2316 // when his post got reapproved
2317 $phpbb_notifications->delete_notifications('notification.type.approve_post', $notification_data['post_id']);
2318 break;
2319
2320 case 'edit':
2321 case 'edit_last_post':
2322 $phpbb_notifications->add_notifications('notification.type.post_in_queue', $notification_data);
2323
2324 // Delete the approve_post notification so we can notify the user again,
2325 // when his post got reapproved
2326 $phpbb_notifications->delete_notifications('notification.type.approve_post', $notification_data['post_id']);
2327 break;
2328
2329 case 'post':
2330 case 'reply':
2331 case 'quote':
2332 // Nothing to do here
2333 break;
2334 }
2335 }
2336 else if ($post_visibility == ITEM_DELETED)
2337 {
2338 switch ($mode)
2339 {
2340 case 'post':
2341 case 'reply':
2342 case 'quote':
2343 case 'edit_topic':
2344 case 'edit_first_post':
2345 case 'edit':
2346 case 'edit_last_post':
2347 // Nothing to do here
2348 break;
2349 }
2350 }
2351
2352 $params = $add_anchor = '';
2353
2354 if ($post_visibility == ITEM_APPROVED)
2355 {
2356 $params .= '&t=' . $data['topic_id'];
2357
2358 if ($mode != 'post')
2359 {
2360 $params .= '&p=' . $data['post_id'];
2361 $add_anchor = '#p' . $data['post_id'];
2362 }
2363 }
2364 else if ($mode != 'post' && $post_mode != 'edit_first_post' && $post_mode != 'edit_topic')
2365 {
2366 $params .= '&t=' . $data['topic_id'];
2367 }
2368
2369 $url = (!$params) ? "{$phpbb_root_path}viewforum.$phpEx" : "{$phpbb_root_path}viewtopic.$phpEx";
2370 $url = append_sid($url, 'f=' . $data['forum_id'] . $params) . $add_anchor;
2371
2372 /**
2373 * This event is used for performing actions directly after a post or topic
2374 * has been submitted. When a new topic is posted, the topic ID is
2375 * available in the $data array.
2376 *
2377 * The only action that can be done by altering data made available to this
2378 * event is to modify the return URL ($url).
2379 *
2380 * @event core.submit_post_end
2381 * @var string mode Variable containing posting mode value
2382 * @var string subject Variable containing post subject value
2383 * @var string username Variable containing post author name
2384 * @var int topic_type Variable containing topic type value
2385 * @var array poll Array with the poll data for the post
2386 * @var array data Array with the data for the post
2387 * @var int post_visibility Variable containing up to date post visibility
2388 * @var bool update_message Flag indicating if the post will be updated
2389 * @var bool update_search_index Flag indicating if the search index will be updated
2390 * @var string url The "Return to topic" URL
2391 *
2392 * @since 3.1.0-a3
2393 * @change 3.1.0-RC3 Added vars mode, subject, username, topic_type,
2394 * poll, update_message, update_search_index
2395 */
2396 $vars = array(
2397 'mode',
2398 'subject',
2399 'username',
2400 'topic_type',
2401 'poll',
2402 'data',
2403 'post_visibility',
2404 'update_message',
2405 'update_search_index',
2406 'url',
2407 );
2408 extract($phpbb_dispatcher->trigger_event('core.submit_post_end', compact($vars)));
2409
2410 return $url;
2411 }
2412
2413 /**
2414 * Handle topic bumping
2415 * @param int $forum_id The ID of the forum the topic is being bumped belongs to
2416 * @param int $topic_id The ID of the topic is being bumping
2417 * @param array $post_data Passes some topic parameters:
2418 * - 'topic_title'
2419 * - 'topic_last_post_id'
2420 * - 'topic_last_poster_id'
2421 * - 'topic_last_post_subject'
2422 * - 'topic_last_poster_name'
2423 * - 'topic_last_poster_colour'
2424 * @param int $bump_time The time at which topic was bumped, usually it is a current time as obtained via time().
2425 * @return string An URL to the bumped topic, example: ./viewtopic.php?forum_id=1&topic_id=2&p=3#p3
2426 */
2427 function phpbb_bump_topic($forum_id, $topic_id, $post_data, $bump_time = false)
2428 {
2429 global $config, $db, $user, $phpEx, $phpbb_root_path;
2430
2431 if ($bump_time === false)
2432 {
2433 $bump_time = time();
2434 }
2435
2436 // Begin bumping
2437 $db->sql_transaction('begin');
2438
2439 // Update the topic's last post post_time
2440 $sql = 'UPDATE ' . POSTS_TABLE . "
2441 SET post_time = $bump_time
2442 WHERE post_id = {$post_data['topic_last_post_id']}
2443 AND topic_id = $topic_id";
2444 $db->sql_query($sql);
2445
2446 // Sync the topic's last post time, the rest of the topic's last post data isn't changed
2447 $sql = 'UPDATE ' . TOPICS_TABLE . "
2448 SET topic_last_post_time = $bump_time,
2449 topic_bumped = 1,
2450 topic_bumper = " . $user->data['user_id'] . "
2451 WHERE topic_id = $topic_id";
2452 $db->sql_query($sql);
2453
2454 // Update the forum's last post info
2455 $sql = 'UPDATE ' . FORUMS_TABLE . "
2456 SET forum_last_post_id = " . $post_data['topic_last_post_id'] . ",
2457 forum_last_poster_id = " . $post_data['topic_last_poster_id'] . ",
2458 forum_last_post_subject = '" . $db->sql_escape($post_data['topic_last_post_subject']) . "',
2459 forum_last_post_time = $bump_time,
2460 forum_last_poster_name = '" . $db->sql_escape($post_data['topic_last_poster_name']) . "',
2461 forum_last_poster_colour = '" . $db->sql_escape($post_data['topic_last_poster_colour']) . "'
2462 WHERE forum_id = $forum_id";
2463 $db->sql_query($sql);
2464
2465 // Update bumper's time of the last posting to prevent flood
2466 $sql = 'UPDATE ' . USERS_TABLE . "
2467 SET user_lastpost_time = $bump_time
2468 WHERE user_id = " . $user->data['user_id'];
2469 $db->sql_query($sql);
2470
2471 $db->sql_transaction('commit');
2472
2473 // Mark this topic as posted to
2474 markread('post', $forum_id, $topic_id, $bump_time);
2475
2476 // Mark this topic as read
2477 markread('topic', $forum_id, $topic_id, $bump_time);
2478
2479 // Update forum tracking info
2480 if ($config['load_db_lastread'] && $user->data['is_registered'])
2481 {
2482 $sql = 'SELECT mark_time
2483 FROM ' . FORUMS_TRACK_TABLE . '
2484 WHERE user_id = ' . $user->data['user_id'] . '
2485 AND forum_id = ' . $forum_id;
2486 $result = $db->sql_query($sql);
2487 $f_mark_time = (int) $db->sql_fetchfield('mark_time');
2488 $db->sql_freeresult($result);
2489 }
2490 else if ($config['load_anon_lastread'] || $user->data['is_registered'])
2491 {
2492 $f_mark_time = false;
2493 }
2494
2495 if (($config['load_db_lastread'] && $user->data['is_registered']) || $config['load_anon_lastread'] || $user->data['is_registered'])
2496 {
2497 // Update forum info
2498 $sql = 'SELECT forum_last_post_time
2499 FROM ' . FORUMS_TABLE . '
2500 WHERE forum_id = ' . $forum_id;
2501 $result = $db->sql_query($sql);
2502 $forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time');
2503 $db->sql_freeresult($result);
2504
2505 update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_time, false);
2506 }
2507
2508 add_log('mod', $forum_id, $topic_id, 'LOG_BUMP_TOPIC', $post_data['topic_title']);
2509
2510 $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']}";
2511
2512 return $url;
2513 }
2514
2515 /**
2516 * Show upload popup (progress bar)
2517 */
2518 function phpbb_upload_popup($forum_style = 0)
2519 {
2520 global $template, $user;
2521
2522 ($forum_style) ? $user->setup('posting', $forum_style) : $user->setup('posting');
2523
2524 page_header($user->lang['PROGRESS_BAR']);
2525
2526 $template->set_filenames(array(
2527 'popup' => 'posting_progress_bar.html')
2528 );
2529
2530 $template->assign_vars(array(
2531 'PROGRESS_BAR' => $user->img('upload_bar', $user->lang['UPLOAD_IN_PROGRESS']))
2532 );
2533
2534 $template->display('popup');
2535
2536 garbage_collection();
2537 exit_handler();
2538 }
2539
2540 /**
2541 * Do the various checks required for removing posts as well as removing it
2542 */
2543 function phpbb_handle_post_delete($forum_id, $topic_id, $post_id, &$post_data, $is_soft = false, $delete_reason = '')
2544 {
2545 global $user, $auth, $config, $request;
2546 global $phpbb_root_path, $phpEx;
2547
2548 $perm_check = ($is_soft) ? 'softdelete' : 'delete';
2549
2550 // If moderator removing post or user itself removing post, present a confirmation screen
2551 if ($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'])))
2552 {
2553 $s_hidden_fields = array(
2554 'p' => $post_id,
2555 'f' => $forum_id,
2556 'mode' => ($is_soft) ? 'soft_delete' : 'delete',
2557 );
2558
2559 if (confirm_box(true))
2560 {
2561 $data = array(
2562 'topic_first_post_id' => $post_data['topic_first_post_id'],
2563 'topic_last_post_id' => $post_data['topic_last_post_id'],
2564 'topic_posts_approved' => $post_data['topic_posts_approved'],
2565 'topic_posts_unapproved' => $post_data['topic_posts_unapproved'],
2566 'topic_posts_softdeleted' => $post_data['topic_posts_softdeleted'],
2567 'topic_visibility' => $post_data['topic_visibility'],
2568 'topic_type' => $post_data['topic_type'],
2569 'post_visibility' => $post_data['post_visibility'],
2570 'post_reported' => $post_data['post_reported'],
2571 'post_time' => $post_data['post_time'],
2572 'poster_id' => $post_data['poster_id'],
2573 'post_postcount' => $post_data['post_postcount'],
2574 );
2575
2576 $next_post_id = delete_post($forum_id, $topic_id, $post_id, $data, $is_soft, $delete_reason);
2577 $post_username = ($post_data['poster_id'] == ANONYMOUS && !empty($post_data['post_username'])) ? $post_data['post_username'] : $post_data['username'];
2578
2579 if ($next_post_id === false)
2580 {
2581 add_log('mod', $forum_id, $topic_id, (($is_soft) ? 'LOG_SOFTDELETE_TOPIC' : 'LOG_DELETE_TOPIC'), $post_data['topic_title'], $post_username, $delete_reason);
2582
2583 $meta_info = append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id");
2584 $message = $user->lang['POST_DELETED'];
2585 }
2586 else
2587 {
2588 add_log('mod', $forum_id, $topic_id, (($is_soft) ? 'LOG_SOFTDELETE_POST' : 'LOG_DELETE_POST'), $post_data['post_subject'], $post_username, $delete_reason);
2589
2590 $meta_info = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id&p=$next_post_id") . "#p$next_post_id";
2591 $message = $user->lang['POST_DELETED'];
2592
2593 if (!$request->is_ajax())
2594 {
2595 $message .= '<br /><br />' . $user->lang('RETURN_TOPIC', '<a href="' . $meta_info . '">', '</a>');
2596 }
2597 }
2598
2599 meta_refresh(3, $meta_info);
2600 if (!$request->is_ajax())
2601 {
2602 $message .= '<br /><br />' . $user->lang('RETURN_FORUM', '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id) . '">', '</a>');
2603 }
2604 trigger_error($message);
2605 }
2606 else
2607 {
2608 global $user, $template, $request;
2609
2610 $can_delete = $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));
2611 $can_softdelete = $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));
2612
2613 $template->assign_vars(array(
2614 'S_SOFTDELETED' => $post_data['post_visibility'] == ITEM_DELETED,
2615 'S_CHECKED_PERMANENT' => $request->is_set_post('delete_permanent') ? ' checked="checked"' : '',
2616 'S_ALLOWED_DELETE' => $can_delete,
2617 'S_ALLOWED_SOFTDELETE' => $can_softdelete,
2618 ));
2619
2620 $l_confirm = 'DELETE_POST';
2621 if ($post_data['post_visibility'] == ITEM_DELETED)
2622 {
2623 $l_confirm .= '_PERMANENTLY';
2624 $s_hidden_fields['delete_permanent'] = '1';
2625 }
2626 else if (!$can_softdelete)
2627 {
2628 $s_hidden_fields['delete_permanent'] = '1';
2629 }
2630
2631 confirm_box(false, $l_confirm, build_hidden_fields($s_hidden_fields), 'confirm_delete_body.html');
2632 }
2633 }
2634
2635 // If we are here the user is not able to delete - present the correct error message
2636 if ($post_data['poster_id'] != $user->data['user_id'] && $auth->acl_get('f_delete', $forum_id))
2637 {
2638 trigger_error('DELETE_OWN_POSTS');
2639 }
2640
2641 if ($post_data['poster_id'] == $user->data['user_id'] && $auth->acl_get('f_delete', $forum_id) && $post_id != $post_data['topic_last_post_id'])
2642 {
2643 trigger_error('CANNOT_DELETE_REPLIED');
2644 }
2645
2646 trigger_error('USER_CANNOT_DELETE');
2647 }
2648