Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 237
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
WP_REST_Help_Center_Odie
0.00% covered (danger)
0.00%
0 / 237
0.00% covered (danger)
0.00%
0 / 6
110
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 register_rest_route
0.00% covered (danger)
0.00%
0 / 163
0.00% covered (danger)
0.00%
0 / 1
2
 send_chat_message
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
6
 get_chat
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
6
 save_chat_message_feedback
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
6
 get_conversations
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2/**
3 * WP_REST_Help_Center_Odie file.
4 *
5 * @package automattic/jetpack-mu-wpcom
6 */
7
8namespace A8C\FSE;
9
10use Automattic\Jetpack\Connection\Client;
11
12/**
13 * Class WP_REST_Help_Center_Odie.
14 */
15class WP_REST_Help_Center_Odie extends \WP_REST_Controller {
16
17    /**
18     * WP_REST_Help_Center_Odie constructor.
19     */
20    public function __construct() {
21        $this->namespace = 'help-center';
22        $this->rest_base = '/odie';
23    }
24
25    /**
26     * Register available routes.
27     */
28    public function register_rest_route() {
29        register_rest_route(
30            $this->namespace,
31            $this->rest_base . '/chat/(?P<bot_id>[a-zA-Z0-9-_]+)/(?P<chat_id>\d+)',
32            array(
33                // Get a chat. Supports pagination of messages.
34                array(
35                    'methods'             => \WP_REST_Server::READABLE,
36                    'callback'            => array( $this, 'get_chat' ),
37                    'permission_callback' => 'is_user_logged_in',
38                    'args'                => array(
39                        'bot_id'           => array(
40                            'description' => __( 'The bot id to get the chat for.', 'jetpack-mu-wpcom' ),
41                            'type'        => 'string',
42                            'required'    => true,
43                        ),
44                        'chat_id'          => array(
45                            'description' => __( 'The chat id to get the chat for.', 'jetpack-mu-wpcom' ),
46                            'type'        => 'integer',
47                            'required'    => true,
48                        ),
49                        'page_number'      => array(
50                            'description' => __( 'The number of the page to retrieve, limited to 100', 'jetpack-mu-wpcom' ),
51                            'type'        => 'integer',
52                            'required'    => false,
53                            'default'     => 1,
54                        ),
55                        'items_per_page'   => array(
56                            'description' => __( 'The number of items per page.', 'jetpack-mu-wpcom' ),
57                            'type'        => 'integer',
58                            'required'    => false,
59                            'default'     => 10,
60                        ),
61                        'include_feedback' => array(
62                            'required'    => false,
63                            'type'        => 'boolean',
64                            'description' => __( 'If true, include the feedback rating value for each message in the response.', 'jetpack-mu-wpcom' ),
65                        ),
66                    ),
67                ),
68                // Add a message to a chat.
69                array(
70                    'methods'             => \WP_REST_Server::CREATABLE,
71                    'callback'            => array( $this, 'send_chat_message' ),
72                    'permission_callback' => 'is_user_logged_in',
73                    'args'                => array(
74                        'bot_id'  => array(
75                            'description' => __( 'The bot id to chat with.', 'jetpack-mu-wpcom' ),
76                            'type'        => 'string',
77                            'required'    => true,
78                        ),
79                        'chat_id' => array(
80                            'description' => __( 'The chat id for the existing chat.', 'jetpack-mu-wpcom' ),
81                            'type'        => 'integer',
82                            'required'    => true,
83                        ),
84                        'message' => array(
85                            'description' => __( 'The message to add to the chat', 'jetpack-mu-wpcom' ),
86                            'type'        => 'string',
87                            'required'    => true,
88                        ),
89                        // an arbitray key/value object of data to pass to the bot
90                        'context' => array(
91                            'description' => __( 'The context to continue the chat with.', 'jetpack-mu-wpcom' ),
92                            'type'        => 'object',
93                            'required'    => false,
94                        ),
95                    ),
96                ),
97            )
98        );
99
100        register_rest_route(
101            $this->namespace,
102            $this->rest_base . '/chat/(?P<bot_id>[a-zA-Z0-9-_]+)/(?P<chat_id>\d+)/(?P<message_id>\d+)/feedback',
103            array(
104                array(
105                    'methods'             => \WP_REST_Server::CREATABLE,
106                    'callback'            => array( $this, 'save_chat_message_feedback' ),
107                    'permission_callback' => 'is_user_logged_in',
108                    'args'                => array(
109                        'bot_id'       => array(
110                            'description' => __( 'The bot id to chat with.', 'jetpack-mu-wpcom' ),
111                            'type'        => 'string',
112                            'required'    => true,
113                        ),
114                        'chat_id'      => array(
115                            'description' => __( 'The chat id for the existing chat.', 'jetpack-mu-wpcom' ),
116                            'type'        => 'integer',
117                            'required'    => true,
118                        ),
119                        'message_id'   => array(
120                            'description' => __( 'The message id for the existing message.', 'jetpack-mu-wpcom' ),
121                            'type'        => 'integer',
122                            'required'    => true,
123                        ),
124                        'rating_value' => array(
125                            'description' => __( 'The feedback rating value.', 'jetpack-mu-wpcom' ),
126                            'type'        => 'integer',
127                            'required'    => true,
128                        ),
129                    ),
130                ),
131            )
132        );
133
134        register_rest_route(
135            $this->namespace,
136            $this->rest_base . '/chat/(?P<bot_id>[a-zA-Z0-9-_]+)',
137            array(
138                array(
139                    'methods'             => \WP_REST_Server::CREATABLE,
140                    'callback'            => array( $this, 'send_chat_message' ),
141                    'permission_callback' => 'is_user_logged_in',
142                    'args'                => array(
143                        'bot_id'  => array(
144                            'description' => __( 'The bot id to chat with.', 'jetpack-mu-wpcom' ),
145                            'type'        => 'string',
146                            'required'    => true,
147                        ),
148                        'context' => array(
149                            'description' => __( 'The context to continue the chat with.', 'jetpack-mu-wpcom' ),
150                            'type'        => 'object',
151                            'required'    => false,
152                        ),
153                        'message' => array(
154                            'description' => __( 'The message to add to the chat', 'jetpack-mu-wpcom' ),
155                            'type'        => 'string',
156                            'required'    => true,
157                        ),
158                        'test'    => array(
159                            'description' => __( 'Whether to mark this as a test chat (a11n-only).', 'jetpack-mu-wpcom' ),
160                            'type'        => 'boolean',
161                            'required'    => false,
162                        ),
163                    ),
164                ),
165            )
166        );
167
168        register_rest_route(
169            $this->namespace,
170            $this->rest_base . '/conversations/(?P<bot_ids>[a-zA-Z0-9-_,\@]+)',
171            // Retrieve the latest conversations of a user with the specified bot (i.e. the last messages from each chat)
172            array(
173                array(
174                    'methods'             => \WP_REST_Server::READABLE,
175                    'callback'            => array( $this, 'get_conversations' ),
176                    'permission_callback' => 'is_user_logged_in',
177                    'args'                => array(
178                        'bot_ids'        => array(
179                            'description' => __( 'The bot id(s) to get the conversations for, separated by commas.', 'jetpack-mu-wpcom' ),
180                            'type'        => 'string',
181                            'required'    => true,
182                        ),
183                        'page_number'    => array(
184                            'description' => __( 'The number of the page to retrieve, limited to 100', 'jetpack-mu-wpcom' ),
185                            'type'        => 'integer',
186                            'required'    => false,
187                            'default'     => 1,
188                        ),
189                        'items_per_page' => array(
190                            'description' => __( 'The number of items per page.', 'jetpack-mu-wpcom' ),
191                            'type'        => 'integer',
192                            'required'    => false,
193                            'default'     => 10,
194                        ),
195                    ),
196                ),
197            )
198        );
199    }
200
201    /**
202     * Send a message to the support chat.
203     *
204     * @param \WP_REST_Request $request The request sent to the API.
205     */
206    public function send_chat_message( \WP_REST_Request $request ) {
207        $bot_name_slug = $request->get_param( 'bot_id' );
208        $chat_id       = $request->get_param( 'chat_id' );
209
210        // Forward the request body to the support chat endpoint.
211        $body = Client::wpcom_json_api_request_as_user(
212            '/odie/chat/' . $bot_name_slug . '/' . $chat_id,
213            '2',
214            array(
215                'method'  => 'POST',
216                'timeout' => 60,
217            ),
218            array(
219                'message' => $request->get_param( 'message' ),
220                'context' => $request->get_param( 'context' ) ?? array(),
221                'version' => $request->get_param( 'version' ),
222            )
223        );
224
225        if ( is_wp_error( $body ) ) {
226            return $body;
227        }
228
229        $response = json_decode( wp_remote_retrieve_body( $body ) );
230
231        return rest_ensure_response( $response );
232    }
233
234    /**
235     * Get the chat messages.
236     *
237     * @param \WP_REST_Request $request The request sent to the API.
238     */
239    public function get_chat( \WP_REST_Request $request ) {
240        $bot_name_slug    = $request->get_param( 'bot_id' );
241        $chat_id          = $request->get_param( 'chat_id' );
242        $page_number      = $request['page_number'];
243        $items_per_page   = $request['items_per_page'];
244        $include_feedback = $request['include_feedback'];
245
246        $url_query_params = http_build_query(
247            array(
248                'page_number'      => $page_number,
249                'items_per_page'   => $items_per_page,
250                'include_feedback' => $include_feedback,
251            )
252        );
253
254        $body = Client::wpcom_json_api_request_as_user(
255            '/odie/chat/' . $bot_name_slug . '/' . $chat_id . '?' . $url_query_params
256        );
257
258        if ( is_wp_error( $body ) ) {
259            return $body;
260        }
261
262        $response = json_decode( wp_remote_retrieve_body( $body ) );
263
264        return rest_ensure_response( $response );
265    }
266
267    /**
268     * Save feedback for a chat message.
269     *
270     * @param \WP_REST_Request $request The request sent to the API.
271     */
272    public function save_chat_message_feedback( \WP_REST_Request $request ) {
273        $bot_id       = $request->get_param( 'bot_id' );
274        $chat_id      = $request->get_param( 'chat_id' );
275        $message_id   = $request->get_param( 'message_id' );
276        $rating_value = $request->get_param( 'rating_value' );
277
278        // Forward the request body to the feedback endpoint.
279        $body = Client::wpcom_json_api_request_as_user(
280            '/odie/chat/' . $bot_id . '/' . $chat_id . '/' . $message_id . '/feedback',
281            '2',
282            array( 'method' => 'POST' ),
283            array(
284                'rating_value' => $rating_value,
285            )
286        );
287
288        if ( is_wp_error( $body ) ) {
289            return $body;
290        }
291
292        $response = json_decode( wp_remote_retrieve_body( $body ) );
293
294        return rest_ensure_response( $response );
295    }
296
297    /**
298     * Get list of AI conversations.
299     *
300     * @param \WP_REST_Request $request The request sent to the API.
301     */
302    public function get_conversations( \WP_REST_Request $request ) {
303        $bot_ids           = $request->get_param( 'bot_ids' );
304        $page_number       = $request['page_number'];
305        $items_per_page    = $request['items_per_page'];
306        $truncation_method = $request['truncation_method'];
307
308        $url_query_params = http_build_query(
309            array(
310                'page_number'       => $page_number,
311                'items_per_page'    => $items_per_page,
312                'truncation_method' => $truncation_method,
313            )
314        );
315
316        $body = Client::wpcom_json_api_request_as_user(
317            '/odie/conversations/' . $bot_ids . '?' . $url_query_params
318        );
319
320        if ( is_wp_error( $body ) ) {
321            return $body;
322        }
323
324        $response = json_decode( wp_remote_retrieve_body( $body ) );
325
326        return rest_ensure_response( $response );
327    }
328}