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 | * REST API Order Notes controller |
||
4 | * |
||
5 | * Handles requests to the /orders/<order_id>/notes endpoint. |
||
6 | * |
||
7 | * @author WooThemes |
||
8 | * @category API |
||
9 | * @package WooCommerce/API |
||
10 | * @since 2.6.0 |
||
11 | */ |
||
12 | |||
13 | if ( ! defined( 'ABSPATH' ) ) { |
||
14 | exit; |
||
15 | } |
||
16 | |||
17 | /** |
||
18 | * REST API Order Notes controller class. |
||
19 | * |
||
20 | * @package WooCommerce/API |
||
21 | * @extends WC_REST_Controller |
||
22 | */ |
||
23 | class WC_REST_Order_Notes_Controller extends WC_REST_Controller { |
||
24 | |||
25 | /** |
||
26 | * Endpoint namespace. |
||
27 | * |
||
28 | * @var string |
||
29 | */ |
||
30 | protected $namespace = 'wc/v1'; |
||
31 | |||
32 | /** |
||
33 | * Route base. |
||
34 | * |
||
35 | * @var string |
||
36 | */ |
||
37 | protected $rest_base = 'orders/(?P<order_id>[\d]+)/notes'; |
||
38 | |||
39 | /** |
||
40 | * Post type. |
||
41 | * |
||
42 | * @var string |
||
43 | */ |
||
44 | protected $post_type = 'shop_order'; |
||
45 | |||
46 | /** |
||
47 | * Register the routes for order notes. |
||
48 | */ |
||
49 | View Code Duplication | public function register_routes() { |
|
0 ignored issues
–
show
|
|||
50 | register_rest_route( $this->namespace, '/' . $this->rest_base, array( |
||
51 | array( |
||
52 | 'methods' => WP_REST_Server::READABLE, |
||
53 | 'callback' => array( $this, 'get_items' ), |
||
54 | 'permission_callback' => array( $this, 'get_items_permissions_check' ), |
||
55 | 'args' => $this->get_collection_params(), |
||
56 | ), |
||
57 | array( |
||
58 | 'methods' => WP_REST_Server::CREATABLE, |
||
59 | 'callback' => array( $this, 'create_item' ), |
||
60 | 'permission_callback' => array( $this, 'create_item_permissions_check' ), |
||
61 | 'args' => array_merge( $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ), array( |
||
62 | 'note' => array( |
||
63 | 'required' => true, |
||
64 | ), |
||
65 | ) ), |
||
66 | ), |
||
67 | 'schema' => array( $this, 'get_public_item_schema' ), |
||
68 | ) ); |
||
69 | |||
70 | register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array( |
||
71 | array( |
||
72 | 'methods' => WP_REST_Server::READABLE, |
||
73 | 'callback' => array( $this, 'get_item' ), |
||
74 | 'permission_callback' => array( $this, 'get_item_permissions_check' ), |
||
75 | 'args' => array( |
||
76 | 'context' => $this->get_context_param( array( 'default' => 'view' ) ), |
||
77 | ), |
||
78 | ), |
||
79 | array( |
||
80 | 'methods' => WP_REST_Server::DELETABLE, |
||
81 | 'callback' => array( $this, 'delete_item' ), |
||
82 | 'permission_callback' => array( $this, 'delete_item_permissions_check' ), |
||
83 | 'args' => array( |
||
84 | 'force' => array( |
||
85 | 'default' => false, |
||
86 | 'description' => __( 'Required to be true, as resource does not support trashing.', 'woocommerce' ), |
||
87 | ), |
||
88 | ), |
||
89 | ), |
||
90 | 'schema' => array( $this, 'get_public_item_schema' ), |
||
91 | ) ); |
||
92 | } |
||
93 | |||
94 | /** |
||
95 | * Check whether a given request has permission to read order notes. |
||
96 | * |
||
97 | * @param WP_REST_Request $request Full details about the request. |
||
98 | * @return WP_Error|boolean |
||
99 | */ |
||
100 | public function get_items_permissions_check( $request ) { |
||
101 | if ( ! wc_rest_check_post_permissions( $this->post_type, 'read' ) ) { |
||
102 | return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) ); |
||
103 | } |
||
104 | |||
105 | return true; |
||
106 | } |
||
107 | |||
108 | /** |
||
109 | * Check if a given request has access create order notes. |
||
110 | * |
||
111 | * @param WP_REST_Request $request Full details about the request. |
||
112 | * @return boolean |
||
113 | */ |
||
114 | public function create_item_permissions_check( $request ) { |
||
115 | if ( ! wc_rest_check_post_permissions( $this->post_type, 'create' ) ) { |
||
116 | return new WP_Error( 'woocommerce_rest_cannot_create', __( 'Sorry, you are not allowed to create resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) ); |
||
117 | } |
||
118 | |||
119 | return true; |
||
120 | } |
||
121 | |||
122 | /** |
||
123 | * Check if a given request has access to read a order note. |
||
124 | * |
||
125 | * @param WP_REST_Request $request Full details about the request. |
||
126 | * @return WP_Error|boolean |
||
127 | */ |
||
128 | View Code Duplication | public function get_item_permissions_check( $request ) { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
129 | $post = get_post( (int) $request['order_id'] ); |
||
130 | |||
131 | if ( $post && ! wc_rest_check_post_permissions( $this->post_type, 'read', $post->ID ) ) { |
||
132 | return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot view this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) ); |
||
133 | } |
||
134 | |||
135 | return true; |
||
136 | } |
||
137 | |||
138 | /** |
||
139 | * Check if a given request has access delete a order note. |
||
140 | * |
||
141 | * @param WP_REST_Request $request Full details about the request. |
||
142 | * @return boolean |
||
143 | */ |
||
144 | View Code Duplication | public function delete_item_permissions_check( $request ) { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
145 | $post = get_post( (int) $request['order_id'] ); |
||
146 | |||
147 | if ( $post && ! wc_rest_check_post_permissions( $this->post_type, 'delete', $post->ID ) ) { |
||
148 | return new WP_Error( 'woocommerce_rest_cannot_delete', __( 'Sorry, you are not allowed to delete this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) ); |
||
149 | } |
||
150 | |||
151 | return true; |
||
152 | } |
||
153 | |||
154 | /** |
||
155 | * Get order notes from an order. |
||
156 | * |
||
157 | * @param WP_REST_Request $request |
||
158 | * @return array |
||
159 | */ |
||
160 | public function get_items( $request ) { |
||
161 | $order = get_post( (int) $request['order_id'] ); |
||
162 | |||
163 | if ( empty( $order->post_type ) || $this->post_type !== $order->post_type ) { |
||
164 | return new WP_Error( 'woocommerce_rest_{$this->post_type}_invalid_id', __( 'Invalid order id.', 'woocommerce' ), array( 'status' => 404 ) ); |
||
165 | } |
||
166 | |||
167 | $args = array( |
||
168 | 'post_id' => $order->ID, |
||
169 | 'approve' => 'approve', |
||
170 | 'type' => 'order_note', |
||
171 | ); |
||
172 | |||
173 | remove_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ), 10, 1 ); |
||
174 | |||
175 | $notes = get_comments( $args ); |
||
176 | |||
177 | add_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ), 10, 1 ); |
||
178 | |||
179 | $data = array(); |
||
180 | foreach ( $notes as $note ) { |
||
181 | $order_note = $this->prepare_item_for_response( $note, $request ); |
||
182 | $order_note = $this->prepare_response_for_collection( $order_note ); |
||
183 | $data[] = $order_note; |
||
184 | } |
||
185 | |||
186 | return rest_ensure_response( $data ); |
||
187 | } |
||
188 | |||
189 | /** |
||
190 | * Create a single order note. |
||
191 | * |
||
192 | * @param WP_REST_Request $request Full details about the request. |
||
193 | * @return WP_Error|WP_REST_Response |
||
194 | */ |
||
195 | public function create_item( $request ) { |
||
196 | if ( ! empty( $request['id'] ) ) { |
||
197 | return new WP_Error( "woocommerce_rest_{$this->post_type}_exists", sprintf( __( 'Cannot create existing %s.', 'woocommerce' ), $this->post_type ), array( 'status' => 400 ) ); |
||
198 | } |
||
199 | |||
200 | $order = get_post( (int) $request['order_id'] ); |
||
201 | |||
202 | if ( empty( $order->post_type ) || $this->post_type !== $order->post_type ) { |
||
203 | return new WP_Error( 'woocommerce_rest_order_invalid_id', __( 'Invalid order id.', 'woocommerce' ), array( 'status' => 404 ) ); |
||
204 | } |
||
205 | |||
206 | $order = wc_get_order( $order ); |
||
207 | |||
208 | // Create the note. |
||
209 | $note_id = $order->add_order_note( $request['note'], $request['customer_note'] ); |
||
210 | |||
211 | if ( ! $note_id ) { |
||
212 | return new WP_Error( 'woocommerce_api_cannot_create_order_note', __( 'Cannot create order note, please try again.', 'woocommerce' ), array( 'status' => 500 ) ); |
||
213 | } |
||
214 | |||
215 | $note = get_comment( $note_id ); |
||
216 | $this->update_additional_fields_for_object( $note, $request ); |
||
217 | |||
218 | /** |
||
219 | * Fires after a order note is created or updated via the REST API. |
||
220 | * |
||
221 | * @param WP_Comment $note New order note object. |
||
222 | * @param WP_REST_Request $request Request object. |
||
223 | * @param boolean $creating True when creating item, false when updating. |
||
224 | */ |
||
225 | do_action( 'woocommerce_rest_insert_order_note', $note, $request, true ); |
||
226 | |||
227 | $request->set_param( 'context', 'edit' ); |
||
228 | $response = $this->prepare_item_for_response( $note, $request ); |
||
229 | $response = rest_ensure_response( $response ); |
||
230 | $response->set_status( 201 ); |
||
231 | $response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, str_replace( '(?P<order_id>[\d]+)', $order->id, $this->rest_base ), $note_id ) ) ); |
||
232 | |||
233 | return $response; |
||
234 | } |
||
235 | |||
236 | /** |
||
237 | * Get a single order note. |
||
238 | * |
||
239 | * @param WP_REST_Request $request Full details about the request. |
||
240 | * @return WP_Error|WP_REST_Response |
||
241 | */ |
||
242 | View Code Duplication | public function get_item( $request ) { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
243 | $id = (int) $request['id']; |
||
244 | $order = get_post( (int) $request['order_id'] ); |
||
245 | |||
246 | if ( empty( $order->post_type ) || $this->post_type !== $order->post_type ) { |
||
247 | return new WP_Error( 'woocommerce_rest_order_invalid_id', __( 'Invalid order id.', 'woocommerce' ), array( 'status' => 404 ) ); |
||
248 | } |
||
249 | |||
250 | $note = get_comment( $id ); |
||
251 | |||
252 | if ( empty( $id ) || empty( $note ) || intval( $note->comment_post_ID ) !== intval( $order->ID ) ) { |
||
253 | return new WP_Error( 'woocommerce_rest_invalid_id', __( 'Invalid resource id.', 'woocommerce' ), array( 'status' => 404 ) ); |
||
254 | } |
||
255 | |||
256 | $order_note = $this->prepare_item_for_response( $note, $request ); |
||
257 | $response = rest_ensure_response( $order_note ); |
||
258 | |||
259 | return $response; |
||
260 | } |
||
261 | |||
262 | /** |
||
263 | * Delete a single order note. |
||
264 | * |
||
265 | * @param WP_REST_Request $request Full details about the request. |
||
266 | * @return WP_REST_Response|WP_Error |
||
267 | */ |
||
268 | public function delete_item( $request ) { |
||
269 | $id = (int) $request['id']; |
||
270 | $force = isset( $request['force'] ) ? (bool) $request['force'] : false; |
||
271 | |||
272 | // We don't support trashing for this type, error out. |
||
273 | if ( ! $force ) { |
||
274 | return new WP_Error( 'woocommerce_rest_trash_not_supported', __( 'Webhooks do not support trashing.', 'woocommerce' ), array( 'status' => 501 ) ); |
||
275 | } |
||
276 | |||
277 | $order = get_post( (int) $request['order_id'] ); |
||
278 | |||
279 | if ( empty( $order->post_type ) || $this->post_type !== $order->post_type ) { |
||
280 | return new WP_Error( 'woocommerce_rest_order_invalid_id', __( 'Invalid order id.', 'woocommerce' ), array( 'status' => 404 ) ); |
||
281 | } |
||
282 | |||
283 | $note = get_comment( $id ); |
||
284 | |||
285 | if ( empty( $id ) || empty( $note ) || intval( $note->comment_post_ID ) !== intval( $order->ID ) ) { |
||
286 | return new WP_Error( 'woocommerce_rest_invalid_id', __( 'Invalid resource id.', 'woocommerce' ), array( 'status' => 404 ) ); |
||
287 | } |
||
288 | |||
289 | $request->set_param( 'context', 'edit' ); |
||
290 | $response = $this->prepare_item_for_response( $note, $request ); |
||
291 | |||
292 | $result = wp_delete_comment( $note->comment_ID, true );; |
||
293 | |||
294 | if ( ! $result ) { |
||
295 | return new WP_Error( 'woocommerce_rest_cannot_delete', sprintf( __( 'The %s cannot be deleted.', 'woocommerce' ), 'order_note' ), array( 'status' => 500 ) ); |
||
296 | } |
||
297 | |||
298 | /** |
||
299 | * Fires after a order note is deleted or trashed via the REST API. |
||
300 | * |
||
301 | * @param WP_Comment $note The deleted or trashed order note. |
||
302 | * @param WP_REST_Response $response The response data. |
||
303 | * @param WP_REST_Request $request The request sent to the API. |
||
304 | */ |
||
305 | do_action( 'woocommerce_rest_delete_order_note', $note, $response, $request ); |
||
306 | |||
307 | return $response; |
||
308 | } |
||
309 | |||
310 | /** |
||
311 | * Prepare a single order note output for response. |
||
312 | * |
||
313 | * @param WP_Comment $note Order note object. |
||
314 | * @param WP_REST_Request $request Request object. |
||
315 | * @return WP_REST_Response $response Response data. |
||
316 | */ |
||
317 | public function prepare_item_for_response( $note, $request ) { |
||
318 | $data = array( |
||
319 | 'id' => (int) $note->comment_ID, |
||
320 | 'date_created' => wc_rest_prepare_date_response( $note->comment_date_gmt ), |
||
321 | 'note' => $note->comment_content, |
||
322 | 'customer_note' => (bool) get_comment_meta( $note->comment_ID, 'is_customer_note', true ), |
||
323 | ); |
||
324 | |||
325 | $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; |
||
326 | $data = $this->add_additional_fields_to_object( $data, $request ); |
||
327 | $data = $this->filter_response_by_context( $data, $context ); |
||
328 | |||
329 | // Wrap the data in a response object. |
||
330 | $response = rest_ensure_response( $data ); |
||
331 | |||
332 | $response->add_links( $this->prepare_links( $note ) ); |
||
333 | |||
334 | /** |
||
335 | * Filter order note object returned from the REST API. |
||
336 | * |
||
337 | * @param WP_REST_Response $response The response object. |
||
338 | * @param WP_Comment $note Order note object used to create response. |
||
339 | * @param WP_REST_Request $request Request object. |
||
340 | */ |
||
341 | return apply_filters( 'woocommerce_rest_prepare_order_note', $response, $note, $request ); |
||
342 | } |
||
343 | |||
344 | /** |
||
345 | * Prepare links for the request. |
||
346 | * |
||
347 | * @param WP_Comment $note Delivery order_note object. |
||
348 | * @return array Links for the given order note. |
||
349 | */ |
||
350 | View Code Duplication | protected function prepare_links( $note ) { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
351 | $order_id = (int) $note->comment_post_ID; |
||
352 | $base = str_replace( '(?P<order_id>[\d]+)', $order_id, $this->rest_base ); |
||
353 | $links = array( |
||
354 | 'self' => array( |
||
355 | 'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, $base, $note->comment_ID ) ), |
||
356 | ), |
||
357 | 'collection' => array( |
||
358 | 'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $base ) ), |
||
359 | ), |
||
360 | 'up' => array( |
||
361 | 'href' => rest_url( sprintf( '/%s/orders/%d', $this->namespace, $order_id ) ), |
||
362 | ), |
||
363 | ); |
||
364 | |||
365 | return $links; |
||
366 | } |
||
367 | |||
368 | /** |
||
369 | * Get the Order Notes schema, conforming to JSON Schema. |
||
370 | * |
||
371 | * @return array |
||
372 | */ |
||
373 | public function get_item_schema() { |
||
374 | $schema = array( |
||
375 | '$schema' => 'http://json-schema.org/draft-04/schema#', |
||
376 | 'title' => 'tax', |
||
377 | 'type' => 'order_note', |
||
378 | 'properties' => array( |
||
379 | 'id' => array( |
||
380 | 'description' => __( 'Unique identifier for the resource.', 'woocommerce' ), |
||
381 | 'type' => 'integer', |
||
382 | 'context' => array( 'view', 'edit' ), |
||
383 | 'readonly' => true, |
||
384 | ), |
||
385 | 'date_created' => array( |
||
386 | 'description' => __( "The date the order note was created, in the site's timezone.", 'woocommerce' ), |
||
387 | 'type' => 'date-time', |
||
388 | 'context' => array( 'view', 'edit' ), |
||
389 | 'readonly' => true, |
||
390 | ), |
||
391 | 'note' => array( |
||
392 | 'description' => __( 'Order note.', 'woocommerce' ), |
||
393 | 'type' => 'string', |
||
394 | 'context' => array( 'view', 'edit' ), |
||
395 | ), |
||
396 | 'customer_note' => array( |
||
397 | 'description' => __( 'Shows/define if the note is only for reference or for the customer (the user will be notified).', 'woocommerce' ), |
||
398 | 'type' => 'boolean', |
||
399 | 'default' => false, |
||
400 | 'context' => array( 'view', 'edit' ), |
||
401 | ), |
||
402 | ), |
||
403 | ); |
||
404 | |||
405 | return $this->add_additional_fields_schema( $schema ); |
||
406 | } |
||
407 | |||
408 | /** |
||
409 | * Get the query params for collections. |
||
410 | * |
||
411 | * @return array |
||
412 | */ |
||
413 | public function get_collection_params() { |
||
414 | return array( |
||
415 | 'context' => $this->get_context_param( array( 'default' => 'view' ) ), |
||
416 | ); |
||
417 | } |
||
418 | } |
||
419 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.