This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /** |
||
4 | * Class WP_REST_React_Controller |
||
5 | */ |
||
6 | class WP_REST_React_Controller extends WP_REST_Controller { |
||
7 | /** |
||
8 | * The namespace of this controller's route. |
||
9 | * |
||
10 | * @var string |
||
11 | */ |
||
12 | public $namespace; |
||
13 | |||
14 | /** |
||
15 | * The base of this controller's route. |
||
16 | * |
||
17 | * @var string |
||
18 | */ |
||
19 | public $rest_base; |
||
20 | |||
21 | /** |
||
22 | * Constructor. |
||
23 | */ |
||
24 | public function __construct() { |
||
25 | $this->namespace = 'wp/v2'; |
||
26 | $this->rest_base = 'react'; |
||
27 | } |
||
28 | |||
29 | /** |
||
30 | * Register the routes for the objects of the controller. |
||
31 | */ |
||
32 | public function register_routes() { |
||
33 | register_rest_route( $this->namespace, $this->rest_base, array( |
||
34 | array( |
||
35 | 'methods' => WP_Rest_Server::READABLE, |
||
36 | 'callback' => array( $this, 'get_items' ), |
||
37 | 'permission_callback' => array( $this, 'get_items_permissions_check' ), |
||
38 | 'args' => $this->get_collection_params(), |
||
39 | ), |
||
40 | array( |
||
41 | 'methods' => WP_Rest_Server::CREATABLE, |
||
42 | 'callback' => array( $this, 'create_item' ), |
||
43 | 'permission_callback' => array( $this, 'create_item_permissions_check' ), |
||
44 | 'args' => $this->get_creation_params(), |
||
45 | ), |
||
46 | 'schema' => array( $this, 'get_public_item_schema' ), |
||
47 | ) ); |
||
48 | } |
||
49 | |||
50 | /** |
||
51 | * Check if a given request has access to read reactions. |
||
52 | * |
||
53 | * @param WP_REST_Request $request Full details about the request. |
||
54 | * @return WP_Error|boolean |
||
55 | */ |
||
56 | public function get_items_permissions_check( $request ) { |
||
57 | if ( ! empty( $request['post'] ) ) { |
||
58 | foreach ( (array) $request['post'] as $post_id ) { |
||
59 | $post = get_post( $post_id ); |
||
60 | if ( ! empty( $post_id ) && $post && ! $this->check_read_post_permission( $post ) ) { |
||
61 | return new WP_Error( 'rest_cannot_read_post', __( 'Sorry, you cannot read the post for this reaction.' ), array( 'status' => rest_authorization_required_code() ) ); |
||
62 | } else if ( 0 === $post_id && ! current_user_can( 'moderate_comments' ) ) { |
||
63 | return new WP_Error( 'rest_cannot_read', __( 'Sorry, you cannot read reactions without a post.' ), array( 'status' => rest_authorization_required_code() ) ); |
||
64 | } |
||
65 | } |
||
66 | } |
||
67 | |||
68 | return true; |
||
69 | } |
||
70 | |||
71 | /** |
||
72 | * Get a list of reactions. |
||
73 | * |
||
74 | * @param WP_REST_Request $request Full details about the request. |
||
75 | * @return WP_Error|WP_REST_Response |
||
76 | */ |
||
77 | public function get_items( $request ) { |
||
78 | $prepared_args = array( |
||
79 | 'post__in' => $request['post'], |
||
80 | 'type' => 'reaction', |
||
81 | ); |
||
82 | |||
83 | /** |
||
84 | * Filter arguments, before passing to WP_Comment_Query, when querying reactions via the REST API. |
||
85 | * |
||
86 | * @see https://developer.wordpress.org/reference/classes/wp_comment_query/ |
||
87 | * |
||
88 | * @param array $prepared_args Array of arguments for WP_Comment_Query. |
||
89 | * @param WP_REST_Request $request The current request. |
||
90 | */ |
||
91 | $prepared_args = apply_filters( 'rest_reaction_query', $prepared_args, $request ); |
||
92 | |||
93 | $query = new WP_Comment_Query; |
||
94 | $query_result = $query->query( $prepared_args ); |
||
95 | |||
96 | $reactions_count = array(); |
||
97 | foreach ( $query_result as $reaction ) { |
||
98 | if ( empty( $reactions_count[ $reaction->comment_content ] ) ) { |
||
99 | $reactions_count[ $reaction->comment_content ] = array( |
||
100 | 'count' => 0, |
||
101 | 'post_id' => $reaction->comment_post_ID, |
||
102 | ); |
||
103 | } |
||
104 | |||
105 | $reactions_count[ $reaction->comment_content ]++; |
||
106 | } |
||
107 | |||
108 | $reactions = array(); |
||
109 | foreach ( $reactions_count as $emoji => $data ) { |
||
110 | $reaction = array( |
||
111 | 'emoji' => $emoji, |
||
112 | 'count' => $data['count'], |
||
113 | 'post_id' => $data['post_id'], |
||
114 | ); |
||
115 | |||
116 | $data = $this->prepare_item_for_response( $reaction, $request ); |
||
117 | $reactions[] = $this->prepare_response_for_collection( $data ); |
||
118 | } |
||
119 | |||
120 | $total_reactions = (int) $query->found_comments; |
||
121 | $reaction_groups = count( $reactions ); |
||
122 | |||
123 | $response = rest_ensure_response( $reactions ); |
||
124 | $response->header( 'X-WP-Total', $total_reactions ); |
||
125 | $response->header( 'X-WP-TotalGroups', $reaction_groups ); |
||
126 | |||
127 | return $response; |
||
128 | } |
||
129 | |||
130 | /** |
||
131 | * Check if a given request has access to create a reaction |
||
132 | * |
||
133 | * @param WP_REST_Request $request Full details about the request. |
||
134 | * @return WP_Error|boolean |
||
135 | */ |
||
136 | public function create_item_permissions_check( $request ) { |
||
137 | if ( ! empty( $request['post'] ) && $post = get_post( (int) $request['post'] ) ) { |
||
138 | if ( ! $this->check_read_post_permission( $post ) ) { |
||
139 | return new WP_Error( 'rest_cannot_read_post', __( 'Sorry, you cannot read the post for this reaction.' ), array( 'status' => rest_authorization_required_code() ) ); |
||
140 | } |
||
141 | |||
142 | if ( ! comments_open( $post->ID ) ) { |
||
143 | return new WP_Error( 'rest_reactions_closed', __( 'Sorry, reactions are closed on this post.' ), array( 'status' => 403 ) ); |
||
144 | } |
||
145 | } |
||
146 | return true; |
||
147 | } |
||
148 | |||
149 | /** |
||
150 | * Create a reaction. |
||
151 | * |
||
152 | * @param WP_REST_Request $request Full details about the request. |
||
153 | * @return WP_Error|WP_REST_Response |
||
154 | */ |
||
155 | public function create_item( $request ) { |
||
156 | $comment = array( |
||
157 | 'comment_content' => $request['emoji'], |
||
158 | 'comment_post_ID' => $request['post'], |
||
159 | 'comment_type' => 'reaction', |
||
160 | ); |
||
161 | |||
162 | wp_insert_comment( $comment ); |
||
163 | |||
164 | return $this->get_items( $request ); |
||
165 | } |
||
166 | |||
167 | /** |
||
168 | * Check if we can read a post. |
||
169 | * |
||
170 | * Correctly handles posts with the inherit status. |
||
171 | * |
||
172 | * @param object $post Post object. |
||
173 | * @return boolean Can we read it? |
||
174 | */ |
||
175 | public function check_read_post_permission( $post ) { |
||
176 | $posts_controller = new WP_REST_Posts_Controller( $post->post_type ); |
||
177 | |||
178 | return $posts_controller->check_read_permission( $post ); |
||
179 | } |
||
180 | |||
181 | /** |
||
182 | * Prepare a reaction group output for response. |
||
183 | * |
||
184 | * @param array $reaction Reaction data. |
||
185 | * @param WP_REST_Request $request Request object. |
||
186 | * @return WP_REST_Response $response |
||
187 | */ |
||
188 | public function prepare_item_for_response( $reaction, $request ) { |
||
189 | $data = array( |
||
190 | 'emoji' => $reaction['emoji'], |
||
191 | 'count' => (int) $reaction['count'], |
||
192 | 'post_id' => (int) $reaction['post_id'], |
||
193 | ); |
||
194 | |||
195 | // Wrap the data in a response object |
||
196 | $response = rest_ensure_response( $data ); |
||
197 | |||
198 | $response->add_links( $this->prepare_links( $reaction ) ); |
||
199 | |||
200 | /** |
||
201 | * Filter a reaction group returned from the API. |
||
202 | * |
||
203 | * Allows modification of the reaction right before it is returned. |
||
204 | * |
||
205 | * @param WP_REST_Response $response The response object. |
||
206 | * @param array $reaction The original reaction data. |
||
207 | * @param WP_REST_Request $request Request used to generate the response. |
||
208 | */ |
||
209 | return apply_filters( 'rest_prepare_comment', $response, $reaction, $request ); |
||
210 | } |
||
211 | |||
212 | /** |
||
213 | * Prepare a response for inserting into a collection. |
||
214 | * |
||
215 | * @param WP_REST_Response $response Response object. |
||
216 | * @return array Response data, ready for insertion into collection data. |
||
217 | */ |
||
218 | public function prepare_response_for_collection( $response ) { |
||
219 | if ( ! ( $response instanceof WP_REST_Response ) ) { |
||
0 ignored issues
–
show
|
|||
220 | return $response; |
||
221 | } |
||
222 | |||
223 | $data = (array) $response->get_data(); |
||
224 | $links = WP_REST_Server::get_response_links( $response ); |
||
225 | if ( ! empty( $links ) ) { |
||
226 | $data['_links'] = $links; |
||
227 | } |
||
228 | |||
229 | return $data; |
||
230 | } |
||
231 | |||
232 | /** |
||
233 | * Prepare links for the request. |
||
234 | * |
||
235 | * @param array $reaction Reaction. |
||
236 | * @return array Links for the given reaction. |
||
237 | */ |
||
238 | protected function prepare_links( $reaction ) { |
||
239 | $links = array( |
||
240 | 'self' => array( |
||
241 | 'href' => rest_url( sprintf( '/%s/%s/%s', $this->namespace, $this->rest_base, $reaction['emoji'] ) ), |
||
242 | ), |
||
243 | 'collection' => array( |
||
244 | 'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ), |
||
245 | ), |
||
246 | ); |
||
247 | |||
248 | if ( 0 !== (int) $reaction['post_id'] ) { |
||
249 | $post = get_post( $reaction['post_id'] ); |
||
250 | if ( ! empty( $post->ID ) ) { |
||
251 | $obj = get_post_type_object( $post->post_type ); |
||
252 | $base = ! empty( $obj->rest_base ) ? $obj->rest_base : $obj->name; |
||
253 | $links['up'] = array( |
||
254 | 'href' => rest_url( '/wp/v2/' . $base . '/' . $reaction['post_id'] ), |
||
255 | 'embeddable' => true, |
||
256 | 'post_type' => $post->post_type, |
||
257 | ); |
||
258 | } |
||
259 | } |
||
260 | |||
261 | return $links; |
||
262 | } |
||
263 | |||
264 | /** |
||
265 | * Get the query params for collections |
||
266 | * |
||
267 | * @return array |
||
268 | */ |
||
269 | public function get_collection_params() { |
||
270 | $query_params = array(); |
||
271 | |||
272 | $query_params['post'] = array( |
||
273 | 'default' => array(), |
||
274 | 'description' => __( 'Limit result set to resources assigned to specific post ids.' ), |
||
275 | 'type' => 'array', |
||
276 | 'sanitize_callback' => 'wp_parse_id_list', |
||
277 | 'validate_callback' => 'rest_validate_request_arg', |
||
278 | ); |
||
279 | |||
280 | return $query_params; |
||
281 | } |
||
282 | /** |
||
283 | * Get the query params for collections |
||
284 | * |
||
285 | * @return array |
||
286 | */ |
||
287 | public function get_creation_params() { |
||
288 | $query_params = array(); |
||
289 | |||
290 | $query_params['post'] = array( |
||
291 | 'default' => array(), |
||
292 | 'description' => __( 'The post ID to add a reaction to.' ), |
||
293 | 'type' => 'integer', |
||
294 | 'sanitize_callback' => 'absint', |
||
295 | 'validate_callback' => 'rest_validate_request_arg', |
||
296 | ); |
||
297 | |||
298 | $query_params['emoji'] = array( |
||
299 | 'default' => array(), |
||
300 | 'description' => __( 'The reaction emoji.' ), |
||
301 | 'type' => 'string', |
||
302 | 'validate_callback' => 'rest_validate_request_arg', |
||
303 | ); |
||
304 | |||
305 | return $query_params; |
||
306 | } |
||
307 | } |
This error could be the result of:
1. Missing dependencies
PHP Analyzer uses your
composer.json
file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects thecomposer.json
to be in the root folder of your repository.Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the
require
orrequire-dev
section?2. Missing use statement
PHP does not complain about undefined classes in
ìnstanceof
checks. For example, the following PHP code will work perfectly fine:If you have not tested against this specific condition, such errors might go unnoticed.