← All changes
|
includes/rest-api/controller/version2/class-mainwp-rest-controller.php
+245
-178
6.0.11
→
6.2.2
View file →
| @@ -474,8 +474,166 @@ | ||
| 474 | 474 | return $site; |
| 475 | 475 | } |
| 476 | 476 | |
| 477 | 477 | /** |
| 478 | + * Get the args a batch create item is validated against. | |
| 479 | + * | |
| 480 | + * Mirrors the args the controller's own create route registers. | |
| 481 | + * | |
| 482 | + * @return array | |
| 483 | + */ | |
| 484 | + public function get_batch_create_args() { | |
| 485 | + return $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ); | |
| 486 | + } | |
| 487 | + | |
| 488 | + /** | |
| 489 | + * Get the args a batch update item is validated against. | |
| 490 | + * | |
| 491 | + * Mirrors the args the controller's own edit route registers. | |
| 492 | + * | |
| 493 | + * @return array | |
| 494 | + */ | |
| 495 | + public function get_batch_update_args() { | |
| 496 | + $args = $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ); | |
| 497 | + $args['id'] = $this->get_batch_item_id_arg(); | |
| 498 | + return $args; | |
| 499 | + } | |
| 500 | + | |
| 501 | + /** | |
| 502 | + * Get the args a batch delete item is validated against. | |
| 503 | + * | |
| 504 | + * @return array | |
| 505 | + */ | |
| 506 | + public function get_batch_delete_args() { | |
| 507 | + return array( | |
| 508 | + 'id' => $this->get_batch_item_id_arg(), | |
| 509 | + 'force' => array( | |
| 510 | + 'type' => 'boolean', | |
| 511 | + 'description' => __( 'Force deletion.', 'mainwp' ), | |
| 512 | + 'sanitize_callback' => 'rest_parse_request_arg', | |
| 513 | + 'validate_callback' => 'rest_validate_request_arg', | |
| 514 | + ), | |
| 515 | + ); | |
| 516 | + } | |
| 517 | + | |
| 518 | + /** | |
| 519 | + * Get the id arg a batch update or delete item is validated against. | |
| 520 | + * | |
| 521 | + * The sites item schema registers id with a wp_parse_id_list sanitizer for the | |
| 522 | + * collection filter, which would turn a batch item's scalar id into an array | |
| 523 | + * before get_site_item() reads it, so batch items get their own scalar id arg. | |
| 524 | + * | |
| 525 | + * @return array | |
| 526 | + */ | |
| 527 | + protected function get_batch_item_id_arg() { | |
| 528 | + return array( | |
| 529 | + 'type' => 'integer', | |
| 530 | + 'required' => true, | |
| 531 | + 'minimum' => 1, | |
| 532 | + 'description' => __( 'Item ID.', 'mainwp' ), | |
| 533 | + 'sanitize_callback' => 'rest_parse_request_arg', | |
| 534 | + 'validate_callback' => 'rest_validate_request_arg', | |
| 535 | + ); | |
| 536 | + } | |
| 537 | + | |
| 538 | + /** | |
| 539 | + * Build the internal request for one batch item addressed by id. | |
| 540 | + * | |
| 541 | + * The raw value goes in uncast and is validated against the batch id arg: an | |
| 542 | + * (int) cast first would turn true, 5.9 or ["x"] into a valid-looking id and | |
| 543 | + * act on a different item. | |
| 544 | + * | |
| 545 | + * @param string $route Batch route the parent request came in on. | |
| 546 | + * @param mixed $id Raw id from the batch payload. | |
| 547 | + * @param array $query Extra query params (e.g. force for delete). | |
| 548 | + * @param array $args Args to validate against; defaults to the id arg alone. | |
| 549 | + * @return WP_REST_Request|WP_Error | |
| 550 | + */ | |
| 551 | + protected function prepare_batch_id_request( $route, $id, $query = array(), $args = array() ) { | |
| 552 | + if ( empty( $args ) ) { | |
| 553 | + $args = array( 'id' => $this->get_batch_item_id_arg() ); | |
| 554 | + } | |
| 555 | + $_item = new WP_REST_Request( 'DELETE', $route ); | |
| 556 | + $_item->set_query_params( array_merge( array( 'id' => $id ), $query ) ); | |
| 557 | + // Core only validates the registered args of a dispatched request, so a | |
| 558 | + // request assembled here has to run those checks itself. | |
| 559 | + $_item->set_attributes( array( 'args' => $args ) ); | |
| 560 | + $valid = $_item->has_valid_params(); | |
| 561 | + if ( ! is_wp_error( $valid ) ) { | |
| 562 | + $valid = $_item->sanitize_params(); | |
| 563 | + } | |
| 564 | + return is_wp_error( $valid ) ? $valid : $_item; | |
| 565 | + } | |
| 566 | + | |
| 567 | + /** | |
| 568 | + * Build the internal request for one batch update item. | |
| 569 | + * | |
| 570 | + * An update item has to carry its fields in an object: a scalar cannot be a body, | |
| 571 | + * and core only validates the registered args of a dispatched request, so a | |
| 572 | + * request assembled here has to run those checks itself. | |
| 573 | + * | |
| 574 | + * @param string $route Batch route the parent request came in on. | |
| 575 | + * @param mixed $item Raw item from the batch payload. | |
| 576 | + * @param array $args Args to validate against. | |
| 577 | + * @return WP_REST_Request|WP_Error | |
| 578 | + */ | |
| 579 | + protected function prepare_batch_update_request( $route, $item, $args ) { | |
| 580 | + if ( ! is_array( $item ) ) { | |
| 581 | + return new WP_Error( 'rest_invalid_param', __( 'Batch update items must be objects carrying an item ID.', 'mainwp' ), array( 'status' => 400 ) ); | |
| 582 | + } | |
| 583 | + $_item = new WP_REST_Request( 'PUT', $route ); | |
| 584 | + $_item->set_body_params( $item ); | |
| 585 | + $_item->set_attributes( array( 'args' => $args ) ); | |
| 586 | + $valid = $_item->has_valid_params(); | |
| 587 | + if ( ! is_wp_error( $valid ) ) { | |
| 588 | + $valid = $_item->sanitize_params(); | |
| 589 | + } | |
| 590 | + return is_wp_error( $valid ) ? $valid : $_item; | |
| 591 | + } | |
| 592 | + | |
| 593 | + /** | |
| 594 | + * Build the internal request for one batch create item. | |
| 595 | + * | |
| 596 | + * A create item has to carry its fields in an object: no create arg is required, so a | |
| 597 | + * scalar or a JSON list would pass validation and then insert a row built out of the | |
| 598 | + * schema defaults alone. An empty array stays allowed because json_decode() reports | |
| 599 | + * {} and [] as the same empty PHP array. Core only validates the registered args of a | |
| 600 | + * dispatched request, so a request assembled here has to run those checks itself. | |
| 601 | + * | |
| 602 | + * @param string $route Batch route the parent request came in on. | |
| 603 | + * @param mixed $item Raw item from the batch payload. | |
| 604 | + * @param array $args Args to validate against. | |
| 605 | + * @param array $defaults Schema defaults the item falls back on. | |
| 606 | + * @param array $query Query params of the batch request. | |
| 607 | + * @return WP_REST_Request|WP_Error | |
| 608 | + */ | |
| 609 | + protected function prepare_batch_create_request( $route, $item, $args, $defaults, $query ) { | |
| 610 | + if ( ! is_array( $item ) || ( ! empty( $item ) && wp_is_numeric_array( $item ) ) ) { | |
| 611 | + return new WP_Error( 'rest_invalid_param', __( 'Batch create items must be objects.', 'mainwp' ), array( 'status' => 400 ) ); | |
| 612 | + } | |
| 613 | + $_item = new WP_REST_Request( 'POST', $route ); | |
| 614 | + $_item->set_default_params( $defaults ); | |
| 615 | + $_item->set_body_params( $item ); | |
| 616 | + $_item->set_query_params( $query ); | |
| 617 | + $_item->set_attributes( array( 'args' => $args ) ); | |
| 618 | + $valid = $_item->has_valid_params(); | |
| 619 | + if ( ! is_wp_error( $valid ) ) { | |
| 620 | + $valid = $_item->sanitize_params(); | |
| 621 | + } | |
| 622 | + return is_wp_error( $valid ) ? $valid : $_item; | |
| 623 | + } | |
| 624 | + | |
| 625 | + /** | |
| 626 | + * Id to report for a batch item that failed before it could be resolved. | |
| 627 | + * | |
| 628 | + * @param mixed $id Raw id from the batch payload. | |
| 629 | + * @return int | |
| 630 | + */ | |
| 631 | + protected function batch_error_id( $id ) { | |
| 632 | + return is_numeric( $id ) ? (int) $id : 0; | |
| 633 | + } | |
| 634 | + | |
| 635 | + /** | |
| 478 | 636 | * Bulk create, update and delete items. |
| 479 | 637 | * |
| 480 | 638 | * @param WP_REST_Request $request Full details about the request. |
| 481 | 639 | * @return array Of WP_Error or WP_REST_Response. |
| @@ -500,10 +658,8 @@ | ||
| 500 | 658 | } |
| 501 | 659 | |
| 502 | 660 | if ( ! empty( $items['create'] ) ) { |
| 503 | 661 | foreach ( $items['create'] as $item ) { |
| 504 | - $_item = new WP_REST_Request( 'POST', $request->get_route() ); | |
| 505 | - | |
| 506 | 662 | // Default parameters. |
| 507 | 663 | $defaults = array(); |
| 508 | 664 | $schema = $this->get_public_item_schema(); |
| 509 | 665 | foreach ( $schema['properties'] as $arg => $options ) { |
| @@ -510,18 +666,12 @@ | ||
| 510 | 666 | if ( isset( $options['default'] ) ) { |
| 511 | 667 | $defaults[ $arg ] = $options['default']; |
| 512 | 668 | } |
| 513 | 669 | } |
| 514 | - $_item->set_default_params( $defaults ); | |
| 515 | 670 | |
| 516 | - // Set request parameters. | |
| 517 | - $_item->set_body_params( $item ); | |
| 671 | + $_item = $this->prepare_batch_create_request( $request->get_route(), $item, $this->get_batch_create_args(), $defaults, $query ); | |
| 672 | + $_response = is_wp_error( $_item ) ? $_item : $this->create_item( $_item ); | |
| 518 | 673 | |
| 519 | - // Set query (GET) parameters. | |
| 520 | - $_item->set_query_params( $query ); | |
| 521 | - | |
| 522 | - $_response = $this->create_item( $_item ); | |
| 523 | - | |
| 524 | 674 | if ( is_wp_error( $_response ) ) { |
| 525 | 675 | $response['create'][] = array( |
| 526 | 676 | 'id' => 0, |
| 527 | 677 | 'error' => array( |
| @@ -537,15 +687,14 @@ | ||
| 537 | 687 | } |
| 538 | 688 | |
| 539 | 689 | if ( ! empty( $items['update'] ) ) { |
| 540 | 690 | foreach ( $items['update'] as $item ) { |
| 541 | - $_item = new WP_REST_Request( 'PUT', $request->get_route() ); | |
| 542 | - $_item->set_body_params( $item ); | |
| 543 | - $_response = $this->update_item( $_item ); | |
| 691 | + $_item = $this->prepare_batch_update_request( $request->get_route(), $item, $this->get_batch_update_args() ); | |
| 692 | + $_response = is_wp_error( $_item ) ? $_item : $this->update_item( $_item ); | |
| 544 | 693 | |
| 545 | 694 | if ( is_wp_error( $_response ) ) { |
| 546 | 695 | $response['update'][] = array( |
| 547 | - 'id' => $item['id'], | |
| 696 | + 'id' => is_array( $item ) ? $this->batch_error_id( $item['id'] ?? 0 ) : 0, | |
| 548 | 697 | 'error' => array( |
| 549 | 698 | 'code' => $_response->get_error_code(), |
| 550 | 699 | 'message' => $_response->get_error_message(), |
| 551 | 700 | 'data' => $_response->get_error_data(), |
| @@ -558,26 +707,14 @@ | ||
| 558 | 707 | } |
| 559 | 708 | |
| 560 | 709 | if ( ! empty( $items['delete'] ) ) { |
| 561 | 710 | foreach ( $items['delete'] as $id ) { |
| 562 | - $id = (int) $id; | |
| 711 | + $_item = $this->prepare_batch_id_request( $request->get_route(), $id, array( 'force' => true ), $this->get_batch_delete_args() ); | |
| 712 | + $_response = is_wp_error( $_item ) ? $_item : $this->delete_item( $_item ); | |
| 563 | 713 | |
| 564 | - if ( 0 === $id ) { | |
| 565 | - continue; | |
| 566 | - } | |
| 567 | - | |
| 568 | - $_item = new WP_REST_Request( 'DELETE', $request->get_route() ); | |
| 569 | - $_item->set_query_params( | |
| 570 | - array( | |
| 571 | - 'id' => $id, | |
| 572 | - 'force' => true, | |
| 573 | - ) | |
| 574 | - ); | |
| 575 | - $_response = $this->delete_item( $_item ); | |
| 576 | - | |
| 577 | 714 | if ( is_wp_error( $_response ) ) { |
| 578 | 715 | $response['delete'][] = array( |
| 579 | - 'id' => $id, | |
| 716 | + 'id' => $this->batch_error_id( $id ), | |
| 580 | 717 | 'error' => array( |
| 581 | 718 | 'code' => $_response->get_error_code(), |
| 582 | 719 | 'message' => $_response->get_error_message(), |
| 583 | 720 | 'data' => $_response->get_error_data(), |
| @@ -592,25 +729,14 @@ | ||
| 592 | 729 | $route = $request->get_route(); |
| 593 | 730 | if ( MainWP_Utility::string_ends_by( $route, '/sites/batch' ) ) { |
| 594 | 731 | if ( ! empty( $items['sync'] ) ) { |
| 595 | 732 | foreach ( $items['sync'] as $id ) { |
| 596 | - $id = (int) $id; | |
| 733 | + $_item = $this->prepare_batch_id_request( $request->get_route(), $id ); | |
| 734 | + $_response = is_wp_error( $_item ) ? $_item : $this->sync_item( $_item ); | |
| 597 | 735 | |
| 598 | - if ( 0 === $id ) { | |
| 599 | - continue; | |
| 600 | - } | |
| 601 | - | |
| 602 | - $_item = new WP_REST_Request( 'DELETE', $request->get_route() ); | |
| 603 | - $_item->set_query_params( | |
| 604 | - array( | |
| 605 | - 'id' => $id, | |
| 606 | - ) | |
| 607 | - ); | |
| 608 | - $_response = $this->sync_item( $_item ); | |
| 609 | - | |
| 610 | 736 | if ( is_wp_error( $_response ) ) { |
| 611 | 737 | $response['sync'][] = array( |
| 612 | - 'id' => $id, | |
| 738 | + 'id' => $this->batch_error_id( $id ), | |
| 613 | 739 | 'error' => array( |
| 614 | 740 | 'code' => $_response->get_error_code(), |
| 615 | 741 | 'message' => $_response->get_error_message(), |
| 616 | 742 | 'data' => $_response->get_error_data(), |
| @@ -623,25 +749,14 @@ | ||
| 623 | 749 | } |
| 624 | 750 | |
| 625 | 751 | if ( ! empty( $items['reconnect'] ) ) { |
| 626 | 752 | foreach ( $items['reconnect'] as $id ) { |
| 627 | - $id = (int) $id; | |
| 753 | + $_item = $this->prepare_batch_id_request( $request->get_route(), $id ); | |
| 754 | + $_response = is_wp_error( $_item ) ? $_item : $this->reconnect_item( $_item ); | |
| 628 | 755 | |
| 629 | - if ( 0 === $id ) { | |
| 630 | - continue; | |
| 631 | - } | |
| 632 | - | |
| 633 | - $_item = new WP_REST_Request( 'DELETE', $request->get_route() ); | |
| 634 | - $_item->set_query_params( | |
| 635 | - array( | |
| 636 | - 'id' => $id, | |
| 637 | - ) | |
| 638 | - ); | |
| 639 | - $_response = $this->reconnect_item( $_item ); | |
| 640 | - | |
| 641 | 756 | if ( is_wp_error( $_response ) ) { |
| 642 | 757 | $response['reconnect'][] = array( |
| 643 | - 'id' => $id, | |
| 758 | + 'id' => $this->batch_error_id( $id ), | |
| 644 | 759 | 'error' => array( |
| 645 | 760 | 'code' => $_response->get_error_code(), |
| 646 | 761 | 'message' => $_response->get_error_message(), |
| 647 | 762 | 'data' => $_response->get_error_data(), |
| @@ -654,25 +769,14 @@ | ||
| 654 | 769 | } |
| 655 | 770 | |
| 656 | 771 | if ( ! empty( $items['disconnect'] ) ) { |
| 657 | 772 | foreach ( $items['disconnect'] as $id ) { |
| 658 | - $id = (int) $id; | |
| 773 | + $_item = $this->prepare_batch_id_request( $request->get_route(), $id ); | |
| 774 | + $_response = is_wp_error( $_item ) ? $_item : $this->disconnect_site( $_item ); | |
| 659 | 775 | |
| 660 | - if ( 0 === $id ) { | |
| 661 | - continue; | |
| 662 | - } | |
| 663 | - | |
| 664 | - $_item = new WP_REST_Request( 'DELETE', $request->get_route() ); | |
| 665 | - $_item->set_query_params( | |
| 666 | - array( | |
| 667 | - 'id' => $id, | |
| 668 | - ) | |
| 669 | - ); | |
| 670 | - $_response = $this->disconnect_site( $_item ); | |
| 671 | - | |
| 672 | 776 | if ( is_wp_error( $_response ) ) { |
| 673 | 777 | $response['disconnect'][] = array( |
| 674 | - 'id' => $id, | |
| 778 | + 'id' => $this->batch_error_id( $id ), | |
| 675 | 779 | 'error' => array( |
| 676 | 780 | 'code' => $_response->get_error_code(), |
| 677 | 781 | 'message' => $_response->get_error_message(), |
| 678 | 782 | 'data' => $_response->get_error_data(), |
| @@ -685,25 +789,14 @@ | ||
| 685 | 789 | } |
| 686 | 790 | |
| 687 | 791 | if ( ! empty( $items['suspend'] ) ) { |
| 688 | 792 | foreach ( $items['suspend'] as $id ) { |
| 689 | - $id = (int) $id; | |
| 793 | + $_item = $this->prepare_batch_id_request( $request->get_route(), $id ); | |
| 794 | + $_response = is_wp_error( $_item ) ? $_item : $this->suspend_item( $_item ); | |
| 690 | 795 | |
| 691 | - if ( 0 === $id ) { | |
| 692 | - continue; | |
| 693 | - } | |
| 694 | - | |
| 695 | - $_item = new WP_REST_Request( 'DELETE', $request->get_route() ); | |
| 696 | - $_item->set_query_params( | |
| 697 | - array( | |
| 698 | - 'id' => $id, | |
| 699 | - ) | |
| 700 | - ); | |
| 701 | - $_response = $this->suspend_item( $_item ); | |
| 702 | - | |
| 703 | 796 | if ( is_wp_error( $_response ) ) { |
| 704 | 797 | $response['suspend'][] = array( |
| 705 | - 'id' => $id, | |
| 798 | + 'id' => $this->batch_error_id( $id ), | |
| 706 | 799 | 'error' => array( |
| 707 | 800 | 'code' => $_response->get_error_code(), |
| 708 | 801 | 'message' => $_response->get_error_message(), |
| 709 | 802 | 'data' => $_response->get_error_data(), |
| @@ -716,25 +809,14 @@ | ||
| 716 | 809 | } |
| 717 | 810 | |
| 718 | 811 | if ( ! empty( $items['check'] ) ) { |
| 719 | 812 | foreach ( $items['check'] as $id ) { |
| 720 | - $id = (int) $id; | |
| 813 | + $_item = $this->prepare_batch_id_request( $request->get_route(), $id ); | |
| 814 | + $_response = is_wp_error( $_item ) ? $_item : $this->check_item( $_item ); | |
| 721 | 815 | |
| 722 | - if ( 0 === $id ) { | |
| 723 | - continue; | |
| 724 | - } | |
| 725 | - | |
| 726 | - $_item = new WP_REST_Request( 'DELETE', $request->get_route() ); | |
| 727 | - $_item->set_query_params( | |
| 728 | - array( | |
| 729 | - 'id' => $id, | |
| 730 | - ) | |
| 731 | - ); | |
| 732 | - $_response = $this->check_item( $_item ); | |
| 733 | - | |
| 734 | 816 | if ( is_wp_error( $_response ) ) { |
| 735 | 817 | $response['check'][] = array( |
| 736 | - 'id' => $id, | |
| 818 | + 'id' => $this->batch_error_id( $id ), | |
| 737 | 819 | 'error' => array( |
| 738 | 820 | 'code' => $_response->get_error_code(), |
| 739 | 821 | 'message' => $_response->get_error_message(), |
| 740 | 822 | 'data' => $_response->get_error_data(), |
| @@ -747,25 +829,14 @@ | ||
| 747 | 829 | } |
| 748 | 830 | |
| 749 | 831 | if ( ! empty( $items['remove'] ) ) { |
| 750 | 832 | foreach ( $items['remove'] as $id ) { |
| 751 | - $id = (int) $id; | |
| 833 | + $_item = $this->prepare_batch_id_request( $request->get_route(), $id ); | |
| 834 | + $_response = is_wp_error( $_item ) ? $_item : $this->delete_item( $_item ); | |
| 752 | 835 | |
| 753 | - if ( 0 === $id ) { | |
| 754 | - continue; | |
| 755 | - } | |
| 756 | - | |
| 757 | - $_item = new WP_REST_Request( 'DELETE', $request->get_route() ); | |
| 758 | - $_item->set_query_params( | |
| 759 | - array( | |
| 760 | - 'id' => $id, | |
| 761 | - ) | |
| 762 | - ); | |
| 763 | - $_response = $this->delete_item( $_item ); | |
| 764 | - | |
| 765 | 836 | if ( is_wp_error( $_response ) ) { |
| 766 | 837 | $response['remove'][] = array( |
| 767 | - 'id' => $id, | |
| 838 | + 'id' => $this->batch_error_id( $id ), | |
| 768 | 839 | 'error' => array( |
| 769 | 840 | 'code' => $_response->get_error_code(), |
| 770 | 841 | 'message' => $_response->get_error_message(), |
| 771 | 842 | 'data' => $_response->get_error_data(), |
| @@ -778,25 +849,14 @@ | ||
| 778 | 849 | } |
| 779 | 850 | |
| 780 | 851 | if ( ! empty( $items['security'] ) ) { |
| 781 | 852 | foreach ( $items['security'] as $id ) { |
| 782 | - $id = (int) $id; | |
| 853 | + $_item = $this->prepare_batch_id_request( $request->get_route(), $id ); | |
| 854 | + $_response = is_wp_error( $_item ) ? $_item : $this->security_item( $_item ); | |
| 783 | 855 | |
| 784 | - if ( 0 === $id ) { | |
| 785 | - continue; | |
| 786 | - } | |
| 787 | - | |
| 788 | - $_item = new WP_REST_Request( 'DELETE', $request->get_route() ); | |
| 789 | - $_item->set_query_params( | |
| 790 | - array( | |
| 791 | - 'id' => $id, | |
| 792 | - ) | |
| 793 | - ); | |
| 794 | - $_response = $this->security_item( $_item ); | |
| 795 | - | |
| 796 | 856 | if ( is_wp_error( $_response ) ) { |
| 797 | 857 | $response['security'][] = array( |
| 798 | - 'id' => $id, | |
| 858 | + 'id' => $this->batch_error_id( $id ), | |
| 799 | 859 | 'error' => array( |
| 800 | 860 | 'code' => $_response->get_error_code(), |
| 801 | 861 | 'message' => $_response->get_error_message(), |
| 802 | 862 | 'data' => $_response->get_error_data(), |
| @@ -809,25 +869,14 @@ | ||
| 809 | 869 | } |
| 810 | 870 | |
| 811 | 871 | if ( ! empty( $items['plugins'] ) ) { |
| 812 | 872 | foreach ( $items['plugins'] as $id ) { |
| 813 | - $id = (int) $id; | |
| 873 | + $_item = $this->prepare_batch_id_request( $request->get_route(), $id ); | |
| 874 | + $_response = is_wp_error( $_item ) ? $_item : $this->get_site_plugins( $_item ); | |
| 814 | 875 | |
| 815 | - if ( 0 === $id ) { | |
| 816 | - continue; | |
| 817 | - } | |
| 818 | - | |
| 819 | - $_item = new WP_REST_Request( 'DELETE', $request->get_route() ); | |
| 820 | - $_item->set_query_params( | |
| 821 | - array( | |
| 822 | - 'id' => $id, | |
| 823 | - ) | |
| 824 | - ); | |
| 825 | - $_response = $this->get_site_plugins( $_item ); | |
| 826 | - | |
| 827 | 876 | if ( is_wp_error( $_response ) ) { |
| 828 | 877 | $response['plugins'][] = array( |
| 829 | - 'id' => $id, | |
| 878 | + 'id' => $this->batch_error_id( $id ), | |
| 830 | 879 | 'error' => array( |
| 831 | 880 | 'code' => $_response->get_error_code(), |
| 832 | 881 | 'message' => $_response->get_error_message(), |
| 833 | 882 | 'data' => $_response->get_error_data(), |
| @@ -840,25 +889,14 @@ | ||
| 840 | 889 | } |
| 841 | 890 | |
| 842 | 891 | if ( ! empty( $items['themes'] ) ) { |
| 843 | 892 | foreach ( $items['themes'] as $id ) { |
| 844 | - $id = (int) $id; | |
| 893 | + $_item = $this->prepare_batch_id_request( $request->get_route(), $id ); | |
| 894 | + $_response = is_wp_error( $_item ) ? $_item : $this->get_site_themes( $_item ); | |
| 845 | 895 | |
| 846 | - if ( 0 === $id ) { | |
| 847 | - continue; | |
| 848 | - } | |
| 849 | - | |
| 850 | - $_item = new WP_REST_Request( 'DELETE', $request->get_route() ); | |
| 851 | - $_item->set_query_params( | |
| 852 | - array( | |
| 853 | - 'id' => $id, | |
| 854 | - ) | |
| 855 | - ); | |
| 856 | - $_response = $this->get_site_themes( $_item ); | |
| 857 | - | |
| 858 | 896 | if ( is_wp_error( $_response ) ) { |
| 859 | 897 | $response['themes'][] = array( |
| 860 | - 'id' => $id, | |
| 898 | + 'id' => $this->batch_error_id( $id ), | |
| 861 | 899 | 'error' => array( |
| 862 | 900 | 'code' => $_response->get_error_code(), |
| 863 | 901 | 'message' => $_response->get_error_message(), |
| 864 | 902 | 'data' => $_response->get_error_data(), |
| @@ -871,25 +909,14 @@ | ||
| 871 | 909 | } |
| 872 | 910 | |
| 873 | 911 | if ( ! empty( $items['non-mainwp-changes'] ) ) { |
| 874 | 912 | foreach ( $items['non-mainwp-changes'] as $id ) { |
| 875 | - $id = (int) $id; | |
| 913 | + $_item = $this->prepare_batch_id_request( $request->get_route(), $id ); | |
| 914 | + $_response = is_wp_error( $_item ) ? $_item : $this->get_non_mainwp_changes_of_site( $_item ); | |
| 876 | 915 | |
| 877 | - if ( 0 === $id ) { | |
| 878 | - continue; | |
| 879 | - } | |
| 880 | - | |
| 881 | - $_item = new WP_REST_Request( 'DELETE', $request->get_route() ); | |
| 882 | - $_item->set_query_params( | |
| 883 | - array( | |
| 884 | - 'id' => $id, | |
| 885 | - ) | |
| 886 | - ); | |
| 887 | - $_response = $this->get_non_mainwp_changes_of_site( $_item ); | |
| 888 | - | |
| 889 | 916 | if ( is_wp_error( $_response ) ) { |
| 890 | 917 | $response['non-mainwp-changes'][] = array( |
| 891 | - 'id' => $id, | |
| 918 | + 'id' => $this->batch_error_id( $id ), | |
| 892 | 919 | 'error' => array( |
| 893 | 920 | 'code' => $_response->get_error_code(), |
| 894 | 921 | 'message' => $_response->get_error_message(), |
| 895 | 922 | 'data' => $_response->get_error_data(), |
| @@ -1506,12 +1533,45 @@ | ||
| 1506 | 1533 | public function sanitize_field( $value ) { |
| 1507 | 1534 | if ( null === $value || '' === $value ) { |
| 1508 | 1535 | return ''; |
| 1509 | 1536 | } |
| 1510 | - return sanitize_text_field( wp_unslash( trim( $value ) ) ); | |
| 1537 | + // trim() raises a TypeError on arrays and objects under PHP 8, and a body value is free to be either. | |
| 1538 | + if ( ! is_scalar( $value ) ) { | |
| 1539 | + return ''; | |
| 1540 | + } | |
| 1541 | + return sanitize_text_field( trim( $value ) ); | |
| 1511 | 1542 | } |
| 1512 | 1543 | |
| 1513 | 1544 | /** |
| 1545 | + * Read the request body as an associative array. | |
| 1546 | + * | |
| 1547 | + * The published routes accept either a JSON or a form-encoded body; clients | |
| 1548 | + * send both, so JSON params are tried first and form params second. | |
| 1549 | + * | |
| 1550 | + * @param WP_REST_Request $request Request object. | |
| 1551 | + * @return array|WP_Error Body data, or an empty_body error when nothing usable was sent. | |
| 1552 | + */ | |
| 1553 | + protected function get_request_body_data( $request ) { | |
| 1554 | + $body = $request->get_json_params(); | |
| 1555 | + | |
| 1556 | + // Only the two parsed bags count: a raw-body decode would hand the | |
| 1557 | + // handler values that never went through the registered-arg validation. | |
| 1558 | + if ( ! is_array( $body ) || empty( $body ) ) { | |
| 1559 | + $body = $request->get_body_params(); | |
| 1560 | + } | |
| 1561 | + | |
| 1562 | + if ( ! is_array( $body ) || empty( $body ) ) { | |
| 1563 | + return new WP_Error( | |
| 1564 | + 'empty_body', | |
| 1565 | + __( 'Request body is empty.', 'mainwp' ), | |
| 1566 | + array( 'status' => 400 ) | |
| 1567 | + ); | |
| 1568 | + } | |
| 1569 | + | |
| 1570 | + return $body; | |
| 1571 | + } | |
| 1572 | + | |
| 1573 | + /** | |
| 1514 | 1574 | * Make enum sanitizer. |
| 1515 | 1575 | * |
| 1516 | 1576 | * @param array $allowed Allowed values. |
| 1517 | 1577 | * @param string $type Type to coerce to. |
| @@ -1556,13 +1616,16 @@ | ||
| 1556 | 1616 | return $sanitized; |
| 1557 | 1617 | } |
| 1558 | 1618 | |
| 1559 | 1619 | // Standard sanitization for non-array types. |
| 1560 | - $value = $this->sanitize_field( $value ); | |
| 1561 | - $v = $this->coerce_type( $value, $type ); | |
| 1620 | + // sanitize_field() trims, which fatals on an array or object, so treat those as a plain enum mismatch. | |
| 1621 | + if ( is_scalar( $value ) ) { | |
| 1622 | + $value = $this->sanitize_field( $value ); | |
| 1623 | + $v = $this->coerce_type( $value, $type ); | |
| 1562 | 1624 | |
| 1563 | - if ( in_array( $v, $allowed_norm, true ) ) { | |
| 1564 | - return $v; | |
| 1625 | + if ( in_array( $v, $allowed_norm, true ) ) { | |
| 1626 | + return $v; | |
| 1627 | + } | |
| 1565 | 1628 | } |
| 1566 | 1629 | |
| 1567 | 1630 | return new WP_Error( |
| 1568 | 1631 | "invalid_{$param}", |
| @@ -1642,13 +1705,16 @@ | ||
| 1642 | 1705 | return true; |
| 1643 | 1706 | } |
| 1644 | 1707 | |
| 1645 | 1708 | // Standard validation for non-array types. |
| 1646 | - $value = $this->sanitize_field( $value ); | |
| 1647 | - $v = $this->coerce_type( $value, $type ); | |
| 1709 | + // sanitize_field() trims, which fatals on an array or object, so treat those as a plain enum mismatch. | |
| 1710 | + if ( is_scalar( $value ) ) { | |
| 1711 | + $value = $this->sanitize_field( $value ); | |
| 1712 | + $v = $this->coerce_type( $value, $type ); | |
| 1648 | 1713 | |
| 1649 | - if ( in_array( $v, $allowed_norm, true ) ) { | |
| 1650 | - return true; | |
| 1714 | + if ( in_array( $v, $allowed_norm, true ) ) { | |
| 1715 | + return true; | |
| 1716 | + } | |
| 1651 | 1717 | } |
| 1652 | 1718 | |
| 1653 | 1719 | return new WP_Error( |
| 1654 | 1720 | "invalid_{$param}", |
| @@ -1891,8 +1957,9 @@ | ||
| 1891 | 1957 | $system_utility = new MainWP_System_Utility(); |
| 1892 | 1958 | $db = MainWP_DB::instance(); |
| 1893 | 1959 | $data_fields = $system_utility->get_default_map_site_fields(); |
| 1894 | 1960 | $data_fields[] = 'users'; |
| 1961 | + $data_fields[] = 'verify_certificate'; // Add verify_certificate to the list of fields to fetch from the database. | |
| 1895 | 1962 | |
| 1896 | 1963 | // Default result. |
| 1897 | 1964 | $website_url = array(); |
| 1898 | 1965 | $db_websites = array(); |