PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.8
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.8
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.4.8, at inc/rest-api/v1/frontend/class-lp-rest-courses-controller.php

894 lines 27.2 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\Background\LPBackgroundAjax;
8 use LearnPress\ExternalPlugin\Elementor\Widgets\Course\ListCoursesByPageElementor;
9 use LearnPress\Filters\Course\CourseJsonFilter;
10 use LearnPress\Helpers\Response;
11 use LearnPress\Helpers\Template;
12 use LearnPress\Models\CourseModel;
13 use LearnPress\Models\PostModel;
14 use LearnPress\Models\UserItems\UserCourseModel;
15 use LearnPress\Models\UserItems\UserItemModel;
16 use LearnPress\Models\UserModel;
17 use LearnPress\Services\CourseService;
18 use LearnPress\TemplateHooks\Course\ListCoursesTemplate;
19 use LearnPress\TemplateHooks\Course\SingleCourseTemplate;
20
21 class LP_REST_Courses_Controller extends LP_Abstract_REST_Controller {
22 /**
23 * LP_REST_Courses_Controller constructor.
24 */
25 public function __construct() {
26 $this->namespace = 'lp/v1';
27 $this->rest_base = 'courses';
28 parent::__construct();
29 }
30
31 /**
32 * Register routes API
33 */
34 public function register_routes() {
35 $this->routes = array(
36 '' => array(
37 array(
38 'methods' => WP_REST_Server::ALLMETHODS,
39 'callback' => array( $this, 'get_courses' ),
40 ),
41 ),
42 'edit-archive-block' => array(
43 array(
44 'methods' => WP_REST_Server::ALLMETHODS,
45 'callback' => array( $this, 'get_courses_archive_block' ),
46 'permission_callback' => '__return_true',
47 'args' => array(),
48 ),
49 ),
50 'courses-suggest' => array(
51 array(
52 'methods' => WP_REST_Server::ALLMETHODS,
53 'callback' => array( $this, 'courses_suggest' ),
54 'permission_callback' => '__return_true',
55 'args' => [],
56 ),
57 ),
58 'purchase-course' => array(
59 array(
60 'methods' => WP_REST_Server::CREATABLE,
61 'callback' => array( $this, 'purchase_course' ),
62 'permission_callback' => '__return_true',
63 ),
64 ),
65 'enroll-course' => array(
66 array(
67 'methods' => WP_REST_Server::CREATABLE,
68 'callback' => array( $this, 'enroll_courses' ),
69 'permission_callback' => '__return_true',
70 ),
71 ),
72 'retake-course' => array(
73 array(
74 'methods' => WP_REST_Server::CREATABLE,
75 'callback' => array( $this, 'retake_course' ),
76 'permission_callback' => function () {
77 return is_user_logged_in();
78 },
79 'schema' => array(
80 'type' => 'int',
81 ),
82 ),
83 ),
84 /*'archive-course' => array(
85 array(
86 'methods' => WP_REST_Server::ALLMETHODS,
87 'callback' => array( $this, 'list_courses' ),
88 'permission_callback' => '__return_true',
89 'args' => [],
90 ),
91 ),*/
92 'courses-widget-by-page' => array(
93 array(
94 'methods' => WP_REST_Server::ALLMETHODS,
95 'callback' => array( $this, 'courses_widget_by_page' ),
96 'permission_callback' => '__return_true',
97 'args' => [],
98 ),
99 ),
100 '(?P<key>[\w]+)' => array(
101 'args' => array(
102 'id' => array(
103 'description' => __( 'A unique identifier for the resource.', 'learnpress' ),
104 'type' => 'string',
105 ),
106 ),
107 array(
108 'methods' => WP_REST_Server::READABLE,
109 'callback' => array( $this, 'get_item' ),
110 'permission_callback' => array( $this, 'check_admin_permission' ),
111 ),
112 array(
113 'methods' => WP_REST_Server::EDITABLE,
114 'callback' => array( $this, 'update_item' ),
115 'permission_callback' => array( $this, 'check_admin_permission' ),
116 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
117 ),
118 array(
119 'methods' => WP_REST_Server::DELETABLE,
120 'callback' => array( $this, 'delete_item' ),
121 'permission_callback' => array( $this, 'check_admin_permission' ),
122 ),
123 'schema' => array( $this, 'get_public_item_schema' ),
124 ),
125 'continue-course' => array(
126 array(
127 'methods' => WP_REST_Server::CREATABLE,
128 'callback' => array( $this, 'continue_course' ),
129 'permission_callback' => '__return_true',
130 ),
131 ),
132 );
133
134 parent::register_routes();
135 }
136
137 /**
138 * Check user is Admin
139 *
140 * @return bool
141 */
142 public function check_admin_permission(): bool {
143 return LP_Abstract_API::check_admin_permission();
144 }
145
146 /**
147 * Get list courses, return JSON data, not to handle HTML
148 *
149 * @param WP_REST_Request $request
150 *
151 * @return Response
152 * @since 4.2.8.2
153 * @version 1.0.1
154 */
155 public function get_courses( WP_REST_Request $request ): Response {
156 $response = new Response();
157
158 try {
159 $filter = new CourseJsonFilter();
160 $params = $request->get_params();
161 $total_rows = 0;
162
163 CourseService::handle_params_for_query_list_courses( $filter, $params );
164 $filter->only_fields = [ CourseJsonFilter::COL_ID ];
165
166 $coursesRs = CourseService::get_list_courses( $filter, $total_rows );
167
168 $courses = [];
169 foreach ( $coursesRs as $course ) {
170 $courseModel = CourseModel::find( $course->ID, true );
171 $allow_fields = apply_filters(
172 'lp/rest-api/courses/allow_fields',
173 [
174 CourseJsonFilter::COL_ID,
175 CourseJsonFilter::COL_POST_TITLE,
176 CourseJsonFilter::COL_POST_NAME,
177 CourseJsonFilter::COL_POST_AUTHOR,
178 CourseJsonFilter::COL_LANG,
179 CourseJsonFilter::COL_IS_SALE,
180 ],
181 $courseModel,
182 $params
183 );
184 if ( ! $courseModel ) {
185 continue;
186 }
187
188 $course_info = new stdClass();
189 foreach ( $allow_fields as $field ) {
190 $course_info->$field = $courseModel->$field;
191 }
192
193 $courses[] = $course_info;
194 }
195
196 $response->status = Response::STATUS_SUCCESS;
197 $response->data->courses = $courses;
198 $response->data->total = $total_rows;
199 $response->data->page = $filter->page;
200 $response->data->total_pages = LP_Database::get_total_pages( $filter->limit, $total_rows );
201 } catch ( Throwable $e ) {
202 $response->message = $e->getMessage();
203 }
204
205 return apply_filters( 'lp/rest-api/frontend/course/archive_course/response', $response );
206 }
207
208 /**
209 * Get list courses display layout when edit on archive block
210 *
211 * @param WP_REST_Request $request
212 *
213 * @return Response
214 * @since 4.3.7
215 * @version 1.0.0
216 */
217 public function get_courses_archive_block( WP_REST_Request $request ): Response {
218 $response = new Response();
219
220 try {
221 $filter = new CourseJsonFilter();
222 $params = $request->get_params();
223 $total_rows = 0;
224
225 CourseService::handle_params_for_query_list_courses( $filter, $params );
226 // For permission, it only displays for Editor easy config layout, not for get data primary
227 $filter->only_fields = [ CourseJsonFilter::COL_ID ];
228 $filter->post_status = [ PostModel::STATUS_PUBLISH ];
229 $coursesRs = CourseService::get_list_courses( $filter, $total_rows );
230
231 $courses = [];
232 $singleCourseTemplate = SingleCourseTemplate::instance();
233 foreach ( $coursesRs as $course ) {
234 $courseModel = CourseModel::find( $course->ID, true );
235 if ( ! $courseModel ) {
236 continue;
237 }
238
239 $courseItem = new stdClass();
240 $courseItem->ID = $course->ID;
241 $courseItem->description = $singleCourseTemplate->html_short_description( $courseModel );
242 $courseItem->price = $singleCourseTemplate->html_price( $courseModel );
243 $courseItem->title = $courseModel->get_title();
244 $courseItem->student = $singleCourseTemplate->html_count_student( $courseModel );
245 $courseItem->lesson = $singleCourseTemplate->html_count_item( $courseModel, LP_LESSON_CPT );
246 $courseItem->duration = $singleCourseTemplate->html_duration( $courseModel );
247 $courseItem->quiz = $singleCourseTemplate->html_count_item( $courseModel, LP_QUIZ_CPT );
248 $courseItem->level = $singleCourseTemplate->html_level( $courseModel );
249 $courseItem->image = $singleCourseTemplate->html_image( $courseModel );
250 $courseItem->instructor = $singleCourseTemplate->html_instructor( $courseModel, false, [ 'is_link' => false ] );
251 $courseItem->category = $singleCourseTemplate->html_categories( $courseModel );
252 $courseItem->button = __( 'Read more', 'learnpress' );
253
254 $courses[] = apply_filters( 'lp/rest-api/frontend/course/archive_course/courses', $courseItem, $courseModel );
255 }
256
257 $response->status = Response::STATUS_SUCCESS;
258 $response->data->courses = $courses;
259 $response->data->total = $total_rows;
260 $response->data->page = $filter->page;
261 $response->data->total_pages = LP_Database::get_total_pages( $filter->limit, $total_rows );
262 } catch ( Throwable $e ) {
263 $response->message = $e->getMessage();
264 }
265
266 return apply_filters( 'lp/rest-api/frontend/course/archive_course/response', $response );
267 }
268
269 /**
270 * Get list courses for search suggest
271 *
272 * @param WP_REST_Request $request
273 *
274 * @return Response
275 * @since 4.3.7
276 * @version 1.0.0
277 */
278 public function courses_suggest( WP_REST_Request $request ): Response {
279 $response = new Response();
280
281 try {
282 $filter = new CourseJsonFilter();
283 $params = $request->get_params();
284 $total_rows = 0;
285
286 CourseService::handle_params_for_query_list_courses( $filter, $params );
287 $filter->only_fields = [ CourseJsonFilter::COL_ID ];
288 $filter->post_status = [ PostModel::STATUS_PUBLISH ];
289
290 $coursesRs = CourseService::get_list_courses( $filter, $total_rows );
291
292 $courses = [];
293 foreach ( $coursesRs as $course ) {
294 $courseModel = CourseModel::find( $course->ID, true );
295 $courses[] = $courseModel;
296 }
297
298 $data = array(
299 'courses' => $courses,
300 'keyword' => $request['c_search'],
301 'total_course' => $total_rows,
302 );
303 ob_start();
304 do_action( 'learn-press/rest-api/courses/suggest/layout', $data );
305 $response->data->content = ob_get_clean();
306 $response->data->totals = $total_rows;
307 $response->status = Response::STATUS_SUCCESS;
308 } catch ( Throwable $e ) {
309 $response->message = $e->getMessage();
310 }
311
312 return apply_filters( 'lp/rest-api/courses-search-suggest/response', $response );
313 }
314
315 /**
316 * Get list courses
317 *
318 * @param WP_REST_Request $request
319 *
320 * @depreacted 4.3.7
321 * @return LP_REST_Response
322 */
323 public function list_courses( WP_REST_Request $request ): LP_REST_Response {
324 $response = new LP_REST_Response();
325 $response->data = new stdClass();
326 $listCoursesTemplate = ListCoursesTemplate::instance();
327 $pagination_type = LP_Settings::get_option( 'course_pagination_type' );
328
329 try {
330 throw new Exception( 'Deprecated function from 4.3.7' );
331 $filter = new CourseJsonFilter();
332 $params = $request->get_params();
333 $params['c_status'] = 'publish';
334 $params['c_fields'] = 'ID, post_title, post_content, post_status, post_author, meta_input';
335 CourseService::handle_params_for_query_list_courses( $filter, $params );
336
337 // Check is in category page.
338 /*if ( ! empty( $request->get_param( 'page_term_id_current' ) ) &&
339 empty( $request->get_param( 'term_id' ) ) ) {
340 $filter->term_ids[] = $request->get_param( 'page_term_id_current' );
341 } // Check is in tag page.
342 elseif ( ! empty( $request->get_param( 'page_tag_id_current' ) ) &&
343 empty( $request->get_param( 'tag_id' ) ) ) {
344 $filter->tag_ids[] = $request->get_param( 'page_tag_id_current' );
345 }*/
346
347 $total_rows = 0;
348 $courses = CourseService::get_list_courses( $filter, $total_rows );
349 $total_pages = LP_Database::get_total_pages( $filter->limit, $total_rows );
350 $return_type = $request['return_type'] ?? 'html';
351 if ( 'json' === $return_type ) {
352 $response->data->courses = $courses;
353 $response->data->total_pages = $total_pages;
354 } else {
355 // For return data has html
356 ob_start();
357 if ( $courses ) {
358 if ( ! empty( $request['c_suggest'] ) ) {
359 $data = array(
360 'courses' => $courses,
361 'keyword' => $request['c_search'],
362 'total_course' => $total_rows,
363 );
364 do_action( 'learn-press/rest-api/courses/suggest/layout', $data );
365 } else {
366 global $wp, $post;
367
368 // Template Pagination.
369 switch ( $pagination_type ) {
370 case 'load-more':
371 if ( $filter->page < $total_pages ) {
372 $response->data->pagination = $listCoursesTemplate->html_pagination_load_more();
373 }
374 break;
375 case 'infinite':
376 if ( $filter->page < $total_pages ) {
377 $response->data->pagination = $listCoursesTemplate->html_pagination_infinite();
378 }
379 break;
380 default:
381 $pagination_args = [
382 'total_pages' => $total_pages,
383 'paged' => $filter->page,
384 'base' => add_query_arg( 'paged', '%#%', learn_press_get_page_link( 'courses' ) ),
385 ];
386 $response->data->pagination = $listCoursesTemplate->html_pagination_number( $pagination_args );
387 break;
388 }
389 $response->data->pagination_type = $pagination_type;
390 // End Pagination
391
392 // For custom template
393 $template_path = apply_filters( 'lp/api/courses/template', '', $request );
394 if ( ! empty( $template_path ) ) {
395 Template::instance()->get_template( $template_path, compact( 'courses', 'total_pages', 'request' ) );
396 } else {
397 foreach ( $courses as $course ) {
398 $post = get_post( $course->ID );
399 setup_postdata( $post );
400 Template::instance()->get_frontend_template( 'content-course.php' );
401 }
402
403 wp_reset_postdata();
404 }
405 // End content items
406 }
407 } else {
408 LearnPress::instance()->template( 'course' )->no_courses_found();
409 }
410
411 $response->data->content = ob_get_clean();
412 $response->data->totals = $total_rows;
413
414 $from = 1 + ( $filter->page - 1 ) * $filter->limit;
415 $to = ( $filter->page * $filter->limit > $total_rows ) ? $total_rows : $filter->page * $filter->limit;
416
417 if ( 0 === $total_rows ) {
418 $response->data->from_to = '';
419 } elseif ( 1 === $total_rows ) {
420 $response->data->from_to = esc_html__( 'Showing only one result', 'learnpress' );
421 } else {
422 if ( $from == $to ) {
423 $response->data->from_to = sprintf( esc_html__( 'Showing last course of %s results', 'learnpress' ), $total_rows );
424 } else {
425 switch ( $pagination_type ) {
426 case 'load-more':
427 case 'infinite':
428 $from_to = $filter->page * $filter->limit;
429 if ( $from_to > $total_rows ) {
430 $from_to = $total_rows;
431 }
432 break;
433 default:
434 $from_to = $from . '-' . $to;
435 break;
436 }
437
438 $response->data->from_to = sprintf( esc_html__( 'Showing %1$s of %2$s results', 'learnpress' ), $from_to, $total_rows );
439 }
440 }
441 }
442
443 $response->status = 'success';
444 } catch ( Throwable $e ) {
445 $response->data->content = $e->getMessage();
446 $response->message = $e->getMessage();
447 }
448
449 return apply_filters( 'lp/rest-api/frontend/course/archive_course/response', $response );
450 }
451
452 /**
453 * Get list courses - Widget Elementor
454 *
455 * @param WP_REST_Request $request
456 *
457 * @return LP_REST_Response
458 */
459 public function courses_widget_by_page( WP_REST_Request $request ): LP_REST_Response {
460 $response = new LP_REST_Response();
461 $response->data = new stdClass();
462
463 try {
464 $settings = array_merge(
465 $request->get_params(),
466 [
467 'courses_ul_classes' => [ 'list-courses-elm' ],
468 ]
469 );
470 $response->data->content = ListCoursesByPageElementor::render_data_from_setting( $settings );
471
472 $response->status = 'success';
473 } catch ( Throwable $e ) {
474 ob_end_clean();
475 $response->data->content = $e->getMessage();
476 $response->message = $e->getMessage();
477 }
478
479 return apply_filters( 'lp/rest-api/frontend/course/archive_course/response', $response );
480 }
481
482 /**
483 * Rest API for Enroll in single course.
484 *
485 * @param WP_REST_Request $request
486 *
487 * @return LP_REST_Response
488 * @author Nhamdv
489 * @editor tungnx
490 * @version 1.0.3
491 * @since 4.0.0
492 */
493 public function enroll_courses( WP_REST_Request $request ): LP_REST_Response {
494 $response = new LP_REST_Response();
495 $response->data = new stdClass();
496
497 try {
498 $course_id = absint( $request['id'] ?? 0 );
499 $course = CourseModel::find( $course_id, true );
500 if ( ! $course ) {
501 throw new Exception( esc_html__( 'Invalid course!', 'learnpress' ) );
502 }
503
504 $user_id = get_current_user_id();
505 $user = UserModel::find( $user_id, true );
506 $can_enroll = $course->can_enroll( $user );
507 if ( $can_enroll instanceof WP_Error ) {
508 throw new Exception( $can_enroll->get_error_message() );
509 }
510
511 // Case: if user bought course
512 $userCourse = UserCourseModel::find( $user_id, $course_id, true );
513 if ( $userCourse && $userCourse->has_purchased() ) {
514 $userCourse->graduation = LP_COURSE_GRADUATION_IN_PROGRESS;
515 $userCourse->status = LP_COURSE_ENROLLED;
516 $userCourse->start_time = gmdate( LP_Datetime::$format, time() );
517 $userCourse->save();
518
519 do_action( 'learnpress/user/course-enrolled', $userCourse->ref_id, $course_id, $user->get_id() );
520
521 /**
522 * Send mail user enrolled course
523 * @uses SendEmailAjax::send_mail_user_enrolled_course()
524 */
525 $data_send = [
526 $userCourse->ref_id,
527 $course_id,
528 $user->get_id(),
529 ];
530 LPBackgroundAjax::handle(
531 [
532 'params' => $data_send,
533 'lp-load-ajax' => 'send_mail_user_enrolled_course',
534 ]
535 );
536 } else { // Case enroll course free
537 $cart = LearnPress::instance()->cart;
538 $checkout = LP_Checkout::instance();
539
540 if ( ! learn_press_enable_cart() ) {
541 $cart->empty_cart();
542 }
543
544 $cart_id = $cart->add_to_cart( $course_id );
545 if ( ! $cart_id ) {
546 throw new Exception( esc_html__( 'Error: The course cannot be added to the cart.', 'learnpress' ) );
547 }
548
549 if ( is_user_logged_in() ) {
550 $order_id = $checkout->create_order();
551 $order = new LP_Order( $order_id );
552 $order->payment_complete();
553
554 $cart->empty_cart();
555 }
556 }
557
558 if ( is_user_logged_in() ) {
559 $response->message = esc_html__(
560 'Congrats! You have enrolled in the course successfully. Redirecting...',
561 'learnpress'
562 );
563
564 $first_item_id = $course->get_first_item_id();
565 $response->data->redirect = $first_item_id ? $course->get_item_link( $first_item_id ) : get_the_permalink( $course->get_id() );
566 } else {
567 $redirect_url = LP_Page_Controller::get_link_page( 'checkout', [], true );
568 $redirect_url = apply_filters(
569 'learnpress/rest-api/courses/enroll/redirect',
570 $redirect_url,
571 $course_id
572 );
573
574 if ( empty( $redirect_url ) ) {
575 throw new Exception( __( 'Error: Please set up a page for checkout.', 'learnpress' ) );
576 }
577
578 $redirect_url = LP_Helper::get_link_no_cache( $redirect_url );
579 $response->message = esc_html__( 'Redirecting...', 'learnpress' );
580 $response->data->redirect = esc_url_raw( $redirect_url );
581 }
582
583 $response->status = 'success';
584 } catch ( Exception $e ) {
585 $response->message = $e->getMessage();
586 }
587
588 return $response;
589 }
590
591 /**
592 * Rest API for Purchase course in single course.
593 *
594 * @param WP_REST_Request $request .
595 *
596 * @return WP_REST_Response|WP_Error
597 * @throws Exception .
598 * @author Nhamdv
599 */
600 public function purchase_course( WP_REST_Request $request ) {
601 $response = new LP_REST_Response();
602 $response->data = new stdClass();
603 $params = $request->get_params();
604
605 try {
606 $course_id = $params['id'];
607 $allow_repurchase_type = $params['repurchaseType'] ?? false;
608
609 if ( ! $course_id ) {
610 throw new Exception( __( 'Error: Invalid Course ID.', 'learnpress' ) );
611 }
612
613 $course = CourseModel::find( $course_id, true );
614 if ( ! $course ) {
615 throw new Exception( __( 'Error: No Course available.', 'learnpress' ) );
616 }
617
618 $user_id = get_current_user_id();
619 $user = UserModel::find( $user_id, true );
620 $can_purchase = $course->can_purchase( $user );
621 if ( $can_purchase instanceof WP_Error ) {
622 throw new Exception( $can_purchase->get_error_message() );
623 }
624
625 $userCourse = UserCourseModel::find( $user_id, $course_id, true );
626 $option_repurchase = [
627 'reset' => esc_html__( 'Reset course progress', 'learnpress' ),
628 'keep' => esc_html__( 'Keep course progress', 'learnpress' ),
629 ];
630 $html_li_repurchase = '';
631 foreach ( $option_repurchase as $key => $value ) {
632 $html_li_repurchase .= sprintf(
633 '<li><label>%s</label></li>',
634 sprintf(
635 '<input name="_lp_allow_repurchase_type" value="%s" type="radio" checked="checked"/> %s',
636 $key,
637 $value
638 )
639 );
640 }
641
642 $repurchase_type = $course->get_type_repurchase();
643 $section_popup_repurchase = [
644 'wrapper' => '<div class="lp_allow_repurchase_select">',
645 'ul' => '<ul>',
646 'list' => $html_li_repurchase,
647 'ul_end' => '</ul>',
648 'wrapper_end' => '</div>',
649 ];
650 if ( $course->enable_allow_repurchase()
651 && $user_id && $userCourse
652 && empty( $allow_repurchase_type ) ) {
653 if ( $repurchase_type === 'popup' ) {
654 $response->data->html = Template::combine_components( $section_popup_repurchase );
655 $response->data->type = 'allow_repurchase';
656 $response->data->titlePopup = esc_html__( 'Repurchase Options', 'learnpress' );
657 $response->status = 'success';
658
659 return rest_ensure_response( $response );
660 }
661 }
662
663 $cart = LearnPress::instance()->cart;
664 if ( ! learn_press_enable_cart() ) {
665 $cart->empty_cart();
666 }
667
668 // @deprecated hook since v4.2.7.3
669 //do_action( 'learnpress/rest-api/courses/purchase/before-add-to-cart' );
670
671 $cart_id = $cart->add_to_cart( $course_id, 1, $params );
672 if ( empty( $cart_id ) ) {
673 throw new Exception( __( 'Error: The course cannot be added to the cart.', 'learnpress' ) );
674 }
675
676 if ( ! empty( $allow_repurchase_type ) && $userCourse ) {
677 learn_press_update_user_item_meta( $userCourse->get_user_item_id(), '_lp_allow_repurchase_type', $allow_repurchase_type );
678 }
679
680 $redirect_url = LP_Page_Controller::get_link_page( 'checkout', [], true );
681 $redirect_url = apply_filters(
682 'learnpress/rest-api/courses/purchase/redirect',
683 $redirect_url,
684 $course_id,
685 $cart_id
686 );
687
688 if ( empty( $redirect_url ) ) {
689 throw new Exception( __( 'Error: Please set up a page for checkout.', 'learnpress' ) );
690 }
691
692 $redirect_url = LP_Helper::get_link_no_cache( $redirect_url );
693 $response->status = 'success';
694 $response->message = sprintf(
695 esc_html__( '"%s" has been added to your cart. Redirecting...', 'learnpress' ),
696 $course->get_title()
697 );
698 $response->data->redirect = esc_url_raw( $redirect_url );
699 } catch ( Exception $e ) {
700 $response->message = $e->getMessage();
701 }
702
703 return rest_ensure_response( $response );
704 }
705
706 /**
707 * Rest API for retake course.
708 *
709 * @param WP_REST_Request $request .
710 *
711 * @throws Exception .
712 */
713 public function retake_course( WP_REST_Request $request ) {
714 $response = new LP_REST_Response();
715
716 try {
717 $course_id = $request->get_param( 'id' );
718
719 if ( ! $course_id ) {
720 throw new Exception( __( 'Invalid params', 'learnpress' ) );
721 }
722
723 $courseModel = CourseModel::find( $course_id, true );
724 if ( ! $courseModel ) {
725 throw new Exception( __( 'Invalid course', 'learnpress' ) );
726 }
727
728 $userModel = UserModel::find( get_current_user_id(), true );
729 if ( ! $userModel ) {
730 throw new Exception( __( 'Invalid user', 'learnpress' ) );
731 }
732
733 $userCourseModel = UserCourseModel::find( $userModel->get_id(), $courseModel->get_id(), true );
734 if ( ! $userCourseModel ) {
735 throw new Exception( __( 'Invalid user course', 'learnpress' ) );
736 }
737
738 $userCourseModel->handle_retake();
739 $item_continue = $userCourseModel->get_item_continue();
740 if ( $item_continue ) {
741 $link_continue = $courseModel->get_item_link( $item_continue->ID );
742 } else {
743 $link_continue = $courseModel->get_permalink();
744 }
745
746 $response->status = 'success';
747 $response->message = esc_html__( 'Now you can begin this course', 'learnpress' );
748 $response->data->url_redirect = $link_continue;
749 } catch ( Exception $e ) {
750 $response->message = $e->getMessage();
751 }
752
753 return $response;
754 }
755
756 /**
757 * @param WP_REST_Request $request
758 *
759 * @return WP_REST_Response
760 */
761 public function get_items( $request ) {
762 $settings = LP_Settings::instance();
763 $response = array(
764 'result' => $settings->get(),
765 );
766
767 return rest_ensure_response( $response );
768 }
769
770 /**
771 * @param WP_REST_Request $request
772 *
773 * @return WP_REST_Response
774 */
775 public function get_item( $request ) {
776 $settings = LP_Settings::instance();
777 $response = array(
778 'result' => $settings->get( $request['key'] ),
779 );
780
781 return rest_ensure_response( $response );
782 }
783
784 /**
785 * @param WP_REST_Request $request
786 *
787 * @return WP_REST_Response
788 */
789 public function update_item( $request ) {
790 $response = array();
791 $settings = LP_Settings::instance();
792 $option = $settings->get( $request['key'] );
793
794 $settings->update( $request['key'], $request['data'] );
795 $new_option = $settings->get( $request['key'] );
796 $success = maybe_serialize( $option ) !== maybe_serialize( $new_option );
797
798 $response['success'] = $success;
799 $response['result'] = $success ? $new_option : $option;
800
801 return rest_ensure_response( $response );
802 }
803
804 /**
805 * @param WP_REST_Request $request
806 *
807 * @return WP_REST_Response
808 */
809 public function delete_item( $request ) {
810 $response = array();
811
812 return rest_ensure_response( $response );
813 }
814
815 /**
816 * Rest API for get item continue in single course.
817 *
818 * @param WP_REST_Request $request
819 *
820 * @return LP_REST_Response
821 * @since 4.1.4
822 * @version 1.0.5
823 */
824 public function continue_course( WP_REST_Request $request ): LP_REST_Response {
825 $params = $request->get_params();
826 $response = new LP_REST_Response();
827 $response->data = '';
828
829 try {
830 $flag_found = false;
831 $item_link = '';
832 $course_id = absint( $params['courseId'] ?? 0 );
833 $user_id = get_current_user_id();
834
835 $user = UserModel::find( $user_id, true );
836 $course = CourseModel::find( $course_id, true );
837 if ( ! $course ) {
838 throw new Exception( __( 'Invalid course', 'learnpress' ) );
839 }
840
841 if ( ! $user ) {
842 return $response;
843 }
844
845 $userCourseModel = UserCourseModel::find( $user_id, $course_id, true );
846 if ( ! $userCourseModel ) {
847 throw new Exception( __( 'Invalid user course', 'learnpress' ) );
848 }
849
850 $sections_items = $course->get_section_items();
851 $total_items = $course->get_total_items();
852
853 if ( ! empty( $total_items ) ) {
854 foreach ( $sections_items as $section_items ) {
855 if ( $flag_found ) {
856 break;
857 }
858
859 foreach ( $section_items->items as $item ) {
860 $item_id = $item->id ?? $item->item_id;
861 $item_type = $item->type ?? $item->item_type;
862
863 $userItemModel = UserItemModel::find_user_item(
864 $user_id,
865 $item_id,
866 $item_type,
867 $course_id,
868 LP_COURSE_CPT,
869 true
870 );
871 if ( ! $userItemModel || $userItemModel->get_status() !== LP_ITEM_COMPLETED ) {
872 $item_link = $course->get_item_link( $item->id );
873 $flag_found = true;
874 break;
875 }
876 }
877 }
878
879 if ( ! $flag_found ) {
880 $item_link = $course->get_item_link( $course->get_first_item_id() );
881 }
882 }
883
884 $response->data = $item_link;
885 $response->status = 'success';
886 $response->message = '';
887 } catch ( Exception $e ) {
888 $response->message = $e->getMessage();
889 }
890
891 return $response;
892 }
893 }
894