Skip to:
Content

Changeset 6402


Ignore:
Timestamp:
04/20/17 22:08:41 (6 months 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.