QueryPosts.php
4.74 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
147
148
149
150
151
152
153
154
155
156
157
<?php
/**
* Frontend query post restrictions.
*
* @copyright (c) 2023, Code Atlantic LLC.
* @package ContentControl
*/
namespace ContentControl\Controllers\Frontend\Restrictions;
use ContentControl\Base\Controller;
use function ContentControl\query_can_be_ignored;
use function ContentControl\protection_is_disabled;
use function ContentControl\get_restriction_matches_for_queried_posts;
defined( 'ABSPATH' ) || exit;
/**
* Class for handling global restrictions of the query posts.
*
* @package ContentControl
*/
class QueryPosts extends Controller {
/**
* Initiate functionality.
*
* @return void
*/
public function init() {
// We delay this until functions.php is loaded, so that users can use the content_control/query_filter_init_hook filter.
// The assumption is that most code should be registered by init 999999, so we'll use that as the default.
add_action( 'init', [ $this, 'register_hooks' ], 999999 );
}
/**
* Register hooks.
*
* @return void
*/
public function register_hooks() {
/**
* Use this filter to change the hook used to add query post filtering.
*
* This only applies to alternate queries, not the main query, and is used for removing
* posts from the query that are restricted.
*
* - Register earlier for more restriction coverage.
* - Register later for more compatibility with other plugins that late register post types.
*
* @param null|string $init_hook The hook to use to add the query post filtering.
* @return null|string The hook to use, should be: wp_loaded, or maybe even parse_query or wp (if you know what you're doing).
*/
$init_hook = apply_filters( 'content_control/query_filter_init_hook', null );
/**
* Use this filter to change the priority used to add query post filtering.
*
* @param int $init_priority The priority to use to add the query post filtering.
* @return int The priority to use. Default: 999.
*/
$init_priority = apply_filters( 'content_control/query_filter_init_priority', 999 );
if ( is_null( $init_hook ) || ! did_action( $init_hook ) ) {
// If the user has not specified a hook, we'll use the default (now).
$this->enable_query_filtering();
return;
}
add_action( (string) $init_hook, [ $this, 'enable_query_filtering' ], (int) $init_priority );
}
/**
* Late hooks.
*
* @return void
*/
public function enable_query_filtering() {
add_filter( 'the_posts', [ $this, 'restrict_query_posts' ], 10, 2 );
}
/**
* Handle restricted content appropriately.
*
* NOTE. This is only for filtering posts, and should not
* be used to redirect or replace the entire page.
*
* @param \WP_Post[] $posts Array of post objects.
* @param \WP_Query $query The WP_Query instance (passed by reference).
*
* @return \WP_Post[]
*/
public function restrict_query_posts( $posts, $query ) {
if ( query_can_be_ignored( $query ) ) {
return $posts;
}
if ( protection_is_disabled() ) {
return $posts;
}
$post_restrictions = get_restriction_matches_for_queried_posts( $query );
if ( false === $post_restrictions ) {
return $posts;
}
// If we have restrictions on the queried posts, handle them top down.
foreach ( $post_restrictions as $match ) {
$post_id = $match['post_ids'];
$restriction = $match['restriction'];
/**
* Use this filter to prevent a post from being restricted, or to handle it yourself.
*
* @param null|mixed $pre Whether to prevent the post from being restricted.
* @param null|\ContentControl\Models\Restriction $restriction Restriction object.
* @param int[] $post_id Post ID.
* @return null|mixed
*/
if ( null !== apply_filters( 'content_control/pre_restrict_archive_post', null, $restriction, $post_id ) ) {
continue;
}
/**
* Fires when a post is restricted, but before the restriction is handled.
*
* @param \ContentControl\Models\Restriction $restriction Restriction object.
* @param int[] $post_id Post ID.
*/
do_action( 'content_control/restrict_archive_post', $restriction, $post_id );
$handling = $query->is_main_query() ? $restriction->get_setting( 'archiveHandling' ) : $restriction->get_setting( 'additionalQueryHandling' );
switch ( $handling ) {
case 'filter_post_content':
// Filter the title/excerpt/contents of the restricted items.
break;
case 'hide':
foreach ( $posts as $key => $post ) {
if ( in_array( $post->ID, $post_id, true ) ) {
unset( $posts[ $key ] );
}
}
// Update the query's post count.
$query->post_count = count( $posts );
// Reset post indexes.
$posts = array_values( $posts );
break;
}
}
return $posts;
}
}