PluginProbe
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More / 2.6.1
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More v2.6.1
trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.10 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 All 47 releases
content-control / inc / functions / developers.php

developers.php in Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More 2.6.1, at inc/functions/developers.php

463 lines 10.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Restriction utility & helper functions.
4 *
5 * @package ContentControl
6 * @subpackage Functions
7 * @copyright (c) 2023 Code Atlantic LLC
8 */
9
10 namespace ContentControl;
11
12 use ContentControl\Models\Restriction;
13
14 use function ContentControl\plugin;
15 use function ContentControl\set_rules_query;
16 use function ContentControl\is_rest;
17
18 defined( 'ABSPATH' ) || exit;
19
20 /**
21 * Check if content has restrictions.
22 *
23 * @param int|null $content_id Content ID.
24 *
25 * @return bool
26 *
27 * @since 2.0.0
28 */
29 function content_has_restrictions( $content_id = null ) {
30 $overload_content = setup_content_globals( $content_id );
31
32 $has_restrictions = plugin( 'restrictions' )->has_applicable_restrictions( $content_id );
33
34 // Clear content if we overloaded it.
35 if ( $overload_content ) {
36 reset_content_globals();
37 }
38
39 /**
40 * Filter whether content has restrictions.
41 *
42 * @param bool $has_restrictions Whether content has restrictions.
43 * @param int|null $content_id Content ID.
44 *
45 * @return bool
46 *
47 * @since 2.0.0
48 */
49 return (bool) apply_filters( 'content_control/content_has_restrictions', $has_restrictions, $content_id );
50 }
51
52 /**
53 * Check if user can access content.
54 *
55 * @param int|null $content_id Content ID.
56 *
57 * @return bool True if user meets requirements, false if not.
58 *
59 * @since 2.0.0
60 */
61 function user_can_view_content( $content_id = null ) {
62 if ( ! content_has_restrictions( $content_id ) ) {
63 return true;
64 }
65
66 $can_view = true;
67
68 $restrictions = [];
69
70 if ( false === (bool) apply_filters( 'content_control/check_all_restrictions', false, $content_id ) ) {
71 /**
72 * Fetch first applicable restriction.
73 *
74 * @var Restriction|false $restriction
75 */
76 $restriction = get_applicable_restrictions( $content_id, true );
77
78 if ( $restriction ) {
79 $can_view = $restriction->user_meets_requirements();
80 $restrictions[] = $restriction;
81 }
82 } else {
83 /**
84 * Fetch all applicable restrictions.
85 *
86 * @var Restriction[]|false $restrictions
87 */
88 $restrictions = get_applicable_restrictions( $content_id, false );
89
90 if ( count( $restrictions ) ) {
91 $checks = [];
92
93 foreach ( $restrictions as $restriction ) {
94 $checks[] = $restriction->user_meets_requirements();
95 }
96
97 // When checking all, we are looking for any true value.
98 $can_view = in_array( true, $checks, true );
99 }
100 }
101
102 /**
103 * Filter whether user can view content.
104 *
105 * @param bool $can_view Whether user can view content.
106 * @param int|null $content_id Content ID.
107 * @param Restriction[] $restrictions Restrictions.
108 *
109 * @return bool
110 *
111 * @since 2.0.0
112 */
113 return (bool) apply_filters( 'content_control/user_can_view_content', $can_view, $content_id, $restrictions );
114 }
115
116 /**
117 * Helper that checks if given or current content is restricted or not.
118 *
119 * @see \ContentControl\user_can_view_content() to check if user can view content.
120 *
121 * @param int|null $content_id Content ID.
122 *
123 * @return bool
124 *
125 * @since 2.0.0
126 */
127 function content_is_restricted( $content_id = null ) {
128 $is_restricted = ! user_can_view_content( $content_id );
129
130 /**
131 * Filter whether content is restricted.
132 *
133 * @param bool $is_restricted Whether content is restricted.
134 * @param int|null $content_id Content ID.
135 *
136 * @return bool
137 *
138 * @since 2.0.0
139 */
140 return (bool) apply_filters( 'content_control/content_is_restricted', $is_restricted, $content_id );
141 }
142
143 /**
144 * Get applicable restrictions for the given content.
145 *
146 * If $single is true, return the first applicable restriction. If false, return all applicable restrictions.
147 * Sorted by priority and cached internally.
148 *
149 * @param int|null $content_id Content ID.
150 * @param bool $single Whether to return a single match or an array of matches.
151 *
152 * @return Restriction|Restriction[]|false
153 *
154 * @since 2.4.0
155 */
156 function get_applicable_restrictions( $content_id = null, $single = true ) {
157 $overload_content = setup_content_globals( $content_id );
158
159 $restriction = plugin( 'restrictions' )->get_applicable_restrictions( $content_id, $single );
160
161 // Clear content if we overloaded it.
162 if ( $overload_content ) {
163 reset_content_globals();
164 }
165
166 return $restriction;
167 }
168
169 /**
170 * Get applicable restriction.
171 *
172 * @param int|null $content_id Content ID.
173 *
174 * @return Restriction|false
175 *
176 * @since 2.0.0
177 */
178 function get_applicable_restriction( $content_id = null ) {
179 return get_applicable_restrictions( $content_id, true );
180 }
181
182 /**
183 * Get all applicable restrictions.
184 *
185 * @param int|null $content_id Content ID.
186 *
187 * @return Restriction[]
188 *
189 * @since 2.0.11
190 */
191 function get_all_applicable_restrictions( $content_id = null ) {
192 return get_applicable_restrictions( $content_id, false );
193 }
194
195 /**
196 * Check if query has restrictions.
197 *
198 * @param \WP_Query $query Query object.
199 *
200 * @return array<array{restriction:Restriction,post_ids:int[]}>|false
201 *
202 * @since 2.0.0
203 */
204 function get_restriction_matches_for_queried_posts( $query ) {
205 // If its the main query, and not an archive-like page, bail.
206 if ( $query->is_main_query() && ( ! $query->is_home() && ! $query->is_archive() && ! $query->is_search() ) ) {
207 return false;
208 }
209
210 if ( empty( $query->posts ) ) {
211 return false;
212 }
213
214 static $restrictions;
215
216 // Generate cache key from hasing $wp_query.
217 $cache_key = md5( (string) wp_json_encode( $query ) );
218
219 if ( isset( $restrictions[ $cache_key ] ) ) {
220 return $restrictions[ $cache_key ];
221 }
222
223 set_rules_query( $query );
224
225 foreach ( $query->posts as $post ) {
226 /**
227 * Post ID.
228 *
229 * @var \WP_Post $post
230 */
231 if ( content_is_restricted( $post->ID ) ) {
232 // TODO This needs to likely respect the filter for checking all applicable restrictions.
233 $restriction = get_applicable_restriction( $post->ID );
234
235 if ( ! $restriction ) {
236 continue;
237 }
238
239 if ( ! isset( $restrictions[ $cache_key ][ $restriction->priority ] ) ) {
240 // Handles deduplication & sorting.
241 $restrictions[ $cache_key ][ $restriction->priority ] = [
242 'restriction' => $restriction,
243 'post_ids' => [],
244 ];
245 }
246
247 // Add post to restriction.
248 $restrictions[ $cache_key ][ $restriction->priority ]['post_ids'][] = $post->ID;
249 }
250 }
251
252 set_rules_query( null );
253
254 if ( empty( $restrictions[ $cache_key ] ) ) {
255 $restrictions[ $cache_key ] = false;
256 } else {
257 // Sort by priority.
258 ksort( $restrictions[ $cache_key ] );
259 // Remove priority keys.
260 $restrictions[ $cache_key ] = array_values( $restrictions[ $cache_key ] );
261 }
262
263 return $restrictions[ $cache_key ];
264 }
265
266 /**
267 * Check if query has restrictions.
268 *
269 * @param \WP_Term_Query $query Query object.
270 *
271 * @return array<array{restriction:Restriction,term_ids:int[]}>|false
272 *
273 * @since 2.2.0
274 */
275 function get_restriction_matches_for_queried_terms( $query ) {
276 if ( empty( $query->terms ) ) {
277 return false;
278 }
279
280 static $restrictions;
281
282 // Generate cache key from hasing $wp_query.
283 $cache_key = md5( (string) wp_json_encode( $query ) );
284
285 if ( isset( $restrictions[ $cache_key ] ) ) {
286 return $restrictions[ $cache_key ];
287 }
288
289 set_rules_query( $query );
290
291 foreach ( $query->terms as $term ) {
292 $term_id = false;
293
294 if ( is_object( $term ) && isset( $term->term_id ) ) {
295 $term_id = (int) $term->term_id;
296 } elseif ( is_numeric( $term ) ) {
297 $term_id = absint( $term );
298 }
299
300 if ( $term_id > 0 && content_is_restricted( $term_id ) ) {
301 // TODO This needs to likely respect the filter for checking all applicable restrictions.
302 $restriction = get_applicable_restrictions( $term_id, true );
303
304 if ( ! $restriction ) {
305 continue;
306 }
307
308 if ( ! isset( $restrictions[ $cache_key ][ $restriction->priority ] ) ) {
309 // Handles deduplication & sorting.
310 $restrictions[ $cache_key ][ $restriction->priority ] = [
311 'restriction' => $restriction,
312 'term_ids' => [],
313 ];
314 }
315
316 // Add term to restriction.
317 $restrictions[ $cache_key ][ $restriction->priority ]['term_ids'][] = $term_id;
318 }
319 }
320
321 set_rules_query( null );
322
323 if ( empty( $restrictions[ $cache_key ] ) ) {
324 $restrictions[ $cache_key ] = false;
325 } else {
326 // Sort by priority.
327 ksort( $restrictions[ $cache_key ] );
328 // Remove priority keys.
329 $restrictions[ $cache_key ] = array_values( $restrictions[ $cache_key ] );
330 }
331
332 return $restrictions[ $cache_key ];
333 }
334
335 /**
336 * Check if the referrer is the sites admin area.
337 *
338 * @return bool
339 *
340 * @since 2.2.0
341 */
342 function check_referrer_is_admin() {
343 $referrer = wp_get_raw_referer();
344 if ( empty( $referrer ) ) {
345 return false;
346 }
347
348 $admin_url = admin_url();
349 // Normalize URLs for comparison.
350 $normalized_referrer = strtolower( $referrer );
351 $normalized_admin_url = strtolower( $admin_url );
352
353 // Compare the beginning of the referrer with the admin URL.
354 return str_starts_with( $normalized_referrer, $normalized_admin_url );
355 }
356
357 /**
358 * Check if request is excluded.
359 *
360 * @return bool
361 *
362 * @since 2.3.1
363 */
364 function request_is_excluded_rest_endpoint() {
365 /**
366 * Filter whether to exclude a request from being restricted.
367 *
368 * @param bool $is_excluded Whether to exclude the request.
369 *
370 * @return bool
371 */
372 return apply_filters( 'content_control/request_is_excluded_rest_endpoint', ! is_wp_core_rest_namespace() );
373 }
374
375 /**
376 * Check if request is excluded.
377 *
378 * @return bool
379 *
380 * @since 2.3.0
381 */
382 function request_is_excluded() {
383 static $is_excluded;
384
385 if ( isset( $is_excluded ) ) {
386 return $is_excluded;
387 }
388
389 $is_excluded = false;
390
391 if (
392 // Check if doing cron.
393 is_cron() ||
394 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
395 ( is_ajax() && isset( $_REQUEST['action'] ) && 'heartbeat' === $_REQUEST['action'] ) ||
396 // If this is rest request and not core wp namespace.
397 ( is_rest() && request_is_excluded_rest_endpoint() )
398 ) {
399 $is_excluded = true;
400 }
401
402 return $is_excluded;
403 }
404
405 /**
406 * Check if the request is for a priveleged user in the admin area.
407 *
408 * @return bool
409 *
410 * @since 2.3.0
411 */
412 function request_for_user_is_excluded() {
413 // Check if user has permission to manage settings and is on the admin area.
414 if ( user_is_excludable() ) {
415 if (
416 // Is in the admin area.
417 is_admin() ||
418 ( is_preview() && current_user_can( 'edit_post', get_the_ID() ) ) ||
419 // Is an ajax request from the admin area.
420 (
421 ( is_ajax() || is_rest() ) &&
422 check_referrer_is_admin()
423 )
424 ) {
425 return true;
426 }
427 }
428
429 return false;
430 }
431
432 /**
433 * Check if protection methods should be disabled.
434 *
435 * Generally used to bypass protections when using page editors.
436 *
437 * @return bool
438 *
439 * @since 2.0.0
440 */
441 function protection_is_disabled() {
442 static $protection_disabled;
443
444 if ( isset( $protection_disabled ) ) {
445 return $protection_disabled;
446 }
447
448 $protection_disabled = user_is_excluded() || request_is_excluded() || request_for_user_is_excluded();
449
450 /**
451 * Filter whether protection is disabled.
452 *
453 * @param bool $is_disabled Whether protection is disabled.
454 *
455 * @return bool
456 *
457 * @since 2.0.0
458 */
459 $protection_disabled = apply_filters( 'content_control/protection_is_disabled', $protection_disabled );
460
461 return $protection_disabled;
462 }
463