PluginProbe ʕ •ᴥ•ʔ
Kirki – Freeform Page Builder, Website Builder & Customizer / 6.1.1
Kirki – Freeform Page Builder, Website Builder & Customizer v6.1.1
6.1.1 6.1.0 6.0.14 6.0.13 6.0.12 6.0.11 6.0.10 6.0.9 6.0.8 6.0.7 6.0.6 6.0.5 6.0.4 6.0.3 6.0.2 6.0.1 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 4.0.19 4.0.20 4.0.21 4.0.22 4.0.23 4.0.24 4.1 4.2.0 5.0.0 5.1.0 5.1.1 5.2.0 5.2.1 5.2.2 5.2.3 6.0.0 trunk 3.0.40 3.0.41 3.0.42 3.0.43 3.0.44 3.0.45 3.1.0 3.1.1 3.1.2
kirki / includes / API / Frontend / Controllers / FrontendRESTController.php
kirki / includes / API / Frontend / Controllers Last commit date
CollectionController.php 1 month ago FormController.php 3 weeks ago FrontendRESTController.php 2 days ago
FrontendRESTController.php
124 lines
1 <?php
2 /**
3 * FrontendRESTController
4 *
5 * @package kirki
6 */
7
8 namespace Kirki\API\Frontend\Controllers;
9
10 if ( ! defined( 'ABSPATH' ) ) {
11 exit; // Exit if accessed directly.
12 }
13 use WP_Error;
14 use WP_REST_Controller;
15
16
17 /**
18 * FrontendRESTController class
19 */
20 abstract class FrontendRESTController extends WP_REST_Controller {
21 /**
22 * Initialize the class
23 *
24 * @return void
25 */
26 public function __construct() {
27 $this->namespace ='kirki/v1';
28 $this->rest_base = 'frontend';
29 }
30
31
32 /**
33 * Permission gate for all frontend endpoints.
34 *
35 * Checks:
36 * 1. A JSON `context` param — validates the user can read the referenced post.
37 * 2. A direct `post_id` param — validates the user can read that post.
38 *
39 * @param \WP_REST_Request $request
40 * @return bool|\WP_Error
41 */
42 public function get_item_permissions_check( $request ) {
43 // --- Check 1: context-based permission (post or comment context) ---
44 $raw_context = $request->get_param( 'context' );
45
46 if ( $raw_context ) {
47 $context = json_decode( $raw_context, true );
48 $post_id = $this->extract_post_id_from_context( $context );
49
50 if ( $post_id && ! $this->can_user_read_post( $post_id ) ) {
51 return new WP_Error(
52 'rest_forbidden',
53 'You do not have permission to read this post.',
54 array( 'status' => 403 )
55 );
56 }
57 }
58
59 // --- Check 2: direct post_id param ---
60 $post_id = absint( $request->get_param( 'post_id' ) );
61
62 if ( $post_id && ! $this->can_user_read_post( $post_id ) ) {
63 return new WP_Error(
64 'rest_forbidden',
65 'You do not have permission to read this post.',
66 array( 'status' => 403 )
67 );
68 }
69
70 return true;
71 }
72
73 /**
74 * Extracts the relevant post ID from a decoded context array.
75 * - For 'post' context: uses context['id']
76 * - For 'comment' context: uses context['post_id'] (the parent post)
77 * - For all others: no post ID to check
78 *
79 * @param mixed $context Decoded JSON context.
80 * @return int|null Sanitized post ID, or null if not applicable.
81 */
82 private function extract_post_id_from_context( $context ): ?int {
83 if ( ! is_array( $context ) || empty( $context['type'] ) ) {
84 return null;
85 }
86
87 switch( $context['type'] ) {
88 case 'post':
89 return isset( $context['id'] ) ? absint( $context['id'] ) : null;
90 case 'comment':
91 return isset( $context['post_id'] ) ? absint( $context['post_id'] ) : null;
92 default:
93 return null;
94 }
95 }
96
97 /**
98 * Determines whether the current user can read the given post.
99 * Publicly published posts are readable by anyone (no login required).
100 * Private/draft/etc. fall back to WordPress capability check.
101 *
102 * @param int $post_id
103 * @return bool
104 */
105 protected function can_user_read_post( int $post_id ): bool {
106 $post = get_post( $post_id );
107
108 if ( ! $post ) {
109 return false;
110 }
111
112 $is_password_protected = !empty( $post->post_password );
113
114 if ( 'publish' === $post->post_status && ! $is_password_protected ) {
115 return true;
116 }
117
118 if ( 'publish' === $post->post_status && $is_password_protected ) {
119 return ! post_password_required( $post ) || current_user_can( 'read_post', $post_id );
120 }
121
122 return current_user_can( 'read_post', $post_id );
123 }
124 }