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

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