Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
49.25% covered (danger)
49.25%
33 / 67
20.00% covered (danger)
20.00%
1 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
REST_Recommendations_Evaluation
49.25% covered (danger)
49.25%
33 / 67
20.00% covered (danger)
20.00%
1 / 5
39.61
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
33 / 33
100.00% covered (success)
100.00%
1 / 1
1
 permissions_callback
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
6
 evaluate_site_recommendations
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
42
 save_evaluation_recommendations
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
 dismiss_evaluation_recommendations
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2/**
3 * Sets up the Evaluation Recommendations REST API endpoints.
4 *
5 * @package automattic/my-jetpack
6 */
7
8namespace Automattic\Jetpack\My_Jetpack;
9
10use Automattic\Jetpack\Connection\Client;
11use Automattic\Jetpack\Connection\Manager as Connection_Manager;
12use WP_Error;
13
14/**
15 * Registers the REST routes for Evaluation Recommendations.
16 *
17 * @phan-constructor-used-for-side-effects
18 */
19class REST_Recommendations_Evaluation {
20    /**
21     * Constructor.
22     */
23    public function __construct() {
24        register_rest_route(
25            'my-jetpack/v1',
26            '/site/recommendations/evaluation/',
27            array(
28                array(
29                    'methods'             => \WP_REST_Server::READABLE,
30                    'callback'            => __CLASS__ . '::evaluate_site_recommendations',
31                    'permission_callback' => __CLASS__ . '::permissions_callback',
32                ),
33            )
34        );
35
36        register_rest_route(
37            'my-jetpack/v1',
38            '/site/recommendations/evaluation/result/',
39            array(
40                array(
41                    'methods'             => \WP_REST_Server::EDITABLE,
42                    'callback'            => __CLASS__ . '::save_evaluation_recommendations',
43                    'permission_callback' => __CLASS__ . '::permissions_callback',
44                ),
45            )
46        );
47
48        register_rest_route(
49            'my-jetpack/v1',
50            '/site/recommendations/evaluation/result/',
51            array(
52                array(
53                    'methods'             => \WP_REST_Server::DELETABLE,
54                    'callback'            => __CLASS__ . '::dismiss_evaluation_recommendations',
55                    'permission_callback' => __CLASS__ . '::permissions_callback',
56                ),
57            )
58        );
59    }
60
61    /**
62     * Check user capability to access the endpoint.
63     *
64     * @access public
65     * @static
66     *
67     * @return true|WP_Error
68     */
69    public static function permissions_callback() {
70        $connection        = new Connection_Manager();
71        $is_site_connected = $connection->is_connected();
72
73        if ( ! $is_site_connected ) {
74            return new WP_Error(
75                'not_connected',
76                __( 'Your site is not connected to Jetpack.', 'jetpack-my-jetpack' ),
77                array(
78                    'status' => 400,
79                )
80            );
81        }
82
83        return true; // We require site to be connected.
84    }
85
86    /**
87     * Recommendations Evaluation endpoint.
88     *
89     * @param \WP_REST_Request $request Query request.
90     *
91     * @return \WP_REST_Response|WP_Error of 3 product slugs (recommendations).
92     */
93    public static function evaluate_site_recommendations( $request ) {
94        $goals = $request->get_param( 'goals' );
95
96        if ( ! isset( $goals ) ) {
97            return new WP_Error( 'missing_goals', 'Goals are required', array( 'status' => 400 ) );
98        }
99
100        $site_id        = \Jetpack_Options::get_option( 'id' );
101        $wpcom_endpoint = sprintf( '/sites/%1$d/jetpack-recommendations/evaluation?goals=%2$s', $site_id, implode( ',', $goals ) );
102        $response       = Client::wpcom_json_api_request_as_blog( $wpcom_endpoint, '2', array(), null, 'wpcom' );
103        $response_code  = wp_remote_retrieve_response_code( $response );
104        $body           = json_decode( wp_remote_retrieve_body( $response ) );
105
106        if ( is_wp_error( $response ) || empty( $body ) || 200 !== $response_code ) {
107            return new WP_Error( 'recommendations_evaluation_fetch_failed', 'Evaluation processing failed', array( 'status' => $response_code ? $response_code : 400 ) );
108        }
109
110        return rest_ensure_response( $body );
111    }
112
113    /**
114     * Endpoint to save recommendations results.
115     *
116     * @param \WP_REST_Request $request Query request.
117     *
118     * @return \WP_REST_Response|WP_Error success response.
119     */
120    public static function save_evaluation_recommendations( $request ) {
121        $json = $request->get_json_params();
122
123        if ( ! isset( $json['recommendations'] ) ) {
124            return new WP_Error( 'missing_recommendations', 'Recommendations are required', array( 'status' => 400 ) );
125        }
126
127        \Jetpack_Options::update_option( 'recommendations_evaluation', $json['recommendations'] );
128        \Jetpack_Options::delete_option( 'dismissed_recommendations' );
129
130        return rest_ensure_response( Initializer::get_recommended_modules() );
131    }
132
133    /**
134     * Endpoint to dismiss the recommendation section
135     *
136     * @param \WP_REST_Request $request Query request.
137     *
138     * @return \WP_REST_Response|WP_Error success response.
139     */
140    public static function dismiss_evaluation_recommendations( $request ) {
141        $show_welcome_banner = $request->get_param( 'showWelcomeBanner' );
142
143        \Jetpack_Options::update_option( 'dismissed_recommendations', true );
144
145        if ( isset( $show_welcome_banner ) && $show_welcome_banner === 'true' ) {
146            \Jetpack_Options::update_option( 'recommendations_first_run', false );
147            \Jetpack_Options::delete_option( 'dismissed_welcome_banner' );
148        }
149
150        return rest_ensure_response( array() );
151    }
152}