| Total Complexity | 110 |
| Total Lines | 1360 |
| Duplicated Lines | 0 % |
| Changes | 2 | ||
| Bugs | 0 | Features | 0 |
Complex classes like WPInv_REST_Invoice_Controller often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use WPInv_REST_Invoice_Controller, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 20 | class WPInv_REST_Invoice_Controller extends WP_REST_Posts_Controller { |
||
| 21 | |||
| 22 | /** |
||
| 23 | * Post type. |
||
| 24 | * |
||
| 25 | * @var string |
||
| 26 | */ |
||
| 27 | protected $post_type = 'wpi_invoice'; |
||
| 28 | |||
| 29 | /** |
||
| 30 | * Cached results of get_item_schema. |
||
| 31 | * |
||
| 32 | * @since 1.0.13 |
||
| 33 | * @var array |
||
| 34 | */ |
||
| 35 | protected $schema; |
||
| 36 | |||
| 37 | /** |
||
| 38 | * Constructor. |
||
| 39 | * |
||
| 40 | * @since 1.0.13 |
||
| 41 | * |
||
| 42 | * @param string $namespace Api Namespace |
||
| 43 | */ |
||
| 44 | public function __construct( $namespace ) { |
||
| 45 | |||
| 46 | // Set api namespace... |
||
| 47 | $this->namespace = $namespace; |
||
| 48 | |||
| 49 | // ... and the rest base |
||
| 50 | $this->rest_base = 'invoices'; |
||
| 51 | |||
| 52 | } |
||
| 53 | |||
| 54 | /** |
||
| 55 | * Checks if a given request has access to read invoices. |
||
| 56 | * |
||
| 57 | * |
||
| 58 | * @since 1.0.13 |
||
| 59 | * |
||
| 60 | * @param WP_REST_Request $request Full details about the request. |
||
| 61 | * @return true|WP_Error True if the request has read access, WP_Error object otherwise. |
||
| 62 | */ |
||
| 63 | public function get_items_permissions_check( $request ) { |
||
| 64 | |||
| 65 | $post_type = get_post_type_object( $this->post_type ); |
||
| 66 | |||
| 67 | if ( 'edit' === $request['context'] && ! current_user_can( $post_type->cap->edit_posts ) ) { |
||
| 68 | return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit invoices.', 'invoicing' ), array( 'status' => rest_authorization_required_code() ) ); |
||
| 69 | } |
||
| 70 | |||
| 71 | // Read checks will be evaluated on a per invoice basis |
||
| 72 | |||
| 73 | return true; |
||
| 74 | |||
| 75 | } |
||
| 76 | |||
| 77 | /** |
||
| 78 | * Retrieves a collection of invoices. |
||
| 79 | * |
||
| 80 | * @since 1.0.13 |
||
| 81 | * |
||
| 82 | * @param WP_REST_Request $request Full details about the request. |
||
| 83 | * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. |
||
| 84 | */ |
||
| 85 | public function get_items( $request ) { |
||
| 86 | |||
| 87 | // Retrieve the list of registered invoice query parameters. |
||
| 88 | $registered = $this->get_collection_params(); |
||
| 89 | |||
| 90 | $args = array(); |
||
| 91 | |||
| 92 | foreach( array_keys( $registered ) as $key ) { |
||
| 93 | |||
| 94 | if( isset( $request[ $key] ) ) { |
||
| 95 | $args[ $key ] = $request[ $key]; |
||
| 96 | } |
||
| 97 | |||
| 98 | } |
||
| 99 | |||
| 100 | /** |
||
| 101 | * Filters the wpinv_get_invoices arguments for invoices requests. |
||
| 102 | * |
||
| 103 | * |
||
| 104 | * @since 1.0.13 |
||
| 105 | * |
||
| 106 | * |
||
| 107 | * @param array $args Key value array of query var to query value. |
||
| 108 | * @param WP_REST_Request $request The request used. |
||
| 109 | */ |
||
| 110 | $args = apply_filters( "wpinv_rest_get_invoices_arguments", $args, $request, $this ); |
||
| 111 | |||
| 112 | // Special args |
||
| 113 | $args[ 'return' ] = 'objects'; |
||
| 114 | $args[ 'paginate' ] = true; |
||
| 115 | |||
| 116 | // Run the query. |
||
| 117 | $query = wpinv_get_invoices( $args ); |
||
| 118 | |||
| 119 | // Prepare the retrieved invoices |
||
| 120 | $invoices = array(); |
||
| 121 | foreach( $query->invoices as $invoice ) { |
||
| 122 | |||
| 123 | if ( ! $this->check_read_permission( $invoice ) ) { |
||
| 124 | continue; |
||
| 125 | } |
||
| 126 | |||
| 127 | $data = $this->prepare_item_for_response( $invoice, $request ); |
||
| 128 | $invoices[] = $this->prepare_response_for_collection( $data ); |
||
| 129 | |||
| 130 | } |
||
| 131 | |||
| 132 | // Prepare the response. |
||
| 133 | $response = rest_ensure_response( $invoices ); |
||
| 134 | $response->header( 'X-WP-Total', (int) $query->total ); |
||
| 135 | $response->header( 'X-WP-TotalPages', (int) $query->max_num_pages ); |
||
| 136 | |||
| 137 | /** |
||
| 138 | * Filters the responses for invoices requests. |
||
| 139 | * |
||
| 140 | * |
||
| 141 | * @since 1.0.13 |
||
| 142 | * |
||
| 143 | * |
||
| 144 | * @param arrWP_REST_Response $response Response object. |
||
| 145 | * @param WP_REST_Request $request The request used. |
||
| 146 | * @param array $args Array of args used to retrieve the invoices |
||
| 147 | */ |
||
| 148 | $response = apply_filters( "wpinv_rest_invoices_response", $response, $request, $args ); |
||
| 149 | |||
| 150 | return rest_ensure_response( $response ); |
||
| 151 | |||
| 152 | } |
||
| 153 | |||
| 154 | /** |
||
| 155 | * Get the post, if the ID is valid. |
||
| 156 | * |
||
| 157 | * @since 1.0.13 |
||
| 158 | * |
||
| 159 | * @param int $invoice_id Supplied ID. |
||
| 160 | * @return WPInv_Invoice|WP_Error Invoice object if ID is valid, WP_Error otherwise. |
||
| 161 | */ |
||
| 162 | protected function get_post( $invoice_id ) { |
||
| 177 | |||
| 178 | } |
||
| 179 | |||
| 180 | /** |
||
| 181 | * Checks if a given request has access to read an invoice. |
||
| 182 | * |
||
| 183 | * @since 1.0.13 |
||
| 184 | * |
||
| 185 | * @param WP_REST_Request $request Full details about the request. |
||
| 186 | * @return bool|WP_Error True if the request has read access for the invoice, WP_Error object otherwise. |
||
| 187 | */ |
||
| 188 | public function get_item_permissions_check( $request ) { |
||
| 189 | |||
| 190 | // Retrieve the invoice object. |
||
| 191 | $invoice = $this->get_post( $request['id'] ); |
||
| 192 | |||
| 193 | // Ensure it is valid. |
||
| 194 | if ( is_wp_error( $invoice ) ) { |
||
| 195 | return $invoice; |
||
|
|
|||
| 196 | } |
||
| 197 | |||
| 198 | if ( $invoice ) { |
||
| 199 | return $this->check_read_permission( $invoice ); |
||
| 200 | } |
||
| 201 | |||
| 202 | return true; |
||
| 203 | } |
||
| 204 | |||
| 205 | /** |
||
| 206 | * Checks if an invoice can be read. |
||
| 207 | * |
||
| 208 | * An invoice can be read by site admins and owners of the invoice |
||
| 209 | * |
||
| 210 | * |
||
| 211 | * @since 1.0.13 |
||
| 212 | * |
||
| 213 | * @param WPInv_Invoice $invoice WPInv_Invoice object. |
||
| 214 | * @return bool Whether the post can be read. |
||
| 215 | */ |
||
| 216 | public function check_read_permission( $invoice ) { |
||
| 217 | return wpinv_user_can_view_invoice( $invoice->ID ); |
||
| 218 | } |
||
| 219 | |||
| 220 | /** |
||
| 221 | * Retrieves a single invoice. |
||
| 222 | * |
||
| 223 | * @since 1.0.13 |
||
| 224 | * |
||
| 225 | * @param WP_REST_Request $request Full details about the request. |
||
| 226 | * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. |
||
| 227 | */ |
||
| 228 | public function get_item( $request ) { |
||
| 229 | |||
| 230 | // Fetch the invoice. |
||
| 231 | $invoice = $this->get_post( $request['id'] ); |
||
| 232 | |||
| 233 | // Abort early if it does not exist |
||
| 234 | if ( is_wp_error( $invoice ) ) { |
||
| 235 | return $invoice; |
||
| 236 | } |
||
| 237 | |||
| 238 | // Prepare the response |
||
| 239 | $response = $this->prepare_item_for_response( $invoice, $request ); |
||
| 240 | $response->link_header( 'alternate', esc_url( $invoice->get_view_url() ), array( 'type' => 'text/html' ) ); |
||
| 241 | |||
| 242 | /** |
||
| 243 | * Filters the responses for single invoice requests. |
||
| 244 | * |
||
| 245 | * |
||
| 246 | * @since 1.0.13 |
||
| 247 | * @var WP_HTTP_Response |
||
| 248 | * |
||
| 249 | * @param WP_HTTP_Response $response Response. |
||
| 250 | * @param WP_REST_Request $request The request used. |
||
| 251 | */ |
||
| 252 | $response = apply_filters( "wpinv_rest_get_invoice_response", $response, $request ); |
||
| 253 | |||
| 254 | return rest_ensure_response( $response ); |
||
| 255 | |||
| 256 | } |
||
| 257 | |||
| 258 | /** |
||
| 259 | * Checks if a given request has access to create an invoice. |
||
| 260 | * |
||
| 261 | * @since 1.0.13 |
||
| 262 | * |
||
| 263 | * @param WP_REST_Request $request Full details about the request. |
||
| 264 | * @return true|WP_Error True if the request has access to create items, WP_Error object otherwise. |
||
| 265 | */ |
||
| 266 | public function create_item_permissions_check( $request ) { |
||
| 267 | |||
| 268 | if ( ! empty( $request['id'] ) ) { |
||
| 269 | return new WP_Error( 'rest_invoice_exists', __( 'Cannot create existing invoice.', 'invoicing' ), array( 'status' => 400 ) ); |
||
| 270 | } |
||
| 271 | |||
| 272 | $post_type = get_post_type_object( $this->post_type ); |
||
| 273 | |||
| 274 | if ( ! current_user_can( $post_type->cap->create_posts ) ) { |
||
| 275 | return new WP_Error( |
||
| 276 | 'rest_cannot_create', |
||
| 277 | __( 'Sorry, you are not allowed to create invoices as this user.', 'invoicing' ), |
||
| 278 | array( |
||
| 279 | 'status' => rest_authorization_required_code(), |
||
| 280 | ) |
||
| 281 | ); |
||
| 282 | } |
||
| 283 | |||
| 284 | return true; |
||
| 285 | } |
||
| 286 | |||
| 287 | /** |
||
| 288 | * Creates a single invoice. |
||
| 289 | * |
||
| 290 | * @since 1.0.13 |
||
| 291 | * |
||
| 292 | * @param WP_REST_Request $request Full details about the request. |
||
| 293 | * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. |
||
| 294 | */ |
||
| 295 | public function create_item( $request ) { |
||
| 296 | |||
| 297 | if ( ! empty( $request['id'] ) ) { |
||
| 298 | return new WP_Error( 'rest_invoice_exists', __( 'Cannot create existing invoice.', 'invoicing' ), array( 'status' => 400 ) ); |
||
| 299 | } |
||
| 300 | |||
| 301 | $request->set_param( 'context', 'edit' ); |
||
| 302 | |||
| 303 | // Prepare the updated data. |
||
| 304 | $invoice_data = $this->prepare_item_for_database( $request ); |
||
| 305 | |||
| 306 | if ( is_wp_error( $invoice_data ) ) { |
||
| 307 | return $invoice_data; |
||
| 308 | } |
||
| 309 | |||
| 310 | // Try creating the invoice |
||
| 311 | $invoice = wpinv_insert_invoice( $invoice_data, true ); |
||
| 312 | |||
| 313 | if ( is_wp_error( $invoice ) ) { |
||
| 314 | return $invoice; |
||
| 315 | } |
||
| 316 | |||
| 317 | // Prepare the response |
||
| 318 | $response = $this->prepare_item_for_response( $invoice, $request ); |
||
| 319 | |||
| 320 | /** |
||
| 321 | * Fires after a single invoice is created or updated via the REST API. |
||
| 322 | * |
||
| 323 | * @since 1.0.13 |
||
| 324 | * |
||
| 325 | * @param WPinv_Invoice $invoice Inserted or updated invoice object. |
||
| 326 | * @param WP_REST_Request $request Request object. |
||
| 327 | * @param bool $creating True when creating a post, false when updating. |
||
| 328 | */ |
||
| 329 | do_action( "wpinv_rest_insert_invoice", $invoice, $request, true ); |
||
| 330 | |||
| 331 | /** |
||
| 332 | * Filters the responses for creating single invoice requests. |
||
| 333 | * |
||
| 334 | * |
||
| 335 | * @since 1.0.13 |
||
| 336 | * |
||
| 337 | * |
||
| 338 | * @param array $invoice_data Invoice properties. |
||
| 339 | * @param WP_REST_Request $request The request used. |
||
| 340 | */ |
||
| 341 | $response = apply_filters( "wpinv_rest_create_invoice_response", $response, $request ); |
||
| 342 | |||
| 343 | return rest_ensure_response( $response ); |
||
| 344 | } |
||
| 345 | |||
| 346 | /** |
||
| 347 | * Checks if a given request has access to update an invoice. |
||
| 348 | * |
||
| 349 | * @since 1.0.13 |
||
| 350 | * |
||
| 351 | * @param WP_REST_Request $request Full details about the request. |
||
| 352 | * @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise. |
||
| 353 | */ |
||
| 354 | public function update_item_permissions_check( $request ) { |
||
| 355 | |||
| 356 | // Retrieve the invoice. |
||
| 357 | $invoice = $this->get_post( $request['id'] ); |
||
| 358 | if ( is_wp_error( $invoice ) ) { |
||
| 359 | return $invoice; |
||
| 360 | } |
||
| 361 | |||
| 362 | $post_type = get_post_type_object( $this->post_type ); |
||
| 363 | |||
| 364 | if ( ! current_user_can( $post_type->cap->edit_post, $invoice->ID ) ) { |
||
| 365 | return new WP_Error( |
||
| 366 | 'rest_cannot_edit', |
||
| 367 | __( 'Sorry, you are not allowed to update this invoice.', 'invoicing' ), |
||
| 368 | array( |
||
| 369 | 'status' => rest_authorization_required_code(), |
||
| 370 | ) |
||
| 371 | ); |
||
| 372 | } |
||
| 373 | |||
| 374 | return true; |
||
| 375 | } |
||
| 376 | |||
| 377 | /** |
||
| 378 | * Updates a single invoice. |
||
| 379 | * |
||
| 380 | * @since 1.0.13 |
||
| 381 | * |
||
| 382 | * @param WP_REST_Request $request Full details about the request. |
||
| 383 | * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. |
||
| 384 | */ |
||
| 385 | public function update_item( $request ) { |
||
| 386 | |||
| 387 | // Ensure the invoice exists. |
||
| 388 | $valid_check = $this->get_post( $request['id'] ); |
||
| 389 | |||
| 390 | // Abort early if it does not exist |
||
| 391 | if ( is_wp_error( $valid_check ) ) { |
||
| 392 | return $valid_check; |
||
| 393 | } |
||
| 394 | |||
| 395 | $request->set_param( 'context', 'edit' ); |
||
| 396 | |||
| 397 | // Prepare the updated data. |
||
| 398 | $data_to_update = $this->prepare_item_for_database( $request ); |
||
| 399 | |||
| 400 | if ( is_wp_error( $data_to_update ) ) { |
||
| 401 | return $data_to_update; |
||
| 402 | } |
||
| 403 | |||
| 404 | // Abort if no invoice data is provided |
||
| 405 | if( empty( $data_to_update ) ) { |
||
| 406 | return new WP_Error( 'missing_data', __( 'An update request cannot be empty.', 'invoicing' ) ); |
||
| 407 | } |
||
| 408 | |||
| 409 | // Include the invoice ID |
||
| 410 | $data_to_update['ID'] = $request['id']; |
||
| 411 | |||
| 412 | // Update the invoice |
||
| 413 | $updated_invoice = wpinv_update_invoice( $data_to_update, true ); |
||
| 414 | |||
| 415 | // Incase the update operation failed... |
||
| 416 | if ( is_wp_error( $updated_invoice ) ) { |
||
| 417 | return $updated_invoice; |
||
| 418 | } |
||
| 419 | |||
| 420 | // Prepare the response |
||
| 421 | $response = $this->prepare_item_for_response( $updated_invoice, $request ); |
||
| 422 | |||
| 423 | /** This action is documented in includes/class-wpinv-rest-invoice-controller.php */ |
||
| 424 | do_action( "wpinv_rest_insert_invoice", $updated_invoice, $request, false ); |
||
| 425 | |||
| 426 | /** |
||
| 427 | * Filters the responses for updating single invoice requests. |
||
| 428 | * |
||
| 429 | * |
||
| 430 | * @since 1.0.13 |
||
| 431 | * |
||
| 432 | * |
||
| 433 | * @param array $invoice_data Invoice properties. |
||
| 434 | * @param WP_REST_Request $request The request used. |
||
| 435 | */ |
||
| 436 | $response = apply_filters( "wpinv_rest_update_invoice_response", $response, $request ); |
||
| 437 | |||
| 438 | return rest_ensure_response( $response ); |
||
| 439 | } |
||
| 440 | |||
| 441 | /** |
||
| 442 | * Checks if a given request has access to delete an invoice. |
||
| 443 | * |
||
| 444 | * @since 1.0.13 |
||
| 445 | * |
||
| 446 | * @param WP_REST_Request $request Full details about the request. |
||
| 447 | * @return true|WP_Error True if the request has access to delete the invoice, WP_Error object otherwise. |
||
| 448 | */ |
||
| 449 | public function delete_item_permissions_check( $request ) { |
||
| 450 | |||
| 451 | // Retrieve the invoice. |
||
| 452 | $invoice = $this->get_post( $request['id'] ); |
||
| 453 | if ( is_wp_error( $invoice ) ) { |
||
| 454 | return $invoice; |
||
| 455 | } |
||
| 456 | |||
| 457 | // Ensure the current user can delete invoices |
||
| 458 | if ( wpinv_current_user_can_manage_invoicing() || current_user_can( 'delete_invoices', $request['id'] ) ) { |
||
| 459 | return new WP_Error( |
||
| 460 | 'rest_cannot_delete', |
||
| 461 | __( 'Sorry, you are not allowed to delete this invoice.', 'invoicing' ), |
||
| 462 | array( |
||
| 463 | 'status' => rest_authorization_required_code(), |
||
| 464 | ) |
||
| 465 | ); |
||
| 466 | } |
||
| 467 | |||
| 468 | return true; |
||
| 469 | } |
||
| 470 | |||
| 471 | /** |
||
| 472 | * Deletes a single invoice. |
||
| 473 | * |
||
| 474 | * @since 1.0.13 |
||
| 475 | * |
||
| 476 | * @param WP_REST_Request $request Full details about the request. |
||
| 477 | * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. |
||
| 478 | */ |
||
| 479 | public function delete_item( $request ) { |
||
| 480 | |||
| 481 | // Retrieve the invoice. |
||
| 482 | $invoice = $this->get_post( $request['id'] ); |
||
| 483 | if ( is_wp_error( $invoice ) ) { |
||
| 484 | return $invoice; |
||
| 485 | } |
||
| 486 | |||
| 487 | $request->set_param( 'context', 'edit' ); |
||
| 488 | |||
| 489 | // Prepare the invoice id |
||
| 490 | $id = $invoice->ID; |
||
| 491 | |||
| 492 | // Prepare the response |
||
| 493 | $response = $this->prepare_item_for_response( $invoice, $request ); |
||
| 494 | |||
| 495 | // Check if the user wants to bypass the trash... |
||
| 496 | $force_delete = (bool) $request['force']; |
||
| 497 | |||
| 498 | // Try deleting the invoice. |
||
| 499 | $deleted = wp_delete_post( $id, $force_delete ); |
||
| 500 | |||
| 501 | // Abort early if we can't delete the invoice. |
||
| 502 | if ( ! $deleted ) { |
||
| 503 | return new WP_Error( 'rest_cannot_delete', __( 'The invoice cannot be deleted.', 'invoicing' ), array( 'status' => 500 ) ); |
||
| 504 | } |
||
| 505 | |||
| 506 | /** |
||
| 507 | * Fires immediately after a single invoice is deleted or trashed via the REST API. |
||
| 508 | * |
||
| 509 | * |
||
| 510 | * @since 1.0.13 |
||
| 511 | * |
||
| 512 | * @param WPInv_Invoice $invoice The deleted or trashed invoice. |
||
| 513 | * @param WP_REST_Request $request The request sent to the API. |
||
| 514 | */ |
||
| 515 | do_action( "wpinv_rest_delete_invoice", $invoice, $request ); |
||
| 516 | |||
| 517 | return $response; |
||
| 518 | |||
| 519 | } |
||
| 520 | |||
| 521 | |||
| 522 | /** |
||
| 523 | * Retrieves the query params for the invoices collection. |
||
| 524 | * |
||
| 525 | * @since 1.0.13 |
||
| 526 | * |
||
| 527 | * @return array Collection parameters. |
||
| 528 | */ |
||
| 529 | public function get_collection_params() { |
||
| 530 | |||
| 531 | $query_params = array( |
||
| 532 | |||
| 533 | // Invoice status. |
||
| 534 | 'status' => array( |
||
| 535 | 'default' => 'publish', |
||
| 536 | 'description' => __( 'Limit result set to invoices assigned one or more statuses.', 'invoicing' ), |
||
| 537 | 'type' => 'array', |
||
| 538 | 'items' => array( |
||
| 539 | 'enum' => array_keys( wpinv_get_invoice_statuses( true, true ) ), |
||
| 540 | 'type' => 'string', |
||
| 541 | ), |
||
| 542 | 'sanitize_callback' => array( $this, 'sanitize_post_statuses' ), |
||
| 543 | ), |
||
| 544 | |||
| 545 | // User. |
||
| 546 | 'user' => array( |
||
| 547 | 'description' => __( 'Limit result set to invoices for a specif user.', 'invoicing' ), |
||
| 548 | 'type' => 'integer', |
||
| 549 | ), |
||
| 550 | |||
| 551 | // Number of results per page |
||
| 552 | 'limit' => array( |
||
| 553 | 'description' => __( 'Number of invoices to fetch.', 'invoicing' ), |
||
| 554 | 'type' => 'integer', |
||
| 555 | 'default' => (int) get_option( 'posts_per_page' ), |
||
| 556 | ), |
||
| 557 | |||
| 558 | // Pagination |
||
| 559 | 'page' => array( |
||
| 560 | 'description' => __( 'Current page to fetch.', 'invoicing' ), |
||
| 561 | 'type' => 'integer', |
||
| 562 | 'default' => 1, |
||
| 563 | ), |
||
| 564 | |||
| 565 | // Exclude certain invoices |
||
| 566 | 'exclude' => array( |
||
| 567 | 'description' => __( 'Ensure result set excludes specific IDs.', 'invoicing' ), |
||
| 568 | 'type' => 'array', |
||
| 569 | 'items' => array( |
||
| 570 | 'type' => 'integer', |
||
| 571 | ), |
||
| 572 | 'default' => array(), |
||
| 573 | ), |
||
| 574 | |||
| 575 | // Order invoices by |
||
| 576 | 'orderby' => array( |
||
| 577 | 'description' => __( 'Sort invoices by object attribute.', 'invoicing' ), |
||
| 578 | 'type' => 'string', |
||
| 579 | 'default' => 'date', |
||
| 580 | 'enum' => array( |
||
| 581 | 'author', |
||
| 582 | 'date', |
||
| 583 | 'id', |
||
| 584 | 'modified', |
||
| 585 | 'title' |
||
| 586 | ), |
||
| 587 | ), |
||
| 588 | |||
| 589 | // How to order |
||
| 590 | 'order' => array( |
||
| 591 | 'description' => __( 'Order sort attribute ascending or descending.', 'invoicing' ), |
||
| 592 | 'type' => 'string', |
||
| 593 | 'default' => 'DESC', |
||
| 594 | 'enum' => array( 'ASC', 'DESC' ), |
||
| 595 | ), |
||
| 596 | ); |
||
| 597 | |||
| 598 | /** |
||
| 599 | * Filter collection parameters for the invoices controller. |
||
| 600 | * |
||
| 601 | * |
||
| 602 | * @since 1.0.13 |
||
| 603 | * |
||
| 604 | * @param array $query_params JSON Schema-formatted collection parameters. |
||
| 605 | */ |
||
| 606 | return apply_filters( "wpinv_rest_invoices_collection_params", $query_params ); |
||
| 607 | } |
||
| 608 | |||
| 609 | /** |
||
| 610 | * Checks if a given post type can be viewed or managed. |
||
| 611 | * |
||
| 612 | * @since 1.0.13 |
||
| 613 | * |
||
| 614 | * @param object|string $post_type Post type name or object. |
||
| 615 | * @return bool Whether the post type is allowed in REST. |
||
| 616 | */ |
||
| 617 | protected function check_is_post_type_allowed( $post_type ) { |
||
| 618 | return true; |
||
| 619 | } |
||
| 620 | |||
| 621 | /** |
||
| 622 | * Prepares a single invoice for create or update. |
||
| 623 | * |
||
| 624 | * @since 1.0.13 |
||
| 625 | * |
||
| 626 | * @param WP_REST_Request $request Request object. |
||
| 627 | * @return array|WP_Error Invoice Properties or WP_Error. |
||
| 628 | */ |
||
| 629 | protected function prepare_item_for_database( $request ) { |
||
| 630 | $prepared_invoice = new stdClass(); |
||
| 631 | |||
| 632 | // Post ID. |
||
| 633 | if ( isset( $request['id'] ) ) { |
||
| 634 | $existing_invoice = $this->get_post( $request['id'] ); |
||
| 635 | if ( is_wp_error( $existing_invoice ) ) { |
||
| 636 | return $existing_invoice; |
||
| 637 | } |
||
| 638 | |||
| 639 | $prepared_invoice->ID = $existing_invoice->ID; |
||
| 640 | $prepared_invoice->invoice_id = $existing_invoice->ID; |
||
| 641 | } |
||
| 642 | |||
| 643 | $schema = $this->get_item_schema(); |
||
| 644 | |||
| 645 | // Invoice owner. |
||
| 646 | if ( ! empty( $schema['properties']['user_id'] ) && isset( $request['user_id'] ) ) { |
||
| 647 | $prepared_invoice->user_id = (int) $request['user_id']; |
||
| 648 | } |
||
| 649 | |||
| 650 | // Cart details. |
||
| 651 | if ( ! empty( $schema['properties']['cart_details'] ) && isset( $request['cart_details'] ) ) { |
||
| 652 | $prepared_invoice->cart_details = (array) $request['cart_details']; |
||
| 653 | } |
||
| 654 | |||
| 655 | // Invoice status. |
||
| 656 | if ( ! empty( $schema['properties']['status'] ) && isset( $request['status'] ) ) { |
||
| 657 | |||
| 658 | if ( in_array( $request['status'], array_keys( wpinv_get_invoice_statuses( true, true ) ), true ) ) { |
||
| 659 | $prepared_invoice->status = $request['status']; |
||
| 660 | } |
||
| 661 | |||
| 662 | } |
||
| 663 | |||
| 664 | // User info |
||
| 665 | if ( ! empty( $schema['properties']['user_info'] ) && isset( $request['user_info'] ) ) { |
||
| 666 | $prepared_invoice->user_info = array(); |
||
| 667 | $user_info = (array) $request['user_info']; |
||
| 668 | |||
| 669 | foreach( $user_info as $prop => $value ) { |
||
| 670 | |||
| 671 | if ( ! empty( $schema['properties']['user_info']['properties'][$prop] ) ) { |
||
| 672 | |||
| 673 | $prepared_invoice->user_info[$prop] = $value; |
||
| 674 | |||
| 675 | } |
||
| 676 | |||
| 677 | } |
||
| 678 | |||
| 679 | } |
||
| 680 | |||
| 681 | // IP |
||
| 682 | if ( ! empty( $schema['properties']['ip'] ) && isset( $request['ip'] ) ) { |
||
| 683 | $prepared_invoice->ip = $request['ip']; |
||
| 684 | } |
||
| 685 | |||
| 686 | // Payment details |
||
| 687 | $prepared_invoice->payment_details = array(); |
||
| 688 | |||
| 689 | if ( ! empty( $schema['properties']['gateway'] ) && isset( $request['gateway'] ) ) { |
||
| 690 | $prepared_invoice->payment_details['gateway'] = $request['gateway']; |
||
| 691 | } |
||
| 692 | |||
| 693 | if ( ! empty( $schema['properties']['gateway_title'] ) && isset( $request['gateway_title'] ) ) { |
||
| 694 | $prepared_invoice->payment_details['gateway_title'] = $request['gateway_title']; |
||
| 695 | } |
||
| 696 | |||
| 697 | if ( ! empty( $schema['properties']['currency'] ) && isset( $request['currency'] ) ) { |
||
| 698 | $prepared_invoice->payment_details['currency'] = $request['currency']; |
||
| 699 | } |
||
| 700 | |||
| 701 | if ( ! empty( $schema['properties']['transaction_id'] ) && isset( $request['transaction_id'] ) ) { |
||
| 702 | $prepared_invoice->payment_details['transaction_id'] = $request['transaction_id']; |
||
| 703 | } |
||
| 704 | |||
| 705 | // Dates |
||
| 706 | if ( ! empty( $schema['properties']['date'] ) && isset( $request['date'] ) ) { |
||
| 707 | $post_date = rest_get_date_with_gmt( $request['date'] ); |
||
| 708 | |||
| 709 | if ( ! empty( $post_date ) ) { |
||
| 710 | $prepared_invoice->post_date = $post_date[0]; |
||
| 711 | } |
||
| 712 | |||
| 713 | } |
||
| 714 | |||
| 715 | if ( ! empty( $schema['properties']['due_date'] ) && isset( $request['due_date'] ) ) { |
||
| 716 | $due_date = rest_get_date_with_gmt( $request['due_date'] ); |
||
| 717 | |||
| 718 | if ( ! empty( $due_date ) ) { |
||
| 719 | $prepared_invoice->due_date = $due_date[0]; |
||
| 720 | } |
||
| 721 | |||
| 722 | } |
||
| 723 | |||
| 724 | $invoice_data = (array) wp_unslash( $prepared_invoice ); |
||
| 725 | |||
| 726 | /** |
||
| 727 | * Filters an invoice before it is inserted via the REST API. |
||
| 728 | * |
||
| 729 | * @since 1.0.13 |
||
| 730 | * |
||
| 731 | * @param array $invoice_data An array of invoice data |
||
| 732 | * @param WP_REST_Request $request Request object. |
||
| 733 | */ |
||
| 734 | return apply_filters( "wpinv_rest_pre_insert_invoice", $invoice_data, $request ); |
||
| 735 | |||
| 736 | } |
||
| 737 | |||
| 738 | /** |
||
| 739 | * Prepares a single invoice output for response. |
||
| 740 | * |
||
| 741 | * @since 1.0.13 |
||
| 742 | * |
||
| 743 | * @param WPInv_Invoice $invoice Invoice object. |
||
| 744 | * @param WP_REST_Request $request Request object. |
||
| 745 | * @return WP_REST_Response Response object. |
||
| 746 | */ |
||
| 747 | public function prepare_item_for_response( $invoice, $request ) { |
||
| 748 | |||
| 749 | $GLOBALS['post'] = get_post( $invoice->ID ); |
||
| 750 | |||
| 751 | setup_postdata( $invoice->ID ); |
||
| 752 | |||
| 753 | // Fetch the fields to include in this response. |
||
| 754 | $fields = $this->get_fields_for_response( $request ); |
||
| 755 | |||
| 756 | // Base fields for every invoice. |
||
| 757 | $data = array(); |
||
| 758 | |||
| 759 | // Set up ID |
||
| 760 | if ( rest_is_field_included( 'id', $fields ) ) { |
||
| 761 | $data['id'] = $invoice->ID; |
||
| 762 | } |
||
| 763 | |||
| 764 | |||
| 765 | // Basic properties |
||
| 766 | $invoice_properties = array( |
||
| 767 | 'title', 'email', 'ip', |
||
| 768 | 'key', 'number', 'transaction_id', 'mode', |
||
| 769 | 'gateway', 'gateway_title', |
||
| 770 | 'total', 'discount', 'discount_code', |
||
| 771 | 'tax', 'fees_total', 'subtotal', 'currency', |
||
| 772 | 'status', 'status_nicename', 'post_type' |
||
| 773 | ); |
||
| 774 | |||
| 775 | foreach( $invoice_properties as $property ) { |
||
| 776 | |||
| 777 | if ( rest_is_field_included( $property, $fields ) ) { |
||
| 778 | $data[$property] = $invoice->get( $property ); |
||
| 779 | } |
||
| 780 | |||
| 781 | } |
||
| 782 | |||
| 783 | // Cart details |
||
| 784 | if ( rest_is_field_included( 'cart_details', $fields ) ) { |
||
| 785 | $data['cart_details'] = $invoice->get( 'cart_details' ); |
||
| 786 | } |
||
| 787 | |||
| 788 | //Dates |
||
| 789 | $invoice_properties = array( 'date', 'due_date', 'completed_date' ); |
||
| 790 | |||
| 791 | foreach( $invoice_properties as $property ) { |
||
| 792 | |||
| 793 | if ( rest_is_field_included( $property, $fields ) ) { |
||
| 794 | $data[$property] = $this->prepare_date_response( '0000-00-00 00:00:00', $invoice->get( $property ) ); |
||
| 795 | } |
||
| 796 | |||
| 797 | } |
||
| 798 | |||
| 799 | // User id |
||
| 800 | if ( rest_is_field_included( 'user_id', $fields ) ) { |
||
| 801 | $data['user_id'] = (int) $invoice->get( 'user_id' ); |
||
| 802 | } |
||
| 803 | |||
| 804 | // User info |
||
| 805 | $user_info = array( 'first_name', 'last_name', 'company', 'vat_number', 'vat_rate', 'address', 'city', 'country', 'state', 'zip', 'phone' ); |
||
| 806 | |||
| 807 | foreach( $user_info as $property ) { |
||
| 808 | |||
| 809 | if ( rest_is_field_included( "user_info.$property", $fields ) ) { |
||
| 810 | $data['user_info'][$property] = $invoice->get( $property ); |
||
| 811 | } |
||
| 812 | |||
| 813 | } |
||
| 814 | |||
| 815 | // Slug |
||
| 816 | if ( rest_is_field_included( 'slug', $fields ) ) { |
||
| 817 | $data['slug'] = $invoice->get( 'post_name' ); |
||
| 818 | } |
||
| 819 | |||
| 820 | // View invoice link |
||
| 821 | if ( rest_is_field_included( 'link', $fields ) ) { |
||
| 822 | $data['link'] = esc_url( $invoice->get_view_url() ); |
||
| 823 | } |
||
| 824 | |||
| 825 | |||
| 826 | $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; |
||
| 827 | $data = $this->add_additional_fields_to_object( $data, $request ); |
||
| 828 | $data = $this->filter_response_by_context( $data, $context ); |
||
| 829 | |||
| 830 | // Wrap the data in a response object. |
||
| 831 | $response = rest_ensure_response( $data ); |
||
| 832 | |||
| 833 | $links = $this->prepare_links( $invoice ); |
||
| 834 | $response->add_links( $links ); |
||
| 835 | |||
| 836 | if ( ! empty( $links['self']['href'] ) ) { |
||
| 837 | $actions = $this->get_available_actions( $invoice, $request ); |
||
| 838 | |||
| 839 | $self = $links['self']['href']; |
||
| 840 | |||
| 841 | foreach ( $actions as $rel ) { |
||
| 842 | $response->add_link( $rel, $self ); |
||
| 843 | } |
||
| 844 | } |
||
| 845 | |||
| 846 | /** |
||
| 847 | * Filters the invoice data for a response. |
||
| 848 | * |
||
| 849 | * @since 1.0.13 |
||
| 850 | * |
||
| 851 | * @param WP_REST_Response $response The response object. |
||
| 852 | * @param WPInv_Invoice $invoice The invoice object. |
||
| 853 | * @param WP_REST_Request $request Request object. |
||
| 854 | */ |
||
| 855 | return apply_filters( "wpinv_rest_prepare_invoice", $response, $invoice, $request ); |
||
| 856 | } |
||
| 857 | |||
| 858 | /** |
||
| 859 | * Gets an array of fields to be included on the response. |
||
| 860 | * |
||
| 861 | * Included fields are based on item schema and `_fields=` request argument. |
||
| 862 | * |
||
| 863 | * @since 1.0.13 |
||
| 864 | * |
||
| 865 | * @param WP_REST_Request $request Full details about the request. |
||
| 866 | * @return array Fields to be included in the response. |
||
| 867 | */ |
||
| 868 | public function get_fields_for_response( $request ) { |
||
| 869 | $schema = $this->get_item_schema(); |
||
| 870 | $properties = isset( $schema['properties'] ) ? $schema['properties'] : array(); |
||
| 871 | |||
| 872 | $additional_fields = $this->get_additional_fields(); |
||
| 873 | foreach ( $additional_fields as $field_name => $field_options ) { |
||
| 874 | // For back-compat, include any field with an empty schema |
||
| 875 | // because it won't be present in $this->get_item_schema(). |
||
| 876 | if ( is_null( $field_options['schema'] ) ) { |
||
| 877 | $properties[ $field_name ] = $field_options; |
||
| 878 | } |
||
| 879 | } |
||
| 880 | |||
| 881 | // Exclude fields that specify a different context than the request context. |
||
| 882 | $context = $request['context']; |
||
| 883 | if ( $context ) { |
||
| 884 | foreach ( $properties as $name => $options ) { |
||
| 885 | if ( ! empty( $options['context'] ) && ! in_array( $context, $options['context'], true ) ) { |
||
| 886 | unset( $properties[ $name ] ); |
||
| 887 | } |
||
| 888 | } |
||
| 889 | } |
||
| 890 | |||
| 891 | $fields = array_keys( $properties ); |
||
| 892 | |||
| 893 | if ( ! isset( $request['_fields'] ) ) { |
||
| 894 | return $fields; |
||
| 895 | } |
||
| 896 | $requested_fields = wpinv_parse_list( $request['_fields'] ); |
||
| 897 | if ( 0 === count( $requested_fields ) ) { |
||
| 898 | return $fields; |
||
| 899 | } |
||
| 900 | // Trim off outside whitespace from the comma delimited list. |
||
| 901 | $requested_fields = array_map( 'trim', $requested_fields ); |
||
| 902 | // Always persist 'id', because it can be needed for add_additional_fields_to_object(). |
||
| 903 | if ( in_array( 'id', $fields, true ) ) { |
||
| 904 | $requested_fields[] = 'id'; |
||
| 905 | } |
||
| 906 | // Return the list of all requested fields which appear in the schema. |
||
| 907 | return array_reduce( |
||
| 908 | $requested_fields, |
||
| 909 | function( $response_fields, $field ) use ( $fields ) { |
||
| 910 | if ( in_array( $field, $fields, true ) ) { |
||
| 911 | $response_fields[] = $field; |
||
| 912 | return $response_fields; |
||
| 913 | } |
||
| 914 | // Check for nested fields if $field is not a direct match. |
||
| 915 | $nested_fields = explode( '.', $field ); |
||
| 916 | // A nested field is included so long as its top-level property is |
||
| 917 | // present in the schema. |
||
| 918 | if ( in_array( $nested_fields[0], $fields, true ) ) { |
||
| 919 | $response_fields[] = $field; |
||
| 920 | } |
||
| 921 | return $response_fields; |
||
| 922 | }, |
||
| 923 | array() |
||
| 924 | ); |
||
| 925 | } |
||
| 926 | |||
| 927 | /** |
||
| 928 | * Retrieves the invoice's schema, conforming to JSON Schema. |
||
| 929 | * |
||
| 930 | * @since 1.0.13 |
||
| 931 | * |
||
| 932 | * @return array Invoice schema data. |
||
| 933 | */ |
||
| 934 | public function get_item_schema() { |
||
| 1233 | } |
||
| 1234 | |||
| 1235 | /** |
||
| 1236 | * Retrieve Link Description Objects that should be added to the Schema for the invoices collection. |
||
| 1237 | * |
||
| 1238 | * @since 1.0.13 |
||
| 1239 | * |
||
| 1240 | * @return array |
||
| 1241 | */ |
||
| 1242 | protected function get_schema_links() { |
||
| 1278 | } |
||
| 1279 | |||
| 1280 | /** |
||
| 1281 | * Prepares links for the request. |
||
| 1282 | * |
||
| 1283 | * @since 1.0.13 |
||
| 1284 | * |
||
| 1285 | * @param WPInv_Invoice $invoice Invoice Object. |
||
| 1286 | * @return array Links for the given invoice. |
||
| 1287 | */ |
||
| 1288 | protected function prepare_links( $invoice ) { |
||
| 1320 | |||
| 1321 | } |
||
| 1322 | |||
| 1323 | /** |
||
| 1324 | * Get the link relations available for the post and current user. |
||
| 1325 | * |
||
| 1326 | * @since 1.0.13 |
||
| 1327 | * |
||
| 1328 | * @param WPInv_Invoice $invoice Invoice object. |
||
| 1329 | * @param WP_REST_Request $request Request object. |
||
| 1330 | * @return array List of link relations. |
||
| 1331 | */ |
||
| 1332 | protected function get_available_actions( $invoice, $request ) { |
||
| 1363 | } |
||
| 1364 | |||
| 1365 | /** |
||
| 1366 | * Sanitizes and validates the list of post statuses. |
||
| 1367 | * |
||
| 1368 | * @since 1.0.13 |
||
| 1369 | * |
||
| 1370 | * @param string|array $statuses One or more post statuses. |
||
| 1371 | * @param WP_REST_Request $request Full details about the request. |
||
| 1372 | * @param string $parameter Additional parameter to pass to validation. |
||
| 1373 | * @return array|WP_Error A list of valid statuses, otherwise WP_Error object. |
||
| 1374 | */ |
||
| 1375 | public function sanitize_post_statuses( $statuses, $request, $parameter ) { |
||
| 1380 | |||
| 1381 | } |
||
| 1382 | |||
| 1383 | } |