Skip to:
Content

bbPress.org

Changeset 6402


Ignore:
Timestamp:
04/20/2017 10:08:41 PM (8 years ago)
Author:
johnjamesjacoby
Message:

Stickies: Improved algorithm for merging stickies to queried posts

  • Separate into overloadable function
  • Tighter, less wasteful loops through existing query
  • Improved sort-ordering of topics by their most recent post activity
  • Also separate pagination base URL into new function, out of bbp_has_topics()
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/includes/topics/template.php

    r6388 r6402  
    176176
    177177        // Default view=all statuses
    178         $post_statuses = array(
    179             bbp_get_public_status_id(),
    180             bbp_get_closed_status_id(),
    181             bbp_get_spam_status_id(),
    182             bbp_get_trash_status_id(),
    183             bbp_get_pending_status_id()
    184         );
     178        $post_statuses = array_keys( bbp_get_topic_statuses() );
    185179
    186180        // Add support for private status
     
    227221
    228222    // Put sticky posts at the top of the posts array
    229     if ( ! empty( $r['show_stickies'] ) && $r['paged'] <= 1 ) {
    230 
    231         // Get super stickies and stickies in this forum
    232         $stickies = bbp_get_super_stickies();
    233 
    234         // Get stickies for current forum
    235         if ( ! empty( $r['post_parent'] ) ) {
    236             $stickies = array_merge( $stickies, bbp_get_stickies( $r['post_parent'] ) );
    237         }
    238 
    239         // Remove any duplicate stickies
    240         $stickies = array_unique( $stickies );
    241 
    242         // We have stickies
    243         if ( is_array( $stickies ) && ! empty( $stickies ) ) {
    244 
    245             // Start the offset at -1 so first sticky is at correct 0 offset
    246             $sticky_offset = -1;
    247 
    248             // Loop over topics and relocate stickies to the front.
    249             foreach ( $stickies as $sticky_index => $sticky_ID ) {
    250 
    251                 // Get the post offset from the posts array
    252                 $post_offsets = wp_filter_object_list( $bbp->topic_query->posts, array( 'ID' => $sticky_ID ), 'OR', 'ID' );
    253 
    254                 // Continue if no post offsets
    255                 if ( empty( $post_offsets ) ) {
    256                     continue;
    257                 }
    258 
    259                 // Loop over posts in current query and splice them into position
    260                 foreach ( array_keys( $post_offsets ) as $post_offset ) {
    261                     $sticky_offset++;
    262 
    263                     $sticky = $bbp->topic_query->posts[ $post_offset ];
    264 
    265                     // Remove sticky from current position
    266                     array_splice( $bbp->topic_query->posts, $post_offset, 1 );
    267 
    268                     // Move to front, after other stickies
    269                     array_splice( $bbp->topic_query->posts, $sticky_offset, 0, array( $sticky ) );
    270 
    271                     // Cleanup
    272                     unset( $stickies[ $sticky_index ] );
    273                     unset( $sticky );
    274                 }
    275 
    276                 // Cleanup
    277                 unset( $post_offsets );
    278             }
    279 
    280             // Cleanup
    281             unset( $sticky_offset );
    282 
    283             // If any posts have been excluded specifically, Ignore those that are sticky.
    284             if ( ! empty( $stickies ) && ! empty( $r['post__not_in'] ) ) {
    285                 $stickies = array_diff( $stickies, $r['post__not_in'] );
    286             }
    287 
    288             // Fetch sticky posts that weren't in the query results
    289             if ( ! empty( $stickies ) ) {
    290 
    291                 // Query to use in get_posts to get sticky posts
    292                 $sticky_query = array(
    293                     'post_type'   => bbp_get_topic_post_type(),
    294                     'post_parent' => 'any',
    295                     'meta_key'    => '_bbp_last_active_time',
    296                     'meta_type'   => 'DATETIME',
    297                     'orderby'     => 'meta_value',
    298                     'order'       => 'DESC',
    299                     'include'     => $stickies
    300                 );
    301 
    302                 // Cleanup
    303                 unset( $stickies );
    304 
    305                 // Conditionally exclude private/hidden forum ID's
    306                 $exclude_forum_ids = bbp_exclude_forum_ids( 'array' );
    307                 if ( ! empty( $exclude_forum_ids ) ) {
    308                     $sticky_query['post_parent__not_in'] = $exclude_forum_ids;
    309                 }
    310 
    311                 // What are the default allowed statuses (based on user caps)
    312                 if ( bbp_get_view_all( 'edit_others_topics' ) ) {
    313                     $sticky_query['post_status'] = $r['post_status'];
    314 
    315                 // Lean on the 'perm' query var value of 'readable' to provide statuses
    316                 } else {
    317                     $sticky_query['post_status'] = $r['perm'];
    318                 }
    319 
    320                 // Get all stickies
    321                 $sticky_posts = get_posts( $sticky_query );
    322                 if ( ! empty( $sticky_posts ) ) {
    323 
    324                     // Get a count of the visible stickies
    325                     $sticky_count = count( $sticky_posts );
    326 
    327                     // Merge the stickies topics with the query topics .
    328                     $bbp->topic_query->posts       = array_merge( $sticky_posts, $bbp->topic_query->posts );
    329 
    330                     // Adjust loop and counts for new sticky positions
    331                     $bbp->topic_query->found_posts = (int) $bbp->topic_query->found_posts + (int) $sticky_count;
    332                     $bbp->topic_query->post_count  = (int) $bbp->topic_query->post_count  + (int) $sticky_count;
    333 
    334                     // Cleanup
    335                     unset( $sticky_posts );
    336                 }
    337             }
    338         }
     223    if ( ! empty( $r['show_stickies'] ) && ( $r['paged'] <= 1 ) ) {
     224        bbp_add_sticky_topics( $bbp->topic_query, $r );
    339225    }
    340226
     
    345231
    346232    // Add pagination values to query object
    347     $bbp->topic_query->posts_per_page = $r['posts_per_page'];
    348     $bbp->topic_query->paged          = $r['paged'];
     233    $bbp->topic_query->posts_per_page = (int) $r['posts_per_page'];
     234    $bbp->topic_query->paged          = (int) $r['paged'];
    349235
    350236    // Only add pagination if query returned results
     
    352238
    353239        // Limit the number of topics shown based on maximum allowed pages
    354         if ( ( ! empty( $r['max_num_pages'] ) ) && $bbp->topic_query->found_posts > $bbp->topic_query->max_num_pages * $bbp->topic_query->post_count ) {
     240        if ( ( ! empty( $r['max_num_pages'] ) ) && ( $bbp->topic_query->found_posts > ( $bbp->topic_query->max_num_pages * $bbp->topic_query->post_count ) ) ) {
    355241            $bbp->topic_query->found_posts = $bbp->topic_query->max_num_pages * $bbp->topic_query->post_count;
    356242        }
    357243
    358         // If pretty permalinks are enabled, make our pagination pretty
    359         if ( bbp_use_pretty_urls() ) {
    360 
    361             // User's topics
    362             if ( bbp_is_single_user_topics() ) {
    363                 $base = bbp_get_user_topics_created_url( bbp_get_displayed_user_id() );
    364 
    365             // User's engagements
    366             } elseif ( bbp_is_single_user_engagements() ) {
    367                 $base = bbp_get_user_engagements_url( bbp_get_displayed_user_id() );
    368 
    369             // User's favorites
    370             } elseif ( bbp_is_favorites() ) {
    371                 $base = bbp_get_favorites_permalink( bbp_get_displayed_user_id() );
    372 
    373             // User's subscriptions
    374             } elseif ( bbp_is_subscriptions() ) {
    375                 $base = bbp_get_subscriptions_permalink( bbp_get_displayed_user_id() );
    376 
    377             // Root profile page
    378             } elseif ( bbp_is_single_user() ) {
    379                 $base = bbp_get_user_profile_url( bbp_get_displayed_user_id() );
    380 
    381             // View
    382             } elseif ( bbp_is_single_view() ) {
    383                 $base = bbp_get_view_url();
    384 
    385             // Topic tag
    386             } elseif ( bbp_is_topic_tag() ) {
    387                 $base = bbp_get_topic_tag_link();
    388 
    389             // Page or single post
    390             } elseif ( is_page() || is_single() ) {
    391                 $base = get_permalink();
    392 
    393             // Forum archive
    394             } elseif ( bbp_is_forum_archive() ) {
    395                 $base = bbp_get_forums_url();
    396 
    397             // Topic archive
    398             } elseif ( bbp_is_topic_archive() ) {
    399                 $base = bbp_get_topics_url();
    400 
    401             // Default
    402             } else {
    403                 $base = get_permalink( (int) $r['post_parent'] );
    404             }
    405 
    406             // Use pagination base
    407             $base = trailingslashit( $base ) . user_trailingslashit( bbp_get_paged_slug() . '/%#%/' );
    408 
    409         // Unpretty pagination
    410         } else {
    411             $base = add_query_arg( 'paged', '%#%' );
    412         }
     244        // Total topics for pagination boundaries
     245        $total = ( $r['posts_per_page'] === $bbp->topic_query->found_posts )
     246            ? 1
     247            : ceil( (int) $bbp->topic_query->found_posts / (int) $r['posts_per_page'] );
    413248
    414249        // Pagination settings with filter
    415250        $bbp_topic_pagination = apply_filters( 'bbp_topic_pagination', array(
    416             'base'      => $base,
     251            'base'      => bbp_get_topics_pagination_base( $r['post_parent'] ),
    417252            'format'    => '',
    418             'total'     => $r['posts_per_page'] === $bbp->topic_query->found_posts ? 1 : ceil( (int) $bbp->topic_query->found_posts / (int) $r['posts_per_page'] ),
     253            'total'     => (int) $total,
    419254            'current'   => (int) $bbp->topic_query->paged,
    420255            'prev_text' => is_rtl() ? '&rarr;' : '&larr;',
     
    465300function bbp_the_topic() {
    466301    return bbpress()->topic_query->the_post();
     302}
     303
     304/**
     305 * Add sticky topics to a topics query object
     306 *
     307 * @since 2.6.0 bbPress (r6402)
     308 *
     309 * @param WP_Query $query
     310 * @param array    $args
     311 */
     312function bbp_add_sticky_topics( &$query, $args = array() ) {
     313
     314    // Bail if overloaded
     315    if ( null !== apply_filters( 'bbp_pre_add_stick_topics', null, $query, $args ) ) {
     316        return;
     317    }
     318
     319    // Parse arguments against what gets used locally
     320    $r = bbp_parse_args( $args, array(
     321        'post_parent'         => 0,
     322        'post_parent__not_in' => array(),
     323        'post__not_in'        => array(),
     324        'post_status'         => '',
     325        'perm'                => ''
     326    ), 'add_sticky_topics' );
     327
     328    // Get super stickies and stickies in this forum
     329    $super_stickies = bbp_get_super_stickies();
     330    $forum_stickies = ! empty( $r['post_parent'] )
     331        ? bbp_get_stickies( $r['post_parent'] )
     332        : array();
     333
     334    // Merge stickies (supers first) and remove duplicates
     335    $stickies = array_filter( array_unique( array_merge( $super_stickies, $forum_stickies ) ) );
     336
     337    // Bail if no stickies
     338    if ( empty( $stickies ) ) {
     339        return;
     340    }
     341
     342    // If any posts have been excluded specifically, Ignore those that are sticky.
     343    if ( ! empty( $r['post__not_in'] ) ) {
     344        $stickies = array_diff( $stickies, $r['post__not_in'] );
     345    }
     346
     347    // Default sticky posts array
     348    $sticky_topics = array();
     349
     350    // Loop through posts
     351    foreach ( $query->posts as $key => $post ) {
     352
     353        // Looking for stickies in this query loop, and stash & unset them
     354        if ( in_array( $post->ID, $stickies, true ) ) {
     355            $sticky_topics[] = $post;
     356            unset( $query->posts[ $key ] );
     357        }
     358    }
     359
     360    // Remove queried stickies from stickies array
     361    if ( ! empty( $sticky_topics ) ) {
     362        $stickies = array_diff( $stickies, wp_list_pluck( $sticky_topics, 'ID' ) );
     363    }
     364
     365    // Fetch all stickies that were not in the query
     366    if ( ! empty( $stickies ) ) {
     367
     368        // Query to use in get_posts to get sticky posts
     369        $sticky_query = array(
     370            'post_type'   => bbp_get_topic_post_type(),
     371            'post_parent' => 'any',
     372            'meta_key'    => '_bbp_last_active_time',
     373            'meta_type'   => 'DATETIME',
     374            'orderby'     => 'meta_value',
     375            'order'       => 'DESC',
     376            'include'     => $stickies
     377        );
     378
     379        // Conditionally exclude private/hidden forum ID's
     380        $exclude_forum_ids = bbp_exclude_forum_ids( 'array' );
     381
     382        // Maybe remove the current forum from excluded forum IDs
     383        if ( ! empty( $r['post_parent' ] ) ) {
     384            unset( $exclude_forum_ids[ $r['post_parent' ] ] );
     385        }
     386
     387        // Maybe exclude specific forums
     388        if ( ! empty( $exclude_forum_ids ) ) {
     389            $sticky_query['post_parent__not_in'] = $exclude_forum_ids;
     390        }
     391
     392        // Allowed statuses, or lean on the 'perm' argument (probably 'readable')
     393        $sticky_query['post_status'] = bbp_get_view_all( 'edit_others_topics' )
     394            ? $r['post_status']
     395            : $r['perm'];
     396
     397        // Get unqueried stickies
     398        $_posts = get_posts( $sticky_query );
     399        if ( ! empty( $_posts ) ) {
     400
     401            // Merge the stickies topics with the query topics .
     402            $sticky_topics = array_merge( $sticky_topics, $_posts );
     403
     404            // Get a count of the visible stickies
     405            $sticky_count = count( $_posts );
     406
     407            // Adjust loop and counts for new sticky positions
     408            $query->found_posts = (int) $query->found_posts + (int) $sticky_count;
     409            $query->post_count  = (int) $query->post_count  + (int) $sticky_count;
     410        }
     411    }
     412
     413    // Bail if no sticky topics empty or not an array
     414    if ( empty( $sticky_topics ) || ! is_array( $sticky_topics ) ) {
     415        return;
     416    }
     417
     418    // Default ordered stickies array
     419    $ordered_stickies = array(
     420        'supers' => array(),
     421        'forums' => array()
     422    );
     423
     424    // Separate supers from forums
     425    foreach ( $sticky_topics as $post ) {
     426        if ( in_array( $post->ID, $super_stickies, true ) ) {
     427            $ordered_stickies['supers'][] = $post;
     428        } elseif ( in_array( $post->ID, $forum_stickies, true ) ) {
     429            $ordered_stickies['forums'][] = $post;
     430        }
     431    }
     432
     433    // Merge supers and forums, supers first
     434    $sticky_topics = array_merge( $ordered_stickies['supers'], $ordered_stickies['forums'] );
     435
     436    // Update queried posts
     437    $query->posts = array_merge( $sticky_topics, array_values( $query->posts ) );
    467438}
    468439
     
    31863157
    31873158/**
     3159 * Return the base URL used inside of pagination links
     3160 *
     3161 * @since 2.6.0 bbPress (r6402)
     3162 *
     3163 * @param int $forum_id
     3164 * @return string
     3165 */
     3166function bbp_get_topics_pagination_base( $forum_id = 0 ) {
     3167
     3168    // If pretty permalinks are enabled, make our pagination pretty
     3169    if ( bbp_use_pretty_urls() ) {
     3170
     3171        // User's topics
     3172        if ( bbp_is_single_user_topics() ) {
     3173            $base = bbp_get_user_topics_created_url( bbp_get_displayed_user_id() );
     3174
     3175        // User's engagements
     3176        } elseif ( bbp_is_single_user_engagements() ) {
     3177            $base = bbp_get_user_engagements_url( bbp_get_displayed_user_id() );
     3178
     3179        // User's favorites
     3180        } elseif ( bbp_is_favorites() ) {
     3181            $base = bbp_get_favorites_permalink( bbp_get_displayed_user_id() );
     3182
     3183        // User's subscriptions
     3184        } elseif ( bbp_is_subscriptions() ) {
     3185            $base = bbp_get_subscriptions_permalink( bbp_get_displayed_user_id() );
     3186
     3187        // Root profile page
     3188        } elseif ( bbp_is_single_user() ) {
     3189            $base = bbp_get_user_profile_url( bbp_get_displayed_user_id() );
     3190
     3191        // View
     3192        } elseif ( bbp_is_single_view() ) {
     3193            $base = bbp_get_view_url();
     3194
     3195        // Topic tag
     3196        } elseif ( bbp_is_topic_tag() ) {
     3197            $base = bbp_get_topic_tag_link();
     3198
     3199        // Page or single post
     3200        } elseif ( is_page() || is_single() ) {
     3201            $base = get_permalink();
     3202
     3203        // Forum archive
     3204        } elseif ( bbp_is_forum_archive() ) {
     3205            $base = bbp_get_forums_url();
     3206
     3207        // Topic archive
     3208        } elseif ( bbp_is_topic_archive() ) {
     3209            $base = bbp_get_topics_url();
     3210
     3211        // Default
     3212        } else {
     3213            $base = get_permalink( $forum_id );
     3214        }
     3215
     3216        // Use pagination base
     3217        $base = trailingslashit( $base ) . user_trailingslashit( bbp_get_paged_slug() . '/%#%/' );
     3218
     3219    // Unpretty pagination
     3220    } else {
     3221        $base = add_query_arg( 'paged', '%#%' );
     3222    }
     3223
     3224    return apply_filters( 'bbp_get_topics_pagination_base', $base );
     3225}
     3226
     3227/**
    31883228 * Output the pagination count
    31893229 *
Note: See TracChangeset for help on using the changeset viewer.