Making WordPress.org


Ignore:
Timestamp:
09/17/2023 06:18:29 PM (19 months ago)
Author:
Clorith
Message:

Support Forums: Improved topic report flows.

Where previously, a reported topic would store the report in post meta and be limited to the sidebar view, and any reaction would be secret, unless a moderator contacted reporters publicly, this is no longer the case.

When a report is made, while we maintain the modlook tag as before for compatibility reasons, the report is added as a custom post type entry. This allows for tracking vigilant users who help out a lot, as well as giving us access to valuable data about what kind of reports are being made.

The reports are also presented as "replies" within a topic, giving valuable contextual information to those reviewing reports during the time of the report. This element is also presented in such a way that a moderator is able to respond to a report directly, letting the user view their previous reports and their outcomes within their forum profile, as well as them getting notified of the outcome by email when a topic is handled.

Fixes #5715.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/support-forums/inc/class-report-topic.php

    r12801 r12892  
    44
    55class Report_Topic {
     6
     7    /**
     8     * @var array An array of notices to potential show users reporting a topic.
     9     */
     10    private $frontend_notices = array();
     11
     12    private $report_inline_notices = array();
    613
    714    public function __construct() {
    815        add_action( 'wporg_support_after_topic_info', array( $this, 'add_sidebar_form' ) );
    916
     17        add_action( 'init', array( $this, 'register_report_post_type' ) );
     18        add_action( 'add_meta_boxes_reported_topics', array( $this, 'add_report_meta_boxes' ) );
     19
    1020        add_action( 'set_object_terms', array( $this, 'detect_manual_modlook' ), 10, 6 );
    11 
    1221        add_action( 'init', array( $this, 'capture_topic_report' ) );
    13     }
    14 
     22        add_action( 'wp', array( $this, 'capture_topic_report_response' ) );
     23
     24        add_filter( 'bbp_after_has_replies_parse_args', array( $this, 'maybe_include_reports' ) );
     25        add_action( 'bbp_theme_before_reply_author_details', array( $this, 'show_report_author_badge' ) );
     26
     27        add_filter( 'bbp_get_reply_content', array( $this, 'append_report_meta' ) );
     28    }
     29
     30    /**
     31     * Register a new notice to append to the topic report form.
     32     *
     33     * @param string $type The type of notice, will be added as part of the class-name for the HTML element.
     34     * @param string $notice The plain-text message that should be displayed.
     35     * @return void
     36     */
     37    private function add_frontend_notice( $type, $notice ) {
     38        $this->frontend_notices[] = array(
     39            'type'   => $type,
     40            'notice' => $notice,
     41        );
     42    }
     43
     44    /**
     45     * Output any registered notices.
     46     *
     47     * @return void
     48     */
     49    private function show_frontend_notices() {
     50        foreach ( $this->frontend_notices as $notice ) {
     51            printf(
     52                '<div class="topic-report-notice topic-report-notice-type-%s">%s</div>',
     53                esc_attr( $notice['type'] ),
     54                esc_html( $notice['notice'] )
     55            );
     56        }
     57    }
     58
     59    /**
     60     * Append the chosen report taxonomy to any displayed reports outside of wp-admin.
     61     *
     62     * @param string $content The post content.
     63     * @return string
     64     */
     65    public function append_report_meta( $content ) {
     66        if ( 'reported_topics' !== get_post_type() ) {
     67            return $content;
     68        }
     69
     70        if ( isset( $this->report_inline_notices[ get_the_ID() ] ) && ! empty( $this->report_inline_notices[ get_the_ID() ] ) ) {
     71            foreach ( $this->report_inline_notices[ get_the_ID() ] as $notice ) {
     72                $message = sprintf(
     73                    '<div class="notice notice-inline notice-warning"><p>%s</p></div>',
     74                    esc_html( $notice )
     75                );
     76
     77                $content = $message . $content;
     78            }
     79        }
     80
     81        $reasons = get_the_terms( get_the_ID(), 'report_reasons' );
     82        if ( $reasons ) {
     83            $categories = array();
     84            foreach ( $reasons as $reason ) {
     85                $categories[] = $reason->name;
     86            }
     87
     88            $content .= sprintf(
     89                '<p class="topic-report-categories">%s</p>',
     90                sprintf(
     91                    // translators: 1: A comma-separated list of categories this report relates to.
     92                    __( 'Report category: %s', 'wporg-forums' ),
     93                    implode( ', ', $categories )
     94                )
     95            );
     96        }
     97
     98        $replies = get_comments( array(
     99            'post_id' => get_the_ID(),
     100        ) );
     101
     102        foreach ( $replies as $reply ) {
     103            if ( current_user_can( 'moderate' ) ) {
     104                $reply_meta = sprintf(
     105                    // translators: 1: The display-name of the reporter, as a link to their user profile. 2: date
     106                    __( 'Reply from %1$s on %2$s', 'wporg-forums' ),
     107                    sprintf(
     108                        '<a href="%s">%s</a>',
     109                        esc_url( bbp_get_user_profile_url( $reply->user_id ) ),
     110                        esc_html( get_the_author_meta( 'display_name', $reply->user_id ) )
     111                    ),
     112                    esc_html( get_comment_date( 'Y-m-d H:i', $reply->comment_ID ) )
     113                );
     114            } else {
     115                $reply_meta = sprintf(
     116                    // translators: 1: date
     117                    __( 'Reply from moderator on %1$s', 'wporg-forums' ),
     118                    esc_html( get_comment_date( 'Y-m-d H:i', $reply->comment_ID ) )
     119                );
     120            }
     121
     122            $content .= sprintf(
     123                '<div class="topic-report-reply">%s<div class="topic-report-reply-meta">%s</div></div>',
     124                $reply->comment_content,
     125                $reply_meta
     126            );
     127        }
     128
     129        // To avoid a back and forth situation, only accept a single response to a report.
     130        if ( empty( $replies ) && current_user_can( 'moderate' ) ) {
     131            $nonce_action = sprintf(
     132                'topic_report_reply_%d',
     133                bbp_get_reply_id()
     134            );
     135
     136            $content .= sprintf(
     137                '<hr>
     138                <form action="%s" method="post" class="topic-report-reply-form">
     139                    %s<input type="hidden" name="wporg-support-report-topic" value="%d">
     140                    <p>%s</p>
     141                    <textarea name="topic-report-reply" id="topic-report-reply" class="widefat" required="required"></textarea>
     142                    <div class="topic-report-reply-form-actions"><button type="submit" class="button button-primary">%s</button></div>
     143                </form>',
     144                esc_url( bbp_get_reply_url() ),
     145                wp_nonce_field( $nonce_action, '_wpnonce', true, false ),
     146                esc_attr( bbp_get_reply_id() ),
     147                __( 'Reply to this report:', 'wporg-forums' ),
     148                __( 'Send response', 'wporg-forums' )
     149            );
     150        }
     151
     152        return $content;
     153    }
     154
     155    /**
     156     * Handle the response action when a report has been responded to.
     157     *
     158     * @return void
     159     */
     160    public function capture_topic_report_response() {
     161        // Don't start doing expensive lookups if this is not a reply action.
     162        if ( empty( $_POST['topic-report-reply'] ) ) {
     163            return;
     164        }
     165
     166        // Do not process anything if the user is not logged in with the appropriate capabilities.
     167        if ( ! is_user_logged_in() || ! current_user_can( 'moderate' ) ) {
     168            return;
     169        }
     170
     171        $nonce_action = sprintf(
     172            'topic_report_reply_%d',
     173            (int) $_POST['wporg-support-report-topic']
     174        );
     175
     176        // Verify the nonce  to acknowledge the action.
     177        if ( ! wp_verify_nonce( $_POST['_wpnonce'], $nonce_action ) ) {
     178            return;
     179        }
     180
     181        $report = get_post( (int) $_POST['wporg-support-report-topic'] );
     182
     183        // Ensure this is a report post type being replied to.
     184        if ( 'reported_topics' !== get_post_type( $report ) ) {
     185            return;
     186        }
     187
     188        // Verify that we are posting to a report that does not already have replies
     189        if ( (int) get_comments_number( $report ) > 0 ) {
     190            if ( ! isset( $this->report_inline_notices[ $report->ID ] ) ) {
     191                $this->report_inline_notices[ $report->ID ] = array();
     192            }
     193
     194            $this->report_inline_notices[ $report->ID ][] = __( 'Your reply has not been sent, as a response was already submitted by another moderator.', 'wporg-forums' );
     195
     196            return;
     197        }
     198
     199        $prepared_post = wp_kses_post( $_POST['topic-report-reply'] );
     200
     201        wp_insert_comment(
     202            array(
     203                'comment_content' => $prepared_post,
     204                'comment_post_ID' => $report->ID,
     205                'user_id'         => get_current_user_id(),
     206            )
     207        );
     208
     209        $email_text = sprintf(
     210            // translators: 1: The users displayname. 2: The title of the reported topic. 3: The message response from a moderator.
     211            __( '%1$s,
     212
     213You recently reported the topic "%2$s".
     214
     215A moderator has reviewed the report, taken appropriate action, and provided you the following feedback:
     216
     217%3$s
     218
     219Regards,
     220The WordPress.org Team',
     221                'wporg-forums'
     222            ),
     223            get_the_author_meta( 'display_name', $report->post_author ),
     224            bbp_get_topic_title(),
     225            $prepared_post
     226        );
     227
     228        $reporter = get_userdata( $report->post_author );
     229
     230        // Send a response notification to the reporter.
     231        wp_mail(
     232            $reporter->user_email,
     233            __( 'A topic you reported has been reviewed', 'wporg-forums' ),
     234            $email_text
     235        );
     236
     237        // The report has been resolved, so remove the modlook tag.
     238        wp_remove_object_terms( get_the_ID(), 'modlook', 'topic-tag' );
     239
     240        $this->report_inline_notices[ $report->ID ][] = __( 'Your response to the report has been stored, and a copy has been emailed to the reporter.', 'wporg-forums' );
     241    }
     242
     243    /**
     244     * Display a "Report" badge on any posts injected into the topic replies that
     245     * were generated from a user reporting the active topic.
     246     *
     247     * @return void
     248     */
     249    public function show_report_author_badge() {
     250        if ( 'reported_topics' !== get_post_type() ) {
     251            return;
     252        }
     253
     254        printf(
     255            '<span class="author-badge author-badge-reporter" title="%s">%s</span>',
     256            esc_attr__( 'This entry displays the reason for reporting this topic', 'wporg-forums' ),
     257            esc_html__( 'Topic report', 'wporg-forums' )
     258        );
     259    }
     260
     261    /**
     262     * Include topic reports in the topic reply loop.
     263     *
     264     * Filters the WP_Query arguments used by bbPress to generate post replies, and append
     265     * the topic reports if the user has sufficient capabilities.
     266     *
     267     * @param array $args WP_Query arguments.
     268     * @return array
     269     */
     270    public function maybe_include_reports( $args ) {
     271        /*
     272         * Check using `bbp_is_single_user_replies()` to avoid including reports in the profile reply view.
     273         *
     274         * This is currently the only page which uses the same lookup as topic replies, but because of the
     275         * timing on when the `bbp_after_has_replies_parse_args` filter fires, we can not reliably
     276         * check if the query is done from within a topic loop, so instead we have to approach it in
     277         * the opposite way and explicitly exclude known conflicts.
     278         */
     279        if ( ! current_user_can( 'moderate' ) || ( function_exists( 'bbp_is_single_user_replies' ) && bbp_is_single_user_replies() ) ) {
     280            return $args;
     281        }
     282
     283        if ( ! is_array( $args['post_type'] ) ) {
     284            $args['post_type'] = (array) $args['post_type'];
     285        }
     286
     287        $args['post_type'][] = 'reported_topics';
     288
     289        return $args;
     290    }
     291
     292    /**
     293     * Register the Custom Post Type and taxonomy used by the report functionality.
     294     *
     295     * @return void
     296     */
     297    public function register_report_post_type() {
     298        register_post_type(
     299            'reported_topics',
     300            array(
     301                'label'             => __( 'Reported Topics', 'wporg-forums' ),
     302                'description'       => __( 'User-submitted reports of support topics or reviews.', 'wporg-forums' ),
     303                'public'            => false,
     304                'show_ui'           => current_user_can( 'moderate' ),
     305                'show_in_admin_bar' => false,
     306                'show_in_rest'      => false,
     307                'menu_icon'         => 'dashicons-flag',
     308                'capability_type'   => 'moderate',
     309                'supports'          => array( 'editor' ),
     310            )
     311        );
     312
     313        register_taxonomy(
     314            'report_reasons',
     315            'reported_topics',
     316            array(
     317                'hierarchical' => true,
     318                'labels' => array(
     319                    'name' => __( 'Reasons', 'wporg-forums' ),
     320                    'singular_name' => __( 'Reason', 'wporg-forums' ),
     321                ),
     322                'public' => false,
     323                'show_ui' => true,
     324            )
     325        );
     326    }
     327
     328    /**
     329     * Generate a set of default terms for the report reason taxonomy.
     330     *
     331     * @return void
     332     */
     333    private function create_initial_report_taxonomies() {
     334        $default_terms = array(
     335            _x( 'Guideline violation', 'Default reason for reporting a topic', 'wporg-forums' ),
     336            _x( 'Security related', 'Default reason for reporting a topic', 'wporg-forums' ),
     337            _x( 'Spam', 'Default reason for reporting a topic', 'wporg-forums' ),
     338            _x( 'NSFW (Not Safe For Work) link', 'Default reason for reporting a topic', 'wporg-forums' ),
     339            _x( 'Other', 'Default reason for reporting a topic', 'wporg-forums' ),
     340        );
     341
     342        foreach ( $default_terms as $default_term ) {
     343            wp_insert_term(
     344                $default_term,
     345                'report_reasons'
     346            );
     347        }
     348    }
     349
     350    /**
     351     * Register the custom meta boxes used to show contextual information about a report in wp-admin.
     352     *
     353     * @return void
     354     */
     355    public function add_report_meta_boxes() {
     356        add_meta_box(
     357            'report_topic',
     358            __( 'Topic', 'wporg-forums' ),
     359            array( $this, 'render_report_topic_meta_boxes' ),
     360            'reported_topics',
     361            'side'
     362        );
     363
     364        add_meta_box(
     365            'report_user',
     366            __( 'Reporter', 'wporg-forums' ),
     367            array( $this, 'render_reporter_meta_boxes' ),
     368            'reported_topics',
     369            'side'
     370        );
     371    }
     372
     373    /**
     374     * Output the contents of the reported topic meta box.
     375     *
     376     * @return void
     377     */
     378    public function render_report_topic_meta_boxes() {
     379        $topic = wp_get_post_parent_id();
     380        printf(
     381            '<p>%s</p>',
     382            sprintf(
     383                // translators: 1: Title of reported topic as a link.
     384                __( 'Reported topic: %s', 'wporg-forums' ),
     385                sprintf(
     386                    '<a href="%s">%s</a>',
     387                    esc_url( get_the_permalink( $topic ) ),
     388                    esc_html( get_the_title( $topic ) )
     389                )
     390            )
     391        );
     392
     393        printf(
     394            '<p>%s</p>',
     395            sprintf(
     396                // translators: 1: Number of posts in the topic.
     397                __( 'Replies in this topic: %d', 'wporg-forums' ),
     398                esc_html( bbp_get_topic_reply_count( $topic ) )
     399            )
     400        );
     401
     402        printf(
     403            '<p>%s</p>',
     404            sprintf(
     405                // translators: 1: Number of participants in the topic.
     406                __( 'Participants in this topic: %d', 'wporg-forums' ),
     407                esc_html( bbp_get_topic_voice_count( $topic ) )
     408            )
     409        );
     410    }
     411
     412    /**
     413     * Output the contents of the reporting user meta box.
     414     *
     415     * @return void
     416     */
     417    public function render_reporter_meta_boxes() {
     418        $post_id = get_the_ID();
     419        $author_id = get_post_field( 'post_author', $post_id );
     420
     421        $reporter_ip = get_post_meta( $post_id, '_bbp_author_ip', true );
     422
     423        printf(
     424            '<p>%s</p>',
     425            sprintf(
     426                // translators: 1: The display-name of the reporter, as a link to their user profile.
     427                __( 'Reporter: %s', 'wporg-forums' ),
     428                sprintf(
     429                    '<a href="%s">%s</a>',
     430                    esc_url( bbp_get_user_profile_url( $author_id ) ),
     431                    esc_html( get_the_author_meta( 'display_name', $author_id ) )
     432                )
     433            )
     434        );
     435
     436        printf(
     437            '<p>%s</p>',
     438            sprintf(
     439                // translators: 1: The IP address the report was submitted from.
     440                __( 'IP Address: %s', 'wporg-forums' ),
     441                esc_html( $reporter_ip )
     442            )
     443        );
     444    }
     445
     446    /**
     447     * Register a user report when the `modlook` tag is manually added to a topic via reply.
     448     *
     449     * @param int $object_id The post ID being modified.
     450     * @param array $terms An array of object term IDs or slugs.
     451     * @param array $tt_ids An array of term taxonomy IDs.
     452     * @param string $taxonomy Taxonomy slug.
     453     * @param bool $append Whether to append new terms to the old terms.
     454     * @param array $old_tt_ids Old array of term taxonomy IDs.
     455     * @return void
     456     */
    15457    public function detect_manual_modlook( $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids ) {
    16458        $modlook = null;
     
    35477
    36478        // Translators: Default string to show when a topic is reported outside the report form feature.
    37         $this->add_modlook_history( $object_id, __( '[Manually added when replying]', 'wporg-forums' ), true );
    38     }
    39 
    40     public function add_modlook_history( $topic, $reason = null ) {
    41         $reporter = $this->get_previous_reports( $topic );
    42         if ( empty( $reporter ) ) {
    43             $reporter = array();
    44         }
    45 
    46         $current_user = get_current_user_id();
    47 
    48         // In those odd cases where the same user reports a topic multiple times, let's increment them, so we can track each report time.
    49         $report_id = $current_user;
    50         if ( isset( $reporter[ $report_id ] ) ) {
    51             $increment = 1;
    52 
    53             $report_id = sprintf(
    54                 '%d-%d',
    55                 $current_user,
    56                 $increment
    57             );
    58 
    59             while ( isset( $reporter[ $report_id ] ) ) {
    60                 $increment++;
    61 
    62                 /*
    63                  * If someone reports the same topic repeatedly, let's just stop logging it to avoid
    64                  * a never ending incremental loop, our moderators are smart enough to pick up on such behavior.
    65                  */
    66                 if ( $increment > 10 ) {
    67                     return;
    68                 }
    69 
    70                 $report_id = sprintf(
    71                     '%d-%d',
    72                     $current_user,
    73                     $increment
    74                 );
    75             }
    76         }
    77 
    78         $reporter[ $report_id ] = array(
    79             'time'   => current_time( 'mysql' ),
    80             'user'   => $current_user,
    81             'reason' => $reason,
    82         );
    83 
    84         update_post_meta( $topic, '_wporg_topic_reported_by', $reporter );
    85 
    86     }
    87 
     479        $this->add_modlook_history( $object_id, __( '[This report was manually submitted using a topic-tag while submitting a reply]', 'wporg-forums' ) );
     480    }
     481
     482    /**
     483     * Create an entry in the report post type.
     484     *
     485     * @param int $topic The post ID of the topic being reported.
     486     * @param string $reason The reason provided for reporting a given topic.
     487     * @param int|null $reason_term Optional. Default `null`. The term ID for the report reason taxonomy.
     488     * @return void
     489     */
     490    public function add_modlook_history( $topic, $reason, $reason_term = null ) {
     491        $new_report = array(
     492            'post_author'    => get_current_user_id(),
     493            'post_content'   => $reason,
     494            'post_status'    => 'publish',
     495            'post_title'     => sprintf(
     496                // translators: 1: The title of the topic being reported.
     497                __( 'Topic: %s', 'wporg-forums' ),
     498                get_the_title( $topic )
     499            ),
     500            'post_type'      => 'reported_topics',
     501            'post_parent'    => $topic,
     502            'comment_status' => 'closed',
     503            'ping_status'    => 'closed',
     504            'meta_input' => array(
     505                '_bbp_author_ip' => $_SERVER['REMOTE_ADDR'],
     506            ),
     507        );
     508
     509        $new_report_id = wp_insert_post( $new_report );
     510
     511        /*
     512         * Assign the report taxonomy after the report post is created
     513         *
     514         * This is not applied during `wp_insert_post` and its report array due
     515         * to how WordPress checks capabilities for the `input_tax`, and anyone
     516         * creating a report is unlikely to have the capabilities attached to
     517         * the post type or taxonomy.
     518         */
     519        if ( null !== $reason_term && ! is_wp_error( $new_report_id ) && $new_report_id > 0 ) {
     520            wp_set_post_terms( $new_report_id, array( $reason_term ), 'report_reasons' );
     521        }
     522    }
     523
     524    /**
     525     * Capture, and process, submissions from the "Report Topic" form.
     526     *
     527     * @return void
     528     */
    88529    public function capture_topic_report() {
    89530        // Do not process anything if the user is not logged in.
     
    103544            }
    104545
     546            if ( empty( $_POST['topic-report-reason-details'] ) ) {
     547                $this->add_frontend_notice(
     548                    'error',
     549                    __( 'You must supply a reason when reporting a topic', 'wporg-forums' )
     550                );
     551                return;
     552            }
     553
     554            $validate_term = get_term( (int) $_POST['topic-report-reason'], 'report_reasons' );
     555            if ( null === $validate_term || is_wp_error( $validate_term ) ) {
     556                $this->add_frontend_notice(
     557                    'error',
     558                    __( 'You must choose a categorization for this report from the drop-down menu.', 'wporg-forums' )
     559                );
     560                return;
     561            }
     562
    105563            remove_action( 'set_object_terms', array( $this, 'detect_manual_modlook' ), 10 );
    106564            wp_add_object_terms( $_POST['wporg-support-report-topic'], 'modlook', 'topic-tag' );
    107565
    108             $reason = sprintf(
    109                 '%s: %s',
    110                 $_POST['topic-report-reason'],
    111                 $_POST['topic-report-reason-details']
    112             );
    113 
    114             $this->add_modlook_history( $_POST['wporg-support-report-topic'], $reason );
     566            $this->add_modlook_history( $_POST['wporg-support-report-topic'], $_POST['topic-report-reason-details'], (int) $_POST['topic-report-reason'] );
    115567
    116568            wp_safe_redirect( get_the_permalink( $_POST['wporg-support-report-topic'] ) );
     
    138590    }
    139591
     592    /**
     593     * Output the "Report topic" form in the forum sidebar.
     594     *
     595     * @return void
     596     */
    140597    public function add_sidebar_form() {
    141598        // We don't want to allow anonymous users to report topics, we want to track who reports them.
     
    153610        }
    154611
    155         $previous_reports = $this->get_previous_reports();
     612        $previous_reports = get_posts(
     613            array(
     614                'post_type' => 'reported_topics',
     615                'post_parent' => $topic_id,
     616                'posts_per_page' => -1
     617            )
     618        );
    156619        $is_reported      = has_term( 'modlook', 'topic-tag', $topic_id );
    157620
     
    165628            );
    166629
     630            $has_terms = get_terms(
     631                array(
     632                    'taxonomy'   => 'report_reasons',
     633                    'hide_empty' => false,
     634                    'orderby'    => 'term_id',
     635                )
     636            );
     637
     638            if ( ! $has_terms ) {
     639                $this->create_initial_report_taxonomies();
     640            }
     641
    167642            ob_start();
    168 ?>
    169 
    170             <form action="" method="post">
     643            ?>
     644
     645            <form action="" method="post">
    171646                <?php wp_nonce_field( $action ); ?>
    172                 <input type="hidden" name="wporg-support-report-topic" value="<?php echo esc_attr( bbp_get_topic_id() ); ?>">
    173 
    174                 <label for="topic-report-reason"><?php _e( 'Report this topic for:', 'wporg-forums' ); ?></label>
    175                 <select name="topic-report-reason" id="topic-report-reason" required="required">
    176                     <option value=""><?php _ex( '&mdash; Choose one &mdash;', 'Report a topic reason', 'wporg-forums' ); ?></option>
    177                     <option><?php _ex( 'Guideline violation', 'Report a topic reason', 'wporg-forums' ); ?></option>
    178                     <option><?php _ex( 'Security related', 'Report a topic reason', 'wporg-forums' ); ?></option>
    179                     <option><?php _ex( 'Spam', 'Report a topic reason', 'wporg-forums' ); ?></option>
    180                     <option><?php _ex( 'NSFW (Not Safe For Work) link', 'Report a topic reason', 'wporg-forums' ); ?></option>
    181                     <option value="other-input"><?php _ex( 'Other', 'Report a topic reason', 'wporg-forums' ); ?></option>
    182                 </select>
    183                 <aside id="report-topic-other">
    184                     <label for="topic-report-reason-details"><?php _e( 'Why are you reporting this topic:', 'wporg-forums' ); ?></label>
    185                     <input type="text" name="topic-report-reason-details" id="topic-report-reason-details" required="required">
    186                 </aside>
    187                 <input type="submit" name="submit" value="<?php esc_attr_e( 'Report', 'wporg-forums' ); ?>">
    188             </form>
    189 <?php
     647                <input type="hidden" name="wporg-support-report-topic" value="<?php echo esc_attr( bbp_get_topic_id() ); ?>">
     648
     649                <label for="topic-report-reason"><?php _e( 'Report this topic for:', 'wporg-forums' ); ?></label>
     650                <?php
     651                wp_dropdown_categories(
     652                    array(
     653                        'hide_empty'        => false,
     654                        'name'              => 'topic-report-reason',
     655                        'id'                => 'topic-report-reason',
     656                        'required'          => true,
     657                        'taxonomy'          => 'report_reasons',
     658                        'show_option_none'  => __( '&mdash; Choose one &mdash;', 'wporg-forums' ),
     659                        'option_none_value' => null,
     660                    )
     661                );
     662                ?>
     663
     664                <p>
     665                    <label for="topic-report-reason-details"><?php _e( 'Why are you reporting this topic:', 'wporg-forums' ); ?></label>
     666                    <textarea type="text" name="topic-report-reason-details" id="topic-report-reason-details" class="widefat" required="required"></textarea>
     667                </p>
     668
     669                <?php $this->show_frontend_notices(); ?>
     670
     671                <input type="submit" name="submit" value="<?php esc_attr_e( 'Submit report', 'wporg-forums' ); ?>">
     672            </form>
     673            <?php
    190674            $report_text = ob_get_clean();
    191675        }
     
    196680                esc_url( $this->remove_topic_modlook_url() ),
    197681                // translators: `modlook` is the term used for posts tagged by users when they want a moderator to have a look.
    198                 __( 'Remove modlook', 'wporg-forums' )
     682                __( 'Remove modlook', 'wporg-support' )
    199683            );
    200684        }
     
    214698            foreach( $previous_reports as $report ) {
    215699                $lines[] = sprintf(
    216                     '<li>%s</li>',
     700                    '<li><a href="%s">%s</a></li>',
     701                    esc_url( bbp_get_reply_url( $report->ID ) ),
    217702                    sprintf(
    218                         /* translators: 1: Reporters display name, 2: date, 3: time, 4: reason (when provided) */
    219                         '%1$s on %2$s at %3$s %4$s',
    220                         sprintf(
    221                             '<a href="%s">%s</a>',
    222                             esc_url( bbp_get_user_profile_url( $report['user']) ),
    223                             get_the_author_meta( 'display_name', $report['user'] )
    224                         ),
    225                         /* translators: localized date format, see https://www.php.net/date */
    226                         mysql2date( __( 'F j, Y', 'wporg-forums' ), $report['time'] ),
    227                         /* translators: localized time format, see https://www.php.net/date */
    228                         mysql2date( __( 'g:i a', 'wporg-forums' ), $report['time'] ),
    229                         ( ! isset( $report['reason'] ) || empty( $report['reason'] ) ?  '' : sprintf(
    230                             /* translators: %s: The reason this topic was reported. */
    231                             'reason: %s',
    232                             esc_html( $report['reason'] )
    233                         ) )
     703                        /* translators: 1: Reporters display name, 2: date */
     704                        '%1$s on %2$s',
     705                        esc_html( get_the_author_meta( 'display_name', $report->post_author ) ),
     706                        esc_html( bbp_get_reply_post_date( $report->ID ) ),
    234707                    )
    235708                );
     
    238711            printf(
    239712                '<li class="topic-previous-reports">%s<ul class="previous-reports">%s</ul></li>',
    240                 __( 'Previously reported by:', 'wporg-forums' ),
     713                __( 'Previous reports:', 'wporg-support' ),
    241714                implode( ' ', $lines )
    242715            );
     
    244717    }
    245718
    246     public function get_previous_reports( $topic_id = null ) {
    247         if ( null === $topic_id ) {
    248             $topic_id = bbp_get_topic_id();
    249         }
    250 
    251         $reporters = get_post_meta( $topic_id, '_wporg_topic_reported_by', true );
    252 
    253         if ( empty( $reporters ) ) {
    254             $reporters = array();
    255         }
    256 
    257         return $reporters;
    258     }
    259 
     719    /**
     720     * Generate a URL for the action of removing the `modlook` tag from a topic.
     721     *
     722     * @return string A prepared URL with nonce and actions.
     723     */
    260724    public function remove_topic_modlook_url() {
    261725        $url = add_query_arg( array(
Note: See TracChangeset for help on using the changeset viewer.