Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 57
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
WP_REST_Comment_Like
0.00% covered (danger)
0.00%
0 / 57
0.00% covered (danger)
0.00%
0 / 6
156
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 register_routes
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
2
 permission_callback
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 new_like
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
2
 delete_like
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
2
 ensure_response
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
56
1<?php
2/**
3 * File: class-wp-rest-comments-likes.php
4 *
5 * Provides REST API endpoints for creating and deleting comment likes.
6 *
7 * @package automattic/jetpack-mu-wpcom
8 */
9
10/**
11 * Class WP_REST_Comment_Like.
12 *
13 * A thin wrapper around the wpcom implementation, specifically designed for comments moderation.
14 * Handles endpoints for creating a new like and deleting a like on comments.
15 */
16class WP_REST_Comment_Like extends WP_REST_Controller {
17
18    /**
19     * Constructor.
20     */
21    public function __construct() {
22        $this->namespace = 'rest/v1.1';
23    }
24
25    /**
26     * Register available routes.
27     */
28    public function register_routes() {
29        // Endpoint for creating a new like.
30        register_rest_route(
31            $this->namespace,
32            '/comments/(?P<comment_id>\d+)/likes/new',
33            array(
34                array(
35                    'methods'             => \WP_REST_Server::CREATABLE,
36                    'callback'            => array( $this, 'new_like' ),
37                    'permission_callback' => array( $this, 'permission_callback' ),
38                ),
39            )
40        );
41
42        // Endpoint for deleting the current user's like.
43        register_rest_route(
44            $this->namespace,
45            '/comments/(?P<comment_id>\d+)/likes/mine/delete',
46            array(
47                array(
48                    'methods'             => \WP_REST_Server::CREATABLE,
49                    'callback'            => array( $this, 'delete_like' ),
50                    'permission_callback' => array( $this, 'permission_callback' ),
51                ),
52            )
53        );
54    }
55
56    /**
57     * Permission callback.
58     *
59     * @return bool
60     */
61    public function permission_callback(): bool {
62        return is_user_logged_in();
63    }
64
65    /**
66     * Callback for the new like endpoint.
67     *
68     * @param WP_REST_Request $request Request object.
69     *
70     * @return WP_Error|WP_REST_Response
71     */
72    public function new_like( WP_REST_Request $request ) {
73        $comment_id = $request->get_param( 'comment_id' );
74        $blog_id    = \Jetpack_Options::get_option( 'id' );
75
76        // Call WPCom remote API to record a new like.
77        $response = \Automattic\Jetpack\Connection\Client::wpcom_json_api_request_as_user(
78            "/sites/$blog_id/comments/$comment_id/likes/new",
79            'v1.1',
80            array( 'method' => 'POST' ),
81            null,
82            'rest'
83        );
84
85        return $this->ensure_response( $response );
86    }
87
88    /**
89     * Callback for the delete like endpoint.
90     *
91     * @param WP_REST_Request $request Request object.
92     *
93     * @return WP_Error|WP_REST_Response
94     */
95    public function delete_like( WP_REST_Request $request ) {
96        $comment_id = $request->get_param( 'comment_id' );
97        $blog_id    = \Jetpack_Options::get_option( 'id' );
98
99        // Call WPCom remote API to delete the current user's like.
100        $response = \Automattic\Jetpack\Connection\Client::wpcom_json_api_request_as_user(
101            "/sites/$blog_id/comments/$comment_id/likes/mine/delete",
102            'v1.1',
103            array( 'method' => 'POST' ),
104            null,
105            'rest'
106        );
107
108        return $this->ensure_response( $response );
109    }
110
111    /**
112     * Ensures a valid rest response.
113     *
114     * @param array|WP_Error $response The remote response object.
115     *
116     * @return WP_Error|WP_REST_Response
117     */
118    private function ensure_response( $response ) {
119        if ( ! $response ) {
120            return new WP_Error( 'unknown_response', 'Empty response from server', 500 );
121        }
122
123        if ( is_wp_error( $response ) ) {
124            return $response;
125        }
126
127        $body = wp_remote_retrieve_body( $response );
128
129        if ( is_wp_error( $body ) && $body instanceof WP_Error ) {
130            return $body;
131        }
132
133        if ( ! $body ) {
134            return new WP_Error( 'unknown_response', 'Empty response body from server', 500 );
135        }
136
137        $response = json_decode( $body, true );
138
139        if ( ! $response ) {
140            return new WP_Error( 'unknown_response', 'Empty decoded response body', 500 );
141        }
142
143        // Return the response from the server.
144        return rest_ensure_response( $response );
145    }
146}