Completed
Push — master ( e22200...77a5d7 )
by Gary
02:18
created

lib/class-wp-rest-react-controller.php (3 issues)

calls to non-existent methods.

Bug Major

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * Class WP_REST_React_Controller
5
 */
6
class WP_REST_React_Controller {
7
	/**
8
	 * The namespace of this controller's route.
9
	 *
10
	 * @var string
11
	 */
12
	protected $namespace;
13
14
	/**
15
	 * The base of this controller's route.
16
	 *
17
	 * @var string
18
	 */
19
	protected $rest_base;
20
21
	/**
22
	 * Constructor.
23
	 */
24
	public function __construct() {
25
		$this->namespace = 'wp/v2';
26
		$this->rest_base = 'react';
27
	}
28
29
	/**
30
	 * Register the routes for the objects of the controller.
31
	 */
32
	public function register_routes() {
33
		register_rest_route( $this->namespace, $this->rest_base, array(
34
			array(
35
				'methods'             => WP_Rest_Server::READABLE,
36
				'callback'            => array( $this, 'get_items' ),
37
				'permission_callback' => array( $this, 'get_items_permission_callback' ),
38
				'args'                => $this->get_collection_params(),
39
			),
40
			array(
41
				'methods'             => WP_Rest_Server::CREATABLE,
42
				'callback'            => array( $this, 'create_item' ),
43
				'permission_callback' => array( $this, 'create_item_permission_callback' ),
44
				'args'                => $this->get_creation_params(),
45
			),
46
			'schema' => array( $this, 'get_public_item_schema' ),
47
		) );
48
	}
49
50
	/**
51
	 * Check if a given request has access to read reactions.
52
	 *
53
	 * @param  WP_REST_Request $request Full details about the request.
54
	 * @return WP_Error|boolean
55
	 */
56
	public function get_items_permissions_check( $request ) {
57
		if ( ! empty( $request['post'] ) ) {
58
			foreach ( (array) $request['post'] as $post_id ) {
59
				$post = get_post( $post_id );
60
				if ( ! empty( $post_id ) && $post && ! $this->check_read_post_permission( $post ) ) {
61
					return new WP_Error( 'rest_cannot_read_post', __( 'Sorry, you cannot read the post for this reaction.' ), array( 'status' => rest_authorization_required_code() ) );
62
				} else if ( 0 === $post_id && ! current_user_can( 'moderate_comments' ) ) {
63
					return new WP_Error( 'rest_cannot_read', __( 'Sorry, you cannot read reactions without a post.' ), array( 'status' => rest_authorization_required_code() ) );
64
				}
65
			}
66
		}
67
68
		return true;
69
	}
70
71
	/**
72
	 * Get a list of reactions.
73
	 *
74
	 * @param  WP_REST_Request $request Full details about the request.
75
	 * @return WP_Error|WP_REST_Response
76
	 */
77
	public function get_items( $request ) {
78
		$prepared_args = array(
79
			'post__in' => $request['post'],
80
			'type'     => 'reaction',
81
		);
82
83
		/**
84
		 * Filter arguments, before passing to WP_Comment_Query, when querying reactions via the REST API.
85
		 *
86
		 * @see https://developer.wordpress.org/reference/classes/wp_comment_query/
87
		 *
88
		 * @param array           $prepared_args Array of arguments for WP_Comment_Query.
89
		 * @param WP_REST_Request $request       The current request.
90
		 */
91
		$prepared_args = apply_filters( 'rest_reaction_query', $prepared_args, $request );
92
93
		$query = new WP_Comment_Query;
94
		$query_result = $query->query( $prepared_args );
95
96
		$reactions_count = array();
97
		foreach( $query_result as $reaction ) {
98
			if ( empty( $reactions_count[ $reaction->comment_content ] ) ) {
99
				$reactions_count[ $reaction->comment_content ] = array(
100
					'count'   => 0,
101
					'post_id' => $reaction->comment_post_ID,
102
				);
103
			}
104
105
			$reactions_count[ $reaction->comment_content ]++;
106
		}
107
108
		$reactions = array();
109
		foreach( $reactions_count as $emoji => $data ) {
110
			$reaction = array(
111
				'emoji'   => $emoji,
112
				'count'   => $data['count'],
113
				'post_id' => $data['post_id'],
114
			);
115
116
			$data = $this->prepare_item_for_response( $reaction, $request );
117
			$reactions[] = $this->prepare_response_for_collection( $data );
118
		}
119
120
		$total_reactions = (int) $query->found_comments;
121
		$reaction_groups = count( $reactions );
122
123
		$response = rest_ensure_response( $reactions );
124
		$response->header( 'X-WP-Total', $total_reactions );
125
		$response->header( 'X-WP-TotalGroups', $reaction_groups );
126
127
		return $response;
128
	}
129
130
	/**
131
	 * Check if a given request has access to create a reaction
132
	 *
133
	 * @param  WP_REST_Request $request Full details about the request.
134
	 * @return WP_Error|boolean
135
	 */
136
	public function create_item_permissions_check( $request ) {
137
		return true;
138
	}
139
140
	/**
141
	 * Create a reaction.
142
	 *
143
	 * @param  WP_REST_Request $request Full details about the request.
144
	 * @return WP_Error|WP_REST_Response
145
	 */
146
	public function create_item( $request ) {
147
	}
148
149
/**
150
	 * Check if we can read a post.
151
	 *
152
	 * Correctly handles posts with the inherit status.
153
	 *
154
	 * @param object $post Post object.
155
	 * @return boolean Can we read it?
156
	 */
157
	public function check_read_post_permission( $post ) {
158
		if ( ! empty( $post->post_password ) && ! $this->check_update_permission( $post ) ) {
0 ignored issues
show
The method check_update_permission() does not seem to exist on object<WP_REST_React_Controller>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
159
			return false;
160
		}
161
162
		$post_type = get_post_type_object( $post->post_type );
163
		if ( ! $this->check_is_post_type_allowed( $post_type ) ) {
0 ignored issues
show
The method check_is_post_type_allowed() does not seem to exist on object<WP_REST_React_Controller>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
164
			return false;
165
		}
166
167
		// Can we read the post?
168
		if ( 'publish' === $post->post_status || current_user_can( $post_type->cap->read_post, $post->ID ) ) {
169
			return true;
170
		}
171
172
		$post_status_obj = get_post_status_object( $post->post_status );
173
		if ( $post_status_obj && $post_status_obj->public ) {
174
			return true;
175
		}
176
177
		// Can we read the parent if we're inheriting?
178
		if ( 'inherit' === $post->post_status && $post->post_parent > 0 ) {
179
			$parent = get_post( $post->post_parent );
180
			return $this->check_read_permission( $parent );
0 ignored issues
show
The method check_read_permission() does not seem to exist on object<WP_REST_React_Controller>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
181
		}
182
183
		// If we don't have a parent, but the status is set to inherit, assume
184
		// it's published (as per get_post_status()).
185
		if ( 'inherit' === $post->post_status ) {
186
			return true;
187
		}
188
189
		return false;
190
	}
191
	/**
192
	 * Prepare a reaction group output for response.
193
	 *
194
	 * @param  array            $reaction Reaction data.
195
	 * @param  WP_REST_Request  $request  Request object.
196
	 * @return WP_REST_Response $response
197
	 */
198
	public function prepare_item_for_response( $reaction, $request ) {
199
		$data = array(
200
			'emoji'   => $reaction['emoji'],
201
			'count'   => (int) $reaction['count'],
202
			'post_id' => (int) $reaction['post_id'],
203
		);
204
205
		// Wrap the data in a response object
206
		$response = rest_ensure_response( $data );
207
208
		$response->add_links( $this->prepare_links( $reaction ) );
209
210
		/**
211
		 * Filter a reaction group returned from the API.
212
		 *
213
		 * Allows modification of the reaction right before it is returned.
214
		 *
215
		 * @param WP_REST_Response  $response   The response object.
216
		 * @param array             $reaction   The original reaction data.
217
		 * @param WP_REST_Request   $request    Request used to generate the response.
218
		 */
219
		return apply_filters( 'rest_prepare_comment', $response, $reaction, $request );
220
	}
221
222
	/**
223
	 * Prepare a response for inserting into a collection.
224
	 *
225
	 * @param WP_REST_Response $response Response object.
226
	 * @return array Response data, ready for insertion into collection data.
227
	 */
228
	public function prepare_response_for_collection( $response ) {
229
		if ( ! ( $response instanceof WP_REST_Response ) ) {
230
			return $response;
231
		}
232
233
		$data = (array) $response->get_data();
234
		$links = WP_REST_Server::get_response_links( $response );
235
		if ( ! empty( $links ) ) {
236
			$data['_links'] = $links;
237
		}
238
239
		return $data;
240
	}
241
242
	/**
243
	 * Prepare links for the request.
244
	 *
245
	 * @param array $reaction Reaction.
246
	 * @return array Links for the given reaction.
247
	 */
248
	protected function prepare_links( $reaction ) {
249
		$links = array(
250
			'self' => array(
251
				'href' => rest_url( sprintf( '/%s/%s/%s', $this->namespace, $this->rest_base, $reaction->emoji ) ),
252
			),
253
			'collection' => array(
254
				'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),
255
			),
256
		);
257
258
		if ( 0 !== (int) $reaction['post_id'] ) {
259
			$post = get_post( $reaction['post_id'] );
260
			if ( ! empty( $post->ID ) ) {
261
				$obj = get_post_type_object( $post->post_type );
262
				$base = ! empty( $obj->rest_base ) ? $obj->rest_base : $obj->name;
263
				$links['up'] = array(
264
					'href'       => rest_url( '/wp/v2/' . $base . '/' . $reaction['post_id'] ),
265
					'embeddable' => true,
266
					'post_type'  => $post->post_type,
267
				);
268
			}
269
		}
270
271
		return $links;
272
	}
273
274
	/**
275
	 * Get the query params for collections
276
	 *
277
	 * @return array
278
	 */
279
	public function get_collection_params() {
280
		$query_params = array();
281
282
		$query_params['post']   = array(
283
			'default'           => array(),
284
			'description'       => __( 'Limit result set to resources assigned to specific post ids.' ),
285
			'type'              => 'array',
286
			'sanitize_callback' => 'wp_parse_id_list',
287
			'validate_callback' => 'rest_validate_request_arg',
288
		);
289
290
		return $query_params;
291
	}
292
	/**
293
	 * Get the query params for collections
294
	 *
295
	 * @return array
296
	 */
297
	public function get_creation_params() {
298
		$query_params = array();
299
300
		$query_params['post']   = array(
301
			'default'           => array(),
302
			'description'       => __( 'The post ID to add a reaction to.' ),
303
			'type'              => 'integer',
304
			'sanitize_callback' => 'absint',
305
			'validate_callback' => 'rest_validate_request_arg',
306
		);
307
308
		$query_params['emoji']  = array(
309
			'default'           => array(),
310
			'description'       => __( 'The reaction emoji.' ),
311
			'type'              => 'string',
312
			'validate_callback' => 'rest_validate_request_arg',
313
		);
314
315
		return $query_params;
316
	}
317
}