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