Skip to:
Content

bbPress.org

Ticket #2036: 2036.6.diff

File 2036.6.diff, 40.0 KB (added by jmdodd, 8 years ago)
  • includes/admin/metaboxes.php

     
    400400        // Get some meta
    401401        $reply_topic_id = bbp_get_reply_topic_id( $post_id );
    402402        $reply_forum_id = bbp_get_reply_forum_id( $post_id );
     403        $reply_to       = bbp_get_reply_to(       $post_id );
    403404
    404405        // Allow individual manipulation of reply forum
    405406        if ( current_user_can( 'edit_others_replies' ) || current_user_can( 'moderate' ) ) : ?>
     
    435436                <input name="parent_id" id="bbp_topic_id" type="text" value="<?php echo esc_attr( $reply_topic_id ); ?>" />
    436437        </p>
    437438
     439        <p>
     440                <strong class="label"><?php _e( 'Reply To:', 'bbpress' ); ?></strong>
     441                <label class="screen-reader-text" for="bbp_reply_to"><?php _e( 'Reply To', 'bbpress' ); ?></label>
     442                <input name="bbp_reply_to" id="bbp_reply_to" type="text" value="<?php echo esc_attr( $reply_to ); ?>" />
     443        </p>
     444
    438445        <?php
    439446        wp_nonce_field( 'bbp_reply_metabox_save', 'bbp_reply_metabox' );
    440447        do_action( 'bbp_reply_metabox', $post_id );
  • includes/admin/replies.php

     
    223223                                '<ul>' .
    224224                                        '<li>' . __( '<strong>Forum</strong> dropdown determines the parent forum that the reply belongs to. Select the forum, or leave the default (Use Forum of Topic) to post the reply in forum of the topic.', 'bbpress' ) . '</li>' .
    225225                                        '<li>' . __( '<strong>Topic</strong> determines the parent topic that the reply belongs to.', 'bbpress' ) . '</li>' .
     226                                        '<li>' . __( '<strong>Reply To</strong> determines the threading of the reply.', 'bbpress' ) . '</li>' .
    226227                                '</ul>'
    227228                ) );
    228229
     
    311312                // Get the reply meta post values
    312313                $topic_id = !empty( $_POST['parent_id']    ) ? (int) $_POST['parent_id']    : 0;
    313314                $forum_id = !empty( $_POST['bbp_forum_id'] ) ? (int) $_POST['bbp_forum_id'] : bbp_get_topic_forum_id( $topic_id );
     315                $reply_to = !empty( $_POST['bbp_reply_to'] ) ? (int) $_POST['bbp_reply_to'] : 0;
    314316
    315317                // Get reply author data
    316318                $anonymous_data = bbp_filter_anonymous_post_data();
     
    318320                $is_edit        = (bool) isset( $_POST['save'] );
    319321
    320322                // Formally update the reply
    321                 bbp_update_reply( $reply_id, $topic_id, $forum_id, $anonymous_data, $author_id, $is_edit );
     323                bbp_update_reply( $reply_id, $topic_id, $forum_id, $anonymous_data, $author_id, $is_edit, $reply_to );
    322324
    323325                // Allow other fun things to happen
    324                 do_action( 'bbp_reply_attributes_metabox_save', $reply_id, $topic_id, $forum_id );
     326                do_action( 'bbp_reply_attributes_metabox_save', $reply_id, $topic_id, $forum_id, $reply_to );
    325327                do_action( 'bbp_author_metabox_save',           $reply_id, $anonymous_data      );
    326328
    327329                return $reply_id;
  • includes/admin/settings.php

     
    169169
    170170                'bbp_settings_theme_compat' => array(
    171171
    172                         // Replies per page setting
     172                        // Theme package setting
    173173                        '_bbp_theme_package_id' => array(
    174174                                'title'             => __( 'Current Package', 'bbpress' ),
    175175                                'callback'          => 'bbp_admin_setting_callback_subtheme_id',
     
    196196                                'callback'          => 'bbp_admin_setting_callback_replies_per_page',
    197197                                'sanitize_callback' => 'intval',
    198198                                'args'              => array()
     199                        ),
     200
     201                        // Set reply threading level
     202                        '_bbp_thread_replies_depth' => array(
     203                                'title'             => __( 'Thread level', 'bbpress' ),
     204                                'callback'          => 'bbp_admin_setting_callback_thread_replies_depth',
     205                                'sanitize_callback' => 'intval',
     206                                'args'              => array()
    199207                        )
    200208                ),
    201209
     
    461469}
    462470
    463471/**
     472 * Hierarchical reply max depth level setting field; replies will be threaded
     473 * if depth is 2 or greater
     474 *
     475 * @since bbPress (r####)
     476 *
     477 * @uses apply_filters() Calls 'bbp_thread_replies_depth_max' to set a
     478 *                        maximum displayed level
     479 * @uses selected() To display the selected attribute
     480 */
     481function bbp_admin_setting_callback_thread_replies_depth() {
     482
     483        // Set maximum depth for dropdown
     484        $max_depth = (int) apply_filters( 'bbp_thread_replies_depth_max', 10 );
     485        $current_depth = get_option( '_bbp_thread_replies_depth' );
     486
     487?>
     488        <label for="_bbp_thread_replies_depth">
     489                <select id="_bbp_thread_replies_depth" name="_bbp_thread_replies_depth">
     490                <?php for ( $i = 0; $i <= $max_depth; $i++ ) : ?>
     491
     492                        <option value="<?php echo esc_attr( $i ); ?>" <?php selected( $i, $current_depth ); ?>><?php echo esc_html( $i ); ?></option>
     493
     494                <?php endfor; ?>
     495                </select>
     496        <?php _e( ' levels deep', 'bbpress' ); ?>
     497        </label>
     498<?php
     499}
     500
     501/**
    464502 * Allow topic and reply revisions
    465503 *
    466504 * @since bbPress (r3412)
  • includes/common/classes.php

     
    259259        }
    260260}
    261261
     262/**
     263 * Create hierarchical list of bbPress replies.
     264 *
     265 * @package bbPress
     266 * @subpackage Classes
     267 *
     268 * @since bbPress (r####)
     269 */
     270class Walker_Reply extends Walker {
     271
     272        /**
     273         * @see Walker::$tree_type
     274         *
     275         * @since bbPress (r####)
     276         *
     277         * @var string
     278         */
     279        var $tree_type = 'reply';
     280
     281        /**
     282         * @see Walker::$db_fields
     283         *
     284         * @since bbPress (r####)
     285         *
     286         * @var array
     287         */
     288        var $db_fields = array(
     289                'parent' => 'reply_to',
     290                'id' => 'ID'
     291        );
     292
     293        /**
     294         * @see Walker::start_lvl()
     295         *
     296         * @since bbPress (r####)
     297         *
     298         * @param string $output Passed by reference. Used to append additional content
     299         * @param int $depth Depth of reply
     300         * @param array $args Uses 'style' argument for type of HTML list
     301         */
     302        public function start_lvl( &$output, $depth = 0, $args = array( ) ) {
     303                $GLOBALS['reply_depth'] = $depth + 1;
     304
     305                switch ( $args['style'] ) {
     306                        case 'div':
     307                                break;
     308                        case 'ol':
     309                                echo "<ol class='children'>\n";
     310                                break;
     311                        case 'ul':
     312                        default:
     313                                echo "<ul class='children'>\n";
     314                                break;
     315                }
     316        }
     317
     318        /**
     319         * @see Walker::end_lvl()
     320         *
     321         * @since bbPress (r####)
     322         *
     323         * @param string $output Passed by reference. Used to append additional content
     324         * @param int $depth Depth of reply
     325         * @param array $args Will only append content if style argument value is 'ol' or 'ul'
     326         */
     327        public function end_lvl( &$output, $depth = 0, $args = array( ) ) {
     328                $GLOBALS['reply_depth'] = $depth + 1;
     329
     330                switch ( $args['style'] ) {
     331                        case 'div':
     332                                break;
     333                        case 'ol':
     334                                echo "</ol>\n";
     335                                break;
     336                        case 'ul':
     337                        default:
     338                                echo "</ul>\n";
     339                                break;
     340                }
     341        }
     342
     343        /**
     344         * @since bbPress (r####)
     345         */
     346        public function display_element( $element, &$children_elements, $max_depth, $depth = 0, $args, &$output ) {
     347
     348                if ( !$element )
     349                        return;
     350
     351                // Get element's id
     352                $id_field = $this->db_fields['id'];
     353                $id = $element->$id_field;
     354
     355                // Display element
     356                parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
     357
     358                // If we're at the max depth and the current element still has children, loop over those
     359                // and display them at this level to prevent them being orphaned to the end of the list.
     360                if ( $max_depth <= $depth + 1 && isset( $children_elements[$id] ) ) {
     361                        foreach ( $children_elements[$id] as $child )
     362                                $this->display_element( $child, $children_elements, $max_depth, $depth, $args, $output );
     363
     364                        unset( $children_elements[$id] );
     365                }
     366        }
     367
     368        /**
     369         * @see Walker:start_el()
     370         *
     371         * @since bbPress (r####)
     372         */
     373        public function start_el( &$output, $reply, $depth, $args, $id = 0 ) {
     374
     375                // Set up reply
     376                $depth++;
     377                $GLOBALS['reply_depth'] = $depth;
     378                bbpress()->reply_query->post = $reply;
     379                bbpress()->current_reply_id = $reply->ID;
     380
     381                // Check for a callback and use it if specified
     382                if ( !empty( $args['callback'] ) ) {
     383                        call_user_func( $args['callback'], $reply, $args, $depth );
     384                        return;
     385                }
     386
     387                // Style for div or list element
     388                if ( 'div' == $args['style'] ) {
     389                        $tag = 'div';
     390                        $add_below = 'reply';
     391                } else {
     392                        $tag = 'li';
     393                        $add_below = 'div-reply';
     394                } ?>
     395
     396                <<?php echo $tag ?>>
     397
     398                        <?php bbp_get_template_part( 'loop', 'single-reply' ); ?>
     399
     400                </<?php echo $tag ?>>
     401
     402                <?php
     403        }
     404
     405        /**
     406         * @since bbPress (r####)
     407         */
     408        public function end_el( &$output, $reply, $depth = 0, $args = array( ) ) {
     409
     410                // Check for a callback and use it if specified
     411                if ( !empty( $args['end-callback'] ) ) {
     412                        call_user_func( $args['end-callback'], $reply, $args, $depth );
     413                        return;
     414                }
     415
     416                // Style for div or list element
     417                if ( 'div' == $args['style'] )
     418                        echo "</div>\n";
     419                else
     420                        echo "</li>\n";
     421        }
     422}
     423
    262424endif; // class_exists check
  • includes/common/template-tags.php

     
    15411541
    15421542                <input type="hidden" name="bbp_reply_title" id="bbp_reply_title" value="<?php bbp_reply_title(); ?>" />
    15431543                <input type="hidden" name="bbp_reply_id"    id="bbp_reply_id"    value="<?php bbp_reply_id(); ?>" />
     1544                <input type="hidden" name="bbp_reply_to"    id="bbp_reply_to"    value="<?php bbp_form_reply_to(); ?>" />
    15441545                <input type="hidden" name="action"          id="bbp_post_action" value="bbp-edit-reply" />
    15451546
    15461547                <?php if ( current_user_can( 'unfiltered_html' ) )
     
    15521553
    15531554                <input type="hidden" name="bbp_reply_title" id="bbp_reply_title" value="<?php printf( __( 'Reply To: %s', 'bbpress' ), bbp_get_topic_title() ); ?>" />
    15541555                <input type="hidden" name="bbp_topic_id"    id="bbp_topic_id"    value="<?php bbp_topic_id(); ?>" />
     1556                <input type="hidden" name="bbp_reply_to"    id="bbp_reply_to"    value="<?php bbp_form_reply_to(); ?>" />
    15551557                <input type="hidden" name="action"          id="bbp_post_action" value="bbp-new-reply" />
    15561558
    15571559                <?php if ( current_user_can( 'unfiltered_html' ) )
  • includes/core/actions.php

     
    179179add_action( 'bbp_forum_attributes_metabox_save', 'bbp_save_forum_extras', 2 );
    180180
    181181// New/Edit Reply
    182 add_action( 'bbp_new_reply',  'bbp_update_reply', 10, 6 );
    183 add_action( 'bbp_edit_reply', 'bbp_update_reply', 10, 6 );
     182add_action( 'bbp_new_reply',  'bbp_update_reply', 10, 7 );
     183add_action( 'bbp_edit_reply', 'bbp_update_reply', 10, 7 );
    184184
    185185// Before Delete/Trash/Untrash Reply
    186186add_action( 'wp_trash_post', 'bbp_trash_reply'   );
  • includes/core/options.php

     
    3434                '_bbp_enable_favorites'     => 1,                          // Favorites
    3535                '_bbp_enable_subscriptions' => 1,                          // Subscriptions
    3636                '_bbp_allow_topic_tags'     => 1,                          // Topic Tags
     37                '_bbp_thread_replies_depth' => 0,                          // Thread replies depth
    3738                '_bbp_allow_anonymous'      => 0,                          // Allow anonymous posting
    3839                '_bbp_allow_global_access'  => 1,                          // Users from all sites can post
    3940                '_bbp_use_wp_editor'        => 1,                          // Use the WordPress editor if available
     
    224225}
    225226
    226227/**
     228 * Are replies threaded
     229 *
     230 * @since bbPress (r####)
     231 *
     232 * @param bool $default Optional. Default value true
     233 * @uses apply_filters() Calls 'bbp_thread_replies' with the calculated value and
     234 *                        the thread replies depth
     235 * @uses get_option() To get thread replies option
     236 * @return bool Are replies threaded?
     237 */
     238function bbp_thread_replies() {
     239        $depth  = bbp_thread_replies_depth();
     240        $retval = (bool) ( $depth > 1 );
     241
     242        return (bool) apply_filters( 'bbp_thread_replies', $retval, $depth );
     243}
     244
     245/**
     246 * Maximum reply thread depth
     247 *
     248 * @since bbPress (r####)
     249 *
     250 * @param int $default Thread replies depth
     251 * @uses apply_filters() Calls 'bbp_thread_replies_depth' with the option value and
     252 *                       the default depth
     253 * @uses get_option() To get the thread replies depth
     254 * @return int Thread replies depth
     255 */
     256function bbp_thread_replies_depth( $default = 1 ) {
     257        return (int) apply_filters( 'bbp_thread_replies_depth', (int) get_option( '_bbp_thread_replies_depth', $default ) );
     258}
     259
     260/**
    227261 * Are topic and reply revisions allowed
    228262 *
    229263 * @since bbPress (r3412)
     
    280314 * @return bool Use WP editor?
    281315 */
    282316function bbp_use_wp_editor( $default = 1 ) {
     317
     318        // Disable if replies are threaded
     319        if ( bbp_thread_replies() )
     320                $default = 0;
     321
    283322        return (bool) apply_filters( 'bbp_use_wp_editor', (bool) get_option( '_bbp_use_wp_editor', $default ) );
    284323}
    285324
  • includes/replies/functions.php

     
    9797 * @uses wp_set_post_terms() To set the topic tags
    9898 * @uses wp_insert_post() To insert the reply
    9999 * @uses do_action() Calls 'bbp_new_reply' with the reply id, topic id, forum
    100  *                    id, anonymous data and reply author
     100 *                    id, anonymous data, reply author, edit (false), and
     101 *                    the reply to id
    101102 * @uses bbp_get_reply_url() To get the paginated url to the reply
    102103 * @uses wp_safe_redirect() To redirect to the reply url
    103104 * @uses bbPress::errors::get_error_message() To get the {@link WP_Error} error
     
    116117        }
    117118
    118119        // Define local variable(s)
    119         $topic_id = $forum_id = $reply_author = $anonymous_data = 0;
     120        $topic_id = $forum_id = $reply_author = $anonymous_data = $reply_to = 0;
    120121        $reply_title = $reply_content = $terms = '';
    121122
    122123        /** Reply Author **********************************************************/
     
    165166                bbp_add_error( 'bbp_reply_forum_id', __( '<strong>ERROR</strong>: Forum ID is missing.', 'bbpress' ) );
    166167        }
    167168
     169        /** Reply To **************************************************************/
     170
     171        // Handle Reply To of the reply; $_REQUEST for non-JS submissions
     172        if ( isset( $_REQUEST['bbp_reply_to'] ) ) {
     173                $reply_to = (int) $_REQUEST['bbp_reply_to'];
     174        }
     175
     176        $reply_to = bbp_get_reply_id( $reply_to );
     177
    168178        /** Unfiltered HTML *******************************************************/
    169179
    170180        // Remove the custom kses filters from title and content for capable users and if the nonce is verified
     
    333343
    334344                /** Update counts, etc... *********************************************/
    335345
    336                 do_action( 'bbp_new_reply', $reply_id, $topic_id, $forum_id, $anonymous_data, $reply_author );
     346                do_action( 'bbp_new_reply', $reply_id, $topic_id, $forum_id, $anonymous_data, $reply_author, false, $reply_to );
    337347
    338348                /** Additional Actions (After Save) ***********************************/
    339349
     
    390400 * @uses wp_update_post() To update the reply
    391401 * @uses bbp_get_reply_topic_id() To get the reply topic id
    392402 * @uses bbp_get_topic_forum_id() To get the topic forum id
     403 * @uses bbp_get_reply_to() To get the reply to id
    393404 * @uses do_action() Calls 'bbp_edit_reply' with the reply id, topic id, forum
    394  *                    id, anonymous data, reply author and bool true (for edit)
     405 *                    id, anonymous data, reply author, bool true (for edit),
     406 *                    and the reply to id
    395407 * @uses bbp_get_reply_url() To get the paginated url to the reply
    396408 * @uses wp_safe_redirect() To redirect to the reply url
    397409 * @uses bbPress::errors::get_error_message() To get the {@link WP_Error} error
     
    469481
    470482        $forum_id = bbp_get_topic_forum_id( $topic_id );
    471483
     484        /** Reply To **************************************************************/
     485
     486        $reply_to = bbp_get_reply_to( $reply_id );
     487
    472488        // Forum exists
    473489        if ( !empty( $forum_id ) && ( $forum_id !== bbp_get_reply_forum_id( $reply_id ) ) ) {
    474490
     
    618634        if ( !empty( $reply_id ) && !is_wp_error( $reply_id ) ) {
    619635
    620636                // Update counts, etc...
    621                 do_action( 'bbp_edit_reply', $reply_id, $topic_id, $forum_id, $anonymous_data, $reply_author , true /* Is edit */ );
     637                do_action( 'bbp_edit_reply', $reply_id, $topic_id, $forum_id, $anonymous_data, $reply_author , true /* Is edit */, $reply_to );
    622638
    623639                /** Additional Actions (After Save) ***********************************/
    624640
     
    660676 * @param bool|array $anonymous_data Optional logged-out user data.
    661677 * @param int $author_id Author id
    662678 * @param bool $is_edit Optional. Is the post being edited? Defaults to false.
     679 * @param int $reply_to Optional. Reply to id
    663680 * @uses bbp_get_reply_id() To get the reply id
    664681 * @uses bbp_get_topic_id() To get the topic id
    665682 * @uses bbp_get_forum_id() To get the forum id
     
    676693 * @uses bbp_add_user_subscription() To add the user's subscription
    677694 * @uses bbp_update_reply_forum_id() To update the reply forum id
    678695 * @uses bbp_update_reply_topic_id() To update the reply topic id
     696 * @uses bbp_update_reply_to() To update the reply to id
    679697 * @uses bbp_update_reply_walker() To update the reply's ancestors' counts
    680698 */
    681 function bbp_update_reply( $reply_id = 0, $topic_id = 0, $forum_id = 0, $anonymous_data = false, $author_id = 0, $is_edit = false ) {
     699function bbp_update_reply( $reply_id = 0, $topic_id = 0, $forum_id = 0, $anonymous_data = false, $author_id = 0, $is_edit = false, $reply_to = 0 ) {
    682700
    683701        // Validate the ID's passed from 'bbp_new_reply' action
    684         $reply_id = bbp_get_reply_id( $reply_id );
    685         $topic_id = bbp_get_topic_id( $topic_id );
    686         $forum_id = bbp_get_forum_id( $forum_id );
     702        $reply_id    = bbp_get_reply_id( $reply_id );
     703        $topic_id    = bbp_get_topic_id( $topic_id );
     704        $forum_id    = bbp_get_forum_id( $forum_id );
     705        $reply_to    = bbp_get_reply_id( $reply_to );
    687706
    688707        // Bail if there is no reply
    689708        if ( empty( $reply_id ) )
     
    747766        // Reply meta relating to reply position in tree
    748767        bbp_update_reply_forum_id( $reply_id, $forum_id );
    749768        bbp_update_reply_topic_id( $reply_id, $topic_id );
     769        bbp_update_reply_to(       $reply_id, $reply_to );
    750770
    751771        // Update associated topic values if this is a new reply
    752772        if ( empty( $is_edit ) ) {
     
    9841004        return apply_filters( 'bbp_update_reply_topic_id', (int) $topic_id, $reply_id );
    9851005}
    9861006
     1007/*
     1008 * Update the reply's meta data with its reply to id
     1009 *
     1010 * @since bbPress (r####)
     1011 *
     1012 * @param int $reply_id Reply id to update
     1013 * @param int $reply_to Optional. Reply to id
     1014 * @uses bbp_get_reply_id() To get the reply id
     1015 * @uses update_post_meta() To update the reply to meta
     1016 * @uses apply_filters() Calls 'bbp_update_reply_to' with the reply id and
     1017 *                        and reply to id
     1018 * @return bool Reply's parent reply id
     1019 */
     1020function bbp_update_reply_to( $reply_id = 0, $reply_to = 0 ) {
     1021
     1022        // Validation
     1023        $reply_id = bbp_get_reply_id( $reply_id );
     1024        $reply_to = bbp_get_reply_id( $reply_to );
     1025
     1026        // Return if no reply
     1027        if ( empty( $reply_id ) )
     1028                return;
     1029
     1030        // Return if no reply to
     1031        if ( empty( $reply_to ) )
     1032                return;
     1033
     1034        // Set the reply to
     1035        update_post_meta( $reply_id, '_bbp_reply_to', $reply_to );
     1036
     1037        return (int) apply_filters( 'bbp_update_reply_to', (int) $reply_to, $reply_id );
     1038}
     1039
    9871040/**
    9881041 * Update the revision log of the reply
    9891042 *
     
    12441297        $last_reply_id = $move_reply->ID;
    12451298        $freshness     = $move_reply->post_date;
    12461299
     1300        // Get the reply to
     1301        $parent = bbp_get_reply_to( $move_reply->ID );
     1302
     1303        // Fix orphaned children
     1304        $children = get_posts( array(
     1305                'post_type'  => bbp_get_reply_post_type(),
     1306                'meta_key'   => '_bbp_reply_to',
     1307                'meta_value' => $move_reply->ID,
     1308        ) );
     1309        foreach ( $children as $child )
     1310                bbp_update_reply_to( $child->ID, $parent );
     1311
     1312        // Remove reply_to from moved reply
     1313        delete_post_meta( $move_reply->ID, '_bbp_reply_to' );
     1314
    12471315        // It is a new topic and we need to set some default metas to make
    12481316        // the topic display in bbp_has_topics() list
    12491317        if ( 'topic' == $move_option ) {
     
    20302098
    20312099        return (int) $reply_position;
    20322100}
     2101
     2102/** Hierarchical Replies ******************************************************/
     2103
     2104/**
     2105 * List replies
     2106 *
     2107 * @since bbPress (r####)
     2108 */
     2109function bbp_list_replies( $args = array(), $replies = null ) {
     2110        global $reply_alt, $reply_depth, $reply_thread_alt;
     2111
     2112        // In reply loop
     2113        bbpress()->reply_query->in_the_loop = true;
     2114
     2115        // Initialize variables
     2116        $reply_alt = $reply_thread_alt = 0;
     2117        $reply_depth = 1;
     2118
     2119        $defaults = array(
     2120                'walker'       => null,
     2121                'max_depth'    => bbp_thread_replies_depth(),
     2122                'style'        => 'ul',
     2123                'callback'     => null,
     2124                'end_callback' => null,
     2125                'page'         => 1,
     2126                'per_page'     => -1
     2127        );
     2128
     2129        $r = wp_parse_args( $args, $defaults );
     2130
     2131        // Get replies to loop through in $_replies
     2132        if ( null !== $replies ) {
     2133                $replies = (array) $replies;
     2134                if ( empty( $replies ) )
     2135                        return;
     2136                $_replies = $replies;
     2137        } else {
     2138                if ( empty( bbpress()->reply_query->posts ) )
     2139                        return;
     2140                $_replies = bbpress()->reply_query->posts;
     2141        }
     2142
     2143        if ( empty( $walker ) )
     2144                $walker = new Walker_Reply;
     2145
     2146        $walker->paged_walk( $_replies, $r['max_depth'], $r['page'], $r['per_page'], $r );
     2147        bbpress()->max_num_pages = $walker->max_pages;
     2148
     2149        bbpress()->reply_query->in_the_loop = false;
     2150}
  • includes/replies/template-tags.php

     
    8080                'paged'          => bbp_get_paged(),            // On this page
    8181                'orderby'        => 'date',                     // Sorted by date
    8282                'order'          => 'ASC',                      // Oldest to newest
     83                'hierarchical'   => false,                      // Hierarchical replies
    8384                's'              => $default_reply_search,      // Maybe search
    8485        );
    8586
     
    112113        // Parse arguments against default values
    113114        $r = bbp_parse_args( $args, $default, 'has_replies' );
    114115
     116        // Set posts_per_page value if replies are threaded
     117        $replies_per_page = $r['posts_per_page'];
     118        if ( $r['hierarchical'] ) {
     119                $r['posts_per_page'] = -1;
     120        }
     121
    115122        // Get bbPress
    116123        $bbp = bbpress();
    117124
     
    119126        $bbp->reply_query = new WP_Query( $r );
    120127
    121128        // Add pagination values to query object
    122         $bbp->reply_query->posts_per_page = $r['posts_per_page'];
     129        $bbp->reply_query->posts_per_page = $replies_per_page;
    123130        $bbp->reply_query->paged          = $r['paged'];
    124131
    125132        // Never home, regardless of what parse_query says
     
    130137                $bbp->reply_query->is_single = true;
    131138        }
    132139
     140        // Only add reply to if query returned results
     141        if ( (int) $bbp->reply_query->found_posts ) {
     142
     143                // Get reply to for each reply
     144                foreach ( $bbp->reply_query->posts as &$post ) {
     145
     146                        // Check for reply post type
     147                        if ( $post->post_type == bbp_get_reply_post_type() ) {
     148                                $reply_to = bbp_get_reply_to( $post->ID );
     149
     150                                // Make sure it's a reply to a reply
     151                                if ( empty( $reply_to ) || ( bbp_get_reply_topic_id( $post->ID ) == $reply_to ) )
     152                                        $reply_to = 0;
     153                                $post->reply_to = $reply_to;
     154                        }
     155                }
     156        }
     157
    133158        // Only add pagination if query returned results
    134159        if ( (int) $bbp->reply_query->found_posts && (int) $bbp->reply_query->posts_per_page ) {
    135160
     
    160185                        $base = add_query_arg( 'paged', '%#%' );
    161186                }
    162187
    163                 // Add pagination to query object
    164                 $bbp->reply_query->pagination_links = paginate_links(
    165                         apply_filters( 'bbp_replies_pagination', array(
    166                                 'base'      => $base,
    167                                 'format'    => '',
    168                                 'total'     => ceil( (int) $bbp->reply_query->found_posts / (int) $r['posts_per_page'] ),
    169                                 'current'   => (int) $bbp->reply_query->paged,
    170                                 'prev_text' => is_rtl() ? '&rarr;' : '&larr;',
    171                                 'next_text' => is_rtl() ? '&larr;' : '&rarr;',
    172                                 'mid_size'  => 1,
    173                                 'add_args'  => ( bbp_get_view_all() ) ? array( 'view' => 'all' ) : false
    174                         ) )
    175                 );
     188                // Figure out total pages
     189                if ( $r['hierarchical'] ) {
     190                        $walker      = new Walker_Reply;
     191                        $total_pages = ceil( (int) $walker->get_number_of_root_elements( $bbp->reply_query->posts ) / (int) $replies_per_page );
     192                } else {
     193                        $total_pages = ceil( (int) $bbp->reply_query->found_posts / (int) $replies_per_page );
    176194
    177                 // Remove first page from pagination
    178                 if ( $wp_rewrite->using_permalinks() ) {
    179                         $bbp->reply_query->pagination_links = str_replace( $wp_rewrite->pagination_base . '/1/', '', $bbp->reply_query->pagination_links );
    180                 } else {
    181                         $bbp->reply_query->pagination_links = str_replace( '&#038;paged=1', '', $bbp->reply_query->pagination_links );
     195                        // Add pagination to query object
     196                        $bbp->reply_query->pagination_links = paginate_links(
     197                                apply_filters( 'bbp_replies_pagination', array(
     198                                        'base'      => $base,
     199                                        'format'    => '',
     200                                        'total'     => $total_pages,
     201                                        'current'   => (int) $bbp->reply_query->paged,
     202                                        'prev_text' => is_rtl() ? '&rarr;' : '&larr;',
     203                                        'next_text' => is_rtl() ? '&larr;' : '&rarr;',
     204                                        'mid_size'  => 1,
     205                                        'add_args'  => ( bbp_get_view_all() ) ? array( 'view' => 'all' ) : false
     206                                ) )
     207                        );
     208
     209                        // Remove first page from pagination
     210                        if ( $wp_rewrite->using_permalinks() ) {
     211                                $bbp->reply_query->pagination_links = str_replace( $wp_rewrite->pagination_base . '/1/', '', $bbp->reply_query->pagination_links );
     212                        } else {
     213                                $bbp->reply_query->pagination_links = str_replace( '&#038;paged=1', '', $bbp->reply_query->pagination_links );
     214                        }
    182215                }
    183216        }
    184217
     
    385418                // Set needed variables
    386419                $reply_id   = bbp_get_reply_id      ( $reply_id );
    387420                $topic_id   = bbp_get_reply_topic_id( $reply_id );
    388                 $reply_page = ceil( (int) bbp_get_reply_position( $reply_id, $topic_id ) / (int) bbp_get_replies_per_page() );
     421
     422                // Hierarchical reply page
     423                if ( bbp_thread_replies() ) {
     424                        $reply_page = 1;
     425
     426                // Standard reply page
     427                } else {
     428                        $reply_page = ceil( (int) bbp_get_reply_position( $reply_id, $topic_id ) / (int) bbp_get_replies_per_page() );
     429                }
     430
    389431                $reply_hash = '#post-' . $reply_id;
    390432                $topic_link = bbp_get_topic_permalink( $topic_id, $redirect_to );
    391433                $topic_url  = remove_query_arg( 'view', $topic_link );
     
    13761418        }
    13771419
    13781420/**
     1421 * Output the reply's ancestor reply id
     1422 *
     1423 * @since bbPress (r####)
     1424 *
     1425 * @param int $reply_id Optional. Reply id
     1426 * @uses bbp_get_reply_ancestor_id() To get the reply's ancestor id
     1427 */
     1428function bbp_reply_ancestor_id( $reply_id = 0 ) {
     1429        echo bbp_get_reply_ancestor_id( $reply_id );
     1430}
     1431        /**
     1432         * Return the reply's ancestor reply id
     1433         *
     1434         * @since bbPress (r####)
     1435         *
     1436         * @param in $reply_id Reply id
     1437         * @uses bbp_get_reply_id() To get the reply id
     1438         */
     1439        function bbp_get_reply_ancestor_id( $reply_id = 0 ) {
     1440
     1441                // Validation
     1442                $reply_id = bbp_get_reply_id( $reply_id );
     1443                if ( empty( $reply_id ) )
     1444                        return false;
     1445
     1446                // Find highest reply ancestor
     1447                $ancestor_id = $reply_id;
     1448                while ( $parent_id = bbp_get_reply_to( $ancestor_id ) ) {
     1449                        if ( empty( $parent_id ) || $parent_id == $ancestor_id || $parent_id == bbp_get_reply_topic_id( $reply_id ) || $parent_id == $reply_id )
     1450                                break;
     1451                        $ancestor_id = $parent_id;
     1452                }
     1453
     1454                return (int) $ancestor_id;
     1455        }
     1456
     1457/**
     1458 * Output the reply to id of a reply
     1459 *
     1460 * @since bbPress (r####)
     1461 *
     1462 * @param int $reply_id Optional. Reply id
     1463 * @uses bbp_get_reply_to() To get the reply to id
     1464 */
     1465function bbp_reply_to( $reply_id = 0 ) {
     1466        echo bbp_get_reply_to( $reply_id );
     1467}
     1468        /**
     1469         * Return the reply to id of a reply
     1470         *
     1471         * @since bbPress (r####)
     1472         *
     1473         * @param int $reply_id Optional. Reply id
     1474         * @uses bbp_get_reply_id() To get the reply id
     1475         * @uses get_post_meta() To get the reply to id
     1476         * @uses apply_filters() Calls 'bbp_get_reply_to' with the reply to id and
     1477         *                        reply id
     1478         * @return int Reply's reply to id
     1479         */
     1480        function bbp_get_reply_to( $reply_id = 0 ) {
     1481
     1482                // Assume there is no reply_to set
     1483                $reply_to = 0;
     1484
     1485                // Check that reply_id is valid
     1486                if ( $reply_id = bbp_get_reply_id( $reply_id ) )
     1487
     1488                        // Get reply_to value
     1489                        $reply_to = (int) get_post_meta( $reply_id, '_bbp_reply_to', true );
     1490
     1491                return (int) apply_filters( 'bbp_get_reply_to', $reply_to, $reply_id );
     1492        }
     1493
     1494/**
     1495 * Output the link for the reply to
     1496 *
     1497 * @since bbPress (r####)
     1498 *
     1499 * @param array $args
     1500 * @param int $reply
     1501 * @uses bbp_get_reply_to_link() To get the reply to link
     1502 */
     1503function bbp_reply_to_link( $args = array(), $reply = 0 ) {
     1504        echo bbp_get_reply_to_link( $args, $reply );
     1505}
     1506
     1507        /**
     1508         * Return the link for a reply to a reply
     1509         *
     1510         * @since bbPress (r####)
     1511         *
     1512         * @param array $args Arguments
     1513         * @param int $reply_id Reply id
     1514         * @uses bbp_current_user_can_access_create_reply_form() To check permissions
     1515         * @uses bbp_get_reply_id() To validate the reply id
     1516         * @uses bbp_get_reply() To get the reply
     1517         * @uses apply_filters() Calls 'bbp_get_reply_to_link' with the formatted link,
     1518         *                        the arguments array, and the reply
     1519         * @return string Link for a reply to a reply
     1520         */
     1521        function bbp_get_reply_to_link( $args = array(), $reply_id = 0 ) {
     1522
     1523                // Parse arguments against default values
     1524                $r = bbp_parse_args( $args, array(
     1525                        'id'           => 0,
     1526                        'link_before'  => '',
     1527                        'link_after'   => '',
     1528                        'reply_text'   => __( 'Reply', 'bbpress' )
     1529                ), 'get_reply_to_link' );
     1530
     1531                $reply = bbp_get_reply( bbp_get_reply_id( (int) $r['id'] ) );
     1532
     1533                // Bail if no reply or user cannot reply
     1534                if ( empty( $reply ) || ! bbp_current_user_can_access_create_reply_form() )
     1535                        return;
     1536
     1537                // Build the URI and return value
     1538                $uri      = remove_query_arg( array( 'bbp_reply_to' ) );
     1539                $uri      = add_query_arg( array( 'bbp_reply_to' => $reply->ID ) );
     1540                $uri      = esc_url( wp_nonce_url( $uri, 'respond_id_' . $reply->ID ) );
     1541                $uri      = $uri . '#new-post';
     1542                $r['uri'] = $uri;
     1543                $retval   = $r['link_before'] . '<a href="' . $r['uri'] . '">' . $r['reply_text'] . '</a>' . $r['link_after'];
     1544
     1545                return apply_filters( 'bbp_get_reply_spam_link', $retval, $r );
     1546        }
     1547
     1548/**
     1549 * Output the reply to a reply cancellation link
     1550 *
     1551 * @since bbPress (r####)
     1552 *
     1553 * @uses bbp_get_cancel_reply_to_link() To get the reply cancellation link
     1554 */
     1555function bbp_cancel_reply_to_link( $text = '' ) {
     1556        echo bbp_get_cancel_reply_to_link( $text );
     1557}
     1558        /**
     1559         * Return the cancellation link for a reply to a reply
     1560         *
     1561         * @since bbPress (r####)
     1562         *
     1563         * @param string $text The cancel text
     1564         * @uses apply_filters() Calls 'bbp_get_cancel_reply_to_link' with the cancellation
     1565         *                        link and the cancel text
     1566         * @return string The cancellation link
     1567         */
     1568        function bbp_get_cancel_reply_to_link( $text = '' ) {
     1569
     1570                // Bail if not hierarchical or editing a reply
     1571                if ( ! bbp_thread_replies() || bbp_is_reply_edit() )
     1572                        return;
     1573
     1574                // Set default text
     1575                if ( empty( $text ) )
     1576                        $text = __( 'Cancel', 'bbpress' );
     1577
     1578                $reply_to = isset( $_GET['bbp_reply_to'] ) ? (int) $_GET['bbp_reply_to'] : 0;
     1579
     1580                // Set visibility
     1581                $style = !empty( $reply_to ) ? '' : ' style="display:none;"';
     1582                $link  = esc_url( remove_query_arg( array( 'bbp_reply_to', '_wpnonce' ) ) ) . '#post-' . $reply_to;
     1583
     1584                return apply_filters( 'bbp_get_cancel_reply_to_link', '<a rel="nofollow" id="bbp-cancel-reply-to-link" href="' . $link . '"' . $style . '>' . $text . '</a>', $link, $text );
     1585        }
     1586
     1587/**
    13791588 * Output the numeric position of a reply within a topic
    13801589 *
    13811590 * @since bbPress (r2984)
     
    15151724                                'split' => bbp_get_topic_split_link( $r ),
    15161725                                'trash' => bbp_get_reply_trash_link( $r ),
    15171726                                'spam'  => bbp_get_reply_spam_link ( $r ),
     1727                                'reply' => bbp_get_reply_to_link   ( $r )
    15181728                        ), $r['id'] );
    15191729                }
    15201730
     
    20102220                $total_int = (int) $bbp->reply_query->found_posts;
    20112221                $total     = bbp_number_format( $total_int );
    20122222
     2223                // We are threading replies
     2224                if ( bbp_thread_replies() ) {
     2225                        $walker  = new Walker_Reply;
     2226                        $threads = (int) $walker->get_number_of_root_elements( $bbp->reply_query->posts );
     2227
     2228                        // Adjust for topic
     2229                        $threads--;
     2230                        $retstr  = sprintf( _n( 'Viewing %1$d reply thread', 'Viewing %1$d reply threads', $threads, 'bbbpress' ), $threads );
     2231
    20132232                // We are not including the lead topic
    2014                 if ( bbp_show_lead_topic() ) {
     2233                } elseif ( bbp_show_lead_topic() ) {
    20152234
    20162235                        // Several replies in a topic with a single page
    20172236                        if ( empty( $to_num ) ) {
     
    21072326        }
    21082327
    21092328/**
     2329 * Output the value of the reply to field
     2330 *
     2331 * @since bbPress (r####)
     2332 *
     2333 * @uses bbp_get_form_reply_to() To get value of the reply to field
     2334 */
     2335function bbp_form_reply_to() {
     2336        echo bbp_get_form_reply_to();
     2337}
     2338
     2339        /**
     2340         * Return the value of reply to field
     2341         *
     2342         * @since bbPress (r####)
     2343         *
     2344         * @uses bbp_get_reply_id() To validate the reply to
     2345         * @uses apply_filters() Calls 'bbp_get_form_reply_to' with the reply to
     2346         * @return string Value of reply to field
     2347         */
     2348        function bbp_get_form_reply_to() {
     2349
     2350                // Set initial value
     2351                $reply_to = 0;
     2352
     2353                // Get $_REQUEST data
     2354                if ( isset( $_REQUEST['bbp_reply_to'] ) )
     2355                        $reply_to = (int) $_REQUEST['bbp_reply_to'];
     2356
     2357                // If empty, get from meta
     2358                if ( empty( $reply_to ) )
     2359                        $reply_to = bbp_get_reply_to();
     2360
     2361                // Validate
     2362                $reply_to = bbp_get_reply_id( $reply_to );
     2363
     2364                return (int) apply_filters( 'bbp_get_form_reply_to', $reply_to );
     2365        }
     2366
     2367/**
    21102368 * Output checked value of reply log edit field
    21112369 *
    21122370 * @since bbPress (r31301)
  • includes/topics/functions.php

     
    12571257                        bbp_update_reply_topic_id( $reply->ID, $destination_topic->ID                           );
    12581258                        bbp_update_reply_forum_id( $reply->ID, bbp_get_topic_forum_id( $destination_topic->ID ) );
    12591259
     1260                        // Adjust reply to values
     1261                        $reply_to = bbp_get_reply_to( $reply->ID );
     1262                        if ( empty( $reply_to ) )
     1263                                bbp_update_reply_to( $reply->ID, $source_topic->ID );
     1264
    12601265                        // Do additional actions per merged reply
    12611266                        do_action( 'bbp_merged_topic_reply', $reply->ID, $destination_topic->ID );
    12621267                }
     
    15901595                                break;
    15911596                }
    15921597
     1598                // Save reply ids
     1599                $reply_ids = array();
     1600
    15931601                // Change the post_parent of each reply to the destination topic id
    15941602                foreach ( $replies as $reply ) {
    15951603
     
    16091617                        // Update the reply
    16101618                        wp_update_post( $postarr );
    16111619
     1620                        // Gather reply ids
     1621                        $reply_ids[] = $reply->ID;
     1622
    16121623                        // Adjust reply meta values
    16131624                        bbp_update_reply_topic_id( $reply->ID, $destination_topic->ID                           );
    16141625                        bbp_update_reply_forum_id( $reply->ID, bbp_get_topic_forum_id( $destination_topic->ID ) );
    16151626
     1627                        // Adjust reply to values
     1628                        $reply_to = bbp_get_reply_to( $reply->ID );
     1629
     1630                        // Not a reply to a reply that moved over
     1631                        if ( !in_array( $reply_to, $reply_ids ) )
     1632                                bbp_update_reply_to( $reply->ID, 0 );
     1633
     1634                        // New topic from reply can't be a reply to
     1635                        if ( ( $from_reply->ID == $destination_topic->ID && $from_reply->ID == $reply_to ) )
     1636                                bbp_update_reply_to( $reply->ID, 0 );
     1637
    16161638                        // Do additional actions per split reply
    16171639                        do_action( 'bbp_split_topic_reply', $reply->ID, $destination_topic->ID );
    16181640                }
    16191641
     1642                // Remove reply to from new topic
     1643                if ( $from_reply->ID == $destination_topic->ID )
     1644                        delete_post_meta( $from_reply->ID, '_bbp_reply_to' );
     1645
    16201646                // Set the last reply ID and freshness
    16211647                $last_reply_id = $reply->ID;
    16221648                $freshness     = $reply->post_date;
  • includes/topics/template-tags.php

     
    784784        function bbp_get_topic_pagination( $args = '' ) {
    785785                global $wp_rewrite;
    786786
     787                if ( bbp_thread_replies() )
     788                        return;
     789
    787790                // Parse arguments against default values
    788791                $r = bbp_parse_args( $args, array(
    789792                        'topic_id' => bbp_get_topic_id(),
  • templates/default/bbpress/content-single-topic.php

     
    3131
    3232                <?php endif; ?>
    3333
    34                 <?php if ( bbp_has_replies() ) : ?>
     34                <?php if ( bbp_has_replies( array( 'hierarchical' => bbp_thread_replies() ) ) ) : ?>
    3535
    3636                        <?php bbp_get_template_part( 'pagination', 'replies' ); ?>
    3737
  • templates/default/bbpress/form-reply.php

     
    142142
    143143                                                <?php do_action( 'bbp_theme_before_reply_form_submit_button' ); ?>
    144144
     145                                                <?php bbp_cancel_reply_to_link(); ?>
     146
    145147                                                <button type="submit" tabindex="<?php bbp_tab_index(); ?>" id="bbp_reply_submit" name="bbp_reply_submit" class="button submit"><?php _e( 'Submit', 'bbpress' ); ?></button>
    146148
    147149                                                <?php do_action( 'bbp_theme_after_reply_form_submit_button' ); ?>
  • templates/default/bbpress/loop-replies.php

     
    3939
    4040        <li class="bbp-body">
    4141
    42                 <?php while ( bbp_replies() ) : bbp_the_reply(); ?>
     42                <?php if ( bbp_thread_replies() ) : ?>
    4343
    44                         <?php bbp_get_template_part( 'loop', 'single-reply' ); ?>
     44                        <?php bbp_list_replies(); ?>
    4545
    46                 <?php endwhile; ?>
     46                <?php else : ?>
    4747
     48                        <?php while ( bbp_replies() ) : bbp_the_reply(); ?>
     49
     50                                <?php bbp_get_template_part( 'loop', 'single-reply' ); ?>
     51
     52                        <?php endwhile; ?>
     53
     54                <?php endif; ?>
     55
    4856        </li><!-- .bbp-body -->
    4957
    5058        <li class="bbp-footer">
  • templates/default/bbpress/pagination-replies.php

     
    1212<?php do_action( 'bbp_template_before_pagination_loop' ); ?>
    1313
    1414<div class="bbp-pagination">
     15
    1516        <div class="bbp-pagination-count">
    1617
    1718                <?php bbp_topic_pagination_count(); ?>
  • templates/default/bbpress-functions.php

     
    179179                        wp_enqueue_script( 'jquery' );
    180180                }
    181181
    182                 // Topic favorite/subscribe
     182                // Topic-specific scripts
    183183                if ( bbp_is_single_topic() ) {
     184
     185                        // Topic favorite/unsubscribe
    184186                        wp_enqueue_script( 'bbpress-topic', $this->url . 'js/topic.js', array( 'jquery' ), $this->version );
     187
     188                        // Hierarchical replies
     189                        if ( bbp_thread_replies() ) {
     190                                wp_enqueue_script( 'bbpress-reply', $this->url . 'js/reply.js', array(), $this->version );
     191                        }
    185192                }
    186193
    187194                // User Profile edit
  • templates/default/css/bbpress-rtl.css

     
    6060        padding: 0;
    6161}
    6262
     63#bbpress-forums ul.children {
     64        margin-right: 2em;
     65}
     66
    6367#bbpress-forums li {
    6468        margin: 0;
    6569        list-style: none;
     
    345349        overflow-wrap: normal;
    346350}
    347351
     352/* =Reply to
     353-------------------------------------------------------------- */
     354
     355#bbpress-forums div.bbp-reply-to {
     356        margin-right: 130px;
     357        padding: 12px 0px 12px 12px;
     358        text-align: left;
     359}
     360
     361#bbpress-forums div#bbp-cancel-reply-to {
     362        text-align: left;
     363}
     364
    348365/* =Breadcrumb and Tags
    349366-------------------------------------------------------------- */
    350367
  • templates/default/css/bbpress.css

     
    6060        padding: 0;
    6161}
    6262
     63#bbpress-forums ul.children {
     64        margin-left: 2em;
     65}
     66
    6367#bbpress-forums li {
    6468        margin: 0;
    6569        list-style: none;
     
    345349        overflow-wrap: normal;
    346350}
    347351
     352/* =Reply to
     353-------------------------------------------------------------- */
     354
     355#bbpress-forums div.bbp-reply-to {
     356        margin-left: 130px;
     357        padding: 12px 12px 12px 0;
     358        text-align: right;
     359}
     360
     361#bbpress-forums div#bbp-cancel-reply-to {
     362        text-align: right;
     363}
     364
    348365/* =Breadcrumb and Tags
    349366-------------------------------------------------------------- */
    350367