← All changes
|
includes/rest-api/controller/version2/class-mainwp-rest-updates-controller.php
+256
-36
5.2.1
→
6.2.2
View file →
| @@ -7,9 +7,8 @@ | ||
| 7 | 7 | * @package MainWP\Dashboard |
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | 10 | use MainWP\Dashboard\MainWP_DB; |
| 11 | -use MainWP\Dashboard\MainWP_Common_Handler; | |
| 12 | 11 | use MainWP\Dashboard\MainWP_Updates_Helper; |
| 13 | 12 | use MainWP\Dashboard\MainWP_DB_Common; |
| 14 | 13 | use MainWP\Dashboard\MainWP_Updates_Handler; |
| 15 | 14 | use MainWP\Dashboard\MainWP_Connect; |
| @@ -18,8 +17,14 @@ | ||
| 18 | 17 | use MainWP\Dashboard\MainWP_Common_Functions; |
| 19 | 18 | use MainWP\Dashboard\MainWP_Cron_Jobs_Batch; |
| 20 | 19 | use MainWP\Dashboard\MainWP_Logger; |
| 21 | 20 | use MainWP\Dashboard\MainWP_Auto_Updates_DB; |
| 21 | + | |
| 22 | +// Exit if accessed directly. | |
| 23 | +if ( ! defined( 'ABSPATH' ) ) { | |
| 24 | + exit; | |
| 25 | +} | |
| 26 | + | |
| 22 | 27 | /** |
| 23 | 28 | * Class MainWP_Rest_Updates_Controller |
| 24 | 29 | * |
| 25 | 30 | * @package MainWP\Dashboard |
| @@ -266,11 +271,8 @@ | ||
| 266 | 271 | * @return WP_Error|WP_REST_Response |
| 267 | 272 | */ |
| 268 | 273 | public function get_items( $request ) { //phpcs:ignore -- NOSONAR complex function. |
| 269 | 274 | |
| 270 | - $all_updates = array(); | |
| 271 | - $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_for_current_user( true, null, 'wp.url', false, false, null, false, array( 'ignored_wp_upgrades', 'rollback_updates_data' ) ) ); | |
| 272 | - | |
| 273 | 275 | $args = $this->prepare_objects_query( $request ); |
| 274 | 276 | $args = $this->validate_rest_args( $args, $this->get_validate_args_params( 'get_sites' ) ); |
| 275 | 277 | if ( is_wp_error( $args ) ) { |
| 276 | 278 | return $args; |
| @@ -281,8 +283,65 @@ | ||
| 281 | 283 | $s = isset( $args['s'] ) ? trim( $args['s'] ) : ''; |
| 282 | 284 | $exclud = isset( $args['exclude'] ) ? wp_parse_id_list( $args['exclude'] ) : array(); |
| 283 | 285 | $includ = isset( $args['include'] ) ? wp_parse_id_list( $args['include'] ) : array(); |
| 284 | 286 | |
| 287 | + // Try abilities-first approach (with fallback to legacy logic). | |
| 288 | + $ability = function_exists( 'wp_get_ability' ) ? wp_get_ability( 'mainwp/list-updates-v1' ) : null; | |
| 289 | + | |
| 290 | + if ( null !== $ability ) { | |
| 291 | + // Build ability input from REST parameters. | |
| 292 | + // Note: For backward compatibility, we do NOT paginate here. The legacy path | |
| 293 | + // returns ALL updates (no page/per_page constraints), so we omit pagination | |
| 294 | + // to maintain consistent behavior. Callers who need paginated results should | |
| 295 | + // use the ability directly with explicit page/per_page values. | |
| 296 | + // See: .mwpdev/plans/abilities-api/phase-3-rest-integration-notes.md | |
| 297 | + | |
| 298 | + // Determine site IDs to include. | |
| 299 | + // The ability uses site_ids_or_domains (array of IDs or domains). | |
| 300 | + // REST API uses 'include' for site IDs to include. | |
| 301 | + $site_ids = ! empty( $includ ) ? $includ : array(); | |
| 302 | + | |
| 303 | + // Map REST 'type' parameter to ability 'types' parameter. | |
| 304 | + // REST uses 'type' (singular), ability uses 'types' (plural). | |
| 305 | + $ability_types = ! empty( $type ) ? $type : array(); | |
| 306 | + | |
| 307 | + $ability_input = array( | |
| 308 | + 'site_ids_or_domains' => $site_ids, | |
| 309 | + 'types' => $ability_types, | |
| 310 | + ); | |
| 311 | + | |
| 312 | + $result = $ability->execute( $ability_input ); | |
| 313 | + | |
| 314 | + if ( is_wp_error( $result ) ) { | |
| 315 | + $error_data = $result->get_error_data(); | |
| 316 | + $status = isset( $error_data['status'] ) ? $error_data['status'] : 500; | |
| 317 | + return new WP_Error( $result->get_error_code(), $result->get_error_message(), array( 'status' => $status ) ); | |
| 318 | + } | |
| 319 | + | |
| 320 | + // Re-apply exclude filter for backward compatibility. | |
| 321 | + // The ability doesn't support this parameter, so we filter post-fetch. | |
| 322 | + // This matches the pattern used in the Sites controller. | |
| 323 | + $updates = isset( $result['updates'] ) ? $result['updates'] : array(); | |
| 324 | + if ( ! empty( $exclud ) && ! empty( $updates ) ) { | |
| 325 | + foreach ( $exclud as $excluded_id ) { | |
| 326 | + unset( $updates[ $excluded_id ] ); | |
| 327 | + } | |
| 328 | + } | |
| 329 | + | |
| 330 | + // Transform ability output to REST response format. | |
| 331 | + // Ability returns 'updates' keyed by site ID with nested type arrays. | |
| 332 | + return rest_ensure_response( | |
| 333 | + array( | |
| 334 | + 'success' => 1, | |
| 335 | + 'data' => $updates, | |
| 336 | + ) | |
| 337 | + ); | |
| 338 | + } | |
| 339 | + | |
| 340 | + // Fallback: Legacy logic when Abilities API is not available. | |
| 341 | + $all_updates = array(); | |
| 342 | + $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_for_current_user( true, null, 'wp.url', false, false, null, false, array( 'ignored_wp_upgrades', 'rollback_updates_data' ) ) ); | |
| 343 | + | |
| 285 | 344 | if ( empty( $type ) ) { |
| 286 | 345 | $type[] = 'all'; |
| 287 | 346 | } |
| 288 | 347 | |
| @@ -423,9 +482,9 @@ | ||
| 423 | 482 | * @return WP_Error|Object Item. |
| 424 | 483 | */ |
| 425 | 484 | public function get_request_item( $request ) { |
| 426 | 485 | $route = $request->get_route(); |
| 427 | - if ( str_ends_with( $route, '/batch' ) ) { | |
| 486 | + if ( MainWP_Utility::string_ends_by( $route, '/batch' ) ) { | |
| 428 | 487 | $by = 'id'; |
| 429 | 488 | $value = $request['id']; |
| 430 | 489 | } else { |
| 431 | 490 | $value = $request['id_domain']; |
| @@ -616,8 +675,51 @@ | ||
| 616 | 675 | * @return WP_Error|WP_REST_Response |
| 617 | 676 | */ |
| 618 | 677 | public function get_all_global_ignored_updates( $request ) { //phpcs:ignore -- NOSONAR - complex. |
| 619 | 678 | |
| 679 | + $args = $this->prepare_objects_query( $request ); | |
| 680 | + | |
| 681 | + $type = isset( $args['type'] ) && ! empty( $args['type'] ) ? wp_parse_list( $args['type'] ) : array(); | |
| 682 | + $type = array_filter( array_map( 'trim', $type ) ); | |
| 683 | + $s = isset( $args['s'] ) ? trim( $args['s'] ) : ''; | |
| 684 | + | |
| 685 | + // Normalize type array: add 'all' if empty or missing both 'plugins' and 'themes'. | |
| 686 | + // This ensures consistent behavior between ability and legacy paths. | |
| 687 | + if ( empty( $type ) || ( ! in_array( 'plugins', $type ) && ! in_array( 'themes', $type ) ) ) { | |
| 688 | + $type[] = 'all'; | |
| 689 | + } | |
| 690 | + | |
| 691 | + // Try abilities-first approach (with fallback to legacy logic). | |
| 692 | + $ability = function_exists( 'wp_get_ability' ) ? wp_get_ability( 'mainwp/list-ignored-updates-v1' ) : null; | |
| 693 | + | |
| 694 | + if ( null !== $ability ) { | |
| 695 | + // Build ability input using normalized type. | |
| 696 | + $ability_input = array( | |
| 697 | + 'scope' => 'global', | |
| 698 | + 'type' => $type, | |
| 699 | + 'search' => $s, | |
| 700 | + ); | |
| 701 | + | |
| 702 | + $result = $ability->execute( $ability_input ); | |
| 703 | + | |
| 704 | + if ( is_wp_error( $result ) ) { | |
| 705 | + $error_data = $result->get_error_data(); | |
| 706 | + $status = isset( $error_data['status'] ) ? $error_data['status'] : 500; | |
| 707 | + return new WP_Error( $result->get_error_code(), $result->get_error_message(), array( 'status' => $status ) ); | |
| 708 | + } | |
| 709 | + | |
| 710 | + // Transform ability output to REST response format. | |
| 711 | + // Ability returns 'ignored' object with 'plugins' and 'themes' keys. | |
| 712 | + return rest_ensure_response( | |
| 713 | + array( | |
| 714 | + 'success' => 1, | |
| 715 | + 'data' => isset( $result['ignored'] ) ? $result['ignored'] : array(), | |
| 716 | + ) | |
| 717 | + ); | |
| 718 | + } | |
| 719 | + | |
| 720 | + // Fallback: Legacy logic when Abilities API is not available. | |
| 721 | + // Note: $type is already normalized above before the ability check. | |
| 620 | 722 | $userExtension = MainWP_DB_Common::instance()->get_user_extension(); |
| 621 | 723 | $ignored_plugins = ! empty( $userExtension->ignored_plugins ) ? json_decode( $userExtension->ignored_plugins, true ) : array(); |
| 622 | 724 | $ignored_themes = ! empty( $userExtension->ignored_themes ) ? json_decode( $userExtension->ignored_themes, true ) : array(); |
| 623 | 725 | |
| @@ -627,18 +729,8 @@ | ||
| 627 | 729 | if ( ! is_array( $ignored_themes ) ) { |
| 628 | 730 | $ignored_themes = array(); |
| 629 | 731 | } |
| 630 | 732 | |
| 631 | - $args = $this->prepare_objects_query( $request ); | |
| 632 | - | |
| 633 | - $type = isset( $args['type'] ) && ! empty( $args['type'] ) ? wp_parse_list( $args['type'] ) : array(); | |
| 634 | - $type = array_filter( array_map( 'trim', $type ) ); | |
| 635 | - $s = isset( $args['s'] ) ? trim( $args['s'] ) : ''; | |
| 636 | - | |
| 637 | - if ( empty( $type ) || ( ! in_array( 'plugins', $type ) && ! in_array( 'themes', $type ) ) ) { | |
| 638 | - $type[] = 'all'; | |
| 639 | - } | |
| 640 | - | |
| 641 | 733 | $all = in_array( 'all', $type ) ? true : false; |
| 642 | 734 | |
| 643 | 735 | if ( ! empty( $s ) ) { |
| 644 | 736 | $ignored_plugins = mainwp_search_in_array( $ignored_plugins, $s, array( 'in_sub_fields' => 'Name' ) ); |
| @@ -677,8 +769,52 @@ | ||
| 677 | 769 | if ( is_wp_error( $website ) ) { |
| 678 | 770 | return $website; |
| 679 | 771 | } |
| 680 | 772 | |
| 773 | + $args = $this->prepare_objects_query( $request ); | |
| 774 | + | |
| 775 | + $type = isset( $args['type'] ) && ! empty( $args['type'] ) ? wp_parse_list( $args['type'] ) : array(); | |
| 776 | + $type = array_filter( array_map( 'trim', $type ) ); | |
| 777 | + $s = isset( $args['s'] ) ? trim( $args['s'] ) : ''; | |
| 778 | + | |
| 779 | + // Normalize type array: add 'all' if empty or missing both 'plugins' and 'themes'. | |
| 780 | + // This ensures consistent behavior between ability and legacy paths. | |
| 781 | + if ( empty( $type ) || ( ! in_array( 'plugins', $type ) && ! in_array( 'themes', $type ) ) ) { | |
| 782 | + $type[] = 'all'; | |
| 783 | + } | |
| 784 | + | |
| 785 | + // Try abilities-first approach (with fallback to legacy logic). | |
| 786 | + $ability = function_exists( 'wp_get_ability' ) ? wp_get_ability( 'mainwp/list-ignored-updates-v1' ) : null; | |
| 787 | + | |
| 788 | + if ( null !== $ability ) { | |
| 789 | + // Build ability input using normalized type. | |
| 790 | + $ability_input = array( | |
| 791 | + 'scope' => 'site', | |
| 792 | + 'site_id_or_domain' => (int) $website->id, | |
| 793 | + 'type' => $type, | |
| 794 | + 'search' => $s, | |
| 795 | + ); | |
| 796 | + | |
| 797 | + $result = $ability->execute( $ability_input ); | |
| 798 | + | |
| 799 | + if ( is_wp_error( $result ) ) { | |
| 800 | + $error_data = $result->get_error_data(); | |
| 801 | + $status = isset( $error_data['status'] ) ? $error_data['status'] : 500; | |
| 802 | + return new WP_Error( $result->get_error_code(), $result->get_error_message(), array( 'status' => $status ) ); | |
| 803 | + } | |
| 804 | + | |
| 805 | + // Transform ability output to REST response format. | |
| 806 | + // Ability merges per-site and global ignores, matching REST behavior. | |
| 807 | + return rest_ensure_response( | |
| 808 | + array( | |
| 809 | + 'success' => 1, | |
| 810 | + 'data' => isset( $result['ignored'] ) ? $result['ignored'] : array(), | |
| 811 | + ) | |
| 812 | + ); | |
| 813 | + } | |
| 814 | + | |
| 815 | + // Fallback: Legacy logic when Abilities API is not available. | |
| 816 | + // Note: $type is already normalized above before the ability check. | |
| 681 | 817 | $ignored_plugins = ! empty( $website->ignored_plugins ) ? json_decode( $website->ignored_plugins, true ) : array(); |
| 682 | 818 | $ignored_themes = ! empty( $website->ignored_themes ) ? json_decode( $website->ignored_themes, true ) : array(); |
| 683 | 819 | |
| 684 | 820 | if ( ! is_array( $ignored_plugins ) ) { |
| @@ -701,19 +837,8 @@ | ||
| 701 | 837 | |
| 702 | 838 | $ignored_plugins = $ignored_plugins + $ignored_plugins2; |
| 703 | 839 | $ignored_themes = $ignored_themes + $ignored_themes2; |
| 704 | 840 | |
| 705 | - $args = $this->prepare_objects_query( $request ); | |
| 706 | - | |
| 707 | - $type = isset( $args['type'] ) && ! empty( $args['type'] ) ? wp_parse_list( $args['type'] ) : array(); | |
| 708 | - $type = array_filter( array_map( 'trim', $type ) ); | |
| 709 | - | |
| 710 | - $s = isset( $args['s'] ) ? trim( $args['s'] ) : ''; | |
| 711 | - | |
| 712 | - if ( empty( $type ) || ( ! in_array( 'plugins', $type ) && ! in_array( 'themes', $type ) ) ) { | |
| 713 | - $type[] = 'all'; | |
| 714 | - } | |
| 715 | - | |
| 716 | 841 | $all = in_array( 'all', $type ) ? true : false; |
| 717 | 842 | |
| 718 | 843 | if ( ! empty( $s ) ) { |
| 719 | 844 | $ignored_plugins = mainwp_search_in_array( $ignored_plugins, $s, array( 'in_sub_fields' => 'Name' ) ); |
| @@ -744,9 +869,9 @@ | ||
| 744 | 869 | * |
| 745 | 870 | * @param WP_REST_Request $request Full details about the request. |
| 746 | 871 | * @return WP_Error|WP_REST_Response |
| 747 | 872 | */ |
| 748 | - public function update_all_items_start( $request ) { | |
| 873 | + public function update_all_items_start( $request ) { //phpcs:ignore -- NOSONAR complex function. | |
| 749 | 874 | |
| 750 | 875 | $batch_updates_running = get_option( 'mainwp_batch_updates_is_running', 0 ); |
| 751 | 876 | $start_time = get_option( 'mainwp_batch_updates_start_time', 0 ); |
| 752 | 877 | |
| @@ -759,8 +884,52 @@ | ||
| 759 | 884 | ); |
| 760 | 885 | return rest_ensure_response( $resp_data ); |
| 761 | 886 | } |
| 762 | 887 | |
| 888 | + // Try abilities-first approach (with fallback to legacy logic). | |
| 889 | + $ability = function_exists( 'wp_get_ability' ) ? wp_get_ability( 'mainwp/run-updates-v1' ) : null; | |
| 890 | + | |
| 891 | + if ( null !== $ability ) { | |
| 892 | + // Build ability input for updating all sites with all update types. | |
| 893 | + // Empty arrays mean "all sites" and "all types" respectively. | |
| 894 | + $ability_input = array( | |
| 895 | + 'site_ids_or_domains' => array(), // All sites. | |
| 896 | + 'types' => array(), // All types. | |
| 897 | + ); | |
| 898 | + | |
| 899 | + $result = $ability->execute( $ability_input ); | |
| 900 | + | |
| 901 | + if ( is_wp_error( $result ) ) { | |
| 902 | + $error_data = $result->get_error_data(); | |
| 903 | + $status = isset( $error_data['status'] ) ? $error_data['status'] : 500; | |
| 904 | + return new WP_Error( $result->get_error_code(), $result->get_error_message(), array( 'status' => $status ) ); | |
| 905 | + } | |
| 906 | + | |
| 907 | + // Check if updates were queued for background processing. | |
| 908 | + if ( isset( $result['job_id'] ) ) { | |
| 909 | + return rest_ensure_response( | |
| 910 | + array( | |
| 911 | + 'success' => 1, | |
| 912 | + 'message' => esc_html__( 'Batch updates queued.', 'mainwp' ), | |
| 913 | + 'job_id' => $result['job_id'], | |
| 914 | + 'queued_count' => isset( $result['queued_count'] ) ? $result['queued_count'] : 0, | |
| 915 | + 'last_time_start_batch_updates' => mainwp_rest_prepare_date_response( current_time( 'mysql' ) ), | |
| 916 | + ) | |
| 917 | + ); | |
| 918 | + } | |
| 919 | + | |
| 920 | + // Transform immediate results. | |
| 921 | + return rest_ensure_response( | |
| 922 | + array( | |
| 923 | + 'success' => 1, | |
| 924 | + 'message' => esc_html__( 'Batch updates completed.', 'mainwp' ), | |
| 925 | + 'summary' => isset( $result['summary'] ) ? $result['summary'] : array(), | |
| 926 | + 'last_time_start_batch_updates' => mainwp_rest_prepare_date_response( current_time( 'mysql' ) ), | |
| 927 | + ) | |
| 928 | + ); | |
| 929 | + } | |
| 930 | + | |
| 931 | + // Fallback: Legacy logic when Abilities API is not available. | |
| 763 | 932 | $local_timestamp = MainWP_Utility::get_timestamp(); |
| 764 | 933 | $start_time = $local_timestamp; |
| 765 | 934 | MainWP_Utility::update_option( 'mainwp_batch_updates_start_time', $start_time ); |
| 766 | 935 | MainWP_Utility::update_option( 'mainwp_batch_updates_is_running', 1 ); // to start perform batch update job. |
| @@ -795,9 +964,9 @@ | ||
| 795 | 964 | * |
| 796 | 965 | * @param WP_REST_Request $request Full details about the request. |
| 797 | 966 | * @return WP_Error|WP_REST_Response |
| 798 | 967 | */ |
| 799 | - public function update_all_items_inidividual_site_start( $request ) { | |
| 968 | + public function update_all_items_inidividual_site_start( $request ) { //phpcs:ignore -- NOSONAR complex function. | |
| 800 | 969 | $website = $this->get_request_item( $request ); |
| 801 | 970 | |
| 802 | 971 | if ( is_wp_error( $website ) ) { |
| 803 | 972 | return $website; |
| @@ -802,8 +971,10 @@ | ||
| 802 | 971 | if ( is_wp_error( $website ) ) { |
| 803 | 972 | return $website; |
| 804 | 973 | } |
| 805 | 974 | |
| 975 | + // Fetch full site data with options needed for business rule checks. | |
| 976 | + // This is done BEFORE checking abilities to ensure consistent behavior. | |
| 806 | 977 | $fetch_one = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_for_current_user( true, null, 'wp.url', false, false, null, false, array( 'ignored_wp_upgrades', 'batch_individual_queue_time', 'premium_upgrades' ), 'no', array( 'include' => array( $website->id ) ) ) ); |
| 807 | 978 | $website = $fetch_one ? MainWP_DB::fetch_object( $fetch_one ) : false; |
| 808 | 979 | MainWP_DB::free_result( $fetch_one ); |
| 809 | 980 | |
| @@ -810,17 +981,18 @@ | ||
| 810 | 981 | if ( empty( $website ) ) { |
| 811 | 982 | return $this->get_rest_data_error( 'id', 'site' ); |
| 812 | 983 | } |
| 813 | 984 | |
| 814 | - if ( 1 === $website->suspended ) { | |
| 985 | + // Enforce business rules BEFORE checking abilities. | |
| 986 | + // This ensures consistent behavior regardless of whether Abilities API is available. | |
| 987 | + if ( 1 === (int) $website->suspended ) { | |
| 815 | 988 | return new \WP_Error( 'mainwp_rest_updates_site_error', __( 'Website suspended. Please unsuspended the website and try again.', 'mainwp' ), array( 'status' => 400 ) ); |
| 816 | - | |
| 817 | 989 | } |
| 818 | 990 | |
| 819 | 991 | $batch_individual_updates_running = get_option( 'mainwp_batch_individual_updates_is_running', 0 ); |
| 820 | 992 | $start_individual_time = get_option( 'mainwp_batch_updates_individual_start_time', 0 ); |
| 821 | 993 | |
| 822 | - // check if the site in batch updates queue. | |
| 994 | + // Check if the site is already in the batch updates queue. | |
| 823 | 995 | if ( $batch_individual_updates_running && ! empty( $website->batch_individual_queue_time ) && (int) $website->batch_individual_queue_time >= (int) $start_individual_time ) { |
| 824 | 996 | $datetime = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $start_individual_time ) ); |
| 825 | 997 | $resp_data = array( |
| 826 | 998 | 'success' => 1, |
| @@ -826,13 +998,61 @@ | ||
| 826 | 998 | 'success' => 1, |
| 827 | 999 | 'message' => esc_html__( 'A batch updates for the site are queuing to run.', 'mainwp' ), |
| 828 | 1000 | 'last_time_start_batch_updates' => mainwp_rest_prepare_date_response( $datetime ), |
| 829 | 1001 | 'site' => apply_filters( 'mainwp_rest_routes_sites_controller_filter_allowed_fields_by_context', $website, 'simple_view' ), |
| 1002 | + ); | |
| 1003 | + return rest_ensure_response( $resp_data ); | |
| 1004 | + } | |
| 830 | 1005 | |
| 1006 | + // Try abilities-first approach (with fallback to legacy logic). | |
| 1007 | + $ability = function_exists( 'wp_get_ability' ) ? wp_get_ability( 'mainwp/run-updates-v1' ) : null; | |
| 1008 | + | |
| 1009 | + if ( null !== $ability ) { | |
| 1010 | + // Build ability input for single-site update. | |
| 1011 | + // Empty types array means "all types". | |
| 1012 | + $ability_input = array( | |
| 1013 | + 'site_ids_or_domains' => array( (int) $website->id ), | |
| 1014 | + 'types' => array(), // All types. | |
| 831 | 1015 | ); |
| 832 | - return rest_ensure_response( $resp_data ); | |
| 1016 | + | |
| 1017 | + $result = $ability->execute( $ability_input ); | |
| 1018 | + | |
| 1019 | + if ( is_wp_error( $result ) ) { | |
| 1020 | + $error_data = $result->get_error_data(); | |
| 1021 | + $status = isset( $error_data['status'] ) ? $error_data['status'] : 500; | |
| 1022 | + return new \WP_Error( $result->get_error_code(), $result->get_error_message(), array( 'status' => $status ) ); | |
| 1023 | + } | |
| 1024 | + | |
| 1025 | + // Normalize site data through REST response filters for consistency. | |
| 1026 | + $site_filtered = apply_filters( 'mainwp_rest_routes_sites_controller_filter_allowed_fields_by_context', $website, 'simple_view' ); | |
| 1027 | + | |
| 1028 | + // Handle queued response (background job). | |
| 1029 | + if ( isset( $result['job_id'] ) ) { | |
| 1030 | + return rest_ensure_response( | |
| 1031 | + array( | |
| 1032 | + 'success' => 1, | |
| 1033 | + 'message' => esc_html__( 'Batch updates for the site queued successfully.', 'mainwp' ), | |
| 1034 | + 'job_id' => $result['job_id'], | |
| 1035 | + 'last_time_start_batch_updates' => mainwp_rest_prepare_date_response( current_time( 'mysql' ) ), | |
| 1036 | + 'site' => $site_filtered, | |
| 1037 | + ) | |
| 1038 | + ); | |
| 1039 | + } | |
| 1040 | + | |
| 1041 | + // Transform immediate results - extract first result from results array. | |
| 1042 | + $site_result = isset( $result['results'][0] ) ? $result['results'][0] : array(); | |
| 1043 | + return rest_ensure_response( | |
| 1044 | + array( | |
| 1045 | + 'success' => 1, | |
| 1046 | + 'message' => esc_html__( 'Batch updates for the site completed.', 'mainwp' ), | |
| 1047 | + 'summary' => isset( $site_result['summary'] ) ? $site_result['summary'] : array(), | |
| 1048 | + 'last_time_start_batch_updates' => mainwp_rest_prepare_date_response( current_time( 'mysql' ) ), | |
| 1049 | + 'site' => $site_filtered, | |
| 1050 | + ) | |
| 1051 | + ); | |
| 833 | 1052 | } |
| 834 | 1053 | |
| 1054 | + // Fallback: Legacy logic when Abilities API is not available. | |
| 835 | 1055 | // reload full data. |
| 836 | 1056 | $website = MainWP_DB::instance()->get_website_by_id( $website->id ); |
| 837 | 1057 | MainWP_Cron_Jobs_Batch::instance()->prepare_bulk_updates( $website ); |
| 838 | 1058 | |
| @@ -890,9 +1110,9 @@ | ||
| 890 | 1110 | $success = true; |
| 891 | 1111 | } elseif ( ! empty( $info['error'] ) ) { |
| 892 | 1112 | $error = esc_html( $error ); |
| 893 | 1113 | } else { |
| 894 | - $error = esc_html__( 'An undefined error occured. Please try again.', 'mainwp' ); | |
| 1114 | + $error = esc_html__( 'An undefined error occurred. Please try again.', 'mainwp' ); | |
| 895 | 1115 | } |
| 896 | 1116 | |
| 897 | 1117 | if ( ! empty( $info['old_version'] ) ) { |
| 898 | 1118 | $data['old_version'] = $info['old_version']; |
| @@ -1137,9 +1357,9 @@ | ||
| 1137 | 1357 | ); |
| 1138 | 1358 | } |
| 1139 | 1359 | |
| 1140 | 1360 | try { |
| 1141 | - MainWP_Connect::fetch_url_authed( | |
| 1361 | + $information = MainWP_Connect::fetch_url_authed( | |
| 1142 | 1362 | $website, |
| 1143 | 1363 | 'upgradetranslation', |
| 1144 | 1364 | array( |
| 1145 | 1365 | 'type' => 'translation', |
| @@ -1379,15 +1599,15 @@ | ||
| 1379 | 1599 | 'context' => array( 'view' ), |
| 1380 | 1600 | ), |
| 1381 | 1601 | 'plugins' => array( |
| 1382 | 1602 | 'type' => 'array', |
| 1383 | - 'description' => __( 'Plugins Updates.', 'mainwp' ), | |
| 1603 | + 'description' => __( 'Plugin Updates.', 'mainwp' ), | |
| 1384 | 1604 | 'validate_callback' => 'rest_validate_request_arg', |
| 1385 | 1605 | 'context' => array( 'view' ), |
| 1386 | 1606 | ), |
| 1387 | 1607 | 'themes' => array( |
| 1388 | 1608 | 'type' => 'array', |
| 1389 | - 'description' => __( 'Themes Updates.', 'mainwp' ), | |
| 1609 | + 'description' => __( 'Theme Updates.', 'mainwp' ), | |
| 1390 | 1610 | 'validate_callback' => 'rest_validate_request_arg', |
| 1391 | 1611 | 'context' => array( 'view' ), |
| 1392 | 1612 | ), |
| 1393 | 1613 | 'translation' => array( |