Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
3.97% covered (danger)
3.97%
14 / 353
50.00% covered (danger)
50.00%
2 / 4
CRAP
n/a
0 / 0
mcp_post_details
0.00% covered (danger)
0.00%
0 / 278
0.00% covered (danger)
0.00%
0 / 1
5550
phpbb_get_num_posters_for_ip
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
phpbb_get_num_ips_for_poster
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
change_poster
0.00% covered (danger)
0.00%
0 / 61
0.00% covered (danger)
0.00%
0 / 1
210
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*/
17if (!defined('IN_PHPBB'))
18{
19    exit;
20}
21
22/**
23* Handling actions in post details screen
24*/
25function mcp_post_details($id, $mode, $action)
26{
27    global $phpEx, $phpbb_root_path, $config, $request;
28    global $template, $db, $user, $auth;
29    global $phpbb_container, $phpbb_dispatcher;
30
31    $user->add_lang('posting');
32
33    $post_id = $request->variable('p', 0);
34    $start    = $request->variable('start', 0);
35
36    // Get post data
37    $post_info = phpbb_get_post_data(array($post_id), false, true);
38
39    add_form_key('mcp_post_details');
40
41    if (!count($post_info))
42    {
43        trigger_error('POST_NOT_EXIST');
44    }
45
46    $post_info = $post_info[$post_id];
47    $url = append_sid("{$phpbb_root_path}mcp.$phpEx?" . phpbb_extra_url());
48
49    switch ($action)
50    {
51        case 'whois':
52
53            if ($auth->acl_get('m_info', $post_info['forum_id']))
54            {
55                $ip = $request->variable('ip', '');
56                if (!function_exists('user_ipwhois'))
57                {
58                    include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
59                }
60
61                $template->assign_vars(array(
62                    'RETURN_POST'    => sprintf($user->lang['RETURN_POST'], '<a href="' . append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&amp;mode=$mode&amp;p=$post_id") . '">', '</a>'),
63                    'U_RETURN_POST'    => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&amp;mode=$mode&amp;p=$post_id"),
64                    'L_RETURN_POST'    => sprintf($user->lang['RETURN_POST'], '', ''),
65                    'WHOIS'            => user_ipwhois($ip),
66                ));
67            }
68
69            // We're done with the whois page so return
70            return;
71
72        break;
73
74        case 'chgposter':
75        case 'chgposter_ip':
76
77            if ($action == 'chgposter')
78            {
79                $username = $request->variable('username', '', true);
80                $sql_where = "username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'";
81            }
82            else
83            {
84                $new_user_id = $request->variable('u', 0);
85                $sql_where = 'user_id = ' . $new_user_id;
86            }
87
88            $sql = 'SELECT *
89                FROM ' . USERS_TABLE . '
90                WHERE ' . $sql_where;
91            $result = $db->sql_query($sql);
92            $row = $db->sql_fetchrow($result);
93            $db->sql_freeresult($result);
94
95            if (!$row)
96            {
97                trigger_error('NO_USER');
98            }
99
100            if ($auth->acl_get('m_chgposter', $post_info['forum_id']))
101            {
102                if (check_form_key('mcp_post_details'))
103                {
104                    change_poster($post_info, $row);
105                }
106                else
107                {
108                    trigger_error('FORM_INVALID');
109                }
110            }
111
112        break;
113
114        default:
115
116            /**
117            * This event allows you to handle custom post moderation options
118            *
119            * @event core.mcp_post_additional_options
120            * @var    string    action        Post moderation action name
121            * @var    array    post_info    Information on the affected post
122            * @since 3.1.5-RC1
123            */
124            $vars = array('action', 'post_info');
125            extract($phpbb_dispatcher->trigger_event('core.mcp_post_additional_options', compact($vars)));
126
127        break;
128    }
129
130    // Set some vars
131    $users_ary = $usernames_ary = array();
132    $attachments = array();
133    $post_id = $post_info['post_id'];
134
135    // Get topic tracking info
136    if ($config['load_db_lastread'])
137    {
138        $tmp_topic_data = array($post_info['topic_id'] => $post_info);
139        $topic_tracking_info = get_topic_tracking($post_info['forum_id'], $post_info['topic_id'], $tmp_topic_data, array($post_info['forum_id'] => $post_info['forum_mark_time']));
140        unset($tmp_topic_data);
141    }
142    else
143    {
144        $topic_tracking_info = get_complete_topic_tracking($post_info['forum_id'], $post_info['topic_id']);
145    }
146
147    $post_unread = (isset($topic_tracking_info[$post_info['topic_id']]) && $post_info['post_time'] > $topic_tracking_info[$post_info['topic_id']]) ? true : false;
148
149    // Process message, leave it uncensored
150    $parse_flags = ($post_info['bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0) | OPTION_FLAG_SMILIES;
151    $message = generate_text_for_display($post_info['post_text'], $post_info['bbcode_uid'], $post_info['bbcode_bitfield'], $parse_flags, false);
152
153    if ($post_info['post_attachment'] && $auth->acl_get('u_download') && $auth->acl_get('f_download', $post_info['forum_id']))
154    {
155        $sql = 'SELECT *
156            FROM ' . ATTACHMENTS_TABLE . '
157            WHERE post_msg_id = ' . $post_id . '
158                AND in_message = 0
159            ORDER BY filetime DESC, post_msg_id ASC';
160        $result = $db->sql_query($sql);
161
162        while ($row = $db->sql_fetchrow($result))
163        {
164            $attachments[] = $row;
165        }
166        $db->sql_freeresult($result);
167
168        if (count($attachments))
169        {
170            $user->add_lang('viewtopic');
171            $update_count = array();
172            parse_attachments($post_info['forum_id'], $message, $attachments, $update_count);
173        }
174
175        // Display not already displayed Attachments for this post, we already parsed them. ;)
176        if (!empty($attachments))
177        {
178            $template->assign_var('S_HAS_ATTACHMENTS', true);
179
180            foreach ($attachments as $attachment)
181            {
182                $template->assign_block_vars('attachment', array(
183                    'DISPLAY_ATTACHMENT'    => $attachment)
184                );
185            }
186        }
187    }
188
189    // Deleting information
190    if ($post_info['post_visibility'] == ITEM_DELETED && $post_info['post_delete_user'])
191    {
192        // User having deleted the post also being the post author?
193        if (!$post_info['post_delete_user'] || $post_info['post_delete_user'] == $post_info['poster_id'])
194        {
195            $display_username = get_username_string('full', $post_info['poster_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']);
196        }
197        else
198        {
199            $sql = 'SELECT user_id, username, user_colour
200                FROM ' . USERS_TABLE . '
201                WHERE user_id = ' . (int) $post_info['post_delete_user'];
202            $result = $db->sql_query($sql);
203            $user_delete_row = $db->sql_fetchrow($result);
204            $db->sql_freeresult($result);
205            $display_username = get_username_string('full', $post_info['post_delete_user'], $user_delete_row['username'], $user_delete_row['user_colour']);
206        }
207
208        $user->add_lang('viewtopic');
209        $l_deleted_by = $user->lang('DELETED_INFORMATION', $display_username, $user->format_date($post_info['post_delete_time'], false, true));
210    }
211    else
212    {
213        $l_deleted_by = '';
214    }
215
216    // parse signature
217    $parse_flags = ($post_info['user_sig_bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0) | OPTION_FLAG_SMILIES;
218    $post_info['user_sig'] = generate_text_for_display($post_info['user_sig'], $post_info['user_sig_bbcode_uid'], $post_info['user_sig_bbcode_bitfield'], $parse_flags, true);
219
220    $mcp_post_template_data = array(
221        'U_MCP_ACTION'            => "$url&amp;i=main&amp;quickmod=1&amp;mode=post_details", // Use this for mode paramaters
222        'U_POST_ACTION'            => "$url&amp;i=$id&amp;mode=post_details", // Use this for action parameters
223        'U_APPROVE_ACTION'        => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=queue&amp;p=$post_id"),
224
225        'S_CAN_APPROVE'            => $auth->acl_get('m_approve', $post_info['forum_id']),
226        'S_CAN_VIEWIP'            => $auth->acl_get('m_info', $post_info['forum_id']),
227        'S_CAN_CHGPOSTER'        => $auth->acl_get('m_chgposter', $post_info['forum_id']),
228        'S_CAN_LOCK_POST'        => $auth->acl_get('m_lock', $post_info['forum_id']),
229        'S_CAN_DELETE_POST'        => $auth->acl_get('m_delete', $post_info['forum_id']),
230
231        'S_POST_REPORTED'        => ($post_info['post_reported']) ? true : false,
232        'S_POST_UNAPPROVED'        => ($post_info['post_visibility'] == ITEM_UNAPPROVED || $post_info['post_visibility'] == ITEM_REAPPROVE) ? true : false,
233        'S_POST_DELETED'        => ($post_info['post_visibility'] == ITEM_DELETED) ? true : false,
234        'S_POST_LOCKED'            => ($post_info['post_edit_locked']) ? true : false,
235        'S_USER_NOTES'            => true,
236        'S_CLEAR_ALLOWED'        => ($auth->acl_get('a_clearlogs')) ? true : false,
237        'DELETED_MESSAGE'        => $l_deleted_by,
238        'DELETE_REASON'            => $post_info['post_delete_reason'],
239
240        'U_EDIT'                => ($auth->acl_get('m_edit', $post_info['forum_id'])) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=edit&amp;p={$post_info['post_id']}") : '',
241        'U_FIND_USERNAME'        => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=mcp_chgposter&amp;field=username&amp;select_single=true'),
242        'U_MCP_APPROVE'            => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&amp;mode=approve_details&amp;p=' . $post_id),
243        'U_MCP_REPORT'            => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&amp;mode=report_details&amp;p=' . $post_id),
244        'U_MCP_USER_NOTES'        => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&amp;mode=user_notes&amp;u=' . $post_info['user_id']),
245        'U_MCP_WARN_USER'        => ($auth->acl_get('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&amp;mode=warn_user&amp;u=' . $post_info['user_id']) : '',
246        'U_VIEW_POST'            => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'p=' . $post_info['post_id'] . '#p' . $post_info['post_id']),
247        'U_VIEW_TOPIC'            => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=' . $post_info['topic_id']),
248
249        'MINI_POST_IMG'            => ($post_unread) ? $user->img('icon_post_target_unread', 'UNREAD_POST') : $user->img('icon_post_target', 'POST'),
250        'MINI_POST'                => ($post_unread) ? $user->lang['UNREAD_POST'] : $user->lang['POST'],
251
252        'RETURN_TOPIC'            => sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", "p=$post_id") . "#p$post_id\">", '</a>'),
253        'RETURN_FORUM'            => sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", "f={$post_info['forum_id']}&amp;start={$start}") . '">', '</a>'),
254        'REPORTED_IMG'            => $user->img('icon_topic_reported', $user->lang['POST_REPORTED']),
255        'UNAPPROVED_IMG'        => $user->img('icon_topic_unapproved', $user->lang['POST_UNAPPROVED']),
256        'DELETED_IMG'            => $user->img('icon_topic_deleted', $user->lang['POST_DELETED']),
257        'EDIT_IMG'                => $user->img('icon_post_edit', $user->lang['EDIT_POST']),
258        'SEARCH_IMG'            => $user->img('icon_user_search', $user->lang['SEARCH']),
259
260        'POST_AUTHOR_FULL'        => get_username_string('full', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']),
261        'POST_AUTHOR_COLOUR'    => get_username_string('colour', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']),
262        'POST_AUTHOR'            => get_username_string('username', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']),
263        'U_POST_AUTHOR'            => get_username_string('profile', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']),
264
265        'POST_PREVIEW'            => $message,
266        'POST_SUBJECT'            => $post_info['post_subject'],
267        'POST_DATE'                => $user->format_date($post_info['post_time']),
268        'POST_IP'                => $post_info['poster_ip'],
269        'POST_IPADDR'            => ($auth->acl_get('m_info', $post_info['forum_id']) && $request->variable('lookup', '')) ? @gethostbyaddr($post_info['poster_ip']) : '',
270        'POST_ID'                => $post_info['post_id'],
271        'SIGNATURE'                => $post_info['user_sig'],
272
273        'U_LOOKUP_IP'            => ($auth->acl_get('m_info', $post_info['forum_id'])) ? "$url&amp;i=$id&amp;mode=$mode&amp;lookup={$post_info['poster_ip']}#ip" : '',
274        'U_WHOIS'                => ($auth->acl_get('m_info', $post_info['forum_id'])) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&amp;mode=$mode&amp;action=whois&amp;p=$post_id&amp;ip={$post_info['poster_ip']}") : '',
275    );
276
277    $s_additional_opts = false;
278
279    /**
280    * Event to add/modify MCP post template data
281    *
282    * @event core.mcp_post_template_data
283    * @var    array    post_info                    Array with the post information
284    * @var    array    mcp_post_template_data        Array with the MCP post template data
285    * @var    array    attachments                    Array with the post attachments, if any
286    * @var    bool    s_additional_opts            Must be set to true in extension if additional options are presented in MCP post panel
287    * @since 3.1.5-RC1
288    */
289    $vars = array(
290        'post_info',
291        'mcp_post_template_data',
292        'attachments',
293        's_additional_opts',
294    );
295    extract($phpbb_dispatcher->trigger_event('core.mcp_post_template_data', compact($vars)));
296
297    $template->assign_vars($mcp_post_template_data);
298    $template->assign_var('S_MCP_POST_ADDITIONAL_OPTS', $s_additional_opts);
299
300    unset($mcp_post_template_data);
301
302    // Get User Notes
303    $log_data = array();
304    $log_count = false;
305    view_log('user', $log_data, $log_count, $config['posts_per_page'], 0, 0, 0, $post_info['user_id']);
306
307    if (!empty($log_data))
308    {
309        $template->assign_var('S_USER_NOTES', true);
310
311        foreach ($log_data as $row)
312        {
313            $template->assign_block_vars('usernotes', array(
314                'REPORT_BY'        => $row['username_full'],
315                'REPORT_AT'        => $user->format_date($row['time']),
316                'ACTION'        => $row['action'],
317                'ID'            => $row['id'])
318            );
319        }
320    }
321
322    // Get Reports
323    if ($auth->acl_get('m_report', $post_info['forum_id']))
324    {
325        $sql = 'SELECT r.*, re.*, u.user_id, u.username
326            FROM ' . REPORTS_TABLE . ' r, ' . USERS_TABLE . ' u, ' . REPORTS_REASONS_TABLE . " re
327            WHERE r.post_id = $post_id
328                AND r.reason_id = re.reason_id
329                AND u.user_id = r.user_id
330            ORDER BY r.report_time DESC";
331        $result = $db->sql_query($sql);
332
333        if ($row = $db->sql_fetchrow($result))
334        {
335            $template->assign_var('S_SHOW_REPORTS', true);
336
337            do
338            {
339                // If the reason is defined within the language file, we will use the localized version, else just use the database entry...
340                if (isset($user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]) && isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])]))
341                {
342                    $row['reson_description'] = $user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])];
343                    $row['reason_title'] = $user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])];
344                }
345
346                $template->assign_block_vars('reports', array(
347                    'REPORT_ID'        => $row['report_id'],
348                    'REASON_TITLE'    => $row['reason_title'],
349                    'REASON_DESC'    => $row['reason_description'],
350                    'REPORTER'        => get_username_string('username', $row['user_id'], $row['username']),
351                    'U_REPORTER'    => get_username_string('profile', $row['user_id'], $row['username']),
352                    'USER_NOTIFY'    => ($row['user_notify']) ? true : false,
353                    'REPORT_TIME'    => $user->format_date($row['report_time']),
354                    'REPORT_TEXT'    => bbcode_nl2br(trim($row['report_text'])),
355                ));
356            }
357            while ($row = $db->sql_fetchrow($result));
358        }
359        $db->sql_freeresult($result);
360    }
361
362    // Get IP
363    if ($auth->acl_get('m_info', $post_info['forum_id']))
364    {
365        /** @var \phpbb\pagination $pagination */
366        $pagination = $phpbb_container->get('pagination');
367
368        $start_users = $request->variable('start_users', 0);
369        $rdns_ip_num = $request->variable('rdns', '');
370        $lookup_all = $rdns_ip_num === 'all';
371
372        $base_url = $url . '&amp;i=main&amp;mode=post_details';
373        $base_url .= $lookup_all ? '&amp;rdns=all' : '';
374
375        if (!$lookup_all)
376        {
377            $template->assign_var('U_LOOKUP_ALL', $base_url . '&amp;rdns=all');
378        }
379
380        $num_users = false;
381        if ($start_users)
382        {
383            $num_users = phpbb_get_num_posters_for_ip($db, $post_info['poster_ip']);
384            $start_users = $pagination->validate_start($start_users, $config['posts_per_page'], $num_users);
385        }
386
387        // Get other users who've posted under this IP
388        $sql = 'SELECT poster_id, COUNT(poster_id) as postings
389            FROM ' . POSTS_TABLE . "
390            WHERE poster_ip = '" . $db->sql_escape($post_info['poster_ip']) . "'
391                AND poster_id <> " . (int) $post_info['poster_id'] . "
392            GROUP BY poster_id
393            ORDER BY postings DESC, poster_id ASC";
394        $result = $db->sql_query_limit($sql, $config['posts_per_page'], $start_users);
395
396        $page_users = 0;
397        while ($row = $db->sql_fetchrow($result))
398        {
399            $page_users++;
400            $users_ary[$row['poster_id']] = $row;
401        }
402        $db->sql_freeresult($result);
403
404        if ($page_users == $config['posts_per_page'] || $start_users)
405        {
406            if ($num_users === false)
407            {
408                $num_users = phpbb_get_num_posters_for_ip($db, $post_info['poster_ip']);
409            }
410
411            $pagination->generate_template_pagination(
412                $base_url,
413                'pagination',
414                'start_users',
415                $num_users,
416                $config['posts_per_page'],
417                $start_users
418            );
419        }
420
421        if (count($users_ary))
422        {
423            // Get the usernames
424            $sql = 'SELECT user_id, username
425                FROM ' . USERS_TABLE . '
426                WHERE ' . $db->sql_in_set('user_id', array_keys($users_ary));
427            $result = $db->sql_query($sql);
428
429            while ($row = $db->sql_fetchrow($result))
430            {
431                $users_ary[$row['user_id']]['username'] = $row['username'];
432                $usernames_ary[utf8_clean_string($row['username'])] = $users_ary[$row['user_id']];
433            }
434            $db->sql_freeresult($result);
435
436            foreach ($users_ary as $user_id => $user_row)
437            {
438                $template->assign_block_vars('userrow', array(
439                    'USERNAME'        => get_username_string('username', $user_id, $user_row['username']),
440                    'NUM_POSTS'        => $user_row['postings'],
441                    'L_POST_S'        => ($user_row['postings'] == 1) ? $user->lang['POST'] : $user->lang['POSTS'],
442
443                    'U_PROFILE'        => get_username_string('profile', $user_id, $user_row['username']),
444                    'U_SEARCHPOSTS' => append_sid("{$phpbb_root_path}search.$phpEx", 'author_id=' . $user_id . '&amp;sr=topics'))
445                );
446            }
447        }
448
449        // Get other IP's this user has posted under
450
451        // A compound index on poster_id, poster_ip (posts table) would help speed up this query a lot,
452        // but the extra size is only valuable if there are persons having more than a thousands posts.
453        // This is better left to the really really big forums.
454        $start_ips = $request->variable('start_ips', 0);
455
456        $num_ips = false;
457        if ($start_ips)
458        {
459            $num_ips = phpbb_get_num_ips_for_poster($db, $post_info['poster_id']);
460            $start_ips = $pagination->validate_start($start_ips, $config['posts_per_page'], $num_ips);
461        }
462
463        $sql = 'SELECT poster_ip, COUNT(poster_ip) AS postings
464            FROM ' . POSTS_TABLE . '
465            WHERE poster_id = ' . $post_info['poster_id'] . "
466            GROUP BY poster_ip
467            ORDER BY postings DESC, poster_ip ASC";
468        $result = $db->sql_query_limit($sql, $config['posts_per_page'], $start_ips);
469
470        $page_ips = 0;
471        while ($row = $db->sql_fetchrow($result))
472        {
473            $page_ips++;
474            $hostname = (($rdns_ip_num == $row['poster_ip'] || $rdns_ip_num == 'all') && $row['poster_ip']) ? @gethostbyaddr($row['poster_ip']) : '';
475
476            $template->assign_block_vars('iprow', array(
477                'IP'            => $row['poster_ip'],
478                'HOSTNAME'        => $hostname,
479                'NUM_POSTS'        => $row['postings'],
480                'L_POST_S'        => ($row['postings'] == 1) ? $user->lang['POST'] : $user->lang['POSTS'],
481
482                'U_LOOKUP_IP'    => (!$lookup_all && $rdns_ip_num != $row['poster_ip']) ? "$base_url&amp;start_ips={$start_ips}&amp;rdns={$row['poster_ip']}#ip" : '',
483                'U_WHOIS'        => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&amp;mode=$mode&amp;action=whois&amp;p=$post_id&amp;ip={$row['poster_ip']}"))
484            );
485        }
486        $db->sql_freeresult($result);
487
488        if ($page_ips == $config['posts_per_page'] || $start_ips)
489        {
490            if ($num_ips === false)
491            {
492                $num_ips = phpbb_get_num_ips_for_poster($db, $post_info['poster_id']);
493            }
494
495            $pagination->generate_template_pagination(
496                $base_url,
497                'pagination_ips',
498                'start_ips',
499                $num_ips,
500                $config['posts_per_page'],
501                $start_ips
502            );
503        }
504
505        $user_select = '';
506
507        if (count($usernames_ary))
508        {
509            ksort($usernames_ary);
510
511            foreach ($usernames_ary as $row)
512            {
513                $user_select .= '<option value="' . $row['poster_id'] . '">' . $row['username'] . "</option>\n";
514            }
515        }
516
517        $template->assign_var('S_USER_SELECT', $user_select);
518    }
519
520}
521
522/**
523 * Get the number of posters for a given ip
524 *
525 * @param \phpbb\db\driver\driver_interface $db DBAL interface
526 * @param string $poster_ip IP
527 * @return int Number of posters
528 */
529function phpbb_get_num_posters_for_ip(\phpbb\db\driver\driver_interface $db, $poster_ip)
530{
531    $sql = 'SELECT COUNT(DISTINCT poster_id) as num_users
532        FROM ' . POSTS_TABLE . "
533        WHERE poster_ip = '" . $db->sql_escape($poster_ip) . "'";
534    $result = $db->sql_query($sql);
535    $num_users = (int) $db->sql_fetchfield('num_users');
536    $db->sql_freeresult($result);
537
538    return $num_users;
539}
540
541/**
542 * Get the number of ips for a given poster
543 *
544 * @param \phpbb\db\driver\driver_interface $db
545 * @param int $poster_id Poster user ID
546 * @return int Number of IPs for given poster
547 */
548function phpbb_get_num_ips_for_poster(\phpbb\db\driver\driver_interface $db, $poster_id)
549{
550    $sql = 'SELECT COUNT(DISTINCT poster_ip) as num_ips
551        FROM ' . POSTS_TABLE . '
552        WHERE poster_id = ' . (int) $poster_id;
553    $result = $db->sql_query($sql);
554    $num_ips = (int) $db->sql_fetchfield('num_ips');
555    $db->sql_freeresult($result);
556
557    return $num_ips;
558}
559
560/**
561* Change a post's poster
562*/
563function change_poster(&$post_info, $userdata)
564{
565    global $db, $config, $user, $phpbb_log, $phpbb_dispatcher, $phpbb_container;
566
567    if (empty($userdata) || $userdata['user_id'] == $post_info['user_id'])
568    {
569        return;
570    }
571
572    $post_id = $post_info['post_id'];
573
574    $sql = 'UPDATE ' . POSTS_TABLE . "
575        SET poster_id = {$userdata['user_id']}
576        WHERE post_id = $post_id";
577    $db->sql_query($sql);
578
579    // Resync topic/forum if needed
580    if ($post_info['topic_last_post_id'] == $post_id || $post_info['forum_last_post_id'] == $post_id || $post_info['topic_first_post_id'] == $post_id)
581    {
582        sync('topic', 'topic_id', $post_info['topic_id'], false, false);
583        sync('forum', 'forum_id', $post_info['forum_id'], false, false);
584    }
585
586    // Adjust post counts... only if the post is approved (else, it was not added the users post count anyway)
587    if ($post_info['post_postcount'] && $post_info['post_visibility'] == ITEM_APPROVED)
588    {
589        $sql = 'UPDATE ' . USERS_TABLE . '
590            SET user_posts = user_posts - 1
591            WHERE user_id = ' . $post_info['user_id'] .'
592            AND user_posts > 0';
593        $db->sql_query($sql);
594
595        $sql = 'UPDATE ' . USERS_TABLE . '
596            SET user_posts = user_posts + 1
597            WHERE user_id = ' . $userdata['user_id'];
598        $db->sql_query($sql);
599    }
600
601    // Add posted to information for this topic for the new user
602    markread('post', $post_info['forum_id'], $post_info['topic_id'], time(), $userdata['user_id']);
603
604    // Remove the dotted topic option if the old user has no more posts within this topic
605    if ($config['load_db_track'] && $post_info['user_id'] != ANONYMOUS)
606    {
607        $sql = 'SELECT topic_id
608            FROM ' . POSTS_TABLE . '
609            WHERE topic_id = ' . $post_info['topic_id'] . '
610                AND poster_id = ' . $post_info['user_id'];
611        $result = $db->sql_query_limit($sql, 1);
612        $topic_id = (int) $db->sql_fetchfield('topic_id');
613        $db->sql_freeresult($result);
614
615        if (!$topic_id)
616        {
617            $sql = 'DELETE FROM ' . TOPICS_POSTED_TABLE . '
618                WHERE user_id = ' . $post_info['user_id'] . '
619                    AND topic_id = ' . $post_info['topic_id'];
620            $db->sql_query($sql);
621        }
622    }
623
624    // change the poster_id within the attachments table, else the data becomes out of sync and errors displayed because of wrong ownership
625    if ($post_info['post_attachment'])
626    {
627        $sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
628            SET poster_id = ' . $userdata['user_id'] . '
629            WHERE poster_id = ' . $post_info['user_id'] . '
630                AND post_msg_id = ' . $post_info['post_id'] . '
631                AND topic_id = ' . $post_info['topic_id'];
632        $db->sql_query($sql);
633    }
634
635    // refresh search cache of this post
636    try
637    {
638        $search_backend_factory = $phpbb_container->get('search.backend_factory');
639        $search = $search_backend_factory->get_active();
640    }
641    catch (\phpbb\search\exception\no_search_backend_found_exception $e)
642    {
643        trigger_error('NO_SUCH_SEARCH_MODULE');
644    }
645
646    $search->index_remove([], [$post_info['user_id'], $userdata['user_id']], []);
647
648    $from_username = $post_info['username'];
649    $to_username = $userdata['username'];
650
651    /**
652    * This event allows you to perform additional tasks after changing a post's poster
653    *
654    * @event core.mcp_change_poster_after
655    * @var    array    userdata    Information on a post's new poster
656    * @var    array    post_info    Information on the affected post
657    * @since 3.1.6-RC1
658    * @changed 3.1.7-RC1        Change location to prevent post_info from being set to the new post information
659    */
660    $vars = array('userdata', 'post_info');
661    extract($phpbb_dispatcher->trigger_event('core.mcp_change_poster_after', compact($vars)));
662
663    // Renew post info
664    $post_info = phpbb_get_post_data(array($post_id), false, true);
665
666    if (!count($post_info))
667    {
668        trigger_error('POST_NOT_EXIST');
669    }
670
671    $post_info = $post_info[$post_id];
672
673    // Now add log entry
674    $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_MCP_CHANGE_POSTER', false, array(
675        'forum_id' => $post_info['forum_id'],
676        'topic_id' => $post_info['topic_id'],
677        'post_id'  => $post_info['post_id'],
678        $post_info['topic_title'],
679        $from_username,
680        $to_username
681    ));
682}