filter_response_data_by_allowed_fields( $this->prepare_item_for_response( $item, $request ), $context ); } /** * Get filter sites. * * @param string $context context. * * @return object item in context. */ public function hook_get_allowed_fields_by_context( $context = 'view' ) { return $this->get_allowed_fields_by_context( $context ); } /** * Method register_routes() * * Creates the necessary endpoints for the api. * Note, for a request to be successful the URL query parameters consumer_key and consumer_secret need to be set and correct. */ public function register_routes() { // phpcs:ignore -- NOSONAR - complex. register_rest_route( $this->namespace, '/' . $this->rest_base, array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_items' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/basic', array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_basic_items' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/count', array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'count_items' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/sync', array( array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'sync_items' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/reconnect', array( array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'reconnect_items' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/disconnect', array( array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'disconnect_sites' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/check', array( array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'check_items' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[\d]+)', array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_item' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), 'args' => array( 'id_domain' => array( 'description' => __( 'Site ID or domain.', 'mainwp' ), 'type' => 'string', ), ), ), 'schema' => array( $this, 'get_public_item_schema' ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[A-Za-z0-9-\.]*[A-Za-z0-9-]{1,63}\.[A-Za-z]{2,6}$)', array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_item' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), 'args' => array( 'id_domain' => array( 'description' => __( 'Site ID or domain.', 'mainwp' ), 'type' => 'string', ), ), ), 'schema' => array( $this, 'get_public_item_schema' ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/add', array( array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => array( $this, 'create_item' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-zA-Z0-9\-\.\_]+)/edit', array( array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'update_item' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-zA-Z0-9\-\.\_]+)/sync', array( array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'sync_item' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-zA-Z0-9\-\.\_]+)/security', array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'security_item' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-zA-Z0-9\-\.\_]+)/plugins', array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_site_plugins' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-zA-Z0-9\-\.\_]+)/plugins/activate', array( array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'activate_plugins_of_site' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-zA-Z0-9\-\.\_]+)/plugins/deactivate', array( array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'deactivate_plugins_of_site' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-zA-Z0-9\-\.\_]+)/plugins/delete', array( array( 'methods' => WP_REST_Server::DELETABLE, 'callback' => array( $this, 'delete_plugins_of_site' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), 'args' => $this->get_collection_params(), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-zA-Z0-9\-\.\_]+)/plugins/abandoned', array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_abandoned_plugins_of_site' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), 'args' => $this->get_collection_params(), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-zA-Z0-9\-\.\_]+)/themes', array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_site_themes' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-zA-Z0-9\-\.\_]+)/themes/activate', array( array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'activate_themes_of_site' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-zA-Z0-9\-\.\_]+)/themes/delete', array( array( 'methods' => WP_REST_Server::DELETABLE, 'callback' => array( $this, 'delete_themes_of_site' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-zA-Z0-9\-\.\_]+)/themes/abandoned', array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_abandoned_themes_of_site' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), 'args' => $this->get_collection_params(), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-zA-Z0-9\-\.\_]+)/non-mainwp-changes', array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_non_mainwp_changes_of_site' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), 'args' => $this->get_collection_params(), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-zA-Z0-9\-\.\_]+)/reconnect', array( array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'reconnect_item' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), 'args' => $this->get_collection_params(), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-zA-Z0-9\-\.\_]+)/disconnect', array( array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'disconnect_site' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), 'args' => $this->get_collection_params(), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-zA-Z0-9\-\.\_]+)/suspend', array( array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'suspend_item' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), 'args' => $this->get_collection_params(), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-zA-Z0-9\-\.\_]+)/unsuspend', array( array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'unsuspend_item' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), 'args' => $this->get_collection_params(), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-zA-Z0-9\-\.\_]+)/check', array( array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'check_item' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-zA-Z0-9\-\.\_]+)/remove', array( array( 'methods' => WP_REST_Server::DELETABLE, 'callback' => array( $this, 'delete_item' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), 'args' => $this->get_collection_params(), ), ) ); // Retrieves client Object for the site by site ID or Domain. register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-zA-Z0-9\-\.\_]+)/client', array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_client_site' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), 'args' => $this->get_collection_params(), ), ) ); // Retrieves costs for the site by ID or Domain. register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-zA-Z0-9\-\.\_]+)/costs', array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_costs_site' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), 'args' => $this->get_collection_params(), ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/batch', array( array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'batch_items' ), 'permission_callback' => array( $this, 'get_rest_permissions_check' ), 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ), ), 'schema' => array( $this, 'get_public_batch_schema' ), ) ); } /** * Get item. * * @param WP_REST_Request $request Request object. * * @return array|mixed Response data, ready for insertion into collection data. */ public function get_item( $request ) { $value = isset( $request['id_domain'] ) ? $request['id_domain'] : ''; $by = 'domain'; if ( is_numeric( $value ) ) { $by = 'id'; } else { $value = urldecode( $value ); } $with_tags = isset( $request['with_tags'] ) ? mainwp_string_to_bool( $request['with_tags'] ) : false; $prepared_args = array( 'with_tags' => $with_tags, ); $item = $this->get_site_by( $by, $value, $prepared_args ); if ( is_wp_error( $item ) ) { return $item; } $params = array( 'full_data' => true, 'selectgroups' => true, 'include' => array( $item->id ), 'fields' => $this->get_fields_for_response( $request ), ); $websites = MainWP_DB::instance()->get_websites_for_current_user( $params ); $data = $websites ? current( $websites ) : array(); if ( ! empty( $data ) ) { $data = $this->filter_response_data_by_allowed_fields( $this->prepare_item_for_response( $data, $request ), 'view' ); } return rest_ensure_response( array( 'data' => $data ) ); } /** * Get all sites. * * @param WP_REST_Request $request Full details about the request. * @return WP_Error|WP_REST_Response */ public function get_items( $request ) { $args = $this->prepare_objects_query( $request ); $args = $this->validate_rest_args( $args, $this->get_validate_args_params( 'get_sites' ) ); if ( is_wp_error( $args ) ) { return $args; } $args['selectgroups'] = isset( $request['with_tags'] ) ? mainwp_string_to_bool( $request['with_tags'] ) : true; $args['full_data'] = isset( $request['full_data'] ) ? mainwp_string_to_bool( $request['full_data'] ) : true; // get data. $websites = MainWP_DB::instance()->get_websites_for_current_user( $args ); $data = array(); if ( $websites ) { foreach ( $websites as $site ) { $data[] = $this->filter_response_data_by_allowed_fields( $this->prepare_item_for_response( $site, $request ), 'view' ); } } return rest_ensure_response( array( 'success' => 1, 'total' => count( $data ), 'data' => $data, ) ); } /** * Get all sites. * * @param WP_REST_Request $request Full details about the request. * @return WP_Error|WP_REST_Response */ public function get_basic_items( $request ) { $args = $this->prepare_objects_query( $request ); $args = $this->validate_rest_args( $args, $this->get_validate_args_params( 'get_sites' ) ); if ( is_wp_error( $args ) ) { return $args; } $args['selectgroups'] = isset( $request['with_tags'] ) ? mainwp_string_to_bool( $request['with_tags'] ) : false; $args['full_data'] = isset( $request['full_data'] ) ? mainwp_string_to_bool( $request['full_data'] ) : false; // get data. $websites = MainWP_DB::instance()->get_websites_for_current_user( $args ); $data = array(); if ( $websites ) { foreach ( $websites as $site ) { $data[] = $this->filter_response_data_by_allowed_fields( $this->prepare_item_for_response( $site, $request ), 'simple_view' ); } } return rest_ensure_response( array( 'success' => 1, 'total' => count( $data ), 'data' => $data, ) ); } /** * Get the query params for collections. * * @return array */ public function get_collection_params() { $params = array(); $params['context']['default'] = 'view'; return $params; } /** * Count all sites. * * @param WP_REST_Request $request Request object. * * @return WP_Error|WP_REST_Response */ public function count_items( $request ) { $args = $this->prepare_objects_query( $request ); $args = $this->validate_rest_args( $args, $this->get_validate_args_params( 'get_sites' ) ); if ( is_wp_error( $args ) ) { return $args; } $params = array( 'exclude' => isset( $args['exclude'] ) ? $args['exclude'] : array(), 'include' => isset( $args['include'] ) ? $args['include'] : array(), 'status' => isset( $args['status'] ) ? $args['status'] : array(), ); // get data. $websites = MainWP_DB::instance()->get_websites_for_current_user( $params ); $data = array( 'count' => count( $websites ), ); return rest_ensure_response( $data ); } /** * Sync sites. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|WP_REST_Response */ public function sync_item( $request ) { $website = $this->get_request_item( $request ); if ( is_wp_error( $website ) ) { return $website; } try { $success = MainWP_Sync::sync_site( $website ); } catch ( \Exception $e ) { return new WP_Error( 'mainwp_rest_sync_site_error', $e->getMessage(), array( 'status' => 404 ) ); } $data = array(); if ( $success ) { $params = array( 'full_data' => true, 'selectgroups' => true, 'include' => array( $website->id ), 'fields' => $this->get_fields_for_response( $request ), ); $websites = MainWP_DB::instance()->get_websites_for_current_user( $params ); $data = $websites ? current( $websites ) : array(); $data = $this->filter_response_data_by_allowed_fields( $this->prepare_item_for_response( $data, $request ), 'view' ); } return rest_ensure_response( array( 'success' => $success ? 1 : 0, 'data' => $data, ) ); } /** * Secure site info. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|WP_REST_Response */ public function security_item( $request ) { $website = $this->get_request_item( $request ); if ( is_wp_error( $website ) ) { return $website; } try { $result = MainWP_Connect::fetch_url_authed( $website, 'security' ); } catch ( \Exception $e ) { return new WP_Error( 'mainwp_rest_get_secure_site_error', $e->getMessage(), array( 'status' => 404 ) ); } $data = array( 'data' => $result, 'site' => $this->filter_response_data_by_allowed_fields( $website, 'simple_view' ), ); return rest_ensure_response( $data ); } /** * Get plugins of site. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|WP_REST_Response */ public function get_site_plugins( $request ) { //phpcs:ignore -- NOSONAR - complex. $website = $this->get_request_item( $request ); if ( is_wp_error( $website ) ) { return $website; } $args = $this->prepare_objects_query( $request ); $args = $this->validate_rest_args( $args, $this->get_validate_args_params( 'site_plugins' ) ); if ( is_wp_error( $args ) ) { return $args; } $data = json_decode( $website->plugins, 1 ); if ( is_array( $data ) ) { if ( ! empty( $args['must_use'] ) ) { $data = MainWP_Utility::get_sub_array_having( $data, 'mu', 1 ); } if ( ! empty( $args['s'] ) ) { $s = trim( $args['s'] ); if ( ! empty( $s ) ) { $data = mainwp_search_in_array( $data, $s, array( 'search_in_key' => false, 'in_sub_fields' => array( 'name', 'description', 'version', 'slug' ), 'use_index_result' => false, ) ); } } if ( ! empty( $args['status'] ) && is_array( $args['status'] ) && ! in_array( 'any', $args['status'] ) ) { $status_act = in_array( 'active', $args['status'] ) ? 1 : 0; $status_inact = in_array( 'inactive', $args['status'] ) ? 1 : 0; $status_val = false; if ( $status_act && $status_inact ) { $status_val = false; } elseif ( $status_act ) { $status_val = 1; } elseif ( $status_inact ) { $status_val = 0; } if ( false !== $status_val ) { $data = MainWP_Utility::get_sub_array_having( $data, 'active', $status_val ); } } if ( ! empty( $args['paged'] ) && ! empty( $args['items_per_page'] ) ) { $pag = (int) $args['paged']; $per = (int) $args['items_per_page']; $data = MainWP_Utility::get_sub_array_with_limit( $data, $per * ( $pag - 1 ), $per ); } } $resp_data = array( 'success' => 1, 'total' => is_array( $data ) ? count( $data ) : 0, 'data' => $data, 'site' => $this->filter_response_data_by_allowed_fields( $website, 'simple_view' ), ); return rest_ensure_response( $resp_data ); } /** * Handle plugins actions of site. * * @param object $website object. * @param string $action action. * @param string $slugs plugins slugs. * * @return WP_Error|array */ public function handle_plugins_actions_of_site( $website, $action, $slugs ) { try { $information = MainWP_Connect::fetch_url_authed( $website, 'plugin_action', array( 'action' => $action, 'plugin' => implode( '||', $slugs ), ) ); $success = false; $data = array(); if ( is_array( $information ) && isset( $information['other_data']['plugin_action_data'] ) ) { $action_data = $information['other_data']['plugin_action_data']; foreach ( $action_data as $item ) { $success = true; $item = MainWP_Utility::instance()->sanitize_data( $item ); if ( ! empty( $item ) && isset( $item['name'] ) ) { $data[] = array( 'name' => $item['name'], 'version' => $item['version'], 'slug' => $item['slug'], ); } } } return array( 'success' => $success ? 1 : 0, 'data' => $data, ); } catch ( \Exception $e ) { return new WP_Error( "mainwp_rest_{$action}_plugins_action", $e->getMessage() ); } } /** * Activate plugins of site. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|WP_REST_Response */ public function activate_plugins_of_site( $request ) { $website = $this->get_request_item( $request ); if ( is_wp_error( $website ) ) { return $website; } $slugs = isset( $request['slug'] ) ? array_map( 'trim', wp_parse_list( $request['slug'] ) ) : array(); if ( empty( $slugs ) ) { return new WP_Error( 'mainwp_rest_invalid_plugins_slugs', __( 'Plugins slugs are empty or invalid.', 'mainwp' ), 400 ); } $result = $this->handle_plugins_actions_of_site( $website, 'activate', $slugs ); if ( is_wp_error( $result ) ) { return $result; } $resp_data = array( 'success' => ! empty( $result['success'] ) ? 1 : 0, 'data' => ! empty( $result['data'] ) ? $result['data'] : array(), 'site' => $this->filter_response_data_by_allowed_fields( $website, 'simple_view' ), ); return rest_ensure_response( $resp_data ); } /** * Deactivate plugins of site. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|WP_REST_Response */ public function deactivate_plugins_of_site( $request ) { $website = $this->get_request_item( $request ); if ( is_wp_error( $website ) ) { return $website; } $slugs = isset( $request['slug'] ) ? array_map( 'trim', wp_parse_list( $request['slug'] ) ) : array(); if ( empty( $slugs ) ) { return new WP_Error( 'mainwp_rest_invalid_plugins_slugs', __( 'Plugins slug is empty or invalid.', 'mainwp' ), 400 ); } $result = $this->handle_plugins_actions_of_site( $website, 'deactivate', $slugs ); if ( is_wp_error( $result ) ) { return $result; } $resp_data = array( 'success' => ! empty( $result['success'] ) ? 1 : 0, 'data' => ! empty( $result['data'] ) ? $result['data'] : array(), 'site' => $this->filter_response_data_by_allowed_fields( $website, 'simple_view' ), ); return rest_ensure_response( $resp_data ); } /** * Delete plugins of site. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|WP_REST_Response */ public function delete_plugins_of_site( $request ) { $website = $this->get_request_item( $request ); if ( is_wp_error( $website ) ) { return $website; } $slugs = isset( $request['slug'] ) ? array_map( 'trim', wp_parse_list( $request['slug'] ) ) : array(); if ( empty( $slugs ) ) { return new WP_Error( 'mainwp_rest_invalid_plugins_slugs', __( 'Plugins slugs is empty or invalid.', 'mainwp' ), 400 ); } $result = $this->handle_plugins_actions_of_site( $website, 'delete', $slugs ); if ( is_wp_error( $result ) ) { return $result; } $resp_data = array( 'success' => ! empty( $result['success'] ) ? 1 : 0, 'data' => ! empty( $result['data'] ) ? $result['data'] : array(), 'site' => $this->filter_response_data_by_allowed_fields( $website, 'simple_view' ), ); return rest_ensure_response( $resp_data ); } /** * Get abandoned plugins of site. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|WP_REST_Response */ public function get_abandoned_plugins_of_site( $request ) { $website = $this->get_request_item( $request ); if ( is_wp_error( $website ) ) { return $website; } // get data. $data = MainWP_DB::instance()->get_website_option( $website, 'plugins_outdate_info' ); $data = ! empty( $data ) ? json_decode( $data, true ) : array(); $resp_data = array( 'success' => 1, 'total' => is_array( $data ) ? count( $data ) : 0, 'data' => $data, 'site' => $this->filter_response_data_by_allowed_fields( $website, 'simple_view' ), ); return rest_ensure_response( $resp_data ); } /** * Get themes of site. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|WP_REST_Response */ public function get_site_themes( $request ) { //phpcs:ignore - NOSONAR - complex. $website = $this->get_request_item( $request ); if ( is_wp_error( $website ) ) { return $website; } $args = $this->prepare_objects_query( $request ); $args = $this->validate_rest_args( $args, $this->get_validate_args_params( 'site_themes' ) ); if ( is_wp_error( $args ) ) { return $args; } if ( isset( $args['status'] ) ) { $args['status'] = array_unique( wp_parse_list( $args['status'] ) ); } $data = json_decode( $website->themes, 1 ); if ( is_array( $data ) ) { if ( ! empty( $args['s'] ) ) { $s = trim( $args['s'] ); if ( ! empty( $s ) ) { $data = mainwp_search_in_array( $data, $s, array( 'search_in_key' => false, 'in_sub_fields' => array( 'name', 'description', 'version', 'slug', 'title' ), 'use_index_result' => false, ) ); } } if ( ! empty( $args['status'] ) ) { $status_act = in_array( 'active', $args['status'] ) ? 1 : 0; $status_inact = in_array( 'inactive', $args['status'] ) ? 1 : 0; $status_val = false; if ( $status_act && $status_inact ) { $status_val = false; } elseif ( $status_act ) { $status_val = 1; } elseif ( $status_inact ) { $status_val = 0; } if ( false !== $status_val ) { $data = MainWP_Utility::get_sub_array_having( $data, 'active', $status_val ); } } if ( ! empty( $args['paged'] ) && ! empty( $args['items_per_page'] ) ) { $pag = (int) $args['paged']; $per = (int) $args['items_per_page']; $data = MainWP_Utility::get_sub_array_with_limit( $data, $per * ( $pag - 1 ), $per ); } } $resp_data = array( 'success' => 1, 'total' => is_array( $data ) ? count( $data ) : 0, 'data' => $data, 'site' => $this->filter_response_data_by_allowed_fields( $website, 'simple_view' ), ); return rest_ensure_response( $resp_data ); } /** * Handle plugins actions of site. * * @param object $website object. * @param string $action action. * @param string $slugs themes slugs. * * @return WP_Error|array */ public function handle_theme_actions_of_site( $website, $action, $slugs ) { //phpcs:ignore -- NOSONAR - complex. try { $information = MainWP_Connect::fetch_url_authed( $website, 'theme_action', array( 'action' => $action, 'theme' => $slugs, ) ); if ( ! is_array( $information ) ) { $information = array(); } $success = 0; $data = array(); if ( 'delete' === $action && is_array( $information ) && ! empty( $information['error']['is_activated_theme'] ) ) { $data['error'] = sprintf( esc_html__( 'The theme %s is active.', 'mainwp' ), $information['error']['is_activated_theme'] ); } if ( 'activate' === $action && isset( $information['other_data']['theme_deactivate_data'] ) ) { $success = 1; $act_slug = 'deactivate'; $data[ $act_slug ] = array(); $action_data = $information['other_data']['theme_deactivate_data']; foreach ( $action_data as $item ) { $success = true; $item = MainWP_Utility::instance()->sanitize_data( $item ); if ( ! empty( $item ) && isset( $item['name'] ) ) { $data[ $act_slug ] = array( 'name' => $item['name'], 'version' => $item['version'], 'slug' => $item['slug'], ); } } } if ( in_array( $action, array( 'activate', 'delete' ) ) && isset( $information['other_data']['theme_action_data'] ) ) { $success = 1; if ( 'activate' === $action ) { $act_slug = 'activate'; } else { $act_slug = 'delete'; } $data[ $act_slug ] = array(); $action_data = $information['other_data']['theme_action_data']; foreach ( $action_data as $item ) { $success = true; $item = MainWP_Utility::instance()->sanitize_data( $item ); if ( ! empty( $item ) && isset( $item['name'] ) ) { $data[ $act_slug ] = array( 'name' => $item['name'], 'version' => $item['version'], 'slug' => $item['slug'], ); } } } return array( 'success' => $success, 'data' => $data, ); } catch ( \Exception $e ) { return new WP_Error( "mainwp_rest_{$action}_plugins_action", $e->getMessage() ); } } /** * Activate themes of site. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|WP_REST_Response */ public function activate_themes_of_site( $request ) { $website = $this->get_request_item( $request ); if ( is_wp_error( $website ) ) { return $website; } $slugs = isset( $request['slug'] ) && is_string( $request['slug'] ) ? trim( $request['slug'] ) : ''; if ( empty( $slugs ) ) { return new WP_Error( 'mainwp_rest_invalid_themes_slugs', __( 'Theme slug is empty or invalid.', 'mainwp' ), 400 ); } $result = $this->handle_theme_actions_of_site( $website, 'activate', $slugs ); if ( is_wp_error( $result ) ) { return $result; } $resp_data = array( 'success' => ! empty( $result['success'] ) ? 1 : 0, 'data' => ! empty( $result['data'] ) ? $result['data'] : array(), 'site' => $this->filter_response_data_by_allowed_fields( $website, 'simple_view' ), ); return rest_ensure_response( $resp_data ); } /** * Delete themes of site. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|WP_REST_Response */ public function delete_themes_of_site( $request ) { $website = $this->get_request_item( $request ); if ( is_wp_error( $website ) ) { return $website; } $slugs = isset( $request['slug'] ) ? array_map( 'trim', wp_parse_list( $request['slug'] ) ) : array(); if ( empty( $slugs ) ) { return new WP_Error( 'mainwp_rest_invalid_themes_slugs', __( 'Theme slug is empty or invalid.', 'mainwp' ), 400 ); } $result = $this->handle_theme_actions_of_site( $website, 'delete', implode( '||', $slugs ) ); if ( is_wp_error( $result ) ) { return $result; } $resp_data = array( 'success' => ! empty( $result['success'] ) ? 1 : 0, 'data' => ! empty( $result['data'] ) ? $result['data'] : array(), 'site' => $this->filter_response_data_by_allowed_fields( $website, 'simple_view' ), ); return rest_ensure_response( $resp_data ); } /** * Get abandoned themes of site. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|WP_REST_Response */ public function get_abandoned_themes_of_site( $request ) { $website = $this->get_request_item( $request ); if ( is_wp_error( $website ) ) { return $website; } // get data. $data = MainWP_DB::instance()->get_website_option( $website, 'themes_outdate_info' ); $data = ! empty( $data ) ? json_decode( $data, true ) : array(); $resp_data = array( 'success' => 1, 'total' => is_array( $data ) ? count( $data ) : 0, 'data' => $data, 'site' => $this->filter_response_data_by_allowed_fields( $website, 'simple_view' ), ); return rest_ensure_response( $resp_data ); } /** * Get non-mainwp changes of site. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|WP_REST_Response */ public function get_non_mainwp_changes_of_site( $request ) { //phpcs:ignore -- NOSONAR -complex. $website = $this->get_request_item( $request ); if ( is_wp_error( $website ) ) { return $website; } $args = $this->prepare_objects_query( $request ); $params = array( 'wpid' => $website->id, 'where_extra' => ' AND dismiss = 0 ', 'order' => ! empty( $args['order'] ) ? sanitize_text_field( wp_unslash( $args['order'] ) ) : '', 'order_by' => ! empty( $args['orderby'] ) ? sanitize_text_field( wp_unslash( $args['orderby'] ) ) : '', 'source' => ! empty( $request['source'] ) ? sanitize_text_field( wp_unslash( $request['source'] ) ) : 'wpadmin', ); if ( ! empty( $args['paged'] ) && ! empty( $args['items_per_page'] ) ) { $params['rowcount'] = intval( $args['items_per_page'] ); $params['offset'] = ( (int) ( $args['paged'] ) - 1 ) * $params['rowcount']; } else { // support compatible api param. $limit = ! empty( $args['limit'] ) ? (int) ( $args['limit'] ) : 200; $params['rowcount'] = $limit; $params['offset'] = 0; } $params['actions'] = ! empty( $request['actions'] ) ? sanitize_text_field( wp_unslash( $request['actions'] ) ) : ''; $params['contexts'] = ! empty( $request['contexts'] ) ? sanitize_text_field( wp_unslash( $request['contexts'] ) ) : ''; $params['total_count'] = ! empty( $request['total_count'] ) ? mainwp_string_to_bool( $request['total_count'] ) : false; $data = MainWP_DB_Site_Actions::instance()->get_wp_actions( $params, $website ); if ( $params['total_count'] ) { $total = $data; $data = array( 'total' => $total ); } else { $total = is_array( $data ) ? count( $data ) : 0; } $resp_data = array( 'success' => 1, 'total' => $total, 'data' => $data, 'site' => $this->filter_response_data_by_allowed_fields( $website, 'simple_view' ), ); return rest_ensure_response( $resp_data ); } /** * Sync all sites. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|WP_REST_Response */ public function sync_items( $request ) { $args = $this->prepare_objects_query( $request ); $params = array( 'exclude' => isset( $args['exclude'] ) && ! empty( $args['exclude'] ) ? $args['exclude'] : array(), 'include' => isset( $args['include'] ) && ! empty( $args['include'] ) ? $args['include'] : array(), ); $data = array(); $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_for_current_user( false, null, 'wp.url', false, false, null, false, array( 'favi_icon' ), 'no', $params ) ); while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) { try { $ret = MainWP_Sync::sync_site( $website ); } catch ( \Exception $e ) { $ret = false; } $item = $this->filter_response_data_by_allowed_fields( $this->prepare_item_for_response( $website, $request ), 'view' ); $data[ $website->id ] = array_merge( array( 'result' => $ret ? 'success' : 'failed' ), $item ); } MainWP_DB::free_result( $websites ); update_option( 'mainwp_last_synced_all_sites', time() ); return rest_ensure_response( array( 'total' => count( $data ), 'data' => $data, ) ); } /** * Reconnect site. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|WP_REST_Response */ public function reconnect_item( $request ) { $website = $this->get_request_item( $request ); if ( is_wp_error( $website ) ) { return $website; } $resp_data = array(); try { $ret = MainWP_Manage_Sites_View::m_reconnect_site( $website ); $resp_data['success'] = $ret ? 1 : 0; } catch ( \Exception $e ) { // failed. return new \WP_Error( 'mainwp_rest_reconnect_site_error', sprintf( esc_html__( 'Reconnect Site "%d" error:', 'mainwp' ), $website->id ) . ': ' . $e->getMessage() ); } $website = $this->get_site_by( 'id', $website->id ); $resp_data['data'] = $this->filter_response_data_by_allowed_fields( $website, 'simple_view' ); return rest_ensure_response( $resp_data ); } /** * Reconnect sites. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|WP_REST_Response */ public function reconnect_items( $request ) { $args = $this->prepare_objects_query( $request ); $params = array( 'exclude' => isset( $args['exclude'] ) && ! empty( $args['exclude'] ) ? $args['exclude'] : array(), 'include' => isset( $args['include'] ) && ! empty( $args['include'] ) ? $args['include'] : array(), ); $data = array(); $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_for_current_user( false, null, 'wp.url', false, false, null, false, array( 'favi_icon' ), 'no', $params ) ); while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) && '' !== $website->sync_errors ) { $ret = false; try { $ret = MainWP_Manage_Sites_View::m_reconnect_site( $website ); } catch ( \Exception $e ) { // failed. } $data[ $website->id ] = $ret ? 'success' : 'failed'; } MainWP_DB::free_result( $websites ); return rest_ensure_response( array( 'total' => count( $data ), 'data' => $data, ) ); } /** * Disconnect site. * * @param WP_REST_Request $request Full details about the request. * * @return array|mixed Response data, ready for insertion into collection data. */ public function disconnect_site( $request ) { $website = $this->get_request_item( $request ); if ( is_wp_error( $website ) ) { return $website; } $data = $this->filter_response_data_by_allowed_fields( $website, 'simple_view' ); $success = 0; $error = ''; try { $info = MainWP_Connect::fetch_url_authed( $website, 'disconnect' ); $success = is_array( $info ) && isset( $info['result'] ) && 'success' === $info['result'] ? 1 : 0; $error = is_array( $info ) && ! empty( $info['error'] ) ? $info['error'] : ''; } catch ( \Exception $e ) { return new \WP_Error( 'mainwp_rest_disconnect_site_error', sprintf( esc_html__( 'Disconnect Site "%d" error:', 'mainwp' ), $website->id ) . ': ' . $e->getMessage() ); } $resp_data = array( 'success' => $success, 'data' => $data, ); if ( ! empty( $error ) ) { $resp_data['error'] = $error; } return rest_ensure_response( $resp_data ); } /** * Suspend site. * * @param WP_REST_Request $request Full details about the request. * * @return array|mixed Response data, ready for insertion into collection data. */ public function suspend_item( $request ) { $website = $this->get_request_item( $request ); if ( is_wp_error( $website ) ) { return $website; } $suspended = 1; if ( $website && ! $website->suspended ) { //phpcs:ignore -- to valid. $newValues = array( 'suspended' => $suspended, ); MainWP_DB::instance()->update_website_values( $website->id, $newValues ); /** * Fires immediately after website suspended/unsuspend. * * @since 4.5.2 * * @param object $website website data. * @param int $suspended The new suspended value. */ do_action( 'mainwp_site_suspended', $website, $suspended ); } $resp_data = array( 'success' => 1, 'suspended' => $suspended, 'data' => $this->filter_response_data_by_allowed_fields( $website, 'simple_view' ), ); return rest_ensure_response( $resp_data ); } /** * Unsuspend site. * * @param WP_REST_Request $request Full details about the request. * * @return array|mixed Response data, ready for insertion into collection data. */ public function unsuspend_item( $request ) { $website = $this->get_request_item( $request ); if ( is_wp_error( $website ) ) { return $website; } $suspended = 0; if ( $website && $website->suspended ) { //phpcs:ignore -- to valid. $newValues = array( 'suspended' => $suspended, ); MainWP_DB::instance()->update_website_values( $website->id, $newValues ); /** * Fires immediately after website suspended/unsuspend. * * @since 4.5.2 * * @param object $website website data. * @param int $suspended The new suspended value. */ do_action( 'mainwp_site_suspended', $website, $suspended ); } $resp_data = array( 'success' => 1, 'suspended' => $suspended, 'data' => $this->filter_response_data_by_allowed_fields( $website, 'simple_view' ), ); return rest_ensure_response( $resp_data ); } /** * Disconnect sites. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|WP_REST_Response */ public function disconnect_sites( $request ) { $args = $this->prepare_objects_query( $request ); $params = array( 'view' => 'base_view', 'exclude' => isset( $args['exclude'] ) && ! empty( $args['exclude'] ) ? $args['exclude'] : array(), 'include' => isset( $args['include'] ) && ! empty( $args['include'] ) ? $args['include'] : array(), ); $data = array(); $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_for_current_user_by_params( $params ) ); while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) { $info = false; try { $info = MainWP_Connect::fetch_url_authed( $website, 'disconnect' ); } catch ( \Exception $e ) { // ok. } $success = 0; if ( is_array( $info ) ) { $success = isset( $info['result'] ) ? 1 : 0; } $data[ $website->id ] = $success ? 'success' : 'failed'; } MainWP_DB::free_result( $websites ); return rest_ensure_response( array( 'total' => count( $data ), 'data' => $data, ) ); } /** * Check site. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|WP_REST_Response */ public function check_item( $request ) { $website = $this->get_request_item( $request ); if ( is_wp_error( $website ) ) { return $website; } $error = ''; try { $ret = MainWP_Monitoring_Handler::handle_check_website( $website ); } catch ( \Exception $e ) { $ret = false; $error = $e->getMessage(); } $resp_data = array( 'success' => $ret ? 1 : 0 ); $new_code = is_array( $ret ) && isset( $ret['httpCode'] ) ? $ret['httpCode'] : false; if ( ! empty( $error ) ) { $resp_data ['error'] = esc_html( $result ); } $data = $this->filter_response_data_by_allowed_fields( $website, 'simple_view' ); if ( false !== $new_code ) { if ( is_array( $result ) && isset( $result['new_uptime_status'] ) ) { $data['status'] = $result['new_uptime_status']; } else { $data['status'] = MainWP_Monitoring_Handler::get_site_checking_status( $new_code ); } $data['http_code'] = $new_code; } $resp_data['data'] = $data; return rest_ensure_response( $resp_data ); } /** * Check sites. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|WP_REST_Response */ public function check_items( $request ) { $args = $this->prepare_objects_query( $request ); $params = array( 'exclude' => isset( $args['exclude'] ) && ! empty( $args['exclude'] ) ? $args['exclude'] : array(), 'include' => isset( $args['include'] ) && ! empty( $args['include'] ) ? $args['include'] : array(), ); $data = array(); $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_for_current_user( false, null, 'wp.url', false, false, null, false, array( 'favi_icon' ), 'no', $params ) ); while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) { try { $ret = MainWP_Monitoring_Handler::handle_check_website( $website ); } catch ( \Exception $e ) { $ret = false; } $item = $this->filter_response_data_by_allowed_fields( $this->prepare_item_for_response( $website, $request ), 'view' ); $data[ $website->id ] = array_merge( array( 'result' => $ret ? 'success' : 'failed' ), $item ); } MainWP_DB::free_result( $websites ); return rest_ensure_response( array( 'total' => count( $data ), 'data' => $data, ) ); } /** * Remove site. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|WP_REST_Response */ public function delete_item( $request ) { $website = $this->get_request_item( $request ); if ( is_wp_error( $website ) ) { return $website; } $error = ''; $result = false; try { $result = MainWP_Manage_Sites_Handler::remove_wp_site( $website->id ); } catch ( MainWP_Extra_Exception $e ) { $error = $e->getMessage(); } $success = ( is_array( $result ) && isset( $result['result'] ) && ( 'success' === $result['result'] || 'removed' === $result['result'] ) ) ? 1 : 0; $resp_data = array( 'success' => $success, ); if ( is_array( $result ) && ! empty( $result['result'] ) ) { if ( 'success' === $result['result'] ) { $message = esc_html__( 'The site has been removed and the MainWP Child plugin has been disabled.', 'mainwp' ); } else { $message = esc_html__( 'The site has been removed. Please make sure that the MainWP Child plugin has been deactivated properly.', 'mainwp' ); } $resp_data['message'] = $message; } if ( ! empty( $error ) ) { $resp_data['error'] = $error; } $resp_data['data'] = $this->filter_response_data_by_allowed_fields( $website, 'simple_view' ); return rest_ensure_response( $resp_data ); } /** * Get client of site. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|WP_REST_Response */ public function get_client_site( $request ) { $website = $this->get_request_item( $request ); if ( is_wp_error( $website ) ) { return $website; } $client = false; if ( $website->client_id ) { $client = MainWP_DB_Client::instance()->get_wp_client_by( 'client_id', $website->client_id ); } $resp_data = array( 'success' => $client ? 1 : 0, ); if ( empty( $client ) ) { $resp_data['error'] = esc_html__( 'Client is not set or not found.', 'mainwp' ); } else { $resp_data['data'] = $client; } return rest_ensure_response( $resp_data ); } /** * Get costs of site. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|WP_REST_Response */ public function get_costs_site( $request ) { $website = $this->get_request_item( $request ); if ( is_wp_error( $website ) ) { return $website; } $resp_data = array( 'success' => 1, ); $costs = Cost_Tracker_DB::get_instance()->get_cost_tracker_by( 'site_id', $website->id ); if ( $costs ) { $data = Cost_Tracker_Rest_Api_Handle_V1::instance()->prepare_api_costs_data( $costs ); $resp_data['total'] = is_array( $data ) ? count( $data ) : 0; $resp_data['data'] = $data; } else { $resp_data['message'] = esc_html__( 'Cost not found.', 'mainwp' ); $resp_data['data'] = array(); } return rest_ensure_response( $resp_data ); } /** * Get site by. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|Object Item. */ public function get_request_item( $request ) { return $this->get_site_item( $request ); } /** * Get the location schema, conforming to JSON Schema. * * @since 3.5.0 * @return array */ public function get_item_schema() { //phpcs:ignore -- NOSONAR - long function. return array( '$schema' => 'http://json-schema.org/draft-04/schema#', 'title' => 'sites', 'type' => 'object', 'properties' => array( 'id' => array( 'type' => 'integer', 'description' => __( 'Site ID.', 'mainwp' ), 'context' => array( 'view', 'edit', 'simple_view' ), 'arg_options' => array( 'sanitize_callback' => 'wp_parse_id_list', ), ), 'name' => array( 'type' => 'string', 'description' => __( 'Site name.', 'mainwp' ), 'context' => array( 'view', 'edit', 'simple_view' ), 'arg_options' => array( 'sanitize_callback' => 'sanitize_text_field', ), ), 'url' => array( 'type' => 'string', 'description' => __( 'Site url.', 'mainwp' ), 'context' => array( 'view', 'edit', 'simple_view' ), 'arg_options' => array( 'sanitize_callback' => 'sanitize_text_field', ), ), 'tags' => array( // response as tags. 'type' => 'string', 'description' => __( 'Site tags.', 'mainwp' ), 'context' => array( 'view' ), ), 'note' => array( 'type' => 'string', 'description' => __( 'Site note.', 'mainwp' ), 'context' => array( 'view', 'edit' ), ), 'ip' => array( 'type' => 'string', 'description' => __( 'Site IP.', 'mainwp' ), 'context' => array( 'view' ), 'arg_options' => array( 'sanitize_callback' => 'sanitize_text_field', ), ), 'client_id' => array( 'type' => 'integer', 'default' => 0, 'description' => __( 'Client id', 'mainwp' ), 'context' => array( 'view', 'simple_view' ), ), 'is_staging' => array( 'type' => 'integer', 'default' => 0, 'description' => __( 'is staging', 'mainwp' ), 'context' => array( 'view' ), ), 'wp_version' => array( 'type' => 'string', 'default' => '', 'description' => __( 'wp version', 'mainwp' ), 'context' => array( 'view' ), ), 'php_version' => array( 'type' => 'string', 'default' => '', 'description' => __( 'php version', 'mainwp' ), 'context' => array( 'view' ), ), 'child_version' => array( 'type' => 'string', 'default' => '', 'description' => __( 'child version', 'mainwp' ), 'context' => array( 'view' ), ), 'mysql_version' => array( 'type' => 'string', 'default' => '', 'description' => __( 'mysql version', 'mainwp' ), 'context' => array( 'view' ), ), 'memory_limit' => array( 'type' => 'string', 'default' => '', 'description' => __( 'memory limit', 'mainwp' ), 'context' => array( 'view' ), ), 'database_size' => array( 'type' => 'string', 'default' => '', 'description' => __( 'Database size', 'mainwp' ), 'context' => array( 'view' ), ), 'active_theme' => array( 'type' => 'string', 'default' => '', 'description' => __( 'Active theme', 'mainwp' ), 'context' => array( 'view' ), ), 'status' => array( 'type' => array( 'string', 'array' ), 'default' => '', 'description' => __( 'Status', 'mainwp' ), 'context' => array( 'view' ), ), 'sync_errors' => array( 'type' => 'string', 'default' => '', 'description' => __( 'Sync errors', 'mainwp' ), 'context' => array( 'view' ), ), 'http_status' => array( 'type' => 'string', 'default' => '', 'description' => __( 'Http status', 'mainwp' ), 'context' => array( 'view' ), ), 'health_status' => array( 'type' => 'string', 'default' => '', 'description' => __( 'Health status', 'mainwp' ), 'context' => array( 'view' ), ), 'health_score' => array( 'type' => 'string', 'default' => '', 'description' => __( 'Health score', 'mainwp' ), 'context' => array( 'view' ), ), 'icon' => array( 'type' => 'string', 'default' => '', 'description' => __( 'Icon', 'mainwp' ), 'context' => array( 'view' ), ), 'last_sync' => array( 'type' => 'string', 'default' => '', 'description' => __( 'Last sync', 'mainwp' ), 'context' => array( 'view' ), ), 'plugins' => array( 'type' => array( 'string', 'array' ), 'default' => '', 'description' => __( 'Plugins', 'mainwp' ), 'context' => array( 'view' ), ), 'themes' => array( 'type' => array( 'string', 'array' ), 'default' => '', 'description' => __( 'Themes', 'mainwp' ), 'context' => array( 'view' ), ), 'last_post_time' => array( 'type' => 'string', 'default' => '', 'description' => __( 'Last post time', 'mainwp' ), 'context' => array( 'view' ), ), 'recent_posts' => array( 'type' => 'string', 'default' => '', 'description' => __( 'Recent posts', 'mainwp' ), 'context' => array( 'view' ), ), 'recent_pages' => array( 'type' => 'string', 'default' => '', 'description' => __( 'Recent pages', 'mainwp' ), 'context' => array( 'view' ), ), 'recent_comments' => array( 'type' => 'string', 'default' => '', 'description' => __( 'Recent comments', 'mainwp' ), 'context' => array( 'view' ), ), 'categories' => array( 'type' => 'string', 'default' => '', 'description' => __( 'Categories', 'mainwp' ), 'context' => array( 'view' ), ), 'wp_upgrades' => array( 'type' => 'string', 'default' => '', 'context' => array( 'view' ), ), 'plugin_upgrades' => array( 'type' => 'string', 'default' => '', 'context' => array( 'view' ), ), 'premium_upgrades' => array( 'type' => 'string', 'default' => '', 'context' => array( 'view' ), ), 'theme_upgrades' => array( 'type' => 'string', 'default' => '', 'context' => array( 'view' ), ), 'translation_upgrades' => array( 'type' => 'string', 'default' => '', 'context' => array( 'view' ), ), 'ignored_plugins' => array( 'type' => 'string', 'default' => '', 'context' => array( 'view' ), ), 'ignored_themes' => array( 'type' => 'string', 'default' => '', 'context' => array( 'view' ), ), 'automatic_update' => array( 'type' => 'integer', 'default' => 0, 'description' => __( 'Automatic update', 'mainwp' ), 'context' => array( 'edit' ), 'enum' => array( 0, 1 ), 'arg_options' => array( 'sanitize_callback' => 'absint', ), ), 'http_user' => array( 'type' => 'string', 'description' => __( 'HTTP user', 'mainwp' ), 'context' => array( 'view', 'edit' ), 'arg_options' => array( 'sanitize_callback' => 'sanitize_text_field', ), ), 'http_pass' => array( 'type' => 'string', 'description' => __( 'HTTP password', 'mainwp' ), 'context' => array( 'view', 'edit' ), // no need to sanitize pass. ), 'uniqueId' => array( 'type' => 'string', 'default' => '', 'context' => array( 'view' ), ), 'disable_health_check' => array( 'type' => 'integer', 'default' => 0, 'description' => __( 'Disable health check', 'mainwp' ), 'context' => array( 'edit' ), 'enum' => array( 0, 1 ), 'arg_options' => array( 'sanitize_callback' => 'absint', ), ), 'health_threshold' => array( 'type' => 'integer', 'default' => 0, 'description' => __( 'Health threshold', 'mainwp' ), 'context' => array( 'edit' ), 'arg_options' => array( 'sanitize_callback' => 'absint', ), ), 'is_ignoreCoreUpdates' => array( 'type' => 'string', 'default' => '', 'context' => array( 'view' ), ), 'is_ignorePluginUpdates' => array( 'type' => 'string', 'default' => '', 'context' => array( 'view' ), ), 'is_ignoreThemeUpdates' => array( 'type' => 'string', 'default' => '', 'context' => array( 'view' ), ), 'verify_certificate' => array( 'type' => 'string', 'default' => '', 'context' => array( 'view' ), ), 'force_use_ipv4' => array( 'type' => 'string', 'default' => '', 'context' => array( 'view' ), ), 'ssl_version' => array( 'type' => 'string', 'default' => '', 'context' => array( 'view' ), ), 'suspended' => array( 'type' => 'integer', 'default' => 0, 'description' => __( 'Suspended', 'mainwp' ), 'context' => array( 'view', 'edit' ), 'enum' => array( 0, 1 ), 'arg_options' => array( 'sanitize_callback' => 'absint', ), ), ), ); } /** * Prepare a single order for create or update. * * @throws MainWP_Rest_Data_Exception When fails to set any item. * @param WP_REST_Request $request Request object. * @return array */ protected function prepare_object_for_database( $request ) { $item_fields = array(); $item_fields['url'] = isset( $request['url'] ) ? sanitize_text_field( wp_unslash( $request['url'] ) ) : ''; $item_fields['name'] = isset( $request['name'] ) ? sanitize_text_field( wp_unslash( $request['name'] ) ) : ''; $item_fields['wpadmin'] = isset( $request['admin'] ) ? sanitize_text_field( wp_unslash( $request['admin'] ) ) : ''; $item_fields['adminpwd'] = isset( $request['adminpassword'] ) ? wp_unslash( $request['adminpassword'] ) : ''; $item_fields['unique_id'] = isset( $request['uniqueid'] ) ? sanitize_text_field( wp_unslash( $request['uniqueid'] ) ) : ''; $item_fields['ssl_verify'] = empty( $request['ssl_verify'] ) ? false : intval( $request['ssl_verify'] ); $item_fields['force_use_ipv4'] = isset( $request['force_use_ipv4'] ) && mainwp_string_to_bool( $request['force_use_ipv4'] ) ? 1 : 0; $item_fields['http_user'] = isset( $request['http_user'] ) ? sanitize_text_field( wp_unslash( $request['http_user'] ) ) : ''; $item_fields['http_pass'] = isset( $request['http_pass'] ) ? wp_unslash( $request['http_pass'] ) : ''; $item_fields['groupids'] = isset( $request['groupids'] ) && ! empty( $request['groupids'] ) ? explode( ',', sanitize_text_field( wp_unslash( $request['groupids'] ) ) ) : array(); /** * Filters an object before it is inserted via the REST API. * * @since 5.2 * * @param array $item_fields Site data. * @param WP_REST_Request $request Request object. */ return apply_filters( 'mainwp_rest_pre_insert_site_item', $item_fields, $request ); } /** * Prepare a single order for create or update. * * @param WP_REST_Request $request Request object. * @return array */ protected function prepare_object_for_update( $request ) { $map_fields_update = array( 'http_user' => 'http_user', 'http_pass' => 'http_pass', 'name' => 'name', 'adminname' => 'admin', 'ssl_version' => 'sslversion', 'uniqueId' => 'uniqueid', 'protocol' => 'protocol', 'disable_health_check' => 'disablehealthchecking', 'health_threshold' => 'healththreshold', 'suspended' => 'suspended', 'groupids' => 'groupids', 'automatic_update' => 'automatic_update', 'backup_before_upgrade' => 'backup_before_upgrade', 'force_use_ipv4' => 'force_use_ipv4', 'is_ignoreCoreUpdates' => 'ignore_core_updates', 'is_ignorePluginUpdates' => 'ignore_plugin_updates', 'is_ignoreThemeUpdates' => 'ignore_theme_updates', 'monitoring_emails' => 'monitoring_emails', ); $data = array(); foreach ( $map_fields_update as $field ) { if ( isset( $request[ $field ] ) ) { $data[ $field ] = $request[ $field ]; } } /** * Filters an object before it is inserted via the REST API. * * @since 5.2 * * @param array $item_fields Site data. * @param WP_REST_Request $request Request object. */ return apply_filters( 'mainwp_rest_pre_update_site_item', $data, $request ); } /** * Get formatted item object. * * @since 5.2 * @param object $site_object Site object. * @param array $args Request args. * * @return array */ protected function get_pre_formatted_item_data( $site_object, $args = array() ) { $fields = false; // Determine if the response fields were specified. if ( ! empty( $this->request['_fields'] ) ) { $fields = wp_parse_list( $this->request['_fields'] ); if ( 0 === count( $fields ) ) { $fields = false; } else { $fields = array_map( 'trim', $fields ); } } $extra_fields = array(); $extra_fields = false === $fields ? $extra_fields : array_intersect( $extra_fields, $fields ); $formatted_data = array( 'id' => $site_object->id, 'url' => $site_object->url, 'name' => $site_object->name, 'client_id' => $site_object->client_id, ); if ( ! empty( $args['selectgroups'] ) ) { $formatted_data['wpgroups'] = $site_object->wpgroups; } if ( ! empty( $args['full_data'] ) ) { $formatted_extra = array( 'id' => $site_object->id, 'url' => $site_object->url, 'name' => $site_object->name, 'offline_checks_last' => $site_object->offline_checks_last, 'offline_check_result' => $site_object->offline_check_result, // 1 - online, -1 offline. 'http_response_code' => $site_object->http_response_code, 'disable_health_check' => $site_object->disable_health_check, 'health_threshold' => $site_object->health_threshold, 'note' => $site_object->note, 'plugin_upgrades' => $site_object->plugin_upgrades, 'theme_upgrades' => $site_object->theme_upgrades, 'translation_upgrades' => $site_object->translation_upgrades, 'securityIssues' => $site_object->securityIssues, 'themes' => $site_object->themes, 'plugins' => $site_object->plugins, 'automatic_update' => ! empty( $site_object->automatic_update ) ? $site_object->automatic_update : 0, 'sync_errors' => $site_object->sync_errors, 'last_post_gmt' => $site_object->last_post_gmt, 'health_value' => $site_object->health_value, 'phpversion' => $site_object->phpversion, 'wp_upgrades' => $site_object->wp_upgrades, 'security_stats' => $site_object->security_stats, 'client_id' => $site_object->client_id, 'adminname' => $site_object->adminname, 'http_user' => $site_object->http_user, 'http_pass' => $site_object->http_pass, 'ssl_version' => $site_object->ssl_version, 'signature_algo' => $site_object->signature_algo, 'verify_method' => $site_object->verify_method, 'verify_certificate' => $site_object->verify_certificate, ); $format_date = array( 'dtsAutomaticSync', 'dtsAutomaticSyncStart', 'dtsSync', 'dtsSyncStart' ); // Format date values. foreach ( $format_date as $key ) { // Date created is stored UTC, date modified is stored WP local time. $datetime = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $site_object->$key ) ); $formatted_extra[ $key ] = mainwp_rest_prepare_date_response( $datetime, false ); } $formatted_data = array_merge( $formatted_data, $formatted_extra ); } return $formatted_data; } /** * Prepare a single product review output for response. * * @param object $item site object. * @param WP_REST_Request $request Request object. * @param array $args args. * * @return WP_REST_Response $response Response data. */ public function prepare_item_for_response( $item, $request, $args = array() ) { //phpcs:ignore -- NOSONAR - complex. if ( ! is_object( $item ) ) { $item = new \stdClass(); } $fields = $this->get_fields_for_response( $request ); if ( ! is_array( $fields ) ) { $fields = array(); } $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; $data = $this->filter_response_by_context( $item, $context ); if ( is_object( $data ) ) { $_data = array(); foreach ( $data as $field => $value ) { $_data[ $field ] = $value; } $data = $_data; } if ( in_array( 'tags', $fields ) && property_exists( $item, 'wpgroups' ) && property_exists( $item, 'wpgroupids' ) ) { $wpgroupids = ! empty( $item->wpgroupids ) ? explode( ',', $item->wpgroupids ) : array(); $wpgroups = ! empty( $item->wpgroups ) ? explode( ',', $item->wpgroups ) : array(); $tags = array(); if ( is_array( $wpgroupids ) ) { foreach ( $wpgroupids as $gidx => $groupid ) { if ( $groupid && ! isset( $tags[ $groupid ] ) ) { $tags[ $groupid ] = isset( $wpgroups[ $gidx ] ) ? $wpgroups[ $gidx ] : ''; } } } $data['tags'] = $tags; } $map_fields = array( 'database_size' => 'dbsize', 'http_status' => 'http_response_code', 'health_score' => 'health_value', 'icon' => 'cust_site_icon_info', 'last_sync' => 'dtsSync', 'last_post_time' => 'last_post_gmt', ); if ( is_array( $data ) ) { foreach ( $map_fields as $field1 => $field2 ) { if ( in_array( $field1, $fields ) && property_exists( $item, $field2 ) ) { $data[ $field1 ] = $item->{$field2}; } } } $website_info = MainWP_DB::instance()->get_website_option( $item->id, 'site_info' ); $website_info = ! empty( $website_info ) ? json_decode( $website_info, true ) : array(); if ( is_array( $website_info ) && property_exists( $item, 'http_response_code' ) ) { $code = $item->http_response_code; $code_string = MainWP_Utility::get_http_codes( $code ); if ( ! empty( $code_string ) ) { $code .= ' - ' . $code_string; } $website_info['http_status'] = $code; } $map_meta_fields = array( 'wp_version' => 'wpversion', 'php_version' => 'phpversion', 'child_version' => 'child_version', 'mysql_version' => 'mysql_version', 'memory_limit' => 'memory_limit', 'http_status' => 'http_status', ); foreach ( $map_meta_fields as $_field1 => $_field2 ) { if ( in_array( $_field1, $fields ) ) { $data[ $_field1 ] = isset( $website_info[ $_field2 ] ) ? $website_info[ $_field2 ] : ''; } } if ( in_array( 'active_theme', $fields ) ) { $active_theme = array(); if ( ! empty( $item->themes ) ) { $themes = json_decode( $item->themes, 1 ); if ( is_array( $themes ) && ! empty( $themes ) ) { foreach ( $themes as $theme ) { if ( ! empty( $theme['active'] ) ) { $active_theme = $theme; break; } } } } $data['active_theme'] = is_array( $active_theme ) && ! empty( $active_theme['name'] ) ? esc_html( $active_theme['name'] . ' ' . $active_theme['version'] ) : ''; } if ( in_array( 'status', $fields ) ) { $data['status'] = ! empty( $item->sync_errors ) ? 'disconnected' : 'connected'; if ( $item->suspended ) { $data['status'] = 'suspended'; } } if ( is_array( $fields ) && ! empty( $fields ) ) { $_data = array(); foreach ( $data as $field => $value ) { if ( in_array( $field, $fields ) ) { $_data[ $field ] = $value; } } $data = $_data; } if ( isset( $data['last_sync'] ) ) { $data['last_sync'] = mainwp_rest_prepare_date_response( $data['last_sync'] ); } /** * Filterobject returned from the REST API. * * @param array $data The object. * @param mixed $item The object used to create response. * @param WP_REST_Request $request Request object. */ return apply_filters( 'mainwp_rest_prepare_site', $data, $item, $request ); } /** * Add Site. * * @since 5.2 * @throws Exception But all errors are validated before returning any data. * * @param WP_REST_Request $request Full details about the request. * * @return WP_Error|WP_REST_Response */ public function create_item( $request ) { //phpcs:ignore -- NOSONAR - complex. $resp_data = array(); $resp_data['success'] = 0; $site_id = 0; $url = ''; $data = array(); //phpcs:ignore -- NOSONAR - not used data. $found_id = 0; try { $item = $this->prepare_object_for_database( $request ); if ( empty( $item['name'] ) && ! empty( $item['url'] ) ) { $item['name'] = MainWP_Utility::remove_http_prefix( $item['url'], true ); $item['name'] = rtrim( $item['name'], '/' ); } $url = $item['url']; $website = MainWP_DB::instance()->get_websites_by_url( $item['url'] ); list( $message, $error, $site_id, $found_id ) = MainWP_Manage_Sites_View::add_wp_site( $website, $item ); if ( ! empty( $site_id ) ) { $site = MainWP_DB::instance()->get_website_by_id( $site_id ); $resp_data['success'] = 1; $resp_data['data'] = $this->filter_response_data_by_allowed_fields( $site, 'simple_view' ); if ( ! empty( $message ) ) { $resp_data['message'] = wp_strip_all_tags( $message ); } } elseif ( ! empty( $error ) ) { $resp_data['error'] = wp_strip_all_tags( $error ); } else { $resp_data['error'] = esc_html__( 'Add site failed. Please try again.', 'mainwp' ); } } catch ( Exception $e ) { $resp_data['error'] = wp_strip_all_tags( $e->getMessage() ); } $user = $this->get_rest_api_user(); $is_dashboard_connect = ! empty( $user ) && 1 === (int) $user->key_type ? true : false; if ( $is_dashboard_connect ) { if ( ! empty( $resp_data['error'] ) ) { MainWP_Logger::instance()->log_action( 'Dashboard Connect add Site :: [url=' . $url . '] :: [result=Failed] :: [error=' . esc_html( $resp_data['error'] ) . ']', MainWP_Logger::CONNECT_LOG_PRIORITY ); } elseif ( ! empty( $resp_data['success'] ) ) { MainWP_Logger::instance()->log_action( 'Dashboard Connect add Site :: [url=' . $url . '] :: [result=Success]', MainWP_Logger::CONNECT_LOG_PRIORITY ); } } if ( ! empty( $found_id ) ) { $resp_data['found_id'] = $found_id; // if found connected and is dashboard connect request then try to reconnect to prevent incorrect connection. if ( $is_dashboard_connect ) { $reconnect = false; $site = MainWP_DB::instance()->get_website_by_id( $found_id ); try { $reconnect = MainWP_Manage_Sites_View::m_reconnect_site( $site ); $resp_data['reconnect_success'] = $reconnect ? 1 : 0; } catch ( \Exception $e ) { // failed. $resp_data['reconnect_error'] = $e->getMessage(); } MainWP_Logger::instance()->log_action( 'Dashboard Connect reconnect site :: [url=' . $url . '] :: [result=' . ( $reconnect ? 'success' : 'failed' ) . ']', MainWP_Logger::CONNECT_LOG_PRIORITY ); } } return rest_ensure_response( $resp_data ); } /** * Update site. * * @param WP_REST_Request $request Request object. * * @return WP_Error|WP_REST_Response */ public function update_item( $request ) { $website = $this->get_request_item( $request ); if ( is_wp_error( $website ) ) { return $website; } $resp_data = array(); $resp_data['success'] = 0; try { $item = $this->prepare_object_for_update( $request ); $result = MainWP_DB_Common::instance()->rest_api_update_website( $website->id, $item ); if ( is_array( $result ) && ! empty( $result['success'] ) ) { $resp_data['success'] = 1; $params = array( 'full_data' => true, 'selectgroups' => true, 'include' => array( $website->id ), 'fields' => $this->get_fields_for_response( $request ), ); $websites = MainWP_DB::instance()->get_websites_for_current_user( $params ); $data = $websites ? current( $websites ) : array(); $resp_data['data'] = $this->filter_response_data_by_allowed_fields( $this->prepare_item_for_response( $data, $request ), 'view' ); } else { $resp_data['error'] = esc_html__( 'Update site failed. Please try again.', 'mainwp' ); } } catch ( \Exception $e ) { $resp_data['error'] = $e->getMessage(); } return rest_ensure_response( $resp_data ); } }