Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 43
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
Send_Request
0.00% covered (danger)
0.00%
0 / 43
0.00% covered (danger)
0.00%
0 / 6
210
0.00% covered (danger)
0.00%
0 / 1
 name
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 request_methods
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 maybe_get_json
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 response
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 1
12
 get_transport_function
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
20
 permissions
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
1<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2
3namespace Automattic\Jetpack_Inspect\REST_API\Endpoints;
4
5use Automattic\Jetpack_Inspect\Monitors;
6use Automattic\Jetpack_Inspect\REST_API\Permissions\Current_User_Admin;
7use WP_Error;
8use WP_REST_Request;
9use WP_REST_Server;
10
11/**
12 * Request sender endpoint class.
13 */
14class Send_Request {
15
16    /**
17     * Returns the endpoint name.
18     */
19    public function name() {
20        return 'send-request';
21    }
22
23    /**
24     * Returns the endpoint read/write setting.
25     */
26    public function request_methods() {
27        return WP_REST_Server::EDITABLE;
28    }
29
30    /**
31     * Returns a parsed value from a JSON string, or throws.
32     *
33     * @param String $value JSON value.
34     */
35    public function maybe_get_json( $value ) {
36
37        if ( ! is_string( $value ) ) {
38            return $value;
39        }
40
41        try {
42            return json_decode( $value, true, 512, JSON_THROW_ON_ERROR );
43        } catch ( \Exception $e ) {
44            if ( '' === $value ) {
45                return array();
46            }
47        }
48        return $value;
49    }
50
51    /**
52     * Handle the request and return the response.
53     *
54     * @param WP_REST_Request $request request.
55     */
56    public function response( $request ) {
57
58        $body    = $request->get_param( 'body' );
59        $headers = $request->get_param( 'headers' );
60        $method  = $request->get_param( 'method' );
61        $url     = $request->get_param( 'url' );
62
63        $headers = $this->maybe_get_json( $headers );
64        $body    = $this->maybe_get_json( $body );
65
66        $args = array(
67            'method'  => $method,
68            'body'    => $body,
69            'headers' => $headers,
70        );
71
72        $function = $this->get_transport_function( $request );
73        if ( is_wp_error( $function ) ) {
74            return rest_ensure_response( $function );
75        }
76        '@phan-var callable-string $function'; // Alas Phan doesn't have `@phan-assert-if-true`, so it can't know how `is_wp_error()` works. See https://github.com/phan/phan/issues/3127.
77
78        $monitor = Monitors::get( 'outgoing' );
79        if ( is_wp_error( $monitor ) ) {
80            return rest_ensure_response( $monitor );
81        }
82
83        $monitor->ensure_enabled();
84        $results = $function( $url, $args, );
85
86        return rest_ensure_response( $results );
87    }
88
89    /**
90     * Returns transport function name.
91     *
92     * @param WP_REST_Request $request request.
93     * @return callable-string|WP_Error
94     */
95    private function get_transport_function( $request ) {
96        $transport_name       = $request->get_param( 'transport' ) ?? 'wp_remote_request';
97        $available_transports = array(
98            'jetpack_connection' => 'jetpack_inspect_request',
99            'wp'                 => 'wp_remote_request',
100        );
101
102        if ( isset( $available_transports[ $transport_name ] ) ) {
103            $function = $available_transports[ $transport_name ];
104        }
105
106        if ( ! isset( $function ) || ! function_exists( $function ) ) {
107            return new \WP_Error( 'Invalid Request Type' );
108        }
109
110        return $function;
111    }
112
113    /**
114     * Returns access permissions for the endpoint.
115     */
116    public function permissions() {
117        return array(
118            new Current_User_Admin(),
119        );
120    }
121}