-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.php
More file actions
146 lines (122 loc) · 4.46 KB
/
index.php
File metadata and controls
146 lines (122 loc) · 4.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
<?php
/*
Plugin Name: Unique WP Query
Plugin URI: https://github.com/firstandthird/unique_wp_query
Description: A plugin for doing unique WP_Query
Author: firstandthird
Version: 1.0.0
// adapted & taken from https://gist.github.com/jameswburke/d0776d742ab74c469cd8af8dacd916fc
*/
class Unique_WP_Query extends WP_Query {
function __construct($args) {
// Act as a flag for pre_get_posts
$args['unique_wp_query'] = true;
// don't get any pages specified by post__not_in:
if (key_exists( 'post__not_in', $args)) {
foreach ($args['post__not_in'] as $key => $id) {
Unique_WP_Query_Manager::add_post_id($id);
}
unset($args['post__not_in']);
}
// don't get the current post or page:
if (is_single()) {
$id = get_the_ID();
Unique_WP_Query_Manager::add_post_id($id);
}
// Initialize the WP_Query object like normal
parent::__construct($args);
// Track used posts, and remove duplicates
Unique_WP_Query_Manager::process_posts($this->posts, $this->post_count, $this->get('original_posts_per_page'));
}
}
/**
* Keeps track of which posts have already appeared and
* removes them from future Unique_WP_Query objects.
*/
class Unique_WP_Query_Manager {
/**
* Keep track of which post_ids have already been used
* @var array
*/
public static $used_post_ids = [];
/**
* Keeps track of how many used_posts_ids exist
* @var integer
*/
public static $used_post_count = 0;
/**
* Helper to make sure no duplicate ids are added
* useful for content outside of the normal query
*/
public static function add_post_id($id) {
if (!in_array($id, Unique_WP_Query_Manager::$used_post_ids, true)) {
Unique_WP_Query_Manager::$used_post_ids[] = $id;
Unique_WP_Query_Manager::$used_post_count = count(Unique_WP_Query_Manager::$used_post_ids);
}
}
/**
* Takes the posts and post count of a WP_Query object and
* ensures that it removes posts that have already been used,
* and then trims it to the necessary size.
*
* @param array &$posts
* @param integer &$post_count
*/
public static function process_posts(&$posts, &$post_count, $original_posts_per_page) {
// Keep track of how many posts are acceptable to return
$current_accepted_post_count = 0;
// Make sure we have posts
if (empty((array) $posts)) {
return;
}
// Loop through all the found posts
foreach ((array) $posts as $key => $post) {
// If we have enough acceptable posts, break the loop
// Otherwise, determine if we've already used this post
if ($original_posts_per_page > $current_accepted_post_count) {
// Has this post already been used?
if (in_array($post->ID, Unique_WP_Query_Manager::$used_post_ids, true)) {
// Remove from $posts
unset($posts[$key]);
// And update count
$post_count--;
} else {
// If not, add it to the list of used ids
Unique_WP_Query_Manager::$used_post_ids[] = $post->ID;
// Update how many accepted posts we have
$current_accepted_post_count++;
}
} else {
// If we have enough acceptable posts, break the foreach
// This prevents extra results from accidently being added to $used_post_ids
break;
}
}
// Reindex the array correctly
$posts = array_values($posts);
// Update the $used_post_count
Unique_WP_Query_Manager::$used_post_count = count(Unique_WP_Query_Manager::$used_post_ids);
// Trim any excess posts and update $post_count
if (count($posts) > $original_posts_per_page) {
// Remove extra posts
$posts = array_slice($posts, 0, $original_posts_per_page);
// Update post count to our new value
$post_count = $original_posts_per_page;
}
}
}
if (!function_exists('unique_wp_query_pre_get_posts')) {
/**
* Increase the posts_per_page value by the number of posts that have
* already been used. Executes as the last pre_get_posts action.
*/
function unique_wp_query_pre_get_posts(&$query) {
if (true === $query->get('unique_wp_query')) {
$posts_per_page = $query->get('posts_per_page');
// Increase posts_per_page by the amount of used post_ids
$query->set('original_posts_per_page', min($posts_per_page, 200));
$query->set('posts_per_page', min($posts_per_page + Unique_WP_Query_Manager::$used_post_count, 200));
}
}
add_action('pre_get_posts', 'unique_wp_query_pre_get_posts', PHP_INT_MAX);
}