|
| 1 | +<?php |
| 2 | +/** |
| 3 | + * Query Block functions. |
| 4 | + * |
| 5 | + * Override WP Query to respect perPage count even with sticky posts. |
| 6 | + * |
| 7 | + * @package wdsbt |
| 8 | + */ |
| 9 | + |
| 10 | +namespace WebDevStudios\wdsbt; |
| 11 | + |
| 12 | +/** |
| 13 | + * Adds a custom query variable to indicate whether sticky posts should be ignored. |
| 14 | + * |
| 15 | + * This function adds 'ignore_sticky_posts' to the list of recognized query variables. |
| 16 | + * |
| 17 | + * @param array $query_vars An array of query variables. |
| 18 | + * @return array The modified array of query variables. |
| 19 | + */ |
| 20 | +function add_query_var( $query_vars ) { |
| 21 | + $query_vars[] = 'ignore_sticky_posts'; |
| 22 | + return $query_vars; |
| 23 | +} |
| 24 | +add_filter( 'query_vars', __NAMESPACE__ . '\add_query_var' ); |
| 25 | + |
| 26 | +/** |
| 27 | + * Sets the 'ignore_sticky_posts' query variable. |
| 28 | + * |
| 29 | + * This function forces the 'ignore_sticky_posts' query variable to true, |
| 30 | + * ensuring that sticky posts are always ignored in the main query. |
| 31 | + * |
| 32 | + * @param \WP_Query $query The WP_Query instance (passed by reference). |
| 33 | + */ |
| 34 | +function parse_query_var( $query ) { |
| 35 | + // Check if ignoring sticky posts is requested. |
| 36 | + $query->query_vars['ignore_sticky_posts'] = isset( $query->query_vars['ignore_sticky_posts'] ) && $query->query_vars['ignore_sticky_posts']; |
| 37 | + $query->query_vars['ignore_sticky_posts'] = true; |
| 38 | +} |
| 39 | +add_filter( 'parse_query', __NAMESPACE__ . '\parse_query_var' ); |
| 40 | + |
| 41 | +/** |
| 42 | + * Modifies the query clauses to handle sticky posts without including them in the main results. |
| 43 | + * |
| 44 | + * This function alters the WHERE and ORDER BY clauses of the query to ensure that |
| 45 | + * sticky posts are included in a specific order without affecting the main result set. |
| 46 | + * |
| 47 | + * @param array $clauses An associative array of the query clauses. |
| 48 | + * @param \WP_Query $query The WP_Query instance. |
| 49 | + * @return array The modified query clauses. |
| 50 | + */ |
| 51 | +function modify_posts_clauses( $clauses, $query ) { |
| 52 | + global $wpdb; |
| 53 | + |
| 54 | + if ( ! $query->query_vars['post__in'] && $query->is_home && ! $query->query_vars['ignore_sticky_posts'] ) { |
| 55 | + $sticky_posts = get_option( 'sticky_posts' ); |
| 56 | + |
| 57 | + // Retrieve published sticky posts of the desired post type(s). |
| 58 | + $stickies_query = new \WP_Query( |
| 59 | + array( |
| 60 | + 'post__in' => $sticky_posts, |
| 61 | + 'post_type' => $query->query_vars['post_type'], |
| 62 | + 'post_status' => 'publish', |
| 63 | + 'fields' => 'ids', |
| 64 | + 'posts_per_page' => count( $sticky_posts ), |
| 65 | + ) |
| 66 | + ); |
| 67 | + |
| 68 | + $queried_stickies = $stickies_query->posts; |
| 69 | + |
| 70 | + if ( ! empty( $queried_stickies ) ) { |
| 71 | + // Generate the WHERE clause to exclude sticky posts. |
| 72 | + $post__in_sticky = implode( ',', array_map( 'absint', $queried_stickies ) ); |
| 73 | + $clauses['where'] = 'AND ((1=1 ' . $clauses['where'] . ") OR {$wpdb->posts}.ID IN ($post__in_sticky))"; |
| 74 | + $sticky_orderby = "FIELD( {$wpdb->posts}.ID, $post__in_sticky ) DESC"; |
| 75 | + |
| 76 | + // Add the sticky posts handling to the ORDER BY clause. |
| 77 | + if ( $clauses['orderby'] ) { |
| 78 | + $clauses['orderby'] = $sticky_orderby . ', ' . $clauses['orderby']; |
| 79 | + } else { |
| 80 | + $clauses['orderby'] = $sticky_orderby; |
| 81 | + } |
| 82 | + } |
| 83 | + } |
| 84 | + |
| 85 | + return $clauses; |
| 86 | +} |
| 87 | +add_filter( 'posts_clauses', __NAMESPACE__ . '\modify_posts_clauses', 10, 2 ); |
0 commit comments