PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.2.0
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.2.0
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 4.2.0 All 139 releases
learnpress / inc / rest-api / v1 / frontend / class-lp-rest-courses-controller.php

class-lp-rest-courses-controller.php in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.2.0, at inc/rest-api/v1/frontend/class-lp-rest-courses-controller.php

675 lines 20.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Class LP_REST_Courses_Controller
5 */
6
7 use LearnPress\Helpers\Template;
8
9 class LP_REST_Courses_Controller extends LP_Abstract_REST_Controller {
10 /**
11 * LP_REST_Courses_Controller constructor.
12 */
13 public function __construct() {
14 $this->namespace = 'lp/v1';
15 $this->rest_base = 'courses';
16 parent::__construct();
17 }
18
19 /**
20 * Register routes API
21 */
22 public function register_routes() {
23 $this->routes = array(
24 'purchase-course' => array(
25 array(
26 'methods' => WP_REST_Server::CREATABLE,
27 'callback' => array( $this, 'purchase_course' ),
28 'permission_callback' => '__return_true',
29 ),
30 ),
31 'enroll-course' => array(
32 array(
33 'methods' => WP_REST_Server::CREATABLE,
34 'callback' => array( $this, 'enroll_courses' ),
35 'permission_callback' => '__return_true',
36 ),
37 ),
38 'retake-course' => array(
39 array(
40 'methods' => WP_REST_Server::CREATABLE,
41 'callback' => array( $this, 'retake_course' ),
42 'permission_callback' => function () {
43 return is_user_logged_in();
44 },
45 'schema' => array(
46 'type' => 'int',
47 ),
48 ),
49 ),
50 'archive-course' => array(
51 array(
52 'methods' => WP_REST_Server::ALLMETHODS,
53 'callback' => array( $this, 'list_courses' ),
54 'permission_callback' => '__return_true',
55 'args' => [],
56 ),
57 ),
58 '(?P<key>[\w]+)' => array(
59 'args' => array(
60 'id' => array(
61 'description' => __( 'A unique identifier for the resource.', 'learnpress' ),
62 'type' => 'string',
63 ),
64 ),
65 array(
66 'methods' => WP_REST_Server::READABLE,
67 'callback' => array( $this, 'get_item' ),
68 'permission_callback' => array( $this, 'check_admin_permission' ),
69 ),
70 array(
71 'methods' => WP_REST_Server::EDITABLE,
72 'callback' => array( $this, 'update_item' ),
73 'permission_callback' => array( $this, 'check_admin_permission' ),
74 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
75 ),
76 array(
77 'methods' => WP_REST_Server::DELETABLE,
78 'callback' => array( $this, 'delete_item' ),
79 'permission_callback' => array( $this, 'check_admin_permission' ),
80 ),
81 'schema' => array( $this, 'get_public_item_schema' ),
82 ),
83 'continue-course' => array(
84 array(
85 'methods' => WP_REST_Server::CREATABLE,
86 'callback' => array( $this, 'continue_course' ),
87 'permission_callback' => function () {
88 return is_user_logged_in();
89 },
90 ),
91 ),
92 );
93
94 parent::register_routes();
95 }
96
97 /**
98 * Check user is Admin
99 *
100 * @return bool
101 */
102 public function check_admin_permission(): bool {
103 return LP_Abstract_API::check_admin_permission();
104 }
105
106 /**
107 * Get list courses
108 *
109 * @param WP_REST_Request $request
110 *
111 * @return LP_REST_Response
112 */
113 public function list_courses( WP_REST_Request $request ): LP_REST_Response {
114 $response = new LP_REST_Response();
115 $response->data = new stdClass();
116
117 try {
118 $filter = new LP_Course_Filter();
119 $filter->page = absint( $request['paged'] ?? 1 );
120 $filter->post_title = LP_Helper::sanitize_params_submitted( $request['c_search'] ?? '' );
121 $fields_str = LP_Helper::sanitize_params_submitted( urldecode( $request['c_fields'] ?? '' ) );
122 $fields_exclude_str = LP_Helper::sanitize_params_submitted( urldecode( $request['c_exclude_fields'] ?? '' ) );
123 if ( ! empty( $fields_str ) ) {
124 $fields = explode( ',', $fields_str );
125 $filter->fields = $fields;
126 }
127
128 if ( ! empty( $fields_exclude_str ) ) {
129 $fields_exclude = explode( ',', $fields_exclude_str );
130 $filter->exclude_fields = $fields_exclude;
131 }
132
133 $filter->post_author = LP_Helper::sanitize_params_submitted( $request['c_author'] ?? 0 );
134 $author_ids_str = LP_Helper::sanitize_params_submitted( $request['c_authors'] ?? 0 );
135 if ( ! empty( $author_ids_str ) ) {
136 $author_ids = explode( ',', $author_ids_str );
137 $filter->post_authors = $author_ids;
138 }
139
140 $term_ids_str = LP_Helper::sanitize_params_submitted( urldecode( $request['term_id'] ?? '' ) );
141 if ( ! empty( $term_ids_str ) ) {
142 $term_ids = explode( ',', $term_ids_str );
143 $filter->term_ids = $term_ids;
144 }
145
146 $on_sale = absint( $request['on_sale'] ?? '0' );
147 1 === $on_sale ? $filter->sort_by[] = 'on_sale' : '';
148 $on_feature = absint( $request['on_feature'] ?? '0' );
149 1 === $on_feature ? $filter->sort_by[] = 'on_feature' : '';
150
151 $filter->order_by = LP_Helper::sanitize_params_submitted( ! empty( $request['order_by'] ) ? $request['order_by'] : 'post_date' );
152 $filter->order = LP_Helper::sanitize_params_submitted( ! empty( $request['order'] ) ? $request['order'] : 'DESC' );
153 $filter->limit = $request['limit'] ?? LP_Settings::get_option( 'archive_course_limit', 10 );
154 $return_type = $request['return_type'] ?? 'html';
155 if ( 'json' !== $return_type ) {
156 $filter->only_fields = array( 'DISTINCT(ID) AS ID' );
157 }
158
159 $total_rows = 0;
160 $filter = apply_filters( 'lp/api/courses/filter', $filter, $request );
161 $courses = LP_Course::get_courses( $filter, $total_rows );
162 $total_pages = LP_Database::get_total_pages( $filter->limit, $total_rows );
163
164 if ( 'json' === $return_type ) {
165 $response->data->courses = $courses;
166 $response->data->total_pages = $total_pages;
167 } else {
168 // For return data has html
169 ob_start();
170 if ( $courses ) {
171 global $wp, $post;
172
173 // Template Pagination.
174 $response->data->pagination = learn_press_get_template_content(
175 'loop/course/pagination.php',
176 array(
177 'total' => $total_pages,
178 'paged' => $filter->page,
179 )
180 );
181 // End Pagination
182
183 // For custom template
184 $template_path = apply_filters( 'lp/api/courses/template', '' );
185 if ( ! empty( $template_path ) ) {
186 Template::instance()->get_template( $template_path, compact( 'courses', 'total_pages' ) );
187 } else {
188 foreach ( $courses as $course ) {
189 $post = get_post( $course->ID );
190 setup_postdata( $post );
191 Template::instance()->get_frontend_template( 'content-course.php' );
192 }
193
194 wp_reset_postdata();
195 }
196 // End content items
197 } else {
198 LearnPress::instance()->template( 'course' )->no_courses_found();
199 }
200
201 $response->data->content = ob_get_clean();
202 $response->data->totals = $total_rows;
203
204 $from = 1 + ( $filter->page - 1 ) * $filter->limit;
205 $to = ( $filter->page * $filter->limit > $total_rows ) ? $total_rows : $filter->page * $filter->limit;
206
207 if ( 0 === $total_rows ) {
208 $response->data->from_to = '';
209 } elseif ( 1 === $total_rows ) {
210 $response->data->from_to = esc_html__( 'Showing only one result', 'learnpress' );
211 } else {
212 if ( $from == $to ) {
213 $response->data->from_to = sprintf( esc_html__( 'Showing last course of %s results', 'learnpress' ), $total_rows );
214 } else {
215 $from_to = $from . '-' . $to;
216 $response->data->from_to = sprintf( esc_html__( 'Showing %1$s of %2$s results', 'learnpress' ), $from_to, $total_rows );
217 }
218 }
219 }
220
221 $response->status = 'success';
222 } catch ( Throwable $e ) {
223 ob_end_clean();
224 $response->data->content = $e->getMessage();
225 $response->message = $e->getMessage();
226 }
227
228 return apply_filters( 'lp/rest-api/frontend/course/archive_course/response', $response );
229 }
230
231 /**
232 * Rest API for Enroll in single course.
233 *
234 * @param WP_REST_Request $request
235 *
236 * @return LP_REST_Response
237 * @author Nhamdv
238 * @editor tungnx
239 * @version 1.0.2
240 * @since 4.0.0
241 */
242 public function enroll_courses( WP_REST_Request $request ): LP_REST_Response {
243 $response = new LP_REST_Response();
244 $response->data = new stdClass();
245 $lp_user_items_db = LP_User_Items_DB::getInstance();
246
247 try {
248 $course_id = absint( $request['id'] ?? 0 );
249 $course = learn_press_get_course( $course_id );
250 if ( ! $course ) {
251 throw new Exception( esc_html__( 'Invalid course!', 'learnpress' ) );
252 }
253
254 $user = learn_press_get_current_user();
255 $can_enroll = $user->can_enroll_course( $course_id, false );
256
257 if ( ! $can_enroll->check ) {
258 throw new Exception( $can_enroll->message ?? esc_html__( 'Error: Cannot enroll in the course.', 'learnpress' ) );
259 }
260
261 $filter = new LP_User_Items_Filter();
262 $filter->user_id = get_current_user_id();
263 $filter->item_id = $course_id;
264 $course_item = $lp_user_items_db->get_last_user_course( $filter );
265
266 // Case: if user bought course - or create order manual with order "completed".
267 if ( $course_item && 'purchased' == $course_item->status ) {
268 $user_item_data = [
269 'user_item_id' => $course_item->user_item_id,
270 'graduation' => LP_COURSE_GRADUATION_IN_PROGRESS,
271 'status' => LP_COURSE_ENROLLED,
272 'start_time' => time(),
273 ];
274
275 $user_item_new_or_update = new LP_User_Item_Course( $user_item_data );
276 $result = $user_item_new_or_update->update();
277
278 if ( ! $result ) {
279 throw new Exception( esc_html__( 'Error: Cannot Enroll in the course.', 'learnpress' ) );
280 }
281
282 do_action( 'learnpress/user/course-enrolled', $course_item->ref_id, $course_id, $user->get_id() );
283 } else { // Case enroll course free
284 //LearnPress::instance()->session->set( 'order_awaiting_payment', '' );
285
286 $cart = LearnPress::instance()->cart;
287 $checkout = LP_Checkout::instance();
288
289 if ( ! learn_press_enable_cart() ) {
290 //$order_awaiting_payment = LearnPress::instance()->session->order_awaiting_payment;
291 $cart->empty_cart();
292 //LearnPress::instance()->session->order_awaiting_payment = $order_awaiting_payment;
293 }
294
295 $cart_id = $cart->add_to_cart( $course_id, 1, array() );
296
297 if ( ! $cart_id ) {
298 throw new Exception( esc_html__( 'Error: The course cannot be added to the cart.', 'learnpress' ) );
299 }
300
301 if ( is_user_logged_in() ) {
302 $order_id = $checkout->create_order();
303
304 if ( is_wp_error( $order_id ) ) {
305 throw new Exception( $order_id->get_error_message() );
306 }
307
308 $order = new LP_Order( $order_id );
309
310 $order->payment_complete();
311
312 $cart->empty_cart();
313 }
314 }
315
316 if ( is_user_logged_in() ) {
317 $response->status = 'success';
318 // Course has no items
319 $response->message = esc_html__(
320 'Congrats! You have enrolled in the course successfully. Redirecting...',
321 'learnpress'
322 );
323
324 $response->data->redirect = $course->get_redirect_url_after_enroll();
325
326 if ( empty( $course->count_items() ) ) {
327 $response->data->redirect = get_permalink( $course->get_id() );
328 }
329 } else {
330 $redirect_url = apply_filters(
331 'learnpress/rest-api/courses/enroll/redirect',
332 learn_press_get_page_link( 'checkout' ),
333 $course_id
334 );
335
336 if ( empty( $redirect_url ) ) {
337 throw new Exception( __( 'Error: Please set up a page for checkout.', 'learnpress' ) );
338 } elseif ( ! is_user_logged_in() ) { // Fix case: cache page with user anonymous
339 $redirect_url = LP_Helper::get_link_no_cache( $redirect_url );
340 }
341
342 $response->message = esc_html__( 'Redirecting...', 'learnpress' );
343 $response->data->redirect = $redirect_url;
344 }
345 } catch ( Exception $e ) {
346 $response->message = $e->getMessage();
347 }
348
349 return $response;
350 }
351
352 /**
353 * Rest API for Purchase course in single course.
354 *
355 * @param WP_REST_Request $request .
356 *
357 * @return WP_REST_Response|WP_Error
358 * @throws Exception .
359 * @author Nhamdv
360 */
361 public function purchase_course( WP_REST_Request $request ) {
362 $response = new LP_REST_Response();
363 $response->data = new stdClass();
364 $params = $request->get_params();
365 $lp_user_items_db = LP_User_Items_DB::getInstance();
366
367 try {
368 $course_id = $params['id'];
369 $allow_repurchase_type = $params['repurchaseType'] ?? false;
370
371 if ( ! $course_id ) {
372 throw new Exception( __( 'Error: Invalid Course ID.', 'learnpress' ) );
373 }
374
375 $course = learn_press_get_course( $course_id );
376 if ( ! $course ) {
377 throw new Exception( __( 'Error: No Course available.', 'learnpress' ) );
378 }
379
380 $user = learn_press_get_current_user();
381 if ( ! $user->can_purchase_course( $course_id ) ) {
382 throw new Exception( esc_html__( 'Error: Cannot purchase the course!', 'learnpress' ) );
383 }
384
385 $latest_user_item_id = 0;
386
387 $filter = new LP_User_Items_Filter();
388 $filter->user_id = get_current_user_id();
389 $filter->item_id = $course_id;
390 $course_item = $lp_user_items_db->get_last_user_course( $filter );
391
392 if ( $course_item && isset( $course_item->user_item_id ) ) {
393 $latest_user_item_id = $course_item->user_item_id;
394 }
395
396 if ( $course->allow_repurchase() && ! empty( $latest_user_item_id ) && empty( $allow_repurchase_type ) ) {
397 if ( $course->allow_repurchase_course_option() === 'popup' ) {
398 ob_start();
399 ?>
400 <div class="lp_allow_repuchase_select">
401 <ul>
402 <li>
403 <label>
404 <input name="_lp_allow_repurchase_type" value="reset" type="radio" checked="checked" />
405 <?php esc_html_e( 'Reset Course progress', 'learnpress' ); ?>
406 </label>
407 </li>
408 <li>
409 <label>
410 <input name="_lp_allow_repurchase_type" value="keep" type="radio" />
411 <?php esc_html_e( 'Continue Course progress', 'learnpress' ); ?>
412 </label>
413 </li>
414 </ul>
415 </div>
416 <?php
417 $response->data->html = ob_get_clean();
418 $response->data->type = 'allow_repurchase';
419 $response->data->titlePopup = esc_html__( 'Repurchase Options', 'learnpress' );
420 $response->status = 'success';
421
422 return rest_ensure_response( $response );
423 } else {
424 learn_press_update_user_item_meta( $latest_user_item_id, '_lp_allow_repurchase_type', $course->allow_repurchase_course_option() );
425 }
426 }
427
428 //LearnPress::instance()->session->set( 'order_awaiting_payment', '' );
429
430 $cart = LearnPress::instance()->cart;
431 //$checkout = LP_Checkout::instance();
432
433 if ( ! learn_press_enable_cart() ) {
434 //$order_awaiting_payment = LearnPress::instance()->session->order_awaiting_payment;
435 $cart->empty_cart();
436 //LearnPress::instance()->session->order_awaiting_payment = $order_awaiting_payment;
437 }
438
439 do_action( 'learnpress/rest-api/courses/purchase/before-add-to-cart' );
440
441 $cart_id = $cart->add_to_cart( $course_id, 1, array() );
442 if ( empty( $cart_id ) ) {
443 throw new Exception( __( 'Error: The course cannot be added to the cart.', 'learnpress' ) );
444 }
445
446 if ( ! empty( $allow_repurchase_type ) ) {
447 learn_press_update_user_item_meta( $latest_user_item_id, '_lp_allow_repurchase_type', $allow_repurchase_type );
448 }
449
450 $redirect_url = apply_filters(
451 'learnpress/rest-api/courses/purchase/redirect',
452 learn_press_get_page_link( 'checkout' ),
453 $course_id,
454 $cart_id
455 );
456
457 if ( empty( $redirect_url ) ) {
458 throw new Exception( __( 'Error: Please set up a page for checkout.', 'learnpress' ) );
459 } elseif ( ! is_user_logged_in() ) { // Fix case: cache page with user anonymous
460 $redirect_url = LP_Helper::get_link_no_cache( $redirect_url );
461 }
462
463 $response->status = 'success';
464 $response->message = sprintf(
465 esc_html__( '"%s" has been added to your cart.', 'learnpress' ),
466 $course->get_title()
467 );
468 $response->data->redirect = $redirect_url;
469 } catch ( Exception $e ) {
470 $response->message = $e->getMessage();
471 }
472
473 return rest_ensure_response( $response );
474 }
475
476 /**
477 * Rest API for retake course.
478 *
479 * @param WP_REST_Request $request .
480 *
481 * @throws Exception .
482 */
483 public function retake_course( WP_REST_Request $request ) {
484 $response = new LP_REST_Response();
485
486 try {
487 $course_id = $request->get_param( 'id' );
488
489 if ( ! $course_id ) {
490 throw new Exception( __( 'Invalid params', 'learnpress' ) );
491 }
492
493 $course = learn_press_get_course( $course_id );
494
495 if ( ! $course ) {
496 throw new Exception( __( 'Invalid course', 'learnpress' ) );
497 }
498
499 $user = learn_press_get_current_user();
500
501 // if ( ! is_user_logged_in() ) {
502 // throw new Exception( esc_html__( 'Please login!', 'learnpress' ) );
503 // }
504
505 $can_retry = $user->can_retry_course( $course_id );
506
507 if ( ! $can_retry ) {
508 throw new Exception( __( 'You can\'t retry the course', 'learnpress' ) );
509 }
510
511 $user_course_data = $user->get_course_data( $course_id );
512 if ( ! $user_course_data ) {
513 throw new Exception( __( 'Invalid course data of user', 'learnpress' ) );
514 }
515
516 // Up retaken.
517 $user_course_data->increase_retake_count();
518
519 // Set status, start_time, end_time of course to enrol.
520 $user_course_data->set_status( LP_COURSE_ENROLLED )
521 ->set_start_time( time() )
522 ->set_end_time()
523 ->set_graduation( LP_COURSE_GRADUATION_IN_PROGRESS )
524 ->update();
525
526 // Remove items' course user learned.
527 $filter_remove = new LP_User_Items_Filter();
528 $filter_remove->parent_id = $user_course_data->get_user_item_id();
529 $filter_remove->user_id = $user_course_data->get_user_id();
530 $filter_remove->limit = - 1;
531 LP_User_Items_DB::getInstance()->remove_items_of_user_course( $filter_remove );
532
533 // Create new result in table learnpress_user_item_results.
534 LP_User_Items_Result_DB::instance()->insert( $user_course_data->get_user_item_id() );
535
536 $response->status = 'success';
537 $response->message = esc_html__( 'Now you can learn this course', 'learnpress' );
538 $response->data->url_redirect = $course->get_redirect_url_after_enroll();
539 } catch ( Exception $e ) {
540 $response->message = $e->getMessage();
541 }
542
543 wp_send_json( $response );
544 }
545
546 /**
547 * @param WP_REST_Request $request
548 *
549 * @return WP_REST_Response
550 */
551 public function get_items( $request ) {
552 $settings = LP_Settings::instance();
553 $response = array(
554 'result' => $settings->get(),
555 );
556
557 return rest_ensure_response( $response );
558 }
559
560 /**
561 * @param WP_REST_Request $request
562 *
563 * @return WP_REST_Response
564 */
565 public function get_item( $request ) {
566 $settings = LP_Settings::instance();
567 $response = array(
568 'result' => $settings->get( $request['key'] ),
569 );
570
571 return rest_ensure_response( $response );
572 }
573
574 /**
575 * @param WP_REST_Request $request
576 *
577 * @return WP_REST_Response
578 */
579 public function update_item( $request ) {
580 $response = array();
581 $settings = LP_Settings::instance();
582 $option = $settings->get( $request['key'] );
583
584 $settings->update( $request['key'], $request['data'] );
585 $new_option = $settings->get( $request['key'] );
586 $success = maybe_serialize( $option ) !== maybe_serialize( $new_option );
587
588 $response['success'] = $success;
589 $response['result'] = $success ? $new_option : $option;
590
591 return rest_ensure_response( $response );
592 }
593
594 /**
595 * @param WP_REST_Request $request
596 *
597 * @return WP_REST_Response
598 */
599 public function delete_item( $request ) {
600 $response = array();
601
602 return rest_ensure_response( $response );
603 }
604
605 /**
606 * Rest API for get item continue in single course.
607 *
608 * @param WP_REST_Request $request
609 *
610 * @author minhpd
611 * @editor tungnx
612 * @since 4.1.4
613 * @version 1.0.2
614 * @return LP_REST_Response
615 */
616 public function continue_course( WP_REST_Request $request ): LP_REST_Response {
617 $params = $request->get_params();
618 $response = new LP_REST_Response();
619 $response->data = '';
620
621 try {
622 $flag_found = false;
623 $item_link = '';
624 $course_id = absint( $params['courseId'] ?? 0 );
625 $user_id = absint( $params['userId'] ?? 0 );
626
627 $user = learn_press_get_user( $user_id );
628 $course = learn_press_get_course( $course_id );
629
630 if ( ! $course ) {
631 throw new Exception( __( 'Invalid course', 'learnpress' ) );
632 }
633
634 $sections_items = $course->get_full_sections_and_items_course();
635 $total_items = $course->count_items();
636
637 if ( ! empty( $total_items ) ) {
638 foreach ( $sections_items as $section_items ) {
639 if ( $flag_found ) {
640 break;
641 }
642
643 foreach ( $section_items->items as $item ) {
644 $item_now_condition = apply_filters(
645 'lp/course/item-continue/condition',
646 ! $user->has_completed_item( $item->id, $course_id ),
647 $item,
648 $course,
649 $user
650 );
651 if ( $item_now_condition ) {
652 $item_link = $course->get_item_link( $item->id );
653 $flag_found = true;
654 break;
655 }
656 }
657 }
658
659 if ( ! $flag_found ) {
660 $item_link = $course->get_item_link( $course->get_first_item_id() );
661 }
662 }
663
664 $response->data = $item_link;
665 $response->status = 'success';
666 $response->message = '';
667 } catch ( Exception $e ) {
668 $response->message = $e->getMessage();
669 }
670
671 return $response;
672 }
673
674 }
675