Skip to content

Commit c5a753c

Browse files
committed
WDSBT-23 - Override WP Query to respect perPage count even with sticky posts
1 parent 24c0cbe commit c5a753c

File tree

1 file changed

+87
-0
lines changed

1 file changed

+87
-0
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
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

Comments
 (0)