PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.9
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.9
4.4.9 4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 All 140 releases
← All changes | inc/jwt/rest-api/version1/class-lp-rest-posts-controller.php +639 -639 4.3.8 → 4.4.9 View file →
@@ -1,639 +1,639 @@
1 -<?php
2 -abstract class LP_REST_Jwt_Posts_Controller extends LP_REST_Jwt_Controller {
3 - protected $namespace = 'learnpress/v1';
4 -
5 - protected $rest_base = '';
6 -
7 - protected $post_type = '';
8 -
9 - protected $public = false;
10 -
11 - protected $hierarchical = false;
12 -
13 - protected function get_object( $id ) {
14 - return new WP_Error( 'invalid-method', sprintf( __( "The method '%s' not implemented. It must be overridden in the subclass.", 'learnpress' ), __METHOD__ ), array( 'status' => 405 ) );
15 - }
16 -
17 - public function get_items_permissions_check( $request ) {
18 - if ( ! lp_rest_check_post_permissions( $this->post_type, 'read' ) ) {
19 - return new WP_Error( 'lp_jwt_rest_cannot_view', __( 'Sorry, you cannot get lists', 'learnpress' ), array( 'status' => rest_authorization_required_code() ) );
20 - }
21 -
22 - return true;
23 - }
24 -
25 - /**
26 - * Check if a given request has access to create an item.
27 - *
28 - * @param WP_REST_Request $request Full details about the request.
29 - * @return WP_Error|boolean
30 - */
31 - public function create_item_permissions_check( $request ) {
32 - if ( ! lp_rest_check_post_permissions( $this->post_type, 'create' ) ) {
33 - return new WP_Error( 'lp_rest_cannot_create', __( 'Sorry, you are not allowed to create resources.', 'learnpress' ), array( 'status' => rest_authorization_required_code() ) );
34 - }
35 -
36 - return true;
37 - }
38 -
39 - public function get_item_permissions_check( $request ) {
40 - if ( $this->post_type !== get_post_type( (int) $request['id'] ) ) {
41 - return new WP_Error( 'lp_jwt_rest_not_in_post_type', __( 'Sorry, You cannot view this item.', 'learnpress' ), array( 'status' => rest_authorization_required_code() ) );
42 - }
43 -
44 - $object = $this->get_object( (int) $request['id'] );
45 -
46 - if ( $object && 0 !== $object->get_id() && ! $this->check_read_permission( $object->get_id() ) ) {
47 - return new WP_Error( 'lp_jwt_rest_cannot_view', __( 'Sorry, you cannot view this resource.', 'learnpress' ), array( 'status' => rest_authorization_required_code() ) );
48 - }
49 -
50 - return true;
51 - }
52 -
53 - public function check_read_permission( $post_id ) {
54 - if ( ! lp_rest_check_post_permissions( $this->post_type, 'read', $post_id ) ) {
55 - return false;
56 - }
57 -
58 - return true;
59 - }
60 -
61 - public function get_item( $request ) {
62 - $object = $this->get_object( (int) $request['id'] );
63 -
64 - if ( ! $object || 0 === $object->get_id() ) {
65 - return new WP_Error( "lp_rest_{$this->post_type}_invalid_id", esc_html__( 'Invalid ID.', 'learnpress' ), array( 'status' => 404 ) );
66 - }
67 -
68 - $data = $this->prepare_object_for_response( $object, $request );
69 - $response = rest_ensure_response( $data );
70 -
71 - if ( $this->public ) {
72 - $response->link_header( 'alternate', $this->get_permalink( $object ), array( 'type' => 'text/html' ) );
73 - }
74 -
75 - return $response;
76 - }
77 -
78 - public function get_items( $request ) {
79 - $query_args = $this->prepare_objects_query( $request );
80 - $query_results = $this->get_objects( $query_args );
81 -
82 - $objects = array();
83 - foreach ( $query_results['objects'] as $object ) {
84 - $object_id = ! empty( $object->ID ) ? $object->ID : $object->get_id();
85 -
86 - if ( ! $this->check_read_permission( $object_id ) ) {
87 - continue;
88 - }
89 -
90 - $data = $this->prepare_object_for_response( $object, $request );
91 - $objects[] = $this->prepare_response_for_collection( $data );
92 - }
93 -
94 - $page = (int) $query_args['paged'];
95 - $max_pages = $query_results['pages'];
96 -
97 - $response = rest_ensure_response( $objects );
98 - $response->header( 'X-WP-Total', $query_results['total'] );
99 - $response->header( 'X-WP-TotalPages', (int) $max_pages );
100 -
101 - $base = $this->rest_base;
102 - $attrib_prefix = '(?P<';
103 -
104 - if ( strpos( $base, $attrib_prefix ) !== false ) {
105 - $attrib_names = array();
106 - preg_match( '/\(\?P<[^>]+>.*\)/', $base, $attrib_names, PREG_OFFSET_CAPTURE );
107 -
108 - foreach ( $attrib_names as $attrib_name_match ) {
109 - $beginning_offset = strlen( $attrib_prefix );
110 - $attrib_name_end = strpos( $attrib_name_match[0], '>', $attrib_name_match[1] );
111 - $attrib_name = substr( $attrib_name_match[0], $beginning_offset, $attrib_name_end - $beginning_offset );
112 -
113 - if ( isset( $request[ $attrib_name ] ) ) {
114 - $base = str_replace( "(?P<$attrib_name>[\d]+)", $request[ $attrib_name ], $base );
115 - }
116 - }
117 - }
118 -
119 - $base = esc_url_raw( add_query_arg( $request->get_query_params(), rest_url( sprintf( '/%s/%s', $this->namespace, $base ) ) ) );
120 -
121 - if ( $page > 1 ) {
122 - $prev_page = $page - 1;
123 - if ( $prev_page > $max_pages ) {
124 - $prev_page = $max_pages;
125 - }
126 - $prev_link = esc_url_raw( add_query_arg( 'page', $prev_page, $base ) );
127 - $response->link_header( 'prev', $prev_link );
128 - }
129 -
130 - if ( $max_pages > $page ) {
131 - $next_page = $page + 1;
132 - $next_link = esc_url_raw( add_query_arg( 'page', $next_page, $base ) );
133 - $response->link_header( 'next', $next_link );
134 - }
135 -
136 - return $response;
137 - }
138 -
139 - /**
140 - * Create a single item.
141 - *
142 - * @param WP_REST_Request $request Full details about the request.
143 - * @return WP_Error|WP_REST_Response
144 - */
145 - public function create_item( $request ) {
146 - if ( ! empty( $request['id'] ) ) {
147 - /* translators: %s: post type */
148 - return new WP_Error( "lp_rest_{$this->post_type}_exists", sprintf( __( 'Cannot create existing %s.', 'learnpress' ), $this->post_type ), array( 'status' => 400 ) );
149 - }
150 -
151 - $post = $this->prepare_item_for_database( $request );
152 - if ( is_wp_error( $post ) ) {
153 - return $post;
154 - }
155 -
156 - $post->post_type = $this->post_type;
157 - $post_id = wp_insert_post( $post, true );
158 -
159 - if ( is_wp_error( $post_id ) ) {
160 - if ( in_array( $post_id->get_error_code(), array( 'db_insert_error' ) ) ) {
161 - $post_id->add_data( array( 'status' => 500 ) );
162 - } else {
163 - $post_id->add_data( array( 'status' => 400 ) );
164 - }
165 - return $post_id;
166 - }
167 -
168 - $post->ID = $post_id;
169 - $post = get_post( $post_id );
170 -
171 - $this->update_additional_fields_for_object( $post, $request );
172 -
173 - // Add meta fields.
174 - $meta_fields = $this->add_post_meta_fields( $post, $request );
175 - if ( is_wp_error( $meta_fields ) ) {
176 - // Remove post.
177 - $this->delete_post( $post );
178 -
179 - return $meta_fields;
180 - }
181 -
182 - /**
183 - * Fires after a single item is created or updated via the REST API.
184 - *
185 - * @param WP_Post $post Post object.
186 - * @param WP_REST_Request $request Request object.
187 - * @param boolean $creating True when creating item, false when updating.
188 - */
189 - do_action( "lp_rest_insert_{$this->post_type}", $post, $request, true );
190 -
191 - $request->set_param( 'context', 'edit' );
192 - $response = $this->prepare_item_for_response( $post, $request );
193 - $response = rest_ensure_response( $response );
194 - $response->set_status( 201 );
195 - $response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $post_id ) ) );
196 -
197 - return $response;
198 - }
199 -
200 - public function prepare_item_for_database( $request, $creating = false ) {
201 - $prepared_post = new stdClass();
202 - $current_status = '';
203 -
204 - $id = isset( $request['id'] ) ? absint( $request['id'] ) : 0;
205 -
206 - if ( isset( $request['id'] ) ) {
207 - $existing_post = get_post( $id );
208 -
209 - if ( empty( $existing_post ) || empty( $existing_post->ID ) || $this->post_type !== $existing_post->post_type ) {
210 - return new WP_Error( 'rest_invalid_course', __( 'Invalid Course', 'learnpress' ), array( 'status' => 404 ) );
211 - }
212 -
213 - $prepared_post->ID = $existing_post->ID;
214 - $current_status = $existing_post->post_status;
215 - }
216 -
217 - $schema = $this->get_item_schema();
218 -
219 - // Post title.
220 - if ( ! empty( $schema['properties']['name'] ) && isset( $request['name'] ) ) {
221 - if ( is_string( $request['name'] ) ) {
222 - $prepared_post->post_title = $request['name'];
223 - } elseif ( ! empty( $request['name']['raw'] ) ) {
224 - $prepared_post->post_title = $request['name']['raw'];
225 - }
226 - }
227 -
228 - // Post content.
229 - if ( ! empty( $schema['properties']['content'] ) && isset( $request['content'] ) ) {
230 - if ( is_string( $request['content'] ) ) {
231 - $prepared_post->post_content = $request['content'];
232 - } elseif ( isset( $request['content']['raw'] ) ) {
233 - $prepared_post->post_content = $request['content']['raw'];
234 - }
235 - }
236 -
237 - // Post excerpt.
238 - if ( ! empty( $schema['properties']['excerpt'] ) && isset( $request['excerpt'] ) ) {
239 - if ( is_string( $request['excerpt'] ) ) {
240 - $prepared_post->post_excerpt = $request['excerpt'];
241 - } elseif ( isset( $request['excerpt']['raw'] ) ) {
242 - $prepared_post->post_excerpt = $request['excerpt']['raw'];
243 - }
244 - }
245 -
246 - // Post type.
247 - if ( empty( $request['id'] ) ) {
248 - // Creating new post, use default type for the controller.
249 - $prepared_post->post_type = $this->post_type;
250 - } else {
251 - // Updating a post, use previous type.
252 - $prepared_post->post_type = get_post_type( $request['id'] );
253 - }
254 -
255 - $post_type = get_post_type_object( $prepared_post->post_type );
256 -
257 - // Post status.
258 - if (
259 - ! empty( $schema['properties']['status'] ) &&
260 - isset( $request['status'] ) &&
261 - ( ! $current_status || $current_status !== $request['status'] )
262 - ) {
263 - $status = $this->handle_status_param( $request['status'], $post_type );
264 -
265 - if ( is_wp_error( $status ) ) {
266 - return $status;
267 - }
268 -
269 - $prepared_post->post_status = $status;
270 - }
271 -
272 - // Post date.
273 - if ( ! empty( $schema['properties']['date'] ) && ! empty( $request['date'] ) ) {
274 - $current_date = isset( $prepared_post->ID ) ? get_post( $prepared_post->ID )->post_date : false;
275 - $date_data = rest_get_date_with_gmt( $request['date'] );
276 -
277 - if ( ! empty( $date_data ) && $current_date !== $date_data[0] ) {
278 - list( $prepared_post->post_date, $prepared_post->post_date_gmt ) = $date_data;
279 - $prepared_post->edit_date = true;
280 - }
281 - } elseif ( ! empty( $schema['properties']['date_gmt'] ) && ! empty( $request['date_gmt'] ) ) {
282 - $current_date = isset( $prepared_post->ID ) ? get_post( $prepared_post->ID )->post_date_gmt : false;
283 - $date_data = rest_get_date_with_gmt( $request['date_gmt'], true );
284 -
285 - if ( ! empty( $date_data ) && $current_date !== $date_data[1] ) {
286 - list( $prepared_post->post_date, $prepared_post->post_date_gmt ) = $date_data;
287 - $prepared_post->edit_date = true;
288 - }
289 - }
290 -
291 - // Sending a null date or date_gmt value resets date and date_gmt to their
292 - // default values (`0000-00-00 00:00:00`).
293 - if (
294 - ( ! empty( $schema['properties']['date_gmt'] ) && $request->has_param( 'date_gmt' ) && null === $request['date_gmt'] ) ||
295 - ( ! empty( $schema['properties']['date'] ) && $request->has_param( 'date' ) && null === $request['date'] )
296 - ) {
297 - $prepared_post->post_date_gmt = null;
298 - $prepared_post->post_date = null;
299 - }
300 -
301 - // Post slug.
302 - if ( ! empty( $schema['properties']['slug'] ) && isset( $request['slug'] ) ) {
303 - $prepared_post->post_name = $request['slug'];
304 - }
305 -
306 - // Author.
307 - if ( ! empty( $schema['properties']['author'] ) && ! empty( $request['author'] ) ) {
308 - $post_author = (int) $request['author'];
309 -
310 - if ( get_current_user_id() !== $post_author ) {
311 - $user_obj = get_userdata( $post_author );
312 -
313 - if ( ! $user_obj ) {
314 - return new WP_Error(
315 - 'rest_invalid_author',
316 - __( 'Invalid author ID.' ),
317 - array( 'status' => 400 )
318 - );
319 - }
320 - }
321 -
322 - $prepared_post->post_author = $post_author;
323 - }
324 -
325 - // Post password.
326 - if ( ! empty( $schema['properties']['password'] ) && isset( $request['password'] ) ) {
327 - $prepared_post->post_password = $request['password'];
328 -
329 - if ( '' !== $request['password'] ) {
330 - if ( ! empty( $schema['properties']['sticky'] ) && ! empty( $request['sticky'] ) ) {
331 - return new WP_Error(
332 - 'rest_invalid_field',
333 - __( 'A post can not be sticky and have a password.' ),
334 - array( 'status' => 400 )
335 - );
336 - }
337 -
338 - if ( ! empty( $prepared_post->ID ) && is_sticky( $prepared_post->ID ) ) {
339 - return new WP_Error(
340 - 'rest_invalid_field',
341 - __( 'A sticky post can not be password protected.' ),
342 - array( 'status' => 400 )
343 - );
344 - }
345 - }
346 - }
347 -
348 - return apply_filters( "lp_rest_pre_insert_{$this->post_type}", $prepared_post, $request );
349 - }
350 -
351 - /**
352 - * Determines validity and normalizes the given status parameter.
353 - *
354 - * @since 4.7.0
355 - *
356 - * @param string $post_status Post status.
357 - * @param WP_Post_Type $post_type Post type.
358 - * @return string|WP_Error Post status or WP_Error if lacking the proper permission.
359 - */
360 - protected function handle_status_param( $post_status, $post_type ) {
361 -
362 - switch ( $post_status ) {
363 - case 'draft':
364 - case 'pending':
365 - break;
366 - case 'private':
367 - if ( ! current_user_can( $post_type->cap->publish_posts ) ) {
368 - return new WP_Error(
369 - 'rest_cannot_publish',
370 - __( 'Sorry, you are not allowed to create private posts in this post type.' ),
371 - array( 'status' => rest_authorization_required_code() )
372 - );
373 - }
374 - break;
375 - case 'publish':
376 - case 'future':
377 - if ( ! current_user_can( $post_type->cap->publish_posts ) ) {
378 - return new WP_Error(
379 - 'rest_cannot_publish',
380 - __( 'Sorry, you are not allowed to publish posts in this post type.' ),
381 - array( 'status' => rest_authorization_required_code() )
382 - );
383 - }
384 - break;
385 - default:
386 - if ( ! get_post_status_object( $post_status ) ) {
387 - $post_status = 'draft';
388 - }
389 - break;
390 - }
391 -
392 - return $post_status;
393 - }
394 -
395 - protected function prepare_objects_query( $request ) {
396 - global $wpdb;
397 -
398 - $args = array();
399 - $args['offset'] = $request['offset'];
400 - $args['order'] = $request['order'];
401 - $args['orderby'] = $request['orderby'];
402 - $args['paged'] = $request['page'];
403 - $args['post__in'] = $request['include'];
404 - $args['post__not_in'] = $request['exclude'];
405 - $args['posts_per_page'] = $request['per_page'];
406 - $args['name'] = $request['slug'];
407 - $args['post_parent__in'] = $request['parent'];
408 - $args['post_parent__not_in'] = $request['parent_exclude'];
409 - $args['s'] = $request['search'];
410 - $args['author__in'] = ! empty( $request['user'] ) ? $request['user'] : $request['author'];
411 - $args['author__not_in'] = $request['author_exclude'];
412 - $args['fields'] = $this->get_fields_for_response( $request );
413 -
414 - if ( 'date' === $args['orderby'] ) {
415 - $args['orderby'] = 'date ID';
416 - }
417 -
418 - $args['date_query'] = array();
419 -
420 - if ( isset( $request['before'] ) ) {
421 - $args['date_query'][0]['before'] = $request['before'];
422 - }
423 -
424 - if ( isset( $request['after'] ) ) {
425 - $args['date_query'][0]['after'] = $request['after'];
426 - }
427 -
428 - // Get item user is learned
429 - if ( ! empty( $request['learned'] ) ) {
430 - $item_ids = $this->get_item_learned_ids( $request );
431 -
432 - // Force WP_Query return empty if don't found any order.
433 - $item_ids = ! empty( $item_ids ) ? $item_ids : array( 0 );
434 -
435 - $args['post__in'] = $item_ids;
436 - }
437 -
438 - $args['post_type'] = $this->post_type;
439 -
440 - $args = apply_filters( "lp_jwt_rest_{$this->post_type}_object_query", $args, $request );
441 -
442 - return $this->prepare_items_query( $args, $request );
443 - }
444 -
445 - /** Get all items has in database learnpress_user_items by post_type */
446 - public function get_item_learned_ids( $request ) {
447 - return array();
448 - }
449 -
450 - protected function get_objects( $query_args ) {
451 - $query = new WP_Query();
452 - $result = $query->query( $query_args );
453 -
454 - $total_posts = $query->found_posts;
455 -
456 - if ( $total_posts < 1 ) {
457 - unset( $query_args['paged'] );
458 - $count_query = new WP_Query();
459 - $count_query->query( $query_args );
460 - $total_posts = $count_query->found_posts;
461 - }
462 -
463 - return array(
464 - 'objects' => array_filter( array_map( array( $this, 'get_object' ), $result ) ),
465 - 'total' => (int) $total_posts,
466 - 'pages' => (int) ceil( $total_posts / (int) $query->query_vars['posts_per_page'] ),
467 - );
468 - }
469 -
470 - protected function add_post_meta_fields( $post, $request ) {
471 - return true;
472 - }
473 -
474 - protected function prepare_object_for_response( $object, $request ) {
475 - return new WP_Error( 'invalid-method', sprintf( __( "The method '%s' not implemented. It must be overridden in the subclass.", 'learnpress' ), __METHOD__ ), array( 'status' => 405 ) );
476 - }
477 -
478 - protected function prepare_items_query( $prepared_args = array(), $request = null ) {
479 - $query_args = array();
480 -
481 - foreach ( $prepared_args as $key => $value ) {
482 - $query_args[ $key ] = apply_filters( "rest_query_var-{$key}", $value ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
483 - }
484 -
485 - if ( 'post' !== $this->post_type || ! isset( $query_args['ignore_sticky_posts'] ) ) {
486 - $query_args['ignore_sticky_posts'] = true;
487 - }
488 -
489 - if ( 'include' === $query_args['orderby'] ) {
490 - $query_args['orderby'] = 'post__in';
491 - } elseif ( 'id' === $query_args['orderby'] ) {
492 - $query_args['orderby'] = 'ID';
493 - } elseif ( 'slug' === $query_args['orderby'] ) {
494 - $query_args['orderby'] = 'name';
495 - }
496 -
497 - return $query_args;
498 - }
499 -
500 - public function get_collection_params() {
501 - $params = array();
502 - $params['context'] = $this->get_context_param();
503 - $params['context']['default'] = 'view';
504 -
505 - $params['page'] = array(
506 - 'description' => __( 'The current page of the collection.', 'learnpress' ),
507 - 'type' => 'integer',
508 - 'default' => 1,
509 - 'sanitize_callback' => 'absint',
510 - 'validate_callback' => 'rest_validate_request_arg',
511 - 'minimum' => 1,
512 - );
513 - $params['per_page'] = array(
514 - 'description' => __( 'The maximum number of items to be returned in the result set.', 'learnpress' ),
515 - 'type' => 'integer',
516 - 'default' => 10,
517 - 'minimum' => 1,
518 - 'maximum' => 100,
519 - 'sanitize_callback' => 'absint',
520 - 'validate_callback' => 'rest_validate_request_arg',
521 - );
522 - $params['search'] = array(
523 - 'description' => __( 'Limit results to those matching a string.', 'learnpress' ),
524 - 'type' => 'string',
525 - 'sanitize_callback' => 'sanitize_text_field',
526 - 'validate_callback' => 'rest_validate_request_arg',
527 - );
528 - $params['after'] = array(
529 - 'description' => __( 'Limit response to resources published after a given ISO8601 compliant date.', 'learnpress' ),
530 - 'type' => 'string',
531 - 'format' => 'date-time',
532 - 'validate_callback' => 'rest_validate_request_arg',
533 - );
534 - $params['before'] = array(
535 - 'description' => __( 'Limit response to resources published before a given ISO8601 compliant date.', 'learnpress' ),
536 - 'type' => 'string',
537 - 'format' => 'date-time',
538 - 'validate_callback' => 'rest_validate_request_arg',
539 - );
540 - $params['exclude'] = array(
541 - 'description' => __( 'Ensure the result set excludes specific IDs.', 'learnpress' ),
542 - 'type' => 'array',
543 - 'items' => array(
544 - 'type' => 'integer',
545 - ),
546 - 'default' => array(),
547 - 'sanitize_callback' => 'wp_parse_id_list',
548 - );
549 - $params['include'] = array(
550 - 'description' => __( 'Limit the result set to specific IDs.', 'learnpress' ),
551 - 'type' => 'array',
552 - 'items' => array(
553 - 'type' => 'integer',
554 - ),
555 - 'default' => array(),
556 - 'sanitize_callback' => 'wp_parse_id_list',
557 - );
558 - $params['offset'] = array(
559 - 'description' => __( 'Offset the result set by a specific number of items.', 'learnpress' ),
560 - 'type' => 'integer',
561 - 'sanitize_callback' => 'absint',
562 - 'validate_callback' => 'rest_validate_request_arg',
563 - );
564 - $params['order'] = array(
565 - 'description' => __( 'Sorting attributes in ascending or descending order.', 'learnpress' ),
566 - 'type' => 'string',
567 - 'default' => 'desc',
568 - 'enum' => array( 'asc', 'desc' ),
569 - 'validate_callback' => 'rest_validate_request_arg',
570 - );
571 - $params['orderby'] = array(
572 - 'description' => __( 'Sort collections by the object attribute.', 'learnpress' ),
573 - 'type' => 'string',
574 - 'default' => 'date',
575 - 'enum' => array(
576 - 'date',
577 - 'id',
578 - 'include',
579 - 'title',
580 - 'slug',
581 - 'modified',
582 - ),
583 - 'validate_callback' => 'rest_validate_request_arg',
584 - );
585 - $params['author'] = array(
586 - 'description' => __( 'Limit the result set to posts assigned to specific authors.', 'learnpress' ),
587 - 'type' => 'array',
588 - 'items' => array(
589 - 'type' => 'integer',
590 - ),
591 - 'default' => array(),
592 - );
593 - $params['author_exclude'] = array(
594 - 'description' => __( 'Ensure the result set excludes posts assigned to specific authors.', 'learnpress' ),
595 - 'type' => 'array',
596 - 'items' => array(
597 - 'type' => 'integer',
598 - ),
599 - 'default' => array(),
600 - );
601 - $params['user'] = array(
602 - 'description' => __( 'Limit the result set to posts assigned to specific authors.', 'learnpress' ),
603 - 'type' => 'array',
604 - 'items' => array(
605 - 'type' => 'integer',
606 - ),
607 - 'default' => array(),
608 - );
609 - $params['learned'] = array(
610 - 'description' => __( 'Get item learned by user.', 'learnpress' ),
611 - 'type' => 'boolean',
612 - 'default' => false,
613 - 'validate_callback' => 'rest_validate_request_arg',
614 - );
615 -
616 - if ( $this->hierarchical ) {
617 - $params['parent'] = array(
618 - 'description' => __( 'Limit the result set to those of particular parent IDs.', 'learnpress' ),
619 - 'type' => 'array',
620 - 'items' => array(
621 - 'type' => 'integer',
622 - ),
623 - 'sanitize_callback' => 'wp_parse_id_list',
624 - 'default' => array(),
625 - );
626 - $params['parent_exclude'] = array(
627 - 'description' => __( 'Limit the result set to all items except those of a particular parent ID.', 'learnpress' ),
628 - 'type' => 'array',
629 - 'items' => array(
630 - 'type' => 'integer',
631 - ),
632 - 'sanitize_callback' => 'wp_parse_id_list',
633 - 'default' => array(),
634 - );
635 - }
636 -
637 - return apply_filters( "rest_{$this->post_type}_collection_params", $params, $this->post_type );
638 - }
639 -}
1 +<?php
2 +abstract class LP_REST_Jwt_Posts_Controller extends LP_REST_Jwt_Controller {
3 + protected $namespace = 'learnpress/v1';
4 +
5 + protected $rest_base = '';
6 +
7 + protected $post_type = '';
8 +
9 + protected $public = false;
10 +
11 + protected $hierarchical = false;
12 +
13 + protected function get_object( $id ) {
14 + return new WP_Error( 'invalid-method', sprintf( __( "The method '%s' not implemented. It must be overridden in the subclass.", 'learnpress' ), __METHOD__ ), array( 'status' => 405 ) );
15 + }
16 +
17 + public function get_items_permissions_check( $request ) {
18 + if ( ! lp_rest_check_post_permissions( $this->post_type, 'read' ) ) {
19 + return new WP_Error( 'lp_jwt_rest_cannot_view', __( 'Sorry, you cannot get lists', 'learnpress' ), array( 'status' => rest_authorization_required_code() ) );
20 + }
21 +
22 + return true;
23 + }
24 +
25 + /**
26 + * Check if a given request has access to create an item.
27 + *
28 + * @param WP_REST_Request $request Full details about the request.
29 + * @return WP_Error|boolean
30 + */
31 + public function create_item_permissions_check( $request ) {
32 + if ( ! lp_rest_check_post_permissions( $this->post_type, 'create' ) ) {
33 + return new WP_Error( 'lp_rest_cannot_create', __( 'Sorry, you are not allowed to create resources.', 'learnpress' ), array( 'status' => rest_authorization_required_code() ) );
34 + }
35 +
36 + return true;
37 + }
38 +
39 + public function get_item_permissions_check( $request ) {
40 + if ( $this->post_type !== get_post_type( (int) $request['id'] ) ) {
41 + return new WP_Error( 'lp_jwt_rest_not_in_post_type', __( 'Sorry, You cannot view this item.', 'learnpress' ), array( 'status' => rest_authorization_required_code() ) );
42 + }
43 +
44 + $object = $this->get_object( (int) $request['id'] );
45 +
46 + if ( $object && 0 !== $object->get_id() && ! $this->check_read_permission( $object->get_id() ) ) {
47 + return new WP_Error( 'lp_jwt_rest_cannot_view', __( 'Sorry, you cannot view this resource.', 'learnpress' ), array( 'status' => rest_authorization_required_code() ) );
48 + }
49 +
50 + return true;
51 + }
52 +
53 + public function check_read_permission( $post_id ) {
54 + if ( ! lp_rest_check_post_permissions( $this->post_type, 'read', $post_id ) ) {
55 + return false;
56 + }
57 +
58 + return true;
59 + }
60 +
61 + public function get_item( $request ) {
62 + $object = $this->get_object( (int) $request['id'] );
63 +
64 + if ( ! $object || 0 === $object->get_id() ) {
65 + return new WP_Error( "lp_rest_{$this->post_type}_invalid_id", esc_html__( 'Invalid ID.', 'learnpress' ), array( 'status' => 404 ) );
66 + }
67 +
68 + $data = $this->prepare_object_for_response( $object, $request );
69 + $response = rest_ensure_response( $data );
70 +
71 + if ( $this->public ) {
72 + $response->link_header( 'alternate', $this->get_permalink( $object ), array( 'type' => 'text/html' ) );
73 + }
74 +
75 + return $response;
76 + }
77 +
78 + public function get_items( $request ) {
79 + $query_args = $this->prepare_objects_query( $request );
80 + $query_results = $this->get_objects( $query_args );
81 +
82 + $objects = array();
83 + foreach ( $query_results['objects'] as $object ) {
84 + $object_id = ! empty( $object->ID ) ? $object->ID : $object->get_id();
85 +
86 + if ( ! $this->check_read_permission( $object_id ) ) {
87 + continue;
88 + }
89 +
90 + $data = $this->prepare_object_for_response( $object, $request );
91 + $objects[] = $this->prepare_response_for_collection( $data );
92 + }
93 +
94 + $page = (int) $query_args['paged'];
95 + $max_pages = $query_results['pages'];
96 +
97 + $response = rest_ensure_response( $objects );
98 + $response->header( 'X-WP-Total', $query_results['total'] );
99 + $response->header( 'X-WP-TotalPages', (int) $max_pages );
100 +
101 + $base = $this->rest_base;
102 + $attrib_prefix = '(?P<';
103 +
104 + if ( strpos( $base, $attrib_prefix ) !== false ) {
105 + $attrib_names = array();
106 + preg_match( '/\(\?P<[^>]+>.*\)/', $base, $attrib_names, PREG_OFFSET_CAPTURE );
107 +
108 + foreach ( $attrib_names as $attrib_name_match ) {
109 + $beginning_offset = strlen( $attrib_prefix );
110 + $attrib_name_end = strpos( $attrib_name_match[0], '>', $attrib_name_match[1] );
111 + $attrib_name = substr( $attrib_name_match[0], $beginning_offset, $attrib_name_end - $beginning_offset );
112 +
113 + if ( isset( $request[ $attrib_name ] ) ) {
114 + $base = str_replace( "(?P<$attrib_name>[\d]+)", $request[ $attrib_name ], $base );
115 + }
116 + }
117 + }
118 +
119 + $base = esc_url_raw( add_query_arg( $request->get_query_params(), rest_url( sprintf( '/%s/%s', $this->namespace, $base ) ) ) );
120 +
121 + if ( $page > 1 ) {
122 + $prev_page = $page - 1;
123 + if ( $prev_page > $max_pages ) {
124 + $prev_page = $max_pages;
125 + }
126 + $prev_link = esc_url_raw( add_query_arg( 'page', $prev_page, $base ) );
127 + $response->link_header( 'prev', $prev_link );
128 + }
129 +
130 + if ( $max_pages > $page ) {
131 + $next_page = $page + 1;
132 + $next_link = esc_url_raw( add_query_arg( 'page', $next_page, $base ) );
133 + $response->link_header( 'next', $next_link );
134 + }
135 +
136 + return $response;
137 + }
138 +
139 + /**
140 + * Create a single item.
141 + *
142 + * @param WP_REST_Request $request Full details about the request.
143 + * @return WP_Error|WP_REST_Response
144 + */
145 + public function create_item( $request ) {
146 + if ( ! empty( $request['id'] ) ) {
147 + /* translators: %s: post type */
148 + return new WP_Error( "lp_rest_{$this->post_type}_exists", sprintf( __( 'Cannot create existing %s.', 'learnpress' ), $this->post_type ), array( 'status' => 400 ) );
149 + }
150 +
151 + $post = $this->prepare_item_for_database( $request );
152 + if ( is_wp_error( $post ) ) {
153 + return $post;
154 + }
155 +
156 + $post->post_type = $this->post_type;
157 + $post_id = wp_insert_post( $post, true );
158 +
159 + if ( is_wp_error( $post_id ) ) {
160 + if ( in_array( $post_id->get_error_code(), array( 'db_insert_error' ) ) ) {
161 + $post_id->add_data( array( 'status' => 500 ) );
162 + } else {
163 + $post_id->add_data( array( 'status' => 400 ) );
164 + }
165 + return $post_id;
166 + }
167 +
168 + $post->ID = $post_id;
169 + $post = get_post( $post_id );
170 +
171 + $this->update_additional_fields_for_object( $post, $request );
172 +
173 + // Add meta fields.
174 + $meta_fields = $this->add_post_meta_fields( $post, $request );
175 + if ( is_wp_error( $meta_fields ) ) {
176 + // Remove post.
177 + $this->delete_post( $post );
178 +
179 + return $meta_fields;
180 + }
181 +
182 + /**
183 + * Fires after a single item is created or updated via the REST API.
184 + *
185 + * @param WP_Post $post Post object.
186 + * @param WP_REST_Request $request Request object.
187 + * @param boolean $creating True when creating item, false when updating.
188 + */
189 + do_action( "lp_rest_insert_{$this->post_type}", $post, $request, true );
190 +
191 + $request->set_param( 'context', 'edit' );
192 + $response = $this->prepare_item_for_response( $post, $request );
193 + $response = rest_ensure_response( $response );
194 + $response->set_status( 201 );
195 + $response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $post_id ) ) );
196 +
197 + return $response;
198 + }
199 +
200 + public function prepare_item_for_database( $request, $creating = false ) {
201 + $prepared_post = new stdClass();
202 + $current_status = '';
203 +
204 + $id = isset( $request['id'] ) ? absint( $request['id'] ) : 0;
205 +
206 + if ( isset( $request['id'] ) ) {
207 + $existing_post = get_post( $id );
208 +
209 + if ( empty( $existing_post ) || empty( $existing_post->ID ) || $this->post_type !== $existing_post->post_type ) {
210 + return new WP_Error( 'rest_invalid_course', __( 'Invalid Course', 'learnpress' ), array( 'status' => 404 ) );
211 + }
212 +
213 + $prepared_post->ID = $existing_post->ID;
214 + $current_status = $existing_post->post_status;
215 + }
216 +
217 + $schema = $this->get_item_schema();
218 +
219 + // Post title.
220 + if ( ! empty( $schema['properties']['name'] ) && isset( $request['name'] ) ) {
221 + if ( is_string( $request['name'] ) ) {
222 + $prepared_post->post_title = $request['name'];
223 + } elseif ( ! empty( $request['name']['raw'] ) ) {
224 + $prepared_post->post_title = $request['name']['raw'];
225 + }
226 + }
227 +
228 + // Post content.
229 + if ( ! empty( $schema['properties']['content'] ) && isset( $request['content'] ) ) {
230 + if ( is_string( $request['content'] ) ) {
231 + $prepared_post->post_content = $request['content'];
232 + } elseif ( isset( $request['content']['raw'] ) ) {
233 + $prepared_post->post_content = $request['content']['raw'];
234 + }
235 + }
236 +
237 + // Post excerpt.
238 + if ( ! empty( $schema['properties']['excerpt'] ) && isset( $request['excerpt'] ) ) {
239 + if ( is_string( $request['excerpt'] ) ) {
240 + $prepared_post->post_excerpt = $request['excerpt'];
241 + } elseif ( isset( $request['excerpt']['raw'] ) ) {
242 + $prepared_post->post_excerpt = $request['excerpt']['raw'];
243 + }
244 + }
245 +
246 + // Post type.
247 + if ( empty( $request['id'] ) ) {
248 + // Creating new post, use default type for the controller.
249 + $prepared_post->post_type = $this->post_type;
250 + } else {
251 + // Updating a post, use previous type.
252 + $prepared_post->post_type = get_post_type( $request['id'] );
253 + }
254 +
255 + $post_type = get_post_type_object( $prepared_post->post_type );
256 +
257 + // Post status.
258 + if (
259 + ! empty( $schema['properties']['status'] ) &&
260 + isset( $request['status'] ) &&
261 + ( ! $current_status || $current_status !== $request['status'] )
262 + ) {
263 + $status = $this->handle_status_param( $request['status'], $post_type );
264 +
265 + if ( is_wp_error( $status ) ) {
266 + return $status;
267 + }
268 +
269 + $prepared_post->post_status = $status;
270 + }
271 +
272 + // Post date.
273 + if ( ! empty( $schema['properties']['date'] ) && ! empty( $request['date'] ) ) {
274 + $current_date = isset( $prepared_post->ID ) ? get_post( $prepared_post->ID )->post_date : false;
275 + $date_data = rest_get_date_with_gmt( $request['date'] );
276 +
277 + if ( ! empty( $date_data ) && $current_date !== $date_data[0] ) {
278 + list( $prepared_post->post_date, $prepared_post->post_date_gmt ) = $date_data;
279 + $prepared_post->edit_date = true;
280 + }
281 + } elseif ( ! empty( $schema['properties']['date_gmt'] ) && ! empty( $request['date_gmt'] ) ) {
282 + $current_date = isset( $prepared_post->ID ) ? get_post( $prepared_post->ID )->post_date_gmt : false;
283 + $date_data = rest_get_date_with_gmt( $request['date_gmt'], true );
284 +
285 + if ( ! empty( $date_data ) && $current_date !== $date_data[1] ) {
286 + list( $prepared_post->post_date, $prepared_post->post_date_gmt ) = $date_data;
287 + $prepared_post->edit_date = true;
288 + }
289 + }
290 +
291 + // Sending a null date or date_gmt value resets date and date_gmt to their
292 + // default values (`0000-00-00 00:00:00`).
293 + if (
294 + ( ! empty( $schema['properties']['date_gmt'] ) && $request->has_param( 'date_gmt' ) && null === $request['date_gmt'] ) ||
295 + ( ! empty( $schema['properties']['date'] ) && $request->has_param( 'date' ) && null === $request['date'] )
296 + ) {
297 + $prepared_post->post_date_gmt = null;
298 + $prepared_post->post_date = null;
299 + }
300 +
301 + // Post slug.
302 + if ( ! empty( $schema['properties']['slug'] ) && isset( $request['slug'] ) ) {
303 + $prepared_post->post_name = $request['slug'];
304 + }
305 +
306 + // Author.
307 + if ( ! empty( $schema['properties']['author'] ) && ! empty( $request['author'] ) ) {
308 + $post_author = (int) $request['author'];
309 +
310 + if ( get_current_user_id() !== $post_author ) {
311 + $user_obj = get_userdata( $post_author );
312 +
313 + if ( ! $user_obj ) {
314 + return new WP_Error(
315 + 'rest_invalid_author',
316 + __( 'Invalid author ID.' ),
317 + array( 'status' => 400 )
318 + );
319 + }
320 + }
321 +
322 + $prepared_post->post_author = $post_author;
323 + }
324 +
325 + // Post password.
326 + if ( ! empty( $schema['properties']['password'] ) && isset( $request['password'] ) ) {
327 + $prepared_post->post_password = $request['password'];
328 +
329 + if ( '' !== $request['password'] ) {
330 + if ( ! empty( $schema['properties']['sticky'] ) && ! empty( $request['sticky'] ) ) {
331 + return new WP_Error(
332 + 'rest_invalid_field',
333 + __( 'A post can not be sticky and have a password.' ),
334 + array( 'status' => 400 )
335 + );
336 + }
337 +
338 + if ( ! empty( $prepared_post->ID ) && is_sticky( $prepared_post->ID ) ) {
339 + return new WP_Error(
340 + 'rest_invalid_field',
341 + __( 'A sticky post can not be password protected.' ),
342 + array( 'status' => 400 )
343 + );
344 + }
345 + }
346 + }
347 +
348 + return apply_filters( "lp_rest_pre_insert_{$this->post_type}", $prepared_post, $request );
349 + }
350 +
351 + /**
352 + * Determines validity and normalizes the given status parameter.
353 + *
354 + * @since 4.7.0
355 + *
356 + * @param string $post_status Post status.
357 + * @param WP_Post_Type $post_type Post type.
358 + * @return string|WP_Error Post status or WP_Error if lacking the proper permission.
359 + */
360 + protected function handle_status_param( $post_status, $post_type ) {
361 +
362 + switch ( $post_status ) {
363 + case 'draft':
364 + case 'pending':
365 + break;
366 + case 'private':
367 + if ( ! current_user_can( $post_type->cap->publish_posts ) ) {
368 + return new WP_Error(
369 + 'rest_cannot_publish',
370 + __( 'Sorry, you are not allowed to create private posts in this post type.' ),
371 + array( 'status' => rest_authorization_required_code() )
372 + );
373 + }
374 + break;
375 + case 'publish':
376 + case 'future':
377 + if ( ! current_user_can( $post_type->cap->publish_posts ) ) {
378 + return new WP_Error(
379 + 'rest_cannot_publish',
380 + __( 'Sorry, you are not allowed to publish posts in this post type.' ),
381 + array( 'status' => rest_authorization_required_code() )
382 + );
383 + }
384 + break;
385 + default:
386 + if ( ! get_post_status_object( $post_status ) ) {
387 + $post_status = 'draft';
388 + }
389 + break;
390 + }
391 +
392 + return $post_status;
393 + }
394 +
395 + protected function prepare_objects_query( $request ) {
396 + global $wpdb;
397 +
398 + $args = array();
399 + $args['offset'] = $request['offset'];
400 + $args['order'] = $request['order'];
401 + $args['orderby'] = $request['orderby'];
402 + $args['paged'] = $request['page'];
403 + $args['post__in'] = $request['include'];
404 + $args['post__not_in'] = $request['exclude'];
405 + $args['posts_per_page'] = $request['per_page'];
406 + $args['name'] = $request['slug'];
407 + $args['post_parent__in'] = $request['parent'];
408 + $args['post_parent__not_in'] = $request['parent_exclude'];
409 + $args['s'] = $request['search'];
410 + $args['author__in'] = ! empty( $request['user'] ) ? $request['user'] : $request['author'];
411 + $args['author__not_in'] = $request['author_exclude'];
412 + $args['fields'] = $this->get_fields_for_response( $request );
413 +
414 + if ( 'date' === $args['orderby'] ) {
415 + $args['orderby'] = 'date ID';
416 + }
417 +
418 + $args['date_query'] = array();
419 +
420 + if ( isset( $request['before'] ) ) {
421 + $args['date_query'][0]['before'] = $request['before'];
422 + }
423 +
424 + if ( isset( $request['after'] ) ) {
425 + $args['date_query'][0]['after'] = $request['after'];
426 + }
427 +
428 + // Get item user is learned
429 + if ( ! empty( $request['learned'] ) ) {
430 + $item_ids = $this->get_item_learned_ids( $request );
431 +
432 + // Force WP_Query return empty if don't found any order.
433 + $item_ids = ! empty( $item_ids ) ? $item_ids : array( 0 );
434 +
435 + $args['post__in'] = $item_ids;
436 + }
437 +
438 + $args['post_type'] = $this->post_type;
439 +
440 + $args = apply_filters( "lp_jwt_rest_{$this->post_type}_object_query", $args, $request );
441 +
442 + return $this->prepare_items_query( $args, $request );
443 + }
444 +
445 + /** Get all items has in database learnpress_user_items by post_type */
446 + public function get_item_learned_ids( $request ) {
447 + return array();
448 + }
449 +
450 + protected function get_objects( $query_args ) {
451 + $query = new WP_Query();
452 + $result = $query->query( $query_args );
453 +
454 + $total_posts = $query->found_posts;
455 +
456 + if ( $total_posts < 1 ) {
457 + unset( $query_args['paged'] );
458 + $count_query = new WP_Query();
459 + $count_query->query( $query_args );
460 + $total_posts = $count_query->found_posts;
461 + }
462 +
463 + return array(
464 + 'objects' => array_filter( array_map( array( $this, 'get_object' ), $result ) ),
465 + 'total' => (int) $total_posts,
466 + 'pages' => (int) ceil( $total_posts / (int) $query->query_vars['posts_per_page'] ),
467 + );
468 + }
469 +
470 + protected function add_post_meta_fields( $post, $request ) {
471 + return true;
472 + }
473 +
474 + protected function prepare_object_for_response( $object, $request ) {
475 + return new WP_Error( 'invalid-method', sprintf( __( "The method '%s' not implemented. It must be overridden in the subclass.", 'learnpress' ), __METHOD__ ), array( 'status' => 405 ) );
476 + }
477 +
478 + protected function prepare_items_query( $prepared_args = array(), $request = null ) {
479 + $query_args = array();
480 +
481 + foreach ( $prepared_args as $key => $value ) {
482 + $query_args[ $key ] = apply_filters( "rest_query_var-{$key}", $value ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
483 + }
484 +
485 + if ( 'post' !== $this->post_type || ! isset( $query_args['ignore_sticky_posts'] ) ) {
486 + $query_args['ignore_sticky_posts'] = true;
487 + }
488 +
489 + if ( 'include' === $query_args['orderby'] ) {
490 + $query_args['orderby'] = 'post__in';
491 + } elseif ( 'id' === $query_args['orderby'] ) {
492 + $query_args['orderby'] = 'ID';
493 + } elseif ( 'slug' === $query_args['orderby'] ) {
494 + $query_args['orderby'] = 'name';
495 + }
496 +
497 + return $query_args;
498 + }
499 +
500 + public function get_collection_params() {
501 + $params = array();
502 + $params['context'] = $this->get_context_param();
503 + $params['context']['default'] = 'view';
504 +
505 + $params['page'] = array(
506 + 'description' => __( 'The current page of the collection.', 'learnpress' ),
507 + 'type' => 'integer',
508 + 'default' => 1,
509 + 'sanitize_callback' => 'absint',
510 + 'validate_callback' => 'rest_validate_request_arg',
511 + 'minimum' => 1,
512 + );
513 + $params['per_page'] = array(
514 + 'description' => __( 'The maximum number of items to be returned in the result set.', 'learnpress' ),
515 + 'type' => 'integer',
516 + 'default' => 10,
517 + 'minimum' => 1,
518 + 'maximum' => 100,
519 + 'sanitize_callback' => 'absint',
520 + 'validate_callback' => 'rest_validate_request_arg',
521 + );
522 + $params['search'] = array(
523 + 'description' => __( 'Limit results to those matching a string.', 'learnpress' ),
524 + 'type' => 'string',
525 + 'sanitize_callback' => 'sanitize_text_field',
526 + 'validate_callback' => 'rest_validate_request_arg',
527 + );
528 + $params['after'] = array(
529 + 'description' => __( 'Limit response to resources published after a given ISO8601 compliant date.', 'learnpress' ),
530 + 'type' => 'string',
531 + 'format' => 'date-time',
532 + 'validate_callback' => 'rest_validate_request_arg',
533 + );
534 + $params['before'] = array(
535 + 'description' => __( 'Limit response to resources published before a given ISO8601 compliant date.', 'learnpress' ),
536 + 'type' => 'string',
537 + 'format' => 'date-time',
538 + 'validate_callback' => 'rest_validate_request_arg',
539 + );
540 + $params['exclude'] = array(
541 + 'description' => __( 'Ensure the result set excludes specific IDs.', 'learnpress' ),
542 + 'type' => 'array',
543 + 'items' => array(
544 + 'type' => 'integer',
545 + ),
546 + 'default' => array(),
547 + 'sanitize_callback' => 'wp_parse_id_list',
548 + );
549 + $params['include'] = array(
550 + 'description' => __( 'Limit the result set to specific IDs.', 'learnpress' ),
551 + 'type' => 'array',
552 + 'items' => array(
553 + 'type' => 'integer',
554 + ),
555 + 'default' => array(),
556 + 'sanitize_callback' => 'wp_parse_id_list',
557 + );
558 + $params['offset'] = array(
559 + 'description' => __( 'Offset the result set by a specific number of items.', 'learnpress' ),
560 + 'type' => 'integer',
561 + 'sanitize_callback' => 'absint',
562 + 'validate_callback' => 'rest_validate_request_arg',
563 + );
564 + $params['order'] = array(
565 + 'description' => __( 'Sorting attributes in ascending or descending order.', 'learnpress' ),
566 + 'type' => 'string',
567 + 'default' => 'desc',
568 + 'enum' => array( 'asc', 'desc' ),
569 + 'validate_callback' => 'rest_validate_request_arg',
570 + );
571 + $params['orderby'] = array(
572 + 'description' => __( 'Sort collections by the object attribute.', 'learnpress' ),
573 + 'type' => 'string',
574 + 'default' => 'date',
575 + 'enum' => array(
576 + 'date',
577 + 'id',
578 + 'include',
579 + 'title',
580 + 'slug',
581 + 'modified',
582 + ),
583 + 'validate_callback' => 'rest_validate_request_arg',
584 + );
585 + $params['author'] = array(
586 + 'description' => __( 'Limit the result set to posts assigned to specific authors.', 'learnpress' ),
587 + 'type' => 'array',
588 + 'items' => array(
589 + 'type' => 'integer',
590 + ),
591 + 'default' => array(),
592 + );
593 + $params['author_exclude'] = array(
594 + 'description' => __( 'Ensure the result set excludes posts assigned to specific authors.', 'learnpress' ),
595 + 'type' => 'array',
596 + 'items' => array(
597 + 'type' => 'integer',
598 + ),
599 + 'default' => array(),
600 + );
601 + $params['user'] = array(
602 + 'description' => __( 'Limit the result set to posts assigned to specific authors.', 'learnpress' ),
603 + 'type' => 'array',
604 + 'items' => array(
605 + 'type' => 'integer',
606 + ),
607 + 'default' => array(),
608 + );
609 + $params['learned'] = array(
610 + 'description' => __( 'Get item learned by user.', 'learnpress' ),
611 + 'type' => 'boolean',
612 + 'default' => false,
613 + 'validate_callback' => 'rest_validate_request_arg',
614 + );
615 +
616 + if ( $this->hierarchical ) {
617 + $params['parent'] = array(
618 + 'description' => __( 'Limit the result set to those of particular parent IDs.', 'learnpress' ),
619 + 'type' => 'array',
620 + 'items' => array(
621 + 'type' => 'integer',
622 + ),
623 + 'sanitize_callback' => 'wp_parse_id_list',
624 + 'default' => array(),
625 + );
626 + $params['parent_exclude'] = array(
627 + 'description' => __( 'Limit the result set to all items except those of a particular parent ID.', 'learnpress' ),
628 + 'type' => 'array',
629 + 'items' => array(
630 + 'type' => 'integer',
631 + ),
632 + 'sanitize_callback' => 'wp_parse_id_list',
633 + 'default' => array(),
634 + );
635 + }
636 +
637 + return apply_filters( "rest_{$this->post_type}_collection_params", $params, $this->post_type );
638 + }
639 +}