PluginProbe
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More / trunk
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More vtrunk
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 / rule-callbacks.php

rule-callbacks.php in Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More trunk, at inc/functions/rule-callbacks.php

1,026 lines 22.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Rule callback functions.
4 *
5 * @package ContentControl
6 */
7
8 namespace ContentControl\Rules;
9
10 defined( 'ABSPATH' ) || exit;
11
12 use function ContentControl\get_main_wp_query;
13 use function ContentControl\Rules\is_post_type;
14 use function ContentControl\Rules\get_rule_extra;
15 use function ContentControl\Rules\get_rule_option;
16 use function ContentControl\current_query_context;
17 use function ContentControl\get_rest_api_intent;
18 use function ContentControl\Rules\allowed_user_roles;
19
20 // TODO add support for "Main Query Only" option for Rules & rule processing.
21
22
23 /**
24 * Checks if a user has one of the selected roles.
25 *
26 * @return bool
27 *
28 * @since 2.0.0
29 */
30 function user_has_role() {
31 if ( ! \is_user_logged_in() ) {
32 return false;
33 }
34
35 // Get rules from the current rule.
36 $roles = get_rule_option( 'roles', [] );
37
38 if ( ! count( $roles ) ) {
39 return true;
40 }
41
42 // Get Enabled Roles to check for.
43 $user_roles = array_keys( allowed_user_roles() );
44
45 /**
46 * Get the roles that are both enabled and required.
47 *
48 * @var string[] $required_roles
49 */
50 $required_roles = array_intersect( $user_roles, $roles );
51
52 if ( count( $required_roles ) === 0 ) {
53 return true;
54 }
55
56 // Check if the user has one of the required roles.
57 foreach ( $required_roles as $role ) {
58 if ( \current_user_can( $role ) ) {
59 return true;
60 }
61 }
62
63 return false;
64 }
65
66 /**
67 * Check if this is the home page.
68 *
69 * @uses current_query_context() To get the current query context.
70 *
71 * @return bool
72 *
73 * @since 2.0.0
74 * @since 2.5.0 Use explicit contexts.
75 */
76 function content_is_home_page() {
77
78 $context = current_query_context();
79
80 switch ( $context ) {
81 // Check main query.
82 case 'main':
83 case 'main/blocks':
84 $main_query = get_main_wp_query();
85
86 return $main_query->is_front_page();
87
88 // Check based on current post & context.
89 case 'main/posts':
90 case 'posts':
91 case 'blocks':
92 case 'restapi/posts':
93 global $post;
94
95 $page_id = 'page' === get_option( 'show_on_front' ) && get_option( 'page_on_front' ) ? get_option( 'page_on_front' ) : -1;
96 $post_id = $post && is_a( $post, '\WP_Post' ) ? $post->ID : 0;
97
98 return (int) $page_id === (int) $post_id;
99
100 // Catch all known contexts.
101 case 'terms':
102 case 'restapi':
103 case 'restapi/terms':
104 case 'unknown':
105 default:
106 return false;
107 }
108 }
109
110 /**
111 * Check if this is the home page.
112 *
113 * @uses current_query_context() To get the current query context.
114 *
115 * @return bool
116 *
117 * @since 2.0.0
118 * @since 2.5.0 Use explicit contexts.
119 */
120 function content_is_blog_index() {
121 $context = current_query_context();
122
123 switch ( $context ) {
124 // Check main query.
125 case 'main':
126 case 'main/blocks':
127 $main_query = get_main_wp_query();
128
129 return $main_query->is_home();
130
131 // Check based on current post & context.
132 case 'main/posts':
133 case 'posts':
134 case 'blocks':
135 case 'restapi/posts':
136 global $post;
137
138 $page_for_posts = 'page' === get_option( 'show_on_front' ) && get_option( 'page_for_posts' ) ? get_option( 'page_for_posts' ) : -1;
139 $post_id = $post && is_a( $post, '\WP_Post' ) ? $post->ID : 0;
140
141 return (int) $page_for_posts === (int) $post_id;
142
143 // Catch all known contexts.
144 case 'restapi':
145 case 'restapi/terms':
146 case 'terms':
147 case 'unknown':
148 default:
149 return false;
150 }
151 }
152
153 /**
154 * Check if this is an archive for a specific post type.
155 *
156 * @return bool
157 *
158 * @since 2.0.0
159 * @since 2.2.0 Added support for REST API.
160 * @since 2.5.0 Use explicit contexts.
161 */
162 function content_is_post_type_archive() {
163 $context = current_query_context();
164
165 $query = get_main_wp_query();
166
167 $post_type = get_rule_extra( 'post_type', '' );
168
169 switch ( $context ) {
170 case 'main':
171 case 'main/blocks':
172 // For posts we need to check a few different things.
173 if ( 'post' === $post_type ) {
174 return ( $query->is_home() || $query->is_category() || $query->is_tag() || $query->is_date() || $query->is_author() );
175 }
176
177 // Context doesn't matter for this check.
178 return $query->is_post_type_archive( $post_type );
179
180 case 'restapi':
181 $rest_intent = get_rest_api_intent();
182
183 if ( 'unknown' === $rest_intent['type'] ) {
184 return false;
185 }
186
187 if ( ! $rest_intent['index'] ) {
188 return false;
189 }
190
191 // First be sure this is for a post type of the right kind.
192 if ( ! rest_intent_matches_post_type( $post_type, $rest_intent ) ) {
193 return false;
194 }
195
196 return true;
197
198 // This is for main query only.
199 case 'main/posts':
200 case 'posts':
201 case 'blocks':
202 case 'restapi/posts':
203 case 'restapi/terms':
204 case 'terms':
205 case 'unknown':
206 default:
207 return false;
208 }
209 }
210
211 /**
212 * Check if this is a single post for a specific post type.
213 *
214 * @return bool
215 *
216 * @since 2.0.0
217 * @since 2.2.0 Added support for REST API.
218 * @since 2.5.0 Use explicit contexts.
219 */
220 function content_is_post_type() {
221 $context = current_query_context();
222 $post_type = get_rule_extra( 'post_type', '' );
223
224 switch ( $context ) {
225 case 'main':
226 case 'main/blocks':
227 $main_query = get_main_wp_query();
228 return $main_query->is_singular( $post_type );
229
230 case 'main/posts':
231 case 'posts':
232 case 'blocks':
233 return is_post_type( $post_type );
234
235 case 'restapi':
236 $rest_intent = get_rest_api_intent();
237
238 if ( 'unknown' === $rest_intent['type'] ) {
239 return false;
240 }
241
242 // First be sure this is for a singular post type of the right kind.
243 if ( ! rest_intent_matches_post_type( $post_type, $rest_intent ) ) {
244 return false;
245 }
246
247 if ( true === $rest_intent['index'] ) {
248 return true;
249 }
250
251 $post_id = $rest_intent['id'] > 0 ? $rest_intent['id'] : 0;
252
253 return get_post_type( $post_id ) === $post_type;
254
255 case 'restapi/posts':
256 global $post;
257
258 return $post && $post->post_type === $post_type;
259
260 // Catch all known contexts.
261 case 'restapi/terms':
262 case 'terms':
263 case 'unknown':
264 default:
265 return false;
266 }
267 }
268
269 /**
270 * Check if content is a selected post(s).
271 *
272 * @return bool
273 *
274 * @since 2.0.0
275 * @since 2.2.0 Added support for REST API.
276 * @since 2.5.0 Use explicit contexts.
277 */
278 function content_is_selected_post() {
279 global $post;
280
281 $context = current_query_context();
282
283 $post_type = get_rule_extra( 'post_type', '' );
284 // Handle array of string or int, and comman list.
285 $selected = \wp_parse_id_list(
286 get_rule_option( 'selected', [] )
287 );
288
289 $post_id = $post && is_a( $post, '\WP_Post' ) ? $post->ID : null;
290
291 switch ( $context ) {
292 case 'main':
293 case 'main/blocks':
294 $main_query = get_main_wp_query();
295 return $main_query->is_singular( $post_type ) && in_array( $main_query->get_queried_object_id(), $selected, true );
296
297 case 'main/posts':
298 case 'posts':
299 case 'blocks':
300 return is_post_type( $post_type ) && in_array( $post_id, $selected, true );
301
302 case 'restapi':
303 case 'restapi/posts':
304 $rest_intent = get_rest_api_intent();
305
306 if ( 'unknown' === $rest_intent['type'] ) {
307 return false;
308 }
309
310 if ( ! rest_intent_matches_post_type( $post_type, $rest_intent ) ) {
311 return false;
312 }
313
314 if ( 'restapi' === $context ) {
315 if ( $rest_intent['id'] > 0 ) {
316 $post_id = (int) $rest_intent['id'];
317 }
318 }
319
320 return in_array( $post_id, $selected, true );
321
322 // Catch all known contexts.
323 case 'restapi/terms':
324 case 'terms':
325 case 'unknown':
326 default:
327 return false;
328 }
329 }
330
331 /**
332 * Check if the current post is a child of a selected post(s).
333 *
334 * @return bool
335 *
336 * @since 2.0.0
337 * @since 2.2.0 Added support for REST API.
338 * @since 2.5.0 Use explicit contexts.
339 */
340 function content_is_child_of_post() {
341 global $post;
342
343 $context = current_query_context();
344
345 $post_type = get_rule_extra( 'post_type', '' );
346 // Handle array of string or int, and comman list.
347 $selected = \wp_parse_id_list(
348 get_rule_option( 'selected', [] )
349 );
350
351 if ( ! \is_post_type_hierarchical( $post_type ) ) {
352 return false;
353 }
354
355 $the_post = isset( $post ) ? $post : null;
356
357 switch ( $context ) {
358 case 'main':
359 case 'main/blocks':
360 $main_query = get_main_wp_query();
361 // Check if current page is a post type.
362 if ( ! $main_query->is_singular( $post_type ) ) {
363 return false;
364 }
365 break;
366
367 case 'main/posts':
368 case 'posts':
369 case 'blocks':
370 case 'restapi/posts':
371 // Check if current post is a post type.
372 if ( ! is_post_type( $post_type ) ) {
373 return false;
374 }
375 break;
376
377 case 'restapi':
378 $rest_intent = get_rest_api_intent();
379
380 if ( 'unknown' === $rest_intent['type'] ) {
381 return false;
382 }
383
384 if ( ! rest_intent_matches_post_type( $post_type, $rest_intent ) ) {
385 return false;
386 }
387
388 if ( $rest_intent['id'] > 0 ) {
389 $the_post = get_post( (int) $rest_intent['id'] );
390 }
391 break;
392
393 // Catch all known contexts.
394 case 'restapi/terms':
395 case 'terms':
396 case 'unknown':
397 break;
398 }
399
400 if ( ! $the_post ) {
401 return false;
402 }
403
404 foreach ( $selected as $id ) {
405 if ( $the_post->post_parent === $id ) {
406 return true;
407 }
408 }
409
410 return false;
411 }
412
413 /**
414 * Check if the current post is a ancestor of a selected post(s).
415 *
416 * @return bool
417 *
418 * @since 2.0.0
419 * @since 2.2.0 Added support for REST API.
420 * @since 2.5.0 Use explicit contexts.
421 */
422 function content_is_ancestor_of_post() {
423 global $post;
424
425 $context = current_query_context();
426
427 $post_type = get_rule_extra( 'post_type', '' );
428 // Handle array of string or int, and comman list.
429 $selected = \wp_parse_id_list(
430 get_rule_option( 'selected', [] )
431 );
432
433 if ( ! \is_post_type_hierarchical( $post_type ) ) {
434 return false;
435 }
436
437 $the_post = isset( $post ) ? $post : null;
438
439 switch ( $context ) {
440 case 'main':
441 case 'main/blocks':
442 $main_query = get_main_wp_query();
443 // Check if current page is a post type.
444 if ( ! $main_query->is_singular( $post_type ) ) {
445 return false;
446 }
447 break;
448
449 case 'main/posts':
450 case 'posts':
451 case 'blocks':
452 case 'restapi/posts':
453 // Check if current post is a post type.
454 if ( ! is_post_type( $post_type ) ) {
455 return false;
456 }
457 break;
458
459 case 'restapi':
460 $rest_intent = get_rest_api_intent();
461
462 if ( 'unknown' === $rest_intent['type'] ) {
463 return false;
464 }
465
466 if ( ! rest_intent_matches_post_type( $post_type, $rest_intent ) ) {
467 return false;
468 }
469
470 if ( $rest_intent['id'] > 0 ) {
471 $the_post = get_post( (int) $rest_intent['id'] );
472 }
473
474 break;
475
476 // Catch all known contexts.
477 case 'restapi/terms':
478 case 'terms':
479 case 'unknown':
480 return false;
481 }
482
483 // Ancestors of the current page.
484 $ancestors = $the_post ? \get_post_ancestors( $the_post->ID ) : [];
485
486 foreach ( $selected as $id ) {
487 if ( in_array( $id, $ancestors, true ) ) {
488 return true;
489 }
490 }
491
492 return false;
493 }
494
495 /**
496 * Check if current post uses selected template(s).
497 *
498 * @return bool
499 *
500 * @since 2.0.0
501 * @since 2.5.0 Use explicit contexts.
502 */
503 function content_is_post_with_template() {
504
505 $context = current_query_context();
506
507 $selected = get_rule_option( 'selected', [] );
508
509 $page_template = '';
510
511 switch ( $context ) {
512 case 'main':
513 case 'main/blocks':
514 $main_query = get_main_wp_query();
515
516 $page_template = get_page_template_slug( $main_query->get_queried_object_id() );
517 break;
518
519 case 'main/posts':
520 case 'posts':
521 case 'blocks':
522 case 'restapi/posts':
523 global $post;
524
525 $post_id = $post && is_a( $post, '\WP_Post' ) ? $post->ID : null;
526
527 if ( $post_id ) {
528 $page_template = get_page_template_slug( $post_id );
529 }
530 break;
531
532 case 'restapi':
533 $rest_intent = get_rest_api_intent();
534
535 if ( 'unknown' === $rest_intent['type'] ) {
536 return false;
537 }
538
539 $the_post = $rest_intent['id'] > 0 ? get_post( (int) $rest_intent['id'] ) : null;
540
541 if ( $the_post ) {
542 $page_template = get_page_template_slug( $the_post );
543 }
544 break;
545
546 // Catch all known contexts.
547 case 'restapi/terms':
548 case 'terms':
549 case 'unknown':
550 return false;
551 }
552
553 if ( empty( $selected ) ) {
554 return (bool) $page_template;
555 }
556
557 foreach ( $selected as $template ) {
558 if ( $template === $page_template ) {
559 return true;
560 }
561 }
562
563 return false;
564 }
565
566 /**
567 * Check if current post has selected taxonomy term(s).
568 *
569 * @return bool
570 *
571 * @since 2.0.0
572 * @since 2.2.0 Added support for REST API.
573 * @since 2.5.0 Use explicit contexts.
574 */
575 function content_is_post_with_tax_term() {
576 global $post;
577
578 $context = current_query_context();
579
580 $post_type = get_rule_extra( 'post_type', '' );
581 $taxonomy = get_rule_extra( 'taxonomy', '' );
582
583 // Handle array of string or int, and comman list.
584 $selected = \wp_parse_id_list(
585 get_rule_option( 'selected', [] )
586 );
587
588 $post_id = $post && is_a( $post, '\WP_Post' ) ? $post->ID : null;
589
590 switch ( $context ) {
591 case 'main':
592 case 'main/blocks':
593 $main_query = get_main_wp_query();
594
595 if ( ! $main_query->is_singular( $post_type ) ) {
596 return false;
597 }
598
599 // Ensure we are using the main query object ID.
600 $post_id = $main_query->get_queried_object_id();
601 break;
602
603 case 'restapi':
604 case 'restapi/posts':
605 $rest_intent = get_rest_api_intent();
606
607 if ( 'unknown' === $rest_intent['type'] ) {
608 return false;
609 }
610
611 // Bail if we didn't detect a post type in the intent, or the post type is not the same as the one we're checking.
612 if ( ! rest_intent_matches_post_type( $post_type, $rest_intent ) ) {
613 return false;
614 }
615
616 if ( 'restapi' === $context ) {
617 if ( $rest_intent['id'] > 0 ) {
618 $post_id = (int) $rest_intent['id'];
619 }
620 }
621 break;
622
623 case 'main/posts':
624 case 'posts':
625 case 'blocks':
626 if ( ! is_post_type( $post_type ) ) {
627 return false;
628 }
629 break;
630
631 // Catch all known contexts.
632 case 'restapi/terms':
633 case 'terms':
634 case 'unknown':
635 return false;
636 }
637
638 if ( 'category' === $taxonomy ) {
639 return \has_category( $selected, $post_id );
640 }
641
642 if ( 'post_tag' === $taxonomy ) {
643 return \has_tag( $selected, $post_id );
644 }
645
646 return \has_term( $selected, $taxonomy, $post_id );
647 }
648
649 /**
650 * Check if current content is a selected taxonomy(s).
651 *
652 * @return bool
653 *
654 * @since 2.0.0
655 * @since 2.2.0 Added support for REST API.
656 * @since 2.5.0 Use explicit contexts.
657 *
658 * @todo This needs to allow for option to check main query only.
659 */
660 function content_is_taxonomy_archive() {
661 // Get settings from the current rule.
662 $taxonomy = get_rule_extra( 'taxonomy', '' );
663
664 // Get query context.
665 $context = current_query_context();
666
667 switch ( $context ) {
668 // Handle detection of rest taxonomy endpoint.
669 case 'restapi':
670 $rest_intent = get_rest_api_intent();
671
672 if ( 'unknown' === $rest_intent['type'] ) {
673 return false;
674 }
675
676 return rest_intent_matches_taxonomy( $taxonomy, $rest_intent );
677
678 case 'restapi/terms':
679 // This is a term query, so we we aren't checking against a taxonomy archive.
680 return false;
681
682 // Hanlde main query only.
683 case 'main':
684 case 'main/blocks':
685 case 'main/posts':
686 case 'posts':
687 case 'blocks':
688 case 'restapi/posts':
689 // TODO This needs to allow for option to check main query only.
690 $main_query = get_main_wp_query();
691
692 // No context needed, always looking for main query only.
693 if ( 'category' === $taxonomy ) {
694 return $main_query->is_category();
695 } elseif ( 'post_tag' === $taxonomy ) {
696 return $main_query->is_tag();
697 }
698
699 return $main_query->is_tax( $taxonomy );
700
701 // Catch all known contexts.
702 case 'terms':
703 case 'unknown':
704 default:
705 return false;
706 }
707 }
708
709 /**
710 * Check if current content is a selected taxonomy term(s).
711 *
712 * @return bool
713 *
714 * @since 2.0.0
715 * @since 2.2.0 Added support for REST API.
716 * @since 2.5.0 Use explicit contexts.
717 */
718 function content_is_selected_term() {
719 // Get settings from the current rule.
720 $taxonomy = get_rule_extra( 'taxonomy', '' );
721 // Handle array of string or int, and comman list.
722 $selected = \wp_parse_id_list(
723 get_rule_option( 'selected', [] )
724 );
725
726 // Get query context.
727 $context = current_query_context();
728
729 // Handle detection of rest taxonomy endpoint.
730 switch ( $context ) {
731 case 'main':
732 case 'main/blocks':
733 // Get main query for 'main' context.
734 $main_query = get_main_wp_query();
735
736 // Handle everything else.
737 switch ( $taxonomy ) {
738 case 'category':
739 return $main_query->is_category( $selected );
740 case 'post_tag':
741 return $main_query->is_tag( $selected );
742 default:
743 return $main_query->is_tax( $taxonomy, $selected );
744 }
745
746 case 'terms':
747 $term = get_global( 'term' ); // Used instead of global $cc_term.
748
749 // Check if we have a term object from the term query.
750 if ( $term && $term->term_id > 0 ) {
751 return in_array( (int) $term->term_id, $selected, true );
752 }
753 break;
754
755 // Handles REST API querys.
756 case 'restapi':
757 case 'restapi/terms':
758 $rest_intent = get_rest_api_intent();
759 $term = get_global( 'term' ); // Used instead of global $cc_term.
760
761 if ( 'unknown' === $rest_intent['type'] ) {
762 return false;
763 }
764
765 if ( ! rest_intent_matches_taxonomy( $taxonomy, $rest_intent ) ) {
766 return false;
767 }
768
769 // Check if we have a term ID from the rest intent.
770 if ( $rest_intent['id'] > 0 ) {
771 return in_array( (int) $rest_intent['id'], $selected, true );
772 }
773
774 // Check if we have a term object from the term query.
775 if ( $term && $term->term_id > 0 ) {
776 return in_array( (int) $term->term_id, $selected, true );
777 }
778
779 // Always return false if no ID is set.
780 return false;
781
782 case 'main/posts':
783 case 'posts':
784 case 'blocks':
785 case 'restapi/posts':
786 case 'unknown':
787 return false;
788 }
789
790 return false;
791 }
792
793 /**
794 * Get the current term when it belongs to the selected taxonomy.
795 *
796 * @param string $taxonomy Taxonomy slug.
797 * @return \WP_Term|false
798 *
799 * @since 2.7.0
800 */
801 function get_current_taxonomy_term( $taxonomy ) {
802 $context = current_query_context();
803 $term = false;
804
805 switch ( $context ) {
806 case 'main':
807 case 'main/blocks':
808 $main_query = get_main_wp_query();
809
810 if (
811 ( 'category' === $taxonomy && ! $main_query->is_category() ) ||
812 ( 'post_tag' === $taxonomy && ! $main_query->is_tag() ) ||
813 ( ! in_array( $taxonomy, [ 'category', 'post_tag' ], true ) && ! $main_query->is_tax( $taxonomy ) )
814 ) {
815 return false;
816 }
817
818 $term = $main_query->get_queried_object();
819 break;
820
821 case 'terms':
822 $term = get_global( 'term' );
823 break;
824
825 case 'restapi':
826 case 'restapi/terms':
827 $rest_intent = get_rest_api_intent();
828
829 if ( 'unknown' === $rest_intent['type'] || ! rest_intent_matches_taxonomy( $taxonomy, $rest_intent ) ) {
830 return false;
831 }
832
833 $term = $rest_intent['id'] > 0
834 ? get_term( (int) $rest_intent['id'], $taxonomy )
835 : get_global( 'term' );
836 break;
837
838 case 'main/posts':
839 case 'posts':
840 case 'blocks':
841 case 'restapi/posts':
842 case 'unknown':
843 default:
844 return false;
845 }
846
847 if (
848 ! $term ||
849 is_wp_error( $term ) ||
850 empty( $term->term_id ) ||
851 empty( $term->taxonomy ) ||
852 $taxonomy !== $term->taxonomy
853 ) {
854 return false;
855 }
856
857 return $term;
858 }
859
860 /**
861 * Check if the current term is a child of a selected term.
862 *
863 * @return bool
864 *
865 * @since 2.7.0
866 */
867 function content_is_child_of_term() {
868 $taxonomy = get_rule_extra( 'taxonomy', '' );
869 $selected = \wp_parse_id_list( get_rule_option( 'selected', [] ) );
870
871 if ( ! \is_taxonomy_hierarchical( $taxonomy ) ) {
872 return false;
873 }
874
875 $term = get_current_taxonomy_term( $taxonomy );
876
877 return $term && in_array( (int) $term->parent, $selected, true );
878 }
879
880 /**
881 * Check if the current term has a selected ancestor.
882 *
883 * @return bool
884 *
885 * @since 2.7.0
886 */
887 function content_is_ancestor_of_term() {
888 $taxonomy = get_rule_extra( 'taxonomy', '' );
889 $selected = \wp_parse_id_list( get_rule_option( 'selected', [] ) );
890
891 if ( ! \is_taxonomy_hierarchical( $taxonomy ) ) {
892 return false;
893 }
894
895 $term = get_current_taxonomy_term( $taxonomy );
896
897 if ( ! $term ) {
898 return false;
899 }
900
901 $ancestors = array_map( 'intval', \get_ancestors( $term->term_id, $taxonomy, 'taxonomy' ) );
902
903 return (bool) array_intersect( $selected, $ancestors );
904 }
905
906 /**
907 * Check if post type matches.
908 *
909 * @param string $type Type to check (post type or taxonomy key).
910 * @param string|string[] $matches Type matches against. Array or string of comma separated values.
911 *
912 * @return bool
913 *
914 * @since 2.3.0
915 */
916 function check_type_match( $type, $matches ) {
917 // Deal with 'any' and 'all' values.
918 if (
919 // Check if any or all is in $mathces array.
920 (
921 is_array( $matches ) &&
922 (
923 in_array( 'any', $matches, true ) ||
924 in_array( 'all', $matches, true )
925 )
926 ) ||
927 'any' === $matches ||
928 'all' === $matches
929 ) {
930 return true;
931 }
932
933 if ( is_string( $matches ) ) {
934 $matches = explode( ',', $matches );
935 }
936
937 return in_array( $type, $matches, true );
938 }
939
940
941 /**
942 * Simplifies checking if a post type matches a rest intent.
943 *
944 * @param string $post_type Post type to check.
945 * @param array<string,bool|string|int>|null $rest_intent Rest intent to check.
946 *
947 * @return bool
948 *
949 * @since 2.3.0
950 */
951 function rest_intent_matches_post_type( $post_type, $rest_intent = null ) {
952 if ( ! $rest_intent ) {
953 $rest_intent = get_rest_api_intent();
954 }
955
956 // Fill in defaults to prevent errors.
957 wp_parse_args( $rest_intent, [
958 'type' => '',
959 'name' => '',
960 'search' => false,
961 ] );
962
963 // Check if this is a post type intent.
964 if ( 'post_type' !== $rest_intent['type'] ) {
965
966 // If this is a search request, we need to check if the post type is public and searchable.
967 if ( false !== $rest_intent['search'] ) {
968 $post_type_object = get_post_type_object( $post_type );
969 return $post_type_object && $post_type_object->show_in_rest && $post_type_object->publicly_queryable;
970 }
971
972 return false;
973 }
974
975 $post_type_object = get_post_type_object( $post_type );
976
977 // Check that rest_base or selected name match.
978 return // Check the rest_base for the selected post type matches the intent.
979 check_type_match( $post_type_object->rest_base, $rest_intent['name'] ) ||
980 // Check the post type matches the intent.
981 check_type_match( $post_type, $rest_intent['name'] );
982 }
983
984 /**
985 * Simplifies checking if a taxonomy matches a rest intent.
986 *
987 * @param string $taxonomy Taxonomy to check.
988 * @param array<string,bool|string|int>|null $rest_intent Rest intent to check.
989 *
990 * @return bool
991 *
992 * @since 2.3.0
993 */
994 function rest_intent_matches_taxonomy( $taxonomy, $rest_intent = null ) {
995 if ( ! $rest_intent ) {
996 $rest_intent = get_rest_api_intent();
997 }
998
999 // Fill in defaults to prevent errors.
1000 wp_parse_args( $rest_intent, [
1001 'type' => '',
1002 'name' => '',
1003 'search' => false,
1004 ] );
1005
1006 // Check if this is a taxonomy intent.
1007 if ( 'taxonomy' !== $rest_intent['type'] ) {
1008
1009 // If this is a search request, we need to check if the taxonomy is public and searchable.
1010 if ( false !== $rest_intent['search'] ) {
1011 $taxonomy_object = get_taxonomy( $taxonomy );
1012 return $taxonomy_object && $taxonomy_object->show_in_rest && $taxonomy_object->publicly_queryable;
1013 }
1014
1015 return false;
1016 }
1017
1018 $taxonomy_object = get_taxonomy( $taxonomy );
1019
1020 // Check that rest_base or selected name match.
1021 return // Check the rest_base for the selected taxonomy matches the intent.
1022 check_type_match( $taxonomy_object->rest_base, $rest_intent['name'] ) ||
1023 // Check the taxonomy matches the intent.
1024 check_type_match( $taxonomy, $rest_intent['name'] );
1025 }
1026