Skip to content

Commit 29f15a4

Browse files
authored
Merge pull request #1 from firstandthird/v1
Create index.php
2 parents 38aa4d0 + 6d015b6 commit 29f15a4

File tree

6 files changed

+265
-0
lines changed

6 files changed

+265
-0
lines changed

.editorconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# This file is for unifying the coding style for different editors and IDEs
2+
# editorconfig.org
3+
4+
root = true
5+
6+
[*]
7+
end_of_line = lf
8+
charset = utf-8
9+
trim_trailing_whitespace = true
10+
insert_final_newline = true
11+
indent_style = space
12+
indent_size = 2

docker-compose.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
services:
2+
wordpress:
3+
image: wordpress:latest
4+
depends_on:
5+
- db
6+
ports:
7+
- "8000:80"
8+
environment:
9+
VIRTUAL_HOST: 'unique_wp_query.dev'
10+
WORDPRESS_DB_PASSWORD: 'dev'
11+
WORDPRESS_DEBUG: 1
12+
WORDPRESS_DB_HOST: db:3306
13+
volumes:
14+
- .:/var/www/html/wp-content/plugins/unique_wp_query
15+
- ./test_theme:/var/www/html/wp-content/themes/testtheme
16+
db:
17+
image: mariadb
18+
environment:
19+
MYSQL_ROOT_PASSWORD: 'dev'

index.php

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

readme.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<h1 align="center">unique-wp-query</h1>
2+
3+
4+
unique-wp-query is a Wordpress plugin that can be used to ensure no post is
5+
loaded more than once per screen
6+
7+
## Features
8+
9+
* ensures only one of each post is loaded
10+
11+
## Installation
12+
13+
just put the root folder in your __wp-content/plugins__ directory and Activate
14+
from the plugins console
15+
16+
## Usage:
17+
18+
From the demo:
19+
20+
```php
21+
$latest_posts1 = new Unique_WP_Query([
22+
'post_type' => 'post',
23+
'posts_per_page' => 3,
24+
'post_status' => 'publish',
25+
'post__not_in' => array(18)
26+
]);
27+
$latest_posts2 = new Unique_WP_Query([
28+
'post_type' => 'post',
29+
'posts_per_page' => 3,
30+
'post_status' => 'publish',
31+
]);
32+
while ($latest_posts1->have_posts()) {
33+
$latest_posts1->the_post();
34+
echo get_the_title(), '<br>';
35+
}
36+
echo "<br><br>---------------------------------------------------------------------<br><br>";
37+
while ($latest_posts2->have_posts()) {
38+
$latest_posts2->the_post();
39+
echo get_the_title(), '<br>';
40+
}
41+
```
42+
43+
The second list will not include any posts that were in the first
44+
45+
46+
## Demo:
47+
48+
```
49+
This repo includes a docker-compose with a dummy theme that demonstrates the plugin, to use it:
50+
- __docker-compose up__
51+
- Open a browser and log in to the Wordpress server
52+
- Add some dummy posts and then load the main page
53+
```
54+
55+
56+
<a href="https://firstandthird.com"><img src="https://firstandthird.com/_static/ui/images/safari-pinned-tab-62813db097.svg" height="32" width="32" align="right"></a>
57+
58+
_A [First + Third](https://firstandthird.com) Project_

test_theme/index.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<div id="contentArea">
2+
<div id="mainContent">
3+
<?php
4+
$latest_posts1 = new Unique_WP_Query([
5+
'post_type' => 'post',
6+
'posts_per_page' => 3,
7+
'post_status' => 'publish',
8+
'post__not_in' => array(18)
9+
]);
10+
$latest_posts2 = new Unique_WP_Query([
11+
'post_type' => 'post',
12+
'posts_per_page' => 3,
13+
'post_status' => 'publish',
14+
]);
15+
while ($latest_posts1->have_posts()) {
16+
$latest_posts1->the_post();
17+
echo get_the_title(), '<br>';
18+
}
19+
echo "<br><br>---------------------------------------------------------------------<br><br>";
20+
while ($latest_posts2->have_posts()) {
21+
$latest_posts2->the_post();
22+
echo get_the_title(), '<br>';
23+
}
24+
25+
?>
26+
</div>
27+
</div>

test_theme/style.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/*
2+
Theme Name: Test Theme
3+
*/

0 commit comments

Comments
 (0)